ChangeSkinX

ChangeSkinX

446k Downloads

Update skin into db

Feerko opened this issue ยท 58 comments

commented

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?

commented

Base64 decode the texture data string

commented

$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

commented

The skin id should be incremented automatically, so you need to remove SkinId and DisplayName

commented

Ok but still doesn't work $signature part.

commented

You have to escape the parameters like with prepared statements.

commented

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(); 
commented

Signature is no string. It's binary

commented

zrzut ekranu 2017-11-21 o 02 45 32

I decode string. In database this file is BLOB-512 B

commented

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:

CREATE TABLE IF NOT EXISTS `skinData` (
`SkinID` INTEGER PRIMARY KEY AUTO_INCREMENT,
`DisplayName` VARCHAR(255),
`Timestamp` BIGINT NOT NULL,
`UUID` CHAR(36) NOT NULL,
`Name` VARCHAR(16) NOT NULL,
`SlimModel` BIT DEFAULT 0 NOT NULL,
`SkinURL` VARCHAR(255) NOT NULL,
`CapeURL` VARCHAR(255),
`Signature` BLOB NOT NULL
);

commented

Add skin to database works but if I try to /skinselect [id] it's doesn't work

commented

Do you tried /skinselect Skin-rowNumber ?

commented

Yes and i'm alex.

commented

and i'm alex.

?

Yes

What error do you got? It could be because the empty capeurl

commented
commented

Please try it with an NULL as capeurl. The alex skin shows up if the skin signature doesn't match.

commented

Doesn't work too

commented

Which version do you run?

commented

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?

commented

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.

commented

How can I invoke this packet? I just create simple php code to adding skin.

commented

^ missclick

commented

Sorry it's a command from ProtocolLib, but be warned it could be spam a lot for many player joins.

commented

Ok, i see this is command. It's still doesn't work.

commented

I need the output to debug.

commented
[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 }) }

commented

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

commented
[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]
commented

This means it failed to steup the core. Please look for startup errors.

commented

There is no errors on startup. /setskin [nick] works but /skinselect [id] gives error in console

commented

Do you use BungeeCord?

commented

yes

commented

That's the issue. I found a typo. Try /skin-select

commented
[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]
> 
commented

yes

commented

New version is uploaded.

commented

Your site is dead? 502 Bad Gateway. Ok, site works.

commented

I meant the github testing url

commented

There is only previous release 34 minutes ago

commented

Same URL different version.

commented

[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}}

commented
commented

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.

commented

It works when I change values. How can I get this values?

commented

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.

commented

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?

commented

Yes, I'm going to add it in a few weeks.

commented

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.

commented

Is it enough to just decode from base64?

commented

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.

commented

Keep in mind that you have to escape the data properly.

The difficulties of translation. Please explain!

commented

mysql_real_escape_string or with bindParam (better)

commented

Thx

commented

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?

commented

@ziceptor Could you post your code

commented

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();
commented

You must add a condition. Remove all skins with Name=InventiveGames. They do not work.

commented

Download more working skins. Less drop is not working. It is necessary to use the id in descending order.