About the author

J Sawyer is a developer based in Houston, TX and loves to write code, especially ASP.NET and other web-related stuff.

He also loves to ride his Kawasaki Ninja.

But he doesn't code and ride at the same time.

Calendar

<<  March 2010  >>
MoTuWeThFrSaSu
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar

Bikers, Geeks and Community

April 24, 2009 5:06 PM

When motorcyclists pass each other in opposite directions, they wave at each other. Watch them sometime; you’ll see this happen. A lot of non-motorcyclists (we call them “cagers”) don’t notice this until it’s pointed out but you’ll see it if you look for it. It doesn’t matter if you are riding a crotch rocket or a Harley, a Goldwing or a dual-sport, if you are suited up in all leather and a helmet or are riding with no gear at all, bikers will still wave. If a motorcyclist sees another biker stopped on the side of the road, they will usually stop to check and see if they are OK. That’s just how it is. When commuting, bikers will also sometimes join each other in traffic and ride together for a time as their commute allows. Again, you’ll see this. But I’d bet you never even considered that those two bikers didn’t know each other. There are also biker-specific forums – I’m on Two Wheeled Texans – that all kinds of bikers participate in. There are also group rides; random people hooking up just to ride together. Some are random groups from the boards, some more “organized”. For example, TWT has a monthly “Pie Run” to a small restaurant in a small town in Texas and there will be anywhere from 80 – 250 bikers show up, on ALL kinds of bikes from ALL over Texas. I even saw someone at one of the Pie Runs on a vintage 1943 Army issue Harley! Bikers will also get together for a “Bike Night”. As the name implies, it’s an evening for bikes and bikers to hang out together at a local restaurant/ice cream shop/parking lot/whatever. I can often be found at “Katy Bike Night” on Wednesdays, munching on empanadas with anywhere from 3 to 20 fellow TWT’ers.

There is a strong sense of community among motorcyclists that is built on a common, shared experience … namely riding a motorcycle. We share a love for riding, feeling the wind blowing over us. We also share common dangers and risks - for the most part, “cagers” are the greatest risk but that’s not the only one (think … weather … a 45 MPH crosswind is absolutely, positively NOT FUN). Sure, we have our differences – every group does - but the sense of community is stronger than that. Yes, there are some individual exceptions to this but, as a rule, that’s how it is. And those that get snobby about their “group” are considered rude at best. And I won’t even mention “squids”.

Why do I mention this? Well … it’s that community thing. I’ve been involved in the developer community for some six years now and the biker community for about 2 years. I can tell you, the biker community is much stronger and, even more importantly, much more inclusive. In the developer community, there is – and let’s be honest here – a huge wall separating technologists with different specializations. Java guys don’t talk to .NET folks and they don’t talk to PHP folks. Linux folks don’t talk to Microsoft folks. Sure, there are exceptions here and there but the rule is different; we don’t intermingle. Do you know of any boards online where you have PHP and .NET and Java folks all mixin’ it up together in harmony? I certainly don’t. Even boards that cater to all types of technologists will have different forums where techies of like technologies congregate, with very little interaction between the groups. We tend to get wrapped up in our own areas of technology and look at technologists in other areas with wariness at best. Certainly one difference is competition … if Java is chosen as a technology at a given company, the .NET folks will be looking for work. And, again, vice-versa. That’s not the case with motorcyclists – it has no impact on my life if a fellow biker buys a new Ninja or a new Goldwing … I can appreciate both and it has no bearing at all on my ability to provide for my family (even if you won’t get me caught dead on a Goldwing!).

But there’s something more than that – overall, there also seems to be little interaction between infrastructure/network folks and developer types even in the same technology area.

When you think about it, it’s actually quite silly. Yes, there is that competition but I can’t see why we can’t be more like the motorcyclist community … inclusive and sharing what we have in common (which is quite a bit) rather than focusing solely on our differences. All of us have a love for technology and we all have the same gripes and issues with end users, customers, managers and the like. Regardless of our technology, there is much that we can share and much that we can learn from each other. Even if that’s only an appreciation for other technologies.

I think it’ll be interesting to walk into a PHP user group. I’d bet that they are little different from the .NET user groups that I go to. I won’t say anything. Well, I’ll try not to say anything or too much at least. Not there to convert them, spy on them or any other such nonsense. Just getting a feel. Who knows … maybe I could persuade one or two to see what a .NET user group is like. And get them cross-pollinating with .NET folks going to PHP user groups. It won’t be the end of the world by any stretch of the imagination. But it certainly make the community much more interesting. And maybe … just maybe … we’ll take a step towards breaking down these silly walls that would divide us.

