Security idea

You know how some sites say your password has to be at least 6 characters? That's good for security in that more characters are harder to brute force.

But it's bad for security in that the most common password on the Internet is currently "123456" - just enough to fit the length requirement with pretty much no entropy at all. You could brute force usernames always using the password "123456" and probably have a pretty decent success rate.

...light bulb?

So here's an idea: Why not randomize the length limit?

"Your password must be at least {6-10} characters long."

Now you don't know whether the worst password is "123456" or "1234567890". Guessing a single password from the moron group just became 4 times harder (which isn't much, but it's getting somewhere).

This could be extended:

"Your password must be at least {6-10} characters long and contain at least {0-2} symbols and at least {0-2} uppercase letters."

Now it's 36 times harder. That's actually a meaningful difference.

NodeJS: module.exports vs exports

I read an article on the difference between module.exports and exports in NodeJS and thought I could contribute to the discussion.

The key difference between the two is that module.exports is what matters, and exports just happens to point to the same thing.

It might help clarify things to show how the two variables are initialized. Essentially before your code runs, there is code that runs like this:

var module = {…}; // other module stuff
var exports = module.exports = {};

So both variables initially point to the same empty Object, but of course can be reassigned to any other value instead. If you reassign the exports variable, it doesn’t affect module.exports. Similarly, if you reassign module.exports, it no longer affects exports. They will be pointing at different values.

It's important to note the distinction between variables and values. module.exports and exports are just variables that start out pointing to the same value. If you modify the value they both point to, for example if that value is an object and you set properties on it, then both of those variables are both affected. But if you point one of those variables at a different value, then modifying the value of one will no longer change the other.

What makes module.exports the “real deal” is that when someone require()s your module, require executes something like this:

function require(moduleName) {
    var module = getModule(moduleName);
    return module.exports;
}

require grabs the module and finds the exports property of it. So the values that matter are first whatever value module points to, and then whatever value the exports property on it points to.

It might also help to say that module is the real deal, not that module.exports is. Take this code for example:

var truth = module;
var notExports = module.exports;

truth.exports = { genre: "Rock" };
notExports.genre = "Blues";

Rock will be exported. Since truth is pointing to module, it can make lasting changes to the exports that notExports can’t. As soon as truth changes the value of module's exports property, the old value that notExports still points to is moot.

Functional NodeJS - callback composition

I've been trying to get into functional programming a bit, and just had the opportunity to create a function I haven't seen before. I also found out just how unfriendly Node's conventions can be to functional programmers.

I thought I'd share just how difficult this can get, and try to explain each step for anyone else trying to understand functional concepts.

I'll cover partial and compose which are a widely used higher order functions. Then I'll show you partialRight which I haven't seen before, and talk about how it can help you combine NodeJS-style asynchronous functions.

"partial", prior art

Most functional libraries have something called partial which is super useful. This function lets you fill in arguments left to right, without affecting the this value of the function.

Let's set up an example:

function logMyName(logger) {
    logger.log(this.name);
}

function Dog(name) {
    this.name = name;
}
Dog.prototype.print = logMyName;

Say you wanted Dog to use a version of logMyName that always logged the name using console.log.

If you were to use the built-in Function.prototype.bind in ES5, you'd be stuck.

Dog.prototype.print = logMyName.bind(?, console);

There's no good value for ? that will work, because this needs to change dynamically with the instance of Dog that calls it. You really want to use partial.

Dog.prototype.print = partial(logMyName, console);

This means the first argument, logger will be set to console, but will continue to see the correct this value when called.

var myDog = new Dog('Lassie');
myDog.print(); // logMyName.call(myDog, console)

partial, not a complete solution

I had a similar problem in NodeJS. I was looking at implementing a function that will "compose" other functions. That means it will call each function, right-to-left, with the result of the previous function.

var composed = compose(a, b, c);
composed(1) === a( b( c(1) ) );

BUT, I wanted it to work with Node-style asynchronous functions.

The async library already has this (which is awesome), but I felt like writing my own, to help me get into the functional programming swing.

Given a call like

var cThenBThenA = composeAsync(a, b, c);

I wanted to be able to call it like:

function next(err, res) {
    // callback
}
cThenBThenA(1, next);

This should be equivalent to the much more long-winded:

function next(err, res) {
    // callback
}
c(1, function(err, cRes) {
    err ?
        next(err) :
        b(cRes, function(err, bRes) {
            err ?
                next(err) :
                a(bRes, next);
        });
});

So what do we need to do to get there?

Well there are two big hurdles. The first is that tedious error handling. Notice how we manually short-circuit and call next any time we see an error? Let's write a function that handles those Node-style errors:

