Skip to content

Commit 8299421

Browse files
committed
Remove cardholder name from card scan data and parsing
OCR-based name detection is unreliable and inconsistent per Design team decision. Remove the field, regex, and related tests.
1 parent 65e6bd2 commit 8299421

3 files changed

Lines changed: 0 additions & 87 deletions

File tree

ui/src/main/kotlin/com/bitwarden/ui/platform/feature/cardscanner/util/CardDataParserImpl.kt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ private val EXPIRY_REGEX = Regex("""\b(0[1-9]|1[0-2])\s?[/\-]\s?(\d{2}|\d{4})\b"
77
private val CVV3_REGEX = Regex("""\b\d{3}\b""")
88
private val CVV4_REGEX = Regex("""\b\d{4}\b""")
99

10-
private val NAME_REGEX = Regex("""^[A-Z][A-Z .'-]+$""")
11-
1210
/**
1311
* Default [CardDataParser] implementation that uses regex patterns
1412
* and Luhn validation to extract card details from OCR text.
@@ -49,13 +47,10 @@ class CardDataParserImpl : CardDataParser {
4947
}
5048
?.value
5149

52-
val cardholderName = extractCardholderName(text)
53-
5450
return listOfNotNull(
5551
number,
5652
expirationMonth,
5753
expirationYear,
58-
cardholderName,
5954
securityCode,
6055
)
6156
.takeIf { it.isNotEmpty() }
@@ -64,16 +59,8 @@ class CardDataParserImpl : CardDataParser {
6459
number = number,
6560
expirationMonth = expirationMonth,
6661
expirationYear = expirationYear,
67-
cardholderName = cardholderName,
6862
securityCode = securityCode,
6963
)
7064
}
7165
}
7266
}
73-
74-
@Suppress("MagicNumber")
75-
private fun extractCardholderName(text: String): String? =
76-
text.lines()
77-
.map { it.trim() }
78-
.filter { it.length > 3 }
79-
.firstOrNull { NAME_REGEX.matches(it) }

ui/src/main/kotlin/com/bitwarden/ui/platform/feature/cardscanner/util/CardScanData.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,16 @@ package com.bitwarden.ui.platform.feature.cardscanner.util
66
* @property number The detected card number.
77
* @property expirationMonth The detected expiration month (01-12).
88
* @property expirationYear The detected expiration year.
9-
* @property cardholderName The detected cardholder name.
109
* @property securityCode The detected security code.
1110
*/
1211
data class CardScanData(
1312
val number: String?,
1413
val expirationMonth: String?,
1514
val expirationYear: String?,
16-
val cardholderName: String?,
1715
val securityCode: String?,
1816
) {
1917
override fun toString(): String = "CardScanData(number=****," +
2018
" expirationMonth=$expirationMonth," +
2119
" expirationYear=$expirationYear," +
22-
" cardholderName=****," +
2320
" securityCode=****)"
2421
}

ui/src/test/kotlin/com/bitwarden/ui/platform/feature/cardscanner/util/CardDataParserImplTest.kt

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class CardDataParserImplTest {
1616
number = "4111111111111111",
1717
expirationMonth = "12",
1818
expirationYear = "2025",
19-
cardholderName = null,
2019
securityCode = null,
2120
),
2221
parser.parseCardData(text),
@@ -31,7 +30,6 @@ class CardDataParserImplTest {
3130
number = null,
3231
expirationMonth = "12",
3332
expirationYear = "2025",
34-
cardholderName = null,
3533
securityCode = null,
3634
),
3735
parser.parseCardData(text),
@@ -46,7 +44,6 @@ class CardDataParserImplTest {
4644
number = "4111111111111111",
4745
expirationMonth = "06",
4846
expirationYear = "2028",
49-
cardholderName = null,
5047
securityCode = null,
5148
),
5249
parser.parseCardData(text),
@@ -61,7 +58,6 @@ class CardDataParserImplTest {
6158
number = "4111111111111111",
6259
expirationMonth = "12",
6360
expirationYear = "2025",
64-
cardholderName = null,
6561
securityCode = "789",
6662
),
6763
parser.parseCardData(text),
@@ -76,7 +72,6 @@ class CardDataParserImplTest {
7672
number = "4111111111111111",
7773
expirationMonth = "12",
7874
expirationYear = "2025",
79-
cardholderName = null,
8075
securityCode = null,
8176
),
8277
parser.parseCardData(text),
@@ -95,7 +90,6 @@ class CardDataParserImplTest {
9590
number = "4111111111111111",
9691
expirationMonth = "12",
9792
expirationYear = "2025",
98-
cardholderName = null,
9993
securityCode = null,
10094
),
10195
parser.parseCardData(text),
@@ -110,7 +104,6 @@ class CardDataParserImplTest {
110104
number = "4111111111111111",
111105
expirationMonth = "12",
112106
expirationYear = "2025",
113-
cardholderName = null,
114107
securityCode = null,
115108
),
116109
parser.parseCardData(text),
@@ -130,7 +123,6 @@ class CardDataParserImplTest {
130123
number = "4111111111111111",
131124
expirationMonth = "12",
132125
expirationYear = "2025",
133-
cardholderName = null,
134126
securityCode = "456",
135127
),
136128
parser.parseCardData(text),
@@ -145,70 +137,12 @@ class CardDataParserImplTest {
145137
number = "378282246310005",
146138
expirationMonth = "09",
147139
expirationYear = "2026",
148-
cardholderName = null,
149140
securityCode = "1234",
150141
),
151142
parser.parseCardData(text),
152143
)
153144
}
154145

