sns-verify.sh

#!/bin/sh

if [ $# -lt 3 ]; then
  echo "usage: sns-verify.sh CERT SIG MESS"
  exit 1
fi

CERT=$1
SIG=$2
MESS=$3

PUB=`/bin/tempfile`
SIGRAW=`/bin/tempfile`

# http://sns-public-resources.s3.amazonaws.com/SNS_Message_Signing_Release_Note_Jan_25_2011.pdf
/usr/bin/openssl x509 -in $CERT -pubkey -noout > $PUB
/usr/bin/base64 -i -d $SIG > $SIGRAW
RET=`/usr/bin/openssl dgst -sha1 -verify $PUB -signature $SIGRAW $MESS`

if [ X"$RET" = X"Verified OK" ]; then
  exit 0
fi

exit 1

Tagged with:

Categorised as:


S3 client-upload parameter generation with Python

# http://aws.amazon.com/articles/1434   
def S3UploadParams(bucket_name, object_name, expiry, maxsize, redirect):
    import os, boto, json, base64, hmac, hashlib
    from time import time, gmtime, strftime

    def SignS3Upload(policy_document):
        policy = base64.b64encode(policy_document)
        return base64.b64encode(hmac.new(
                boto.config.get('Credentials', 'aws_secret_access_key'),
                policy,
                hashlib.sha1
                ).digest())

    def GenerateS3PolicyString(bucket_name, object_name, expiry, maxsize, redirect):
        policy_template = '{ "expiration": "%s", "conditions": [ {"bucket": "%s"}, ["eq", "$key", "%s"], {"acl": "private"}, {"success_action_redirect": "%s"}, ["content-length-range", 0, %s] ] }'
        return policy_template % (
            strftime("%Y-%m-%dT%H:%M:%SZ", gmtime(time() + expiry)),
            bucket_name,
            object_name,
            redirect,
            maxsize
            )
    
    params = {
        'key': object_name,
        'AWSAccessKeyId': boto.config.get('Credentials', 'aws_access_key_id'),
        'acl': 'private',
        'success_action_redirect': redirect,
        }

    policy = GenerateS3PolicyString(bucket_name, object_name, expiry, maxsize, redirect)
    params['policy'] = base64.b64encode(policy)

    signature = SignS3Upload(policy)
    params['signature'] = signature

    return params

Tagged with:

Categorised as:


KinectVision.com code

This is old, from December 2010 it seems, but it's here in case the machine goes titsup. Quick, dirty and ugly but it works most of the time. First, the capture program:

#include <libusb-1.0/libusb.h>
#include "libfreenect.h"
#include "libfreenect_sync.h"
#include <stdio.h>
#include <stdlib.h>

/*
  No error checking performed whatsoever; dealing with it later (or not).
 */
int main(int argc, char** argv)
{
  uint16_t * depth = (uint16_t *)malloc(FREENECT_DEPTH_11BIT_SIZE);
  uint32_t timestamp;
  int index = 0;
  freenect_depth_format fmt = FREENECT_DEPTH_11BIT;

  uint8_t * depth8 = (uint8_t *)malloc(FREENECT_FRAME_PIX);
  int i;

  /* Capture one Kinect depth frame */
  freenect_sync_get_depth(&depth, &timestamp, index, fmt);

  /* Convert captured frame to an 8-bit greyscale image */
  for(i = 0; i < FREENECT_FRAME_PIX; i++) {
    depth8[i] = (2048 * 256) / (2048.0 - depth[i]);
  }

  /* Write raw greyscale image to stdout  */
  fwrite(depth8, FREENECT_FRAME_PIX, 1, stdout);

  return 0;
}

Makefile:

all:		capkinect

clean:
		rm -f capkinect.o capkinect

capkinect.o:	capkinect.c
	gcc -g -I/usr/local/include/libfreenect/ -c capkinect.c -o capkinect.o

capkinect:	capkinect.o
	gcc -g capkinect.o -L/usr/local/lib/ -lfreenect_sync -o capkinect

Uploader:

#!/bin/sh

INPUT=`mktemp`
AVG=`mktemp`
TEMP=`mktemp`
OUTPUT=`mktemp --directory`

#COLORMAP="black-#45931c"
COLORMAP="black-white"

# initial average frame
capkinect | rawtopgm 640 480 | pnmcut 8 8 624 464 | pgmtoppm $COLORMAP >$AVG

while [ true ]; do

    #echo "input: $INPUT avg: $AVG temp: $TEMP output: $OUTPUT colormap: $COLORMAP"

    capkinect | rawtopgm 640 480 | pnmcut 8 8 624 464 | pgmtoppm $COLORMAP >$INPUT

    FILENAME=$OUTPUT/`date +%s.%N`

    ppmmix 0.035 $AVG $INPUT >$FILENAME.ppm

    cp $FILENAME.ppm $AVG

    cat $FILENAME.ppm | cjpeg -greyscale -quality 65 >$FILENAME.jpg

    echo "user=XXXX:AAAA" | curl --digest -K - -F "file=@$FILENAME.jpg" http://kinectvision.com/depth

    rm $FILENAME.ppm $FILENAME.jpg

    sleep 1

done

Server end script that inputs and outputs frames:

$latest_path = $_SERVER["DOCUMENT_ROOT"] . "/incoming/latest";

if($_SERVER["REQUEST_METHOD"] == "POST") {

  if(!isset($_FILES["file"]["name"])) {
    exit();
  }
  if(move_uploaded_file($_FILES["file"]["tmp_name"], $_SERVER["DOCUMENT_ROOT"] . "/incoming/" . $_FILES["file"]["name"])) {
    file_put_contents($latest_path, $_FILES["file"]["name"]);
  }

} elseif($_SERVER["REQUEST_METHOD"] == "HEAD") {

  $latest = file_get_contents($latest_path);
  header("X-KinectVision-Latest: " . $latest);

} elseif($_SERVER["REQUEST_METHOD"] == "GET") {

  $latest = $_SERVER["DOCUMENT_ROOT"] . "/incoming/" . file_get_contents($latest_path);
  header("Content-Type: image/jpeg");
  header("X-KinectVision-Latest: " . $latest);

  if(isset($_GET["width"]) && intval($_GET["width"]) < 624) {
    $width = intval($_GET["width"]);
    $f = popen("djpeg -pnm -fast -greyscale $latest | pnmscalefixed -width=$width | cjpeg -greyscale -quality 65", "r");
    while(!feof($f)) {
      echo fread($f, 1024);
    }
    fclose($f);
  } else {
    echo file_get_contents($latest);
  }

}

(Don't know if it's the Suffusion theme or what that kill all the newlines from these listings. They're there, I can assure you, they're just not visible.)

Tagged with:

Categorised as:


Backbone.js automagic syncing of Collections and Models

The idea here is to periodically fetch() and keep the client and server Collections in sync in such a way that the consuming View(s) only get updated when a Model is added to or removed from a Collection, or the attributes of one of the Models in it change. What's done is:

  • Compare the existing Collection to the incoming set and remove every Model from the existing Collection that is not in the incoming set.
  • Compare the incoming set to the existing Collection and add every Model from the incoming set to the existing Collection that is not already there.
  • Compare each Model in the two sets and update the ones in the existing Collection to the ones in the incoming set that are different.

The first two steps compare the Model's resource_uris and the last part is done with SHA1 hashes.

window.Model = Backbone.Model.extend({
    urlRoot: BASE_API + 'model/',
    defaults: {
        foo: ''
    },
    initialize: function() {
        console.log('Model->initialize()', this);
        this.bind('change', function(model) {
            console.log('Model->change()', model);
        });
    }
});
window.ModelCollection = Backbone.Collection.extend({
    model: Model,
    url: BASE_API + 'model/',
    initialize: function() {
        console.log('ModelCollection->initialize()', this);
        this.bind('add', function(model) {
            console.log('ModelCollection->add()', model);
        });
        this.bind('remove', function(model) {
            console.log('ModelCollection->remove()', model);
        });
    }
});

window.Root = Backbone.Model.extend({
    urlRoot: BASE_API + 'root/',
    defaults: {
        models: new ModelCollection()
    },
    parse: function(data) {
        var attrs = data && data.objects && ( _.isArray( data.objects ) ? data.objects[ 0 ] : data.objects ) || data;
        var model = this;
        incoming_model_uris = _.map(attrs.models, function(model) {
            return model.resource_uri;
        });
        existing_model_uris = this.get('models').map(function(model) {
            return model.get('resource_uri');
        });
        _.each(existing_model_uris, function(uri) {
            if(incoming_model_uris.indexOf(uri) == -1) {
                model.get('models').remove(model.get('models').get(uri));
            }
        });
        _.each(incoming_model_uris, function(uri) {
            if(existing_model_uris.indexOf(uri) == -1) {
                model.get('models').add(_.detect( attrs.models, function(model) { return model.resource_uri == uri; }));
            }
        });
        _.each(attrs.models, function(model) {
            if(Sha1.hash(JSON.stringify(model)) != Sha1.hash(JSON.stringify(model.get('models').get(model.resource_uri)))) {
                model.get('models').get(model.resource_uri).set(model);
            }
        });         

        delete attrs.models;        

        return attrs;
    },
    initialize: function() {
        _.bindAll(this, 'parse');
        this.fetch();
    }
});

Update 3: looking at this afterwards, I'm not sure of the complete watertightness of the above. Perhaps the Backbone Poller project would be be a better approach.

Update 2: In order to avoid borking on an empty response, do:

var attrs = Backbone.Model.prototype.parse.apply(this, data);
if(!attrs) return;

Update: My Javascript-Fu is weak which made me not see the obvious. As suggested in Backbone.js documentation, you can call the parent's implementation like this:

Backbone.Model.prototype.method.apply(this, args);

So, instead of unnecessarily copypasting behavior from Backbone-tastypie.js, we can say:

var attrs = Backbone.Model.prototype.parse.apply(this, data);

…and still have Backbone-tastypie.js do it's parsing thing for us.

Ugh.

Tagged with:

Categorised as:


Emacs and UTF-8 Encoding

From http://blog.jonnay.net/archives/820-Emacs-and-UTF-8-Encoding.html:
;;;;;;;;;;;;;;;;;;;;
;; set up unicode
(prefer-coding-system       'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
;; This from a japanese individual.  I hope it works.
(setq default-buffer-file-coding-system 'utf-8)
;; From Emacs wiki
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
;; MS Windows clipboard is UTF-16LE
(set-clipboard-coding-system 'utf-16le-dos)
Also, add this to the beginning of your source files when working with Python (otherwise you'll get "SyntaxError: Non-ASCII character '\xc3' in file…" etc. errors):
# -*- coding: utf-8 -*-

Tagged with:

Categorised as: