1package com.android.hotspot2.osu;
2
3import com.android.hotspot2.omadm.MOTree;
4import com.android.hotspot2.omadm.OMAConstants;
5import com.android.hotspot2.omadm.XMLNode;
6
7import java.util.EnumMap;
8import java.util.HashMap;
9import java.util.Map;
10
11public 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