001/**
002 *
003 * Copyright the original author or authors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.privacy.packet;
018
019import org.jivesoftware.smack.util.NumberUtil;
020
021/**
022 * A privacy item acts a rule that when matched defines if a stanza should be blocked or not.
023 *
024 * Privacy Items can handle different kind of blocking communications based on JID, group,
025 * subscription type or globally by:<ul>
026 * <li>Allowing or blocking messages.
027 * <li>Allowing or blocking inbound presence notifications.
028 * <li>Allowing or blocking outbound presence notifications.
029 * <li>Allowing or blocking IQ stanzas.
030 * <li>Allowing or blocking all communications.
031 * </ul>
032 * @author Francisco Vives
033 */
034public class PrivacyItem {
035    /**
036     * Value for subscription type rules.
037     */
038    public static final String SUBSCRIPTION_BOTH = "both";
039    public static final String SUBSCRIPTION_TO = "to";
040    public static final String SUBSCRIPTION_FROM = "from";
041    public static final String SUBSCRIPTION_NONE = "none";
042
043    /** allow is the action associated with the item, it can allow or deny the communication. */
044    private final boolean allow;
045
046    /**
047     * order is a unsigned 32-bit integer that is unique among all items in the list.
048     **/
049    private final long order;
050
051    /**
052     * Type defines if the rule is based on JIDs, roster groups or presence subscription types.
053     * Available values are: [jid|group|subscription]
054     */
055    private final Type type;
056
057    /**
058     * The value hold the element identifier to apply the action. If the type is "jid", then the
059     * 'value' attribute MUST contain a valid Jabber ID. If the type is "group", then the
060     * 'value' attribute SHOULD contain the name of a group in the user's roster. If the type is
061     * "subscription", then the 'value' attribute MUST be one of "both", "to", "from", or
062     * "none".
063     */
064    private final String value;
065
066    /** blocks incoming IQ stanzas. */
067    private boolean filterIQ = false;
068    /** filterMessage blocks incoming message stanzas. */
069    private boolean filterMessage = false;
070    /** blocks incoming presence notifications. */
071    private boolean filterPresenceIn = false;
072    /** blocks outgoing presence notifications. */
073    private boolean filterPresenceOut = false;
074
075    /**
076     * Creates a new fall-through privacy item.
077     *
078     * This is usually the last item in a privacy list and has no 'type' attribute.
079     *
080     * @param allow true if this is an allow item
081     * @param order the order of this privacy item
082     */
083    public PrivacyItem(boolean allow, long order) {
084        this(null, null, allow, order);
085    }
086
087    /**
088     * Creates a new privacy item.
089     *
090     * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
091     * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
092     * in the user's roster.
093     * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
094     * "from", or "none".
095     *
096     * @param type the type.
097     * @param value the value of the privacy item
098     * @param allow true if this is an allow item
099     * @param order the order of this privacy item
100     */
101    public PrivacyItem(Type type, String value, boolean allow, long order) {
102        NumberUtil.checkIfInUInt32Range(order);
103        this.type = type;
104        this.value = value;
105        this.allow = allow;
106        this.order = order;
107    }
108
109    /**
110     * Creates a new privacy item.
111     *
112     * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
113     * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
114     * in the user's roster.
115     * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
116     * "from", or "none".
117     *
118     * @param type the type.
119     * @param value the value of the privacy item
120     * @param allow true if this is an allow item
121     * @param order the order of this privacy item
122     */
123    public PrivacyItem(Type type, CharSequence value, boolean allow, long order) {
124        this(type, value != null ? value.toString() : null, allow, order);
125    }
126
127    /**
128     * Returns the action associated with the item, it MUST be filled and will allow or deny
129     * the communication.
130     *
131     * @return the allow communication status.
132     */
133    public boolean isAllow() {
134    // CHECKSTYLE:OFF
135                return allow;
136        }
137    // CHECKSTYLE:ON
138
139    /**
140     * Returns whether the receiver allow or deny incoming IQ stanzas or not.
141     *
142     * @return the iq filtering status.
143     */
144    public boolean isFilterIQ() {
145    // CHECKSTYLE:OFF
146                return filterIQ;
147        }
148    // CHECKSTYLE:ON
149
150    /**
151     * Sets whether the receiver allows or denies incoming IQ stanzas or not.
152     *
153     * @param filterIQ indicates if the receiver allows or denies incoming IQ stanzas.
154     */
155    public void setFilterIQ(boolean filterIQ) {
156    // CHECKSTYLE:OFF
157
158                this.filterIQ = filterIQ;
159        }
160    // CHECKSTYLE:ON
161
162    /**
163     * Returns whether the receiver allows or denies incoming messages or not.
164     *
165     * @return the message filtering status.
166     */
167    public boolean isFilterMessage() {
168        // CHECKSTYLE:OFF
169                return filterMessage;
170        }
171    // CHECKSTYLE:ON
172
173    /**
174     * Sets wheather the receiver allows or denies incoming messages or not.
175     *
176     * @param filterMessage indicates if the receiver allows or denies incoming messages or not.
177     */
178    public void setFilterMessage(boolean filterMessage) {
179        // CHECKSTYLE:OFF
180                this.filterMessage = filterMessage;
181        }
182    // CHECKSTYLE:ON
183
184    /**
185     * Returns whether the receiver allows or denies incoming presence or not.
186     *
187     * @return the iq filtering incoming presence status.
188     */
189    public boolean isFilterPresenceIn() {
190        // CHECKSTYLE:OFF
191                return filterPresenceIn;
192        }
193    // CHECKSTYLE:ON
194
195    /**
196     * Sets whether the receiver allows or denies incoming presence or not.
197     *
198     * @param filterPresenceIn indicates if the receiver allows or denies filtering incoming presence.
199     */
200    public void setFilterPresenceIn(boolean filterPresenceIn) {
201        // CHECKSTYLE:OFF
202                this.filterPresenceIn = filterPresenceIn;
203        }
204    // CHECKSTYLE:ON
205
206    /**
207     * Returns whether the receiver allows or denies incoming presence or not.
208     *
209     * @return the iq filtering incoming presence status.
210     */
211    public boolean isFilterPresenceOut() {
212        // CHECKSTYLE:OFF
213                return filterPresenceOut;
214        }
215    // CHECKSTYLE:ON
216
217    /**
218     * Sets whether the receiver allows or denies outgoing presence or not.
219     *
220     * @param filterPresenceOut indicates if the receiver allows or denies filtering outgoing presence
221     */
222    public void setFilterPresenceOut(boolean filterPresenceOut) {
223        // CHECKSTYLE:OFF
224                this.filterPresenceOut = filterPresenceOut;
225        }
226    // CHECKSTYLE:ON
227
228    /**
229     * Returns the order where the receiver is processed. List items are processed in
230     * ascending order.
231     *
232     * The order MUST be filled and its value MUST be a non-negative integer
233     * that is unique among all items in the list.
234     *
235     * @return the order number.
236     */
237    public long getOrder() {
238        // CHECKSTYLE:OFF
239                return order;
240        }
241    // CHECKSTYLE:ON
242
243    /**
244     * Returns the type hold the kind of communication it will allow or block.
245     * It MUST be filled with one of these values: jid, group or subscription.
246     *
247     * @return the type of communication it represent.
248     */
249    public Type getType() {
250        return type;
251    // CHECKSTYLE:OFF
252        }
253    // CHECKSTYLE:ON
254
255    /**
256     * Returns the element identifier to apply the action.
257     *
258     * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
259     * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
260     * in the user's roster.
261     * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
262     * "from", or "none".
263     *
264     * @return the identifier to apply the action.
265     */
266    public String getValue() {
267        return value;
268        // CHECKSTYLE:OFF
269        }
270    // CHECKSTYLE:ON
271
272    /**
273     * Returns whether the receiver allows or denies every kind of communication.
274     *
275     * When filterIQ, filterMessage, filterPresenceIn and filterPresenceOut are not set
276     * the receiver will block all communications.
277     *
278     * @return the all communications status.
279     */
280    public boolean isFilterEverything() {
281        // CHECKSTYLE:OFF
282                return !(this.isFilterIQ() || this.isFilterMessage() || this.isFilterPresenceIn()
283                                || this.isFilterPresenceOut());
284        }
285
286        /**
287         * Answer an xml representation of the receiver according to the RFC 3921.
288         *
289         * @return the text xml representation.
290     */
291    public String toXML() {
292        StringBuilder buf = new StringBuilder();
293        buf.append("<item");
294        if (this.isAllow()) {
295                buf.append(" action=\"allow\"");
296        } else {
297                buf.append(" action=\"deny\"");
298        }
299        buf.append(" order=\"").append(getOrder()).append('"');
300        if (getType() != null) {
301            buf.append(" type=\"").append(getType()).append('"');
302        }
303        if (getValue() != null) {
304            buf.append(" value=\"").append(getValue()).append('"');
305        }
306        if (isFilterEverything()) {
307                buf.append("/>");
308        } else {
309                buf.append('>');
310                if (this.isFilterIQ()) {
311                buf.append("<iq/>");
312            }
313                if (this.isFilterMessage()) {
314                buf.append("<message/>");
315            }
316                if (this.isFilterPresenceIn()) {
317                buf.append("<presence-in/>");
318            }
319                if (this.isFilterPresenceOut()) {
320                buf.append("<presence-out/>");
321            }
322                buf.append("</item>");
323        }
324        // CHECKSTYLE:ON
325        return buf.toString();
326    }
327
328    /**
329     * Type defines if the rule is based on JIDs, roster groups or presence subscription types.
330     */
331    public enum Type {
332        /**
333         * JID being analyzed should belong to a roster group of the list's owner.
334         */
335        group,
336        /**
337         * JID being analyzed should have a resource match, domain match or bare JID match.
338         */
339        jid,
340        /**
341         * JID being analyzed should belong to a contact present in the owner's roster with the
342         * specified subscription status.
343         */
344        subscription
345    }
346}