<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-17882482</id><updated>2012-01-30T03:34:39.879+11:00</updated><category term='mvc'/><category term='virtualization'/><category term='cryptography'/><category term='iis'/><category term='css'/><category term='javascript'/><category term='silverlight'/><category term='mvvm'/><category term='wpf'/><category term='ajax'/><category term='html'/><category term='security'/><category term='web dev'/><category term='azure'/><category term='asp.net'/><category term='viewstate'/><category term='timezones'/><category term='links'/><category term='dkim'/><category term='networking'/><category term='mssql'/><category term='subversion'/><category term='utilities'/><title type='text'>Tin Isles</title><subtitle type='html'>Somewhere people can _choose_ to hear/read my tech blathering...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>75</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-17882482.post-3571840235081934553</id><published>2010-07-17T23:09:00.003+10:00</published><updated>2010-07-17T23:13:53.268+10:00</updated><title type='text'>WordPress, it's what the cool kids are doing</title><content type='html'>&lt;p&gt;About time my blog "grew up" a bit, and moved to its own domain: &lt;a href="http://blog.tinisles.com"&gt;blog.tinisles.com&lt;/a&gt;.  I've splashed out and set-up a WordPress blog at &lt;a href="http://www.dreamhost.com/"&gt;DreamHost&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Expect an article on the &lt;span style="font-style:italic;"&gt;new&lt;/span&gt; blog detailing my geek adventures setting up WordPress and tranferring the articles over!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-3571840235081934553?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/3571840235081934553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=3571840235081934553' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/3571840235081934553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/3571840235081934553'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2010/07/wordpress-its-what-cool-kids-are-doing.html' title='WordPress, it&apos;s what the cool kids are doing'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-3853652444898490719</id><published>2010-01-10T23:39:00.008+11:00</published><updated>2010-07-17T22:23:26.960+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cryptography'/><title type='text'>Should you trust lastpass.com?</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2010/01/should-you-trust-lastpass-com/"&gt;http://blog.tinisles.com/2010/01/should-you-trust-lastpass-com/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;&lt;a href="https://lastpass.com/"&gt;lastpass.com&lt;/a&gt; looks like a handy online service for storing all your website passwords.  Browser extensions are available to make the whole process easier.  If you use the web from several PCs it does sound nice to have all your passwords available and synced between your PCs.&lt;/p&gt;

&lt;p&gt;First thought was wether I should hand over my passwords to the 3rd party, hopefully they are storing them with some serious crypto.  Perusing their &lt;a href="https://lastpass.com/support_faqs.php"&gt;FAQ&lt;/a&gt; I found some info on this:

&lt;blockquote&gt;We only support keeping the encryption done on your computer so LastPass can't see your sensitive data&lt;/blockquote&gt;

&lt;blockquote&gt;...your sensitive data is always encrypted and decrypted locally on your computer before being synchronized. Your master password never leaves your computer and your key never leaves your computer. No one at LastPass (or anywhere else) can decrypt your data without you giving up your password (we will never ask you for it). Your key is created by taking a SHA-256 hash of your password. When you login, we make a hash of your username concatenated with your password, and that hash is what's sent to verify if you can download your encrypted data.&lt;/blockquote&gt;
&lt;/p&gt;

&lt;p&gt;So they are encrypting everything with a key derived from your password - plus they don't know your password - so they CANNOT access any of your passwords.  Nice.  But why stop there?  Let's fire up fiddler to make sure they definitely don't have my passwords.&lt;/p&gt;

&lt;p&gt;I've created a junk account on lastpass username: russell.sayers.junk@gmail.com, password: test1234 (the account will be gone by the time you read this!).  The first form I see submitted to the server is when I create my account:


&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;username &lt;/td&gt;&lt;td&gt;russell.sayers.junk@gmail.com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hash &lt;/td&gt;&lt;td&gt;53c81a859a3f3d4dc3762d3a47bab07fad7ad3f2673724deb20fb420e8bdc03a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;password &lt;/td&gt;&lt;td&gt;********&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;password2 &lt;/td&gt;&lt;td&gt;********&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;password_hint&lt;/td&gt;&lt;td&gt;testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;timezone2 &lt;/td&gt;&lt;td&gt;+10:00,1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;language2 &lt;/td&gt;&lt;td&gt;en-US&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;agree &lt;/td&gt;&lt;td&gt;on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;agreeupload &lt;/td&gt;&lt;td&gt;on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;loglogins &lt;/td&gt;&lt;td&gt;on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;improve &lt;/td&gt;&lt;td&gt;on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;json &lt;/td&gt;&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;/p&gt;

&lt;p&gt;I don't see my password going to their servers in the clear.  I can confirm that the hash getting sent is geniune by creating the same hash elsewhere via an online &lt;a href="http://www.xorbin.com/tools/sha256-hash-calculator"&gt;SHA256 generator&lt;/a&gt;, or writing some code myself.  Try it yourself, the hash created is SHA256(SHA256(username + password) + password) - everything checks out.  All the C# code to verify the encryption/hashing is at the end of the article.&lt;/p&gt;

&lt;p&gt;The login form:

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;method&lt;/td&gt;&lt;td&gt;web&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hash&lt;/td&gt;&lt;td&gt;53c81a859a3f3d4dc3762d3a47bab07fad7ad3f2673724deb20fb420e8bdc03a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;username&lt;/td&gt;&lt;td&gt;russell.sayers.junk@gmail.com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;encrypted_username&lt;/td&gt;&lt;td&gt;T2tBleI3PxuLOoNEwNkv5PZ/rYr5dDIoYZS+We4vER4=&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;otp&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gridresponse&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;trustlabel&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uuid&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sesameotp&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;email&lt;/td&gt;&lt;td&gt;russell.sayers.junk@gmail.com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;password&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/p&gt;

