]>
git.immae.eu Git - perso/Immae/Projets/Nodejs/Surfer.git/blob - src/files.js
3 var async
= require('async'),
5 path
= require('path'),
7 debug
= require('debug')('files'),
8 mkdirp
= require('mkdirp'),
9 HttpError
= require('connect-lastmile').HttpError
,
10 HttpSuccess
= require('connect-lastmile').HttpSuccess
;
14 exports
= module
.exports = function (basePath
) {
25 // http://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js
26 function copyFile(source
, target
, cb
) {
30 mkdirp(path
.dirname(target
), function (error
) {
31 if (error
) return cb(error
);
33 var rd
= fs
.createReadStream(source
);
34 rd
.on("error", function(err
) {
38 var wr
= fs
.createWriteStream(target
);
39 wr
.on("error", function(err
) {
43 wr
.on("close", function(ex
) {
58 function createDirectory(targetPath
, callback
) {
59 mkdirp(targetPath
, function (error
) {
60 if (error
) return callback(error
);
65 function isProtected(targetPath
) {
66 return targetPath
.indexOf(getAbsolutePath('_admin')) === 0;
69 function getAbsolutePath(filePath
) {
70 var absoluteFilePath
= path
.resolve(path
.join(gBasePath
, filePath
));
72 if (absoluteFilePath
.indexOf(gBasePath
) !== 0) return null;
73 return absoluteFilePath
;
76 function removeBasePath(filePath
) {
77 return filePath
.slice(gBasePath
.length
);
80 function get(req
, res
, next
) {
81 var filePath
= decodeURIComponent(req
.params
[0]);
82 var absoluteFilePath
= getAbsolutePath(filePath
);
83 if (!absoluteFilePath
) return next(new HttpError(403, 'Path not allowed'));
85 fs
.stat(absoluteFilePath
, function (error
, result
) {
86 if (error
) return next(new HttpError(404, error
));
88 debug('get', absoluteFilePath
);
90 if (!result
.isDirectory() && !result
.isFile()) return next(new HttpError(500, 'unsupported type'));
91 if (result
.isFile()) return res
.download(absoluteFilePath
);
93 async
.map(fs
.readdirSync(absoluteFilePath
), function (filePath
, callback
) {
94 fs
.stat(path
.join(absoluteFilePath
, filePath
), function (error
, result
) {
95 if (error
) return callback(error
);
98 isDirectory: result
.isDirectory(),
99 isFile: result
.isFile(),
103 birthtime: result
.birthtime
,
108 }, function (error
, results
) {
109 if (error
) return next(new HttpError(500, error
));
110 res
.status(222).send({ entries: results
});
115 function post(req
, res
, next
) {
116 var filePath
= decodeURIComponent(req
.params
[0]);
118 if (!(req
.files
&& req
.files
.file
) && !req
.query
.directory
) return next(new HttpError(400, 'missing file or directory'));
119 if ((req
.files
&& req
.files
.file
) && req
.query
.directory
) return next(new HttpError(400, 'either file or directory'));
121 debug('post:', filePath
);
123 var absoluteFilePath
= getAbsolutePath(filePath
);
124 if (!absoluteFilePath
|| isProtected(absoluteFilePath
)) return next(new HttpError(403, 'Path not allowed'));
126 fs
.stat(absoluteFilePath
, function (error
, result
) {
127 if (error
&& error
.code
!== 'ENOENT') return next(new HttpError(500, error
));
129 if (result
&& req
.query
.directory
) return next(new HttpError(409, 'name already exists'));
130 if (result
&& result
.isDirectory()) return next(new HttpError(409, 'cannot post on directories'));
132 if (req
.query
.directory
) {
133 return createDirectory(absoluteFilePath
, function (error
) {
134 if (error
) return next(new HttpError(500, error
));
135 next(new HttpSuccess(201, {}));
137 } else if (!result
|| result
.isFile()) {
138 return copyFile(req
.files
.file
.path
, absoluteFilePath
, function (error
) {
139 if (error
) return next(new HttpError(500, error
));
140 next(new HttpSuccess(201, {}));
144 return next(new HttpError(500, 'unsupported type'));
148 function put(req
, res
, next
) {
149 var oldFilePath
= decodeURIComponent(req
.params
[0]);
151 if (!req
.body
|| !req
.body
.newFilePath
) return next(new HttpError(400, 'missing newFilePath'));
153 var newFilePath
= decodeURIComponent(req
.body
.newFilePath
);
155 debug('put: %s -> %s', oldFilePath
, newFilePath
);
157 var absoluteOldFilePath
= getAbsolutePath(oldFilePath
);
158 if (!absoluteOldFilePath
|| isProtected(absoluteOldFilePath
)) return next(new HttpError(403, 'Path not allowed'));
160 var absoluteNewFilePath
= getAbsolutePath(newFilePath
);
161 if (!absoluteNewFilePath
|| isProtected(absoluteNewFilePath
)) return next(new HttpError(403, 'Path not allowed'));
163 fs
.rename(absoluteOldFilePath
, absoluteNewFilePath
, function (error
) {
164 if (error
) return next (new HttpError(500, error
));
166 debug('put: successful');
168 return next(new HttpSuccess(200, {}));
172 function del(req
, res
, next
) {
173 var filePath
= decodeURIComponent(req
.params
[0]);
174 var recursive
= !!req
.query
.recursive
;
175 var dryRun
= !!req
.query
.dryRun
;
177 var absoluteFilePath
= getAbsolutePath(filePath
);
178 if (!absoluteFilePath
) return next(new HttpError(404, 'Not found'));
180 if (isProtected(absoluteFilePath
)) return next(new HttpError(403, 'Path not allowed'));
182 // absoltueFilePath has to have the base path prepended
183 if (absoluteFilePath
.length
<= gBasePath
.length
) return next(new HttpError(404, 'Not found'));
185 fs
.stat(absoluteFilePath
, function (error
, result
) {
186 if (error
) return next(new HttpError(404, error
));
188 if (result
.isDirectory() && !recursive
) return next(new HttpError(403, 'Is directory'));
190 // add globs to get file listing
191 if (result
.isDirectory()) absoluteFilePath
+= '/**';
193 rm(absoluteFilePath
, { dryRun: dryRun
, force: true }).then(function (result
) {
194 result
= result
.map(removeBasePath
);
195 next(new HttpSuccess(200, { entries: result
}));
196 }, function (error
) {
197 console
.error(error
);
198 next(new HttpError(500, 'Unable to remove'));