1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Vladimir N. Molotkov, Stepan M. Mishura
20* @version $Revision$
21*/
22
23package org.apache.harmony.security.asn1;
24
25import java.io.IOException;
26import java.nio.charset.StandardCharsets;
27
28/**
29 * This class is the super class for all string ASN.1 types
30 *
31 * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
32 */
33public abstract class ASN1StringType extends ASN1Type {
34
35    private static class ASN1StringUTF8Type extends ASN1StringType {
36        public ASN1StringUTF8Type(int tagNumber) {
37            super(tagNumber);
38        }
39
40        @Override
41        public Object getDecodedObject(BerInputStream in) throws IOException {
42            return new String(in.buffer, in.contentOffset, in.length, StandardCharsets.UTF_8);
43        }
44
45        @Override
46        public void setEncodingContent(BerOutputStream out) {
47            byte[] bytes = ((String) out.content).getBytes(StandardCharsets.UTF_8);
48            out.content = bytes;
49            out.length = bytes.length;
50        }
51    }
52
53    // TODO: what about defining them as separate classes?
54    // TODO: check decoded/encoded characters
55    public static final ASN1StringType BMPSTRING = new ASN1StringType(TAG_BMPSTRING) {};
56
57    public static final ASN1StringType IA5STRING = new ASN1StringType(TAG_IA5STRING) {};
58
59    public static final ASN1StringType GENERALSTRING = new ASN1StringType(TAG_GENERALSTRING) {};
60
61    public static final ASN1StringType PRINTABLESTRING = new ASN1StringType(TAG_PRINTABLESTRING) {};
62
63    public static final ASN1StringType TELETEXSTRING = new ASN1StringUTF8Type(TAG_TELETEXSTRING) {};
64
65    public static final ASN1StringType UNIVERSALSTRING = new ASN1StringType(TAG_UNIVERSALSTRING) {};
66
67    public static final ASN1StringType UTF8STRING = new ASN1StringUTF8Type(TAG_UTF8STRING) {};
68
69    public ASN1StringType(int tagNumber) {
70        super(tagNumber);
71    }
72
73    /**
74     * Tests provided identifier.
75     *
76     * @param identifier identifier to be verified
77     * @return true if identifier correspond to primitive or constructed
78     *     identifier of this ASN.1 string type, otherwise false
79     */
80    public final boolean checkTag(int identifier) {
81        return this.id == identifier || this.constrId == identifier;
82    }
83
84    public Object decode(BerInputStream in) throws IOException {
85        in.readString(this);
86
87        if (in.isVerify) {
88            return null;
89        }
90        return getDecodedObject(in);
91    }
92
93    /**
94     * Extracts String object from BER input stream.
95     */
96    public Object getDecodedObject(BerInputStream in) throws IOException {
97        /* To ensure we get the correct encoding on non-ASCII platforms, specify
98           that we wish to convert from ASCII to the default platform encoding */
99        return new String(in.buffer, in.contentOffset, in.length, StandardCharsets.ISO_8859_1);
100    }
101
102    public void encodeASN(BerOutputStream out) {
103        out.encodeTag(id);
104        encodeContent(out);
105    }
106
107    public void encodeContent(BerOutputStream out) {
108        out.encodeString();
109    }
110
111    public void setEncodingContent(BerOutputStream out) {
112        byte[] bytes = ((String) out.content).getBytes(StandardCharsets.UTF_8);
113        out.content = bytes;
114        out.length = bytes.length;
115    }
116}
117