Merge "LOG SQL dump files getting installed"
[sdnc/oam.git] / dgbuilder / dgeflows / node_modules / express / node_modules / etag / index.js
1 /*!
2  * etag
3  * Copyright(c) 2014 Douglas Christopher Wilson
4  * MIT Licensed
5  */
6
7 /**
8  * Module exports.
9  */
10
11 module.exports = etag
12
13 /**
14  * Module dependencies.
15  */
16
17 var crc = require('crc').crc32
18 var crypto = require('crypto')
19 var Stats = require('fs').Stats
20
21 /**
22  * Module variables.
23  */
24
25 var crc32threshold = 1000 // 1KB
26 var NULL = new Buffer([0])
27 var toString = Object.prototype.toString
28
29 /**
30  * Create a simple ETag.
31  *
32  * @param {string|Buffer|Stats} entity
33  * @param {object} [options]
34  * @param {boolean} [options.weak]
35  * @return {String}
36  * @api public
37  */
38
39 function etag(entity, options) {
40   if (entity == null) {
41     throw new TypeError('argument entity is required')
42   }
43
44   var isStats = isstats(entity)
45   var weak = options && typeof options.weak === 'boolean'
46     ? options.weak
47     : isStats
48
49   // support fs.Stats object
50   if (isStats) {
51     return stattag(entity, weak)
52   }
53
54   if (typeof entity !== 'string' && !Buffer.isBuffer(entity)) {
55     throw new TypeError('argument entity must be string, Buffer, or fs.Stats')
56   }
57
58   var hash = weak
59     ? weakhash(entity)
60     : stronghash(entity)
61
62   return weak
63     ? 'W/"' + hash + '"'
64     : '"' + hash + '"'
65 }
66
67 /**
68  * Determine if object is a Stats object.
69  *
70  * @param {object} obj
71  * @return {boolean}
72  * @api private
73  */
74
75 function isstats(obj) {
76   // not even an object
77   if (obj === null || typeof obj !== 'object') {
78     return false
79   }
80
81   // genuine fs.Stats
82   if (obj instanceof Stats) {
83     return true
84   }
85
86   // quack quack
87   return 'atime' in obj && toString.call(obj.atime) === '[object Date]'
88     && 'ctime' in obj && toString.call(obj.ctime) === '[object Date]'
89     && 'mtime' in obj && toString.call(obj.mtime) === '[object Date]'
90     && 'ino' in obj && typeof obj.ino === 'number'
91     && 'size' in obj && typeof obj.size === 'number'
92 }
93
94 /**
95  * Generate a tag for a stat.
96  *
97  * @param {Buffer} entity
98  * @return {String}
99  * @api private
100  */
101
102 function stattag(stat, weak) {
103   var mtime = stat.mtime.toISOString()
104   var size = stat.size.toString(16)
105
106   if (weak) {
107     return 'W/"' + size + '-' + crc(mtime) + '"'
108   }
109
110   var hash = crypto
111     .createHash('md5')
112     .update('file', 'utf8')
113     .update(NULL)
114     .update(size, 'utf8')
115     .update(NULL)
116     .update(mtime, 'utf8')
117     .digest('base64')
118
119   return '"' + hash + '"'
120 }
121
122 /**
123  * Generate a strong hash.
124  *
125  * @param {Buffer} entity
126  * @return {String}
127  * @api private
128  */
129
130 function stronghash(entity) {
131   if (entity.length === 0) {
132     // fast-path empty
133     return '1B2M2Y8AsgTpgAmY7PhCfg=='
134   }
135
136   return crypto
137     .createHash('md5')
138     .update(entity, 'utf8')
139     .digest('base64')
140 }
141
142 /**
143  * Generate a weak hash.
144  *
145  * @param {Buffer} entity
146  * @return {String}
147  * @api private
148  */
149
150 function weakhash(entity) {
151   if (entity.length === 0) {
152     // fast-path empty
153     return '0-0'
154   }
155
156   var len = typeof entity === 'string'
157     ? Buffer.byteLength(entity, 'utf8')
158     : entity.length
159
160   if (len <= crc32threshold) {
161     // crc32 plus length when it's fast
162     // crc(str) only accepts utf-8 encoding
163     return len.toString(16) + '-' + crc(entity).toString(16)
164   }
165
166   // use md4 for long strings
167   return crypto
168     .createHash('md4')
169     .update(entity, 'utf8')
170     .digest('base64')
171 }