&lt;p&gt;Again the same hash is being used to verify me when I login.  I can see an encrypted username is being sent (although I'm not sure why?), rooting around in the javascript I can see the key being used for encyption is SHA(username+password).  Importantly this is different to the hash being used to authenticate me - as we don't want the server to be able to decypt anything encypted by the client, i.e. they would have to know my password to derive the same key on their side.&lt;/p&gt;

&lt;p&gt;The form to add a new website:
&lt;a href="http://blog.tinisles.com/blogger-images/2010/01/lg_lastpass_add.JPG"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2010/01/sm_lastpass_add.JPG" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 307px;" /&gt;&lt;/a&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;hasplugin&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;extjs&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;search&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;purgeext&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deleteext&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;undeleteext&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ajax&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ob&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;basic_auth&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isbookmark&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;openid_url&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aid&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useurid&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fromwebsite&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;&lt;td&gt;pyJlY+AX0Aoczlx50hwlHg==&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;grouping&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;origurl&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;url&lt;/td&gt;&lt;td&gt;66616365626f6f6b2e636f6d&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;username&lt;/td&gt;&lt;td&gt;ICkGIGAn7SIk16iKNkl3DA==&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;password&lt;/td&gt;&lt;td&gt;dl78FYUSIdsxxSdkBuBWEA==&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;extra&lt;/td&gt;&lt;td&gt;faESoIpzmCQg5PeHpXN0GQ==&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

We can see here the client is sending encyrypted versions of name, username, password, and the extra info.  Again this is encrypted with a key we only have on our client - no one at lastpass could have this key.  For some reason the URL is being sent in a HEX representation of the string - not sure why they aren't just sending the string?
&lt;/p&gt;

&lt;p&gt;So when I log back into lastpass, I can drill down into this entry and see it again.  Let's make sure everything looks okay here.  The HTML that renders this screen is available in fiddler:


&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: html"&gt;
&amp;lt;tr&amp;gt;
  &amp;lt;td class='col1'&amp;gt;Name&amp;lt;/td&amp;gt;
  &amp;lt;td&amp;gt;&amp;lt;input name='name' id='name' type='text' value='pyJlY+AX0Aoczlx50hwlHg==' style='width: 250px'&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
...
&amp;lt;tr&amp;gt;
  &amp;lt;td class='col1'&amp;gt;Username&amp;lt;/td&amp;gt;
  &amp;lt;td&amp;gt;&amp;lt;input name='username' id='idusername' type='text' value='SgVkuVKH4MjkP+Saz64UhA=='&amp;gt;&amp;#160;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
...
&amp;lt;tr&amp;gt;
  &amp;lt;td class='col1'&amp;gt;Notes&amp;lt;/td&amp;gt;
  &amp;lt;td&amp;gt;&amp;lt;textarea name='extra' id='extra' rows='6' cols='35'&amp;gt;1rZ3sSuggtdavyCu446GZA==&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt; &lt;/pre&gt;

The server is sending down our encrypted details, and relying on the client to decrypt everything.
&lt;/p&gt;

&lt;p&gt;So, yes - you CAN trust lastpass.com with your passwords!  Don't just take my word for it; fire up Fiddler, and compare the hashed/encrypted values with what you expect.&lt;/p&gt;

&lt;p&gt;Lastly the c# code to confirm the AES encrypted strings above are geniune.

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
static void Main(string[] args)
{
    string username = &amp;quot;russell.sayers.junk@gmail.com&amp;quot;;
    string password = &amp;quot;test1234&amp;quot;;
    string hash_auth = ByteArrayToHexString(SHA256(ByteArrayToHexString(SHA256(username+password)) + password));
    byte[] hash_key = SHA256(username + password);

    Console.WriteLine(&amp;quot;hash for authentication =&amp;gt; &amp;quot; + hash_auth);
    Console.WriteLine(&amp;quot;hash for encryption =&amp;gt; &amp;quot; +  ByteArrayToHexString(hash_key));
    Console.WriteLine(&amp;quot;'{0}' encrypted =&amp;gt; {1}&amp;quot;, username, Encrypt(username, hash_key, &amp;quot;&amp;quot;));
    Console.WriteLine(&amp;quot;'{0}' encrypted =&amp;gt; {1}&amp;quot;, &amp;quot;facebook&amp;quot;, Encrypt(&amp;quot;facebook&amp;quot;, hash_key, &amp;quot;&amp;quot;));
    Console.WriteLine(&amp;quot;'{0}' encrypted =&amp;gt; {1}&amp;quot;, &amp;quot;cryptolearner&amp;quot;, Encrypt(&amp;quot;cryptolearner&amp;quot;, hash_key, &amp;quot;&amp;quot;));
    Console.WriteLine(&amp;quot;'{0}' encrypted =&amp;gt; {1}&amp;quot;, &amp;quot;password&amp;quot;, Encrypt(&amp;quot;password&amp;quot;, hash_key, &amp;quot;&amp;quot;));
    Console.WriteLine(&amp;quot;'{0}' encrypted =&amp;gt; {1}&amp;quot;, &amp;quot;no notes&amp;quot;, Encrypt(&amp;quot;no notes&amp;quot;, hash_key, &amp;quot;&amp;quot;));
}

static byte[] SHA256(string data)
{
    byte[] indata = Encoding.UTF8.GetBytes(data);
    SHA256 shaM = new SHA256Managed();
    return shaM.ComputeHash(indata);
}

/// &amp;lt;remarks&amp;gt;From http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/3928b8cb-3703-4672-8ccd-33718148d1e3&amp;lt;/remarks&amp;gt;
static string ByteArrayToHexString(byte[] data)
{
    StringBuilder sb = new StringBuilder(data.Length * 2);
    foreach (byte b in data)
    {
        sb.AppendFormat(&amp;quot;{0:x2}&amp;quot;, b);
    }
    return sb.ToString();
}

/// &amp;lt;remarks&amp;gt;From http://stackoverflow.com/questions/1079131/c-aes-256-encryption&amp;lt;/remarks&amp;gt;
static public string Encrypt(string plaintext, byte[] KeyBytes, string InitialVector)
{
    byte[] PlainTextBytes = Encoding.UTF8.GetBytes(plaintext);
    byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
    RijndaelManaged SymmetricKey = new RijndaelManaged();
    SymmetricKey.Mode = CipherMode.ECB;
    SymmetricKey.Padding = PaddingMode.PKCS7;
    ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
    MemoryStream MemStream = new MemoryStream();
    CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
    CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
    CryptoStream.FlushFinalBlock();
    byte[] CipherTextBytes = MemStream.ToArray();
    MemStream.Close();
    CryptoStream.Close();
    return Convert.ToBase64String(CipherTextBytes);
}&lt;/pre&gt;
&lt;/p&gt;


&lt;p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-3853652444898490719?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/3853652444898490719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=3853652444898490719' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/3853652444898490719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/3853652444898490719'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2010/01/should-you-trust-lastpasscom.html' title='Should you trust lastpass.com?'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-7665603290844357813</id><published>2010-01-05T23:31:00.002+11:00</published><updated>2010-07-17T22:28:43.981+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mvvm'/><category scheme='http://www.blogger.com/atom/ns#' term='wpf'/><title type='text'>Expanding on Josh Smith's WPF MVVM app</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2010/01/expanding-on-josh-smiths-wpf-mvvm-app/"&gt;http://blog.tinisles.com/2010/01/expanding-on-josh-smiths-wpf-mvvm-app/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Over the holidays I've got a start on a new project idea.  I decided to do the simple UI of the project as an MVVM WPF app.  First thing to do was to google up some sample MVVM WPF app.  There are some very good example apps out there, some honourable mentions: &lt;a href="http://www.codeproject.com/KB/smart/Sonic.aspx"&gt;Sonic&lt;/a&gt;, Karl Shifflett's &lt;a href="http://www.codeproject.com/KB/WPF/ExploringWPFMVVM.aspx"&gt;Cipher&lt;/a&gt;, and Josh Smith's &lt;a href="http://msdn.microsoft.com/en-us/magazine/dd419663.aspx"&gt;MVVM Demo App&lt;/a&gt; (some good comments on the accompanying blog post: &lt;a href="http://joshsmithonwpf.wordpress.com/2009/01/27/my-mvvm-article-in-msdn-magazine/"&gt;My MVVM article in MSDN Magazine&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Josh's demo app is simple enough for me to quickly get my head around some WPF and MVVM concepts.  But the article includes a challenge :) :
&lt;blockquote&gt;The application does not have support for deleting or editing an existing customer, but that functionality, and many other features similar to it, are easy to implement by building on top of the existing application architecture.&lt;/blockquote&gt;
&lt;/p&gt;

&lt;p&gt;The following is a quick summary on how I added editing to the demo app.  This is TOTALLY up for debate.  I'm interested to know if I could've taken an easier approach.  In summary, I've added a RelayCommand '_editCommand' up in MainWindowViewModel to display the edit tab.  I pass this command down to CustomerViewModel so I can bind it to a new button on AllCustomersView.  Am I creating ViewModel's that are too tightly coupled?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MainWindowViewModel.cs
&lt;ul&gt;
&lt;li&gt;added a private field: &lt;br&gt;
ICommand _editCommand; 
&lt;li&gt;in the constructor this is pointed to a method in MainWindowViewModel: &lt;br&gt;
_editCommand = new RelayCommand(cust =&gt; EditCustomer(cust as CustomerViewModel));
&lt;li&gt;constructors for CustomerViewModel and AllCustomersViewModel are now passed _editCommand
&lt;li&gt;added method EditCustomer to display the workspace: &lt;br&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
void EditCustomer(CustomerViewModel workspace)
{
    WorkspaceViewModel exisitingModel = Workspaces.FirstOrDefault(cust =&amp;gt; cust is CustomerViewModel &amp;amp;&amp;amp; (cust as CustomerViewModel) ==  workspace);
    if (exisitingModel == null)
    {
        this.Workspaces.Add(workspace);
    }
    this.SetActiveWorkspace(workspace);
}
&lt;/pre&gt;
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;AllCustomersViewModel.cs
&lt;ul&gt;
&lt;li&gt;added a private field: &lt;br&gt;
ICommand _editCommand; 
&lt;li&gt;_editCommand is set by a new parameter in the constructor (passed in by MainWindowViewModel)
&lt;li&gt;_editCommand is passed to the CustomerViewModel constructor in OnCustomerAddedToRepository and CreateAllCustomers.
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;li&gt;CustomerViewModel.cs
&lt;ul&gt;
&lt;li&gt;added a private field: &lt;br&gt;
ICommand _editCommand; 
&lt;li&gt;_editCommand is set by a new parameter in the constructor
&lt;li&gt; fixed the _CustomerType defaulting to 'not specified':
&lt;br&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
_customerType = (this.IsNewCustomer) ? Strings.CustomerViewModel_CustomerTypeOption_NotSpecified :
    (_customer.IsCompany) ? Strings.CustomerViewModel_CustomerTypeOption_Company : 
    Strings.CustomerViewModel_CustomerTypeOption_Person;&lt;/pre&gt;
&lt;li&gt; exposed _EditCustomer as a public property: EditCustomer
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;AllCustomersView.xaml - bound a new 'Edit' button to the EditCommand
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: xml"&gt;
&amp;lt;GridViewColumn Header=&amp;quot;Action&amp;quot;&amp;gt;
    &amp;lt;GridViewColumn.CellTemplate&amp;gt;
        &amp;lt;DataTemplate&amp;gt;
            &amp;lt;StackPanel&amp;gt;
                &amp;lt;Button Content=&amp;quot;Edit&amp;quot; 
                        Command=&amp;quot;{Binding EditCustomer}&amp;quot; 
                        CommandParameter=&amp;quot;{Binding}&amp;quot;/&amp;gt;
            &amp;lt;/StackPanel&amp;gt;
        &amp;lt;/DataTemplate&amp;gt;
    &amp;lt;/GridViewColumn.CellTemplate&amp;gt;
&amp;lt;/GridViewColumn&amp;gt;&lt;/pre&gt;
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;


&lt;p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-7665603290844357813?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/7665603290844357813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=7665603290844357813' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/7665603290844357813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/7665603290844357813'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2010/01/expanding-on-josh-smiths-wpf-mvvm-app.html' title='Expanding on Josh Smith&amp;#39;s WPF MVVM app'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-5389907687042803092</id><published>2009-12-01T22:47:00.002+11:00</published><updated>2010-07-17T22:35:50.148+10:00</updated><title type='text'>Wifi Geolocation</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2009/12/wifi-geolocation/"&gt;http://blog.tinisles.com/2009/12/wifi-geolocation/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Playing around with Google Latitude I was VERY surprised to see Latitude work out my exact location.  How are they doing this?  I don't have a GPS in my netbook?&lt;/p&gt;

&lt;p&gt;Turns out they use &lt;a href="http://www.google.com/support/mobile/bin/topic.py?hl=en&amp;topic=15483"&gt;wifi location&lt;/a&gt; to do this.  When Latitude determines your location it gathers up a list of all the nearby Wifi SSIDs / MAC addresses and sends this to Google.  Google have a database of Wifi access point locations created by driving cars around.  This database, in combination with the nearby Wifi details, is used to determine your location.  Pretty amazing that this actually works!  &lt;a href="http://www.skyhookwireless.com/howitworks/wps.php"&gt;Skyhook wireless&lt;/a&gt; is the first company I heard about building a Wifi database.&lt;/p&gt;

&lt;p&gt;Always curious to see this stuff in action I fired up Fiddler to see exactly what is being sent to determine my location.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Request:&lt;/span&gt;&lt;br&gt;
&lt;pre&gt;POST /loc/json HTTP/1.1

{
  "access_token": "2:Fv--0aj9-Vr4_3ir:8uFyciMoILwtrXry", 
  "host": "lfkq9vbe9u4sg98ip8rfvf00l7atcn3d.ig.ig.gmodules.com", 
  "radio_type": "unknown", 
  "request_address": false, 
  "version": "1.1.0", 
  "wifi_towers": [
    {
      "mac_address": "00-0b-6b-81-7b-14", 
      "signal_strength": -72, 
      "ssid": "OA0509-0077-1-M"
    }, 
    {
      "mac_address": "00-0b-6b-81-7d-0d", 
      "signal_strength": -78, 
      "ssid": "OA0509-0096-1-1"
    }, 
    {
      "mac_address": "00-0b-6b-81-7d-0f", 
      "signal_strength": -85, 
      "ssid": "OA0509-0052-2-1"
    }, 
    {
      "mac_address": "00-0b-6b-81-7d-29", 
      "signal_strength": -80, 
      "ssid": "OA0509-0096-2-1"
    }, 
    {
      "mac_address": "00-0b-6b-81-7d-8a", 
      "signal_strength": -82, 
      "ssid": "OA0509-0101-1-1"
    }, 
    {
      "mac_address": "00-0b-6b-81-7e-bd", 
      "signal_strength": -79, 
      "ssid": "OA0509-0052-1-1"
    }, 
    {
      "mac_address": "00-22-3f-9b-f1-a4", 
      "signal_strength": -61, 
      "ssid": "2/107"
    }
  ]
}

&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Response:&lt;/span&gt;&lt;br&gt;
&lt;pre&gt;
{
  "location": {
    "accuracy": 165.0, 
    "latitude": -33.874097499999998, 
    "longitude": 151.20640280000001
  }
}
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Want to add geolocation to your own web application?  Check out the Google Gears &lt;a href="http://code.google.com/apis/gears/api_geolocation.html"&gt;Geolocation API&lt;/a&gt;, or the Firefox's &lt;a href="https://developer.mozilla.org/en/using_geolocation"&gt;geolocation&lt;/a&gt; object &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-5389907687042803092?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/5389907687042803092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=5389907687042803092' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/5389907687042803092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/5389907687042803092'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2009/12/wifi-geolocation.html' title='Wifi Geolocation'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-8307333941769946166</id><published>2009-09-20T00:09:00.003+10:00</published><updated>2010-07-17T22:35:57.111+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cryptography'/><category scheme='http://www.blogger.com/atom/ns#' term='dkim'/><title type='text'>Sending a DKIM Signed Email from C#</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2009/09/sending-a-dkim-signed-email-from-c/"&gt;http://blog.tinisles.com/2009/09/sending-a-dkim-signed-email-from-c/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;First off this code is intended to be instructional only!  Yes it is possible to send a DKIM email from .net's SmtpClient.  But there are a few hacks/warnings to go with the following code.  I'm pretty sure DKIM is designed for signatures to be added by the STMP server.  All the emails I've seen with DKIM signatures sign headers that would only be available to the server, e.g:  Message-ID and Received.  What does the RFC 4871 have to say about this:

&lt;blockquote&gt;Note that verifiers may treat unsigned header fields with extreme skepticism, including refusing to display them to the end user or even ignoring the signature if it does not cover certain header fields.  For this reason, signing fields present in the message such as Date, Subject, Reply-To, Sender, and all MIME header fields are highly advised.&lt;/blockquote&gt;

Second: We need to sign the message body exactly as SmtpClient is going to deliver it to the SMTP server.  Unfortunately MailMessage doesn't give us access to this.  I've found some code to do the &lt;a href="http://en.wikipedia.org/wiki/Quoted-printable"&gt;Quoted-printable&lt;/a&gt; encoding here: &lt;a href="http://www.nicecleanexample.com/ViewApp.aspx?TID=quoteprint"&gt;Nice Clean C# Generate Quoted-Printable&lt;/a&gt;.  Still we couldn't guarantee we are going to hash the body exactly as SmtpClient is going to send.  In this example I'm just replacing the carriage returns for an extremely simple sample email.
&lt;/p&gt;

&lt;p&gt;Let's get started.  First use OpenSSL to generate your public and private keys: &lt;a href="http://domainkeys.sourceforge.net/keygen.html"&gt;DomainKeys Public/Private Key-pair Generation&lt;/a&gt;.  Now add the public key to the relevant TXT record on the domain you intend to send email from.  I bought a cheap .info domain for this demo, and pointed the registrar to &lt;a href="http://zoneedit.com/"&gt;ZoneEdit&lt;/a&gt;.  I had no trouble adding to TXT record to my domain via ZoneEdit.&lt;/p&gt;

&lt;p&gt;...and now the code: (again I'm using  &lt;a href="http://www.bouncycastle.org/"&gt;Bouncy Castle Crypto APIs&lt;/a&gt; to create the signature)&lt;/p&gt;

&lt;p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
string smtp = &amp;quot;~~ YOUR STMP SERVER HERE ~~&amp;quot;;
string from = &amp;quot;russ@dkimtester.info&amp;quot;;
string subject = &amp;quot;dkim test email&amp;quot;;
string to = &amp;quot;check-auth@verifier.port25.com&amp;quot;;
string body = &amp;quot;This is the body of the message.&amp;quot; + Environment.NewLine + &amp;quot;This is the second line&amp;quot;;
string base64privatekey = @&amp;quot;-----BEGIN RSA PRIVATE KEY-----
~~ YOUR PRIVATE KEY HERE ~~
-----END RSA PRIVATE KEY-----&amp;quot;;

HashAlgorithm hash = new SHA256Managed();
// HACK!! simulate the quoted-printable encoding SmtpClient will use
string hashBody = body.Replace(Environment.NewLine, &amp;quot;=0D=0A&amp;quot;) + Environment.NewLine;
byte[] bodyBytes = Encoding.ASCII.GetBytes(hashBody);
string hashout = Convert.ToBase64String(hash.ComputeHash(bodyBytes));
// timestamp  - seconds since 00:00:00 on January 1, 1970 UTC
TimeSpan t = DateTime.Now.ToUniversalTime() - DateTime.SpecifyKind(DateTime.Parse(&amp;quot;00:00:00 January 1, 1970&amp;quot;), DateTimeKind.Utc);

string signatureHeader = &amp;quot;v=1; &amp;quot; +
 &amp;quot;a=rsa-sha256; &amp;quot; +
 &amp;quot;c=relaxed/relaxed; &amp;quot; +
 &amp;quot;d=dkimtester.info; &amp;quot; +
 &amp;quot;s=p; &amp;quot; +
 &amp;quot;t=&amp;quot; + Convert.ToInt64(t.TotalSeconds) + &amp;quot;; &amp;quot; +
 &amp;quot;bh=&amp;quot; + hashout + &amp;quot;; &amp;quot; +     
 &amp;quot;h=From:To:Subject:Content-Type:Content-Transfer-Encoding; &amp;quot; +
 &amp;quot;b=&amp;quot;; 

string canonicalizedHeaders =
&amp;quot;from:&amp;quot; + from + Environment.NewLine +
&amp;quot;to:&amp;quot; + to + Environment.NewLine +
&amp;quot;subject:&amp;quot; + subject + Environment.NewLine +
@&amp;quot;content-type:text/plain; charset=us-ascii
content-transfer-encoding:quoted-printable
dkim-signature:&amp;quot; + signatureHeader;

TextReader reader = new StringReader(base64privatekey);
Org.BouncyCastle.OpenSsl.PemReader r = new Org.BouncyCastle.OpenSsl.PemReader(reader);
AsymmetricCipherKeyPair o = r.ReadObject() as AsymmetricCipherKeyPair;
byte[] plaintext = Encoding.ASCII.GetBytes(canonicalizedHeaders);
ISigner sig = SignerUtilities.GetSigner(&amp;quot;SHA256WithRSAEncryption&amp;quot;);
sig.Init(true, o.Private);
sig.BlockUpdate(plaintext, 0, plaintext.Length);
byte[] signature = sig.GenerateSignature();
signatureHeader += Convert.ToBase64String(signature);

MailMessage message = new MailMessage();
message.From = new MailAddress(from);
message.To.Add(new MailAddress(to));
message.Subject = subject;
message.Body = body;

message.Headers.Add(&amp;quot;DKIM-Signature&amp;quot;, signatureHeader);
SmtpClient client = new SmtpClient(smtp);
client.Send(message);
Console.Write(&amp;quot;sent to: &amp;quot; + to);&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
An email sent to gmail gets the cool "signed-by" info:

&lt;a href="http://blog.tinisles.com/blogger-images/2009/09/lg_dkim_signed.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2009/09/sm_dkim_signed.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 153px;" /&gt;&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-8307333941769946166?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/8307333941769946166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=8307333941769946166' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/8307333941769946166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/8307333941769946166'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2009/09/sending-dkim-email-from-c.html' title='Sending a DKIM Signed Email from C#'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-4011143759790479115</id><published>2009-08-30T23:44:00.008+10:00</published><updated>2010-07-17T22:36:02.322+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cryptography'/><category scheme='http://www.blogger.com/atom/ns#' term='dkim'/><title type='text'>Verifying a DKIM signature in C#</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2009/08/verifying-a-dkim-signature-in-c/"&gt;http://blog.tinisles.com/2009/08/verifying-a-dkim-signature-in-c/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Quick background: &lt;a href="http://en.wikipedia.org/wiki/Dkim"&gt;DomainKeys Identified Mail&lt;/a&gt; (DKIM) is a digital signature and hash which are placed on your emails to verify they are coming from the domain they claim to be.  One step in the defence against SPAM and phishing emails.&lt;/p&gt;

&lt;p&gt;What does the signature look like.  Here's a signature grabbed from an email sent from Yahoo mail:

&lt;span style="font-size:x-small"&gt;
&lt;pre&gt;
DKIM-Signature: 
 v=1; 
 a=rsa-sha256; 
 c=relaxed/relaxed; 
 d=yahoo.com.au; 
 s=s1024; 
 t=1250214285; 
 bh=cHSvmWBBhlnc7HYJ0cXdBZfzQDwcJskaGayavbFvzSY=; 
 h=Message-ID:X-YMail-OSG:Received:X-Mailer:Date:From:Subject:To:MIME-Version:Content-Type; 
 b=gsz2P/9h3SL8PwBIU8g9dMGnHI+mwfSqjDhrkJljG3HNCbL0I4/DZJBGHnuqRwgpP4Rq0K3E/1z2Zwez4OhMI+naVzGg0P0ePG75GOwfXvl0XBvN8x8j1pgIOS8KQS24E1+6RogWIKJR2mht+KwiFK5uq3BYc9+nC9XMWsIE1fw=
&lt;/pre&gt;
&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;Verifying a signature is going to require a public key.  The public key is grabbed from a TXT record on the sender's the domain.  The domain name is built with the "s" and "d" tags above.  "s" + "._domainkey." + d = "s1024._domainkey.yahoo.com.au".
&lt;/p&gt;

&lt;p&gt;
Using nslookup from the command prompt give us:
&lt;span style="font-size:x-small"&gt;
&lt;pre&gt;
C:\&gt;nslookup
Default Server:  DD-WRT
Address:  192.168.1.1

&gt; set type=TXT
&gt; s1024._domainkey.yahoo.com.au
Server:  DD-WRT
Address:  192.168.1.1

Non-authoritative answer:
s1024._domainkey.yahoo.com.au   text =

        "k=rsa; t=y; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4Pel
eB3gfm"
        "JiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB; n=A 1024 bit key
;"
&lt;/pre&gt;
&lt;/span&gt;

&lt;/p&gt;

&lt;p&gt;The "b=" tag in DKIM-Signature is a signature of the canonicalized headers.  The canonicalization process is done to make sure the signature is resilient to header modifications by mail servers.  In this example we are using the 'relaxed' canonicalization algorithm.  (Much more details about canonicalization in the &lt;a href="http://tools.ietf.org/html/rfc4871#section-3.4"&gt;RFC4871&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;
The original headers:
&lt;span style="font-size:x-small"&gt;
&lt;pre&gt;
Message-ID: &lt;88014.32082.qm@web112514.mail.gq1.yahoo.com&gt;
X-YMail-OSG: aJFcCYUVM1mfioaf5zF7Pv_aQQ27DjD57ShG_QdRO6jTz5SGM4lVBkiJ1SD0tZmtvLEHhR4YtNFpTpI26b3VFERE44rlTAN3nP7a9.snzPvxcIIVOy6d0XWg1fvWS5bpOInMbv7M0bltJc6ml3gWPn8S3tT6U.Wz4OXu22meLo5VrikBRKeSGItA5Kw5Asn20GT84javGzv9_3znhG0HMejyHxpDjDbn.C_9OpKMVheG6HmBpgFVYmsW9q2IKc4r08YZvyADKNKnjN066fNhCNaYKWu3PEpHpbV4pZf66cFChegx94phIMQCI0cScc8ZQ5BLRj7qwV2F85C2ib22DWbZvTY-
Received: from [114.76.223.211] by web112514.mail.gq1.yahoo.com via HTTP; Thu, 13 Aug 2009 18:44:43 PDT
X-Mailer: YahooMailRC/1358.27 YahooMailWebService/0.7.338.2
Date: Thu, 13 Aug 2009 18:44:43 -0700 (PDT)
From: Russell Sayers &lt;russell_sayers@yahoo.com.au&gt;
Subject: from yahoo
To: diagnostic@smtp2web.com
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="0-1193717202-1250214283=:32082"
&lt;/pre&gt;
&lt;/span&gt;

After relaxed canonicalization:
&lt;span style="font-size:x-small"&gt;
&lt;pre&gt;
message-id:&lt;88014.32082.qm@web112514.mail.gq1.yahoo.com&gt;
x-ymail-osg:aJFcCYUVM1mfioaf5zF7Pv_aQQ27DjD57ShG_QdRO6jTz5SGM4lVBkiJ1SD0tZmtvLEHhR4YtNFpTpI26b3VFERE44rlTAN3nP7a9.snzPvxcIIVOy6d0XWg1fvWS5bpOInMbv7M0bltJc6ml3gWPn8S3tT6U.Wz4OXu22meLo5VrikBRKeSGItA5Kw5Asn20GT84javGzv9_3znhG0HMejyHxpDjDbn.C_9OpKMVheG6HmBpgFVYmsW9q2IKc4r08YZvyADKNKnjN066fNhCNaYKWu3PEpHpbV4pZf66cFChegx94phIMQCI0cScc8ZQ5BLRj7qwV2F85C2ib22DWbZvTY-
received:from [114.76.223.211] by web112514.mail.gq1.yahoo.com via HTTP; Thu, 13 Aug 2009 18:44:43 PDT
x-mailer:YahooMailRC/1358.27 YahooMailWebService/0.7.338.2
date:Thu, 13 Aug 2009 18:44:43 -0700 (PDT)
from:Russell Sayers &lt;russell_sayers@yahoo.com.au&gt;
subject:from yahoo
to:diagnostic@smtp2web.com
mime-version:1.0
content-type:multipart/alternative; boundary="0-1193717202-1250214283=:32082"
&lt;/pre&gt;
&lt;/span&gt;
&lt;p&gt;

&lt;p&gt;Now the canonicalized signature, minus the "b=" value. is placed after the headers.  This had me scratching my head for a bit until I read this from the RFC:

&lt;blockquote&gt;The header field MUST be presented to the hash algorithm after the body of the message rather than with the rest of the header fields and MUST be canonicalized as specified in the "c=" (canonicalization) tag.  The DKIM-Signature header field MUST NOT be included in its own h= tag..&lt;/blockquote&gt;

&lt;/p&gt;

&lt;p&gt;We now have everything we need to verify the signature on the email using &lt;a href="http://www.bouncycastle.org/"&gt;Bouncy Castle Crypto APIs&lt;/a&gt;&lt;/p&gt;

&lt;span style="font-size:x-small"&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
string base64pubkey = &amp;quot;MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB&amp;quot;;
RsaKeyParameters pubKey = PublicKeyFactory.CreateKey(Convert.FromBase64String(base64pubkey)) as RsaKeyParameters;
byte[] signature = Convert.FromBase64String(&amp;quot;gsz2P/9h3SL8PwBIU8g9dMGnHI+mwfSqjDhrkJljG3HNCbL0I4/DZJBGHnuqRwgpP4Rq0K3E/1z2Zwez4OhMI+naVzGg0P0ePG75GOwfXvl0XBvN8x8j1pgIOS8KQS24E1+6RogWIKJR2mht+KwiFK5uq3BYc9+nC9XMWsIE1fw=&amp;quot;);

string canonicalized =
@&amp;quot;message-id:&amp;lt;88014.32082.qm@web112514.mail.gq1.yahoo.com&amp;gt;
x-ymail-osg:aJFcCYUVM1mfioaf5zF7Pv_aQQ27DjD57ShG_QdRO6jTz5SGM4lVBkiJ1SD0tZmtvLEHhR4YtNFpTpI26b3VFERE44rlTAN3nP7a9.snzPvxcIIVOy6d0XWg1fvWS5bpOInMbv7M0bltJc6ml3gWPn8S3tT6U.Wz4OXu22meLo5VrikBRKeSGItA5Kw5Asn20GT84javGzv9_3znhG0HMejyHxpDjDbn.C_9OpKMVheG6HmBpgFVYmsW9q2IKc4r08YZvyADKNKnjN066fNhCNaYKWu3PEpHpbV4pZf66cFChegx94phIMQCI0cScc8ZQ5BLRj7qwV2F85C2ib22DWbZvTY-
received:from [114.76.223.211] by web112514.mail.gq1.yahoo.com via HTTP; Thu, 13 Aug 2009 18:44:43 PDT
x-mailer:YahooMailRC/1358.27 YahooMailWebService/0.7.338.2
date:Thu, 13 Aug 2009 18:44:43 -0700 (PDT)
from:Russell Sayers &amp;amp;lt;russell_sayers@yahoo.com.au&amp;amp;gt;
subject:from yahoo
to:diagnostic@smtp2web.com
mime-version:1.0
content-type:multipart/alternative; boundary=&amp;quot;&amp;quot;0-1193717202-1250214283=:32082&amp;quot;&amp;quot;
dkim-signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com.au; s=s1024; t=1250214285; bh=cHSvmWBBhlnc7HYJ0cXdBZfzQDwcJskaGayavbFvzSY=; h=Message-ID:X-YMail-OSG:Received:X-Mailer:Date:From:Subject:To:MIME-Version:Content-Type; b=&amp;quot;;
byte[] message = Encoding.ASCII.GetBytes(canonicalized);


ISigner sig = SignerUtilities.GetSigner(&amp;quot;SHA256WithRSAEncryption&amp;quot;);
sig.Init(false, pubKey);
sig.BlockUpdate(message, 0, message.Length);
if (sig.VerifySignature(signature))
{
    Console.WriteLine(&amp;quot;all good!&amp;quot;);
}&lt;/pre&gt;
&lt;/span&gt;

&lt;p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-4011143759790479115?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/4011143759790479115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=4011143759790479115' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4011143759790479115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4011143759790479115'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2009/08/verifying-dkim-signature-in-c.html' title='Verifying a DKIM signature in C#'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-905929164140541510</id><published>2009-04-05T17:30:00.002+10:00</published><updated>2010-07-17T22:36:36.229+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='azure'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Windows Azure - SlashView</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2009/04/windows-azure-slashview/"&gt;http://blog.tinisles.com/2009/04/windows-azure-slashview/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;span style="font-weight:bold;"&gt;Update (18-Sept-2009): &lt;/span&gt;  Hot off twitter:  &lt;a href="http://blogs.msdn.com/windowsazure/archive/2009/09/17/introducing-the-windows-azure-service-management-api.aspx"&gt;Introducing the Windows Azure Service Management API&lt;/a&gt; - my wish (below) has been granted. :)

&lt;p&gt;Here's my first attempt playing around with Azure: &lt;a href="http://slashview.cloudapp.net/"&gt;SlashView&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;The idea behind the site is pretty simple - I've got a worker process scraping all the comments off &lt;a href="http://slashdot.org"&gt;Slashdot&lt;/a&gt; every 10 minutes.  I get all the stats off the comments, and display the results in a Silverlight graph.&lt;/p&gt;

&lt;p&gt;The learning curve for Azure isn't too steep if you are already an ASP.NET developer.  The only new technology I've had come up to speed with is the deployment process, and the table/blog storage services.&lt;/p&gt;

&lt;p&gt;Some indispensable resources I've discovered along the way:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.codeplex.com/azurestorageexplorer"&gt;Azure Storage Explorer&lt;/a&gt; - From the codeplex description: "Azure Storage Explorer is a useful GUI tool for inspecting the data in your Azure cloud storage projects including the logs of your cloud-hosted applications. All three types of cloud storage can be viewed: blobs, queues, and tables."
&lt;li&gt;&lt;a href="http://blogs.msdn.com/jnak/archive/2008/10/29/walkthrough-simple-blob-storage-sample.aspx"&gt;Windows Azure Walkthrough: Blob Storage Sample&lt;/a&gt; - good introduction to blob storage
&lt;li&gt;&lt;a href="http://oakleafblog.blogspot.com/2008/11/azure-storage-services-test-harness.html"&gt;Azure Storage Services Test Harness: Table Services 1 – Introduction and Overview&lt;/a&gt; - contains some info on paging table storage data (which I'm yet to implement)
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/dd179355.aspx"&gt;REST API Reference for Windows Azure Storage Service&lt;/a&gt; - rather than totally relying on the &lt;a href="http://msdn.microsoft.com/en-us/library/dd135716.aspx"&gt;StorageClient&lt;/a&gt; library that comes with all the samples.
&lt;li&gt;Interesting tidbit - all the azure domains appear to have unique IPs.  I just assumed everything would be going thru host headers.  This makes it possible to use your own domain for an Azure app: &lt;a href="http://blog.smarx.com/posts/custom-domain-names-in-windows-azure"&gt;Custom Domain Names in Windows Azure&lt;/a&gt;.
&lt;li&gt;I would assume this also makes it possible to add an SSL cert to as Azure app (&lt;a href="http://msdn.microsoft.com/en-us/library/dd203056.aspx"&gt;Enabling SSL Connections on Windows Azure&lt;/a&gt;).  The MSDN article is a bit light on details, it sounds like you go thru the CSR/purchase cert process away from Azure.  Then ensure you can export the cert to have to included in a deploy?
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;Wish list: an automated deploy.  It can take a long while to 'Suspend', 'Delete', 'Deploy' from the developer portal..&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-905929164140541510?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/905929164140541510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=905929164140541510' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/905929164140541510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/905929164140541510'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2009/04/windows-azure-slashview.html' title='Windows Azure - SlashView'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-4233076652950644488</id><published>2009-03-01T10:04:00.007+11:00</published><updated>2010-07-17T22:36:43.237+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='azure'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Windows Azure - Getting Started</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2009/02/windows-azure-getting-started/"&gt;http://blog.tinisles.com/2009/02/windows-azure-getting-started/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Windows Azure - so where do you get started?  Some links:

&lt;ul&gt;
&lt;li&gt;Dare Obasanjo's &lt;a href="http://www.25hoursaday.com/weblog/2008/11/03/WindowsAzureFromADevelopersPerspective.aspx"&gt;Windows Azure from a Developer's Perspective&lt;/a&gt; - cuts though all the info that is out there and spells out exactly what a developer can expect from Azure.
&lt;li&gt;Katrien De Graeve &lt;a href="http://blogs.msdn.com/katriend/archive/2009/01/04/windows-azure-installing-sdk-tools-and-creating-a-first-cloud-project.aspx"&gt;Windows Azure – installing SDK, tools and creating a first cloud project &lt;/a&gt; - has the link to request a evaluation token.  Two days after after filling out the survey I got an "Invitation Code to Microsoft .NET Services and Microsoft SQL Services", a day after this I got an "Invitation Code to Windows Azure".  Katrien's article also contains links to the SDK and Visual Studio tools you will need to get started.
&lt;li&gt;Maarten Balliauw's - &lt;a href="http://blog.maartenballiauw.be/post/2008/12/09/Track-your-car-expenses-in-the-cloud!-CarTrackr-on-Windows-Azure-Part-1-Introduction.aspx"&gt;CarTrackr on Windows Azure&lt;/a&gt;.
&lt;li&gt;First road block - trying to run an Azure project in Visual Studio requires 'elevated privileges'.  So (at least in Vista) you'll need do a right-click 'run as administrator' when you fire up Visual Studio.  The issue is described in : &lt;a href="http://blogs.msdn.com/virtualearth/archive/2009/02/18/microsoft-virtual-earth-on-windows-azure.aspx"&gt;Microsoft Virtual Earth on Windows Azure&lt;/a&gt; 
&lt;li&gt; Getting Table Storage to work: &lt;a href="http://blogs.msdn.com/jnak/archive/2008/10/28/walkthrough-simple-table-storage.aspx"&gt;Windows Azure Walkthrough: Simple Table Storage&lt;/a&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;I've done articles on Amazon's &lt;a href="http://tinisles.blogspot.com/2008/04/amazon-elastic-compute-cloud-ec2.html"&gt;EC2&lt;/a&gt; and Google's &lt;a href="http://tinisles.blogspot.com/2008/12/google-app-engine-tetris-challenge.html"&gt;AppEngine&lt;/a&gt; - so I guess I'm obligated to do an Azure article, right? :)
&lt;/p&gt;

&lt;p&gt;
I do have an Azure idea in the works.  It's not very exciting to write an app that is barely different to something I could do on my cheap ASP.NET hosting.  Something that cheap hosting &lt;span style="font-style:italic;"&gt;doesn't&lt;/span&gt; offer is an easy way to write a background processing application such as the Azure worker role. So I've revived a 'shelved' screen scraping application.  The idea is to pull down all the comments on Slashdot articles, and generate some visualization of the comments growing over time.  
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-4233076652950644488?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/4233076652950644488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=4233076652950644488' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4233076652950644488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4233076652950644488'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2009/03/windows-azure-getting-started.html' title='Windows Azure - Getting Started'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-6136920740105389867</id><published>2009-02-18T20:05:00.003+11:00</published><updated>2010-07-17T22:36:47.082+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mvvm'/><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><title type='text'>Silverlight 2: MVVM, Databinding &amp; Cascading ComboBoxes - Part 2</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2009/02/silverlight-2-mvvm-databinding-cascading-comboboxes-part-2/"&gt;http://blog.tinisles.com/2009/02/silverlight-2-mvvm-databinding-cascading-comboboxes-part-2/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;So I've finally got a fix for this issue.  The solution does feel like a bit of a hack - but I can understand why I need to go down this path.  Hopefully one of the people who read this post will be inspired to come up with a more elegant solution!&lt;/p&gt;

&lt;p&gt;See a demo of '&lt;a href="http://blog.time2call.net/CitiesVisited_step3/testpage.html"&gt;cascading ComboBoxes in Silverlight 2&lt;/a&gt;', and get the source here: &lt;a href="http://blog.time2call.net/CitiesVisited_step3.zip"&gt;CitiesVisited_step3.zip&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I finished the last post with two possible solutions.  The first option was to bind the 'cities' ComboBox to a collection containing a union of all the possible cities - and toggling a visibility property as the country changes.  I attempted to code this, but it had two strange side effects.  The text part of the drop down, e.g. just where it has 'Melbourne', became unresponsive to mouse clicks.  And the ComboBoxListItems with Visibility toggles to collapsed still appeared in the ComboBox empty and a few pixels tall.&lt;/p&gt;

&lt;p&gt;The second option was two combine the previous/new lists of cities just at the time when Visit.City is being databound, then removed all previous cities.  This approach I did get to work!&lt;/p&gt;

&lt;p&gt;
The PageViewModel gets two new properties BindCity and BindableCities bound to the cities ComboBox.  BindCity is just a wrapper for _SelectedVisit.City, this exists so I can control when the UI is notified about the city change.
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
public City BindCity
{
    get { return _SelectedVisit.City; }
    set
    {
        _SelectedVisit.City = value;
        OnPropertyChanged(&amp;quot;BindCity&amp;quot;);
    }
}


public ObservableCollection&amp;lt;City&amp;gt; BindableCities
{
    get { return _BindableCities; }
}
&lt;/pre&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
&amp;lt;ComboBox 
    ItemsSource=&amp;quot;{Binding BindableCities}&amp;quot; 
    SelectedItem=&amp;quot;{Binding BindCity, Mode=TwoWay}&amp;quot; 
    DisplayMemberPath=&amp;quot;Name&amp;quot;/&amp;gt;&lt;/pre&gt;

&lt;/p&gt;

&lt;p&gt;
The SelectedVisit setter is now doing a lot more.  There are two scenarios where I need to update the BindableCities collection: when the SelectedVisit is changed (by clicking on a left-hand visit), and when the Country ComboBox is changed.  When a new SelectedVisit is set by the databinding, the SwitchBindableCities method populates the BindableCities with the combination of cities.  Here I'm also attaching to the PropertyChanged event of the SelectedVisit - to populate the BindableCities when the Country ComboBox changes.
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
public Visit SelectedVisit
{
    get { return _SelectedVisit; }
    set
    {
        if (_SelectedVisit != null)
        {
            _SelectedVisit.PropertyChanged -= new PropertyChangedEventHandler(_SelectedVisit_PropertyChanged);
        }
        _SelectedVisit = value;
        _SelectedVisit.PropertyChanged += new PropertyChangedEventHandler(_SelectedVisit_PropertyChanged);

        SwitchBindableCities(true);
        OnPropertyChanged(&amp;quot;SelectedVisit&amp;quot;);
    }
}

void _SelectedVisit_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    // the country property of the visit has changed
    // update the bindable cities
    if (e.PropertyName == &amp;quot;Country&amp;quot;)
    {
        SwitchBindableCities(false);
    }
}&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Where it all happens.  The SwitchBindableCities method:
&lt;ol&gt;
&lt;li&gt;First 'if': we've arrived here from someone changing a Country drop down, set the _SelectedVisit.City to null.  E.g someone changing from Australia/Melbourne to United States.  The City=Melbourne gets set to null.
&lt;li&gt;Second 'if': we've arrived here from someone toggling between Visits. If the BindableCities collection already contains what we want - it is save to allow the data binding to happen, then we can exit with the BindableCities untouched.
&lt;li&gt;The remainder of the method changes the list of cities.  First it stores the list of cities presently in BindableCities.  Adds the 'new' cities to the collection.  Then raises the property changed on BindCity.  The UI now does the binding when the BindableCities collection contains the UNION of cities.  Now its safe to remove the original list of cities from BindableCities.
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ol&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
private void SwitchBindableCities(bool visitChanged)
{
    if (!visitChanged)
    {
        // changed the country, and the visit city isn't in that
        // country - so set the city to null
        _SelectedVisit.City = null;
    }

    if (visitChanged &amp;amp;&amp;amp; _BindableCities.Contains(_SelectedVisit.City))
    {
        // the selected vist city IS in the selected country
        // and already in the bindable cities
        OnPropertyChanged(&amp;quot;BindCity&amp;quot;);
        return;
    }

    List&amp;lt;City&amp;gt; toBeRemoved = _BindableCities.ToList();
    foreach (City c in _SelectedVisit.Country.Cities)
    {
        _BindableCities.Add(c);
    }

    // tell the UI that the bind city has changed
    OnPropertyChanged(&amp;quot;BindCity&amp;quot;);

    foreach (City c in toBeRemoved)
    {
        _BindableCities.Remove(c);
    }
}&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;

&lt;p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-6136920740105389867?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/6136920740105389867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=6136920740105389867' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/6136920740105389867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/6136920740105389867'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2009/02/silverlight-2-mvvm-databinding_18.html' title='Silverlight 2: MVVM, Databinding &amp;amp; Cascading ComboBoxes - Part 2'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-7262937806286880112</id><published>2009-02-17T23:33:00.003+11:00</published><updated>2010-07-17T22:36:49.589+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mvvm'/><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><title type='text'>Silverlight 2: MVVM, Databinding &amp; Cascading ComboBoxes - Part 1</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2009/02/silverlight-2-mvvm-databinding-cascading-comboboxes-part-1/"&gt;http://blog.tinisles.com/2009/02/silverlight-2-mvvm-databinding-cascading-comboboxes-part-1/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;
Update: see follow up post to see how I got the cascading ComboBoxes to work: I did mange to get a 'working' solution for cascading ComboBoxes - see the solution here:
&lt;a href="http://tinisles.blogspot.com/2009/02/silverlight-2-mvvm-databinding_18.html "&gt;Silverlight 2: MVVM, Databinding &amp; Cascading ComboBoxes - Part 2&lt;/a&gt;

&lt;p&gt;

&lt;p&gt;I'm presently working on a Silverlight 2 application at work, and really enjoying the getting into the new technology.  Hitting a few issues along the way that are going to make good blog articles when I find the time.  This article intends to be the first in a series to demonstrate some of the issues I'm discovering.&lt;/p&gt;

&lt;p&gt;Issue no. 1: Databinding Cascading ComboBoxes to a ViewModel.&lt;/p&gt;

&lt;p&gt;If you've been following Silverlight 2 developer blogs you'll notice Model-View-ViewModel (MVVM) is a popular separation pattern for UI.  Luckily Craig of &lt;a href="http://conceptdev.blogspot.com/"&gt;ConceptDev&lt;/a&gt; has already pulled together a good list of links for those wanting to read up on MVVM: &lt;a href="http://conceptdev.blogspot.com/2009/02/silverlight-model-view-viewmodel-mvvm.html"&gt;Silverlight + Model-View-ViewModel (MVVM)&lt;/a&gt;.  My first introduction to MVVM was the &lt;a href="http://jonas.follesoe.no/TechEd2008NdashSilverlight2ForDevelopers.aspx"&gt;Divelog app&lt;/a&gt; from &lt;a href="http://jonas.follesoe.no/"&gt;Jonas Follesø&lt;/a&gt;.  The Divelog app is a good introduction to several concepts: silverlight unit tests, dependency injection, command pattern and MVVM &lt;/p&gt;

&lt;p&gt;The actual problem.  Let's say we are building an app of all the cities you've visited around the world.  The Model classes involved:  A Country class contains a collection of Cities, and a Visit class contains references to a Country and a City.  The PageViewModel contains: Countries collection of all countries, Visits collection of all visit, and a SelectedVisit property.

&lt;a href="http://blog.tinisles.com/blogger-images/2009/02/lg_cccb_class_diagram.png"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2009/02/sm_cccb_class_diagram.png" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 230px;" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt; 
The databinding seems simple...
&lt;a href="http://blog.tinisles.com/blogger-images/2009/02/lg_cccb_screenshot01.png"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2009/02/sm_cccb_screenshot01.png" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 253px;" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
...but clicking on the 2nd visit causes the city on the first option to disappear.  See a demo of the issue: &lt;a href="http://blog.time2call.net/CitiesVisited_step1/testpage.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
Anything related to databinding issues is best understood by attaching some 'do nothing' Converter classes.  Inside the Converter I've added debugging statements to try work out what order things are happening.  The debugging output from the Converters looks like this:
&lt;a href="http://blog.tinisles.com/blogger-images/2009/02/lg_cccb_debug_output.png"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2009/02/sm_cccb_debug_output.png" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 333px; height: 400px;" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The statements after the red line were created after the second option was clicked.  This is how I interpreted the output after the red line:
&lt;ol&gt;
&lt;li&gt;The ItemSelected property of the countries ComboBox is set to 'United States'
&lt;li&gt;The ItemSource property of the cities ComboBox is populated with the cities belonging to the 'United States'
&lt;li&gt;The interesting bit: ConvertBack is telling us that the city selected in the first option (previously Melbourne) is now null!
&lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;My theory: in step number 2 we are changing the contents of a ComboBox still bound to the 'Melbourne' visit.  The databinding between the ComboBox and Visit.City fires, cannot find a city in the Visit.Country.Cities and interprets this as null.&lt;/p&gt;

&lt;p&gt;The fix.... comes in my next blog post.  I've experimented with two approaches for the issue.  Approach 1: binding the city ComboBox to a different collection which is temporarily populated with the ALL the possible cities when the PageViewModel.SelectedVisit changes.  Approach 2: again populate the city ComboBox will all possible cities - and use databinding to modify the city's visibility.&lt;/p&gt;

&lt;p&gt;Grab the source code for this demo: &lt;a href="http://blog.time2call.net/CitiesVisited_step1.zip"&gt;CitiesVisited_step1.zip&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-7262937806286880112?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/7262937806286880112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=7262937806286880112' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/7262937806286880112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/7262937806286880112'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2009/02/silverlight-2-mvvm-databinding.html' title='Silverlight 2: MVVM, Databinding &amp;amp; Cascading ComboBoxes - Part 1'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-916999920563285627</id><published>2008-12-02T22:51:00.000+11:00</published><updated>2010-07-17T22:36:59.362+10:00</updated><title type='text'>Google App Engine - Tetris Challenge</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/12/google-app-engine-tetris-challenge/"&gt;http://blog.tinisles.com/2008/12/google-app-engine-tetris-challenge/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Here's my attempt to learn &lt;a href="http://code.google.com/appengine/"&gt;Google App Engine&lt;/a&gt; / &lt;a href="http://www.python.org/"&gt;python&lt;/a&gt;:  The Tetris code
challenge, you write a tetris playing algorithm, and the app
challenges your algorithm.&lt;/p&gt;

&lt;p&gt;Anyone can write an auto-player algorithm in anything that can do &lt;a href="http://en.wikipedia.org/wiki/Common_Gateway_Interface"&gt;cgi&lt;/a&gt;: php, asp.net,
jsp, etc.  I've provided a sample client that can easily be hosted on
App Engine itself.&lt;/p&gt;

&lt;p&gt;Check it out here: &lt;a href="http://tetrisapp.appspot.com/"&gt;http://tetrisapp.appspot.com/&lt;/a&gt; - it will default to
my sample algorithm..  You'll need a gmail/google account to log in.&lt;/p&gt;

&lt;p&gt;Read more on how to write your own algorithm here:
&lt;a href="http://tetrisapp.appspot.com/static/howto.html"&gt;http://tetrisapp.appspot.com/static/howto.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its a bit rough at the moment.. If you struggle with any of the
details let me know - I really need to get the documentation a bit
more readable.  I've got more features to add, depending on how
popular it is.. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-916999920563285627?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/916999920563285627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=916999920563285627' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/916999920563285627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/916999920563285627'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/12/google-app-engine-tetris-challenge.html' title='Google App Engine - Tetris Challenge'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-5813266154206168371</id><published>2008-11-24T21:31:00.007+11:00</published><updated>2010-08-03T07:43:57.670+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='iis'/><title type='text'>IIS, SSL and Host-Headers</title><content type='html'>&lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/11/iis-ssl-and-host-headers/"&gt;http://blog.tinisles.com/2008/11/iis-ssl-and-host-headers/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;

&lt;strong&gt;Update (3-Aug-2010)&lt;/strong&gt;: Multiple SSL domains on a single IP are now possible using Unified Communications UC SSL Certificates (Subject Alternative Name) - see my follow up article: &lt;a href="http://blog.tinisles.com/2010/08/subject-alternative-names-for-ssl/"&gt;Subject Alternative Names for SSL&lt;/a&gt;
            
            &lt;p&gt;Here's a knowledge base article I use to explain why an SSL site needs its own IP address: &lt;a href="http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q187504&amp;ID=KB;EN-US;Q187504"&gt;HTTP 1.1 host headers are not supported when you use SSL&lt;/a&gt;.  Host headers allow a web server to host several websites on the same IP address.  When a browser makes a request the domain name of the website is passed in the request host header.  The server uses this to check against the list of websites it is serving.  When this is combined with SSL the server needs to know which website's private certificate to establish the secure session - which is impossible as the session is established before any HTTP headers are sent.&lt;/p&gt;

&lt;p&gt;Yet the article says: "Beginning in Windows Server 2003 Service Pack 1 (SP1) and IIS 6.0, Secure Sockets Layer (SSL) host headers are supported in IIS.", and points you to the article: &lt;a href="http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/596b9108-b1a7-494d-885d-f8941b07554c.mspx"&gt;Configuring SSL Host Headers (IIS 6.0)&lt;/a&gt;.  So we are all covered now?  Well, no.  The issue of SSL session being established before the host header still exists.  IIS 6 only supports host headers where all the sites being served use the same wildcard SSL certificate; e.g. *.mydomain.com.au.  The server doesn't need to know the host header when establishing the session, as there is only one certificate to choose from.&lt;/p&gt;

&lt;p&gt;Why not include the the host header when we establish SSL?  That is the plan of &lt;a href="http://en.wikipedia.org/wiki/Server_Name_Indication"&gt;Server Name Indication&lt;/a&gt; - this does mean web browsers and servers all need to be updated to support the new standard.  So it will be a while before SNI is well supported on the web.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-5813266154206168371?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/5813266154206168371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=5813266154206168371' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/5813266154206168371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/5813266154206168371'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/11/iis-ssl-and-host-headers.html' title='IIS, SSL and Host-Headers'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-3786546582753516296</id><published>2008-10-25T13:48:00.007+11:00</published><updated>2010-07-17T22:37:03.703+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><title type='text'>Amazon EC2 - Now with Windows Server 2003!</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/10/amazon-ec2-now-with-windows-server-2003/"&gt;http://blog.tinisles.com/2008/10/amazon-ec2-now-with-windows-server-2003/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Amazon EC2 now supports Windows Server 2003 based virtual machines: &lt;a href="http://aws.amazon.com/windows/"&gt;Amazon Elastic Compute Cloud (EC2) Running Microsoft Windows Server and SQL Server&lt;/a&gt;.  Grab a Windows virtual machine for $USD0.125 an hour.&lt;/p&gt;

&lt;p&gt;Quick recap: EC2 is akin to virtual private server hosting, where you pay by the hour.  EC2 is administered via a service that allows you instantly create any number of virtual machines, and manage firewall rules.&lt;/p&gt;

&lt;p&gt;I was going to write up a quick guide on firing up a Windows box - but this has already been covered well in the &lt;a href="http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/index.html?running-an-instance-windows.html"&gt;Getting Started Guide&lt;/a&gt;&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/10/lg_ec2_windows.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/10/sm_ec2_windows.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 315px;" /&gt;&lt;/a&gt;

&lt;p&gt;Some lessons learned along the way:  I had to download the new &lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351&amp;categoryID=88"&gt;EC2 API tools&lt;/a&gt; - extracted into a new folder the 'ec2-describe-keypairs' knew about keys I'd created previously.  Where do the keys actually get stored?  &lt;a href="http://docs.amazonwebservices.com/AmazonEC2/dg/2006-10-01/CLTRG-create-keypair.html"&gt;ec-add-keypair&lt;/a&gt; explains what is happening - your public key is sent to Amazon's servers.  Your private key you save to a file - in the Linux world you use this private key in Putty to connect to your server.  In the Windows world you pass your private key file to &lt;a href="http://docs.amazonwebservices.com/AWSEC2/latest/DeveloperGuide/CLTRG-get-password.html"&gt;ec2-get-password&lt;/a&gt; to get your server password from Amazon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-3786546582753516296?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/3786546582753516296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=3786546582753516296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/3786546582753516296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/3786546582753516296'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/10/amazon-ec2-now-with-windows-server-2003.html' title='Amazon EC2 - Now with Windows Server 2003!'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-626734517127854177</id><published>2008-10-06T17:16:00.004+11:00</published><updated>2010-07-17T22:37:06.116+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Playing with JQuery and ASP.NET MVC</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/10/playing-with-jquery-and-asp-net-mvc/"&gt;http://blog.tinisles.com/2008/10/playing-with-jquery-and-asp-net-mvc/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;&lt;span style="font-weight:bold;"&gt;UPDATE:&lt;/span&gt; Thanks for the comment Chris.  I guess after years of wrestling with Javascript I didn't think of reading in the UI elements to set the cookie.  If the cookie was storing something like timezones, I could stick the timezone key into an expando property of the div - nice!&lt;/p&gt;

&lt;p&gt;I've updated the &lt;a href="http://mvc.time2call.net/MvcJQueryMuckingCode.zip"&gt;source code zip&lt;/a&gt;, and the &lt;a href="http://mvc.time2call.net/"&gt;demo&lt;/a&gt;.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;jQuery and ASP.NET MVC have both caught my eye as interesting web technologies.  &lt;a href="http://www.asp.net/mvc/"&gt;ASP.NET MVC&lt;/a&gt; is a Model-View-Controller approach to web development in .net.  I've heard it described as Microsoft thinking up another way they could've upgraded from ASP Classic to ASP.NET.  &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; is a very handy javascript library which abstracts a lot of standard client-side functionality into a cross-browser library, e.g DHTML and Ajax.  Microsoft must agree on the usefulness of jQuery - as Microsoft have plans to include jQuery in their own products: &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/09/28/jquery-and-microsoft.aspx"&gt;jQuery and Microsoft&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get my hands dirty with ASP.NET MVC and jQuery I'm using it to rebuild a languishing project of mine: &lt;a href="http://www.time2call.net"&gt;www.time2call.net&lt;/a&gt;.  I've developed a little spike to test a timezone picker scenario.  There's a few design goals I had in mind:
&lt;ol&gt;
&lt;li&gt;An ajax 'picker' - displays the results via Ajax, stores the options in a cookie.  Subsequent visits can re-create the UI server-side.
&lt;li&gt;The same server-side code to build UI HTML for Ajax AND 'from cookie' page load.  I.e no duplication of HTML build code client-side and server-side.
&lt;li&gt;Minimal / incredibly readable client side-code.
&lt;li&gt;All the whizzy Ajax loading animation people expect.
&lt;li&gt;Maintain Ajax context, so options appear on the page in the order they were clicked, regardless of the order of processing on the server.
&lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;See the spike: &lt;a href="http://mvc.time2call.net/"&gt;here&lt;/a&gt; - grab the code: &lt;a href="http://mvc.time2call.net/MvcJQueryMuckingCode.zip"&gt;MvcJQueryMuckingCode.zip&lt;/a&gt;.  The code is built against &lt;a href="http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16775"&gt;ASP.NET MVC Preview 5&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some notes / questions:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://knol.google.com/k/jason-pincin/jquery-callback-contexts/1fk6f8qeqtvqa/2"&gt;jQuery Callback Contexts&lt;/a&gt; - maintaining context between Ajax request / response.
&lt;li&gt;&lt;a href="http://bradwilson.typepad.com/blog/2008/08/partial-renderi.html"&gt;Partial Rendering &amp; View Engines in ASP.NET MVC&lt;/a&gt; - rendering the ViewUserControl for the Ajax request.
&lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2007/12/06/asp-net-mvc-framework-part-3-passing-viewdata-from-controllers-to-views.aspx"&gt;Passing ViewData from Controllers to Views&lt;/a&gt; - I don't get the "ViewData.Products" style accessor in my example - I'm accessing the collection through "ViewData.Model".  Is this something that's changed in release 5?
&lt;li&gt;To remove a color option I pick up the position of delete link:
&lt;pre&gt;var index = $('.delLink').index(this);&lt;/pre&gt;
Then use this to get the DIV in the same position:
&lt;pre&gt;$('#fldColors &gt; div').eq(index)...&lt;/pre&gt;
Is there a better way of doing this?
&lt;li&gt;When I delete an option I'm expecting the color DIVs to be in the same position as the options in the cookie.  That's why I remove the DIV in the fadeout callback.  So there's 500ms there where that could go wrong :(.  I experimented with selecting just the 'visible' DIVs.  But the the div's display style remains 'block' until it disappears.
&lt;/ul&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-626734517127854177?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/626734517127854177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=626734517127854177' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/626734517127854177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/626734517127854177'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/10/playing-with-jquery-and-aspnet-mvc.html' title='Playing with JQuery and ASP.NET MVC'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-4617198429188717877</id><published>2008-10-01T19:20:00.020+10:00</published><updated>2010-07-17T22:37:08.710+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='timezones'/><title type='text'>Converting Timezones in .net</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/10/converting-timezones-in-net/"&gt;http://blog.tinisles.com/2008/10/converting-timezones-in-net/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Ever had the need to convert a date/time to another timezone?  I had to do it a while back to display publishing deadlines for a website used in Australia and New Zealand.  Back then I used a wrapper for the kernel32 function &lt;a href="http://msdn.microsoft.com/en-us/library/ms724949(VS.85).aspx"&gt;SystemTimeToTzSpecificLocalTime&lt;/a&gt; from the CodeProject article &lt;a href="http://www.codeproject.com/KB/cs/timezoneconversions.aspx"&gt;Convert between UTC (Universal Co-ordinated Time) and local time&lt;/a&gt;.  As of version 3.5 of the framework there is now the &lt;a href="http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx"&gt;TimeZoneInfo&lt;/a&gt; class making this much easier to do in managed code.  But both come with some small caveats.&lt;/p&gt;

&lt;p&gt;The API function works with daylight saving data retrieved from the registry.  To use it you extract the data in the registry key "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\[Timezone name]\Tzi", and memcopy this into a &lt;a href="http://msdn.microsoft.com/en-us/library/ms725481(VS.85).aspx"&gt;TIME_ZONE_INFORMATION&lt;/a&gt; structure.&lt;/p&gt;

&lt;p&gt;The TIME_ZONE_INFORMATION structure contains two &lt;a href="http://msdn.microsoft.com/en-us/library/ms724950(VS.85).aspx"&gt;SYSTEMTIME&lt;/a&gt; structures StandardDate, and DaylightDate date - which specify when the people in this timezone wind their clocks back / forward.  This value in the registry is only ever the daylight rules for 'right now' - so we can run into problems with dates ~12 months outside of this range.  Windows treats these rules as if they have been in effect forever - even when they are changed by a Windows Update.&lt;/p&gt;

&lt;p&gt;As an example: lets say we are working on an app that stores ATM transactions in UTC time - we want to convert them to a local time to print onto statements for a bank in Los Angeles.  A customer made withdrawals at UTC times: 31-Mar-2006 17:00, and 31-Mar-2007 17:00.  The code to convert the UTC time using the wrapper from the CodeProject article looks like this:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
DateTime utcTime = DateTime.Parse(&amp;quot;2006-03-31T17:00:00&amp;quot;);
DateTime converted = TimeZoneInformation.FromUniversalTime(&amp;quot;Pacific Standard Time&amp;quot;, utcTime);
Console.WriteLine(converted.ToString(&amp;quot;s&amp;quot;));

utcTime = DateTime.Parse(&amp;quot;2007-03-31T17:00:00&amp;quot;);
converted = TimeZoneInformation.FromUniversalTime(&amp;quot;Pacific Standard Time&amp;quot;, utcTime);
Console.WriteLine(converted.ToString(&amp;quot;s&amp;quot;));&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Which gives:
&lt;pre&gt;UTC:2006-03-31T17:00:00 Los Angeles:2006-03-31T10:00:00
UTC:2007-03-31T17:00:00 Los Angeles:2007-03-31T10:00:00&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;So 5pm UTC converts to 10pm in LA - sounds about right?  Well no..  I've obviously picked some dates where the daylight settings in the registry give us the wrong conversion.  From 1987 to 2006 the USA East coast wound their clocks forward on the first Sunday of April, this changed in 2007 to the second Sunday of March.  So on 31-Mar-2006 daylight savings hadn't kicked in, LA should've been 8 hours behind UTC.  On 31-Mar-2007 daylight savings did apply - and we've correctly calculated LA time as 7 hours behind UTC.  Windows is applying the second Sunday of March rule in 2006 - as this is the only rule it knows about.&lt;/p&gt;

&lt;p&gt;That is - unless you are on Vista or Server 2008.  The newer version of the Windows API is able to read the &lt;a href="http://msdn.microsoft.com/en-us/library/ms724253(VS.85).aspx"&gt;DYNAMIC_TIME_ZONE_INFORMATION&lt;/a&gt; - from a collection of &lt;span style="font-style:italic;"&gt;multiple&lt;/span&gt; rules in the "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\[Timezone name]\Dynamic DST".&lt;/p&gt;

&lt;p&gt;Enter the .net TimeZoneInfo class - lucky for us this class can interpret the dynamic DST data from the registry (even in XP).  Here's the previous example using the TimeZoneInfo class:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(&amp;quot;Pacific Standard Time&amp;quot;);
DateTime utcTime = DateTime.Parse(&amp;quot;2006-03-31T17:00:00&amp;quot;);
DateTime converted = TimeZoneInfo.ConvertTimeFromUtc(utcTime, tzi);
Console.WriteLine(&amp;quot;UTC:{0:s} Los Angeles:{1:s}&amp;quot;, utcTime, converted);

utcTime = DateTime.Parse(&amp;quot;2007-03-31T17:00:00&amp;quot;);
converted = TimeZoneInfo.ConvertTimeFromUtc(utcTime, tzi);
Console.WriteLine(&amp;quot;UTC:{0:s} Los Angeles:{1:s}&amp;quot;, utcTime, converted);&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;The output:
&lt;pre&gt;UTC:2006-03-31T17:00:00 Los Angeles:2006-03-31T09:00:00
UTC:2007-03-31T17:00:00 Los Angeles:2007-03-31T10:00:00&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Seeing what I expect for the 2006 date.  So everything is covered?  Well no.. :)&lt;/p&gt;

&lt;p&gt;The full list of daylight rules is VERY complicated - lots of governments worldwide seem to like messing with daylight rules.  The new registry rules are not populated with historic rules.  For example Sydney changed the rules for the Olympic games in 2000 - the daylight transition was on the last Sunday of August, rather than the last Sunday in October.  Try converting a date in September 2000 - we should get the usual 10 hours difference plus 1 hour for daylight time.  And we get:
&lt;pre&gt;UTC:2000-09-15T00:00:00 Sydney:2000-09-15T10:00:00&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;This conversion website gives the results we expect: &lt;a href="http://www.timezoneconverter.com/cgi-bin/tzc.tzc?style=1&amp;use_current_datetime=0&amp;month=9&amp;day=15&amp;year=2000&amp;time=00%3A00%3A00&amp;time_type=24hour&amp;fromzone=GMT&amp;tozone=Australia%2FSydney&amp;Submit.x=157&amp;Submit.y=6&amp;Submit=Convert"&gt;here&lt;/a&gt;.&lt;p&gt;

&lt;p&gt;We can actually look in the TimeZoneInfo GetAdjustmentRules() and see the list of rules Windows knows about.

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(&amp;quot;AUS Eastern Standard Time&amp;quot;);
int i = 0;
foreach (TimeZoneInfo.AdjustmentRule adj in tzi.GetAdjustmentRules())
{
    i++;
    Console.WriteLine(&amp;quot;AdjustmentRule &amp;quot; + i);
    Console.WriteLine(&amp;quot;adj.DateStart = &amp;quot; + adj.DateStart);
    Console.WriteLine(&amp;quot;adj.DateEnd = &amp;quot; + adj.DateEnd);
    Console.WriteLine(String.Format(&amp;quot;adj.DaylightTransitionStart = Day: {0}, DayOfWeek: {1}, Month: {2}, TimeOfDay: {3}, Week: {4}&amp;quot;, adj.DaylightTransitionStart.Day,
        adj.DaylightTransitionStart.DayOfWeek,
        adj.DaylightTransitionStart.Month,
        adj.DaylightTransitionStart.TimeOfDay.ToShortTimeString(),
        adj.DaylightTransitionStart.Week));
    Console.WriteLine(String.Format(&amp;quot;adj.DaylightTransitionEnd = Day: {0}, DayOfWeek: {1}, Month: {2}, TimeOfDay: {3}, Week: {4}&amp;quot;, adj.DaylightTransitionEnd.Day,
        adj.DaylightTransitionEnd.DayOfWeek,
        adj.DaylightTransitionEnd.Month,
        adj.DaylightTransitionEnd.TimeOfDay.ToShortTimeString(),
        adj.DaylightTransitionEnd.Week));
    Console.WriteLine(&amp;quot;adj.DaylightDelta = &amp;quot; + adj.DaylightDelta);
    Console.WriteLine();
}&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;The output:
&lt;pre&gt;AdjustmentRule 1
adj.DateStart = 1/01/0001 12:00:00 AM
adj.DateEnd = 31/12/2007 12:00:00 AM
adj.DaylightTransitionStart = Day: 1, DayOfWeek: Sunday, Month: 10, TimeOfDay: 2:00 AM, Week: 5
adj.DaylightTransitionEnd = Day: 1, DayOfWeek: Sunday, Month: 3, TimeOfDay: 3:00 AM, Week: 5
adj.DaylightDelta = 01:00:00

AdjustmentRule 2
adj.DateStart = 1/01/2008 12:00:00 AM
adj.DateEnd = 31/12/9999 12:00:00 AM
adj.DaylightTransitionStart = Day: 1, DayOfWeek: Sunday, Month: 10, TimeOfDay: 2:00 AM, Week: 1
adj.DaylightTransitionEnd = Day: 1, DayOfWeek: Sunday, Month: 4, TimeOfDay: 3:00 AM, Week: 1
adj.DaylightDelta = 01:00:00&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;How would you deal with this scenario?  The MSDN article for TimeZoneInfo mentions the class can be used for "Creating a new time zone that is not already defined by the operating system." The popular &lt;a href="http://www.twinsun.com/tz/tz-link.htm"&gt;tz&lt;/a&gt; database contains a very comprehensive collection of date rules.  So I was 'sort of' expecting someone would write the code to import the tz database to custom TimeZoneInfo timezones.  Unfortunately a quick google doesn't come up with someone who has already done this for me.  An alternative exists to use the tz database in .net: &lt;a href="http://www.codeplex.com/publicdomain"&gt;PublicDomain&lt;/a&gt; - described in more detail in the CodeProject article: &lt;a href="http://www.codeproject.com/KB/dotnet/Using_time_zones_in_NET.aspx"&gt;How to Use the Olson Time Zone Database in .NET&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Futher reading:
&lt;ul&gt;
&lt;li&gt; &lt;a href="http://www.hanselman.com/blog/KB928388BreakingTestsWithWindowsDSTTimeZonePatchAndPastDates.aspx"&gt;KB928388 Breaking Tests with Windows DST TimeZone Patch and Past Dates&lt;/a&gt; - Scott Hanselman running into the same issue.
&lt;li&gt; &lt;a href="http://blogs.msdn.com/bclteam/archive/2007/06/07/exploring-windows-time-zones-with-system-timezoneinfo-josh-free.aspx"&gt;Exploring Windows Time Zones with System.TimeZoneInfo&lt;/a&gt;

&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-4617198429188717877?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/4617198429188717877/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=4617198429188717877' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4617198429188717877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4617198429188717877'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/10/converting-timezones-in-net.html' title='Converting Timezones in .net'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-8644257272409822234</id><published>2008-09-21T23:05:00.002+10:00</published><updated>2010-07-17T22:37:11.420+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>ASP.NET Defending Against Form Hackers</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/09/asp-net-defending-against-form-hackers/"&gt;http://blog.tinisles.com/2008/09/asp-net-defending-against-form-hackers/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Something I've pondered previously: an ASP.NET page is populated with data retrieved from ViewState, is it possible to falsify the ViewState in the POST and trick the server into doing something that it shouldn't.  In other words, a scenario where the original developer is just "trusting" information coming from ViewState.&lt;/p&gt;

&lt;p&gt;Here's an example - a company 'extranet' application which gives me an admin page to manage the username/passwords of my subordinate users.  Let's guess the "trusting" developer behind this system implements the save by iterating over the GridView rows, and updating the database with the emails / passwords in the textboxes.&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/09/lg_viewstate1.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/09/sm_viewstate1.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;


&lt;p&gt;My superior's login is 'jvandelay' - of course I'm not able to see his record on my admin screen.   After a postback the page is being populated using the data stored in ViewState.  Can I craft up some viewstate that will add a row to the dataview, allowing me to update my superior's password?&lt;/p&gt;

&lt;p&gt;Seaching around gets some good articles to answer my intial questions.  
&lt;ul&gt;
&lt;li&gt;Can you falsify ViewState?  By default: no - From ScottGu's &lt;a href="http://weblogs.asp.net/scottgu/archive/2003/02/16/2495.aspx"&gt;Cool Viewstate Decoder&lt;/a&gt;: "Note that ViewState is MAC (message authentication check) encoded to prevent tampering by remote clients.  As such, while you can decypher the viewstate settings using the above program, you can't actually change them and repost to the server.".  There is a setting "EnableViewStateMac" on the &lt;a href="http://msdn.microsoft.com/en-us/library/ydy4x04a.aspx"&gt;@ Page&lt;/a&gt; directive to switch this off, so we can have a play around.&lt;/li&gt;
&lt;li&gt;How would you build a falsified ViewState?  Paul Wilson's &lt;a href="http://aspalliance.com/articleViewer.aspx?aId=135&amp;pId="&gt;ViewState: All You Wanted to Know&lt;/a&gt; give a good intro to the ViewState format, and the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.losformatter.aspx"&gt;LosFormatter&lt;/a&gt; class used to serialize/deserialize ViewState&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;How do you craft up the 'malicious' ViewState?  Let's start with deserializing the ViewState using LosFormatter.  Paul Wilson's article provides a some code to traverse the object graph.  See the results &lt;a href="http://blog.time2call.net/viewstatehacking/viewstate1.html"&gt;here&lt;/a&gt;. Now I can insert the objects into the object graph to fake an extra row in the ViewState.  I've modified Paul Wilson's code to give to generate code to access the unwieldy positions in the graph, see the code &lt;a href="http://blog.time2call.net/viewstatehacking/viewstate2.html"&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Here's the code to fake the ViewState, and serialize it back to a string we can put in a browser: &lt;a href="http://blog.time2call.net/viewstatehacking/viewstate3.html"&gt;here&lt;/a&gt;.  The fake ViewState can be inserted into the __VIEWSTATE hidden field with the &lt;a href="http://chrispederick.com/work/web-developer/"&gt;Web Developer extension&lt;/a&gt; in Firefox: right-click &gt; Web Developer &gt; Forms &gt; Display Form Details.  Click 'Save' and we get... &lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/09/lg_viewstate2.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/09/sm_viewstate2.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;Foiled by EventValidation - somthing else I can switch off in the &lt;a href="http://msdn.microsoft.com/en-us/library/ydy4x04a.aspx"&gt;@ Page&lt;/a&gt; directive.  More on Event Validation in K. Scott Allen's &lt;a href="http://odetocode.com/Blogs/scott/archive/2006/03/20/3145.aspx"&gt;ASP.NET Event Validation and “Invalid Callback Or Postback Argument” : Part I&lt;/a&gt;.  Interestingly the __EVENTVALIDATION value is derived from a hash of UniqueIDs XORed with a hash of the allowed values.  Would I be able to fake this also?  Maybe I'll follow that up in another blog article...&lt;/p&gt;

&lt;p&gt;Anyway with EnableEventValidation off we get:&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/09/lg_viewstate3.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/09/sm_viewstate3.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;Success!  And I certainly can fill in the email and password details for 'jvandelay' and see them saved!  So it is did take quite a few things to come together to make this possible:
&lt;ul&gt;
&lt;li&gt; the original developer was a little to 'trusting' - the application could be testing if my login is attempting to update a superior's details
&lt;li&gt; ViewState MAC encoding and Event validation needed to be turned off
&lt;/ul&gt;
 &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-8644257272409822234?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/8644257272409822234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=8644257272409822234' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/8644257272409822234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/8644257272409822234'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/09/aspnet-defending-against-form-hackers.html' title='ASP.NET Defending Against Form Hackers'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-2311968978815851500</id><published>2008-07-22T20:56:00.002+10:00</published><updated>2010-07-17T22:37:17.771+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='subversion'/><title type='text'>Release Branches and Bugfixes with Subversion</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/07/release-branches-and-bugfixes-with-subversion/"&gt;http://blog.tinisles.com/2008/07/release-branches-and-bugfixes-with-subversion/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;I've finally taken out the time to properly learn about the subversion "trunk, branches, and tags" structure. So while its fresh in my head I thought I'd blog about a common scenario with an extremely contrived example.  New to Subversion?  Here's the links that got me started:&lt;p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://svnbook.red-bean.com/"&gt;Version Control with Subversion&lt;/a&gt; - a free  book about Subversion.
&lt;li&gt;&lt;a href="http://www.visualsvn.com/server/"&gt;VisualSVN Server&lt;/a&gt; - a simple to use (and free!) Subverion server for Windows.
&lt;li&gt;&lt;a href="http://www.collab.net/downloads/subversion/"&gt;CollabNet Subversion Downloads&lt;/a&gt; - a command line server and client.
&lt;li&gt;&lt;a href="http://tortoisesvn.tigris.org/"&gt;TortoiseSVN&lt;/a&gt; - a Subversion client, implemented as a windows shell extension.
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;This is the scenario: You've deployed an application to production.  A few weeks later development work is continuing on the source tree, when someone finds a bug in production.  The development code isn't ready for production, and hasn't been tested.  So we want to pull out the production version of the source code, apply a bugfix, reapply the fix to the development tree, and roll out the updated production build.  This is a very common scenario outlined in the "Version Control with Subversion" book here: &lt;a href="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.commonpatterns.html#svn.branchmerge.commonpatterns.release"&gt;Release Branches&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The fix?  In short terms Subversion makes this possible with the following steps.  Once code is ready for a production deploy we create a production branch "/TurtlesApp/branches/Production".  Any production bugfixes can be carried out in this location and, with the help of Subversion, merged back into the developement tree "/TurtlesApp/trunk"&lt;/p&gt;

&lt;p&gt;Step by step: Here's the &lt;span style="font-style:italic;"&gt;extremely contrived&lt;/span&gt; application ready to go to production.  We've created a simple application which reads in an XML file, populates a collection of business objects, and binds this to a GridView.&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/07/lg_subv_pic1.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/07/sm_subv_pic1.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;
&lt;a href="http://blog.time2call.net/TurtlesApp1_code.html" target="_blank"&gt;View Code&lt;/a&gt;

&lt;p&gt;Ready for production - create a branch:&lt;/p&gt;
&lt;a href="http://blog.tinisles.com/blogger-images/2008/07/lg_subv_branch.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/07/sm_subv_branch.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

Now we have a something that looks like this in the repository:
&lt;a href="http://blog.tinisles.com/blogger-images/2008/07/lg_subv_tree.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/07/sm_subv_tree.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

Work continues in the development trunk, with new features are being added.

&lt;a href="http://blog.tinisles.com/blogger-images/2008/07/lg_subv_pic2.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/07/sm_subv_pic2.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;
&lt;a href="http://blog.time2call.net/TurtlesApp2_code.html" target="_blank"&gt;View Code&lt;/a&gt;

&lt;p&gt;But in production someone has discovered a bug.  They've attempted to add this line to the XML file:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
&amp;lt;Turtle Name=&amp;quot;Splinter&amp;quot;/&amp;gt;&lt;/pre&gt;

&lt;p&gt;The code is crashing out attempting to read the 'null' weapon.  The development tree hasn't been tested, and isn't ready for production (&lt;span style="font-style:italic;"&gt;contrived&lt;/span&gt;, I tell you!).  So the changes can be made in the 'Production' branch and merged back into the trunk.&lt;/p&gt;

&lt;p&gt;Let's say we are doing our dev on the "C:\VS2008\TurtlesApp\trunk" folder.  We've got IIS vdirs pointing at this app, and a number of build scripts expect things to be in this location.  This is where the &lt;a href="http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.switch.html"&gt;svn switch&lt;/a&gt; command comes in handy.  Using this command we can replace our code in "C:\VS2008\TurtlesApp\trunk" with the production branch.&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/07/lg_subv_switch.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/07/sm_subv_switch.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;The bugfix is a simple test for null:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
turtle.Name = (node.Attributes[&amp;quot;Name&amp;quot;] != null) ? node.Attributes[&amp;quot;Name&amp;quot;].Value : null;
turtle.Weapon = (node.Attributes[&amp;quot;Weapon&amp;quot;] != null) ? node.Attributes[&amp;quot;Weapon&amp;quot;].Value : null;
&lt;/pre&gt;

&lt;p&gt;Let's commit this to the "Production" branch, and we are ready to build and deploy.&lt;/p&gt;
&lt;a href="http://blog.tinisles.com/blogger-images/2008/07/lg_subv_commit1.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/07/sm_subv_commit1.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;The bug still exists in our development trunk.  Subversion can merge the changes we've made in production back into development.  In the real world a bugfix could impact any number of source files.  I start the merge by first switching my directory back to the trunk, getting an update of the source - always a good convention if you are about change a bunch of files - then do the merge.&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/07/lg_subv_merge.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/07/sm_subv_merge.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

So what does the Turtle.cs file look like now with the changes merged in...
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
Turtle turtle = new Turtle();
turtle.Name = (node.Attributes[&amp;quot;Name&amp;quot;] != null) ? node.Attributes[&amp;quot;Name&amp;quot;].Value : null;
turtle.Weapon = (node.Attributes[&amp;quot;Weapon&amp;quot;] != null) ? node.Attributes[&amp;quot;Weapon&amp;quot;].Value : null;
turtle.Nickname = node.Attributes["Nickname"].Value;
turtle.Colour = node.Attributes["Colour"].Value;
results.Add(turtle);&lt;/pre&gt;

&lt;p&gt;Very cool!  Subversion has automatically added our production changes to the development branch!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-2311968978815851500?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/2311968978815851500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=2311968978815851500' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/2311968978815851500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/2311968978815851500'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/07/release-branches-and-bugfixes-with.html' title='Release Branches and Bugfixes with Subversion'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-607511650436171423</id><published>2008-04-20T20:20:00.005+10:00</published><updated>2010-07-17T22:38:50.037+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><title type='text'>Amazon Elastic Compute Cloud - EC2</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/04/amazon-elastic-compute-cloud-ec2/"&gt;http://blog.tinisles.com/2008/04/amazon-elastic-compute-cloud-ec2/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;The &lt;a href="http://www.amazon.com/b/?node=201590011"&gt;Amazon Elastic Compute Cloud&lt;/a&gt; (EC2 for short) was recently mentioned on the IT Conversations podcast episode &lt;a href="http://itc.conversationsnetwork.org/shows/detail3497.html"&gt;A Web-Scale Computing Architecture&lt;/a&gt;.  EC2 looks very similar to a Virtual Private Server hosting service - where you rent a virtualized server.  On top of this service is a webservice giving you the ability to dynamically create, stop and start multiple server instances.  Which makes this service an ideal platform for an application with variable load.  For example; a concert ticket website could rent an additional 40 servers when a popular concert is about to go on sale.  Or dynamically ramp up the number of servers as load increases.  The service bills you for hours each instance runs, plus bandwidth.  Running a single small instance non stop for one year will cost you approximately $USD876 - so cheaper options exist elsewhere if you don't need a dynamic number of servers.&lt;/p&gt;

&lt;p&gt;Interested enough to check it out?  Follow the steps in the &lt;a href="http://docs.amazonwebservices.com/AWSEC2/2008-02-01/GettingStartedGuide/?ref=get-started"&gt;Getting Started Guide&lt;/a&gt; to fire up your own instance.  In the guide you communicate with the 'cloud' via a collection of java commandline utilities.  The utilities themselves are ulitising the public webservice API.  Just like Amazon's &lt;a href="http://www.amazon.com/gp/browse.html?node=16427261"&gt;S3&lt;/a&gt;, third parties are free to build applications upon the API.  &lt;a href="http://www.rightscale.com/"&gt;RightScale&lt;/a&gt;, mentioned in the podcast, uses the public API to deliver an automated cloud computing management system.  The &lt;a href="http://sourceforge.net/projects/elasticfox/"&gt;Firefox extension for EC2&lt;/a&gt; uses the public API to offer a GUI alternative to the command line utilities.&lt;/p&gt;

&lt;p&gt;The Getting Started Guide takes you through the steps of firing up a public instance of a Linux server, making modifications to the instance, then packaging this up as a custom Amazon Machine Image (AMI).  The customised AMI is then uploaded to your S3 storage.&lt;/p&gt;

&lt;p&gt;This is a very interesting technology from Amazon, I'm intrigued to see what services get built on top the cloud!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-607511650436171423?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/607511650436171423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=607511650436171423' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/607511650436171423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/607511650436171423'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/04/amazon-elastic-compute-cloud-ec2.html' title='Amazon Elastic Compute Cloud - EC2'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-3466989197521398121</id><published>2008-03-26T20:37:00.005+11:00</published><updated>2010-07-17T22:38:52.511+10:00</updated><title type='text'>PropertyInfo.GetCustomAttributes() Doesn't Return Inherited Attributes</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/03/propertyinfo-getcustomattributes-doesnt-return-inherited-attributes/"&gt;http://blog.tinisles.com/2008/03/propertyinfo-getcustomattributes-doesnt-return-inherited-attributes/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Here's a problem I ran into today.  If you have an attribute on the property of a base class; are you able to read it via PropertyInfo.GetCustomAttributes on the properties of a subclass.&lt;/p&gt;

&lt;p&gt;Here's where it helps to read the fine print.  PropertyInfo.GetCustomAttributes takes a parameter for 'inherit' -  yet the reference for &lt;a href="http://msdn2.microsoft.com/en-us/library/system.reflection.propertyinfo.aspx"&gt;PropertyInfo&lt;/a&gt; contains some important details: 

&lt;quote&gt;Calling ICustomAttributeProvider.GetCustomAttributes on PropertyInfo when the inherit parameter of GetCustomAttributes is true does not walk the type hierarchy. Use &lt;a href="http://msdn2.microsoft.com/en-us/library/system.attribute.aspx"&gt;System.Attribute&lt;/a&gt; to inherit custom attributes.&lt;/quote&gt;
&lt;/p&gt;

&lt;p&gt;
The code to read the attributes ended up looking like this:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
foreach (PropertyInfo property in type.GetProperties())
{
    // not this one -&amp;gt; property.GetCustomAttributes(true);
    Attribute[] attributes = Attribute.GetCustomAttributes(property);
}&lt;/pre&gt;

&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-3466989197521398121?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/3466989197521398121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=3466989197521398121' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/3466989197521398121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/3466989197521398121'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/03/propertyinfogetcustomattributes-doesnt.html' title='PropertyInfo.GetCustomAttributes() Doesn&amp;#39;t Return Inherited Attributes'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-4027951107005256358</id><published>2008-02-23T21:34:00.005+11:00</published><updated>2010-07-17T22:38:57.276+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><title type='text'>Silverlight Animated Optical Illusion</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/02/silverlight-animated-optical-illusion/"&gt;http://blog.tinisles.com/2008/02/silverlight-animated-optical-illusion/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Spotted this illusion on digg: &lt;a href="http://scienceblogs.com/cognitivedaily/2008/02/what_illusions_tell_us_about_t.php"&gt;The anatomy of an illusion -- and what it tells us about the visual system&lt;/a&gt;.  Being the skepical fellow I am - I decided to recreate this illusion.
&lt;/p&gt;

&lt;p&gt;The animation is simply cycling the colours of inner circles.  From/to the frames below.&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/02/lg_illusion_start.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/02/sm_illusion_start.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;


&lt;a href="http://blog.tinisles.com/blogger-images/2008/02/lg_illusion_end.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/02/sm_illusion_end.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

So, here's my Silverlight version of the &lt;a href="http://blog.time2call.net/AnimatedIllusion/index.html"&gt;animated illusion&lt;/a&gt;.  Feeling skeptical yourself?  View the source!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-4027951107005256358?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/4027951107005256358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=4027951107005256358' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4027951107005256358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4027951107005256358'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/02/silverlight-animated-optical-illusion.html' title='Silverlight Animated Optical Illusion'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-8534094416964368282</id><published>2008-02-18T20:29:00.004+11:00</published><updated>2010-07-17T22:38:59.738+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>ObjectDataSource DateTime, and Locale</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/02/objectdatasource-datetime-and-locale/"&gt;http://blog.tinisles.com/2008/02/objectdatasource-datetime-and-locale/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Thinking of using an ObjectDataSource and DetailsView to populate/save your business object?  If the object has a DateTime property - lets hope you live in the United States!&lt;/p&gt;

&lt;p&gt;Had an strange problem today with a birthday set to October 9, 1940.  The edit screen would populate a TextBox with "9/10/1940", correct for my culture en-AU.  Clicking save populates the database with "September 10, 1940".  Strange the edit screen would observe the my culture settings, yet populating the business object doesn't.&lt;/p&gt;

&lt;p&gt;Googling around turned up this: &lt;a href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=105016"&gt;ObjectDataSource ignores culture information when updating&lt;/a&gt;.  Do'h!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-8534094416964368282?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/8534094416964368282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=8534094416964368282' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/8534094416964368282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/8534094416964368282'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/02/objectdatasource-datetime-and-locale.html' title='ObjectDataSource DateTime, and Locale'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-9156409597710856334</id><published>2008-02-12T13:05:00.001+11:00</published><updated>2010-07-17T22:39:11.230+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='web dev'/><title type='text'>How Does OpenID Work?</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2008/02/how-does-openid-work/"&gt;http://blog.tinisles.com/2008/02/how-does-openid-work/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;I've heard about &lt;a href="http://openid.net/"&gt;OpenID&lt;/a&gt; on a &lt;a href="http://www.twit.tv/natn16"&gt;podcast&lt;/a&gt; I listen to.  Sounds interesting - an open source solution to have a 'single sign on' for many websites.  Interested to see how this works - both as a user, and as a website author.&lt;/p&gt;

&lt;p&gt;Here's a run through of an example authentication: &lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2008/02/lg_openid_diag01.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2008/02/sm_openid_diag01.jpg" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" /&gt;&lt;/a&gt;

&lt;ol&gt;
&lt;li&gt;User accesses an OpenID enabled website, site responds with a form requesting the user's OpenID identity.
&lt;/li&gt;&lt;li&gt;User enters their identity, e.g: russau.myopenid.com.  Then submits the form to the website.
&lt;/li&gt;&lt;li&gt;Website server accesses http://russau.myopenid.com.  
&lt;li&gt;Retrieves the location of the OpenID provider from the link tag:
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: csharp"&gt;
&amp;lt;link rel=&amp;quot;openid.server&amp;quot; href=&amp;quot;http://www.myopenid.com/server&amp;quot; /&amp;gt;&lt;/pre&gt;
&lt;/li&gt;&lt;li&gt;Website POSTs an 'associate' request to the provider.  The two machines establish a secret using a &lt;a href="http://en.wikipedia.org/wiki/Diffie_hellman"&gt;Diffie-Hellman key exchange&lt;/a&gt;.
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;openid.mode&lt;/td&gt;&lt;td&gt;associate&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.assoc_type&lt;/td&gt;&lt;td&gt;HMAC-SHA1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.session_type&lt;/td&gt;&lt;td&gt;DH-SHA1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.dh_consumer_public&lt;/td&gt;&lt;td&gt;&lt;really big BASE64 number&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.dh_modulus&lt;/td&gt;&lt;td&gt;&lt;really big BASE64 number&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.dh_gen&lt;/td&gt;&lt;td&gt;Ag==&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt; Provider's response provides the website an 'assoc_handle' (and expiry) for future requests.  The two servers now have established a shared secret, without passing it over the wire.
&lt;/li&gt;
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;assoc_handle&lt;/td&gt;&lt;td&gt;{HMAC-SHA1}{47b0ec92}{5hMN8A==}&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;assoc_type&lt;/td&gt;&lt;td&gt;HMAC-SHA1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;dh_server_public&lt;/td&gt;&lt;td&gt;&lt;really big BASE64 number&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;enc_mac_key&lt;/td&gt;&lt;td&gt;&lt;big BASE64 number&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;expires_in&lt;/td&gt;&lt;td&gt;1209600&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;session_type&lt;/td&gt;&lt;td&gt;DH-SHA1&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;li&gt;The comsumer's response from step 2 contains a redirect to the provider, containing a number of parameters in the querystring.  Note, the querystring contains the established 'assoc_handle', and a 'nonce' has been attached onto the 'return_to'.
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;openid.mode&lt;/td&gt;&lt;td&gt;checkid_setup&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.identity&lt;/td&gt;&lt;td&gt;http://russau.myopenid.com/&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.return_to&lt;/td&gt;&lt;td&gt;http://openidconsumer.test/cp/login.aspx?&lt;b&gt;&amp;nonce=vovudmLa&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.trust_root&lt;/td&gt;&lt;td&gt;http://openidconsumer.test/cp&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.assoc_handle&lt;/td&gt;&lt;td&gt;{HMAC-SHA1}{47b0ec92}{5hMN8A==}&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.sreg.required&lt;/td&gt;&lt;td&gt;gender,postcode,timezone&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.sreg.optional&lt;/td&gt;&lt;td&gt;email,country&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.sreg.policy_url&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;li&gt;The user is now on the provider website, and performs the step needed to authenticate, e.g. entering a password.
&lt;li&gt;The provider redirects the user back to the consumer website, along with parameters in the querystring.  The consumer now has everything it needs to log in the user.
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;nonce&lt;/td&gt;&lt;td&gt;vovudmLa&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.assoc_handle&lt;/td&gt;&lt;td&gt;{HMAC-SHA1}{47b0ec92}{5hMN8A==}&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.identity&lt;/td&gt;&lt;td&gt;http://russau.myopenid.com/&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.mode&lt;/td&gt;&lt;td&gt;id_res
&lt;tr&gt;&lt;td&gt;openid.op_endpoint&lt;/td&gt;&lt;td&gt;http://www.myopenid.com/server&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.response_nonce&lt;/td&gt;&lt;td&gt;2008-02-12T00:47:53ZyUUam3&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.return_to&lt;/td&gt;&lt;td&gt;http://openidconsumer.test/cp/login.aspx?nonce=vovudmLa&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.sig&lt;/td&gt;&lt;td&gt;EpvWdJtxacv2WtCaZLbud85M84k=&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.signed&lt;/td&gt;&lt;td&gt;assoc_handle, identity, mode, op_endpoint, response_nonce, return_to, signed, sreg.country, sreg.email&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.sreg.country&lt;/td&gt;&lt;td&gt;AU&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;openid.sreg.email&lt;/td&gt;&lt;td&gt;testuser@webmail.com&lt;/td&gt;&lt;/tr&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

This querystring contains a couple of things to prevent an attacker from spoofing it.  The 'assoc_handle' established in steps 5 and 6, the consumer uses to this look up the established secret.  'openid.sig' contains a digital signature of the parameter values listed in 'openid.signed', using the established secret.  If an attacker were to change the 'openid.identity' in an attempt to login as someone else, the signature wouldn't match (without knowing the secret, the attacker cannot re-create the signature).  Finally, the initial 'openid.return_to' in step 7 contained a nonce.  If an attacker were to resubmit the querystring above unchanged (a &lt;a href="http://en.wikipedia.org/wiki/Replay_attack"&gt;replay attack&lt;/a&gt;), the consumer web site would know the nonce has already been used.

&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ol&gt;


&lt;p&gt;Further reading&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="http://openid.net/specs/openid-authentication-1_1.html"&gt;OpenID Authentication 1.1&lt;/a&gt;
&lt;/li&gt;&lt;li&gt;&lt;a href="http://openid.net/specs/openid-simple-registration-extension-1_0.html"&gt;OpenID Simple Registration Extension 1.0&lt;/a&gt;
&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/dotnetopenid/"&gt;dotnetopenid&lt;/a&gt; - C# implementation of OpenID consumer and provider
&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.lifewiki.net/openid/OpenIDSpecification"&gt;OpenIDSpecification&lt;/a&gt;
&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-9156409597710856334?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/9156409597710856334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=9156409597710856334' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/9156409597710856334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/9156409597710856334'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2008/02/how-does-openid-work.html' title='How Does OpenID Work?'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-1681922539611087667</id><published>2007-12-05T20:48:00.001+11:00</published><updated>2010-07-17T22:39:20.646+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='iis'/><title type='text'>Facebook dev, IIS 5.1, and error 405</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/12/facebook-dev-iis-5-1-and-error-405/"&gt;http://blog.tinisles.com/2007/12/facebook-dev-iis-5-1-and-error-405/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;In the middle of a Facebook application idea of mine.  Using the &lt;a href="http://www.codeplex.com/FacebookToolkit"&gt;FacebookToolkit&lt;/a&gt; to get something together.&lt;/p&gt;

&lt;p&gt;It's pretty interesting how Facebook integrates with 3rd party applications.  Short version: User accesses "http://apps.facebook.com/&amp;lt;appplication_name&amp;gt;", Facebooks sends your page a POST (you host it wherever you want); Facebook displays the output of your page.  Long story: &lt;a href="http://wiki.developers.facebook.com/index.php/Random_questions#Basic_Application_Architecture"&gt;Basic Application Architecture&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can configure the location of the page Facebook POSTs to - called the Callback Url.  I initially had this set to something like: http://www.mycheaphosting.com/Canvas.aspx.  The location the Facebook user accesses, i.e. apps.facebook.com/myapplication/ is called the Canvas Page.&lt;/p&gt;

&lt;p&gt;Any relative links within your Callback page will become relative to your Canvas page.  For example a link to "blah.aspx", will be treated by the browser as a link to  "apps.facebook.com/myapplication/blah.aspx".  What does Facebook do with a URL like this?  It POSTs to the same 'relative' location on your server.  Which in my case would be:  &lt;span style="font-style:italic;"&gt;http://www.mycheaphosting.com/Canvas.aspxblah.aspx&lt;/span&gt;.  Yuck!&lt;/p&gt;

&lt;p&gt;My first thought was: Okay, I can put the logic into a 'default.aspx', and change the Callback URL to: http://www.mycheaphosting.com/.&lt;/p&gt;

&lt;p&gt;Have you ever tried to POST to a default document?  Under IIS 5.1 - it actually causes a 405 - 'Resource not allowed' error.  The best reference on this I could find was in this comment from David Wang's article &lt;a href="http://w3-4u.blogspot.com/2007/01/howto-post-resources-to-iis.html"&gt;HOWTO: POST Resources to IIS&lt;/a&gt;:
&lt;blockquote&gt;The ability to POST to a DefaultDocument requires IIS6. Prior IIS versions will return "405 Method not Allowed". That is simply a limitation of the IIS Request Processing Pipeline.&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;The fix: &lt;a href="http://www.wilcob.com/Wilco/Toolbox/WebDevWebServer2.aspx"&gt;WebDev.WebServer2&lt;/a&gt;
 - an alternative to the Cassini web server that comes with VS2005.  Unlike Cassini this web server can service external requests.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-1681922539611087667?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/1681922539611087667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=1681922539611087667' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/1681922539611087667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/1681922539611087667'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/12/facebook-dev-iis-51-and-error-405.html' title='Facebook dev, IIS 5.1, and error 405'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-793019477777492221</id><published>2007-08-28T20:28:00.001+10:00</published><updated>2010-07-17T22:39:32.776+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='iis'/><title type='text'>Creating Your Own Dev SSL Cert for IIS</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/08/creating-your-own-dev-ssl-cert-for-iis/"&gt;http://blog.tinisles.com/2007/08/creating-your-own-dev-ssl-cert-for-iis/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            Ever wanted to create an SSL certificate for your dev box?  There's no need for a well known CA like Verisign or Comodo on your dev box. Here are some guides to creating your own CA/signed certificates: 

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.visualwin.com/SelfSSL/"&gt;Setting up SSL with a SelfSSL certificate on Windows Server 2003&lt;/a&gt; - create a self signed certificate with a utility from the IIS Resource Kit.
&lt;li&gt;&lt;a href="http://www.dylanbeattie.net/docs/openssl_iis_ssl_howto.html"&gt;Creating a Self-Signed Certificate using OpenSSL for use with Microsoft Internet Information Services (IIS) 5&lt;/a&gt; - use the open source OpenSSL to create your own CA, and sign requests yourself.  Has the advantage that users can trust one CA, and never receive SSL warnings from your dev sites.
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-793019477777492221?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/793019477777492221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=793019477777492221' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/793019477777492221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/793019477777492221'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/08/creating-your-own-dev-ssl-cert-for-iis.html' title='Creating Your Own Dev SSL Cert for IIS'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-5004577967908872482</id><published>2007-08-28T20:00:00.001+10:00</published><updated>2010-07-17T22:39:39.646+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Moving from ASP.NET 1.1 to 2.0</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/08/moving-from-asp-net-1-1-to-2-0/"&gt;http://blog.tinisles.com/2007/08/moving-from-asp-net-1-1-to-2-0/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.asp.net/learn/whitepapers/request-validation/"&gt;Request Validation&lt;/a&gt; - 2.0 picks up 'malicious' HTML even when it's escaped.
&lt;li&gt;&lt;a href="http://west-wind.com/weblog/posts/5127.aspx"&gt;ASP.NET 2.0 MasterPages and FindControl()&lt;/a&gt; - recursively searching for controls inside a masterpage.
&lt;li&gt;&lt;a href="http://dotnetslackers.com/ado_net/re-26241_textbox_readonly_in_asp_net_v2_0.aspx"&gt;TextBox ReadOnly in ASP.NET v2.0&lt;/a&gt; - populating a readonly textbox via script, the contents of the textbox don't get populated on the PostBack page.
&lt;li&gt;&lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;Q309338"&gt;The Attributes property of a ListItem control only works within an HtmlSelect control&lt;/a&gt; - is no longer the case in 2.0 (even though "This behavior is by design" in 1.1).
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-5004577967908872482?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/5004577967908872482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=5004577967908872482' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/5004577967908872482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/5004577967908872482'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/08/moving-from-aspnet-11-to-20.html' title='Moving from ASP.NET 1.1 to 2.0'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-6579090411750248223</id><published>2007-08-07T21:52:00.001+10:00</published><updated>2010-07-17T22:39:55.304+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='links'/><title type='text'>Link Drop VI</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/?p=72"&gt;http://blog.tinisles.com/?p=72&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.uvnc.com/addons/singleclick.html"&gt;UltraVNC SC&lt;/a&gt; - a VNC 'server' you can package up and send to friend.  When launched UltraVNC SC makes the outbound connection back to your waiting VNC client.  No need to set-up any firewall rules on the 'controlled' PC. 
&lt;li&gt;&lt;a href="http://thoof.com/"&gt;Thoof&lt;/a&gt; - always has a few articles I find interesting.  Uses your stats (articles clicked, your browser make/version, geographic location) to find articles tailored for you. 
&lt;li&gt;&lt;a href="http://www.mapsofwar.com/ind/imperial-history.html"&gt;Imperial History of the Middle East&lt;/a&gt; - found this on Thoof.
&lt;li&gt;&lt;a href="http://synergy2.sourceforge.net/"&gt;Synergy&lt;/a&gt; - control several PCs from one mouse/keyboard, moving the mouse off one screen seamlessly flows onto the next screen. 
&lt;li&gt;&lt;a href="http://www.btplc.com/Innovation/News/timeline/TechnologyTimeline.pdf"&gt;2005 BT Technology Timeline&lt;/a&gt; [warning PDF link]
&lt;li&gt;&lt;a href="http://www.slowwave.com"&gt;Slow Wave&lt;/a&gt; - people send in their dreams for some pretty weird cartoons
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-6579090411750248223?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/6579090411750248223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=6579090411750248223' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/6579090411750248223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/6579090411750248223'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/08/link-drop-vi.html' title='Link Drop VI'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-4065379411856398023</id><published>2007-07-30T19:12:00.001+10:00</published><updated>2010-07-17T22:40:00.633+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><title type='text'>Silverlight createFromXaml Bug</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/07/silverlight-createfromxaml-bug/"&gt;http://blog.tinisles.com/2007/07/silverlight-createfromxaml-bug/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Odd Silverlight bug when calling 'createFromXaml' - here's the error for the search engines:&lt;/p&gt;

Firefox: &lt;code&gt;Error calling method on NPObject!&lt;/code&gt;
Internet Explorer: &lt;code&gt;Error: AG_E_RUNTIME_METHOD : CreateFromXAML&lt;/code&gt;

&lt;p&gt;The error occurred when I was trying pull apart the Video Library Sample for my own project.&lt;/p&gt;

&lt;p&gt;The cause of the bug comes down to this:
&lt;ul&gt;
&lt;li&gt;Using the replaceAll prototype to get a string which is passed to createFromXaml:
&lt;li&gt;works fine when it finds the placeholder and replaces it
&lt;li&gt;crashes when it doesn't find the placeholder in the string.
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;Have a look at an example: &lt;a href="http://blog.time2call.net/Silverlightbug10/"&gt;Silverlight createFromXaml bug&lt;/a&gt;.  I'm writing out the string I'm using with createFromXaml in the textarea.  The first button uses the untouched template, the second replaces the $2 placeholder, and the third attempts to replace a non-existent $3 placeholder.&lt;/p&gt;

&lt;p&gt;Stripping all the functionality out of replaceAll causes the error to happen everytime - suggesting Silverlight has a problem dealing with an untouched 'this' coming from a prototype method on a string.&lt;/p&gt;

&lt;pre class="brush: javascript"&gt;
String.prototype.replaceAll = function(strTarget, strSubString) {
    var strText = this;
    return( strText );
}&lt;/pre&gt;

&lt;p&gt;I've created a post about it in the Silverlight forums: &lt;a href="http://silverlight.net/forums/t/3148.aspx"&gt;BUG: createFromXaml and prototypes&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-4065379411856398023?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/4065379411856398023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=4065379411856398023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4065379411856398023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4065379411856398023'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/07/silverlight-createfromxaml-bug.html' title='Silverlight createFromXaml Bug'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-2060074530866198898</id><published>2007-07-22T20:26:00.000+10:00</published><updated>2010-07-17T22:43:19.974+10:00</updated><title type='text'>C# command line parser?</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/07/c-command-line-parser/"&gt;http://blog.tinisles.com/2007/07/c-command-line-parser/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Sat down to start a little command-line app on the weekend - anyone know of a good library to parse command line arguments?  Expecting something with a simple api to set up a list of arguments, specific mandatory ones, and enforce some validation (types and ranges?).&lt;/p&gt;

&lt;p&gt;Quick Google search came up with:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.codeproject.com/csharp/commandlineparser.asp"&gt;Automatic Command Line Parsing in C#&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.codeproject.com/csharp/Command_Line.asp"&gt;C#/.NET Command Line Arguments Parser&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.codeproject.com/csharp/simplecommandlineparser.asp"&gt;Simple Command Line Parser&lt;/a&gt;
&lt;li&gt;CommandLineParser class in &lt;a href="http://www.genghisgroup.com/"&gt;Ghenhis&lt;/a&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;Expect an update (and the finished project) soon! :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-2060074530866198898?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/2060074530866198898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=2060074530866198898' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/2060074530866198898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/2060074530866198898'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/07/c-command-line-parser.html' title='C# command line parser?'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-4792328038646185462</id><published>2007-06-24T08:19:00.001+10:00</published><updated>2010-07-17T22:43:29.463+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web dev'/><title type='text'>Firefox extension: CookiePie</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/06/firefox-extension-cookiepie/"&gt;http://blog.tinisles.com/2007/06/firefox-extension-cookiepie/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Problem: I'm testing a Facebook application of mine, so I've created a few 'testing' accounts.  Rather than logging in/out of each account - I'd like to be logged into all accounts at the same time.  Got me thinking there must be a Firefox extension to do this.&lt;/p&gt;

&lt;p&gt;Solution: &lt;a href="http://www.nektra.com/oss/firefox/extensions/cookiepie/"&gt;CookiePie&lt;/a&gt;:  The CookiePie Firefox extension allows you to have cookies which remain only within one tab.  After installing the extension, a new option is added to the right-click menu on your tabs - to toggle on/off the CookiePie feature.  Exactly what I was after!&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2007/06/lg_cookiepie_1.gif"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2007/06/sm_cookiepie_1.gif" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-4792328038646185462?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/4792328038646185462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=4792328038646185462' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4792328038646185462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/4792328038646185462'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/06/firefox-extension-cookiepie.html' title='Firefox extension: CookiePie'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-1116187195909267688</id><published>2007-06-07T21:36:00.001+10:00</published><updated>2010-07-17T22:43:34.110+10:00</updated><title type='text'>Hand-held browser</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/06/hand-held-browser/"&gt;http://blog.tinisles.com/2007/06/hand-held-browser/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Here's something I've been trying to convince anyone who'd listen for a while: I think there's a market for a hand-held browser appliance.  And judging by some of the products coming out recently someone out there agrees with me.&lt;/p&gt;

&lt;p&gt;I'd like a device with a display at least 800 pixels wide, wifi connectivity, and a 'fully-fledged' browser.  Something my wife could take into the kitchen to view a recipe.  I could sit on the couch a surf the net while I'm watching TV, reply to emails from bed..  How many people buy a PC/Laptop and just browse websites?  Most importantly this device would have to be CHEAP - this is competing with Celeron M laptops selling for $AUD800.  Throw in a skype client and this device could also become your cordless phone.&lt;/p&gt;

&lt;p&gt;What devices are out there that fit the bill?
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/N800"&gt;Nokia N800&lt;/a&gt; - looks very nice, 800 pixels wide display, Linux based OS with a good following of hackers, I'd prefer a slide out keyboard though: $USD400.
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Sony_mylo"&gt;Sony mylo&lt;/a&gt; - 320×240 resolution, sounds a bit too small.  But does come out of the box with a skype client: $USD280
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Pepper_Pad"&gt;Pepper Pad&lt;/a&gt; - $USD699, enough said?  Those keys also look they could be comfortable for typing.
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Palm_Foleo"&gt;Palm Foleo&lt;/a&gt; - announced just last Thursday, touted as a "companion device for all brands of smartphones" - translated from marketingese means "we don't want this device to cannibalise our existing markets": $USD499.  (The comments on the Engadget article are pretty amusing: &lt;a href="http://www.engadget.com/2007/05/30/palm-foleo-announced/"&gt;Palm Foleo announced&lt;/a&gt;.)
&lt;li&gt;&lt;a href="http://www.engadget.com/2007/04/16/intels-mid-umpcs-so-long-xp-vista-hello-linux/"&gt;Intel's MID UMPC&lt;/a&gt; / &lt;a href="http://en.wikipedia.org/wiki/Mobile_Internet_Device"&gt;Mobile Internet Device&lt;/a&gt; - not a lot of news on this one just yet.
&lt;li&gt;&lt;a href="http://www.engadget.com/2007/06/05/asus-new-eee-pc-701-joins-the-laptop-lite-fray-with-a-bang/"&gt;Asus Eee PC 701&lt;/a&gt; - "supposed to start as low as $USD200".  Not bad!  Even the Engadget crowd like this one! 
&lt;/ul&gt;

&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-1116187195909267688?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/1116187195909267688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=1116187195909267688' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/1116187195909267688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/1116187195909267688'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/06/hand-held-browser.html' title='Hand-held browser'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-8425160542478794918</id><published>2007-05-27T18:10:00.003+10:00</published><updated>2010-07-17T22:47:28.663+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight'/><title type='text'>Silverlight</title><content type='html'>&lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/05/silverlight/"&gt;http://blog.tinisles.com/2007/05/silverlight/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Microsoft's new technology Silverlight is out - and already being referred to as a potential flash killer.  Silverlight performs a similar function to Flash, giving developers a platform to create rich internet applications.  Silverlight appeals to me as a developer as applications are built using Microsoft's XAML to create the user interface, and Javascript to add interactivity. These are technologies I'm already familiar with.  Beta 1.1 of Silverlight even has a cross platform CLR called the &lt;a href="http://www.hanselman.com/blog/PuttingMixSilverlightTheCoreCLRAndTheDLRIntoContext.aspx"&gt;CoreCLR&lt;/a&gt; - making it possible to code Silverlight applications in any .net language.  Strongly typed .net languages make an intriguing alternative to Javascript/DHTML/AJAX development.  Using an XML language to describe the user-interface also makes it easier for me to code generate portions of an application.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;So what's it look like?&lt;/span&gt;  Plenty of examples in the &lt;a href="http://silverlight.net/Showcase/"&gt;Showcase&lt;/a&gt;. You'll need to install the Silverlight beta - download links on the &lt;a href="http://silverlight.net/GetStarted/"&gt;Getting Started&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Great, what tools are there for it?&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt; &lt;a href="http://www.microsoft.com/expression/"&gt;Microsoft Expression&lt;/a&gt; - comes in a few flavours (from Wikipedia's &lt;a href="http://en.wikipedia.org/wiki/Microsoft_Expression"&gt;Microsoft Expression&lt;/a&gt; page):
&lt;ul&gt;
&lt;li&gt;Microsoft Expression Web (code-named Quartz) - WYSIWYG website designer and HTML editor.
&lt;li&gt;Microsoft Expression Blend (code-named Sparkle) - Visual user interface builder for Windows Presentation Foundation applications.
&lt;li&gt;Microsoft Expression Design (code-named Acrylic) - Raster and vector graphics editor.
&lt;li&gt;Microsoft Expression Media - Digital asset and media manager.
&lt;/ul&gt;
&lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=6c2b309b-8f2d-44a5-b04f-836f0d4ec1c4&amp;amp;displaylang=en"&gt;Silverlight tools for Orcas&lt;/a&gt; - the add-on tools for the beta version of the next Visual Studio.
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;So, how do I start coding?&lt;/span&gt; So far I've just used Textpad to edit the HTML/XAML/JS files in my sample applications.  The &lt;a href="http://www.silverlight.net/quickstarts/default.aspx"&gt;QuickStarts&lt;/a&gt; pages are a very good place to start.  I've also used Expression Blend to "drag-and-drop" the XAML, but continued my development in Textpad.  Once you start 'trying your own hand' at XAML/Silverlight, you will need a resource like the MSDN &lt;a href="http://msdn2.microsoft.com/en-us/library/bb188567.aspx"&gt;Silverlight Reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've been working on a little Silverlight project - so expect a follow-up blog post sometime soon. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-8425160542478794918?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/8425160542478794918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=8425160542478794918' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/8425160542478794918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/8425160542478794918'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/05/silverlight.html' title='Silverlight'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-1714246805783658434</id><published>2007-04-22T10:12:00.000+10:00</published><updated>2010-07-17T22:47:58.068+10:00</updated><title type='text'>Google Finance</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/04/google-finance/"&gt;http://blog.tinisles.com/2007/04/google-finance/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Google has entered the finance info field - and brought with them some very fancy features, all with a nice UI: &lt;a href="http://finance.google.com/finance?q=AUDUSD"&gt;AUD to USD&lt;/a&gt;.  The graph is draggable, grab it and move back into the history - or click the '1y', '5y' links.  News items are plotted on the graph, and scroll into view as you move back through the history.  The viewable area is expandable, by dragging the edge of history window under the graph. View a stock graph - &lt;a href="http://finance.google.com/finance?q=GOOG"&gt;GOOG&lt;/a&gt; - compare the history with another stock by clicking the compare button.&lt;/p&gt;

&lt;img src="http://blog.tinisles.com/blogger-images/2007/04/sm_goog_aud.gif" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer;" /&gt;

&lt;p&gt;Feature request: a 'permalink' - so I can send someone a link that would take them directly to the 5 year history of the Australian Dollar, or directly to a comparison of GOOG and MSFT.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-1714246805783658434?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/1714246805783658434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=1714246805783658434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/1714246805783658434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/1714246805783658434'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/04/google-finance.html' title='Google Finance'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-5559619128021552437</id><published>2007-04-15T15:01:00.001+10:00</published><updated>2010-07-17T22:48:02.021+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='links'/><title type='text'>Link drop V</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/04/link-drop-v/"&gt;http://blog.tinisles.com/2007/04/link-drop-v/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.methodstudios.com/project/653.html"&gt;Method Studios - Mountain Dew "Spy vs. Spy"&lt;/a&gt; - some clever CGI makes for a bit of nostalgia for old MAD magazine fans.
&lt;li&gt;&lt;a href="http://simile.mit.edu/timeline/"&gt;SIMILE | Timeline&lt;/a&gt; - Javascript library for displaying a draggable/clickable timeline.
&lt;li&gt;&lt;a href="http://www.ports-services.com/"&gt;Free Ports &amp; Network Services Informations Database&lt;/a&gt; - AJAXy port number lookup.
&lt;li&gt;&lt;a href="http://www.digitalmediaminute.com/article/1816/top-ruby-on-rails-tutorials"&gt;Top 12 Ruby on Rails Tutorials&lt;/a&gt; - some tutorials to quickly get up to speed with Ruby on Rails.
&lt;li&gt;&lt;a href="http://blogs.nationalgeographic.com/channel/blog/2007/02/explorer_korea.html"&gt;Inside North Korea&lt;/a&gt; - behind the scenes documentary in North Korea.
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-5559619128021552437?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/5559619128021552437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=5559619128021552437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/5559619128021552437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/5559619128021552437'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/04/link-drop-v.html' title='Link drop V'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-6523118290728114037</id><published>2007-04-06T11:26:00.001+10:00</published><updated>2010-07-17T22:48:05.533+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cryptography'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>ShowMeDo: WASTE tutorial</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/04/showmedo-waste-tutorial/"&gt;http://blog.tinisles.com/2007/04/showmedo-waste-tutorial/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://www.showmedo.com/static/images/showmedoNewLogo.png" border="0" alt="" /&gt;

My ShowMeDo tutorial &lt;a href="http://www.showmedo.com/videos/video?name=sayersWaste000&amp;fromSeriesID=63"&gt;Secure File Transfer With WASTE&lt;/a&gt; has just gone online.  &lt;a href="http://www.showmedo.com/"&gt;ShowMeDo&lt;/a&gt; is web site for tech tutorials in flash video - the majority are screencasts on varied programming topics.  ShowMeDo has huge potential for learning new technologies, I think its going to get bigger and bigger...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-6523118290728114037?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/6523118290728114037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=6523118290728114037' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/6523118290728114037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/6523118290728114037'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/04/showmedo-waste-tutorial.html' title='ShowMeDo: WASTE tutorial'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-639465652139397713</id><published>2007-01-27T17:17:00.000+11:00</published><updated>2010-07-17T22:48:25.927+10:00</updated><title type='text'>Flash video</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2007/01/flash-video/"&gt;http://blog.tinisles.com/2007/01/flash-video/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            Experimenting with flash video - and time-lapse.  This involved a few free source apps:

&lt;ol&gt;
&lt;li&gt;Time-lapse video: &lt;a href="http://makeavi.sourceforge.net/"&gt;MakeAVI&lt;/a&gt;, 
 &lt;a href="http://www.virtualdub.org/"&gt;virtualdub&lt;/a&gt; to dub the soundtrack (although I found out virtual dub can do the time-lapse stuff itself).
&lt;li&gt;Creating the flash video file: &lt;a href="http://ffmpeg.mplayerhq.hu/"&gt;FFmpeg&lt;/a&gt;, there's a tutorial on it here: &lt;a href="http://blog.gwikzone.org/articles/2006/09/25/flv-encoding-with-ffmpeg"&gt;FLV encoding with ffmpeg&lt;/a&gt;.
&lt;li&gt;Jeroen Wijering's &lt;a href="http://www.jeroenwijering.com/?item=Flash_Video_Player"&gt;Flash Video Player&lt;/a&gt;
&lt;/ol&gt;


&lt;object width="320" height="240"
  classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
  codebase="http://fpdownload.macromedia.com/pub/
  shockwave/cabs/flash/swflash.cab#version=8,0,0,0"&gt;
&lt;param name="movie" value="http://russell.sayers.googlepages.com/flvplayer.swf" /&gt;
&lt;param name="flashvars"
  value="file=http://russell.sayers.googlepages.com/yard_work.flv&amp;showdigits=false&amp;autostart=false&amp;showfsbutton=true&amp;repeat=false" /&gt;
&lt;embed src="http://russell.sayers.googlepages.com/flvplayer.swf" width="320" height="240"
  type="application/x-shockwave-flash" pluginspage=
  "http://www.macromedia.com/go/getflashplayer"
  flashvars="file=http://russell.sayers.googlepages.com/yard_work.flv&amp;showdigits=false&amp;autostart=false&amp;showfsbutton=true&amp;repeat=false"&gt;&lt;/embed&gt;
&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-639465652139397713?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/639465652139397713/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=639465652139397713' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/639465652139397713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/639465652139397713'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2007/01/flash-video.html' title='Flash video'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-116202221122455940</id><published>2006-10-28T10:12:00.000+10:00</published><updated>2010-07-17T22:48:28.853+10:00</updated><title type='text'>TWOCrowds.com flickr CAPTCHA test</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/10/twocrowds-com-flickr-captcha-test/"&gt;http://blog.tinisles.com/2006/10/twocrowds-com-flickr-captcha-test/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Noticed on the web somewhere &lt;a href="http://www.twocrowds.com/"&gt;TWOCrowds.com&lt;/a&gt; is using the flickr api to create a &lt;a href="http://en.wikipedia.org/wiki/CAPTCHA"&gt;CAPTCHA &lt;/a&gt; test.  Looks like they are using the flickr api to pull up a &lt;a href="http://www.flickr.com/photos/bip/114556884/"&gt;photo&lt;/a&gt; tagged with a convention that says "this is a photo of a single letter: r".&lt;/p&gt;

&lt;p&gt;Wouldn't this be pretty easy to defeat?  The JPG's are being served from flickr - and a named like this: "114556884_45d6dd4ec4_s.jpg".  The first part of the filename is the photo id which you can pass to the flick API method &lt;a href="http://www.flickr.com/services/api/explore/?method=flickr.photos.getInfo"&gt;flickr.photos.getInfo&lt;/a&gt;.  Which returns all the tags (among other things) for the image - the "Rr" tag being the convention that says this is a photo of the letter R:&lt;/p&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: xml"&gt;

    &amp;lt;tags&amp;gt;
        &amp;lt;tag id=&amp;quot;256536-114556884-484&amp;quot; author=&amp;quot;95229107@N00&amp;quot; raw=&amp;quot;Paris&amp;quot;&amp;gt;paris&amp;lt;/tag&amp;gt;
        &amp;lt;tag id=&amp;quot;256536-114556884-6562&amp;quot; author=&amp;quot;95229107@N00&amp;quot; raw=&amp;quot;claudecf&amp;quot;&amp;gt;claudecf&amp;lt;/tag&amp;gt;
        &amp;lt;tag id=&amp;quot;256536-114556884-17897&amp;quot; author=&amp;quot;95229107@N00&amp;quot; raw=&amp;quot;letter&amp;quot;&amp;gt;letter&amp;lt;/tag&amp;gt;
        &amp;lt;tag id=&amp;quot;256536-114556884-67834&amp;quot; author=&amp;quot;95229107@N00&amp;quot; raw=&amp;quot;oneletter&amp;quot;&amp;gt;oneletter&amp;lt;/tag&amp;gt;
        &amp;lt;tag id=&amp;quot;256536-114556884-6496&amp;quot; author=&amp;quot;95229107@N00&amp;quot; raw=&amp;quot;letters&amp;quot;&amp;gt;letters&amp;lt;/tag&amp;gt;
        &amp;lt;tag id=&amp;quot;256536-114556884-8513&amp;quot; author=&amp;quot;95229107@N00&amp;quot; raw=&amp;quot;Rr&amp;quot;&amp;gt;rr&amp;lt;/tag&amp;gt;
    &amp;lt;/tags&amp;gt;
&lt;/pre&gt;

&lt;p&gt;They could prevent this by not revealing the image names in the HTML - by having their webserver read in the JPG and delivering it with a different filename.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-116202221122455940?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/116202221122455940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=116202221122455940' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/116202221122455940'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/116202221122455940'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/10/twocrowdscom-flickr-captcha-test.html' title='TWOCrowds.com flickr CAPTCHA test'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-116108475599176279</id><published>2006-10-23T20:14:00.001+10:00</published><updated>2010-07-17T22:48:32.027+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cryptography'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>SSL + Man-in-the-Middle</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/10/ssl-man-in-the-middle/"&gt;http://blog.tinisles.com/2006/10/ssl-man-in-the-middle/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Spent some time reading up on SSL and how it defends against against the '&lt;a href="http://en.wikipedia.org/wiki/Man-in-the-middle"&gt;man-in-the-middle&lt;/a&gt;' attack.  All the pieces to the puzzle were there in my previous post - I just needed a good reference on the protocol.  The best references I found were:
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="http://developer.mozilla.org/en/docs/Introduction_to_SSL"&gt;Introduction to SSL&lt;/a&gt;
&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.homeport.org/%7Eadam/ssl.html"&gt;An Overview of SSL (version 2)&lt;/a&gt; (Thanks &lt;a href="http://conceptdev.blogspot.com/"&gt;Craig&lt;/a&gt;)
&lt;/li&gt;&lt;li&gt;Special mention: Mentalis's &lt;a href="http://www.mentalis.org/soft/projects/ssocket/"&gt;Secure Socket Library&lt;/a&gt; - free and open source implementation of the Secure Socket Layer (SSL) protocol version 3 and the Transport Layer Security (TLS) in C#!
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;
Examining the protocol reveals how SSL defends against a man-in-the-middle attack.

&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;
&lt;div style="text-align: center;"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/10/sm_ssl_client_t.gif" /&gt;

&lt;/div&gt;&lt;/td&gt;
&lt;td&gt;
&lt;div style="text-align: center;"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/10/sm_ssl_server_t.gif" /&gt;
&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;ClientHello: SSL version number, cipher settings, randomly generated data
&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;td&gt;ServerHello: SSL version number, cipher settings, randomly generated data, server certificate.   The server certificate contains the server's public key.
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;ClientKeyExchange: premaster secret for the session - derived from a hash of all the communcations to this point. This is sent encrypted with the server's public key.  The server decrypts this, and ensures the hash matches its own hash of the communcations.&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="3"&gt;
The client and server both create a session key to be used for the remainder of the session.  The session key is derived from the premaster secret, client random data, and server random data.
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;td&gt;ChangeCipherSpec: Finshed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP GET (communcations now encrypted with the established session key)&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/p&gt;

&lt;p&gt;The server certifcate delivered in the ServerHello is signed by a trusted certifcate authority (CA).  The client tests this signature against its own list of CA public keys.  The server certifcate also contains the domain name of the server.  This is used to confirm you have the certicate that has been authorised by an authority for the website located at amazon.com.  If the certificate does not pass either criteria your browser will give you a warning.&lt;/p&gt;

&lt;p&gt;If an attacker did sit in between your browser and a server and they passed along the certificate in the ServerHello - they wouldn't be able to decrypt the ClientKeyExchange.  As this has been encrypted with the server's public key - and the attacker is only in posession of the public key.  It &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; possible for the attacker to substitue their own certificate in this step.  But the browser will issue a warning if the certificate isn't:
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;signed by a trusted authority,
&lt;/li&gt;&lt;li&gt;and certificate's domain matches the site the client is connecting to.
&lt;/li&gt;&lt;/ul&gt;
As you may have already guessed: To have your server certificate signed by a trusted CA's (like Verign, Thawte and Comodo) you have to provide evidence you own the domain!  The other weakness is the list of trusted authorities you have installed in your browser.  As mention by Steve Gibson in the Security Now podcast (&lt;a href="http://www.grc.com/sn/sn-036.htm"&gt;episode 36&lt;/a&gt;) some corporate environments have inserted their own CA certificate in the client installations exactly so they can perform a man-in-the-attack to filter content at the proxy.

&lt;blockquote&gt;Now, there is an exception, though, which is the other reason I put this question in here today, because when you connect to a remote server you are accepting the credentials of the server, which has been signed by someone who signed their certificate, like we were talking about briefly before, about VeriSign, for example, signing GRC’s certificate.  Some corporations do want to proxy and filter and literally basically decrypt and be able to read their employees’ encrypted traffic.  So what they do is they run a proxy server in their corporate environment, which has a certificate.  And every browser in the company has been told to trust that certificate.  So essentially the encrypted traffic is decrypted at the corporate border.&lt;/blockquote&gt;

&lt;blockquote&gt;It’s decrypted at the corporate border and then, essentially, filtered, proxied, checked for spyware, or even for naughty content.  I mean, they could do anything they want to once they’ve got your connection decrypted.  Then it is reencrypted using a certificate that every corporate browser has been deliberately installed with in order for the browser not to complain.  So employees may believe they have encrypted and secure SSL connections, when in fact it is being decrypted in, you know, en route, essentially, you know, by their corporate firewall or IT staff or proxy server for whatever corporate reasons.&lt;/blockquote&gt;
&lt;/p&gt;

&lt;p&gt;Which finally does explain &lt;span style="font-style:italic;"&gt;how &lt;/span&gt;SSL defends against this attack!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-116108475599176279?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/116108475599176279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=116108475599176279' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/116108475599176279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/116108475599176279'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/10/ssl-man-in-middle.html' title='SSL + Man-in-the-Middle'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-116027277871068860</id><published>2006-10-08T11:51:00.002+10:00</published><updated>2010-07-17T22:48:36.459+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web dev'/><category scheme='http://www.blogger.com/atom/ns#' term='networking'/><title type='text'>Charles Proxy</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/10/charles-proxy/"&gt;http://blog.tinisles.com/2006/10/charles-proxy/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Checking out &lt;a href="http://xk72.com/charles/"&gt;Charles Web Debugging Proxy&lt;/a&gt; while I'm having a bit of a look under of the hood of SSL-Explorer.  Snooping on an a SSL session works straight out of the box.  Must be using a '&lt;a href="http://en.wikipedia.org/wiki/Man-in-the-middle"&gt;man-in-the-middle&lt;/a&gt;' method to sit between me an the SSL website.&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;p&gt;Yet, when I access &lt;a href="https://www.amazon.com"&gt;https://www.amazon.com&lt;/a&gt; via Charles Proxy I get a warning about the certificate.  Viewing the certificate 'certification path' shows that the content coming from the proxy has been encrypted with a certificate signed by 'Charles CA Certificate'.&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2006/10/lg_cproxy_sslcert.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/10/sm_cproxy_sslcert.jpg" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" /&gt;&lt;/a&gt;
&lt;div style="text-align: center;"&gt;&lt;span style="font-size:85%;"&gt;Left: without the proxy. Right: with Charles Proxy.&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;I know SSL does protect itself against a man-in-the-middle attack - but I don't know exactly how this works.  There's an SSL certificate on the server that's been signed by a 'certificate authority (CA)' - and your browser contains public keys of the trusted CAs (IE: Tools -&gt; Options -&gt; Content -&gt; Certificates -&gt; Trusted Root Certification Authorities, Firefox: Tools -&gt; Options -&gt; Advanced -&gt; Security -&gt; View Certificates -&gt; Authorities).  How do these pieces fit together to protect against this attack?&lt;/p&gt;

&lt;p&gt;More material for a blog post - stay tuned for the update.  In the mean time I'll be translating this:
&lt;/p&gt;&lt;ol&gt;

SSL 3.0 includes support for ephemerally-keyed
Diffie-Hellman key-exchange. Since Diffie-Hellman
is the only public key algorithm known which can
effciently provide perfect forward secrecy, this is
an excellent addition to SSL. In a SSL 3.0 Diffie-
Hellman key-exchange, the server specifes its Diffie-
Hellman exponent as well as the prime modulus and
generator. To avoid server-generated trapdoors, the
client should be careful to check that the modulus
and generator are from a fixed public list of safe
values. The well-known man-in-the-middle attack is
prevented in SSL 3.0 by requiring the server's Diffie-
Hellman exponential to be authenticated.
&lt;br&gt;
(Bruce Schneier - &lt;a href="http://www.schneier.com/paper-ssl.html"&gt;Analysis of the SSL 3.0 Protocol&lt;/a&gt;)
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-116027277871068860?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/116027277871068860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=116027277871068860' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/116027277871068860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/116027277871068860'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/10/charles-proxy.html' title='Charles Proxy'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-115977817155958767</id><published>2006-10-02T17:56:00.000+10:00</published><updated>2010-07-17T22:48:39.677+10:00</updated><title type='text'>My SSL-Explorer Questions Answered</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/10/my-ssl-explorer-questions-answered/"&gt;http://blog.tinisles.com/2006/10/my-ssl-explorer-questions-answered/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;My previous post &lt;a href="http://tinisles.blogspot.com/2006/03/remote-desktop-sshputty.html"&gt;Remote Desktop + SSH/Putty&lt;/a&gt; covered one approach for accessing your home PC via a strong security, strong encryption SSH tunnel.  &lt;a href="http://3sp.com/showSslExplorerCommunity.do"&gt;SSL-Explorer&lt;/a&gt; from 3SP also looks like a very simple way to remotely access your PC.  I first heard of this project when it was mentioned on Steve Gibson's 'Security Now!' podcast (&lt;a href="http://www.grc.com/sn/notes-015.htm"&gt;episode 15&lt;/a&gt;).  There is also a review on Tom's Networking: &lt;a href="http://www.tomsnetworking.com/2006/07/21/diy_ssl_vpn_with_ssl_explorer_pt1/page2.html"&gt;A DIY SSL VPN with SSL-Explorer&lt;/a&gt;, and &lt;a href="http://www.tomsnetworking.com/2006/07/27/diy_ssl_vpn_with_ssl_explorer_pt2/"&gt;part 2&lt;/a&gt;.  After reading the review I was left with a few questions, and sensing some material for a blog article.  I'm about to install SSL-Explorer on a spare PC: and try answering some of my questions.&lt;/p&gt;

&lt;p&gt;SSL-Explorer is an web-based SSL VPN server.  A VPN exists for a secure external access to resources you have one your network.  Perfect for 'roadwarrior' staff to access internal files and desktops from external sites, such as a hotel room, or home.  SSL-Explorer provides this though a web-browser interface.&lt;/p&gt;

&lt;p&gt;Once installed you get a web-based admin to administer the application - create users, set-up permissions, and configure the resources that will be made available to the users.  A user connects via a browser, after logging-in they are presented a simple screen displaying the resources they have access to.  Users can access the web securely, view Remote Desktops, and transfer files all via SSL-Explorer.&lt;/p&gt;


&lt;div style="text-align: center;"&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2006/10/lg_sslesp_applications.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/10/sm_sslesp_applications.jpg" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" /&gt;&lt;/a&gt;
&lt;span style="font-size:85%;"&gt;SSL-Explorer's User Console displaying the 'Applications' available to the user.&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;The fresh install allows me to create: Web Forwards, Network Places, Applications, and SSL Tunnels.  My first question was: how exactly do you make applications available via a web browser?  The Tom's Hardware article goes through the steps of creating a VNC connection back to a server behind the firewall in the section "&lt;a href="http://www.tomsnetworking.com/2006/07/27/diy_ssl_vpn_with_ssl_explorer_pt2/page7.html"&gt;Checking out Remote Desktop&lt;/a&gt;".  More questions:
&lt;ul&gt;
&lt;li&gt;Where is this VNC executing?  
&lt;li&gt;If it is executing on the client:
&lt;ul&gt;
&lt;li&gt;How did it get there?
&lt;li&gt;How can it connect to the VNC behind the firewall?
&lt;/ul&gt;
&lt;/ul&gt;

Trying this out on my own set-up: in the admininstration I first set-up the VNC application short cut.  I'm presented will a lot of options for the short cut:

&lt;a href="http://blog.tinisles.com/blogger-images/2006/10/lg_sslexp_vnc_options.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/10/sm_sslexp_vnc_options.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

Logging into the website as a 'user' I now have an option to launch VNC.  Launching the app reveals an extra component to the SSL-Explorer application: the SSL-Explorer Agent.  The first time I attempt to launch the VNC application from the web console - I'm prompted to install a signed java applet.  This launches the SSL-Explorer Agent on my client.

&lt;a href="http://blog.tinisles.com/blogger-images/2006/10/lg_sslexp_app_launch.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/10/sm_sslexp_app_launch.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

The SSL-Explorer Agent has:
&lt;ul&gt;
&lt;li&gt; copied the application down to my PC (a search finds the application in %USERPROFILE%\.sslexplorer\applications),
&lt;li&gt; created a tunnel port on the client PC,
&lt;li&gt; and launched the VNC application with the command line options to connect to the tunnel port.
&lt;/ul&gt;

So the application sharing is conceptually very similar to using SSH tunnels to connect to a server behind a firewall.  VNC is connecting a tunnel port on the local machine created by SSL-Explorer Agent.  The agent is transferring this data to the SSL-Explorer application via SSL - which then transfers the data to and from the VNC server.  SSL-Explorer is wrapping this up in a nice web interface.  Not all applications are suitable to be shared this way.  To work, an application needs to:
&lt;ul&gt;
&lt;li&gt; Be the client in a TCP client/server environment, i.e. Remote Desktop, VNC, Putty.  
&lt;li&gt; Allow the server address and port to be 'fed in' to the app, either via a command line argument, or config file.  This is how the SSL-Explorer Agent tells the client to connect to the local tunnel port.  The multitude of options available when creating the VNC shortcut is used to create a VNC parameter file on the client machine. This rules out MSN Messenger and Skype as they are 'hardcoded' with their server address and port.
&lt;/ul&gt;

Notably all the applications that come out of the box prompt the user for a password when a password is not present in the command line or config.  Presumably this is preferable to leaving a password on the client machine.

&lt;/p&gt;

&lt;p&gt;Well that's answered the initial questions I had of SSL-Explorer, and has given me some more questions for my next blog post.  Maybe try my hand at creating my own application extension?  I've had a quick look around for a minimal Jabber client which meets all the criteria, may play a bit more with that.  Also thinking of using a snooping proxy to see what is actually going over the HTTPS wire (&lt;a href="http://xk72.com/charles/"&gt;Charles Proxy&lt;/a&gt; is capable of this).  If someone were given an account without any tunnels setup - could you falsify the server traffic to have the agent create a tunnel?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-115977817155958767?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/115977817155958767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=115977817155958767' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115977817155958767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115977817155958767'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/10/my-ssl-explorer-questions-answered.html' title='My SSL-Explorer Questions Answered'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-115607381526464773</id><published>2006-08-20T20:25:00.002+10:00</published><updated>2010-07-17T22:48:50.987+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mssql'/><title type='text'>Importing the Geo-Names database into MsSql Server</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/08/importing-the-geo-names-database-into-mssql-server/"&gt;http://blog.tinisles.com/2006/08/importing-the-geo-names-database-into-mssql-server/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;span style="font-weight:bold;"&gt;Update (26-Jul-2009)&lt;/span&gt;: This article is now a little outdated.  The table now has some extra columns.  Have a look at &lt;a href="http://blogs.msdn.com/edkatibah/archive/2009/01/13/loading-geonames-data-into-sql-server-2008-yet-another-way.aspx"&gt;Loading GeoNames Data Into SQL Server 2008&lt;/a&gt; by EdKatibah for an up-to-date approach.  I've successfully imported the newest allCountries.txt with the following steps:
&lt;ol&gt;
&lt;li&gt; UNIX2DOS to update the line endings of AllCountries.txt
&lt;li&gt; Same nant script below to convert AllCountries.txt to UNICODE
&lt;li&gt; CREATE TABLE now looks like this:
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: sql"&gt;
CREATE TABLE [GeoNames] (
    [GeonameID] [int] NOT NULL ,
    [Name] [nvarchar] (200) NOT NULL ,
    [AnsiName] [varchar] (200) NULL ,
    [AlternateNames] [nvarchar] (MAX) NULL ,
    [Latitude] [float] NOT NULL ,
    [Longitude] [float] NOT NULL ,
    [FeatureClass] [char] (1) NULL ,
    [FeatureCode] [varchar] (10) NULL ,
    [CountryCode] [char] (2) NULL ,
    [CC2] [varchar] (60) NULL ,
    [Admin1Code] [varchar] (20) NULL ,
    [Admin2Code] [varchar] (80) NULL ,
    [Admin3Code] [varchar] (20) NULL ,
    [Admin4Code] [varchar] (20) NULL ,
    [Population] [bigint] NOT NULL ,
    [Elevation] [int] NULL ,
    [GTopo30] [int] NULL ,
    [Timezone] [varchar] (50) NULL ,
    [ModificationDate] [datetime] NULL 
) &lt;/pre&gt;
&lt;li&gt; EdKatibah's BULK INSERT works nicely:
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: sql"&gt;
BULK INSERT GeoNames
FROM 'D:\Developer\Geonames\allCountries_unicode.txt'
WITH(
   DATAFILETYPE = 'widechar',
   FIELDTERMINATOR = '\t',
   ROWTERMINATOR = '\n'
)
GO &lt;/pre&gt;
&lt;/ol&gt;

Using BULK INSERT to load the data is MUCH nicer than using BCP.  As BULK INSERT will actually tell you where and WHY and import failed.  I was originally trying to do this with BCP.  I had DECIMAL types for latitude and longitude - which resulted in an infuriating error because a handful of rows have scientific notation representation.
&lt;hr&gt;

&lt;p&gt;&lt;a href="http://www.geonames.org/export/"&gt;Geo-Names&lt;/a&gt; "provides free geo-data such as geographical names and postal codes. The database contains over 6 million entries for geographical names whereof 2.2 million cities and villages".  The offer their content via a webservice, and as a &lt;a href="http://download.geonames.org/export/dump/"&gt;database download&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm using a subset of this data for my 'learn ASP.NET 2.0' project, so I've imported the database export into my SQL Server. Here's the steps I followed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Create a table that looks like this (note the nvarchar columns for the extendend characters):

&lt;pre class="brush: sql"&gt;

CREATE TABLE [CityNames] (
    [GeonameID] [int] NOT NULL ,
    [Name] [nvarchar] (200) NOT NULL ,
    [AnsiName] [varchar] (200) NOT NULL ,
    [Latitude] [decimal](18, 15) NOT NULL ,
    [Longitude] [decimal](18, 15) NOT NULL ,
    [FeatureCode] [varchar] (10) NULL ,
    [CountryCode] [char] (2) NULL ,
    [Admin1Code] [varchar] (20) NULL ,
    [Population] [int] NOT NULL 
) 

&lt;/pre&gt;

&lt;li&gt; The database export is a UTF8 file - MSSQL DTS import wants a UTF16 file.  Easy to convert a file by opening it in Textpad/VS.Net and using 'Save As' to change the encoding.  Not so easy with the 500meg 'allCountries' file.  The nant &lt;a href="http://nant.sourceforge.net/nightly/latest/help/tasks/copy.html"&gt;copy task&lt;/a&gt; works well for this:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: xml"&gt;
&amp;lt;target name=&amp;quot;build&amp;quot;&amp;gt;
    &amp;lt;copy file=&amp;quot;allCountries.txt&amp;quot; 
    todir=&amp;quot;Converted&amp;quot; inputencoding=&amp;quot;UTF-8&amp;quot; 
    outputencoding=&amp;quot;UNICODE&amp;quot;/&amp;gt;
&amp;lt;/target&amp;gt;&lt;/pre&gt;
&lt;li&gt;Import the converted file via the DTS Import/Export Wizard.  In Enterprise Manager right-click the database &gt; All Tasks &gt; Import Data...
&lt;li&gt;Follow the prompts to import the converted file.  On the file format screen select the following options: File Type = Unicode, Row Delimeter = {LF}, Text Qualifer = &lt;none&gt;.

&lt;a href="http://blog.tinisles.com/blogger-images/2006/08/lg_geonames.png"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/08/sm_geonames.png" style="cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;li&gt;If all the names look neatly lined up on the next screen your file has imported okay.

&lt;a href="http://blog.tinisles.com/blogger-images/2006/08/lg_geonames2.png"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/08/sm_geonames2.png" style="cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;li&gt;In the next two steps select the destination database / table created in the first step.

&lt;li&gt;Just to make sure all the UTF-16 content has come across okay - jump into Query Analyzer and run something like this:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: sql"&gt;
SELECT AlternateNames FROM GeoNames WHERE GeonameID=2147714&lt;/pre&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-115607381526464773?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/115607381526464773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=115607381526464773' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115607381526464773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115607381526464773'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/08/importing-geo-names-database-into.html' title='Importing the Geo-Names database into MsSql Server'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-115356435071957386</id><published>2006-07-30T20:25:00.001+10:00</published><updated>2010-07-17T22:49:25.264+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='utilities'/><title type='text'>Better Password Management</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/07/better-password-management/"&gt;http://blog.tinisles.com/2006/07/better-password-management/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Saturday night geek project: do something about my dodgy password management.  Maybe listening to the &lt;a href="http://www.grc.com/securitynow.htm"&gt;Security Now&lt;/a&gt; podcast has got me paranoid enough to do something about my passwords.  I currently deal with passwords in a way that's no embarrassingly bad I'm not going to mention it.  Not as bad as a "passwords.txt" on the desktop - but still pretty bad.  (And by the time you read this it'll be A LOT more secure :)&lt;/p&gt;

&lt;p&gt;I REALLY REALLY should be doing the following things for my passwords:
&lt;ol&gt;
&lt;li&gt;Different passwords for all my logins.
&lt;li&gt;Using randomly generated passwords - filled with lots of funny characters, mixed case, and numbers.
&lt;li&gt;Regularly changing passwords.  Take out a night every few months to log into all the sites I use and change my password?
&lt;li&gt;NOT storing them in a clear file somewhere.  Maybe I shouldn't be storing them in the IE &amp; Firefox autocomplete databases.  How strongly encrypted are they?
&lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;Thinking though the features I'd want for an app to automate this:
&lt;ol&gt;
&lt;li&gt;Generates random passwords.  
&lt;li&gt;Stores everything with strong encryption.
&lt;li&gt;Runs from a USB key so I can use it from work and home.
&lt;li&gt;preferably open source (or a free download).
&lt;li&gt;Nice to have: integration with the IE &amp; Firefox password autocomplete.  Or maybe just an easy way to export the existing passwords from my browsers.
&lt;li&gt;Some automated means of doing the monthly password update?
&lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;A search of Firefox extensions, and &lt;a href="http://sourceforge.net/"&gt;SourceForge&lt;/a&gt; came up with:  
&lt;a href="http://www.roboform.com/"&gt;RoboForm&lt;/a&gt;, &lt;a href="http://passwordsafe.sourceforge.net/"&gt;Password Safe&lt;/a&gt;, and &lt;a href="http://keepass.sourceforge.net/"&gt;KeePass&lt;/a&gt;.  RoboForm has most of the features I'm after (USB key operation, IE/Firefox integration, and password generation) but is limited after the &lt;a href="http://www.roboform.com/why-pro.html"&gt;trial period&lt;/a&gt; runs out.  Password Safe  and KeePass look very similar - decided to go with KeePass as: it's a single EXE, has a prettier UI, and it's a more popular project for SourceForge.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2006/07/lg_main_big.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/07/sm_main_big.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;KeePass stores all your passwords in an encrypted database - which requires a password to access.  When adding an entry you can choose to generate a random password.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2006/07/lg_keypass_gen_password.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/07/sm_keypass_gen_password.jpg" style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately there is no browser integration, but there in an auto-type feature.  This enters your credentials into the active form.  By default it'll simulate you typing your username, pressing tab, typing your password, and pressing enter.  This is also configurable per entry.  An entry can be set to expire by date - this is the closest to any automation of a monthly password update.&lt;/p&gt;

&lt;p&gt;Now I've spent a night logging into a stack of websites, and changing my passwords to randomly generated ones.  Which means I'm completely reliant on the Keypass database - there's no way I'd be able to commit these passwords to memory.  A copy of the KeePass database at home, and work is fine - how often do I go to an internet cafe anyways?  For convenience I've allowed Firefox to remember passwords for the sites that allow it (banking sites are "autocomplete=false" for good reason!) - and I've set a master password on the Firefox password store.  This reliance also means it's &lt;span style="font-style:italic;"&gt;very&lt;/span&gt; important I have backups of theKeyPasss database, plus a backup of "plaintext" export in the event I forget the KeyPass password.&lt;/p&gt;

&lt;p&gt;Some words of warning about the process of updating all your passwords.  After you've generated your password you'll paste it into the change password page somewhere.  The password input box will most likely display stars as you type.  You want to be pretty confident you are pasting the right thing in there.  If you accidentally paste something else you'll just see stars and won't know - effectively locking yourself out of the account!  Another website I use had a 8 character limit on their passwords - I pasted in a 15 character string and only the first 8 characters were saved.  Because I was seeing stars I had no way of knowing what'd happened - I only worked out what'd happened when I noticed the wrong password page had the same limit (yet the main login page didn't!).  Chris Pederick's &lt;a href="http://chrispederick.com/work/webdeveloper/"&gt;Web Developer Extension&lt;/a&gt; has a feature to turn password fields into plain text fields - this means you can be totally confident you've pasted the right thing.  
&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2006/07/lg_firefox_password_manager.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/07/sm_firefox_password_manager.jpg" style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;p&gt;Another warning on the autotype feature: if you have the Firefox Password Manager open when you select auto type - all your passwords get wiped out.  Because the 'auto-typed' tab selects the 'Remove All' button, and then the 'enter' clicks it!  Firefox wipes out all your passwords without prompting you!&lt;/p&gt;

&lt;p&gt;I've been running for a week now with KeePass and I find it's working well.  As I mentioned I now can't pop into an internet cafe and check my mail - something which I haven't done in a long time.  Plus I'm now WAY too paranoid to log into an online banking site from an internet cafe.  &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-115356435071957386?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/115356435071957386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=115356435071957386' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115356435071957386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115356435071957386'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/07/better-password-management.html' title='Better Password Management'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-115218868945088961</id><published>2006-07-06T21:59:00.001+10:00</published><updated>2010-07-17T22:54:23.978+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='links'/><title type='text'>Some Things I Currently Think Are Cool</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/07/some-things-i-currently-think-are-cool/"&gt;http://blog.tinisles.com/2006/07/some-things-i-currently-think-are-cool/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            Okay, I'm a geek..  There won't be any going back after this.. 

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://thedailywtf.com/"&gt;The Daily WTF&lt;/a&gt; - a regular dose of schadenfreude.
&lt;li&gt;&lt;a href="http://alterslash.org/"&gt;AlterSlash ~ the unofficial SlashDot digest&lt;/a&gt; - has an algorithm to pull out the best comments for each Slashdot article displayed in digest format.  Its got me back reading Slashdot, the comments are actually the best bit!
&lt;li&gt;&lt;a href="http://www.grc.com/securitynow.htm"&gt;Security Now!&lt;/a&gt; - podcast on computer security issues.  Steve Gibson does a good job of explaining the fundamentals, and how they relate to security hazards.  Could be a good place to point people who are having trouble with some networking concepts.  Some are a bit less interesting than others - safe to skip to the Buffer Overrun episode. (Thanks Ben)
&lt;li&gt;&lt;a href="http://www.gmap-pedometer.com/"&gt;Gmaps Pedometer&lt;/a&gt; - draw a route on a google map, measure the distance, and save it for a unique URL of your route: &lt;a href="http://www.gmap-pedometer.com/?r=167809"&gt;http://www.gmap-pedometer.com/?r=167809&lt;/a&gt; (Thanks &lt;a href="http://conceptdev.blogspot.com/"&gt;Craig&lt;/a&gt;)
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Featured_desktop_backgrounds"&gt;Wikipedia featured desktop backgrounds&lt;/a&gt;
&lt;li&gt;Opera Widgets: &lt;a href="http://widgets.opera.com/widget/4196"&gt;Circular Tetris&lt;/a&gt; and &lt;a href="http://widgets.opera.com/widget/4162"&gt;Bounce&lt;/a&gt;. (Thanks Ellecer)
&lt;li&gt;Watch some doccos online from ABC's &lt;a href="http://abc.net.au/4corners/specials.htm"&gt;Four Corners&lt;/a&gt; and PBS's &lt;a href="http://www.pbs.org/wgbh/pages/frontline/view/"&gt;Frontline&lt;/a&gt;.
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-115218868945088961?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/115218868945088961/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=115218868945088961' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115218868945088961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115218868945088961'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/07/some-things-i-currently-think-are-cool.html' title='Some Things I Currently Think Are Cool'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-115037170998378161</id><published>2006-06-15T21:33:00.001+10:00</published><updated>2010-07-17T22:54:27.835+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><title type='text'>VMware update</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/06/vmware-update/"&gt;http://blog.tinisles.com/2006/06/vmware-update/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;What I've discovered playing with VMware server.  &lt;/p&gt;

&lt;p&gt;The &lt;a href="http://en.wikipedia.org/wiki/VMware"&gt;wikipedia entry&lt;/a&gt; is actually more informative than the VMware website (or I was more patient tonight).  From wikipedia:
&lt;ul&gt;
&lt;li&gt; the difference between VMware Player and Server: &lt;span style="font-style:italic;"&gt;VMware Player, a free virtual-machine host, can run virtual machines made by other VMware products, but cannot itself create new virtual machines.&lt;/span&gt;
&lt;li&gt; how to lock your VM network adapter to one MAC address: &lt;span style="font-style:italic;"&gt;disable all networks/adapters other than bridged and edit each virtual machine's .vmx file to change "ethernet0.address" to a unique MAC and "ethernet0.addresstype" to "static". Make sure to also remove the "ethernet0.generatedaddress" entry entirely.&lt;/span&gt;  &lt;a href="http://www.vmware.com/support/esx15/doc/esx15_netwk2.html"&gt;Setting the MAC Address Manually for a Virtual Machine&lt;/a&gt; goes into more detail.
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;At first I was a bit puzzled that I could power up my Trustix VM - and it'll be visible on my network via ping and SSH.  Yet when I logged out of the &lt;span style="font-style:italic;"&gt;host&lt;/span&gt; OS the VM would disappear.  According to the forum post "&lt;a href="http://www.vmware.com/community/thread.jspa?threadID=45086&amp;tstart=0"&gt;VM powers off by itself....&lt;/a&gt;" this is caused by connecting to the host OS via Remote Desktop.  A better alternative is to power up my VM via the VMware Server Console.&lt;/p&gt;

&lt;p&gt;VMware Server is a true client/server app.  Your virtual machines execute on a server somewhere - and you can connect to administer/view the machines from another PC using the VMware Server Console.  For me this required opening up port 902 on my host OS.&lt;/p&gt;

Connecting to the VM Server.
&lt;a href="http://blog.tinisles.com/blogger-images/2006/06/lg_trustix02.png"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/06/sm_trustix02.png" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

Trustix VM viewed from my main PC.
&lt;a href="http://blog.tinisles.com/blogger-images/2006/06/lg_trustix03.png"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/06/sm_trustix03.png" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;Now that my VM is running continuously - I can do all my Linux mucking around from an SSH client.  So I don't really have much need to connect via the VMware Server Console.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-115037170998378161?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/115037170998378161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=115037170998378161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115037170998378161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115037170998378161'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/06/vmware-update.html' title='VMware update'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-115009461866483852</id><published>2006-06-12T16:28:00.001+10:00</published><updated>2010-07-17T22:54:30.754+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><title type='text'>Trustix + VMware Server</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/06/trustix-vmware-server/"&gt;http://blog.tinisles.com/2006/06/trustix-vmware-server/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Queen's birthday long weekend - and I've found another quick geeky project to play with at home.  This one was quick (I swear!).  I've being contemplating recently how I'd go about setting up a small business network with the essentials - web/mail/file/proxy server plus the very necessary extras like back-up and spam/virus filtering for email.&lt;/p&gt;

&lt;p&gt;The offerings from the open source world are pretty impressive (without getting into a debate over paid-for / free software).  Which led me to the &lt;a href="http://www.trustix.org/"&gt;Trustix&lt;/a&gt; Linux distro - from their website:&lt;/p&gt;

&lt;blockquote&gt;Trustix Secure Linux is a distribution for servers with a heavy focus on security and stability. One of the main features of Trustix is its small size which combined with easy updating by the automated secure software updater swup, makes it a smooth and inviting system to administer.&lt;/blockquote&gt;

&lt;p&gt;Having been away from the Linux world for 10 years and having never been an expert - the idea of a 'minimal' distribution appeals to me.  An 'everything plus the kitchen sink' distro just means more things that could go wrong, more potential security holes, and more applications to patch/update.&lt;/p&gt;

&lt;p&gt;Got an install up-and-running on my 'test' machine.  In the mood for experimenting I downloaded the free &lt;a href="http://www.vmware.com/products/server/"&gt;VMware Server&lt;/a&gt;, and a Trustix install ISO file.  The virtual PC can be set-up to boot straight from the ISO image, and install Trustix effortlessly.  I know of a few people working with production servers hosted in VMware.  I can see the advantages - I can now easily move my Trustix install between PCs running VMserver.  Making it possible to run several servers on one physical machine - and move them off onto more physical machines as the additional resources become needed.&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2006/06/lg_trustix01.png"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/06/sm_trustix01.png" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;Documentation is a bit thin on the ground, the &lt;a href="http://www.trustix.org/wiki/index.php/Main_Page"&gt;TrustixWiki&lt;/a&gt; covers most of the scenarios I'm interested in.  So now its time to roll up my sleeves (stop saying 'I bet this is easier in Windows') and think about the features I want on my new server!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-115009461866483852?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/115009461866483852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=115009461866483852' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115009461866483852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/115009461866483852'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/06/trustix-vmware-server.html' title='Trustix + VMware Server'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114809693458503378</id><published>2006-05-20T13:42:00.001+10:00</published><updated>2010-07-17T22:54:37.270+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>IE Javascript problem?</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/05/ie-javascript-problem/"&gt;http://blog.tinisles.com/2006/05/ie-javascript-problem/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;What would you expect the bit of javascript below to do?&lt;/p&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: html"&gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;

    &amp;lt;select id=&amp;quot;testing&amp;quot;&amp;gt;
    &amp;lt;/select&amp;gt;

    &amp;lt;script&amp;gt;
        var testing = document.getElementById('testing');
            
        var georgeOpt = new Option(&amp;quot;George&amp;quot;, 1);
        testing.options[testing.length]=georgeOpt;        
        
        var paulOpt = new Option(&amp;quot;Paul&amp;quot;, 2);
        testing.options[testing.length]=paulOpt;    
            
        var johnOpt = new Option(&amp;quot;John&amp;quot;, 3);
        testing.options[testing.length]=johnOpt;    
            
        var ringoOpt = new Option(&amp;quot;Ringo&amp;quot;, 4);
        ringoOpt.selected = true;
        testing.options[testing.length]=ringoOpt;        
    &amp;lt;/script&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;In Firefox the SELECT is displayed with Ringo selected, in IE John is selected.  If you swap the last two lines of script - Ringo is selected in both browsers.  Easily fixed so its no biggie.  I &lt;span style="font-style:italic;"&gt;guess&lt;/span&gt; it doesn't really make sense to tell an OPTION it is selected &lt;span style="font-style:italic;"&gt;before&lt;/span&gt; it belongs to a SELECT?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114809693458503378?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114809693458503378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114809693458503378' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114809693458503378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114809693458503378'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/05/ie-javascript-problem.html' title='IE Javascript problem?'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114794737716988846</id><published>2006-05-18T19:53:00.001+10:00</published><updated>2010-07-17T22:54:39.886+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Scott Guthrie's ASP.NET + Atlas Tutorial</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/05/scott-guthries-asp-net-atlas-tutorial/"&gt;http://blog.tinisles.com/2006/05/scott-guthries-asp-net-atlas-tutorial/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Pretty cool demo of some of the new features of VS.NET 2005 + ASP.NET from Scott Guthrie &lt;a href="http://download.microsoft.com/download/8/5/8/85803fdd-fe9a-4783-ab37-e0c565172ffd/asp_net_atlas.wmv"&gt;here&lt;/a&gt;.  Scott shows off the new features in: DataSets, master pages, and Atlas.&lt;/p&gt;

&lt;p&gt;Try count how many times he says 'go ahead'.&lt;/p&gt;

&lt;p&gt;How is he recording that?  Maybe it's that 'clapper board' icon in the systray?  Looks like an Office icon.  Got me interested in recording tutorials via screen cam software.  Discovered you can record your own with the &lt;a href="http://www.microsoft.com/windows/windowsmedia/forpros/encoder/default.mspx"&gt;Windows Media Encoder&lt;/a&gt;.  So here's my &lt;a href="http://blog.time2call.net/iis-recording2.wmv"&gt;first attempt at a screen capture tutorial&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114794737716988846?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114794737716988846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114794737716988846' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114794737716988846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114794737716988846'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/05/scott-guthries-aspnet-atlas-tutorial.html' title='Scott Guthrie&amp;#39;s ASP.NET + Atlas Tutorial'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114747801590097975</id><published>2006-05-13T09:29:00.000+10:00</published><updated>2010-07-17T22:54:43.058+10:00</updated><title type='text'>Google Trends</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/05/google-trends/"&gt;http://blog.tinisles.com/2006/05/google-trends/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Okay, Google's latest project &lt;a href="http://www.google.com/trends"&gt;Google Trends&lt;/a&gt; is pretty entertaining.&lt;/p&gt;

&lt;p&gt;Type in a search term like,  '&lt;a href="http://www.google.com/trends?q=hurricane+katrina"&gt;hurricane katrina&lt;/a&gt;' and get back a graph of search volume over time, and a table of the cities where the search term was most popular.  The results are normalised, i.e. the table is ordered by searches for 'hurricane katrina' over the total searches for that city.  The labels on the graph correlate the dates of news articles.&lt;/p&gt;

&lt;p&gt;Or view a comparison by comma separating search terms, '&lt;a href="http://www.google.com/trends?q=coke%2C+pepsi&amp;ctab=0&amp;geo=all&amp;date=all"&gt;coke, pepsi&lt;/a&gt;' or '&lt;a href="http://www.google.com/trends?q=kfc%2C+macdonalds&amp;ctab=0&amp;geo=all&amp;date=all"&gt;kfc, macdonalds&lt;/a&gt;'.&lt;/p&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2006/05/sm_google_trends.0.gif"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/05/sm_google_trends.0.gif" style="border:1px solid black; display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114747801590097975?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114747801590097975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114747801590097975' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114747801590097975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114747801590097975'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/05/google-trends.html' title='Google Trends'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114579902932919926</id><published>2006-04-23T23:09:00.001+10:00</published><updated>2010-07-17T22:54:55.520+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><title type='text'>Microsoft Virtual Labs</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/04/microsoft-virtual-labs/"&gt;http://blog.tinisles.com/2006/04/microsoft-virtual-labs/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            This rates as one of the handiest things I've seen in a while (okay I'm a geek).  Say you feel like brushing up on some new Microsoft server/application - so you set up a VirtualPC and play with it there.  Microsoft's Virtual Labs have made this much much easier by setting up test environments for you which you can access via a web browser.  I had a play with the "&lt;a href="http://go.microsoft.com/?linkid=4671353"&gt;Introduction to Windows Server 2003 Management&lt;/a&gt;" tutorial - which allows you to switch between the four PCs being "virtualized" for the tutorial (domain controller, workstation, etc).

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.microsoft.com/technet/traincert/virtuallab"&gt;TechNet Virtual Labs for IT Pros&lt;/a&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/virtuallabs"&gt;MSDN Virtual Labs for Developers&lt;/a&gt;
&lt;/ul&gt;

&lt;a href="http://blog.tinisles.com/blogger-images/2006/04/lg_virtuallabs.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/04/sm_virtuallabs.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;
It looks like it all works around virtual servers hosted in Microsoft Virtual Server.  Virtual servers can be viewed over the network via the 'Virtual Machine Remote Control' ActiveX control.  You can view a virtual server which has it network connection intentionally "restricted" - something you couldn't do with Remote Desktop.  Thinking of hosting CruiseControl.net inside a virtual server at home - and adding a page to the CruiseControl webapplication with the VMRC ActiveX to jump onto the server. 
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://www.microsoft.com/windowsserversystem/virtualserver/software/default.mspx"&gt;Microsoft Virtual Server&lt;/a&gt; is now a free download.  As are two VMWare products: &lt;a href="http://www.vmware.com/products/player/"&gt;Player&lt;/a&gt; and &lt;a href="http://www.vmware.com/products/server/"&gt;Server&lt;/a&gt;.  VMWare also provide a directory of "pre-installed" virtual machines: &lt;a href="http://www.vmware.com/vmtn/appliances/directory/"&gt;Virtual Appliances&lt;/a&gt;.  Looks like a very easy way to check out a Linux distro.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114579902932919926?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114579902932919926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114579902932919926' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114579902932919926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114579902932919926'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/04/microsoft-virtual-labs.html' title='Microsoft Virtual Labs'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114326386409126821</id><published>2006-03-25T16:17:00.001+11:00</published><updated>2010-07-17T22:55:02.645+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='utilities'/><title type='text'>SyncToy for Windows XP</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/03/synctoy-for-windows-xp/"&gt;http://blog.tinisles.com/2006/03/synctoy-for-windows-xp/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;&lt;a href="http://www.microsoft.com/windowsxp/using/digitalphotography/prophoto/synctoy.mspx"&gt;SyncToy for Windows XP&lt;/a&gt; is a simple bit of software from Microsoft that fits the bill for my home PC backups.  Give it any number of folder pairs, and configure how you'd like the two folders to remain in sync.  There are 5 different synchronisation methods, each differ in the way they treat deleted/modified/new files.  For example; to back up my digital photos I have a D:\Photos folder and an E:\Photos folder on two different physical disks.  I can configure sync toy to keep the two folders in sync, and I'm protected from a hard disk failure.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2006/03/lg_synctoy01.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/03/sm_synctoy01.jpg" style="display:block; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sync doesn't happen automatically, which is something I like about it.  Alternatively there are instructions on how to use the Windows Scheduled Tasks to schedule recurrent SyncToy runs. &lt;/p&gt;

&lt;p&gt;If I got really keen I could set-up folder pairs to sync everything I'd want for a rebuild (installers, coding projects, documents, bookmarks, photos, etc) with an external HD.  I'll have a back-up and rebuilding my PC would be infinitely easier.&lt;/p&gt;

&lt;p&gt;Just experimented synchronising with a CDRW.  When you select the CD drive from the folder dialog the folder actually selected is in %USERPROFILE%\Local Settings\Application Data\Microsoft\CD Burning.  If you try manually typing the CD-ROM drive name, you get an error telling you to 'make sure external devices are attached'.  The first time you attempt to synchronise, the files get delivered to the "CD Burning" folder, and you get the disk burning pop-up.&lt;p&gt;

&lt;p&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2006/03/lg_synctoy02.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/03/sm_synctoy02.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything gets burnt to the disk okay.  But second time around the "CD Burning" folder is empty - so SyncToy attempts to copy every file again, and you get an error when you try burn the CD.  Everything does work okay if you first format the CDRW, which I &lt;span style="font-style:italic;"&gt;could&lt;/span&gt; put up with.  Ideally it'd be great if SyncToy itself could handle the CD burning process, and support spanning disks.  Otherwise I'm very happy with this little discovery.  Thanks to &lt;a href="http://www.flickr.com/people/ellecer/"&gt;Ellecer&lt;/a&gt; for getting me onto this!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114326386409126821?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114326386409126821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114326386409126821' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114326386409126821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114326386409126821'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/03/synctoy-for-windows-xp.html' title='SyncToy for Windows XP'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114177414905695172</id><published>2006-03-25T10:29:00.001+11:00</published><updated>2010-07-17T22:55:07.975+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='links'/><title type='text'>Another link drop</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/03/another-link-drop/"&gt;http://blog.tinisles.com/2006/03/another-link-drop/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;ul&gt;
&lt;li&gt;Holidaying in Rio de Janeiro: Why not stay at &lt;a href="http://www.favelinha.com/en/index.php"&gt;Pousada Favelinha&lt;/a&gt;?  Sounds like &lt;a href="http://news.bbc.co.uk/1/hi/world/americas/3247709.stm"&gt;favela tourism&lt;/a&gt; is the way to discover Brazil!
&lt;li&gt;&lt;a href="http://www.seoconsultants.com/css/menus/horizontal/"&gt;CSS Menus - Horizontal CSS Menu with Dropdown and Popout Menus&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.s-e-u-l.org/SEUL/dome.html"&gt;Bucky's BR Dome&lt;/a&gt; - &lt;a href="http://en.wikipedia.org/wiki/Urban_Exploration"&gt;Urban exploration&lt;/a&gt; in a derelict geodesic dome in Louisiana
&lt;li&gt;Currently my favourite ad on telly for the &lt;a href="http://ia300239.us.archive.org/3/items/Changes_4/54_www.joeytomatoes.com_Agency_DDBLondon_VWJettaChanges.mov"&gt;Volkswagen Jetta&lt;/a&gt;
&lt;li&gt;&lt;a href="http://blog.html.it/layoutgala/"&gt;Layout Gala&lt;/a&gt;: a collection of 40 CSS layouts based on the same markup and ready for download!
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114177414905695172?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114177414905695172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114177414905695172' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114177414905695172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114177414905695172'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/03/another-link-drop.html' title='Another link drop'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114221815915268243</id><published>2006-03-13T13:49:00.000+11:00</published><updated>2010-07-17T22:55:15.075+10:00</updated><title type='text'>States Pass Thousands of Info Restriction Laws</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/03/states-pass-thousands-of-info-restriction-laws/"&gt;http://blog.tinisles.com/2006/03/states-pass-thousands-of-info-restriction-laws/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Wow, I just saw this really thought provoking &lt;a href="http://slashdot.org/comments.pl?sid=06/03/11/2046257&amp;amp;threshold=1&amp;amp;commentsort=0&amp;amp;mode=nested&amp;amp;cid=14900276"&gt;comment&lt;/a&gt; on the the Slashdot article:  &lt;a href="http://politics.slashdot.org/article.pl?sid=06/03/11/2046257"&gt;States Pass Thousands of Info Restriction Laws&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;"The smart way to keep people passive and obedient is to strictly limit the spectrum of acceptable opinion, but allow very lively debate within that spectrum - even encourage the more critical and dissident views. That gives people the sense that there's free thinking going on, while all the time the presuppositions of the system are being reinforced by the limits put on the range of the debate." Noam Chomsky&lt;/blockquote&gt;

&lt;p&gt;I always knew there was something sinister about &lt;a href="http://en.wikipedia.org/wiki/Speaker%27s_Corner"&gt;Speaker's Corner&lt;/a&gt; in London..&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114221815915268243?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114221815915268243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114221815915268243' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114221815915268243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114221815915268243'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/03/states-pass-thousands-of-info.html' title='States Pass Thousands of Info Restriction Laws'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114147350044749432</id><published>2006-03-04T22:52:00.001+11:00</published><updated>2010-07-17T22:56:35.077+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='networking'/><title type='text'>Update:  Remote Desktop + SSH/Putty</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/03/update-remote-desktop-sshputty/"&gt;http://blog.tinisles.com/2006/03/update-remote-desktop-sshputty/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;This is an update to the article below: 
&lt;a href="http://tinisles.blogspot.com/2006/03/remote-desktop-sshputty.html"&gt;Remote Desktop + SSH/Putty&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After reading this article on &lt;a href="http://www.infosecwriters.com/text_resources/pdf/ssh_tunneling.pdf"&gt;accessing a machine behind a firewall&lt;/a&gt; [pdf link] it occured to me that the configuration in the previous post could also be used to access a work PC from home.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2006/03/lg_putty02.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/03/sm_putty02.jpg" style="cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you add a 'tunnel' via the dialog above, you can add either a local or remote tunnel.  A local tunnel is like saying "I want to create a 'wormhole' port x on this PC which emerges at port y on at the SSH server".  My configuration above has local ports 3390 and 3391 configured to 'emerge' at the Remote Desktop ports on my two home machines.&lt;/p&gt;

&lt;p&gt;A remote tunnel tells the SSH server to create a 'wormhole' port on the SSH server.  The remote port above points port 3400 on my SSH box to port 80 on the client machine.  So I can open a browser on my SSH machine, and browse localhost:3400 and see the webserver on my work PC.&lt;/p&gt;

&lt;p&gt;This is all explained well in the &lt;a href="http://the.earth.li/~sgtatham/putty/0.58/htmldoc/Chapter4.html#config-ssh-portfwd"&gt;Putty documentation&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114147350044749432?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114147350044749432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114147350044749432' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114147350044749432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114147350044749432'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/03/update-remote-desktop-sshputty.html' title='Update:  Remote Desktop + SSH/Putty'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114143861031443617</id><published>2006-03-04T13:06:00.001+11:00</published><updated>2010-07-17T22:56:38.237+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='networking'/><title type='text'>Remote Desktop + SSH/Putty</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/03/remote-desktop-sshputty/"&gt;http://blog.tinisles.com/2006/03/remote-desktop-sshputty/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            If you ever want to open your PC for remote access - but want something relatively secured.  Here is a good solution using: OpenSSH, Putty, and public/private key authentication.  Putty can access your OpenSSH server via a HTTP proxy on port 443, which is handy if you are behind a firewall (i.e. at work).

Took a couple of articles to get it going:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://weyland.be/wrdprss/index.php/2005/09/28/connections-through-firewall-via-ssh-tunnel/"&gt;Connections through Firewall via SSH tunnel&lt;/a&gt;
&lt;li&gt;&lt;a href="http://bmonday.com/articles/653.aspx"&gt;Configuring OpenSSH (Win32) for Public Key Authentication&lt;/a&gt;
&lt;/ul&gt;

Nothing like this works straight away, so here's a logical order of steps to get things going:
&lt;ul&gt;
&lt;li&gt;Install OpenSSH on the target machine, and install Putty on a non-firewalled machine somewhere.  Go though the steps in the first document, and forget everything about the HTTP proxy stuff.  If you can click 'Open' in Putty and see the 'Login:' prompt you're on the right track.

&lt;p&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2006/03/lg_putty01.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/03/sm_putty01.jpg" style="cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;

Luckily for me a friend opened up VNC for me on his home machine so I could test this step.  If things aren't working here: make sure port 433 is being forwarded on your router (and you ISP doesn't block it!), and you've set up an &lt;a href="http://www.microsoft.com/windowsxp/using/security/internet/sp2_wfexceptions.mspx"&gt;exception in Windows Firewall&lt;/a&gt; to let port 443 in.  Experiment with a different port number - make sure you configure the right port number in sshd_config, your router, and windows firewall.

&lt;li&gt;Now that works try the HTTP proxy bit.
&lt;li&gt;Happy with that?  Now try setting up the public key authentication.  I had some troubles here with OpenSSH being very sensitive to config settings.  After changing a setting the SSH terminal window (above) wouldn't display anything.  Keep a back-up of the config file when it works!
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114143861031443617?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114143861031443617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114143861031443617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114143861031443617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114143861031443617'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/03/remote-desktop-sshputty.html' title='Remote Desktop + SSH/Putty'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114112136015924395</id><published>2006-02-28T20:59:00.000+11:00</published><updated>2010-07-17T22:56:40.677+10:00</updated><title type='text'>Google Kirkland</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/02/google-kirkland/"&gt;http://blog.tinisles.com/2006/02/google-kirkland/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;a href="http://blog.tinisles.com/blogger-images/2006/02/lg_googlekirkland.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2006/02/sm_googlekirkland.jpg" style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;Noticed on a blog somewhere that Google now has a location in Kirland, WA.  Thought I'd have a look whereabouts, as I stayed in Kirkland while working with Microsoft.  Turns out they are just across the road from the apartment building I was staying in (and where my digital camera was stolen, grrr).  Have a look on &lt;a href="http://maps.google.com/?q=720+4th+Avenue,+Kirkland,+WA+(Google+Kirkland)&amp;ll=47.679276,-122.196969&amp;spn=0.002358,0.006781&amp;t=k"&gt;Google maps&lt;/a&gt;.  I was right on the corner of Central Way, and 6th - with my bedroom window getting all the noises from the early trucks going through that intersection.&lt;/p&gt;

&lt;p&gt;Now why would Google set up in Kirkland?  Couldn't be because it's a handy location to tempt engineers away from nearby &lt;a href="http://maps.google.com/maps?f=d&amp;hl=en&amp;saddr=720+4th+Avenue,+Kirkland,+WA+(Google+Kirkland)&amp;daddr=1+Microsoft+Way,+Redmond,+WA&amp;t=h"&gt;Redmond&lt;/a&gt;?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114112136015924395?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114112136015924395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114112136015924395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114112136015924395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114112136015924395'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/02/google-kirkland.html' title='Google Kirkland'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-114022061075944186</id><published>2006-02-18T10:49:00.001+11:00</published><updated>2010-07-17T22:56:43.387+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='links'/><title type='text'>More links</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/02/more-links/"&gt;http://blog.tinisles.com/2006/02/more-links/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;ul&gt;
&lt;li&gt;&lt;a href="http://news.bbc.co.uk/1/hi/world/asia-pacific/4715788.stm"&gt;Monkey magic casts spell in Asia&lt;/a&gt; - funnily enough Monkey is being played by &lt;a href="http://en.wikipedia.org/wiki/Shingo_Katori"&gt;Shingo Katori&lt;/a&gt; who is Shingo Mama in &lt;a href="http://video.google.com/videoplay?docid=-9105575935534995120"&gt;No Oha!&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=1J9ufqCoqyo"&gt;Shining Spoof Trailer&lt;/a&gt; - A spoof trailer for Shining that makes it look like a heartwarming drama rather than a horror movie
&lt;li&gt;&lt;a href="http://www.flickr.com/groups/stickfiguresinperil/pool/"&gt;Stick figures in Peril&lt;/a&gt; - flickr group I got a few laughs out of
&lt;li&gt;&lt;a href="http://www.alistapart.com/articles/vdaymassacre"&gt;A List Apart: Articles: Valentine's Day Massacre&lt;/a&gt; - What do you hate about the web?  Have to agree with: browser display issues, smileycentral adverts, and the "unnecessary urge to criticize, accuse and ridicule"
&lt;li&gt;&lt;a href="http://theillustratednetwork.mvps.org/Ssh/RemoteDesktopSSH.html"&gt;Remote Desktop and SSH for the home user&lt;/a&gt; - setting up Remote Desktop to go via SSH tunnels
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-114022061075944186?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/114022061075944186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=114022061075944186' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114022061075944186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/114022061075944186'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/02/more-links.html' title='More links'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113996711653762345</id><published>2006-02-15T12:31:00.000+11:00</published><updated>2010-07-17T22:56:45.814+10:00</updated><title type='text'>Yahoo! UI Library</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/02/yahoo-ui-library/"&gt;http://blog.tinisles.com/2006/02/yahoo-ui-library/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Yahoo are getting geek cred again.  It wasn't that long ago I thought their web email, and photo hosting were the best.  Google Mail and flickr have topped both of those.&lt;/p&gt;

&lt;p&gt;Yet, the tide is turning.  Just noticed the public APIs and code they are making available on the &lt;a href="http://developer.yahoo.net/"&gt;Yahoo! Developer Network Home&lt;/a&gt;.  Of particular interest to me is the &lt;a href="http://developer.yahoo.net/yui/"&gt;Yahoo! UI Library&lt;/a&gt;; check out the &lt;a href="http://developer.yahoo.net/yui/calendar/examples/default/index.html"&gt;DHTML calendar sample&lt;/a&gt; (see the &lt;a href="http://developer.yahoo.net/yui/calendar/index.html"&gt;calendar reference&lt;/a&gt;).

&lt;p&gt;
Also thought the &lt;a href="http://www.angieandderek.com/videos/"&gt;Random Videos&lt;/a&gt; was a very cool demo of the &lt;a href="http://developer.yahoo.net/maps/index.html"&gt;Maps API&lt;/a&gt;.  Why does &lt;a href="http://flickrservice.liquidmesh.com/GeoViewer.aspx?set=573742"&gt;San Francisco&lt;/a&gt; lend itself so well to these projects? ;)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113996711653762345?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113996711653762345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113996711653762345' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113996711653762345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113996711653762345'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/02/yahoo-ui-library.html' title='Yahoo! UI Library'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113870278390024240</id><published>2006-01-31T21:19:00.000+11:00</published><updated>2010-07-17T22:56:49.317+10:00</updated><title type='text'>Debugging XmlSerializer</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/01/debugging-xmlserializer/"&gt;http://blog.tinisles.com/2006/01/debugging-xmlserializer/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;This is pretty much the reason why I started this blog.  I regularly find an article to help with a particular coding problem I'm having.  The really frustrating thing is having the problem (or a similar one) a second time and not being able to google up the article again!&lt;/p&gt;

