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