001/*
002 * $Id: PdfString.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf;
045
046import java.io.IOException;
047import java.io.OutputStream;
048
049/**
050 * A <CODE>PdfString</CODE>-class is the PDF-equivalent of a
051 * JAVA-<CODE>String</CODE>-object.
052 * <P>
053 * A string is a sequence of characters delimited by parenthesis.
054 * If a string is too long to be conveniently placed on a single line, it may
055 * be split across multiple lines by using the backslash character (\) at the
056 * end of a line to indicate that the string continues on the following line.
057 * Within a string, the backslash character is used as an escape to specify
058 * unbalanced parenthesis, non-printing ASCII characters, and the backslash
059 * character itself. Use of the \<I>ddd</I> escape sequence is the preferred
060 * way to represent characters outside the printable ASCII character set.<BR>
061 * This object is described in the 'Portable Document Format Reference Manual
062 * version 1.7' section 3.2.3 (page 53-56).
063 *
064 * @see PdfObject
065 * @see BadPdfFormatException
066 */
067public class PdfString extends PdfObject {
068    
069    // CLASS VARIABLES
070    
071    /** The value of this object. */
072    protected String value = NOTHING;
073    
074    protected String originalValue = null;
075    
076    /** The encoding. */
077    protected String encoding = TEXT_PDFDOCENCODING;
078    
079    protected int objNum = 0;
080    
081    protected int objGen = 0;
082    
083    protected boolean hexWriting = false;
084
085    // CONSTRUCTORS
086    
087    /**
088     * Constructs an empty <CODE>PdfString</CODE>-object.
089     */
090    public PdfString() {
091        super(STRING);
092    }
093    
094    /**
095     * Constructs a <CODE>PdfString</CODE>-object containing a string in the
096     * standard encoding <CODE>TEXT_PDFDOCENCODING</CODE>.
097     *
098     * @param value    the content of the string
099     */
100    public PdfString(String value) {
101        super(STRING);
102        this.value = value;
103    }
104    
105    /**
106     * Constructs a <CODE>PdfString</CODE>-object containing a string in the
107     * specified encoding.
108     *
109     * @param value    the content of the string
110     * @param encoding an encoding
111     */
112    public PdfString(String value, String encoding) {
113        super(STRING);
114        this.value = value;
115        this.encoding = encoding;
116    }
117    
118    /**
119     * Constructs a <CODE>PdfString</CODE>-object.
120     *
121     * @param bytes    an array of <CODE>byte</CODE>
122     */
123    public PdfString(byte[] bytes) {
124        super(STRING);
125        value = PdfEncodings.convertToString(bytes, null);
126        encoding = NOTHING;
127    }
128    
129    // methods overriding some methods in PdfObject
130    
131    /**
132     * Writes the PDF representation of this <CODE>PdfString</CODE> as an array
133     * of <CODE>byte</CODE> to the specified <CODE>OutputStream</CODE>.
134     * 
135     * @param writer for backwards compatibility
136     * @param os The <CODE>OutputStream</CODE> to write the bytes to.
137     */
138    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
139        byte b[] = getBytes();
140        PdfEncryption crypto = null;
141        if (writer != null)
142            crypto = writer.getEncryption();
143        if (crypto != null && !crypto.isEmbeddedFilesOnly())
144            b = crypto.encryptByteArray(b);
145        if (hexWriting) {
146            ByteBuffer buf = new ByteBuffer();
147            buf.append('<');
148            int len = b.length;
149            for (int k = 0; k < len; ++k)
150                buf.appendHex(b[k]);
151            buf.append('>');
152            os.write(buf.toByteArray());
153        }
154        else
155            os.write(PdfContentByte.escapeString(b));
156    }
157    
158    /**
159     * Returns the <CODE>String</CODE> value of this <CODE>PdfString</CODE>-object.
160     *
161     * @return A <CODE>String</CODE>
162     */
163    public String toString() {
164        return value;
165    }
166    
167    public byte[] getBytes() {
168        if (bytes == null) {
169            if (encoding != null && encoding.equals(TEXT_UNICODE) && PdfEncodings.isPdfDocEncoding(value))
170                bytes = PdfEncodings.convertToBytes(value, TEXT_PDFDOCENCODING);
171            else
172                bytes = PdfEncodings.convertToBytes(value, encoding);
173        }
174        return bytes;
175    }
176    
177    // other methods
178    
179    /**
180     * Returns the Unicode <CODE>String</CODE> value of this
181     * <CODE>PdfString</CODE>-object.
182     *
183     * @return A <CODE>String</CODE>
184     */
185    public String toUnicodeString() {
186        if (encoding != null && encoding.length() != 0)
187            return value;
188        getBytes();
189        if (bytes.length >= 2 && bytes[0] == (byte)254 && bytes[1] == (byte)255)
190            return PdfEncodings.convertToString(bytes, PdfObject.TEXT_UNICODE);
191        else
192            return PdfEncodings.convertToString(bytes, PdfObject.TEXT_PDFDOCENCODING);
193    }
194    
195    /**
196     * Gets the encoding of this string.
197     *
198     * @return a <CODE>String</CODE>
199     */
200    public String getEncoding() {
201        return encoding;
202    }
203    
204    void setObjNum(int objNum, int objGen) {
205        this.objNum = objNum;
206        this.objGen = objGen;
207    }
208    
209    /**
210     * Decrypt an encrypted <CODE>PdfString</CODE>
211     */
212    void decrypt(PdfReader reader) {
213        PdfEncryption decrypt = reader.getDecrypt();
214        if (decrypt != null) {
215            originalValue = value;
216            decrypt.setHashKey(objNum, objGen);
217            bytes = PdfEncodings.convertToBytes(value, null);
218            bytes = decrypt.decryptByteArray(bytes);
219            value = PdfEncodings.convertToString(bytes, null);
220        }
221    }
222   
223    public byte[] getOriginalBytes() {
224        if (originalValue == null)
225            return getBytes();
226        return PdfEncodings.convertToBytes(originalValue, null);
227    }
228    
229    public PdfString setHexWriting(boolean hexWriting) {
230        this.hexWriting = hexWriting;
231        return this;
232    }
233    
234    public boolean isHexWriting() {
235        return hexWriting;
236    }
237}