For my Browserling startup I decided to use Haskell to write Windows software that manages the browsers. As I haven't written much about Haskell here on catonmat before, I decided to do a small write-up on how to create a TCP server in Haskell. To keep the article simple, this TCP server will just listen on the given port on command line and execute some simple commands.

Sidenote - People often ask me how do I learn new languages. Talking about Haskell, I learned the basics from Graham Hutton's awesome book Programming in Haskell and after that asked questions in #haskell Freenode channel, and Googled a ton.

Okay, let's get started. So first we need to include the necessary functions and data constructors from Haskell libraries. This particular TCP server will use the Network library to listen on a port and accept connections, System library to get command line arguments, System.IO library to change socket handle's buffering mode, to read and write it, and Control.Concurrent library to spawn new Haskell threads.

So let's import the necessary stuff,

import Network (listenOn, withSocketsDo, accept, PortID(..), Socket)
import System (getArgs)
import System.IO (hSetBuffering, hGetLine, hPutStrLn, BufferMode(..), Handle)
import Control.Concurrent (forkIO)

Every Haskell program begins with the main function, so let's write one. Our main function will parse the port command line argument, start the server on the port, and then call sockHandler function that will accept connections and put them in a new thread,

main :: IO ()
main = withSocketsDo $ do
    args <- getArgs
    let port = fromIntegral (read $ head args :: Int)
    sock <- listenOn $ PortNumber port
    putStrLn $ "Listening on " ++ (head args)
    sockHandler sock

The withSocketsDo function is only necessary for Windows and it initializes the Windows winsock stuff.

The getArgs function returns a list of arguments that were passed on command line. For example, if we run the program as server.exe 5555, then args gets assigned a list ["5555"].

The next line converts the first element in the argument list to an Integer.

Next we start listening on the port by using listenOn. The code listenOn $ PortNumber port is just short for listenOn (PortNumber port). The dollar sign function $ allows to avoid using parenthesis.

Then we simply print a string to console which port we're listening by using putStrLn from Prelude Haskell library, which is almost always implicitly imported.

Next we call sockHandler function and pass it the sock that was returned from the listenOn function.

Now let's take a look at sockHandler function. This function takes a Socket and returns "nothing", so its type signature is sockHandler :: Socket -> IO (),

sockHandler :: Socket -> IO ()
sockHandler sock = do
    (handle, _, _) <- accept sock
    hSetBuffering handle NoBuffering
    forkIO $ commandProcessor handle
    sockHandler sock

If we look at accept function's documentation, we find that it returns a tuple of 3 elements (Handle, HostName, PortNumber). In this tutorial we are not interested in the connecting party's hostname or port, so we use _ to discard last two args. accept is a blocking call, so it will return the handle only when a new connection comes in.

Next we use hSetBuffering to change buffering mode for the client's socket handle to NoBuffering, so we didn't have buffering surprises.

Then we use forkIO to call commandProcessor function in a new Haskell thread. We do this so that we could handle more than one client connection. We'll write commandProcessor soon.

Finally we recurse and call the same sockHandler function again to handle more incoming connections. Haskell optimizes for tail recursion, so we never get stack overflows in long run.

Now let's write commandProcessor. It takes a Handle and returns IO () so its type is commandProcessor :: Handle -> IO ()

commandProcessor :: Handle -> IO ()
commandProcessor handle = do
    line <- hGetLine handle
    let cmd = words line
    case (head cmd) of
        ("echo") -> echoCommand handle cmd
        ("add") -> addCommand handle cmd
        _ -> do hPutStrLn handle "Unknown command"
    commandProcessor handle

Here we use hGetLine to get a line of text from handle, then we use the words from Prelude to split the line into words, and then we use the case statement on head of the command to find out which command was sent to the server, and call the right command function.

For example, if you send echo hello world to the server, line gets set to the string "echo hello world", then words function splits it into a list of words, ["echo", "hello", "world"], and head ["echo", "hello", "world"] is just "echo", so the echoCommand executes. Same for addCommand.

If it's an unknown command, we send the string "Unknown command" back to the client by using hPutStrLn function that writes the given string followed by a new line to the given handle.

Finally we recurse on commandProcessor so that we could execute several commands over the same connection.

Here is the echoCommand. It sends everything it receives back to the client. This function's type is Handle -> [String] -> IO (), because it takes the client socket handle, the list of command words, which are string, and returns nothing, so

