""" Author: Mitchell Pomery (bobgeorge33) System to connect to OpenDispense2. Most of this code has been copied out of VendServer.py, then had variables updated so that it runs. This is so VendServer can easily operate regardless of the current accounting backend. Documentation for this code can be found inder Dispence.DispenceInterface """ from DispenseInterface import DispenseInterface import os import re import pwd from subprocess import Popen, PIPE from LDAPConnector import get_uid,get_uname, set_card_id class OpenDispense(DispenseInterface): _username = "" _disabled = True _loggedIn = False _userId = None def __init__(self, username=None, secret=False): pass def authUserIdPin(self, userId, pin): try: # Get info from info = pwd.getpwuid(int(userId)) except KeyError: logging.info('getting pin for uid %d: user not in password file'%userId) return False if info.pw_dir == None: return False pinfile = os.path.join(info.pw_dir, '.pin') try: s = os.stat(pinfile) except OSError: logging.info('getting pin for uid %d: .pin not found in home directory'%userId) return False if s.st_mode & 077: logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%userId) os.chmod(pinfile, 0600) try: f = file(pinfile) except IOError: logging.info('getting pin for uid %d: I cannot read pin file'%userId) return False pinstr = f.readline().strip() f.close() if not re.search('^[0-9]{4}$', pinstr): logging.info('getting pin for uid %d: %s not a good pin'%(userId,repr(pinstr))) return False if pinstr == str(pin): #Login Successful self._userid = userId self._loggedIn = True self._disabled = False self._username = info.pw_name return True # Login Unsuccessful return False def authMifareCard(self, cardId): # Get the users ID self._userid = get_uid(cardId) # Check for thier username try: # Get info from info = pwd.getpwuid(userId) except KeyError: logging.info('getting pin for uid %d: user not in password file'%uid) return False # If we get this far all is good self._loggedIn = True self._disabled = False self._username = info.pw_name return True def addCard(self, cardId): if self.isLoggedIn(): set_card_id(self._userId, cardId) return True def isLoggedIn(self): return self._loggedIn def getUsername(self): return self._username def getBalance(self): # Balance checking if self.isLoggedIn(): acct, unused = Popen(['dispense', 'acct', self._username], close_fds=True, stdout=PIPE).communicate() else: return None balance = acct[acct.find("$")+1:acct.find("(")].strip() return balance def getItemInfo(self, itemId): itemId = OpenDispenseMapping.vendingMachineToOpenDispense(itemId) args = ('dispense', 'iteminfo', itemId) info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate() m = re.match("\s*[a-z]+:\d+\s+(\d+)\.(\d\d)\s+([^\n]+)", info) if m == None: return("dead", 0) cents = int(m.group(1))*100 + int(m.group(2)) # return (name, price in cents) return (m.group(3), cents) def isDisabled(self): return self._disabled def dispenseItem(self, itemId): if not self.isLoggedIn() or self.getItemInfo(itemId)[0] == "dead": return False else: print('dispense -u "%s" %s'%(self._username, itemId)) #os.system('dispense -u "%s" %s'%(self._username, itemId)) return True def logOut(self): self._username = "" self._disabled = True self._loggedIn = False self._userId = None """ This class abstracts the idea of item numbers. It removes the need for VendServer to know the mappings between inputted numbers and the equivalent itemId in OpenDispense. """ class OpenDispenseMapping(): @staticmethod def vendingMachineToOpenDispense(itemId): _mappingFile = "OpenDispenseMappings.conf" fh = open(_mappingFile) map = "" for line in fh: #line = line.strip() if line.startswith(str(itemId) + " "): map = line[len(str(itemId)) + 1:].strip() print(map) return map