Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ZlibExpanderProvider.java « jcajce « cms « bouncycastle « org « jdk1.1 « main « src « pkix - gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ff5c4518c6dd73c5b517bdfb81a33d7c654344f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package org.bouncycastle.cms.jcajce;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.InflaterInputStream;

import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.InputExpander;
import org.bouncycastle.operator.InputExpanderProvider;
import org.bouncycastle.util.io.StreamOverflowException;

public class ZlibExpanderProvider
    implements InputExpanderProvider
{
    private long limit;

    public ZlibExpanderProvider()
    {
        this.limit = -1;
    }

    /**
     * Create a provider which caps the number of expanded bytes that can be produced when the
     * compressed stream is parsed.
     *
     * @param limit max number of bytes allowed in an expanded stream.
     */
    public ZlibExpanderProvider(long limit)
    {
        this.limit = limit;
    }

    public InputExpander get(final AlgorithmIdentifier algorithm)
    {
        return new InputExpander()
        {
            public AlgorithmIdentifier getAlgorithmIdentifier()
            {
                return algorithm;
            }

            public InputStream getInputStream(InputStream comIn)
            {
                InputStream s = new InflaterInputStream(comIn);                
                if (limit >= 0)
                {
                    s = new LimitedInputStream(s, limit);
                }
                return s;
            }
        };
    }

    private static class LimitedInputStream
        extends FilterInputStream
    {
        private long remaining;

        public LimitedInputStream(InputStream input, long limit)
        {
            super(input);

            this.remaining = limit;
        }

        public int read()
            throws IOException
        {
            // Only a single 'extra' byte will ever be read
            if (remaining >= 0)
            {
                int b = super.in.read();
                if (b < 0 || --remaining >= 0)
                {
                    return b;
                }
            }

            throw new StreamOverflowException("expanded byte limit exceeded");
        }

        public int read(byte[] buf, int off, int len)
            throws IOException
        {
            if (len < 1)
            {
                // This will give correct exceptions/returns for strange lengths
                return super.read(buf, off, len);
            }

            if (remaining < 1)
            {
                // Will either return EOF or throw exception
                read();
                return -1;
            }

            /*
             * Limit the underlying request to 'remaining' bytes. This ensures the
             * caller will see the full 'limit' bytes before getting an exception.
             * Also, only one extra byte will ever be read.
             */
            int actualLen = (remaining > len ? len : (int)remaining);
            int numRead = super.in.read(buf, off, actualLen);
            if (numRead > 0)
            {
                remaining -= numRead;
            }
            return numRead;
        }
    }
}