echoCommand :: Handle -> [String] -> IO ()
echoCommand handle cmd = do
    hPutStrLn handle (unwords $ tail cmd)

Here hPutStrLn sends the given string to the given handle. The string in this case is unwords $ tail cmd, which is basically everything but the first word. So for example, if cmd was ["echo", "hello", "world"], then tail cmd is ["hello", "world"] and unwords ["hello", "world"] is the string "hello world".

The other command is addCommand, it takes the two numbers the client sends to it, adds them together and sends back,

addCommand :: Handle -> [String] -> IO ()
addCommand handle cmd = do
    hPutStrLn handle $ show $ (read $ cmd !! 1) + (read $ cmd !! 2)

Here we first take the second cmd !! 1 and third cmd !! 2 elements from cmd string list, then read it converts it to integers, which get added together, and then show converts the result back to a string, which gets sent back to client.

Here is the whole program, server.hs:

import Network (listenOn, withSocketsDo, accept, PortID(..), Socket)
import System (getArgs)
import System.IO (hSetBuffering, hGetLine, hPutStrLn, BufferMode(..), Handle)
import Control.Concurrent (forkIO)

main :: IO ()
main = withSocketsDo $ do
    args <- getArgs
    let port = fromIntegral (read $ head args :: Int)
    sock <- listenOn $ PortNumber port
    putStrLn $ "Listening on " ++ (head args)
    sockHandler sock

sockHandler :: Socket -> IO ()
sockHandler sock = do
    (handle, _, _) <- accept sock
    hSetBuffering handle NoBuffering
    forkIO $ commandProcessor handle
    sockHandler sock

commandProcessor :: Handle -> IO ()
commandProcessor handle = do
    line <- hGetLine handle
    let cmd = words line
    case (head cmd) of
        ("echo") -> echoCommand handle cmd
        ("add") -> addCommand handle cmd
        _ -> do hPutStrLn handle "Unknown command"
    commandProcessor handle

echoCommand :: Handle -> [String] -> IO ()
echoCommand handle cmd = do
    hPutStrLn handle (unwords $ tail cmd)

addCommand :: Handle -> [String] -> IO ()
addCommand handle cmd = do
    hPutStrLn handle $ show $ (read $ cmd !! 1) + (read $ cmd !! 2)

To use it, just run it via runhaskell server.hs 5555, and the server will start on port 5555. Or you can compile it to binary with ghc -threaded --make server.hs and then execute server binary.

And server.hs is also available for download,

Download server.hs

Download link: haskell tcp server, server.hs
Downloaded: 2857 times

This tutorial didn't cover error handling, but it's pretty easy to add through exception catching. I'll cover that in the 2nd part of the article! Until next time!

At Browserling I just solved an interesting Windows sysadmin problem of how to allow Windows users to run just a few programs and nothing else. Since anyone can use Browserling for free, I had to find a way to restrict them from downloading and running viruses and trojans. So I took time to investigate and found a very elegant solution. No one had really documented this so this blog post will be very handy for people who can't figure it out themselves.

The solution is to configure the Software Restriction Policy (SRP) in the user's Group Policy Object (GPO) and disallow the user to run everything except the programs that are necessary to login and the programs you want the user to use.

The hardest part was figuring out all the programs that the user absolutely must be allowed to run for him/her to login the system:

  • C:\Windows\explorer.exe
  • C:\Windows\System32\csrss.exe
  • C:\Windows\System32\dwm.exe
  • C:\Windows\System32\rdclip.exe
  • C:\Windows\System32\taskhost.exe
  • C:\Windows\System32\TSTheme.exe
  • C:\Windows\System32\userinit.exe

If you don't have these in the SRP, then the user will never be able to login. So make sure they are in the SRP's "Additional Rules" and their security level is "Unrestricted."

After you add these, the user will be able to login but he wont be able to run anything! He'll just see desktop and that's it. If you want to allow the user to run, let's say, Paint, then add C:\Windows\System32\paint.exe the Unrestricted Access list.

Here is a precise list of steps to take to disallow running programs. Run them from Administrator account:

1. Open up the Microsoft Management Console (Start -> Run -> mmc):

2. Select File -> Add/Remove Snap-in.

3. Select Group Policy Object.

4. Click Add.

5. Click Browse, select the user you want to configure the GPO for.

6. Click Finish, and OK. Now you'll see the tree view with "<username> Policy."

7. Navigate to User Configuration -> Windows Settings -> Security Settings -> Software Restriction Policies.

