001/** 002 * 003 * Copyright 2020 Paul Schaub 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.stanza_content_encryption.provider; 018 019import java.io.IOException; 020import java.text.ParseException; 021import java.util.Date; 022 023import org.jivesoftware.smack.packet.XmlElement; 024import org.jivesoftware.smack.packet.XmlEnvironment; 025import org.jivesoftware.smack.parsing.SmackParsingException; 026import org.jivesoftware.smack.provider.ExtensionElementProvider; 027import org.jivesoftware.smack.util.PacketParserUtils; 028import org.jivesoftware.smack.util.ParserUtils; 029import org.jivesoftware.smack.xml.XmlPullParser; 030import org.jivesoftware.smack.xml.XmlPullParserException; 031 032import org.jivesoftware.smackx.stanza_content_encryption.element.AffixElement; 033import org.jivesoftware.smackx.stanza_content_encryption.element.ContentElement; 034import org.jivesoftware.smackx.stanza_content_encryption.element.FromAffixElement; 035import org.jivesoftware.smackx.stanza_content_encryption.element.PayloadElement; 036import org.jivesoftware.smackx.stanza_content_encryption.element.RandomPaddingAffixElement; 037import org.jivesoftware.smackx.stanza_content_encryption.element.TimestampAffixElement; 038import org.jivesoftware.smackx.stanza_content_encryption.element.ToAffixElement; 039 040import org.jxmpp.jid.impl.JidCreate; 041import org.jxmpp.stringprep.XmppStringprepException; 042 043public class ContentElementProvider extends ExtensionElementProvider<ContentElement> { 044 045 @Override 046 public ContentElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) 047 throws XmlPullParserException, IOException, ParseException, SmackParsingException { 048 ContentElement.Builder builder = ContentElement.builder(); 049 050 while (true) { 051 XmlPullParser.Event tag = parser.next(); 052 if (tag == XmlPullParser.Event.START_ELEMENT) { 053 String name = parser.getName(); 054 switch (name) { 055 case ToAffixElement.ELEMENT: 056 parseToAffix(parser, builder); 057 break; 058 059 case FromAffixElement.ELEMENT: 060 parseFromAffix(parser, builder); 061 break; 062 063 case TimestampAffixElement.ELEMENT: 064 parseTimestampAffix(parser, builder); 065 break; 066 067 case RandomPaddingAffixElement.ELEMENT: 068 parseRPadAffix(parser, builder); 069 break; 070 071 case PayloadElement.ELEMENT: 072 parsePayload(parser, xmlEnvironment, builder); 073 break; 074 075 default: 076 parseCustomAffix(parser, xmlEnvironment, builder); 077 break; 078 } 079 } else if (tag == XmlPullParser.Event.END_ELEMENT) { 080 if (parser.getDepth() == initialDepth) { 081 break; 082 } 083 } 084 } 085 return builder.build(); 086 } 087 088 private static void parseCustomAffix(XmlPullParser parser, XmlEnvironment outerXmlEnvironment, ContentElement.Builder builder) 089 throws XmlPullParserException, IOException, SmackParsingException { 090 String name = parser.getName(); 091 String namespace = parser.getNamespace(); 092 093 AffixElement element = (AffixElement) PacketParserUtils.parseExtensionElement(name, namespace, parser, outerXmlEnvironment); 094 builder.addFurtherAffixElement(element); 095 } 096 097 private static void parsePayload(XmlPullParser parser, XmlEnvironment outerXmlEnvironment, ContentElement.Builder builder) 098 throws IOException, XmlPullParserException, SmackParsingException { 099 final int initialDepth = parser.getDepth(); 100 while (true) { 101 XmlPullParser.Event tag = parser.next(); 102 103 if (tag == XmlPullParser.Event.START_ELEMENT) { 104 String name = parser.getName(); 105 String namespace = parser.getNamespace(); 106 XmlElement element = PacketParserUtils.parseExtensionElement(name, namespace, parser, outerXmlEnvironment); 107 builder.addPayloadItem(element); 108 } 109 110 if (tag == XmlPullParser.Event.END_ELEMENT && parser.getDepth() == initialDepth) { 111 return; 112 } 113 } 114 } 115 116 private static void parseRPadAffix(XmlPullParser parser, ContentElement.Builder builder) 117 throws IOException, XmlPullParserException { 118 builder.setRandomPadding(parser.nextText()); 119 } 120 121 private static void parseTimestampAffix(XmlPullParser parser, ContentElement.Builder builder) 122 throws ParseException { 123 Date timestamp = ParserUtils.getDateFromXep82String( 124 parser.getAttributeValue("", TimestampAffixElement.ATTR_STAMP)); 125 builder.setTimestamp(timestamp); 126 } 127 128 private static void parseFromAffix(XmlPullParser parser, ContentElement.Builder builder) 129 throws XmppStringprepException { 130 String jidString = parser.getAttributeValue("", FromAffixElement.ATTR_JID); 131 builder.setFrom(JidCreate.from(jidString)); 132 } 133 134 private static void parseToAffix(XmlPullParser parser, ContentElement.Builder builder) 135 throws XmppStringprepException { 136 String jidString = parser.getAttributeValue("", ToAffixElement.ATTR_JID); 137 builder.addTo(JidCreate.from(jidString)); 138 } 139}