package com.l7tech.security.cert;

import com.l7tech.common.io.CertGenParams;
import com.l7tech.common.io.CertUtils;
import com.l7tech.common.io.CertificateGeneratorException;
import com.l7tech.common.io.KeyGenParams;
import com.l7tech.common.io.ParamsCertificateGenerator;
import com.l7tech.common.io.X509GeneralName;
import com.l7tech.util.ArrayUtils;
import com.l7tech.util.HexUtils;
import com.l7tech.util.Pair;
import com.l7tech.util.ResourceUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.x509.KeyPurposeId;

public class TestCertificateGenerator {
   private CertGenParams a;
   private KeyGenParams b;
   private static final SecureRandom c;
   private SecureRandom d;
   private String e;
   private KeyPair f;
   public Pair<X509Certificate, PrivateKey> issuer;
   private static final String[] g;

   public TestCertificateGenerator() {
      this.reset();
   }

   private KeyPair a() {
      InvalidAlgorithmParameterException var1;
      try {
         if (this.f != null) {
            return this.f;
         }

         try {
            this.f = new ParamsKeyGenerator(this.b, this.d).generateKeyPair();
            return this.f;
         } catch (NoSuchAlgorithmException var2) {
            throw new RuntimeException(var2);
         } catch (InvalidAlgorithmParameterException var3) {
            var1 = var3;
         }
      } catch (RuntimeException var4) {
         throw a(var4);
      }

      throw new RuntimeException(var1);
   }

   public PrivateKey getPrivateKey() {
      return this.a().getPrivate();
   }

   public TestCertificateGenerator reset() {
      this.d = c;
      this.e = null;
      this.f = null;
      this.issuer = null;
      this.b = new KeyGenParams();
      String[] var1 = g;
      this.b.setAlgorithm(var1[12]);
      this.b.setNamedParam(var1[10]);
      this.b.setKeySize(1024);
      this.a = new CertGenParams();
      this.a.setSerialNumber(new BigInteger(64, this.d).abs());
      this.a.setNotBefore(new Date(new Date().getTime() - 600000L));
      this.a.setDaysUntilExpiry(7300);
      this.a.setNotAfter(null);
      this.a.setSignatureAlgorithm(null);
      this.a.setSubjectDn(new X500Principal(var1[5]));
      this.a.setIncludeBasicConstraints(false);
      this.a.setKeyUsageBits(224);
      this.a.setIncludeKeyUsage(true);
      this.a.setKeyUsageCritical(true);
      this.a.setIncludeSki(true);
      this.a.setIncludeAki(true);
      this.a.setIncludeExtendedKeyUsage(true);
      this.a.setExtendedKeyUsageCritical(true);
      this.a.setExtendedKeyUsageKeyPurposeOids(Arrays.asList(KeyPurposeId.anyExtendedKeyUsage.getId()));
      this.a.setIncludeSubjectDirectoryAttributes(false);
      this.a.setSubjectDirectoryAttributesCritical(false);
      this.a.setCountryOfCitizenshipCountryCodes(Collections.emptyList());
      this.a.setCertificatePolicies(Collections.emptyList());
      this.a.setSubjectAlternativeNames(Collections.emptyList());
      return this;
   }

   public X509Certificate generate() throws GeneralSecurityException {
      return (X509Certificate)this.generateWithKey().left;
   }

   public Pair<X509Certificate, PrivateKey> generateWithKey() throws GeneralSecurityException {
      KeyPair var1 = this.a();
      PublicKey var2 = var1.getPublic();
      PrivateKey var3 = var1.getPrivate();

      try {
         ParamsCertificateGenerator var4 = new ParamsCertificateGenerator(this.a, this.d, this.e);

         X509Certificate var10000;
         label21: {
            try {
               if (this.issuer == null) {
                  var10000 = var4.generateCertificate(var2, var3, null);
                  break label21;
               }
            } catch (CertificateGeneratorException var6) {
               throw a(var6);
            }

            var10000 = var4.generateCertificate(var2, (PrivateKey)this.issuer.right, (X509Certificate)this.issuer.left);
         }

         X509Certificate var5 = var10000;
         return new Pair(asJdkCertificate(var5), var3);
      } catch (CertificateGeneratorException var7) {
         throw new CertificateException(var7);
      }
   }

