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