<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Salient Solutions</title>
        <link>http://skysanders.net/subtext/Default.aspx</link>
        <description>wrasslin ones and nones for fun and profit - Sky Sanders' Blog</description>
        <language>en-US</language>
        <copyright>Sky Sanders</copyright>
        <generator>Subtext Version 2.1.1.1</generator>
        <image>
            <title>Salient Solutions</title>
            <url>http://skysanders.net/subtext/images/RSS2Image.gif</url>
            <link>http://skysanders.net/subtext/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <item>
            <title>JavaScript console and Firebug mocks</title>
            <link>http://skysanders.net/subtext/archive/2010/07/10/javascript-console-and-firebug-mocks.aspx</link>
            <description>&lt;p&gt;For when you don't want to gut your debugging code for IE.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mock Console&lt;br /&gt;
&lt;/strong&gt;Just enough to swallow 'console.log()' &lt;/p&gt;
&lt;pre class="brush:js;"&gt;        if ("undefined" === typeof window.console)
        {
            window.console = {
                "log": function() { }
            };
        };

&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Mock Firebug&lt;/strong&gt;&lt;br /&gt;
Fairly complete mock of Firebug.&lt;/p&gt;
&lt;pre class="brush:js;"&gt;        if (!("undefined" !== typeof window.console &amp;amp;&amp;amp; (window.console.firebugVersion || window.console.firebug )))
        {
            window.console = {
                "assert": function() { },
                "count": function() { },
                "clear": function() { },
                "debug": function() { },
                "dir": function() { },
                "dirxml": function() { },
                "info": function() { },
                "error": function() { },
                "getFirebugElement": function() { },
                "group": function() { },
                "groupEnd": function() { },
                "groupCollapsed": function() { },
                "log": function() { },
                "notifyFirebug": function() { },
                "profile": function() { },
                "profileEnd": function() { },
                "time": function() { },
                "timeEnd": function() { },
                "trace": function() { },
                "warn": function() { },
                "userObjects": [],
                "element": {},
                "firebug": "foo"
            };
        };

&lt;/pre&gt;&lt;img src="http://skysanders.net/subtext/aggbug/129.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sky Sanders</dc:creator>
            <guid>http://skysanders.net/subtext/archive/2010/07/10/javascript-console-and-firebug-mocks.aspx</guid>
            <pubDate>Sun, 11 Jul 2010 10:00:21 GMT</pubDate>
            <wfw:comment>http://skysanders.net/subtext/comments/129.aspx</wfw:comment>
            <comments>http://skysanders.net/subtext/archive/2010/07/10/javascript-console-and-firebug-mocks.aspx#feedback</comments>
            <wfw:commentRss>http://skysanders.net/subtext/comments/commentRss/129.aspx</wfw:commentRss>
        </item>
        <item>
            <title>irony indeed...</title>
            <link>http://skysanders.net/subtext/archive/2010/06/29/irony-indeed.aspx</link>
            <description>After all the reams of  C# and MembershipProvider sample code I have written on stack overflow, a silly &lt;a href="http://stackoverflow.com/questions/3146817/javascript-this-from-jquery-this/3146826#3146826"&gt;jquery/javascript question&lt;/a&gt; is about to eclipse all others.&lt;img src="http://skysanders.net/subtext/aggbug/128.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sky Sanders</dc:creator>
            <guid>http://skysanders.net/subtext/archive/2010/06/29/irony-indeed.aspx</guid>
            <pubDate>Wed, 30 Jun 2010 08:12:27 GMT</pubDate>
            <wfw:comment>http://skysanders.net/subtext/comments/128.aspx</wfw:comment>
            <comments>http://skysanders.net/subtext/archive/2010/06/29/irony-indeed.aspx#feedback</comments>
            <wfw:commentRss>http://skysanders.net/subtext/comments/commentRss/128.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Lenovo notebook keyboard blues: Misplace CTRL</title>
            <link>http://skysanders.net/subtext/archive/2010/06/10/lenovo-notebook-keyboard-blues-misplace-ctrl.aspx</link>
            <description>&lt;p&gt;The one complaint I have had with my Lenovo T61-p has been the transposition of the CTRL and FN keys.&lt;/p&gt;