   public TestCertificateGenerator random(SecureRandom var1) {
      this.d = var1;
      return this;
   }

   public TestCertificateGenerator keySize(int var1) {
      this.b.setAlgorithm(g[9]);
      this.b.setKeySize(var1);
      return this;
   }

   public TestCertificateGenerator dsaKeySize(int var1) {
      this.b.setAlgorithm(g[6]);
      this.b.setKeySize(var1);
      return this;
   }

   public TestCertificateGenerator curveName(String var1) {
      this.b.setAlgorithm(g[4]);
      this.b.setNamedParam(var1);
      return this;
   }

   public TestCertificateGenerator keyPair(KeyPair var1) {
      this.f = var1;
      return this;
   }

   public TestCertificateGenerator signatureProvider(String var1) {
      this.e = var1;
      return this;
   }

   public TestCertificateGenerator issuer(X509Certificate var1, PrivateKey var2) {
      return this.issuer(new Pair(var1, var2));
   }

   public TestCertificateGenerator issuer(Pair<X509Certificate, PrivateKey> var1) {
      this.issuer = var1;
      return this;
   }

   public TestCertificateGenerator subject(String var1) {
      this.a.setSubjectDn(new X500Principal(var1));
      return this;
   }

   public TestCertificateGenerator noExtensions() {
      this.a.disableAllExtensions();
      return this;
   }

   public TestCertificateGenerator noBasicConstraints() {
      this.a.setIncludeBasicConstraints(false);
      return this;
   }

   public TestCertificateGenerator basicConstraintsNoCa() {
      this.a.setIncludeBasicConstraints(true);
      this.a.setBasicConstraintsCa(false);
      return this;
   }

   public TestCertificateGenerator basicConstraintsCa(int var1) {
      this.a.setIncludeBasicConstraints(true);
      this.a.setBasicConstraintsCa(true);
      this.a.setBasicConstraintsPathLength(var1);
      return this;
   }

   public TestCertificateGenerator noKeyUsage() {
      this.a.setIncludeKeyUsage(false);
      return this;
   }

   public TestCertificateGenerator keyUsage(boolean var1, int var2) {
      this.a.setIncludeKeyUsage(true);
      this.a.setKeyUsageCritical(var1);
      this.a.setKeyUsageBits(var2);
      return this;
   }

   public TestCertificateGenerator keyUsageCriticality(boolean var1) {
      this.a.setKeyUsageCritical(var1);
      return this;
   }

   public TestCertificateGenerator noExtKeyUsage() {
      this.a.setIncludeExtendedKeyUsage(false);
      return this;
   }

   public TestCertificateGenerator extKeyUsage(boolean var1, List<String> var2) {
      this.a.setIncludeExtendedKeyUsage(true);
      this.a.setExtendedKeyUsageCritical(var1);
      this.a.setExtendedKeyUsageKeyPurposeOids(var2);
      return this;
   }

   public TestCertificateGenerator extKeyUsage(boolean var1, String var2, String... var3) {
      return this.extKeyUsage(var1, Arrays.asList(ArrayUtils.unshift(var3, var2)));
   }

   public TestCertificateGenerator extKeyUsage(boolean var1, KeyPurposeId var2, KeyPurposeId... var3) {
      ArrayList var4 = new ArrayList(var3.length + 1);
      var4.add(var2.getId());

      for (KeyPurposeId var8 : var3) {
         var4.add(var8.getId());
      }

      return this.extKeyUsage(var1, var4);
   }

   public void setExtendedKeyUsageKeyPurposeOids(List<String> var1) {
      this.a.setExtendedKeyUsageKeyPurposeOids(var1);
   }

   public boolean extendedKeyUsageCriticality() {
      return this.a.isExtendedKeyUsageCritical();
   }

   public TestCertificateGenerator extendedKeyUsageCriticality(boolean var1) {
      this.a.setExtendedKeyUsageCritical(var1);
      return this;
   }

