Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed bugs relate to prevent copying to itself. #61

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ node_modules
.*.sw[op]
.DS_Store
test/*fixtures/out
test/*fixtures/*_out
test/sub-directory-fixtures/src-symlink
27 changes: 24 additions & 3 deletions lib/ncp.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,33 @@ function ncp (source, dest, options, callback) {

limit = (limit < 1) ? 1 : (limit > 512) ? 512 : limit;

function startsWith(target, source) {
function contains(target, source) {
target = target === null ? '' : String(target);
return target.lastIndexOf(source, 0) === 0;

// if target exists, get the target real path.
if(fs.existsSync(target)){
target = fs.realpathSync(target);
}
source = fs.realpathSync(source);

// the target doesn't start with source path
var containsSource = target.lastIndexOf(source, 0) === 0 ;
if(!containsSource){
return false;
}
// get the part without source path .
var lastStirng = target.slice(source.length);

// target equals with source
if(!lastStirng){
return true;
}

// the target is a chlid of source if the lastString starts with path.sep.
return lastStirng.indexOf(path.sep) === 0;
}

if (startsWith(targetPath, currentPath)) {
if (contains(targetPath, currentPath)) {
return cback(selfCopyError);
}

Expand Down
57 changes: 29 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
{
"name" : "ncp",
"version" : "1.0.0",
"author": "AvianFlu <[email protected]>",
"description" : "Asynchronous recursive file copy utility.",
"bin": {
"ncp": "./bin/ncp"
},
"devDependencies" : {
"mocha": "1.15.x",
"rimraf" : "1.0.x",
"read-dir-files" : "0.0.x"
},
"main": "./lib/ncp.js",
"repository" : {
"type" : "git",
"url" : "https://github.com/AvianFlu/ncp.git"
},
"keywords" : [
"cli",
"copy"
],
"license" : "MIT",
"engine" : {
"node" : ">=0.8"
},
"scripts" : {
"test": "mocha -R spec"
}
"name": "ncp",
"version": "1.0.0",
"author": "AvianFlu <[email protected]>",
"description": "Asynchronous recursive file copy utility.",
"bin": {
"ncp": "./bin/ncp"
},
"devDependencies": {
"mkdirp": "^0.5.0",
"mocha": "1.15.x",
"read-dir-files": "0.0.x",
"rimraf": "1.0.x"
},
"main": "./lib/ncp.js",
"repository": {
"type": "git",
"url": "https://github.com/AvianFlu/ncp.git"
},
"keywords": [
"cli",
"copy"
],
"license": "MIT",
"engine": {
"node": ">=0.8"
},
"scripts": {
"test": "mocha -R spec"
}
}
92 changes: 85 additions & 7 deletions test/ncp.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var assert = require('assert'),
rimraf = require('rimraf'),
readDirFiles = require('read-dir-files'),
util = require('util'),
mkdirp = require('mkdirp'),
ncp = require('../').ncp;


Expand Down Expand Up @@ -194,23 +195,100 @@ describe('ncp', function () {
});
});

describe('sub directory handling', function () {
describe('sub directory handling', function() {
var fixtures = path.join(__dirname, 'sub-directory-fixtures'),
src = path.join(fixtures, 'src'),
out = path.join(fixtures, 'src/out');
out = path.join(fixtures, 'src/out'),
src_out = path.join(fixtures, 'src_out'),
src_symlink = path.join(fixtures, 'src-symlink'),
src_a = path.join(fixtures, 'src/a'),
double_src_before_out = path.join(src, src + '_out'),
double_src_middle_out = path.join(src+ '_out', src );

beforeEach(function (cb) {
rimraf(out, function(){
fs.mkdir(out,cb);
before(function(cb) {
rimraf(out, function() {
fs.mkdirSync(out);
rimraf(src_out, function(e) {
fs.mkdirSync(src_out);
rimraf(double_src_before_out, function() {
mkdirp.sync(double_src_before_out);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The double_src_before_out is similar to C:\source\C:\source_out. So it will block the whole testcase.
double_src_middle_out causes the same issue.

rimraf(double_src_middle_out, function() {
mkdirp.sync(double_src_middle_out);
if (fs.existsSync(src_symlink)) {
fs.unlink(src_symlink, cb);
} else {
cb();
}
});
});
});
});
});

it('returns an error when user copy the parent to itself', function (cb) {
ncp(src, out, function (err) {
it('returns an error when user copies the parent to itself', function(cb) {
ncp(src, out, function(err) {
assert.equal(err.code, 'ESELF');
cb();
});
});

it('copies `src` to `src` itself', function(cb) {
ncp(src, src, function(err) {
assert.equal(err.code, 'ESELF');
cb();
});
});

it('copies `src` to `src/out` and directory `src/out` doesn\'t exists ', function(cb) {
rimraf(out, function() {
ncp(src, out, function(err) {
assert.equal(err.code, 'ESELF');
cb();
});
})
});

it('copies `src` to `src_out` ', function(cb) {
ncp(src, src_out, function(err) {
assert.ok(!err);
cb();
});
});


it('copies `src` to `src-symlink`', function(cb) {
fs.symlinkSync(src, src_symlink);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail in Windows.

ncp(src, src_symlink, function(err) {
assert.equal(err.code, 'ESELF');
cb();
});
});

it('copies file `src/a` to file `src/a` ', function(cb) {
ncp(src_a, src_a, function(err) {
assert.equal(err.code, 'ESELF');
cb();
});
});

it('copies directory `src` to `src`/`src`_out', function(cb){
ncp(src, double_src_before_out, function(err){
assert.equal(err.code, 'ESELF');
cb();
});
});

it('copies directory `src` to `src`_out/`src`', function(cb){
ncp(src, double_src_middle_out, function(err){
assert.ok(!err);
cb();
});
});
// it('copies directory `src/out` to file `src/a` ', function(cb) {
// ncp(src_out, src_a, function(err) {
// assert.ok(!err);
// cb();
// });
// });
});
});