&lt;p&gt;The keyboard is quite usable for it's size but the ctrl/fn issue makes it unusable, for me. It bugs me so much that I had decided, to my dismay, that I would not buy another Lenovo. If I had hands on experience with the keyboard before cutting the check for this box I would have reconsidered.&lt;/p&gt;
&lt;p&gt;So, I have grumbled about this for a couple years. And somehow I never thought of &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897578.aspx"&gt;Ctrl2Cap&lt;/a&gt;, a sysinternals utility by Mark Russinovich.&lt;/p&gt;
&lt;p&gt;Tada! I am back in love with my notebook. Granted, it is a couple years old, but with core2 2.1ghz, 8 gb fast ram and an intel x-25 SSD, I rarely find myself complaining about performance. And now I can hack out code while on the move without toting around an external keyboard. Yay!&lt;/p&gt;
&lt;p&gt;Now I just need to install Ctrl2Cap on all my boxes for a consistant UX. &lt;/p&gt;&lt;img src="http://skysanders.net/subtext/aggbug/127.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sky Sanders</dc:creator>
            <guid>http://skysanders.net/subtext/archive/2010/06/10/lenovo-notebook-keyboard-blues-misplace-ctrl.aspx</guid>
            <pubDate>Fri, 11 Jun 2010 02:08:12 GMT</pubDate>
            <wfw:comment>http://skysanders.net/subtext/comments/127.aspx</wfw:comment>
            <comments>http://skysanders.net/subtext/archive/2010/06/10/lenovo-notebook-keyboard-blues-misplace-ctrl.aspx#feedback</comments>
            <wfw:commentRss>http://skysanders.net/subtext/comments/commentRss/127.aspx</wfw:commentRss>
        </item>
        <item>
            <title>SharpZipLib: recursively zip/unzip directory structure</title>
            <link>http://skysanders.net/subtext/archive/2010/05/23/sharpziplib-recursively-zip-directory-structure.aspx</link>
            <description>&lt;pre class="brush:c#;"&gt;
// Project: Salient
// http://salient.codeplex.com
// 
// Copyright 2010, Sky Sanders &amp;lt;sky at skysanders.net&amp;gt;
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://salient.codeplex.com/license
//  
// Date: May 24 2010 

#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ICSharpCode.SharpZipLib.Zip;

#endregion

namespace Salient.IO.Compression
{
    public static class DirectoryCompression
    {
        public static void CompressDirectory(this Stream target, string sourcePath,
                                             Func&amp;lt;string, bool&amp;gt; excludeFromCompression)
        {
            sourcePath = Path.GetFullPath(sourcePath);

            string parentDirectory = Path.GetDirectoryName(sourcePath);

            int trimOffset = (string.IsNullOrEmpty(parentDirectory)
                                  ? Path.GetPathRoot(sourcePath).Length
                                  : parentDirectory.Length);


            List&amp;lt;string&amp;gt; fileSystemEntries = new List&amp;lt;string&amp;gt;();

            fileSystemEntries
                .AddRange(Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories)
                              .Select(d =&amp;gt; d + "\\"));

            fileSystemEntries
                .AddRange(Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories));


