From 325025f02e8c17387e4a83db0681db327cc4daec Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Wed, 19 Dec 2018 21:10:29 -0500 Subject: [PATCH 01/15] refactor --- dlidparser/dlidlicense.go | 211 +++------------------ dlidparser/dlidparser_test.go | 342 +++++++++++++++++----------------- dlidparser/parseV1.go | 133 +++++-------- dlidparser/parseV2.go | 72 +++---- dlidparser/parseV3.go | 93 ++++----- dlidparser/parseV4.go | 77 ++++---- dlidparser/parser.go | 15 +- go.mod | 1 + main.go | 21 ++- 9 files changed, 384 insertions(+), 581 deletions(-) create mode 100644 go.mod diff --git a/dlidparser/dlidlicense.go b/dlidparser/dlidlicense.go index 9887031..0e8c1f7 100644 --- a/dlidparser/dlidlicense.go +++ b/dlidparser/dlidlicense.go @@ -1,197 +1,46 @@ package dlidparser import ( + "encoding/json" "time" ) +//DriverSex - states record a sex type DriverSex int +//Possibilities for different sex const ( DriverSexNone DriverSex = iota DriverSexMale DriverSexFemale ) +//DLIDLicense holds extracted driver's license info type DLIDLicense struct { - firstName string - middleNames []string - lastName string - nameSuffix string - street string - city string - state string - country string - postal string - sex DriverSex - socialSecurityNumber string - dateOfBirth time.Time - issuerId string - issuerName string - expiryDate time.Time - issueDate time.Time - vehicleClass string - restrictionCodes string - endorsementCodes string - customerId string - documentDiscriminator string -} - -func (d *DLIDLicense) SetFirstName(s string) { - d.firstName = s -} - -func (d *DLIDLicense) FirstName() string { - return d.firstName -} - -func (d *DLIDLicense) SetMiddleNames(s []string) { - d.middleNames = s -} - -func (d *DLIDLicense) MiddleNames() []string { - return d.middleNames -} - -func (d *DLIDLicense) SetLastName(s string) { - d.lastName = s -} - -func (d *DLIDLicense) LastName() string { - return d.lastName -} - -func (d *DLIDLicense) SetNameSuffix(s string) { - d.nameSuffix = s -} - -func (d *DLIDLicense) NameSuffix() string { - return d.nameSuffix -} - -func (d *DLIDLicense) SetStreet(s string) { - d.street = s -} - -func (d *DLIDLicense) Street() string { - return d.street -} - -func (d *DLIDLicense) SetCity(s string) { - d.city = s -} - -func (d *DLIDLicense) City() string { - return d.city -} - -func (d *DLIDLicense) SetState(s string) { - d.state = s -} - -func (d *DLIDLicense) State() string { - return d.state -} - -func (d *DLIDLicense) SetCountry(s string) { - d.country = s -} - -func (d *DLIDLicense) Country() string { - return d.country -} - -func (d *DLIDLicense) SetPostal(s string) { - d.postal = s -} - -func (d *DLIDLicense) Postal() string { - return d.postal -} - -func (d *DLIDLicense) SetSex(s DriverSex) { - d.sex = s -} - -func (d *DLIDLicense) Sex() DriverSex { - return d.sex -} - -func (d *DLIDLicense) SetSocialSecurityNumber(s string) { - d.socialSecurityNumber = s -} - -func (d *DLIDLicense) SocialSecurityNumber() string { - return d.socialSecurityNumber -} - -func (d *DLIDLicense) SetDateOfBirth(t time.Time) { - d.dateOfBirth = t -} - -func (d *DLIDLicense) DateOfBirth() time.Time { - return d.dateOfBirth -} - -func (d *DLIDLicense) IssuerId() string { - return d.issuerId -} - -func (d *DLIDLicense) SetIssuerId(s string) { - d.issuerId = s -} - -func (d *DLIDLicense) IssuerName() string { - return d.issuerName -} - -func (d *DLIDLicense) SetIssuerName(s string) { - d.issuerName = s -} - -func (d *DLIDLicense) VehicleClass() string { - return d.vehicleClass -} - -func (d *DLIDLicense) SetVehicleClass(s string) { - d.vehicleClass = s -} - -func (d *DLIDLicense) RestrictionCodes() string { - return d.restrictionCodes -} - -func (d *DLIDLicense) SetRestrictionCodes(s string) { - d.restrictionCodes = s -} - -func (d *DLIDLicense) EndorsementCodes() string { - return d.endorsementCodes -} - -func (d *DLIDLicense) SetEndorsementCodes(s string) { - d.endorsementCodes = s -} - -func (d *DLIDLicense) CustomerId() string { - return d.customerId -} - -func (d *DLIDLicense) SetCustomerId(s string) { - d.customerId = s -} - -func (d *DLIDLicense) SetExpiryDate(t time.Time) { - d.expiryDate = t -} - -func (d *DLIDLicense) ExpiryDate() time.Time { - return d.expiryDate -} - -func (d *DLIDLicense) SetIssueDate(t time.Time) { - d.issueDate = t -} - -func (d *DLIDLicense) IssueDate() time.Time { - return d.issueDate + FirstName string `json:"first_name,omitempty"` + MiddleNames []string `json:"middle_names,omitempty"` + LastName string `json:"last_name,omitempty"` + NameSuffix string `json:"name_suffix,omitempty"` + Street string `json:"street,omitempty"` + City string `json:"city,omitempty"` + State string `json:"state,omitempty"` + Country string `json:"country,omitempty"` + Postal string `json:"postal,omitempty"` + Sex DriverSex `json:"sex,omitempty"` + SocialSecurityNumber string `json:"social_security_number,omitempty"` + DateOfBirth time.Time `json:"date_of_birth,omitempty"` + IssuerID string `json:"issuer_id,omitempty"` + IssuerName string `json:"issuer_name,omitempty"` + ExpiryDate time.Time `json:"expiry_date,omitempty"` + IssueDate time.Time `json:"issue_date,omitempty"` + VehicleClass string `json:"vehicle_class,omitempty"` + RestrictionCodes string `json:"restriction_codes,omitempty"` + EndorsementCodes string `json:"endorsement_codes,omitempty"` + CustomerID string `json:"customer_id,omitempty"` + DocumentDiscriminator string `json:"document_discriminator,omitempty"` +} + +func (d DLIDLicense) String() string { + b, _ := json.Marshal(d) + return string(b) } diff --git a/dlidparser/dlidparser_test.go b/dlidparser/dlidparser_test.go index db2f836..0ec8ffe 100644 --- a/dlidparser/dlidparser_test.go +++ b/dlidparser/dlidparser_test.go @@ -31,15 +31,15 @@ func TestV1IllinoisParser(t *testing.T) { t.Error("V1 Illinois parser failed") } - if s.FirstName() != "SAMPLE" { + if s.FirstName != "SAMPLE" { t.Error("V1 Illinois parser extracted wrong first name") } - if s.MiddleNames()[0] != "CARD" { + if s.MiddleNames[0] != "CARD" { t.Error("V1 Illinois parser extracted wrong middle name") } - if s.LastName() != "CDL" { + if s.LastName != "CDL" { t.Error("V1 Illinois parser extracted wrong last name") } } @@ -51,15 +51,15 @@ func TestV1ConnecticutParser(t *testing.T) { t.Error("V1 Connecticut parser failed") } - if s.FirstName() != "JOHN" { + if s.FirstName != "JOHN" { t.Error("V1 Connecticut parser extracted wrong first name") } - if s.MiddleNames()[0] != "Q" { + if s.MiddleNames[0] != "Q" { t.Error("V1 Connecticut parser extracted wrong middle name") } - if s.LastName() != "PUBLIC" { + if s.LastName != "PUBLIC" { t.Error("V1 Connecticut parser extracted wrong last name") } } @@ -71,15 +71,15 @@ func TestV1MassachusettsParser(t *testing.T) { t.Error("V1 Massachusetts parser failed") } - if s.FirstName() != "JOHN" { + if s.FirstName != "JOHN" { t.Error("V1 Massachusetts parser extracted wrong first name") } - if s.MiddleNames()[0] != "Q" { + if s.MiddleNames[0] != "Q" { t.Error("V1 Massachusetts parser extracted wrong middle name") } - if s.LastName() != "PUBLIC" { + if s.LastName != "PUBLIC" { t.Error("V1 Massachusetts parser extracted wrong last name") } } @@ -91,15 +91,15 @@ func TestV1PennsylvaniaParser(t *testing.T) { t.Error("V1 Pennsylvania parser failed") } - if s.FirstName() != "JOHN" { + if s.FirstName != "JOHN" { t.Error("V1 Pennsylvania parser extracted wrong first name") } - if s.MiddleNames()[0] != "Q" { + if s.MiddleNames[0] != "Q" { t.Error("V1 Pennsylvania parser extracted wrong middle name") } - if s.LastName() != "PUBLIC" { + if s.LastName != "PUBLIC" { t.Error("V1 Pennsylvania parser extracted wrong last name") } } @@ -111,15 +111,15 @@ func TestV1ColoradoParser(t *testing.T) { t.Error("V1 Colorado parser failed") } - if s.FirstName() != "JOHN" { + if s.FirstName != "JOHN" { t.Error("V1 Colorado parser extracted wrong first name") } - if s.MiddleNames()[0] != "Q" { + if s.MiddleNames[0] != "Q" { t.Error("V1 Colorado parser extracted wrong middle name") } - if s.LastName() != "PUBLIC" { + if s.LastName != "PUBLIC" { t.Error("V1 Colorado parser extracted wrong last name") } } @@ -131,95 +131,95 @@ func TestV1Parser(t *testing.T) { t.Error("V1 parser failed") } - if s.IssuerName() != "Virginia" { + if s.IssuerName != "Virginia" { t.Error("V1 parser extracted wrong issuer") } - if s.FirstName() != "JOHN" { + if s.FirstName != "JOHN" { t.Error("V1 parser extracted wrong first name") } - if s.MiddleNames()[0] != "Q" { + if s.MiddleNames[0] != "Q" { t.Error("V1 parser extracted wrong middle name") } - if s.LastName() != "PUBLIC" { + if s.LastName != "PUBLIC" { t.Error("V1 parser extracted wrong last name") } - if s.Country() != "USA" { + if s.Country != "USA" { t.Error("V1 parser got wrong country") } - if s.Street() != "123 MAIN STREET" { + if s.Street != "123 MAIN STREET" { t.Error("V1 parser got wrong street") } - if s.City() != "ANYTOWN" { + if s.City != "ANYTOWN" { t.Error("V1 parser got wrong city") } - if s.State() != "VA" { + if s.State != "VA" { t.Error("V1 parser got wrong state") } - if s.Postal() != "123459999" { + if s.Postal != "123459999" { t.Error("V1 parser got wrong postal code") } - if s.DateOfBirth().Day() != 23 { + if s.DateOfBirth.Day() != 23 { t.Error("V1 parser got wrong date of birth day") } - if s.DateOfBirth().Month() != 11 { + if s.DateOfBirth.Month() != 11 { t.Error("V1 parser got wrong date of birth month") } - if s.DateOfBirth().Year() != 1976 { + if s.DateOfBirth.Year() != 1976 { t.Error("V1 parser got wrong date of birth year") } - if s.CustomerId() != "0123456789ABC" { + if s.CustomerID != "0123456789ABC" { t.Error("V1 parser got wrong customer id") } - if s.EndorsementCodes() != "" { + if s.EndorsementCodes != "" { t.Error("V1 parser got wrong endorsement codes") } - if s.VehicleClass() != "DM" { + if s.VehicleClass != "DM" { t.Error("V1 parser got wrong vehicle class") } - if s.RestrictionCodes() != "" { + if s.RestrictionCodes != "" { t.Error("V1 parser got wrong restriction codes") } - if s.Sex() != DriverSexMale { + if s.Sex != DriverSexMale { t.Error("V1 parser got wrong sex") } - if s.ExpiryDate().Day() != 1 { + if s.ExpiryDate.Day() != 1 { t.Error("V1 parser got wrong expiry day") } - if s.ExpiryDate().Month() != 12 { + if s.ExpiryDate.Month() != 12 { t.Error("V1 parser got wrong expiry month") } - if s.ExpiryDate().Year() != 2001 { + if s.ExpiryDate.Year() != 2001 { t.Error("V1 parser got wrong expiry year") } - if s.IssueDate().Day() != 1 { + if s.IssueDate.Day() != 1 { t.Error("V1 parser got wrong issue day") } - if s.IssueDate().Month() != 12 { + if s.IssueDate.Month() != 12 { t.Error("V1 parser got wrong issue month") } - if s.IssueDate().Year() != 1996 { + if s.IssueDate.Year() != 1996 { t.Error("V1 parser got wrong issue year") } } @@ -235,99 +235,99 @@ func TestV3Parser(t *testing.T) { t.Error("V3 parser failed") } - if s.IssuerName() != "Texas" { + if s.IssuerName != "Texas" { t.Error("V3 parser extracted wrong issuer") } - if s.FirstName() != "JAMES" { + if s.FirstName != "JAMES" { t.Error("V3 parser extracted wrong first name") } - if len(s.MiddleNames()) != 2 { + if len(s.MiddleNames) != 2 { t.Error("V3 parser failed to extract middle names") } - if s.MiddleNames()[0] != "ROBERT" || s.MiddleNames()[1] != "R" { + if s.MiddleNames[0] != "ROBERT" || s.MiddleNames[1] != "R" { t.Error("V3 parser extracted wrong middle names") } - if s.LastName() != "JONES" { + if s.LastName != "JONES" { t.Error("V3 parser extracted wrong last name") } - if s.DateOfBirth().Day() != 11 { + if s.DateOfBirth.Day() != 11 { t.Error("V3 parser got wrong date of birth day") } - if s.DateOfBirth().Month() != 10 { + if s.DateOfBirth.Month() != 10 { t.Error("V3 parser got wrong date of birth month") } - if s.DateOfBirth().Year() != 1978 { + if s.DateOfBirth.Year() != 1978 { t.Error("V3 parser got wrong date of birth year") } - if s.CustomerId() != "22334455" { + if s.CustomerID != "22334455" { t.Error("V3 parser got wrong customer id") } - if s.EndorsementCodes() != "P" { + if s.EndorsementCodes != "P" { t.Error("V3 parser got wrong endorsement codes") } - if s.VehicleClass() != "B" { + if s.VehicleClass != "B" { t.Error("V3 parser got wrong vehicle class") } - if s.RestrictionCodes() != "LP" { + if s.RestrictionCodes != "LP" { t.Error("V3 parser got wrong restriction codes") } - if s.Country() != "USA" { + if s.Country != "USA" { t.Error("V3 parser got wrong country") } - if s.Street() != "123 SOME STREET" { + if s.Street != "123 SOME STREET" { t.Error("V3 parser got wrong street") } - if s.City() != "CITY 12" { + if s.City != "CITY 12" { t.Error("V3 parser got wrong city") } - if s.State() != "TX" { + if s.State != "TX" { t.Error("V3 parser got wrong state") } - if s.Postal() != "90210" { + if s.Postal != "90210" { t.Error("V3 parser got wrong postal code") } - if s.Sex() != DriverSexMale { + if s.Sex != DriverSexMale { t.Error("V3 parser got wrong sex") } - if s.ExpiryDate().Day() != 5 { + if s.ExpiryDate.Day() != 5 { t.Error("V4 parser got wrong expiry day") } - if s.ExpiryDate().Month() != 4 { + if s.ExpiryDate.Month() != 4 { t.Error("V3 parser got wrong expiry month") } - if s.ExpiryDate().Year() != 2018 { + if s.ExpiryDate.Year() != 2018 { t.Error("V3 parser got wrong expiry year") } - if s.IssueDate().Day() != 8 { + if s.IssueDate.Day() != 8 { t.Error("V3 parser got wrong issue day") } - if s.IssueDate().Month() != 7 { + if s.IssueDate.Month() != 7 { t.Error("V3 parser got wrong issue month") } - if s.IssueDate().Year() != 2012 { + if s.IssueDate.Year() != 2012 { t.Error("V3 parser got wrong issue year") } } @@ -339,103 +339,103 @@ func TestV4Parser(t *testing.T) { t.Error("V4 parser failed") } - if s.IssuerName() != "Virginia" { + if s.IssuerName != "Virginia" { t.Error("V4 parser extracted wrong issuer") } - if s.FirstName() != "MICHAEL" { + if s.FirstName != "MICHAEL" { t.Error("V4 parser extracted wrong first name") } - if len(s.MiddleNames()) != 2 { + if len(s.MiddleNames) != 2 { t.Error("V4 parser failed to extract middle names") } - if s.MiddleNames()[0] != "JOHN" || s.MiddleNames()[1] != "BOB" { + if s.MiddleNames[0] != "JOHN" || s.MiddleNames[1] != "BOB" { t.Error("V4 parser extracted wrong middle names") } - if s.LastName() != "SAMPLE" { + if s.LastName != "SAMPLE" { t.Error("V4 parser extracted wrong last name") } - if s.NameSuffix() != "JR" { + if s.NameSuffix != "JR" { t.Error("V4 parser extracted wrong name suffix") } - if s.DateOfBirth().Day() != 7 { + if s.DateOfBirth.Day() != 7 { t.Error("V4 parser got wrong date of birth day") } - if s.DateOfBirth().Month() != 6 { + if s.DateOfBirth.Month() != 6 { t.Error("V4 parser got wrong date of birth month") } - if s.DateOfBirth().Year() != 1986 { + if s.DateOfBirth.Year() != 1986 { t.Error("V4 parser got wrong date of birth year") } - if s.CustomerId() != "T64235789" { + if s.CustomerID != "T64235789" { t.Error("V4 parser got wrong customer id") } - if s.EndorsementCodes() != "PH" { + if s.EndorsementCodes != "PH" { t.Error("V4 parser got wrong endorsement codes") } - if s.VehicleClass() != "D" { + if s.VehicleClass != "D" { t.Error("V4 parser got wrong vehicle class") } - if s.RestrictionCodes() != "K" { + if s.RestrictionCodes != "K" { t.Error("V4 parser got wrong restriction codes") } - if s.Country() != "USA" { + if s.Country != "USA" { t.Error("V4 parser got wrong country") } - if s.Street() != "2300 WEST BROAD STREET" { + if s.Street != "2300 WEST BROAD STREET" { t.Error("V4 parser got wrong street") } - if s.City() != "RICHMOND" { + if s.City != "RICHMOND" { t.Error("V4 parser got wrong city") } - if s.State() != "VA" { + if s.State != "VA" { t.Error("V4 parser got wrong state") } - if s.Postal() != "23269" { + if s.Postal != "23269" { t.Error("V4 parser got wrong postal code") } - if s.Sex() != DriverSexMale { + if s.Sex != DriverSexMale { t.Error("V4 parser got wrong sex") } - if s.ExpiryDate().Day() != 10 { + if s.ExpiryDate.Day() != 10 { t.Error("V4 parser got wrong expiry day") } - if s.ExpiryDate().Month() != 12 { + if s.ExpiryDate.Month() != 12 { t.Error("V4 parser got wrong expiry month") } - if s.ExpiryDate().Year() != 2012 { + if s.ExpiryDate.Year() != 2012 { t.Error("V4 parser got wrong expiry year") } - if s.IssueDate().Day() != 6 { + if s.IssueDate.Day() != 6 { t.Error("V4 parser got wrong issue day") } - if s.IssueDate().Month() != 6 { + if s.IssueDate.Month() != 6 { t.Error("V4 parser got wrong issue month") } - if s.IssueDate().Year() != 2008 { + if s.IssueDate.Year() != 2008 { t.Error("V4 parser got wrong issue year") } } @@ -447,103 +447,103 @@ func TestV5Parser(t *testing.T) { t.Error("V5 parser failed") } - if s.IssuerName() != "Virginia" { + if s.IssuerName != "Virginia" { t.Error("V5 parser extracted wrong issuer") } - if s.FirstName() != "MICHAEL" { + if s.FirstName != "MICHAEL" { t.Error("V5 parser extracted wrong first name") } - if len(s.MiddleNames()) != 2 { + if len(s.MiddleNames) != 2 { t.Error("V5 parser failed to extract middle names") } - if s.MiddleNames()[0] != "JOHN" || s.MiddleNames()[1] != "BOB" { + if s.MiddleNames[0] != "JOHN" || s.MiddleNames[1] != "BOB" { t.Error("V5 parser extracted wrong middle names") } - if s.LastName() != "SAMPLE" { + if s.LastName != "SAMPLE" { t.Error("V5 parser extracted wrong last name") } - if s.NameSuffix() != "JR" { + if s.NameSuffix != "JR" { t.Error("V4 parser extracted wrong name suffix") } - if s.DateOfBirth().Day() != 7 { + if s.DateOfBirth.Day() != 7 { t.Error("V5 parser got wrong date of birth day") } - if s.DateOfBirth().Month() != 6 { + if s.DateOfBirth.Month() != 6 { t.Error("V5 parser got wrong date of birth month") } - if s.DateOfBirth().Year() != 1986 { + if s.DateOfBirth.Year() != 1986 { t.Error("V5 parser got wrong date of birth year") } - if s.CustomerId() != "T64235789" { + if s.CustomerID != "T64235789" { t.Error("V5 parser got wrong customer id") } - if s.EndorsementCodes() != "PH" { + if s.EndorsementCodes != "PH" { t.Error("V5 parser got wrong endorsement codes") } - if s.VehicleClass() != "D" { + if s.VehicleClass != "D" { t.Error("V5 parser got wrong vehicle class") } - if s.RestrictionCodes() != "K" { + if s.RestrictionCodes != "K" { t.Error("V5 parser got wrong restriction codes") } - if s.Country() != "USA" { + if s.Country != "USA" { t.Error("V5 parser got wrong country") } - if s.Street() != "2300 WEST BROAD STREET" { + if s.Street != "2300 WEST BROAD STREET" { t.Error("V5 parser got wrong street") } - if s.City() != "RICHMOND" { + if s.City != "RICHMOND" { t.Error("V5 parser got wrong city") } - if s.State() != "VA" { + if s.State != "VA" { t.Error("V5 parser got wrong state") } - if s.Postal() != "23269" { + if s.Postal != "23269" { t.Error("V5 parser got wrong postal code") } - if s.Sex() != DriverSexMale { + if s.Sex != DriverSexMale { t.Error("V5 parser got wrong sex") } - if s.ExpiryDate().Day() != 10 { + if s.ExpiryDate.Day() != 10 { t.Error("5V5 parser got wrong expiry day") } - if s.ExpiryDate().Month() != 12 { + if s.ExpiryDate.Month() != 12 { t.Error("V5 parser got wrong expiry month") } - if s.ExpiryDate().Year() != 2012 { + if s.ExpiryDate.Year() != 2012 { t.Error("V5 parser got wrong expiry year") } - if s.IssueDate().Day() != 6 { + if s.IssueDate.Day() != 6 { t.Error("V5 parser got wrong issue day") } - if s.IssueDate().Month() != 6 { + if s.IssueDate.Month() != 6 { t.Error("V5 parser got wrong issue month") } - if s.IssueDate().Year() != 2008 { + if s.IssueDate.Year() != 2008 { t.Error("V5 parser got wrong issue year") } } @@ -555,103 +555,103 @@ func TestV6Parser(t *testing.T) { t.Error("V6 parser failed") } - if s.IssuerName() != "Virginia" { + if s.IssuerName != "Virginia" { t.Error("V6 parser extracted wrong issuer") } - if s.FirstName() != "MICHAEL" { + if s.FirstName != "MICHAEL" { t.Error("V6 parser extracted wrong first name") } - if len(s.MiddleNames()) != 2 { + if len(s.MiddleNames) != 2 { t.Error("V6 parser failed to extract middle names") } - if s.MiddleNames()[0] != "JOHN" || s.MiddleNames()[1] != "BOB" { + if s.MiddleNames[0] != "JOHN" || s.MiddleNames[1] != "BOB" { t.Error("V6 parser extracted wrong middle names") } - if s.LastName() != "SAMPLE" { + if s.LastName != "SAMPLE" { t.Error("V6 parser extracted wrong last name") } - if s.NameSuffix() != "JR" { + if s.NameSuffix != "JR" { t.Error("V4 parser extracted wrong name suffix") } - if s.DateOfBirth().Day() != 7 { + if s.DateOfBirth.Day() != 7 { t.Error("V6 parser got wrong date of birth day") } - if s.DateOfBirth().Month() != 6 { + if s.DateOfBirth.Month() != 6 { t.Error("V6 parser got wrong date of birth month") } - if s.DateOfBirth().Year() != 1986 { + if s.DateOfBirth.Year() != 1986 { t.Error("V6 parser got wrong date of birth year") } - if s.CustomerId() != "T64235789" { + if s.CustomerID != "T64235789" { t.Error("V6 parser got wrong customer id") } - if s.EndorsementCodes() != "PH" { + if s.EndorsementCodes != "PH" { t.Error("V6 parser got wrong endorsement codes") } - if s.VehicleClass() != "D" { + if s.VehicleClass != "D" { t.Error("V6 parser got wrong vehicle class") } - if s.RestrictionCodes() != "K" { + if s.RestrictionCodes != "K" { t.Error("V6 parser got wrong restriction codes") } - if s.Country() != "USA" { + if s.Country != "USA" { t.Error("V6 parser got wrong country") } - if s.Street() != "2300 WEST BROAD STREET" { + if s.Street != "2300 WEST BROAD STREET" { t.Error("V6 parser got wrong street") } - if s.City() != "RICHMOND" { + if s.City != "RICHMOND" { t.Error("V6 parser got wrong city") } - if s.State() != "VA" { + if s.State != "VA" { t.Error("V6 parser got wrong state") } - if s.Postal() != "23269" { + if s.Postal != "23269" { t.Error("V6 parser got wrong postal code") } - if s.Sex() != DriverSexMale { + if s.Sex != DriverSexMale { t.Error("V6 parser got wrong sex") } - if s.ExpiryDate().Day() != 10 { + if s.ExpiryDate.Day() != 10 { t.Error("V6 parser got wrong expiry day") } - if s.ExpiryDate().Month() != 12 { + if s.ExpiryDate.Month() != 12 { t.Error("V6 parser got wrong expiry month") } - if s.ExpiryDate().Year() != 2012 { + if s.ExpiryDate.Year() != 2012 { t.Error("V6 parser got wrong expiry year") } - if s.IssueDate().Day() != 6 { + if s.IssueDate.Day() != 6 { t.Error("V6 parser got wrong issue day") } - if s.IssueDate().Month() != 6 { + if s.IssueDate.Month() != 6 { t.Error("V6 parser got wrong issue month") } - if s.IssueDate().Year() != 2008 { + if s.IssueDate.Year() != 2008 { t.Error("V6 parser got wrong issue year") } } @@ -663,103 +663,103 @@ func TestV7Parser(t *testing.T) { t.Error("V7 parser failed") } - if s.IssuerName() != "Virginia" { + if s.IssuerName != "Virginia" { t.Error("V7 parser extracted wrong issuer") } - if s.FirstName() != "MICHAEL" { + if s.FirstName != "MICHAEL" { t.Error("V7 parser extracted wrong first name") } - if len(s.MiddleNames()) != 2 { + if len(s.MiddleNames) != 2 { t.Error("V7 parser failed to extract middle names") } - if s.MiddleNames()[0] != "JOHN" || s.MiddleNames()[1] != "BOB" { + if s.MiddleNames[0] != "JOHN" || s.MiddleNames[1] != "BOB" { t.Error("V7 parser extracted wrong middle names") } - if s.LastName() != "SAMPLE" { + if s.LastName != "SAMPLE" { t.Error("V7 parser extracted wrong last name") } - if s.NameSuffix() != "JR" { + if s.NameSuffix != "JR" { t.Error("V4 parser extracted wrong name suffix") } - if s.DateOfBirth().Day() != 7 { + if s.DateOfBirth.Day() != 7 { t.Error("V7 parser got wrong date of birth day") } - if s.DateOfBirth().Month() != 6 { + if s.DateOfBirth.Month() != 6 { t.Error("V7 parser got wrong date of birth month") } - if s.DateOfBirth().Year() != 1986 { + if s.DateOfBirth.Year() != 1986 { t.Error("V7 parser got wrong date of birth year") } - if s.CustomerId() != "T64235789" { + if s.CustomerID != "T64235789" { t.Error("V7 parser got wrong customer id") } - if s.EndorsementCodes() != "PH" { + if s.EndorsementCodes != "PH" { t.Error("V7 parser got wrong endorsement codes") } - if s.VehicleClass() != "D" { + if s.VehicleClass != "D" { t.Error("V7 parser got wrong vehicle class") } - if s.RestrictionCodes() != "K" { + if s.RestrictionCodes != "K" { t.Error("V7 parser got wrong restriction codes") } - if s.Country() != "USA" { + if s.Country != "USA" { t.Error("V7 parser got wrong country") } - if s.Street() != "2300 WEST BROAD STREET" { + if s.Street != "2300 WEST BROAD STREET" { t.Error("V7 parser got wrong street") } - if s.City() != "RICHMOND" { + if s.City != "RICHMOND" { t.Error("V7 parser got wrong city") } - if s.State() != "VA" { + if s.State != "VA" { t.Error("V7 parser got wrong state") } - if s.Postal() != "23269" { + if s.Postal != "23269" { t.Error("V7 parser got wrong postal code") } - if s.Sex() != DriverSexMale { + if s.Sex != DriverSexMale { t.Error("V7 parser got wrong sex") } - if s.ExpiryDate().Day() != 10 { + if s.ExpiryDate.Day() != 10 { t.Error("V7 parser got wrong expiry day") } - if s.ExpiryDate().Month() != 12 { + if s.ExpiryDate.Month() != 12 { t.Error("V7 parser got wrong expiry month") } - if s.ExpiryDate().Year() != 2012 { + if s.ExpiryDate.Year() != 2012 { t.Error("V7 parser got wrong expiry year") } - if s.IssueDate().Day() != 6 { + if s.IssueDate.Day() != 6 { t.Error("V7 parser got wrong issue day") } - if s.IssueDate().Month() != 6 { + if s.IssueDate.Month() != 6 { t.Error("V7 parser got wrong issue month") } - if s.IssueDate().Year() != 2008 { + if s.IssueDate.Year() != 2008 { t.Error("V7 parser got wrong issue year") } } @@ -771,39 +771,39 @@ func TestV7CanadaParser(t *testing.T) { t.Error("V7 Canada parser failed") } - if s.DateOfBirth().Day() != 7 { + if s.DateOfBirth.Day() != 7 { t.Error("V7 Canada parser got wrong date of birth day") } - if s.DateOfBirth().Month() != 6 { + if s.DateOfBirth.Month() != 6 { t.Error("V7 Canada parser got wrong date of birth month") } - if s.DateOfBirth().Year() != 1986 { + if s.DateOfBirth.Year() != 1986 { t.Error("V7 Canada parser got wrong date of birth year") } - if s.ExpiryDate().Day() != 10 { + if s.ExpiryDate.Day() != 10 { t.Error("V7 Canada parser got wrong expiry day") } - if s.ExpiryDate().Month() != 12 { + if s.ExpiryDate.Month() != 12 { t.Error("V7 Canada parser got wrong expiry month") } - if s.ExpiryDate().Year() != 2012 { + if s.ExpiryDate.Year() != 2012 { t.Error("V7 Canada parser got wrong expiry year") } - if s.IssueDate().Day() != 6 { + if s.IssueDate.Day() != 6 { t.Error("V7 Canada parser got wrong issue day") } - if s.IssueDate().Month() != 6 { + if s.IssueDate.Month() != 6 { t.Error("V7 Canada parser got wrong issue month") } - if s.IssueDate().Year() != 2008 { + if s.IssueDate.Year() != 2008 { t.Error("V7 Canada parser got wrong issue year") } } diff --git a/dlidparser/parseV1.go b/dlidparser/parseV1.go index 697521a..9b3fafe 100644 --- a/dlidparser/parseV1.go +++ b/dlidparser/parseV1.go @@ -7,18 +7,18 @@ import ( "time" ) -const ColoradoIssuerId string = "636020" -const ConnecticutIssuerId string = "636006" -const IllinoisIssuerId string = "636035" -const MassachusettsIssuerId string = "636002" -const SouthCarolinaIssuerId string = "636005" -const TennesseeIssuerId string = "636053" +const coloradoIssuerID string = "636020" +const connecticutIssuerID string = "636006" +const illinoisIssuerID string = "636035" +const massachusettsIssuerID string = "636002" +const southCarolinaIssuerID string = "636005" +const tennesseeIssuerID string = "636053" -func parseV1(data string, issuer string) (license *DLIDLicense, err error) { +func parseV1(data string, issuer string) (*DLIDLicense, error) { start, end, err := dataRangeV1(data) - if issuer == IllinoisIssuerId { + if issuer == illinoisIssuerID { // Illinois are the worst offenders so far in terms of mangling the DLID // spec. They store name, licence number, expiry date and date of birth @@ -29,46 +29,38 @@ func parseV1(data string, issuer string) (license *DLIDLicense, err error) { } if end >= len(data) { - err = errors.New("Payload location does not exist in data") + return nil, errors.New("Payload location does not exist in data") } payload := data[start:end] if err != nil { - return + return nil, err } - license, err = parseDataV1(payload, issuer) - - if err != nil { - return - } - - return + return parseDataV1(payload, issuer) } -func dataRangeV1(data string) (start int, end int, err error) { +func dataRangeV1(data string) (int, int, error) { - start, err = strconv.Atoi(data[21:25]) + start, err := strconv.Atoi(data[21:25]) if err != nil { - err = errors.New("Data contains malformed payload location") - return + return 0, 0, errors.New("Data contains malformed payload location") } - end, err = strconv.Atoi(data[25:29]) + end, err := strconv.Atoi(data[25:29]) if err != nil { - err = errors.New("Data contains malformed payload length") - return + return 0, 0, errors.New("Data contains malformed payload length") } end += start - return + return start, end, nil } -func parseDataV1(licenceData string, issuer string) (license *DLIDLicense, err error) { +func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { // Version 1 of the DLID card spec was published in 2000. As of 2012, it is // the version used in Colorado. @@ -101,13 +93,13 @@ func parseDataV1(licenceData string, issuer string) (license *DLIDLicense, err e components := strings.Split(licenceData, "\n") - license = new(DLIDLicense) + license := &DLIDLicense{} - license.SetIssuerId(issuer) - license.SetIssuerName(issuers[issuer]) + license.IssuerID = issuer + license.IssuerName = issuers[issuer] // Country is always USA for V1 licenses - license.SetCountry("USA") + license.Country = "USA" for component := range components { @@ -122,27 +114,19 @@ func parseDataV1(licenceData string, issuer string) (license *DLIDLicense, err e switch identifier { case "DAR": - license.SetVehicleClass(data) - + license.VehicleClass = data case "DAS": - license.SetRestrictionCodes(data) - + license.RestrictionCodes = data case "DAT": - license.SetEndorsementCodes(data) - + license.EndorsementCodes = data case "DAA": - // Early versions of the Colorado implementation screwed up the // delimiter - they use a space instead of the specified comma. - separator := " " - if strings.Index(data, separator) == -1 { separator = "," } - names := strings.Split(data, separator) - // According to the spec, names are ordered LAST,FIRST,MIDDLE. // However, the geniuses in the Colorado and Tennessee DMVs order it // FIRST,MIDDLE,LAST. We'll use the issuer ID number to @@ -151,66 +135,54 @@ func parseDataV1(licenceData string, issuer string) (license *DLIDLicense, err e // // http://www.aamva.org/IIN-and-RID/ - if issuer == ColoradoIssuerId || issuer == TennesseeIssuerId { - + if issuer == coloradoIssuerID || issuer == tennesseeIssuerID { // Colorado's backwards formatting style... - license.SetFirstName(names[0]) + license.FirstName = names[0] if len(names) > 2 { - license.SetMiddleNames(names[1 : len(names)-1]) - license.SetLastName(names[len(names)-1]) + license.MiddleNames = names[1 : len(names)-1] + license.LastName = names[len(names)-1] } else if len(names) > 1 { - license.SetLastName(names[1]) + license.LastName = names[1] } } else { // Everyone else, hopefully. - license.SetLastName(names[0]) + license.LastName = names[0] if len(names) > 1 { - license.SetFirstName(names[1]) + license.FirstName = names[1] if len(names) > 2 { - license.SetMiddleNames(names[2:]) + license.MiddleNames = names[2:] } } } case "DAE": - license.SetNameSuffix(data) + license.NameSuffix = data case "DAL": - // Colorado screws up again: they omit the *required* DAG field and // substitute the optional DAL field in older licences. fallthrough - case "DAG": - license.SetStreet(data) - + license.Street = data case "DAN": - // Again, old Colorado licences ignore the spec. fallthrough - case "DAI": - license.SetCity(data) - + license.City = data case "DAO": - // Colorado strikes again. Honestly, what is the point in having a // spec if you don't follow it? fallthrough - case "DAJ": - license.SetState(data) - + license.State = data case "DAP": // More Colorado shenanigans. fallthrough - case "DAK": - // Colorado uses the 5-digit zip code. South Carolina uses the // 5 digit zip code plus the +4 extension all smooshed together // into one long string. Massachusetts uses the 5 digit zip @@ -221,19 +193,14 @@ func parseDataV1(licenceData string, issuer string) (license *DLIDLicense, err e // defeat in trying to untangle the incredible mess implemented // in this single field; we'll just show the zip as it is // stored. - license.SetPostal(strings.Trim(data, " ")) - + license.Postal = strings.Trim(data, " ") case "DAQ": - license.SetCustomerId(data) - + license.CustomerID = data case "DBA": - license.SetExpiryDate(parseDateV1(data)) - + license.ExpiryDate = parseDateV1(data) case "DBB": - license.SetDateOfBirth(parseDateV1(data)) - + license.DateOfBirth = parseDateV1(data) case "DBC": - // Sex can be stored as M/F if it uses the DLID code. It could // also be stored as 0/1/2/9 if it uses the ANSI D-20 codes, // available here: @@ -244,26 +211,22 @@ func parseDataV1(licenceData string, issuer string) (license *DLIDLicense, err e case "M": fallthrough case "1": - license.SetSex(DriverSexMale) + license.Sex = DriverSexMale case "F": fallthrough case "2": - license.SetSex(DriverSexFemale) + license.Sex = DriverSexFemale default: - license.SetSex(DriverSexNone) + license.Sex = DriverSexNone } - case "DBD": - license.SetIssueDate(parseDateV1(data)) - + license.IssueDate = parseDateV1(data) case "DBK": - // Optional and probably not available - license.SetSocialSecurityNumber(data) + license.SocialSecurityNumber = data } } - - return + return license, nil } func parseDateV1(data string) time.Time { @@ -286,7 +249,7 @@ func parseDateV1(data string) time.Time { return time.Unix(0, 0) } - location, err := time.LoadLocation("UTC") + location, _ := time.LoadLocation("UTC") return time.Date(year, time.Month(month), day, 0, 0, 0, 0, location) } diff --git a/dlidparser/parseV2.go b/dlidparser/parseV2.go index 1bfe23f..28b7efa 100644 --- a/dlidparser/parseV2.go +++ b/dlidparser/parseV2.go @@ -7,67 +7,57 @@ import ( "time" ) -func parseV2(data string, issuer string) (license *DLIDLicense, err error) { +func parseV2(data string, issuer string) (*DLIDLicense, error) { start, end, err := dataRangeV2(data) if end >= len(data) { - err = errors.New("Payload location does not exist in data") + return nil, errors.New("Payload location does not exist in data") } payload := data[start:end] if err != nil { - return + return nil, err } - - license, err = parseDataV2(payload, issuer) - - if err != nil { - return - } - - return + return parseDataV2(payload, issuer) } -func dataRangeV2(data string) (start int, end int, err error) { +func dataRangeV2(data string) (int, int, error) { - start, err = strconv.Atoi(data[23:27]) + start, err := strconv.Atoi(data[23:27]) if err != nil { - err = errors.New("Data contains malformed payload location") - return + return 0, 0, errors.New("Data contains malformed payload location") } - end, err = strconv.Atoi(data[27:31]) + end, err := strconv.Atoi(data[27:31]) if err != nil { - err = errors.New("Data contains malformed payload length") - return + return 0, 0, errors.New("Data contains malformed payload length") } end += start - return + return start, end, nil } -func parseDataV2(licenceData string, issuer string) (license *DLIDLicense, err error) { +func parseDataV2(licenceData string, issuer string) (*DLIDLicense, error) { // Version 1 of the DLID card spec was published in 2003. if !strings.HasPrefix(licenceData, "DL") { - err = errors.New("Missing header in licence data chunk") - return + return nil, errors.New("Missing header in licence data chunk") } licenceData = licenceData[2:] components := strings.Split(licenceData, "\n") - license = new(DLIDLicense) + license := &DLIDLicense{} - license.SetIssuerId(issuer) - license.SetIssuerName(issuers[issuer]) + license.IssuerID = issuer + license.IssuerName = issuers[issuer] for component := range components { @@ -82,16 +72,16 @@ func parseDataV2(licenceData string, issuer string) (license *DLIDLicense, err e switch identifier { case "DCA": - license.SetVehicleClass(data) + license.VehicleClass = data case "DCB": - license.SetRestrictionCodes(data) + license.RestrictionCodes = data case "DCD": - license.SetEndorsementCodes(data) + license.EndorsementCodes = data case "DCS": - license.SetLastName(data) + license.LastName = data case "DCT": @@ -109,29 +99,29 @@ func parseDataV2(licenceData string, issuer string) (license *DLIDLicense, err e names := strings.Split(data, separator) - license.SetFirstName(names[0]) + license.FirstName = names[0] if len(names) > 1 { - license.SetMiddleNames(names[1:]) + license.MiddleNames = names[1:] } case "DAG": - license.SetStreet(data) + license.Street = data case "DAI": - license.SetCity(data) + license.City = data case "DAJ": - license.SetState(data) + license.State = data case "DAK": - license.SetPostal(data) + license.Postal = data case "DAQ": - license.SetCustomerId(data) + license.CustomerID = data case "DBB": - license.SetDateOfBirth(parseDateV2(data)) + license.DateOfBirth = parseDateV2(data) case "DBC": @@ -141,16 +131,16 @@ func parseDataV2(licenceData string, issuer string) (license *DLIDLicense, err e switch data { case "1": - license.SetSex(DriverSexMale) + license.Sex = DriverSexMale case "2": - license.SetSex(DriverSexFemale) + license.Sex = DriverSexFemale default: - license.SetSex(DriverSexNone) + license.Sex = DriverSexNone } } } - return + return license, nil } func parseDateV2(data string) time.Time { diff --git a/dlidparser/parseV3.go b/dlidparser/parseV3.go index 6d055a2..2b0dcea 100644 --- a/dlidparser/parseV3.go +++ b/dlidparser/parseV3.go @@ -7,47 +7,46 @@ import ( "time" ) -func parseV3(data string, issuer string) (license *DLIDLicense, err error) { +func parseV3(data string, issuer string) (*DLIDLicense, error) { start, end, err := dataRangeV2(data) + if err != nil { + return nil, err + } if end >= len(data) { - err = errors.New("Payload location does not exist in data") + return nil, errors.New("Payload location does not exist in data") } payload := data[start:end] - if err != nil { - return - } - - license, err = parseDataV3(payload, issuer) + license, err := parseDataV3(payload, issuer) if err != nil { - return + return nil, err } - return + return license, nil } -func parseDataV3(licenceData string, issuer string) (license *DLIDLicense, err error) { +func parseDataV3(licenceData string, issuer string) (*DLIDLicense, error) { // Version 3 of the DLID card spec was published in 2005. It is currently // (as of 2012) used in Wisconsin. if !strings.HasPrefix(licenceData, "DL") { - err = errors.New("Missing header in licence data chunk") - return + err := errors.New("Missing header in licence data chunk") + return nil, err } licenceData = licenceData[2:] components := strings.Split(licenceData, "\n") - license = new(DLIDLicense) + license := &DLIDLicense{} - license.SetIssuerId(issuer) - license.SetIssuerName(issuers[issuer]) + license.IssuerID = issuer + license.IssuerName = issuers[issuer] var dateOfBirth string var expiryDate string @@ -66,22 +65,16 @@ func parseDataV3(licenceData string, issuer string) (license *DLIDLicense, err e switch identifier { case "DCA": - license.SetVehicleClass(data) - + license.VehicleClass = data case "DCB": - license.SetRestrictionCodes(data) - + license.RestrictionCodes = data case "DCD": - license.SetEndorsementCodes(data) - + license.EndorsementCodes = data case "DCS": - license.SetLastName(data) - + license.LastName = data case "DCG": - license.SetCountry(data) - + license.Country = data case "DCT": - // This field contains all of the licencee's names except last // name. The V3 spec doc doesn't specify how the names are // separated and doesn't provide an example (unlike the 2000 @@ -96,41 +89,38 @@ func parseDataV3(licenceData string, issuer string) (license *DLIDLicense, err e names := strings.Split(data, separator) - license.SetFirstName(names[0]) + license.FirstName = names[0] if len(names) > 1 { - license.SetMiddleNames(names[1:]) + license.MiddleNames = names[1:] } case "DAG": - license.SetStreet(data) + license.Street = data case "DAI": - license.SetCity(data) + license.City = data case "DAJ": - license.SetState(data) + license.State = data case "DAK": - license.SetPostal(data) + license.Postal = data case "DAQ": - license.SetCustomerId(data) - + license.CustomerID = data case "DBA": expiryDate = data - case "DBB": dateOfBirth = data - case "DBC": switch data { case "1": - license.SetSex(DriverSexMale) + license.Sex = DriverSexMale case "2": - license.SetSex(DriverSexFemale) + license.Sex = DriverSexFemale default: - license.SetSex(DriverSexNone) + license.Sex = DriverSexNone } case "DBD": @@ -142,7 +132,7 @@ func parseDataV3(licenceData string, issuer string) (license *DLIDLicense, err e // mandatory fields) so we can undo the desperate mess the standards body // made of the postal code field. - if license.Country() == "USA" && len(license.Postal()) > 0 { + if strings.Contains(license.Country, "USA") && len(license.Postal) > 0 { // For some reason known only to themselves, the standards guys took // the V1 and 2 postal code standards (code padded to 11 characters with @@ -159,26 +149,25 @@ func parseDataV3(licenceData string, issuer string) (license *DLIDLicense, err e // Naturally, some Texas licences ignore the spec and just use 5 // characters if they don't have a +4 section. - if len(license.Postal()) > 5 { - zip := license.Postal()[:5] - plus4 := license.Postal()[5:9] + if len(license.Postal) > 5 { + zip := license.Postal[:5] + plus4 := license.Postal[5:9] if plus4 == "0000" { - license.SetPostal(zip) + license.Postal = zip } else { - license.SetPostal(zip + "+" + plus4) + license.Postal = zip + "+" + plus4 } } } // Now we can parse the birth date, too. - if len(license.Country()) > 0 { - license.SetDateOfBirth(parseDateV3(dateOfBirth, license.Country())) - license.SetExpiryDate(parseDateV3(expiryDate, license.Country())) - license.SetIssueDate(parseDateV3(issueDate, license.Country())) + if len(license.Country) > 0 { + license.DateOfBirth = parseDateV3(dateOfBirth, license.Country) + license.ExpiryDate = parseDateV3(expiryDate, license.Country) + license.IssueDate = parseDateV3(issueDate, license.Country) } - - return + return license, nil } func parseDateV3(data string, country string) time.Time { @@ -197,7 +186,7 @@ func parseDateV3(data string, country string) time.Time { var err error var location *time.Location - if country == "USA" { + if strings.Contains(country, "USA") { month, err = strconv.Atoi(data[:2]) if err != nil { diff --git a/dlidparser/parseV4.go b/dlidparser/parseV4.go index 7be2710..ff72b28 100644 --- a/dlidparser/parseV4.go +++ b/dlidparser/parseV4.go @@ -5,7 +5,7 @@ import ( "strings" ) -func parseV4(data string, issuer string) (license *DLIDLicense, err error) { +func parseV4(data string, issuer string) (*DLIDLicense, error) { start, end, err := dataRangeV2(data) @@ -16,35 +16,28 @@ func parseV4(data string, issuer string) (license *DLIDLicense, err error) { payload := data[start:end] if err != nil { - return + return nil, err } - license, err = parseDataV4(payload, issuer) - - if err != nil { - return - } - - return + return parseDataV4(payload, issuer) } -func parseDataV4(licenceData string, issuer string) (license *DLIDLicense, err error) { +func parseDataV4(licenceData string, issuer string) (*DLIDLicense, error) { // Version 4 of the DLID card spec was published in 2009. if !strings.HasPrefix(licenceData, "DL") { - err = errors.New("Missing header in licence data chunk") - return + return nil, errors.New("Missing header in licence data chunk") } licenceData = licenceData[2:] components := strings.Split(licenceData, "\n") - license = new(DLIDLicense) + license := &DLIDLicense{} - license.SetIssuerId(issuer) - license.SetIssuerName(issuers[issuer]) + license.IssuerID = issuer + license.IssuerName = issuers[issuer] var dateOfBirth string var expiryDate string @@ -63,44 +56,44 @@ func parseDataV4(licenceData string, issuer string) (license *DLIDLicense, err e switch identifier { case "DCA": - license.SetVehicleClass(data) + license.VehicleClass = data case "DCB": - license.SetRestrictionCodes(data) + license.RestrictionCodes = data case "DCD": - license.SetEndorsementCodes(data) + license.EndorsementCodes = data case "DCS": - license.SetLastName(data) + license.LastName = data case "DCU": - license.SetNameSuffix(data) + license.NameSuffix = data case "DAC": - license.SetFirstName(data) + license.FirstName = data case "DAD": names := strings.Split(data, ",") - license.SetMiddleNames(names) + license.MiddleNames = names case "DCG": - license.SetCountry(data) + license.Country = data case "DAG": - license.SetStreet(data) + license.Street = data case "DAI": - license.SetCity(data) + license.City = data case "DAJ": - license.SetState(data) + license.State = data case "DAK": - license.SetPostal(data) + license.Postal = data case "DAQ": - license.SetCustomerId(data) + license.CustomerID = data case "DBA": expiryDate = data @@ -111,11 +104,11 @@ func parseDataV4(licenceData string, issuer string) (license *DLIDLicense, err e case "DBC": switch data { case "1": - license.SetSex(DriverSexMale) + license.Sex = DriverSexMale case "2": - license.SetSex(DriverSexFemale) + license.Sex = DriverSexFemale default: - license.SetSex(DriverSexNone) + license.Sex = DriverSexNone } case "DBD": @@ -127,7 +120,7 @@ func parseDataV4(licenceData string, issuer string) (license *DLIDLicense, err e // mandatory fields) so we can undo the desperate mess the standards body // made of the postal code field. - if license.Country() == "USA" && len(license.Postal()) > 0 { + if license.Country == "USA" && len(license.Postal) > 0 { // Another change to the postal code field! Surprise! This time the // standards guys trimmed the field down to 9 characters, which makes @@ -138,24 +131,24 @@ func parseDataV4(licenceData string, issuer string) (license *DLIDLicense, err e // We will extract the 5-digit zip and the +4 section. If the +4 is all // zeros we can discard it. - if len(license.Postal()) > 5 { - zip := license.Postal()[:5] - plus4 := license.Postal()[5:9] + if len(license.Postal) > 5 { + zip := license.Postal[:5] + plus4 := license.Postal[5:9] if plus4 == "0000" { - license.SetPostal(zip) + license.Postal = zip } else { - license.SetPostal(zip + "+" + plus4) + license.Postal = zip + "+" + plus4 } } } // Now we can parse the dates, too. - if len(license.Country()) > 0 { - license.SetDateOfBirth(parseDateV3(dateOfBirth, license.Country())) - license.SetExpiryDate(parseDateV3(expiryDate, license.Country())) - license.SetIssueDate(parseDateV3(issueDate, license.Country())) + if len(license.Country) > 0 { + license.DateOfBirth = parseDateV3(dateOfBirth, license.Country) + license.ExpiryDate = parseDateV3(expiryDate, license.Country) + license.IssueDate = parseDateV3(issueDate, license.Country) } - return + return license, nil } diff --git a/dlidparser/parser.go b/dlidparser/parser.go index 11522e9..8269c6f 100644 --- a/dlidparser/parser.go +++ b/dlidparser/parser.go @@ -5,7 +5,8 @@ import ( "strconv" ) -func Parse(data string) (license *DLIDLicense, err error) { +//Parse the data string from a pdf417 driver's license barcode +func Parse(data string) (*DLIDLicense, error) { // This parser is based on standards from here: // @@ -22,22 +23,23 @@ func Parse(data string) (license *DLIDLicense, err error) { // "AAMVA" instead of "ANSI " as part of the header. if len(data) < 15 { - return license, errors.New("Data does not contain expected header") + return nil, errors.New("Data does not contain expected header") } if data[0:2] != "@\n" || data[3] != '\r' || - (data[4:9] != "ANSI " && data[4:9] != "AAMVA") { - return license, errors.New("Data does not contain expected header") + (data[4:9] != "ANSI " && data[4:9] != "AAMVA") { + return nil, errors.New("Data does not contain expected header") } issuer := data[9:15] version, err := strconv.Atoi(data[15:17]) if err != nil { - return license, errors.New("Data does not contain a version number") + return nil, errors.New("Data does not contain a version number") } + var license *DLIDLicense switch version { case 1: license, err = parseV1(data, issuer) @@ -56,6 +58,5 @@ func Parse(data string) (license *DLIDLicense, err error) { default: err = errors.New("Unsupported DLID version number") } - - return + return license, err } diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..89365da --- /dev/null +++ b/go.mod @@ -0,0 +1 @@ +module github.com/derekg/DLID diff --git a/main.go b/main.go index b82ed59..cacff6d 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,12 @@ package main import ( - "github.com/ant512/DLID/dlidparser" + "fmt" + "io/ioutil" "log" + "os" + + "github.com/derekg/DLID/dlidparser" ) func main() { @@ -13,5 +17,18 @@ func main() { return } - log.Println(s) + fmt.Println() + fmt.Println(s) + if len(os.Args) > 1 { + data, err := ioutil.ReadFile(os.Args[1]) + if err != nil { + log.Fatal(err) + } + foo, err := dlidparser.Parse(string(data)) + if err != nil { + log.Fatal(err) + } + fmt.Println(foo) + } + } From 5f1946a0950eb5c8f8a44c304e52b0a9fa0a1821 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Wed, 29 May 2019 17:30:11 -0400 Subject: [PATCH 02/15] support for ID not just DL and versions 8 and 9 --- dlidparser/parseV4.go | 2 +- dlidparser/parser.go | 5 +++++ go.mod | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dlidparser/parseV4.go b/dlidparser/parseV4.go index ff72b28..185aa94 100644 --- a/dlidparser/parseV4.go +++ b/dlidparser/parseV4.go @@ -26,7 +26,7 @@ func parseDataV4(licenceData string, issuer string) (*DLIDLicense, error) { // Version 4 of the DLID card spec was published in 2009. - if !strings.HasPrefix(licenceData, "DL") { + if !strings.HasPrefix(licenceData, "DL") && !strings.HasPrefix(licenceData, "ID") { return nil, errors.New("Missing header in licence data chunk") } diff --git a/dlidparser/parser.go b/dlidparser/parser.go index 8269c6f..0f967ed 100644 --- a/dlidparser/parser.go +++ b/dlidparser/parser.go @@ -55,6 +55,11 @@ func Parse(data string) (*DLIDLicense, error) { fallthrough case 7: license, err = parseV4(data, issuer) + case 8: + license, err = parseV4(data, issuer) + case 9: + //aamva 09 is 2016 the latest spec - compat w/ the v4 + license, err = parseV4(data, issuer) default: err = errors.New("Unsupported DLID version number") } diff --git a/go.mod b/go.mod index 89365da..aa9ff0b 100644 --- a/go.mod +++ b/go.mod @@ -1 +1,3 @@ module github.com/derekg/DLID + +go 1.12 From a41d21e60bb57504e9c5fc298b12b516ee9d99bc Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Thu, 30 May 2019 16:58:13 -0400 Subject: [PATCH 03/15] fixes missing country code - MI doesn't follow specs --- dlidparser/parseV3.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dlidparser/parseV3.go b/dlidparser/parseV3.go index 2b0dcea..70cdb22 100644 --- a/dlidparser/parseV3.go +++ b/dlidparser/parseV3.go @@ -128,6 +128,12 @@ func parseDataV3(licenceData string, issuer string) (*DLIDLicense, error) { } } + //if empty default to USA - Michigan - doesn't set DCG - based on license issue 1.20.2017 + //without country - doesn't parse dates + if license.Country == "" { + license.Country = "USA" + } + // At this point we should know the country and the postal code (both are // mandatory fields) so we can undo the desperate mess the standards body // made of the postal code field. From e0bee2fc1acf1ba45531aff898cdffcbac3f1f77 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Wed, 3 Jul 2019 14:11:32 -0400 Subject: [PATCH 04/15] fix of TX dl that can't count well. --- dlidparser/parseV4.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dlidparser/parseV4.go b/dlidparser/parseV4.go index 185aa94..3167dc9 100644 --- a/dlidparser/parseV4.go +++ b/dlidparser/parseV4.go @@ -9,16 +9,15 @@ func parseV4(data string, issuer string) (*DLIDLicense, error) { start, end, err := dataRangeV2(data) - if end >= len(data) { + if end > len(data) { err = errors.New("Payload location does not exist in data") } - payload := data[start:end] - if err != nil { return nil, err } + payload := data[start:end] return parseDataV4(payload, issuer) } From 3c43baa3bb5a5b415563d3df083c07234b387042 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Sun, 28 Jul 2019 12:50:26 -0400 Subject: [PATCH 05/15] adjust for states that don't set offset correctly --- dlidparser/parseV2.go | 3 ++- dlidparser/parseV3.go | 3 ++- dlidparser/parseV4.go | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/dlidparser/parseV2.go b/dlidparser/parseV2.go index 28b7efa..ae407be 100644 --- a/dlidparser/parseV2.go +++ b/dlidparser/parseV2.go @@ -2,6 +2,7 @@ package dlidparser import ( "errors" + "fmt" "strconv" "strings" "time" @@ -34,7 +35,7 @@ func dataRangeV2(data string) (int, int, error) { end, err := strconv.Atoi(data[27:31]) if err != nil { - return 0, 0, errors.New("Data contains malformed payload length") + return 0, 0, errors.New(fmt.Sprintf("Data contains malformed payload length - %v", data[27:31])) } end += start diff --git a/dlidparser/parseV3.go b/dlidparser/parseV3.go index 70cdb22..751067e 100644 --- a/dlidparser/parseV3.go +++ b/dlidparser/parseV3.go @@ -15,7 +15,8 @@ func parseV3(data string, issuer string) (*DLIDLicense, error) { } if end >= len(data) { - return nil, errors.New("Payload location does not exist in data") + //lots of states don't count correct - VA i'm looking at you + end = len(data) - 1 } payload := data[start:end] diff --git a/dlidparser/parseV4.go b/dlidparser/parseV4.go index 3167dc9..e3a2970 100644 --- a/dlidparser/parseV4.go +++ b/dlidparser/parseV4.go @@ -10,7 +10,8 @@ func parseV4(data string, issuer string) (*DLIDLicense, error) { start, end, err := dataRangeV2(data) if end > len(data) { - err = errors.New("Payload location does not exist in data") + //lots of states don't count correct - VA i'm looking at you + end = len(data) - 1 } if err != nil { From 337d5d3b0fe9cc1214c7593b2ebae72112beb0f5 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Mon, 19 Aug 2019 22:25:23 -0400 Subject: [PATCH 06/15] crazy fixes --- dlidparser/parseV4.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/dlidparser/parseV4.go b/dlidparser/parseV4.go index e3a2970..e5141c6 100644 --- a/dlidparser/parseV4.go +++ b/dlidparser/parseV4.go @@ -1,7 +1,6 @@ package dlidparser import ( - "errors" "strings" ) @@ -9,10 +8,15 @@ func parseV4(data string, issuer string) (*DLIDLicense, error) { start, end, err := dataRangeV2(data) - if end > len(data) { - //lots of states don't count correct - VA i'm looking at you - end = len(data) - 1 - } + /* + if end > len(data) { + //lots of states don't count correct - VA i'm looking at you + end = len(data) - 1 + } + */ + + //license files don't really contain extra data + end = len(data) - 1 if err != nil { return nil, err @@ -26,9 +30,13 @@ func parseDataV4(licenceData string, issuer string) (*DLIDLicense, error) { // Version 4 of the DLID card spec was published in 2009. - if !strings.HasPrefix(licenceData, "DL") && !strings.HasPrefix(licenceData, "ID") { - return nil, errors.New("Missing header in licence data chunk") - } + /* + This would be nice but encdoing errors - SC 2014 issued - fail this + + if !strings.HasPrefix(licenceData, "DL") && !strings.HasPrefix(licenceData, "ID") { + return nil, errors.New("Missing header in licence data chunk") + } + */ licenceData = licenceData[2:] From 1c5a529a5fab375bb479aca082a0362e99ef8261 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Sun, 1 Sep 2019 11:53:50 -0400 Subject: [PATCH 07/15] hacks to fix CT/NC Identification Cards --- dlidparser/parseV1.go | 47 ++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/dlidparser/parseV1.go b/dlidparser/parseV1.go index 9b3fafe..7a274e9 100644 --- a/dlidparser/parseV1.go +++ b/dlidparser/parseV1.go @@ -2,6 +2,7 @@ package dlidparser import ( "errors" + "fmt" "strconv" "strings" "time" @@ -15,29 +16,20 @@ const southCarolinaIssuerID string = "636005" const tennesseeIssuerID string = "636053" func parseV1(data string, issuer string) (*DLIDLicense, error) { - - start, end, err := dataRangeV1(data) - - if issuer == illinoisIssuerID { - - // Illinois are the worst offenders so far in terms of mangling the DLID - // spec. They store name, licence number, expiry date and date of birth - // as expected, but then go all-out crazy and encrypt everything else. - // This means that the data range exceeds the size of the licence data - // string. We have to treat Illinois as a special case. - end = len(data) - 1 + start, _, _ := dataRangeV1(data) + if start == -1 { + start, _, _ = dataRangeV1(data) } - - if end >= len(data) { - return nil, errors.New("Payload location does not exist in data") + //yeah this is a hack + if start > len(data) && strings.Index(data, "DAB") != -1 { + start = strings.Index(data, "DAB") } - - payload := data[start:end] - - if err != nil { - return nil, err + if start > len(data) { + return nil, fmt.Errorf("couldn't find start of payload") } + end := len(data) - 1 + payload := data[start:end] return parseDataV1(payload, issuer) } @@ -52,11 +44,10 @@ func dataRangeV1(data string) (int, int, error) { end, err := strconv.Atoi(data[25:29]) if err != nil { - return 0, 0, errors.New("Data contains malformed payload length") + end = len(data) - 1 + } else { + end += start } - - end += start - return start, end, nil } @@ -224,6 +215,16 @@ func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { case "DBK": // Optional and probably not available license.SocialSecurityNumber = data + case "DAB": + license.LastName = data + case "DAC": + license.FirstName = data + case "DAD": + license.MiddleNames = []string{data} + /* + default: + fmt.Printf("Unknown: %v : %v\n", identifier, data) + */ } } return license, nil From 4594df3e4569539285303302d08ae9bddb4b9d48 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Tue, 11 Feb 2020 17:28:34 -0500 Subject: [PATCH 08/15] NH OPR license don't have the DL indentitfier --- dlidparser/parseV3.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/dlidparser/parseV3.go b/dlidparser/parseV3.go index 751067e..74eabb9 100644 --- a/dlidparser/parseV3.go +++ b/dlidparser/parseV3.go @@ -1,7 +1,6 @@ package dlidparser import ( - "errors" "strconv" "strings" "time" @@ -35,10 +34,12 @@ func parseDataV3(licenceData string, issuer string) (*DLIDLicense, error) { // Version 3 of the DLID card spec was published in 2005. It is currently // (as of 2012) used in Wisconsin. - if !strings.HasPrefix(licenceData, "DL") { - err := errors.New("Missing header in licence data chunk") - return nil, err - } + /* + if !strings.HasPrefix(licenceData, "DL") { + err := errors.New("Missing header in licence data chunk") + return nil, err + } + */ licenceData = licenceData[2:] From 1737f8e5af1cdd971bc421a803bcee214a6db87b Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Thu, 20 Feb 2020 15:58:07 -0500 Subject: [PATCH 09/15] fixed bounds checking on slices - oh canada --- dlidparser/parseV1.go | 4 ++++ dlidparser/parseV2.go | 6 ++++++ dlidparser/parseV3.go | 19 ++++++++++--------- dlidparser/parseV4.go | 16 +++++++--------- dlidparser/parser.go | 2 +- 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/dlidparser/parseV1.go b/dlidparser/parseV1.go index 7a274e9..a9f65b5 100644 --- a/dlidparser/parseV1.go +++ b/dlidparser/parseV1.go @@ -232,6 +232,10 @@ func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { func parseDateV1(data string) time.Time { + if len(data) != 8 { + return time.Unix(0, 0) + } + year, err := strconv.Atoi(data[:4]) if err != nil { diff --git a/dlidparser/parseV2.go b/dlidparser/parseV2.go index ae407be..15964c1 100644 --- a/dlidparser/parseV2.go +++ b/dlidparser/parseV2.go @@ -26,6 +26,9 @@ func parseV2(data string, issuer string) (*DLIDLicense, error) { func dataRangeV2(data string) (int, int, error) { + if len(data) < 31 { + return 0, 0, errors.New("Data is short") + } start, err := strconv.Atoi(data[23:27]) if err != nil { @@ -149,6 +152,9 @@ func parseDateV2(data string) time.Time { // Sooo, let me get this straight. They switched from a reasonably-standard // and universal date format (yyyyMMdd) to the bizarre US lumpy format // (MMddyyyy)? What were they thinking!? + if len(data) != 8 { + return time.Unix(0, 0) + } month, err := strconv.Atoi(data[:2]) diff --git a/dlidparser/parseV3.go b/dlidparser/parseV3.go index 74eabb9..9cde359 100644 --- a/dlidparser/parseV3.go +++ b/dlidparser/parseV3.go @@ -140,7 +140,7 @@ func parseDataV3(licenceData string, issuer string) (*DLIDLicense, error) { // mandatory fields) so we can undo the desperate mess the standards body // made of the postal code field. - if strings.Contains(license.Country, "USA") && len(license.Postal) > 0 { + if strings.Contains(license.Country, "USA") && len(strings.TrimSpace(license.Postal)) == 9 { // For some reason known only to themselves, the standards guys took // the V1 and 2 postal code standards (code padded to 11 characters with @@ -157,15 +157,13 @@ func parseDataV3(licenceData string, issuer string) (*DLIDLicense, error) { // Naturally, some Texas licences ignore the spec and just use 5 // characters if they don't have a +4 section. - if len(license.Postal) > 5 { - zip := license.Postal[:5] - plus4 := license.Postal[5:9] + zip := license.Postal[:5] + plus4 := license.Postal[5:9] - if plus4 == "0000" { - license.Postal = zip - } else { - license.Postal = zip + "+" + plus4 - } + if plus4 == "0000" { + license.Postal = zip + } else { + license.Postal = zip + "+" + plus4 } } @@ -194,6 +192,9 @@ func parseDateV3(data string, country string) time.Time { var err error var location *time.Location + if len(data) != 8 { + return time.Unix(0, 0) + } if strings.Contains(country, "USA") { month, err = strconv.Atoi(data[:2]) diff --git a/dlidparser/parseV4.go b/dlidparser/parseV4.go index e5141c6..d7d4c56 100644 --- a/dlidparser/parseV4.go +++ b/dlidparser/parseV4.go @@ -128,7 +128,7 @@ func parseDataV4(licenceData string, issuer string) (*DLIDLicense, error) { // mandatory fields) so we can undo the desperate mess the standards body // made of the postal code field. - if license.Country == "USA" && len(license.Postal) > 0 { + if license.Country == "USA" && len(strings.TrimSpace(license.Postal)) == 9 { // Another change to the postal code field! Surprise! This time the // standards guys trimmed the field down to 9 characters, which makes @@ -139,15 +139,13 @@ func parseDataV4(licenceData string, issuer string) (*DLIDLicense, error) { // We will extract the 5-digit zip and the +4 section. If the +4 is all // zeros we can discard it. - if len(license.Postal) > 5 { - zip := license.Postal[:5] - plus4 := license.Postal[5:9] + zip := license.Postal[:5] + plus4 := license.Postal[5:9] - if plus4 == "0000" { - license.Postal = zip - } else { - license.Postal = zip + "+" + plus4 - } + if plus4 == "0000" { + license.Postal = zip + } else { + license.Postal = zip + "+" + plus4 } } diff --git a/dlidparser/parser.go b/dlidparser/parser.go index 0f967ed..40376d6 100644 --- a/dlidparser/parser.go +++ b/dlidparser/parser.go @@ -22,7 +22,7 @@ func Parse(data string) (*DLIDLicense, error) { // PA and CT appear to have used old versions of the spec because they use // "AAMVA" instead of "ANSI " as part of the header. - if len(data) < 15 { + if len(data) < 17 { return nil, errors.New("Data does not contain expected header") } From 9568fba6cc8c33050f7ec973ce149aec09dc60ee Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Thu, 5 Mar 2020 15:33:37 -0500 Subject: [PATCH 10/15] fixes for OR/AZ and older licenses --- dlidparser/parseV2.go | 2 +- dlidparser/parser.go | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/dlidparser/parseV2.go b/dlidparser/parseV2.go index 15964c1..c64bb59 100644 --- a/dlidparser/parseV2.go +++ b/dlidparser/parseV2.go @@ -38,7 +38,7 @@ func dataRangeV2(data string) (int, int, error) { end, err := strconv.Atoi(data[27:31]) if err != nil { - return 0, 0, errors.New(fmt.Sprintf("Data contains malformed payload length - %v", data[27:31])) + return 0, 0, errors.New(fmt.Sprintf("Data contains malformed payload length -%v %v", start, data[27:31])) } end += start diff --git a/dlidparser/parser.go b/dlidparser/parser.go index 40376d6..f5cdd4b 100644 --- a/dlidparser/parser.go +++ b/dlidparser/parser.go @@ -2,7 +2,9 @@ package dlidparser import ( "errors" + "fmt" "strconv" + "strings" ) //Parse the data string from a pdf417 driver's license barcode @@ -23,13 +25,21 @@ func Parse(data string) (*DLIDLicense, error) { // "AAMVA" instead of "ANSI " as part of the header. if len(data) < 17 { - return nil, errors.New("Data does not contain expected header") + return nil, errors.New("Data does not contain expected header - ") + } + + if strings.HasPrefix(data, "@\n\u001e\rANSI6") { + data = strings.Replace(data, "ANSI6", "ANSI 6", 1) + } + //OREGON / AZ + if data[0:8] == "@\r\nANSI " { + data = "@\n\u001e\rANSI " + data[8:] } if data[0:2] != "@\n" || data[3] != '\r' || (data[4:9] != "ANSI " && data[4:9] != "AAMVA") { - return nil, errors.New("Data does not contain expected header") + return nil, fmt.Errorf("Data does not contain expected header %v", string(data[4:9])) } issuer := data[9:15] From 3ccb6ea600ab5a994548cf3666b35a51e2a9ce45 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Wed, 11 Mar 2020 12:13:02 -0400 Subject: [PATCH 11/15] fix for AZ license circa 2009 --- dlidparser/parser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlidparser/parser.go b/dlidparser/parser.go index f5cdd4b..e3dcc07 100644 --- a/dlidparser/parser.go +++ b/dlidparser/parser.go @@ -32,7 +32,7 @@ func Parse(data string) (*DLIDLicense, error) { data = strings.Replace(data, "ANSI6", "ANSI 6", 1) } //OREGON / AZ - if data[0:8] == "@\r\nANSI " { + if data[0:8] == "@\r\nANSI " || data[0:8] == "@\n\rANSI " /* for AZ circa 2009 licenses */ { data = "@\n\u001e\rANSI " + data[8:] } From cc49a1dedc35444a047576d92b84b161391f2744 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Wed, 8 Apr 2020 17:36:59 -0400 Subject: [PATCH 12/15] fixes for names in MN, dates in WY and WV --- dlidparser/dlidlicense.go | 1 + dlidparser/parseV1.go | 21 ++++++++++++++------- dlidparser/parseV2.go | 4 +--- dlidparser/parseV3.go | 5 +---- dlidparser/parseV4.go | 6 +++++- dlidparser/parser.go | 6 ++++++ 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/dlidparser/dlidlicense.go b/dlidparser/dlidlicense.go index 0e8c1f7..c7bc3d4 100644 --- a/dlidparser/dlidlicense.go +++ b/dlidparser/dlidlicense.go @@ -38,6 +38,7 @@ type DLIDLicense struct { EndorsementCodes string `json:"endorsement_codes,omitempty"` CustomerID string `json:"customer_id,omitempty"` DocumentDiscriminator string `json:"document_discriminator,omitempty"` + AAMVAVersion int `json:"aamva_version,omitempty"` } func (d DLIDLicense) String() string { diff --git a/dlidparser/parseV1.go b/dlidparser/parseV1.go index a9f65b5..aa778bd 100644 --- a/dlidparser/parseV1.go +++ b/dlidparser/parseV1.go @@ -14,6 +14,7 @@ const illinoisIssuerID string = "636035" const massachusettsIssuerID string = "636002" const southCarolinaIssuerID string = "636005" const tennesseeIssuerID string = "636053" +const minnIssuerID string = "636038" func parseV1(data string, issuer string) (*DLIDLicense, error) { start, _, _ := dataRangeV1(data) @@ -91,6 +92,9 @@ func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { // Country is always USA for V1 licenses license.Country = "USA" + expire := "" + issue := "" + dob := "" for component := range components { @@ -126,7 +130,7 @@ func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { // // http://www.aamva.org/IIN-and-RID/ - if issuer == coloradoIssuerID || issuer == tennesseeIssuerID { + if issuer == coloradoIssuerID || issuer == tennesseeIssuerID || issuer == minnIssuerID { // Colorado's backwards formatting style... license.FirstName = names[0] @@ -188,9 +192,9 @@ func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { case "DAQ": license.CustomerID = data case "DBA": - license.ExpiryDate = parseDateV1(data) + expire = data case "DBB": - license.DateOfBirth = parseDateV1(data) + dob = data case "DBC": // Sex can be stored as M/F if it uses the DLID code. It could // also be stored as 0/1/2/9 if it uses the ANSI D-20 codes, @@ -211,7 +215,7 @@ func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { license.Sex = DriverSexNone } case "DBD": - license.IssueDate = parseDateV1(data) + issue = data case "DBK": // Optional and probably not available license.SocialSecurityNumber = data @@ -227,6 +231,11 @@ func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { */ } } + + license.ExpiryDate = parseDateV1(expire) + license.DateOfBirth = parseDateV1(dob) + license.IssueDate = parseDateV1(issue) + return license, nil } @@ -254,7 +263,5 @@ func parseDateV1(data string) time.Time { return time.Unix(0, 0) } - location, _ := time.LoadLocation("UTC") - - return time.Date(year, time.Month(month), day, 0, 0, 0, 0, location) + return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) } diff --git a/dlidparser/parseV2.go b/dlidparser/parseV2.go index c64bb59..189d936 100644 --- a/dlidparser/parseV2.go +++ b/dlidparser/parseV2.go @@ -174,7 +174,5 @@ func parseDateV2(data string) time.Time { return time.Unix(0, 0) } - location, err := time.LoadLocation("UTC") - - return time.Date(year, time.Month(month), day, 0, 0, 0, 0, location) + return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) } diff --git a/dlidparser/parseV3.go b/dlidparser/parseV3.go index 9cde359..66dcc3e 100644 --- a/dlidparser/parseV3.go +++ b/dlidparser/parseV3.go @@ -190,7 +190,6 @@ func parseDateV3(data string, country string) time.Time { var month int var year int var err error - var location *time.Location if len(data) != 8 { return time.Unix(0, 0) @@ -233,7 +232,5 @@ func parseDateV3(data string, country string) time.Time { } } - location, err = time.LoadLocation("UTC") - - return time.Date(year, time.Month(month), day, 0, 0, 0, 0, location) + return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) } diff --git a/dlidparser/parseV4.go b/dlidparser/parseV4.go index d7d4c56..3a59e63 100644 --- a/dlidparser/parseV4.go +++ b/dlidparser/parseV4.go @@ -149,7 +149,11 @@ func parseDataV4(licenceData string, issuer string) (*DLIDLicense, error) { } } - // Now we can parse the dates, too. + if license.IssuerName == "Wyoming" || license.IssuerName == "West Virginia" { + license.DateOfBirth = parseDateV3(dateOfBirth, "CANADA") + license.ExpiryDate = parseDateV3(expiryDate, "CANADA") + license.IssueDate = parseDateV3(issueDate, "CANADA") + } else // Now we can parse the dates, too. if len(license.Country) > 0 { license.DateOfBirth = parseDateV3(dateOfBirth, license.Country) license.ExpiryDate = parseDateV3(expiryDate, license.Country) diff --git a/dlidparser/parser.go b/dlidparser/parser.go index e3dcc07..579eef9 100644 --- a/dlidparser/parser.go +++ b/dlidparser/parser.go @@ -53,10 +53,13 @@ func Parse(data string) (*DLIDLicense, error) { switch version { case 1: license, err = parseV1(data, issuer) + license.AAMVAVersion = 1 case 2: license, err = parseV2(data, issuer) + license.AAMVAVersion = 2 case 3: license, err = parseV3(data, issuer) + license.AAMVAVersion = 3 case 4: fallthrough case 5: @@ -65,11 +68,14 @@ func Parse(data string) (*DLIDLicense, error) { fallthrough case 7: license, err = parseV4(data, issuer) + license.AAMVAVersion = 7 case 8: license, err = parseV4(data, issuer) + license.AAMVAVersion = 8 case 9: //aamva 09 is 2016 the latest spec - compat w/ the v4 license, err = parseV4(data, issuer) + license.AAMVAVersion = 9 default: err = errors.New("Unsupported DLID version number") } From 04b820cece0d25b2671671d211c240569ddb4630 Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Thu, 9 Apr 2020 10:35:17 -0400 Subject: [PATCH 13/15] fix moron mistake of not checking for nil pointer --- dlidparser/parser.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/dlidparser/parser.go b/dlidparser/parser.go index 579eef9..0357bae 100644 --- a/dlidparser/parser.go +++ b/dlidparser/parser.go @@ -53,13 +53,19 @@ func Parse(data string) (*DLIDLicense, error) { switch version { case 1: license, err = parseV1(data, issuer) - license.AAMVAVersion = 1 + if license != nil { + license.AAMVAVersion = 1 + } case 2: license, err = parseV2(data, issuer) - license.AAMVAVersion = 2 + if license != nil { + license.AAMVAVersion = 2 + } case 3: license, err = parseV3(data, issuer) - license.AAMVAVersion = 3 + if license != nil { + license.AAMVAVersion = 3 + } case 4: fallthrough case 5: @@ -68,14 +74,20 @@ func Parse(data string) (*DLIDLicense, error) { fallthrough case 7: license, err = parseV4(data, issuer) - license.AAMVAVersion = 7 + if license != nil { + license.AAMVAVersion = 7 + } case 8: license, err = parseV4(data, issuer) - license.AAMVAVersion = 8 + if license != nil { + license.AAMVAVersion = 8 + } case 9: //aamva 09 is 2016 the latest spec - compat w/ the v4 license, err = parseV4(data, issuer) - license.AAMVAVersion = 9 + if license != nil { + license.AAMVAVersion = 9 + } default: err = errors.New("Unsupported DLID version number") } From 6784a53b121460d78e4a673b65417b1f68c14bde Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Sat, 11 Jul 2020 21:39:50 -0400 Subject: [PATCH 14/15] fixes for older NC driver's licenses --- dlidparser/parseV1.go | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/dlidparser/parseV1.go b/dlidparser/parseV1.go index aa778bd..b0887b6 100644 --- a/dlidparser/parseV1.go +++ b/dlidparser/parseV1.go @@ -240,28 +240,19 @@ func parseDataV1(licenceData string, issuer string) (*DLIDLicense, error) { } func parseDateV1(data string) time.Time { - - if len(data) != 8 { + var format string + switch len(data) { + case 8: + format = "20060102" + case 10: //odd NC vintage 2008 edition licenses + format = "01-02-2006" + default: return time.Unix(0, 0) } - year, err := strconv.Atoi(data[:4]) - - if err != nil { - return time.Unix(0, 0) - } - - month, err := strconv.Atoi(data[4:6]) - + d, err := time.Parse(format, data) if err != nil { return time.Unix(0, 0) } - - day, err := strconv.Atoi(data[6:8]) - - if err != nil { - return time.Unix(0, 0) - } - - return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) + return d } From 522b2e8d10b0e35eeb00888e0f46e3a43c6ca18f Mon Sep 17 00:00:00 2001 From: Derek Gottfrid Date: Tue, 4 Aug 2020 23:04:07 -0400 Subject: [PATCH 15/15] use time.Parse and have format fallbacks --- dlidparser/parseV2.go | 19 ++-------------- dlidparser/parseV3.go | 50 +++++++------------------------------------ dlidparser/parseV4.go | 2 +- 3 files changed, 11 insertions(+), 60 deletions(-) diff --git a/dlidparser/parseV2.go b/dlidparser/parseV2.go index 189d936..5ea3f2d 100644 --- a/dlidparser/parseV2.go +++ b/dlidparser/parseV2.go @@ -155,24 +155,9 @@ func parseDateV2(data string) time.Time { if len(data) != 8 { return time.Unix(0, 0) } - - month, err := strconv.Atoi(data[:2]) - - if err != nil { - return time.Unix(0, 0) - } - - day, err := strconv.Atoi(data[2:4]) - + t, err := time.Parse("01022006", data) if err != nil { return time.Unix(0, 0) } - - year, err := strconv.Atoi(data[4:8]) - - if err != nil { - return time.Unix(0, 0) - } - - return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) + return t } diff --git a/dlidparser/parseV3.go b/dlidparser/parseV3.go index 66dcc3e..387fc18 100644 --- a/dlidparser/parseV3.go +++ b/dlidparser/parseV3.go @@ -1,7 +1,6 @@ package dlidparser import ( - "strconv" "strings" "time" ) @@ -186,51 +185,18 @@ func parseDateV3(data string, country string) time.Time { // implementations of a standard within a single field in a single version // of the standard. Breathtakingly stupid. - var day int - var month int - var year int - var err error - if len(data) != 8 { return time.Unix(0, 0) } + order := []string{"20060102", "01022006"} if strings.Contains(country, "USA") { - month, err = strconv.Atoi(data[:2]) - - if err != nil { - return time.Unix(0, 0) - } - - day, err = strconv.Atoi(data[2:4]) - - if err != nil { - return time.Unix(0, 0) - } - - year, err = strconv.Atoi(data[4:8]) - - if err != nil { - return time.Unix(0, 0) - } - } else { - year, err = strconv.Atoi(data[:4]) - - if err != nil { - return time.Unix(0, 0) - } - - month, err = strconv.Atoi(data[4:6]) - - if err != nil { - return time.Unix(0, 0) - } - - day, err = strconv.Atoi(data[6:8]) - - if err != nil { - return time.Unix(0, 0) + order = []string{"01022006", "20060102"} + } + for _, format := range order { + t, err := time.Parse(format, data) + if err == nil { + return t } } - - return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) + return time.Unix(0, 0) } diff --git a/dlidparser/parseV4.go b/dlidparser/parseV4.go index 3a59e63..dbfbd51 100644 --- a/dlidparser/parseV4.go +++ b/dlidparser/parseV4.go @@ -149,7 +149,7 @@ func parseDataV4(licenceData string, issuer string) (*DLIDLicense, error) { } } - if license.IssuerName == "Wyoming" || license.IssuerName == "West Virginia" { + if license.IssuerName == "Wyoming" || (license.IssuerName == "West Virginia") { license.DateOfBirth = parseDateV3(dateOfBirth, "CANADA") license.ExpiryDate = parseDateV3(expiryDate, "CANADA") license.IssueDate = parseDateV3(issueDate, "CANADA")