http service: add xtea service for storing xtea keys

This commit is contained in:
Adam
2017-04-14 19:41:31 -04:00
parent 188b3b6f41
commit 93588bda35
8 changed files with 474 additions and 4 deletions

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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);
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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<XteaKey> keys = new ArrayList<>();
public int getRevision()
{
return revision;
}
public void setRevision(int revision)
{
this.revision = revision;
}
public List<XteaKey> getKeys()
{
return keys;
}
public void addKey(XteaKey key)
{
keys.add(key);
}
}

View File

@@ -47,6 +47,11 @@
<artifactId>spark-core</artifactId> <artifactId>spark-core</artifactId>
<version>2.5.5</version> <version>2.5.5</version>
</dependency> </dependency>
<dependency>
<groupId>org.sql2o</groupId>
<artifactId>sql2o</artifactId>
<version>1.5.4</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>

View File

@@ -24,9 +24,14 @@
*/ */
package net.runelite.http.service; 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.api.RuneliteAPI;
import net.runelite.http.service.hiscore.HiscoreService; import net.runelite.http.service.hiscore.HiscoreService;
import net.runelite.http.service.worlds.WorldsService; import net.runelite.http.service.worlds.WorldsService;
import net.runelite.http.service.xtea.XteaService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import spark.servlet.SparkApplication; import spark.servlet.SparkApplication;
@@ -36,21 +41,46 @@ public class Service implements SparkApplication
{ {
private static final Logger logger = LoggerFactory.getLogger(Service.class); private static final Logger logger = LoggerFactory.getLogger(Service.class);
private DataSource dataSource;
private final JsonTransformer transformer = new JsonTransformer(); private final JsonTransformer transformer = new JsonTransformer();
private HiscoreService hiscores = new HiscoreService(); private HiscoreService hiscores = new HiscoreService();
private WorldsService worlds = new WorldsService(); private WorldsService worlds = new WorldsService();
private XteaService xtea = new XteaService(this);
@Override @Override
public void init() public void init()
{ {
loadDatasource();
xtea.init();
get("/version", (request, response) -> RuneliteAPI.getVersion()); get("/version", (request, response) -> RuneliteAPI.getVersion());
get("/hiscore", (request, response) -> hiscores.lookup(request.queryParams("username")), transformer); get("/hiscore", (request, response) -> hiscores.lookup(request.queryParams("username")), transformer);
get("/worlds", (request, response) -> worlds.listWorlds(), 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)); 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() public HiscoreService getHiscores()
{ {
return hiscores; return hiscores;
@@ -61,4 +91,14 @@ public class Service implements SparkApplication
this.hiscores = hiscores; this.hiscores = hiscores;
} }
public DataSource getDataSource()
{
return dataSource;
}
public void setDataSource(DataSource dataSource)
{
this.dataSource = dataSource;
}
} }

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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;
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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<XteaKey> 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<XteaEntry> 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;
}
}

View File

@@ -22,10 +22,13 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--> -->
<web-app xmlns="http://java.sun.com/xml/ns/javaee" <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
version="3.0"> http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Runelite API</display-name>
<filter> <filter>
<filter-name>SparkFilter</filter-name> <filter-name>SparkFilter</filter-name>
@@ -40,4 +43,11 @@
<filter-name>SparkFilter</filter-name> <filter-name>SparkFilter</filter-name>
<url-pattern>/*</url-pattern> <url-pattern>/*</url-pattern>
</filter-mapping> </filter-mapping>
<resource-ref>
<description>Database Connection</description>
<res-ref-name>jdbc/runelite</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app> </web-app>