1 package com.android.hotspot2.osu; 2 3 import com.android.hotspot2.omadm.MOTree; 4 import com.android.hotspot2.omadm.OMAConstants; 5 import com.android.hotspot2.omadm.XMLNode; 6 7 import java.util.EnumMap; 8 import java.util.HashMap; 9 import java.util.Map; 10 11 public class SOAPBuilder { 12 private static final String EnvelopeTag = "s12:Envelope"; 13 private static final String BodyTag = "s12:Body"; 14 15 private static final Map<String, String> sEnvelopeAttributes = new HashMap<>(2); 16 private static final Map<RequestReason, String> sRequestReasons = 17 new EnumMap<>(RequestReason.class); 18 19 static { 20 sEnvelopeAttributes.put("xmlns:s12", "http://www.w3.org/2003/05/soap-envelope"); 21 sEnvelopeAttributes.put("xmlns:spp", 22 "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp"); 23 24 sRequestReasons.put(RequestReason.SubRegistration, "Subscription registration"); 25 sRequestReasons.put(RequestReason.SubProvisioning, "Subscription provisioning"); 26 sRequestReasons.put(RequestReason.SubRemediation, "Subscription remediation"); 27 sRequestReasons.put(RequestReason.InputComplete, "User input completed"); 28 sRequestReasons.put(RequestReason.NoClientCert, "No acceptable client certificate"); 29 sRequestReasons.put(RequestReason.CertEnrollmentComplete, 30 "Certificate enrollment completed"); 31 sRequestReasons.put(RequestReason.CertEnrollmentFailed, "Certificate enrollment failed"); 32 sRequestReasons.put(RequestReason.SubMetaDataUpdate, "Subscription metadata update"); 33 sRequestReasons.put(RequestReason.PolicyUpdate, "Policy update"); 34 sRequestReasons.put(RequestReason.NextCommand, "Retrieve next command"); 35 sRequestReasons.put(RequestReason.MOUpload, "MO upload"); 36 sRequestReasons.put(RequestReason.Unspecified, "Unspecified"); 37 } 38 39 public static String buildPostDevDataResponse(RequestReason reason, String sessionID, 40 String redirURI, MOTree... mos) { 41 XMLNode envelope = buildEnvelope(); 42 buildSppPostDevData(envelope.getChildren().get(0), sessionID, reason, redirURI, mos); 43 return envelope.toString(); 44 } 45 46 public static String buildUpdateResponse(String sessionID, OSUError error) { 47 XMLNode envelope = buildEnvelope(); 48 buildSppUpdateResponse(envelope.getChildren().get(0), sessionID, error); 49 return envelope.toString(); 50 } 51 52 private static XMLNode buildEnvelope() { 53 XMLNode envelope = new XMLNode(null, EnvelopeTag, sEnvelopeAttributes); 54 envelope.addChild(new XMLNode(envelope, BodyTag, (Map<String, String>) null)); 55 return envelope; 56 } 57 58 private static XMLNode buildSppPostDevData(XMLNode parent, String sessionID, 59 RequestReason reason, String redirURI, 60 MOTree... mos) { 61 Map<String, String> pddAttributes = new HashMap<>(); 62 pddAttributes.put(OMAConstants.TAG_Version, OMAConstants.MOVersion); 63 pddAttributes.put("requestReason", sRequestReasons.get(reason)); 64 if (sessionID != null) { 65 pddAttributes.put(OMAConstants.TAG_SessionID, sessionID); 66 } 67 if (redirURI != null) { 68 pddAttributes.put("redirectURI", redirURI); 69 } 70 71 XMLNode pddNode = new XMLNode(parent, OMAConstants.TAG_PostDevData, pddAttributes); 72 73 XMLNode vNode = new XMLNode(pddNode, OMAConstants.TAG_SupportedVersions, 74 (HashMap<String, String>) null); 75 vNode.setText("1.0"); 76 pddNode.addChild(vNode); 77 78 XMLNode moNode = new XMLNode(pddNode, OMAConstants.TAG_SupportedMOs, 79 (HashMap<String, String>) null); 80 StringBuilder sb = new StringBuilder(); 81 boolean first = true; 82 for (String urn : OMAConstants.SupportedMO_URNs) { 83 if (first) { 84 first = false; 85 } else { 86 sb.append(' '); 87 } 88 sb.append(urn); 89 } 90 moNode.setText(sb.toString()); 91 pddNode.addChild(moNode); 92 93 if (mos != null) { 94 for (MOTree moTree : mos) { 95 Map<String, String> map = null; 96 if (moTree.getUrn() != null) { 97 map = new HashMap<>(1); 98 map.put(OMAConstants.SppMOAttribute, moTree.getUrn()); 99 } 100 moNode = new XMLNode(pddNode, OMAConstants.TAG_MOContainer, map); 101 moNode.setText(moTree.toXml()); 102 pddNode.addChild(moNode); 103 } 104 } 105 106 parent.addChild(pddNode); 107 return pddNode; 108 } 109 110 private static XMLNode buildSppUpdateResponse(XMLNode parent, String sessionID, 111 OSUError error) { 112 Map<String, String> urAttributes = new HashMap<>(); 113 urAttributes.put(OMAConstants.TAG_Version, OMAConstants.MOVersion); 114 if (sessionID != null) { 115 urAttributes.put(OMAConstants.TAG_SessionID, sessionID); 116 } 117 if (error == null) { 118 urAttributes.put(OMAConstants.TAG_Status, OMAConstants.mapStatus(OSUStatus.OK)); 119 } else { 120 urAttributes.put(OMAConstants.TAG_Status, OMAConstants.mapStatus(OSUStatus.Error)); 121 } 122 123 XMLNode urNode = new XMLNode(parent, OMAConstants.TAG_UpdateResponse, urAttributes); 124 125 if (error != null) { 126 Map<String, String> errorAttributes = new HashMap<>(); 127 errorAttributes.put("errorCode", OMAConstants.mapError(error)); 128 XMLNode errorNode = new XMLNode(urNode, OMAConstants.TAG_Error, errorAttributes); 129 urNode.addChild(errorNode); 130 } 131 132 parent.addChild(urNode); 133 return urNode; 134 } 135 136 /* 137 <xsd:element name="sppUpdateResponse"> 138 <xsd:annotation> 139 <xsd:documentation>SOAP method used by SPP client to confirm installation of MO addition or update.</xsd:documentation> 140 </xsd:annotation> 141 <xsd:complexType> 142 <xsd:sequence> 143 <xsd:element ref="sppError" minOccurs="0"/> 144 <xsd:any namespace="##other" maxOccurs="unbounded" minOccurs="0"/> 145 </xsd:sequence> 146 <xsd:attribute ref="sppVersion" use="required"/> 147 <xsd:attribute ref="sppStatus" use="required"/> 148 <xsd:attribute ref="sessionID" use="required"/> 149 <xsd:anyAttribute namespace="##other"/> 150 </xsd:complexType> 151 </xsd:element> 152 153 <xsd:element name="sppError"> 154 <xsd:annotation> 155 <xsd:documentation>Error response.</xsd:documentation> 156 </xsd:annotation> 157 <xsd:complexType> 158 <xsd:attribute name="errorCode" use="required"> 159 <xsd:simpleType> 160 <xsd:restriction base="xsd:string"> 161 <xsd:enumeration value="SPP version not supported"/> 162 <xsd:enumeration value="One or more mandatory MOs not supported"/> 163 <xsd:enumeration value="Credentials cannot be provisioned at this time"/> 164 <xsd:enumeration value="Remediation cannot be completed at this time"/> 165 <xsd:enumeration value="Provisioning cannot be completed at this time"/> 166 <xsd:enumeration value="Continue to use existing certificate"/> 167 <xsd:enumeration value="Cookie invalid"/> 168 <xsd:enumeration value="No corresponding web-browser-connection Session ID"/> 169 <xsd:enumeration value="Permission denied"/> 170 <xsd:enumeration value="Command failed"/> 171 <xsd:enumeration value="MO addition or update failed"/> 172 <xsd:enumeration value="Device full"/> 173 <xsd:enumeration value="Bad management tree URI"/> 174 <xsd:enumeration value="Requested entity too large"/> 175 <xsd:enumeration value="Command not allowed"/> 176 <xsd:enumeration value="Command not executed due to user"/> 177 <xsd:enumeration value="Not found"/> 178 <xsd:enumeration value="Other"/> 179 </xsd:restriction> 180 </xsd:simpleType> 181 </xsd:attribute> 182 <xsd:anyAttribute namespace="##other"/> 183 </xsd:complexType> 184 </xsd:element> 185 186 187 */ 188 } 189