+ -- token-create-time / master-token crc
+ for i=0, #tag.MTC do
+ table.insert(bytes, tag.MTC[i])
+ end
+ -- process segments
+ if (type(tag.SEG[0])=='table') then
+ for i=0, #tag.SEG do
+ for i2=1, #tag.SEG[i].raw+1 do
+ table.insert(bytes, #bytes+1, tag.SEG[i].raw[i2])
+ end
+ table.insert(bytes, #bytes+1, tag.SEG[i].crc)
+ for i2=0, #tag.SEG[i].data-1 do
+ table.insert(bytes, #bytes+1, tag.SEG[i].data[i2])
+ end
+ end
+ end
+ -- fill with zeros
+ for i=#bytes+1, 1024 do
+ table.insert(bytes, i, '00')
+ end
+ return bytes
+ end
+ return oops("tag is no table in tagToBytes ("..type(tag)..")")
+end
+
+--- PM3 I/O ---
+---
+-- read from pm3 into virtual-tag
+function readFromPM3()
+ local tag, bytes, infile
+ infile="legic.temp"
+ core.console("hf legic reader")
+ core.console("hf legic save "..infile)
+ tag=readFile(infile)
+ return tag
+end
+
+---
+-- write virtual Tag to real Tag
+function writeToTag(tag)
+ local bytes
+ local filename='MylegicClone.hex'
+ local taglen=22
+ if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then
+ return
+ end
+ -- get used bytes / tag-len
+ if(istable(tag.SEG)) then
+ if (istable(tag.Bck)) then
+ for i=0, #tag.SEG do
+ taglen=taglen+tag.SEG[i].len+5
+ end
+ end
+ local uid_old=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
+ -- read new tag into memory so we can xor the new data with the new MCC
+ outTAG=readFromPM3()
+ outbytes=tagToBytes(outTAG)
+ -- copy 'inputbuffer' to 'outputbuffer'
+ tag.MCD = outbytes[1]
+ tag.MSN0 = outbytes[2]
+ tag.MSN1 = outbytes[3]
+ tag.MSN2 = outbytes[4]
+ tag.MCC = outbytes[5]
+ -- recheck all segments-crc/kghcrc (only on a credential)
+ if(istable(tag.Bck)) then
+ checkAllSegCrc(tag)
+ checkAllKghCrc(tag)
+ local uid_new=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
+ for i=0, #tag.SEG do
+ if (check43rdPartyCash1(uid_old, tag.SEG[i].data)) then
+ io.write(accyan.."\nfixing known checksums"..acoff.." ... ")
+ if (fix3rdPartyCash1(uid_new, tag.SEG[i].data)) then
+ io.write(acgreen.." done\n"..acoff)
+ else oops("\nsomething went wrong at the repair of the 3rd-party-cash-segment") end
+ end
+ end
+ end
+ bytes=tagToBytes(tag)
+ -- master-token-crc
+ if (tag.Type~="SAM") then bytes[22]=calcMtCrc(bytes) end
+ if (bytes) then
+ print("write temp-file '"..filename.."'")
+ print(accyan)
+ writeFile(bytes, filename)
+ --writeToTag(bytes, taglen, 'MylegicClone.hex')
+ print(acoff)
+ end
+ end
+ -- write data to file
+ if (taglen > 0) then
+ WriteBytes = utils.input(acyellow.."enter number of bytes to write?"..acoff, taglen)
+ -- load file into pm3-buffer
+ if (type(filename)~="string") then filename=input(acyellow.."filename to load to pm3-buffer?"..acoff,"legic.temp") end
+ cmd = 'hf legic load '..filename
+ core.console(cmd)
+ -- write pm3-buffer to Tag
+ for i=0, WriteBytes do
+ if ( i<5 or i>6) then
+ cmd = ('hf legic write 0x%02x 0x01'):format(i)
+ core.console(cmd)
+ --print(cmd)
+ elseif (i == 6) then
+ -- write DCF in reverse order (requires 'mosci-patch')
+ cmd = 'hf legic write 0x05 0x02'
+ print(acgreen..cmd..acoff)
+ core.console(cmd)
+ --print(cmd)
+ else
+ print(acgreen.."skip byte 0x05 - will be written next step"..acoff)
+ end
+ utils.Sleep(0.2)
+ end
+ end
+end
+
+--- File I/O ---
+---
+-- read file into virtual-tag
+function readFile(filename)
+ print(accyan)
+ local bytes = {}
+ local tag = {}
+ if (file_check(filename)==false) then
+ return oops("input file: "..filename.." not found")
+ else
+ bytes = getInputBytes(filename)
+ if (bytes == false) then return oops('couldnt get input bytes')
+ else
+ -- make plain bytes
+ bytes = xorBytes(bytes,bytes[5])
+ print("create virtual tag from ".. #bytes .. " bytes")
+ -- create Tag for plain bytes
+ tag=createTagTable()
+ -- load plain bytes to tag-table
+ print(acoff)
+ tag=bytesToTag(bytes, tag)
+ end
+ end
+ return tag
+end
+
+---
+-- write bytes to file
+function writeFile(bytes, filename)
+ if (filename~='MylegicClone.hex') then
+ if (file_check(filename)) then
+ local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?")
+ if (answer==false) then return print("user abort") end
+ end
+ end
+ local line
+ local bcnt=0
+ local fho,err = io.open(filename, "w")
+ if err then oops("OOps ... faild to open output-file ".. filename) end
+ bytes=xorBytes(bytes, bytes[5])
+ for i = 1, #bytes do
+ if (bcnt == 0) then
+ line=bytes[i]
+ elseif (bcnt <= 7) then
+ line=line.." "..bytes[i]
+ end
+ if (bcnt == 7) then
+ -- write line to new file
+ fho:write(line.."\n")
+ -- reset counter & line
+ bcnt=-1
+ line=""
+ end
+ bcnt=bcnt+1
+ end
+ fho:close()
+ print("\nwrote ".. #bytes .." bytes to " .. filename)
+ return true
+end
+
+--- Map related ---
+---
+-- make tagMap
+function makeTagMap()
+ local tagMap={}
+ if (#tagMap==0) then
+ tagMap['name']=input(accyan.."enter Name for this Map: "..acoff , "newTagMap")
+ tagMap['mappings']={}
+ tagMap['crc8']={}
+ -- insert fixed Tag-CRC
+ table.insert(tagMap.crc8, {name='TAG-CRC', pos=5, seq={1, 4}})
+ tagMap['crc16']={}
+ end
+ print(accyan.."new tagMap created"..acoff)
+ return tagMap
+end
+
+---
+-- save mapping to file
+function saveTagMap(map, filename)
+ if (string.len(filename)>0) then
+ if (file_check(filename)) then
+ local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?")
+ if (answer==false) then return print("user abort") end
+ end
+ end
+
+ local line
+ local fho,err = io.open(filename, "w")
+ if err then oops("OOps ... faild to open output-file ".. filename) end
+
+ -- write line to new file
+ for k, v in pairs(map) do
+ if (istable(v)) then
+ for k2, v2 in pairs(v) do
+ if (k=='mappings') then
+ fho:write(k..","..k2..","..v2['name']..","..v2['start']..","..v2['end']..","..((v2['highlight']) and "1" or "0").."\n")
+ elseif (k=="crc8") then
+ local tmp=""
+ tmp=k..","..k2..","..v2['name']..","..v2['pos']..","
+ tmp=tmp..tbl2seqstr(v2['seq'])
+ fho:write(tmp.."\n")
+ end
+ end
+ else
+ fho:write(k..","..v.."\n")
+ end
+ end
+ fho:close()
+ return true
+end
+
+---
+-- toggle higligh
+function toggleHighlight(tbl)
+ if (tbl['highlight']) then tbl['highlight']=false
+ else tbl['highlight']=true end
+ return tbl
+end
+
+---
+-- return table od seqence-string
+function seqstr2tbl(seqstr)
+ local s=split(seqstr)
+ local res={}
+ if (#s>=1) then
+ for sk, sv in pairs(s) do
+ s2=split(sv, '-')
+ if(#s2==2) then
+ table.insert(res, s2[1])
+ table.insert(res, s2[2])
+ end
+ end
+ end
+ return res
+end
+
+---
+-- return sequence-string from table
+function tbl2seqstr(seqtbl)
+ local res=""
+ if (istable(seqtbl)) then
+ for sk, sv in pairs(seqtbl) do
+ res=res..sv..((sk%2==0) and "," or "-")
+ end
+ if (string.sub(res, string.len(res))==",") then
+ res=string.sub(res, 1, string.len(res)-1)
+ end
+ end
+ return res
+end
+
+---
+-- read map-file into map
+function loadTagMap(filename)
+ local map={mappings={}, crc8={}, crc16={}}
+ local m=0
+ local c=0
+ local line, fields
+ local temp={}
+ local offset=0
+ if (file_check(filename)==false) then
+ return oops("input file: "..filename.." not found")
+ else
+ local fhi,err = io.open(filename)
+ while true do
+ line = fhi:read()
+ if line == nil then
+ break
+ else
+ fields=split(line)
+ end
+ if (#fields==2) then
+ if (fields[1]=='offset') then
+ offset=tonumber(fields[2],10)
+ end
+ -- map-name
+ map[fields[1]]=fields[2]
+ elseif (fields[1]=='mappings') then
+ m=m+1
+ temp={}
+ -- mapping
+ temp['name']=fields[3]
+ temp['start']=tonumber(fields[4], 10)
+ temp['end']=tonumber(fields[5], 10)
+ if(temp['start']>22) then
+ temp['start']=temp['start']+offset
+ temp['end']=temp['end']+offset
+ end
+ if (tonumber(fields[6], 10)==1) then temp['highlight']= true
+ else temp['highlight']= false end
+ table.insert(map['mappings'], m, temp)
+ elseif (fields[1]=='crc8') then
+ c=c+1
+ temp={}
+ -- crc8
+ temp['name']=fields[3]
+ temp['pos']=tonumber(fields[4], 10)+offset
+ local s=string.sub(line, string.len(fields[1]..","..fields[2]..","..fields[3]..",")+1, string.len(line))
+ temp['seq']=seqstr2tbl(s)
+ for k, v in pairs(temp['seq']) do
+ if(tonumber(v, 10)>22) then v=tonumber(v, 10)+offset end
+ temp['seq'][k]=tonumber(v, 10)
+ end
+ table.insert(map.crc8, temp)
+ end
+ end
+ fhi:close()
+ end
+ return map
+end
+
+---
+-- dump tagMap (mappings only)
+function dumpTagMap(tag, tagMap)
+ if(#tagMap.mappings>0) then
+ bytes=tagToBytes(tag)
+ local temp
+ local lastend=0
+ -- start display mappings
+ for k, v in pairs(tagMap.mappings) do
+ if ((lastend+1)<v['start']) then
+ print("...")
+ end
+ if (isPosCrc8(tagMap, v['start'])>0) then
+ if ( checkMapCrc8(tagMap, bytes, isPosCrc8(tagMap, v['start']) ) ) then
+ io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..acgreen..v['name']..acoff..":")
+ else
+ io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..acred..v['name']..acoff..":")
+ end
+ else
+ io.write("("..("%04d"):format(v['start']).."-"..("%04d"):format(v['end'])..") "..((v['highlight']) and acmagenta or acyellow)..v['name']..acoff..":")
+ end
+ temp=""
+ for i=((string.len(v['name']))/10), 2 do
+ temp=temp.."\t"
+ end
+ for i=v['start'], v['end'] do
+ temp=temp..bytes[i].." "
+ end
+ print(temp)
+ lastend=v['end']
+ end
+ end
+end
+
+---
+--
+function isPosCrc8(tagMap, pos)
+ local res=0
+ if (#tagMap.crc8>0) then
+ for k, v in pairs(tagMap.crc8) do
+ if(v['pos']==pos) then res=k end
+ end
+ end
+ return res
+end
+
+---
+-- check mapped crc
+function checkMapCrc8(tagMap, bytes, n)
+ local res=false
+ if (#tagMap.crc8>0) then
+ if(istable(tagMap.crc8[n])) then
+ temp=""
+ for k2, v2 in pairs(tagMap.crc8[n]) do
+ if (istable(v2)) then
+ temp=temp..tbl2seqstr(v2)
+ end
+ end
+ local tempres=""
+ local tempres=getSequences(bytes, temp)
+ tempres=("%02x"):format(utils.Crc8Legic(tempres))
+ if (bytes[tagMap.crc8[n]['pos']]==tempres) then
+ res=true
+ end
+ end
+ end
+ return res
+end
+
+---
+-- edit existing Map
+function editTagMap(tag, tagMap)
+ local t = [[
+ Data: dm = show dr = dump raw
+Mappings: im = insert am = add rm = remove
+ CRC8: ac8 = add sc8 = show rc8 = remove
+ : q = exit h = Help
+ ]]
+ --if(#tagMap.mappings==0) then oops("no mappings in tagMap"); return tagMap end
+ print("tagMap edit-mode submenu")
+ repeat
+ x=input('tagMap submenu:', 'h')
+ if (x=='h') then print(t)
+ elseif (x=='dm') then tagMmap=dumpTagMap(tag, tagMap)
+ elseif (x=='dr') then tagMmap=dumpMap(tag, tagMap)
+ elseif (x=='rc8') then
+ if (istable(tagMap.crc8)) then
+ local x1 = selectTableEntry(tagMap.crc8, "select number of CRC8 to remove:")
+ if (istable(tagMap.crc8[x1])) then
+ table.remove(tagMap.crc8, x1)
+ end
+ end
+ elseif (x=='ac8') then
+ local p=tonumber(input("enter byte-addr of crc8", '0'),10)
+ if (p>0) then
+ local i1=input("enter comma-seperated byte-sequences (e.g.: '1-4,23-26')", '1-4,23-26')
+ local s1=split(i1, ',')
+ if (#s1>0) then
+ local temp={seq={}}
+ for k, v in pairs(s1) do
+ v1=split(v, '-')
+ if(#v1==2) then
+ table.insert(temp.seq, v1[1])
+ table.insert(temp.seq, v1[2])
+ end
+ end
+ temp['pos']=p
+ temp['name']=input("enter a name for the CRC8", "CRC "..(#tagMap.crc8+1))
+ table.insert(tagMap.crc8, temp)
+ end
+ end
+ elseif (string.sub(x, 1, 3)=='sc8') then
+ local bytes=tagToBytes(tag)
+ local res, pos
+ -- trigger manually by sc8 <'4digit' checkadd> <'seqeuence-string'>
+ -- e.g.: sc8 0027 1-4,23-36
+ if (string.len(x)>=9) then
+ pos=tonumber(string.sub(x, 5, 8), 10)
+ x=string.sub(x, 9, string.len(x))
+ print("x: "..x.." - pos:"..pos)
+ else
+ x=selectTableEntry(tagMap.crc8, "select CRC:")
+ if(istable(tagMap.crc8[x])) then
+ pos=tagMap.crc8[x]['pos']
+ x=tbl2seqstr(tagMap.crc8[x]['seq'])
+ end
+ end
+ if (type(x)=='string') then
+ res=("%02x"):format(utils.Crc8Legic(getSequences(bytes, x)))
+ print(accyan.."Sequence:\t"..acoff..x)
+ print(accyan.."Bytes:\t\t"..acoff..getSequences(bytes, x))
+ print(accyan.."calculated: "..acoff..res..accyan.." bytes["..pos.."]: "..acoff..bytes[pos].." ("..compareCrc(utils.Crc8Legic(getSequences(bytes, x)), bytes[pos])..")")
+ end
+ elseif (x=="tm") then
+ x=selectTableEntry(tagMap.mappings, "select number of Mapping:")
+ tagMap.mappings[x]=toggleHighlight(tagMap.mappings[x])
+ elseif (x=='am') then tagMap=addMapping(tag, tagMap)
+ elseif (x=='im') then tagMap=addMapping(tag, tagMap, selectTableEntry(tagMap.mappings, "select List-Position for insert:"))
+ elseif (x=='rm') then tagMap=deleteMapping(tag, tagMap)
+ elseif (x=='mas') then tagMap=mapTag(tagMap); tagMap=mapAllSegments(tag, tagMap)
+ elseif (type(actions[string.sub(x, 3)])=='function') then actions[string.sub(x, 3)]()
+ end
+ until x=='q'
+ print("exit sub-Menu")
+ return tagMap
+end
+
+---
+-- dump raw mapped and unmapped
+function dumpMap(tag, tagMap)
+ local dstart=1
+ local dend, cnt
+ local bytes = tagToBytes(tag)
+ local stats = getSegmentStats(bytes)
+ dend=stats[#stats]['end']
+ print(accyan.."Tag uses "..dend.." bytes:"..acoff)
+ for i=dstart, dend do
+ if (check4MappedByte(i, tagMap) and not check4MapCrc8(i, tagMap) and not check4Highlight(i, tagMap)) then io.write(""..acyellow)
+ elseif (check4MapCrc8(i, tagMap)) then
+ if ( checkMapCrc8(tagMap, bytes, isPosCrc8(tagMap, i) ) ) then
+ io.write(""..acgreen)
+ else
+ io.write(""..acred)
+ end
+ else
+ io.write(""..acoff)
+ end
+ -- highlighted mapping
+ if (check4Highlight(i, tagMap)) then io.write(""..acmagenta) end
+
+ io.write(bytes[i])
+ if (i%8==0) then io.write("\n")
+ else io.write(" ") end
+ end
+
+ io.write("\n"..acoff)
+end
+
+---
+-- show bytes used for crc-calculation
+function getSequences(bytes, seqstr)
+ if (type(seqstr)~="string") then seqstr=input("enter comma-seperated sequences (e.g.: '1-4,23-26')", '1-4,23-26') end
+ local seqs=split(seqstr, ',')
+ local res = ""
+ if(#seqs>0) then
+ for k, v in pairs(seqs) do
+ local seq = split(v,'-')
+ if (#seq>=2) then
+ for i=seq[1], seq[2] do
+ res=res..bytes[i].." "
+ end
+ end
+ if(string.len(res)>0) then res=res.." " end
+ end
+ else
+ oops("no sequence found in '"..seqstr.."'")
+ end
+ return res
+end
+
+---
+-- check if byte-addr is a know crc
+function check4MapCrc8(addr, tagMap)
+ local res=false
+ for i=1, #tagMap.crc8 do
+ if (addr == tagMap.crc8[i]['pos']) then
+ res=true
+ end
+ end
+ return res
+end
+
+---
+-- check if byte-addr is a know crc
+function check4MapCrc16(addr, tagMap)
+ local res=false
+ for i=1, #tagMap.crc16 do
+ if (addr == tagMap.crc16[i]['pos']) then
+ res=true
+ end
+ end
+ return res
+end
+
+---
+-- check if byte is mapped or not
+function check4MappedByte(addr, tagMap)
+ local res=false
+ for _, v in pairs(tagMap.mappings) do
+ if (addr >= v['start'] and addr <= v['end'] ) then
+ res= true
+ end
+ end
+ return res
+end
+
+---
+-- check if byte is highlighted or not
+function check4Highlight(addr, tagMap)
+ local res=false
+ for _, v in pairs(tagMap.mappings) do
+ if (addr >= v['start'] and addr <= v['end'] ) then
+ res= v['highlight']
+ end
+ end
+ return res
+end
+
+---
+-- add interactive mapping
+function addMapping(tag, tagMap, x)
+ if (type(x)~="number") then x=#tagMap.mappings+1 end
+ local bytes=tagToBytes(tag)
+ local myMapping={}
+ myMapping['name'] =input(accyan.."enter Maping-Name:"..acoff, string.format("mapping %d", #tagMap.mappings+1))
+ myMapping['start']=tonumber(input(accyan.."enter start-addr:"..acoff, '1'), 10)
+ myMapping['end'] =tonumber(input(accyan.."enter end-addr:"..acoff, #bytes), 10)
+ myMapping['highlight']=confirm("set highlighted")
+ table.insert(tagMap.mappings, x, myMapping)
+ return tagMap
+end
+
+---
+-- delete mapping
+function deleteMapping(tag, tagMap)
+ if(#tagMap.mappings>0) then
+ local d = selectTableEntry(tagMap.mappings, "select number of Mapping to remove:")
+ if (type(d)=='number') then
+ table.remove(tagMap.mappings, d)
+ else oops("deleteMapping: got type = "..type(d).." - expected type = 'number'")
+ end
+ end
+ return tagMap
+end
+
+---
+-- select a mapping from a tagmap
+function selectTableEntry(table, action)
+ if (type(action)~="string") then action="select number of item:" end
+ for k, v in pairs(table) do
+ print(accyan..k..acoff.."\t-> "..accyan..v['name']..acoff)
+ end
+ local res = tonumber(input(action , 0), 10)
+ if (istable(table[res])) then
+ return res
+ else
+ return false
+ end
+end
+
+---
+-- map all segments
+function mapAllSegments(tag, tagMap)
+ local bytes=tagToBytes(tag)
+ local WRP,WRC,WRPC
+ segs=getSegmentStats(bytes)
+ if (istable(segs)) then
+ for k, v in pairs(segs) do
+ -- wrp (write proteted) = byte 2
+ WRP = tonumber(bytes[v['start']+2],16)
+ -- wrc (write control) - bit 4-6 of byte 3
+ WRC = tonumber(bbit("0x"..bytes[v['start']+3],4,3),16)
+ --tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." HDR", v['start'], v['start']+3)
+ tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." CRC", v['start']+4, v['start']+4, true)
+ table.insert(tagMap.crc8, {name = 'Segment '..("%02d"):format(v['index']).." CRC", pos=v['start']+4, seq={1,4,v['start'],v['start']+3}} )
+ if(WRC>WRP) then
+ WRPC=WRC
+ tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." WRC", v['start']+5, v['start']+5+WRC-1, true)
+ elseif (WRP>WRC and WRC>0) then
+ WRPC=WRP
+ tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." WRC", v['start']+5, v['start']+5+WRC-1, true)
+ tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." WRP", v['start']+WRC+5, v['start']+5+WRP-1, true)
+ else
+ WRPC=WRP
+ tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." WRP", v['start']+5, v['start']+5+WRP-1, true)
+ end
+ tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." data", v['start']+5+WRPC, v['end'], false)
+
+ end
+ print(#segs.." Segments mapped")
+ else
+ oops("autoMapSegments failed: no Segments found")
+ end
+ return tagMap
+end
+
+---
+-- map all token data
+function mapTokenData(tagMap, mname, mstart, mend, mhigh)
+ --if ( not mhigh ) then mhigh=false end
+ local myMapping={}
+ myMapping['name'] =mname
+ myMapping['start']=mstart
+ myMapping['end'] =mend
+ myMapping['highlight']=mhigh
+ table.insert(tagMap.mappings, myMapping)
+ return tagMap
+end
+
+---
+-- map a map
+function mapTag(tagMap)
+ tagMap=makeTagMap()
+ tagMap=mapTokenData(tagMap, 'Tag-ID', 1, 4, true)
+ tagMap=mapTokenData(tagMap, 'Tag-CRC', 5, 5, false)
+ tagMap=mapTokenData(tagMap, 'DCF', 6, 7, true)
+ tagMap=mapTokenData(tagMap, 'THDR-Raw/Stamp-Len', 8, 8, true)
+ tagMap=mapTokenData(tagMap, 'SSC', 9, 9, true)
+ tagMap=mapTokenData(tagMap, 'Header', 10, 13, false)
+ tagMap=mapTokenData(tagMap, 'Backup', 14, 19, true)
+ tagMap=mapTokenData(tagMap, 'Bck-CRC', 20, 20, false)
+ tagMap=mapTokenData(tagMap, 'TokenTime', 21, 22, false)
+ return tagMap
+end
+
+--- Dump Data ---
+---
+-- dump virtual Tag-Data
+function dumpTag(tag)
+ local i, i2
+ local res
+ local dp=0
+ local raw=""
+ -- sytstem area
+ res =acyellow.."\nCDF: System Area"..acoff
+ res= res.."\n"..dumpCDF(tag)
+ -- segments (user-token area)
+ if(tag.Type=="SAM" and tag.raw=='9f') then
+ res = res..acyellow.."\n\nADF: User Area"..acoff
+ for i=0, #tag.SEG do
+ res=res.."\n"..dumpSegment(tag, i).."\n"
+ end
+ end
+ return res
+end
+
+---
+-- dump tag-system area
+function dumpCDF(tag)
+ local res=""
+ local i=0
+ local raw=""
+ local bytes
+ if (istable(tag)) then
+ res = res..accyan.."MCD: "..acoff..tag.MCD..accyan.." MSN: "..acoff..tag.MSN0.." "..tag.MSN1.." "..tag.MSN2..accyan.." MCC: "..acoff..tag.MCC.."\n"
+ res = res.."DCF: "..tag.DCFl.." "..tag.DCFh..", Token_Type="..tag.Type.." (OLE="..tag.OLE.."), Stamp_len="..tag.Stamp_len.."\n"
+ res = res.."WRP="..tag.WRP..", WRC="..tag.WRC..", RD="..tag.RD..", raw="..tag.raw..((tag.raw=='9f') and (", SSC="..tag.SSC.."\n") or "\n")
+
+ -- credential (end-user tag)
+ if (tag.Type=="SAM" and tag.raw=='9f') then
+ res = res.."Remaining Header Area\n"
+ for i=0, (#tag.data) do
+ res = res..tag.data[i].." "
+ end
+ res = res.."\nBackup Area\n"
+ for i=0, (#tag.Bck) do
+ res = res..tag.Bck[i].." "
+ end
+ res = res.."\nTime Area\n"
+ for i=0, (#tag.MTC) do
+ res = res..tag.MTC[i].." "
+ end
+
+
+ -- Master Token specific
+ elseif (tag.Type~="SAM") then
+ res = res .."Master-Token Area\nStamp: "
+ res= res..tag.SSC.." "
+ for i=0, tag.Stamp_len-2 do
+ res = res..tag.data[i].." "
+ end
+ res=res.."\nunused payload\n"
+ for i=0, (#tag.data-tag.Stamp_len-1) do
+ res = res..tag.data[i].." "
+ end
+ bytes=tagToBytes(tag)
+ local mtcrc=calcMtCrc(bytes)
+ res=res.."\nMaster-Token CRC: "
+ res = res ..tag.MTC[1].." ("..((tag.MTC[1]==mtcrc) and "valid" or "error")..")"
+
+
+ -- 'Gantner User-Credential' specific
+ elseif (tag.Type=="SAM" and (tag.raw=='08' or tag.raw=='09')) then
+ print(acgreen.."Gantner Detected"..acoff)
+ end
+
+ return res
+ else print("no valid Tag in dumpCDF") end
+end
+
+---
+-- dump single segment
+function dumpSegment(tag, index)
+ local i=index
+ local i2
+ local dp=0 --data-position in table
+ local res="" --result
+ local raw="" --raw-header
+ -- segment
+ if ( (istable(tag.SEG[i])) and tag.Type=="SAM" and tag.raw=="9f") then
+ if (istable(tag.SEG[i].raw)) then
+ for k,v in pairs(tag.SEG[i].raw) do
+ raw=raw..v.." "
+ end
+ end
+
+ -- segment header
+ res = res..accyan.."Segment "..("%02d"):format(tag.SEG[i].index)..acoff..": "
+ res = res .."raw header: "..string.sub(raw,0,-2)..", flag="..tag.SEG[i].flag..", (valid="..("%x"):format(tag.SEG[i].valid)..", last="..("%x"):format(tag.SEG[i].last).."), "
+ res = res .."len="..("%04d"):format(tag.SEG[i].len)..", WRP="..("%02x"):format(tag.SEG[i].WRP)..", WRC="..("%02x"):format(tag.SEG[i].WRC)..", "