// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.cms;

import java.util.Collections;
import org.bouncycastle.operator.OutputAEADEncryptor;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.BERSequenceGenerator;
import java.io.IOException;
import org.bouncycastle.operator.OutputEncryptor;
import java.io.OutputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.cms.EnvelopedData;
import org.bouncycastle.asn1.DLSet;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1EncodableVector;

public class CMSEnvelopedDataStreamGenerator extends CMSEnvelopedGenerator
{
    private int _bufferSize;
    private boolean _berEncodeRecipientSet;
    
    public void setBufferSize(final int bufferSize) {
        this._bufferSize = bufferSize;
    }
    
    public void setBEREncodeRecipients(final boolean berEncodeRecipientSet) {
        this._berEncodeRecipientSet = berEncodeRecipientSet;
    }
    
    private ASN1Integer getVersion(final ASN1EncodableVector asn1EncodableVector) {
        if (this.unprotectedAttributeGenerator != null) {
            return new ASN1Integer(EnvelopedData.calculateVersion(this.originatorInfo, new DLSet(asn1EncodableVector), new DLSet()));
        }
        return new ASN1Integer(EnvelopedData.calculateVersion(this.originatorInfo, new DLSet(asn1EncodableVector), null));
    }
    
    private OutputStream doOpen(final ASN1ObjectIdentifier asn1ObjectIdentifier, final OutputStream outputStream, final OutputEncryptor outputEncryptor) throws IOException, CMSException {
        return this.open(asn1ObjectIdentifier, outputStream, CMSUtils.getRecipentInfos(outputEncryptor.getKey(), this.recipientInfoGenerators), outputEncryptor);
    }
    
    protected OutputStream open(final ASN1ObjectIdentifier asn1ObjectIdentifier, final OutputStream outputStream, final ASN1EncodableVector asn1EncodableVector, final OutputEncryptor outputEncryptor) throws IOException {
        final BERSequenceGenerator berSequenceGenerator = new BERSequenceGenerator(outputStream);
        berSequenceGenerator.addObject(CMSObjectIdentifiers.envelopedData);
        final BERSequenceGenerator berSequenceGenerator2 = new BERSequenceGenerator(berSequenceGenerator.getRawOutputStream(), 0, true);
        berSequenceGenerator2.addObject(this.getVersion(asn1EncodableVector));
        CMSUtils.addOriginatorInfoToGenerator(berSequenceGenerator2, this.originatorInfo);
        CMSUtils.addRecipientInfosToGenerator(asn1EncodableVector, berSequenceGenerator2, this._berEncodeRecipientSet);
        final BERSequenceGenerator berSequenceGenerator3 = new BERSequenceGenerator(berSequenceGenerator2.getRawOutputStream());
        berSequenceGenerator3.addObject(asn1ObjectIdentifier);
        berSequenceGenerator3.getRawOutputStream().write(outputEncryptor.getAlgorithmIdentifier().getEncoded());
        return new CmsEnvelopedDataOutputStream(outputEncryptor, CMSUtils.createBEROctetOutputStream(berSequenceGenerator3.getRawOutputStream(), 0, false, this._bufferSize), berSequenceGenerator, berSequenceGenerator2, berSequenceGenerator3);
    }
    
    protected OutputStream open(final OutputStream outputStream, final ASN1EncodableVector asn1EncodableVector, final OutputEncryptor outputEncryptor) throws CMSException {
        try {
            return this.open(CMSObjectIdentifiers.data, outputStream, asn1EncodableVector, outputEncryptor);
        }
        catch (final IOException ex) {
            throw new CMSException("exception decoding algorithm parameters.", ex);
        }
    }
    
    public OutputStream open(final OutputStream outputStream, final OutputEncryptor outputEncryptor) throws CMSException, IOException {
        return this.doOpen(new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId()), outputStream, outputEncryptor);
    }
    
    public OutputStream open(final ASN1ObjectIdentifier asn1ObjectIdentifier, final OutputStream outputStream, final OutputEncryptor outputEncryptor) throws CMSException, IOException {
        return this.doOpen(asn1ObjectIdentifier, outputStream, outputEncryptor);
    }
    
    private class CmsEnvelopedDataOutputStream extends OutputStream
    {
        private final OutputEncryptor _encryptor;
        private final OutputStream _cOut;
        private OutputStream _octetStream;
        private BERSequenceGenerator _cGen;
        private BERSequenceGenerator _envGen;
        private BERSequenceGenerator _eiGen;
        
        public CmsEnvelopedDataOutputStream(final OutputEncryptor encryptor, final OutputStream octetStream, final BERSequenceGenerator cGen, final BERSequenceGenerator envGen, final BERSequenceGenerator eiGen) {
            this._encryptor = encryptor;
            this._octetStream = octetStream;
            this._cOut = encryptor.getOutputStream(octetStream);
            this._cGen = cGen;
            this._envGen = envGen;
            this._eiGen = eiGen;
        }
        
        @Override
        public void write(final int n) throws IOException {
            this._cOut.write(n);
        }
        
        @Override
        public void write(final byte[] b, final int off, final int len) throws IOException {
            this._cOut.write(b, off, len);
        }
        
        @Override
        public void write(final byte[] b) throws IOException {
            this._cOut.write(b);
        }
        
        @Override
        public void close() throws IOException {
            this._cOut.close();
            if (this._encryptor instanceof OutputAEADEncryptor) {
                this._octetStream.write(((OutputAEADEncryptor)this._encryptor).getMAC());
                this._octetStream.close();
            }
            this._eiGen.close();
            CMSUtils.addAttriSetToGenerator(this._envGen, CMSEnvelopedDataStreamGenerator.this.unprotectedAttributeGenerator, 1, Collections.EMPTY_MAP);
            this._envGen.close();
            this._cGen.close();
        }
    }
}