155-
@Test
156-
fun `parseCardData extracts cardholder name in all caps`() {
157-
val text = """
158-
JOHN DOE
159-
4111 1111 1111 1111
160-
12/25
161-
""".trimIndent()
162-
assertEquals(
163-
CardScanData(
164-
number = "4111111111111111",
165-
expirationMonth = "12",
166-
expirationYear = "2025",
167-
cardholderName = "JOHN DOE",
168-
securityCode = null,
169-
),
170-
parser.parseCardData(text),
171-
)
172-
}
173-
174-
@Test
175-
fun `parseCardData does not extract lowercase name`() {
176-
val text = """
177-
John Doe
178-
4111 1111 1111 1111
179-
12/25
180-
""".trimIndent()
181-
assertEquals(
182-
CardScanData(
183-
number = "4111111111111111",
184-
expirationMonth = "12",
185-
expirationYear = "2025",
186-
cardholderName = null,
187-
securityCode = null,
188-
),
189-
parser.parseCardData(text),
190-
)
191-
}
192-
193-
@Test
194-
fun `parseCardData does not extract short names`() {
195-
val text = """
196-
JD
197-
4111 1111 1111 1111
198-
12/25
199-
""".trimIndent()
200-
assertEquals(
201-
CardScanData(
202-
number = "4111111111111111",
203-
expirationMonth = "12",
204-
expirationYear = "2025",
205-
cardholderName = null,
206-
securityCode = null,
207-
),
208-
parser.parseCardData(text),
209-
)
210-
}
211-
212146
@Test
213147
fun `parseCardData returns null when no card data is found`() {
214148
assertNull(parser.parseCardData("Hello world, no card here"))
@@ -222,7 +156,6 @@ class CardDataParserImplTest {
222156
number = "4111111111111111",
223157
expirationMonth = "03",
224158
expirationYear = "2027",
225-
cardholderName = null,
226159
securityCode = null,
227160
),
228161
parser.parseCardData(text),
@@ -237,7 +170,6 @@ class CardDataParserImplTest {
237170
number = "4111111111111111",
238171
expirationMonth = "12",
239172
expirationYear = "2025",
240-
cardholderName = null,
241173
// Visa expects 3-digit CVV, so "1234" should not match
242174
securityCode = null,
243175
),
@@ -253,7 +185,6 @@ class CardDataParserImplTest {
253185
number = "378282246310005",
254186
expirationMonth = "09",
255187
expirationYear = "2026",
256-
cardholderName = null,
257188
// Amex expects 4-digit CID, so "789" should not match
258189
securityCode = null,
259190
),
@@ -269,7 +200,6 @@ class CardDataParserImplTest {
269200
number = "4111111111111111",
270201
expirationMonth = "12",
271202
expirationYear = "2025",
272-
cardholderName = null,
273203
securityCode = "321",
274204
),
275205
parser.parseCardData(text),
@@ -287,7 +217,6 @@ class CardDataParserImplTest {
287217
number = null,
288218
expirationMonth = "12",
289219
expirationYear = "2025",
290-
cardholderName = null,
291220
securityCode = "789",
292221
),
293222
parser.parseCardData(text),

0 commit comments

Comments
 (0)