Compare commits

..

No commits in common. "master" and "v2.1.4" have entirely different histories.

13 changed files with 699 additions and 1330 deletions

View File

@ -1,6 +1,6 @@
FROM node:12-alpine AS builder FROM node:12-alpine AS builder
RUN apk --no-cache add git python3 build-base redis cairo-dev pango-dev jpeg-dev giflib-dev RUN apk --no-cache add git python build-base redis cairo-dev pango-dev jpeg-dev giflib-dev
RUN adduser -D app RUN adduser -D app
USER app USER app

View File

@ -39,7 +39,7 @@ Please [visit the website](https://crafatar.com) for details.
```sh ```sh
docker network create crafatar docker network create crafatar
docker run --net crafatar -d --name redis redis docker run --net crafatar -d --name redis redis
docker run --net crafatar -v crafatar-images:/home/app/crafatar/images -e REDIS_URL=redis://redis -p 3000:3000 crafatar/crafatar docker run --net crafatar -v crafatar-images:/crafatar/images -e REDIS_URL=redis://redis -p 3000:3000 crafatar/crafatar
``` ```
## Manual ## Manual

View File

@ -60,10 +60,6 @@ var config = {
sidebar: process.env.SPONSOR_SIDE, sidebar: process.env.SPONSOR_SIDE,
top_right: process.env.SPONSOR_TOP_RIGHT top_right: process.env.SPONSOR_TOP_RIGHT
}, },
endpoints: {
textures_url: process.env.TEXTURES_ENDPOINT || "https://textures.minecraft.net/texture/",
session_url: process.env.SESSION_ENDPOINT || "https://sessionserver.mojang.com/session/minecraft/profile/"
}
}; };
module.exports = config; module.exports = config;

View File

@ -7,8 +7,8 @@ var skins = require("./skins");
var path = require("path"); var path = require("path");
var fs = require("fs"); var fs = require("fs");
// 0098cb60fa8e427cb299793cbd302c9a // 0098cb60-fa8e-427c-b299-793cbd302c9a
var valid_user_id = /^[0-9a-fA-F]{32}$/; // uuid var valid_user_id = /^[0-9a-fA-F\-]{32,36}$/; // uuid
var hash_pattern = /[0-9a-f]+$/; var hash_pattern = /[0-9a-f]+$/;
// gets the hash from the textures.minecraft.net +url+ // gets the hash from the textures.minecraft.net +url+
@ -122,14 +122,6 @@ var requests = {
cape: {} cape: {}
}; };
var loginterval = setInterval(function(){
var skinreqs = Object.keys(requests.skin).length;
var capereqs = Object.keys(requests.cape).length;
if (skinreqs || capereqs) {
logging.log("Currently waiting for " + skinreqs + " skin requests and " + capereqs + " cape requests.");
}
}, 1000);
// add a request for +userId+ and +type+ to the queue // add a request for +userId+ and +type+ to the queue
function push_request(userId, type, callback) { function push_request(userId, type, callback) {
// avoid special properties (e.g. 'constructor') // avoid special properties (e.g. 'constructor')
@ -395,8 +387,4 @@ exp.get_cape = function(rid, userId, callback) {
}); });
}; };
exp.stoplog = function() {
clearInterval(loginterval);
}
module.exports = exp; module.exports = exp;

View File

@ -5,8 +5,8 @@ var skins = require("./skins");
var http = require("http"); var http = require("http");
require("./object-patch"); require("./object-patch");
var session_url = config.endpoints.session_url; var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/";
var textures_url = config.endpoints.textures_url; var textures_url = "https://textures.minecraft.net/texture/";
// count requests made to session_url in the last 1000ms // count requests made to session_url in the last 1000ms
var session_requests = []; var session_requests = [];

View File