&lt;p&gt;Which is what happened last night when I recieved a "Input string was not in a correct format" when deserializing the response from a flickr method call.  Something had changed in the XML I was receiving from flickr, which caused a problem when attempting to deserialize the XML into a class.  Here is a handy article that explains what is exactly going on when you deserialize an object: 
&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnxmlnet/html/trblshtxsd.asp"&gt;Troubleshooting Common Problems with the XmlSerializer&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;The last section 'Debugging Serialization Code' shows how you can grab the dynamically generated serialization classes, and step into them to find where an error is occurring.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113870278390024240?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113870278390024240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113870278390024240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113870278390024240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113870278390024240'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/01/debugging-xmlserializer.html' title='Debugging XmlSerializer'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113809955219572290</id><published>2006-01-24T21:45:00.000+11:00</published><updated>2010-07-17T22:56:53.959+10:00</updated><title type='text'>Google Video Highlights</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/01/google-video-highlights/"&gt;http://blog.tinisles.com/2006/01/google-video-highlights/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;It took someone as smart as Google to realise the current multitude of video clients and codecs isn't good for the web.  The Google video site uses Flash for video playback.  No need to download Quicktime, Real, or the latest Windows Media.  I can actually send someone a link to a streamed video reasonably confident they'll be able to play it!&lt;/p&gt;

