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>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>org.sql2o</groupId>
<artifactId>sql2o</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>

View File

@@ -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;
}
}

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
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
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"
version="3.0">
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Runelite API</display-name>
<filter>
<filter-name>SparkFilter</filter-name>
@@ -40,4 +43,11 @@
<filter-name>SparkFilter</filter-name>
<url-pattern>/*</url-pattern>
</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>