We’ll see …



Tags: , ,

Idle Babbling | Community

Moving from dasBlog to BlogEngine.NET

April 22, 2009 9:54 AM

As I mentioned previously, I’ve moved from dasBlog to BlogEngine.NET for this blog. This, of course, involved reformatting and redesigning the look and feel of the site; that’s nothing unique to the migration and I’m not going to go into that at all. What I will do, however, is discuss the process of moving existing content over from dasBlog to BlogEngine, something that isn’t really hard but does have a few gotchas.

Moving the Content

That’s the first thing that needs to be done. In fact, I did this before I even started formatting the new site – I wanted to be sure that the existing content rendered relatively well in the new design. It was not quite as simple as described on Merill’s blog. All of his steps are valid, but there is actually a couple of other things that need to be done. You will definitely want to use the dasBlog to BlogML Converter that Merill posted on MSDN Code Gallery – dasBlog doesn’t do BlogML and, while BlogEngine will import RSS, RSS usually will not get all of your content. BlogML works much better.

There were two things with moving the content … how big a deal those are depend on how picky you are about the move. I was. First, the timestamp on the entry. dasBlog uses UTC (GMT) to store the time and that’s how it is imported into BlogML. BlogEngine uses the server time. Both have an offset to convert the saved time into blog local time, but dasBlog’s offset is from UTC (using standard time zones) and BlogEngine uses an offset from the server time. My server is on US Eastern Time and my local blog time is US Central Time, which means that, on import, I had to convert the time to US Eastern and then set my offset in BlogEngine to –1 (US Central is 1 hour “behind” US Eastern). To do this, I had to modify the code that imported the blog entries, which can be found at BlogEngine.Web\api\BlogImporter.asmx. Since the incoming BlogML only had a post date, not a DateCreated and a DateModified (as BlogEngine does), I also set both the create date and the modify date to the same value. Here’s the code snippet from AddPost:

Post post = new Post();
post.Title = import.Title;
post.Author = import.Author;
post.DateCreated = import.PostDate.AddHours(-5);
post.DateModified = import.PostDate.AddHours(-5);
post.Content = import.Content;
post.Description = import.Description;
post.IsPublished = import.Publish;

Once I set BlogEngine’s server time offset (in the admin section under “Settings”), all of the times were now correctly displayed as US Central.

The second thing relates to the tags … BE uses tags (and categories) while dasBlog only uses categories. In dasBlog, the “tag cloud” is generated from the categories and BE generates this from the actual post tags. I can’t say which method I like better yet or if I prefer some mish-mash of the two (generate the cloud from tags and categories … that may be an idea) but I did know that I didn’t want to lose my tag cloud. So, on import, I added tags for each post category to the imported post. Again, simple and again, in AddPost:

if (import.Tags.Count == 0)
{
    post.Tags.AddRange(import.Categories);
}
else
{
    post.Tags.AddRange(import.Tags);
}

From a performance standpoint, I couldn’t tell you if AddRange is faster than looping block to add each value individually (and it really doesn’t matter here), but it is simpler, cleaner and much easier to read … so I tend to prefer AddRange().

With these two “issues” resolved – and they aren’t issues with BE, to be sure, just a difference between the two – I was ready to move on.

Preserving links

Some of my entries have a pretty good page rank on various search engines and there is a non-trivial amount of traffic that is generated from these search engines. While I can go in and change things like the RSS source for my feed from FeedBurner to make the move transparent, that doesn’t help with the search engines. Therefore, I needed a way to ensure that existing links would continue to work without returning 404’s. Yes, I moved the old domain over to the new domain and added it as a host header on the new site, but that does not help prevent link breakage and BE and dasBlog have different formats for their links. I also did not, at this point in time, want to force a redirect as soon as a new person hit my site from a search engine; it’s just rude (IMHO) and doesn’t create a great user experience. Sure, maybe it wouldn’t be a big deal, but I didn’t like it. And besides, it gave me an excuse to write code. :-)

To keep the links intact, I decided that I would leave BlogEngine’s UrlRewriting intact; I didn’t want to make too many changes to the base source code as it would make it harder for me to move between versions/revisions. Rather, I wanted to sit on top of it and make sure that the links worked. So I used ASP.NET Url Routing to intercept the requests and send them to the right place (post.aspx). Before I go into the code, let’s first examine the (default) url structures for individual posts. In dasBlog, the post link is in the format yyyy/mm/dd/{CompressedTitle}. In BlogEngine, this would be post/{CompressedTitle} –or- (the permalink format) post.aspx?id={PostGUID}. While BE can have the date as a part of the post link, it still wouldn’t work; they compress their titles differently and, as mentioned before, dasBlog uses UTC internally and it’s used in the link as well.

