From 93588bda35561286440fda0d3d4b81248d6c8964 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 14 Apr 2017 19:41:31 -0400 Subject: [PATCH] http service: add xtea service for storing xtea keys --- .../runelite/http/api/xtea/XteaClient.java | 78 ++++++++++ .../net/runelite/http/api/xtea/XteaKey.java | 51 +++++++ .../runelite/http/api/xtea/XteaRequest.java | 54 +++++++ http-service/pom.xml | 5 + .../net/runelite/http/service/Service.java | 40 ++++++ .../runelite/http/service/xtea/XteaEntry.java | 96 +++++++++++++ .../http/service/xtea/XteaService.java | 136 ++++++++++++++++++ http-service/src/main/webapp/WEB-INF/web.xml | 18 ++- 8 files changed, 474 insertions(+), 4 deletions(-) create mode 100644 http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java create mode 100644 http-api/src/main/java/net/runelite/http/api/xtea/XteaKey.java create mode 100644 http-api/src/main/java/net/runelite/http/api/xtea/XteaRequest.java create mode 100644 http-service/src/main/java/net/runelite/http/service/xtea/XteaEntry.java create mode 100644 http-service/src/main/java/net/runelite/http/service/xtea/XteaService.java diff --git a/http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java b/http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java new file mode 100644 index 0000000000..baa2147159 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/xtea/XteaClient.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.api.xtea; + +import com.google.gson.Gson; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import net.runelite.http.api.RuneliteAPI; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class XteaClient +{ + private static final Logger logger = LoggerFactory.getLogger(XteaClient.class); + + private static final String URL = RuneliteAPI.getApiBase() + "/xtea"; + + private final Gson gson = new Gson(); + + public void submut(int revision, int region, int[] keys) throws URISyntaxException, UnsupportedEncodingException, IOException + { + URIBuilder builder = new URIBuilder(URL); + + URI uri = builder.build(); + + logger.debug("Built URI: {}", uri); + + XteaRequest xteaRequest = new XteaRequest(); + xteaRequest.setRevision(revision); + + XteaKey xteaKey = new XteaKey(); + xteaKey.setRegion(region); + xteaKey.setKeys(keys); + + xteaRequest.addKey(xteaKey); + + String json = gson.toJson(xteaRequest); + + HttpPost request = new HttpPost(uri); + request.setEntity(new StringEntity(json)); + + try (CloseableHttpClient client = HttpClients.createDefault(); + CloseableHttpResponse response = client.execute(request)) + { + logger.debug("Submitted XTEA key for region {}", region); + } + } +} diff --git a/http-api/src/main/java/net/runelite/http/api/xtea/XteaKey.java b/http-api/src/main/java/net/runelite/http/api/xtea/XteaKey.java new file mode 100644 index 0000000000..c108f223cb --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/xtea/XteaKey.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.api.xtea; + +public class XteaKey +{ + private int region; + private int keys[]; + + public int getRegion() + { + return region; + } + + public void setRegion(int region) + { + this.region = region; + } + + public int[] getKeys() + { + return keys; + } + + public void setKeys(int[] keys) + { + this.keys = keys; + } +} diff --git a/http-api/src/main/java/net/runelite/http/api/xtea/XteaRequest.java b/http-api/src/main/java/net/runelite/http/api/xtea/XteaRequest.java new file mode 100644 index 0000000000..f84c85b83b --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/xtea/XteaRequest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.api.xtea; + +import java.util.ArrayList; +import java.util.List; + +public class XteaRequest +{ + private int revision; + private List keys = new ArrayList<>(); + + public int getRevision() + { + return revision; + } + + public void setRevision(int revision) + { + this.revision = revision; + } + + public List getKeys() + { + return keys; + } + + public void addKey(XteaKey key) + { + keys.add(key); + } +} diff --git a/http-service/pom.xml b/http-service/pom.xml index 65dcafd8a0..9f2817f96f 100644 --- a/http-service/pom.xml +++ b/http-service/pom.xml @@ -47,6 +47,11 @@ spark-core 2.5.5 + + org.sql2o + sql2o + 1.5.4 + org.apache.commons diff --git a/http-service/src/main/java/net/runelite/http/service/Service.java b/http-service/src/main/java/net/runelite/http/service/Service.java index 1dab4e4254..b120f91783 100644 --- a/http-service/src/main/java/net/runelite/http/service/Service.java +++ b/http-service/src/main/java/net/runelite/http/service/Service.java @@ -24,9 +24,14 @@ */ package net.runelite.http.service; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; import net.runelite.http.api.RuneliteAPI; import net.runelite.http.service.hiscore.HiscoreService; import net.runelite.http.service.worlds.WorldsService; +import net.runelite.http.service.xtea.XteaService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import spark.servlet.SparkApplication; @@ -36,21 +41,46 @@ public class Service implements SparkApplication { private static final Logger logger = LoggerFactory.getLogger(Service.class); + private DataSource dataSource; + private final JsonTransformer transformer = new JsonTransformer(); private HiscoreService hiscores = new HiscoreService(); private WorldsService worlds = new WorldsService(); + private XteaService xtea = new XteaService(this); @Override public void init() { + loadDatasource(); + + xtea.init(); + get("/version", (request, response) -> RuneliteAPI.getVersion()); get("/hiscore", (request, response) -> hiscores.lookup(request.queryParams("username")), transformer); get("/worlds", (request, response) -> worlds.listWorlds(), transformer); + post("/xtea", xtea::submit); + get("/xtea/:rev", xtea::get, transformer); exception(Exception.class, (exception, request, response) -> logger.warn(null, exception)); } + private void loadDatasource() + { + try + { + // It is difficult to inject things into Spark + Context initCtx = new InitialContext(); + Context envCtx = (Context) initCtx.lookup("java:comp/env"); + + dataSource = (DataSource) envCtx.lookup("jdbc/runelite"); + } + catch (NamingException ex) + { + throw new RuntimeException(ex); + } + } + public HiscoreService getHiscores() { return hiscores; @@ -61,4 +91,14 @@ public class Service implements SparkApplication this.hiscores = hiscores; } + public DataSource getDataSource() + { + return dataSource; + } + + public void setDataSource(DataSource dataSource) + { + this.dataSource = dataSource; + } + } diff --git a/http-service/src/main/java/net/runelite/http/service/xtea/XteaEntry.java b/http-service/src/main/java/net/runelite/http/service/xtea/XteaEntry.java new file mode 100644 index 0000000000..a6cff54912 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/xtea/XteaEntry.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.xtea; + +public class XteaEntry +{ + private int rev; + private int region; + private int key1; + private int key2; + private int key3; + private int key4; + + public int getRev() + { + return rev; + } + + public void setRev(int rev) + { + this.rev = rev; + } + + public int getRegion() + { + return region; + } + + public void setRegion(int region) + { + this.region = region; + } + + public int getKey1() + { + return key1; + } + + public void setKey1(int key1) + { + this.key1 = key1; + } + + public int getKey2() + { + return key2; + } + + public void setKey2(int key2) + { + this.key2 = key2; + } + + public int getKey3() + { + return key3; + } + + public void setKey3(int key3) + { + this.key3 = key3; + } + + public int getKey4() + { + return key4; + } + + public void setKey4(int key4) + { + this.key4 = key4; + } + +} diff --git a/http-service/src/main/java/net/runelite/http/service/xtea/XteaService.java b/http-service/src/main/java/net/runelite/http/service/xtea/XteaService.java new file mode 100644 index 0000000000..4fa31cd453 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/xtea/XteaService.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.xtea; + +import com.google.gson.Gson; +import java.util.List; +import java.util.stream.Collectors; +import net.runelite.http.api.xtea.XteaKey; +import net.runelite.http.api.xtea.XteaRequest; +import net.runelite.http.service.Service; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sql2o.Connection; +import org.sql2o.Query; +import org.sql2o.Sql2o; +import spark.Request; +import spark.Response; + +public class XteaService +{ + private static final Logger logger = LoggerFactory.getLogger(XteaService.class); + + private static final String CREATE_SQL = "CREATE TABLE IF NOT EXISTS `xtea` (\n" + + " `rev` int(11) NOT NULL,\n" + + " `region` int(11) NOT NULL,\n" + + " `key1` int(11) NOT NULL,\n" + + " `key2` int(11) NOT NULL,\n" + + " `key3` int(11) NOT NULL,\n" + + " `key4` int(11) NOT NULL,\n" + + " PRIMARY KEY (`rev`,`region`,`key1`,`key2`,`key3`,`key4`)\n" + + ") ENGINE=InnoDB;"; + + private final Service service; + private final Gson gson = new Gson(); + + public XteaService(Service service) + { + this.service = service; + } + + public void init() + { + Sql2o sql2o = new Sql2o(service.getDataSource()); + + try (Connection con = sql2o.beginTransaction()) + { + con.createQuery(CREATE_SQL) + .executeUpdate(); + } + } + + public Object submit(Request request, Response response) + { + XteaRequest xteaRequest = gson.fromJson(request.body(), XteaRequest.class); + + Sql2o sql2o = new Sql2o(service.getDataSource()); + + try (Connection con = sql2o.beginTransaction()) + { + Query query = con.createQuery("insert ignore into xtea (rev, region, key1, key2, key3, key4) values (:rev, :region, :key1, :key2, :key3, :key4)"); + + for (XteaKey key : xteaRequest.getKeys()) + { + query.addParameter("rev", xteaRequest.getRevision()) + .addParameter("region", key.getRegion()) + .addParameter("key1", key.getKeys()[0]) + .addParameter("key2", key.getKeys()[1]) + .addParameter("key3", key.getKeys()[2]) + .addParameter("key4", key.getKeys()[3]) + .addToBatch(); + } + + query.executeBatch(); + con.commit(); + } + + return ""; + } + + public List get(Request request, Response response) + { + String revStr = request.params("rev"); + int revision = Integer.parseInt(revStr); + + Sql2o sql2o = new Sql2o(service.getDataSource()); + + try (Connection con = sql2o.open()) + { + List entries = con.createQuery("select * from xtea where rev = :rev") + .addParameter("rev", revision) + .executeAndFetch(XteaEntry.class); + + response.type("application/json"); + + return entries.stream() + .map(XteaService::entryToKey) + .collect(Collectors.toList()); + } + } + + private static XteaKey entryToKey(XteaEntry xe) + { + XteaKey xteaKey = new XteaKey(); + xteaKey.setRegion(xe.getRegion()); + xteaKey.setKeys(new int[] + { + xe.getKey1(), + xe.getKey2(), + xe.getKey3(), + xe.getKey4() + }); + return xteaKey; + } +} diff --git a/http-service/src/main/webapp/WEB-INF/web.xml b/http-service/src/main/webapp/WEB-INF/web.xml index 7ebcddad92..259f969420 100644 --- a/http-service/src/main/webapp/WEB-INF/web.xml +++ b/http-service/src/main/webapp/WEB-INF/web.xml @@ -22,10 +22,13 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + + + Runelite API SparkFilter @@ -40,4 +43,11 @@ SparkFilter /* + + + Database Connection + jdbc/runelite + javax.sql.DataSource + Container + \ No newline at end of file