001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 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 PosCapability extends PosFlags implements Loggeable { 027 public enum ReadingCapability 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 ReadingCapability (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 061 public enum VerificationCapability implements Flag { 062 UNKNOWN (1, "Unknown"), 063 NONE (1 << 1, "None"), 064 MANUAL_SIGNATURE (1 << 2, "Manual signature"), 065 ONLINE_PIN (1 << 3, "Online PIN"), 066 OFFLINE_PIN_IN_CLEAR (1 << 4, "Offline PIN in clear"), 067 OFFLINE_PIN_ENCRYPTED (1 << 5, "Offline PIN encrypted"), 068 OFFLINE_DIGITIZED_SIGNATURE_ANALYSIS (1 << 6, "Offline digitized signature analysis"), 069 OFFLINE_BIOMETRICS (1 << 7, "Offline biometrics"), 070 OFFLINE_MANUAL_VERIFICATION (1 << 8, "Offline manual verification"), 071 OFFLINE_BIOGRAPHICS (1 << 9, "Offline biographics"), 072 ACCOUNT_BASED_DIGITAL_SIGNATURE (1 << 10, "Account based digital signature"), 073 PUBLIC_KEY_BASED_DIGITAL_SIGNATURE (1 << 11, "Public key based digital signature"); 074 075 private int val; 076 private String description; 077 VerificationCapability (int val, String description) { 078 this.val = val; 079 this.description = description; 080 } 081 public int intValue() { 082 return val; 083 } 084 public String toString () { 085 return description; 086 } 087 088 public static int OFFSET = 0; 089 @Override 090 public int getOffset() { 091 return OFFSET; 092 } 093 } 094 095 private byte[] b = new byte[8]; 096 097 public PosCapability() {} 098 099 public PosCapability ( 100 int readingCapability, 101 int verificationCapability) 102 { 103 super(); 104 105 b[0] = (byte) readingCapability; 106 b[1] = (byte) (readingCapability >>> 8); 107 b[2] = (byte) (readingCapability >>> 16); 108 b[3] = (byte) (readingCapability >>> 24); 109 110 b[4] = (byte) verificationCapability; 111 b[5] = (byte) (verificationCapability >>> 8); 112 b[6] = (byte) (verificationCapability >>> 16); 113 b[7] = (byte) (verificationCapability >>> 24); 114 } 115 116 private PosCapability (byte[] b) { 117 if (b != null) { 118 // will always use our own internal copy of array 119 int copyLen= Math.min(b.length, 16); 120 System.arraycopy(b, 0, this.b, 0, copyLen); 121 } 122 } 123 124 public boolean hasReadingCapability (int readingMethods) { 125 int i = b[3] << 24 | b[2] << 16 & 0xFF0000 | b[1] << 8 & 0xFF00 | b[0] & 0xFF ; 126 return (i & readingMethods) == readingMethods; 127 } 128 public boolean hasReadingCapability (ReadingCapability method) { 129 return hasReadingCapability (method.intValue()); 130 } 131 public boolean hasVerificationCapability (int verificationMethods) { 132 int i = b[7] << 24 | b[6] << 16 & 0xFF0000 | b[5] << 8 & 0xFF00 | b[4] & 0xFF; 133 return (i & verificationMethods) == verificationMethods; 134 } 135 public boolean hasVerificationCapability (VerificationCapability method) { 136 return hasVerificationCapability(method.intValue()); 137 } 138 public byte[] getBytes() { 139 return b; 140 } 141 public boolean canEMV() { 142 return hasReadingCapability(ReadingCapability.ICC) || hasReadingCapability(ReadingCapability.CONTACTLESS); 143 } 144 public boolean canManualEntry() { 145 return hasReadingCapability(ReadingCapability.PHYSICAL); 146 } 147 public boolean isSwiped() { 148 return hasReadingCapability(ReadingCapability.MAGNETIC_STRIPE); 149 } 150 public String toString() { 151 return super.toString() + "[" + ISOUtil.hexString (getBytes())+ "]"; 152 } 153 154 public static PosCapability valueOf (byte[] b) { 155 return new PosCapability(b); // we create new objects for now, but may return cached instances in the future 156 } 157 158 public void dump(PrintStream p, String indent) { 159 String inner = indent + " "; 160 StringBuilder sb = new StringBuilder(); 161 p.printf("%s<pvc value='%s'>%n", indent, ISOUtil.hexString(getBytes())); 162 for (ReadingCapability m : ReadingCapability.values()) { 163 if (hasReadingCapability(m)) { 164 if (sb.length() > 0) 165 sb.append(','); 166 sb.append(m.name()); 167 } 168 } 169 p.printf ("%src: %s%n", inner, sb); 170 sb = new StringBuilder(); 171 for (VerificationCapability m : VerificationCapability.values()) { 172 if (hasVerificationCapability(m)) { 173 if (sb.length() > 0) 174 sb.append(','); 175 sb.append(m.name()); 176 } 177 } 178 p.printf ("%svc: %s%n", inner, sb); 179 p.println("</pvc>"); 180 } 181 182 public void setReadingCapabilities(boolean value, ReadingCapability ... capabilities ){ 183 setFlags(value, capabilities); 184 } 185 186 public void unsetReadingCapabilities(ReadingCapability ... capabilities) { 187 setReadingCapabilities(false, capabilities); 188 } 189 190 public void setReadingCapabilities(ReadingCapability ... capabilities) { 191 setReadingCapabilities(true, capabilities); 192 } 193 194 public void setVerificationCapabilities(boolean value, VerificationCapability ... capabilities){ 195 setFlags(value, capabilities); 196 } 197 198 public void unsetVerificationCapabilities(VerificationCapability ... capabilities) { 199 setVerificationCapabilities(false, capabilities); 200 } 201 202 public void setVerificationCapabilities(VerificationCapability ... capabilities) { 203 setVerificationCapabilities(true, capabilities); 204 } 205}