001/* 002 * 003 * Copyright © 2017 Grigory Fedorov, 2017-2024 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.httpfileupload.provider; 018 019import java.io.IOException; 020import java.net.URI; 021import java.net.URL; 022import java.util.HashMap; 023import java.util.Map; 024 025import org.jivesoftware.smack.packet.IqData; 026import org.jivesoftware.smack.packet.XmlEnvironment; 027import org.jivesoftware.smack.parsing.SmackParsingException.SmackUriSyntaxParsingException; 028import org.jivesoftware.smack.provider.IqProvider; 029import org.jivesoftware.smack.util.ParserUtils; 030import org.jivesoftware.smack.xml.XmlPullParser; 031import org.jivesoftware.smack.xml.XmlPullParserException; 032 033import org.jivesoftware.smackx.httpfileupload.HttpFileUploadManager; 034import org.jivesoftware.smackx.httpfileupload.UploadService; 035import org.jivesoftware.smackx.httpfileupload.element.Slot; 036import org.jivesoftware.smackx.httpfileupload.element.Slot_V0_2; 037 038import org.jxmpp.JxmppContext; 039 040/** 041 * Provider for Slot. 042 * 043 * @author Grigory Fedorov 044 * @see <a href="http://xmpp.org/extensions/xep-0363.html">XEP-0363: HTTP File Upload</a> 045 */ 046public class SlotProvider extends IqProvider<Slot> { 047 048 @Override 049 public Slot parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException, SmackUriSyntaxParsingException { 050 final String namespace = parser.getNamespace(); 051 052 final UploadService.Version version = HttpFileUploadManager.namespaceToVersion(namespace); 053 assert version != null; 054 055 URL putUrl = null; 056 URL getUrl = null; 057 PutElement_V0_4_Content putElementV04Content = null; 058 059 outerloop: while (true) { 060 XmlPullParser.Event event = parser.next(); 061 062 switch (event) { 063 case START_ELEMENT: 064 String name = parser.getName(); 065 switch (name) { 066 case "put": { 067 switch (version) { 068 case v0_2: 069 String putUrlString = parser.nextText(); 070 putUrl = toUrl(putUrlString); 071 break; 072 case v0_3: 073 putElementV04Content = parsePutElement_V0_4(parser); 074 break; 075 default: 076 throw new AssertionError(); 077 } 078 break; 079 } 080 case "get": 081 String getUrlString; 082 switch (version) { 083 case v0_2: 084 getUrlString = parser.nextText(); 085 break; 086 case v0_3: 087 getUrlString = parser.getAttributeValue(null, "url"); 088 break; 089 default: 090 throw new AssertionError(); 091 } 092 getUrl = toUrl(getUrlString); 093 break; 094 } 095 break; 096 case END_ELEMENT: 097 if (parser.getDepth() == initialDepth) { 098 break outerloop; 099 } 100 break; 101 default: 102 // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. 103 break; 104 } 105 } 106 107 switch (version) { 108 case v0_3: 109 return new Slot(putElementV04Content.putUrl, getUrl, putElementV04Content.headers); 110 case v0_2: 111 return new Slot_V0_2(putUrl, getUrl); 112 default: 113 throw new AssertionError(); 114 } 115 } 116 117 public static PutElement_V0_4_Content parsePutElement_V0_4(XmlPullParser parser) throws XmlPullParserException, IOException { 118 final int initialDepth = parser.getDepth(); 119 120 String putUrlString = parser.getAttributeValue(null, "url"); 121 URL putUrl = URI.create(putUrlString).toURL(); 122 123 Map<String, String> headers = null; 124 outerloop: while (true) { 125 XmlPullParser.Event next = parser.next(); 126 switch (next) { 127 case START_ELEMENT: 128 String name = parser.getName(); 129 switch (name) { 130 case "header": 131 String headerName = ParserUtils.getRequiredAttribute(parser, "name"); 132 String headerValue = ParserUtils.getRequiredNextText(parser); 133 if (headers == null) { 134 headers = new HashMap<>(); 135 } 136 headers.put(headerName, headerValue); 137 break; 138 default: 139 break; 140 } 141 break; 142 case END_ELEMENT: 143 if (parser.getDepth() == initialDepth) { 144 break outerloop; 145 } 146 break; 147 default: 148 // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. 149 break; 150 } 151 } 152 153 return new PutElement_V0_4_Content(putUrl, headers); 154 } 155 156 public static final class PutElement_V0_4_Content { 157 private final URL putUrl; 158 private final Map<String, String> headers; 159 160 private PutElement_V0_4_Content(URL putUrl, Map<String, String> headers) { 161 this.putUrl = putUrl; 162 this.headers = headers; 163 } 164 165 public URL getPutUrl() { 166 return putUrl; 167 } 168 169 public Map<String, String> getHeaders() { 170 return headers; 171 } 172 } 173}