For the routing, I created the route using "{Y}/{M}/{D}/{Title}" as the route url. From there, I needed to implement GetHttpHandler to do the work. Initially, I did the matching to title using a Linq query and it worked just fine. The problem with this is that every title in the posts would need to be converted to the dasBlog format (I copied over the dasBlog CompressTitle method as dasBlogCompressTitle), a process that seemed far from ideal. Once I understood how the dates worked, I was able to do the primary matching on the date and then, if necessary, match the titles for posts on the same date, minimizing the string manipulation that was required. Once I determined what the matching post was, all I needed to do was append the query string “?id={postGuid}” to the URL and then pass back the HttpHandler from post.aspx for the actually processing. If there was no match, then there would be no query string appended and post.aspx would show a 404. The code for this is below:

public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext)
{
    //Get the date from the route. 
    string dateString = string.Format(@"{0}/{1}/{2}",
        requestContext.RouteData.Values["M"],
        requestContext.RouteData.Values["D"],
        requestContext.RouteData.Values["Y"]);
    string titleString = ((string)requestContext.RouteData.Values["Title"]).Replace(".aspx", ""); 


    DateTime postDate = DateTime.MaxValue;
    Post selectedPost = null; 
    if (DateTime.TryParse(dateString, out postDate))
    {
        //Date is valid at least. 
        //Find posts with the same date.
        //Date in URL is in UTC. 
        var postsForTitle =
            from p in Post.Posts
            where p.DateCreated.ToUniversalTime().Date == postDate
            select p;
        if (postsForTitle.Count() == 1)
        {
            //There is only one posts for the date, so this must be it. 
            selectedPost = postsForTitle.First(); 
            
        }
        else
        {
            //differentiate on title. 
            foreach (var p in postsForTitle)
            {
                if (dasBlogCompressTitle(p.Title).Equals(titleString, StringComparison.InvariantCultureIgnoreCase))
                {
                    selectedPost = p;
                    break; 
                }
            }
        }
        if (selectedPost != null)
        {
            //Use UrlRewriting to put the id of the post in the query string. 
            requestContext.HttpContext.RewritePath(requestContext.HttpContext.Request.Path + "?id=" + selectedPost.Id.ToString(), false);
        }
    }

    return BuildManager.CreateInstanceFromVirtualPath(
        "~/post.aspx", typeof(System.Web.UI.Page)) as System.Web.IHttpHandler; 

}

Once I set it up on the web.config file and added the routes to the RouteTable, all was good and it worked fine.

Preserving the RSS Feed Url

The final step - and the thing that occurred to me last – was to make sure that the RSS feed url continued to work. While FeedBurner had no problem with changes the RSS url for my blog, there was the possibility (however remote it may have seemed) that someone was using the dasBlog’s RSS feed rather than FeedBurner. I’m not sure how remote a possibility this is but I didn’t use FeedBurner in the early days of the blog, so I figured that it might be an issue. And I certainly wouldn’t want to alienate the longest-time subscribers to my feed. This was incredibly simple and didn’t require any code at all, just two lines line in the web.config file to have SyndicationService.asmx (dasBlog’s RSS feed) handled by BlogEngine’s RSS feed, which is implemented as an HttpHandler and, by default, at syndication.axd. The first line is for IIS 6.0/IIS 7.0 Classic mode and is under the httpHandlers node of system.web:

<add verb="*" path="SyndicationService.asmx" 
type="BlogEngine.Core.Web.HttpHandlers.SyndicationHandler, BlogEngine.Core"
validate="false"/

The second goes in the corresponding location for IIS 7 Pipeline mode, in the handlers node of system.webServer:

<add name="dasBlogSyndication" verb="*" path="SyndicationService.asmx" 
type="BlogEngine.Core.Web.HttpHandlers.SyndicationHandler, BlogEngine.Core"
resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode"/>
These were copied from the default nodes used by BlogEngine for it’s syndication.axd and then the relevant attributes were changed. Simple enough.

Tags: , , , ,

BlogEngine.NET | Web (and ASP.NET) Stuff

Sql Injection #1 Hacker Technique

April 21, 2009 11:37 AM

