LinuxTAG was interesting.. I got a better grasp of the Linux and Open Source crowd in Berlin (and in Germany in general). I think my geek-side will be satisfied there. I've decided to check out Sugar-on-a-stick after chatting to them there (and pointed one of the developers in the direction of Numptyphysics, which just may appear as a Sugar package at some point). I'm looking forward to settling down in a proper apartment again, and setting up a media center for myself - A nice ATOM dual core + NVidia (ION) server combination (TEO-X had one there) should provide all the power that I need (with lower power consumption) for XBMC & a retro (& not so retro) gaming setup. :-)
Also interesting was Büro 2.0, which involves a shared workspace and services for Open Source companies and freelancers in Berlin. If I decide to be a freelancer there, this might be an option.
— by Robert Thomson, created 30th Jun, 2009, last modified 30th Jun, 2009 | Tags: Tech
This Italian weather is killing us. We're about to step out the door and head to the mild temperature in Berlin for a week. We're taking our big suitcases, and we'll leave them there, because we will be travelling around Italy in August and we can't take so much with us. And I'm taking my laptop, since I want to work from Berlin. I plan to visit LinuxTAG during the week too.
— by Robert Thomson, created 20th Jun, 2009, last modified 20th Jun, 2009 | Tags: World
Announcing Seantis Questionnaire, a Django Questionnaire/Survey application that I developed for Seantis GmbH in Switzerland.
Features
- Multiple Questionnaires, multiple pages (QuestionSets) per questionnaire, multiple runs of same questionnaire per subject (eg. for annual surveys)
- Multilingual using the django transmeta application.
- Questions (ie. 6) & SubQuestions (ie. 6a), with appropriate layout tweaks.
- Email Invitations (direct URL to Questionnaire)
- Does _not_ require Django’s authentication system to answer questionnaires
- CSV export of answers.
- Complex dependencies utilising a full Boolean Expression Parser, and Javascript support. eg. (6a=yes and 6b=yes) OR 5=no
- Built-in Question types including:
- Open (single line), Open (text area)
- Yes/No, Yes/No/Dont Know, Yes/No/Comment
- Single Choice, Single Choice + Freeform Option
- Multiple Choice, Multiple Choice + Freeform Option(s)
- Number Range
- Time Period
- Easily extensible question types (Question Processor + Template, and Answer Processor)
- Django Signals on completion of QuestionSets and Questionnaires
- Javascript to hide irrelevant questions (works fine without Javascript too) and disable irrelevant form fields.
Talk to Seantis GmbH about custom development.
Download Seantis Questionnaire from GitHub. It is released under the same license as Django itself.
— by Robert Thomson, created 15th Jun, 2009, last modified 18th Jun, 2009 | Tags: Tech
Zope 3's Pluggable Authentication Utility doesn't automatically store a cookie saying that you're logged in if you've been authenticated once. Instead, it uses credentials and authentication plugins. For each credentials plugin, it passes the credential's output to each of the authentication plugins, and if any succeed, then it returns a Principal. It sounds logical enough, except that it does that every time, instead of storing a variable in my session stating that I'm already authenticated. Since I'll be authenticating against an external system, I didn't like the idea of checking the password on every request.. It wasn't immediately obvious to me how I could simply achieve this within the Pluggable Authentication framework, and I wasn't sure I needed the power of it anyway, so I decided to create my own IAuthentication implementation, and forget about the PAU altogether.
What it does
This implementation stores all the IPrincipal information (id, name, and description) as a signed cookie in the user's browser. By default, the session will expire after 6 hours of non-use, and the cookie's timestamp will be updated every 5 minutes with a new timestamp.
The Code
The signed string code is located in securestring.py, and the authentication code in auth.py. You also need to implement the authentication in your login form, and add it as a local utility to your application/site.
securestring.py
# coding: utf-8
import md5, random
SECRET='SomeRandomStringThatYouShouldNotShare' # CHANGE THIS
def make_sstring(question, string, r = None):
if r is None:
r = ''.join([random.choice('1234567890abcdef') for x in '12345678'])
m = md5.md5(SECRET + question + ":" + string + r)
return "%s|%s|%s" % (string, r, m.hexdigest())
def get_sstring(question, securestring):
string, r, md5 = securestring.split('|',2)
if make_sstring(question, string, r) == securestring:
return string
return False
auth.py
# coding: utf-8
from zope.app.security.interfaces import IAuthentication, IUnauthenticatedPrincipal, PrincipalLookupError, IPrincipal, ILogout
from zope import interface, schema, security
from securestring import make_sstring, get_sstring
from zope.app.component import hooks
from zope.traversing.browser.absoluteurl import absoluteURL
import time
from urllib import urlencode
class Principal(object):
interface.implements(IPrincipal)
def __init__(self, id, title, description):
self.id = id
self.title = title
self.description = description
def __str__(self):
return "<Principal: %s>" % self.title
def make_authenticated(request, principal):
id = principal.id
title = (principal.title or '').replace("::","..")
description = (principal.description or '').replace("::","..")
tm = int(time.time())
sstring = "%d::%s::%s::%s" % (tm, id, title, description)
sstring = make_sstring('z3c_sstring_login', sstring)
request.response.setCookie('z3c_sstring_login', sstring, path="/")
return principal
class SStringAuthenticator(object):
interface.implements(IAuthentication, ILogout)
loginpagename = 'login'
timeout_in_seconds = 60*60*6 # 6 hours
update_timeout = 60*5 # how often to update the cookie
def logout(self, request):
request.response.expireCookie('z3c_sstring_login', path="/")
def authenticate(self, request):
sstring = request.cookies.get('z3c_sstring_login', None)
if sstring is None:
return None
sstring = get_sstring('z3c_sstring_login', sstring)
if not sstring:
return None
try:
tm, id, title, description = sstring.split('::',3)
tm = int(tm)
now = int(time.time())
if (now - tm) < self.timeout_in_seconds:
principal = Principal(id, title, description)
if (now-tm) > self.update_timeout:
make_authenticated(request, principal)
return principal
except:
pass
def unauthenticatedPrincipal(self):
# not really sure what to do here, but it doesnt seem to hurt
return None
def unauthorized(self, id, request):
site = hooks.getSite()
stack = request.getTraversalStack()
stack.reverse()
query = request.get('QUERY_STRING')
camefrom = '/'.join([request.getURL(path_only=True)] + stack)
if query:
camefrom = camefrom + '?' + query
url = '%s/@@%s?%s' % (absoluteURL(site, request),
self.loginpagename,
urlencode({'camefrom': camefrom}))
request.response.redirect(url)
def getPrincipal(self, id):
principal = Principal(id, id, id)
interface.directlyProvides(principal, IUnauthenticatedPrincipal)
return principal
Install it as a local utility
In your application, you can add it as a local utility. Since I'm using Grok, I'll give a Grok example:
class MyApp(grok.Application)
grok.local_utility(SStringAuthenticator, provides=IAuthentication)
You could of course also provide a setup function, to modify the string.
Local Utilities will only appear on NEW objects, so your existing applications/sites won't make use of it.
Authenticate from your login form
I wasn't sure the best way to do the actual authentication here, so I thought I'd just leave it up to the login form. If successful, the login form should just call auth.make_authenticated(request, principal) where Principal is an instance of an IPrincipal (you can use auth.Principal if you like, but there's no doubt a better way).
The Alternative using Pluggable Auth
I realised afterwards that it would be possible to do the same thing within the pluggable auth framework. You could do it almost exactly the same way, except that the credentials plugin should just return the cookie if it's set (credentials just returns a dict, so you're not limited to just a login/password), and the authentication plugin can just check if it's valid. The credentials plugin can still redirect unauthorized users to a login page. http://grok.zope.org/documentation/how-to/authentication-with-grok should be able to give you an idea about how to implement Pluggable Authentication.
— by Robert Thomson, created 9th Jun, 2009, last modified 18th Jun, 2009 | Tags: Tech
My Xen server is now IPv6 enabled, and I have 4bn or so routable IPs. Yay!
And with a little bit of playing, I have IPv6 over the openvpn connection to my laptop, so now I have my very own public IPv6 network at home. And of course, yay for ip6tables!
— by Robert Thomson, created 22nd May, 2009, last modified 22nd May, 2009 | Tags: Tech
I got busy with work just after the N810 arrived, but nevertheless I’ve enjoyed having it and I find it quite a cool gadget. It’s screen is readable in all but direct sunlight, which helps to make it a great device when traveling. I found myself using it mostly as an E-Book reader when on the road, and loving Project Gutenberg and the Baen Library. I still have quite a few application ideas for it – largely revolving around making online content easily searchable and then available offline (eg. train timetable searches, hostel/hotel contact information & reviews).
As a side note, I suspect that the next device I buy will come with a PixelQi screen for it’s easy readability, low power, and versatility, but it will still be a few months until the first commercial device using it makes it to market.
I’ve developed a reasonably complex Django application for questionnaires/surveys for a medical study, which I hope to release publically in the near future, after the internal project is released. We’re still working on a name, as django-questionnaire and django-survey are both taken.
— by Robert Thomson, created 11th May, 2009, last modified 11th May, 2009 | Tags: Tech, World
I received my N810 about 3 weeks ago, and despite the fact it says "N00" instead of "N810" on the front (N00 is the normal number for prototype models from Nokia, but its internal labeling and hardware specs are that of a N810), I am quite taken with it. Surprisingly, I use it mostly as an Ebook reader (it turns out that I really enjoy reading, I just hate carrying books around). As far as Internet goes, I mostly use the weather widget, and receive email updates on it too. Maemo Mapper is quite good to have around also, when one gets lost in a city.. but the GPS doesn't work that well. One of my primary reasons for geting the device itself was that I wanted something that I could hack on and program for easily.. it certainly fits the bill. Some of the standard software release's libraries are a little old, but they're easy enough to update. Python works fine, but I'm partial to using Vala for efficiency. All I need now is a good phone and data plan to go along with it.. but I think that will have to wait until I'm settled in Germany.
On the work front, I've found some programming work with a small Swiss company. I'm currently in Luzern, enjoying the weather and the lovely water views. I miss having the water nearby.. I'm doing some Django and Zope work, and will continue working from home from next week. Sophia's coming up on Thursday and we'll meet some friends in Switzerland and see some of the sights.
— by Robert Thomson, created 7th Apr, 2009, last modified 7th Apr, 2009 | Tags: Tech
Yesterday I placed an order for the N810 Internet tablet. They've been talking about a successor to the N810 for months now (RX-51 / N900), but frankly, the N810 will probably suffice for years whether or not a new (and more expensive) model appears in the next few months.
— by Robert Thomson, created 13th Mar, 2009, last modified 13th Mar, 2009 | Tags: Tech
I’ve been playing around with Parrot again lately, since it’s approaching a 1.0 release. I’m going through the tutorials for the Parrot Compiler Toolkit, and I’m quite impressed. Sure, I keep shooting myself in the foot since I don’t understand how everything interacts yet, but it does work. I like it because it makes it easy to figure out what’s really going on and how the conversion processes work, and it seems to be reasonably well documented.
One of my longer term goals is to have a suitable nice language for MUD world programming (which assumes that the programmers can’t be trusted), and I think I’d like to modify an existing language to fulfill the requirements. Of course, having almost no idea about compiler design seriously limits how much I can tweak without wreaking havoc.
— by Robert Thomson, created 10th Mar, 2009, last modified 10th Mar, 2009 | Tags: Tech
From the website: “Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages. It is also fully interoperable with Java.”
I quite like it.. I’ve never been a fan of Java, but I have been of good VMs and their well tested highly tuned libraries. Java and the CLR being the two common ones these days. I did briefly look at the website a few months ago, but disregarded it because the funny syntax didn’t appeal to me at the time.. I shouldn’t have. I recommend the book “Programming in Scala” (available as an PDF download from the publisher Artima or from a bookshop near you) in preference to the online tutorials and documentation that exist today.
Of course, given my tendency to get bored easily, I could be learning another language next week. :-)
— by Robert Thomson, created 17th Jan, 2009, last modified 19th Jun, 2009 | Tags: Tech