Initial Commit
This commit is contained in:
112
iTechSharp/srcbc/asn1/x509/qualified/BiometricData.cs
Normal file
112
iTechSharp/srcbc/asn1/x509/qualified/BiometricData.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
/**
|
||||
* The BiometricData object.
|
||||
* <pre>
|
||||
* BiometricData ::= SEQUENCE {
|
||||
* typeOfBiometricData TypeOfBiometricData,
|
||||
* hashAlgorithm AlgorithmIdentifier,
|
||||
* biometricDataHash OCTET STRING,
|
||||
* sourceDataUri IA5String OPTIONAL }
|
||||
* </pre>
|
||||
*/
|
||||
public class BiometricData
|
||||
: Asn1Encodable
|
||||
{
|
||||
private readonly TypeOfBiometricData typeOfBiometricData;
|
||||
private readonly AlgorithmIdentifier hashAlgorithm;
|
||||
private readonly Asn1OctetString biometricDataHash;
|
||||
private readonly DerIA5String sourceDataUri;
|
||||
|
||||
public static BiometricData GetInstance(
|
||||
object obj)
|
||||
{
|
||||
if (obj == null || obj is BiometricData)
|
||||
{
|
||||
return (BiometricData)obj;
|
||||
}
|
||||
|
||||
if (obj is Asn1Sequence)
|
||||
{
|
||||
return new BiometricData(Asn1Sequence.GetInstance(obj));
|
||||
}
|
||||
|
||||
throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
|
||||
}
|
||||
|
||||
private BiometricData(
|
||||
Asn1Sequence seq)
|
||||
{
|
||||
typeOfBiometricData = TypeOfBiometricData.GetInstance(seq[0]);
|
||||
hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
|
||||
biometricDataHash = Asn1OctetString.GetInstance(seq[2]);
|
||||
|
||||
if (seq.Count > 3)
|
||||
{
|
||||
sourceDataUri = DerIA5String.GetInstance(seq[3]);
|
||||
}
|
||||
}
|
||||
|
||||
public BiometricData(
|
||||
TypeOfBiometricData typeOfBiometricData,
|
||||
AlgorithmIdentifier hashAlgorithm,
|
||||
Asn1OctetString biometricDataHash,
|
||||
DerIA5String sourceDataUri)
|
||||
{
|
||||
this.typeOfBiometricData = typeOfBiometricData;
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.biometricDataHash = biometricDataHash;
|
||||
this.sourceDataUri = sourceDataUri;
|
||||
}
|
||||
|
||||
public BiometricData(
|
||||
TypeOfBiometricData typeOfBiometricData,
|
||||
AlgorithmIdentifier hashAlgorithm,
|
||||
Asn1OctetString biometricDataHash)
|
||||
{
|
||||
this.typeOfBiometricData = typeOfBiometricData;
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.biometricDataHash = biometricDataHash;
|
||||
this.sourceDataUri = null;
|
||||
}
|
||||
|
||||
public TypeOfBiometricData TypeOfBiometricData
|
||||
{
|
||||
get { return typeOfBiometricData; }
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier HashAlgorithm
|
||||
{
|
||||
get { return hashAlgorithm; }
|
||||
}
|
||||
|
||||
public Asn1OctetString BiometricDataHash
|
||||
{
|
||||
get { return biometricDataHash; }
|
||||
}
|
||||
|
||||
public DerIA5String SourceDataUri
|
||||
{
|
||||
get { return sourceDataUri; }
|
||||
}
|
||||
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
Asn1EncodableVector seq = new Asn1EncodableVector(
|
||||
typeOfBiometricData, hashAlgorithm, biometricDataHash);
|
||||
|
||||
if (sourceDataUri != null)
|
||||
{
|
||||
seq.Add(sourceDataUri);
|
||||
}
|
||||
|
||||
return new DerSequence(seq);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
public abstract class EtsiQCObjectIdentifiers
|
||||
{
|
||||
//
|
||||
// base id
|
||||
//
|
||||
public static readonly DerObjectIdentifier IdEtsiQcs = new DerObjectIdentifier("0.4.0.1862.1");
|
||||
|
||||
public static readonly DerObjectIdentifier IdEtsiQcsQcCompliance = new DerObjectIdentifier(IdEtsiQcs+".1");
|
||||
public static readonly DerObjectIdentifier IdEtsiQcsLimitValue = new DerObjectIdentifier(IdEtsiQcs+".2");
|
||||
public static readonly DerObjectIdentifier IdEtsiQcsRetentionPeriod = new DerObjectIdentifier(IdEtsiQcs+".3");
|
||||
public static readonly DerObjectIdentifier IdEtsiQcsQcSscd = new DerObjectIdentifier(IdEtsiQcs+".4");
|
||||
}
|
||||
}
|
84
iTechSharp/srcbc/asn1/x509/qualified/Iso4217CurrencyCode.cs
Normal file
84
iTechSharp/srcbc/asn1/x509/qualified/Iso4217CurrencyCode.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
/**
|
||||
* The Iso4217CurrencyCode object.
|
||||
* <pre>
|
||||
* Iso4217CurrencyCode ::= CHOICE {
|
||||
* alphabetic PrintableString (SIZE 3), --Recommended
|
||||
* numeric INTEGER (1..999) }
|
||||
* -- Alphabetic or numeric currency code as defined in ISO 4217
|
||||
* -- It is recommended that the Alphabetic form is used
|
||||
* </pre>
|
||||
*/
|
||||
public class Iso4217CurrencyCode
|
||||
: Asn1Encodable
|
||||
{
|
||||
internal const int AlphabeticMaxSize = 3;
|
||||
internal const int NumericMinSize = 1;
|
||||
internal const int NumericMaxSize = 999;
|
||||
|
||||
internal Asn1Encodable obj;
|
||||
// internal int numeric;
|
||||
|
||||
public static Iso4217CurrencyCode GetInstance(
|
||||
object obj)
|
||||
{
|
||||
if (obj == null || obj is Iso4217CurrencyCode)
|
||||
{
|
||||
return (Iso4217CurrencyCode) obj;
|
||||
}
|
||||
|
||||
if (obj is DerInteger)
|
||||
{
|
||||
DerInteger numericobj = DerInteger.GetInstance(obj);
|
||||
int numeric = numericobj.Value.IntValue;
|
||||
return new Iso4217CurrencyCode(numeric);
|
||||
}
|
||||
|
||||
if (obj is DerPrintableString)
|
||||
{
|
||||
DerPrintableString alphabetic = DerPrintableString.GetInstance(obj);
|
||||
return new Iso4217CurrencyCode(alphabetic.GetString());
|
||||
}
|
||||
|
||||
throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
|
||||
}
|
||||
|
||||
public Iso4217CurrencyCode(
|
||||
int numeric)
|
||||
{
|
||||
if (numeric > NumericMaxSize || numeric < NumericMinSize)
|
||||
{
|
||||
throw new ArgumentException("wrong size in numeric code : not in (" +NumericMinSize +".."+ NumericMaxSize +")");
|
||||
}
|
||||
|
||||
obj = new DerInteger(numeric);
|
||||
}
|
||||
|
||||
public Iso4217CurrencyCode(
|
||||
string alphabetic)
|
||||
{
|
||||
if (alphabetic.Length > AlphabeticMaxSize)
|
||||
{
|
||||
throw new ArgumentException("wrong size in alphabetic code : max size is " + AlphabeticMaxSize);
|
||||
}
|
||||
|
||||
obj = new DerPrintableString(alphabetic);
|
||||
}
|
||||
|
||||
public bool IsAlphabetic { get { return obj is DerPrintableString; } }
|
||||
|
||||
public string Alphabetic { get { return ((DerPrintableString) obj).GetString(); } }
|
||||
|
||||
public int Numeric { get { return ((DerInteger)obj).Value.IntValue; } }
|
||||
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return obj.ToAsn1Object();
|
||||
}
|
||||
}
|
||||
}
|
83
iTechSharp/srcbc/asn1/x509/qualified/MonetaryValue.cs
Normal file
83
iTechSharp/srcbc/asn1/x509/qualified/MonetaryValue.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
/**
|
||||
* The MonetaryValue object.
|
||||
* <pre>
|
||||
* MonetaryValue ::= SEQUENCE {
|
||||
* currency Iso4217CurrencyCode,
|
||||
* amount INTEGER,
|
||||
* exponent INTEGER }
|
||||
* -- value = amount * 10^exponent
|
||||
* </pre>
|
||||
*/
|
||||
public class MonetaryValue
|
||||
: Asn1Encodable
|
||||
{
|
||||
internal Iso4217CurrencyCode currency;
|
||||
internal DerInteger amount;
|
||||
internal DerInteger exponent;
|
||||
|
||||
public static MonetaryValue GetInstance(
|
||||
object obj)
|
||||
{
|
||||
if (obj == null || obj is MonetaryValue)
|
||||
{
|
||||
return (MonetaryValue) obj;
|
||||
}
|
||||
|
||||
if (obj is Asn1Sequence)
|
||||
{
|
||||
return new MonetaryValue(Asn1Sequence.GetInstance(obj));
|
||||
}
|
||||
|
||||
throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
|
||||
}
|
||||
|
||||
private MonetaryValue(
|
||||
Asn1Sequence seq)
|
||||
{
|
||||
if (seq.Count != 3)
|
||||
throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
|
||||
|
||||
currency = Iso4217CurrencyCode.GetInstance(seq[0]);
|
||||
amount = DerInteger.GetInstance(seq[1]);
|
||||
exponent = DerInteger.GetInstance(seq[2]);
|
||||
}
|
||||
|
||||
public MonetaryValue(
|
||||
Iso4217CurrencyCode currency,
|
||||
int amount,
|
||||
int exponent)
|
||||
{
|
||||
this.currency = currency;
|
||||
this.amount = new DerInteger(amount);
|
||||
this.exponent = new DerInteger(exponent);
|
||||
}
|
||||
|
||||
public Iso4217CurrencyCode Currency
|
||||
{
|
||||
get { return currency; }
|
||||
}
|
||||
|
||||
public BigInteger Amount
|
||||
{
|
||||
get { return amount.Value; }
|
||||
}
|
||||
|
||||
public BigInteger Exponent
|
||||
{
|
||||
get { return exponent.Value; }
|
||||
}
|
||||
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return new DerSequence(currency, amount, exponent);
|
||||
}
|
||||
}
|
||||
}
|
85
iTechSharp/srcbc/asn1/x509/qualified/QCStatement.cs
Normal file
85
iTechSharp/srcbc/asn1/x509/qualified/QCStatement.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
/**
|
||||
* The QCStatement object.
|
||||
* <pre>
|
||||
* QCStatement ::= SEQUENCE {
|
||||
* statementId OBJECT IDENTIFIER,
|
||||
* statementInfo ANY DEFINED BY statementId OPTIONAL}
|
||||
* </pre>
|
||||
*/
|
||||
public class QCStatement
|
||||
: Asn1Encodable
|
||||
{
|
||||
private readonly DerObjectIdentifier qcStatementId;
|
||||
private readonly Asn1Encodable qcStatementInfo;
|
||||
|
||||
public static QCStatement GetInstance(
|
||||
object obj)
|
||||
{
|
||||
if (obj == null || obj is QCStatement)
|
||||
{
|
||||
return (QCStatement) obj;
|
||||
}
|
||||
|
||||
if (obj is Asn1Sequence)
|
||||
{
|
||||
return new QCStatement(Asn1Sequence.GetInstance(obj));
|
||||
}
|
||||
|
||||
throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
|
||||
}
|
||||
|
||||
private QCStatement(
|
||||
Asn1Sequence seq)
|
||||
{
|
||||
qcStatementId = DerObjectIdentifier.GetInstance(seq[0]);
|
||||
|
||||
if (seq.Count > 1)
|
||||
{
|
||||
qcStatementInfo = seq[1];
|
||||
}
|
||||
}
|
||||
|
||||
public QCStatement(
|
||||
DerObjectIdentifier qcStatementId)
|
||||
{
|
||||
this.qcStatementId = qcStatementId;
|
||||
}
|
||||
|
||||
public QCStatement(
|
||||
DerObjectIdentifier qcStatementId,
|
||||
Asn1Encodable qcStatementInfo)
|
||||
{
|
||||
this.qcStatementId = qcStatementId;
|
||||
this.qcStatementInfo = qcStatementInfo;
|
||||
}
|
||||
|
||||
public DerObjectIdentifier StatementId
|
||||
{
|
||||
get { return qcStatementId; }
|
||||
}
|
||||
|
||||
public Asn1Encodable StatementInfo
|
||||
{
|
||||
get { return qcStatementInfo; }
|
||||
}
|
||||
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
Asn1EncodableVector seq = new Asn1EncodableVector(qcStatementId);
|
||||
|
||||
if (qcStatementInfo != null)
|
||||
{
|
||||
seq.Add(qcStatementInfo);
|
||||
}
|
||||
|
||||
return new DerSequence(seq);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
public sealed class Rfc3739QCObjectIdentifiers
|
||||
{
|
||||
private Rfc3739QCObjectIdentifiers()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// base id
|
||||
//
|
||||
public static readonly DerObjectIdentifier IdQcs = new DerObjectIdentifier("1.3.6.1.5.5.7.11");
|
||||
|
||||
public static readonly DerObjectIdentifier IdQcsPkixQCSyntaxV1 = new DerObjectIdentifier(IdQcs+".1");
|
||||
public static readonly DerObjectIdentifier IdQcsPkixQCSyntaxV2 = new DerObjectIdentifier(IdQcs+".2");
|
||||
}
|
||||
}
|
124
iTechSharp/srcbc/asn1/x509/qualified/SemanticsInformation.cs
Normal file
124
iTechSharp/srcbc/asn1/x509/qualified/SemanticsInformation.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
/**
|
||||
* The SemanticsInformation object.
|
||||
* <pre>
|
||||
* SemanticsInformation ::= SEQUENCE {
|
||||
* semanticsIdentifier OBJECT IDENTIFIER OPTIONAL,
|
||||
* nameRegistrationAuthorities NameRegistrationAuthorities
|
||||
* OPTIONAL }
|
||||
* (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
|
||||
* WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
|
||||
*
|
||||
* NameRegistrationAuthorities ::= SEQUENCE SIZE (1..MAX) OF
|
||||
* GeneralName
|
||||
* </pre>
|
||||
*/
|
||||
public class SemanticsInformation
|
||||
: Asn1Encodable
|
||||
{
|
||||
private readonly DerObjectIdentifier semanticsIdentifier;
|
||||
private readonly GeneralName[] nameRegistrationAuthorities;
|
||||
|
||||
public static SemanticsInformation GetInstance(
|
||||
object obj)
|
||||
{
|
||||
if (obj == null || obj is SemanticsInformation)
|
||||
{
|
||||
return (SemanticsInformation) obj;
|
||||
}
|
||||
|
||||
if (obj is Asn1Sequence)
|
||||
{
|
||||
return new SemanticsInformation(Asn1Sequence.GetInstance(obj));
|
||||
}
|
||||
|
||||
throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
|
||||
}
|
||||
|
||||
public SemanticsInformation(
|
||||
Asn1Sequence seq)
|
||||
{
|
||||
if (seq.Count < 1)
|
||||
{
|
||||
throw new ArgumentException("no objects in SemanticsInformation");
|
||||
}
|
||||
|
||||
IEnumerator e = seq.GetEnumerator();
|
||||
e.MoveNext();
|
||||
object obj = e.Current;
|
||||
if (obj is DerObjectIdentifier)
|
||||
{
|
||||
semanticsIdentifier = DerObjectIdentifier.GetInstance(obj);
|
||||
if (e.MoveNext())
|
||||
{
|
||||
obj = e.Current;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj != null)
|
||||
{
|
||||
Asn1Sequence generalNameSeq = Asn1Sequence.GetInstance(obj );
|
||||
nameRegistrationAuthorities = new GeneralName[generalNameSeq.Count];
|
||||
for (int i= 0; i < generalNameSeq.Count; i++)
|
||||
{
|
||||
nameRegistrationAuthorities[i] = GeneralName.GetInstance(generalNameSeq[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SemanticsInformation(
|
||||
DerObjectIdentifier semanticsIdentifier,
|
||||
GeneralName[] generalNames)
|
||||
{
|
||||
this.semanticsIdentifier = semanticsIdentifier;
|
||||
this.nameRegistrationAuthorities = generalNames;
|
||||
}
|
||||
|
||||
public SemanticsInformation(
|
||||
DerObjectIdentifier semanticsIdentifier)
|
||||
{
|
||||
this.semanticsIdentifier = semanticsIdentifier;
|
||||
}
|
||||
|
||||
public SemanticsInformation(
|
||||
GeneralName[] generalNames)
|
||||
{
|
||||
this.nameRegistrationAuthorities = generalNames;
|
||||
}
|
||||
|
||||
public DerObjectIdentifier SemanticsIdentifier { get { return semanticsIdentifier; } }
|
||||
|
||||
public GeneralName[] GetNameRegistrationAuthorities()
|
||||
{
|
||||
return nameRegistrationAuthorities;
|
||||
}
|
||||
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
Asn1EncodableVector seq = new Asn1EncodableVector();
|
||||
|
||||
if (this.semanticsIdentifier != null)
|
||||
{
|
||||
seq.Add(semanticsIdentifier);
|
||||
}
|
||||
|
||||
if (this.nameRegistrationAuthorities != null)
|
||||
{
|
||||
seq.Add(new DerSequence(nameRegistrationAuthorities));
|
||||
}
|
||||
|
||||
return new DerSequence(seq);
|
||||
}
|
||||
}
|
||||
}
|
91
iTechSharp/srcbc/asn1/x509/qualified/TypeOfBiometricData.cs
Normal file
91
iTechSharp/srcbc/asn1/x509/qualified/TypeOfBiometricData.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
/**
|
||||
* The TypeOfBiometricData object.
|
||||
* <pre>
|
||||
* TypeOfBiometricData ::= CHOICE {
|
||||
* predefinedBiometricType PredefinedBiometricType,
|
||||
* biometricDataOid OBJECT IDENTIFIER }
|
||||
*
|
||||
* PredefinedBiometricType ::= INTEGER {
|
||||
* picture(0),handwritten-signature(1)}
|
||||
* (picture|handwritten-signature)
|
||||
* </pre>
|
||||
*/
|
||||
public class TypeOfBiometricData
|
||||
: Asn1Encodable
|
||||
{
|
||||
public const int Picture = 0;
|
||||
public const int HandwrittenSignature = 1;
|
||||
|
||||
internal Asn1Encodable obj;
|
||||
|
||||
public static TypeOfBiometricData GetInstance(
|
||||
object obj)
|
||||
{
|
||||
if (obj == null || obj is TypeOfBiometricData)
|
||||
{
|
||||
return (TypeOfBiometricData) obj;
|
||||
}
|
||||
|
||||
if (obj is DerInteger)
|
||||
{
|
||||
DerInteger predefinedBiometricTypeObj = DerInteger.GetInstance(obj);
|
||||
int predefinedBiometricType = predefinedBiometricTypeObj.Value.IntValue;
|
||||
|
||||
return new TypeOfBiometricData(predefinedBiometricType);
|
||||
}
|
||||
|
||||
if (obj is DerObjectIdentifier)
|
||||
{
|
||||
DerObjectIdentifier BiometricDataOid = DerObjectIdentifier.GetInstance(obj);
|
||||
return new TypeOfBiometricData(BiometricDataOid);
|
||||
}
|
||||
|
||||
throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
|
||||
}
|
||||
|
||||
public TypeOfBiometricData(
|
||||
int predefinedBiometricType)
|
||||
{
|
||||
if (predefinedBiometricType == Picture || predefinedBiometricType == HandwrittenSignature)
|
||||
{
|
||||
obj = new DerInteger(predefinedBiometricType);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType);
|
||||
}
|
||||
}
|
||||
|
||||
public TypeOfBiometricData(
|
||||
DerObjectIdentifier biometricDataOid)
|
||||
{
|
||||
obj = biometricDataOid;
|
||||
}
|
||||
|
||||
public bool IsPredefined
|
||||
{
|
||||
get { return obj is DerInteger; }
|
||||
}
|
||||
|
||||
public int PredefinedBiometricType
|
||||
{
|
||||
get { return ((DerInteger) obj).Value.IntValue; }
|
||||
}
|
||||
|
||||
public DerObjectIdentifier BiometricDataOid
|
||||
{
|
||||
get { return (DerObjectIdentifier) obj; }
|
||||
}
|
||||
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return obj.ToAsn1Object();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user