@ -14,10 +14,12 @@ function handle_default(img_status, userId, size, def, req, err, callback) {
if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") { if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") {
if (helpers.id_valid(def)) { if (helpers.id_valid(def)) {
// clean up the old URL to match new image // clean up the old URL to match new image
req.url.searchParams.delete('default'); var parsed = req.url;
req.url.path_list[1] = def; delete parsed.query.default;
req.url.pathname = req.url.path_list.join('/'); delete parsed.search;
var newUrl = req.url.toString(); parsed.path_list[1] = def;
parsed.pathname = "/" + parsed.path_list.join("/");
var newUrl = url.format(parsed);
callback({ callback({
status: img_status, status: img_status,
redirect: newUrl, redirect: newUrl,
@ -51,9 +53,9 @@ function handle_default(img_status, userId, size, def, req, err, callback) {
// GET avatar request // GET avatar request
module.exports = function(req, callback) { module.exports = function(req, callback) {
var userId = (req.url.path_list[1] || "").split(".")[0]; var userId = (req.url.path_list[1] || "").split(".")[0];
var size = parseInt(req.url.searchParams.get("size")) || config.avatars.default_size; var size = parseInt(req.url.query.size) || config.avatars.default_size;
var def = req.url.searchParams.get("default"); var def = req.url.query.default;
var overlay = req.url.searchParams.has("overlay") || req.url.searchParams.has("helm"); var overlay = Object.prototype.hasOwnProperty.call(req.url.query, "overlay") || Object.prototype.hasOwnProperty.call(req.url.query, "helm");
// check for extra paths // check for extra paths
if (req.url.path_list.length > 2) { if (req.url.path_list.length > 2) {
@ -65,9 +67,6 @@ module.exports = function(req, callback) {
return; return;
} }
// strip dashes
userId = userId.replace(/-/g, "");
// Prevent app from crashing/freezing // Prevent app from crashing/freezing
if (size < config.avatars.min_size || size > config.avatars.max_size) { if (size < config.avatars.min_size || size > config.avatars.max_size) {
// "Unprocessable Entity", valid request, but semantically erroneous: // "Unprocessable Entity", valid request, but semantically erroneous:
@ -85,6 +84,9 @@ module.exports = function(req, callback) {
return; return;
} }
// strip dashes
userId = userId.replace(/-/g, "");
try { try {
helpers.get_avatar(req.id, userId, overlay, size, function(err, status, image, hash) { helpers.get_avatar(req.id, userId, overlay, size, function(err, status, image, hash) {
if (err) { if (err) {

View File

@ -4,7 +4,7 @@ var cache = require("../cache");
// GET cape request // GET cape request
module.exports = function(req, callback) { module.exports = function(req, callback) {
var userId = (req.url.path_list[1] || "").split(".")[0]; var userId = (req.url.path_list[1] || "").split(".")[0];
var def = req.url.searchParams.get('default'); var def = req.url.query.default;
var rid = req.id; var rid = req.id;
// check for extra paths // check for extra paths
@ -17,8 +17,6 @@ module.exports = function(req, callback) {
return; return;
} }
// strip dashes
userId = userId.replace(/-/g, "");
if (!helpers.id_valid(userId)) { if (!helpers.id_valid(userId)) {
callback({ callback({
status: -2, status: -2,
@ -27,6 +25,9 @@ module.exports = function(req, callback) {
return; return;
} }
// strip dashes
userId = userId.replace(/-/g, "");
try { try {
helpers.get_cape(rid, userId, function(err, hash, status, image) { helpers.get_cape(rid, userId, function(err, hash, status, image) {
if (err) { if (err) {

View File

@ -17,10 +17,12 @@ function handle_default(rid, scale, overlay, body, img_status, userId, size, def
if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") { if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") {
if (helpers.id_valid(def)) { if (helpers.id_valid(def)) {
// clean up the old URL to match new image // clean up the old URL to match new image
req.url.searchParams.delete('default'); var parsed = req.url;
req.url.path_list[2] = def; delete parsed.query.default;
req.url.pathname = req.url.path_list.join('/'); delete parsed.search;
var newUrl = req.url.toString(); parsed.path_list[2] = def;
parsed.pathname = "/" + parsed.path_list.join("/");
var newUrl = url.format(parsed);
callback({ callback({
status: img_status, status: img_status,
redirect: newUrl, redirect: newUrl,
@ -60,9 +62,9 @@ module.exports = function(req, callback) {
var rid = req.id; var rid = req.id;
var body = raw_type === "body"; var body = raw_type === "body";
var userId = (req.url.path_list[2] || "").split(".")[0]; var userId = (req.url.path_list[2] || "").split(".")[0];
var def = req.url.searchParams.get("default"); var def = req.url.query.default;
var scale = parseInt(req.url.searchParams.get("scale")) || config.renders.default_scale; var scale = parseInt(req.url.query.scale) || config.renders.default_scale;
var overlay = req.url.searchParams.has("overlay") || req.url.searchParams.has("helm"); var overlay = Object.prototype.hasOwnProperty.call(req.url.query, "overlay") || Object.prototype.hasOwnProperty.call(req.url.query, "helm");
// check for extra paths // check for extra paths
if (req.url.path_list.length > 3) { if (req.url.path_list.length > 3) {
@ -83,9 +85,6 @@ module.exports = function(req, callback) {
return; return;
} }
// strip dashes
userId = userId.replace(/-/g, "");
if (scale < config.renders.min_scale || scale > config.renders.max_scale) { if (scale < config.renders.min_scale || scale > config.renders.max_scale) {
callback({ callback({
status: -2, status: -2,
@ -100,6 +99,9 @@ module.exports = function(req, callback) {
return; return;
} }
// strip dashes
userId = userId.replace(/-/g, "");
try { try {
helpers.get_render(rid, userId, scale, overlay, body, function(err, status, hash, image) { helpers.get_render(rid, userId, scale, overlay, body, function(err, status, hash, image) {
if (err) { if (err) {

View File

@ -14,10 +14,12 @@ function handle_default(img_status, userId, def, req, err, callback) {
if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") { if (defname !== "steve" && defname !== "mhf_steve" && defname !== "alex" && defname !== "mhf_alex") {
if (helpers.id_valid(def)) { if (helpers.id_valid(def)) {
// clean up the old URL to match new image // clean up the old URL to match new image
req.url.searchParams.delete('default'); var parsed = req.url;
req.url.path_list[1] = def; delete parsed.query.default;
req.url.pathname = req.url.path_list.join('/'); delete parsed.search;
var newUrl = req.url.toString(); parsed.path_list[1] = def;
parsed.pathname = "/" + parsed.path_list.join("/");
var newUrl = url.format(parsed);
callback({ callback({
status: img_status, status: img_status,
redirect: newUrl, redirect: newUrl,
@ -60,7 +62,7 @@ function handle_default(img_status, userId, def, req, err, callback) {
// GET skin request // GET skin request
module.exports = function(req, callback) { module.exports = function(req, callback) {
var userId = (req.url.path_list[1] || "").split(".")[0]; var userId = (req.url.path_list[1] || "").split(".")[0];
var def = req.url.searchParams.get("default"); var def = req.url.query.default;
var rid = req.id; var rid = req.id;
// check for extra paths // check for extra paths
@ -73,8 +75,6 @@ module.exports = function(req, callback) {
return; return;
} }
// strip dashes
userId = userId.replace(/-/g, "");
if (!helpers.id_valid(userId)) { if (!helpers.id_valid(userId)) {
callback({ callback({
status: -2, status: -2,
@ -83,6 +83,9 @@ module.exports = function(req, callback) {
return; return;
} }
// strip dashes
userId = userId.replace(/-/g, "");
try { try {
helpers.get_skin(rid, userId, function(err, hash, status, image, slim) { helpers.get_skin(rid, userId, function(err, hash, status, image, slim) {
if (err) { if (err) {

View File

@ -1,7 +1,6 @@
#!/usr/bin/env node #!/usr/bin/env node
var querystring = require("querystring"); var querystring = require("querystring");
var response = require("./response"); var response = require("./response");
var helpers = require("./helpers.js");
var toobusy = require("toobusy-js"); var toobusy = require("toobusy-js");
var logging = require("./logging"); var logging = require("./logging");
var config = require("../config"); var config = require("../config");
@ -22,9 +21,7 @@ var routes = {
// serves assets from lib/public // serves assets from lib/public
function asset_request(req, callback) { function asset_request(req, callback) {
const filename = path.join(__dirname, "public", ...req.url.path_list); var filename = path.join(__dirname, "public", req.url.path_list.join("/"));
const relative = path.relative(path.join(__dirname, "public"), filename);
if (relative && !relative.startsWith('..') && !path.isAbsolute(relative)) {
fs.access(filename, function(fs_err) { fs.access(filename, function(fs_err) {
if (!fs_err) { if (!fs_err) {
fs.readFile(filename, function(err, data) { fs.readFile(filename, function(err, data) {
@ -42,13 +39,6 @@ function asset_request(req, callback) {
}); });
} }
}); });
} else {
callback({
body: "Forbidden",
status: -2,
code: 403,
});
}
} }
// generates a 12 character random string // generates a 12 character random string
@ -56,18 +46,26 @@ function request_id() {
return Math.random().toString(36).substring(2, 14); return Math.random().toString(36).substring(2, 14);
} }
// splits decoded URL path into an Array // splits a URL path into an Array
// the path is resolved and decoded
function path_list(pathname) { function path_list(pathname) {
// remove double and trailing slashes
pathname = pathname.replace(/\/\/+/g, "/").replace(/(.)\/$/, "$1");
var list = pathname.split("/"); var list = pathname.split("/");
list.shift(); list.shift();
for (var i = 0; i < list.length; i++) {
// URL decode
list[i] = querystring.unescape(list[i]);
}
return list; return list;
} }
// handles the +req+ by routing to the request to the appropriate module // handles the +req+ by routing to the request to the appropriate module
function requestHandler(req, res) { function requestHandler(req, res) {
req.url = new URL(decodeURI(req.url), 'http://' + req.headers.host); req.url = url.parse(req.url, true);
req.url.pathname = path.resolve('/', req.url.pathname); req.url.query = req.url.query || {};
req.url.path_list = path_list(req.url.pathname); req.url.path_list = path_list(req.url.pathname);
req.id = request_id(); req.id = request_id();
req.start = Date.now(); req.start = Date.now();
@ -168,7 +166,6 @@ exp.boot = function(callback) {
// Close the server // Close the server
exp.close = function(callback) { exp.close = function(callback) {
helpers.stoplog();
server.close(callback); server.close(callback);
}; };

1812
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "crafatar", "name": "crafatar",
"version": "2.1.5", "version": "2.1.4",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "node www.js", "start": "node www.js",

View File

@ -88,8 +88,8 @@ describe("Crafatar", function() {
assert.strictEqual(helpers.id_valid("1DCEF164FF0A47F2B9A691385C774EE7"), true); assert.strictEqual(helpers.id_valid("1DCEF164FF0A47F2B9A691385C774EE7"), true);
done(); done();
}); });
it("dashed uuid is not valid", function(done) { it("dashed uuid is valid", function(done) {
assert.strictEqual(helpers.id_valid("0098cb60-fa8e-427c-b299-793cbd302c9a"), false); assert.strictEqual(helpers.id_valid("0098cb60-fa8e-427c-b299-793cbd302c9a"), true);
done(); done();
}); });
it("username is invalid", function(done) { it("username is invalid", function(done) {
@ -158,7 +158,7 @@ describe("Crafatar", function() {
it("should time out on skin download", function(done) { it("should time out on skin download", function(done) {
var original_timeout = config.http_timeout; var original_timeout = config.http_timeout;
config.server.http_timeout = 1; config.server.http_timeout = 1;
networking.get_from(rid(), config.endpoints.textures_url + "477be35554684c28bdeee4cf11c591d3c88afb77e0b98da893fd7bc318c65184", function(body, res, error) { networking.get_from(rid(), "http://textures.minecraft.net/texture/477be35554684c28bdeee4cf11c591d3c88afb77e0b98da893fd7bc318c65184", function(body, res, error) {
assert.notStrictEqual(["ETIMEDOUT", "ESOCKETTIMEDOUT"].indexOf(error.code), -1); assert.notStrictEqual(["ETIMEDOUT", "ESOCKETTIMEDOUT"].indexOf(error.code), -1);
config.server.http_timeout = original_timeout; config.server.http_timeout = original_timeout;
done(); done();
@ -166,7 +166,7 @@ describe("Crafatar", function() {
}); });
it("should not find the skin", function(done) { it("should not find the skin", function(done) {
assert.doesNotThrow(function() { assert.doesNotThrow(function() {
networking.get_from(rid(), config.endpoints.textures_url + "this-does-not-exist", function(img, response, err) { networking.get_from(rid(), "http://textures.minecraft.net/texture/this-does-not-exist", function(img, response, err) {
assert.strictEqual(err, null); // no error here, but it shouldn't throw exceptions assert.strictEqual(err, null); // no error here, but it shouldn't throw exceptions
done(); done();
}); });
@ -300,10 +300,6 @@ describe("Crafatar", function() {
url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16", url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
crc32: [4264176600], crc32: [4264176600],
}, },
"avatar with existing dashed uuid": {
url: "http://localhost:3000/avatars/853c80ef-3c37-49fd-aa49938b674adae6?size=16",
crc32: [4264176600],
},
"avatar with non-existent uuid": { "avatar with non-existent uuid": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16",
crc32: [3348154329], crc32: [3348154329],
@ -315,7 +311,7 @@ describe("Crafatar", function() {
"avatar with non-existent uuid defaulting to uuid": { "avatar with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
redirect: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16", redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
}, },
"avatar with non-existent uuid defaulting to url": { "avatar with non-existent uuid defaulting to url": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=http%3A%2F%2Fexample.com%2FCaseSensitive", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
@ -337,7 +333,7 @@ describe("Crafatar", function() {
"overlay avatar with non-existent uuid defaulting to uuid": { "overlay avatar with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
redirect: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16", redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
}, },
"overlay avatar with non-existent uuid defaulting to url": { "overlay avatar with non-existent uuid defaulting to url": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
@ -346,7 +342,7 @@ describe("Crafatar", function() {
}, },
"cape with existing uuid": { "cape with existing uuid": {
url: "http://localhost:3000/capes/853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/capes/853c80ef3c3749fdaa49938b674adae6",
crc32: [985789174, 2099310578], crc32: [985789174],
}, },
"cape with non-existent uuid": { "cape with non-existent uuid": {
url: "http://localhost:3000/capes/00000000000000000000000000000000", url: "http://localhost:3000/capes/00000000000000000000000000000000",
@ -372,7 +368,7 @@ describe("Crafatar", function() {
"skin with non-existent uuid defaulting to uuid": { "skin with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
redirect: "http://localhost:3000/skins/853c80ef3c3749fdaa49938b674adae6?size=16", redirect: "/skins/853c80ef3c3749fdaa49938b674adae6?size=16",
}, },
"skin with non-existent uuid defaulting to url": { "skin with non-existent uuid defaulting to url": {
url: "http://localhost:3000/skins/00000000000000000000000000000000?default=http%3A%2F%2Fexample.com%2FCaseSensitive", url: "http://localhost:3000/skins/00000000000000000000000000000000?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
@ -394,7 +390,7 @@ describe("Crafatar", function() {
"head render with non-existent uuid defaulting to uuid": { "head render with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
redirect: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2", redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2",
}, },
"head render with non-existent uuid defaulting to url": { "head render with non-existent uuid defaulting to url": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive", url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
@ -416,7 +412,7 @@ describe("Crafatar", function() {
"overlay head with non-existent uuid defaulting to uuid": { "overlay head with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
redirect: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay=", redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay=",
}, },
"overlay head render with non-existent uuid defaulting to url": { "overlay head render with non-existent uuid defaulting to url": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive", url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
@ -438,7 +434,7 @@ describe("Crafatar", function() {
"body render with non-existent uuid defaulting to uuid": { "body render with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
redirect: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2", redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2",
}, },
"body render with non-existent uuid defaulting to url": { "body render with non-existent uuid defaulting to url": {
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive", url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
@ -568,30 +564,6 @@ describe("Crafatar", function() {
}); });
}(loc)); }(loc));
} }
it("should return /public resources", function(done) {
request.get("http://localhost:3000/javascript/crafatar.js", function(error, res, body) {
assert.ifError(error);
assert.strictEqual(res.statusCode, 200);
done();
});
});
it("should not allow path traversal on /public", function(done) {
request.get("http://localhost:3000/../server.js", function(error, res, body) {
assert.ifError(error);
assert.strictEqual(res.statusCode, 404);
done();
});
});
it("should not allow encoded path traversal on /public", function(done) {
request.get("http://localhost:3000/%2E%2E/server.js", function(error, res, body) {
assert.ifError(error);
assert.strictEqual(res.statusCode, 404);
done();
});
});
}); });
// we have to make sure that we test both a 32x64 and 64x64 skin // we have to make sure that we test both a 32x64 and 64x64 skin