diff --git a/ecs.go b/ecs.go
index 060177b..e61af9d 100644
--- a/ecs.go
+++ b/ecs.go
@@ -56,28 +56,14 @@ func ecsHandler(w http.ResponseWriter, r *http.Request) {
}
fmt.Println(CDS)
fmt.Println("The request is valid! Responding...")
- fmt.Fprintf(w, `
-
-
-
- %s
- %s
- %s
- %s
- 0
- false
-
+ custom := fmt.Sprintf(`
2018
POINTS
0
%s
- %s
-
-
-`, CDS.Version, CDS.DeviceID, CDS.MessageID, timestamp, timestamp, timestamp)
+ %s`, timestamp, timestamp)
+ fmt.Fprint(w, formatSuccess("ecs", action, CDS.Version, CDS.DeviceID, CDS.MessageID, custom))
case "NotifiedETicketsSynced":
fmt.Println("NETS")
@@ -90,21 +76,7 @@ func ecsHandler(w http.ResponseWriter, r *http.Request) {
}
fmt.Println(NETS)
fmt.Println("The request is valid! Responding...")
- fmt.Fprintf(w, `
-
-
-
- %s
- %s
- %s
- %s
- 0
- false
-
-
-`, NETS.Version, NETS.DeviceID, NETS.MessageID, timestamp)
+ fmt.Fprint(w, formatSuccess("ecs", action, NETS.Version, NETS.DeviceID, NETS.MessageID, ""))
case "ListETickets":
fmt.Println("LET")
@@ -117,24 +89,10 @@ func ecsHandler(w http.ResponseWriter, r *http.Request) {
}
fmt.Println(LET)
fmt.Println("The request is valid! Responding...")
- fmt.Fprintf(w, `
-
-
-
- %s
- %s
- %s
- %s
- 0
- false
- 0
+ custom := fmt.Sprintf(`0
%s
- %s
-
-
-`, LET.Version, LET.DeviceID, LET.MessageID, timestamp, timestamp, timestamp)
+ %s`, timestamp, timestamp)
+ fmt.Fprint(w, formatSuccess("ecs", action, LET.Version, LET.DeviceID, LET.MessageID, custom))
case "PurchaseTitle":
fmt.Println("PT")
@@ -147,19 +105,7 @@ func ecsHandler(w http.ResponseWriter, r *http.Request) {
}
fmt.Println(PT)
fmt.Println("The request is valid! Responding...")
- fmt.Fprintf(w, `
-
-
-
- %s
- %s
- %s
- %s
- 0
- false
-
+ custom := fmt.Sprintf(`
2018
POINTS
@@ -172,13 +118,11 @@ func ecsHandler(w http.ResponseWriter, r *http.Request) {
00000000
00000000
00000000
- 00000000
-
-
-`, PT.Version, PT.DeviceID, PT.MessageID, timestamp, timestamp, timestamp)
+ 00000000`, timestamp, timestamp)
+ fmt.Fprint(w, formatSuccess("ecs", action, PT.Version, PT.DeviceID, PT.MessageID, custom))
default:
- fmt.Fprintf(w, "WiiSOAP can't handle this. Try again later or actually use a Wii instead of a computer.")
+ fmt.Fprint(w, "WiiSOAP can't handle this. Try again later or actually use a Wii instead of a computer.")
return
}
diff --git a/ias.go b/ias.go
index 9cd9cb9..6896f10 100644
--- a/ias.go
+++ b/ias.go
@@ -22,8 +22,6 @@ import (
"fmt"
"io/ioutil"
"net/http"
- "strconv"
- "time"
)
func iasHandler(w http.ResponseWriter, r *http.Request) {
@@ -31,10 +29,6 @@ func iasHandler(w http.ResponseWriter, r *http.Request) {
action := r.Header.Get("SOAPAction")
action = parseAction(action, "ias")
- // Get a sexy new timestamp to use.
- timestampNano := strconv.FormatInt(time.Now().UTC().Unix(), 10)
- timestamp := timestampNano + "000"
-
fmt.Println("[!] Incoming IAS request.")
body, err := ioutil.ReadAll(r.Body)
if err != nil {
@@ -57,23 +51,9 @@ func iasHandler(w http.ResponseWriter, r *http.Request) {
}
fmt.Println(CR)
fmt.Println("The request is valid! Responding...")
- fmt.Fprintf(w, `
-
-
-
- %s
- %s
- %s
- %s
- 0
- false
- %s
- R
-
-
-`, CR.Version, CR.DeviceID, CR.DeviceID, timestamp, CR.SerialNo)
+ custom := fmt.Sprintf(`%s
+ R`, CR.SerialNo)
+ fmt.Fprint(w, formatSuccess("ias", action, CR.Version, CR.DeviceID, CR.MessageID, custom))
case "GetRegistrationInfo":
fmt.Println("GRI.")
@@ -86,29 +66,15 @@ func iasHandler(w http.ResponseWriter, r *http.Request) {
}
fmt.Println(GRI)
fmt.Println("The request is valid! Responding...")
- fmt.Fprintf(w, `
-
-
-
- %s
- %s
- %s
- %s
- 0
- false
- %s
+ custom := fmt.Sprintf(`%s
00000000
false
%s
0000000000000000
R
- POINTS
-
-
-`, GRI.Version, GRI.DeviceID, GRI.MessageID, timestamp, GRI.AccountID, GRI.Country)
+ POINTS`, GRI.AccountID, GRI.Country)
+ fmt.Fprint(w, formatSuccess("ias", action, GRI.Version, GRI.DeviceID, GRI.MessageID, custom))
case "Register":
fmt.Println("REG.")
@@ -121,26 +87,12 @@ func iasHandler(w http.ResponseWriter, r *http.Request) {
}
fmt.Println(REG)
fmt.Println("The request is valid! Responding...")
- fmt.Fprintf(w, `
-
-
-
- %s
- %s
- %s
- %s
- 0
- false
- %s
+ custom := fmt.Sprintf(`%s
00000000
%s
- 00000000
-
-
-`, REG.Version, REG.DeviceID, REG.MessageID, timestamp, REG.AccountID, REG.Country)
+ 00000000`, REG.AccountID, REG.Country)
+ fmt.Fprint(w, formatSuccess("ias", action, REG.Version, REG.DeviceID, REG.MessageID, custom))
case "Unregister":
fmt.Println("UNR.")
@@ -153,22 +105,10 @@ func iasHandler(w http.ResponseWriter, r *http.Request) {
}
fmt.Println(UNR)
fmt.Println("The request is valid! Responding...")
- fmt.Fprintf(w, `
-
-
-
- %s
- %s
- %s
- %s
- 0
- false
-
-
-`, UNR.Version, UNR.DeviceID, UNR.MessageID, timestamp)
+ fmt.Fprint(w, formatSuccess("ias", action, UNR.Version, UNR.DeviceID, UNR.MessageID, ""))
default:
- fmt.Fprintf(w, "WiiSOAP can't handle this. Try again later or actually use a Wii instead of a computer.")
+ fmt.Fprint(w, "WiiSOAP can't handle this. Try again later or actually use a Wii instead of a computer.")
return
}
diff --git a/main.go b/main.go
index 2908ec3..3f20257 100644
--- a/main.go
+++ b/main.go
@@ -29,10 +29,25 @@ import (
)
const (
- // Header is a generic XML header suitable for use with the output of Marshal.
- // This is not automatically added to any output of this package,
- // it is provided as a convenience.
- Header = `` + "\n"
+ // Header is the base format of a SOAP response with string substitutions available.
+ // All XML constants must be treated as temporary until a proper XPath solution is investigated.
+ Header = `
+
+
+<%sResponse xmlns="%s">` + "\n"
+ // Template describes common fields across all requests, for easy replication.
+ Template = ` %s
+ %s
+ %s
+ %s
+ %d
+ false` + "\n"
+ // Footer is the base format of a closing envelope in SOAP.
+ Footer = ` %sResponse>
+
+`
)
// checkError makes error handling not as ugly and inefficient.
diff --git a/utils.go b/utils.go
index 3adb2ca..376c9c3 100644
--- a/utils.go
+++ b/utils.go
@@ -17,13 +17,19 @@
package main
-import "strings"
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+// namespaceForType returns the expected XML namespace format for a service.
func namespaceForType(service string) string {
return "urn:" + service + ".wsapi.broadon.com"
}
-// Expected contents are along the lines of "urn:ecs.wsapi.broadon.com/CheckDeviceStatus"
+// parseAction interprets contents along the lines of "urn:ecs.wsapi.broadon.com/CheckDeviceStatus".
func parseAction(original string, service string) string {
prefix := namespaceForType(service) + "/"
stripped := strings.Replace(original, prefix, "", 1)
@@ -35,3 +41,42 @@ func parseAction(original string, service string) string {
return stripped
}
}
+
+// formatHeader formats a response type and the proper service.
+func formatHeader(responseType string, service string) string {
+ return fmt.Sprintf(Header, responseType, namespaceForType(service))
+}
+
+// formatTemplate inserts common, cross-requests values into every request.
+func formatTemplate(version string, deviceId string, messageId string, errorCode int) string {
+ // Get a sexy new timestamp to use.
+ timestampNano := strconv.FormatInt(time.Now().UTC().Unix(), 10)
+ timestamp := timestampNano + "000"
+
+ return fmt.Sprintf(Template, version, deviceId, messageId, timestamp, errorCode)
+}
+
+// formatFooter formats the closing tags of any SOAP request per previous response type.
+func formatFooter(responseType string) string {
+ return fmt.Sprintf(Footer, responseType)
+}
+
+// formatForNamespace mangles together several variables throughout a SOAP request.
+func formatForNamespace(service string, responseType string, version string, deviceId string, messageId string, errorCode int, extraContents string) string {
+ return fmt.Sprintf("%s%s%s%s",
+ formatHeader(responseType, service),
+ formatTemplate(version, deviceId, messageId, errorCode),
+ "\t\t"+extraContents,
+ formatFooter(responseType),
+ )
+}
+
+// formatSuccess returns a standard SOAP response with a positive error code, and additional contents.
+func formatSuccess(service string, responseType string, version string, deviceId string, messageId string, extraContents string) string {
+ return formatForNamespace(service, responseType, version, deviceId, messageId, 0, extraContents)
+}
+
+// formatError returns a standard SOAP response with an error code.
+func formatError(service string, responseType string, version string, deviceId string, messageId string, errorCode int) string {
+ return formatForNamespace(service, responseType, version, deviceId, messageId, errorCode, "")
+}