Update skin into db
Feerko opened this issue ยท 58 comments
Hello, i want to update skin from mineskin using mineskin api in php.
http://api.mineskin.org/get/id/12356
I have a problem with update a signature. How can i convert string to blob and update it to database?
$signature = base64_decode('lW/V3pJhlVhEap6FoAvSjeOwBc22AIaq74VeO9KXaxxL6BQ4xCfB4pm9+1vXByi1yaYq2XFN6hj8EJrK1ijk+NMBXqKJ6l2Jo35TV5uD0XUuMHcPyxe52myfLnV1ZlH1QZoXmTeWFh6lL6aRe9o13q3zwO7CybZl4ClaXSbphHho0ZsOolu4/ieiazNibM9XrOuLm89PlW7YLYxkKBlpXeTfG+nDNyQF8XhZGIfc46u0gMn6iH4q+bEKm/+kxGvppHcUa9bGGaPyfE+1s5ocbWqqs+DEgrmUSDQe5Jy3WJ4LaTWnoyVfzTxctiwkFY5FEnFaJhY7DFGWrE7SxGftwVo8uaPti6pshvT74jihn2MWhJuC6jogaWlA7mjSnjc2lnwv8tCZRpAVD+KZQmLuHPDzl2l26IskKo/bKVZrkf5HashoAxX8RpWICPIsG9egfne6KQ+s3YQB3SXzD4oOW5oWQAunBJx80cPB9zQLIoguVInW2E2WiBJd2g+Rh+lC/0+0OkzQY4cmf/3sBLsKoIjmwzvqlWW2gUt3WqYywwRrnnP/AfdpG4cbFe1cgMiSK0CV/ZQ2PSotNRguM5Od1k2HUnPWOm14uETM3aXE2lLl+vv6U17q/Z8Gp/A+Scll2gZfwc4vquILic/+U77wt6VAh02LMI+8eW4vLzHKhCA=');
i have something like this for tests only but how to update it to mysql?
$sql = "INSERT INTO skinData
(SkinID
, DisplayName
, Timestamp
, UUID
, Name
, SlimModel
, SkinURL
, CapeURL
, Signature
) VALUES (NULL, NULL, $timestamp, '$uuid', '$name', $slimmodel, '$skinurl', '$capeurl', '$signature');";
it's doesn't work
The skin id should be incremented automatically, so you need to remove SkinId and DisplayName
Ok i did it with statements.
I'm do it with http://api.mineskin.org/get/id/70507
it was add into database but /skinselect [id] doesn't work for this skin. What i do wrong?
$stmt = $conn->prepare("INSERT INTO skinData (SkinID, DisplayName, Timestamp, UUID, Name, SlimModel, SkinURL, CapeURL, Signature) VALUES (NULL, NULL, ?, ?, ?, ?, ?, ?, ?);");
$stmt->bind_param("sssssss", $Timestamp, $UUID, $Name, $SlimModel, $skinURL, $CapeURL, $Signature);
$Timestamp = 1511278348;
$UUID = "fe2673ac98214d08bb692eb91af8c103";
$Name = "mineskintest";
$SlimModel = false;
$skinURL = "c143d47d52fb675b9b98333f03f8c2424082b019f9a4c1f493ff5c9d21ed";
$CapeURL = "";
$Signature = base64_decode('tCYFZ7munFlrlr6gbaP7i3/yfe56Z4AQQ8oLuHHY8GUszc6iIl8twW4axcX1Vbu/XkCPy7DZj2fY6SWeuUBd/+OnjiQWCmZT3AlC1joDv/TTPx+o/049wBMRQ2Vv+8ZRhuPFePD4Fm5LFbjizl4h0ZdKZ1guM9KTs7AV6p2QybjojR0YtzoyS1qckPxw0FzU/TcI0+twvShaliJDKJdVy3C2ZUm19ON6OKCzYqWVLNsM9rzGk4BKTQf7Mmz7uvGTXom1nCgA7E53gunBBCZHLHmBzViM+KsF9Zi0bEG954DdPXlpQ2dC3+fuimerWRnzsFLZ3AwO2ZD9hmPHj/A9qydSNBPArUjwXPE/FmLgYnj5QWM3qWmrsHlEjWy12mf37zi3oetVo7jeSdFWE2tQZRjo5h0U0qBczndDL6UW+fhTj8W9qIONiO/NTcQbQadJMGcauKzwj3IVo+/gMDla6bvUbykEHpN7T5efsXd51OmgX75cTQjKwNmAg0endZZm/MrvgX7y1lDRDdSML+yA4y7D9z2BrAO0CoSJDO63qjWGfN3BSxwkPYBbQjRgviHUrcnXYOR4A7PhIxYuNZWZWHp8UgLUvTOP2BjD+rDCCnJKaxCaZuf9g3vW24yZyrXhfZHns+x9mk+y6cuE+tqKFhi5Ruaxzb0vHNuAWtfszBw=');
$stmt->execute();
So it worked? If so please close it.
BTW you can remove more arguments like SlimMode and CapeURL, because it would use default values specified here:
ChangeSkin/core/src/main/resources/create.sql
Lines 1 to 11 in 0cea42e
Yes i'm trying with /skinselect Skin-[id] and i don't get my skin. I get Alex's skin https://camo.githubusercontent.com/de01eae929520976392b9780aff3dc5e991885e9/687474703a2f2f692e696d6775722e636f6d2f766262674b6e532e706e67
Please try it with an NULL as capeurl. The alex skin shows up if the skin signature doesn't match.
Why ChangeSkin have this structure of db? SkinsRestorer has only Value, Signature and Timestamp its a lot easier. Is there a chance that you will add api mineskin to your plugin in the near future?
ChangeSkin just uses the base64 decoded value. This way you can easier which skin you actually have by having direct access to the true representation.
Please try to invoke packet add PLAY server PLAYER_INFO true
before changeskin sets the skin. I think there is something wrong with encoding the values.
Sorry it's a command from ProtocolLib, but be warned it could be spam a lot for many player joins.
[19:19:27 INFO]: [ChangeSkin] Instant update for Feerko
[19:19:27 INFO]: PacketContainer[type=PLAYER_INFO[class=PacketPlayOutPlayerInfo, id=46], structureModifier=StructureModifier[fieldType=class java.lang.Object, data=[private net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo$EnumPlayerInfoAction net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo.a, private final java.util.List net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo.b]]]
[19:19:27 INFO]: [ProtocolLib] Sent PLAYER_INFO[class=PacketPlayOutPlayerInfo, id=46] to Feerko:
{ a = { name = "REMOVE_PLAYER", ordinal = 4 }, b = ({ b = 0, c = "ADVENTURE", d = com.mojang.authlib.GameProfile@56d68951[id=704cce29-d05f-3359-9464-9aa0d06a98eb,name=Feerko,properties={},legacy=false], e = "TextComponent{text='Feerko', siblings=[], style=Style{hasParent=false, color=null, bold=null, italic=null, underlined=null, obfuscated=null, clickEvent=null, hoverEvent=null, insertion=null}}", a = NULL }) }
[19:19:27 INFO]: PacketContainer[type=PLAYER_INFO[class=PacketPlayOutPlayerInfo, id=46], structureModifier=StructureModifier[fieldType=class java.lang.Object, data=[private net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo$EnumPlayerInfoAction net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo.a, private final java.util.List net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo.b]]]
[19:19:27 INFO]: [ProtocolLib] Sent PLAYER_INFO[class=PacketPlayOutPlayerInfo, id=46] to Feerko:
{ a = { name = "ADD_PLAYER", ordinal = 0 }, b = ({ b = 0, c = "ADVENTURE", d = com.mojang.authlib.GameProfile@e3bc416[id=704cce29-d05f-3359-9464-9aa0d06a98eb,name=Feerko,properties={textures=[com.mojang.authlib.properties.Property@55e3b666]},legacy=false], e = NULL, a = NULL }) }
[19:19:27 INFO]: PacketContainer[type=RESPAWN[class=PacketPlayOutRespawn, id=53], structureModifier=StructureModifier[fieldType=class java.lang.Object, data=[private int net.minecraft.server.v1_12_R1.PacketPlayOutRespawn.a, private net.minecraft.server.v1_12_R1.EnumDifficulty net.minecraft.server.v1_12_R1.PacketPlayOutRespawn.b, private net.minecraft.server.v1_12_R1.EnumGamemode net.minecraft.server.v1_12_R1.PacketPlayOutRespawn.c, private net.minecraft.server.v1_12_R1.WorldType net.minecraft.server.v1_12_R1.PacketPlayOutRespawn.d]]]
[19:19:27 INFO]: PacketContainer[type=POSITION[class=PacketPlayOutPosition, id=47], structureModifier=StructureModifier[fieldType=class java.lang.Object, data=[private double net.minecraft.server.v1_12_R1.PacketPlayOutPosition.a, private double net.minecraft.server.v1_12_R1.PacketPlayOutPosition.b, private double net.minecraft.server.v1_12_R1.PacketPlayOutPosition.c, private float net.minecraft.server.v1_12_R1.PacketPlayOutPosition.d, private float net.minecraft.server.v1_12_R1.PacketPlayOutPosition.e, private java.util.Set net.minecraft.server.v1_12_R1.PacketPlayOutPosition.f, private int net.minecraft.server.v1_12_R1.PacketPlayOutPosition.g]]]
[19:19:27 INFO]: PacketContainer[type=UPDATE_HEALTH[class=PacketPlayOutUpdateHealth, id=65], structureModifier=StructureModifier[fieldType=class java.lang.Object, data=[private float net.minecraft.server.v1_12_R1.PacketPlayOutUpdateHealth.a, private int net.minecraft.server.v1_12_R1.PacketPlayOutUpdateHealth.b, private float net.minecraft.server.v1_12_R1.PacketPlayOutUpdateHealth.c]]]
[19:19:27 INFO]: [ProtocolLib] Sent PLAYER_INFO[class=PacketPlayOutPlayerInfo, id=46] to Feerko:
{ a = { name = "UPDATE_DISPLAY_NAME", ordinal = 3 }, b = ({ b = 63, c = "ADVENTURE", d = com.mojang.authlib.GameProfile@56d68951[id=704cce29-d05f-3359-9464-9aa0d06a98eb,name=Feerko,properties={},legacy=false], e = NULL, a = NULL }) }
Okay I thought it makes a deep toString. Here is a debug build. It prints a debug message on skin apply:
https://github.com/games647/ChangeSkin/releases/tag/testing
[19:26:51 WARN]: [ChangeSkin] Plugin ChangeSkin v3.0 generated an exception while executing task 345
java.lang.NullPointerException: null
at com.github.games647.changeskin.core.shared.SharedSkinSelect.run(SharedSkinSelect.java:18) ~[?:?]
at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftTask.run(CraftTask.java:58) ~[patched_1.12.2.jar:git-Paper-1261]
at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:52) [patched_1.12.2.jar:git-Paper-1261]
at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22) [patched_1.12.2.jar:git-Paper-1261]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_141]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_141]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_141]
There is no errors on startup. /setskin [nick] works but /skinselect [id] gives error in console
[19:36:42 INFO]: [ChangeSkin] Instant update for Feerko
[19:36:42 WARN]: [ChangeSkin] Task #1234 for ChangeSkin v3.0 generated an exception
java.lang.NullPointerException: null
at com.github.games647.changeskin.bukkit.tasks.SkinUpdater.sendPacketsSelf(SkinUpdater.java:205) ~[?:?]
at com.github.games647.changeskin.bukkit.tasks.SkinUpdater.sendUpdateSelf(SkinUpdater.java:121) ~[?:?]
at com.github.games647.changeskin.bukkit.tasks.SkinUpdater.sendUpdate(SkinUpdater.java:102) ~[?:?]
at com.github.games647.changeskin.bukkit.tasks.SkinUpdater.onInstantUpdate(SkinUpdater.java:94) ~[?:?]
at com.github.games647.changeskin.bukkit.tasks.SkinUpdater.run(SkinUpdater.java:80) ~[?:?]
at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftTask.run(CraftTask.java:58) ~[patched_1.12.2.jar:git-Paper-1261]
at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:356) [patched_1.12.2.jar:git-Paper-1261]
at net.minecraft.server.v1_12_R1.MinecraftServer.D(MinecraftServer.java:833) [patched_1.12.2.jar:git-Paper-1261]
at net.minecraft.server.v1_12_R1.DedicatedServer.D(DedicatedServer.java:426) [patched_1.12.2.jar:git-Paper-1261]
at net.minecraft.server.v1_12_R1.MinecraftServer.C(MinecraftServer.java:767) [patched_1.12.2.jar:git-Paper-1261]
at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:665) [patched_1.12.2.jar:git-Paper-1261]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_141]
>
[20:05:20 INFO] [ChangeSkin]: Skin update for Feerko with eyJ0aW1lc3RhbXAiOjE0ODY3NjU1NjUsInByb2ZpbGVJZCI6ImU1OWYzM2VlNGNmZTNmYzE4ZDE0OWZlZmM5ZmNhYTk2IiwicHJvZmlsZU5hbWUiOiIiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzM2NmE1NDk4ODFkNGY1NjI0Mjk4ZmFjMDQ1MmQ4YTQ5OGQ5YTQzMmRmNGZlODgyOTg2NTUzNTJkNGVmYjIifX19 SkinModel{skinId=52, encodedValue=eyJ0aW1lc3RhbXAiOjE0ODY3NjU1NjUsInByb2ZpbGVJZCI6ImU1OWYzM2VlNGNmZTNmYzE4ZDE0OWZlZmM5ZmNhYTk2IiwicHJvZmlsZU5hbWUiOiIiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzM2NmE1NDk4ODFkNGY1NjI0Mjk4ZmFjMDQ1MmQ4YTQ5OGQ5YTQzMmRmNGZlODgyOTg2NTUzNTJkNGVmYjIifX19, encodedSignature=rDjUUs+VTmIN8nEpEmQ/KQOgI9SScCZoiqAtrOPF2Eb7QtLZHmOsEQrH7QCMYPwtveIj+pbnzjQIdkM0hXzLywZEWbtaN7sH8QoiAaCGEcLZ0d1cjNDnTQwYits1iBxcemt1+q6oc2Hh6q4eLUgP+OKZjrheIDRsja3gDyIzxYG2stOkoQ6cWF871QNMczu8EyP0DytRhGzOYzLNWB9jBCrPNttIYW6inH7eDv79e7nvpsZLs+Quyg+U6EOXS6n76g6hES4oPlDZ+c5EstlQBTC7yuQMb/0CJc6PEccQ+gXmSRW2sSm9bZoYcMwRPa9QdbYhs2ILRgERLs1aQ6WiyvlYoZbXWjz+C7mv2iFpHMkDM/xQrNbeD1NeVqXrdO6tjXeGhnxJkkK/NXsJ2v3q0V9RviN2IQZJrQJP/MIiyPCd3xHz5Du8ADZZ3uzJWX5IT93Vj7W71/TtkqiewQJU/pxHSbxCDHelrYAEm7iZW842tLSlHsD7qCa1ND9xdiA0Kxl5Sjryo5SPGz0dnBEaNjYSj8uzecJmrWs35730AIx+93/hZZ87HcAEk7qqlAwPsrEGFULo2xpqEEz+xjAQOndmLUel3vZpdGA1yVggrqGdOLDzxWk39y8FjtQFr1PmazflKHIjOloP2NQLPh5K6XgZarwv3+wrlJsVqOc/FhE=, timestamp=1486823562, profileId=e59f33ee-4cfe-3fc1-8d14-9fefc9fcaa96, profileName=, signatureRequired=true, textures={SKIN=com.github.games647.changeskin.core.model.skin.TextureModel@504ab1e2}}
I'm used this skin http://api.mineskin.org/get/id/7090
I found it the profileName in your database doesn't match the name inside the skin data. (Could be a bug in mineskin?)
If you decode the string you get this:
{"timestamp":1486823564991,
"profileId":"b0d4b28bc1d74889af0e8661cee96aab",
"profileName":"Yeleha",
"signatureRequired":true,
"textures":
{"SKIN":{"url":"http://textures.minecraft.net/texture/366a549881d4f5624298fac0452d8a498d9a432df4fe88298655352d4efb2"}}}
If I decode the data from your database it's:
{"timestamp":1486765565,
"profileId":"e59f33ee4cfe3fc18d149fefc9fcaa96",
"profileName":"",
"signatureRequired":true,
"textures":
{"SKIN":{"url":"http://textures.minecraft.net/texture/366a549881d4f5624298fac0452d8a498d9a432df4fe88298655352d4efb2"}}}
As you can see the timestamp, profile id, ... is different. That's why the signature verification failed. So you just have to change those values in the database.
Once you base64 decode the "ey..." string you get a JSON object, which looks the one above. https://www.base64decode.org/ is nice little website if I don't want to open by IDE.
Great! I see the problem and I understand it now. Thanks for your help. Is there a chance that you will add api mineskin to your plugin in the near future?
How to convert the $Signature in the BLOB? Maybe there are tools for this? While there is no API support Mineskin, I'd like to manually add skins to the database. @games647 help me.
Yes it's enough to decode it from Base64. As a result you'll get a binary output. Keep in mind that you have to escape the data properly.
Keep in mind that you have to escape the data properly.
The difficulties of translation. Please explain!
I have difficulties with the signature. MineSkin/api.mineskin.org#4
@Feerko You have got to add healthy skin in the database? How do you do it?
@games647 How are you doing with this?
@ziceptor Could you post your code
Works. This is an prototipe for SQLite.
<?php
//print_r(SQLite3::version());
$db = new SQLite3('ChangeSkin.db');
// min http://api.mineskin.org/get/id/1
// max http://api.mineskin.org/get/id/107508
for ($x=1; $x<107509; $x++) {
$url = 'http://api.mineskin.org/get/id/' . $x;
echo $url;
echo(PHP_EOL);
sleep(10);
$MineSkin = file_get_contents($url);
$MineSkinDec = json_decode($MineSkin,true);
$MineSkinDecVal = $MineSkinDec['data']['texture']['value'];
$MineSkinDecValB64D = base64_decode($MineSkinDecVal);
$MineSkinDecValB64DDec = json_decode($MineSkinDecValB64D, true);
$Timestamp = $MineSkinDecValB64DDec['timestamp'];
$UUID = $MineSkinDecValB64DDec['profileId'];
$Name = $MineSkinDecValB64DDec['profileName'];
$SkinURLRAW = $MineSkinDecValB64DDec['textures']['SKIN']['url'];
$pos = strrpos($SkinURLRAW, "/");
$SkinURL = substr($SkinURLRAW, $pos + 1);
$jsignature = $MineSkinDec['data']['texture']['signature'];
$Signature = base64_decode($jsignature);
$CapeURL = "";
$stmt = $db->prepare('INSERT INTO skinData (Name, Timestamp, UUID, SkinURL, CapeURL, Signature) values (:Name, :Timestamp, :UUID, :SkinURL, :CapeURL, :Signature)');
$stmt->bindValue(':Name', $Name, SQLITE3_TEXT);
$stmt->bindValue(':Timestamp', $Timestamp, SQLITE3_INTEGER);
$stmt->bindValue(':UUID', $UUID, SQLITE3_TEXT);
$stmt->bindValue(':SkinURL', $SkinURL, SQLITE3_TEXT);
$stmt->bindValue(':CapeURL', $CapeURL, SQLITE3_TEXT);
$stmt->bindValue(':Signature', $Signature, SQLITE3_BLOB);
$result = $stmt->execute();
}
$db->close();
You must add a condition. Remove all skins with Name=InventiveGames
. They do not work.