Cleaned sources
This commit is contained in:
@ -1,21 +1,24 @@
|
|||||||
package org.skinner;
|
package org.skinner;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.util.Base64;
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.skinner.json.*;
|
import org.skinner.json.JSON;
|
||||||
|
import org.skinner.json.JSONArray;
|
||||||
|
import org.skinner.json.JSONObject;
|
||||||
|
|
||||||
import com.sun.net.httpserver.*;
|
import com.sun.net.httpserver.Headers;
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
|
||||||
public class RestAPI extends SafeHttpHandler {
|
public class RestAPI extends SafeHttpHandler {
|
||||||
|
|
||||||
RestAPI(String root) {
|
RestAPI(String root) {
|
||||||
super(root);
|
super(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void handle(HttpExchange exchange, URI uri) throws Exception {
|
protected void handle(HttpExchange exchange, URI uri) throws Exception {
|
||||||
String path = uri.getPath();
|
String path = uri.getPath();
|
||||||
switch (exchange.getRequestMethod().toUpperCase())
|
switch (exchange.getRequestMethod().toUpperCase())
|
||||||
@ -26,11 +29,11 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
case "/skins":
|
case "/skins":
|
||||||
getSkins(exchange);
|
getSkins(exchange);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case "/profiles":
|
case "/profiles":
|
||||||
profiles(exchange);
|
profiles(exchange);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Template-ish routes
|
// Template-ish routes
|
||||||
default:
|
default:
|
||||||
if (path.startsWith("/skin/")) {
|
if (path.startsWith("/skin/")) {
|
||||||
@ -40,14 +43,14 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "POST":
|
case "POST":
|
||||||
switch (path)
|
switch (path)
|
||||||
{
|
{
|
||||||
case "/skin":
|
case "/skin":
|
||||||
addSkin(exchange);
|
addSkin(exchange);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case "/profile":
|
case "/profile":
|
||||||
register(exchange);
|
register(exchange);
|
||||||
return;
|
return;
|
||||||
@ -57,14 +60,14 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "PATCH":
|
case "PATCH":
|
||||||
switch (path)
|
switch (path)
|
||||||
{
|
{
|
||||||
case "/profile":
|
case "/profile":
|
||||||
updateProfile(exchange, uri);
|
updateProfile(exchange, uri);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (path.startsWith("/skin/")) {
|
if (path.startsWith("/skin/")) {
|
||||||
renameSkin(exchange, uri);
|
renameSkin(exchange, uri);
|
||||||
@ -72,7 +75,7 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
switch (path)
|
switch (path)
|
||||||
{
|
{
|
||||||
@ -86,26 +89,26 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
}
|
}
|
||||||
Headers headers = exchange.getResponseHeaders();
|
Headers headers = exchange.getResponseHeaders();
|
||||||
headers.add("Content-Type", "text/plain");
|
headers.add("Content-Type", "text/plain");
|
||||||
|
|
||||||
byte[] response = "Missing API endpoint".getBytes();
|
byte[] response = "Missing API endpoint".getBytes();
|
||||||
exchange.sendResponseHeaders(404, response.length);
|
exchange.sendResponseHeaders(404, response.length);
|
||||||
exchange.getResponseBody().write(response);
|
exchange.getResponseBody().write(response);
|
||||||
exchange.close();
|
exchange.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void getSkin(HttpExchange exchange, URI uri) throws Exception {
|
protected void getSkin(HttpExchange exchange, URI uri) throws Exception {
|
||||||
String[] pathParts = uri.getPath().split("/");
|
String[] pathParts = uri.getPath().split("/");
|
||||||
String hash = pathParts[pathParts.length-1].split("\\.")[0];
|
String hash = pathParts[pathParts.length-1].split("\\.")[0];
|
||||||
|
|
||||||
Skin skin = Database.getSkin(hash);
|
Skin skin = Database.getSkin(hash);
|
||||||
if (skin == null) {
|
if (skin == null) {
|
||||||
notfound(exchange, "Skin not found");
|
notfound(exchange, "Skin not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query query = new Query(uri.getQuery());
|
Query query = new Query(uri.getQuery());
|
||||||
|
|
||||||
byte[] response = query.getOrDefault("legacy", "false").toLowerCase().equals("true") ?
|
byte[] response = query.getOrDefault("legacy", "false").toLowerCase().equals("true") ?
|
||||||
skin.getPngOld() :
|
skin.getPngOld() :
|
||||||
skin.getPng();
|
skin.getPng();
|
||||||
@ -114,10 +117,10 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
exchange.getResponseBody().write(response);
|
exchange.getResponseBody().write(response);
|
||||||
exchange.close();
|
exchange.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void getSkins(HttpExchange exchange) throws Exception {
|
protected void getSkins(HttpExchange exchange) throws Exception {
|
||||||
HashLabelPair[] pairs = Database.getSkinHashesAndLabels();
|
HashLabelPair[] pairs = Database.getSkinHashesAndLabels();
|
||||||
|
|
||||||
JSONArray array = new JSONArray();
|
JSONArray array = new JSONArray();
|
||||||
for (HashLabelPair pair : pairs) {
|
for (HashLabelPair pair : pairs) {
|
||||||
JSONObject object = new JSONObject();
|
JSONObject object = new JSONObject();
|
||||||
@ -127,66 +130,6 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
object.put("png_old", JSON.from(getRoot() + "skin/"+pair.getHash()+".png?legacy=true"));
|
object.put("png_old", JSON.from(getRoot() + "skin/"+pair.getHash()+".png?legacy=true"));
|
||||||
array.add(object);
|
array.add(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] response = array.toString().getBytes();
|
|
||||||
exchange.getResponseHeaders().add("Content-Type", "application/json");
|
|
||||||
exchange.sendResponseHeaders(200, response.length);
|
|
||||||
exchange.getResponseBody().write(response);
|
|
||||||
exchange.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void getSkinsFull(HttpExchange exchange) throws Exception {
|
|
||||||
Skin[] skins = Database.getSkins();
|
|
||||||
|
|
||||||
JSONArray array = new JSONArray();
|
|
||||||
for (Skin skin : skins)
|
|
||||||
array.add(skinToResponseJSON(skin));
|
|
||||||
|
|
||||||
byte[] response = array.toString().getBytes();
|
|
||||||
exchange.getResponseHeaders().add("Content-Type", "application/json");
|
|
||||||
exchange.sendResponseHeaders(200, response.length);
|
|
||||||
exchange.getResponseBody().write(response);
|
|
||||||
exchange.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addSkin(HttpExchange exchange) throws Exception {
|
|
||||||
MultipartForm form = new MultipartForm(exchange);
|
|
||||||
|
|
||||||
if (!form.contains("skin")) {
|
|
||||||
text(exchange, 400, "Expected \"skin\" field not provided");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStream is = new ByteArrayInputStream(form.get("skin"));
|
|
||||||
Skin skin = Skin.loadFromImage(is, form.getString("label"));
|
|
||||||
Database.addSkin(skin);
|
|
||||||
ok(exchange);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void renameSkin(HttpExchange exchange, URI uri) throws Exception {
|
|
||||||
String[] pathParts = uri.getPath().split("/");
|
|
||||||
String hash = pathParts[pathParts.length-1];
|
|
||||||
|
|
||||||
String label = new String(exchange.getRequestBody().readAllBytes());
|
|
||||||
|
|
||||||
Database.updateSkinLabel(hash, label);
|
|
||||||
ok(exchange);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void deleteSkin(HttpExchange exchange, URI uri) throws Exception {
|
|
||||||
String[] pathParts = uri.getPath().split("/");
|
|
||||||
String hash = pathParts[pathParts.length-1];
|
|
||||||
|
|
||||||
Database.deleteSkin(hash);
|
|
||||||
ok(exchange);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void profiles(HttpExchange exchange) throws Exception {
|
|
||||||
Profile[] profiles = Database.getProfiles();
|
|
||||||
|
|
||||||
JSONArray array = new JSONArray();
|
|
||||||
for (Profile profile : profiles)
|
|
||||||
array.add(profileToResponseJSON(profile));
|
|
||||||
|
|
||||||
byte[] response = array.toString().getBytes();
|
byte[] response = array.toString().getBytes();
|
||||||
exchange.getResponseHeaders().add("Content-Type", "application/json");
|
exchange.getResponseHeaders().add("Content-Type", "application/json");
|
||||||
@ -194,10 +137,72 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
exchange.getResponseBody().write(response);
|
exchange.getResponseBody().write(response);
|
||||||
exchange.close();
|
exchange.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void getSkinsFull(HttpExchange exchange) throws Exception {
|
||||||
|
Skin[] skins = Database.getSkins();
|
||||||
|
|
||||||
|
JSONArray array = new JSONArray();
|
||||||
|
for (Skin skin : skins) {
|
||||||
|
array.add(skinToResponseJSON(skin));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] response = array.toString().getBytes();
|
||||||
|
exchange.getResponseHeaders().add("Content-Type", "application/json");
|
||||||
|
exchange.sendResponseHeaders(200, response.length);
|
||||||
|
exchange.getResponseBody().write(response);
|
||||||
|
exchange.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addSkin(HttpExchange exchange) throws Exception {
|
||||||
|
MultipartForm form = new MultipartForm(exchange);
|
||||||
|
|
||||||
|
if (!form.contains("skin")) {
|
||||||
|
text(exchange, 400, "Expected \"skin\" field not provided");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream is = new ByteArrayInputStream(form.get("skin"));
|
||||||
|
Skin skin = Skin.loadFromImage(is, form.getString("label"));
|
||||||
|
Database.addSkin(skin);
|
||||||
|
ok(exchange);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renameSkin(HttpExchange exchange, URI uri) throws Exception {
|
||||||
|
String[] pathParts = uri.getPath().split("/");
|
||||||
|
String hash = pathParts[pathParts.length-1];
|
||||||
|
|
||||||
|
String label = new String(exchange.getRequestBody().readAllBytes());
|
||||||
|
|
||||||
|
Database.updateSkinLabel(hash, label);
|
||||||
|
ok(exchange);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteSkin(HttpExchange exchange, URI uri) throws Exception {
|
||||||
|
String[] pathParts = uri.getPath().split("/");
|
||||||
|
String hash = pathParts[pathParts.length-1];
|
||||||
|
|
||||||
|
Database.deleteSkin(hash);
|
||||||
|
ok(exchange);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void profiles(HttpExchange exchange) throws Exception {
|
||||||
|
Profile[] profiles = Database.getProfiles();
|
||||||
|
|
||||||
|
JSONArray array = new JSONArray();
|
||||||
|
for (Profile profile : profiles) {
|
||||||
|
array.add(profileToResponseJSON(profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] response = array.toString().getBytes();
|
||||||
|
exchange.getResponseHeaders().add("Content-Type", "application/json");
|
||||||
|
exchange.sendResponseHeaders(200, response.length);
|
||||||
|
exchange.getResponseBody().write(response);
|
||||||
|
exchange.close();
|
||||||
|
}
|
||||||
|
|
||||||
protected void register(HttpExchange exchange) throws Exception {
|
protected void register(HttpExchange exchange) throws Exception {
|
||||||
MultipartForm form = new MultipartForm(exchange);
|
MultipartForm form = new MultipartForm(exchange);
|
||||||
|
|
||||||
if (!form.contains("username")) {
|
if (!form.contains("username")) {
|
||||||
text(exchange, 400, "Expected \"username\" field not provided");
|
text(exchange, 400, "Expected \"username\" field not provided");
|
||||||
return;
|
return;
|
||||||
@ -206,14 +211,14 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
text(exchange, 400, "Expected \"password\" field not provided");
|
text(exchange, 400, "Expected \"password\" field not provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String username = form.getString("username");
|
String username = form.getString("username");
|
||||||
String password = form.getString("password");
|
String password = form.getString("password");
|
||||||
|
|
||||||
String salt = Profile.generateSalt();
|
String salt = Profile.generateSalt();
|
||||||
String hash = Profile.generateHash(password, salt);
|
String hash = Profile.generateHash(password, salt);
|
||||||
String uuid = Profile.generateUUID();
|
String uuid = Profile.generateUUID();
|
||||||
|
|
||||||
Database.addProfile(new Profile(
|
Database.addProfile(new Profile(
|
||||||
-1,
|
-1,
|
||||||
username,
|
username,
|
||||||
@ -224,7 +229,7 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
));
|
));
|
||||||
ok(exchange);
|
ok(exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateProfile(HttpExchange exchange, URI uri) throws Exception {
|
protected void updateProfile(HttpExchange exchange, URI uri) throws Exception {
|
||||||
Headers headers = exchange.getRequestHeaders();
|
Headers headers = exchange.getRequestHeaders();
|
||||||
if (!headers.containsKey("Authorization")) {
|
if (!headers.containsKey("Authorization")) {
|
||||||
@ -237,33 +242,34 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
}
|
}
|
||||||
String auth = headers.getFirst("Authorization");
|
String auth = headers.getFirst("Authorization");
|
||||||
String[] authParts = auth.trim().split(" ");
|
String[] authParts = auth.trim().split(" ");
|
||||||
|
|
||||||
if (!authParts[0].equals("Basic")) {
|
if (!authParts[0].equals("Basic")) {
|
||||||
text(exchange, 401, "Invalid authorization method");
|
text(exchange, 401, "Invalid authorization method");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] cerd = new String(Base64.getDecoder().decode(authParts[1])).split(":");
|
String[] cerd = new String(Base64.getDecoder().decode(authParts[1])).split(":");
|
||||||
if (cerd.length != 2) {
|
if (cerd.length != 2) {
|
||||||
text(exchange, 401, "Invalid cerdentials format");
|
text(exchange, 401, "Invalid cerdentials format");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Profile profile = Database.getProfileByName(cerd[0]);
|
Profile profile = Database.getProfileByName(cerd[0]);
|
||||||
|
|
||||||
if (profile == null || !Profile.generateHash(cerd[1], profile.getSalt()).equals(profile.getPassword())) {
|
if (profile == null || !Profile.generateHash(cerd[1], profile.getSalt()).equals(profile.getPassword())) {
|
||||||
text(exchange, 401, "Failed to authorize");
|
text(exchange, 401, "Failed to authorize");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query query = new Query(uri.getQuery());
|
Query query = new Query(uri.getQuery());
|
||||||
|
|
||||||
if (query.containsKey("skin"))
|
if (query.containsKey("skin")) {
|
||||||
Database.setProfileSkin(profile, Database.getSkin(query.get("skin")));
|
Database.setProfileSkin(profile, Database.getSkin(query.get("skin")));
|
||||||
|
}
|
||||||
|
|
||||||
ok(exchange);
|
ok(exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JSONObject skinToResponseJSON(Skin skin) {
|
private JSONObject skinToResponseJSON(Skin skin) {
|
||||||
JSONObject object = new JSONObject();
|
JSONObject object = new JSONObject();
|
||||||
object.put("hash", JSON.from(skin.getHash()));
|
object.put("hash", JSON.from(skin.getHash()));
|
||||||
@ -271,7 +277,7 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
object.put("png_old", JSON.from(getRoot() + "skin/"+skin.getHash()+".png?legacy=true"));
|
object.put("png_old", JSON.from(getRoot() + "skin/"+skin.getHash()+".png?legacy=true"));
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JSONObject profileToResponseJSON(Profile profile) {
|
private JSONObject profileToResponseJSON(Profile profile) {
|
||||||
JSONObject object = new JSONObject();
|
JSONObject object = new JSONObject();
|
||||||
object.put("username", JSON.from(profile.getUsername()));
|
object.put("username", JSON.from(profile.getUsername()));
|
||||||
@ -279,5 +285,5 @@ public class RestAPI extends SafeHttpHandler {
|
|||||||
object.put("skin", skinToResponseJSON(profile.getSkin()));
|
object.put("skin", skinToResponseJSON(profile.getSkin()));
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user