001package ezvcard.property;
002
003import java.io.IOException;
004import java.io.InputStream;
005import java.nio.file.Path;
006import java.util.List;
007import java.util.Map;
008
009import ezvcard.VCard;
010import ezvcard.VCardVersion;
011import ezvcard.ValidationWarning;
012import ezvcard.parameter.KeyType;
013
014/*
015 Copyright (c) 2012-2023, Michael Angstadt
016 All rights reserved.
017
018 Redistribution and use in source and binary forms, with or without
019 modification, are permitted provided that the following conditions are met: 
020
021 1. Redistributions of source code must retain the above copyright notice, this
022 list of conditions and the following disclaimer. 
023 2. Redistributions in binary form must reproduce the above copyright notice,
024 this list of conditions and the following disclaimer in the documentation
025 and/or other materials provided with the distribution. 
026
027 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
028 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
029 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
030 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
031 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
032 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
033 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
034 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
035 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
036 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037
038 The views and conclusions contained in the software and documentation are those
039 of the authors and should not be interpreted as representing official policies, 
040 either expressed or implied, of the FreeBSD Project.
041 */
042
043/**
044 * <p>
045 * Defines a public encryption key.
046 * </p>
047 * 
048 * <p>
049 * <b>Code sample (creating)</b>
050 * </p>
051 * 
052 * <pre class="brush:java">
053 * VCard vcard = new VCard();
054 * 
055 * //URL
056 * Key key = new Key("http://www.mywebsite.com/my-public-key.pgp", KeyType.PGP);
057 * vcard.addKey(key);
058 * 
059 * //URI
060 * Key key = new Key("OPENPGP4FPR:ABAF11C65A2970B130ABE3C479BE3E4300411886", null);
061 * vcard.addKey(key);
062 * 
063 * //binary data
064 * byte data[] = ...
065 * key = new Key(data, KeyType.PGP);
066 * vcard.addKey(key);
067 * 
068 * //plain text value
069 * key = new Key();
070 * key.setText("...", KeyType.PGP);
071 * vcard.addKey(key);
072 * </pre>
073 * 
074 * <p>
075 * <b>Code sample (retrieving)</b>
076 * </p>
077 * 
078 * <pre class="brush:java">
079 * VCard vcard = ...
080 * for (Key key : vcard.getKeys()) {
081 *   KeyType contentType = key.getContentType(); //e.g. "application/pgp-keys"
082 * 
083 *   String url = key.getUrl();
084 *   if (url != null) {
085 *     //property value is a URL
086 *     continue;
087 *   }
088 *   
089 *   byte[] data = key.getData();
090 *   if (data != null) {
091 *     //property value is binary data
092 *     continue;
093 *   }
094 *   
095 *   String text = key.getText();
096 *   if (text != null) {
097 *     //property value is plain-text
098 *     continue;
099 *   }
100 * }
101 * </pre>
102 * 
103 * <p>
104 * <b>Property name:</b> {@code KEY}
105 * </p>
106 * <p>
107 * <b>Supported versions:</b> {@code 2.1, 3.0, 4.0}
108 * </p>
109 * @author Michael Angstadt
110 * @see <a href="http://tools.ietf.org/html/rfc6350#page-48">RFC 6350 p.48</a>
111 * @see <a href="http://tools.ietf.org/html/rfc2426#page-26">RFC 2426 p.26</a>
112 * @see <a href="http://www.imc.org/pdi/vcard-21.doc">vCard 2.1 p.22</a>
113 */
114public class Key extends BinaryProperty<KeyType> {
115        private String text;
116
117        /**
118         * Creates an empty key property.
119         */
120        public Key() {
121                super();
122        }
123
124        /**
125         * Creates a key property.
126         * @param data the binary data
127         * @param type the type of key (e.g. PGP)
128         */
129        public Key(byte data[], KeyType type) {
130                super(data, type);
131        }
132
133        /**
134         * Creates a key property.
135         * @param url the URI or URL to the key
136         * @param type the type of key (e.g. PGP) or null if the type can be
137         * identified from the URI
138         */
139        public Key(String url, KeyType type) {
140                super(url, type);
141        }
142
143        /**
144         * Creates a key property.
145         * @param in an input stream to the binary data (will be closed)
146         * @param type the content type (e.g. PGP)
147         * @throws IOException if there's a problem reading from the input stream
148         */
149        public Key(InputStream in, KeyType type) throws IOException {
150                super(in, type);
151        }
152
153        /**
154         * Creates a key property.
155         * @param file the key file
156         * @param type the content type (e.g. PGP)
157         * @throws IOException if there's a problem reading from the file
158         */
159        public Key(Path file, KeyType type) throws IOException {
160                super(file, type);
161        }
162
163        /**
164         * Copy constructor.
165         * @param original the property to make a copy of
166         */
167        public Key(Key original) {
168                super(original);
169                text = original.text;
170        }
171
172        /**
173         * Sets a plain text representation of the key.
174         * @param text the key in plain text
175         * @param type the key type
176         */
177        public void setText(String text, KeyType type) {
178                this.text = text;
179                data = null;
180                url = null;
181                setContentType(type);
182        }
183
184        /**
185         * Gets the plain text representation of the key.
186         * @return the key in plain text
187         */
188        public String getText() {
189                return text;
190        }
191
192        /**
193         * Sets the URL or URI of the key.
194         * @param url the URL or URI of the key
195         * @param type the type of key (e.g. PGP) or null if the type can be
196         * identified from the URI
197         */
198        @Override
199        public void setUrl(String url, KeyType type) {
200                super.setUrl(url, type);
201                text = null;
202        }
203
204        /**
205         * Gets the URL or URI of the key.
206         * @return the URL/URI or null if there is none
207         */
208        @Override
209        public String getUrl() {
210                return super.getUrl();
211        }
212
213        @Override
214        public void setData(byte[] data, KeyType type) {
215                super.setData(data, type);
216                text = null;
217        }
218
219        @Override
220        protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) {
221                if (url == null && data == null && text == null) {
222                        warnings.add(new ValidationWarning(8));
223                }
224
225                if (url != null && (version == VCardVersion.V2_1 || version == VCardVersion.V3_0)) {
226                        warnings.add(new ValidationWarning(15));
227                }
228        }
229
230        @Override
231        protected Map<String, Object> toStringValues() {
232                Map<String, Object> values = super.toStringValues();
233                values.put("text", text);
234                return values;
235        }
236
237        @Override
238        public Key copy() {
239                return new Key(this);
240        }
241
242        @Override
243        public int hashCode() {
244                final int prime = 31;
245                int result = super.hashCode();
246                result = prime * result + ((text == null) ? 0 : text.hashCode());
247                return result;
248        }
249
250        @Override
251        public boolean equals(Object obj) {
252                if (this == obj) return true;
253                if (!super.equals(obj)) return false;
254                Key other = (Key) obj;
255                if (text == null) {
256                        if (other.text != null) return false;
257                } else if (!text.equals(other.text)) return false;
258                return true;
259        }
260}