&lt;p&gt;Here's some highlights I've discovered from the most popular page:

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://video.google.com/videoplay?docid=-8530918890580805143"&gt;Tom Kills Oprah&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://video.google.com/videoplay?docid=-9105575935534995120"&gt;Shingo Mama No Oha!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://video.google.com/videoplay?docid=-8602472107022912201"&gt;Cup stacking world record&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://video.google.com/videoplay?docid=6605730767077503480"&gt;Smart car&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113809955219572290?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113809955219572290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113809955219572290' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113809955219572290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113809955219572290'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/01/google-video-highlights.html' title='Google Video Highlights'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113807070256785657</id><published>2006-01-24T13:43:00.001+11:00</published><updated>2010-07-17T22:56:59.587+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mssql'/><title type='text'>Quick way to find space used by each table in a database</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/01/quick-way-to-find-space-used-by-each-table-in-a-database/"&gt;http://blog.tinisles.com/2006/01/quick-way-to-find-space-used-by-each-table-in-a-database/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Found this very handy:&lt;/p&gt;

&lt;code&gt;sp_msforeachtable 'sp_spaceused "?"'&lt;/code&gt;
 
&lt;p&gt;Produces a kind of ugly output (returns a table for each table).  The original article includes a query to get all the results into one table: &lt;a href="http://searchvb.techtarget.com/tip/1,289483,sid8_gci823821,00.html"&gt;Quick way to find space used by each table in a database&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113807070256785657?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113807070256785657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113807070256785657' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113807070256785657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113807070256785657'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/01/quick-way-to-find-space-used-by-each.html' title='Quick way to find space used by each table in a database'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113801820337993067</id><published>2006-01-23T23:10:00.001+11:00</published><updated>2010-07-17T22:57:02.023+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='networking'/><title type='text'>Reverse IP Lookup</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/01/reverse-ip-lookup/"&gt;http://blog.tinisles.com/2006/01/reverse-ip-lookup/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;&lt;a href="http://www.whois.sc/"&gt;Whois Source&lt;/a&gt; has a pretty cool feature: &lt;a href="http://www.whois.sc/reverse-ip/"&gt;Reverse IP Lookup&lt;/a&gt;.  Enter an IP or domain and find out how many other sites are sharing the same IP.  Requires 'silver membership' to see all the matching sites, but the free membership will tell you the number of sites that match.  Good way to check if your hosting company is being honest about their &lt;a href="http://www.webhost4life.com/manageddedi.asp"&gt;semi-dedicated hosting&lt;/a&gt;! &lt;/p&gt;