   public TestCertificateGenerator countriesOfCitizenship(boolean var1, String... var2) {
      this.a.setIncludeSubjectDirectoryAttributes(true);
      this.a.setSubjectDirectoryAttributesCritical(var1);
      this.a.setCountryOfCitizenshipCountryCodes(Arrays.asList(var2));
      return this;
   }

   public TestCertificateGenerator certificatePolicies(boolean var1, String[] var2) {
      this.a.setIncludeCertificatePolicies(true);
      this.a.setCertificatePoliciesCritical(var1);
      this.a.setCertificatePolicies(Arrays.asList(var2));
      return this;
   }

   public TestCertificateGenerator subjectAlternativeNames(boolean var1, X509GeneralName... var2) {
      this.a.setIncludeSubjectAlternativeName(true);
      this.a.setSubjectAlternativeNameCritical(var1);
      this.a.setSubjectAlternativeNames(Arrays.asList(var2));
      return this;
   }

   public TestCertificateGenerator subjectAlternativeNames(boolean var1, String... var2) {
      this.a.setIncludeSubjectAlternativeName(true);
      this.a.setSubjectAlternativeNameCritical(var1);
      this.a.setSubjectAlternativeNames(X509GeneralName.fromHostNamesOrIps(Arrays.asList(var2)));
      return this;
   }

   public TestCertificateGenerator daysUntilExpiry(int var1) {
      this.a.setDaysUntilExpiry(var1);
      return this;
   }

   public TestCertificateGenerator notBefore(Date var1) {
      this.a.setNotBefore(var1);
      return this;
   }

   public TestCertificateGenerator notAfter(Date var1) {
      this.a.setNotAfter(var1);
      return this;
   }

   public TestCertificateGenerator signatureAlgorithm(String var1) {
      this.a.setSignatureAlgorithm(var1);
      return this;
   }

   public CertGenParams getCertGenParams() {
      return this.a;
   }

   public KeyGenParams getKeyGenParams() {
      return this.b;
   }

   public static X509Certificate asJdkCertificate(X509Certificate var0) throws CertificateException {
      return (X509Certificate)CertUtils.getFactory().generateCertificate(new ByteArrayInputStream(var0.getEncoded()));
   }

