Cleaned sources

This commit is contained in:
2025-06-12 04:49:36 +02:00
parent 82f946bb36
commit 4ccb49f702

View File

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