UNPKG

5.38 kBJavaScriptView Raw
1/*jslint node: true, nomen: true, esversion: 6 */
2"use strict";
3
4const assert = require('assert');
5const Mime = require('mime');
6const fs = require('fs');
7const Path = require('path');
8const Async = require('async');
9const debug = require('debug')('upnpserver:contentProviders:File');
10const crypto = require('crypto');
11
12const logger = require('../logger');
13
14const ContentProvider = require('./contentProvider');
15
16const DIRECTORY_MIME_TYPE = "inode/directory";
17
18const CHANGE_PATH_SEPARATOR = (Path.sep !== '/');
19
20const COMPUTE_HASH = false;
21
22class FileContentProvider extends ContentProvider {
23
24 /**
25 *
26 */
27 get isLocalFilesystem() {
28 return true;
29 }
30
31 /**
32 *
33 */
34 readdir(basePath, callback) {
35
36 assert(typeof (basePath) === "string", "Base path is not a string (" +
37 basePath + ")");
38
39 var osPath = basePath;
40 if (CHANGE_PATH_SEPARATOR) {
41 osPath = osPath.replace(/\//g, Path.sep);
42 }
43
44 fs.readdir(osPath, (error, files) => {
45 if (error) {
46 return callback(error);
47 }
48
49 for (var i = 0; i < files.length; i++) {
50 files[i] = this.newURL(basePath + '/' + files[i]);
51 }
52
53 debug("readdir", "returns basePath=", basePath, "=>", files);
54
55 callback(null, files);
56 });
57 }
58
59 /**
60 *
61 */
62 stat(path, callback) {
63 var osPath = path;
64 if (CHANGE_PATH_SEPARATOR) {
65 osPath = osPath.replace(/\//g, Path.sep);
66 }
67
68 fs.stat(osPath, (error, stats) => {
69 if (error) {
70 return callback(error);
71 }
72
73 var reg=/\/([^\/]+)$/.exec(path);
74 if (reg) {
75 stats.name=reg[1];
76 }
77
78 if (stats.isDirectory()) {
79 stats.mimeType = DIRECTORY_MIME_TYPE;
80
81 return callback(null, stats);
82 }
83
84 var mimeType = Mime.lookup(path, "");
85 stats.mimeType = mimeType;
86
87 if (!COMPUTE_HASH) {
88 return callback(null, stats);
89 }
90
91 this.computeHash(path, stats, (error, hash) => {
92
93 stats.sha256 = hash;
94
95 callback(null, stats);
96 });
97 });
98 }
99
100 _mkdir(osPath, callback) {
101 debug("_mkdir", "path=",osPath);
102
103 fs.access(osPath, fs.R_OK | fs.W_OK, (error) => {
104 if (error) {
105 console.log("_mkdir", "parent=",osPath,"access problem=",error);
106
107 if (error.code==='ENOENT') {
108 var parent=Path.dirname(osPath);
109
110 this._mkdir(parent, (error) => {
111 if (error) {
112 return callback(error);
113 }
114
115 fs.mkdir(osPath, callback);
116 });
117 return;
118 }
119
120 return callback(error);
121 }
122
123 callback();
124 });
125 }
126
127 /**
128 *
129 */
130 createWriteStream(url, options, callback) {
131 debug("createWriteStream", "Url=",url,"options=",options);
132
133 var osPath = url;
134 if (CHANGE_PATH_SEPARATOR) {
135 osPath = osPath.replace(/\//g, Path.sep);
136 }
137
138 var parent=Path.dirname(osPath);
139
140 this._mkdir(parent, (error) => {
141 if (error) {
142 console.log("createWriteStream", "parent=",parent,"access problem=",error);
143 return callback(error);
144 }
145
146 var stream = fs.createWriteStream(url, options);
147
148 callback(null, stream);
149 });
150 }
151
152 /**
153 *
154 */
155 createReadStream(session, path, options, callback) {
156 debug("createReadStream", "path=",path,"options=",options);
157 assert(path, "Path parameter is null");
158
159 var osPath = path;
160 if (CHANGE_PATH_SEPARATOR) {
161 osPath = osPath.replace(/\//g, Path.sep);
162 }
163
164 options = options || {}; // Fix for Nodejs v4
165
166 var openStream = () => {
167 if (debug.enabled) {
168 debug("createReadStream", "osPath=", osPath, "options=", options);
169 }
170
171 try {
172 var stream = fs.createReadStream(osPath, options);
173
174 if (options && options.fd) {
175 // Disable default destroy callback
176 stream.destroy = () => {
177 };
178 }
179
180 return callback(null, stream);
181
182 } catch (x) {
183 logger.error("Can not access to " + path, x);
184
185 return callback(x);
186 }
187 };
188
189 if (session) {
190 options = options || {};
191 options.flags = 'r';
192 options.autoClose = false;
193
194 if (debug.enabled) {
195 debug("createReadStream", "Has session: path=", osPath, "session.fd=" + session.fd);
196 }
197
198 if (!session.fd) {
199 fs.open(osPath, 'r', (error, fd) => {
200 if (error) {
201 return callback(error);
202 }
203 session.fd = fd;
204 options.fd = fd;
205
206 if (debug.enabled) {
207 debug("createReadStream", "Has session open '" + osPath + "' => session.fd=" +
208 session.fd);
209 }
210
211 openStream();
212 });
213
214 return;
215 }
216
217 options.fd = session.fd;
218 }
219
220 openStream();
221 }
222
223 /**
224 *
225 */
226 end(session, callback) {
227 if (session && session.fd) {
228
229 if (debug.enabled) {
230 debug("Close fd " + session.fd);
231 }
232
233 fs.close(session.fd, (error) => {
234 delete session.fd;
235
236 callback(error);
237 });
238 return;
239 }
240 callback();
241 }
242}
243
244module.exports = FileContentProvider;