   private static Pair<X509Certificate[], PrivateKey> a(InputStream param0, char[] param1, String param2) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, IOException {
      // $VF: Couldn't be decompiled
      // Please report this to the Vineflower issue tracker, at https://github.com/Vineflower/vineflower/issues with a copy of the class file (if you have the rights to distribute it!)
      // java.lang.RuntimeException: parsing failure!
      //   at org.jetbrains.java.decompiler.modules.decompiler.decompose.DomHelper.parseGraph(DomHelper.java:211)
      //   at org.jetbrains.java.decompiler.main.rels.MethodProcessor.codeToJava(MethodProcessor.java:174)
      //
      // Bytecode:
      // 00: getstatic com/l7tech/security/cert/TestCertificateGenerator.g [Ljava/lang/String;
      // 03: astore 8
      // 05: aload 8
      // 07: bipush 8
      // 09: aaload
      // 0a: invokestatic java/security/KeyStore.getInstance (Ljava/lang/String;)Ljava/security/KeyStore;
      // 0d: astore 3
      // 0e: aload 3
      // 0f: aload 0
      // 10: aload 1
      // 11: invokevirtual java/security/KeyStore.load (Ljava/io/InputStream;[C)V
      // 14: aconst_null
      // 15: astore 4
      // 17: aconst_null
      // 18: astore 5
      // 1a: aload 2
      // 1b: ifnull 42
      // 1e: aload 3
      // 1f: aload 2
      // 20: invokevirtual java/security/KeyStore.isKeyEntry (Ljava/lang/String;)Z
      // 23: ifeq 42
      // 26: goto 2d
      // 29: invokestatic com/l7tech/security/cert/TestCertificateGenerator.a (Ljava/lang/Exception;)Ljava/lang/Exception;
      // 2c: athrow
      // 2d: aload 3
      // 2e: aload 2
      // 2f: aload 1
      // 30: invokevirtual java/security/KeyStore.getKey (Ljava/lang/String;[C)Ljava/security/Key;
      // 33: checkcast java/security/PrivateKey
      // 36: astore 4
      // 38: aload 3
      // 39: aload 2
      // 3a: invokevirtual java/security/KeyStore.getCertificateChain (Ljava/lang/String;)[Ljava/security/cert/Certificate;
      // 3d: astore 5
      // 3f: goto 7e
      // 42: aload 3
      // 43: invokevirtual java/security/KeyStore.aliases ()Ljava/util/Enumeration;
      // 46: astore 6
      // 48: aload 6
      // 4a: invokeinterface java/util/Enumeration.hasMoreElements ()Z 1
      // 4f: ifeq 7e
      // 52: aload 6
      // 54: invokeinterface java/util/Enumeration.nextElement ()Ljava/lang/Object; 1
      // 59: checkcast java/lang/String
      // 5c: astore 7
      // 5e: aload 3
      // 5f: aload 7
      // 61: invokevirtual java/security/KeyStore.isKeyEntry (Ljava/lang/String;)Z
      // 64: ifeq 7b
      // 67: aload 3
      // 68: aload 7
      // 6a: aload 1
      // 6b: invokevirtual java/security/KeyStore.getKey (Ljava/lang/String;[C)Ljava/security/Key;
      // 6e: checkcast java/security/PrivateKey
      // 71: astore 4
      // 73: aload 3
      // 74: aload 7
      // 76: invokevirtual java/security/KeyStore.getCertificateChain (Ljava/lang/String;)[Ljava/security/cert/Certificate;
      // 79: astore 5
      // 7b: goto 48
      // 7e: aload 4
      // 80: ifnull 8f
      // 83: aload 5
      // 85: ifnonnull a0
      // 88: goto 8f
      // 8b: invokestatic com/l7tech/security/cert/TestCertificateGenerator.a (Ljava/lang/Exception;)Ljava/lang/Exception;
      // 8e: athrow
      // 8f: new java/security/KeyStoreException
      // 92: dup
      // 93: getstatic com/l7tech/security/cert/TestCertificateGenerator.g [Ljava/lang/String;
      // 96: bipush 2
      // 97: aaload
      // 98: invokespecial java/security/KeyStoreException.<init> (Ljava/lang/String;)V
      // 9b: athrow
      // 9c: invokestatic com/l7tech/security/cert/TestCertificateGenerator.a (Ljava/lang/Exception;)Ljava/lang/Exception;
      // 9f: athrow
      // a0: aload 5
      // a2: invokestatic com/l7tech/security/cert/TestCertificateGenerator.a ([Ljava/security/cert/Certificate;)[Ljava/security/cert/X509Certificate;
      // a5: astore 6
      // a7: new com/l7tech/util/Pair
      // aa: dup
      // ab: aload 6
      // ad: aload 4
      // af: invokespecial com/l7tech/util/Pair.<init> (Ljava/lang/Object;Ljava/lang/Object;)V
      // b2: areturn
      // try (15 -> 21): 22 java/security/KeyStoreException
      // try (60 -> 64): 65 java/security/KeyStoreException
      // try (62 -> 74): 74 java/security/KeyStoreException
   }

