diff options
author | CGantert345 <57003061+CGantert345@users.noreply.github.com> | 2021-06-29 14:59:45 +0200 |
---|---|---|
committer | CGantert345 <57003061+CGantert345@users.noreply.github.com> | 2021-06-29 14:59:45 +0200 |
commit | 67bd1413dc47ec37a9ba042949973eff0a5045fd (patch) | |
tree | 3e9718717fb9219aa02ac826dc2495c3941ac373 /src/main/java/org | |
parent | - option to use a dedicated security provider implementation (diff) | |
download | UIC-barcode-67bd1413dc47ec37a9ba042949973eff0a5045fd.tar UIC-barcode-67bd1413dc47ec37a9ba042949973eff0a5045fd.tar.gz UIC-barcode-67bd1413dc47ec37a9ba042949973eff0a5045fd.tar.bz2 UIC-barcode-67bd1413dc47ec37a9ba042949973eff0a5045fd.tar.lz UIC-barcode-67bd1413dc47ec37a9ba042949973eff0a5045fd.tar.xz UIC-barcode-67bd1413dc47ec37a9ba042949973eff0a5045fd.tar.zst UIC-barcode-67bd1413dc47ec37a9ba042949973eff0a5045fd.zip |
Diffstat (limited to '')
14 files changed, 108 insertions, 174 deletions
diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index e9dd4b0..09ee839 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -108,7 +108,7 @@ public class Decoder { */
public int validateLevel1(PublicKey key, String signingAlg, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException {
if (!isStaticHeader(data)) {
- return dynamicFrame.validateLevel1(key) ;
+ return dynamicFrame.validateLevel1(key, provider) ;
} else {
if (staticFrame.verifyByAlgorithmOid(key,signingAlg, provider)) {
return Constants.LEVEL1_VALIDATION_OK;
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java index 1d96d05..6cc1eaa 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java @@ -127,6 +127,7 @@ public class DynamicFrame extends Object{ String level2KeyAlg = this.getLevel2SignedData().getLevel1Data().level2KeyAlg;
+
if (level2KeyAlg == null || level2KeyAlg.length() == 0) {
return Constants.LEVEL2_VALIDATION_NO_KEY;
@@ -135,9 +136,7 @@ public class DynamicFrame extends Object{ if (this.level2Signature.toByteArray() == null || this.level2Signature.toByteArray().length == 0) {
return Constants.LEVEL2_VALIDATION_NO_SIGNATURE;
}
-
-
-
+
String keyAlgName = null;
try {
keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg);
@@ -147,31 +146,35 @@ public class DynamicFrame extends Object{ if (keyAlgName == null || keyAlgName.length() == 0) {
return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
}
-
+
PublicKey key = null;
try {
- key = KeyFactory.getInstance(keyAlgName).generatePublic(new X509EncodedKeySpec(this.getLevel2SignedData().getLevel1Data().level2publicKey.toByteArray()));
+ byte[] keyBytes = this.getLevel2SignedData().getLevel1Data().level2publicKey.toByteArray();
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+ key = KeyFactory.getInstance(keyAlgName).generatePublic(keySpec);
} catch (InvalidKeySpecException | NoSuchAlgorithmException e1) {
return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
}
//find the algorithm name for the signature OID
- String algo = null;
+ String level2SigAlg = this.getLevel2SignedData().getLevel1Data().level2SigningAlg;
+
+ String sigAlgName = null;
try {
- algo = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
+ sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg);
} catch (Exception e1) {
return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
}
- if (algo == null) {
+ if (sigAlgName == null) {
return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
}
Signature sig;
try {
if (prov == null) {
- sig = Signature.getInstance(algo);
+ sig = Signature.getInstance(sigAlgName);
} else {
- sig = Signature.getInstance(algo, prov);
+ sig = Signature.getInstance(sigAlgName, prov);
}
} catch (NoSuchAlgorithmException e) {
return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
@@ -183,7 +186,8 @@ public class DynamicFrame extends Object{ }
try {
- sig.update(UperEncoder.encode(level2SignedData));
+ byte[] data = UperEncoder.encode(level2SignedData);
+ sig.update(data);
} catch (SignatureException e) {
return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
} catch (IllegalArgumentException e) {
@@ -210,7 +214,7 @@ public class DynamicFrame extends Object{ * Note: an appropriate security provider (e.g. BC) must be registered before
*
*/
- public int validateLevel1(PublicKey key) {
+ public int validateLevel1(PublicKey key, Provider prov) {
if (this.level2SignedData == null) {
return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
@@ -236,7 +240,12 @@ public class DynamicFrame extends Object{ Signature sig;
try {
- sig = Signature.getInstance(algo);
+ if (prov != null) {
+ sig = Signature.getInstance(algo, prov);
+ } else {
+ sig = Signature.getInstance(algo);
+
+ }
} catch (NoSuchAlgorithmException e) {
return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
}
@@ -268,6 +277,18 @@ public class DynamicFrame extends Object{ }
}
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ */
+ public int validateLevel1(PublicKey key) {
+
+ return validateLevel1(key, null);
+
+ }
+
public void signLevel2(PrivateKey key) throws Exception {
//find the algorithm name for the signature OID
@@ -276,7 +297,8 @@ public class DynamicFrame extends Object{ sig.initSign(key);
byte[] data = level2SignedData.encode();
sig.update(data);
- this.level2Signature = new OctetString(sig.sign());
+ byte[] signature = sig.sign();
+ this.level2Signature = new OctetString(signature);
}
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/OpenTicketData.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/OpenTicketData.java index 87e3f36..fa4208c 100644 --- a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/OpenTicketData.java +++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/OpenTicketData.java @@ -35,7 +35,7 @@ import org.uic.barcode.asn1.datatypes.RestrictedString; import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.datatypes.SizeRange;
import org.uic.barcode.asn1.datatypesimpl.SequenceOfStringIA5;
-import org.uic.barcode.ticket.api.asn.omv2.SequenceOfActivatedDays;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfActivatedDays;
import org.uic.barcode.ticket.api.utils.DateTimeUtils;
@Sequence
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/PassData.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/PassData.java index 5334761..e4c42a6 100644 --- a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/PassData.java +++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/PassData.java @@ -34,7 +34,7 @@ import org.uic.barcode.asn1.datatypes.IntRange; import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.datatypesimpl.SequenceOfStringIA5;
-import org.uic.barcode.ticket.api.asn.omv2.SequenceOfActivatedDays;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfActivatedDays;
import org.uic.barcode.ticket.api.utils.DateTimeUtils;
@Sequence
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/TrainValidityType.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/TrainValidityType.java index 8f75dc9..88e5614 100644 --- a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/TrainValidityType.java +++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/TrainValidityType.java @@ -25,12 +25,14 @@ import java.util.List; import org.uic.barcode.asn1.datatypes.Asn1Default;
import org.uic.barcode.asn1.datatypes.Asn1Optional;
import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.HasExtensionMarker;
import org.uic.barcode.asn1.datatypes.IntRange;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.datatypesimpl.SequenceOfStringIA5;
import org.uic.barcode.ticket.api.utils.DateTimeUtils;
@Sequence
+@HasExtensionMarker
public class TrainValidityType extends Object {
public TrainValidityType() {
}
diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Api2AsnEncoder.java b/src/main/java/org/uic/barcode/ticket/api/utils/Api2AsnEncoder.java new file mode 100644 index 0000000..11052b0 --- /dev/null +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Api2AsnEncoder.java @@ -0,0 +1,13 @@ +package org.uic.barcode.ticket.api.utils;
+
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.asn.omv1.UicRailTicketData;
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+public abstract interface Api2AsnEncoder {
+
+
+ public byte[] encode(IUicRailTicket uicTicket) throws EncodingFormatException;
+
+
+}
diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoder.java b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoder.java index 3f781ef..cab9b53 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoder.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoder.java @@ -151,7 +151,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /**
* The Class Api2OpenAsnEncoder.
*/
-public class Api2OpenAsnEncoder {
+public class Api2OpenAsnEncoder implements Api2AsnEncoder {
/**
diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV2.java b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV2.java index 61bdba1..184dfd7 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV2.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV2.java @@ -152,7 +152,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /**
* The Class Api2OpenAsnEncoder.
*/
-public class Api2OpenAsnEncoderV2 {
+public class Api2OpenAsnEncoderV2 implements Api2AsnEncoder {
/**
* encode to asn1 model.
@@ -1512,9 +1512,13 @@ public class Api2OpenAsnEncoderV2 { asnData.setValidity(document.getValidFrom(), document.getValidUntil());
- asnData.setType(UicEncoderUtils.getRestrictedInt(document.getType(), 1,9999));
+ if (document.getType() != null) {
+ asnData.setType(UicEncoderUtils.getRestrictedInt(document.getType(), 1,32000));
+ }
- asnData.setValue(UicEncoderUtils.getRestrictedInt(document.getAmount(),1,9999999));
+ if (document.getAmount() != null) {
+ asnData.setValue(UicEncoderUtils.getRestrictedInt(document.getAmount(),1,9999999));
+ }
return asnDocument;
}
diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV3.java b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV3.java index 83406e8..9084d7a 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV3.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV3.java @@ -155,7 +155,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /**
* The Class Api2OpenAsnEncoder.
*/
-public class Api2OpenAsnEncoderV3 {
+public class Api2OpenAsnEncoderV3 implements Api2AsnEncoder {
/**
* encode to asn1 model.
@@ -1500,8 +1500,7 @@ public class Api2OpenAsnEncoderV3 { DocumentData asnDocument = new DocumentData();
TicketDetailData asnTicket = new TicketDetailData();
asnDocument.setTicket(asnTicket);
-
-
+
VoucherData asnData = new VoucherData();
asnDocument.getTicket().setVoucher(asnData);
@@ -1518,9 +1517,13 @@ public class Api2OpenAsnEncoderV3 { asnData.setValidity(document.getValidFrom(), document.getValidUntil());
- asnData.setType(UicEncoderUtils.getRestrictedInt(document.getType(), 1,9999));
+ if (document.getType() != null) {
+ asnData.setType(UicEncoderUtils.getRestrictedInt(document.getType(), 1,32000));
+ }
- asnData.setValue(UicEncoderUtils.getRestrictedInt(document.getAmount(),1,9999999));
+ if (document.getAmount() != null) {
+ asnData.setValue(UicEncoderUtils.getRestrictedInt(document.getAmount(),1,9999999));
+ }
return asnDocument;
}
diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Asn2ApiDecoder.java b/src/main/java/org/uic/barcode/ticket/api/utils/Asn2ApiDecoder.java new file mode 100644 index 0000000..e751f48 --- /dev/null +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Asn2ApiDecoder.java @@ -0,0 +1,13 @@ +package org.uic.barcode.ticket.api.utils;
+
+import java.io.IOException;
+
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+public interface Asn2ApiDecoder {
+
+
+ public IUicRailTicket decodeFromAsn (byte[] data) throws IOException;
+
+
+}
diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoder.java b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoder.java index d203487..bf3918c 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoder.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoder.java @@ -118,7 +118,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /**
* The Class OpenAsn2ApiDecoder.
*/
-public class OpenAsn2ApiDecoder {
+public class OpenAsn2ApiDecoder implements Asn2ApiDecoder {
IUicTicketObjectFactory factory = SimpleUicTicketObjectFactory.getInstance();
diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV2.java b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV2.java index b8ee363..fc68f91 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV2.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV2.java @@ -118,7 +118,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /**
* The Class OpenAsn2ApiDecoder.
*/
-public class OpenAsn2ApiDecoderV2 {
+public class OpenAsn2ApiDecoderV2 implements Asn2ApiDecoder {
IUicTicketObjectFactory factory = SimpleUicTicketObjectFactory.getInstance();
diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV3.java b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV3.java index 36622fc..56efcb1 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV3.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV3.java @@ -121,7 +121,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /**
* The Class OpenAsn2ApiDecoder.
*/
-public class OpenAsn2ApiDecoderV3 {
+public class OpenAsn2ApiDecoderV3 implements Asn2ApiDecoder {
IUicTicketObjectFactory factory = SimpleUicTicketObjectFactory.getInstance();
diff --git a/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java b/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java index 1671ba9..4491358 100644 --- a/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java +++ b/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java @@ -3,11 +3,6 @@ package org.uic.barcode.utils; import java.security.Provider;
import java.security.Provider.Service;
import java.security.Security;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
public class AlgorithmNameResolver {
@@ -16,10 +11,6 @@ public class AlgorithmNameResolver { public static final String TYPE_SIGNATURE_ALG = "Signature";
- private static final Pattern KEY_TYPE_PATTERN = Pattern.compile("^(\\w+)[.].*$");
- private static final Pattern KEY_ALIAS_TYPE_PATTERN = Pattern.compile("^Alg[.]Alias[.](\\w+).*$");
- private static final Pattern KEY_OID_PATTERN = Pattern.compile(".*?(\\d+(?:[.]\\d+){3,})$");
-
public static String getSignatureAlgorithmName (String oid) throws Exception {
Provider[] provs = Security.getProviders();
@@ -32,85 +23,35 @@ public class AlgorithmNameResolver { return null;
}
+
+ public static String getName (String type, String oid) throws Exception {
-
- public static String getName(String type, String oid) throws Exception {
-
- Provider[] provs = Security.getProviders();
-
- for (Provider prov : provs) {
-
- String name = getName(type, oid, prov);
- if (name != null) return name;
-
- }
-
- if (oid.startsWith("1.2.840.10045")) {
- return "ECDSA";
- } else if (oid.startsWith("1.2.840.10040")) {
- return "DSA";
+ Provider[] provs = Security.getProviders();
+ for (Provider prov : provs) {
+ Service service = prov.getService(type,oid);
+ if (service != null) {
+ return service.getAlgorithm();
+ }
}
- return null;
-
- }
-
- public static String getName(String type, String oid, Provider prov) throws Exception {
-
- SortedSet<String> typeAndOID = getTypeAndOIDStrings(prov);
-
- for (String entry : typeAndOID) {
- String[] typeAndOIDArray = entry.split("-");
- String ptype = typeAndOIDArray[0];
- if (ptype.equalsIgnoreCase(type)) {
- String poid = typeAndOIDArray[1];
- Service pservice = prov.getService(ptype, poid);
- String palgo = pservice.getAlgorithm();
-
- if (poid != null && ptype.equalsIgnoreCase(type) && poid.equals(oid)) {
- return palgo;
- }
- }
- }
-
-
if (oid.startsWith("1.2.840.10045")) {
return "ECDSA";
} else if (oid.startsWith("1.2.840.10040")) {
return "DSA";
}
-
- return null;
-
- }
-
- public static String getName(String type, String oid, String providerName) throws Exception {
-
- Provider[] provs = Security.getProviders();
-
- for (Provider prov : provs) {
-
- if (providerName == null || prov.getName().equals(providerName)) {
-
- SortedSet<String> typeAndOID = getTypeAndOIDStrings(prov);
- for (String entry : typeAndOID) {
- String[] typeAndOIDArray = entry.split("-");
- String ptype = typeAndOIDArray[0];
- if (ptype.equalsIgnoreCase(type)) {
- String poid = typeAndOIDArray[1];
- Service pservice = prov.getService(ptype, poid);
- String palgo = pservice.getAlgorithm();
-
- if (ptype.equalsIgnoreCase(type) && poid.equals(oid)) {
- return palgo;
- }
- }
- }
- }
- }
-
-
+ return null;
+
+ }
+
+
+ public static String getName(String type, String oid, Provider prov) throws Exception {
+
+ Service service = prov.getService(type,oid);
+ if (service != null) {
+ return service.getAlgorithm();
+ }
+
if (oid.startsWith("1.2.840.10045")) {
return "ECDSA";
} else if (oid.startsWith("1.2.840.10040")) {
@@ -119,73 +60,9 @@ public class AlgorithmNameResolver { return null;
- }
-
-
-
- private static SortedSet<String> getTypeAndOIDStrings(Provider prov) {
-
- SortedSet<String> typeAndOID = new TreeSet<>();
-
- Set<Object> keys = prov.keySet();
- for (Object key : keys) {
- String keyString = key.toString();
- Matcher oidMatcher = KEY_OID_PATTERN.matcher(keyString);
- if (oidMatcher.matches()) {
- // get OID from matched keyString
- String oid = oidMatcher.group(1);
-
- // determine type
- String type;
- Matcher aliasTypeMatcher = KEY_ALIAS_TYPE_PATTERN.matcher(keyString);
- if (aliasTypeMatcher.matches()) {
- type = aliasTypeMatcher.group(1);
- } else {
- Matcher typeMatcher = KEY_TYPE_PATTERN.matcher(keyString);
- typeMatcher.matches();
- type = typeMatcher.group(1);
- }
- // algorithm parameters are not algorithms, so skip them
- if (type.equals("AlgorithmParameters")) {
- continue;
- }
-
- // auto-removes dupes
- typeAndOID.add(type + "-" + oid);
- }
- }
- return typeAndOID;
- }
+ }
+
- public static String getSecurityNames() throws Exception {
-
- Provider[] provs = Security.getProviders();
-
- StringBuilder sb = new StringBuilder();
-
- for (Provider prov : provs) {
-
- SortedSet<String> typeAndOID = getTypeAndOIDStrings(prov);
-
- for (String entry : typeAndOID) {
- String[] typeAndOIDArray = entry.split("-");
- String ptype = typeAndOIDArray[0];
- String poid = typeAndOIDArray[1];
- Service pservice = prov.getService(ptype, poid);
- String palgo = "";
- if ( pservice != null) {
- palgo = pservice.getAlgorithm();
- }
- sb.append(prov).append(";");
- sb.append(ptype).append(";");
- sb.append(poid).append(";");
- sb.append(palgo).append(";");
- sb.append("\r\n");
- }
- }
- return sb.toString();
-
- }
}
|