Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/filename-generator/by-site-structure.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ var resourceTypeExtensions = require('../config/resource-ext-by-type');

module.exports = function generateFilename (resource, options) {
var resourceUrl = resource.getUrl();
var host = utils.getHostFromUrl(resourceUrl);
var filePath = utils.getFilepathFromUrl(resourceUrl);
var extension = utils.getFilenameExtension(filePath);

filePath = path.join(host.replace(':', '_'), filePath);

// If we have HTML from 'http://example.com/path' => set 'path/index.html' as filepath
if (resource.isHtml()) {
var htmlExtensions = resourceTypeExtensions[resourceTypes.html];
Expand Down
11 changes: 11 additions & 0 deletions lib/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ function getHashFromUrl (u) {
return url.parse(u).hash || '';
}

/**
* Returns host with port from given url
* Example: http://example.com:8080/some/path/file.js => example.com:8080
* @param {string} u - url
* @returns {string} host with port
*/
function getHostFromUrl (u) {
return url.parse(u).host;
}

/**
* Returns extension for given filepath
* Example: some/path/file.js => .js
Expand Down Expand Up @@ -135,6 +145,7 @@ module.exports = {
getFilepathFromUrl,
getFilenameExtension,
getHashFromUrl,
getHostFromUrl,
shortenFilename,
waitAllFulfilled,
normalizeUrl,
Expand Down
27 changes: 16 additions & 11 deletions test/unit/filename-generator/by-site-structure-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,54 @@ var options = { defaultFilename: 'index.html' };
describe('FilenameGenerator: bySiteStructure', function() {
it('should return the normalized relative path of the resource url', function(){
var r1 = new Resource('http://example.com/some/path/a.png');
bySiteStructureFilenameGenerator(r1, options).should.equalFileSystemPath('some/path/a.png');
bySiteStructureFilenameGenerator(r1, options).should.equalFileSystemPath('example.com/some/path/a.png');

var r2 = new Resource('http://example.com/a.png');
bySiteStructureFilenameGenerator(r2, options).should.equalFileSystemPath('a.png');
bySiteStructureFilenameGenerator(r2, options).should.equalFileSystemPath('example.com/a.png');

var r3 = new Resource('http://example.com/some/path/../images/a.png');
bySiteStructureFilenameGenerator(r3, options).should.equalFileSystemPath('some/images/a.png');
bySiteStructureFilenameGenerator(r3, options).should.equalFileSystemPath('example.com/some/images/a.png');
});

it('should replace the colon, for url with port number', function(){
var r1 = new Resource('http://example.com:8080/some/path/a.png');
bySiteStructureFilenameGenerator(r1, options).should.equalFileSystemPath('example.com_8080/some/path/a.png');
});

it('should add the defaultFilename to the path, for html resources without extension', function(){
var isHtmlMock = sinon.stub().returns(true);

var r1 = new Resource('http://example.com/some/path/');
r1.isHtml = isHtmlMock;
bySiteStructureFilenameGenerator(r1, options).should.equalFileSystemPath('some/path/index.html');
bySiteStructureFilenameGenerator(r1, options).should.equalFileSystemPath('example.com/some/path/index.html');

var r2 = new Resource('http://example.com/some/path');
r2.isHtml = isHtmlMock;
bySiteStructureFilenameGenerator(r2, options).should.equalFileSystemPath('some/path/index.html');
bySiteStructureFilenameGenerator(r2, options).should.equalFileSystemPath('example.com/some/path/index.html');

var r3 = new Resource('http://example.com');
r3.isHtml = isHtmlMock;
bySiteStructureFilenameGenerator(r3, options).should.equalFileSystemPath('index.html');
bySiteStructureFilenameGenerator(r3, options).should.equalFileSystemPath('example.com/index.html');
});

it('should add the defaultFilename to the path, for html resources with wrong extension', function(){
var isHtmlMock = sinon.stub().returns(true);

var r1 = new Resource('http://example.com/some/path/test.com');
r1.isHtml = isHtmlMock;
bySiteStructureFilenameGenerator(r1, options).should.equalFileSystemPath('some/path/test.com/index.html');
bySiteStructureFilenameGenerator(r1, options).should.equalFileSystemPath('example.com/some/path/test.com/index.html');
});

it('should normalize to safe relative paths, without ..', function(){
var r = new Resource('http://example.com/some/path/../../../../images/a.png');
bySiteStructureFilenameGenerator(r, options).should.equalFileSystemPath('images/a.png');
bySiteStructureFilenameGenerator(r, options).should.equalFileSystemPath('example.com/images/a.png');
});

it('should not replace thrice dot in filenames', function() {
// if it replaces them we receive 'some/path/../../../../etc/passwd'
// path.resolve('some/path/../../../../etc/passwd'); = '/etc/passwd' => which is not safe
var r = new Resource('http://example.com/some/path/.../.../.../.../etc/passwd');
bySiteStructureFilenameGenerator(r, options).should.equalFileSystemPath('some/path/.../.../.../.../etc/passwd');
bySiteStructureFilenameGenerator(r, options).should.equalFileSystemPath('example.com/some/path/.../.../.../.../etc/passwd');
});

it('should shorten filename', function() {
Expand All @@ -74,10 +79,10 @@ describe('FilenameGenerator: bySiteStructure', function() {
it('should return decoded filepath', function() {
var r = new Resource('https://developer.mozilla.org/ru/docs/JavaScript_%D1%88%D0%B5%D0%BB%D0%BB%D1%8B');
var filename = bySiteStructureFilenameGenerator(r, options);
filename.should.equalFileSystemPath('ru/docs/JavaScript_шеллы');
filename.should.equalFileSystemPath('developer.mozilla.org/ru/docs/JavaScript_шеллы');

var r2 = new Resource('https://developer.mozilla.org/Hello%20G%C3%BCnter.png');
var filename2 = bySiteStructureFilenameGenerator(r2, options);
filename2.should.equalFileSystemPath('Hello Günter.png');
filename2.should.equalFileSystemPath('developer.mozilla.org/Hello Günter.png');
});
});