&lt;p&gt;Turns out the cheap (and reasonably good) hosting that I'm using for a project of mine, has managed to squeeze 183 sites onto the one box (for the cheap hosting - NOT the semi-dedicated one)!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113801820337993067?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113801820337993067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113801820337993067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113801820337993067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113801820337993067'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/01/reverse-ip-lookup.html' title='Reverse IP Lookup'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113711906809538440</id><published>2006-01-13T13:04:00.000+11:00</published><updated>2010-07-17T22:57:07.666+10:00</updated><title type='text'>Electronic Paper - Update</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/01/electronic-paper-update/"&gt;http://blog.tinisles.com/2006/01/electronic-paper-update/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            Some more e-ink devices have appeared recently:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://engadget.com/2006/01/06/sony-reader-details-and-pics/"&gt;Sony Reader&lt;/a&gt;, very a Librie-like E-Ink e-book handheld for the North American market. From SMH: &lt;a href="http://www.smh.com.au/articles/2006/01/08/1136655086801.html"&gt;Easy on the eye: new e-book is a page turner&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://engadget.com/2006/01/03/lexar_jumpdrive_mercury/"&gt;Lexar JumpDrive Mercury&lt;/a&gt; - uses an e-ink display for the capacity meter.  Pretty clever, because e-ink only needs power to change the display.  That way it can constantly show you the capicity, without the need for an power within the device.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ambientdevices.com/cat/5dayforecaster.html"&gt;Ambient 5 Day Weather Forecaster&lt;/a&gt; from ambient.&lt;/li&gt;
&lt;/ul&gt;