On April 15, Verizon Business Security Solutions released The 2009 Data Breach Investigations Report, a comprehensive analysis of the data breaches that they investigated throughout 2008. A total of 285 million records were compromised as a result of these breaches and 79% (approximately 214 million records) of the compromised records were compromised utilizing SQL injection based attacks, typically through custom-developed web applications. As attackers are targeting the financial industry (representing 93% of total records) and, in particular, PIN data together with their associated credit and debit accounts, for focused attention, these records represent a far greater risk to the compromised user’s financial data and funds than magnetic stripe records or simple credit card account numbers.

Do I have your attention yet? Are you thinking to yourself “Holy Cow!”? I know that I was when I first saw this … we’ve known about the potential exploits of Sql Injection for a long time now (almost 10 years) and it’s still the most successful method of choice for data breaches. And these aren’t easy or simple breaches … the breaches that are considered the most complex are responsible for 95% of the compromised records … some of these attacks were the result of months of research. Who, you may ask, would have the time, patience and resources to dedicate so much time to an attack? Of the external breaches where the IP was traced to a specific entity, 16 out of 25 were traced to known organized crime outfits We aren’t dealing with the zit-faced script kiddie here, munching pizza in the darkness of his parent’s basement. We’re talking about career criminals that will take advantage of this information. Conventional wisdom often points to insiders as the most dangerous breach, but this data does put give pause to that assumption. The largest and most damaging breaches were externally sourced, not internally. Still, one should not, and in looking at the data, cannot, dismiss the damage potential of internal breaches; while the largest individual breaches were external, the median number of records compromised from internal attacks was just over 2.5 times the number of records from external sources. As far as risk and damage potential, both sources are a high risk for compromise.

“Wow!” you say “I thought that Cross Site Scripting was OWASP’s #1 threat!” Well, injection attacks are #2 and I’d bet it was a close race. That said, it’s not so simple. Cross Site Scripting (XSS) and Cross Site Request Forgery (CSRF) have been used to spread JavaScript-based worms that then use Sql Injection for an attack. Attacks vectors, it seems, don’t like to be alone and prefer to travel with their buddies.

We’ve known about Sql Injection and its potential for damage for a long time now. We’ve known that this type of attack is technology and database agnostic. Yet it is still a major issue. And it’s difficult to get developers to actually listen to security talks … there is still the attitude, it seems, that security is an infrastructure problem – but it clearly is not.

Are you one of the ones that care deeply about security? Or do you want to prove my previous statement wrong (I’d love to be proven wrong on that)? Why don’t you show up at the Houston OWASP group or your local OWASP group?



Tags: , ,

Security

Major Blog Update

April 20, 2009 3:25 PM

OK … I’ve been holding off a few posts because I’ve been working on completely reworking the blog. Here’s what’s new:

BlogEngine.NET: Yes, it’s true. I’ve migrated from dasBlog over to BlogEngine.NET. It was a process, not a happening and it took longer than I would have liked it to. Part of that was because BE was in the process of a new release and I kept moving the versions … and then had to migrate changes as well. There were a few issues that I found in the pre-release builds of v1.5 but the BE team got those ironed out – hopefully some of the patches that I submitted helped out here. So far, my experience with BlogEngine has been very good and I really like working with it and the extra features that it has over dasBlog. First … and this one’s a big part of the reason that I moved … BE uses ASP.NET Master Pages and controls and the like, not a templating engine like dasBlog. Yes, that is very likely due to when each one was first started but I do like master pages and it’s a lot easier to work with. As I’ve dug around more, I also like the way the BE extension mechanism works and the extensibility that it provides. I haven’t done any yet (because I’ve not had the need) but I am using several of the extensions.

New Domain: I know, I know, I broke one of the cardinal rules of Blogging. I’m moving everything over to a new domain (www.devbiker.net) and I’ll be retiring the old one … eventually. The old domain … well, it was hard to remember, too long to type and somewhat unwieldy. The new one is short, sweet and easier to remember. The old domain will, however, still work; it’s currently a host header on this site and, in time, I’ll start changing it to HTTP 301 redirect. Since I’m using FeedBurner, the Feed url won’t change so most (if not all) of the subscribers won’t have a problem. I also did some work to make sure that the dasBlog Url’s migrated over as well … both the dasBlog feed Url as well as the links to individual posts too. For the individual post links, I used Url Routing to “convert” the dasBlog Url for use in BlogEngine.

New Hosting Provider: This has been a tale of woe lately but I think it’s all finally settled. I’ve moved everything over to a provider (KinetikHosts) that is run by a friend of mine.

Now that this is all out of the way, I’ll be publishing the back-logged stuff.



Tags: