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}