Article JCVQ CodeSOD: Foxy Checksum

CodeSOD: Foxy Checksum

by
Remy Porter
from The Daily WTF on (#JCVQ)

Pavel D inherited some" we'll call it "software"" that helps run warehouse operations for a boiler/heating manufacturer. That software was a Visual FoxPro database.

Now, this application needs to read barcodes off of products in the warehouse. Since the laser-scanners can sometimes mis-read those barcodes, the database uses a custom check-sum algorithm.

FUNCTION GetCheckSum LPARAMETERS lcSerNum LOCAL lnCalcSum, lnI, lcCheckSum m.lnCalcSum=0 FOR lnI=1 TO LEN( m.lcSerNum ) DO CASE CASE SUBSTR(m.lcSerNum, m.lnI,1)= ' ' m.lnCalcSum= m.lnCalcSum+0*m.lnI CASE SUBSTR(m.lcSerNum, m.lnI,1)= '!' m.lnCalcSum= m.lnCalcSum+1*m.lnI CASE SUBSTR(m.lcSerNum, m.lnI,1)= '"' m.lnCalcSum= m.lnCalcSum+2*m.lnI CASE SUBSTR(m.lcSerNum, m.lnI,1)= '#' m.lnCalcSum= m.lnCalcSum+3*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='$' m.lnCalcSum=m.lnCalcSum+4*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='%' m.lnCalcSum=m.lnCalcSum+5*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='&' m.lnCalcSum=m.lnCalcSum+6*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)="'" m.lnCalcSum=m.lnCalcSum+7*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='(' m.lnCalcSum=m.lnCalcSum+8*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)=')' m.lnCalcSum=m.lnCalcSum+9*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='*' m.lnCalcSum=m.lnCalcSum+10*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='+' m.lnCalcSum=m.lnCalcSum+11*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)=',' m.lnCalcSum=m.lnCalcSum+12*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='-' m.lnCalcSum=m.lnCalcSum+13*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='.' m.lnCalcSum=m.lnCalcSum+14*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='/' m.lnCalcSum=m.lnCalcSum+15*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='0' m.lnCalcSum=m.lnCalcSum+16*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='1' m.lnCalcSum=m.lnCalcSum+17*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='2' m.lnCalcSum=m.lnCalcSum+18*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='3' m.lnCalcSum=m.lnCalcSum+19*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='4' m.lnCalcSum=m.lnCalcSum+20*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='5' m.lnCalcSum=m.lnCalcSum+21*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='6' m.lnCalcSum=m.lnCalcSum+22*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='7' m.lnCalcSum=m.lnCalcSum+23*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='8' m.lnCalcSum=m.lnCalcSum+24*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='9' m.lnCalcSum=m.lnCalcSum+25*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)=':' m.lnCalcSum=m.lnCalcSum+26*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)=';' m.lnCalcSum=m.lnCalcSum+27*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='<' m.lnCalcSum=m.lnCalcSum+28*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='=' m.lnCalcSum=m.lnCalcSum+29*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='>' m.lnCalcSum=m.lnCalcSum+30*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='?' m.lnCalcSum=m.lnCalcSum+31*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='@' m.lnCalcSum=m.lnCalcSum+32*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='A' m.lnCalcSum=m.lnCalcSum+33*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='B' m.lnCalcSum=m.lnCalcSum+34*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='C' m.lnCalcSum=m.lnCalcSum+35*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='D' m.lnCalcSum=m.lnCalcSum+36*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='E' m.lnCalcSum=m.lnCalcSum+37*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='F' m.lnCalcSum=m.lnCalcSum+38*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='G' m.lnCalcSum=m.lnCalcSum+39*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='H' m.lnCalcSum=m.lnCalcSum+40*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='I' m.lnCalcSum=m.lnCalcSum+41*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='J' m.lnCalcSum=m.lnCalcSum+42*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='K' m.lnCalcSum=m.lnCalcSum+43*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='L' m.lnCalcSum=m.lnCalcSum+44*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='M' m.lnCalcSum=m.lnCalcSum+45*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='N' m.lnCalcSum=m.lnCalcSum+46*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='O' m.lnCalcSum=m.lnCalcSum+47*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='P' m.lnCalcSum=m.lnCalcSum+48*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='Q' m.lnCalcSum=m.lnCalcSum+49*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='R' m.lnCalcSum=m.lnCalcSum+50*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='S' m.lnCalcSum=m.lnCalcSum+51*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='T' m.lnCalcSum=m.lnCalcSum+52*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='U' m.lnCalcSum=m.lnCalcSum+53*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='V' m.lnCalcSum=m.lnCalcSum+54*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='W' m.lnCalcSum=m.lnCalcSum+55*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='X' m.lnCalcSum=m.lnCalcSum+56*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='Y' m.lnCalcSum=m.lnCalcSum+57*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='Z' m.lnCalcSum=m.lnCalcSum+58*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='[' m.lnCalcSum=m.lnCalcSum+59*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='\' m.lnCalcSum=m.lnCalcSum+60*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)=']' m.lnCalcSum=m.lnCalcSum+61*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='^' m.lnCalcSum=m.lnCalcSum+62*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='_' m.lnCalcSum=m.lnCalcSum+63*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='`' m.lnCalcSum=m.lnCalcSum+64*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='a' m.lnCalcSum=m.lnCalcSum+65*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='b' m.lnCalcSum=m.lnCalcSum+66*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='c' m.lnCalcSum=m.lnCalcSum+67*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='d' m.lnCalcSum=m.lnCalcSum+68*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='e' m.lnCalcSum=m.lnCalcSum+69*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='f' m.lnCalcSum=m.lnCalcSum+70*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='g' m.lnCalcSum=m.lnCalcSum+71*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='h' m.lnCalcSum=m.lnCalcSum+72*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='i' m.lnCalcSum=m.lnCalcSum+73*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='j' m.lnCalcSum=m.lnCalcSum+74*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='k' m.lnCalcSum=m.lnCalcSum+75*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='l' m.lnCalcSum=m.lnCalcSum+76*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='m' m.lnCalcSum=m.lnCalcSum+77*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='n' m.lnCalcSum=m.lnCalcSum+78*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='o' m.lnCalcSum=m.lnCalcSum+79*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='p' m.lnCalcSum=m.lnCalcSum+80*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='q' m.lnCalcSum=m.lnCalcSum+81*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='r' m.lnCalcSum=m.lnCalcSum+82*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='s' m.lnCalcSum=m.lnCalcSum+83*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='t' m.lnCalcSum=m.lnCalcSum+84*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='u' m.lnCalcSum=m.lnCalcSum+85*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='v' m.lnCalcSum=m.lnCalcSum+86*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='w' m.lnCalcSum=m.lnCalcSum+87*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='x' m.lnCalcSum=m.lnCalcSum+88*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='y' m.lnCalcSum=m.lnCalcSum+89*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='z' m.lnCalcSum=m.lnCalcSum+90*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='{' m.lnCalcSum=m.lnCalcSum+91*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='|' m.lnCalcSum=m.lnCalcSum+92*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='}' m.lnCalcSum=m.lnCalcSum+93*m.lnI CASE SUBSTR(m.lcSerNum,m.lnI,1)='~' m.lnCalcSum=m.lnCalcSum+94*m.lnI ENDCASE ENDFOR m.lcCheckSum = RIGHT(STR(m.lnCalcSum,7,0),1) RETURN m.lcCheckSumENDFUNC

Now, the obvious issue here is that the entire "CASE" statement could be replaced with a call to "ASC", which returns the ASCII code for a given character , but as Pavel notes, "the value of a character at position which equals a multiple of 10 is ignored".

Pavel was tasked with reimplementing this in Python, and after a little thought, recreated the function in a much more concise fashion:

def validate(sn): checksum = 0 for i, x in enumerate(sn[:-1]): checksum += (i + 1) * (ord(x) - 32) return str(checksum % 10) == sn[-1]
puppetlabs50.png[Advertisement] Manage IT infrastructure as code across all environments with Puppet. Puppet Enterprise now offers more control and insight, with role-based access control, activity logging and all-new Puppet Apps. Start your free trial today! TheDailyWtf?d=yIl2AUoC8zA-9WcHR-i8tk
External Content
Source RSS or Atom Feed
Feed Location http://syndication.thedailywtf.com/TheDailyWtf
Feed Title The Daily WTF
Feed Link http://thedailywtf.com/
Reply 0 comments