Blog Splash

Our View on Fair Licensing

by Kerido Wednesday, April 14, 2010 1:41 AM

We do take money for KO Approach. This is part of our strategy pretty much the same way as it is the strategy of some enthusiasts to deliver their products for free. It's hard to write on such ethically ambiguous things without getting involved into a perpetual controversy – what's better: free or non-free software. On one hand, they say that providing free software is the same as helping your neighbor. On the other, labor must be rewarded.

I don't mind helping my neighbor and I do it quite often. I do donate to charity and non-profit organizations. Not only because I want to believe that I'm a good person, but also because it makes me feel that I make a contribution to the world.

Unless it becomes a duty. When Richard Stallman declares that "proprietary software ... forbids cooperation", I feel that there's a ghetto some place where all non-free software vendors will eventually be sent. I'm serious – this compulsory moral that you may not ask for reward for your wok, is a real threat. Just because I'm free to believe I'm worth something. This is why KO Approach will never be free.

How It All Started

I started working on KO Approach not for money, but for one straightforward goal – access my files quicker. One day I just realized how much time I was wasting on things that didn't have anything to do with real work. Although things have somewhat improved on Windows, opening files is still a surprisingly time consuming task.

What I came up with was a program that displayed a list of files in a Windows folder when I clicked on the folder's icon. This functionality is now known as Folder Menus. Instead of beating my way through stacking windows, I now had a convenient menu-based interface that allowed me to reach even a deeply buried file in seconds. I was happy with this minimalistic approach to opening files. My screen was finally clean and free for real tasks. At first, I wasn't even concerned about distributing my product to somebody else. There were no installers, help files, or websites.

Eventually, I showed the tool to a local community. The feedback was roughly as follows: "You know what, browsing folders through menus is cool, but I won't be using your tool unless you add [feature]." This is where I learned three things:

  1. There is demand for the product
  2. More time and effort need to be invested in order to satisfy potential customers
  3. I should take money for the product

So I'm working hard to implement additional features. But this work is fun as I learn new things all the time. I love software development and I love KO Approach. I always wish I had more time to make an even better product.

Licensing Explained

The licensing scheme I implemented may seem extremely harsh. By default, a copy of KO Approach runs in a limited functionality mode in which the following restrictions apply

  1. Only two out of three program features can be turned on. For example, you can run Folder Menus and Approach Items, or Folder Menus and Titlebar Menus, but not all three together.
  2. A maximum of four menus can be displayed. When the fourth menu appears, folders do not show submenu arrows.
  3. At most, two plug-ins can be loaded. This becomes essential with version 0.4.4 that ships with four handy plug-ins out of the box.

In order to unlock, Approach needs a small Activation Key file. Each Key file contains commands and data that provide missing functionality to the program module. A Key file is only valid for one particular machine. This is achieved by gathering hardware data which uniquely identifies the computer on which Approach is running. A hardware update renders the existing Activation Key unusable. Each License has a fixed number of unique computers on which Approach can be activated. When a purchase is made, the customer receives a Serial Number which he or she must then specify in order to receive an Activation Key.

This may seem even crueler than Windows activation policy. The latter at least permits minor hardware changes without the need to reactivate. However, the goal is not to screw our customers by soaking the last penny out of their pockets, but to prevent Serial Number leakage.

Feel Free to Request Additional Activations

Whenever you make a hardware update and you don't have available activations left, just write us an email with a request for additional activations. By receiving an email, we can identify you as a valid customer and assist you as soon as possible. As a matter of fact, I remember one customer who has already requested about ten additional activations. I don't even mind if he installs KO Approach to his entire family with all these extra Keys.

It's fair to me because this is where mutual trust is established: you know you won't be forced into buying additional Licenses after a tiny RAM update and we know your Serial Number remains in good hands. It's probably the same as giving the keys from your house to your friend. But you still want to protect yourself from intruders and thieves, right?

KO Approach 0.4.4 Is Here

by Kerido Saturday, April 10, 2010 1:09 AM

It's been almost three months since we announced we'd be releasing a new version of KO Approach. Finally, it's here! And it's better than ever! A lot of features have been redesigned from scratch to enable greater reliability and future extensibility.

Improved Compatibility

We are happy to let you know that KO Approach is now fully compatible with 64-bit Windows, including Windows 7, and that all the plug-ins have been thoroughly tested under the 64-bit architecture. We've also put a quite a bit of effort into optimizing Approach to reduce resource consumption on both 32-bit and 64-bit systems.