The last two both use a segmented display (like a calculator or the old &lt;a href="http://en.wikipedia.org/wiki/Game_%26_Watch"&gt;Game &amp; Watch&lt;/a&gt;) which isn't nearly exciting as a high-res display.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113711906809538440?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113711906809538440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113711906809538440' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113711906809538440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113711906809538440'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/01/electronic-paper-update.html' title='Electronic Paper - Update'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113637251830954309</id><published>2006-01-04T21:49:00.001+11:00</published><updated>2010-07-17T22:57:10.157+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='links'/><title type='text'>Some links</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/01/some-links/"&gt;http://blog.tinisles.com/2006/01/some-links/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            Back to work tomorrow, 2 weeks of holidays are over.  Some links I found funny / interesting over the holidays:

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.blogjam.com/north-korea/"&gt;blogjam's North Korea trip&lt;/a&gt; - I think I discovered this from flickr.  After I read it, I had Korean for lunch...&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dotnet.jku.at/courses/"&gt;Courseware for .NET and C#&lt;/a&gt; - Know of anyone about to learn .net?  I was pretty impressed with the online lessons here.  The &lt;a href="http://www.ssw.uni-linz.ac.at/Teaching/Lectures/CSharp/Tutorial/"&gt;C# Tutorial&lt;/a&gt; looks like it'd be good for a developer to come up to speed on the language, and &lt;a href="http://dotnet.jku.at/courses/dotnet/"&gt;Application Development with C# and .NET&lt;/a&gt; covers the major APIs of the framework (plus more).&lt;/li&gt;
&lt;li&gt;Did you get a webcam for Christmas?  Or did you get one for someone else, and open it to 'make sure it works'?  I found the &lt;a href="http://www.gskinner.com/blog/archives/2005/11/flash_8_webcam_1.html"&gt;Webcam Fire&lt;/a&gt; flash demo pretty cool (so is the &lt;a href="http://www.gskinner.com/blog/archives/2005/08/flash_8_webcam.html"&gt;snowstorm&lt;/a&gt;).
&lt;li&gt;&lt;a href="http://www.pointlesswasteoftime.com/film/trilogy.html"&gt;Lord of the Rings vs. The Matrix vs. Star Wars&lt;/a&gt; - really made me laugh.
&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113637251830954309?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113637251830954309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113637251830954309' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113637251830954309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113637251830954309'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/01/some-links.html' title='Some links'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113624089137831446</id><published>2006-01-03T09:28:00.001+11:00</published><updated>2010-07-17T22:57:12.770+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Listamatic: CSS lists</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2006/01/listamatic-css-lists/"&gt;http://blog.tinisles.com/2006/01/listamatic-css-lists/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;In a similar vein to the &lt;a href="http://www.csszengarden.com/"&gt;css Zen Garden&lt;/a&gt; comes  Max Design's &lt;a href="http://css.maxdesign.com.au/listamatic/index.htm"&gt;Listamatic&lt;/a&gt;. A collections of CSS styles that can be applied to simple lists for "radically different list options".  There is also a &lt;a href="http://css.maxdesign.com.au/listamatic/browser-support.htm"&gt;browser support chart&lt;/a&gt; that can save you some hassle of testing in a stack of browsers.&lt;/p&gt;

