Simple Download Counter - Al Nyveldt

August 15, 2008 at 9:57 AMAmer Gerzic

THIS POST IS RELEVANT TO EARLIER VERSIONS OF BLOGENGINE (1.4.5 and earlier)

For a while, I have been using Simple Download Counter Extension provided by Al Nyveldt. I really liked it because it was easy to install and use (just like any other BlogEngine extension), and it provided me with valuable information about download counts. However, I noticed following bugs:

  1. Download count is not tracked properly if the file contains a space character within the name;
  2. Download count is not tracked properly if the file is in a sub-directory;
  3. If your post contains a string saying "/file.axd?file=" then simple download counter will try to interpret that as file serving and crash your web site (I discovered it when I wrote this post);

Quick look at the code revealed that after the file name is retrieved from the path, no URL decoding is preformed leaving special characters in URL format (space = %20, slash=%2f, etc.) The fix is very simple (for 1 and 2) and it is applied in UpdateDisplay(string body) method of the extension. Let's look at the modified code:

private string UpdateDisplay(string body)
{
  if (body.Contains("/file.axd?file="))
  {
    int pos = body.IndexOf("/file.axd?file=");
    while (pos > 0)
    {
      pos = pos + 14;

      /* Bug fixes:
         - http://www.amergerzic.com/post/Simple-Download-Counter-Al-Nyveldt.aspx */
      int quote_pos = body.IndexOf("\"", pos);
      if (quote_pos > -1)
      {
          /* Get the file name */
          string url_filename = body.Substring(pos, quote_pos - pos);

          /* Get rid of special characters */
          string filename = HttpUtility.UrlDecode(url_filename);
        
          /* Find where the download link ends */
          int linkTextEnds = body.IndexOf("</a>", pos);

          /* Serch for link begin */
          int linkTextBegins = body.IndexOf("<a ", pos);

          /* If we found a link begin before the link end, 
             then our link end does not belong to the download */
          if (linkTextBegins != -1)
              if (linkTextBegins < linkTextEnds)
                  break;

          /* Verify that we found link end in the first place */
          if (linkTextEnds > -1)
          {
              /* Look up the count */
              int count = GetFileCount(filename);

              /* Insert the number */
              body = body.Insert(linkTextEnds, " [Downloads: " + count.ToString() + "]");
          }
      }
      pos = body.IndexOf("file.axd?file=", pos);
    }
  }
  return body;
}

Before passing the file name for lookup (GetFileCount method), we need to make sure that the file name is URL decoded, for which we use static method HttpUtility.URLDecode(...). In this way, the file name that contains any special characters is properly decoded and can be matched against XML entry.

Fixing bug 3 is somewhat trickier. The solution presented here is not perfect, but it provides decent workaround. The solution consists of multiple checks:

  1. We are checking that closing quote character is found. If the character is not found then we do not have valid file name;
  2. We are checking that ending tag of the link is found. If we cannot find ending tag then this is not file download link, but simply text;
  3. If we find ending tag, we must make sure that it belongs to the file download link. We are doing that by checking if starting tag can be found between file link and ending tag;

Posted in: BlogEngine.NET

Tags:

Add comment

biuquote
Loading