function handleError(errback, callback) {
    return function (err) {
        err ?
            errback(err) :
            callback.apply(this,
                [].slice.call(arguments, 1));
    };
}

This function will take in a function to call when there is an error (errback) and a function to call when there's no error (callback). It returns a function that will call whichever one is appropriate and give it the correct arguments: either just the error for errback, or everything except the error for callback.

This makes it a bit better:

function next(err, res) {
    // callback
}
c(1, handleError(next, function(cRes) {
    b(cRes, handleError(next, function(bRes) {
        a(bRes, next);
    });
});

And we can use the partial function we just learned to improve it even more, by binding the handleError function to the next callback.

function next(err, res) {
    // callback
}
var nextOnError = partial(handleError, next);
c(1, nextOnError(function(cRes) {
    b(cRes, nextOnError(function(bRes) {
        a(bRes, next);
    });
});

But even though we've removed the repetitive error-handling logic, we still have that annoying callback stack.

Notice how we need to inject a unique callback parameter at the end of each function call? This isn't something where you can use partial. The partial function only lets you specify parameters left-to-right, which means we'd have to know the arguments to pass in. For example:

function next(err, res) {
    // callback
}
var nextOnError = partial(handleError, next);

var aWithCallback = partial(a, bRes?, next);
var callA = nextOnError(aWithCallback);

var bWithCallback = partial(b, cRes?, callA);
var callB = nextOnError(bWithCallback);

c(1, callB);

This almost works - we try to bind each function to a callback. But we're tripped up with the bRes and cRes bits. We don't know those results yet, because those functions haven't been called! And we can't partially apply just the callback, because partial works left-to-right.

Enter partialRight

So I wrote a function to work like partial, but appends the arguments after the ones passed in. It looks like this:

function partialRight(fn/*, ...args*/) {
    var args = [].slice.call(arguments, 1);
    return function() {
        var firstArgs = [].slice.call(arguments);
        return fn.apply(this, 
            firstArgs.concat(args));
    };
}

Easy! Now I can inject just a callback, without knowing the other arguments bRes and cRes.

var aWithCallback = partialRight(a, next);
aWithCallback(?) === a(?, next);

So the whole chain becomes:

function next(err, res) {
    // callback
}
var nextOnError = partial(handleError, next);

var aWithCallback = partialRight(a, next);
var callA = nextOnError(aWithCallback);

var bWithCallback = partialRight(b, callA);
var callB = nextOnError(bWithCallback);

c(1, callB);

And now we're almost there! Just need to turn the manual callA and callB functions into something we can iterate over for any number of functions. We do this with a map to add the nextOnError, and a reduce to add the callbacks:

function next(err, res) {
    // callback
}
var nextOnError = partial(handleError, next);
// turn each function into a version of itself
// that is a Node-style callback.
var callFns = [a,b,c].map(nextOnError);

// connect each function to its callback,
// without knowing its other arguments
var composed = callFns.reduce(function(cb, fn) {
    return partialRight(fn, cb);
}, next);

composed(null, 1);

Notice that we now call composed with a null first. This is because we turned c into a Node-style callback as well, so we have to specify that there is no error when we call it.

So here's the composeAsync we end up with:

function composeAsync() {
    var fns = toArray(arguments);
    return function() {
        var args = toArray(arguments);
        var next = args.pop();
        var nextOnError = partial(handleError, next);
        var callFns = fns.map(nextOnError);

        var composed = callFns.reduce(function(next, fn) {
            return partialRight(fn, next);
        }, next);

        composed.apply(this, [ null ].concat(args));
    };
}

And it works!

function add1(a, next) {
    next(null, a+1);
}

function mul2(a, next) {
    next(null, a*2);
}

composeAsync(add1, mul2, add1)(1, function next(err, res) {
    console.log(res); // ((1 + 1) * 2) + 1 == 5
});

I'll write another post on why compose is cool, but I recommend checking out Brian Lonsdorf's talk which gets the message across.

Gist including all the code

Deprecating Javascript

At work I've been doing some work related to exposing and supporting a Javascript API in our app (Stash). The idea is that plugin developers could use the functions and data in our API when implementing their plugins.

It's be pretty interesting so far, and it doesn't seem like there is a lot of prior art out there for deprecating JS APIs. There are a lot of questionsto be asked.

What does it mean to deprecate?

When you deprecate a function in any language, you are saying "look, this code won't be around forever and you should stop using it ASAP, but I'll leave it in for a while to give you time to stop using it."

What does it mean to deprecate in JS?

In static languages there is a compile step. This compile step is usually used as a way to communicate the deprecation to the developers. In JS, there is no such step. Usually this means JS libraries fall back to a less useful means of indicating deprecation: documentation.

When you deprecate your code through documentation, you put burden on the users of your API. Not only do they have to read your documentation to get started using your API, now they also have to continue reading your documentation for as long as they want their code to keep working. This is a huge cost.

But there is another time you an inform the developer that your code is deprecated, and it makes it much easier for developers to know when code they use has been deprecated. That time is runtime.

How can I deprecate in JS?

Documentation is always a useful fallback. Release notes of your API should indicate what code has been deprecated.

But informing developers of deprecation at runtime means you only inform them of deprecations that might actually affect them.

Deprecating functions

Functions are easy to deprecate. You simply wrap them in a function that will call console.log() the first time it is invoked. Something like:

function deprecateFunction(fn, displayName) {
    var called = false;
    return function() {
        if (!called) {
            called = true;
            console.log('WARNING: ' +
                displayName + ' is deprecated, ' +
                'please stop using it.');
        }
        return fn.apply(this, arguments);
    };
}

And you can use it like:

var myFunc = deprecateFunction(function old() {
     // deprecated code ...
}, 'myFunc');

myFunc(); // logs the warning
myFunc(); // doesn't log

Deprecating data

In modern browsers, you can also deprecate data. You can do this with Object.defineProperty.

function deprecateData(obj, prop, displayName) {
    var val = obj[prop];
    Object.defineProperty(obj, prop, {
        get : deprecateFunction(function() {
                return val;
            }, displayName),
        set : deprecateFunction(function(newVal) {
                val = newVal;
            }, displayName)
    });
}

Object.defineProperty lets you define a "get" and "set" function for your data, so that when the variable is read, it evaluates as the value returned from "get". And when it is assigned to, the "set" function is called with the new value.

Don't forget to check that Object.defineProperty is supported. In older browsers, just don't log the deprecation. Chances are that self-respecting developers will be using modern browsers anyway. And if not, they should at least be testing in them.

var supportsProperties = false;
try {
    Object.defineProperty({}, 'blam', {
        get:function(){},
        set:function(){}
    });
    supportsProperties = true;
} catch(e){
    /*IE8 only supports properties on DOM elements.*/
}

function deprecateData(obj, prop, displayName) {
    if (supportsProperties) {
        // ...
    }
}

And then you can use it like:

var myModel = {
    someOldProperty : 'a value'
};
deprecateData(myModel, 'someOldProperty',
    'myModel.someOldProperty');

// logs a warning in modern browsers
var checkIt = myModel.someOldProperty;

And there you go! The basics down!

A useful deprecation message

So we've gotten our code to log warnings when it is used. But what if you could do more? It would really make a developer's life easy if you told them when the code stopped being valid, when it will stop working altogether, what they can use instead, and where they are currently using the wrong code.

Well the whens and the whats are easy - just add more more inputs to your deprecation methods.

function deprecateFunction(fn, displayName,
    alternateName, vSince, vRemove) {
    var called = false;
    return function() {
        if (!called) {
            called = true;
            console.log('WARNING: ' +
                displayName + ' is deprecated since ' +
                vSince + ' and will be removed in ' + 
                vRemove + '. ' +
                'Use ' + alternateName + ' instead.');
        }
        return fn.apply(this, arguments);
    };
}

function deprecateData(obj, prop, displayName,
    alternateName, vSince, vRemove) {
    var val = obj[prop];
    Object.defineProperty(obj, prop, {
        get : deprecateFunction(function() {
                return val;
            }, displayName, alternateName, vSince, vRemove),
        set : deprecateFunction(function(newVal) {
                val = newVal;
            }, displayName, alternateName, vSince, vRemove)
    });
}

Now when you call the deprecated function, you get a detailed message:

var myFunc = deprecateFunction(func,
             'myFunc', 'newFunc', '0.2.0', '1.0.0');

// logs "WARNING: myFunc is deprecated since 0.2.0
// and will be removed in 1.0.0. Use newFunc instead."
myFunc();

Sweet as! But now, how do we let the developer know where there are calling the bad code? Pretty easy in modern browsers: just use the browser's built-in stack traces by creating an Error object.

function getStackTrace() {
    return new Error().stack || 'Stacktrace not available';
}

Then log it along with the deprecation warning.

Final code

Here is the final code. For good measure, we'll stick our functions onto a single global deprecate variable as deprecate.fn and deprecate.data;

(function() {
    var supportsProperties = false;
    try {
        Object.defineProperty({}, 'blam', {
            get:function() {},
            set:function() {}
        });
        supportsProperties = true;
    } catch(e){
        /*IE8 only supports properties on DOM elements.*/
    }

    function getStackTrace() {
        return new Error().stack ||
        'Stacktrace not available';
    }

    function deprecateFunction(fn, displayName,
        alternateName, vSince, vRemove) {
        var called = false;
        return function() {
            if (!called) {
                called = true;
                console.log('WARNING: ' +
                    displayName + ' is deprecated since ' +
                    vSince + ' and will be removed in ' + 
                    vRemove + '. ' +
                    'Use ' + alternateName + ' instead.');
                console.log(getStackTrace());
            }
            return fn.apply(this, arguments);
        };
    }

    function deprecateData(obj, prop, displayName,
        alternateName, vSince, vRemove) {
        if (supportsProperties) {
            var val = obj[prop];
            Object.defineProperty(obj, prop, {
                get : deprecateFunction(function() {
                        return val;
                    }, displayName, alternateName, vSince, vRemove),
                set : deprecateFunction(function(newVal) {
                        val = newVal;
                    }, displayName, alternateName, vSince, vRemove)
            });
        }
    }

    window.deprecate = {
        fn : deprecateFunction,
        data : deprecateData
    };
}());

Escaping the Boolean Trap in JS

The Boolean Trap refers to a common mistake when writing APIs in which you use booleans as input parameters and the code becomes unreadable.

NodeJS has an example in url.parse

url.parse('example.com', true, false);

Here's an example that jQuery is looking to solve.

$('.thing').animate(...).stop(true, false);

What the hell does .stop(true, false) mean?!

Usually as caller of this API you're stuck with either the above unreadable code, or you add some extra variables in that clarify the purpose of the boolean. Something like:

var clearQueue = true, jumpToEnd = false;
$('.thing').stop(clearQueue, jumpToEnd);

But sometimes there are advantages to dynamic typing. In JS, I'm a fan of

$('.thing').stop('clearQueue', !'jumpToEnd');

Or in the Node case

url.parse('example.com', 'parseQuery', !'slashesDenoteHost');

The purpose of the parameter is clear and the value of the parameter is clear. You can clarify the type by wrapping the params with Boolean('clearQueue') or similar if it makes you feel better.

Further reading:

Wordpress: Botnet bait

Belated Update: This botnet is not unique to my wife's website. It has be ravaging any Wordpress sites it can find. You can read more at siliconrepublic.

I learned this morning that since Boxing Day, a botnet of at least 151 IP addresses has been attempting to take over my wife's Wordpress blog, Raging Cravings. After some research, I believe this is the same attack as seen by GraphiclineWeb and Perishable Press.

We discovered the hacking attempt because the hackers actually succeeded. My wife complained about her website getting a lot of 404s, so I looked into it. I immediately discovered that some spam files had been uploaded into the root of our Wordpress folder. I immediately deleted all files, restored from a recent backup (thank god for backups), and changed passwords. So how did they do it?

Lots of Wordpress (or any PHP) websites make use of a library called TimThumb for uploading and displaying thumbnails. It turns out that this library has a HUGE vulnerability that allows anyone to upload PHP code to the server and execute it. Luckily the vulnerability has long been fixed, but unfortunately the theme we were using, TrulyMinimal, had an old version of the library that was still vulnerable. I have emailed them and they say they are expecting to put out a new version that doesn't use TimThumb at all in the next couple weeks (though the vulnerability has been around for a year so it's a bit of a fail already that they're still vulnerable). In the meantime, I've updated timthumb.php locally, so this vulnerability is no longer an issue on our site.

Great! All fixed then? No, unfortunately. At the same time as they exploited timthumb, they also attempted to brute force the admin password for the blog. In the past 5 days, 151 different IP addresses have attempted to log into the blog as "admin". Why did they do this if they already had access to my server? I have no idea. It would seem they aren't that well organized.

For anyone interested, I looked into the IP addresses:

  • 103.7.56.210 (Unique, THAILAND)
  • 107.22.208.133 (Unique, UNITED STATES)
  • 108.163.128.206 (Unique, CANADA)
  • 108.163.228.218 (Unique, UNITED STATES)
  • 108.163.250.74 (Unique, UNITED STATES)
  • 108.179.218.220 (Unique, UNITED STATES)
  • 109.74.204.186 (Unique, UNITED KINGDOM)
  • 112.213.84.166 (Unique, VIET NAM)
  • 112.78.8.3 (Unique, VIET NAM)
  • 115.68.15.54 (Unique, KOREA, REPUBLIC OF)
  • 118.69.198.230 (Unique, VIET NAM)
  • 142.4.30.233 (Unique, UNITED STATES)
  • 163.43.132.41 (Unique, JAPAN)
  • 173.166.75.217 (Unique, UNITED STATES)
  • 173.193.71.176 (Unique, UNITED STATES)
  • 173.231.52.246 (Unique, UNITED STATES)
  • 173.243.113.200 (Unique, UNITED STATES)
  • 173.255.243.68 (Unique, UNITED STATES)
  • 174.120.181.179 (Unique, UNITED STATES)
  • 174.121.83.162 (Unique, UNITED STATES)
  • 176.28.11.67 (Unique, GERMANY)
  • 176.31.234.69 (Unique, FRANCE)
  • 176.9.43.178 (Unique, GERMANY)
  • 176.9.49.228 (Unique, GERMANY)
  • 178.157.80.11 (Unique, ROMANIA)
  • 178.255.225.89 (Unique, SPAIN)
  • 178.63.53.21 (Unique, GERMANY)
  • 182.50.141.162 (Unique, SINGAPORE)
  • 183.91.14.204 (Unique, VIET NAM)
  • 184.106.168.183 (Unique, UNITED STATES)
  • 184.107.237.66 (Unique, CANADA)
  • 184.170.145.10 (Unique, UNITED STATES)
  • 184.82.62.205 (Unique, UNITED STATES)
  • 188.116.32.134 (Unique, POLAND)
  • 188.132.179.34 (Unique, TURKEY)
  • 188.132.225.242 (Unique, TURKEY)
  • 188.190.98.26 (Unique, UKRAINE)
  • 188.227.182.67 (Unique, UNITED KINGDOM)
  • 188.95.251.2 (Unique, SPAIN)
  • 190.186.237.2 (Unique, BOLIVIA, PLURINATIONAL STATE OF)
  • 193.33.186.241 (Unique, UNITED KINGDOM)
  • 194.14.79.29 (Unique, SWEDEN)
  • 194.28.172.172 (Unique, UKRAINE)
  • 194.38.104.59 (Unique, HUNGARY)
  • 195.16.88.174 (Unique, UKRAINE)
  • 195.189.80.101 (Unique, BULGARIA)
  • 195.219.57.56 (Unique, SPAIN)
  • 195.22.20.231 (Unique, PORTUGAL)
  • 195.225.171.122 (Unique, ITALY)
  • 196.200.16.88 (Unique, KENYA)
  • 198.1.101.205 (Unique, UNITED STATES)
  • 198.24.141.82 (Unique, -)
  • 199.116.250.88 (Unique, UNITED STATES)
  • 199.16.130.58 (Unique, CANADA)
  • 205.204.81.100 (Unique, CANADA)
  • 206.126.97.12 (Unique, UNITED STATES)
  • 208.115.125.60 (Unique, CHINA)
  • 208.77.45.58 (Unique, UNITED STATES)
  • 209.151.224.240 (Unique, UNITED STATES)
  • 209.191.186.199 (Unique, UNITED STATES)
  • 209.191.187.104 (Unique, UNITED STATES)
  • 209.217.246.138 (Unique, UNITED STATES)
  • 212.178.198.80 (Unique, NETHERLANDS)
  • 216.238.64.58 (Unique, UNITED STATES)
  • 217.172.188.12 (Unique, GERMANY)
  • 221.132.33.130 (Unique, VIET NAM)
  • 31.210.46.106 (Unique, TURKEY)
  • 37.1.222.114 (Unique, GERMANY)
  • 37.1.223.19 (Unique, GERMANY)
  • 37.123.98.92 (Unique, TURKEY)
  • 37.59.134.60 (Unique, FRANCE)
  • 46.17.97.28 (Unique, RUSSIAN FEDERATION)
  • 46.22.211.11 (Unique, ESTONIA)
  • 46.252.193.47 (Unique, NETHERLANDS)
  • 46.32.226.96 (Unique, UNITED KINGDOM)
  • 46.32.254.132 (Unique, UNITED KINGDOM)
  • 46.45.143.50 (Unique, TURKEY)
  • 46.45.161.250 (Unique, TURKEY)
  • 46.45.169.180 (Unique, TURKEY)
  • 5.9.240.238 (Unique, GERMANY)
  • 5.9.81.50 (Unique, GERMANY)
  • 50.116.121.84 (Unique, UNITED STATES)
  • 50.22.21.114 (Unique, UNITED STATES)
  • 50.22.79.226 (Unique, UNITED STATES)
  • 50.22.91.134 (Unique, UNITED STATES)
  • 50.28.21.75 (Unique, UNITED STATES)
  • 50.57.174.146 (Unique, UNITED STATES)
  • 50.63.67.12 (Unique, UNITED STATES)
  • 50.93.197.25 (Unique, UNITED STATES)
  • 54.243.214.134 (Unique, UNITED STATES)
  • 64.207.152.84 (Unique, UNITED STATES)
  • 64.62.164.94 (Unique, UNITED STATES)
  • 64.64.14.79 (Unique, UNITED STATES)
  • 65.49.39.194 (Unique, UNITED STATES)
  • 66.135.50.49 (Unique, UNITED STATES)
  • 66.154.54.43 (Unique, UNITED STATES)
  • 66.7.203.158 (Unique, UNITED STATES)
  • 67.205.107.173 (Unique, ECUADOR)
  • 67.205.111.202 (Unique, CANADA)
  • 67.227.150.178 (Unique, UNITED STATES)
  • 67.227.238.95 (Unique, UNITED STATES)
  • 68.169.44.28 (Unique, UNITED STATES)
  • 69.162.127.133 (Unique, UNITED STATES)
  • 69.175.78.234 (Unique, UNITED STATES)
  • 69.41.174.38 (Unique, UNITED STATES)
  • 69.60.24.170 (Unique, UNITED STATES)
  • 69.64.68.159 (Unique, UNITED STATES)
  • 69.90.163.60 (Unique, CANADA)
  • 70.32.114.50 (Unique, UNITED STATES)
  • 70.32.92.169 (Unique, UNITED STATES)
  • 70.38.54.242 (Unique, CANADA)
  • 72.9.231.10 (Unique, UNITED STATES)
  • 74.117.220.10 (Unique, CAYMAN ISLANDS)
  • 74.208.64.189 (Unique, UNITED STATES)
  • 74.82.186.98 (Unique, UNITED STATES)
  • 77.81.241.197 (Unique, NETHERLANDS)
  • 78.111.80.205 (Unique, RUSSIAN FEDERATION)
  • 78.46.128.32 (Unique, GERMANY)
  • 82.194.82.102 (Unique, SPAIN)
  • 83.170.121.209 (Unique, UNITED KINGDOM)
  • 84.19.186.238 (Unique, GERMANY)
  • 84.200.20.191 (Unique, GERMANY)
  • 85.214.45.181 (Unique, GERMANY)
  • 85.25.124.220 (Unique, GERMANY)
  • 85.31.96.201 (Unique, LATVIA)
  • 87.106.133.227 (Unique, GERMANY)
  • 89.107.224.106 (Unique, TURKEY)
  • 89.223.49.163 (Unique, RUSSIAN FEDERATION)
  • 89.44.47.203 (Unique, ROMANIA)
  • 91.207.6.6 (Unique, UKRAINE)
  • 92.47.29.12 (Unique, KAZAKHSTAN)
  • 93.114.41.220 (Unique, ROMANIA)
  • 93.114.43.144 (Unique, ROMANIA)
  • 93.186.115.18 (Unique, TURKEY)
  • 94.23.250.149 (Unique, FRANCE)
  • 94.23.27.29 (Unique, FRANCE)
  • 95.173.186.127 (Unique, TURKEY)
  • 96.126.117.240 (Unique, UNITED STATES)
  • 98.126.160.18 (Unique, UNITED STATES)
  • 188.143.232.173 (Duplicate, RUSSIAN FEDERATION)
  • 188.143.232.189 (Duplicate, RUSSIAN FEDERATION)
  • 188.143.233.177 (Duplicate, RUSSIAN FEDERATION)
  • 188.143.233.2 (Duplicate, RUSSIAN FEDERATION)
  • 91.215.216.35 (Duplicate, BULGARIA)
  • 91.215.216.37 (Duplicate, BULGARIA)
  • 91.215.216.46 (Duplicate, BULGARIA)
  • 91.224.160.135 (Duplicate, NETHERLANDS)
  • 91.224.160.24 (Duplicate, NETHERLANDS)
  • 91.224.160.35 (Duplicate, NETHERLANDS)
  • 96.127.139.170 (Duplicate, UNITED STATES)
  • 96.127.139.186 (Duplicate, UNITED STATES)

Unique servers: 139 Shared servers: 12

I thought this was pretty interesting. I've never been hacked before, and I always sort of got the impression that these servers were all in Eastern Europe somewhere. But in reality, most of these compromised machines are in the US. It's a pretty diverse set, actually.

The only reason I was able to weed out these IPs from normal readers is that I'm using the WP plugin Simple Login Log which records all login attempts. So I'm able to easily grab a CSV of all login attempts on my server, the IPs, and whether they've passed or failed. There have been 3600+ attempts so far, so that would have been a pain to grab data from otherwise.

I've temporarily "solved" this issue by blocking the above ips from accessing my server. I did this by adding them to my .htaccess file:

deny from IP ADDRESS
deny from OTHER IP ADDRESS

The biggest issue here for me is that I'm not sure if or when it will end. It's quite possible this attack will last...forever. I'm not too worried because I've enabled a plugin, Limit Login Attempts that does as advertised. Also they are stupidly attempting to log in as a user that doesn't exist. So...

I've reported a few of the IPs to the whois results for them, but it doesn't scale too well (150 whois lookups will take a while).

If anyone has any advice on dealing with this sort of thing, it'd be great to hear. I've never been hacked before, so I'm not sure what methods I have for fighting back.

Meetups, JS, Robots

I just got back from another SydJS (@sydjs) which was f*ckin' awesome! I really love the JS community here in Sydney (and around the globe, really). There's something about the shared experience of Javascript that makes it really easy to strike up a conversation with a complete stranger and talk like you've been friends forever. The past few days has given me ample opportunity to experience this.

It started with JSConfAU last Thursday which is really good. I got to talk to a bunch of these "strangers" throughout the day, including some of the people I usually only get exposed to on Twitter. So that was really fun! When I go to events like this, I feel like everyone is doing their best to help everyone else succeed. The love is awesome.

The speeches were great too. When Brendan Eich talked about ES6, most of it was already available on the Internet. But it was still good hearing it all in one place in a well-organized form, and coming from a trustworthy source. He mentioned that in ES6, you might be able to override operators based on the types of its operands.

I also loved Isaacs talk about Streams in Node. Not because I particularly care about Streams in Node (they're cool, but I don't use them directly enough for it to matter), but because it was a great lesson in API design and in the value of a good API. Node contributors went through a great deal of effort to ensure backwards compatibility, which still giving a much better API in newer versions. It inspired me and I hope to offer the same stability to users of my APIs in Stash.

Then tonight's SydJS was awesome as well. Felix Geisendörfer spoke from Berlin about Nodecopter and the hassles he went through trying to control my AR Drone from 10,000 miles away. It was a really good presentation, despite a bit of flaking out on my part with audio, and the Skype call cutting out every so often. I'm so glad I bought that drone, and I'm really looking forward to playing around with it more, and getting some Node on there.

Then Dan Friedman from Ninja Blocks came on and did a similar talk to the one he did for JSConfAUwhere he live-coded some devices in Node to react to external changes (broken builds or twitter feeds). But this time went full-on and showed us how anything could be programmed to act like a block - he put some code in a browser window, and suddenly that browser was acting like a Ninja Block. It was pretty awesome, even after seeing it once already.

So after all that I really want to program some robots. I have an AR Drone, a Ninja Block, and a need to use some duplex streams. Anybody have an idea?

Making Noir Egrets, Part II: Hello blogosphere

Imagine a million lunatics wandering the streets mumbling to themselves. Write it all down and put it on the web. Congratulations, you've just created the blogosphere. - Urban Dictionary

What is true of blog content is true of blog software - every wandering lunatic has created their own blogging app at one point or another. Mostly because there are a lot of coding tutorials based around the idea of writing one.

Seeing as Noir Egrets is my personal playground, I thought it would be good to throw down some insane blogging code. ...so I did!

The tools I used were:

I gotta say, this blog platform isn't in any way competitive with real platforms out there, but I enjoyed writing it, and it works well enough for me. And in the process, I got to learn a lot about some popular technologies.

MongoDB

MongoDB has taken a lot of flak for being prone to corruption at scale. I can't really comment on that since this blog isn't popular enough to hit any corruption. I can say it's been a breeze to work with though. I can test very easily (Just need to run a local db with the mongod command). And I trialed (and eventually bought) MongoVUE which has made it really easy to inspect what's going on.

Mongoose

MongoDB is a document-store - you can put objects of any arbitrary shape into a collection. That's why I used Mongoose to add some structure. I only wanted "Post" objects in there, so I defined a Post model with mongoose.

I gotta say, I didn't really like the code that makes up Mongoose. It's very spaghetti, poorly documented, and I would guess it doesn't perform very well. But the API is pretty phenomenal. I really like how you define the types of a model's properties, especially Array properties.

var PostSchema = new Schema({
    id : String,
    tags : [ String ]
});

It's beautiful! And it's so easy to read that an id is a string and tags is an array of strings.

Markdown

I have mixed feelings about Markdown, but it's popular and it works, so I went with it. The module I choose offers a few different flavors, and seems to be fairly well written so I went with it.

Browserify

Browserify was a bit of a hack for this. I wanted to make sure my previews were WYSIWYG, so I used browserify to make sure the same code that does the conversion in the backend is used in the front-end. Consudering there aren't a lot of dependencies with Markdown, Browserify made it super easy to load it client-side.

I'm using Grunt for builds, so I quickly wrote up something to call out to browserify from a Grunt task:

grunt.registerMultiTask('browserify', 'Run browserify on a file', function() {
    //var inputs = grunt.file.expandFiles(this.file.src);
    var inputs = grunt.config(['browserify', this.target, 'src']);
    var output = grunt.config(['browserify', this.target, 'dest']);
    fs.writeFile(output, require('browserify')({
        exports: ['require'],
        require: inputs
    }).bundle(), this.async());
});

But it looks like there are other grunt-browserify solutions that have been written since then.

The downside is that the markdown rendering is now 70kB being sent to the client, but for now that's pretty meh to me. Playgrounds don't have to worry about payload. :)

Making Noir Egrets, Part I: The Middleware Way

I know I'm pretty behind the times, but I've finally gotten into NodeJS, and I'm loving it! Coming from C# (also good) and Java (not so good) backends, it's really refreshing getting all the benefits of an interpreted, dynamically-typed language like JS on the server.

Slowpoke using NodeJS thinks you've never heard of it

I'd been trying out all the stuff the cool kids get to use, and I decided I need some place to put it. I could have used GitHub or Bitbucket to host my projects, but a real geek needs a cyberplace to call their own, so I decided to write up a NodeJS-based website.

I'd heard good things about Express, so I gave that a go. I gotta say, I love the concept of middleware that is at the heart of Connect (which Express is built on). Why? Number one, because there is a phenomenal amount of reusable code. And number two, because it promotes you writing just as reusable modular code yourself.

For example, say you want to check a session cookie to see if a user is logged in. You could first make use of the existing express.cookieParser middleware to grab the keys in the cookie, then the express.session middleware to grab the express session cookie and take parameters from it:

// parse request.headers.cookie into request.cookies using a secret key for signed cookies.
app.use(express.cookieParser("Zombo.com"));

// parse the session values from request.cookies
app.use(express.session({ secret: 'happiness is self-control' }));

When you see app.use(func) that means "for every request, call func". The cool thing about it is the functions will be called in the order that you use them. So like in our example, one can rely on another when you call them in the correct order. So I can write

function checkCookie(request, response, next) {
    var user = getUserById(request.session.userId);
    if (user) {
        request.user = user;
    }
    next();
}
app.use(checkCookie);

And checkCookie will have access to the session variables that express.session parsed out for us. In this case the assumption is that I set request.session.userId and call request.session.save() when you log in, which makes the it available for all subsequent requests.

You'll notice the standard function signature for middleware. The first parameter is the request, the second parameter is the response, and the third parameter, next, is a callback. If you want to end the chain of middleware, you ignore that callback. If you want to invoke the error handler, you call it with an error argument:

next(new Error("shit.hit(fan)"))

If you just want to let the next guy have his turn, you call it with nothing.

next()

Here are some other examples of how gloriously reusable middleware can be. I've written these for Noir Egrets and other apps:

  • "flash" session storage for showing success/error messages after a redirect:

    // Anything saved in req.session.flash is removed from session, and is accessible in
    // req.flash for the next request only.
    function flash() {
        return function(req, res, next) {
            if (req.session.flash) {
                req.flash = req.session.flash;
                delete req.session.flash;
                req.session.save(next);
            } else {
                next();
            }
        };
    }
  • Allowing cross-origin access to my APIs:

    function allowCORS(req, res, next) {
        res.header('Access-Control-Allow-Origin', '*');
        next();
    }
  • or setting specific caching times:

    function cacheFor(seconds) {
        return function (req, res, next) {
            res.header('Cache-Control', 'public, max-age=' + seconds);
            next();
        };
    }

They can be used globally with app.use, or just for specific routes like:

app.get('/api/things',
    flash(),
    allowCORS,
    cacheFor(60),
function(req, res, next) {
    /* do the real work of rendering some Things. */
}); 

Middleware was by far the greatest part about trying out Express. It's an amazing concept.

first!

Having a website/blog is one of those things I've always thought I should do, but never did. So now I am. Empty for now, but the plan is to post JS-related info here that won't fit in a tweet.

I'm just happy to finally have a website!