   private static X509Certificate[] a(Certificate[] param0) throws KeyStoreException {
      // $VF: Couldn't be decompiled
      // Please report this to the Vineflower issue tracker, at https://github.com/Vineflower/vineflower/issues with a copy of the class file (if you have the rights to distribute it!)
      // java.lang.RuntimeException: parsing failure!
      //   at org.jetbrains.java.decompiler.modules.decompiler.decompose.DomHelper.parseGraph(DomHelper.java:211)
      //   at org.jetbrains.java.decompiler.main.rels.MethodProcessor.codeToJava(MethodProcessor.java:174)
      //
      // Bytecode:
      // 00: aload 0
      // 01: arraylength
      // 02: anewarray 36
      // 05: astore 1
      // 06: bipush 0
      // 07: istore 2
      // 08: iload 2
      // 09: aload 0
      // 0a: arraylength
      // 0b: if_icmpge 3e
      // 0e: aload 0
      // 0f: iload 2
      // 10: aaload
      // 11: instanceof java/security/cert/X509Certificate
      // 14: ifne 2f
      // 17: goto 1e
      // 1a: invokestatic com/l7tech/security/cert/TestCertificateGenerator.a (Ljava/lang/Exception;)Ljava/lang/Exception;
      // 1d: athrow
      // 1e: new java/security/KeyStoreException
      // 21: dup
      // 22: getstatic com/l7tech/security/cert/TestCertificateGenerator.g [Ljava/lang/String;
      // 25: bipush 3
      // 26: aaload
      // 27: invokespecial java/security/KeyStoreException.<init> (Ljava/lang/String;)V
      // 2a: athrow
      // 2b: invokestatic com/l7tech/security/cert/TestCertificateGenerator.a (Ljava/lang/Exception;)Ljava/lang/Exception;
      // 2e: athrow
      // 2f: aload 1
      // 30: iload 2
      // 31: aload 0
      // 32: iload 2
      // 33: aaload
      // 34: checkcast java/security/cert/X509Certificate
      // 37: aastore
      // 38: iinc 2 1
      // 3b: goto 08
      // 3e: aload 1
      // 3f: areturn
      // try (6 -> 15): 16 java/security/KeyStoreException
      // try (10 -> 25): 25 java/security/KeyStoreException
   }

   public static void saveAsPkcs12(X509Certificate[] var0, PrivateKey var1, OutputStream var2, String var3) throws IOException, GeneralSecurityException {
      char[] var4 = var3.toCharArray();
      String[] var6 = g;
      KeyStore var5 = KeyStore.getInstance(var6[14]);
      var5.load(null, var4);
      var5.setKeyEntry(var6[0], var1, var4, var0);
      var5.store(var2, var4);
   }

   public static void saveAsPkcs12(X509Certificate[] var0, PrivateKey var1, String var2, String var3) throws IOException, GeneralSecurityException {
      FileOutputStream var4 = new FileOutputStream(var2);

      try {
         saveAsPkcs12(var0, var1, var4, var3);
      } finally {
         ResourceUtils.closeQuietly(var4);
      }
   }

   public static Pair<X509Certificate[], PrivateKey> loadFromPkcs12(InputStream var0, String var1) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, IOException {
      return a(var0, var1.toCharArray(), null);
   }

   public static Pair<X509Certificate[], PrivateKey> loadFromPkcs12(String var0, String var1) throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException {
      FileInputStream var2 = new FileInputStream(var0);

      try {
         return loadFromPkcs12(var2, var1);
      } finally {
         ResourceUtils.closeQuietly(var2);
      }
   }

   public static String convertToBase64Pkcs12(X509Certificate var0, PrivateKey var1) throws GeneralSecurityException {
      try {
         String[] var5 = g;
         char[] var2 = var5[7].toCharArray();
         KeyStore var3 = KeyStore.getInstance(var5[14]);
         var3.load(null, null);
         var3.setKeyEntry(var5[11], var1, var2, new X509Certificate[]{var0});
         ByteArrayOutputStream var4 = new ByteArrayOutputStream();
         var3.store(var4, var2);
         return HexUtils.encodeBase64(var4.toByteArray());
      } catch (IOException var6) {
         throw new KeyStoreException(var6);
      }
   }

   public static Pair<X509Certificate, PrivateKey> convertFromBase64Pkcs12(String var0) throws GeneralSecurityException, IOException {
      String[] var7 = g;
      char[] var1 = var7[13].toCharArray();
      KeyStore var2 = KeyStore.getInstance(var7[14]);
      var2.load(new ByteArrayInputStream(HexUtils.decodeBase64(var0)), var1);
      Enumeration var3 = var2.aliases();

      while (var3.hasMoreElements()) {
         String var4 = (String)var3.nextElement();
         if (var2.isKeyEntry(var4)) {
            PrivateKey var5 = (PrivateKey)var2.getKey(var4, var1);
            Certificate[] var6 = var2.getCertificateChain(var4);
            return new Pair((X509Certificate)var6[0], var5);
         }
      }

      throw new IOException(g[1]);
   }