&lt;p&gt;
I'm currently playing with the &lt;a href="http://www.clagnut.com/writings/csstabs/"&gt;clagnut CSS tabs&lt;/a&gt; for a project of mine.  More on that later.  Possibly much later...
&lt;/p&gt;

&lt;p&gt;Update: I think I'm going to go with &lt;a href="http://concepts.waetech.com/dhtml_tabs/"&gt;Super-Simple DHTML Tabs&lt;/a&gt; now.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113624089137831446?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113624089137831446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113624089137831446' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113624089137831446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113624089137831446'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2006/01/listamatic-css-lists.html' title='Listamatic: CSS lists'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113585287335585523</id><published>2005-12-29T21:14:00.000+11:00</published><updated>2010-07-17T22:57:15.971+10:00</updated><title type='text'>Electronic paper</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/12/electronic-paper/"&gt;http://blog.tinisles.com/2005/12/electronic-paper/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;a href="http://blog.tinisles.com/blogger-images/2005/12/lg_librie01.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2005/12/sm_librie01.jpg" style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;


&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/EPaper"&gt;Electronic paper&lt;/a&gt; (or epaper) is a new display technology that I'm really keen to check out.  LCD works by shining a light through a transparent display. Electronic paper contains configurable pigment that reflects light - just as ink on a piece of paper does.  So epaper is just as readable as normal printed text.  Anyone who has attempted to read a laptop in bright sunlight is probably half as excited as I am about this technology.&lt;/p&gt;

&lt;p&gt;Citizen have a &lt;a href="http://engadget.com/2005/12/15/citizens-flexible-e-ink-wall-clock-nears-release/"&gt;upcoming flexible digital wall clock&lt;/a&gt;. Currently the only commerical implementation of epaper is the &lt;a href="http://en.wikipedia.org/wiki/Sony_Librie_EBR-1000EP"&gt;Sony Librie EBR-1000EP&lt;/a&gt;.  The product itself has some questionable purpose, but the reviewers are all commend the display.  
&lt;/p&gt;

&lt;p&gt;From &lt;a href="http://www.makezine.com/blog/archive/2005/06/sony_librie_hac.html"&gt;MAKE: blog&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;The display looks so "real" it appears as if it's a sticker or printed on the screen.&lt;/blockquote&gt;

