Killing Spam Dead

Ok, I finally got rid of all Spam on my site. The Akismet plug-in did nothing. Maybe it slowed down the spam a little bit but I was still getting 10-15 spam comments per day. I think the problem was that they can’t blacklist everything in the universe and the comments were actually mostly-legitimate text that was just so general yet seemingly perfectly valid from a Bayesian filters perspective that there really was no way to actually filter it.

So I decided to create my own hack 🙂

I’m a little reluctant to post the solution here in case some spammers are able to adjust their tools to work around my hack… but the very fact that it works sort of indicates to me that they’re just blindly spamming me anyway so here we go.

The trick is basically to just create a new text box for the comments area. Then, with CSS you set the text box to be collapsed. On the server, if there is any text in the field then you throw away the comment. Spam tools must just blindly fill out everything then submit, or else they know the magic POST Url for BlogEngine.NET which is now slightly altered on my particular site and thus doesn’t work. Either way it seems to fix it.

Here are the relevant snippets:

~\User controls\CommentView.ascx, Line 43

<input type="text" id="txtCompany" style="visibility:collapse" />

~\User controls\CommentView.ascx.cs

public void RaiseCallbackEvent(string eventArgument)
{
    // ...
    string company = args[8];

    if (!string.IsNullOrEmpty(company))
    {
        _Callback = "failedCaptcha";
        return;
    }

~\blog.js

function AddComment(preview) {
    // ...
    var company = $("txtCompany").value;

    // ...
    var argument = 
        author + "-|-" +
        email + "-|-" +
        website + "-|-" +
        country + "-|-" +
        content + "-|-" +
        notify + "-|-" +
        isPreview + "-|-" +
        captcha + "-|-" + 
        company;

    // ...
}
function AppendComment(args, context) {
    if (context == "comment") {
        if (args == "failedCaptcha") {
            $("status").innerHTML = "<span style=\"color: red; font-weight: bold\">" +
            "Please enter the correct word</span>";
            return;
        }

        // ...
    }
}

Where “…” is the code currently inside of these methods, just leave that stuff alone. I have made a few test comments on my own blogs which seems to work but if someone could leave a quick confirmation comment that it is working for them also that would be great!

I seriously hope the spammers don’t see this though :-/

Silverlight 3 and Expression 3

After months of top secret work at Microsoft my labors are nearly realized. Yesterday Silverlight 3 and Expression 3 were released as an RC. If you haven’t checked it out you should definitely go and play around with the new bits. Here is a overview from Soma himself:

http://blogs.msdn.com/somasegar/archive/2009/07/10/launching-silverlight-3-and-expression-studio-3.aspx

Specifically I worked on the Photoshop Import functionality found in Expressoin Blend, Design and Web. It has been an exciting and rewarding project and I’m really looking forward to what is coming up next!

One of the other cool features to check out which was created by fellow Minnesotans, is Sketch Flow for Expression Blend. It’s a cool tool you can use to quickly prototype new applications and features.

The Illusion of Strongly Typed XML with C#

This is essentially a redo of an earlier blog post of mine on how to create the illusion of a strongly typed xml in Boo using Duck Typing, except this time we’re using the dynamic keyword in C#.

http://cid-dfcd2d88d3fe101c.skydrive.live.com/embedrowdetail.aspx/blog/justnbusiness/XmlBuilder.cs

Here is an example of how it might look to use such a thing.

dynamic builder = new XmlBuilder();
builder.Main.One = "Hello";
builder.Main.Two = "World";

Console.WriteLine(builder.ToString());

Console.WriteLine(
    "{0} {1}!",
    builder.Main.One,
    builder.Main.Two);

builder = new XmlBuilder();
builder.Main["One"] = "Hello";
builder.Main["Two"] = "World";

Console.WriteLine(builder.ToString());

Console.WriteLine(
    "{0} {1}!",
    builder.Main["One"],
    builder.Main["Two"]);

XmlBuilder is a class I created myself, it inherits from DynamicObject and it intercepts TryGetMember, TrySetMember, TryGetIndex and TrySetIndex in order to allow you to navigate an internal XmlDocument object. Here is the output when the above is run.

<Main><One>Hello</One><Two>World</Two></Main>
Hello World!
<Main One=”Hello” Two=”World” />
Hello World!

Notice the use of properties corresponds to drilling into elements and the use of indexers corresponds to drilling into Attributes. This is just a proof of concept but you could see how this sort of thing would be useful.

Here is the complete XmlBuilder class that makes it all happen.

public class XmlBuilder : DynamicObject
{
    private Func<string, XmlElement> createElement;
    private Func<string, XmlAttribute> createAttribute;
    private XmlNode node;

    public XmlBuilder()
    {
        this.node = new XmlDocument();
        this.createElement = s => ((XmlDocument)this.node).CreateElement(s);
        this.createAttribute = s => ((XmlDocument)this.node).CreateAttribute(s);
    }

    private XmlBuilder(
        XmlNode node, 
        Func<string, XmlElement> createElement, 
        Func<string, XmlAttribute> createAttribute)
    {
        this.node = node;
        this.createElement = createElement;
        this.createAttribute = createAttribute;
    }

    public override bool  TryGetMember(GetMemberBinder binder, out object result)
    {
        XmlNode found = this.node[binder.Name];
        if (found == null)
        {
            found = this.createElement(binder.Name);
            this.node.AppendChild(found);
        }

        result = new XmlBuilder(found, this.createElement, this.createAttribute);
        return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        XmlNode found = this.node[binder.Name];
        if (found == null)
        {
            found = this.createElement(binder.Name);
            this.node.AppendChild(found);
        }

        found.InnerText = value.ToString();
        return true;
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {
        if (indexes.Length != 1)
        {
            throw new InvalidOperationException("You may only specify a single index.");
        }

        XmlNode found = null;
        if (indexes[0] is string)
        {
            string name = (string)indexes[0];
            found = this.node.Attributes[name];
            if (found == null)
            {
                found = this.createElement(name);
                this.node.AppendChild(found);
            }
        }
        else if (indexes[0] is int)
        {
            int index = (int)indexes[0];
            found = this.node.Attributes[index];
        }

        if (found != null)
        {
            result = new XmlBuilder(found, this.createElement, this.createAttribute);
            return true;
        }
        else
        {
            result = null;
            return false;
        }
    }

    public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
    {
        if (indexes.Length != 1)
        {
            throw new InvalidOperationException("You may only specify a single index.");
        }

        XmlAttribute found = null;
        if (indexes[0] is string)
        {
            string name = (string)indexes[0];
            found = this.node.Attributes[name];
            if (found == null)
            {
                found = this.createAttribute(name);
                this.node.Attributes.Append(found);
            }
        }
        else if (indexes[0] is int)
        {
            int index = (int)indexes[0];
            found = this.node.Attributes[index];
        }

        if (found != null)
        {
            found.InnerText = value.ToString();
            return true;
        }
        else
        {
            return false;
        }
    }

    public override string ToString()
    {
        return this.node.InnerXml;
    }
}

MetaSharp mentioned on “M” Language Gallery

http://msdn.microsoft.com/en-us/oslo/cc749619.aspx

MetaSharp

A simple Common Language Specification (CLS)-compliant, general purpose programming language for MetaSharp, a fully extensible, pipelined transformation engine that can be used for templated textual transformations (code generation), AST transformations and any combination thereof.
Justin Chase

There are a bunch of other cool grammars and Oslo related projects on there as well. Check em’ out.

Member Exists – Dynamic C# 4.0

I have been using the dynamic keyword a little bit in C# and I have recently run into a small problem and I have been trying to figure out the most elegant way to resolve it. The problem is, when you try to invoke a member that does not exist on a dynamic object it throws an exception, there is no easy way to detect if the member exists built-in to accommodate this.

For example what I would really like is an ‘exists’ keyword, something like:

dynamic instance = new { Foo = "Hello World!" };
if (exists(instance.Foo))
{
Console.WriteLine(instance.Foo);
}

But there appears to be no magic ‘exists’. Turns out the only way to do this is with reflection. So I created some helper extension methods to enable the following example:

object instance = new { Foo = "Hello World!" };

if (instance.Reflection().Exists().Foo)
{
    string value = instance.Reflection().Call().Foo;
    Console.WriteLine(value);
}

Interestingly enough the Foo in this case is a call to a DynamicObject I created that can intercept calls to members and returns a bool if they exist, never calling them. The Reflection().Call() simply casts any object into a dynamic object for dynamic calling.

I also found out that you can’t use the dynamic Type as the first parameter in an extension method. Dynamic objects and extension methods don’t really play together very nicely.

Download the full example here:

https://onedrive.live.com/redir?resid=DFCD2D88D3FE101C%21341

Creating an internal DSL with MetaSharp

Inside of MetaSharp is a CLS compliant language using the same system and patterns that you would use to create an external DSL. One of the parts of creating your own DSL in MetaSharp is declaring Node objects to represent your parsed graph. MetaSharp will convert your parsed MGrammar graph into your strongly Typed AST (Nodes) which you can then use to transform however you wish.

Declaring your AST nodes requires a certain design pattern and after some prompting from Attila the Hun I have created a DSL specifically for creating nodes. Here it is before the DSL:

//-----------------------------------------------------------------------
// <copyright company="MetaSharp">
//     Copyright (c) MetaSharp. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace MetaSharp.Lang.Ast.Standard
{
    using System.Collections.Generic;
    using MetaSharp.Lang.Ast.Common;

    /// <summary>
    /// A foreach statement node.
    /// </summary>
    public class ForEachStatement : Statement
    {
        /// <summary>
        /// The VariableType NodeProperty.
        /// </summary>
        public static readonly NodeProperty VariableTypeProperty = 
            NodeProperty.Register<ForEachStatement>(n => n.VariableType);

        /// <summary>
        /// The VariableName NodeProperty.
        /// </summary>
        public static readonly NodeProperty VariableNameProperty = 
            NodeProperty.Register<ForEachStatement>(n => n.VariableName);

        /// <summary>
        /// The Expression NodeProperty.
        /// </summary>
        public static readonly NodeProperty ExpressionProperty = 
            NodeProperty.Register<ForEachStatement>(n => n.Expression);

        /// <summary>
        /// The Statements NodeProperty.
        /// </summary>
        public static readonly NodeProperty StatementsProperty = 
            NodeProperty.Register<ForEachStatement>(n => n.Statements);

        /// <summary>
        /// Gets the variable type.
        /// </summary>
        public TypeReference VariableType
        {
            get { return (TypeReference)this.GetValue(VariableTypeProperty); }
            set { this.SetValue(ForEachStatement.VariableTypeProperty, value); }
        }

        /// <summary>
        /// Gets the variable name.
        /// </summary>
        public string VariableName
        {
            get { return (string)this.GetValue(VariableNameProperty); }
            set { this.SetValue(ForEachStatement.VariableNameProperty, value); }
        }

        /// <summary>
        /// Gets the enumeration expression.
        /// </summary>
        public Expression Expression
        {
            get { return (Expression)this.GetValue(ExpressionProperty); }
            set { this.SetValue(ForEachStatement.ExpressionProperty, value); }
        }

        /// <summary>
        /// Gets the statements.
        /// </summary>
        public IEnumerable<Statement> Statements
        {
            get { return (IEnumerable<Statement>)this.GetValue(StatementsProperty); }
            set { this.SetValue(ForEachStatement.StatementsProperty, value); }
        }
    }
}

And here it is as a DSL:

//-----------------------------------------------------------------------
// <copyright company="MetaSharp">
//     Copyright (c) MetaSharp. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace MetaSharp.Lang.Ast.Standard:

    import System.Collections.Generic;
    import MetaSharp.Lang.Ast.Common;
    import MetaSharp.Transformation;

    /// <summary>
    /// A foreach statement node.
    /// </summary>
    node ForEachStatement as Statement:
    
        /// <summary>
        /// The VariableType NodeProperty.
        /// </summary>
        property VariableType as TypeReference;

        /// <summary>
        /// The VariableName NodeProperty.
        /// </summary>
        property VariableName as string;

        /// <summary>
        /// The Expression NodeProperty.
        /// </summary>
        property Expression as Expression;

        /// <summary>
        /// The Statements NodeProperty.
        /// </summary>
        property Statements as IEnumerable<Statement>;

    end
end

It went from 76 lines to 38, so that’s a win in my book. Plus most of the lines that are there are much shorter. The only downside is the lack of intellisense and syntax hilighting but I have reason to believe that that is a solvable problem in general if you’re using MGrammar as your parser, since it’s already possible in Intellipad.

To use this DSL all you have to do is import MetaSharp.Lang.targets into your .csproj file.

<Import Project="$(NodeBuilderBinPath)\MetaSharp.Lang.targets" />

Then in your project you simply add your items to the project as Nodes. Like so:

image

This will generate a file for you at compile time in your projects language (i.e. this should work in VB as well) and that file will get compiled along with the assembly. Next I want to build a Pipeline DSL, then the process of building your own DSL will all be done in DSLs as well!