   static {
      String[] var5 = new String[15];
      int var3 = 0;
      String var2 = "Q\u007fl\u001cz\u001e\u007fta\u001dw\u00186Q1{\u0001m\u0003%]\u007fkNm\u0018d_taNf\u00190Fh3ga}\rj\u0011-Qu8>H4\u0017\u0017 *NH\u0012=gew\u001cfW'[\u007fl\u000fj\u0019!P1v\u0001#\u001c!M1}\u0000w\u0005-Qb=ga}\rj\u0011-Qu8\rf\u00050]wq\rb\u0003!\u0014rp\u000fj\u0019dW~v\u001ab\u001e*Qu8\u000f#\u0019+Z<@@6G}\u0014r}\u001cw\u001e\"]ry\u001af\u0002qR\u0007W\u007f%\u001af\u00040\u0003pBY\bDpk\u001dt\u00186P\u0006dZ[=2E\u0003fBY\tGt{\u001e6EuF \u0005Q\u007fl\u001cz\u0003fBY";
      int var4 = "Q\u007fl\u001cz\u001e\u007fta\u001dw\u00186Q1{\u0001m\u0003%]\u007fkNm\u0018d_taNf\u00190Fh3ga}\rj\u0011-Qu8>H4\u0017\u0017 *NH\u0012=gew\u001cfW'[\u007fl\u000fj\u0019!P1v\u0001#\u001c!M1}\u0000w\u0005-Qb=ga}\rj\u0011-Qu8\rf\u00050]wq\rb\u0003!\u0014rp\u000fj\u0019dW~v\u001ab\u001e*Qu8\u000f#\u0019+Z<@@6G}\u0014r}\u001cw\u001e\"]ry\u001af\u0002qR\u0007W\u007f%\u001af\u00040\u0003pBY\bDpk\u001dt\u00186P\u0006dZ[=2E\u0003fBY\tGt{\u001e6EuF \u0005Q\u007fl\u001cz\u0003fBY"
         .length();
      char var1 = 5;
      int var7 = -1;

      label24:
      while (true) {
         byte var10000 = 64;
         String var10001 = var2.substring(++var7, var7 + var1);
         byte var10002 = -1;

         while (true) {
            String var8 = a(var10000, a(var10001));
            switch (var10002) {
               case 0:
                  var5[var3++] = var8;
                  if ((var7 += var1) >= var4) {
                     g = var5;
                     c = new SecureRandom();
                     return;
                  }

                  var1 = var2.charAt(var7);
                  break;
               default:
                  var5[var3++] = var8;
                  if ((var7 += var1) < var4) {
                     var1 = var2.charAt(var7);
                     continue label24;
                  }

                  var2 = "zNU#J&\bn\u0006Zde\u0003\f{";
                  var4 = "zNU#J&\bn\u0006Zde\u0003\f{".length();
                  var1 = '\b';
                  var7 = -1;
            }

            var10000 = 126;
            var10001 = var2.substring(++var7, var7 + var1);
            var10002 = 0;
         }
      }
   }

   private static Exception a(Exception var0) {
      return var0;
   }

   private static char[] a(String var0) {
      char[] var10000 = var0.toCharArray();
      if (var10000.length < 2) {
         var10000[0] = (char)(var10000[0] ^ 4);
      }

      return var10000;
   }

   private static String a(int var0, char[] var1) {
      int var10003 = var1.length;
      int var10002 = var0;
      char[] var10001 = var1;
      int var10000 = var10003;

      for (int var2 = 0; var10000 > var2; var2++) {
         var10001[var2] = (char)(var10001[var2] ^ var10002 ^ switch (var2 % 7) {
            case 0 -> 116;
            case 1 -> 81;
            case 2 -> 88;
            case 3 -> 46;
            case 4 -> 67;
            case 5 -> 55;
            default -> 4;
         });
      }

      return new String(var10001).intern();
   }
}