KO Approach now has an improved look-and-feel. Menus are always rendered consistently with the Operating System, no matter which version of Windows you are running. Approach works great with the Aero theme, too.

Feature Enhancements

The Approach Items feature has been completely rewritten to support not only file and folder lists, but also custom objects that can be added to the menu. As an example, we've included an item displaying a list of recent commands from the Run dialog box. Just open up the Approach Items menu, choose Run, and fire up a command from the menu that will appear. It's a huge time saver for commands that you use most frequently! With extensibility in mind, we will be adding new handy objects into upcoming versions of Approach, as well as create new plugins implementing similar functionality. As a matter of fact, there are some experimental objects already under development!

We've added new options into Titlebar Menus to improve user experience. Browse the entire folder hierarchy, from Desktop to the current folder, with CTRL+click on an Explorer window's title bar. Set Titlebar Menus to order items as you like: parent-to-child or child-to-parent. The current folder can also be automatically highlighted.

New Plugins

KO Approach now ships with four plugins, as we have added two more plugins to the application package. These include  InstantTxt, which now has been extended to support multiple text formats, and a brand-new plugin, ClipboardAssistant. The latter is an extention to KO Approach's contextual menus which allows you to copy to clipboard the full path to the selected item, the path to the target of a shortcut, and even the entire directory listing of any folder!

As always, Scope and InstantWave, the two familiar companions to KO Approach, allow for previewing graphics files as well as playing back sound files, right from KO Approach menus!

Get a Free KO Approach License

There are opportunities to receive a license absolutely free of charge! If you know a foreign language and have experience in software localization, please help us deliver a version of KO Approach to your compatriots! We will compensate your time and effort with free licensing of our product.

For registered customers, the upgrade to the new version is absolutely FREE! Simply download and start enjoying all the great new features right now! Otherwise, the Basic license is only $19.95.

Permanent Redirect Using ASP.NET

by Kerido Monday, February 22, 2010 7:49 AM

As Google recomments, when changing a website's domain name, you should add the HTTP 301 "Moved Permanently" status to the old address. To my shame, I always thought this is what HttpResponse.Redirect is about. However, using the latter produces the HTTP 302 status which is semantically somewhat different.

A trivial task that ASP.NET has no pretty code for. Here is a convenience class that does the job:

public static class HttpResponseUtility
{
  public static void PermanentRedirect(HttpResponse theResp, string theUrl)
  {
    PermanentRedirect(theResp, theUrl, true);
  }

  public static void PermanentRedirect(HttpResponse theResp,
    string theUrl, bool theEndRequest)
  {
    theResp.Redirect(theUrl, false);
    theResp.StatusCode = 301;  // as opposed to 302 set by Redirect

    if(theEndRequest)
      theResp.End();
  }
}

With this class in place, you simply call the following from a page:

HttpResponseUtility.PermanentRedirect(Response, newUrl);

Also, if you use .NET version 3.5, an extension method would do an even better job (notice the this keyword):

public static class HttpResponseUtility
{
  public static void PermanentRedirect(this HttpResponse theResp, string theUrl)
  {
    PermanentRedirect(theResp, theUrl, true);
  }

  public static void PermanentRedirect(this HttpResponse theResp,
    string theUrl, bool theEndRequest)
  {
    theResp.Redirect(theUrl, false);
    theResp.StatusCode = 301;  // as opposed to 302 set by Redirect

    if(theEndRequest)
      theResp.End();
  }
}

Your client code would then look even prettier:

Response.PermanentRedirect(newUrl);

Monitoring Site Uptime

by Kerido Wednesday, February 10, 2010 8:46 AM

I'd rather not mention the name of my hosting provider, but I'm definitely dissatisfied with their service. In the beginning of February I started monitoring website uptime.

The idea behind the tool I've written is simple. The program runs as a service on a dedicated machine and periodically queries a known resource on the website. The query intervals are adjustable. Currently I've specified them as follows:

  • every 30 minutes if the resource has been successfully accessed;
  • every 5 minutes if the resource cannot be accessed.

This is actually the main reason I decided to write my own tool – you only get hourly monitoring from free services. If you want more frequent pings, you have to pay. And I'm just too old school to pay for this.

If the resource on the website cannot be reached, the tool tries to determine if the server on which it is running, has no connection. To do so, it queries a so called trusted URL. Finally, the site is considered down only if the trusted URL can be reached.

