diff --git a/sql-edition/servers/VendServer.py b/sql-edition/servers/VendServer.py
index eff58e08755d44014cf386ba68debf6b9b9d98fb..fa5ba5b88a5a80b0c5cd23e5d75c989848047e1a 100755
--- a/sql-edition/servers/VendServer.py
+++ b/sql-edition/servers/VendServer.py
@@ -43,6 +43,7 @@ DOOR = 1
 SWITCH = 2
 KEY = 3
 TICK = 4
+MIFARE = 5
 
 
 (
@@ -55,7 +56,7 @@ STATE_GET_SELECTION,
 STATE_GRANDFATHER_CLOCK,
 ) = range(1,8)
 
-TEXT_SPEED = 0.8
+TEXT_SPEED = 0.6
 IDLE_SPEED = 0.05
 
 class DispenseDatabaseException(Exception): pass
@@ -91,8 +92,14 @@ class DispenseDatabase:
 
 def scroll_options(username, mk, welcome = False):
 	if welcome:
+	    # Balance checking: crap code, [DAA]'s fault
+	    acct = os.popen('dispense acct %s' % username)
+		balance = acct.read()[15:22]
+		acct.close()
+        
 		msg = [(center('WELCOME'), False, TEXT_SPEED),
-			   (center(username), False, TEXT_SPEED)]
+			   (center(username), False, TEXT_SPEED),
+			   (center(balance), False, TEXT_SPEED),]
 	else:
 		msg = []
 	choices = ' '*10+'CHOICES: '
@@ -157,8 +164,8 @@ def get_pin(uid):
 def has_good_pin(uid):
 	return get_pin(uid) != None
 
-def verify_user_pin(uid, pin):
-	if get_pin(uid) == pin:
+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))
 		return info.pw_name
@@ -514,45 +521,9 @@ def handle_getting_uid_key(state, event, params, v, vstatus):
 		else:
 			vstatus.mk.set_message('UID: '+vstatus.cur_user)
 	
-
-	# Easter egg for nikita's birthday -- DGB
-	if len(vstatus.cur_user) == 8:
-		if vstatus.cur_user != "07051980":
-			vstatus.mk.set_messages(
-				[(' '*9+'ONE MORE TRY NiKiTa'+' '*10, False, 3)])
-			vstatus.cur_user = ''
-			reset_idler(v, vstatus, 3)
-			return
-
-		# Do stuff here
-		vstatus.mk.set_messages(
-		[(center('                  GUILD MAILBOX NUMBER 64                  '), False, 20),
-		(center('                  GUILD MAILBOX NUMBER 64                  '), False, 20),
-		(center('                  GUILD MAILBOX NUMBER 64                  '), False, 20),
-		(center('                  GUILD MAILBOX NUMBER 64                  '), False, 20)])
-
-		# Reset
-		vstatus.cur_user = ''
-		vstatus.cur_pin = ''
-		#reset_idler(v, vstatus, 10)
-		reset_idler(v, vstatus, 2)
-		return
-	# End easter egg part 1
 	if len(vstatus.cur_user) == 5:
 		uid = int(vstatus.cur_user)
 
