pinokiod 3.51.0 → 3.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/kernel/gitconfig_template +3 -1
  2. package/kernel/index.js +65 -43
  3. package/kernel/peer.js +21 -8
  4. package/kernel/router/index.js +10 -10
  5. package/kernel/router/localhost_static_router.js +3 -0
  6. package/kernel/router/peer_static_router.js +1 -0
  7. package/kernel/scripts/git/create +1 -2
  8. package/kernel/scripts/git/push +1 -1
  9. package/package.json +6 -2
  10. package/server/index.js +178 -87
  11. package/server/public/common.js +0 -13
  12. package/server/public/serve/directory.html +106 -0
  13. package/server/public/serve/icons/application_xp.png +0 -0
  14. package/server/public/serve/icons/application_xp_terminal.png +0 -0
  15. package/server/public/serve/icons/box.png +0 -0
  16. package/server/public/serve/icons/cd.png +0 -0
  17. package/server/public/serve/icons/controller.png +0 -0
  18. package/server/public/serve/icons/drive.png +0 -0
  19. package/server/public/serve/icons/film.png +0 -0
  20. package/server/public/serve/icons/folder.png +0 -0
  21. package/server/public/serve/icons/font.png +0 -0
  22. package/server/public/serve/icons/image.png +0 -0
  23. package/server/public/serve/icons/map.png +0 -0
  24. package/server/public/serve/icons/page.png +0 -0
  25. package/server/public/serve/icons/page_add.png +0 -0
  26. package/server/public/serve/icons/page_attach.png +0 -0
  27. package/server/public/serve/icons/page_code.png +0 -0
  28. package/server/public/serve/icons/page_copy.png +0 -0
  29. package/server/public/serve/icons/page_delete.png +0 -0
  30. package/server/public/serve/icons/page_edit.png +0 -0
  31. package/server/public/serve/icons/page_error.png +0 -0
  32. package/server/public/serve/icons/page_excel.png +0 -0
  33. package/server/public/serve/icons/page_find.png +0 -0
  34. package/server/public/serve/icons/page_gear.png +0 -0
  35. package/server/public/serve/icons/page_go.png +0 -0
  36. package/server/public/serve/icons/page_green.png +0 -0
  37. package/server/public/serve/icons/page_key.png +0 -0
  38. package/server/public/serve/icons/page_lightning.png +0 -0
  39. package/server/public/serve/icons/page_link.png +0 -0
  40. package/server/public/serve/icons/page_paintbrush.png +0 -0
  41. package/server/public/serve/icons/page_paste.png +0 -0
  42. package/server/public/serve/icons/page_red.png +0 -0
  43. package/server/public/serve/icons/page_refresh.png +0 -0
  44. package/server/public/serve/icons/page_save.png +0 -0
  45. package/server/public/serve/icons/page_white.png +0 -0
  46. package/server/public/serve/icons/page_white_acrobat.png +0 -0
  47. package/server/public/serve/icons/page_white_actionscript.png +0 -0
  48. package/server/public/serve/icons/page_white_add.png +0 -0
  49. package/server/public/serve/icons/page_white_c.png +0 -0
  50. package/server/public/serve/icons/page_white_camera.png +0 -0
  51. package/server/public/serve/icons/page_white_cd.png +0 -0
  52. package/server/public/serve/icons/page_white_code.png +0 -0
  53. package/server/public/serve/icons/page_white_code_red.png +0 -0
  54. package/server/public/serve/icons/page_white_coldfusion.png +0 -0
  55. package/server/public/serve/icons/page_white_compressed.png +0 -0
  56. package/server/public/serve/icons/page_white_copy.png +0 -0
  57. package/server/public/serve/icons/page_white_cplusplus.png +0 -0
  58. package/server/public/serve/icons/page_white_csharp.png +0 -0
  59. package/server/public/serve/icons/page_white_cup.png +0 -0
  60. package/server/public/serve/icons/page_white_database.png +0 -0
  61. package/server/public/serve/icons/page_white_delete.png +0 -0
  62. package/server/public/serve/icons/page_white_dvd.png +0 -0
  63. package/server/public/serve/icons/page_white_edit.png +0 -0
  64. package/server/public/serve/icons/page_white_error.png +0 -0
  65. package/server/public/serve/icons/page_white_excel.png +0 -0
  66. package/server/public/serve/icons/page_white_find.png +0 -0
  67. package/server/public/serve/icons/page_white_flash.png +0 -0
  68. package/server/public/serve/icons/page_white_freehand.png +0 -0
  69. package/server/public/serve/icons/page_white_gear.png +0 -0
  70. package/server/public/serve/icons/page_white_get.png +0 -0
  71. package/server/public/serve/icons/page_white_go.png +0 -0
  72. package/server/public/serve/icons/page_white_h.png +0 -0
  73. package/server/public/serve/icons/page_white_horizontal.png +0 -0
  74. package/server/public/serve/icons/page_white_key.png +0 -0
  75. package/server/public/serve/icons/page_white_lightning.png +0 -0
  76. package/server/public/serve/icons/page_white_link.png +0 -0
  77. package/server/public/serve/icons/page_white_magnify.png +0 -0
  78. package/server/public/serve/icons/page_white_medal.png +0 -0
  79. package/server/public/serve/icons/page_white_office.png +0 -0
  80. package/server/public/serve/icons/page_white_paint.png +0 -0
  81. package/server/public/serve/icons/page_white_paintbrush.png +0 -0
  82. package/server/public/serve/icons/page_white_paste.png +0 -0
  83. package/server/public/serve/icons/page_white_php.png +0 -0
  84. package/server/public/serve/icons/page_white_picture.png +0 -0
  85. package/server/public/serve/icons/page_white_powerpoint.png +0 -0
  86. package/server/public/serve/icons/page_white_put.png +0 -0
  87. package/server/public/serve/icons/page_white_ruby.png +0 -0
  88. package/server/public/serve/icons/page_white_stack.png +0 -0
  89. package/server/public/serve/icons/page_white_star.png +0 -0
  90. package/server/public/serve/icons/page_white_swoosh.png +0 -0
  91. package/server/public/serve/icons/page_white_text.png +0 -0
  92. package/server/public/serve/icons/page_white_text_width.png +0 -0
  93. package/server/public/serve/icons/page_white_tux.png +0 -0
  94. package/server/public/serve/icons/page_white_vector.png +0 -0
  95. package/server/public/serve/icons/page_white_visualstudio.png +0 -0
  96. package/server/public/serve/icons/page_white_width.png +0 -0
  97. package/server/public/serve/icons/page_white_word.png +0 -0
  98. package/server/public/serve/icons/page_white_world.png +0 -0
  99. package/server/public/serve/icons/page_white_wrench.png +0 -0
  100. package/server/public/serve/icons/page_white_zip.png +0 -0
  101. package/server/public/serve/icons/page_word.png +0 -0
  102. package/server/public/serve/icons/page_world.png +0 -0
  103. package/server/public/serve/style.css +308 -0
  104. package/server/public/style.css +13 -5
  105. package/server/public/urldropdown.css +95 -3
  106. package/server/public/urldropdown.js +245 -23
  107. package/server/serveIndex.js +691 -0
  108. package/server/views/app.ejs +305 -89
  109. package/server/views/connect.ejs +3 -0
  110. package/server/views/container.ejs +2 -1
  111. package/server/views/index.ejs +3 -0
  112. package/server/views/init/index.ejs +3 -0
  113. package/server/views/net.ejs +30 -27
  114. package/server/views/network.ejs +23 -70
  115. package/server/views/screenshots.ejs +3 -0
  116. package/server/views/settings.ejs +3 -0
  117. package/server/views/tools.ejs +3 -0
