diff --git a/admin/index.php b/admin/index.php
index d1d0ede8..25d92e8b 100644
--- a/admin/index.php
+++ b/admin/index.php
@@ -3,7 +3,7 @@
* @Author: prpr
* @Date: 2016-02-03 14:39:50
* @Last Modified by: prpr
- * @Last Modified time: 2016-02-04 23:45:06
+ * @Last Modified time: 2016-02-05 15:52:39
*/
session_start();
@@ -83,13 +83,14 @@ if (isset($_SESSION['uname'])) {
|
|
- '; ?>
- '; ?>
+ '; ?>
+ '; ?>
+ '; ?>
|
- Skin
+ Skin
Cape
- Model
+ Model
()
|
diff --git a/ajax.php b/ajax.php
index b1da2cea..bcc4f497 100644
--- a/ajax.php
+++ b/ajax.php
@@ -3,7 +3,7 @@
* @Author: printempw
* @Date: 2016-01-16 23:01:33
* @Last Modified by: prpr
- * @Last Modified time: 2016-02-04 18:48:30
+ * @Last Modified time: 2016-02-05 15:35:31
*
* - login, register, logout
* - upload, change, delete
@@ -20,7 +20,12 @@ require "$dir/includes/autoload.inc.php";
database::checkConfig();
if (isset($_POST['uname'])) {
- $user = new user($_POST['uname']);
+ $uname = $_POST['uname'];
+ if (user::checkValidUname($uname)) {
+ $user = new user($_POST['uname']);
+ } else {
+ utils::raise(1, 'Invalid username. Only letters, numbers and _ is allowed.');
+ }
} else {
utils::raise('1', 'Empty username.');
}
@@ -29,7 +34,6 @@ $json = null;
/**
* Handle requests from index.php
- * @var [type]
*/
if ($action == "login") {
if (checkPost()) {
@@ -59,7 +63,7 @@ if ($action == "login") {
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
- // If amout of registered accounts of IP is more than allowed mounts,
+ // If amount of registered accounts of IP is more than allowed mounts,
// then reject the registration.
if ($user->db->getNumRows('ip', $ip) < REGS_PER_IP) {
// use once md5 to encrypt password
@@ -99,7 +103,8 @@ if ($action == "upload") {
if (utils::getValue('token', $_SESSION) == $user->getToken()) {
if (checkFile()) {
if ($file = utils::getValue('skin_file', $_FILES)) {
- if ($user->setTexture('skin', $file)) {
+ $model = (isset($_GET['model']) && $_GET['model'] == "steve") ? "steve" : "alex";
+ if ($user->setTexture($model, $file)) {
$json['skin']['errno'] = 0;
$json['skin']['msg'] = "Skin uploaded successfully.";
} else {
@@ -121,14 +126,15 @@ if ($action == "upload") {
$json['errno'] = 1;
$json['msg'] = "Invalid token.";
}
-} else if ($action == "logout") {
- if (utils::getValue('token', $_SESSION)) {
- session_destroy();
+} else if ($action == "model") {
+ if (utils::getValue('token', $_SESSION) == $user->getToken()) {
+ $new_model = ($user->getPreference() == "default") ? "slim" : "default";
+ $user->setPreference($new_model);
$json['errno'] = 0;
- $json['msg'] = 'Session destroyed.';
+ $json['msg'] = "Preferred model successfully changed to ".$user->getPreference().".";
} else {
$json['errno'] = 1;
- $json['msg'] = 'No available session.';
+ $json['msg'] = "Invalid token.";
}
}
@@ -221,6 +227,15 @@ if ($action == "change") {
$json['errno'] = 1;
$json['msg'] = "Invalid token.";
}
+} else if ($action == "logout") {
+ if (utils::getValue('token', $_SESSION)) {
+ session_destroy();
+ $json['errno'] = 0;
+ $json['msg'] = 'Session destroyed.';
+ } else {
+ $json['errno'] = 1;
+ $json['msg'] = 'No available session.';
+ }
}
if (!$action) {
diff --git a/assets/css/user.style.css b/assets/css/user.style.css
index 33e498b2..69b86e89 100644
--- a/assets/css/user.style.css
+++ b/assets/css/user.style.css
@@ -2,7 +2,7 @@
* @Author: prpr
* @Date: 2016-01-21 19:12:06
* @Last Modified by: prpr
-* @Last Modified time: 2016-02-05 11:16:53
+* @Last Modified time: 2016-02-05 15:13:00
*/
.home-menu-blur {
@@ -100,3 +100,6 @@ input[type=radio] {
.container {
position: initial !important;
}
+#skinpreview > p {
+ margin: 20px 0;
+}
diff --git a/assets/js/admin.utils.js b/assets/js/admin.utils.js
index 1116f79e..386bd619 100644
--- a/assets/js/admin.utils.js
+++ b/assets/js/admin.utils.js
@@ -2,11 +2,23 @@
* @Author: prpr
* @Date: 2016-02-04 16:48:42
* @Last Modified by: prpr
-* @Last Modified time: 2016-02-04 18:27:44
+* @Last Modified time: 2016-02-05 15:52:32
*/
'use strict';
+function uploadSkin(uname) {
+ Ply.dialog("confirm", {
+ text: "Which model do you want to change?",
+ ok: "Steve",
+ cancel: "Alex"
+ }).done(function(){
+ uploadTexture(uname, 'steve');
+ }).fail(function(){
+ uploadTexture(uname, 'alex');
+ });
+}
+
function uploadTexture(uname, type) {
var ply = new Ply({
el: 'Upload new '+type+':'+
@@ -31,7 +43,7 @@ function uploadTexture(uname, type) {
location.reload();
});
} else {
- showAlert("Error when uploading cape:\n" + json.msg);
+ showAlert("Error when uploading texture:\n" + json.msg);
}
}
});
diff --git a/assets/js/user.utils.js b/assets/js/user.utils.js
index d76bb66b..fcbfebbb 100644
--- a/assets/js/user.utils.js
+++ b/assets/js/user.utils.js
@@ -2,115 +2,134 @@
* @Author: prpr
* @Date: 2016-01-21 13:56:40
* @Last Modified by: prpr
-* @Last Modified time: 2016-02-05 11:38:39
+* @Last Modified time: 2016-02-05 15:35:02
*/
'use strict';
-$("body").on("change", "#skininput", function(){
- var files = $("#skininput").prop("files");
- handleFiles(files, "skin");
+$('body').on('change', '#skininput', function(){
+ var files = $('#skininput').prop('files');
+ handleFiles(files, 'skin');
});
-$("body").on("change", "#capeinput", function(){
- var files = $("#capeinput").prop("files");
- handleFiles(files, "cape");
+$('body').on('change', '#capeinput', function(){
+ var files = $('#capeinput').prop('files');
+ handleFiles(files, 'cape');
});
+// Real-time preview
function handleFiles(files, type) {
- if(files.length > 0) {
- var file = files[0];
- if(file.type === 'image/png') {
- var fr = new FileReader();
- fr.onload = function (e) {
- var img = new Image();
- img.onload = function () {
- if (type == "skin") {
- MSP.changeSkin(img.src);
- } else {
- MSP.changeCape(img.src);
- }
- };
- img.onerror = function () {
- showMsg("alert-danger", "Error: Not an image or unknown file format");
- };
- img.src = this.result;
- };
- fr.readAsDataURL(file);
- } else {
- showMsg("alert-danger", "Error: This is not a PNG image!");
- }
- }
+ if(files.length > 0) {
+ var file = files[0];
+ if(file.type === "image/png") {
+ var fr = new FileReader();
+ fr.onload = function (e) {
+ var img = new Image();
+ img.onload = function () {
+ if (type == "skin") {
+ MSP.changeSkin(img.src);
+ } else {
+ MSP.changeCape(img.src);
+ }
+ };
+ img.onerror = function () {
+ showMsg("alert-danger", "Error: Not an image or unknown file format");
+ };
+ img.src = this.result;
+ };
+ fr.readAsDataURL(file);
+ } else {
+ showMsg("alert-danger", "Error: This is not a PNG image!");
+ }
+ }
};
function init3dCanvas() {
- if ($(window).width() < 800) {
- var canvas = MSP.get3dSkinCanvas($('#skinpreview').width(), $('#skinpreview').width());
- $("#skinpreview").append($(canvas).prop("id", "canvas3d"));
- } else {
- var canvas = MSP.get3dSkinCanvas(400, 400);
- $("#skinpreview").append($(canvas).prop("id", "canvas3d"));
- }
+ if ($(window).width() < 800) {
+ var canvas = MSP.get3dSkinCanvas($('#skinpreview').width(), $('#skinpreview').width());
+ $("#skinpreview").append($(canvas).prop("id", "canvas3d"));
+ } else {
+ var canvas = MSP.get3dSkinCanvas(400, 400);
+ $("#skinpreview").append($(canvas).prop("id", "canvas3d"));
+ }
}
-$(document).ready(function(){
- init3dCanvas();
-});
-
-$(window).resize(function(){
- init3dCanvas();
-});
+$(document).ready(init3dCanvas);
+// Auto resize canvas to fit responsive design
+$(window).resize(init3dCanvas);
+// Change 3D preview status
$("[title='Movements']").click(function(){
- MSP.setStatus("movements", !MSP.getStatus("movements"));
+ MSP.setStatus("movements", !MSP.getStatus("movements"));
});
-
$("[title='Running']").click(function(){
- MSP.setStatus("running", !MSP.getStatus("running"));
+ MSP.setStatus("running", !MSP.getStatus("running"));
});
-
$("[title='Rotation']").click(function(){
- MSP.setStatus("rotation", !MSP.getStatus("rotation"));
+ MSP.setStatus("rotation", !MSP.getStatus("rotation"));
});
function show2dPreview() {
- $('#canvas3d').remove();
- $("#skinpreview").html($('Skin for Steve model: ').append($(' ').css('float', 'right').attr('src', '../skin/admin.png')));
+ $('#canvas3d').remove();
+ $("#skinpreview").html($('Skin for Steve model: ').append($(' ').css('float', 'right').attr('src', '../skin/'+docCookies.getItem('uname')+'-steve.png')));
+ $("#skinpreview").append($('Skin for Alex model: ').append($(' ').css('float', 'right').attr('src', '../skin/'+docCookies.getItem('uname')+'-alex.png')));
+ $("#skinpreview").append($('Cape: ').append($(' ').css('float', 'right').attr('src', '../cape/'+docCookies.getItem('uname')+'.png')));
}
$("#upload").click(function(){
- var skin_file = $("#skininput").get(0).files[0];
- var cape_file = $("#capeinput").get(0).files[0];
- var form_data = new FormData();
- if (skin_file) form_data.append('skin_file', skin_file);
- if (cape_file) form_data.append('cape_file', cape_file);
- if (skin_file || cape_file) {
- $.ajax({
- type: 'POST',
- url: '../ajax.php?action=upload',
- contentType: false,
- dataType: "json",
- data: form_data,
- processData: false,
- beforeSend: function() {
- showMsg("alert-info", "Uploading...");
- },
- success: function(json) {
- console.log(json);
- if (json.skin.errno == 0 && json.cape.errno == 0) {
- showMsg("alert-success", "Successfully uploaded.");
- }
- if (json.skin.errno != 0) {
- showMsg("alert-danger", "Error when uploading skin:\n"+json.skin.msg);
- }
- if (json.cape.errno != 0) {
- showMsg("alert-danger", "Error when uploading cape:\n"+json.cape.msg);
- }
- }
- });
- } else {
- showMsg("alert-warning", "No input file selected");
- }
+ var model = $('#model-steve').prop('checked') ? "steve" : "alex";
+ var skin_file = $('#skininput').get(0).files[0];
+ var cape_file = $('#capeinput').get(0).files[0];
+ var form_data = new FormData();
+ if (skin_file) form_data.append('skin_file', skin_file);
+ if (cape_file) form_data.append('cape_file', cape_file);
+ form_data.append('uname', docCookies.getItem('uname'));
+ // Ajax file upload
+ if (skin_file || cape_file) {
+ $.ajax({
+ type: 'POST',
+ url: '../ajax.php?action=upload&model='+model,
+ contentType: false,
+ dataType: "json",
+ data: form_data,
+ processData: false,
+ beforeSend: function() {
+ showMsg('alert-info', 'Uploading...');
+ },
+ success: function(json) {
+ console.log(json);
+ if (json.skin.errno == 0 && json.cape.errno == 0) {
+ showMsg('alert-success', 'Successfully uploaded.');
+ }
+ if (json.skin.errno != 0) {
+ showMsg('alert-danger', 'Error when uploading skin:\n'+json.skin.msg);
+ }
+ if (json.cape.errno != 0) {
+ showMsg('alert-danger', 'Error when uploading cape:\n'+json.cape.msg);
+ }
+ }
+ });
+ } else {
+ showMsg('alert-warning', 'No input file selected');
+ }
});
-
+function changeModel(uname) {
+ showAlert("Sure to change?", function(){
+ $.ajax({
+ type: "POST",
+ url: "../ajax.php?action=model",
+ data: { "uname": docCookies.getItem('uname') },
+ dataType: "json",
+ success: function(json) {
+ if (json.errno == 0) {
+ showAlert(json.msg, function(){
+ location.reload();
+ });
+ } else {
+ showAlert(json.msg);
+ }
+ }
+ });
+ });
+}
diff --git a/get.php b/get.php
index 38bbbad4..f2f7c4ed 100644
--- a/get.php
+++ b/get.php
@@ -3,7 +3,7 @@
* @Author: prpr
* @Date: 2016-02-02 20:56:42
* @Last Modified by: prpr
- * @Last Modified time: 2016-02-04 22:06:20
+ * @Last Modified time: 2016-02-05 14:51:26
*
* All textures requests of legacy link will be handle here.
*/
@@ -18,10 +18,15 @@ if (isset($_GET['type']) && isset($_GET['uname'])) {
$if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : null;
if ($_GET['type'] == "skin" || $_GET['type'] == "cape") {
+ $model = (isset($_GET['model']) && $_GET['model'] == "steve") ? "steve" : "alex";
if ($if_modified_since >= $user->getLastModified()) {
header('HTTP/1.0 304 Not Modified');
} else {
- echo $user->getBinaryTexture($_GET['type']);
+ if ($_GET['type'] == "cape") {
+ echo $user->getBinaryTexture('cape');
+ } else {
+ echo $user->getBinaryTexture($model);
+ }
}
} else if ($_GET['type'] == "json") {
if (isset($_GET['api'])) {
diff --git a/includes/user.class.php b/includes/user.class.php
index f25bb602..a078e13d 100644
--- a/includes/user.class.php
+++ b/includes/user.class.php
@@ -3,7 +3,7 @@
* @Author: printempw
* @Date: 2016-01-16 23:01:33
* @Last Modified by: prpr
- * @Last Modified time: 2016-02-04 20:38:42
+ * @Last Modified time: 2016-02-05 15:11:35
*/
class user
@@ -37,6 +37,10 @@ class user
}
}
+ public static function checkValidUname($uname) {
+ return preg_match("([A-Za-z0-9_\-]+)", $uname);
+ }
+
public static function checkValidPwd($passwd) {
if (strlen($passwd) > 16 || strlen($passwd) < 5) {
utils::raise(1, 'Illegal password. Password length should be in 5~16.');
@@ -55,32 +59,33 @@ class user
}
public function register($passwd, $ip) {
- if ($this->db->insert(array(
- "uname" => $this->uname,
- "passwd" => $passwd,
- "ip" => $ip
- )))
- {
- return true;
- } else {
- return false;
- }
+ return $this->db->insert(array(
+ "uname" => $this->uname,
+ "passwd" => $passwd,
+ "ip" => $ip
+ ));
}
public function unRegister() {
- if ($this->getTexture('skin') != "")
- utils::remove("./textures/".$this->getTexture('skin'));
- if ($this->getTexture('skin') != "")
+ if ($this->getTexture('steve') != "")
+ utils::remove("./textures/".$this->getTexture('steve'));
+ if ($this->getTexture('alex') != "")
+ utils::remove("./textures/".$this->getTexture('alex'));
+ if ($this->getTexture('cape') != "")
utils::remove("./textures/".$this->getTexture('cape'));
return $this->db->delete($this->uname);
}
+ /**
+ * Get textures of user
+ * @param string $type steve|alex|cape
+ * @return string sha256-hash of texture file
+ */
public function getTexture($type) {
- if ($type == "skin") {
- return $this->db->select('username', $this->uname)['skin_hash'];
- } else if ($type == "cape") {
- return $this->db->select('username', $this->uname)['cape_hash'];
- }
+ if ($type == "skin")
+ $type = ($this->getPreference() == "default") ? "steve" : "alex";
+ if ($type == "steve" | $type == "alex" | $type == "cape")
+ return $this->db->select('username', $this->uname)['hash_'.$type];
return false;
}
@@ -88,9 +93,9 @@ class user
$filename = "./textures/".$this->getTexture($type);
if (file_exists($filename)) {
header('Content-Type: image/png');
+ // Cache friendly
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->getLastModified()).' GMT');
- $data = fread(fopen($filename, 'r'), filesize($filename));
- return $data;
+ return utils::fread($filename);
} else {
utils::raise(-1, 'Texture no longer exists.');
}
@@ -98,21 +103,19 @@ class user
public function setTexture($type, $file) {
$hash = utils::upload($file);
- if ($type == "skin") {
- // remove the original texture first
- if ($this->getTexture('skin') != "")
- utils::remove("./textures/".$this->getTexture('skin'));
- $this->updateLastModified();
- return $this->db->update($this->uname, 'skin_hash', $hash);
- } else if ($type == "cape") {
- if ($this->getTexture('cape') != "")
- utils::remove("./textures/".$this->getTexture('cape'));
- $this->updateLastModified();
- return $this->db->update($this->uname, 'cape_hash', $hash);
- }
+ // Remove the original texture first
+ if ($this->getTexture($type) != "")
+ utils::remove("./textures/".$this->getTexture($type));
+ $this->updateLastModified();
+ if ($type == "steve" | $type == "alex" | $type == "cape")
+ return $this->db->update($this->uname, 'hash_'.$type, $hash);
return false;
}
+ /**
+ * Set preferred model
+ * @param string $type, 'slim' or 'default'
+ */
public function setPreference($type) {
return $this->db->update($this->uname, 'preference', $type);
}
@@ -121,9 +124,15 @@ class user
return $this->db->select('username', $this->uname)['preference'];
}
+ /**
+ * Get JSON profile
+ * @param int $api_type, which API to use, 0 for CustomSkinAPI, 1 for UniSkinAPI
+ * @return string, user profile in json format
+ */
public function getJsonProfile($api_type) {
header('Content-type: application/json');
if ($this->is_registered) {
+ // Support both CustomSkinLoader API & UniSkinAPI
if ($api_type == 0 || $api_type == 1) {
$json[($api_type == 0) ? 'username' : 'player_name'] = $this->uname;
$model = $this->getPreference();
@@ -132,8 +141,9 @@ class user
$json['last_update'] = $this->getLastModified();
$json['model_preference'] = [$model, $sec_model];
}
- $json['skins'][$model] = $this->getTexture('skin');
- $json['skins'][$sec_model] = $this->getTexture('skin');
+ // Skins dict order by preference model
+ $json['skins'][$model] = $this->getTexture($model == "default" ? "steve" : "alex");
+ $json['skins'][$sec_model] = $this->getTexture($sec_model == "default" ? "steve" : "alex");
$json['cape'] = $this->getTexture('cape');
} else {
utils::raise(-1, 'Configuration error. Non-supported API_TYPE.');
diff --git a/includes/utils.class.php b/includes/utils.class.php
index b416ae7f..a842508c 100644
--- a/includes/utils.class.php
+++ b/includes/utils.class.php
@@ -3,7 +3,7 @@
* @Author: printempw
* @Date: 2016-01-16 23:01:33
* @Last Modified by: prpr
- * @Last Modified time: 2016-02-04 23:43:07
+ * @Last Modified time: 2016-02-05 13:27:43
*/
class utils
@@ -36,6 +36,16 @@ class utils
return $hash;
}
+ /**
+ * Read a file and return bin data
+ *
+ * @param string $filename
+ * @return resource, binary data
+ */
+ public static function fread($filename) {
+ return fread(fopen($filename, 'r'), filesize($filename));
+ }
+
/**
* Remove a file
*
diff --git a/user/index.php b/user/index.php
index 00906d2f..1cf2695e 100644
--- a/user/index.php
+++ b/user/index.php
@@ -71,9 +71,9 @@ if (isset($_SESSION['uname'])) {
Select a cape:
- My skin fits on the classic Steve player model.
+
- My skin fits on the new Alex player model.
+
2D Preview
@@ -81,6 +81,12 @@ if (isset($_SESSION['uname'])) {
+
+ Change Preferred Model
+
+ Your preference model is getPreference(); ?>. Change?
+
+
@@ -104,5 +110,9 @@ if (isset($_SESSION['uname'])) {
-
+getTexture('alex') && ($user->getTexture('steve') == "")) {?>
+
+
|