diff --git a/sql-edition/servers/VendServer.py b/sql-edition/servers/VendServer.py
index fa5ba5b88a5a80b0c5cd23e5d75c989848047e1a..f68cf1a93bfafa272e9ebf530caf08b84e6a514f 100755
--- a/sql-edition/servers/VendServer.py
+++ b/sql-edition/servers/VendServer.py
@@ -2,6 +2,7 @@
 # vim:ts=4
 
 USE_DB = 0
+USE_MIFARE = 1
 
 import ConfigParser
 import sys, os, string, re, pwd, signal, math, syslog
@@ -20,6 +21,7 @@ from Idler import GreetingIdler,TrainIdler,GrayIdler,StringIdler,ClockIdler,Fort
 from SnackConfig import get_snacks, get_snack
 import socket
 from posix import geteuid
+from LDAPConnector import get_uid, set_card_id
 
 CREDITS="""
 This vending machine software brought to you by:
@@ -56,7 +58,7 @@ STATE_GET_SELECTION,
 STATE_GRANDFATHER_CLOCK,
 ) = range(1,8)
 
-TEXT_SPEED = 0.6
+TEXT_SPEED = 0.8
 IDLE_SPEED = 0.05
 
 class DispenseDatabaseException(Exception): pass
@@ -167,7 +169,10 @@ def has_good_pin(uid):
 def verify_user_pin(uid, pin, skip_pin_check=False):
 	if skip_pin_check or get_pin(uid) == pin:
 		info = pwd.getpwuid(uid)
-		logging.info('accepted pin for uid %d (%s)'%(uid,info.pw_name))
+		if skip_pin_check:
+			logging.info('accepted mifare for uid %d (%s)'%(uid,info.pw_name))
+		else:
+			logging.info('accepted pin for uid %d (%s)'%(uid,info.pw_name))
 		return info.pw_name
 	else:
 		logging.info('refused pin for uid %d'%(uid))
@@ -754,10 +759,17 @@ def handle_door_event(state, event, params, v, vstatus):
 		v.display("-YUM YUM!-")
 
 def handle_mifare_event(state, event, params, v, vstatus):
-	card_uid = params
+	card_id = params
 	# Translate card_id into uid.
-	vstatus.cur_user = str(card_uid)
-	vstatus.username = verify_user_pin(int(card_uid), None, True)
+	if card_id == None:
+		return
+
+	try:
+		vstatus.cur_user = get_uid(card_id)
+		logging.info('Mapped card id to uid %s'%vstatus.cur_user)
+		vstatus.username = verify_user_pin(int(vstatus.cur_user), None, True)
+	except ValueError:
+		vstatus.username = None
 	if vstatus.username:
 		v.beep(0, False)
 		vstatus.cur_selection = ''
@@ -775,6 +787,32 @@ def handle_mifare_event(state, event, params, v, vstatus):
 		reset_idler(v, vstatus, 2)
 		return
 
+def handle_mifare_add_user_event(state, event, params, v, vstatus):
+ 	card_id = params
+
+	# Translate card_id into uid.
+	if card_id == None:
+		return
+
+	try:
+		if get_uid(card_id) != None:
+			vstatus.mk.set_messages(
+				[(center('ALREADY'), False, 0.5),
+				 (center('ENROLLED'), False, 0.5)])
+
+			# scroll_options(vstatus.username, vstatus.mk)
+			return
+	except ValueError:
+		pass
+
+	logging.info('Enrolling card %s to uid %s (%s)'%(card_id, vstatus.cur_user, vstatus.username))
+	set_card_id(vstatus.cur_user, card_id)
+	vstatus.mk.set_messages(
+		[(center('CARD'), False, 0.5),
+		 (center('ENROLLED'), False, 0.5)])
+
+	# scroll_options(vstatus.username, vstatus.mk)
+
 def return_to_idle(state,event,params,v,vstatus):
 	reset_idler(v, vstatus)
 
@@ -807,7 +845,7 @@ def create_state_table(vstatus):
 	vstatus.state_table[(STATE_GET_SELECTION,TICK,1)] = handle_get_selection_idle
 	vstatus.state_table[(STATE_GET_SELECTION,DOOR,1)] = do_nothing
 	vstatus.state_table[(STATE_GET_SELECTION,KEY,1)] = handle_get_selection_key
-	vstatus.state_table[(STATE_GET_SELECTION,MIFARE,1)] = do_nothing
+	vstatus.state_table[(STATE_GET_SELECTION,MIFARE,1)] = handle_mifare_add_user_event
 
 	vstatus.state_table[(STATE_GRANDFATHER_CLOCK,TICK,1)] = handle_idle_grandfather_tick
 	vstatus.state_table[(STATE_GRANDFATHER_CLOCK,TICK,2)] = handle_grandfather_tick
@@ -829,7 +867,7 @@ def time_to_next_update(vstatus):
 	return idle_update
 
 def run_forever(rfh, wfh, options, cf):
-	v = VendingMachine(rfh, wfh)
+	v = VendingMachine(rfh, wfh, USE_MIFARE)
 	vstatus = VendState(v)
 	create_state_table(vstatus)
 
@@ -891,6 +929,8 @@ def connect_to_vend(options, cf):
 		sock.connect((options.host, options.port))
 		rfh = sock.makefile('r')
 		wfh = sock.makefile('w')
+		global USE_MIFARE
+		USE_MIFARE = 0
 		
 	return rfh, wfh
 
diff --git a/sql-edition/servers/VendingMachine.py b/sql-edition/servers/VendingMachine.py
index aca860e11152fda781953aabacb253bf2b1d1397..b7d747aeb5ed1a8755717cbb1a9917ec62cd25ec 100644
--- a/sql-edition/servers/VendingMachine.py
+++ b/sql-edition/servers/VendingMachine.py
@@ -20,7 +20,7 @@ MIFARE = 5
 class VendingException(Exception): pass
 
 class VendingMachine:
-	def __init__(self, rfh, wfh):
+	def __init__(self, rfh, wfh, use_mifare):
 		self.events = []
 		# Secret
 		self.secret = 'SN4CKZ0RZZZZZZZZ'
@@ -37,7 +37,11 @@ class VendingMachine:
 		while code != '000':
 			code = self.get_response()[0]
 		self.get_switches()
-		self.mifare = MIFAREClient()
+		if use_mifare:
+			self.mifare = MIFAREClient()
+			self.mifare_timeout = 0
+		else:
+			self.mifare = None
 
 	def await_prompt(self):
 		self.wfh.flush()
@@ -169,9 +173,9 @@ class VendingMachine:
 		if timeout == None: timeout = 60*60*24*365
 
 		# Make sure we go through the loop at least once.
-		if timeout <= 0: timeout = 0.01
+		if timeout < 0: timeout = 0
 
-		while timeout > 0:
+		while timeout >= 0:
 			this_timeout = min(timeout, 0.2)
 			timeout -= this_timeout
 
@@ -180,14 +184,17 @@ class VendingMachine:
 				self.get_response(async = True)
 				timeout = 0
 
-			try:
-				mifare_uid = self.mifare.get_card_uid()
-			except ValueError:
-				mifare_uid = None
-			if mifare_uid != None:
-				logging.info('Got MIFARE uid %s'%(str(mifare_uid)))
-				self.events.append((MIFARE, mifare_uid))
-				timeout = 0
+			if self.mifare:
+				now = time()
+				if now > self.mifare_timeout:
+					self.mifare_timeout = now + 0.5
+					mifare_uid = self.mifare.get_card_id()
+					if mifare_uid != None:
+						logging.info('Got MIFARE card id %s'%(str(mifare_uid)))
+						self.events.append((MIFARE, mifare_uid))
+						timeout = 0
+			if timeout == 0:
+				break
 
 		if len(self.events) == 0: return (TICK, time())
 		ret = self.events[0]