Another concept I put into the tool is analysis. The program automatically displays downtime intervals: start time, end time and duration. Given the sum of these intervals, I calculate total uptime, total downtime, and most importantly, relative uptime. I can perform this kind of analysis for various periods.

After a couple of weeks of monitoring I guess, the hosting provider is somewhat cheating with numbers. They promise 99.9% uptime. My tool shows a more truthful figure.

It makes sense to monitor your website uptime because you need to know what you're paying for. If anybody is interested, I'll probably publish the source code some time later.

An Ultra Fast CSS Minify Algorithm

by Kerido Saturday, January 30, 2010 6:10 AM

Introduction

You've probably thought a lot about ways you can optimize your Web site. Since the release of this new site, I've been thinking about it a lot. In this post I would like to introduce an advanced version of the CSS minify algorithm. There are several existing implementations available, but I took the one integrated into BlogEngine.NET, as a reference. Compared to it, my algorithm offers several benefits:

Concept

As opposed to the built-in CSS minify algorithm which uses regular expressions, the current algorithm is more like a state machine. This is why you might think it's harder to read and debug. This is why I am writing this post.

First, here are valid CSS states that the algorithm uses:

enum CssState
  { Punctuation, Token, StringD, StringS }

The CSS code is always considered Punctuation if a different state does not apply. Curly braces, square brackets, parentheses – this is all Punctuation. The Token state includes all tag names, element IDs and classes, properties and values – anything that consists of alpha-numeric characters plus a limited number of auxiliary characters – .#_-@*%(). And finally, there are two string states. StringD represents a double-quoted string, StringS – single-quoted. I'll cover more about the reason why the latter two are required, in the Handling Strings section.

The algorithm reads the input character by character and determines if a sequence of whitespace characters can be removed from it. It also handles comments pretty much the same way. Here is the code illustrating the idea:

public static string Minify(string theCss)
{
  // Assume that the length of the output string
  // will be at most 75% the length of the incoming one to avoid
  // additional StringBuilder reallocations.
  StringBuilder aRet = new StringBuilder(theCss.Length * 3 / 4);

  int aNumChars = theCss.Length;

  CssState aPrevState = CssState.Punctuation;
  int aPrevPos = 0;

  int i = 0;

  while(i < aNumChars)
  {
    CssState aCurState = GetState(theCss, ref i, aPrevState);

    if(i > aPrevPos + 1)
    {
      // If whitespace is found between two tokens, keep it compact
      if (aPrevState != CssState.Punctuation && aCurState != CssState.Punctuation)
        aRet.Append(' ');

      // Otherwise, no whitespace is needed, skip everything between aPrevPos and i
    }

    aPrevPos = i;
    aPrevState = aCurState;
    aRet.Append(theCss[i++]);
  }

  return aRet.ToString();
}

As you can see, whitespace must not be removed is when it delimits token or string characters. Examples of this case are:

border-bottom: solid 2px #9f4c1f;
background-position: center top;
quotes: '« ' ' »';
quotes: "»" "«" "\2039" "\203A";

In all other cases, the whitespace can be trimmed. Again, there is a special case when whitespace is found inside a string, but we'll cover it in the next section.

The key of the algorithm is the GetState method. It skips any comments and whitespace characters found in the incoming string, updates the position variable i to a value represented by a meaningful state:

static CssState GetState(string theCss, ref int thePos, CssState theCurState)
{
  int aLen = theCss.Length;
  int i = thePos;

  if (theCurState == CssState.StringD)
  {
    //REMOVED FOR COMPACTNESS
  }
  else if (theCurState == CssState.StringS)
  {
    //REMOVED FOR COMPACTNESS
  }


  bool aSkip = true;

  while(aSkip)
  {
    /////////////////////////////////////////
    // Skip whitespace
    while(aSkip = (i < aLen - 1 && IsWhitespaceChar(theCss[i]) ) )
      i++;

    /////////////////////////////////////////
    // Skip comments
    if(i < aLen - 1)
      if (theCss[i] == '/' && theCss[i+1] == '*') // comment opening
      {
        aSkip = true;

        while(i < aLen - 1)
        {
          i++;

          if(theCss[i-1] == '*' && theCss[i] == '/') // comment closing
          {
            i++;
            break;
          }
        }
      }
  }

  thePos = i;
  if ( IsTokenChar( theCss[i] ) )
    return CssState.Token;

  else if ( theCss[i] == '\"' )
    return CssState.StringD;

  else if(theCss[i] == '\'')
    return CssState.StringS;

  else
    return CssState.Punctuation;
}

