2 * Copyright (C) 2010 Collabora Ltd.
3 * Copyright (C) 2011 Philip Withnall
5 * This library is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 2.1 of the License, or
8 * (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <http://www.gnu.org/licenses/>.
19 * Philip Withnall <philip.withnall@collabora.co.uk>
26 * Errors related to IM addresses and IM address handling.
28 public errordomain Folks.ImDetailsError
31 * The specified IM address could not be parsed.
37 * Object representing an IM address value that can have some parameters
40 * See {@link Folks.AbstractFieldDetails}.
44 public class Folks.ImFieldDetails : AbstractFieldDetails<string>
47 * Create a new ImFieldDetails.
49 * @param value the value of the field, which should be a valid, non-empty
51 * @param parameters initial parameters. See
52 * {@link AbstractFieldDetails.parameters}. A ``null`` value is equivalent to
53 * an empty map of parameters.
55 * @return a new ImFieldDetails
59 public ImFieldDetails (string value,
60 MultiMap<string, string>? parameters = null)
64 warning ("Empty IM address passed to ImFieldDetails.");
68 if (parameters != null)
69 this.parameters = (!) parameters;
77 public override bool equal (AbstractFieldDetails<string> that)
79 return base.equal (that);
87 public override uint hash ()
94 * IM addresses exposed by an object implementing {@link PresenceDetails}.
98 public interface Folks.ImDetails : Object
101 * A mapping of IM protocol to an (unordered) set of IM addresses.
103 * Each mapping is from an arbitrary protocol identifier to a set of IM
104 * addresses on that protocol for the contact, listed in no particular order.
106 * There must be no duplicate IM addresses in each set, though a given
107 * IM address may be present in the sets for different protocols.
109 * All the IM addresses must be normalised using
110 * {@link ImDetails.normalise_im_address} before being added to this property.
114 public abstract MultiMap<string, ImFieldDetails> im_addresses
120 * Change the contact's set of IM addresses.
122 * It's preferred to call this rather than setting
123 * {@link ImDetails.im_addresses} directly, as this method gives error
124 * notification and will only return once the IM addresses have been written
125 * to the relevant backing store (or the operation's failed).
127 * @param im_addresses the new map of protocols to IM addresses
128 * @throws PropertyError if setting the IM addresses failed
131 public virtual async void change_im_addresses (
132 MultiMap<string, ImFieldDetails> im_addresses) throws PropertyError
134 /* Default implementation. */
135 throw new PropertyError.NOT_WRITEABLE (
136 _("IM addresses are not writeable on this contact."));
140 * Normalise an IM address so that it's suitable for string comparison.
142 * IM addresses for various protocols can be represented in different ways,
143 * only one of which is canonical. In order to allow simple string comparisons
144 * of IM addresses to work, the IM addresses must be normalised beforehand.
146 * If the provided IM address is invalid,
147 * {@link Folks.ImDetailsError.INVALID_IM_ADDRESS} will be thrown. Note that
148 * this isn't guaranteed to be thrown for all invalid addresses, but if it is
149 * thrown, the address is guaranteed to be invalid.
151 * @param im_address the address to normalise
152 * @param protocol the protocol of this im_address
155 * @throws Folks.ImDetailsError if the provided IM address was invalid
157 public static string normalise_im_address (string im_address, string protocol)
158 throws Folks.ImDetailsError
160 if (protocol == "aim" || protocol == "myspace")
162 return im_address.replace (" ", "").down ().normalize ();
164 else if (protocol == "irc" || protocol == "yahoo" ||
165 protocol == "yahoojp" || protocol == "groupwise")
167 return im_address.down ().normalize ();
169 else if (protocol == "jabber")
172 string[] parts = im_address.split ("/", 2);
174 if (parts.length < 1)
176 throw new ImDetailsError.INVALID_IM_ADDRESS (
177 /* Translators: the parameter is an IM address. */
178 _("The IM address '%s' could not be understood."),
182 string? resource = null;
183 if (parts.length == 2)
186 parts = parts[0].split ("@", 2);
188 if (parts.length < 1)
190 throw new ImDetailsError.INVALID_IM_ADDRESS (
191 /* Translators: the parameter is an IM address. */
192 _("The IM address '%s' could not be understood."),
196 string? node, _domain;
197 if (parts.length == 2)
208 if ((node != null && node == "") ||
209 (_domain == null || _domain == "") ||
210 (resource != null && resource == ""))
212 throw new ImDetailsError.INVALID_IM_ADDRESS (
213 /* Translators: the parameter is an IM address. */
214 _("The IM address '%s' could not be understood."),
218 string domain = ((!) _domain).down ();
220 node = ((!) node).down ();
222 /* Build a new JID */
223 string? normalised = null;
225 if (node != null && resource != null)
227 normalised = "%s@%s/%s".printf ((!) node, domain, (!) resource);
229 else if (node != null)
231 normalised = "%s@%s".printf ((!) node, domain);
233 else if (resource != null)
235 normalised = "%s/%s".printf (domain, (!) resource);
239 throw new ImDetailsError.INVALID_IM_ADDRESS (
240 /* Translators: the parameter is an IM address. */
241 _("The IM address '%s' could not be understood."),
245 return ((!) normalised).normalize (-1, NormalizeMode.NFKC);
250 return im_address.normalize ();