@@ -0,0 +1,691 @@
1
+ /*!
2
+ * serve-index
3
+ * Copyright(c) 2011 Sencha Inc.
4
+ * Copyright(c) 2011 TJ Holowaychuk
5
+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
6
+ * MIT Licensed
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /**
12
+ * Module dependencies.
13
+ * @private
14
+ */
15
+
16
+ var accepts = require('accepts');
17
+ var createError = require('http-errors');
18
+ var escapeHtml = require('escape-html');
19
+ var fs = require('fs')
20
+ , path = require('path')
21
+ , normalize = path.normalize
22
+ , sep = path.sep
23
+ , extname = path.extname
24
+ , join = path.join;
25
+ var Batch = require('batch');
26
+ var mime = require('mime-types');
27
+ var parseUrl = require('parseurl');
28
+ var resolve = require('path').resolve;
29
+
30
+ /**
31
+ * Module exports.
32
+ * @public
33
+ */
34
+
35
+ module.exports = serveIndex;
36
+
37
+ /*!
38
+ * Icon cache.
39
+ */
40
+
41
+ var cache = {};
42
+
43
+ /*!
44
+ * Default template.
45
+ */
46
+
47
+ var defaultTemplate = join(__dirname, 'public/serve/directory.html');
48
+
49
+ /*!
50
+ * Stylesheet.
51
+ */
52
+
53
+ var defaultStylesheet = join(__dirname, 'public/serve/style.css');
54
+
55
+ /**
56
+ * Media types and the map for content negotiation.
57
+ */
58
+
59
+ var mediaTypes = [
60
+ 'text/html',
61
+ 'text/plain',
62
+ 'application/json'
63
+ ];
64
+
65
+ var mediaType = {
66
+ 'text/html': 'html',
67
+ 'text/plain': 'plain',
68
+ 'application/json': 'json'
69
+ };
70
+
71
+ /**
72
+ * Serve directory listings with the given `root` path.
73
+ *
74
+ * See Readme.md for documentation of options.
75
+ *
76
+ * @param {String} root
77
+ * @param {Object} options
78
+ * @return {Function} middleware
79
+ * @public
80
+ */
81
+
82
+ function serveIndex(root, options) {
83
+ var opts = options || {};
84
+
85
+ // root required
86
+ if (!root) {
87
+ throw new TypeError('serveIndex() root path required');
88
+ }
89
+
90
+ // resolve root to absolute and normalize
91
+ var rootPath = normalize(resolve(root) + sep);
92
+
93
+ var filter = opts.filter;
94
+ var hidden = opts.hidden;
95
+ var icons = opts.icons;
96
+ var stylesheet = opts.stylesheet || defaultStylesheet;
97
+ var theme = opts.theme || "";
98
+ var template = opts.template || defaultTemplate;
99
+ var view = opts.view || 'tiles';
100
+
101
+ return function (req, res, next) {
102
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
103
+ res.statusCode = 'OPTIONS' === req.method ? 200 : 405;
104
+ res.setHeader('Allow', 'GET, HEAD, OPTIONS');
105
+ res.setHeader('Content-Length', '0');
106
+ res.end();
107
+ return;
108
+ }
109
+
110
+ // get dir
111
+ var dir = getRequestedDir(req)
112
+
113
+ // bad request
114
+ if (dir === null) return next(createError(400))
115
+
116
+ // parse URLs
117
+ var originalUrl = parseUrl.original(req);
118
+ var originalDir = decodeURIComponent(originalUrl.pathname);
119
+
120
+ // join / normalize from root dir
121
+ var path = normalize(join(rootPath, dir));
122
+
123
+ // null byte(s), bad request
124
+ if (~path.indexOf('\0')) return next(createError(400));
125
+
126
+ // malicious path
127
+ if ((path + sep).substr(0, rootPath.length) !== rootPath) {
128
+ return next(createError(403));
129
+ }
130
+
131
+ // determine ".." display
132
+ var showUp = normalize(resolve(path) + sep) !== rootPath;
133
+
134
+ // check if we have a directory
135
+ fs.stat(path, function(err, stat){
136
+ if (err && err.code === 'ENOENT') {
137
+ return next();
138
+ }
139
+
140
+ if (err) {
141
+ err.status = err.code === 'ENAMETOOLONG'
142
+ ? 414
143
+ : 500;
144
+ return next(err);
145
+ }
146
+
147
+ if (!stat.isDirectory()) return next();
148
+
149
+ // fetch files
150
+ fs.readdir(path, function(err, files){
151
+ if (err) return next(err);
152
+ if (!hidden) files = removeHidden(files);
153
+ if (filter) files = files.filter(function(filename, index, list) {
154
+ return filter(filename, index, list, path);
155
+ });
156
+ files.sort();
157
+
158
+ // content-negotiation
159
+ var accept = accepts(req);
160
+ var type = accept.type(mediaTypes);
161
+
162
+ // not acceptable
163
+ if (!type) return next(createError(406));
164
+ serveIndex[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template, stylesheet, theme);
165
+ });
166
+ });
167
+ };
168
+ };
169
+
170
+ /**
171
+ * Respond with text/html.
172
+ */
173
+
174
+ serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path, view, template, stylesheet, theme) {
175
+ var render = typeof template !== 'function'
176
+ ? createHtmlRender(template)
177
+ : template
178
+
179
+ if (showUp) {
180
+ files.unshift('..');
181
+ }
182
+
183
+ // stat all files
184
+ stat(path, files, function (err, fileList) {
185
+ if (err) return next(err);
186
+
187
+ // sort file list
188
+ fileList.sort(fileSort);
189
+
190
+ // read stylesheet
191
+ fs.readFile(stylesheet, 'utf8', function (err, style) {
192
+ if (err) return next(err);
193
+
194
+ // create locals for rendering
195
+ var locals = {
196
+ directory: dir,
197
+ displayIcons: Boolean(icons),
198
+ fileList: fileList,
199
+ path: path,
200
+ style: style,
201
+ viewName: view,
202
+ theme,
203
+ };
204
+
205
+ // render html
206
+ render(locals, function (err, body) {
207
+ if (err) return next(err);
208
+ send(res, 'text/html', body)
209
+ });
210
+ });
211
+ });
212
+ };
213
+
214
+ /**
215
+ * Respond with application/json.
216
+ */
217
+
218
+ serveIndex.json = function _json (req, res, files, next, dir, showUp, icons, path) {
219
+ // stat all files
220
+ stat(path, files, function (err, fileList) {
221
+ if (err) return next(err)
222
+
223
+ // sort file list
224
+ fileList.sort(fileSort)
225
+
226
+ // serialize
227
+ var body = JSON.stringify(fileList.map(function (file) {
228
+ return file.name
229
+ }))
230
+
231
+ send(res, 'application/json', body)
232
+ })
233
+ };
234
+
235
+ /**
236
+ * Respond with text/plain.
237
+ */
238
+
239
+ serveIndex.plain = function _plain (req, res, files, next, dir, showUp, icons, path) {
240
+ // stat all files
241
+ stat(path, files, function (err, fileList) {
242
+ if (err) return next(err)
243
+
244
+ // sort file list
245
+ fileList.sort(fileSort)
246
+
247
+ // serialize
248
+ var body = fileList.map(function (file) {
249
+ return file.name
250
+ }).join('\n') + '\n'
251
+
252
+ send(res, 'text/plain', body)
253
+ })
254
+ };
255
+
256
+ /**
257
+ * Map html `files`, returning an html unordered list.
258
+ * @private
259
+ */
260
+
261
+ function createHtmlFileList(files, dir, useIcons, view) {
262
+ var html = '<ul id="files" class="view-' + escapeHtml(view) + '">'
263
+ + (view === 'details' ? (
264
+ '<li class="header">'
265
+ + '<span class="name">Name</span>'
266
+ + '<span class="size">Size</span>'
267
+ + '<span class="date">Modified</span>'
268
+ + '</li>') : '');
269
+
270
+ html += files.map(function (file) {
271
+ var classes = [];
272
+ var isDir = file.stat && file.stat.isDirectory();
273
+ var path = dir.split('/').map(function (c) { return encodeURIComponent(c); });
274
+
275
+ if (useIcons) {
276
+ classes.push('icon');
277
+
278
+ if (isDir) {
279
+ classes.push('icon-directory');
280
+ } else {
281
+ var ext = extname(file.name);
282
+ var icon = iconLookup(file.name);
283
+
284
+ classes.push('icon');
285
+ classes.push('icon-' + ext.substring(1));
286
+
287
+ if (classes.indexOf(icon.className) === -1) {
288
+ classes.push(icon.className);
289
+ }
290
+ }
291
+ }
292
+
293
+ path.push(encodeURIComponent(file.name));
294
+
295
+ var date = file.stat && file.name !== '..'
296
+ ? file.stat.mtime.toLocaleDateString() + ' ' + file.stat.mtime.toLocaleTimeString()
297
+ : '';
298
+ var size = file.stat && !isDir
299
+ ? file.stat.size
300
+ : '';
301
+
302
+ return '<li><a href="'
303
+ + escapeHtml(normalizeSlashes(normalize(path.join('/'))))
304
+ + '" class="' + escapeHtml(classes.join(' ')) + '"'
305
+ + ' title="' + escapeHtml(file.name) + '">'
306
+ + '<span class="name">' + escapeHtml(file.name) + '</span>'
307
+ + '<span class="size">' + escapeHtml(size) + '</span>'
308
+ + '<span class="date">' + escapeHtml(date) + '</span>'
309
+ + '</a></li>';
310
+ }).join('\n');
311
+
312
+ html += '</ul>';
313
+
314
+ return html;
315
+ }
316
+
317
+ /**
318
+ * Create function to render html.
319
+ */
320
+
321
+ function createHtmlRender(template) {
322
+ return function render(locals, callback) {
323
+ // read template
324
+ fs.readFile(template, 'utf8', function (err, str) {
325
+ if (err) return callback(err);
326
+
327
+ var body = str
328
+ .replace(/\{style\}/g, locals.style.concat(iconStyle(locals.fileList, locals.displayIcons)))
329
+ .replace(/\{files\}/g, createHtmlFileList(locals.fileList, locals.directory, locals.displayIcons, locals.viewName))
330
+ .replace(/\{directory\}/g, escapeHtml(locals.directory))
331
+ .replace(/\{theme\}/g, escapeHtml(locals.theme))
332
+ .replace(/\{linked-path\}/g, htmlPath(locals.directory));
333
+
334
+ callback(null, body);
335
+ });
336
+ };
337
+ }
338
+
339
+ /**
340
+ * Sort function for with directories first.
341
+ */
342
+
343
+ function fileSort(a, b) {
344
+ // sort ".." to the top
345
+ if (a.name === '..' || b.name === '..') {
346
+ return a.name === b.name ? 0
347
+ : a.name === '..' ? -1 : 1;
348
+ }
349
+
350
+ return Number(b.stat && b.stat.isDirectory()) - Number(a.stat && a.stat.isDirectory()) ||
351
+ String(a.name).toLocaleLowerCase().localeCompare(String(b.name).toLocaleLowerCase());
352
+ }
353
+
354
+ /**
355
+ * Get the requested directory from request.
356
+ *
357
+ * @param req
358
+ * @return {string}
359
+ * @api private
360
+ */
361
+
362
+ function getRequestedDir (req) {
363
+ try {
364
+ return decodeURIComponent(parseUrl(req).pathname)
365
+ } catch (e) {
366
+ return null
367
+ }
368
+ }
369
+
370
+ /**
371
+ * Map html `dir`, returning a linked path.
372
+ */
373
+
374
+ function htmlPath(dir) {
375
+ var parts = dir.split('/');
376
+ var crumb = new Array(parts.length);
377
+
378
+ for (var i = 0; i < parts.length; i++) {
379
+ var part = parts[i];
380
+
381
+ if (part) {
382
+ parts[i] = encodeURIComponent(part);
383
+ crumb[i] = '<a href="' + escapeHtml(parts.slice(0, i + 1).join('/')) + '">' + escapeHtml(part) + '</a>';
384
+ }
385
+ }
386
+
387
+ return crumb.join(' / ');
388
+ }
389
+
390
+ /**
391
+ * Get the icon data for the file name.
392
+ */
393
+
394
+ function iconLookup(filename) {
395
+ var ext = extname(filename);
396
+
397
+ // try by extension
398
+ if (icons[ext]) {
399
+ return {
400
+ className: 'icon-' + ext.substring(1),
401
+ fileName: icons[ext]
402
+ };
403
+ }
404
+
405
+ var mimetype = mime.lookup(ext);
406
+
407
+ // default if no mime type
408
+ if (mimetype === false) {
409
+ return {
410
+ className: 'icon-default',
411
+ fileName: icons.default
412
+ };
413
+ }
414
+
415
+ // try by mime type
416
+ if (icons[mimetype]) {
417
+ return {
418
+ className: 'icon-' + mimetype.replace('/', '-').replace('+', '_'),
419
+ fileName: icons[mimetype]
420
+ };
421
+ }
422
+
423
+ var suffix = mimetype.split('+')[1];
424
+
425
+ if (suffix && icons['+' + suffix]) {
426
+ return {
427
+ className: 'icon-' + suffix,
428
+ fileName: icons['+' + suffix]
429
+ };
430
+ }
431
+
432
+ var type = mimetype.split('/')[0];
433
+
434
+ // try by type only
435
+ if (icons[type]) {
436
+ return {
437
+ className: 'icon-' + type,
438
+ fileName: icons[type]
439
+ };
440
+ }
441
+
442
+ return {
443
+ className: 'icon-default',
444
+ fileName: icons.default
445
+ };
446
+ }
447
+
448
+ /**
449
+ * Load icon images, return css string.
450
+ */
451
+
452
+ function iconStyle(files, useIcons) {
453
+ if (!useIcons) return '';
454
+ var i;
455
+ var list = [];
456
+ var rules = {};
457
+ var selector;
458
+ var selectors = {};
459
+ var style = '';
460
+
461
+ for (i = 0; i < files.length; i++) {
462
+ var file = files[i];
463
+
464
+ var isDir = file.stat && file.stat.isDirectory();
465
+ var icon = isDir
466
+ ? { className: 'icon-directory', fileName: icons.folder }
467
+ : iconLookup(file.name);
468
+ var iconName = icon.fileName;
469
+
470
+ selector = '#files .' + icon.className + ' .name';
471
+
472
+ if (!rules[iconName]) {
473
+ rules[iconName] = 'background-image: url(data:image/png;base64,' + load(iconName) + ');'
474
+ selectors[iconName] = [];
475
+ list.push(iconName);
476
+ }
477
+
478
+ if (selectors[iconName].indexOf(selector) === -1) {
479
+ selectors[iconName].push(selector);
480
+ }
481
+ }
482
+
483
+ for (i = 0; i < list.length; i++) {
484
+ iconName = list[i];
485
+ style += selectors[iconName].join(',\n') + ' {\n ' + rules[iconName] + '\n}\n';
486
+ }
487
+
488
+ return style;
489
+ }
490
+
491
+ /**
492
+ * Load and cache the given `icon`.
493
+ *
494
+ * @param {String} icon
495
+ * @return {String}
496
+ * @api private
497
+ */
498
+
499
+ function load(icon) {
500
+ if (cache[icon]) return cache[icon];
501
+ return cache[icon] = fs.readFileSync(__dirname + '/public/serve/icons/' + icon, 'base64');
502
+ }
503
+
504
+ /**
505
+ * Normalizes the path separator from system separator
506
+ * to URL separator, aka `/`.
507
+ *
508
+ * @param {String} path
509
+ * @return {String}
510
+ * @api private
511
+ */
512
+
513
+ function normalizeSlashes(path) {
514
+ return path.split(sep).join('/');
515
+ };
516
+
517
+ /**
518
+ * Filter "hidden" `files`, aka files
519
+ * beginning with a `.`.
520
+ *
521
+ * @param {Array} files
522
+ * @return {Array}
523
+ * @api private
524
+ */
525
+
526
+ function removeHidden(files) {
527
+ return files.filter(function(file){
528
+ return file[0] !== '.'
529
+ });
530
+ }
531
+
532
+ /**
533
+ * Send a response.
534
+ * @private
535
+ */
536
+
537
+ function send (res, type, body) {
538
+ // security header for content sniffing
539
+ res.setHeader('X-Content-Type-Options', 'nosniff')
540
+
541
+ // standard headers
542
+ res.setHeader('Content-Type', type + '; charset=utf-8')
543
+ res.setHeader('Content-Length', Buffer.byteLength(body, 'utf8'))
544
+
545
+ // body
546
+ res.end(body, 'utf8')
547
+ }
548
+
549
+ /**
550
+ * Stat all files and return array of objects in the form
551
+ * `{ name, stat }`.
552
+ *
553
+ * @param {Array} files
554
+ * @return {Array}
555
+ * @api private
556
+ */
557
+
558
+ function stat(dir, files, cb) {
559
+ var batch = new Batch();
560
+
561
+ batch.concurrency(10);
562
+
563
+ files.forEach(function(file){
564
+ batch.push(function(done){
565
+ fs.stat(join(dir, file), function(err, stat){
566
+ if (err && err.code !== 'ENOENT') return done(err);
567
+
568
+ // pass ENOENT as null stat, not error
569
+ done(null, {
570
+ name: file,
571
+ stat: stat || null
572
+ })
573
+ });
574
+ });
575
+ });
576
+
577
+ batch.end(cb);
578
+ }
579
+
580
+ /**
581
+ * Icon map.
582
+ */
583
+
584
+ var icons = {
585
+ // base icons
586
+ 'default': 'page_white.png',
587
+ 'folder': 'folder.png',
588
+
589
+ // generic mime type icons
590
+ 'font': 'font.png',
591
+ 'image': 'image.png',
592
+ 'text': 'page_white_text.png',
593
+ 'video': 'film.png',
594
+
595
+ // generic mime suffix icons
596
+ '+json': 'page_white_code.png',
597
+ '+xml': 'page_white_code.png',
598
+ '+zip': 'box.png',
599
+
600
+ // specific mime type icons
601
+ 'application/javascript': 'page_white_code_red.png',
602
+ 'application/json': 'page_white_code.png',
603
+ 'application/msword': 'page_white_word.png',
604
+ 'application/pdf': 'page_white_acrobat.png',
605
+ 'application/postscript': 'page_white_vector.png',
606
+ 'application/rtf': 'page_white_word.png',
607
+ 'application/vnd.ms-excel': 'page_white_excel.png',
608
+ 'application/vnd.ms-powerpoint': 'page_white_powerpoint.png',
609
+ 'application/vnd.oasis.opendocument.presentation': 'page_white_powerpoint.png',
610
+ 'application/vnd.oasis.opendocument.spreadsheet': 'page_white_excel.png',
611
+ 'application/vnd.oasis.opendocument.text': 'page_white_word.png',
612
+ 'application/x-7z-compressed': 'box.png',
613
+ 'application/x-sh': 'application_xp_terminal.png',
614
+ 'application/x-msaccess': 'page_white_database.png',
615
+ 'application/x-shockwave-flash': 'page_white_flash.png',
616
+ 'application/x-sql': 'page_white_database.png',
617
+ 'application/x-tar': 'box.png',
618
+ 'application/x-xz': 'box.png',
619
+ 'application/xml': 'page_white_code.png',
620
+ 'application/zip': 'box.png',
621
+ 'image/svg+xml': 'page_white_vector.png',
622
+ 'text/css': 'page_white_code.png',
623
+ 'text/html': 'page_white_code.png',
624
+ 'text/less': 'page_white_code.png',
625
+
626
+ // other, extension-specific icons
627
+ '.accdb': 'page_white_database.png',
628
+ '.apk': 'box.png',
629
+ '.app': 'application_xp.png',
630
+ '.as': 'page_white_actionscript.png',
631
+ '.asp': 'page_white_code.png',
632
+ '.aspx': 'page_white_code.png',
633
+ '.bat': 'application_xp_terminal.png',
634
+ '.bz2': 'box.png',
635
+ '.c': 'page_white_c.png',
636
+ '.cab': 'box.png',
637
+ '.cfm': 'page_white_coldfusion.png',
638
+ '.clj': 'page_white_code.png',
639
+ '.cc': 'page_white_cplusplus.png',
640
+ '.cgi': 'application_xp_terminal.png',
641
+ '.cpp': 'page_white_cplusplus.png',
642
+ '.cs': 'page_white_csharp.png',
643
+ '.db': 'page_white_database.png',
644
+ '.dbf': 'page_white_database.png',
645
+ '.deb': 'box.png',
646
+ '.dll': 'page_white_gear.png',
647
+ '.dmg': 'drive.png',
648
+ '.docx': 'page_white_word.png',
649
+ '.erb': 'page_white_ruby.png',
650
+ '.exe': 'application_xp.png',
651
+ '.fnt': 'font.png',
652
+ '.gam': 'controller.png',
653
+ '.gz': 'box.png',
654
+ '.h': 'page_white_h.png',
655
+ '.ini': 'page_white_gear.png',
656
+ '.iso': 'cd.png',
657
+ '.jar': 'box.png',
658
+ '.java': 'page_white_cup.png',
659
+ '.jsp': 'page_white_cup.png',
660
+ '.lua': 'page_white_code.png',
661
+ '.lz': 'box.png',
662
+ '.lzma': 'box.png',
663
+ '.m': 'page_white_code.png',
664
+ '.map': 'map.png',
665
+ '.msi': 'box.png',
666
+ '.mv4': 'film.png',
667
+ '.pdb': 'page_white_database.png',
668
+ '.php': 'page_white_php.png',
669
+ '.pl': 'page_white_code.png',
670
+ '.pkg': 'box.png',
671
+ '.pptx': 'page_white_powerpoint.png',
672
+ '.psd': 'page_white_picture.png',
673
+ '.py': 'page_white_code.png',
674
+ '.rar': 'box.png',
675
+ '.rb': 'page_white_ruby.png',
676
+ '.rm': 'film.png',
677
+ '.rom': 'controller.png',
678
+ '.rpm': 'box.png',
679
+ '.sass': 'page_white_code.png',
680
+ '.sav': 'controller.png',
681
+ '.scss': 'page_white_code.png',
682
+ '.srt': 'page_white_text.png',
683
+ '.tbz2': 'box.png',
684
+ '.tgz': 'box.png',
685
+ '.tlz': 'box.png',
686
+ '.vb': 'page_white_code.png',
687
+ '.vbs': 'page_white_code.png',
688
+ '.xcf': 'page_white_picture.png',
689
+ '.xlsx': 'page_white_excel.png',
690
+ '.yaws': 'page_white_code.png'
691
+ };