001/* 002 * 003 * Copyright 2017 Paul Schaub, 2019 Florian Schmaus 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.jingle_filetransfer.provider; 018 019import java.io.IOException; 020import java.text.ParseException; 021import java.util.ArrayList; 022 023import org.jivesoftware.smack.packet.XmlEnvironment; 024import org.jivesoftware.smack.parsing.SmackParsingException; 025import org.jivesoftware.smack.util.ParserUtils; 026import org.jivesoftware.smack.xml.XmlPullParser; 027import org.jivesoftware.smack.xml.XmlPullParserException; 028 029import org.jivesoftware.smackx.hashes.element.HashElement; 030import org.jivesoftware.smackx.hashes.provider.HashElementProvider; 031import org.jivesoftware.smackx.jingle.element.JingleContentDescription; 032import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionChildElement; 033import org.jivesoftware.smackx.jingle.provider.JingleContentDescriptionProvider; 034import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransfer; 035import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChild; 036import org.jivesoftware.smackx.jingle_filetransfer.element.Range; 037 038import org.jxmpp.JxmppContext; 039import org.jxmpp.util.XmppDateTime; 040 041/** 042 * Provider for JingleContentDescriptionFileTransfer elements. 043 */ 044public class JingleFileTransferProvider 045 extends JingleContentDescriptionProvider<JingleFileTransfer> { 046 047 @Override 048 public JingleFileTransfer parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException, SmackParsingException, ParseException { 049 ArrayList<JingleContentDescriptionChildElement> payloads = new ArrayList<>(); 050 JingleFileTransferChild.Builder builder = JingleFileTransferChild.getBuilder(); 051 052 053 String elementName; 054 while (true) { 055 056 XmlPullParser.TagEvent tag = parser.nextTag(); 057 058 switch (tag) { 059 case START_ELEMENT: 060 elementName = parser.getName(); 061 switch (elementName) { 062 case JingleFileTransferChild.ELEM_DATE: 063 builder.setDate(XmppDateTime.parseXEP0082Date(parser.nextText())); 064 break; 065 066 case JingleFileTransferChild.ELEM_DESC: 067 builder.setDescription(parser.nextText()); 068 break; 069 070 case JingleFileTransferChild.ELEM_MEDIA_TYPE: 071 builder.setMediaType(parser.nextText()); 072 break; 073 074 case JingleFileTransferChild.ELEM_NAME: 075 builder.setName(parser.nextText()); 076 break; 077 078 case JingleFileTransferChild.ELEM_SIZE: 079 builder.setSize(Integer.parseInt(parser.nextText())); 080 break; 081 082 case Range.ELEMENT: 083 Range range = parseRangeElement(parser); 084 builder.setRange(range); 085 086 break; 087 088 case HashElement.ELEMENT: 089 HashElement hashElement = HashElementProvider.INSTANCE.parse(parser); 090 builder.setHash(hashElement); 091 break; 092 } 093 break; 094 case END_ELEMENT: 095 elementName = parser.getName(); 096 switch (elementName) { 097 case JingleFileTransferChild.ELEMENT: 098 payloads.add(builder.build()); 099 builder = JingleFileTransferChild.getBuilder(); 100 break; 101 102 case JingleContentDescription.ELEMENT: 103 return new JingleFileTransfer(payloads); 104 } 105 break; 106 } 107 } 108 } 109 110 public static Range parseRangeElement(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException { 111 final int initialDepth = parser.getDepth(); 112 final Integer offset = ParserUtils.getIntegerAttribute(parser, Range.ATTR_OFFSET); 113 final Integer length = ParserUtils.getIntegerAttribute(parser, Range.ATTR_LENGTH); 114 115 HashElement hashElement = null; 116 outerloop: while (true) { 117 String element; 118 XmlPullParser.Event event = parser.next(); 119 switch (event) { 120 case START_ELEMENT: 121 element = parser.getName(); 122 switch (element) { 123 case HashElement.ELEMENT: 124 hashElement = HashElementProvider.INSTANCE.parse(parser); 125 break; 126 } 127 break; 128 case END_ELEMENT: 129 element = parser.getName(); 130 if (element.equals(Range.ELEMENT) && parser.getDepth() == initialDepth) { 131 break outerloop; 132 } 133 break; 134 default: 135 // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. 136 break; 137 } 138 } 139 140 return new Range(offset, length, hashElement); 141 } 142 143}