8. Right click on Software Restriction Policies and click New Software Restriction Policies.

9. Two new items will appear the tree. Click the Security Levels.

10. Double click the Disallowed security level and click "Set as Default."

11. Go to the other item, the Additional Rules.

12. Delete the crap that Windows adds there by default (%HKEY_LOCAL_MACHINE\... something).

13. Add the rules that I documented in the beginning of the article. They are absolutely necessary for the user to login into the machine (either via desktop or remote desktop).

14. Add full paths to programs that you wish to allow the user to run (such as C:\windows\system32\paint.exe, ... etc.). Make sure the users can't overwrite the programs with their own, otherwise they might be able to execute their own programs.

15. Save the GPO.

16. Done!

Thanks to lewellyn for helping out with all this!

Ps. As I like to joke, the new title of this blog soon will be "Peteris Krumins's blog on Windows Administration" as I have spent so much time during past month messing with Windows. ;)

This is going to be a small privacy tutorial on how to clear cache, cookies and history in all five major browsers - Internet Explorer, Chrome, Firefox, Opera and Safari. The techniques here work only on Windows operating system but it's not hard to transfer the techniques to other systems. The tutorial comes with Windows batch scripts for each browser. It also documents how to erase the nasty flash cookies that are browser independent.

I wrote these batch scripts for the Browserling startup that I am doing together with James Halliday. The problem was that the browsers had to be reset between consequent uses. The easiest way to solve it was to run a batch cleanup script after each browser.

Google Chrome

Chrome stores history, cookies, cache and bookmarks in various databases and directories in the per-user application data directory at C:\Users\<username>\AppData\Local\Google\Chrome\User Data. The easiest way to get rid of all this data is just to erase everything there. Chrome creates this directory anew if it finds it missing.

@echo off

set ChromeDir=C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data

del /q /s /f "%ChromeDir%"
rd /s /q "%ChromeDir%"

This simple batch script first deletes all files in %ChromeDir% directory via del command and then deletes the directory itself via rd command. The /q flag makes the del command quiet, the /s makes it delete files from all subdirectories, and /f forces it to delete read-only files, too. The /s flag to rd makes it delete all subdirectories and /q makes rd quiet.

Mozilla Firefox

Firefox stores cookies, cache and history in two places. The first is per-user appdata directory C:\Users\<username>\AppData\Local\Mozilla\Firefox\Profiles and the second place is roaming profile data directory C:\Users\<username>\AppData\Roaming\Mozilla\Firefox\Profiles. To get rid of all the private data, delete the local data directory and delete all sqlite databases from the roaming data directory.

@echo off

set DataDir=C:\Users\%USERNAME%\AppData\Local\Mozilla\Firefox\Profiles

del /q /s /f "%DataDir%"
rd /s /q "%DataDir%"

for /d %%x in (C:\Users\%USERNAME%\AppData\Roaming\Mozilla\Firefox\Profiles\*) do del /q /s /f %%x\*sqlite

The for command loops over all profile directories and deletes all the sqlite databases. You can also delete the whole roaming data directory but I didn't because Firefox stores extensions there, and there are several I use for Browserling.

Opera

Opera also stores cookies, cache and history in two different locations - the user's application data directory C:\Users\<username>\AppData\Local\Opera\Opera and the user's roaming data directory C:\Users\<username>\AppData\Roaming\Opera\Opera. Just get rid of both directories and you're safe.

@echo off

set DataDir=C:\Users\%USERNAME%\AppData\Local\Opera\Opera
set DataDir2=C:\Users\%USERNAME%\AppData\Roaming\Opera\Opera

del /q /s /f "%DataDir%"
rd /s /q "%DataDir%"

del /q /s /f "%DataDir2%"
rd /s /q "%DataDir2%"

Apple Safari

Safari also stores cookies, cache and history in two locations - the user's application data directory C:\Users\<username>\AppData\Local\Apple Computer\Safari and user's roaming data directory C:\Users\<username>\AppData\Roaming\Apple Computer\Safari

@echo off

set DataDir=C:\Users\%USERNAME%\AppData\Local\Applec~1\Safari
set DataDir2=C:\Users\%USERNAME%\AppData\Roaming\Applec~1\Safari

del /q /s /f "%DataDir%\History"
rd /s /q "%DataDir%\History"

del /q /s /f "%DataDir%\Cache.db"
del /q /s /f "%DataDir%\WebpageIcons.db"