For for the sake of saving space I have removed several lines, so let's move on to see what they are meant for.

Handling Strings

According to the CSS specification, two types of strings are supported: single-quoted and double-quoted. My algorithm leaves the string intact, even if whitespace characters are found inside it. Of course, for the HTML language it may not matter at all since all whitespace characters will be merged by the browser. But I just think that keeping the string unmodified is more intuitive and professional. In order achieve that, support needs to be added for escaped quote characters. An escaped single quote character inside a single-quoted string does not close the string. Similarly, an escaped double quote character does not close a double quoted string:

if (theCurState == CssState.StringD)
{
  if(theCss[i] == '\"')
  {
    // Make sure the double quote character is not escaped
    if(thePos > 0)
      if(theCss[i-1] == '\\')
        return CssState.StringD;

    // Enforce a whitespace afterwards
    return CssState.Token;
  }
  else
    return CssState.StringD;
}
else if (theCurState == CssState.StringS)
{
  if(theCss[i] == '\'')
  {
    // Make sure the single quote character is not escaped
    if(thePos > 0)
      if(theCss[i-1] == '\\')
        return CssState.StringS;

    // Enforce a whitespace afterwards
    return CssState.Token;
  }
  else
    return CssState.StringS;
}

There is a special example attribute in the reference CSS file that illustrates the differences in the way the two algorithms work:

angledouble: "Angle=             00deg00'00\"      ";
anglesingle: 'Angle=             00deg00\'00"      ';

Although these attributes make no sense to a browser, they represent valid CSS syntax. My version produces the same string while the BlogEngine.NET version trims several spaces from it. I consider this a flaw even though string length gets reduced.

Performance Testing

The suggested algorithm provides both speed and size wins. The code below lists two methods I used to measure output length and processing time of the two algorithms:

[TestMethod]
public void CssMinifyTest_Length()
{
  string aCss = Properties.Resources.style;

  string aMin1 = CssMinifier.Minify(aCss);
  string aMin2 = CssHandler.StripWhitespace(aCss);

  Console.WriteLine(
    string.Format("KO Software output ({0} bytes):", aMin1.Length) );
  Console.WriteLine(aMin1);

  Console.WriteLine("---------------------------------");

  Console.WriteLine(
    string.Format("BlogEngine.NET output ({0} bytes):", aMin2.Length) );
  Console.WriteLine(aMin2);

  Assert.IsTrue(aMin1.Length <= aMin2.Length);
}

[TestMethod]
public void CssMinifyTest_Speed()
{
  int aNumCycles = 50000;
  string aCss = Properties.Resources.style;

  DateTime aStart = DateTime.Now;
  for(int i = 0; i < aNumCycles; i++)
  {
    string aMin = CssMinifier.Minify(aCss);
  }
  DateTime aEnd = DateTime.Now;

  TimeSpan aTime_AspxGear = aEnd - aStart;
  Console.WriteLine(aTime_AspxGear.ToString());


  aStart = DateTime.Now;
  for(int i = 0; i < aNumCycles; i++)
  {
    string aMin = CssHandler.StripWhitespace(aCss);
  }
  aEnd = DateTime.Now;


  TimeSpan aTime_BE = aEnd - aStart;
  Console.WriteLine(aTime_BE.ToString());


  Assert.IsTrue(aTime_AspxGear <= aTime_BE);
}

The results are illustrated in the table below:

KO Software CSS Minifier BlogEngine.NET CSS Minifier
Output size, bytes 6,888 7,274
50,000 iteration processing time (Debug build) 33 seconds 1 minute and 25 seconds
50,000 iteration processing time (Release build) 15 seconds 1 minute and 20 seconds

Conclusion

The suggested algorithm produces output which is smaller by almost 400 bytes. And it runs more than 5 times faster! Interestingly, the Release build is more than two times faster than the Debug one while the BlogEngine.NET version yields only subtle performance boost. I suspect, this is because the latter uses regular expressions which are already built with most possible optimizations, regardless of our build type.

I am going to contact the BlogEngine.NET team and e-mail my code as a patch to their source code repository. I think, if this code is properly tested in various environments, it can surely improve web site stability and reduce traffic. As an old school programmer, I am still interested in ways of improving the code. So please, download the source code and leave comments with bugs and improvements.