-		# Easter egg for nikita's birthday -- DGB
-		if vstatus.cur_user == '07051':
-			if key == 11:
-				vstatus.cur_user = ''
-				reset_idler(v, vstatus)
-				return
-#			vstatus.cur_user += chr(key + ord('0'))
-			logging.info(' == 5 dob: '+vstatus.cur_user)
-			vstatus.mk.set_message('>'+vstatus.cur_user)
-			return
-		# end easter egg part 2
-
 		if uid == 0:
 			logging.info('user '+vstatus.cur_user+' has a bad PIN')
 			pfalken="""
@@ -782,6 +753,28 @@ def handle_door_event(state, event, params, v, vstatus):
 		logging.warning('Leaving open door mode')
 		v.display("-YUM YUM!-")
 
+def handle_mifare_event(state, event, params, v, vstatus):
+	card_uid = params
+	# Translate card_id into uid.
+	vstatus.cur_user = str(card_uid)
+	vstatus.username = verify_user_pin(int(card_uid), None, True)
+	if vstatus.username:
+		v.beep(0, False)
+		vstatus.cur_selection = ''
+		vstatus.change_state(STATE_GET_SELECTION)
+		scroll_options(vstatus.username, vstatus.mk, True)
+		return
+	else:
+		v.beep(40, False)
+		vstatus.mk.set_messages(
+			[(center('BAD CARD'), False, 1.0),
+			 (center('SORRY'), False, 0.5)])
+		vstatus.cur_user = ''
+		vstatus.cur_pin = ''
+	
+		reset_idler(v, vstatus, 2)
+		return
+
 def return_to_idle(state,event,params,v,vstatus):
 	reset_idler(v, vstatus)
 
@@ -789,26 +782,32 @@ def create_state_table(vstatus):
 	vstatus.state_table[(STATE_IDLE,TICK,1)] = handle_idle_tick
 	vstatus.state_table[(STATE_IDLE,KEY,1)] = handle_idle_key
 	vstatus.state_table[(STATE_IDLE,DOOR,1)] = handle_door_event
+	vstatus.state_table[(STATE_IDLE,MIFARE,1)] = handle_mifare_event
 
 	vstatus.state_table[(STATE_DOOR_OPENING,TICK,1)] = handle_door_idle
 	vstatus.state_table[(STATE_DOOR_OPENING,DOOR,1)] = handle_door_event
 	vstatus.state_table[(STATE_DOOR_OPENING,KEY,1)] = do_nothing
+	vstatus.state_table[(STATE_DOOR_OPENING,MIFARE,1)] = do_nothing
 
 	vstatus.state_table[(STATE_DOOR_CLOSING,TICK,1)] = return_to_idle
 	vstatus.state_table[(STATE_DOOR_CLOSING,DOOR,1)] = handle_door_event
 	vstatus.state_table[(STATE_DOOR_CLOSING,KEY,1)] = do_nothing
+	vstatus.state_table[(STATE_DOOR_CLOSING,MIFARE,1)] = do_nothing
 
 	vstatus.state_table[(STATE_GETTING_UID,TICK,1)] = handle_getting_uid_idle
 	vstatus.state_table[(STATE_GETTING_UID,DOOR,1)] = do_nothing
 	vstatus.state_table[(STATE_GETTING_UID,KEY,1)] = handle_getting_uid_key
+	vstatus.state_table[(STATE_GETTING_UID,MIFARE,1)] = handle_mifare_event
 
 	vstatus.state_table[(STATE_GETTING_PIN,TICK,1)] = handle_getting_pin_idle
 	vstatus.state_table[(STATE_GETTING_PIN,DOOR,1)] = do_nothing
 	vstatus.state_table[(STATE_GETTING_PIN,KEY,1)] = handle_getting_pin_key
+	vstatus.state_table[(STATE_GETTING_PIN,MIFARE,1)] = handle_mifare_event
 
 	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_GRANDFATHER_CLOCK,TICK,1)] = handle_idle_grandfather_tick
 	vstatus.state_table[(STATE_GRANDFATHER_CLOCK,TICK,2)] = handle_grandfather_tick
@@ -816,6 +815,7 @@ def create_state_table(vstatus):
 	vstatus.state_table[(STATE_GRANDFATHER_CLOCK,DOOR,2)] = do_nothing
 	vstatus.state_table[(STATE_GRANDFATHER_CLOCK,KEY,1)] = do_nothing
 	vstatus.state_table[(STATE_GRANDFATHER_CLOCK,KEY,2)] = do_nothing
+	vstatus.state_table[(STATE_GRANDFATHER_CLOCK,MIFARE,1)] = handle_mifare_event
 
 def get_state_table_handler(vstatus, state, event, counter):
 	return vstatus.state_table[(state,event,counter)]
@@ -858,7 +858,6 @@ def run_forever(rfh, wfh, options, cf):
 			except DispenseDatabaseException, e:
 				logging.error('Database error: '+str(e))
 
-
 		timeout = time_to_next_update(vstatus)
 		e = v.next_event(timeout)
 		(event, params) = e
diff --git a/sql-edition/servers/VendingMachine.py b/sql-edition/servers/VendingMachine.py
index d73eb4beb5234ba96c27cee0fafd22cd96156a95..aca860e11152fda781953aabacb253bf2b1d1397 100644
--- a/sql-edition/servers/VendingMachine.py
+++ b/sql-edition/servers/VendingMachine.py
@@ -4,6 +4,7 @@ from CRC import do_crc
 from select import select
 import socket, logging
 from time import time, sleep
+from MIFAREClient import MIFAREClient
 
 asynchronous_responses = [	'400', '401', # door open/closed
 				'610',        # switches changed
@@ -14,6 +15,7 @@ DOOR = 1
 SWITCH = 2
 KEY = 3
 TICK = 4
+MIFARE = 5
 
 class VendingException(Exception): pass
 
@@ -35,6 +37,7 @@ class VendingMachine:
 		while code != '000':
 			code = self.get_response()[0]
 		self.get_switches()
+		self.mifare = MIFAREClient()
 
 	def await_prompt(self):
 		self.wfh.flush()
@@ -161,15 +164,31 @@ class VendingMachine:
 	def next_event(self, timeout = None):
 		# we don't want to buffer in the serial port, so we get all the events
 		# we can ASAP.
-		if timeout < 0: timeout = 0
-		if len(self.events) > 0: timeout = 0
-		while True:
-			(r, _, _) = select([self.rfh], [], [], timeout)
+
+		# Never have no timeout...
+		if timeout == None: timeout = 60*60*24*365
+
+		# Make sure we go through the loop at least once.
+		if timeout <= 0: timeout = 0.01
+
+		while timeout > 0:
+			this_timeout = min(timeout, 0.2)
+			timeout -= this_timeout
+
+			(r, _, _) = select([self.rfh], [], [], this_timeout)
 			if r:
 				self.get_response(async = True)
 				timeout = 0
-			else:
-				break
+
+			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 len(self.events) == 0: return (TICK, time())
 		ret = self.events[0]
 		del self.events[0]