del /q /s /f "%DataDir2%"
rd /s /q "%DataDir2%"

Microsoft Internet Explorer

Internet Explorer is much more tricker. It stores history, cookies and cache all over the place, including registry. Here is the batch script that deletes all that data from all the places:

@echo off

set DataDir=C:\Users\%USERNAME%\AppData\Local\Microsoft\Intern~1

del /q /s /f "%DataDir%"
rd /s /q "%DataDir%"

set History=C:\Users\%USERNAME%\AppData\Local\Microsoft\Windows\History

del /q /s /f "%History%"
rd /s /q "%History%"

set IETemp=C:\Users\%USERNAME%\AppData\Local\Microsoft\Windows\Tempor~1

del /q /s /f "%IETemp%"
rd /s /q "%IETemp%"

set Cookies=C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Cookies

del /q /s /f "%Cookies%"
rd /s /q "%Cookies%"

C:\bin\regdelete.exe HKEY_CURRENT_USER "Software\Microsoft\Internet Explorer\TypedURLs"

Notice that the last command is regdelete.exe. It's a small win32 utility that I wrote in c++ that erases the IE history, because it stores it in registry.

Here is the regdelete.c program:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
// compile as: mingw32-g++ regdelete.c -o regdelete.exe -mwindows

#define eq(s1,s2) (strcmp((s1),(s2))==0)

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int nCmdShow) 
{ 
    if (!cmdLine || !strlen(cmdLine)) {
        printf("Usage: regdel.exe <HKEY> <path to regkey> - be careful not to delete whole registry\n");
        return 1;
    }

    int argc;
    LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);

    if (argc < 3) {
        printf("Usage: regdel.exe <HKEY> <path to regkey> - be careful not to delete whole registry\n");
        return 1;
    }

    char **argv8 = (char **)malloc(sizeof(char *) * argc);
    for (int i = 0; i<argc; i++) {
        int len = wcslen(argv[i]);
        argv8[i] = (char *)malloc(sizeof(char)*(len+1));
        wcstombs(argv8[i], argv[i], len+1);
    }

    HKEY hkey;
    if (eq(argv8[1], "HKEY_CLASSES_ROOT")) {
        hkey == HKEY_CLASSES_ROOT;
    }
    else if (eq(argv8[1], "HKEY_CURRENT_CONFIG")) {
        hkey = HKEY_CURRENT_CONFIG;
    }
    else if (eq(argv8[1], "HKEY_CURRENT_USER")) {
        hkey = HKEY_CURRENT_USER;
    }
    else if (eq(argv8[1], "HKEY_LOCAL_MACHINE")) {
        hkey = HKEY_LOCAL_MACHINE;
    }
    else if (eq(argv8[1], "HKEY_USERS")) {
        hkey = HKEY_USERS;
    }
    else {
        printf("Unknown hkey\n");
        return 1;
    }

    HKEY key;
    int status = RegOpenKeyEx(hkey, argv8[2], 0, KEY_ALL_ACCESS, &key);
    if (status != ERROR_SUCCESS) {
        printf("failed opening %s\n", argv8[2]);
        return 1;
    }

    std::vector<std::string> vals;

    for (unsigned int i = 0; ; i++) {
        DWORD size = 1024;
        char val[size+1];
        DWORD type;
        status = RegEnumValue(key, i, val, &size, NULL, &type, NULL, NULL);
        if (status == ERROR_NO_MORE_ITEMS) break;
        if (status == ERROR_SUCCESS) {
            vals.push_back(std::string(val));
            continue;
        }
        printf("failed enumerating %s\n", argv8[2]);
        return 1;
    }

    typedef std::vector<std::string>::iterator vsi;
    for (vsi i = vals.begin(); i != vals.end(); i++) {
        status = RegDeleteValue(key, i->c_str());
        if (status != ERROR_SUCCESS) {
            printf("failed deleting %s\n", i->c_str());
            return 1;
        }
    }

    return 0;
}

Compile this source code via mingw or visual studio and you'll have the regdelete.exe program.

Flash Cookies

Flash cookies reside in C:\Users\<username>\AppData\Roaming\Macromedia\Flash Player\*. The easiest way is to get rid everything in there:

@echo off

set FlashCookies=C:\Users\%USERNAME%\AppData\Roaming\Macromedia\Flashp~1

del /q /s /f "%FlashCookies%"
rd /s /q "%FlashCookies%"