            using (ZipOutputStream compressor = new ZipOutputStream(target))
            {
                compressor.SetLevel(9);

                foreach (string filePath in fileSystemEntries)
                {
                    if (excludeFromCompression(filePath))
                    {
                        continue;
                    }

                    compressor.PutNextEntry(new ZipEntry(filePath.Substring(trimOffset)));

                    if (filePath.EndsWith(@"\"))
                    {
                        continue;
                    }

                    byte[] data = new byte[2048];

                    using (FileStream input = File.OpenRead(filePath))
                    {
                        int bytesRead;

                        while ((bytesRead = input.Read(data, 0, data.Length)) &amp;gt; 0)
                        {
                            compressor.Write(data, 0, bytesRead);
                        }
                    }
                }

                compressor.Finish();
            }
        }


        public static void DecompressToDirectory(this Stream source, string targetPath, string pwd,
                                                 Func&amp;lt;string, bool&amp;gt; excludeFromDecompression)
        {
            targetPath = Path.GetFullPath(targetPath);

            using (ZipInputStream decompressor = new ZipInputStream(source))
            {
                if (!string.IsNullOrEmpty(pwd))
                {
                    decompressor.Password = pwd;
                }

                ZipEntry entry;

                while ((entry = decompressor.GetNextEntry()) != null)
                {
                    if (excludeFromDecompression(entry.Name))
                    {
                        continue;
                    }

                    string filePath = Path.Combine(targetPath, entry.Name);

                    string directoryPath = Path.GetDirectoryName(filePath);


                    if (!string.IsNullOrEmpty(directoryPath) &amp;amp;&amp;amp; !Directory.Exists(directoryPath))
                    {
                        Directory.CreateDirectory(directoryPath);
                    }

                    if (entry.IsDirectory)
                    {
                        continue;
                    }

                    byte[] data = new byte[2048];
                    using (FileStream streamWriter = File.Create(filePath))
                    {
                        int bytesRead;
                        while ((bytesRead = decompressor.Read(data, 0, data.Length)) &amp;gt; 0)
                        {
                            streamWriter.Write(data, 0, bytesRead);
                        }
                    }
                }
            }
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;&lt;strong /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class="brush:c#;"&gt;
using System;
using System.IO;
using NUnit.Framework;
using Salient.IO.Compression;

namespace CoreFiveConnector.Tests
{
    [TestFixture]
    public class Class1
    {
        [Test]
        public void Test()
        {
            Func&amp;lt;string, bool&amp;gt; excludeFromCompression = path =&amp;gt; { return false; };

            MemoryStream compressed = new MemoryStream();


            compressed.CompressDirectory("c:\\Temp", excludeFromCompression);


            // sharpzip closes the target so we need to create a new seekable  stream
            MemoryStream compressed2 = new MemoryStream(compressed.ToArray());

            Func&amp;lt;string, bool&amp;gt; excludeFromDecompression = path =&amp;gt; { return false; };

            compressed2.DecompressToDirectory("c:\\Temp2", null, excludeFromDecompression);
        }
    }
}

&lt;/pre&gt;&lt;img src="http://skysanders.net/subtext/aggbug/125.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sky Sanders</dc:creator>
            <guid>http://skysanders.net/subtext/archive/2010/05/23/sharpziplib-recursively-zip-directory-structure.aspx</guid>
            <pubDate>Mon, 24 May 2010 07:10:45 GMT</pubDate>
            <wfw:comment>http://skysanders.net/subtext/comments/125.aspx</wfw:comment>
            <comments>http://skysanders.net/subtext/archive/2010/05/23/sharpziplib-recursively-zip-directory-structure.aspx#feedback</comments>
            <wfw:commentRss>http://skysanders.net/subtext/comments/commentRss/125.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Release: CassiniDev for Visual Studio 2008 - a drop in replacement for WebDev.WebServer</title>
            <link>http://skysanders.net/subtext/archive/2010/05/22/release-cassinidev-for-visual-studio-2008-a-drop-in.aspx</link>
            <description>&lt;p&gt; &lt;/p&gt;
&lt;p&gt;I have just released the beta build of CassiniDev.VisualStudio, a fully compatibly drop in replacement for the Visual Studio Development Server (WebDev.WebServer.exe)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why? &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Myself and others have found over the years that while WebDev is a reliable  development and debugging companion is falls a bit short in some areas including serving the correct content-type for many file types and the lack of discoverable logging.&lt;/p&gt;
&lt;p&gt;These issues and more are now covered in CassiniDev, including the Visual Studio builds.&lt;/p&gt;
&lt;p&gt;But the most attractive reason to replace WebDev.WebHost with CassiniDev is the ability to further customize the behavior and functionality of your development environment with relative ease.&lt;/p&gt;
&lt;p&gt;Check it out and download it here: &lt;a href="http://cassinidev.codeplex.com/"&gt;http://cassinidev.codeplex.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;img src="http://skysanders.net/subtext/aggbug/124.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sky Sanders</dc:creator>
            <guid>http://skysanders.net/subtext/archive/2010/05/22/release-cassinidev-for-visual-studio-2008-a-drop-in.aspx</guid>
            <pubDate>Sat, 22 May 2010 17:58:03 GMT</pubDate>
            <wfw:comment>http://skysanders.net/subtext/comments/124.aspx</wfw:comment>
            <comments>http://skysanders.net/subtext/archive/2010/05/22/release-cassinidev-for-visual-studio-2008-a-drop-in.aspx#feedback</comments>
            <wfw:commentRss>http://skysanders.net/subtext/comments/commentRss/124.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>