001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2023 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.iso;
020
021import java.io.PrintStream;
022
023import org.jpos.util.Loggeable;
024
025@SuppressWarnings("unused")
026public class PosDataCode extends PosFlags implements Loggeable {
027    public enum ReadingMethod implements Flag {
028        UNKNOWN                (1, "Unknown"),
029        CONTACTLESS            (1 << 1, "Information not taken from card"),  // i.e.: RFID
030        PHYSICAL               (1 << 2, "Physical entry"),                   // i.e.: Manual Entry or OCR
031        BARCODE                (1 << 3, "Bar code"),
032        MAGNETIC_STRIPE        (1 << 4, "Magnetic Stripe"),
033        ICC                    (1 << 5, "ICC"),
034        DATA_ON_FILE           (1 << 6, "Data on file"),
035        ICC_FAILED             (1 << 11, "ICC read but failed"),
036        MAGNETIC_STRIPE_FAILED (1 << 12, "Magnetic Stripe read but failed"),
037        FALLBACK               (1 << 13, "Fallback"),
038        TRACK1_PRESENT         (1 << 27, "Track1 data present"), // jCard private field
039        TRACK2_PRESENT         (1 << 28, "Track2 data present"); // jCard private field
040
041        private int val;
042        private String description;
043        ReadingMethod (int val, String description) {
044            this.val = val;
045            this.description = description;
046        }
047        public int intValue() {
048            return val;
049        }
050        public String toString () {
051            return description;
052        }
053
054        public static int OFFSET = 0;
055        @Override
056        public int getOffset() {
057            return OFFSET;
058        }
059    }
060    public enum VerificationMethod implements Flag {
061        UNKNOWN                              (1, "Unknown"),
062        NONE                                 (1 << 1, "None"),
063        MANUAL_SIGNATURE                     (1 << 2, "Manual signature"),
064        ONLINE_PIN                           (1 << 3, "Online PIN"),
065        OFFLINE_PIN_IN_CLEAR                 (1 << 4, "Offline PIN in clear"),
066        OFFLINE_PIN_ENCRYPTED                (1 << 5, "Offline PIN encrypted"),
067        OFFLINE_DIGITIZED_SIGNATURE_ANALYSIS (1 << 6, "Offline digitized signature analysis"),
068        OFFLINE_BIOMETRICS                   (1 << 7, "Offline biometrics"),
069        OFFLINE_MANUAL_VERIFICATION          (1 << 8, "Offline manual verification"),
070        OFFLINE_BIOGRAPHICS                  (1 << 9, "Offline biographics"),
071        ACCOUNT_BASED_DIGITAL_SIGNATURE      (1 << 10, "Account based digital signature"),
072        PUBLIC_KEY_BASED_DIGITAL_SIGNATURE   (1 << 11, "Public key based digital signature");
073
074        private int val;
075        private String description;
076        VerificationMethod (int val, String description) {
077            this.val = val;
078            this.description = description;
079        }
080        public int intValue() {
081            return val;
082        }
083        public String toString () {
084            return description;
085        }
086
087        public static int OFFSET = 4;
088        @Override
089        public int getOffset() {
090            return OFFSET;
091        }
092    }
093    public enum POSEnvironment implements Flag {
094        UNKNOWN                 (1, "Unknown"),
095        ATTENDED                (1 << 1, "Attended POS"),
096        UNATTENDED              (1 << 2, "Unattended, details unknown"),
097        MOTO                    (1 << 3, "Mail order / telephone order"),
098        E_COMMERCE              (1 << 4, "E-Commerce"),
099        M_COMMERCE              (1 << 5, "M-Commerce"),
100        RECURRING               (1 << 6, "Recurring transaction"),
101        STORED_DETAILS          (1 << 7, "Stored details"),
102        CAT                     (1 << 8, "Cardholder Activated Terminal"),
103        ATM_ON_BANK             (1 << 9, "ATM on bank premises"),
104        ATM_OFF_BANK            (1 << 10, "ATM off bank premises"),
105        DEFERRED_TRANSACTION    (1 << 11, "Deferred transaction"),
106        INSTALLMENT_TRANSACTION (1 << 12, "Installment transaction");
107
108        private int val;
109        private String description;
110        POSEnvironment (int val, String description) {
111            this.val = val;
112            this.description = description;
113        }
114        public int intValue() {
115            return val;
116        }
117        public String toString () {
118            return description;
119        }
120
121
122        public static int OFFSET = 8;
123        @Override
124        public int getOffset() {
125            return OFFSET;
126        }
127    }
128
129    public enum SecurityCharacteristic implements Flag {
130        UNKNOWN                                      (1, "Unknown"),
131        PRIVATE_NETWORK                              (1 << 1, "Private network"),
132        OPEN_NETWORK                                 (1 << 2, "Open network (Internet)"),
133        CHANNEL_MACING                               (1 << 3, "Channel MACing"),
134        PASS_THROUGH_MACING                          (1 << 4, "Pass through MACing"),
135        CHANNEL_ENCRYPTION                           (1 << 5, "Channel encryption"),
136        END_TO_END_ENCRYPTION                        (1 << 6, "End-to-end encryption"),
137        PRIVATE_ALG_ENCRYPTION                       (1 << 7, "Private algorithm encryption"),
138        PKI_ENCRYPTION                               (1 << 8, "PKI encryption"),
139        PRIVATE_ALG_MACING                           (1 << 9, "Private algorithm MACing"),
140        STD_ALG_MACING                               (1 << 10, "Standard algorithm MACing"),
141        CARDHOLDER_MANAGED_END_TO_END_ENCRYPTION     (1 << 11, "Cardholder managed end-to-end encryption"),
142        CARDHOLDER_MANAGED_POINT_TO_POINT_ENCRYPTION (1 << 12, "Cardholder managed point-to-point encryption"),
143        MERCHANT_MANAGED_END_TO_END_ENCRYPTION       (1 << 13, "Merchant managed end-to-end encryption"),
144        MERCHANT_MANAGED_POINT_TO_POINT_ENCRYPTION   (1 << 14, "Merchant managed point-to-point encryption"),
145        ACQUIRER_MANAGED_END_TO_END_ENCRYPTION       (1 << 15, "Acquirer managed end-to-end-encryption"),
146        ACQUIRER_MANAGED_POINT_TO_POINT_ENCRYPTION   (1 << 16, "Acquirer managed point-to-point encryption");
147
148        private int val;
149        private String description;
150        SecurityCharacteristic (int val, String description) {
151            this.val = val;
152            this.description = description;
153        }
154        public int intValue() {
155            return val;
156        }
157        public String toString () {
158            return description;
159        }
160
161        public static int OFFSET = 12;
162        @Override
163        public int getOffset() {
164            return OFFSET;
165        }
166    }
167
168    private byte[] b = new byte[16];
169
170    public PosDataCode() {
171    }
172
173    public PosDataCode (
174            int readingMethod,
175            int verificationMethod,
176            int posEnvironment,
177            int securityCharacteristic)
178    {
179        super();
180
181        b[0]  = (byte) readingMethod;
182        b[1]  = (byte) (readingMethod >>> 8);
183        b[2]  = (byte) (readingMethod >>> 16);
184        b[3]  = (byte) (readingMethod >>> 24);
185
186        b[4]  = (byte) verificationMethod;
187        b[5]  = (byte) (verificationMethod >>> 8);
188        b[6]  = (byte) (verificationMethod >>> 16);
189        b[7]  = (byte) (verificationMethod >>> 24);
190
191        b[8]  = (byte) posEnvironment;
192        b[9]  = (byte) (posEnvironment >>> 8);
193        b[10] = (byte) (posEnvironment >>> 16);
194        b[11] = (byte) (posEnvironment >>> 24);
195
196        b[12] = (byte) securityCharacteristic;
197        b[13] = (byte) (securityCharacteristic >>> 8);
198        b[14] = (byte) (securityCharacteristic >>> 16);
199        b[15] = (byte) (securityCharacteristic >>> 24);
200    }
201
202    private PosDataCode (byte[] b) {
203        if (b != null) {
204            // will always use our own internal copy of array
205            int copyLen= Math.min(b.length, 16);
206            System.arraycopy(b, 0, this.b, 0, copyLen);
207        }
208    }
209
210    public boolean hasReadingMethods (int readingMethods) {
211        int i = b[3] << 24 | b[2] << 16  & 0xFF0000 | b[1] << 8  & 0xFF00 | b[0] & 0xFF ;
212        return (i & readingMethods) == readingMethods;
213    }
214    public boolean hasReadingMethod (ReadingMethod method) {
215        return hasReadingMethods (method.intValue());
216    }
217    public boolean hasVerificationMethods (int verificationMethods) {
218        int i = b[7] << 24 | b[6] << 16 & 0xFF0000 | b[5] << 8  & 0xFF00 | b[4] & 0xFF;
219        return (i & verificationMethods) == verificationMethods;
220    }
221    public boolean hasVerificationMethod (VerificationMethod method) {
222        return hasVerificationMethods(method.intValue());
223    }
224    public boolean hasPosEnvironments (int posEnvironments) {
225        int i = b[11] << 24  | b[10] << 16 & 0xFF0000 | b[9] << 8 & 0xFF00 | b[8] & 0xFF;
226        return (i & posEnvironments) == posEnvironments;
227    }
228    public boolean hasPosEnvironment (POSEnvironment method) {
229        return hasPosEnvironments(method.intValue());
230    }
231    public boolean hasSecurityCharacteristics (int securityCharacteristics) {
232        int i = b[15] << 24 | b[14] << 16 & 0xFF0000 | b[13] << 8  & 0xFF00 | b[12] & 0xFF;
233        return (i & securityCharacteristics) == securityCharacteristics;
234    }
235    public boolean hasSecurityCharacteristic (SecurityCharacteristic characteristic) {
236        return  hasSecurityCharacteristics(characteristic.intValue());
237    }
238    public byte[] getBytes() {
239        return b;
240    }
241    public boolean isEMV() {
242        return hasReadingMethod(ReadingMethod.ICC) || hasReadingMethod(ReadingMethod.CONTACTLESS);
243    }
244    public boolean isManualEntry() {
245        return hasReadingMethod(ReadingMethod.PHYSICAL);
246    }
247    public boolean isSwiped() {
248        return hasReadingMethod(ReadingMethod.MAGNETIC_STRIPE);
249    }
250    public boolean isRecurring() {
251        return hasPosEnvironment(POSEnvironment.RECURRING);
252    }
253    public boolean isECommerce() {
254        return hasPosEnvironment(POSEnvironment.E_COMMERCE);
255    }
256    public boolean isCardNotPresent() {
257        return isECommerce() || isManualEntry() || isRecurring();
258    }
259    public String toString() {
260        return super.toString() + "[" + ISOUtil.hexString (getBytes())+ "]";
261    }
262
263    public static PosDataCode valueOf (byte[] b) {
264        return new PosDataCode(b);  // we create new objects for now, but may return cached instances in the future
265    }
266
267    public void dump(PrintStream p, String indent) {
268        String inner = indent + "  ";
269        StringBuilder sb = new StringBuilder();
270        p.printf("%s<pdc value='%s'>%s%n", indent, ISOUtil.hexString(getBytes()), sb.toString());
271        for (ReadingMethod m : ReadingMethod.values()) {
272            if (hasReadingMethod(m)) {
273                if (sb.length() > 0)
274                    sb.append(',');
275                sb.append(m.name());
276            }
277        }
278        p.printf ("%srm: %s%n", inner, sb.toString());
279        sb = new StringBuilder();
280        for (VerificationMethod m : VerificationMethod.values()) {
281            if (hasVerificationMethod(m)) {
282                if (sb.length() > 0)
283                    sb.append(',');
284                sb.append(m.name());
285            }
286        }
287        p.printf ("%svm: %s%n", inner, sb.toString());
288        sb = new StringBuilder();
289        for (POSEnvironment m : POSEnvironment.values()) {
290            if (hasPosEnvironment(m)) {
291                if (sb.length() > 0)
292                    sb.append(',');
293                sb.append(m.name());
294            }
295        }
296        p.printf ("%spe: %s%n", inner, sb.toString());
297        sb = new StringBuilder();
298        for (SecurityCharacteristic m : SecurityCharacteristic.values()) {
299            if (hasSecurityCharacteristic(m)) {
300                if (sb.length() > 0)
301                    sb.append(',');
302                sb.append(m.name());
303            }
304        }
305        p.printf ("%ssc: %s%n", inner, sb.toString());
306        p.println("</pdc>");
307    }
308    
309    public void setReadingMethods(boolean value, ReadingMethod ... methods ){
310        setFlags(value, methods);
311    }
312
313    public void unsetReadingMethods(ReadingMethod ... methods ) {
314        setReadingMethods(false, methods);
315    }
316
317    public void setReadingMethods(ReadingMethod ... methods ) {
318        setReadingMethods(true, methods);
319    }
320
321    public void setVerificationMethods(boolean value, VerificationMethod ... methods ){
322        setFlags(value, methods);
323    }
324
325    public void unsetVerificationMethods(VerificationMethod ... methods){
326        setVerificationMethods(false, methods);
327    }
328
329    public void setVerificationMethods(VerificationMethod ... methods){
330        setVerificationMethods(true, methods);
331    }
332
333    public void setPOSEnvironments(boolean value, POSEnvironment ... envs){
334        setFlags(value, envs);
335    }
336
337    public void unsetPOSEnvironments(POSEnvironment ... envs){
338        setPOSEnvironments(false, envs);
339    }
340
341    public void setPOSEnvironments(POSEnvironment ... envs){
342        setPOSEnvironments(true, envs);
343    }
344
345    public void setSecurityCharacteristics(boolean value, SecurityCharacteristic ... securityCharacteristics){
346        setFlags(value, securityCharacteristics);
347    }
348
349    public void unsetSecurityCharacteristics(SecurityCharacteristic ... envs){
350        setSecurityCharacteristics(false, envs);
351    }
352
353    public void setSecurityCharacteristics(SecurityCharacteristic ... envs){
354        setSecurityCharacteristics(true, envs);
355    }
356
357
358}