That's it. Have fun clearing that cache!

Hey guys, here are the lastest StackVM news. So we applied to Y Combinator for the Winter 2011 funding cycle but got rejected. On November 2 we got an email saying that they could not accept our application for funding, which meant that we wouldn't even get the interview. Our plan was to surprise Y Combinator folks at the interview by launching a private beta version of our software one day before the interview so that at the time we got interviewed the story was on the Hacker News front page. Well, now we can't surprise them this way, but we can surprise everyone else by saying that we are launching public beta!

Our first product is built on top of StackVM and is called Browserling. It's an interactive cross-browser testing tool inside of your browser. A real browser inside of your browser! Just go to browserling.com to try it out! (please use Chrome.)

In case there is a long queue of people willing to try Browserling, we also made a short video that shows what it is and how it works:

Browserling is a freemium based product. If you register, you get 5 mins for free for as many times as you wish (but you have to wait in the queue again with everyone else). If you don't register, it's just 1min 30secs for as many times as you wish. We haven't figured out the paid plans yet, but we'll get there shortly.

As Browserling is beta, we currently provide Internet Explorer versions 5.5, 6, 7, 8, and 9, (version 5.5, 6, 7, 8 via IETester, and version 9 is native IE), Chrome, Firefox, Safari and Opera.

Browserling is also just the first of many projects that we'll be launching. The next one is going to bring arbitrary desktop applications to the web, and then we have a whole bunch more planned. All these projects will be based on the StackVM technology!

If you're interested in how all of this develops, please subscribe to my blog and follow me on Twitter!

Also, if you use IRC, join #stackvm channel on irc.freenode.net and have fun with us!

I wrote an awesome node.js module for use at StackVM - a module called node-lazy that does lazy list processing through events!

It comes really handy when you need to treat a stream of events like a list. The best use case currently is returning a lazy list from an asynchronous function, and having data pumped into it via events. In asynchronous programming you can't just return a regular list because you don't yet have data for it. The usual solution so far has been to provide a callback that gets called when the data is available. But doing it this way you lose the power of chaining functions and creating pipes, which leads to not that nice interfaces. (See the 2nd example below to see how it improved the interface in one of my modules.)

Check out this toy example:

var Lazy = require('lazy');

var lazy = new Lazy;
lazy
  .filter(function (item) {
    return item % 2 == 0
  })
  .take(5)
  .map(function (item) {
    return item*2;
  })
  .join(function (xs) {
    console.log(xs);
  });

This code says that lazy is going to be a lazy list that filters even numbers, takes first five of them, then multiplies all of them by 2, and then calls the join function (think of join as in threads) on the final list.

And now you can emit data events with data in them at some point later,

[0,1,2,3,4,5,6,7,8,9,10].forEach(function (x) {
  lazy.emit('data', x);
});

The output will be produced by the join function, which will output the expected [0, 4, 8, 12, 16].

And here is a real-world example. Some time ago I wrote a hash database for node.js called node-supermarket (think of key-value store except greater). Now it had a similar interface as a list, you could .forEach on the stored elements, .filter them, etc. But being asynchronous in nature it lead to the following code, littered with callbacks and temporary lists:

var Store = require('supermarket');

var db = new Store({ filename : 'users.db', json : true });

var users_over_20 = [];
db.filter(
  function (user, meta) {
    // predicate function
    return meta.age > 20;
  },
  function (err, user, meta) {
    // function that gets executed when predicate is true
    if (users_over_20.length < 5)
      users_over_20.push(meta);
  },
  function () {
    // done function, called when all records have been filtered

    // now do something with users_over_20
  }
)

This code selects first five users who are over 20 years old and stores them in users_over_20.

But now we changed the node-supermarket interface to return lazy lists, and the code became:

var Store = require('supermarket');

var db = new Store({ filename : 'users.db', json : true });

db.filter(function (user, meta) {
    return meta.age > 20;
  })
  .take(5)
  .join(function (xs) {
    // xs contains the first 5 users who are over 20!
  });

This is so much nicer!

If you wish to try node-lazy just do npm install lazy! Alternatively, if you don't have npm, you can git clone http://github.com/pkrumins/node-lazy.git and set your NODE_PATH environment variable to point to that directory.

Enjoy and follow the future node-lazy developments in its github repo - node-lazy at github!

Article Sponsors

None!

Want to sponsor my future (or past) articles? Contact me for prices and options!