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.provider; 018 019import java.io.IOException; 020import java.util.ArrayList; 021 022import org.jivesoftware.smack.datatypes.UInt32; 023import org.jivesoftware.smack.packet.IqData; 024import org.jivesoftware.smack.packet.XmlEnvironment; 025import org.jivesoftware.smack.provider.IqProvider; 026import org.jivesoftware.smack.util.ParserUtils; 027import org.jivesoftware.smack.xml.XmlPullParser; 028import org.jivesoftware.smack.xml.XmlPullParserException; 029 030import org.jivesoftware.smackx.privacy.packet.Privacy; 031import org.jivesoftware.smackx.privacy.packet.PrivacyItem; 032 033import org.jxmpp.JxmppContext; 034 035/** 036 * The PrivacyProvider parses {@link Privacy} packets. {@link Privacy} 037 * Parses the <code>query</code> sub-document and creates an instance of {@link Privacy}. 038 * For each <code>item</code> in the <code>list</code> element, it creates an instance 039 * of {@link PrivacyItem}. 040 * 041 * @author Francisco Vives 042 */ 043public class PrivacyProvider extends IqProvider<Privacy> { 044 045 @Override 046 public Privacy parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) 047 throws XmlPullParserException, IOException { 048 Privacy privacy = new Privacy(); 049 boolean done = false; 050 while (!done) { 051 XmlPullParser.Event eventType = parser.next(); 052 if (eventType == XmlPullParser.Event.START_ELEMENT) { 053 // CHECKSTYLE:OFF 054 if (parser.getName().equals("active")) { 055 String activeName = parser.getAttributeValue("", "name"); 056 if (activeName == null) { 057 privacy.setDeclineActiveList(true); 058 } else { 059 privacy.setActiveName(activeName); 060 } 061 } 062 else if (parser.getName().equals("default")) { 063 String defaultName = parser.getAttributeValue("", "name"); 064 if (defaultName == null) { 065 privacy.setDeclineDefaultList(true); 066 } else { 067 privacy.setDefaultName(defaultName); 068 } 069 } 070 // CHECKSTYLE:ON 071 else if (parser.getName().equals("list")) { 072 parseList(parser, privacy); 073 } 074 } 075 else if (eventType == XmlPullParser.Event.END_ELEMENT) { 076 if (parser.getName().equals("query")) { 077 done = true; 078 } 079 } 080 } 081 082 return privacy; 083 } 084 085 // Parse the list complex type 086 private static void parseList(XmlPullParser parser, Privacy privacy) throws XmlPullParserException, IOException { 087 boolean done = false; 088 String listName = parser.getAttributeValue("", "name"); 089 ArrayList<PrivacyItem> items = new ArrayList<>(); 090 while (!done) { 091 XmlPullParser.Event eventType = parser.next(); 092 if (eventType == XmlPullParser.Event.START_ELEMENT) { 093 if (parser.getName().equals("item")) { 094 // CHECKSTYLE:OFF 095 items.add(parseItem(parser)); 096 // CHECKSTYLE:ON 097 } 098 } 099 else if (eventType == XmlPullParser.Event.END_ELEMENT) { 100 if (parser.getName().equals("list")) { 101 done = true; 102 } 103 } 104 } 105 106 privacy.setPrivacyList(listName, items); 107 // CHECKSTYLE:OFF 108 } 109 110 // Parse the list complex type 111 private static PrivacyItem parseItem(XmlPullParser parser) throws XmlPullParserException, IOException { 112 // CHECKSTYLE:ON 113 // Retrieves the required attributes 114 String actionValue = parser.getAttributeValue("", "action"); 115 // Set the order number, this attribute is required 116 UInt32 order = ParserUtils.getUInt32Attribute(parser, "order"); 117 118 // If type is not set, then it's the fall-through case 119 String type = parser.getAttributeValue("", "type"); 120 121 /* 122 * According the action value it sets the allow status. The fall-through action is assumed 123 * to be "allow" 124 */ 125 boolean allow; 126 switch (actionValue) { 127 case "allow": 128 allow = true; 129 break; 130 case "deny": 131 allow = false; 132 break; 133 default: 134 // TODO: Should be SmackParsingException. 135 throw new IOException("Unknown action value '" + actionValue + "'"); 136 } 137 138 PrivacyItem item; 139 if (type != null) { 140 // If the type is not null, then we are dealing with a standard privacy item 141 String value = parser.getAttributeValue("", "value"); 142 item = new PrivacyItem(PrivacyItem.Type.valueOf(type), value, allow, order); 143 } 144 else { 145 // If the type is null, then we are dealing with the fall-through privacy item. 146 item = new PrivacyItem(allow, order); 147 } 148 parseItemChildElements(parser, item); 149 return item; 150 // CHECKSTYLE:OFF 151 } 152 // CHECKSTYLE:ON 153 154 private static void parseItemChildElements(XmlPullParser parser, PrivacyItem privacyItem) throws XmlPullParserException, IOException { 155 final int initialDepth = parser.getDepth(); 156 157 outerloop: while (true) { 158 XmlPullParser.Event eventType = parser.next(); 159 switch (eventType) { 160 case START_ELEMENT: 161 String name = parser.getName(); 162 switch (name) { 163 case "iq": 164 privacyItem.setFilterIQ(true); 165 break; 166 case "message": 167 privacyItem.setFilterMessage(true); 168 break; 169 case "presence-in": 170 privacyItem.setFilterPresenceIn(true); 171 break; 172 case "presence-out": 173 privacyItem.setFilterPresenceOut(true); 174 break; 175 } 176 break; 177 case END_ELEMENT: 178 if (parser.getDepth() == initialDepth) { 179 break outerloop; 180 } 181 break; 182 default: 183 // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. 184 break; 185 } 186 } 187 } 188}