&lt;p&gt;From &lt;a href="http://www.dottocomu.com/b/archives/002571.html"&gt;dottocomu&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;The screen is unbelievable. Not quite paper, more like a dull plastic like look. My first impression of the device was that it was not an actual working unit, but a plastic mock up made for stores. With high contrast black text on a reflective background, the screen has a readability rivaling actual paper.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113585287335585523?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113585287335585523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113585287335585523' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113585287335585523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113585287335585523'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/12/electronic-paper.html' title='Electronic paper'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113573931959992962</id><published>2005-12-28T14:08:00.000+11:00</published><updated>2010-07-17T22:59:55.563+10:00</updated><title type='text'>Virgin Atlantic Travel Podcast</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/12/virgin-atlantic-travel-podcast/"&gt;http://blog.tinisles.com/2005/12/virgin-atlantic-travel-podcast/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            Anything to do with technology and travel always piques my interest.  Here's an extra podcast I can listen to/from work: &lt;a href="http://virginatlantic.loudish.com/destinations.html"&gt;Virgin Atlantic - Podcast Destinations&lt;/a&gt; [&lt;a href="http://virginatlantic.loudish.com/fullfeed.xml"&gt;RSS&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113573931959992962?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113573931959992962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113573931959992962' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113573931959992962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113573931959992962'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/12/virgin-atlantic-travel-podcast.html' title='Virgin Atlantic Travel Podcast'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113407844200421192</id><published>2005-12-09T08:45:00.001+11:00</published><updated>2010-07-17T23:00:04.303+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='web dev'/><title type='text'>LogParser</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/12/logparser/"&gt;http://blog.tinisles.com/2005/12/logparser/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;This handy utility lets you query logs just like SQL:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.logparser.com/"&gt;LogParser&lt;/a&gt; - &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07&amp;displaylang=en"&gt;Download LogParser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Running this from the command line tells me which pages are getting 500 errors:&lt;/p&gt;

&lt;code&gt;LogParser.exe "SELECT cs-uri-stem, count(*) FROM ex*.log where sc-status=500 group by cs-uri-stem"&lt;/code&gt;

&lt;p&gt;Where ‘ex*.log’ are all my IIS log files…&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.securityfocus.com/infocus/1712"&gt;Forensic Log Parsing with Microsoft's LogParser&lt;/a&gt; - covers some useful samples for identifying suspicious activity in your IIS logs.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113407844200421192?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113407844200421192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113407844200421192' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113407844200421192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113407844200421192'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/12/logparser.html' title='LogParser'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113236563089979390</id><published>2005-11-19T13:00:00.000+11:00</published><updated>2010-07-17T23:00:07.510+10:00</updated><title type='text'>Space Needle</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/11/space-needle/"&gt;http://blog.tinisles.com/2005/11/space-needle/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;style type="text/css"&gt;.flickr-photo { border: solid 1px #000000; }.flickr-frame {	float: right; text-align: center; margin-left: 15px; margin-bottom: 15px; }.flickr-caption { font-size: 0.8em; margin-top: 0px; }&lt;/style&gt;&lt;div class="flickr-frame"&gt;	&lt;a href="http://www.flickr.com/photos/russau/64597897/" title="photo sharing"&gt;&lt;img src="http://static.flickr.com/30/64597897_25d1834ff8_t.jpg" class="flickr-photo" alt="Space Needle" /&gt;&lt;/a&gt;&lt;br /&gt;	&lt;span class="flickr-caption"&gt;		&lt;a href="http://www.flickr.com/photos/russau/64597897/"&gt;Space Needle&lt;/a&gt;,&lt;br /&gt; originally uploaded by &lt;a href="http://www.flickr.com/people/russau/"&gt;russ.au&lt;/a&gt;.	&lt;/span&gt;&lt;/div&gt;Experimenting with the blogs feature of flickr.  Things are really coming together with "Web 2.0" technologies.&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113236563089979390?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113236563089979390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113236563089979390' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113236563089979390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113236563089979390'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/11/space-needle.html' title='Space Needle'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113229189448257665</id><published>2005-11-18T16:30:00.001+11:00</published><updated>2010-07-17T23:00:10.048+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mssql'/><title type='text'>Viewing the Locks in MS-SQL</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/11/viewing-the-locks-in-ms-sql/"&gt;http://blog.tinisles.com/2005/11/viewing-the-locks-in-ms-sql/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: sql"&gt;
select so.name, sli.*, sp.* 
from 
    sysobjects as so 
    join master..syslockinfo as sli on sli.rsc_objid = so.id
    join master..sysprocesses as sp on sp.spid = sli.req_spid
where xtype = 'U'
&lt;/pre&gt;

System tables reference:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/en-us/tsqlref/ts_sys-o_4zll.asp"&gt;sysobjects&lt;/a&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/en-us/tsqlref/ts_sys-l_3u2a.asp"&gt;syslockinfo&lt;/a&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/en-us/tsqlref/ts_sys-p_3kmr.asp"&gt;sysprocesses&lt;/a&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113229189448257665?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113229189448257665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113229189448257665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113229189448257665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113229189448257665'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/11/viewing-locks-in-ms-sql.html' title='Viewing the Locks in MS-SQL'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113214201557719239</id><published>2005-11-16T22:53:00.000+11:00</published><updated>2010-07-17T23:00:12.337+10:00</updated><title type='text'>We're off to Germany</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/11/were-off-to-germany/"&gt;http://blog.tinisles.com/2005/11/were-off-to-germany/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            Australia in Germany 2006!  &lt;strong&gt;Awesome!&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.smh.com.au/articles/2005/11/16/1132016861225.html"&gt;We're off to Germany!&lt;/a&gt;
&lt;li&gt;&lt;a href="http://news.bbc.co.uk/sport2/hi/football/internationals/4435400.stm"&gt;Australia 1-1 Uruguay (4-2 pens)&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.abc.net.au/news/newsitems/200511/s1508492.htm"&gt;Socceroos qualify for World Cup&lt;/a&gt;
&lt;li&gt;&lt;a href="http://wwiii.sbs.com.au/home/index.php3?id=65445"&gt;AUSTRALIA IS THROUGH!&lt;/a&gt;
&lt;li&gt;&lt;a href="http://fifaworldcup.yahoo.com/06/en/051116/1/59cm.html"&gt;The wizards of Oz&lt;/a&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113214201557719239?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113214201557719239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113214201557719239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113214201557719239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113214201557719239'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/11/were-off-to-germany.html' title='We&amp;#39;re off to Germany'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113117601618763331</id><published>2005-11-05T18:21:00.001+11:00</published><updated>2010-07-17T23:00:16.534+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='viewstate'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Tricky Dynamic Controls in ASP.NET</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/11/tricky-dynamic-controls-in-asp-net/"&gt;http://blog.tinisles.com/2005/11/tricky-dynamic-controls-in-asp-net/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;A few months ago I ran into a problem at work that forced me to really read up on dynamic controls and VIEWSTATE.  Creating Dynamic controls requires a good understanding of the sequence of events when a page is generated in ASP.NET.  If you don't understand what is happening things can get real messy, real fast!&lt;/p&gt;

&lt;p&gt;I've created an ultra simplified version of the UI I was attempting to create.  Pretty simple, I've got a DropDownList inside a table, that is populated with a DataBind when the page is first loaded.  When the user selects and option from the DropDownList, and clicks a button, insert a column into the table.  The dropdown always remains in the last column.  I followed the guidelines from the codeproject article: &lt;a href="http://www.codeproject.com/aspnet/dynamiccontrols.asp"&gt;Dynamically Created Controls in ASP.NET&lt;/a&gt;.  Some important lessons to be learned from the article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dynamically created controls don't survive a postback
&lt;li&gt;so we have to 'remember' the controls, and recreate them after a postback
&lt;/ul&gt;

&lt;p&gt;The first time I clicked the button everything worked as expected.  Second attempt: not so happy!  My DropDownList has lost its contents!  View an example of broken dynamic contols:  &lt;a href="http://blog.time2call.net/DynamicTable1.aspx"&gt;DynamicTable1.aspx&lt;/a&gt; (&lt;a href="http://blog.time2call.net/DynamicTable1.aspx.html"&gt;source&lt;/a&gt;).  My first thought was to remove the test for !IsPostback in the Page_Load, so the DropDownList is populated everytime.  This causes the DropDownList to 'forget' its selected position with each postback, and SelectedIndexChanged doesn't fire anymore. Presumably because I'm resetting it in Page_Load, ASP.NET doesn't consider it &lt;span style="font-style:italic;"&gt;changed&lt;/span&gt;?  Things are starting to get ugly.&lt;/p&gt;

&lt;p&gt;The first clue as to what was going wrong came when I moved the DropDownList out of the table.  Everything works!  View an example of the working dynamic contols: &lt;a href="http://blog.time2call.net/DynamicTable2.aspx"&gt;DynamicTable2.aspx&lt;/a&gt; (&lt;a href="http://blog.time2call.net/DynamicTable2.aspx.html"&gt;source&lt;/a&gt;).

&lt;p&gt;Some more research brings me to a really good article on the page events: &lt;a href="http://aspalliance.com/articleViewer.aspx?aId=134&amp;pId="&gt;Page Events: Order and PostBack&lt;/a&gt; by Paul Wilson.  Important to note here is the order in which ASP.NET 'remembers' the contents on the DropDownList, and repopulates it.&lt;/p&gt;

&lt;p&gt;Here is the order in which things are happening.  First time we load the page:
&lt;ol&gt;
&lt;li&gt;OnLoad: DropDownList is data-bound.
&lt;li&gt;SaveViewState: ASP.NET parses through the control tree, and saves the contents of each control.  This is where the contents of the DropDownList are 'remembered'.
&lt;/ol&gt;

An option is selected from the DropDownList, and the button is clicked:
&lt;ol&gt;
&lt;li&gt;LoadViewState: Just as Paul Wilson says: "After ViewState is retrieved, the next method, LoadViewState, restores it to the page, and then recursively to each control and their children".  This is where the DropDownList is being repopulated.
&lt;li&gt;OnLoad: Page_Load calls RecreatePersistedControls, but at this stage there is nothing to recreate.
&lt;li&gt;RaiseChangedEvents: This calls DropDownList1_SelectedIndexChanged, and the dynamically created table cell is added.
&lt;li&gt;SaveViewState: This time around the contents of the DropDownList are 'remembered'.  But the DropDownList is now in a different place in the control tree this time, because there is now a new TableCell.
&lt;/ol&gt;

At this stage everything has populated fine.  For the second time an option is selected from the DropDownList, and the button is clicked:

&lt;ol&gt;
&lt;li&gt;LoadViewState: ASP.NET attempts to populate the page controls with the ViewState that was saved last time around.  The dynamically created TableCell hasn't been created yet - so the control trees don't line up.  The DropDownList doesn't get populated!
&lt;li&gt;OnLoad: Page_Load calls RecreatePersistedControls, and a TableCell is created.  Our TableCell has arrived a little late!
&lt;/ol&gt;

&lt;p&gt;The mismatch of control trees can be demonstrated by switching &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpcontracefunctionality.asp?frame=true"&gt;ASP.NET Trace&lt;/a&gt; on.&lt;/p&gt;

&lt;p&gt;The solution was to move the RecreatePersistedControls to a place earlier in the process.  As Paul Wilson says:  "The best use of this method (LoadViewState) is to restore any dynamic controls you created in events, based on values you must manually save in ViewState, which is now available to use.".  Perfect - moved RecreatePersistedControls into an overriden LoadViewState like this:

&lt;pre class="brush: csharp"&gt;
protected override void LoadViewState(object savedState)
{
    base.LoadViewState (savedState);
    _persisted = (ArrayList)ViewState[&amp;quot;persisted&amp;quot;];
    RecreatePersistedControls();
}
&lt;/pre&gt;

&lt;p&gt;View the completed demo: &lt;a href="http://blog.time2call.net/DynamicTable3.aspx"&gt;DynamicTable3.aspx&lt;/a&gt; (&lt;a href="http://blog.time2call.net/DynamicTable3.aspx.html"&gt;source&lt;/a&gt;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113117601618763331?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113117601618763331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113117601618763331' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113117601618763331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113117601618763331'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/11/tricky-dynamic-controls-in-aspnet.html' title='Tricky Dynamic Controls in ASP.NET'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113093047955739353</id><published>2005-11-02T22:07:00.001+11:00</published><updated>2010-07-17T23:00:19.601+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web dev'/><category scheme='http://www.blogger.com/atom/ns#' term='links'/><title type='text'>Handy Web Reference Links</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/11/handy-web-reference-links/"&gt;http://blog.tinisles.com/2005/11/handy-web-reference-links/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            Some links that I like to have bookmarked everywhere I'm working:

&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;MSDN Library
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/dhtml_reference_entry.asp"&gt;HTML and DHTML Reference&lt;/a&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/29f83a2c-48c5-49e2-9ae0-7371d2cda2ff.asp"&gt;JScript Language Reference&lt;/a&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/en-us/cpgenref/html/gngrfASPNETConfigurationSectionSchema.asp"&gt;ASP.NET Settings Schema&lt;/a&gt;  - web.config settings
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/en-us/cpgenref/html/gnconASPNETSyntax.asp"&gt;ASP.NET Syntax&lt;/a&gt; - handy for the numerous DataGrid settings
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/2380d458-3366-402b-996c-9363906a7353.asp"&gt;Regular Expression Syntax&lt;/a&gt; (JScript), &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconCOMRegularExpressions.asp"&gt;.NET Framework Regular Expressions&lt;/a&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/en-us/cpguide/html/cpconformattingtypes.asp"&gt;Formatting Types&lt;/a&gt; - for String.Format and ToString methods (&lt;a href="http://msdn2.microsoft.com/en-us/library/fbxft59x.aspx"&gt;MSDN2 link&lt;/a&gt;)
&lt;/ul&gt;
&lt;li&gt;Firefox
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference"&gt;Core JavaScript 1.5 Reference&lt;/a&gt;
&lt;li&gt;&lt;a href="http://developer.mozilla.org/en/docs/Gecko_DOM_Reference"&gt;Gecko DOM Reference&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.xulplanet.com/references/objref/XMLHttpRequest.html"&gt;XMLHttpRequest&lt;/a&gt;
&lt;li&gt;&lt;a href="http://xulplanet.com/references/objref/XMLDocument.html"&gt;XMLDocument&lt;/a&gt;
&lt;/ul&gt;
&lt;li&gt;W3C
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.w3.org/TR/html401/"&gt;HTML 4.01 Specification&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.w3.org/TR/xhtml1/"&gt;XHTML 1.0&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.w3.org/TR/CSS21/"&gt;CSS 2.1 Specification&lt;/a&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113093047955739353?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113093047955739353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113093047955739353' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113093047955739353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113093047955739353'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/11/handy-web-reference-links.html' title='Handy Web Reference Links'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-113022716196367841</id><published>2005-10-25T17:59:00.001+10:00</published><updated>2010-07-17T23:02:08.428+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>css Zen Garden: The Beauty in CSS Design</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/10/css-zen-garden-the-beauty-in-css-design/"&gt;http://blog.tinisles.com/2005/10/css-zen-garden-the-beauty-in-css-design/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;CSS is something I've been meaning to learn properly for a while now.  Every time I make a quick attempt to knock up something properly ulitising CSS for layout I get frustrated by browser incompatibilities pretty quick!&lt;p&gt;

&lt;p&gt;&lt;a href="http://www.csszengarden.com/"&gt;css Zen Garden: The Beauty in CSS Design&lt;/a&gt; is pretty phenomenal.  The exact same HTML with different styles (or no style) can be rendered completely differently.  Like these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.csszengarden.com/?cssfile=/185/185.css&amp;page=0"&gt;Manhattan Edition&lt;/a&gt;
&lt;li&gt;&lt;a href="http://www.csszengarden.com/?cssfile=/184/184.css&amp;page=0"&gt;Peace Of Mind&lt;/a&gt;
&lt;/ul&gt;

&lt;p&gt;Idea for a project: take the content from &lt;a href="http://backstage.bbc.co.uk/"&gt;backstage.bbc.co.uk&lt;/a&gt;, and create a stylesheet to give the &lt;a href="http://news.bbc.co.uk/"&gt;BBC News&lt;/a&gt; website a &lt;a href="http://www.useit.com/alertbox/20031110.html"&gt;liquid layout&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-113022716196367841?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/113022716196367841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=113022716196367841' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113022716196367841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/113022716196367841'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/10/css-zen-garden-beauty-in-css-design.html' title='css Zen Garden: The Beauty in CSS Design'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-112971999765349169</id><published>2005-10-19T20:52:00.008+10:00</published><updated>2010-07-17T23:02:11.378+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Onbeforeunload throwing errors in IE - coding around it in ASP.NET</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/10/onbeforeunload-throwing-errors-in-ie-coding-around-it-in-asp-net/"&gt;http://blog.tinisles.com/2005/10/onbeforeunload-throwing-errors-in-ie-coding-around-it-in-asp-net/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Some of the most popular questions on any web dev forum are: 
&lt;ol&gt;
&lt;li&gt;How do I trap the back button / stop people from clicking back?&lt;/li&gt;
&lt;li&gt;How do I stop someone from viewing source?&lt;/li&gt;
&lt;li&gt;How do I stop someone from closing a window/browser?&lt;/li&gt;
&lt;/ol&gt;
Short answer for all is: you can't!  Especially if you are supporting multiple browsers &amp; multiple versions.  There are tricks for the first two questions - and I notice Gmail is pretty clever to redraw the UI without a server trip when you click back.  I'm pretty confident in saying - you can't stop someone determined from viewing the source.  Problem being that your webclient will need the source to display it!
&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style:italic;"&gt;How do&lt;/span&gt; you stop someone from closing a browser?  Can you imagine how nasty pop-up ads would be if you couldn't close them?  There is an event in IE &lt;a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/events/onbeforeunload.asp"&gt;onbeforeunload&lt;/a&gt;.  This will pop-up a dialog asking 'Are you sure you want to navigate away from this page?' plus your own text - if you attempt to navigate away from a page.&lt;/p&gt;  

&lt;a href="http://blog.tinisles.com/blogger-images/2005/10/lg_onunload.gif"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2005/10/sm_onunload.gif" style="cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;

&lt;p&gt;I usually try to talk people out of this - it is kind of bad usability.  I must be losing my powers or getting complacent because I wound up using this on a project recently.  This is how I discovered a problem where a user clicking 'Cancel' on the dialog will throw an error in IE.  It only seems to happen if the navigation is initiated by client-side script.  View a demo of it &lt;a href="http://blog.time2call.net/bodyunload.html"&gt;here&lt;/a&gt;.
 
&lt;p&gt;A google for '&lt;a href="http://www.google.com/search?q=onbeforeunload+%22unspecified+error%22"&gt;onbeforeunload "unspecified error"&lt;/a&gt;' reveals a few articles about it.  All centre around catching the 'unspecified error' in your javascript.  Unfortunately my error was being thrown from within an AutoPostBack from a DropDownList - so I don't have access to the script to catch the error.  There's a demo &lt;a href="http://blog.time2call.net/OnBeforeUnload.aspx"&gt;here&lt;/a&gt;, view the source &lt;a href="http://blog.time2call.net/OnBeforeUnload.aspx.html"&gt;here&lt;/a&gt;.&lt;/p&gt; 

&lt;p&gt;More scavenging around on Google and I find a way to &lt;a href="http://weblogs.asp.net/vga/archive/2004/03/01/NoMoreHijackingOfDoPostBackInWhidbey.aspx"&gt;hijack the postback&lt;/a&gt;.  This is done by:
&lt;ul&gt;
&lt;li&gt; stashing ASP.NET's postback function into a variable
&lt;li&gt; replacing the postback function with your own
&lt;li&gt; your function does what ever you have to do
&lt;li&gt; then calls the 'stashed' postback function 
&lt;/ul&gt;
&lt;/p&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="brush: javascript"&gt;
var __oldDoPostBack = __doPostBack;
__doPostBack = CatchExplorerError;

function CatchExplorerError (eventTarget, eventArgument)
{
    try
    {
        return __oldDoPostBack (eventTarget, eventArgument);
    } catch (ex)
    {
        // don't want to mask a genuine error
        // lets just restrict this to our 'Unspecified' one
        if (ex.message.indexOf('Unspecified') == -1)
        {
            throw ex;
        }
        else
        {
            alert('caught the error!');
        }
    }
}

&lt;/pre&gt;

&lt;p&gt;This will work nicely.  Its important to note that firefox will enter into the catch - because it doesn't like the onbeforeunload event.  Also worth noting that the exception object also has a 'description' property in IE.  I was originally testing this for the 'unspecifed' string - which throws &lt;span style="font-style:italic;"&gt;another&lt;/span&gt; error in firefox. Both browsers seem happy if I use the 'message' property.  The reference for the IE JScript Error object is &lt;a href="http://msdn.microsoft.com/library/en-us/script56/html/js56jsobjerror.asp"&gt;here&lt;/a&gt;. The &lt;a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference"&gt;firefox reference&lt;/a&gt; doesn't appear to be complete?&lt;/p&gt;

&lt;p&gt;This still leaves one more problem: the select box is still has the new item selected.  There's not really any way to know that the user has clicked cancel on the 'Are you sure?' dialog.  I &lt;span style="font-style:italic;"&gt;could&lt;/span&gt; put something inside the catch in the CatchExplorerError.  This would be a very very dodgy solution - as I'm relying on an error to occur to produce the UI that I want.  What will happen when/if this bug gets fixed!  A less dodgy solution (although I'm not entirely happy with it) would be to return the select box to its original selection in the onbeforeunload.  This takes place before the dialog even appears.  Yet at this point the browser has 'decided on' the form it will be sending to the server.  So setting the selection here isn't submitted up to the server.&lt;/p&gt;

&lt;p&gt;The script 'remembers' the original selection of the select box by storing it in an expando property.&lt;/p&gt;

&lt;pre class="brush: html"&gt;
&amp;lt;select id=&amp;quot;DropDownList1&amp;quot; onclick=&amp;quot;this.oldIndex = this.selectedIndex&amp;quot;&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Then I set the select box back to its stored value when onbeforeunload fires.&lt;p&gt;

&lt;pre class="brush: javascript"&gt;
function body_onbeforeunload()
{

    var DropDownList1 = document.getElementById('DropDownList1');
    if (DropDownList1.oldIndex != undefined)
    {
        // return the selectbox to its oldIndex
        DropDownList1.selectedIndex = DropDownList1.oldIndex;
    }

    event.returnValue = &amp;quot;You sure?&amp;quot;;
}
&lt;/pre&gt;

&lt;p&gt;View a demo of the completed solution &lt;a href="http://blog.time2call.net/OnBeforeUnload2.aspx"&gt;here&lt;/a&gt;, and the source &lt;a href="http://blog.time2call.net/OnBeforeUnload2.aspx.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-112971999765349169?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/112971999765349169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=112971999765349169' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/112971999765349169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/112971999765349169'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/10/onbeforeunload-throwing-errors-in-ie.html' title='Onbeforeunload throwing errors in IE - coding around it in ASP.NET'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-112969140338400532</id><published>2005-10-19T13:10:00.001+10:00</published><updated>2010-07-17T23:02:15.000+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>Ajax Safari Update</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/10/ajax-safari-update/"&gt;http://blog.tinisles.com/2005/10/ajax-safari-update/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            The problem I 'discovered' in Safari is a recognised (and fixed) bug in Konqueror:

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://bugs.kde.org/show_bug.cgi?id=108400"&gt;Bug 108400 - XMLHttpRequest doesn't handle document charset&lt;/a&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-112969140338400532?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/112969140338400532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=112969140338400532' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/112969140338400532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/112969140338400532'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/10/ajax-safari-update.html' title='Ajax Safari Update'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17882482.post-112936562204991036</id><published>2005-10-15T18:34:00.001+10:00</published><updated>2010-07-17T23:02:19.396+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>An AJAX Safari...</title><content type='html'>
            
            &lt;table style="" class="metadata plainlinks ambox ambox-style"&gt;
                    &lt;tbody&gt;
                        &lt;tr&gt;
                            &lt;td class="mbox-image"&gt;
                                &lt;div style="width: 52px;"&gt;
                                    &lt;img width="40" height="40" src="http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s1600/Ambox_content.png"/&gt;&lt;/div&gt;
                            &lt;/td&gt;
                            &lt;td style=""&gt;
                                The article you are reading has moved! It is now available at: &lt;a href="http://blog.tinisles.com/2005/10/an-ajax-safari/"&gt;http://blog.tinisles.com/2005/10/an-ajax-safari/&lt;/a&gt;
                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;
                   &lt;/table&gt;
            
            &lt;p&gt;Playing around with an &lt;a href="http://en.wikipedia.org/wiki/AJAX"&gt;AJAX&lt;/a&gt; project at home. More of a learning project than anything. And I've run into a particularly troublesome problem with Apple Safari browser and the &lt;a href="http://developer.apple.com/internet/webcontent/xmlhttpreq.html"&gt;XMLHttpRequest &lt;/a&gt;object. Ah, the joys of cross-browser development. I cringe whenever I hear that a new browser has come out.&lt;/p&gt;

&lt;p&gt;The problem comes about when I'm making an AJAX "method call" and the response contains extended characters. Mac Safari doesn't want to play nice with these characters (yet Win/Mac Opera &amp; Win Firefox are fine). I almost feel sorry for those who have extended characters in their name! Playing with this &lt;a href="http://ajax.schwarz-interactive.de/csharpsample/default.aspx"&gt;AJAX wrapper&lt;/a&gt; from Michael Swartz. A look under the hood reveals how things a working. And I isolate it down to the request from the XMLHttpRequest object. Knocked up a quick spike (&lt;a href="http://www.extremeprogramming.org/rules/spike.html"&gt;?&lt;/a&gt;) to see what is actually coming back from the server.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2005/10/sm_safari01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;First off I tried loading two things from the XMLHttpRequest object:
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;a file on the server containing the extended characters.
&lt;/li&gt;&lt;li&gt;simulating the request the ajax wrapper is making.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Hmmm... Loading the file works fine. The AJAX request comes back with some ugly characters in place of the extended ones. For a further look under the hood I've downloaded the &lt;a href="http://www.fiddlertool.com/fiddler/"&gt;Fiddler&lt;/a&gt; proxy to see what is going over the wire.  Some observations:&lt;/p&gt;

&lt;p&gt;
&lt;table width="100%"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" colspan="2"&gt;&lt;b&gt;Reponse Headers&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=50%&gt;&lt;b&gt;From File&lt;/b&gt;&lt;/td&gt;&lt;td width=50%&gt;&lt;b&gt;From Ajax&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;&lt;span style="font-size:78%;"&gt;
      &lt;/span&gt;&lt;span style="font-size:78%;"&gt;
HTTP/1.1 200 OK&lt;br&gt;
Connection: close&lt;br&gt;
Proxy-Connection: close&lt;br&gt;
Content-Length: 649&lt;br&gt;
Date: Sat, 15 Oct 2005 09:09:23 GMT&lt;br&gt;
&lt;b&gt;Content-Type: text/xml&lt;/b&gt;&lt;br&gt;
ETag: "b04067251cfc51:ae2"&lt;br&gt;
Server: Microsoft-IIS/5.0&lt;br&gt;
X-Powered-By: ASP.NET&lt;br&gt;
Accept-Ranges: bytes&lt;br&gt;
Last-Modified: Wed, 12 Oct 2005 07:47:07 GMT&lt;/span&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;span style="font-size:78%;"&gt;
HTTP/1.1 200 OK&lt;br&gt;
Connection: close&lt;br&gt;
Proxy-Connection: close&lt;br&gt;
Content-Length: 680&lt;br&gt;
Expires: Sat, 15 Oct 2005 09:09:24 GMT&lt;br&gt;
Date: Sat, 15 Oct 2005 09:09:24 GMT&lt;br&gt;
&lt;b&gt;Content-Type: text/html; charset=utf-8&lt;/b&gt;&lt;br&gt;
Server: Microsoft-IIS/5.0&lt;br&gt;
X-Powered-By: ASP.NET&lt;br&gt;
X-AspNet-Version: 1.1.4322&lt;br&gt;
Cache-Control: private&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;table width="100%"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" colspan="2"&gt;&lt;b&gt;Response Bytes&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;From File&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style="font-weight:bold;"&gt;EF BB BF&lt;/span&gt; 5B 27 41 6D 65 72 69 63 61 2F 41 &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;From Ajax&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;5B 27 41 6D 65 72 69 63 61 2F 41&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;

&lt;p&gt;Different content types, and the preceding bytes EF BB BF on the file.  A &lt;a href="http://www.google.com.au/search?q=EF+BB+BF"&gt;quick google&lt;/a&gt; discovers the bytes are a &lt;a href="http://en.wikipedia.org/wiki/Byte_Order_Mark"&gt;byte order mark&lt;/a&gt;.  Presumably one of these is the reason why Safari doesn't want to treat the AJAX response as UTF-8??  Time to read up on unicode, this is a learning exercise after all: &lt;a href="http://www.joelonsoftware.com/articles/Unicode.html"&gt;The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time to have a look at an AJAX application that isn't having problems with extended characters on Safari: Gmail seems to work fine.  Time to fire up Fiddler again and see how the experts are doing it!  I've sent my gmail account an email containing extended characters, interested to see how the content type and BOM will look.  The content type response header from gmail looks like this:&lt;/p&gt;

&lt;span style="font-size:78%;"&gt;&lt;b&gt;Content-Type: text/html; charset=utf-8&lt;/b&gt;&lt;/span&gt;

&lt;p&gt;The byte response starts off like this:&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;61&lt;/td&gt;&lt;td&gt;34 &lt;/td&gt;&lt;td&gt;34 &lt;/td&gt;&lt;td&gt;0D &lt;/td&gt;&lt;td&gt;0A &lt;/td&gt;&lt;td&gt;3C &lt;/td&gt;&lt;td&gt;68 &lt;/td&gt;&lt;td&gt;74 &lt;/td&gt;&lt;td&gt;6D &lt;/td&gt;&lt;td&gt;6C &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;&lt;&lt;/td&gt;&lt;td&gt;h&lt;/td&gt;&lt;td&gt;t&lt;/td&gt;
&lt;td&gt;m&lt;/td&gt;&lt;td&gt;l&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;And the HTML contains this meta tag:&lt;/p&gt;
&lt;span style="font-size:78%;"&gt;&lt;b&gt;
&lt;meta content="text/html; charset=UTF-8" http-equiv="content-type"&gt;
&lt;/b&gt;&lt;/span&gt;

&lt;p&gt;61 34 34 isn't a byte order mark, maybe its just part of Google's own 'wire format'.  This data is being read in via Javascript, maybe they are just stashing something handy here?  The meta tag is worth experimenting with.  So I create two HTML files one with the meta tag, and without.  And load both via the XMLHttpRequest object.  Interesting, the one containing the meta tag loads okay!  Here's a stab in the dark theory:  Maybe Safari doesn't pass the content-type from the response headers onto the XMLHttpRequest object?  But it does interpret the meta tag?  It previously loaded the file okay - but this contained a byte order mark which would've flagged it at UTF-8 regardless of the content type.&lt;/p&gt;

&lt;p&gt;Now to experiment with this in my AJAX world.  This time I try loading an ASPX page from the XMLHttpRequest object.  A plain vanilla ASPX page with extended characters doesn't display the characters correctly.  Now to try it with the meta tag.  Visual Studio even provides an easy way of adding the tag: edit the ASPX page in design mode -&gt; Properties -&gt; Charset -&gt; Unicode (UTF-8).  And how does this look in Safari: Even uglier!&lt;/p&gt;

&lt;p&gt;A closer look at the way &lt;span style="font-style:italic;"&gt;Belém, Pará&lt;/span&gt; is being encoded:&lt;/p&gt;


&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style="font-weight:bold;"&gt;From File:&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;42 65 6C C3 A9 6D 2C 20 50 61 72 C3 A1 &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style="font-weight:bold;"&gt;From AJAX:&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;42 65 6C C3 A9 6D 2C 20 50 61 72 C3 A1 &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style="font-weight:bold;"&gt;From ASPX:&lt;br&gt;(without META)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;42 65 6C C3 A9 6D 2C 20 50 61 72 C3 A1 &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style="font-weight:bold;"&gt;From ASPX:&lt;br&gt;(with META)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;42 65 6C C3 83 C2 A9 6D 2C 20 50 61 72 C3 83 C2 A1&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Huh??  The first two look pretty consistent with my (new found) understanding of UTF-8.  Then adding the meta tag to the ASPX page is causing ASP.NET to change the response?? Is it getting encoded twice?  Time to hit Google and find an explanation for this one!&lt;/p&gt;

&lt;p&gt;The ASP.NET Resources site has an interesting article: &lt;a href="http://www.aspnetresources.com/blog/unicode_in_vsnet.aspx"&gt;Unicode in Visual Studio.NET 2003&lt;/a&gt; - yet this mentions:&lt;/p&gt;

&lt;blockquote&gt;Some people—including myself—use the http-equiv="content-type" meta tag. In the course of this research I learned that this header has no bearing on anything because ASP.NET will always set a response encoding—yours or a default one.
&lt;/blockquote&gt;

&lt;p&gt;Can't find anything about the meta tag on the web.  Played around a bit, and had a look at two ASPX files with and without the meta tag.  When viewed in a hex editor - it shows that Visual Studio is actually encoding the files differently when the meta tag is present!  This only effects the contents of the ASPX page - this doesn't effect a label on the ASPX page, with its Text property set from the code-behind.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2005/10/lg_nometa.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2005/10/sm_nometa.jpg" style="cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;br&gt;&lt;span style="font-size:78%;"&gt;No meta tag&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.tinisles.com/blogger-images/2005/10/lg_withmeta.jpg"&gt;&lt;img src="http://blog.tinisles.com/blogger-images/2005/10/sm_withmeta.jpg" style="cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;br&gt;&lt;span style="font-size:78%;"&gt;With the meta tag&lt;/span&gt;
&lt;/p&gt;

&lt;h2&gt;Discoveries&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;The XMLHttpRequest object under Safari seems to require the meta tag present to correctly interpret a UTF-8 encoded response.&lt;/li&gt;
&lt;li&gt;Visual Studio changes the encoding used to save the ASPX file when the this meta tag is present.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;"When all is said and done - much more is said than done".  Some interesting discoveries there.  But this doesn't actually solve my initial problem.  The response from the AJAX method only contains the result of the method.  I could change it to wrap the reponse with html, head, meta and body tags - which seems to be the way Gmail is doing it.  Experimented with this and it does actually work.  But I'd have to strip out all the wrapper client-side.  More client side code means more cross-browser worries.  Or I could change the AJAX wrapper to make its response look more like downloading a file - the content type header, and the byte order mark at the start.  This should 'play nice' in other browsers.  Ideally I'd want something that integrates nicely back into Michael Swartz's AJAX project - shielding future developers from the palava I've just gone though.  Lots of work for a browser that makes up for &lt;a href="http://www.upsdell.com/BrowserNews/stat.htm"&gt;0.85% - 5.1% of the net&lt;/a&gt; (when you include all KHMTL based browsers)!  As I said - all a learning exercise!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17882482-112936562204991036?l=tinisles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinisles.blogspot.com/feeds/112936562204991036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17882482&amp;postID=112936562204991036' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/112936562204991036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17882482/posts/default/112936562204991036'/><link rel='alternate' type='text/html' href='http://tinisles.blogspot.com/2005/10/ajax-safari.html' title='An AJAX Safari...'/><author><name>Russ</name><uri>http://www.blogger.com/profile/08157016337682021791</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://photos1.blogger.com/blogger/2845/1735/1600/blogpic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p59uR_Ei6jg/S_Udj8WxmaI/AAAAAAAAApU/gyRk7-IWS5w/s72-c/Ambox_content.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
