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