forked from mikedeboer/jsDAV
/
fs.js
179 lines (162 loc) · 5.45 KB
/
fs.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
* @package jsDAV
* @subpackage DAV
* @copyright Copyright(c) 2011 Ajax.org B.V. <info AT ajax DOT org>
* @author Mike de Boer <info AT mikedeboer DOT nl>
* @license http://github.com/mikedeboer/jsDAV/blob/master/LICENSE MIT License
*/
"use strict";
var jsDAV = require("./../../../jsdav");
var jsDAV_Server = require("./../../server");
var Fs = require("fs");
var Path = require("path");
var Async = require("asyncjs");
var Util = require("./../../util");
/**
* The Lock manager allows you to handle all file-locks centrally.
*
* This Lock Manager stores all its data in the filesystem. By default it will do
* this in the system"s standard temporary (session) directory,
* but this can be overriden by specifiying an alternative path in the contructor
*/
function jsDAV_Locks_Backend_FS(dataDir) {
this.dataDir = dataDir || jsDAV_Server.DEFAULT_TMPDIR + "/jsdav";
// ensure that the path is there
Async.makePath(this.dataDir, function() {});
}
module.exports = jsDAV_Locks_Backend_FS;
(function() {
this.getFilenameForUri = function(uri) {
return this.dataDir + "/jsdav_" + Util.sha1(uri) + ".locks";
};
/**
* Returns a list of jsDAV_Locks_LockInfo objects
*
* This method should return all the locks for a particular uri, including
* locks that might be set on a parent uri.
*
* @param string uri
* @return array
*/
this.getLocks = function(uri, returnChildLocks, cbgetlocks) {
var lockList = [];
var currentPath = "";
var parts = uri.split("/");
var self = this;
Async.list(parts).each(function(uriPart, next) {
// weird algorithm that can probably be improved, but we're traversing
// the path top down
if (currentPath)
currentPath += "/";
currentPath += uriPart;
self.getData(currentPath, function(err, uriLocks) {
if (err)
return next(err);
var lock, uriLock, j;
var i = 0;
var l = uriLocks.length;
for (; i < l; ++i) {
uriLock = uriLocks[i];
// Unless we're on the leaf of the uri-tree we should ingore
// locks with depth 0
if (uri == currentPath || uriLock.depth !== 0) {
uriLock.uri = currentPath;
lockList.push(uriLock);
}
}
// Checking if we can remove any of these locks
for (j = lockList.length - 1; j >= 0; --j) {
lock = lockList[j];
if (Date.now() > lock.timeout + lock.created)
lockList.splice(j, 1);
}
next();
});
}).end(function(err) {
if (err)
return cbgetlocks(err);
cbgetlocks(null, lockList);
});
};
/**
* Locks a uri
*
* @param string uri
* @param jsDAV_Locks_LockInfo lockInfo
* @return bool
*/
this.lock = function(uri, lockInfo, cblock) {
// We're making the lock timeout 30 minutes
lockInfo.timeout = 1800;
lockInfo.created = Date.now();
var self = this;
this.getLocks(uri, false, function(err, locks) {
if (err)
return cblock(err, false);
for (var lock, i = locks.length - 1; i >= 0; --i) {
lock = locks[i];
if (lock.token === lockInfo.token)
locks.splice(i, 1);
}
locks.push(lockInfo);
self.putData(uri, locks, function(err) {
cblock(err, !!err);
});
});
};
/**
* Removes a lock from a uri
*
* @param string uri
* @param jsDAV_Locks_LockInfo lockInfo
* @return bool
*/
this.unlock = function(uri, lockInfo, cbunlock) {
var self = this;
this.getLocks(uri, false, function(err, locks) {
for (var found = false, lock, i = locks.length - 1; i >= 0; --i) {
lock = locks[i];
if (lock.token === lockInfo.token) {
locks.splice(i, 1);
found = true;
break;
}
}
if (found)
self.putData(uri, locks, end);
else
end();
function end(err) {
cbunlock(err, !!err);
}
});
};
/**
* Returns the stored data for a uri
*
* @param string uri
* @return array
*/
this.getData = function(uri, cbgetdata) {
var path = this.getFilenameForUri(uri);
Path.exists(path, function(exists) {
if (!exists)
return cbgetdata(null, []);
Fs.readFile(path, "utf8", function(err, data) {
cbgetdata(null, (err || !data) ? [] : JSON.parse(data));
});
});
};
/**
* Updates the lock information
*
* @param string uri
* @param array newData
* @return void
*/
this.putData = function(uri, newData, cbputdata) {
var path = this.getFilenameForUri(uri);
// opening up the file, and creating a shared lock
Fs.writeFile(path, JSON.stringify(newData), "utf8", cbputdata);
};
}).call(jsDAV_Locks_Backend_FS.prototype = new jsDAV.jsDAV_Base());