diff --git a/app.js b/app.js
new file mode 100644
index 0000000..f5bfb07
--- /dev/null
+++ b/app.js
@@ -0,0 +1,75 @@
+var express = require('express');
+var bodyParser = require('body-parser')
+var app = express();
+app.locals.pretty = true;
+app.set('view engine', 'jade');
+app.set('views', './views');
+app.use(express.static('public'));
+app.use(bodyParser.urlencoded({ extended: false }))
+app.get('/form_receiver', function(req, res){
+ var title = req.query.title;
+ var description = req.query.description;
+ res.send(title+','+description);
+});
+app.post('/form_receiver',function(req, res){
+ var title = req.body.title;
+ var description = req.body.description;
+ res.send(title+','+description);
+})
+app.get('/form', function(req, res){
+ res.render('form');
+});
+app.get('/topic/:id', function(req, res){
+ var topics = [
+ 'Javascript is ...',
+ 'Nodejs is ...',
+ 'Express is ...'
+ ];
+ var output = `
+ Javascript
+ Nodejs
+ Express
+ ${topics[req.params.id]}
+ `
+ res.send(output);
+})
+app.get('/topic/:id/:mode', function(req, res){
+ res.send(req.params.id+','+req.params.mode)
+})
+app.get('/template', function(req, res){
+ res.render('temp', {time:Date(), _title:'Jade'});
+})
+app.get('/dynamic', function(req, res){
+ var lis = '';
+ for(var i=0; i<5; i++){
+ lis= lis + '
A JavaScript library for arbitrary-precision arithmetic.
+ + ++ See the README on GitHub for a + quick-start introduction. +
+
+ In all examples below, var
and semicolons are not shown, and if a commented-out
+ value is in quotes it means toString
has been called on the preceding expression.
+
BigNumber(value [, base]) ⇒ BigNumber
+ value
0
, ±Infinity
and
+ NaN
.
+ 15
significant digits are
+ considered invalid (if ERRORS
is true) as calling
+ toString
or valueOf
on
+ such numbers may not result in the intended value.
+ console.log( 823456789123456.3 ); // 823456789123456.2+
'0xff'
, are valid, as are
+ string values with the octal and binary prefixs '0o'
and '0b'
.
+ String values in octal literal form without the prefix will be interpreted as
+ decimals, e.g. '011'
is interpreted as 11, not 9.
+ 10
to 36
, lower and/or upper case letters can be
+ used to represent values from 10
to 35
.
+ a-z
represents values from 10
to
+ 35
, A-Z
from 36
to 61
, and
+ $
and _
represent 62
and 63
respectively
+ (this can be changed by editing the ALPHABET
variable near the top of the
+ source file).
+ base
2
to 64
inclusive
+ value
.base
is omitted, or is null
or undefined
, base
+ 10
is assumed.
+ Returns a new instance of a BigNumber object.
+
+ If a base is specified, the value is rounded according to
+ the current DECIMAL_PLACES
and
+ ROUNDING_MODE
configuration.
+
+ See Errors for the treatment of an invalid value
or
+ base
.
+
+x = new BigNumber(9) // '9' +y = new BigNumber(x) // '9' + +// 'new' is optional if ERRORS is false +BigNumber(435.345) // '435.345' + +new BigNumber('5032485723458348569331745.33434346346912144534543') +new BigNumber('4.321e+4') // '43210' +new BigNumber('-735.0918e-430') // '-7.350918e-428' +new BigNumber(Infinity) // 'Infinity' +new BigNumber(NaN) // 'NaN' +new BigNumber('.5') // '0.5' +new BigNumber('+2') // '2' +new BigNumber(-10110100.1, 2) // '-180.5' +new BigNumber(-0b10110100.1) // '-180.5' +new BigNumber('123412421.234324', 5) // '607236.557696' +new BigNumber('ff.8', 16) // '255.5' +new BigNumber('0xff.8') // '255.5'+
+ The following throws 'not a base 2 number'
if
+ ERRORS
is true, otherwise it returns a BigNumber with value
+ NaN
.
+
new BigNumber(9, 2)+
+ The following throws 'number type has more than 15 significant digits'
if
+ errors
is true, otherwise it returns a BigNumber with value
+ 96517860459076820
.
+
new BigNumber(96517860459076817.4395)+
+ The following throws 'not a number'
if ERRORS
+ is true, otherwise it returns a BigNumber with value NaN
.
+
new BigNumber('blurgh')+
+ A value is only rounded by the constructor if a base is specified. +
+BigNumber.config({ DECIMAL_PLACES: 5 }) +new BigNumber(1.23456789) // '1.23456789' +new BigNumber(1.23456789, 10) // '1.23457'+ + + +
The static methods of a BigNumber constructor.
+ + + + +.another([obj]) ⇒ BigNumber constructor
+ obj
: object
+ Returns a new independent BigNumber constructor with configuration as described by
+ obj
(see config
), or with the default
+ configuration if obj
is null
or undefined
.
+
BigNumber.config({ DECIMAL_PLACES: 5 }) +BN = BigNumber.another({ DECIMAL_PLACES: 9 }) + +x = new BigNumber(1) +y = new BN(1) + +x.div(3) // 0.33333 +y.div(3) // 0.333333333 + +// BN = BigNumber.another({ DECIMAL_PLACES: 9 }) is equivalent to: +BN = BigNumber.another() +BN.config({ DECIMAL_PLACES: 9 })+ + + +
config([obj]) ⇒ object
+ obj
: object: an object that contains some or all of the following
+ properties.
+
Configures the 'global' settings for this particular BigNumber constructor.
+Note: the configuration can also be supplied as an argument list, see below.
+DECIMAL_PLACES
0
to 1e+9
inclusive20
+ BigNumber.config({ DECIMAL_PLACES: 5 }) +BigNumber.config(5) // equivalent+
ROUNDING_MODE
0
to 8
inclusive4
(ROUND_HALF_UP
)
+ round
,
+ toExponential
,
+ toFixed
,
+ toFormat
and
+ toPrecision
.
+ BigNumber.config({ ROUNDING_MODE: 0 }) +BigNumber.config(null, BigNumber.ROUND_UP) // equivalent+
EXPONENTIAL_AT
0
to 1e+9
inclusive, or
+ -1e+9
to 0
inclusive, integer
+ 0
to 1e+9
inclusive ][-7, 20]
+ toString
returns exponential notation.
+ [-7, 20]
.
+ BigNumber.config({ EXPONENTIAL_AT: 2 }) +new BigNumber(12.3) // '12.3' e is only 1 +new BigNumber(123) // '1.23e+2' +new BigNumber(0.123) // '0.123' e is only -1 +new BigNumber(0.0123) // '1.23e-2' + +BigNumber.config({ EXPONENTIAL_AT: [-7, 20] }) +new BigNumber(123456789) // '123456789' e is only 8 +new BigNumber(0.000000123) // '1.23e-7' + +// Almost never return exponential notation: +BigNumber.config({ EXPONENTIAL_AT: 1e+9 }) + +// Always return exponential notation: +BigNumber.config({ EXPONENTIAL_AT: 0 })+
EXPONENTIAL_AT
, the toFixed
method
+ will always return a value in normal notation and the toExponential
method
+ will always return a value in exponential form.
+ toString
with a base argument, e.g. toString(10)
, will
+ also always return normal notation.
+ RANGE
1
to 1e+9
inclusive, or
+ -1e+9
to -1
inclusive, integer
+ 1
to 1e+9
inclusive ][-1e+9, 1e+9]
+ Infinity
and underflow to
+ zero occurs.
+ Infinity
and those with a
+ negative exponent of greater magnitude become zero.
+ Infinity
, use [-324, 308]
.
+ BigNumber.config({ RANGE: 500 }) +BigNumber.config().RANGE // [ -500, 500 ] +new BigNumber('9.999e499') // '9.999e+499' +new BigNumber('1e500') // 'Infinity' +new BigNumber('1e-499') // '1e-499' +new BigNumber('1e-500') // '0' + +BigNumber.config({ RANGE: [-3, 4] }) +new BigNumber(99999) // '99999' e is only 4 +new BigNumber(100000) // 'Infinity' e is 5 +new BigNumber(0.001) // '0.01' e is only -3 +new BigNumber(0.0001) // '0' e is -4+
9.999...e+1000000000
.1e-1000000000
.
+ ERRORS
true
, false
, 0
or
+ 1
.true
+ ERRORS
is false, no errors will be thrown.
+ BigNumber.config({ ERRORS: false })
CRYPTO
true
, false
, 0
or
+ 1
.false
+ CRYPTO
is set to true
then the
+ random
method will generate random digits using
+ crypto.getRandomValues
in browsers that support it, or
+ crypto.randomBytes
if using a version of Node.js that supports it.
+ CRYPTO
to true
will fail, and if ERRORS
+ is true
an exception will be thrown.
+ CRYPTO
is false
then the source of randomness used will be
+ Math.random
(which is assumed to generate at least 30
bits of
+ randomness).
+ random
.BigNumber.config({ CRYPTO: true }) +BigNumber.config().CRYPTO // true +BigNumber.random() // 0.54340758610486147524+
MODULO_MODE
0
to 9
inclusive1
(ROUND_DOWN
)
+ a mod n
.q = a / n
, is calculated according to the
+ ROUNDING_MODE
that corresponds to the chosen
+ MODULO_MODE
.
+ r
, is calculated as: r = a - n * q
.Property | Value | Description |
---|---|---|
ROUND_UP | 0 | ++ The remainder is positive if the dividend is negative, otherwise it is negative. + | +
ROUND_DOWN | 1 | +
+ The remainder has the same sign as the dividend. + This uses 'truncating division' and matches the behaviour of JavaScript's + remainder operator % .
+ |
+
ROUND_FLOOR | 3 | +
+ The remainder has the same sign as the divisor. + This matches Python's % operator.
+ |
+
ROUND_HALF_EVEN | 6 | +The IEEE 754 remainder function. | +
EUCLID | 9 | +
+ The remainder is always positive. Euclidian division: + q = sign(n) * floor(a / abs(n))
+ |
+
modulo
.BigNumber.config({ MODULO_MODE: BigNumber.EUCLID }) +BigNumber.config({ MODULO_MODE: 9 }) // equivalent+
POW_PRECISION
0
to 1e+9
inclusive.100
+ 0
, the number of signifcant digits will not be limited.toPower
.BigNumber.config({ POW_PRECISION: 100 })
FORMAT
FORMAT
object configures the format of the string returned by the
+ toFormat
method.
+ FORMAT
object that are
+ recognised, and their default values.
+ FORMAT
object will not be checked for validity. The existing
+ FORMAT
object will simply be replaced by the object that is passed in.
+ Note that all the properties shown below do not have to be included.
+ toFormat
for examples of usage.+BigNumber.config({ + FORMAT: { + // the decimal separator + decimalSeparator: '.', + // the grouping separator of the integer part + groupSeparator: ',', + // the primary grouping size of the integer part + groupSize: 3, + // the secondary grouping size of the integer part + secondaryGroupSize: 0, + // the grouping separator of the fraction part + fractionGroupSeparator: ' ', + // the grouping size of the fraction part + fractionGroupSize: 0 + } +});+
Returns an object with the above properties and their current values.
+
+ If the value to be assigned to any of the above properties is null
or
+ undefined
it is ignored.
+
See Errors for the treatment of invalid values.
++BigNumber.config({ + DECIMAL_PLACES: 40, + ROUNDING_MODE: BigNumber.ROUND_HALF_CEIL, + EXPONENTIAL_AT: [-10, 20], + RANGE: [-500, 500], + ERRORS: true, + CRYPTO: true, + MODULO_MODE: BigNumber.ROUND_FLOOR, + POW_PRECISION: 80, + FORMAT: { + groupSize: 3, + groupSeparator: ' ', + decimalSeparator: ',' + } +}); + +// Alternatively but equivalently (excluding FORMAT): +BigNumber.config( 40, 7, [-10, 20], 500, 1, 1, 3, 80 ) + +obj = BigNumber.config(); +obj.ERRORS // true +obj.RANGE // [-500, 500]+ + + +
.max([arg1 [, arg2, ...]]) ⇒ BigNumber
+
+ arg1
, arg2
, ...: number|string|BigNumber
+ See BigNumber
for further parameter details.
+
+ Returns a BigNumber whose value is the maximum of arg1
,
+ arg2
,... .
+
The argument to this method can also be an array of values.
+The return value is always exact and unrounded.
+x = new BigNumber('3257869345.0378653') +BigNumber.max(4e9, x, '123456789.9') // '4000000000' + +arr = [12, '13', new BigNumber(14)] +BigNumber.max(arr) // '14'+ + + +
.min([arg1 [, arg2, ...]]) ⇒ BigNumber
+
+ arg1
, arg2
, ...: number|string|BigNumber
+ See BigNumber
for further parameter details.
+
+ Returns a BigNumber whose value is the minimum of arg1
,
+ arg2
,... .
+
The argument to this method can also be an array of values.
+The return value is always exact and unrounded.
+x = new BigNumber('3257869345.0378653') +BigNumber.min(4e9, x, '123456789.9') // '123456789.9' + +arr = [2, new BigNumber(-14), '-15.9999', -12] +BigNumber.min(arr) // '-15.9999'+ + + +
.random([dp]) ⇒ BigNumber
+ dp
: number: integer, 0
to 1e+9
inclusive
+ Returns a new BigNumber with a pseudo-random value equal to or greater than 0
and
+ less than 1
.
+
+ The return value will have dp
decimal places (or less if trailing zeros are
+ produced).
+ If dp
is omitted then the number of decimal places will default to the current
+ DECIMAL_PLACES
setting.
+
+ Depending on the value of this BigNumber constructor's
+ CRYPTO
setting and the support for the
+ crypto
object in the host environment, the random digits of the return value are
+ generated by either Math.random
(fastest), crypto.getRandomValues
+ (Web Cryptography API in recent browsers) or crypto.randomBytes
(Node.js).
+
+ If CRYPTO
is true
, i.e. one of the
+ crypto
methods is to be used, the value of a returned BigNumber should be
+ cryptographically-secure and statistically indistinguishable from a random value.
+
BigNumber.config({ DECIMAL_PLACES: 10 }) +BigNumber.random() // '0.4117936847' +BigNumber.random(20) // '0.78193327636914089009'+ + + +
+ The library's enumerated rounding modes are stored as properties of the constructor.
+ (They are not referenced internally by the library itself.)
+
+ Rounding modes 0
to 6
(inclusive) are the same as those of Java's
+ BigDecimal class.
+
Property | +Value | +Description | +
---|---|---|
ROUND_UP | +0 | +Rounds away from zero | +
ROUND_DOWN | +1 | +Rounds towards zero | +
ROUND_CEIL | +2 | +Rounds towards Infinity |
+
ROUND_FLOOR | +3 | +Rounds towards -Infinity |
+
ROUND_HALF_UP | +4 | +
+ Rounds towards nearest neighbour. + If equidistant, rounds away from zero + |
+
ROUND_HALF_DOWN | +5 | +
+ Rounds towards nearest neighbour. + If equidistant, rounds towards zero + |
+
ROUND_HALF_EVEN | +6 | +
+ Rounds towards nearest neighbour. + If equidistant, rounds towards even neighbour + |
+
ROUND_HALF_CEIL | +7 | +
+ Rounds towards nearest neighbour. + If equidistant, rounds towards Infinity
+ |
+
ROUND_HALF_FLOOR | +8 | +
+ Rounds towards nearest neighbour. + If equidistant, rounds towards -Infinity
+ |
+
+BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_CEIL }) +BigNumber.config({ ROUNDING_MODE: 2 }) // equivalent+ + +
The methods inherited by a BigNumber instance from its constructor's prototype object.
+A BigNumber is immutable in the sense that it is not changed by its methods.
+
+ The treatment of ±0
, ±Infinity
and NaN
is
+ consistent with how JavaScript treats these values.
+
+ Many method names have a shorter alias.
+ (Internally, the library always uses the shorter method names.)
+
.abs() ⇒ BigNumber
+ Returns a BigNumber whose value is the absolute value, i.e. the magnitude, of the value of + this BigNumber. +
+The return value is always exact and unrounded.
++x = new BigNumber(-0.8) +y = x.absoluteValue() // '0.8' +z = y.abs() // '0.8'+ + + +
.ceil() ⇒ BigNumber
+ Returns a BigNumber whose value is the value of this BigNumber rounded to
+ a whole number in the direction of positive Infinity
.
+
+x = new BigNumber(1.3) +x.ceil() // '2' +y = new BigNumber(-1.8) +y.ceil() // '-1'+ + + +
.cmp(n [, base]) ⇒ number
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
Returns | |
---|---|
1 |
+ If the value of this BigNumber is greater than the value of n |
+
-1 |
+ If the value of this BigNumber is less than the value of n |
+
0 |
+ If this BigNumber and n have the same value |
+
null |
+ If the value of either this BigNumber or n is NaN |
+
+x = new BigNumber(Infinity) +y = new BigNumber(5) +x.comparedTo(y) // 1 +x.comparedTo(x.minus(1)) // 0 +y.cmp(NaN) // null +y.cmp('110', 2) // -1+ + + +
.dp() ⇒ number
+ Return the number of decimal places of the value of this BigNumber, or null
if
+ the value of this BigNumber is ±Infinity
or NaN
.
+
+x = new BigNumber(123.45) +x.decimalPlaces() // 2 +y = new BigNumber('9.9e-101') +y.dp() // 102+ + + +
.div(n [, base]) ⇒ BigNumber
+
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
+ Returns a BigNumber whose value is the value of this BigNumber divided by
+ n
, rounded according to the current
+ DECIMAL_PLACES
and
+ ROUNDING_MODE
configuration.
+
+x = new BigNumber(355) +y = new BigNumber(113) +x.dividedBy(y) // '3.14159292035398230088' +x.div(5) // '71' +x.div(47, 16) // '5'+ + + +
.divToInt(n [, base]) ⇒
+ BigNumber
+
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
+ Return a BigNumber whose value is the integer part of dividing the value of this BigNumber by
+ n
.
+
+x = new BigNumber(5) +y = new BigNumber(3) +x.dividedToIntegerBy(y) // '1' +x.divToInt(0.7) // '7' +x.divToInt('0.f', 16) // '5'+ + + +
.eq(n [, base]) ⇒ boolean
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
+ Returns true
if the value of this BigNumber equals the value of n
,
+ otherwise returns false
.
+ As with JavaScript, NaN
does not equal NaN
.
+
Note: This method uses the comparedTo
method internally.
+0 === 1e-324 // true +x = new BigNumber(0) +x.equals('1e-324') // false +BigNumber(-0).eq(x) // true ( -0 === 0 ) +BigNumber(255).eq('ff', 16) // true + +y = new BigNumber(NaN) +y.equals(NaN) // false+ + + +
.floor() ⇒ BigNumber
+ Returns a BigNumber whose value is the value of this BigNumber rounded to a whole number in
+ the direction of negative Infinity
.
+
+x = new BigNumber(1.8) +x.floor() // '1' +y = new BigNumber(-1.3) +y.floor() // '-2'+ + + +
.gt(n [, base]) ⇒ boolean
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
+ Returns true
if the value of this BigNumber is greater than the value of
+ n
, otherwise returns false
.
+
Note: This method uses the comparedTo
method internally.
+0.1 > (0.3 - 0.2) // true +x = new BigNumber(0.1) +x.greaterThan(BigNumber(0.3).minus(0.2)) // false +BigNumber(0).gt(x) // false +BigNumber(11, 3).gt(11.1, 2) // true+ + + +
.gte(n [, base]) ⇒ boolean
+
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
+ Returns true
if the value of this BigNumber is greater than or equal to the value
+ of n
, otherwise returns false
.
+
Note: This method uses the comparedTo
method internally.
+(0.3 - 0.2) >= 0.1 // false +x = new BigNumber(0.3).minus(0.2) +x.greaterThanOrEqualTo(0.1) // true +BigNumber(1).gte(x) // true +BigNumber(10, 18).gte('i', 36) // true+ + + +
.isFinite() ⇒ boolean
+ Returns true
if the value of this BigNumber is a finite number, otherwise
+ returns false
.
+
+ The only possible non-finite values of a BigNumber are NaN
, Infinity
+ and -Infinity
.
+
+x = new BigNumber(1) +x.isFinite() // true +y = new BigNumber(Infinity) +y.isFinite() // false+
+ Note: The native method isFinite()
can be used if
+ n <= Number.MAX_VALUE
.
+
.isInt() ⇒ boolean
+ Returns true
if the value of this BigNumber is a whole number, otherwise returns
+ false
.
+
+x = new BigNumber(1) +x.isInteger() // true +y = new BigNumber(123.456) +y.isInt() // false+ + + +
.isNaN() ⇒ boolean
+ Returns true
if the value of this BigNumber is NaN
, otherwise
+ returns false
.
+
+x = new BigNumber(NaN) +x.isNaN() // true +y = new BigNumber('Infinity') +y.isNaN() // false+
Note: The native method isNaN()
can also be used.
.isNeg() ⇒ boolean
+ Returns true
if the value of this BigNumber is negative, otherwise returns
+ false
.
+
+x = new BigNumber(-0) +x.isNegative() // true +y = new BigNumber(2) +y.isNeg() // false+
Note: n < 0
can be used if n <= -Number.MIN_VALUE
.
.isZero() ⇒ boolean
+ Returns true
if the value of this BigNumber is zero or minus zero, otherwise
+ returns false
.
+
+x = new BigNumber(-0) +x.isZero() && x.isNeg() // true +y = new BigNumber(Infinity) +y.isZero() // false+
Note: n == 0
can be used if n >= Number.MIN_VALUE
.
.lt(n [, base]) ⇒ boolean
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
+ Returns true
if the value of this BigNumber is less than the value of
+ n
, otherwise returns false
.
+
Note: This method uses the comparedTo
method internally.
+(0.3 - 0.2) < 0.1 // true +x = new BigNumber(0.3).minus(0.2) +x.lessThan(0.1) // false +BigNumber(0).lt(x) // true +BigNumber(11.1, 2).lt(11, 3) // true+ + + +
.lte(n [, base]) ⇒ boolean
+
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
+ Returns true
if the value of this BigNumber is less than or equal to the value of
+ n
, otherwise returns false
.
+
Note: This method uses the comparedTo
method internally.
+0.1 <= (0.3 - 0.2) // false +x = new BigNumber(0.1) +x.lessThanOrEqualTo(BigNumber(0.3).minus(0.2)) // true +BigNumber(-1).lte(x) // true +BigNumber(10, 18).lte('i', 36) // true+ + + +
.minus(n [, base]) ⇒ BigNumber
+
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
Returns a BigNumber whose value is the value of this BigNumber minus n
.
The return value is always exact and unrounded.
++0.3 - 0.1 // 0.19999999999999998 +x = new BigNumber(0.3) +x.minus(0.1) // '0.2' +x.minus(0.6, 20) // '0'+ + + +
.mod(n [, base]) ⇒ BigNumber
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
+ Returns a BigNumber whose value is the value of this BigNumber modulo n
, i.e.
+ the integer remainder of dividing this BigNumber by n
.
+
+ The value returned, and in particular its sign, is dependent on the value of the
+ MODULO_MODE
setting of this BigNumber constructor.
+ If it is 1
(default value), the result will have the same sign as this BigNumber,
+ and it will match that of Javascript's %
operator (within the limits of double
+ precision) and BigDecimal's remainder
method.
+
The return value is always exact and unrounded.
+
+ See MODULO_MODE
for a description of the other
+ modulo modes.
+
+1 % 0.9 // 0.09999999999999998 +x = new BigNumber(1) +x.modulo(0.9) // '0.1' +y = new BigNumber(33) +y.mod('a', 33) // '3'+ + + +
.neg() ⇒ BigNumber
+ Returns a BigNumber whose value is the value of this BigNumber negated, i.e. multiplied by
+ -1
.
+
+x = new BigNumber(1.8) +x.negated() // '-1.8' +y = new BigNumber(-1.3) +y.neg() // '1.3'+ + + +
.plus(n [, base]) ⇒ BigNumber
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
Returns a BigNumber whose value is the value of this BigNumber plus n
.
The return value is always exact and unrounded.
++0.1 + 0.2 // 0.30000000000000004 +x = new BigNumber(0.1) +y = x.plus(0.2) // '0.3' +BigNumber(0.7).plus(x).plus(y) // '1' +x.plus('0.1', 8) // '0.225'+ + + +
.sd([z]) ⇒ number
+ z
: boolean|number: true
, false
, 0
+ or 1
+
Returns the number of significant digits of the value of this BigNumber.
+
+ If z
is true
or 1
then any trailing zeros of the
+ integer part of a number are counted as significant digits, otherwise they are not.
+
+x = new BigNumber(1.234) +x.precision() // 4 +y = new BigNumber(987000) +y.sd() // 3 +y.sd(true) // 6+ + + +
.round([dp [, rm]]) ⇒ BigNumber
+ dp
: number: integer, 0
to 1e+9
inclusive
+ rm
: number: integer, 0
to 8
inclusive
+
+ Returns a BigNumber whose value is the value of this BigNumber rounded by rounding mode
+ rm
to a maximum of dp
decimal places.
+
+ if dp
is omitted, or is null
or undefined
, the
+ return value is n
rounded to a whole number.
+ if rm
is omitted, or is null
or undefined
,
+ ROUNDING_MODE
is used.
+
+ See Errors for the treatment of other non-integer or out of range
+ dp
or rm
values.
+
+x = 1234.56 +Math.round(x) // 1235 + +y = new BigNumber(x) +y.round() // '1235' +y.round(1) // '1234.6' +y.round(2) // '1234.56' +y.round(10) // '1234.56' +y.round(0, 1) // '1234' +y.round(0, 6) // '1235' +y.round(1, 1) // '1234.5' +y.round(1, BigNumber.ROUND_HALF_EVEN) // '1234.6' +y // '1234.56'+ + + +
.shift(n) ⇒ BigNumber
+ n
: number: integer,
+ -9007199254740991
to 9007199254740991
inclusive
+
+ Returns a BigNumber whose value is the value of this BigNumber shifted n
places.
+
+ The shift is of the decimal point, i.e. of powers of ten, and is to the left if n
+ is negative or to the right if n
is positive.
+
The return value is always exact and unrounded.
++x = new BigNumber(1.23) +x.shift(3) // '1230' +x.shift(-3) // '0.00123'+ + + +
.sqrt() ⇒ BigNumber
+ Returns a BigNumber whose value is the square root of the value of this BigNumber,
+ rounded according to the current
+ DECIMAL_PLACES
and
+ ROUNDING_MODE
configuration.
+
+ The return value will be correctly rounded, i.e. rounded as if the result was first calculated + to an infinite number of correct digits before rounding. +
++x = new BigNumber(16) +x.squareRoot() // '4' +y = new BigNumber(3) +y.sqrt() // '1.73205080756887729353'+ + + +
.times(n [, base]) ⇒ BigNumber
+ n
: number|string|BigNumber
+ base
: number
+ See BigNumber for further parameter details.
+
Returns a BigNumber whose value is the value of this BigNumber times n
.
The return value is always exact and unrounded.
++0.6 * 3 // 1.7999999999999998 +x = new BigNumber(0.6) +y = x.times(3) // '1.8' +BigNumber('7e+500').times(y) // '1.26e+501' +x.times('-a', 16) // '-6'+ + + +
.toDigits([sd [, rm]]) ⇒ BigNumber
+
+ sd
: number: integer, 1
to 1e+9
inclusive.
+ rm
: number: integer, 0
to 8
inclusive.
+
+ Returns a BigNumber whose value is the value of this BigNumber rounded to sd
+ significant digits using rounding mode rm
.
+
+ If sd
is omitted or is null
or undefined
, the return
+ value will not be rounded.
+ If rm
is omitted or is null
or undefined
,
+ ROUNDING_MODE
will be used.
+
+ See Errors for the treatment of other non-integer or out of range
+ sd
or rm
values.
+
+BigNumber.config({ precision: 5, rounding: 4 }) +x = new BigNumber(9876.54321) + +x.toSignificantDigits() // '9876.5' +x.toSignificantDigits(6) // '9876.54' +x.toSignificantDigits(6, BigNumber.ROUND_UP) // '9876.55' +x.toSD(2) // '9900' +x.toSD(2, 1) // '9800' +x // '9876.54321'+ + + +
.toExponential([dp [, rm]]) ⇒ string
+
+ dp
: number: integer, 0
to 1e+9
inclusive
+ rm
: number: integer, 0
to 8
inclusive
+
+ Returns a string representing the value of this BigNumber in exponential notation rounded
+ using rounding mode rm
to dp
decimal places, i.e with one digit
+ before the decimal point and dp
digits after it.
+
+ If the value of this BigNumber in exponential notation has fewer than dp
fraction
+ digits, the return value will be appended with zeros accordingly.
+
+ If dp
is omitted, or is null
or undefined
, the number
+ of digits after the decimal point defaults to the minimum number of digits necessary to
+ represent the value exactly.
+ If rm
is omitted or is null
or undefined
,
+ ROUNDING_MODE
is used.
+
+ See Errors for the treatment of other non-integer or out of range
+ dp
or rm
values.
+
+x = 45.6 +y = new BigNumber(x) +x.toExponential() // '4.56e+1' +y.toExponential() // '4.56e+1' +x.toExponential(0) // '5e+1' +y.toExponential(0) // '5e+1' +x.toExponential(1) // '4.6e+1' +y.toExponential(1) // '4.6e+1' +y.toExponential(1, 1) // '4.5e+1' (ROUND_DOWN) +x.toExponential(3) // '4.560e+1' +y.toExponential(3) // '4.560e+1'+ + + +
.toFixed([dp [, rm]]) ⇒ string
+
+ dp
: number: integer, 0
to 1e+9
inclusive
+ rm
: number: integer, 0
to 8
inclusive
+
+ Returns a string representing the value of this BigNumber in normal (fixed-point) notation
+ rounded to dp
decimal places using rounding mode rm
.
+
+ If the value of this BigNumber in normal notation has fewer than dp
fraction
+ digits, the return value will be appended with zeros accordingly.
+
+ Unlike Number.prototype.toFixed
, which returns exponential notation if a number
+ is greater or equal to 1021
, this method will always return normal
+ notation.
+
+ If dp
is omitted or is null
or undefined
, the return
+ value will be unrounded and in normal notation. This is also unlike
+ Number.prototype.toFixed
, which returns the value to zero decimal places.
+ It is useful when fixed-point notation is required and the current
+ EXPONENTIAL_AT
setting causes
+ toString
to return exponential notation.
+ If rm
is omitted or is null
or undefined
,
+ ROUNDING_MODE
is used.
+
+ See Errors for the treatment of other non-integer or out of range
+ dp
or rm
values.
+
+x = 3.456 +y = new BigNumber(x) +x.toFixed() // '3' +y.toFixed() // '3.456' +y.toFixed(0) // '3' +x.toFixed(2) // '3.46' +y.toFixed(2) // '3.46' +y.toFixed(2, 1) // '3.45' (ROUND_DOWN) +x.toFixed(5) // '3.45600' +y.toFixed(5) // '3.45600'+ + + +
.toFormat([dp [, rm]]) ⇒ string
+
+ dp
: number: integer, 0
to 1e+9
inclusive
+ rm
: number: integer, 0
to 8
inclusive
+
+
+ Returns a string representing the value of this BigNumber in normal (fixed-point) notation
+ rounded to dp
decimal places using rounding mode rm
, and formatted
+ according to the properties of the FORMAT
object.
+
+ See the examples below for the properties of the
+ FORMAT
object, their types and their usage.
+
+ If dp
is omitted or is null
or undefined
, then the
+ return value is not rounded to a fixed number of decimal places.
+ If rm
is omitted or is null
or undefined
,
+ ROUNDING_MODE
is used.
+
+ See Errors for the treatment of other non-integer or out of range
+ dp
or rm
values.
+
+format = { + decimalSeparator: '.', + groupSeparator: ',', + groupSize: 3, + secondaryGroupSize: 0, + fractionGroupSeparator: ' ', + fractionGroupSize: 0 +} +BigNumber.config({ FORMAT: format }) + +x = new BigNumber('123456789.123456789') +x.toFormat() // '123,456,789.123456789' +x.toFormat(1) // '123,456,789.1' + +// If a reference to the object assigned to FORMAT has been retained, +// the format properties can be changed directly +format.groupSeparator = ' ' +format.fractionGroupSize = 5 +x.toFormat() // '123 456 789.12345 6789' + +BigNumber.config({ + FORMAT: { + decimalSeparator = ',', + groupSeparator = '.', + groupSize = 3, + secondaryGroupSize = 2 + } +}) + +x.toFormat(6) // '12.34.56.789,123'+ + + +
.toFraction([max]) ⇒ [string, string]
+
+ max
: number|string|BigNumber: integer >= 1
and <
+ Infinity
+
+ Returns a string array representing the value of this BigNumber as a simple fraction with an
+ integer numerator and an integer denominator. The denominator will be a positive non-zero
+ value less than or equal to max
.
+
+ If a maximum denominator, max
, is not specified, or is null
or
+ undefined
, the denominator will be the lowest value necessary to represent the
+ number exactly.
+
+ See Errors for the treatment of other non-integer or out of range
+ max
values.
+
+x = new BigNumber(1.75) +x.toFraction() // '7, 4' + +pi = new BigNumber('3.14159265358') +pi.toFraction() // '157079632679,50000000000' +pi.toFraction(100000) // '312689, 99532' +pi.toFraction(10000) // '355, 113' +pi.toFraction(100) // '311, 99' +pi.toFraction(10) // '22, 7' +pi.toFraction(1) // '3, 1'+ + + +
.toJSON() ⇒ string
As valueOf
.
+x = new BigNumber('177.7e+457') +y = new BigNumber(235.4325) +z = new BigNumber('0.0098074') + +// Serialize an array of three BigNumbers +str = JSON.stringify( [x, y, z] ) +// "["1.777e+459","235.4325","0.0098074"]" + +// Return an array of three BigNumbers +JSON.parse(str, function (key, val) { + return key === '' ? val : new BigNumber(val) +})+ + + +
.toNumber() ⇒ number
Returns the value of this BigNumber as a JavaScript number primitive.
++ Type coercion with, for example, the unary plus operator will also work, except that a + BigNumber with the value minus zero will be converted to positive zero. +
++x = new BigNumber(456.789) +x.toNumber() // 456.789 ++x // 456.789 + +y = new BigNumber('45987349857634085409857349856430985') +y.toNumber() // 4.598734985763409e+34 + +z = new BigNumber(-0) +1 / +z // Infinity +1 / z.toNumber() // -Infinity+ + + +
.pow(n [, m]) ⇒ BigNumber
+ n
: number: integer,
+ -9007199254740991
to 9007199254740991
inclusive
+ m
: number|string|BigNumber
+
+ Returns a BigNumber whose value is the value of this BigNumber raised to the power
+ n
, and optionally modulo a modulus m
.
+
+ If n
is negative the result is rounded according to the current
+ DECIMAL_PLACES
and
+ ROUNDING_MODE
configuration.
+
+ If n
is not an integer or is out of range:
+
+ If ERRORS
is true
a BigNumber Error is thrown,
+ else if n
is greater than 9007199254740991
, it is interpreted as
+ Infinity
;
+ else if n
is less than -9007199254740991
, it is interpreted as
+ -Infinity
;
+ else if n
is otherwise a number, it is truncated to an integer;
+ else it is interpreted as NaN
.
+
+ As the number of digits of the result of the power operation can grow so large so quickly,
+ e.g. 123.45610000 has over 50000
digits, the number of significant
+ digits calculated is limited to the value of the
+ POW_PRECISION
setting (default value:
+ 100
) unless a modulus m
is specified.
+
+ Set POW_PRECISION
to 0
for an
+ unlimited number of significant digits to be calculated (this will cause the method to slow
+ dramatically for larger exponents).
+
+ Negative exponents will be calculated to the number of decimal places specified by
+ DECIMAL_PLACES
(but not to more than
+ POW_PRECISION
significant digits).
+
+ If m
is specified and the value of m
, n
and this
+ BigNumber are positive integers, then a fast modular exponentiation algorithm is used,
+ otherwise if any of the values is not a positive integer the operation will simply be
+ performed as x.toPower(n).modulo(m)
with a
+ POW_PRECISION
of 0
.
+
+Math.pow(0.7, 2) // 0.48999999999999994 +x = new BigNumber(0.7) +x.toPower(2) // '0.49' +BigNumber(3).pow(-2) // '0.11111111111111111111'+ + + +
.toPrecision([sd [, rm]]) ⇒ string
+
+ sd
: number: integer, 1
to 1e+9
inclusive
+ rm
: number: integer, 0
to 8
inclusive
+
+ Returns a string representing the value of this BigNumber rounded to sd
+ significant digits using rounding mode rm
.
+
+ If sd
is less than the number of digits necessary to represent the integer part
+ of the value in normal (fixed-point) notation, then exponential notation is used.
+
+ If sd
is omitted, or is null
or undefined
, then the
+ return value is the same as n.toString()
.
+ If rm
is omitted or is null
or undefined
,
+ ROUNDING_MODE
is used.
+
+ See Errors for the treatment of other non-integer or out of range
+ sd
or rm
values.
+
+x = 45.6 +y = new BigNumber(x) +x.toPrecision() // '45.6' +y.toPrecision() // '45.6' +x.toPrecision(1) // '5e+1' +y.toPrecision(1) // '5e+1' +y.toPrecision(2, 0) // '4.6e+1' (ROUND_UP) +y.toPrecision(2, 1) // '4.5e+1' (ROUND_DOWN) +x.toPrecision(5) // '45.600' +y.toPrecision(5) // '45.600'+ + + +
.toString([base]) ⇒ string
base
: number: integer, 2
to 64
inclusive
+ Returns a string representing the value of this BigNumber in the specified base, or base
+ 10
if base
is omitted or is null
or
+ undefined
.
+
+ For bases above 10
, values from 10
to 35
are
+ represented by a-z
(as with Number.prototype.toString
),
+ 36
to 61
by A-Z
, and 62
and
+ 63
by $
and _
respectively.
+
+ If a base is specified the value is rounded according to the current
+ DECIMAL_PLACES
+ and ROUNDING_MODE
configuration.
+
+ If a base is not specified, and this BigNumber has a positive
+ exponent that is equal to or greater than the positive component of the
+ current EXPONENTIAL_AT
setting,
+ or a negative exponent equal to or less than the negative component of the
+ setting, then exponential notation is returned.
+
If base
is null
or undefined
it is ignored.
+ See Errors for the treatment of other non-integer or out of range
+ base
values.
+
+x = new BigNumber(750000) +x.toString() // '750000' +BigNumber.config({ EXPONENTIAL_AT: 5 }) +x.toString() // '7.5e+5' + +y = new BigNumber(362.875) +y.toString(2) // '101101010.111' +y.toString(9) // '442.77777777777777777778' +y.toString(32) // 'ba.s' + +BigNumber.config({ DECIMAL_PLACES: 4 }); +z = new BigNumber('1.23456789') +z.toString() // '1.23456789' +z.toString(10) // '1.2346'+ + + +
.trunc() ⇒ BigNumber
+ Returns a BigNumber whose value is the value of this BigNumber truncated to a whole number. +
++x = new BigNumber(123.456) +x.truncated() // '123' +y = new BigNumber(-12.3) +y.trunc() // '-12'+ + + +
.valueOf() ⇒ string
+ As toString
, but does not accept a base argument and includes the minus sign
+ for negative zero.
+
+x = new BigNumber('-0') +x.toString() // '0' +x.valueOf() // '-0' +y = new BigNumber('1.777e+457') +y.valueOf() // '1.777e+457'+ + + +
A BigNumber is an object with three properties:
+Property | +Description | +Type | +Value | +
---|---|---|---|
c | +coefficient* | +number[] |
+ Array of base 1e14 numbers |
+
e | +exponent | +number | +Integer, -1000000000 to 1000000000 inclusive |
+
s | +sign | +number | +-1 or 1 |
+
*significand
+The value of any of the three properties may also be null
.
+ From v2.0.0 of this library, the value of the coefficient of a BigNumber is stored in a
+ normalised base 100000000000000
floating point format, as opposed to the base
+ 10
format used in v1.x.x
+
+ This change means the properties of a BigNumber are now best considered to be read-only. + Previously it was acceptable to change the exponent of a BigNumber by writing to its exponent + property directly, but this is no longer recommended as the number of digits in the first + element of the coefficient array is dependent on the exponent, so the coefficient would also + need to be altered. +
++ Note that, as with JavaScript numbers, the original exponent and fractional trailing zeros are + not necessarily preserved. +
+x = new BigNumber(0.123) // '0.123' +x.toExponential() // '1.23e-1' +x.c // '1,2,3' +x.e // -1 +x.s // 1 + +y = new Number(-123.4567000e+2) // '-12345.67' +y.toExponential() // '-1.234567e+4' +z = new BigNumber('-123.4567000e+2') // '-12345.67' +z.toExponential() // '-1.234567e+4' +z.c // '1,2,3,4,5,6,7' +z.e // 4 +z.s // -1+ + + +
+ The table below shows how ±0
, NaN
and
+ ±Infinity
are stored.
+
+ | c | +e | +s | +
---|---|---|---|
±0 | +[0] |
+ 0 |
+ ±1 |
+
NaN | +null |
+ null |
+ null |
+
±Infinity | +null |
+ null |
+ ±1 |
+
+x = new Number(-0) // 0 +1 / x == -Infinity // true + +y = new BigNumber(-0) // '0' +y.c // '0' ( [0].toString() ) +y.e // 0 +y.s // -1+ + + +
+ The errors that are thrown are generic Error
objects with name
+ BigNumber Error.
+
+ The table below shows the errors that may be thrown if ERRORS
is
+ true
, and the action taken if ERRORS
is false
.
+
Method(s) | +ERRORS: true Throw BigNumber Error |
+ ERRORS: false Action on invalid argument |
+
---|---|---|
+
+ BigNumber |
+ number type has more than 15 significant digits |
+ Accept. | +
not a base... number | +Substitute NaN . |
+ |
base not an integer | +Truncate to integer. Ignore if not a number. |
+ |
base out of range | +Ignore. | +|
not a number* | +Substitute NaN . |
+ |
another |
+ not an object | +Ignore. | +
config |
+ DECIMAL_PLACES not an integer |
+ Truncate to integer. Ignore if not a number. |
+
DECIMAL_PLACES out of range |
+ Ignore. | +|
ROUNDING_MODE not an integer |
+ Truncate to integer. Ignore if not a number. |
+ |
ROUNDING_MODE out of range |
+ Ignore. | +|
EXPONENTIAL_AT not an integeror not [integer, integer] |
+ Truncate to integer(s). Ignore if not number(s). |
+ |
EXPONENTIAL_AT out of rangeor not [negative, positive] |
+ Ignore. | +|
RANGE not an integeror not [integer, integer] |
+ Truncate to integer(s). Ignore if not number(s). |
+ |
RANGE cannot be zero |
+ Ignore. | +|
RANGE out of rangeor not [negative, positive] |
+ Ignore. | +|
ERRORS not a booleanor binary digit |
+ Ignore. | +|
CRYPTO not a booleanor binary digit |
+ Ignore. | +|
CRYPTO crypto unavailable |
+ Ignore. | +|
MODULO_MODE not an integer |
+ Truncate to integer. Ignore if not a number. |
+ |
MODULO_MODE out of range |
+ Ignore. | +|
POW_PRECISION not an integer |
+ Truncate to integer. Ignore if not a number. |
+ |
POW_PRECISION out of range |
+ Ignore. | +|
FORMAT not an object |
+ Ignore. | +|
precision |
+ argument not a boolean or binary digit |
+ Ignore. | +
round |
+ decimal places not an integer | +Truncate to integer. Ignore if not a number. |
+
decimal places out of range | +Ignore. | +|
rounding mode not an integer | +Truncate to integer. Ignore if not a number. |
+ |
rounding mode out of range | +Ignore. | +|
shift |
+ argument not an integer | +Truncate to integer. Ignore if not a number. |
+
argument out of range | +Substitute ±Infinity .
+ | |
+ toExponential + toFixed + toFormat
+ |
+ decimal places not an integer | +Truncate to integer. Ignore if not a number. |
+
decimal places out of range | +Ignore. | +|
rounding mode not an integer | +Truncate to integer. Ignore if not a number. |
+ |
rounding mode out of range | +Ignore. | +|
toFraction |
+ max denominator not an integer | +Truncate to integer. Ignore if not a number. |
+
max denominator out of range | +Ignore. | +|
+ toDigits + toPrecision
+ |
+ precision not an integer | +Truncate to integer. Ignore if not a number. |
+
precision out of range | +Ignore. | +|
rounding mode not an integer | +Truncate to integer. Ignore if not a number. |
+ |
rounding mode out of range | +Ignore. | +|
toPower |
+ exponent not an integer | +Truncate to integer. Substitute NaN if not a number. |
+
exponent out of range | +Substitute ±Infinity .
+ |
+ |
toString |
+ base not an integer | +Truncate to integer. Ignore if not a number. |
+
base out of range | +Ignore. | +
*No error is thrown if the value is NaN
or 'NaN'.
+ The message of a BigNumber Error will also contain the name of the method from which + the error originated. +
+To determine if an exception is a BigNumber Error:
++try { + // ... +} catch (e) { + if ( e instanceof Error && e.name == 'BigNumber Error' ) { + // ... + } +}+ + + +
+ Some arbitrary-precision libraries retain trailing fractional zeros as they can indicate the + precision of a value. This can be useful but the results of arithmetic operations can be + misleading. +
++x = new BigDecimal("1.0") +y = new BigDecimal("1.1000") +z = x.add(y) // 2.1000 + +x = new BigDecimal("1.20") +y = new BigDecimal("3.45000") +z = x.multiply(y) // 4.1400000+
+ To specify the precision of a value is to specify that the value lies + within a certain range. +
+
+ In the first example, x
has a value of 1.0
. The trailing zero shows
+ the precision of the value, implying that it is in the range 0.95
to
+ 1.05
. Similarly, the precision indicated by the trailing zeros of y
+ indicates that the value is in the range 1.09995
to 1.10005
.
+
+ If we add the two lowest values in the ranges we have, 0.95 + 1.09995 = 2.04995
,
+ and if we add the two highest values we have, 1.05 + 1.10005 = 2.15005
, so the
+ range of the result of the addition implied by the precision of its operands is
+ 2.04995
to 2.15005
.
+
+ The result given by BigDecimal of 2.1000
however, indicates that the value is in
+ the range 2.09995
to 2.10005
and therefore the precision implied by
+ its trailing zeros may be misleading.
+
+ In the second example, the true range is 4.122744
to 4.157256
yet
+ the BigDecimal answer of 4.1400000
indicates a range of 4.13999995
+ to 4.14000005
. Again, the precision implied by the trailing zeros may be
+ misleading.
+
+ This library, like binary floating point and most calculators, does not retain trailing
+ fractional zeros. Instead, the toExponential
, toFixed
and
+ toPrecision
methods enable trailing zeros to be added if and when required.
+
+ Use-case + |
+
+ Class + |
+
+ Method(s) to implement + |
+
---|---|---|
+ Reading only + |
+
+ [Readable](#stream_class_stream_readable_1) + |
+
+
|
+
+ Writing only + |
+
+ [Writable](#stream_class_stream_writable_1) + |
+
+
|
+
+ Reading and writing + |
+
+ [Duplex](#stream_class_stream_duplex_1) + |
+
+
|
+
+ Operate on written data, then read the result + |
+
+ [Transform](#stream_class_stream_transform_1) + |
+
+
|
+
Welcome back, ' + escapeHtml(name) + '!
'); + } else { + res.write('Hello, new visitor!
'); + } + + res.write(' values + * + * @param {string} str + * @param {object} [options] + * @return {object} + * @public + */ + +function parse(str, options) { + if (typeof str !== 'string') { + throw new TypeError('argument str must be a string'); + } + + var obj = {} + var opt = options || {}; + var pairs = str.split(pairSplitRegExp); + var dec = opt.decode || decode; + + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i]; + var eq_idx = pair.indexOf('='); + + // skip things that don't look like key=value + if (eq_idx < 0) { + continue; + } + + var key = pair.substr(0, eq_idx).trim() + var val = pair.substr(++eq_idx, pair.length).trim(); + + // quoted values + if ('"' == val[0]) { + val = val.slice(1, -1); + } + + // only assign once + if (undefined == obj[key]) { + obj[key] = tryDecode(val, dec); + } + } + + return obj; +} + +/** + * Serialize data into a cookie header. + * + * Serialize the a name value pair into a cookie string suitable for + * http headers. An optional options object specified cookie parameters. + * + * serialize('foo', 'bar', { httpOnly: true }) + * => "foo=bar; httpOnly" + * + * @param {string} name + * @param {string} val + * @param {object} [options] + * @return {string} + * @public + */ + +function serialize(name, val, options) { + var opt = options || {}; + var enc = opt.encode || encode; + + if (typeof enc !== 'function') { + throw new TypeError('option encode is invalid'); + } + + if (!fieldContentRegExp.test(name)) { + throw new TypeError('argument name is invalid'); + } + + var value = enc(val); + + if (value && !fieldContentRegExp.test(value)) { + throw new TypeError('argument val is invalid'); + } + + var str = name + '=' + value; + + if (null != opt.maxAge) { + var maxAge = opt.maxAge - 0; + if (isNaN(maxAge)) throw new Error('maxAge should be a Number'); + str += '; Max-Age=' + Math.floor(maxAge); + } + + if (opt.domain) { + if (!fieldContentRegExp.test(opt.domain)) { + throw new TypeError('option domain is invalid'); + } + + str += '; Domain=' + opt.domain; + } + + if (opt.path) { + if (!fieldContentRegExp.test(opt.path)) { + throw new TypeError('option path is invalid'); + } + + str += '; Path=' + opt.path; + } + + if (opt.expires) { + if (typeof opt.expires.toUTCString !== 'function') { + throw new TypeError('option expires is invalid'); + } + + str += '; Expires=' + opt.expires.toUTCString(); + } + + if (opt.httpOnly) { + str += '; HttpOnly'; + } + + if (opt.secure) { + str += '; Secure'; + } + + if (opt.sameSite) { + var sameSite = typeof opt.sameSite === 'string' + ? opt.sameSite.toLowerCase() : opt.sameSite; + + switch (sameSite) { + case true: + str += '; SameSite=Strict'; + break; + case 'lax': + str += '; SameSite=Lax'; + break; + case 'strict': + str += '; SameSite=Strict'; + break; + default: + throw new TypeError('option sameSite is invalid'); + } + } + + return str; +} + +/** + * Try decoding a string using a decoding function. + * + * @param {string} str + * @param {function} decode + * @private + */ + +function tryDecode(str, decode) { + try { + return decode(str); + } catch (e) { + return str; + } +} diff --git a/node_modules/cookie/package.json b/node_modules/cookie/package.json new file mode 100644 index 0000000..aef9f1f --- /dev/null +++ b/node_modules/cookie/package.json @@ -0,0 +1,107 @@ +{ + "_args": [ + [ + { + "raw": "cookie@0.3.1", + "scope": null, + "escapedName": "cookie", + "name": "cookie", + "rawSpec": "0.3.1", + "spec": "0.3.1", + "type": "version" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express" + ] + ], + "_from": "cookie@0.3.1", + "_id": "cookie@0.3.1", + "_inCache": true, + "_installable": true, + "_location": "/cookie", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/cookie-0.3.1.tgz_1464323556714_0.6435900838114321" + }, + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "raw": "cookie@0.3.1", + "scope": null, + "escapedName": "cookie", + "name": "cookie", + "rawSpec": "0.3.1", + "spec": "0.3.1", + "type": "version" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "_shasum": "e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb", + "_shrinkwrap": null, + "_spec": "cookie@0.3.1", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express", + "author": { + "name": "Roman Shtylman", + "email": "shtylman@gmail.com" + }, + "bugs": { + "url": "https://github.com/jshttp/cookie/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + } + ], + "dependencies": {}, + "description": "HTTP server cookie parsing and serialization", + "devDependencies": { + "istanbul": "0.4.3", + "mocha": "1.21.5" + }, + "directories": {}, + "dist": { + "shasum": "e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb", + "tarball": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "gitHead": "e3c77d497d66c8b8d4b677b8954c1b192a09f0b3", + "homepage": "https://github.com/jshttp/cookie", + "keywords": [ + "cookie", + "cookies" + ], + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "cookie", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/cookie.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" + }, + "version": "0.3.1" +} diff --git a/node_modules/core-util-is/LICENSE b/node_modules/core-util-is/LICENSE new file mode 100644 index 0000000..d8d7f94 --- /dev/null +++ b/node_modules/core-util-is/LICENSE @@ -0,0 +1,19 @@ +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/node_modules/core-util-is/README.md b/node_modules/core-util-is/README.md new file mode 100644 index 0000000..5a76b41 --- /dev/null +++ b/node_modules/core-util-is/README.md @@ -0,0 +1,3 @@ +# core-util-is + +The `util.is*` functions introduced in Node v0.12. diff --git a/node_modules/core-util-is/float.patch b/node_modules/core-util-is/float.patch new file mode 100644 index 0000000..a06d5c0 --- /dev/null +++ b/node_modules/core-util-is/float.patch @@ -0,0 +1,604 @@ +diff --git a/lib/util.js b/lib/util.js +index a03e874..9074e8e 100644 +--- a/lib/util.js ++++ b/lib/util.js +@@ -19,430 +19,6 @@ + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + +-var formatRegExp = /%[sdj%]/g; +-exports.format = function(f) { +- if (!isString(f)) { +- var objects = []; +- for (var i = 0; i < arguments.length; i++) { +- objects.push(inspect(arguments[i])); +- } +- return objects.join(' '); +- } +- +- var i = 1; +- var args = arguments; +- var len = args.length; +- var str = String(f).replace(formatRegExp, function(x) { +- if (x === '%%') return '%'; +- if (i >= len) return x; +- switch (x) { +- case '%s': return String(args[i++]); +- case '%d': return Number(args[i++]); +- case '%j': +- try { +- return JSON.stringify(args[i++]); +- } catch (_) { +- return '[Circular]'; +- } +- default: +- return x; +- } +- }); +- for (var x = args[i]; i < len; x = args[++i]) { +- if (isNull(x) || !isObject(x)) { +- str += ' ' + x; +- } else { +- str += ' ' + inspect(x); +- } +- } +- return str; +-}; +- +- +-// Mark that a method should not be used. +-// Returns a modified function which warns once by default. +-// If --no-deprecation is set, then it is a no-op. +-exports.deprecate = function(fn, msg) { +- // Allow for deprecating things in the process of starting up. +- if (isUndefined(global.process)) { +- return function() { +- return exports.deprecate(fn, msg).apply(this, arguments); +- }; +- } +- +- if (process.noDeprecation === true) { +- return fn; +- } +- +- var warned = false; +- function deprecated() { +- if (!warned) { +- if (process.throwDeprecation) { +- throw new Error(msg); +- } else if (process.traceDeprecation) { +- console.trace(msg); +- } else { +- console.error(msg); +- } +- warned = true; +- } +- return fn.apply(this, arguments); +- } +- +- return deprecated; +-}; +- +- +-var debugs = {}; +-var debugEnviron; +-exports.debuglog = function(set) { +- if (isUndefined(debugEnviron)) +- debugEnviron = process.env.NODE_DEBUG || ''; +- set = set.toUpperCase(); +- if (!debugs[set]) { +- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { +- var pid = process.pid; +- debugs[set] = function() { +- var msg = exports.format.apply(exports, arguments); +- console.error('%s %d: %s', set, pid, msg); +- }; +- } else { +- debugs[set] = function() {}; +- } +- } +- return debugs[set]; +-}; +- +- +-/** +- * Echos the value of a value. Trys to print the value out +- * in the best way possible given the different types. +- * +- * @param {Object} obj The object to print out. +- * @param {Object} opts Optional options object that alters the output. +- */ +-/* legacy: obj, showHidden, depth, colors*/ +-function inspect(obj, opts) { +- // default options +- var ctx = { +- seen: [], +- stylize: stylizeNoColor +- }; +- // legacy... +- if (arguments.length >= 3) ctx.depth = arguments[2]; +- if (arguments.length >= 4) ctx.colors = arguments[3]; +- if (isBoolean(opts)) { +- // legacy... +- ctx.showHidden = opts; +- } else if (opts) { +- // got an "options" object +- exports._extend(ctx, opts); +- } +- // set default options +- if (isUndefined(ctx.showHidden)) ctx.showHidden = false; +- if (isUndefined(ctx.depth)) ctx.depth = 2; +- if (isUndefined(ctx.colors)) ctx.colors = false; +- if (isUndefined(ctx.customInspect)) ctx.customInspect = true; +- if (ctx.colors) ctx.stylize = stylizeWithColor; +- return formatValue(ctx, obj, ctx.depth); +-} +-exports.inspect = inspect; +- +- +-// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +-inspect.colors = { +- 'bold' : [1, 22], +- 'italic' : [3, 23], +- 'underline' : [4, 24], +- 'inverse' : [7, 27], +- 'white' : [37, 39], +- 'grey' : [90, 39], +- 'black' : [30, 39], +- 'blue' : [34, 39], +- 'cyan' : [36, 39], +- 'green' : [32, 39], +- 'magenta' : [35, 39], +- 'red' : [31, 39], +- 'yellow' : [33, 39] +-}; +- +-// Don't use 'blue' not visible on cmd.exe +-inspect.styles = { +- 'special': 'cyan', +- 'number': 'yellow', +- 'boolean': 'yellow', +- 'undefined': 'grey', +- 'null': 'bold', +- 'string': 'green', +- 'date': 'magenta', +- // "name": intentionally not styling +- 'regexp': 'red' +-}; +- +- +-function stylizeWithColor(str, styleType) { +- var style = inspect.styles[styleType]; +- +- if (style) { +- return '\u001b[' + inspect.colors[style][0] + 'm' + str + +- '\u001b[' + inspect.colors[style][1] + 'm'; +- } else { +- return str; +- } +-} +- +- +-function stylizeNoColor(str, styleType) { +- return str; +-} +- +- +-function arrayToHash(array) { +- var hash = {}; +- +- array.forEach(function(val, idx) { +- hash[val] = true; +- }); +- +- return hash; +-} +- +- +-function formatValue(ctx, value, recurseTimes) { +- // Provide a hook for user-specified inspect functions. +- // Check that value is an object with an inspect function on it +- if (ctx.customInspect && +- value && +- isFunction(value.inspect) && +- // Filter out the util module, it's inspect function is special +- value.inspect !== exports.inspect && +- // Also filter out any prototype objects using the circular check. +- !(value.constructor && value.constructor.prototype === value)) { +- var ret = value.inspect(recurseTimes, ctx); +- if (!isString(ret)) { +- ret = formatValue(ctx, ret, recurseTimes); +- } +- return ret; +- } +- +- // Primitive types cannot have properties +- var primitive = formatPrimitive(ctx, value); +- if (primitive) { +- return primitive; +- } +- +- // Look up the keys of the object. +- var keys = Object.keys(value); +- var visibleKeys = arrayToHash(keys); +- +- if (ctx.showHidden) { +- keys = Object.getOwnPropertyNames(value); +- } +- +- // Some type of object without properties can be shortcutted. +- if (keys.length === 0) { +- if (isFunction(value)) { +- var name = value.name ? ': ' + value.name : ''; +- return ctx.stylize('[Function' + name + ']', 'special'); +- } +- if (isRegExp(value)) { +- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); +- } +- if (isDate(value)) { +- return ctx.stylize(Date.prototype.toString.call(value), 'date'); +- } +- if (isError(value)) { +- return formatError(value); +- } +- } +- +- var base = '', array = false, braces = ['{', '}']; +- +- // Make Array say that they are Array +- if (isArray(value)) { +- array = true; +- braces = ['[', ']']; +- } +- +- // Make functions say that they are functions +- if (isFunction(value)) { +- var n = value.name ? ': ' + value.name : ''; +- base = ' [Function' + n + ']'; +- } +- +- // Make RegExps say that they are RegExps +- if (isRegExp(value)) { +- base = ' ' + RegExp.prototype.toString.call(value); +- } +- +- // Make dates with properties first say the date +- if (isDate(value)) { +- base = ' ' + Date.prototype.toUTCString.call(value); +- } +- +- // Make error with message first say the error +- if (isError(value)) { +- base = ' ' + formatError(value); +- } +- +- if (keys.length === 0 && (!array || value.length == 0)) { +- return braces[0] + base + braces[1]; +- } +- +- if (recurseTimes < 0) { +- if (isRegExp(value)) { +- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); +- } else { +- return ctx.stylize('[Object]', 'special'); +- } +- } +- +- ctx.seen.push(value); +- +- var output; +- if (array) { +- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); +- } else { +- output = keys.map(function(key) { +- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); +- }); +- } +- +- ctx.seen.pop(); +- +- return reduceToSingleString(output, base, braces); +-} +- +- +-function formatPrimitive(ctx, value) { +- if (isUndefined(value)) +- return ctx.stylize('undefined', 'undefined'); +- if (isString(value)) { +- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') +- .replace(/'/g, "\\'") +- .replace(/\\"/g, '"') + '\''; +- return ctx.stylize(simple, 'string'); +- } +- if (isNumber(value)) { +- // Format -0 as '-0'. Strict equality won't distinguish 0 from -0, +- // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 . +- if (value === 0 && 1 / value < 0) +- return ctx.stylize('-0', 'number'); +- return ctx.stylize('' + value, 'number'); +- } +- if (isBoolean(value)) +- return ctx.stylize('' + value, 'boolean'); +- // For some reason typeof null is "object", so special case here. +- if (isNull(value)) +- return ctx.stylize('null', 'null'); +-} +- +- +-function formatError(value) { +- return '[' + Error.prototype.toString.call(value) + ']'; +-} +- +- +-function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { +- var output = []; +- for (var i = 0, l = value.length; i < l; ++i) { +- if (hasOwnProperty(value, String(i))) { +- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, +- String(i), true)); +- } else { +- output.push(''); +- } +- } +- keys.forEach(function(key) { +- if (!key.match(/^\d+$/)) { +- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, +- key, true)); +- } +- }); +- return output; +-} +- +- +-function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { +- var name, str, desc; +- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; +- if (desc.get) { +- if (desc.set) { +- str = ctx.stylize('[Getter/Setter]', 'special'); +- } else { +- str = ctx.stylize('[Getter]', 'special'); +- } +- } else { +- if (desc.set) { +- str = ctx.stylize('[Setter]', 'special'); +- } +- } +- if (!hasOwnProperty(visibleKeys, key)) { +- name = '[' + key + ']'; +- } +- if (!str) { +- if (ctx.seen.indexOf(desc.value) < 0) { +- if (isNull(recurseTimes)) { +- str = formatValue(ctx, desc.value, null); +- } else { +- str = formatValue(ctx, desc.value, recurseTimes - 1); +- } +- if (str.indexOf('\n') > -1) { +- if (array) { +- str = str.split('\n').map(function(line) { +- return ' ' + line; +- }).join('\n').substr(2); +- } else { +- str = '\n' + str.split('\n').map(function(line) { +- return ' ' + line; +- }).join('\n'); +- } +- } +- } else { +- str = ctx.stylize('[Circular]', 'special'); +- } +- } +- if (isUndefined(name)) { +- if (array && key.match(/^\d+$/)) { +- return str; +- } +- name = JSON.stringify('' + key); +- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { +- name = name.substr(1, name.length - 2); +- name = ctx.stylize(name, 'name'); +- } else { +- name = name.replace(/'/g, "\\'") +- .replace(/\\"/g, '"') +- .replace(/(^"|"$)/g, "'"); +- name = ctx.stylize(name, 'string'); +- } +- } +- +- return name + ': ' + str; +-} +- +- +-function reduceToSingleString(output, base, braces) { +- var numLinesEst = 0; +- var length = output.reduce(function(prev, cur) { +- numLinesEst++; +- if (cur.indexOf('\n') >= 0) numLinesEst++; +- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; +- }, 0); +- +- if (length > 60) { +- return braces[0] + +- (base === '' ? '' : base + '\n ') + +- ' ' + +- output.join(',\n ') + +- ' ' + +- braces[1]; +- } +- +- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +-} +- +- + // NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar) { +@@ -522,166 +98,10 @@ function isPrimitive(arg) { + exports.isPrimitive = isPrimitive; + + function isBuffer(arg) { +- return arg instanceof Buffer; ++ return Buffer.isBuffer(arg); + } + exports.isBuffer = isBuffer; + + function objectToString(o) { + return Object.prototype.toString.call(o); +-} +- +- +-function pad(n) { +- return n < 10 ? '0' + n.toString(10) : n.toString(10); +-} +- +- +-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', +- 'Oct', 'Nov', 'Dec']; +- +-// 26 Feb 16:19:34 +-function timestamp() { +- var d = new Date(); +- var time = [pad(d.getHours()), +- pad(d.getMinutes()), +- pad(d.getSeconds())].join(':'); +- return [d.getDate(), months[d.getMonth()], time].join(' '); +-} +- +- +-// log is just a thin wrapper to console.log that prepends a timestamp +-exports.log = function() { +- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +-}; +- +- +-/** +- * Inherit the prototype methods from one constructor into another. +- * +- * The Function.prototype.inherits from lang.js rewritten as a standalone +- * function (not on Function.prototype). NOTE: If this file is to be loaded +- * during bootstrapping this function needs to be rewritten using some native +- * functions as prototype setup using normal JavaScript does not work as +- * expected during bootstrapping (see mirror.js in r114903). +- * +- * @param {function} ctor Constructor function which needs to inherit the +- * prototype. +- * @param {function} superCtor Constructor function to inherit prototype from. +- */ +-exports.inherits = function(ctor, superCtor) { +- ctor.super_ = superCtor; +- ctor.prototype = Object.create(superCtor.prototype, { +- constructor: { +- value: ctor, +- enumerable: false, +- writable: true, +- configurable: true +- } +- }); +-}; +- +-exports._extend = function(origin, add) { +- // Don't do anything if add isn't an object +- if (!add || !isObject(add)) return origin; +- +- var keys = Object.keys(add); +- var i = keys.length; +- while (i--) { +- origin[keys[i]] = add[keys[i]]; +- } +- return origin; +-}; +- +-function hasOwnProperty(obj, prop) { +- return Object.prototype.hasOwnProperty.call(obj, prop); +-} +- +- +-// Deprecated old stuff. +- +-exports.p = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- console.error(exports.inspect(arguments[i])); +- } +-}, 'util.p: Use console.error() instead'); +- +- +-exports.exec = exports.deprecate(function() { +- return require('child_process').exec.apply(this, arguments); +-}, 'util.exec is now called `child_process.exec`.'); +- +- +-exports.print = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stdout.write(String(arguments[i])); +- } +-}, 'util.print: Use console.log instead'); +- +- +-exports.puts = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stdout.write(arguments[i] + '\n'); +- } +-}, 'util.puts: Use console.log instead'); +- +- +-exports.debug = exports.deprecate(function(x) { +- process.stderr.write('DEBUG: ' + x + '\n'); +-}, 'util.debug: Use console.error instead'); +- +- +-exports.error = exports.deprecate(function(x) { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stderr.write(arguments[i] + '\n'); +- } +-}, 'util.error: Use console.error instead'); +- +- +-exports.pump = exports.deprecate(function(readStream, writeStream, callback) { +- var callbackCalled = false; +- +- function call(a, b, c) { +- if (callback && !callbackCalled) { +- callback(a, b, c); +- callbackCalled = true; +- } +- } +- +- readStream.addListener('data', function(chunk) { +- if (writeStream.write(chunk) === false) readStream.pause(); +- }); +- +- writeStream.addListener('drain', function() { +- readStream.resume(); +- }); +- +- readStream.addListener('end', function() { +- writeStream.end(); +- }); +- +- readStream.addListener('close', function() { +- call(); +- }); +- +- readStream.addListener('error', function(err) { +- writeStream.end(); +- call(err); +- }); +- +- writeStream.addListener('error', function(err) { +- readStream.destroy(); +- call(err); +- }); +-}, 'util.pump(): Use readableStream.pipe() instead'); +- +- +-var uv; +-exports._errnoException = function(err, syscall) { +- if (isUndefined(uv)) uv = process.binding('uv'); +- var errname = uv.errname(err); +- var e = new Error(syscall + ' ' + errname); +- e.code = errname; +- e.errno = errname; +- e.syscall = syscall; +- return e; +-}; ++} \ No newline at end of file diff --git a/node_modules/core-util-is/lib/util.js b/node_modules/core-util-is/lib/util.js new file mode 100644 index 0000000..ff4c851 --- /dev/null +++ b/node_modules/core-util-is/lib/util.js @@ -0,0 +1,107 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} diff --git a/node_modules/core-util-is/package.json b/node_modules/core-util-is/package.json new file mode 100644 index 0000000..dd6ef52 --- /dev/null +++ b/node_modules/core-util-is/package.json @@ -0,0 +1,95 @@ +{ + "_args": [ + [ + { + "raw": "core-util-is@~1.0.0", + "scope": null, + "escapedName": "core-util-is", + "name": "core-util-is", + "rawSpec": "~1.0.0", + "spec": ">=1.0.0 <1.1.0", + "type": "range" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\readable-stream" + ] + ], + "_from": "core-util-is@>=1.0.0 <1.1.0", + "_id": "core-util-is@1.0.2", + "_inCache": true, + "_installable": true, + "_location": "/core-util-is", + "_nodeVersion": "4.0.0", + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "_npmVersion": "3.3.2", + "_phantomChildren": {}, + "_requested": { + "raw": "core-util-is@~1.0.0", + "scope": null, + "escapedName": "core-util-is", + "name": "core-util-is", + "rawSpec": "~1.0.0", + "spec": ">=1.0.0 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/readable-stream" + ], + "_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "_shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7", + "_shrinkwrap": null, + "_spec": "core-util-is@~1.0.0", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\readable-stream", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bugs": { + "url": "https://github.com/isaacs/core-util-is/issues" + }, + "dependencies": {}, + "description": "The `util.is*` functions introduced in Node v0.12.", + "devDependencies": { + "tap": "^2.3.0" + }, + "directories": {}, + "dist": { + "shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7", + "tarball": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "gitHead": "a177da234df5638b363ddc15fa324619a38577c8", + "homepage": "https://github.com/isaacs/core-util-is#readme", + "keywords": [ + "util", + "isBuffer", + "isArray", + "isNumber", + "isString", + "isRegExp", + "isThis", + "isThat", + "polyfill" + ], + "license": "MIT", + "main": "lib/util.js", + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "name": "core-util-is", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/core-util-is.git" + }, + "scripts": { + "test": "tap test.js" + }, + "version": "1.0.2" +} diff --git a/node_modules/core-util-is/test.js b/node_modules/core-util-is/test.js new file mode 100644 index 0000000..1a490c6 --- /dev/null +++ b/node_modules/core-util-is/test.js @@ -0,0 +1,68 @@ +var assert = require('tap'); + +var t = require('./lib/util'); + +assert.equal(t.isArray([]), true); +assert.equal(t.isArray({}), false); + +assert.equal(t.isBoolean(null), false); +assert.equal(t.isBoolean(true), true); +assert.equal(t.isBoolean(false), true); + +assert.equal(t.isNull(null), true); +assert.equal(t.isNull(undefined), false); +assert.equal(t.isNull(false), false); +assert.equal(t.isNull(), false); + +assert.equal(t.isNullOrUndefined(null), true); +assert.equal(t.isNullOrUndefined(undefined), true); +assert.equal(t.isNullOrUndefined(false), false); +assert.equal(t.isNullOrUndefined(), true); + +assert.equal(t.isNumber(null), false); +assert.equal(t.isNumber('1'), false); +assert.equal(t.isNumber(1), true); + +assert.equal(t.isString(null), false); +assert.equal(t.isString('1'), true); +assert.equal(t.isString(1), false); + +assert.equal(t.isSymbol(null), false); +assert.equal(t.isSymbol('1'), false); +assert.equal(t.isSymbol(1), false); +assert.equal(t.isSymbol(Symbol()), true); + +assert.equal(t.isUndefined(null), false); +assert.equal(t.isUndefined(undefined), true); +assert.equal(t.isUndefined(false), false); +assert.equal(t.isUndefined(), true); + +assert.equal(t.isRegExp(null), false); +assert.equal(t.isRegExp('1'), false); +assert.equal(t.isRegExp(new RegExp()), true); + +assert.equal(t.isObject({}), true); +assert.equal(t.isObject([]), true); +assert.equal(t.isObject(new RegExp()), true); +assert.equal(t.isObject(new Date()), true); + +assert.equal(t.isDate(null), false); +assert.equal(t.isDate('1'), false); +assert.equal(t.isDate(new Date()), true); + +assert.equal(t.isError(null), false); +assert.equal(t.isError({ err: true }), false); +assert.equal(t.isError(new Error()), true); + +assert.equal(t.isFunction(null), false); +assert.equal(t.isFunction({ }), false); +assert.equal(t.isFunction(function() {}), true); + +assert.equal(t.isPrimitive(null), true); +assert.equal(t.isPrimitive(''), true); +assert.equal(t.isPrimitive(0), true); +assert.equal(t.isPrimitive(new Date()), false); + +assert.equal(t.isBuffer(null), false); +assert.equal(t.isBuffer({}), false); +assert.equal(t.isBuffer(new Buffer(0)), true); diff --git a/node_modules/cps/.npmignore b/node_modules/cps/.npmignore new file mode 100644 index 0000000..b78027d --- /dev/null +++ b/node_modules/cps/.npmignore @@ -0,0 +1,3 @@ +.idea +cps.iml +npm-debug.log diff --git a/node_modules/cps/LICENSE b/node_modules/cps/LICENSE new file mode 100644 index 0000000..e74e436 --- /dev/null +++ b/node_modules/cps/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013 Chiyan Chen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/cps/README.md b/node_modules/cps/README.md new file mode 100644 index 0000000..59e549d --- /dev/null +++ b/node_modules/cps/README.md @@ -0,0 +1,348 @@ + +# cps + +A CPS (Continuation Passing Style) library to ease the +event-driven/asynchronized coding style in node.js. There seems to be +enough node.js libs (e.g. async) doing the same thing, why yet +another? This lib is notably different from other libs in +exception handling. Using cps: + +* Any "throw" statements in the procedures will be transformed to an + application of the callback onto the error object. +* A "rescue" function is provided, which can be used to catch such + exceptions pass through the callbacks. + +This consistently recovers the try/catch functionality in continuation +passing style programming. + + + +## Install + +```text +npm install cps +``` + +## Terminologies + +### Callback + +We call a function of the following form a callback: + +```javascript +function(err, res) { + // process the err and res +} +``` + +A callback is a function that takes two arguments, "err" and "res". +Semantically, a non-null "err" corresponds to a program exception; +while a null "err" corresponds to normal return without any +exceptions. + +### Procedure + +We call a function of the following form a procedure: + +```javascript +function(arg1, arg2, ..., callback) { + // do some work with the arguments and then invoke the callback to continue +} +``` + +A procedure is a function that takes a callback as the last argument. +Semantically, a procedure does some work with the input arguments and +at some point, call the callback to continue. Note that a call to the +"callback" argument MUST always be a tail call. In particular, the +following is a procedure: + +```javascript +function(callback) { + // do some work and then invoke the callback to continue +} +``` + + +## API Document + +* [seq](#seq) +* [pwhile](#pwhile) +* [peach](#peach) +* [pmap](#pmap) +* [pfor](#pfor) +* [rescue](#rescue) +* [parallel](#parallel) + + +### seq(array_of_procedures, callback) + +Sequence a list of procedures. Note that the result of each procedure +is fed into the next procedure in the listed order. + +__Example__ + +```javascript +var concatFile = function(f1, f2, resFile, cb) { + var contentOfA, contentOfB; + + cps.seq([ + function(_, cb) { + fs.readFile(f1, cb); + }, + function(res, cb) { + contentOfA = res; + fs.readFile(f2, cb); + }, + function(res, cb) { + contentOfB = res; + fs.writeFile(resFile, contentA + contentB, cb); + } + ], cb); +}; +``` + + +### pwhile(bool_procedure, repeat_body_procedure, cb) + +An asynchronized version of while loop. + +__Example__ + +Consider a world in which arithmatic operations do not exists and must +be accomplished through alien technology. Then the Fibonacci function +needs to be written in the following way: + +```javascript +var alienAdd = function(a, b, cb) { + setTimeout(function() { + cb(null, a + b); + }, 0); +}; + +var asyncFib = function(n, cb) { + if (n < 0) { + throw new Error('fib input error'); + } + if (n == 0) {return cb(null, 1);} + if (n == 1) {return cb(null, 1);} + + var a = 1, + b = 1, + i = 2; + cps.seq([ + function(_, cb) { + cps.pwhile( + function(cb) { + cb(null, i <= n); + }, + function(cb) { + cps.seq([ + function(_, cb) { + alienAdd(a, b, cb); + }, + function(res, cb) { + a = b; + b = res; + alienAdd(i, 1, cb); + }, + function(res, cb) { + i = res; + cb(); + } + ], cb); + }, + cb + ); + }, + function(_, cb) { + cb(null, b); + } + ], cb); +}; +``` + + +### peach(arr, procedure_for_each_element, callback) + +Apply a procedure on an array sequentially. + +__Example__ + +Then in the same "arithmetic-less" world, print out the first 10 Fibonacci numbers. + +```javascript +cps.peach( + [1,2,3,4,5,6,7,8,9,10], + function(el, cb) { + cps.seq([ + function(_, cb) { + asyncFib(el, cb); + }, + function(res, cb) { + console.log(res); + cb(); + } + ], cb); + + }, + cb +); +``` + + +### pmap(arr, procedure_for_each_element, callback) + +Apply a procedure on an array sequentially, and record the results in another array, which is pass to the callback. + +__Example__ + +You can also map it out first and then log the result list. + +```javascript +cps.seq([ + function(_, cb) { + cps.pmap( + [1,2,3,4,5,6,7,8,9,10], + function(el, cb) { + asyncFib(el, cb); + }, + cb + ); + }, + function(res, cb) { + console.log(res); + cb(); + } +], cb); +``` + + +### pfor(number_of_iterations, procedure_for_each_index, callback) + +Apply a procedure on a sequence of consecutive indices, starting of 0. + +__Example__ + + +```javascript +var sum = 0; +cps.seq([ + function(_, cb) { + console.log('here'); + cps.pfor(10, function(i, cb) { + setTimeout(function() { + sum += i; + console.log(sum); + cb(); + }, 1000); + }, cb); + }, + function(_, cb) { + console.log(sum); + cb(null, 'ok'); + } +], cb); +``` + + +### rescue(try_clause_procedure, catch_clause_procedure, callback) + +An asyned version of try/catch. It take two procedures as arguments. If the first one fails, the second is executed to rescue. + +__Example__ + +What if there's some invalid input? Let's catch it without disturbing the overall flow. + +```javascript +cps.seq([ + function(_, cb) { + cps.pmap( + [1,2,3,4,5,6,7,8,9,10, -1], + function(el, cb) { + cps.rescue({ + 'try': function(cb) { // try clause + asyncFib(el, cb); + }, + 'catch': function(err, cb) { // catch clause + console.log(err); + cb(null, -1); + }, + 'finally': function(cb) { // finally + console.log("always print this whether it's good or bad."); + cb(); + } + }, cb); + }, + cb + ); + }, + function(res, cb) { + console.log(res); + cb(); + } +], cb); +``` + + +### parallel(array_of_procedures, callback) + +Parallel a list of procedures. The top level callback is only called +after each parallel procedure finishes, regardless the procedure +succeeds or fails. The callback will never take a non-null error +parameter; the result parameter is an array of the following form: + +```js +[ + {"status": "ok", "data": res}, /* in case the procedure in the + corresponding position succeeds + with result res + */ + {"status": "error", "error": err} /* in case the procedure in the + corresponding position fails + with error err + */ + // ... +] +``` + + +__Example__ + +See "thread b" being printed out before "thread a": + +```javascript +var parallelTest = function(cb) { + cps.parallel([ + function(cb) { + setTimeout(function() { + console.log('3'); + cb(new Error('kaz')); + }, 3000); + }, + function(cb) { + setTimeout(function() { + console.log('1'); + cb(null, 'ok'); + }, 2000); + }, + function(cb) { + setTimeout(function() { + console.log('2'); + cb(new Error('foobar')); + }, 1000); + } + ], cb); +}; +``` + +Running this procedure will yield the following output: + +```text +2 +1 +3 +[ { status: 'error', error: [Error: kaz] }, + { status: 'ok', data: 'ok' }, + { status: 'error', error: [Error: foobar] } ] +``` + diff --git a/node_modules/cps/lib/cps.js b/node_modules/cps/lib/cps.js new file mode 100644 index 0000000..0fe0bab --- /dev/null +++ b/node_modules/cps/lib/cps.js @@ -0,0 +1,412 @@ + +var Tail = require('./tail'); + +module.exports = function() { + var procedure = function(fn) { + return function() { + var cb = arguments[arguments.length - 1]; + + try { + fn.apply(this, arguments); + } catch(e) { + handleError(e, cb); + } + }; + }; + + var handleError = function(e, cb) { + cb(e); + }; + + var callback = function(cb, fn) { + var called = false; + + return function(err) { + if (called) { + if (err) { + console.log(err); + if (err.stack) { + console.log(err.stack); + } + } + throw new Error('Continuation is being called more than once!'); + } + called = true; + try { + if (err) { + handleError(err, cb); + } else { + fn.apply(this, arguments); + } + } catch(e) { + handleError(e, cb); + } + }; + }; + + var _seq = procedure(function(procs, i, res, cb) { + if (i >= procs.length) { + return cb(null, res); + } + var proc = procs[i]; + proc(res, callback(cb, function(err, res) { + // return _seq(procs, i+1, res, cb); + return Tail.run(function() { + _seq(procs, i+1, res, cb); + }); + })); + }); + + var seq = function(procs, cb) { + return _seq(procs, 0, null, cb); + }; + + var rescue = procedure(function(procBundle, cb) { + var tryProc = procBundle['try']; + var catchProc = procBundle['catch'] || function(err, cb) {cb(err);}; + var finallyProc = procBundle['finally'] || function(cb) {cb();}; + + var applyTry = procedure(function(cb) { + tryProc(cb); + }); + + var applyCatch = procedure(function(err, cb) { + catchProc(err, cb); + }); + + var applyFinallyOk = procedure(function(res0, cb) { + finallyProc(callback(cb, function(err, res) { + cb(null, res0); + })); + }); + + var applyFinallyError = procedure(function(err0, cb) { + finallyProc(callback(cb, function(err, res) { + cb(err0); + })); + }); + + applyTry(function(err, res) { + if (err) { + applyCatch(err, function(err, res) { + if (err) { + applyFinallyError(err, cb); + } else { + applyFinallyOk(res, cb); + } + }); + } else { + applyFinallyOk(res, cb); + } + }); + }); + + var pwhile = procedure(function(procBool, procBody, cb) { + seq([ + function(_, cb) { + procBool(cb); + }, + function(_, cb) { + if (_) { + seq([ + function(_, cb) { + procBody(cb); + }, + function(_, cb) { + pwhile(procBool, procBody, cb); + } + ], cb); + } else { + cb(); + } + } + ], cb); + }); + + var peach = procedure(function(arr, proc, cb) { + var i = 0; + + pwhile( + function(cb) { + cb(null, i < arr.length); + }, + function(cb) { + seq([ + function(_, cb) { + proc(arr[i], cb); + }, + function(_, cb) { + i++; + cb(); + } + ], cb); + }, + cb + ) + }); + + var pfor = procedure(function(n, proc, cb) { + var i = 0; + + pwhile( + function(cb) { + cb(null, i < n); + }, + function(cb) { + seq([ + function(_, cb) { + proc(i, cb); + }, + function(_, cb) { + i++; + cb(); + } + ], cb); + }, + cb + ); + }); + + var pmap = procedure(function(arr, proc, cb) { + var l = []; + + seq([ + function(_, cb) { + peach(arr, function(e, cb) { + seq([ + function(_, cb) { + proc(e, cb); + }, + function(_, cb) { + l.push(_); + cb(); + } + ], cb); + }, cb); + }, + function(_, cb) { + cb(null, l); + } + ], cb); + }); + + var _parallel2 = procedure(function(proc1, proc2, cb) { + var state1 = 'start'; + var state2 = 'start'; + var res1; + var res2; + var err1; + var err2; + + var applyProc1 = procedure(function(cb) { + proc1(cb); + }); + + var applyProc2 = procedure(function(cb) { + proc2(cb); + }); + + applyProc1(function(err, res) {Tail.run(function() { + if (err) { + state1 = 'error'; + err1 = err; + switch(state2) { + case 'start': + break; + case 'done': + cb(null, [ + {status: 'error', error: err1}, + {status: 'ok', data: res2} + ]); + break; + case 'error': + cb(null, [ + {status: 'error', error: err1}, + {status: 'error', error: err2} + ]); + break; + default: + } + } else { + state1 = 'done'; + res1 = res; + switch(state2) { + case 'start': + break; + case 'done': + cb(null, [ + {status: 'ok', data: res1}, + {status: 'ok', data: res2} + ]); + break; + case 'error': + cb(null, [ + {status: 'ok', data: res1}, + {status: 'error', error: err2} + ]); + break; + default: + } + } + })}); + + applyProc2(function(err, res) {Tail.run(function() { + if (err) { + state2 = 'error'; + err2 = err; + switch(state1) { + case 'start': + break; + case 'done': + cb(null, [ + {status: 'ok', data: res1}, + {status: 'error', error: err2} + ]); + break; + case 'error': + cb(null, [ + {status: 'error', error: err1}, + {status: 'error', error: err2} + ]); + break; + default: + } + } else { + state2 = 'done'; + res2 = res; + switch(state1) { + case 'start': + break; + case 'done': + cb(null, [ + {status: 'ok', data: res1}, + {status: 'ok', data: res2} + ]); + break; + case 'error': + cb(null, [ + {status: 'error', error: err1}, + {status: 'ok', data: res2} + ]); + break; + default: + } + } + })}); + }); + + var _parallel = procedure(function(procs, i, cb) { + if (procs.length == 0) { + return cb(); + } + + if (i == procs.length - 1) { + return procs[i](function(err, res) { + if (err) { + cb(null, [{status: 'error', error: err}]); + } else { + cb(null, [{status: 'ok', data: res}]); + } + }); + } + + if (i < procs.length) { + _parallel2( + procs[i], + function(cb) { + _parallel(procs, i+1, cb); + }, + callback(cb, function(err, res) { + cb(null, [res[0]].concat(res[1].data)); + }) + ); + } + }); + + var parallel = procedure(function(procs, cb) { + _parallel(procs, 0, cb); + }); + + var noFail = function() { + var proc, handler, cb; + + proc = arguments[0]; + cb = arguments[arguments.length - 1]; + + if (arguments.length == 2) { + handler = function(err) { + console.log('ERROR caught by cps.noFail: ', err); + if (err.stack) { + console.log(err.stack); + } + }; + } else if (arguments.length == 3) { + handler = arguments[1]; + } else { + handleError(new Error('Incorrect number of arguments in calling cps.noFail.'), cb); + } + + rescue({ + 'try': function(cb) { + proc(cb); + }, + 'catch': function(err, cb) { + handler(err); + cb(); + } + }, cb); + }; + + var run = function(proc, cfg) { + cfg = cfg || {}; + + var cb = function(err, res) { + try { + if (err) { + if (cfg['error']) { + cfg['error'](err); + } else { + console.log('cps.run ERROR: ', err); + if (err.stack) { + console.log(err.stack); + } + } + } else { + if (cfg['ok']) { + cfg['ok'](res); + } else { + console.log('cps.run OK: ', res); + } + } + } catch(e) { + if (cfg['topLevelError']) { + cfg['topLevelError'](e); + } else { + console.log('cps.run TOP_LEVEL_ERROR: ', e); + } + } finally { + if (cfg['finally']) { + try { + cfg['finally'](); + } catch(e) { + console.log('cps.run FINALLY_ERROR: ', e); + } + } + } + }; + + proc(cb); + }; + + return { + seq: seq, + peach: peach, + pwhile: pwhile, + pmap: pmap, + pfor: pfor, + rescue: rescue, + parallel: parallel, + noFail: noFail, + run: run + }; +}(); diff --git a/node_modules/cps/lib/tail.js b/node_modules/cps/lib/tail.js new file mode 100644 index 0000000..2d68cb6 --- /dev/null +++ b/node_modules/cps/lib/tail.js @@ -0,0 +1,30 @@ + +var Tail = function() { + this._q = []; + this._running = false; +}; + +Tail.prototype = { + run: function(fn) { + this._q.push(fn); + if (!this._running) { + this._run(); + } + }, + + _run: function() { + while(true) { + var fn = this._q.shift(); + if (fn) { + this._running = true; + fn(); + } else { + this._running = false; + break; + } + } + } +}; + +module.exports = new Tail(); + diff --git a/node_modules/cps/lib/tail.js~ b/node_modules/cps/lib/tail.js~ new file mode 100644 index 0000000..2ead477 --- /dev/null +++ b/node_modules/cps/lib/tail.js~ @@ -0,0 +1,6 @@ + +var Tail = Class({ +}); + +module.exports = Tail; + diff --git a/node_modules/cps/package.json b/node_modules/cps/package.json new file mode 100644 index 0000000..0ac2cca --- /dev/null +++ b/node_modules/cps/package.json @@ -0,0 +1,90 @@ +{ + "_args": [ + [ + { + "raw": "cps@*", + "scope": null, + "escapedName": "cps", + "name": "cps", + "rawSpec": "*", + "spec": "*", + "type": "range" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\node-mysql" + ] + ], + "_from": "cps@*", + "_id": "cps@1.0.2", + "_inCache": true, + "_installable": true, + "_location": "/cps", + "_npmUser": { + "name": "redblaze", + "email": "redblaze2005@gmail.com" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "raw": "cps@*", + "scope": null, + "escapedName": "cps", + "name": "cps", + "rawSpec": "*", + "spec": "*", + "type": "range" + }, + "_requiredBy": [ + "/node-mysql" + ], + "_resolved": "https://registry.npmjs.org/cps/-/cps-1.0.2.tgz", + "_shasum": "2cd0b25d80f10909637e0856ad9ba634ce04ff1d", + "_shrinkwrap": null, + "_spec": "cps@*", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\node-mysql", + "author": { + "name": "Chiyan Chen" + }, + "bugs": { + "url": "https://github.com/redblaze/cps/issues" + }, + "dependencies": {}, + "description": "A continuation passing style library to help the coding of asynced programs in Javascript/Node.js.", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "2cd0b25d80f10909637e0856ad9ba634ce04ff1d", + "tarball": "https://registry.npmjs.org/cps/-/cps-1.0.2.tgz" + }, + "gitHead": "c86e117cb4082f2d8feb1650c1a3e479b46968be", + "homepage": "https://github.com/redblaze/cps", + "jam": { + "main": "lib/cps.js", + "include": [ + "lib/cps.js", + "README.md", + "LICENSE" + ] + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/redblaze/cps/raw/master/LICENSE" + } + ], + "main": "./lib/cps", + "maintainers": [ + { + "name": "redblaze", + "email": "redblaze2005@gmail.com" + } + ], + "name": "cps", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/redblaze/cps.git" + }, + "scripts": {}, + "version": "1.0.2" +} diff --git a/node_modules/cps/test/fib.js b/node_modules/cps/test/fib.js new file mode 100644 index 0000000..3e144ca --- /dev/null +++ b/node_modules/cps/test/fib.js @@ -0,0 +1,51 @@ +var cps = require('../lib/cps.js'); + +var alienAdd = function(a, b, cb) { + setTimeout(function() { + cb(null, a + b); + }, 0); +}; + +var asyncFib = function(n, cb) { + if (n < 0) { + throw new Error('fib input error'); + // return cb(new Error('fib input error')); + } + if (n == 0) {return cb(null, 1);} + if (n == 1) {return cb(null, 1);} + + var a = 1, + b = 1, + i = 2; + cps.seq([ + function(_, cb) { + cps.pwhile( + function(cb) { + cb(null, i <= n); + }, + function(cb) { + cps.seq([ + function(_, cb) { + alienAdd(a, b, cb); + }, + function(res, cb) { + a = b; + b = res; + alienAdd(i, 1, cb); + }, + function(res, cb) { + i = res; + cb(); + } + ], cb); + }, + cb + ); + }, + function(_, cb) { + cb(null, b); + } + ], cb); +}; + +module.exports = asyncFib; \ No newline at end of file diff --git a/node_modules/cps/test/test.js b/node_modules/cps/test/test.js new file mode 100644 index 0000000..937931a --- /dev/null +++ b/node_modules/cps/test/test.js @@ -0,0 +1,417 @@ + +var cps = require('../lib/cps.js'); +var fib = require('./fib'); +var assert = require("assert"); + +describe('cps', function() { + describe('seq', function() { + it('should return 3 for 1+2', function(cb) { + var a, b; + + cps.seq([ + function(_, cb) { + setTimeout(function() { + cb(null, 1); + }, 0); + }, + function(_, cb) { + a = _; + setTimeout(function() { + cb(null, 2); + }, 0); + }, + function(_, cb) { + b = _; + cb(null, a + b); + }, + function(_, cb) { + assert.equal(_, 3); + cb(); + } + ], cb); + }); + }); + + describe('pwhile', function() { + it('should return 2 for fib(2)', function(cb) { + cps.seq([ + function(_, cb) { + fib(5, cb); + }, + function(_, cb) { + assert.equal(_, 8); + cb(); + } + ], cb); + }); + + it('should not fail for huge loops', function(cb) { + this.timeout(0); + var i; + + cps.seq([ + function(_, cb) { + i = 0; + cps.rescue({ + 'try': function(cb) { + cps.pwhile( + function(cb) { + cb(null, i < 10000); + }, + function(cb) { + i++; + cb(); + }, + cb + ) + }, + 'catch': function(e, cb) { + console.log('ERROR: ', e); + throw e; + } + }, cb); + }, + function(_, cb) { + console.log('i is: ', i); + cb(); + } + ], cb); + }); + }); + + describe('pfor', function() { + it('should return 45 for the sum of 0 through 9', function(cb) { + var sum = 0; + cps.seq([ + function(_, cb) { + cps.pfor(10, function(i, cb) { + setTimeout(function() { + sum += i; + cb(); + }, 0); + }, cb); + }, + function(_, cb) { + assert.equal(sum, 45); + cb(); + } + ], cb); + }); + }); + + describe('peach', function() { + it('should return 55 for the sum of 1 through 10', function(cb) { + var sum = 0; + + cps.seq([ + function(_, cb) { + cps.peach( + [1,2,3,4,5,6,7,8,9,10], + function(el, cb) { + sum += el; + cb(); + }, + cb + ); + }, + function(_, cb) { + assert.equal(sum, 55); + cb(); + } + ], cb); + }); + }); + + describe('pmap', function() { + it('should return the list of squares of [1..10]', function(cb) { + cps.seq([ + function(_, cb) { + cps.pmap( + [1,2,3,4,5,6,7,8,9,10], + function(el, cb) { + setTimeout(function() { + cb(null, el*el); + }, 0); + }, + cb + ); + }, + function(_, cb) { + for (var i = 1; i <= 10; i++) { + assert.equal(_[i-1], i*i); + } + cb(); + } + ], cb); + }); + }); + + describe('parallel', function() { + it('should work for 3 parallel threads', function(cb) { + this.timeout(0); + + var output = []; + var start, end; + + cps.seq([ + function(_, cb) { + start = new Date(); + + cps.parallel([ + function(cb) { + setTimeout(function() { + output.push(3); + cb(new Error('kaz')); + }, 3000); + }, + function(cb) { + setTimeout(function() { + output.push(2); + cb(null, 'ok'); + }, 2000); + }, + function(cb) { + setTimeout(function() { + output.push(1); + cb(new Error('foobar')); + }, 1000); + } + ], cb); + }, + function(_, cb) { + end = new Date(); + + assert(end-start < 3100, 'parallel is taking too long to run'); + + for (var i = 1; i <= 3; i++) { + assert.equal(output[i-1], i); + } + + assert.equal(_[0].status, 'error'); + assert.equal(_[0].error.message, 'kaz'); + + assert.equal(_[1].status, 'ok'); + assert.equal(_[1].data, 'ok'); + + assert.equal(_[2].status, 'error'); + assert.equal(_[2].error.message, 'foobar'); + + cb(); + } + ], cb); + }); + }); + + describe('noFail', function() { + it('should not fail on success', function(cb) { + cps.noFail(function(cb) { + cb(null, 1); + }, cb); + }); + + it('should not fail on failure', function(cb) { + cps.noFail(function(cb) { + cb(new Error('foobar')); + }, cb); + }); + }); + + describe('rescue', function() { + it('should catch errors', function(cb) { + cps.seq([ + function(_, cb) { + cps.rescue({ + 'try': function(cb) { + setTimeout(function() { + cb(new Error('foobar')); + }, 0); + }, + 'catch': function(err, cb) { + cb(null, 'ok'); + } + }, cb); + }, + function(_, cb) { + assert.equal(_, 'ok'); + cb(); + } + ], cb); + }); + + it('should be able to throw errors', function(cb) { + cps.seq([ + function(_, cb) { + cps.rescue({ + 'try': function(cb) { + setTimeout(function() { + cb(new Error('foobar')); + }, 0); + } + }, cb); + } + ], function(err, res) { + try { + assert.equal(err.message, 'foobar'); + cb(); + } catch(e) { + cb(e); + } + }); + }); + + it('should be able to rethrow errors', function(cb) { + cps.seq([ + function(_, cb) { + cps.rescue({ + 'try': function(cb) { + setTimeout(function() { + cb(new Error('foobar')); + }, 0); + }, + 'catch': function(err, cb) { + throw new Error('kaz'); + } + }, cb); + } + ], function(err, res) { + try { + assert.equal(err.message, 'kaz'); + cb(); + } catch(e) { + cb(e); + } + }); + }); + + it('should execute finally clause on success', function(cb) { + var finallyDone = false; + + cps.seq([ + function(_, cb) { + cps.rescue({ + 'try': function(cb) { + setTimeout(function() { + cb(null, 'ok'); + }, 0); + }, + 'finally': function(cb) { + finallyDone = true; + cb(); + } + }, cb); + }, + function(_, cb) { + assert.equal(_, 'ok'); + assert(finallyDone); + cb(); + } + ], cb); + }); + + it('should execute finally clause on exception being caught', function(cb) { + var finallyDone = false; + + cps.seq([ + function(_, cb) { + cps.rescue({ + 'try': function(cb) { + setTimeout(function() { + cb(new Error('foobar')); + }, 0); + }, + 'catch': function(err, cb) { + cb(null, 'exception caught'); + }, + 'finally': function(cb) { + finallyDone = true; + cb(); + } + }, cb); + }, + function(_, cb) { + assert.equal(_, 'exception caught'); + assert(finallyDone); + cb(); + } + ], cb); + }); + + it('should execute finally clause on exception', function(cb) { + var finallyDone = false; + + cps.seq([ + function(_, cb) { + cps.rescue({ + 'try': function(cb) { + setTimeout(function() { + cb(new Error('foobar')); + }, 0); + }, + 'finally': function(cb) { + finallyDone = true; + cb(); + } + }, cb); + } + ], function(err, res) { + try{ + assert.equal(err.message, 'foobar'); + assert(finallyDone); + cb(); + } catch(e) { + cb(e); + } + }); + }); + + it('should throw exception in finally clause on success', function(cb) { + cps.seq([ + function(_, cb) { + cps.rescue({ + 'try': function(cb) { + setTimeout(function() { + cb(null, 'ok'); + }, 0); + }, + 'finally': function(cb) { + throw new Error('error in finally'); + cb(); + } + }, cb); + } + ], function(err, res) { + try{ + assert.equal(err.message, 'error in finally'); + cb(); + } catch(e) { + cb(e); + } + }); + }); + + it('should throw exception in finally clause on exception', function(cb) { + cps.seq([ + function(_, cb) { + cps.rescue({ + 'try': function(cb) { + setTimeout(function() { + cb(new Error('foobar')); + }, 0); + }, + 'finally': function(cb) { + throw new Error('error in finally'); + cb(); + } + }, cb); + } + ], function(err, res) { + try{ + assert.equal(err.message, 'error in finally'); + cb(); + } catch(e) { + cb(e); + } + }); + }); + }); +}); \ No newline at end of file diff --git a/node_modules/crc/LICENSE b/node_modules/crc/LICENSE new file mode 100644 index 0000000..c49097c --- /dev/null +++ b/node_modules/crc/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright 2014 Alex Gorbatchev + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/crc/README.md b/node_modules/crc/README.md new file mode 100644 index 0000000..499b766 --- /dev/null +++ b/node_modules/crc/README.md @@ -0,0 +1,100 @@ +# crc + +[![GitTip](http://img.shields.io/gittip/alexgorbatchev.svg?style=flat)](https://www.gittip.com/alexgorbatchev/) +[![Dependency status](http://img.shields.io/david/alexgorbatchev/node-crc.svg?style=flat)](https://david-dm.org/alexgorbatchev/node-crc) +[![devDependency Status](http://img.shields.io/david/dev/alexgorbatchev/node-crc.svg?style=flat)](https://david-dm.org/alexgorbatchev/node-crc#info=devDependencies) +[![Build Status](http://img.shields.io/travis/alexgorbatchev/node-crc.svg?style=flat&branch=master)](https://travis-ci.org/alexgorbatchev/node-crc) + +[![NPM](https://nodei.co/npm/crc.svg?style=flat)](https://npmjs.org/package/crc) + +Module for calculating Cyclic Redundancy Check (CRC) for Node.js and the Browser. + +## Features + +* Full test suite comparing values against reference `pycrc` implementation. +* Version 3.x is 3x to 4x faster than version 2.x. +* Pure JavaScript implementation, no dependencies. +* Provides CRC Tables for optimized calculations. +* Provides support for the following CRC algorithms: + * CRC1 `crc.crc1(…)` + * CRC8 `crc.crc8(…)` + * CRC8 1-Wire `crc.crc81wire(…)` + * CRC16 `crc.crc16(…)` + * CRC16 CCITT `crc.crc16ccitt(…)` + * CRC16 Modbus `crc.crc16modbus(…)` + * CRC16 Kermit `crc.crc16kermit(…)` + * CRC16 XModem `crc.crc16xmodem(…)` + * CRC24 `crc.crc24(…)` + * CRC32 `crc.crc32(…)` + +## IMPORTANT + +If you've used `crc` module prior to version 2.x, you might have some inconsistencies with the current implementation because it relied on very old code and wasn't checked against reference implementation. If you upgrading from 1.x, please take special care. + +## Support + + Please support me on [GitTip](https://www.gittip.com/alexgorbatchev/). I'm sure you know that it takes a lot of personal time to write and even more time to maintain open source projects. If you use this package, buy me a beer on GitTip or via Bitcoin [`1CZyBREeHTmy8C5zVGHZHPwqBuWFmEuUCQ`](https://blockchain.info/address/1CZyBREeHTmy8C5zVGHZHPwqBuWFmEuUCQ) + +## Installation + + npm install crc + +## Running tests + + $ npm install + $ npm test + +## Usage Example + +Calculate a CRC32: + + var crc = require('crc'); + + crc.crc32('hello').toString(16); + # => "3610a686" + +Calculate a CRC32 of a file: + + crc.crc32(fs.readFileSync('README.md', 'utf8')).toString(16); + # => "127ad531" + +Or using a `Buffer`: + + crc.crc32(fs.readFileSync('README.md')).toString(16); + # => "127ad531" + +Incrementally calculate a CRC32: + + value = crc.crc32('one'); + value = crc.crc32('two', value); + value = crc.crc32('three', value); + value.toString(16); + # => "9e1c092" + +## Thanks! + +[pycrc](http://www.tty1.net/pycrc/) library is which the source of all of the CRC tables. + +# License + +The MIT License (MIT) + +Copyright (c) 2014 Alex Gorbatchev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/crc/lib/crc1.js b/node_modules/crc/lib/crc1.js new file mode 100644 index 0000000..23e1625 --- /dev/null +++ b/node_modules/crc/lib/crc1.js @@ -0,0 +1,24 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +module.exports = (0, _define_crc2.default)('crc1', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = ~ ~previous; + var accum = 0; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + accum += byte; + } + + crc += accum % 256; + return crc % 256; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc16.js b/node_modules/crc/lib/crc16.js new file mode 100644 index 0000000..feff26a --- /dev/null +++ b/node_modules/crc/lib/crc16.js @@ -0,0 +1,27 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Generated by `./pycrc.py --algorithm=table-driven --model=crc-16 --generate=c` +var TABLE = [0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040]; + +if (typeof Int32Array !== 'undefined') TABLE = new Int32Array(TABLE); + +module.exports = (0, _define_crc2.default)('crc-16', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = ~ ~previous; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + crc = (TABLE[(crc ^ byte) & 0xff] ^ crc >> 8) & 0xffff; + } + + return crc; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc16_ccitt.js b/node_modules/crc/lib/crc16_ccitt.js new file mode 100644 index 0000000..01051d1 --- /dev/null +++ b/node_modules/crc/lib/crc16_ccitt.js @@ -0,0 +1,27 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Generated by `./pycrc.py --algorithm=table-driven --model=ccitt --generate=c` +var TABLE = [0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0]; + +if (typeof Int32Array !== 'undefined') TABLE = new Int32Array(TABLE); + +module.exports = (0, _define_crc2.default)('ccitt', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = typeof previous !== 'undefined' ? ~ ~previous : 0xffff; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + crc = (TABLE[(crc >> 8 ^ byte) & 0xff] ^ crc << 8) & 0xffff; + } + + return crc; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc16_kermit.js b/node_modules/crc/lib/crc16_kermit.js new file mode 100644 index 0000000..9174f4f --- /dev/null +++ b/node_modules/crc/lib/crc16_kermit.js @@ -0,0 +1,27 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Generated by `./pycrc.py --algorithm=table-driven --model=kermit --generate=c` +var TABLE = [0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78]; + +if (typeof Int32Array !== 'undefined') TABLE = new Int32Array(TABLE); + +module.exports = (0, _define_crc2.default)('kermit', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = typeof previous !== 'undefined' ? ~ ~previous : 0x0000; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + crc = (TABLE[(crc ^ byte) & 0xff] ^ crc >> 8) & 0xffff; + } + + return crc; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc16_modbus.js b/node_modules/crc/lib/crc16_modbus.js new file mode 100644 index 0000000..7ce82a0 --- /dev/null +++ b/node_modules/crc/lib/crc16_modbus.js @@ -0,0 +1,27 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Generated by `./pycrc.py --algorithm=table-driven --model=crc-16-modbus --generate=c` +var TABLE = [0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040]; + +if (typeof Int32Array !== 'undefined') TABLE = new Int32Array(TABLE); + +module.exports = (0, _define_crc2.default)('crc-16-modbus', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = typeof previous !== 'undefined' ? ~ ~previous : 0xffff; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + crc = (TABLE[(crc ^ byte) & 0xff] ^ crc >> 8) & 0xffff; + } + + return crc; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc16_xmodem.js b/node_modules/crc/lib/crc16_xmodem.js new file mode 100644 index 0000000..2bc58a6 --- /dev/null +++ b/node_modules/crc/lib/crc16_xmodem.js @@ -0,0 +1,31 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +module.exports = (0, _define_crc2.default)('xmodem', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = typeof previous !== 'undefined' ? ~ ~previous : 0x0; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + var code = crc >>> 8 & 0xFF; + + code ^= byte & 0xFF; + code ^= code >>> 4; + crc = crc << 8 & 0xFFFF; + crc ^= code; + code = code << 5 & 0xFFFF; + crc ^= code; + code = code << 7 & 0xFFFF; + crc ^= code; + } + + return crc; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc24.js b/node_modules/crc/lib/crc24.js new file mode 100644 index 0000000..610aedb --- /dev/null +++ b/node_modules/crc/lib/crc24.js @@ -0,0 +1,27 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Generated by `./pycrc.py --algorithm=table-drive --model=crc-24 --generate=c` +var TABLE = [0x000000, 0x864cfb, 0x8ad50d, 0x0c99f6, 0x93e6e1, 0x15aa1a, 0x1933ec, 0x9f7f17, 0xa18139, 0x27cdc2, 0x2b5434, 0xad18cf, 0x3267d8, 0xb42b23, 0xb8b2d5, 0x3efe2e, 0xc54e89, 0x430272, 0x4f9b84, 0xc9d77f, 0x56a868, 0xd0e493, 0xdc7d65, 0x5a319e, 0x64cfb0, 0xe2834b, 0xee1abd, 0x685646, 0xf72951, 0x7165aa, 0x7dfc5c, 0xfbb0a7, 0x0cd1e9, 0x8a9d12, 0x8604e4, 0x00481f, 0x9f3708, 0x197bf3, 0x15e205, 0x93aefe, 0xad50d0, 0x2b1c2b, 0x2785dd, 0xa1c926, 0x3eb631, 0xb8faca, 0xb4633c, 0x322fc7, 0xc99f60, 0x4fd39b, 0x434a6d, 0xc50696, 0x5a7981, 0xdc357a, 0xd0ac8c, 0x56e077, 0x681e59, 0xee52a2, 0xe2cb54, 0x6487af, 0xfbf8b8, 0x7db443, 0x712db5, 0xf7614e, 0x19a3d2, 0x9fef29, 0x9376df, 0x153a24, 0x8a4533, 0x0c09c8, 0x00903e, 0x86dcc5, 0xb822eb, 0x3e6e10, 0x32f7e6, 0xb4bb1d, 0x2bc40a, 0xad88f1, 0xa11107, 0x275dfc, 0xdced5b, 0x5aa1a0, 0x563856, 0xd074ad, 0x4f0bba, 0xc94741, 0xc5deb7, 0x43924c, 0x7d6c62, 0xfb2099, 0xf7b96f, 0x71f594, 0xee8a83, 0x68c678, 0x645f8e, 0xe21375, 0x15723b, 0x933ec0, 0x9fa736, 0x19ebcd, 0x8694da, 0x00d821, 0x0c41d7, 0x8a0d2c, 0xb4f302, 0x32bff9, 0x3e260f, 0xb86af4, 0x2715e3, 0xa15918, 0xadc0ee, 0x2b8c15, 0xd03cb2, 0x567049, 0x5ae9bf, 0xdca544, 0x43da53, 0xc596a8, 0xc90f5e, 0x4f43a5, 0x71bd8b, 0xf7f170, 0xfb6886, 0x7d247d, 0xe25b6a, 0x641791, 0x688e67, 0xeec29c, 0x3347a4, 0xb50b5f, 0xb992a9, 0x3fde52, 0xa0a145, 0x26edbe, 0x2a7448, 0xac38b3, 0x92c69d, 0x148a66, 0x181390, 0x9e5f6b, 0x01207c, 0x876c87, 0x8bf571, 0x0db98a, 0xf6092d, 0x7045d6, 0x7cdc20, 0xfa90db, 0x65efcc, 0xe3a337, 0xef3ac1, 0x69763a, 0x578814, 0xd1c4ef, 0xdd5d19, 0x5b11e2, 0xc46ef5, 0x42220e, 0x4ebbf8, 0xc8f703, 0x3f964d, 0xb9dab6, 0xb54340, 0x330fbb, 0xac70ac, 0x2a3c57, 0x26a5a1, 0xa0e95a, 0x9e1774, 0x185b8f, 0x14c279, 0x928e82, 0x0df195, 0x8bbd6e, 0x872498, 0x016863, 0xfad8c4, 0x7c943f, 0x700dc9, 0xf64132, 0x693e25, 0xef72de, 0xe3eb28, 0x65a7d3, 0x5b59fd, 0xdd1506, 0xd18cf0, 0x57c00b, 0xc8bf1c, 0x4ef3e7, 0x426a11, 0xc426ea, 0x2ae476, 0xaca88d, 0xa0317b, 0x267d80, 0xb90297, 0x3f4e6c, 0x33d79a, 0xb59b61, 0x8b654f, 0x0d29b4, 0x01b042, 0x87fcb9, 0x1883ae, 0x9ecf55, 0x9256a3, 0x141a58, 0xefaaff, 0x69e604, 0x657ff2, 0xe33309, 0x7c4c1e, 0xfa00e5, 0xf69913, 0x70d5e8, 0x4e2bc6, 0xc8673d, 0xc4fecb, 0x42b230, 0xddcd27, 0x5b81dc, 0x57182a, 0xd154d1, 0x26359f, 0xa07964, 0xace092, 0x2aac69, 0xb5d37e, 0x339f85, 0x3f0673, 0xb94a88, 0x87b4a6, 0x01f85d, 0x0d61ab, 0x8b2d50, 0x145247, 0x921ebc, 0x9e874a, 0x18cbb1, 0xe37b16, 0x6537ed, 0x69ae1b, 0xefe2e0, 0x709df7, 0xf6d10c, 0xfa48fa, 0x7c0401, 0x42fa2f, 0xc4b6d4, 0xc82f22, 0x4e63d9, 0xd11cce, 0x575035, 0x5bc9c3, 0xdd8538]; + +if (typeof Int32Array !== 'undefined') TABLE = new Int32Array(TABLE); + +module.exports = (0, _define_crc2.default)('crc-24', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = typeof previous !== 'undefined' ? ~ ~previous : 0xb704ce; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + crc = (TABLE[(crc >> 16 ^ byte) & 0xff] ^ crc << 8) & 0xffffff; + } + + return crc; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc32.js b/node_modules/crc/lib/crc32.js new file mode 100644 index 0000000..f52abc9 --- /dev/null +++ b/node_modules/crc/lib/crc32.js @@ -0,0 +1,27 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Generated by `./pycrc.py --algorithm=table-driven --model=crc-32 --generate=c` +var TABLE = [0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d]; + +if (typeof Int32Array !== 'undefined') TABLE = new Int32Array(TABLE); + +module.exports = (0, _define_crc2.default)('crc-32', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = previous === 0 ? 0 : ~ ~previous ^ -1; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + crc = TABLE[(crc ^ byte) & 0xff] ^ crc >>> 8; + } + + return crc ^ -1; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc8.js b/node_modules/crc/lib/crc8.js new file mode 100644 index 0000000..97feb1c --- /dev/null +++ b/node_modules/crc/lib/crc8.js @@ -0,0 +1,27 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Generated by `./pycrc.py --algorithm=table-driven --model=crc-8 --generate=c` +var TABLE = [0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3]; + +if (typeof Int32Array !== 'undefined') TABLE = new Int32Array(TABLE); + +module.exports = (0, _define_crc2.default)('crc-8', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = ~ ~previous; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + crc = TABLE[(crc ^ byte) & 0xff] & 0xff; + } + + return crc; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/crc8_1wire.js b/node_modules/crc/lib/crc8_1wire.js new file mode 100644 index 0000000..d5ced54 --- /dev/null +++ b/node_modules/crc/lib/crc8_1wire.js @@ -0,0 +1,27 @@ +'use strict'; + +var _buffer = require('buffer'); + +var _define_crc = require('./define_crc'); + +var _define_crc2 = _interopRequireDefault(_define_crc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Generated by `./pycrc.py --algorithm=table-driven --model=dallas-1-wire --generate=c` +var TABLE = [0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41, 0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc, 0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62, 0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff, 0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5, 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07, 0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58, 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a, 0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24, 0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b, 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9, 0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd, 0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, 0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50, 0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c, 0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee, 0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1, 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73, 0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49, 0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b, 0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4, 0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16, 0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a, 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8, 0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, 0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35]; + +if (typeof Int32Array !== 'undefined') TABLE = new Int32Array(TABLE); + +module.exports = (0, _define_crc2.default)('dallas-1-wire', function (buf, previous) { + if (!_buffer.Buffer.isBuffer(buf)) buf = (0, _buffer.Buffer)(buf); + + var crc = ~ ~previous; + + for (var index = 0; index < buf.length; index++) { + var byte = buf[index]; + crc = TABLE[(crc ^ byte) & 0xff] & 0xff; + } + + return crc; +}); \ No newline at end of file diff --git a/node_modules/crc/lib/define_crc.js b/node_modules/crc/lib/define_crc.js new file mode 100644 index 0000000..70c3bdc --- /dev/null +++ b/node_modules/crc/lib/define_crc.js @@ -0,0 +1,16 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (model, calc) { + var fn = function fn(buf, previous) { + return calc(buf, previous) >>> 0; + }; + fn.signed = calc; + fn.unsigned = fn; + fn.model = model; + + return fn; +}; \ No newline at end of file diff --git a/node_modules/crc/lib/index.js b/node_modules/crc/lib/index.js new file mode 100644 index 0000000..d25d8df --- /dev/null +++ b/node_modules/crc/lib/index.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + crc1: require('./crc1'), + crc8: require('./crc8'), + crc81wire: require('./crc8_1wire'), + crc16: require('./crc16'), + crc16ccitt: require('./crc16_ccitt'), + crc16modbus: require('./crc16_modbus'), + crc16xmodem: require('./crc16_xmodem'), + crc16kermit: require('./crc16_kermit'), + crc24: require('./crc24'), + crc32: require('./crc32') +}; \ No newline at end of file diff --git a/node_modules/crc/package.json b/node_modules/crc/package.json new file mode 100644 index 0000000..0632521 --- /dev/null +++ b/node_modules/crc/package.json @@ -0,0 +1,102 @@ +{ + "_args": [ + [ + { + "raw": "crc@3.4.0", + "scope": null, + "escapedName": "crc", + "name": "crc", + "rawSpec": "3.4.0", + "spec": "3.4.0", + "type": "version" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express-session" + ] + ], + "_from": "crc@3.4.0", + "_id": "crc@3.4.0", + "_inCache": true, + "_installable": true, + "_location": "/crc", + "_nodeVersion": "0.12.7", + "_npmUser": { + "name": "alexgorbatchev", + "email": "alex.gorbatchev@gmail.com" + }, + "_npmVersion": "2.11.3", + "_phantomChildren": {}, + "_requested": { + "raw": "crc@3.4.0", + "scope": null, + "escapedName": "crc", + "name": "crc", + "rawSpec": "3.4.0", + "spec": "3.4.0", + "type": "version" + }, + "_requiredBy": [ + "/express-session" + ], + "_resolved": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz", + "_shasum": "4258e351613a74ef1153dfcb05e820c3e9715d7f", + "_shrinkwrap": null, + "_spec": "crc@3.4.0", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express-session", + "author": { + "name": "Alex Gorbatchev", + "url": "https://github.com/alexgorbatchev" + }, + "babel": { + "presets": [ + "es2015" + ] + }, + "bugs": { + "url": "https://github.com/alexgorbatchev/node-crc/issues" + }, + "dependencies": {}, + "description": "Module for calculating Cyclic Redundancy Check (CRC) for Node.js and the Browser.", + "devDependencies": { + "babel-core": "^6.1.21", + "babel-preset-es2015": "^6.1.18", + "beautify-benchmark": "^0.2.4", + "benchmark": "^1.0.0", + "buffer-crc32": "^0.2.3", + "chai": "^3.4.1", + "mocha": "*", + "seedrandom": "^2.3.6" + }, + "directories": {}, + "dist": { + "shasum": "4258e351613a74ef1153dfcb05e820c3e9715d7f", + "tarball": "https://registry.npmjs.org/crc/-/crc-3.4.0.tgz" + }, + "files": [ + "lib" + ], + "gitHead": "3726e792cb4a328ef2d935cfd896e54fa9529aaf", + "homepage": "https://github.com/alexgorbatchev/node-crc", + "keywords": [ + "crc" + ], + "license": "MIT", + "main": "./lib/index.js", + "maintainers": [ + { + "name": "alexgorbatchev", + "email": "alex.gorbatchev@gmail.com" + } + ], + "name": "crc", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/alexgorbatchev/node-crc.git" + }, + "scripts": { + "pretest": "cd src && babel --out-dir ../lib *.js", + "test": "mocha test/*.test.js" + }, + "version": "3.4.0" +} diff --git a/node_modules/crypt/LICENSE.mkd b/node_modules/crypt/LICENSE.mkd new file mode 100644 index 0000000..96d4c42 --- /dev/null +++ b/node_modules/crypt/LICENSE.mkd @@ -0,0 +1,27 @@ +Copyright © 2011, Paul Vorbach. All rights reserved. +Copyright © 2009, Jeff Mott. All rights reserved. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name Crypto-JS nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/crypt/README.mkd b/node_modules/crypt/README.mkd new file mode 100644 index 0000000..2b1169f --- /dev/null +++ b/node_modules/crypt/README.mkd @@ -0,0 +1 @@ +**crypt** provides utilities for encryption and hashing diff --git a/node_modules/crypt/crypt.js b/node_modules/crypt/crypt.js new file mode 100644 index 0000000..4ec0907 --- /dev/null +++ b/node_modules/crypt/crypt.js @@ -0,0 +1,96 @@ +(function() { + var base64map + = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + + crypt = { + // Bit-wise rotation left + rotl: function(n, b) { + return (n << b) | (n >>> (32 - b)); + }, + + // Bit-wise rotation right + rotr: function(n, b) { + return (n << (32 - b)) | (n >>> b); + }, + + // Swap big-endian to little-endian and vice versa + endian: function(n) { + // If number given, swap endian + if (n.constructor == Number) { + return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00; + } + + // Else, assume array and swap all items + for (var i = 0; i < n.length; i++) + n[i] = crypt.endian(n[i]); + return n; + }, + + // Generate an array of any length of random bytes + randomBytes: function(n) { + for (var bytes = []; n > 0; n--) + bytes.push(Math.floor(Math.random() * 256)); + return bytes; + }, + + // Convert a byte array to big-endian 32-bit words + bytesToWords: function(bytes) { + for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) + words[b >>> 5] |= bytes[i] << (24 - b % 32); + return words; + }, + + // Convert big-endian 32-bit words to a byte array + wordsToBytes: function(words) { + for (var bytes = [], b = 0; b < words.length * 32; b += 8) + bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); + return bytes; + }, + + // Convert a byte array to a hex string + bytesToHex: function(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(''); + }, + + // Convert a hex string to a byte array + hexToBytes: function(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; + }, + + // Convert a byte array to a base-64 string + bytesToBase64: function(bytes) { + for (var base64 = [], i = 0; i < bytes.length; i += 3) { + var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; + for (var j = 0; j < 4; j++) + if (i * 8 + j * 6 <= bytes.length * 8) + base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); + else + base64.push('='); + } + return base64.join(''); + }, + + // Convert a base-64 string to a byte array + base64ToBytes: function(base64) { + // Remove non-base-64 characters + base64 = base64.replace(/[^A-Z0-9+\/]/ig, ''); + + for (var bytes = [], i = 0, imod4 = 0; i < base64.length; + imod4 = ++i % 4) { + if (imod4 == 0) continue; + bytes.push(((base64map.indexOf(base64.charAt(i - 1)) + & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) + | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); + } + return bytes; + } + }; + + module.exports = crypt; +})(); diff --git a/node_modules/crypt/package.json b/node_modules/crypt/package.json new file mode 100644 index 0000000..948452f --- /dev/null +++ b/node_modules/crypt/package.json @@ -0,0 +1,86 @@ +{ + "_args": [ + [ + { + "raw": "crypt@~0.0.1", + "scope": null, + "escapedName": "crypt", + "name": "crypt", + "rawSpec": "~0.0.1", + "spec": ">=0.0.1 <0.1.0", + "type": "range" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\md5" + ] + ], + "_defaultsLoaded": true, + "_engineSupported": true, + "_from": "crypt@>=0.0.1 <0.1.0", + "_id": "crypt@0.0.1", + "_inCache": true, + "_installable": true, + "_location": "/crypt", + "_nodeVersion": "v0.4.12", + "_npmUser": { + "name": "pvorb", + "email": "paul@vorb.de" + }, + "_npmVersion": "1.0.103", + "_phantomChildren": {}, + "_requested": { + "raw": "crypt@~0.0.1", + "scope": null, + "escapedName": "crypt", + "name": "crypt", + "rawSpec": "~0.0.1", + "spec": ">=0.0.1 <0.1.0", + "type": "range" + }, + "_requiredBy": [ + "/md5" + ], + "_resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.1.tgz", + "_shasum": "5f11b21a6c05ef1b5e79708366da6374ece1e6a2", + "_shrinkwrap": null, + "_spec": "crypt@~0.0.1", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\md5", + "author": { + "name": "Paul Vorbach", + "email": "paul@vorb.de", + "url": "http://vorb.de" + }, + "bugs": { + "url": "https://github.com/pvorb/node-crypt/issues" + }, + "dependencies": {}, + "description": "utilities for encryption and hashing", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "5f11b21a6c05ef1b5e79708366da6374ece1e6a2", + "tarball": "https://registry.npmjs.org/crypt/-/crypt-0.0.1.tgz" + }, + "engines": { + "node": "*" + }, + "homepage": "https://github.com/pvorb/node-crypt#readme", + "main": "crypt.js", + "maintainers": [ + { + "name": "pvorb", + "email": "paul@vorb.de" + } + ], + "name": "crypt", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/pvorb/node-crypt.git" + }, + "tags": [ + "hash", + "security" + ], + "version": "0.0.1" +} diff --git a/node_modules/css-parse/.npmignore b/node_modules/css-parse/.npmignore new file mode 100644 index 0000000..4a3c398 --- /dev/null +++ b/node_modules/css-parse/.npmignore @@ -0,0 +1,6 @@ +support +test +examples +*.sock +test.css +test.js diff --git a/node_modules/css-parse/History.md b/node_modules/css-parse/History.md new file mode 100644 index 0000000..5276aab --- /dev/null +++ b/node_modules/css-parse/History.md @@ -0,0 +1,30 @@ + +1.0.4 / 2012-09-17 +================== + + * fix keyframes float percentages + * fix an issue with comments containing slashes. + +1.0.3 / 2012-09-01 +================== + + * add component support + * fix unquoted data uris [rstacruz] + * fix keyframe names with no whitespace [rstacruz] + * fix excess semicolon support [rstacruz] + +1.0.2 / 2012-09-01 +================== + + * fix IE property hack support [rstacruz] + * fix quoted strings in declarations [rstacruz] + +1.0.1 / 2012-07-26 +================== + + * change "selector" to "selectors" array + +1.0.0 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/css-parse/Makefile b/node_modules/css-parse/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/css-parse/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/css-parse/Readme.md b/node_modules/css-parse/Readme.md new file mode 100644 index 0000000..fde74a5 --- /dev/null +++ b/node_modules/css-parse/Readme.md @@ -0,0 +1,62 @@ + +# css-parse + + CSS parser. + +## Example + +js: + +```js +var parse = require('css-parse') +parse('tobi { name: "tobi" }') +``` + +object returned: + +```json +{ + "stylesheet": { + "rules": [ + { + "selectors": ["tobi"], + "declarations": [ + { + "property": "name", + "value": "tobi" + } + ] + } + ] + } +} +``` + +## Performance + + Parsed 15,000 lines of CSS (2mb) in 40ms on my macbook air. + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/css-parse/component.json b/node_modules/css-parse/component.json new file mode 100644 index 0000000..234ebbe --- /dev/null +++ b/node_modules/css-parse/component.json @@ -0,0 +1,8 @@ +{ + "name": "css-parse", + "repo": "visionmedia/node-css-parse", + "version": "1.0.3", + "description": "CSS parser", + "keywords": ["css", "parser", "stylesheet"], + "scripts": ["index.js"] +} \ No newline at end of file diff --git a/node_modules/css-parse/index.js b/node_modules/css-parse/index.js new file mode 100644 index 0000000..3ed278f --- /dev/null +++ b/node_modules/css-parse/index.js @@ -0,0 +1,265 @@ + +module.exports = function(css){ + + /** + * Parse stylesheet. + */ + + function stylesheet() { + return { stylesheet: { rules: rules() }}; + } + + /** + * Opening brace. + */ + + function open() { + return match(/^{\s*/); + } + + /** + * Closing brace. + */ + + function close() { + return match(/^}\s*/); + } + + /** + * Parse ruleset. + */ + + function rules() { + var node; + var rules = []; + whitespace(); + comments(); + while (css[0] != '}' && (node = atrule() || rule())) { + comments(); + rules.push(node); + } + return rules; + } + + /** + * Match `re` and return captures. + */ + + function match(re) { + var m = re.exec(css); + if (!m) return; + css = css.slice(m[0].length); + return m; + } + + /** + * Parse whitespace. + */ + + function whitespace() { + match(/^\s*/); + } + + /** + * Parse comments; + */ + + function comments() { + while (comment()) ; + } + + /** + * Parse comment. + */ + + function comment() { + if ('/' == css[0] && '*' == css[1]) { + var i = 2; + while ('*' != css[i] || '/' != css[i + 1]) ++i; + i += 2; + css = css.slice(i); + whitespace(); + return true; + } + } + + /** + * Parse selector. + */ + + function selector() { + var m = match(/^([^{]+)/); + if (!m) return; + return m[0].trim().split(/\s*,\s*/); + } + + /** + * Parse declaration. + */ + + function declaration() { + // prop + var prop = match(/^(\*?[-\w]+)\s*/); + if (!prop) return; + prop = prop[0]; + + // : + if (!match(/^:\s*/)) return; + + // val + var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)\s*/); + if (!val) return; + val = val[0].trim(); + + // ; + match(/^[;\s]*/); + + return { property: prop, value: val }; + } + + /** + * Parse keyframe. + */ + + function keyframe() { + var m; + var vals = []; + + while (m = match(/^(from|to|\d+%|\.\d+%|\d+\.\d+%)\s*/)) { + vals.push(m[1]); + match(/^,\s*/); + } + + if (!vals.length) return; + + return { + values: vals, + declarations: declarations() + }; + } + + /** + * Parse keyframes. + */ + + function keyframes() { + var m = match(/^@([-\w]+)?keyframes */); + if (!m) return; + var vendor = m[1]; + + // identifier + var m = match(/^([-\w]+)\s*/); + if (!m) return; + var name = m[1]; + + if (!open()) return; + comments(); + + var frame; + var frames = []; + while (frame = keyframe()) { + frames.push(frame); + comments(); + } + + if (!close()) return; + + return { + name: name, + vendor: vendor, + keyframes: frames + }; + } + + /** + * Parse media. + */ + + function media() { + var m = match(/^@media *([^{]+)/); + if (!m) return; + var media = m[1].trim(); + + if (!open()) return; + comments(); + + var style = rules(); + + if (!close()) return; + + return { media: media, rules: style }; + } + + /** + * Parse import + */ + + function atimport() { + return _atrule('import') + } + + /** + * Parse charset + */ + + function atcharset() { + return _atrule('charset'); + } + + /** + * Parse non-block at-rules + */ + + function _atrule(name) { + var m = match(new RegExp('^@' + name + ' *([^;\\n]+);\\s*')); + if (!m) return; + var ret = {} + ret[name] = m[1].trim(); + return ret; + } + + /** + * Parse declarations. + */ + + function declarations() { + var decls = []; + + if (!open()) return; + comments(); + + // declarations + var decl; + while (decl = declaration()) { + decls.push(decl); + comments(); + } + + if (!close()) return; + return decls; + } + + /** + * Parse at rule. + */ + + function atrule() { + return keyframes() + || media() + || atimport() + || atcharset(); + } + + /** + * Parse rule. + */ + + function rule() { + var sel = selector(); + if (!sel) return; + comments(); + return { selectors: sel, declarations: declarations() }; + } + + return stylesheet(); +}; diff --git a/node_modules/css-parse/package.json b/node_modules/css-parse/package.json new file mode 100644 index 0000000..a9b829f --- /dev/null +++ b/node_modules/css-parse/package.json @@ -0,0 +1,75 @@ +{ + "_args": [ + [ + { + "raw": "css-parse@1.0.4", + "scope": null, + "escapedName": "css-parse", + "name": "css-parse", + "rawSpec": "1.0.4", + "spec": "1.0.4", + "type": "version" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\css" + ] + ], + "_from": "css-parse@1.0.4", + "_id": "css-parse@1.0.4", + "_inCache": true, + "_installable": true, + "_location": "/css-parse", + "_npmUser": { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + "_npmVersion": "1.1.61", + "_phantomChildren": {}, + "_requested": { + "raw": "css-parse@1.0.4", + "scope": null, + "escapedName": "css-parse", + "name": "css-parse", + "rawSpec": "1.0.4", + "spec": "1.0.4", + "type": "version" + }, + "_requiredBy": [ + "/css" + ], + "_resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz", + "_shasum": "38b0503fbf9da9f54e9c1dbda60e145c77117bdd", + "_shrinkwrap": null, + "_spec": "css-parse@1.0.4", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\css", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "description": "CSS parser", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "directories": {}, + "dist": { + "shasum": "38b0503fbf9da9f54e9c1dbda60e145c77117bdd", + "tarball": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz" + }, + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "main": "index", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "name": "css-parse", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "version": "1.0.4" +} diff --git a/node_modules/css-stringify/.npmignore b/node_modules/css-stringify/.npmignore new file mode 100644 index 0000000..4a3c398 --- /dev/null +++ b/node_modules/css-stringify/.npmignore @@ -0,0 +1,6 @@ +support +test +examples +*.sock +test.css +test.js diff --git a/node_modules/css-stringify/History.md b/node_modules/css-stringify/History.md new file mode 100644 index 0000000..a6ff960 --- /dev/null +++ b/node_modules/css-stringify/History.md @@ -0,0 +1,30 @@ + +1.0.5 / 2013-03-15 +================== + + * fix indentation of multiple selectors in @media. Closes #11 + +1.0.4 / 2012-11-15 +================== + + * fix indentation + +1.0.3 / 2012-09-04 +================== + + * add __@charset__ support [rstacruz] + +1.0.2 / 2012-09-01 +================== + + * add component support + +1.0.1 / 2012-07-26 +================== + + * add "selectors" array support + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/css-stringify/Makefile b/node_modules/css-stringify/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/css-stringify/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/css-stringify/Readme.md b/node_modules/css-stringify/Readme.md new file mode 100644 index 0000000..a36e780 --- /dev/null +++ b/node_modules/css-stringify/Readme.md @@ -0,0 +1,33 @@ + +# css-stringify + + CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse). + +## Performance + + Formats 15,000 lines of CSS (2mb) in 23ms on my macbook air. + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/css-stringify/component.json b/node_modules/css-stringify/component.json new file mode 100644 index 0000000..259baef --- /dev/null +++ b/node_modules/css-stringify/component.json @@ -0,0 +1,8 @@ +{ + "name": "css-stringify", + "repo": "visionmedia/css-stringify", + "version": "1.0.5", + "description": "CSS compiler", + "keywords": ["css", "stringify", "stylesheet"], + "scripts": ["index.js"] +} diff --git a/node_modules/css-stringify/index.js b/node_modules/css-stringify/index.js new file mode 100644 index 0000000..f528e41 --- /dev/null +++ b/node_modules/css-stringify/index.js @@ -0,0 +1,182 @@ + +/** + * Stringfy the given AST `node`. + * + * @param {Object} node + * @param {Object} options + * @return {String} + * @api public + */ + +module.exports = function(node, options){ + return new Compiler(options).compile(node); +}; + +/** + * Initialize a new `Compiler`. + */ + +function Compiler(options) { + options = options || {}; + this.compress = options.compress; + this.indentation = options.indent; +} + +/** + * Compile `node`. + */ + +Compiler.prototype.compile = function(node){ + return node.stylesheet.rules.map(this.visit, this) + .join(this.compress ? '' : '\n\n'); +}; + +/** + * Visit `node`. + */ + +Compiler.prototype.visit = function(node){ + if (node.charset) return this.charset(node); + if (node.keyframes) return this.keyframes(node); + if (node.media) return this.media(node); + if (node.import) return this.import(node); + return this.rule(node); +}; + +/** + * Visit import node. + */ + +Compiler.prototype.import = function(node){ + return '@import ' + node.import + ';'; +}; + +/** + * Visit media node. + */ + +Compiler.prototype.media = function(node){ + if (this.compress) { + return '@media ' + + node.media + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; + } + + return '@media ' + + node.media + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit charset node. + */ + +Compiler.prototype.charset = function(node){ + if (this.compress) { + return '@charset ' + node.charset + ';'; + } + + return '@charset ' + node.charset + ';\n'; +}; + +/** + * Visit keyframes node. + */ + +Compiler.prototype.keyframes = function(node){ + if (this.compress) { + return '@' + + (node.vendor || '') + + 'keyframes ' + + node.name + + '{' + + node.keyframes.map(this.keyframe, this).join('') + + '}'; + } + + return '@' + + (node.vendor || '') + + 'keyframes ' + + node.name + + ' {\n' + + this.indent(1) + + node.keyframes.map(this.keyframe, this).join('\n') + + this.indent(-1) + + '}'; +}; + +/** + * Visit keyframe node. + */ + +Compiler.prototype.keyframe = function(node){ + if (this.compress) { + return node.values.join(',') + + '{' + + node.declarations.map(this.declaration, this).join(';') + + '}'; + } + + return this.indent() + + node.values.join(', ') + + ' {\n' + + this.indent(1) + + node.declarations.map(this.declaration, this).join(';\n') + + this.indent(-1) + + '\n' + this.indent() + '}\n'; +}; + +/** + * Visit rule node. + */ + +Compiler.prototype.rule = function(node){ + var indent = this.indent(); + + if (this.compress) { + return node.selectors.join(',') + + '{' + + node.declarations.map(this.declaration, this).join(';') + + '}'; + } + + return node.selectors.map(function(s){ return indent + s }).join(',\n') + + ' {\n' + + this.indent(1) + + node.declarations.map(this.declaration, this).join(';\n') + + this.indent(-1) + + '\n' + this.indent() + '}'; +}; + +/** + * Visit declaration node. + */ + +Compiler.prototype.declaration = function(node){ + if (this.compress) { + return node.property + ':' + node.value; + } + + return this.indent() + node.property + ': ' + node.value; +}; + +/** + * Increase, decrease or return current indentation. + */ + +Compiler.prototype.indent = function(level) { + this.level = this.level || 1; + + if (null != level) { + this.level += level; + return ''; + } + + return Array(this.level).join(this.indentation || ' '); +}; diff --git a/node_modules/css-stringify/package.json b/node_modules/css-stringify/package.json new file mode 100644 index 0000000..56519fb --- /dev/null +++ b/node_modules/css-stringify/package.json @@ -0,0 +1,76 @@ +{ + "_args": [ + [ + { + "raw": "css-stringify@1.0.5", + "scope": null, + "escapedName": "css-stringify", + "name": "css-stringify", + "rawSpec": "1.0.5", + "spec": "1.0.5", + "type": "version" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\css" + ] + ], + "_from": "css-stringify@1.0.5", + "_id": "css-stringify@1.0.5", + "_inCache": true, + "_installable": true, + "_location": "/css-stringify", + "_npmUser": { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + "_npmVersion": "1.2.14", + "_phantomChildren": {}, + "_requested": { + "raw": "css-stringify@1.0.5", + "scope": null, + "escapedName": "css-stringify", + "name": "css-stringify", + "rawSpec": "1.0.5", + "spec": "1.0.5", + "type": "version" + }, + "_requiredBy": [ + "/css" + ], + "_resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz", + "_shasum": "b0d042946db2953bb9d292900a6cb5f6d0122031", + "_shrinkwrap": null, + "_spec": "css-stringify@1.0.5", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\css", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "description": "CSS compiler", + "devDependencies": { + "css-parse": "1.0.3", + "mocha": "*", + "should": "*" + }, + "directories": {}, + "dist": { + "shasum": "b0d042946db2953bb9d292900a6cb5f6d0122031", + "tarball": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz" + }, + "keywords": [ + "css", + "stringify", + "stylesheet" + ], + "main": "index", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "name": "css-stringify", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "version": "1.0.5" +} diff --git a/node_modules/css/.npmignore b/node_modules/css/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/css/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/css/History.md b/node_modules/css/History.md new file mode 100644 index 0000000..93b15c2 --- /dev/null +++ b/node_modules/css/History.md @@ -0,0 +1,20 @@ + +1.0.7 / 2012-11-21 +================== + + * fix component.json + +1.0.4 / 2012-11-15 +================== + + * update css-stringify + +1.0.3 / 2012-09-01 +================== + + * add component support + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/css/Makefile b/node_modules/css/Makefile new file mode 100644 index 0000000..f13b4a7 --- /dev/null +++ b/node_modules/css/Makefile @@ -0,0 +1,8 @@ + +test: + @node test + +benchmark: + @node benchmark + +.PHONY: test benchmark \ No newline at end of file diff --git a/node_modules/css/Readme.md b/node_modules/css/Readme.md new file mode 100644 index 0000000..cf578df --- /dev/null +++ b/node_modules/css/Readme.md @@ -0,0 +1,77 @@ + +# css + + CSS parser / stringifier using [css-parse](https://github.com/visionmedia/css-parse) and [css-stringify](https://github.com/visionmedia/css-stringify). + +## Installation + + $ npm install css + +## Example + +js: + +```js +var css = require('css') +var obj = css.parse('tobi { name: "tobi" }') +css.stringify(obj); +``` + +object returned by `.parse()`: + +```json +{ + "stylesheet": { + "rules": [ + { + "selector": "tobi", + "declarations": [ + { + "property": "name", + "value": "tobi" + } + ] + } + ] + } +} +``` + +string returned by `.stringify(ast)`: + +```css +tobi { + name: tobi; +} +``` + +string returned by `.stringify(ast, { compress: true })`: + +```css +tobi{name:tobi} +``` + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/css/benchmark.js b/node_modules/css/benchmark.js new file mode 100644 index 0000000..dec711d --- /dev/null +++ b/node_modules/css/benchmark.js @@ -0,0 +1,36 @@ + +var css = require('./') + , fs = require('fs') + , read = fs.readFileSync + , str = read('examples/ui.css', 'utf8'); + +var n = 5000; +var ops = 200; +var t = process.hrtime(t); +var results = []; + +while (n--) { + css.stringify(css.parse(str)); + if (n % ops == 0) { + t = process.hrtime(t); + var ms = t[1] / 1000 / 1000; + var persec = (ops * (1000 / ms) | 0); + results.push(persec); + process.stdout.write('\r [' + persec + ' ops/s] [' + n + ']'); + t = process.hrtime(); + } +} + +function sum(arr) { + return arr.reduce(function(sum, n){ + return sum + n; + }); +} + +function mean(arr) { + return sum(arr) / arr.length | 0; +} + +console.log(); +console.log(' avg: %d ops/s', mean(results)); +console.log(' size: %d kb', (str.length / 1024).toFixed(2)); \ No newline at end of file diff --git a/node_modules/css/component.json b/node_modules/css/component.json new file mode 100644 index 0000000..2769165 --- /dev/null +++ b/node_modules/css/component.json @@ -0,0 +1,13 @@ +{ + "name": "css", + "version": "1.0.8", + "description": "CSS parser / stringifier using css-parse and css-stringify", + "keywords": ["css", "parser", "stylesheet"], + "dependencies": { + "visionmedia/css-parse": "*", + "visionmedia/css-stringify": "*" + }, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/css/index.js b/node_modules/css/index.js new file mode 100644 index 0000000..19ec91a --- /dev/null +++ b/node_modules/css/index.js @@ -0,0 +1,3 @@ + +exports.parse = require('css-parse'); +exports.stringify = require('css-stringify'); diff --git a/node_modules/css/package.json b/node_modules/css/package.json new file mode 100644 index 0000000..96489b8 --- /dev/null +++ b/node_modules/css/package.json @@ -0,0 +1,75 @@ +{ + "_args": [ + [ + { + "raw": "css@~1.0.8", + "scope": null, + "escapedName": "css", + "name": "css", + "rawSpec": "~1.0.8", + "spec": ">=1.0.8 <1.1.0", + "type": "range" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\transformers" + ] + ], + "_from": "css@>=1.0.8 <1.1.0", + "_id": "css@1.0.8", + "_inCache": true, + "_installable": true, + "_location": "/css", + "_npmUser": { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + "_npmVersion": "1.2.14", + "_phantomChildren": {}, + "_requested": { + "raw": "css@~1.0.8", + "scope": null, + "escapedName": "css", + "name": "css", + "rawSpec": "~1.0.8", + "spec": ">=1.0.8 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/transformers" + ], + "_resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", + "_shasum": "9386811ca82bccc9ee7fb5a732b1e2a317c8a3e7", + "_shrinkwrap": null, + "_spec": "css@~1.0.8", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\transformers", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": { + "css-parse": "1.0.4", + "css-stringify": "1.0.5" + }, + "description": "CSS parser / stringifier using css-parse and css-stringify", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "9386811ca82bccc9ee7fb5a732b1e2a317c8a3e7", + "tarball": "https://registry.npmjs.org/css/-/css-1.0.8.tgz" + }, + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "main": "index", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "name": "css", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "version": "1.0.8" +} diff --git a/node_modules/css/test.js b/node_modules/css/test.js new file mode 100644 index 0000000..3e1b4d3 --- /dev/null +++ b/node_modules/css/test.js @@ -0,0 +1,6 @@ + +var css = require('./') + , assert = require('assert'); + +assert(css.parse); +assert(css.stringify); diff --git a/node_modules/debug/.jshintrc b/node_modules/debug/.jshintrc new file mode 100644 index 0000000..299877f --- /dev/null +++ b/node_modules/debug/.jshintrc @@ -0,0 +1,3 @@ +{ + "laxbreak": true +} diff --git a/node_modules/debug/.npmignore b/node_modules/debug/.npmignore new file mode 100644 index 0000000..7e6163d --- /dev/null +++ b/node_modules/debug/.npmignore @@ -0,0 +1,6 @@ +support +test +examples +example +*.sock +dist diff --git a/node_modules/debug/History.md b/node_modules/debug/History.md new file mode 100644 index 0000000..854c971 --- /dev/null +++ b/node_modules/debug/History.md @@ -0,0 +1,195 @@ + +2.2.0 / 2015-05-09 +================== + + * package: update "ms" to v0.7.1 (#202, @dougwilson) + * README: add logging to file example (#193, @DanielOchoa) + * README: fixed a typo (#191, @amir-s) + * browser: expose `storage` (#190, @stephenmathieson) + * Makefile: add a `distclean` target (#189, @stephenmathieson) + +2.1.3 / 2015-03-13 +================== + + * Updated stdout/stderr example (#186) + * Updated example/stdout.js to match debug current behaviour + * Renamed example/stderr.js to stdout.js + * Update Readme.md (#184) + * replace high intensity foreground color for bold (#182, #183) + +2.1.2 / 2015-03-01 +================== + + * dist: recompile + * update "ms" to v0.7.0 + * package: update "browserify" to v9.0.3 + * component: fix "ms.js" repo location + * changed bower package name + * updated documentation about using debug in a browser + * fix: security error on safari (#167, #168, @yields) + +2.1.1 / 2014-12-29 +================== + + * browser: use `typeof` to check for `console` existence + * browser: check for `console.log` truthiness (fix IE 8/9) + * browser: add support for Chrome apps + * Readme: added Windows usage remarks + * Add `bower.json` to properly support bower install + +2.1.0 / 2014-10-15 +================== + + * node: implement `DEBUG_FD` env variable support + * package: update "browserify" to v6.1.0 + * package: add "license" field to package.json (#135, @panuhorsmalahti) + +2.0.0 / 2014-09-01 +================== + + * package: update "browserify" to v5.11.0 + * node: use stderr rather than stdout for logging (#29, @stephenmathieson) + +1.0.4 / 2014-07-15 +================== + + * dist: recompile + * example: remove `console.info()` log usage + * example: add "Content-Type" UTF-8 header to browser example + * browser: place %c marker after the space character + * browser: reset the "content" color via `color: inherit` + * browser: add colors support for Firefox >= v31 + * debug: prefer an instance `log()` function over the global one (#119) + * Readme: update documentation about styled console logs for FF v31 (#116, @wryk) + +1.0.3 / 2014-07-09 +================== + + * Add support for multiple wildcards in namespaces (#122, @seegno) + * browser: fix lint + +1.0.2 / 2014-06-10 +================== + + * browser: update color palette (#113, @gscottolson) + * common: make console logging function configurable (#108, @timoxley) + * node: fix %o colors on old node <= 0.8.x + * Makefile: find node path using shell/which (#109, @timoxley) + +1.0.1 / 2014-06-06 +================== + + * browser: use `removeItem()` to clear localStorage + * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777) + * package: add "contributors" section + * node: fix comment typo + * README: list authors + +1.0.0 / 2014-06-04 +================== + + * make ms diff be global, not be scope + * debug: ignore empty strings in enable() + * node: make DEBUG_COLORS able to disable coloring + * *: export the `colors` array + * npmignore: don't publish the `dist` dir + * Makefile: refactor to use browserify + * package: add "browserify" as a dev dependency + * Readme: add Web Inspector Colors section + * node: reset terminal color for the debug content + * node: map "%o" to `util.inspect()` + * browser: map "%j" to `JSON.stringify()` + * debug: add custom "formatters" + * debug: use "ms" module for humanizing the diff + * Readme: add "bash" syntax highlighting + * browser: add Firebug color support + * browser: add colors for WebKit browsers + * node: apply log to `console` + * rewrite: abstract common logic for Node & browsers + * add .jshintrc file + +0.8.1 / 2014-04-14 +================== + + * package: re-add the "component" section + +0.8.0 / 2014-03-30 +================== + + * add `enable()` method for nodejs. Closes #27 + * change from stderr to stdout + * remove unnecessary index.js file + +0.7.4 / 2013-11-13 +================== + + * remove "browserify" key from package.json (fixes something in browserify) + +0.7.3 / 2013-10-30 +================== + + * fix: catch localStorage security error when cookies are blocked (Chrome) + * add debug(err) support. Closes #46 + * add .browser prop to package.json. Closes #42 + +0.7.2 / 2013-02-06 +================== + + * fix package.json + * fix: Mobile Safari (private mode) is broken with debug + * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript + +0.7.1 / 2013-02-05 +================== + + * add repository URL to package.json + * add DEBUG_COLORED to force colored output + * add browserify support + * fix component. Closes #24 + +0.7.0 / 2012-05-04 +================== + + * Added .component to package.json + * Added debug.component.js build + +0.6.0 / 2012-03-16 +================== + + * Added support for "-" prefix in DEBUG [Vinay Pulim] + * Added `.enabled` flag to the node version [TooTallNate] + +0.5.0 / 2012-02-02 +================== + + * Added: humanize diffs. Closes #8 + * Added `debug.disable()` to the CS variant + * Removed padding. Closes #10 + * Fixed: persist client-side variant again. Closes #9 + +0.4.0 / 2012-02-01 +================== + + * Added browser variant support for older browsers [TooTallNate] + * Added `debug.enable('project:*')` to browser variant [TooTallNate] + * Added padding to diff (moved it to the right) + +0.3.0 / 2012-01-26 +================== + + * Added millisecond diff when isatty, otherwise UTC string + +0.2.0 / 2012-01-22 +================== + + * Added wildcard support + +0.1.0 / 2011-12-02 +================== + + * Added: remove colors unless stderr isatty [TooTallNate] + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/debug/Makefile b/node_modules/debug/Makefile new file mode 100644 index 0000000..5cf4a59 --- /dev/null +++ b/node_modules/debug/Makefile @@ -0,0 +1,36 @@ + +# get Makefile directory name: http://stackoverflow.com/a/5982798/376773 +THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) +THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd) + +# BIN directory +BIN := $(THIS_DIR)/node_modules/.bin + +# applications +NODE ?= $(shell which node) +NPM ?= $(NODE) $(shell which npm) +BROWSERIFY ?= $(NODE) $(BIN)/browserify + +all: dist/debug.js + +install: node_modules + +clean: + @rm -rf dist + +dist: + @mkdir -p $@ + +dist/debug.js: node_modules browser.js debug.js dist + @$(BROWSERIFY) \ + --standalone debug \ + . > $@ + +distclean: clean + @rm -rf node_modules + +node_modules: package.json + @NODE_ENV= $(NPM) install + @touch node_modules + +.PHONY: all install clean distclean diff --git a/node_modules/debug/Readme.md b/node_modules/debug/Readme.md new file mode 100644 index 0000000..b4f45e3 --- /dev/null +++ b/node_modules/debug/Readme.md @@ -0,0 +1,188 @@ +# debug + + tiny node.js debugging utility modelled after node core's debugging technique. + +## Installation + +```bash +$ npm install debug +``` + +## Usage + + With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility. + +Example _app.js_: + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example _worker.js_: + +```js +var debug = require('debug')('worker'); + +setInterval(function(){ + debug('doing some work'); +}, 1000); +``` + + The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: + + ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png) + + ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png) + +#### Windows note + + On Windows the environment variable is set using the `set` command. + + ```cmd + set DEBUG=*,-not_this + ``` + +Then, run the program to be debugged as usual. + +## Millisecond diff + + When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png) + + When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: + + ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png) + +## Conventions + + If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". + +## Wildcards + + The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + + You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:". + +## Browser support + + Debug works in the browser as well, currently persisted by `localStorage`. Consider the situation shown below where you have `worker:a` and `worker:b`, and wish to debug both. Somewhere in the code on your page, include: + +```js +window.myDebug = require("debug"); +``` + + ("debug" is a global object in the browser so we give this object a different name.) When your page is open in the browser, type the following in the console: + +```js +myDebug.enable("worker:*") +``` + + Refresh the page. Debug output will continue to be sent to the console until it is disabled by typing `myDebug.disable()` in the console. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + b('doing some work'); +}, 1200); +``` + +#### Web Inspector Colors + + Colors are also enabled on "Web Inspectors" that understand the `%c` formatting + option. These are WebKit web inspectors, Firefox ([since version + 31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) + and the Firebug plugin for Firefox (any version). + + Colored output looks something like: + + ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png) + +### stderr vs stdout + +You can set an alternative logging method per-namespace by overriding the `log` method on a per-namespace or globally: + +Example _stdout.js_: + +```js +var debug = require('debug'); +var error = debug('app:error'); + +// by default stderr is used +error('goes to stderr!'); + +var log = debug('app:log'); +// set this namespace to log via console.log +log.log = console.log.bind(console); // don't forget to bind to console! +log('goes to stdout'); +error('still goes to stderr!'); + +// set all output to go via console.info +// overrides all per-namespace log settings +debug.log = console.info.bind(console); +error('now goes to stdout via console.info'); +log('still goes to stdout, but via console.info now'); +``` + +### Save debug output to a file + +You can save all debug statements to a file by piping them. + +Example: + +```bash +$ DEBUG_FD=3 node your-app.js 3> whatever.log +``` + +## Authors + + - TJ Holowaychuk + - Nathan Rajlich + +## License + +(The MIT License) + +Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/debug/bower.json b/node_modules/debug/bower.json new file mode 100644 index 0000000..6af573f --- /dev/null +++ b/node_modules/debug/bower.json @@ -0,0 +1,28 @@ +{ + "name": "visionmedia-debug", + "main": "dist/debug.js", + "version": "2.2.0", + "homepage": "https://github.com/visionmedia/debug", + "authors": [ + "TJ HolowaychukLocation ' + escapeHtml(url) + ' not found
' + + // send a 404 + res.statusCode = 404 + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8'))) + res.end(body, 'utf-8') +}) +``` + +### Encode a URL for use in a header field + +```js +var encodeUrl = require('encodeurl') +var escapeHtml = require('escape-html') +var url = require('url') + +http.createServer(function onRequest (req, res) { + // parse inbound url + var href = url.parse(req) + + // set new host for redirect + href.host = 'localhost' + href.protocol = 'https:' + href.slashes = true + + // create location header + var location = encodeUrl(url.format(href)) + + // create html message + var body = 'Redirecting to new site: ' + escapeHtml(location) + '
' + + // send a 301 + res.statusCode = 301 + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8'))) + res.setHeader('Location', location) + res.end(body, 'utf-8') +}) +``` + +## Testing + +```sh +$ npm test +$ npm run lint +``` + +## References + +- [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax][rfc-3986] +- [WHATWG URL Living Standard][whatwg-url] + +[rfc-3986]: https://tools.ietf.org/html/rfc3986 +[whatwg-url]: https://url.spec.whatwg.org/ + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/encodeurl.svg +[npm-url]: https://npmjs.org/package/encodeurl +[node-version-image]: https://img.shields.io/node/v/encodeurl.svg +[node-version-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/pillarjs/encodeurl.svg +[travis-url]: https://travis-ci.org/pillarjs/encodeurl +[coveralls-image]: https://img.shields.io/coveralls/pillarjs/encodeurl.svg +[coveralls-url]: https://coveralls.io/r/pillarjs/encodeurl?branch=master +[downloads-image]: https://img.shields.io/npm/dm/encodeurl.svg +[downloads-url]: https://npmjs.org/package/encodeurl diff --git a/node_modules/encodeurl/index.js b/node_modules/encodeurl/index.js new file mode 100644 index 0000000..ae77cc9 --- /dev/null +++ b/node_modules/encodeurl/index.js @@ -0,0 +1,60 @@ +/*! + * encodeurl + * Copyright(c) 2016 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = encodeUrl + +/** + * RegExp to match non-URL code points, *after* encoding (i.e. not including "%") + * and including invalid escape sequences. + * @private + */ + +var ENCODE_CHARS_REGEXP = /(?:[^\x21\x25\x26-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]|%(?:[^0-9A-Fa-f]|[0-9A-Fa-f][^0-9A-Fa-f]))+/g + +/** + * RegExp to match unmatched surrogate pair. + * @private + */ + +var UNMATCHED_SURROGATE_PAIR_REGEXP = /(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF]([^\uDC00-\uDFFF]|$)/g + +/** + * String to replace unmatched surrogate pair with. + * @private + */ + +var UNMATCHED_SURROGATE_PAIR_REPLACE = '$1\uFFFD$2' + +/** + * Encode a URL to a percent-encoded form, excluding already-encoded sequences. + * + * This function will take an already-encoded URL and encode all the non-URL + * code points. This function will not encode the "%" character unless it is + * not part of a valid sequence (`%20` will be left as-is, but `%foo` will + * be encoded as `%25foo`). + * + * This encode is meant to be "safe" and does not throw errors. It will try as + * hard as it can to properly encode the given URL, including replacing any raw, + * unpaired surrogate pairs with the Unicode replacement character prior to + * encoding. + * + * @param {string} url + * @return {string} + * @public + */ + +function encodeUrl (url) { + return String(url) + .replace(UNMATCHED_SURROGATE_PAIR_REGEXP, UNMATCHED_SURROGATE_PAIR_REPLACE) + .replace(ENCODE_CHARS_REGEXP, encodeURI) +} diff --git a/node_modules/encodeurl/package.json b/node_modules/encodeurl/package.json new file mode 100644 index 0000000..b55abbd --- /dev/null +++ b/node_modules/encodeurl/package.json @@ -0,0 +1,112 @@ +{ + "_args": [ + [ + { + "raw": "encodeurl@~1.0.1", + "scope": null, + "escapedName": "encodeurl", + "name": "encodeurl", + "rawSpec": "~1.0.1", + "spec": ">=1.0.1 <1.1.0", + "type": "range" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express" + ] + ], + "_from": "encodeurl@>=1.0.1 <1.1.0", + "_id": "encodeurl@1.0.1", + "_inCache": true, + "_installable": true, + "_location": "/encodeurl", + "_nodeVersion": "4.4.3", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/encodeurl-1.0.1.tgz_1465519736251_0.09314409433864057" + }, + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "_npmVersion": "2.15.1", + "_phantomChildren": {}, + "_requested": { + "raw": "encodeurl@~1.0.1", + "scope": null, + "escapedName": "encodeurl", + "name": "encodeurl", + "rawSpec": "~1.0.1", + "spec": ">=1.0.1 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/express", + "/send", + "/serve-static" + ], + "_resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "_shasum": "79e3d58655346909fe6f0f45a5de68103b294d20", + "_shrinkwrap": null, + "_spec": "encodeurl@~1.0.1", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express", + "bugs": { + "url": "https://github.com/pillarjs/encodeurl/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + } + ], + "dependencies": {}, + "description": "Encode a URL to a percent-encoded form, excluding already-encoded sequences", + "devDependencies": { + "eslint": "2.11.1", + "eslint-config-standard": "5.3.1", + "eslint-plugin-promise": "1.3.2", + "eslint-plugin-standard": "1.3.2", + "istanbul": "0.4.3", + "mocha": "2.5.3" + }, + "directories": {}, + "dist": { + "shasum": "79e3d58655346909fe6f0f45a5de68103b294d20", + "tarball": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + }, + "engines": { + "node": ">= 0.8" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "README.md", + "index.js" + ], + "gitHead": "39ed0c235fed4cea7d012038fd6bb0480561d226", + "homepage": "https://github.com/pillarjs/encodeurl#readme", + "keywords": [ + "encode", + "encodeurl", + "url" + ], + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "encodeurl", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/pillarjs/encodeurl.git" + }, + "scripts": { + "lint": "eslint **/*.js", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.0.1" +} diff --git a/node_modules/escape-html/LICENSE b/node_modules/escape-html/LICENSE new file mode 100644 index 0000000..2e70de9 --- /dev/null +++ b/node_modules/escape-html/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2012-2013 TJ Holowaychuk +Copyright (c) 2015 Andreas Lubbe +Copyright (c) 2015 Tiancheng "Timothy" Gu + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/escape-html/Readme.md b/node_modules/escape-html/Readme.md new file mode 100644 index 0000000..653d9ea --- /dev/null +++ b/node_modules/escape-html/Readme.md @@ -0,0 +1,43 @@ + +# escape-html + + Escape string for use in HTML + +## Example + +```js +var escape = require('escape-html'); +var html = escape('foo & bar'); +// -> foo & bar +``` + +## Benchmark + +``` +$ npm run-script bench + +> escape-html@1.0.3 bench nodejs-escape-html +> node benchmark/index.js + + + http_parser@1.0 + node@0.10.33 + v8@3.14.5.9 + ares@1.9.0-DEV + uv@0.10.29 + zlib@1.2.3 + modules@11 + openssl@1.0.1j + + 1 test completed. + 2 tests completed. + 3 tests completed. + + no special characters x 19,435,271 ops/sec ±0.85% (187 runs sampled) + single special character x 6,132,421 ops/sec ±0.67% (194 runs sampled) + many special characters x 3,175,826 ops/sec ±0.65% (193 runs sampled) +``` + +## License + + MIT \ No newline at end of file diff --git a/node_modules/escape-html/index.js b/node_modules/escape-html/index.js new file mode 100644 index 0000000..bf9e226 --- /dev/null +++ b/node_modules/escape-html/index.js @@ -0,0 +1,78 @@ +/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */ + +'use strict'; + +/** + * Module variables. + * @private + */ + +var matchHtmlRegExp = /["'&<>]/; + +/** + * Module exports. + * @public + */ + +module.exports = escapeHtml; + +/** + * Escape special characters in the given string of html. + * + * @param {string} string The string to escape for inserting into HTML + * @return {string} + * @public + */ + +function escapeHtml(string) { + var str = '' + string; + var match = matchHtmlRegExp.exec(str); + + if (!match) { + return str; + } + + var escape; + var html = ''; + var index = 0; + var lastIndex = 0; + + for (index = match.index; index < str.length; index++) { + switch (str.charCodeAt(index)) { + case 34: // " + escape = '"'; + break; + case 38: // & + escape = '&'; + break; + case 39: // ' + escape = '''; + break; + case 60: // < + escape = '<'; + break; + case 62: // > + escape = '>'; + break; + default: + continue; + } + + if (lastIndex !== index) { + html += str.substring(lastIndex, index); + } + + lastIndex = index + 1; + html += escape; + } + + return lastIndex !== index + ? html + str.substring(lastIndex, index) + : html; +} diff --git a/node_modules/escape-html/package.json b/node_modules/escape-html/package.json new file mode 100644 index 0000000..5010c0a --- /dev/null +++ b/node_modules/escape-html/package.json @@ -0,0 +1,95 @@ +{ + "_args": [ + [ + { + "raw": "escape-html@~1.0.3", + "scope": null, + "escapedName": "escape-html", + "name": "escape-html", + "rawSpec": "~1.0.3", + "spec": ">=1.0.3 <1.1.0", + "type": "range" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express" + ] + ], + "_from": "escape-html@>=1.0.3 <1.1.0", + "_id": "escape-html@1.0.3", + "_inCache": true, + "_installable": true, + "_location": "/escape-html", + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "raw": "escape-html@~1.0.3", + "scope": null, + "escapedName": "escape-html", + "name": "escape-html", + "rawSpec": "~1.0.3", + "spec": ">=1.0.3 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/express", + "/finalhandler", + "/send", + "/serve-static" + ], + "_resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "_shasum": "0258eae4d3d0c0974de1c169188ef0051d1d1988", + "_shrinkwrap": null, + "_spec": "escape-html@~1.0.3", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express", + "bugs": { + "url": "https://github.com/component/escape-html/issues" + }, + "dependencies": {}, + "description": "Escape string for use in HTML", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "1.0.0" + }, + "directories": {}, + "dist": { + "shasum": "0258eae4d3d0c0974de1c169188ef0051d1d1988", + "tarball": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "files": [ + "LICENSE", + "Readme.md", + "index.js" + ], + "gitHead": "7ac2ea3977fcac3d4c5be8d2a037812820c65f28", + "homepage": "https://github.com/component/escape-html", + "keywords": [ + "escape", + "html", + "utility" + ], + "license": "MIT", + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "escape-html", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/component/escape-html.git" + }, + "scripts": { + "bench": "node benchmark/index.js" + }, + "version": "1.0.3" +} diff --git a/node_modules/etag/HISTORY.md b/node_modules/etag/HISTORY.md new file mode 100644 index 0000000..bd0f26d --- /dev/null +++ b/node_modules/etag/HISTORY.md @@ -0,0 +1,71 @@ +1.7.0 / 2015-06-08 +================== + + * Always include entity length in ETags for hash length extensions + * Generate non-Stats ETags using MD5 only (no longer CRC32) + * Improve stat performance by removing hashing + * Remove base64 padding in ETags to shorten + * Use MD5 instead of MD4 in weak ETags over 1KB + +1.6.0 / 2015-05-10 +================== + + * Improve support for JXcore + * Remove requirement of `atime` in the stats object + * Support "fake" stats objects in environments without `fs` + +1.5.1 / 2014-11-19 +================== + + * deps: crc@3.2.1 + - Minor fixes + +1.5.0 / 2014-10-14 +================== + + * Improve string performance + * Slightly improve speed for weak ETags over 1KB + +1.4.0 / 2014-09-21 +================== + + * Support "fake" stats objects + * Support Node.js 0.6 + +1.3.1 / 2014-09-14 +================== + + * Use the (new and improved) `crc` for crc32 + +1.3.0 / 2014-08-29 +================== + + * Default strings to strong ETags + * Improve speed for weak ETags over 1KB + +1.2.1 / 2014-08-29 +================== + + * Use the (much faster) `buffer-crc32` for crc32 + +1.2.0 / 2014-08-24 +================== + + * Add support for file stat objects + +1.1.0 / 2014-08-24 +================== + + * Add fast-path for empty entity + * Add weak ETag generation + * Shrink size of generated ETags + +1.0.1 / 2014-08-24 +================== + + * Fix behavior of string containing Unicode + +1.0.0 / 2014-05-18 +================== + + * Initial release diff --git a/node_modules/etag/LICENSE b/node_modules/etag/LICENSE new file mode 100644 index 0000000..142ede3 --- /dev/null +++ b/node_modules/etag/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/etag/README.md b/node_modules/etag/README.md new file mode 100644 index 0000000..8da9e05 --- /dev/null +++ b/node_modules/etag/README.md @@ -0,0 +1,165 @@ +# etag + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Create simple ETags + +## Installation + +```sh +$ npm install etag +``` + +## API + +```js +var etag = require('etag') +``` + +### etag(entity, [options]) + +Generate a strong ETag for the given entity. This should be the complete +body of the entity. Strings, `Buffer`s, and `fs.Stats` are accepted. By +default, a strong ETag is generated except for `fs.Stats`, which will +generate a weak ETag (this can be overwritten by `options.weak`). + +```js +res.setHeader('ETag', etag(body)) +``` + +#### Options + +`etag` accepts these properties in the options object. + +##### weak + +Specifies if the generated ETag will include the weak validator mark (that +is, the leading `W/`). The actual entity tag is the same. The default value +is `false`, unless the `entity` is `fs.Stats`, in which case it is `true`. + +## Testing + +```sh +$ npm test +``` + +## Benchmark + +```bash +$ npm run-script bench + +> etag@1.6.0 bench nodejs-etag +> node benchmark/index.js + + http_parser@1.0 + node@0.10.33 + v8@3.14.5.9 + ares@1.9.0-DEV + uv@0.10.29 + zlib@1.2.3 + modules@11 + openssl@1.0.1j + +> node benchmark/body0-100b.js + + 100B body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 289,198 ops/sec ±1.09% (190 runs sampled) +* buffer - weak x 287,838 ops/sec ±0.91% (189 runs sampled) +* string - strong x 284,586 ops/sec ±1.05% (192 runs sampled) +* string - weak x 287,439 ops/sec ±0.82% (192 runs sampled) + +> node benchmark/body1-1kb.js + + 1KB body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 212,423 ops/sec ±0.75% (193 runs sampled) +* buffer - weak x 211,871 ops/sec ±0.74% (194 runs sampled) + string - strong x 205,291 ops/sec ±0.86% (194 runs sampled) + string - weak x 208,463 ops/sec ±0.79% (192 runs sampled) + +> node benchmark/body2-5kb.js + + 5KB body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 92,901 ops/sec ±0.58% (195 runs sampled) +* buffer - weak x 93,045 ops/sec ±0.65% (192 runs sampled) + string - strong x 89,621 ops/sec ±0.68% (194 runs sampled) + string - weak x 90,070 ops/sec ±0.70% (196 runs sampled) + +> node benchmark/body3-10kb.js + + 10KB body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 54,220 ops/sec ±0.85% (192 runs sampled) +* buffer - weak x 54,069 ops/sec ±0.83% (191 runs sampled) + string - strong x 53,078 ops/sec ±0.53% (194 runs sampled) + string - weak x 53,849 ops/sec ±0.47% (197 runs sampled) + +> node benchmark/body4-100kb.js + + 100KB body + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* buffer - strong x 6,673 ops/sec ±0.15% (197 runs sampled) +* buffer - weak x 6,716 ops/sec ±0.12% (198 runs sampled) + string - strong x 6,357 ops/sec ±0.14% (197 runs sampled) + string - weak x 6,344 ops/sec ±0.21% (197 runs sampled) + +> node benchmark/stats.js + + stats + + 1 test completed. + 2 tests completed. + 3 tests completed. + 4 tests completed. + +* real - strong x 1,671,989 ops/sec ±0.13% (197 runs sampled) +* real - weak x 1,681,297 ops/sec ±0.12% (198 runs sampled) + fake - strong x 927,063 ops/sec ±0.14% (198 runs sampled) + fake - weak x 914,461 ops/sec ±0.41% (191 runs sampled) +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/etag.svg +[npm-url]: https://npmjs.org/package/etag +[node-version-image]: https://img.shields.io/node/v/etag.svg +[node-version-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/jshttp/etag/master.svg +[travis-url]: https://travis-ci.org/jshttp/etag +[coveralls-image]: https://img.shields.io/coveralls/jshttp/etag/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/etag?branch=master +[downloads-image]: https://img.shields.io/npm/dm/etag.svg +[downloads-url]: https://npmjs.org/package/etag diff --git a/node_modules/etag/index.js b/node_modules/etag/index.js new file mode 100644 index 0000000..b582c84 --- /dev/null +++ b/node_modules/etag/index.js @@ -0,0 +1,132 @@ +/*! + * etag + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = etag + +/** + * Module dependencies. + * @private + */ + +var crypto = require('crypto') +var Stats = require('fs').Stats + +/** + * Module variables. + * @private + */ + +var base64PadCharRegExp = /=+$/ +var toString = Object.prototype.toString + +/** + * Generate an entity tag. + * + * @param {Buffer|string} entity + * @return {string} + * @private + */ + +function entitytag(entity) { + if (entity.length === 0) { + // fast-path empty + return '"0-1B2M2Y8AsgTpgAmY7PhCfg"' + } + + // compute hash of entity + var hash = crypto + .createHash('md5') + .update(entity, 'utf8') + .digest('base64') + .replace(base64PadCharRegExp, '') + + // compute length of entity + var len = typeof entity === 'string' + ? Buffer.byteLength(entity, 'utf8') + : entity.length + + return '"' + len.toString(16) + '-' + hash + '"' +} + +/** + * Create a simple ETag. + * + * @param {string|Buffer|Stats} entity + * @param {object} [options] + * @param {boolean} [options.weak] + * @return {String} + * @public + */ + +function etag(entity, options) { + if (entity == null) { + throw new TypeError('argument entity is required') + } + + // support fs.Stats object + var isStats = isstats(entity) + var weak = options && typeof options.weak === 'boolean' + ? options.weak + : isStats + + // validate argument + if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) { + throw new TypeError('argument entity must be string, Buffer, or fs.Stats') + } + + // generate entity tag + var tag = isStats + ? stattag(entity) + : entitytag(entity) + + return weak + ? 'W/' + tag + : tag +} + +/** + * Determine if object is a Stats object. + * + * @param {object} obj + * @return {boolean} + * @api private + */ + +function isstats(obj) { + // genuine fs.Stats + if (typeof Stats === 'function' && obj instanceof Stats) { + return true + } + + // quack quack + return obj && typeof obj === 'object' + && 'ctime' in obj && toString.call(obj.ctime) === '[object Date]' + && 'mtime' in obj && toString.call(obj.mtime) === '[object Date]' + && 'ino' in obj && typeof obj.ino === 'number' + && 'size' in obj && typeof obj.size === 'number' +} + +/** + * Generate a tag for a stat. + * + * @param {object} stat + * @return {string} + * @private + */ + +function stattag(stat) { + var mtime = stat.mtime.getTime().toString(16) + var size = stat.size.toString(16) + + return '"' + size + '-' + mtime + '"' +} diff --git a/node_modules/etag/package.json b/node_modules/etag/package.json new file mode 100644 index 0000000..066b2e5 --- /dev/null +++ b/node_modules/etag/package.json @@ -0,0 +1,109 @@ +{ + "_args": [ + [ + { + "raw": "etag@~1.7.0", + "scope": null, + "escapedName": "etag", + "name": "etag", + "rawSpec": "~1.7.0", + "spec": ">=1.7.0 <1.8.0", + "type": "range" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express" + ] + ], + "_from": "etag@>=1.7.0 <1.8.0", + "_id": "etag@1.7.0", + "_inCache": true, + "_installable": true, + "_location": "/etag", + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "raw": "etag@~1.7.0", + "scope": null, + "escapedName": "etag", + "name": "etag", + "rawSpec": "~1.7.0", + "spec": ">=1.7.0 <1.8.0", + "type": "range" + }, + "_requiredBy": [ + "/express", + "/send" + ], + "_resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "_shasum": "03d30b5f67dd6e632d2945d30d6652731a34d5d8", + "_shrinkwrap": null, + "_spec": "etag@~1.7.0", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express", + "bugs": { + "url": "https://github.com/jshttp/etag/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "David Björklund", + "email": "david.bjorklund@gmail.com" + } + ], + "dependencies": {}, + "description": "Create simple ETags", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "1.0.0", + "istanbul": "0.3.14", + "mocha": "~1.21.4", + "seedrandom": "2.3.11" + }, + "directories": {}, + "dist": { + "shasum": "03d30b5f67dd6e632d2945d30d6652731a34d5d8", + "tarball": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "README.md", + "index.js" + ], + "gitHead": "a511f5c8c930fd9546dbd88acb080f96bc788cfc", + "homepage": "https://github.com/jshttp/etag", + "keywords": [ + "etag", + "http", + "res" + ], + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "etag", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/etag.git" + }, + "scripts": { + "bench": "node benchmark/index.js", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.7.0" +} diff --git a/node_modules/express-mysql-session/.eslintrc.js b/node_modules/express-mysql-session/.eslintrc.js new file mode 100644 index 0000000..0ede07b --- /dev/null +++ b/node_modules/express-mysql-session/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + 'extends': 'eslint:recommended', + 'rules': { + 'indent': ['error', 'tab', { 'SwitchCase': 1 }], + 'no-console': 0, + 'no-undef': 0, + 'no-unused-vars': ['error', { 'vars': 'all', 'args': 'none' }] + } +}; \ No newline at end of file diff --git a/node_modules/express-mysql-session/LICENSE b/node_modules/express-mysql-session/LICENSE new file mode 100644 index 0000000..77b80d3 --- /dev/null +++ b/node_modules/express-mysql-session/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Charles Hill + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/express-mysql-session/grunt/aliases.json b/node_modules/express-mysql-session/grunt/aliases.json new file mode 100644 index 0000000..25d2788 --- /dev/null +++ b/node_modules/express-mysql-session/grunt/aliases.json @@ -0,0 +1,13 @@ +{ + "default": ["test"], + "test": [ + "test:unit", + "test:code-style" + ], + "test:code-style": [ + "eslint" + ], + "test:unit": [ + "mochaTest:unit" + ] +} \ No newline at end of file diff --git a/node_modules/express-mysql-session/grunt/eslint.js b/node_modules/express-mysql-session/grunt/eslint.js new file mode 100644 index 0000000..1c1de98 --- /dev/null +++ b/node_modules/express-mysql-session/grunt/eslint.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = { + src: [ + 'lib/*.js', + 'test/**/*.js', + 'gruntFile.js', + 'index.js' + ], + options: { + configFile: '.eslintrc.js' + } +}; diff --git a/node_modules/express-mysql-session/grunt/mochaTest.js b/node_modules/express-mysql-session/grunt/mochaTest.js new file mode 100644 index 0000000..fcc3fe6 --- /dev/null +++ b/node_modules/express-mysql-session/grunt/mochaTest.js @@ -0,0 +1,16 @@ +'use strict'; + +module.exports = { + unit: { + options: { + reporter: 'spec' + }, + src: ['test/unit/**/*.js'] + }, + integration: { + options: { + reporter: 'spec' + }, + src: ['test/integration/**/*.js'] + } +}; diff --git a/node_modules/express-mysql-session/gruntFile.js b/node_modules/express-mysql-session/gruntFile.js new file mode 100644 index 0000000..d2c3ed2 --- /dev/null +++ b/node_modules/express-mysql-session/gruntFile.js @@ -0,0 +1,7 @@ +'use strict'; + +module.exports = function(grunt) { + + require('time-grunt')(grunt); + require('load-grunt-config')(grunt); +}; diff --git a/node_modules/express-mysql-session/index.js b/node_modules/express-mysql-session/index.js new file mode 100644 index 0000000..647221a --- /dev/null +++ b/node_modules/express-mysql-session/index.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./lib/index.js'); diff --git a/node_modules/express-mysql-session/lib/index.js b/node_modules/express-mysql-session/lib/index.js new file mode 100644 index 0000000..a018e31 --- /dev/null +++ b/node_modules/express-mysql-session/lib/index.js @@ -0,0 +1,431 @@ +'use strict'; + +var mysql = require('mysql'); +var debug_log = require('debug')('express-mysql-session:log'); +var debug_error = require('debug')('express-mysql-session:error'); +var deprecate = require('depd')('express-mysql-session'); +var util = require('util'); + +var defaultOptions = { + checkExpirationInterval: 900000,// How frequently expired sessions will be cleared; milliseconds. + expiration: 86400000,// The maximum age of a valid session; milliseconds. + createDatabaseTable: true,// Whether or not to create the sessions database table, if one does not already exist. + connectionLimit: 1,// Number of connections when creating a connection pool + charset: 'utf8mb4_bin', + schema: { + tableName: 'sessions', + columnNames: { + session_id: 'session_id', + expires: 'expires', + data: 'data' + } + } +}; + +module.exports = function(session) { + + var constructorArgs; + + if (typeof session.Store === 'undefined') { + session = require('express-session'); + constructorArgs = Array.prototype.slice.call(arguments); + } + + var Store = session.Store; + + var MySQLStore = function(options, connection, cb) { + + debug_log('Creating session store'); + + this.options = this.clone(options || {}); + this.setDefaultOptions(); + + if (this.options.debug) { + deprecate('The \'debug\' option has been removed. This module now uses the debug module to output logs and error messages. Run your app with `DEBUG=express-mysql-session* node your-app.js` to have all logs and errors outputted to the console.'); + } + + if (typeof connection === 'function') { + cb = connection; + connection = null; + } + + this.connection = connection || mysql.createPool(this.options); + + var done = function() { + + this.setExpirationInterval(); + + if (cb) { + cb.apply(undefined, arguments); + } + + }.bind(this); + + if (!this.options.createDatabaseTable) { + setTimeout(done, 0); + return; + } + + this.createDatabaseTable(done); + }; + + util.inherits(MySQLStore, Store); + + MySQLStore.prototype.setDefaultOptions = function() { + + debug_log('Setting default options'); + + this.options = this.defaults(this.options, defaultOptions, { recursive: true }); + }; + + MySQLStore.prototype.createDatabaseTable = function(cb) { + + debug_log('Creating sessions database table'); + + var fs = require('fs'); + + fs.readFile(__dirname + '/../schema.sql', 'utf-8', function(error, sql) { + + if (error) { + return cb && cb(error); + } + + sql = sql.replace(/`[^`]+`/g, '??'); + + var params = [ + this.options.schema.tableName, + this.options.schema.columnNames.session_id, + this.options.schema.columnNames.expires, + this.options.schema.columnNames.data, + this.options.schema.columnNames.session_id + ]; + + this.connection.query(sql, params, function(error) { + + if (error) { + debug_error('Failed to create sessions database table.'); + debug_error(error); + return cb && cb(error); + } + + cb && cb(); + }); + + }.bind(this)); + }; + + MySQLStore.prototype.get = function(session_id, cb) { + + debug_log('Getting session: ' + session_id); + + var sql = 'SELECT ?? AS data FROM ?? WHERE ?? = ? LIMIT 1'; + + var params = [ + this.options.schema.columnNames.data, + this.options.schema.tableName, + this.options.schema.columnNames.session_id, + session_id + ]; + + this.connection.query(sql, params, function(error, rows) { + + if (error) { + debug_error('Failed to get session.'); + debug_error(error); + return cb(error, null); + } + + try { + var session = rows[0] ? JSON.parse(rows[0].data) : null; + } catch (error) { + debug_error(error); + return cb(new Error('Failed to parse data for session: ' + session_id)); + } + + cb(null, session); + }); + }; + + MySQLStore.prototype.set = function(session_id, data, cb) { + + debug_log('Setting session: ' + session_id); + + var expires; + + if (data.cookie) { + if (data.cookie.expires) { + expires = data.cookie.expires; + } else if (data.cookie._expires) { + expires = data.cookie._expires; + } + } + + if (!expires) { + expires = Date.now() + this.options.expiration; + } + + if (!(expires instanceof Date)) { + expires = new Date(expires); + } + + // Use whole seconds here; not milliseconds. + expires = Math.round(expires.getTime() / 1000); + + data = JSON.stringify(data); + + var sql = 'INSERT INTO ?? (??, ??, ??) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE ?? = VALUES(??), ?? = VALUES(??)'; + + var params = [ + this.options.schema.tableName, + this.options.schema.columnNames.session_id, + this.options.schema.columnNames.expires, + this.options.schema.columnNames.data, + session_id, + expires, + data, + this.options.schema.columnNames.expires, + this.options.schema.columnNames.expires, + this.options.schema.columnNames.data, + this.options.schema.columnNames.data + ]; + + this.connection.query(sql, params, function(error) { + + if (error) { + debug_error('Failed to insert session data.'); + debug_error(error); + return cb && cb(error); + } + + cb && cb(); + }); + }; + + MySQLStore.prototype.touch = function(session_id, data, cb) { + + debug_log('Touching session: ' + session_id); + + var expires; + + if (data.cookie) { + if (data.cookie.expires) { + expires = data.cookie.expires; + } else if (data.cookie._expires) { + expires = data.cookie._expires; + } + } + + if (!expires) { + expires = Date.now() + this.options.expiration; + } + + if (!(expires instanceof Date)) { + expires = new Date(expires); + } + + // Use whole seconds here; not milliseconds. + expires = Math.round(expires.getTime() / 1000); + + var sql = 'UPDATE ?? SET ?? = ? WHERE ?? = ?'; + + var params = [ + this.options.schema.tableName, + this.options.schema.columnNames.expires, + expires, + this.options.schema.columnNames.session_id, + session_id + ]; + + this.connection.query(sql, params, function(error) { + + if (error) { + debug_error('Failed to touch session.'); + debug_error(error); + return cb && cb(error); + } + + return cb && cb(); + }); + }; + + MySQLStore.prototype.destroy = function(session_id, cb) { + + debug_log('Destroying session: ' + session_id); + + var sql = 'DELETE FROM ?? WHERE ?? = ? LIMIT 1'; + + var params = [ + this.options.schema.tableName, + this.options.schema.columnNames.session_id, + session_id + ]; + + this.connection.query(sql, params, function(error) { + + if (error) { + debug_error('Failed to destroy session.'); + debug_error(error); + return cb && cb(error); + } + + cb && cb(); + }); + }; + + MySQLStore.prototype.length = function(cb) { + + debug_log('Getting number of sessions'); + + var sql = 'SELECT COUNT(*) FROM ??'; + + var params = [ + this.options.schema.tableName + ]; + + this.connection.query(sql, params, function(error, rows) { + + if (error) { + debug_error('Failed to get number of sessions.'); + debug_error(error); + return cb && cb(error); + } + + var count = rows[0] ? rows[0]['COUNT(*)'] : 0; + + cb(null, count); + }); + }; + + MySQLStore.prototype.clear = function(cb) { + + debug_log('Clearing all sessions'); + + var sql = 'DELETE FROM ??'; + + var params = [ + this.options.schema.tableName + ]; + + this.connection.query(sql, params, function(error) { + + if (error) { + debug_error('Failed to clear all sessions.'); + debug_error(error); + return cb && cb(error); + } + + cb && cb(); + }); + }; + + MySQLStore.prototype.clearExpiredSessions = function(cb) { + + debug_log('Clearing expired sessions'); + + var sql = 'DELETE FROM ?? WHERE ?? < ?'; + + var params = [ + this.options.schema.tableName, + this.options.schema.columnNames.expires, + Math.round(Date.now() / 1000) + ]; + + this.connection.query(sql, params, function(error) { + + if (error) { + debug_error('Failed to clear expired sessions.'); + debug_error(error); + return cb && cb(error); + } + + cb && cb(); + }); + }; + + MySQLStore.prototype.setExpirationInterval = function(interval) { + + interval || (interval = this.options.checkExpirationInterval); + + debug_log('Setting expiration interval: ' + interval + 'ms'); + + this.clearExpirationInterval(); + this._expirationInterval = setInterval(this.clearExpiredSessions.bind(this), interval); + }; + + MySQLStore.prototype.clearExpirationInterval = function() { + + debug_log('Clearing expiration interval'); + + clearInterval(this._expirationInterval); + this._expirationInterval = null; + }; + + MySQLStore.prototype.close = function(cb) { + + debug_log('Closing session store'); + + this.clearExpirationInterval(); + + if (this.connection) { + this.connection.end(cb); + } else { + cb && cb(null); + } + }; + + MySQLStore.prototype.defaults = function(object, defaultValues, options) { + + if (!this.isObject(object)) { + return object; + } + + object = this.clone(object); + defaultValues = defaultValues || {}; + options = options || {}; + options.recursive = options.recursive === true; + + for (var key in defaultValues) { + + if (typeof object[key] === 'undefined') { + object[key] = defaultValues[key]; + } + + if (options.recursive) { + object[key] = this.defaults(object[key], defaultValues[key], options); + } + } + + return object; + } + + MySQLStore.prototype.clone = function(object) { + + return JSON.parse(JSON.stringify(object)); + } + + MySQLStore.prototype.isObject = function(value) { + + var type = typeof value; + return type === 'function' || type === 'object' && !!value; + } + + // For backwards compatibility: + MySQLStore.prototype.closeStore = deprecate.function( + MySQLStore.prototype.close, + 'The closeStore() method has been deprecated. Use close() instead.' + ); + + // For backwards compatibility: + MySQLStore.prototype.sync = deprecate.function( + MySQLStore.prototype.createDatabaseTable, + 'The sync() method has been deprecated. Use createDatabaseTable() instead.' + ); + + if (constructorArgs) { + // For backwards compatibility. + // Immediately call as a constructor. + return new (MySQLStore.bind.apply(MySQLStore, [undefined/* context */].concat(constructorArgs)))(); + } + + return MySQLStore; +}; diff --git a/node_modules/express-mysql-session/node_modules/express-session/HISTORY.md b/node_modules/express-mysql-session/node_modules/express-session/HISTORY.md new file mode 100644 index 0000000..8ec8885 --- /dev/null +++ b/node_modules/express-mysql-session/node_modules/express-session/HISTORY.md @@ -0,0 +1,314 @@ +1.14.0 / 2016-07-01 +=================== + + * Correctly inherit from `EventEmitter` class in `Store` base class + * Fix issue where `Set-Cookie` `Expires` was not always updated + * Methods are no longer enumerable on `req.session` object + * deps: cookie@0.3.1 + - Add `sameSite` option + - Improve error message when `encode` is not a function + - Improve error message when `expires` is not a `Date` + - perf: enable strict mode + - perf: use for loop in parse + - perf: use string concatination for serialization + * deps: parseurl@~1.3.1 + - perf: enable strict mode + * deps: uid-safe@~2.1.1 + - Use `random-bytes` for byte source + - deps: base64-url@1.2.2 + * perf: enable strict mode + * perf: remove argument reassignment + +1.13.0 / 2016-01-10 +=================== + + * Fix `rolling: true` to not set cookie when no session exists + - Better `saveUninitialized: false` + `rolling: true` behavior + * deps: crc@3.4.0 + +1.12.1 / 2015-10-29 +=================== + + * deps: cookie@0.2.3 + - Fix cookie `Max-Age` to never be a floating point number + +1.12.0 / 2015-10-25 +=================== + + * Support the value `'auto'` in the `cookie.secure` option + * deps: cookie@0.2.2 + - Throw on invalid values provided to `serialize` + * deps: depd@~1.1.0 + - Enable strict mode in more places + - Support web browser loading + * deps: on-headers@~1.0.1 + - perf: enable strict mode + +1.11.3 / 2015-05-22 +=================== + + * deps: cookie@0.1.3 + - Slight optimizations + * deps: crc@3.3.0 + +1.11.2 / 2015-05-10 +=================== + + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: uid-safe@~2.0.0 + +1.11.1 / 2015-04-08 +=================== + + * Fix mutating `options.secret` value + +1.11.0 / 2015-04-07 +=================== + + * Support an array in `secret` option for key rotation + * deps: depd@~1.0.1 + +1.10.4 / 2015-03-15 +=================== + + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + +1.10.3 / 2015-02-16 +=================== + + * deps: cookie-signature@1.0.6 + * deps: uid-safe@1.1.0 + - Use `crypto.randomBytes`, if available + - deps: base64-url@1.2.1 + +1.10.2 / 2015-01-31 +=================== + + * deps: uid-safe@1.0.3 + - Fix error branch that would throw + - deps: base64-url@1.2.0 + +1.10.1 / 2015-01-08 +=================== + + * deps: uid-safe@1.0.2 + - Remove dependency on `mz` + +1.10.0 / 2015-01-05 +=================== + + * Add `store.touch` interface for session stores + * Fix `MemoryStore` expiration with `resave: false` + * deps: debug@~2.1.1 + +1.9.3 / 2014-12-02 +================== + + * Fix error when `req.sessionID` contains a non-string value + +1.9.2 / 2014-11-22 +================== + + * deps: crc@3.2.1 + - Minor fixes + +1.9.1 / 2014-10-22 +================== + + * Remove unnecessary empty write call + - Fixes Node.js 0.11.14 behavior change + - Helps work-around Node.js 0.10.1 zlib bug + +1.9.0 / 2014-09-16 +================== + + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + +1.8.2 / 2014-09-15 +================== + + * Use `crc` instead of `buffer-crc32` for speed + * deps: depd@0.4.5 + +1.8.1 / 2014-09-08 +================== + + * Keep `req.session.save` non-enumerable + * Prevent session prototype methods from being overwritten + +1.8.0 / 2014-09-07 +================== + + * Do not resave already-saved session at end of request + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + +1.7.6 / 2014-08-18 +================== + + * Fix exception on `res.end(null)` calls + +1.7.5 / 2014-08-10 +================== + + * Fix parsing original URL + * deps: on-headers@~1.0.0 + * deps: parseurl@~1.3.0 + +1.7.4 / 2014-08-05 +================== + + * Fix response end delay for non-chunked responses + +1.7.3 / 2014-08-05 +================== + + * Fix `res.end` patch to call correct upstream `res.write` + +1.7.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + +1.7.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + +1.7.0 / 2014-07-22 +================== + + * Improve session-ending error handling + - Errors are passed to `next(err)` instead of `console.error` + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + +1.6.5 / 2014-07-11 +================== + + * Do not require `req.originalUrl` + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + +1.6.4 / 2014-07-07 +================== + + * Fix blank responses for stores with synchronous operations + +1.6.3 / 2014-07-04 +================== + + * Fix resave deprecation message + +1.6.2 / 2014-07-04 +================== + + * Fix confusing option deprecation messages + +1.6.1 / 2014-06-28 +================== + + * Fix saveUninitialized deprecation message + +1.6.0 / 2014-06-28 +================== + + * Add deprecation message to undefined `resave` option + * Add deprecation message to undefined `saveUninitialized` option + * Fix `res.end` patch to return correct value + * Fix `res.end` patch to handle multiple `res.end` calls + * Reject cookies with missing signatures + +1.5.2 / 2014-06-26 +================== + + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +1.5.1 / 2014-06-21 +================== + + * Move hard-to-track-down `req.secret` deprecation message + +1.5.0 / 2014-06-19 +================== + + * Debug name is now "express-session" + * Deprecate integration with `cookie-parser` middleware + * Deprecate looking for secret in `req.secret` + * Directly read cookies; `cookie-parser` no longer required + * Directly set cookies; `res.cookie` no longer required + * Generate session IDs with `uid-safe`, faster and even less collisions + +1.4.0 / 2014-06-17 +================== + + * Add `genid` option to generate custom session IDs + * Add `saveUninitialized` option to control saving uninitialized sessions + * Add `unset` option to control unsetting `req.session` + * Generate session IDs with `rand-token` by default; reduce collisions + * deps: buffer-crc32@0.2.3 + +1.3.1 / 2014-06-14 +================== + + * Add description in package for npmjs.org listing + +1.3.0 / 2014-06-14 +================== + + * Integrate with express "trust proxy" by default + * deps: debug@1.0.2 + +1.2.1 / 2014-05-27 +================== + + * Fix `resave` such that `resave: true` works + +1.2.0 / 2014-05-19 +================== + + * Add `resave` option to control saving unmodified sessions + +1.1.0 / 2014-05-12 +================== + + * Add `name` option; replacement for `key` option + * Use `setImmediate` in MemoryStore for node.js >= 0.10 + +1.0.4 / 2014-04-27 +================== + + * deps: debug@0.8.1 + +1.0.3 / 2014-04-19 +================== + + * Use `res.cookie()` instead of `res.setHeader()` + * deps: cookie@0.1.2 + +1.0.2 / 2014-02-23 +================== + + * Add missing dependency to `package.json` + +1.0.1 / 2014-02-15 +================== + + * Add missing dependencies to `package.json` + +1.0.0 / 2014-02-15 +================== + + * Genesis from `connect` diff --git a/node_modules/express-mysql-session/node_modules/express-session/LICENSE b/node_modules/express-mysql-session/node_modules/express-session/LICENSE new file mode 100644 index 0000000..9b59ff8 --- /dev/null +++ b/node_modules/express-mysql-session/node_modules/express-session/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 TJ Holowaychukviews: ' + sess.views + '
') + res.write('expires in: ' + (sess.cookie.maxAge / 1000) + 's
') + res.end() + } else { + sess.views = 1 + res.end('welcome to the session demo. refresh!') + } +}) +``` + +#### Session.regenerate() + +To regenerate the session simply invoke the method. Once complete, +a new SID and `Session` instance will be initialized at `req.session`. + +```js +req.session.regenerate(function(err) { + // will have a new session here +}) +``` + +#### Session.destroy() + +Destroys the session, removing `req.session`; will be re-generated next request. + +```js +req.session.destroy(function(err) { + // cannot access session here +}) +``` + +#### Session.reload() + +Reloads the session data. + +```js +req.session.reload(function(err) { + // session updated +}) +``` + +#### Session.save() + +Save the session back to the store, replacing the contents on the store with the +contents in memory (though a store may do something else--consult the store's +documentation for exact behavior). + +This method is automatically called at the end of the HTTP response if the +session data has been altered (though this behavior can be altered with various +options in the middleware constructor). Because of this, typically this method +does not need to be called. + +There are some cases where it is useful to call this method, for example, long- +lived requests or in WebSockets. + +```js +req.session.save(function(err) { + // session saved +}) +``` + +#### Session.touch() + +Updates the `.maxAge` property. Typically this is +not necessary to call, as the session middleware does this for you. + +### req.session.id + +Each session has a unique ID associated with it. This property will +contain the session ID and cannot be modified. + +### req.session.cookie + +Each session has a unique cookie object accompany it. This allows +you to alter the session cookie per visitor. For example we can +set `req.session.cookie.expires` to `false` to enable the cookie +to remain for only the duration of the user-agent. + +#### Cookie.maxAge + +Alternatively `req.session.cookie.maxAge` will return the time +remaining in milliseconds, which we may also re-assign a new value +to adjust the `.expires` property appropriately. The following +are essentially equivalent + +```js +var hour = 3600000 +req.session.cookie.expires = new Date(Date.now() + hour) +req.session.cookie.maxAge = hour +``` + +For example when `maxAge` is set to `60000` (one minute), and 30 seconds +has elapsed it will return `30000` until the current request has completed, +at which time `req.session.touch()` is called to reset `req.session.maxAge` +to its original value. + +```js +req.session.cookie.maxAge // => 30000 +``` + +### req.sessionID + +To get the ID of the loaded session, access the request property +`req.sessionID`. This is simply a read-only value set when a session +is loaded/created. + +## Session Store Implementation + +Every session store _must_ be an `EventEmitter` and implement specific +methods. The following methods are the list of **required**, **recommended**, +and **optional**. + + * Required methods are ones that this module will always call on the store. + * Recommended methods are ones that this module will call on the store if + available. + * Optional methods are ones this module does not call at all, but helps + present uniform stores to users. + +For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo. + +### store.all(callback) + +**Optional** + +This optional method is used to get all sessions in the store as an array. The +`callback` should be called as `callback(error, sessions)`. + +### store.destroy(sid, callback) + +**Required** + +This required method is used to destroy/delete a session from the store given +a session ID (`sid`). The `callback` should be called as `callback(error)` once +the session is destroyed. + +### store.clear(callback) + +**Optional** + +This optional method is used to delete all sessions from the store. The +`callback` should be called as `callback(error)` once the store is cleared. + +### store.length(callback) + +**Optional** + +This optional method is used to get the count of all sessions in the store. +The `callback` should be called as `callback(error, len)`. + +### store.get(sid, callback) + +**Required** + +This required method is used to get a session from the store given a session +ID (`sid`). The `callback` should be called as `callback(error, session)`. + +The `session` argument should be a session if found, otherwise `null` or +`undefined` if the session was not found (and there was no error). A special +case is made when `error.code === 'ENOENT'` to act like `callback(null, null)`. + +### store.set(sid, session, callback) + +**Required** + +This required method is used to upsert a session into the store given a +session ID (`sid`) and session (`session`) object. The callback should be +called as `callback(error)` once the session has been set in the store. + +### store.touch(sid, session, callback) + +**Recommended** + +This recommended method is used to "touch" a given session given a +session ID (`sid`) and session (`session`) object. The `callback` should be +called as `callback(error)` once the session has been touched. + +This is primarily used when the store will automatically delete idle sessions +and this method is used to signal to the store the given session is active, +potentially resetting the idle timer. + +## Compatible Session Stores + +The following modules implement a session store that is compatible with this +module. Please make a PR to add additional modules :) + +[![★][cassandra-store-image] cassandra-store][cassandra-store-url] An Apache Cassandra-based session store. + +[cassandra-store-url]: https://www.npmjs.com/package/cassandra-store +[cassandra-store-image]: https://img.shields.io/github/stars/webcc/cassandra-store.svg?label=%E2%98%85 + +[![★][cluster-store-image] cluster-store][cluster-store-url] A wrapper for using in-process / embedded +stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2 +and other multi-core embedded devices). + +[cluster-store-url]: https://www.npmjs.com/package/cluster-store +[cluster-store-image]: https://img.shields.io/github/stars/coolaj86/cluster-store.svg?label=%E2%98%85 + +[![★][connect-azuretables-image] connect-azuretables][connect-azuretables-url] An [Azure Table Storage](https://azure.microsoft.com/en-gb/services/storage/tables/)-based session store. + +[connect-azuretables-url]: https://www.npmjs.com/package/connect-azuretables +[connect-azuretables-image]: https://img.shields.io/github/stars/mike-goodwin/connect-azuretables.svg?label=%E2%98%85 + +[![★][connect-couchbase-image] connect-couchbase][connect-couchbase-url] A [couchbase](http://www.couchbase.com/)-based session store. + +[connect-couchbase-url]: https://www.npmjs.com/package/connect-couchbase +[connect-couchbase-image]: https://img.shields.io/github/stars/christophermina/connect-couchbase.svg?label=%E2%98%85 + +[![★][connect-dynamodb-image] connect-dynamodb][connect-dynamodb-url] A DynamoDB-based session store. + +[connect-dynamodb-url]: https://github.com/ca98am79/connect-dynamodb +[connect-dynamodb-image]: https://img.shields.io/github/stars/ca98am79/connect-dynamodb.svg?label=%E2%98%85 + +[![★][connect-mssql-image] connect-mssql][connect-mssql-url] A SQL Server-based session store. + +[connect-mssql-url]: https://www.npmjs.com/package/connect-mssql +[connect-mssql-image]: https://img.shields.io/github/stars/patriksimek/connect-mssql.svg?label=%E2%98%85 + +[![★][connect-monetdb-image] connect-monetdb][connect-monetdb-url] A MonetDB-based session store. + +[connect-monetdb-url]: https://www.npmjs.com/package/connect-monetdb +[connect-monetdb-image]: https://img.shields.io/github/stars/MonetDB/npm-connect-monetdb.svg?label=%E2%98%85 + +[![★][connect-mongo-image] connect-mongo][connect-mongo-url] A MongoDB-based session store. + +[connect-mongo-url]: https://www.npmjs.com/package/connect-mongo +[connect-mongo-image]: https://img.shields.io/github/stars/kcbanner/connect-mongo.svg?label=%E2%98%85 + +[![★][connect-mongodb-session-image] connect-mongodb-session][connect-mongodb-session-url] Lightweight MongoDB-based session store built and maintained by MongoDB. + +[connect-mongodb-session-url]: https://www.npmjs.com/package/connect-mongodb-session +[connect-mongodb-session-image]: https://img.shields.io/github/stars/mongodb-js/connect-mongodb-session.svg?label=%E2%98%85 + +[![★][connect-pg-simple-image] connect-pg-simple][connect-pg-simple-url] A PostgreSQL-based session store. + +[connect-pg-simple-url]: https://www.npmjs.com/package/connect-pg-simple +[connect-pg-simple-image]: https://img.shields.io/github/stars/voxpelli/node-connect-pg-simple.svg?label=%E2%98%85 + +[![★][connect-redis-image] connect-redis][connect-redis-url] A Redis-based session store. + +[connect-redis-url]: https://www.npmjs.com/package/connect-redis +[connect-redis-image]: https://img.shields.io/github/stars/tj/connect-redis.svg?label=%E2%98%85 + +[![★][connect-memcached-image] connect-memcached][connect-memcached-url] A memcached-based session store. + +[connect-memcached-url]: https://www.npmjs.com/package/connect-memcached +[connect-memcached-image]: https://img.shields.io/github/stars/balor/connect-memcached.svg?label=%E2%98%85 + +[![★][connect-session-knex-image] connect-session-knex][connect-session-knex-url] A session store using +[Knex.js](http://knexjs.org/), which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle. + +[connect-session-knex-url]: https://www.npmjs.com/package/connect-session-knex +[connect-session-knex-image]: https://img.shields.io/github/stars/llambda/connect-session-knex.svg?label=%E2%98%85 + +[![★][connect-session-sequelize-image] connect-session-sequelize][connect-session-sequelize-url] A session store using +[Sequelize.js](http://sequelizejs.com/), which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL. + +[connect-session-sequelize-url]: https://www.npmjs.com/package/connect-session-sequelize +[connect-session-sequelize-image]: https://img.shields.io/github/stars/mweibel/connect-session-sequelize.svg?label=%E2%98%85 + +[![★][express-mysql-session-image] express-mysql-session][express-mysql-session-url] A session store using native +[MySQL](https://www.mysql.com/) via the [node-mysql](https://github.com/felixge/node-mysql) module. + +[express-mysql-session-url]: https://www.npmjs.com/package/express-mysql-session +[express-mysql-session-image]: https://img.shields.io/github/stars/chill117/express-mysql-session.svg?label=%E2%98%85 + +[![★][connect-sqlite3-image] connect-sqlite3][connect-sqlite3-url] A [SQLite3](https://github.com/mapbox/node-sqlite3) session store modeled after the TJ's `connect-redis` store. + +[connect-sqlite3-url]: https://www.npmjs.com/package/connect-sqlite3 +[connect-sqlite3-image]: https://img.shields.io/github/stars/rawberg/connect-sqlite3.svg?label=%E2%98%85 + +[![★][express-nedb-session-image] express-nedb-session][express-nedb-session-url] A NeDB-based session store. + +[express-nedb-session-url]: https://www.npmjs.com/package/express-nedb-session +[express-nedb-session-image]: https://img.shields.io/github/stars/louischatriot/express-nedb-session.svg?label=%E2%98%85 + +[![★][level-session-store-image] level-session-store][level-session-store-url] A LevelDB-based session store. + +[level-session-store-url]: https://www.npmjs.com/package/level-session-store +[level-session-store-image]: https://img.shields.io/github/stars/scriptollc/level-session-store.svg?label=%E2%98%85 + +[![★][mssql-session-store-image] mssql-session-store][mssql-session-store-url] A SQL Server-based session store. + +[mssql-session-store-url]: https://www.npmjs.com/package/mssql-session-store +[mssql-session-store-image]: https://img.shields.io/github/stars/jwathen/mssql-session-store.svg?label=%E2%98%85 + +[![★][nedb-session-store-image] nedb-session-store][nedb-session-store-url] An alternate NeDB-based (either in-memory or file-persisted) session store. + +[nedb-session-store-url]: https://www.npmjs.com/package/nedb-session-store +[nedb-session-store-image]: https://img.shields.io/github/stars/JamesMGreene/nedb-session-store.svg?label=%E2%98%85 + +[![★][sequelstore-connect-image] sequelstore-connect][sequelstore-connect-url] A session store using [Sequelize.js](http://sequelizejs.com/). + +[sequelstore-connect-url]: https://www.npmjs.com/package/sequelstore-connect +[sequelstore-connect-image]: https://img.shields.io/github/stars/MattMcFarland/sequelstore-connect.svg?label=%E2%98%85 + +[![★][session-file-store-image] session-file-store][session-file-store-url] A file system-based session store. + +[session-file-store-url]: https://www.npmjs.com/package/session-file-store +[session-file-store-image]: https://img.shields.io/github/stars/valery-barysok/session-file-store.svg?label=%E2%98%85 + +[![★][session-rethinkdb-image] session-rethinkdb][session-rethinkdb-url] A [RethinkDB](http://rethinkdb.com/)-based session store. + +[session-rethinkdb-url]: https://www.npmjs.com/package/session-rethinkdb +[session-rethinkdb-image]: https://img.shields.io/github/stars/llambda/session-rethinkdb.svg?label=%E2%98%85 + +## Example + +A simple example using `express-session` to store page views for a user. + +```js +var express = require('express') +var parseurl = require('parseurl') +var session = require('express-session') + +var app = express() + +app.use(session({ + secret: 'keyboard cat', + resave: false, + saveUninitialized: true +})) + +app.use(function (req, res, next) { + var views = req.session.views + + if (!views) { + views = req.session.views = {} + } + + // get the url pathname + var pathname = parseurl(req).pathname + + // count the views + views[pathname] = (views[pathname] || 0) + 1 + + next() +}) + +app.get('/foo', function (req, res, next) { + res.send('you viewed this page ' + req.session.views['/foo'] + ' times') +}) + +app.get('/bar', function (req, res, next) { + res.send('you viewed this page ' + req.session.views['/bar'] + ' times') +}) +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/express-session.svg +[npm-url]: https://npmjs.org/package/express-session +[travis-image]: https://img.shields.io/travis/expressjs/session/master.svg +[travis-url]: https://travis-ci.org/expressjs/session +[coveralls-image]: https://img.shields.io/coveralls/expressjs/session/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/session?branch=master +[downloads-image]: https://img.shields.io/npm/dm/express-session.svg +[downloads-url]: https://npmjs.org/package/express-session +[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg +[gratipay-url]: https://gratipay.com/dougwilson/ diff --git a/node_modules/express-mysql-session/node_modules/express-session/index.js b/node_modules/express-mysql-session/node_modules/express-session/index.js new file mode 100644 index 0000000..5794118 --- /dev/null +++ b/node_modules/express-mysql-session/node_modules/express-session/index.js @@ -0,0 +1,637 @@ +/*! + * express-session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var cookie = require('cookie'); +var crc = require('crc').crc32; +var debug = require('debug')('express-session'); +var deprecate = require('depd')('express-session'); +var parseUrl = require('parseurl'); +var uid = require('uid-safe').sync + , onHeaders = require('on-headers') + , signature = require('cookie-signature') + +var Session = require('./session/session') + , MemoryStore = require('./session/memory') + , Cookie = require('./session/cookie') + , Store = require('./session/store') + +// environment + +var env = process.env.NODE_ENV; + +/** + * Expose the middleware. + */ + +exports = module.exports = session; + +/** + * Expose constructors. + */ + +exports.Store = Store; +exports.Cookie = Cookie; +exports.Session = Session; +exports.MemoryStore = MemoryStore; + +/** + * Warning message for `MemoryStore` usage in production. + * @private + */ + +var warning = 'Warning: connect.session() MemoryStore is not\n' + + 'designed for a production environment, as it will leak\n' + + 'memory, and will not scale past a single process.'; + +/** + * Node.js 0.8+ async implementation. + * @private + */ + +/* istanbul ignore next */ +var defer = typeof setImmediate === 'function' + ? setImmediate + : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) } + +/** + * Setup session store with the given `options`. + * + * @param {Object} [options] + * @param {Object} [options.cookie] Options for cookie + * @param {Function} [options.genid] + * @param {String} [options.name=connect.sid] Session ID cookie name + * @param {Boolean} [options.proxy] + * @param {Boolean} [options.resave] Resave unmodified sessions back to the store + * @param {Boolean} [options.rolling] Enable/disable rolling session expiration + * @param {Boolean} [options.saveUninitialized] Save uninitialized sessions to the store + * @param {String|Array} [options.secret] Secret for signing session ID + * @param {Object} [options.store=MemoryStore] Session store + * @param {String} [options.unset] + * @return {Function} middleware + * @public + */ + +function session(options) { + var opts = options || {} + + // get the cookie options + var cookieOptions = opts.cookie || {} + + // get the session id generate function + var generateId = opts.genid || generateSessionId + + // get the session cookie name + var name = opts.name || opts.key || 'connect.sid' + + // get the session store + var store = opts.store || new MemoryStore() + + // get the trust proxy setting + var trustProxy = opts.proxy + + // get the resave session option + var resaveSession = opts.resave; + + // get the rolling session option + var rollingSessions = Boolean(opts.rolling) + + // get the save uninitialized session option + var saveUninitializedSession = opts.saveUninitialized + + // get the cookie signing secret + var secret = opts.secret + + if (typeof generateId !== 'function') { + throw new TypeError('genid option must be a function'); + } + + if (resaveSession === undefined) { + deprecate('undefined resave option; provide resave option'); + resaveSession = true; + } + + if (saveUninitializedSession === undefined) { + deprecate('undefined saveUninitialized option; provide saveUninitialized option'); + saveUninitializedSession = true; + } + + if (opts.unset && opts.unset !== 'destroy' && opts.unset !== 'keep') { + throw new TypeError('unset option must be "destroy" or "keep"'); + } + + // TODO: switch to "destroy" on next major + var unsetDestroy = opts.unset === 'destroy' + + if (Array.isArray(secret) && secret.length === 0) { + throw new TypeError('secret option array must contain one or more strings'); + } + + if (secret && !Array.isArray(secret)) { + secret = [secret]; + } + + if (!secret) { + deprecate('req.secret; provide secret option'); + } + + // notify user that this store is not + // meant for a production environment + if ('production' == env && store instanceof MemoryStore) { + /* istanbul ignore next: not tested */ + console.warn(warning); + } + + // generates the new session + store.generate = function(req){ + req.sessionID = generateId(req); + req.session = new Session(req); + req.session.cookie = new Cookie(cookieOptions); + + if (cookieOptions.secure === 'auto') { + req.session.cookie.secure = issecure(req, trustProxy); + } + }; + + var storeImplementsTouch = typeof store.touch === 'function'; + + // register event listeners for the store to track readiness + var storeReady = true + store.on('disconnect', function ondisconnect() { + storeReady = false + }) + store.on('connect', function onconnect() { + storeReady = true + }) + + return function session(req, res, next) { + // self-awareness + if (req.session) { + next() + return + } + + // Handle connection as if there is no session if + // the store has temporarily disconnected etc + if (!storeReady) { + debug('store is disconnected') + next() + return + } + + // pathname mismatch + var originalPath = parseUrl.original(req).pathname; + if (originalPath.indexOf(cookieOptions.path || '/') !== 0) return next(); + + // ensure a secret is available or bail + if (!secret && !req.secret) { + next(new Error('secret option required for sessions')); + return; + } + + // backwards compatibility for signed cookies + // req.secret is passed from the cookie parser middleware + var secrets = secret || [req.secret]; + + var originalHash; + var originalId; + var savedHash; + + // expose store + req.sessionStore = store; + + // get the session ID from the cookie + var cookieId = req.sessionID = getcookie(req, name, secrets); + + // set-cookie + onHeaders(res, function(){ + if (!req.session) { + debug('no session'); + return; + } + + if (!shouldSetCookie(req)) { + return; + } + + // only send secure cookies via https + if (req.session.cookie.secure && !issecure(req, trustProxy)) { + debug('not secured'); + return; + } + + // touch session + req.session.touch(); + + // set cookie + setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data); + }); + + // proxy end() to commit the session + var _end = res.end; + var _write = res.write; + var ended = false; + res.end = function end(chunk, encoding) { + if (ended) { + return false; + } + + ended = true; + + var ret; + var sync = true; + + function writeend() { + if (sync) { + ret = _end.call(res, chunk, encoding); + sync = false; + return; + } + + _end.call(res); + } + + function writetop() { + if (!sync) { + return ret; + } + + if (chunk == null) { + ret = true; + return ret; + } + + var contentLength = Number(res.getHeader('Content-Length')); + + if (!isNaN(contentLength) && contentLength > 0) { + // measure chunk + chunk = !Buffer.isBuffer(chunk) + ? new Buffer(chunk, encoding) + : chunk; + encoding = undefined; + + if (chunk.length !== 0) { + debug('split response'); + ret = _write.call(res, chunk.slice(0, chunk.length - 1)); + chunk = chunk.slice(chunk.length - 1, chunk.length); + return ret; + } + } + + ret = _write.call(res, chunk, encoding); + sync = false; + + return ret; + } + + if (shouldDestroy(req)) { + // destroy session + debug('destroying'); + store.destroy(req.sessionID, function ondestroy(err) { + if (err) { + defer(next, err); + } + + debug('destroyed'); + writeend(); + }); + + return writetop(); + } + + // no session to save + if (!req.session) { + debug('no session'); + return _end.call(res, chunk, encoding); + } + + if (shouldSave(req)) { + req.session.save(function onsave(err) { + if (err) { + defer(next, err); + } + + writeend(); + }); + + return writetop(); + } else if (storeImplementsTouch && shouldTouch(req)) { + // store implements touch method + debug('touching'); + store.touch(req.sessionID, req.session, function ontouch(err) { + if (err) { + defer(next, err); + } + + debug('touched'); + writeend(); + }); + + return writetop(); + } + + return _end.call(res, chunk, encoding); + }; + + // generate the session + function generate() { + store.generate(req); + originalId = req.sessionID; + originalHash = hash(req.session); + wrapmethods(req.session); + } + + // wrap session methods + function wrapmethods(sess) { + var _save = sess.save; + + function save() { + debug('saving %s', this.id); + savedHash = hash(this); + _save.apply(this, arguments); + } + + Object.defineProperty(sess, 'save', { + configurable: true, + enumerable: false, + value: save, + writable: true + }); + } + + // check if session has been modified + function isModified(sess) { + return originalId !== sess.id || originalHash !== hash(sess); + } + + // check if session has been saved + function isSaved(sess) { + return originalId === sess.id && savedHash === hash(sess); + } + + // determine if session should be destroyed + function shouldDestroy(req) { + return req.sessionID && unsetDestroy && req.session == null; + } + + // determine if session should be saved to store + function shouldSave(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + debug('session ignored because of bogus req.sessionID %o', req.sessionID); + return false; + } + + return !saveUninitializedSession && cookieId !== req.sessionID + ? isModified(req.session) + : !isSaved(req.session) + } + + // determine if session should be touched + function shouldTouch(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + debug('session ignored because of bogus req.sessionID %o', req.sessionID); + return false; + } + + return cookieId === req.sessionID && !shouldSave(req); + } + + // determine if cookie should be set on response + function shouldSetCookie(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + return false; + } + + return cookieId != req.sessionID + ? saveUninitializedSession || isModified(req.session) + : rollingSessions || req.session.cookie.expires != null && isModified(req.session); + } + + // generate a session if the browser doesn't send a sessionID + if (!req.sessionID) { + debug('no SID sent, generating session'); + generate(); + next(); + return; + } + + // generate the session object + debug('fetching %s', req.sessionID); + store.get(req.sessionID, function(err, sess){ + // error handling + if (err) { + debug('error %j', err); + + if (err.code !== 'ENOENT') { + next(err); + return; + } + + generate(); + // no session + } else if (!sess) { + debug('no session found'); + generate(); + // populate req.session + } else { + debug('session found'); + store.createSession(req, sess); + originalId = req.sessionID; + originalHash = hash(sess); + + if (!resaveSession) { + savedHash = originalHash + } + + wrapmethods(req.session); + } + + next(); + }); + }; +}; + +/** + * Generate a session ID for a new session. + * + * @return {String} + * @private + */ + +function generateSessionId(sess) { + return uid(24); +} + +/** + * Get the session ID cookie from request. + * + * @return {string} + * @private + */ + +function getcookie(req, name, secrets) { + var header = req.headers.cookie; + var raw; + var val; + + // read from cookie header + if (header) { + var cookies = cookie.parse(header); + + raw = cookies[name]; + + if (raw) { + if (raw.substr(0, 2) === 's:') { + val = unsigncookie(raw.slice(2), secrets); + + if (val === false) { + debug('cookie signature invalid'); + val = undefined; + } + } else { + debug('cookie unsigned') + } + } + } + + // back-compat read from cookieParser() signedCookies data + if (!val && req.signedCookies) { + val = req.signedCookies[name]; + + if (val) { + deprecate('cookie should be available in req.headers.cookie'); + } + } + + // back-compat read from cookieParser() cookies data + if (!val && req.cookies) { + raw = req.cookies[name]; + + if (raw) { + if (raw.substr(0, 2) === 's:') { + val = unsigncookie(raw.slice(2), secrets); + + if (val) { + deprecate('cookie should be available in req.headers.cookie'); + } + + if (val === false) { + debug('cookie signature invalid'); + val = undefined; + } + } else { + debug('cookie unsigned') + } + } + } + + return val; +} + +/** + * Hash the given `sess` object omitting changes to `.cookie`. + * + * @param {Object} sess + * @return {String} + * @private + */ + +function hash(sess) { + return crc(JSON.stringify(sess, function (key, val) { + if (key !== 'cookie') { + return val; + } + })); +} + +/** + * Determine if request is secure. + * + * @param {Object} req + * @param {Boolean} [trustProxy] + * @return {Boolean} + * @private + */ + +function issecure(req, trustProxy) { + // socket is https server + if (req.connection && req.connection.encrypted) { + return true; + } + + // do not trust proxy + if (trustProxy === false) { + return false; + } + + // no explicit trust; try req.secure from express + if (trustProxy !== true) { + var secure = req.secure; + return typeof secure === 'boolean' + ? secure + : false; + } + + // read the proto from x-forwarded-proto header + var header = req.headers['x-forwarded-proto'] || ''; + var index = header.indexOf(','); + var proto = index !== -1 + ? header.substr(0, index).toLowerCase().trim() + : header.toLowerCase().trim() + + return proto === 'https'; +} + +/** + * Set cookie on response. + * + * @private + */ + +function setcookie(res, name, val, secret, options) { + var signed = 's:' + signature.sign(val, secret); + var data = cookie.serialize(name, signed, options); + + debug('set-cookie %s', data); + + var prev = res.getHeader('set-cookie') || []; + var header = Array.isArray(prev) ? prev.concat(data) + : Array.isArray(data) ? [prev].concat(data) + : [prev, data]; + + res.setHeader('set-cookie', header) +} + +/** + * Verify and decode the given `val` with `secrets`. + * + * @param {String} val + * @param {Array} secrets + * @returns {String|Boolean} + * @private + */ +function unsigncookie(val, secrets) { + for (var i = 0; i < secrets.length; i++) { + var result = signature.unsign(val, secrets[i]); + + if (result !== false) { + return result; + } + } + + return false; +} diff --git a/node_modules/express-mysql-session/node_modules/express-session/package.json b/node_modules/express-mysql-session/node_modules/express-session/package.json new file mode 100644 index 0000000..51878c4 --- /dev/null +++ b/node_modules/express-mysql-session/node_modules/express-session/package.json @@ -0,0 +1,130 @@ +{ + "_args": [ + [ + { + "raw": "express-session@1.14.0", + "scope": null, + "escapedName": "express-session", + "name": "express-session", + "rawSpec": "1.14.0", + "spec": "1.14.0", + "type": "version" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express-mysql-session" + ] + ], + "_from": "express-session@1.14.0", + "_id": "express-session@1.14.0", + "_inCache": true, + "_installable": true, + "_location": "/express-mysql-session/express-session", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/express-session-1.14.0.tgz_1467429048169_0.3337707840837538" + }, + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "raw": "express-session@1.14.0", + "scope": null, + "escapedName": "express-session", + "name": "express-session", + "rawSpec": "1.14.0", + "spec": "1.14.0", + "type": "version" + }, + "_requiredBy": [ + "/express-mysql-session" + ], + "_resolved": "https://registry.npmjs.org/express-session/-/express-session-1.14.0.tgz", + "_shasum": "f5eeed3f38bfa0c6af27a0aeb8c9ec67dc07e39e", + "_shrinkwrap": null, + "_spec": "express-session@1.14.0", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript\\node_modules\\express-mysql-session", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "bugs": { + "url": "https://github.com/expressjs/session/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Joe Wagner", + "email": "njwjs722@gmail.com" + } + ], + "dependencies": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.0", + "debug": "~2.2.0", + "depd": "~1.1.0", + "on-headers": "~1.0.1", + "parseurl": "~1.3.1", + "uid-safe": "~2.1.1", + "utils-merge": "1.0.0" + }, + "description": "Simple session middleware for Express", + "devDependencies": { + "after": "0.8.1", + "cookie-parser": "1.4.3", + "express": "4.14.0", + "istanbul": "0.4.4", + "mocha": "2.5.3", + "supertest": "1.1.0" + }, + "directories": {}, + "dist": { + "shasum": "f5eeed3f38bfa0c6af27a0aeb8c9ec67dc07e39e", + "tarball": "https://registry.npmjs.org/express-session/-/express-session-1.14.0.tgz" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "session/", + "HISTORY.md", + "LICENSE", + "index.js" + ], + "gitHead": "9fd23195578eac5962d52f46781a75a297fbe685", + "homepage": "https://github.com/expressjs/session", + "license": "MIT", + "maintainers": [ + { + "name": "defunctzombie", + "email": "shtylman@gmail.com" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "mscdex", + "email": "mscdex@mscdex.net" + } + ], + "name": "express-session", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/expressjs/session.git" + }, + "scripts": { + "test": "mocha --bail --reporter spec test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec test/" + }, + "version": "1.14.0" +} diff --git a/node_modules/express-mysql-session/node_modules/express-session/session/cookie.js b/node_modules/express-mysql-session/node_modules/express-session/session/cookie.js new file mode 100644 index 0000000..a4dbd8a --- /dev/null +++ b/node_modules/express-mysql-session/node_modules/express-session/session/cookie.js @@ -0,0 +1,129 @@ +/*! + * Connect - session - Cookie + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + */ + +var merge = require('utils-merge') + , cookie = require('cookie'); + +/** + * Initialize a new `Cookie` with the given `options`. + * + * @param {IncomingMessage} req + * @param {Object} options + * @api private + */ + +var Cookie = module.exports = function Cookie(options) { + this.path = '/'; + this.maxAge = null; + this.httpOnly = true; + if (options) merge(this, options); + this.originalMaxAge = undefined == this.originalMaxAge + ? this.maxAge + : this.originalMaxAge; +}; + +/*! + * Prototype. + */ + +Cookie.prototype = { + + /** + * Set expires `date`. + * + * @param {Date} date + * @api public + */ + + set expires(date) { + this._expires = date; + this.originalMaxAge = this.maxAge; + }, + + /** + * Get expires `date`. + * + * @return {Date} + * @api public + */ + + get expires() { + return this._expires; + }, + + /** + * Set expires via max-age in `ms`. + * + * @param {Number} ms + * @api public + */ + + set maxAge(ms) { + this.expires = 'number' == typeof ms + ? new Date(Date.now() + ms) + : ms; + }, + + /** + * Get expires max-age in `ms`. + * + * @return {Number} + * @api public + */ + + get maxAge() { + return this.expires instanceof Date + ? this.expires.valueOf() - Date.now() + : this.expires; + }, + + /** + * Return cookie data object. + * + * @return {Object} + * @api private + */ + + get data() { + return { + originalMaxAge: this.originalMaxAge + , expires: this._expires + , secure: this.secure + , httpOnly: this.httpOnly + , domain: this.domain + , path: this.path + } + }, + + /** + * Return a serialized cookie string. + * + * @return {String} + * @api public + */ + + serialize: function(name, val){ + return cookie.serialize(name, val, this.data); + }, + + /** + * Return JSON representation of this cookie. + * + * @return {Object} + * @api private + */ + + toJSON: function(){ + return this.data; + } +}; diff --git a/node_modules/express-mysql-session/node_modules/express-session/session/memory.js b/node_modules/express-mysql-session/node_modules/express-session/session/memory.js new file mode 100644 index 0000000..25252b6 --- /dev/null +++ b/node_modules/express-mysql-session/node_modules/express-session/session/memory.js @@ -0,0 +1,185 @@ +/*! + * express-session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Store = require('./store') +var util = require('util') + +/** + * Shim setImmediate for node.js < 0.10 + * @private + */ + +/* istanbul ignore next */ +var defer = typeof setImmediate === 'function' + ? setImmediate + : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) } + +/** + * Module exports. + */ + +module.exports = MemoryStore + +/** + * A session store in memory. + * @public + */ + +function MemoryStore() { + Store.call(this) + this.sessions = Object.create(null) +} + +/** + * Inherit from Store. + */ + +util.inherits(MemoryStore, Store) + +/** + * Get all active sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.all = function all(callback) { + var sessionIds = Object.keys(this.sessions) + var sessions = Object.create(null) + + for (var i = 0; i < sessionIds.length; i++) { + var sessionId = sessionIds[i] + var session = getSession.call(this, sessionId) + + if (session) { + sessions[sessionId] = session; + } + } + + callback && defer(callback, null, sessions) +} + +/** + * Clear all sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.clear = function clear(callback) { + this.sessions = Object.create(null) + callback && defer(callback) +} + +/** + * Destroy the session associated with the given session ID. + * + * @param {string} sessionId + * @public + */ + +MemoryStore.prototype.destroy = function destroy(sessionId, callback) { + delete this.sessions[sessionId] + callback && defer(callback) +} + +/** + * Fetch session by the given session ID. + * + * @param {string} sessionId + * @param {function} callback + * @public + */ + +MemoryStore.prototype.get = function get(sessionId, callback) { + defer(callback, null, getSession.call(this, sessionId)) +} + +/** + * Commit the given session associated with the given sessionId to the store. + * + * @param {string} sessionId + * @param {object} session + * @param {function} callback + * @public + */ + +MemoryStore.prototype.set = function set(sessionId, session, callback) { + this.sessions[sessionId] = JSON.stringify(session) + callback && defer(callback) +} + +/** + * Get number of active sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.length = function length(callback) { + this.all(function (err, sessions) { + if (err) return callback(err) + callback(null, Object.keys(sessions).length) + }) +} + +/** + * Touch the given session object associated with the given session ID. + * + * @param {string} sessionId + * @param {object} session + * @param {function} callback + * @public + */ + +MemoryStore.prototype.touch = function touch(sessionId, session, callback) { + var currentSession = getSession.call(this, sessionId) + + if (currentSession) { + // update expiration + currentSession.cookie = session.cookie + this.sessions[sessionId] = JSON.stringify(currentSession) + } + + callback && defer(callback) +} + +/** + * Get session from the store. + * @private + */ + +function getSession(sessionId) { + var sess = this.sessions[sessionId] + + if (!sess) { + return + } + + // parse + sess = JSON.parse(sess) + + var expires = typeof sess.cookie.expires === 'string' + ? new Date(sess.cookie.expires) + : sess.cookie.expires + + // destroy expired session + if (expires && expires <= Date.now()) { + delete this.sessions[sessionId] + return + } + + return sess +} diff --git a/node_modules/express-mysql-session/node_modules/express-session/session/session.js b/node_modules/express-mysql-session/node_modules/express-session/session/session.js new file mode 100644 index 0000000..2eacde6 --- /dev/null +++ b/node_modules/express-mysql-session/node_modules/express-session/session/session.js @@ -0,0 +1,142 @@ +/*! + * Connect - session - Session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Expose Session. + */ + +module.exports = Session; + +/** + * Create a new `Session` with the given request and `data`. + * + * @param {IncomingRequest} req + * @param {Object} data + * @api private + */ + +function Session(req, data) { + Object.defineProperty(this, 'req', { value: req }); + Object.defineProperty(this, 'id', { value: req.sessionID }); + + if (typeof data === 'object' && data !== null) { + // merge data into this, ignoring prototype properties + for (var prop in data) { + if (!(prop in this)) { + this[prop] = data[prop] + } + } + } +} + +/** + * Update reset `.cookie.maxAge` to prevent + * the cookie from expiring when the + * session is still active. + * + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'touch', function touch() { + return this.resetMaxAge(); +}); + +/** + * Reset `.maxAge` to `.originalMaxAge`. + * + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'resetMaxAge', function resetMaxAge() { + this.cookie.maxAge = this.cookie.originalMaxAge; + return this; +}); + +/** + * Save the session data with optional callback `fn(err)`. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'save', function save(fn) { + this.req.sessionStore.set(this.id, this, fn || function(){}); + return this; +}); + +/** + * Re-loads the session data _without_ altering + * the maxAge properties. Invokes the callback `fn(err)`, + * after which time if no exception has occurred the + * `req.session` property will be a new `Session` object, + * although representing the same session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'reload', function reload(fn) { + var req = this.req + , store = this.req.sessionStore; + store.get(this.id, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(new Error('failed to load session')); + store.createSession(req, sess); + fn(); + }); + return this; +}); + +/** + * Destroy `this` session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'destroy', function destroy(fn) { + delete this.req.session; + this.req.sessionStore.destroy(this.id, fn); + return this; +}); + +/** + * Regenerate this request's session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'regenerate', function regenerate(fn) { + this.req.sessionStore.regenerate(this.req, fn); + return this; +}); + +/** + * Helper function for creating a method on a prototype. + * + * @param {Object} obj + * @param {String} name + * @param {Function} fn + * @private + */ +function defineMethod(obj, name, fn) { + Object.defineProperty(obj, name, { + configurable: true, + enumerable: false, + value: fn, + writable: true + }); +}; diff --git a/node_modules/express-mysql-session/node_modules/express-session/session/store.js b/node_modules/express-mysql-session/node_modules/express-session/session/store.js new file mode 100644 index 0000000..387469c --- /dev/null +++ b/node_modules/express-mysql-session/node_modules/express-session/session/store.js @@ -0,0 +1,94 @@ +/*! + * Connect - session - Store + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Cookie = require('./cookie') +var EventEmitter = require('events').EventEmitter +var Session = require('./session') +var util = require('util') + +/** + * Module exports. + * @public + */ + +module.exports = Store + +/** + * Abstract base class for session stores. + * @public + */ + +function Store () { + EventEmitter.call(this) +} + +/** + * Inherit from EventEmitter. + */ + +util.inherits(Store, EventEmitter) + +/** + * Re-generate the given requests's session. + * + * @param {IncomingRequest} req + * @return {Function} fn + * @api public + */ + +Store.prototype.regenerate = function(req, fn){ + var self = this; + this.destroy(req.sessionID, function(err){ + self.generate(req); + fn(err); + }); +}; + +/** + * Load a `Session` instance via the given `sid` + * and invoke the callback `fn(err, sess)`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +Store.prototype.load = function(sid, fn){ + var self = this; + this.get(sid, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(); + var req = { sessionID: sid, sessionStore: self }; + fn(null, self.createSession(req, sess)) + }); +}; + +/** + * Create session from JSON `sess` data. + * + * @param {IncomingRequest} req + * @param {Object} sess + * @return {Session} + * @api private + */ + +Store.prototype.createSession = function(req, sess){ + var expires = sess.cookie.expires + , orig = sess.cookie.originalMaxAge; + sess.cookie = new Cookie(sess.cookie); + if ('string' == typeof expires) sess.cookie.expires = new Date(expires); + sess.cookie.originalMaxAge = orig; + req.session = new Session(req, sess); + return req.session; +}; diff --git a/node_modules/express-mysql-session/package.json b/node_modules/express-mysql-session/package.json new file mode 100644 index 0000000..5872901 --- /dev/null +++ b/node_modules/express-mysql-session/package.json @@ -0,0 +1,114 @@ +{ + "_args": [ + [ + { + "raw": "express-mysql-session", + "scope": null, + "escapedName": "express-mysql-session", + "name": "express-mysql-session", + "rawSpec": "", + "spec": "latest", + "type": "tag" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript" + ] + ], + "_from": "express-mysql-session@latest", + "_id": "express-mysql-session@1.2.0", + "_inCache": true, + "_installable": true, + "_location": "/express-mysql-session", + "_nodeVersion": "4.5.0", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/express-mysql-session-1.2.0.tgz_1473963364870_0.7496246010996401" + }, + "_npmUser": { + "name": "chill1", + "email": "chill@degreesofzero.com" + }, + "_npmVersion": "2.15.9", + "_phantomChildren": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.0", + "debug": "2.2.0", + "depd": "1.1.0", + "on-headers": "1.0.1", + "parseurl": "1.3.1", + "uid-safe": "2.1.2", + "utils-merge": "1.0.0" + }, + "_requested": { + "raw": "express-mysql-session", + "scope": null, + "escapedName": "express-mysql-session", + "name": "express-mysql-session", + "rawSpec": "", + "spec": "latest", + "type": "tag" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/express-mysql-session/-/express-mysql-session-1.2.0.tgz", + "_shasum": "0db80f2f7abd42c9c8e3d8634dcba7866b261775", + "_shrinkwrap": null, + "_spec": "express-mysql-session", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript", + "author": { + "name": "Charles Hill", + "email": "chill@degreesofzero.com" + }, + "bugs": { + "url": "https://github.com/chill117/express-mysql-session/issues" + }, + "dependencies": { + "debug": "2.2.0", + "depd": "1.1.0", + "express-session": "1.14.0", + "mysql": "2.11.1" + }, + "description": "A MySQL session store for express.js", + "devDependencies": { + "async": "2.0.1", + "body-parser": "1.15.2", + "chai": "3.5.0", + "cookie-parser": "1.4.3", + "express": "4.14.0", + "grunt": "1.0.1", + "grunt-eslint": "19.0.0", + "grunt-mocha-test": "0.12.7", + "load-grunt-config": "0.19.2", + "mocha": "2.5.3", + "time-grunt": "1.4.0", + "underscore": "1.8.3" + }, + "directories": {}, + "dist": { + "shasum": "0db80f2f7abd42c9c8e3d8634dcba7866b261775", + "tarball": "https://registry.npmjs.org/express-mysql-session/-/express-mysql-session-1.2.0.tgz" + }, + "gitHead": "1f8e7566eadfd8b04c8d77c582cfa317ca7bbd58", + "homepage": "https://github.com/chill117/express-mysql-session#readme", + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "chill1", + "email": "chill@degreesofzero.com" + } + ], + "name": "express-mysql-session", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/chill117/express-mysql-session.git" + }, + "scripts": { + "test": "grunt test" + }, + "version": "1.2.0" +} diff --git a/node_modules/express-mysql-session/readme.md b/node_modules/express-mysql-session/readme.md new file mode 100644 index 0000000..8d1aad7 --- /dev/null +++ b/node_modules/express-mysql-session/readme.md @@ -0,0 +1,221 @@ +# express-mysql-session + +A MySQL session store for [express.js](http://expressjs.com/). + +[![Build Status](https://travis-ci.org/chill117/express-mysql-session.svg?branch=master)](https://travis-ci.org/chill117/express-mysql-session) [![Status of Dependencies](https://david-dm.org/chill117/express-mysql-session.svg)](https://david-dm.org/chill117/express-mysql-session) + + +## Installation + +Add to your application via `npm`: +``` +npm install express-mysql-session --save +``` +This will install `express-mysql-session` and add it to your application's `package.json` file. + + +## Note for Older Versions + +For users who are still using express-mysql-session `0.x`. Changes have been made to the constructor, which are backwards compatible, but you could run into troubles if using an older version of this module with the latest documentation. You can find the documentation for the older version [here](https://github.com/chill117/express-mysql-session/tree/9fbcf51416a00a7a525c1e6e431033125a2945b0). + + + +## How to Use + +Use with your express session middleware, like this: +```js +var express = require('express'); +var app = module.exports = express(); +var session = require('express-session'); +var MySQLStore = require('express-mysql-session')(session); + +var options = { + host: 'localhost', + port: 3306, + user: 'session_test', + password: 'password', + database: 'session_test' +}; + +var sessionStore = new MySQLStore(options); + +app.use(session({ + key: 'session_cookie_name', + secret: 'session_cookie_secret', + store: sessionStore, + resave: true, + saveUninitialized: true +})); +``` + +The session store will internally create a `mysql` [connection pool](https://github.com/mysqljs/mysql#pooling-connections) which handles the (re)connection to the database. By default, the pool consists of 1 connection, but you can override this using the `connectionLimit` option. There are additional [pool options](https://github.com/mysqljs/mysql#pool-options) you can provide, which will be passed to the constructor of the `mysql` connection pool. + +### With an existing MySQL connection or pool + +To pass in an existing MySQL database connection or pool, you would do something like this: +```js +var mysql = require('mysql'); +var session = require('express-session'); +var MySQLStore = require('express-mysql-session')(session); + +var options = { + host: 'localhost', + port: 3306, + user: 'db_user', + password: 'password', + database: 'db_name' +}; + +var connection = mysql.createConnection(options); // or mysql.createPool(options); +var sessionStore = new MySQLStore({}/* session store options */, connection); +``` + +### Closing the session store + +To cleanly close the session store: +```js +sessionStore.close(); +``` + + +### Options + +Here is a list of all available options: +```js +var options = { + host: 'localhost',// Host name for database connection. + port: 3306,// Port number for database connection. + user: 'session_test',// Database user. + password: 'password',// Password for the above database user. + database: 'session_test',// Database name. + checkExpirationInterval: 900000,// How frequently expired sessions will be cleared; milliseconds. + expiration: 86400000,// The maximum age of a valid session; milliseconds. + createDatabaseTable: true,// Whether or not to create the sessions database table, if one does not already exist. + connectionLimit: 1,// Number of connections when creating a connection pool + schema: { + tableName: 'sessions', + columnNames: { + session_id: 'session_id', + expires: 'expires', + data: 'data' + } + } +}; +``` + + +#### Configurable sessions table and column names + +You can override the default sessions database table name and column names via the `schema` option: + +```js +var session = require('express-session'); +var MySQLStore = require('express-mysql-session')(session); + +var options = { + host: 'localhost', + port: 3306, + user: 'session_test', + password: 'password', + database: 'session_test', + schema: { + tableName: 'custom_sessions_table_name', + columnNames: { + session_id: 'custom_session_id', + expires: 'custom_expires_column_name', + data: 'custom_data_column_name' + } + } +}; + +var sessionStore = new MySQLStore(options); +``` + + +### Debugging + +`express-mysql-session` uses the [debug module](https://github.com/visionmedia/debug) to output debug messages to the console. To output all debug messages, run your node app with the `DEBUG` environment variable: +``` +DEBUG=express-mysql-session* node your-app.js +``` +This will output log messages as well as error messages from `express-mysql-session`. + +If you also might need MySQL-related debug and error messages, see [debugging node-mysql](https://github.com/mysqljs/mysql#debugging-and-reporting-problems). + + +## Contributing + +There are a number of ways you can contribute: + +* **Improve or correct the documentation** - All the documentation is in this readme file. If you see a mistake, or think something should be clarified or expanded upon, please [submit a pull request](https://github.com/chill117/express-mysql-session/pulls/new) +* **Report a bug** - Please review [existing issues](https://github.com/chill117/express-mysql-session/issues) before submitting a new one; to avoid duplicates. If you can't find an issue that relates to the bug you've found, please [create a new one](https://github.com/chill117/express-mysql-session/issues). +* **Request a feature** - Again, please review the [existing issues](https://github.com/chill117/express-mysql-session/issues) before posting a feature request. If you can't find an existing one that covers your feature idea, please [create a new one](https://github.com/chill117/express-mysql-session/issues). +* **Fix a bug** - Have a look at the [existing issues](https://github.com/chill117/express-mysql-session/issues) for the project. If there's a bug in there that you'd like to tackle, please feel free to do so. I would ask that when fixing a bug, that you first create a failing test that proves the bug. Then to fix the bug, make the test pass. This should hopefully ensure that the bug never creeps into the project again. After you've done all that, you can [submit a pull request](https://github.com/chill117/express-mysql-session/pulls/new) with your changes. + +Before you contribute code, please read through at least some of the source code for the project. I would appreciate it if any pull requests for source code changes follow the coding style of the rest of the project. + +Now if you're still interested, you'll need to get your local environment configured. + + +### Configure Local Environment + +#### Step 1: Get the Code + +First, you'll need to pull down the code from GitHub: +``` +git clone https://github.com/chill117/express-mysql-session.git +``` + +#### Step 2: Install Dependencies + +Second, you'll need to install the project dependencies as well as the dev dependencies. To do this, simply run the following from the directory you created in step 1: +``` +npm install +``` + +#### Step 3: Set Up the Test Database + +Now, you'll need to set up a local test database: +```js +{ + host: 'localhost', + port: 3306, + user: 'session_test', + password: 'password', + database: 'session_test' +}; +``` +*The test database settings are located in [test/config.js](https://github.com/chill117/express-mysql-session/blob/master/test/config.js)* + +Alternatively, you can provide custom database configurations via environment variables: +``` +DB_HOST="localhost" +DB_PORT="3306" +DB_USER="session_test" +DB_PASS="password" +DB_NAME="session_test" +``` + + +### Running Tests + +With your local environment configured, running tests is as simple as: +``` +npm test +``` + + +## Changelog + +* v1.2.0: + * Removed dependency on [mysql-connection-manager](https://github.com/chill117/mysql-connection-manager); now using connection pooling from [node-mysql](https://github.com/mysqljs/mysql) module. + * Fix for issue [#49](https://github.com/chill117/express-mysql-session/issues/46) +* v1.1.1: + * Fix for express-session integration when "cookie.maxAge" is set to NULL. +* v1.1.0: + * Added [touch](https://github.com/expressjs/session#storetouchsid-session-callback) method. + * Deprecated `MySQLStore.closeStore` - should use `MySQLStore.close` instead. + * Fixes for issues: [#46](https://github.com/chill117/express-mysql-session/issues/46) +* v1.0.0: + * Changed constructor interface. Must now pass session module to get `MySQLStore` constructor object. See [How to Use](https://github.com/chill117/express-mysql-session#how-to-use) for more information. + * Fixes for issues: [#28](https://github.com/chill117/express-mysql-session/issues/28), [#33](https://github.com/chill117/express-mysql-session/issues/33). diff --git a/node_modules/express-mysql-session/schema.sql b/node_modules/express-mysql-session/schema.sql new file mode 100644 index 0000000..9367bfb --- /dev/null +++ b/node_modules/express-mysql-session/schema.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS `sessions` ( + `session_id` varchar(128) COLLATE utf8mb4_bin NOT NULL, + `expires` int(11) unsigned NOT NULL, + `data` text COLLATE utf8mb4_bin, + PRIMARY KEY (`session_id`) +) ENGINE=InnoDB \ No newline at end of file diff --git a/node_modules/express-session/HISTORY.md b/node_modules/express-session/HISTORY.md new file mode 100644 index 0000000..972d1c9 --- /dev/null +++ b/node_modules/express-session/HISTORY.md @@ -0,0 +1,322 @@ +1.14.1 / 2016-08-24 +=================== + + * Fix not always resetting session max age before session save + * Fix the cookie `sameSite` option to actually alter the `Set-Cookie` + * deps: uid-safe@~2.1.2 + - deps: base64-url@1.3.2 + +1.14.0 / 2016-07-01 +=================== + + * Correctly inherit from `EventEmitter` class in `Store` base class + * Fix issue where `Set-Cookie` `Expires` was not always updated + * Methods are no longer enumerable on `req.session` object + * deps: cookie@0.3.1 + - Add `sameSite` option + - Improve error message when `encode` is not a function + - Improve error message when `expires` is not a `Date` + - perf: enable strict mode + - perf: use for loop in parse + - perf: use string concatination for serialization + * deps: parseurl@~1.3.1 + - perf: enable strict mode + * deps: uid-safe@~2.1.1 + - Use `random-bytes` for byte source + - deps: base64-url@1.2.2 + * perf: enable strict mode + * perf: remove argument reassignment + +1.13.0 / 2016-01-10 +=================== + + * Fix `rolling: true` to not set cookie when no session exists + - Better `saveUninitialized: false` + `rolling: true` behavior + * deps: crc@3.4.0 + +1.12.1 / 2015-10-29 +=================== + + * deps: cookie@0.2.3 + - Fix cookie `Max-Age` to never be a floating point number + +1.12.0 / 2015-10-25 +=================== + + * Support the value `'auto'` in the `cookie.secure` option + * deps: cookie@0.2.2 + - Throw on invalid values provided to `serialize` + * deps: depd@~1.1.0 + - Enable strict mode in more places + - Support web browser loading + * deps: on-headers@~1.0.1 + - perf: enable strict mode + +1.11.3 / 2015-05-22 +=================== + + * deps: cookie@0.1.3 + - Slight optimizations + * deps: crc@3.3.0 + +1.11.2 / 2015-05-10 +=================== + + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: uid-safe@~2.0.0 + +1.11.1 / 2015-04-08 +=================== + + * Fix mutating `options.secret` value + +1.11.0 / 2015-04-07 +=================== + + * Support an array in `secret` option for key rotation + * deps: depd@~1.0.1 + +1.10.4 / 2015-03-15 +=================== + + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + +1.10.3 / 2015-02-16 +=================== + + * deps: cookie-signature@1.0.6 + * deps: uid-safe@1.1.0 + - Use `crypto.randomBytes`, if available + - deps: base64-url@1.2.1 + +1.10.2 / 2015-01-31 +=================== + + * deps: uid-safe@1.0.3 + - Fix error branch that would throw + - deps: base64-url@1.2.0 + +1.10.1 / 2015-01-08 +=================== + + * deps: uid-safe@1.0.2 + - Remove dependency on `mz` + +1.10.0 / 2015-01-05 +=================== + + * Add `store.touch` interface for session stores + * Fix `MemoryStore` expiration with `resave: false` + * deps: debug@~2.1.1 + +1.9.3 / 2014-12-02 +================== + + * Fix error when `req.sessionID` contains a non-string value + +1.9.2 / 2014-11-22 +================== + + * deps: crc@3.2.1 + - Minor fixes + +1.9.1 / 2014-10-22 +================== + + * Remove unnecessary empty write call + - Fixes Node.js 0.11.14 behavior change + - Helps work-around Node.js 0.10.1 zlib bug + +1.9.0 / 2014-09-16 +================== + + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + +1.8.2 / 2014-09-15 +================== + + * Use `crc` instead of `buffer-crc32` for speed + * deps: depd@0.4.5 + +1.8.1 / 2014-09-08 +================== + + * Keep `req.session.save` non-enumerable + * Prevent session prototype methods from being overwritten + +1.8.0 / 2014-09-07 +================== + + * Do not resave already-saved session at end of request + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + +1.7.6 / 2014-08-18 +================== + + * Fix exception on `res.end(null)` calls + +1.7.5 / 2014-08-10 +================== + + * Fix parsing original URL + * deps: on-headers@~1.0.0 + * deps: parseurl@~1.3.0 + +1.7.4 / 2014-08-05 +================== + + * Fix response end delay for non-chunked responses + +1.7.3 / 2014-08-05 +================== + + * Fix `res.end` patch to call correct upstream `res.write` + +1.7.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + +1.7.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + +1.7.0 / 2014-07-22 +================== + + * Improve session-ending error handling + - Errors are passed to `next(err)` instead of `console.error` + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + +1.6.5 / 2014-07-11 +================== + + * Do not require `req.originalUrl` + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + +1.6.4 / 2014-07-07 +================== + + * Fix blank responses for stores with synchronous operations + +1.6.3 / 2014-07-04 +================== + + * Fix resave deprecation message + +1.6.2 / 2014-07-04 +================== + + * Fix confusing option deprecation messages + +1.6.1 / 2014-06-28 +================== + + * Fix saveUninitialized deprecation message + +1.6.0 / 2014-06-28 +================== + + * Add deprecation message to undefined `resave` option + * Add deprecation message to undefined `saveUninitialized` option + * Fix `res.end` patch to return correct value + * Fix `res.end` patch to handle multiple `res.end` calls + * Reject cookies with missing signatures + +1.5.2 / 2014-06-26 +================== + + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +1.5.1 / 2014-06-21 +================== + + * Move hard-to-track-down `req.secret` deprecation message + +1.5.0 / 2014-06-19 +================== + + * Debug name is now "express-session" + * Deprecate integration with `cookie-parser` middleware + * Deprecate looking for secret in `req.secret` + * Directly read cookies; `cookie-parser` no longer required + * Directly set cookies; `res.cookie` no longer required + * Generate session IDs with `uid-safe`, faster and even less collisions + +1.4.0 / 2014-06-17 +================== + + * Add `genid` option to generate custom session IDs + * Add `saveUninitialized` option to control saving uninitialized sessions + * Add `unset` option to control unsetting `req.session` + * Generate session IDs with `rand-token` by default; reduce collisions + * deps: buffer-crc32@0.2.3 + +1.3.1 / 2014-06-14 +================== + + * Add description in package for npmjs.org listing + +1.3.0 / 2014-06-14 +================== + + * Integrate with express "trust proxy" by default + * deps: debug@1.0.2 + +1.2.1 / 2014-05-27 +================== + + * Fix `resave` such that `resave: true` works + +1.2.0 / 2014-05-19 +================== + + * Add `resave` option to control saving unmodified sessions + +1.1.0 / 2014-05-12 +================== + + * Add `name` option; replacement for `key` option + * Use `setImmediate` in MemoryStore for node.js >= 0.10 + +1.0.4 / 2014-04-27 +================== + + * deps: debug@0.8.1 + +1.0.3 / 2014-04-19 +================== + + * Use `res.cookie()` instead of `res.setHeader()` + * deps: cookie@0.1.2 + +1.0.2 / 2014-02-23 +================== + + * Add missing dependency to `package.json` + +1.0.1 / 2014-02-15 +================== + + * Add missing dependencies to `package.json` + +1.0.0 / 2014-02-15 +================== + + * Genesis from `connect` diff --git a/node_modules/express-session/LICENSE b/node_modules/express-session/LICENSE new file mode 100644 index 0000000..9b59ff8 --- /dev/null +++ b/node_modules/express-session/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 TJ Holowaychukviews: ' + sess.views + '
') + res.write('expires in: ' + (sess.cookie.maxAge / 1000) + 's
') + res.end() + } else { + sess.views = 1 + res.end('welcome to the session demo. refresh!') + } +}) +``` + +#### Session.regenerate() + +To regenerate the session simply invoke the method. Once complete, +a new SID and `Session` instance will be initialized at `req.session`. + +```js +req.session.regenerate(function(err) { + // will have a new session here +}) +``` + +#### Session.destroy() + +Destroys the session, removing `req.session`; will be re-generated next request. + +```js +req.session.destroy(function(err) { + // cannot access session here +}) +``` + +#### Session.reload() + +Reloads the session data. + +```js +req.session.reload(function(err) { + // session updated +}) +``` + +#### Session.save() + +Save the session back to the store, replacing the contents on the store with the +contents in memory (though a store may do something else--consult the store's +documentation for exact behavior). + +This method is automatically called at the end of the HTTP response if the +session data has been altered (though this behavior can be altered with various +options in the middleware constructor). Because of this, typically this method +does not need to be called. + +There are some cases where it is useful to call this method, for example, long- +lived requests or in WebSockets. + +```js +req.session.save(function(err) { + // session saved +}) +``` + +#### Session.touch() + +Updates the `.maxAge` property. Typically this is +not necessary to call, as the session middleware does this for you. + +### req.session.id + +Each session has a unique ID associated with it. This property will +contain the session ID and cannot be modified. + +### req.session.cookie + +Each session has a unique cookie object accompany it. This allows +you to alter the session cookie per visitor. For example we can +set `req.session.cookie.expires` to `false` to enable the cookie +to remain for only the duration of the user-agent. + +#### Cookie.maxAge + +Alternatively `req.session.cookie.maxAge` will return the time +remaining in milliseconds, which we may also re-assign a new value +to adjust the `.expires` property appropriately. The following +are essentially equivalent + +```js +var hour = 3600000 +req.session.cookie.expires = new Date(Date.now() + hour) +req.session.cookie.maxAge = hour +``` + +For example when `maxAge` is set to `60000` (one minute), and 30 seconds +has elapsed it will return `30000` until the current request has completed, +at which time `req.session.touch()` is called to reset `req.session.maxAge` +to its original value. + +```js +req.session.cookie.maxAge // => 30000 +``` + +### req.sessionID + +To get the ID of the loaded session, access the request property +`req.sessionID`. This is simply a read-only value set when a session +is loaded/created. + +## Session Store Implementation + +Every session store _must_ be an `EventEmitter` and implement specific +methods. The following methods are the list of **required**, **recommended**, +and **optional**. + + * Required methods are ones that this module will always call on the store. + * Recommended methods are ones that this module will call on the store if + available. + * Optional methods are ones this module does not call at all, but helps + present uniform stores to users. + +For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo. + +### store.all(callback) + +**Optional** + +This optional method is used to get all sessions in the store as an array. The +`callback` should be called as `callback(error, sessions)`. + +### store.destroy(sid, callback) + +**Required** + +This required method is used to destroy/delete a session from the store given +a session ID (`sid`). The `callback` should be called as `callback(error)` once +the session is destroyed. + +### store.clear(callback) + +**Optional** + +This optional method is used to delete all sessions from the store. The +`callback` should be called as `callback(error)` once the store is cleared. + +### store.length(callback) + +**Optional** + +This optional method is used to get the count of all sessions in the store. +The `callback` should be called as `callback(error, len)`. + +### store.get(sid, callback) + +**Required** + +This required method is used to get a session from the store given a session +ID (`sid`). The `callback` should be called as `callback(error, session)`. + +The `session` argument should be a session if found, otherwise `null` or +`undefined` if the session was not found (and there was no error). A special +case is made when `error.code === 'ENOENT'` to act like `callback(null, null)`. + +### store.set(sid, session, callback) + +**Required** + +This required method is used to upsert a session into the store given a +session ID (`sid`) and session (`session`) object. The callback should be +called as `callback(error)` once the session has been set in the store. + +### store.touch(sid, session, callback) + +**Recommended** + +This recommended method is used to "touch" a given session given a +session ID (`sid`) and session (`session`) object. The `callback` should be +called as `callback(error)` once the session has been touched. + +This is primarily used when the store will automatically delete idle sessions +and this method is used to signal to the store the given session is active, +potentially resetting the idle timer. + +## Compatible Session Stores + +The following modules implement a session store that is compatible with this +module. Please make a PR to add additional modules :) + +[![★][aerospike-session-store-image] aerospike-session-store][aerospike-session-store-url] A session store using [Aerospike](http://www.aerospike.com/). + +[aerospike-session-store-url]: https://www.npmjs.com/package/aerospike-session-store +[aerospike-session-store-image]: https://img.shields.io/github/stars/aerospike/aerospike-session-store-expressjs.svg?label=%E2%98%85 + +[![★][cassandra-store-image] cassandra-store][cassandra-store-url] An Apache Cassandra-based session store. + +[cassandra-store-url]: https://www.npmjs.com/package/cassandra-store +[cassandra-store-image]: https://img.shields.io/github/stars/webcc/cassandra-store.svg?label=%E2%98%85 + +[![★][cluster-store-image] cluster-store][cluster-store-url] A wrapper for using in-process / embedded +stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2 +and other multi-core embedded devices). + +[cluster-store-url]: https://www.npmjs.com/package/cluster-store +[cluster-store-image]: https://img.shields.io/github/stars/coolaj86/cluster-store.svg?label=%E2%98%85 + +[![★][connect-azuretables-image] connect-azuretables][connect-azuretables-url] An [Azure Table Storage](https://azure.microsoft.com/en-gb/services/storage/tables/)-based session store. + +[connect-azuretables-url]: https://www.npmjs.com/package/connect-azuretables +[connect-azuretables-image]: https://img.shields.io/github/stars/mike-goodwin/connect-azuretables.svg?label=%E2%98%85 + +[![★][connect-couchbase-image] connect-couchbase][connect-couchbase-url] A [couchbase](http://www.couchbase.com/)-based session store. + +[connect-couchbase-url]: https://www.npmjs.com/package/connect-couchbase +[connect-couchbase-image]: https://img.shields.io/github/stars/christophermina/connect-couchbase.svg?label=%E2%98%85 + +[![★][connect-db2-image] connect-db2][connect-db2-url] An IBM DB2-based session store built using [ibm_db](https://www.npmjs.com/package/ibm_db) module. + +[connect-db2-url]: https://www.npmjs.com/package/connect-db2 +[connect-db2-image]: https://img.shields.io/github/stars/wallali/connect-db2.svg?label=%E2%98%85 + +[![★][connect-dynamodb-image] connect-dynamodb][connect-dynamodb-url] A DynamoDB-based session store. + +[connect-dynamodb-url]: https://github.com/ca98am79/connect-dynamodb +[connect-dynamodb-image]: https://img.shields.io/github/stars/ca98am79/connect-dynamodb.svg?label=%E2%98%85 + +[![★][connect-loki-image] connect-loki][connect-loki-url] A Loki.js-based session store. + +[connect-loki-url]: https://www.npmjs.com/package/connect-loki +[connect-loki-image]: https://img.shields.io/github/stars/Requarks/connect-loki.svg?label=%E2%98%85 + +[![★][connect-mssql-image] connect-mssql][connect-mssql-url] A SQL Server-based session store. + +[connect-mssql-url]: https://www.npmjs.com/package/connect-mssql +[connect-mssql-image]: https://img.shields.io/github/stars/patriksimek/connect-mssql.svg?label=%E2%98%85 + +[![★][connect-monetdb-image] connect-monetdb][connect-monetdb-url] A MonetDB-based session store. + +[connect-monetdb-url]: https://www.npmjs.com/package/connect-monetdb +[connect-monetdb-image]: https://img.shields.io/github/stars/MonetDB/npm-connect-monetdb.svg?label=%E2%98%85 + +[![★][connect-mongo-image] connect-mongo][connect-mongo-url] A MongoDB-based session store. + +[connect-mongo-url]: https://www.npmjs.com/package/connect-mongo +[connect-mongo-image]: https://img.shields.io/github/stars/kcbanner/connect-mongo.svg?label=%E2%98%85 + +[![★][connect-mongodb-session-image] connect-mongodb-session][connect-mongodb-session-url] Lightweight MongoDB-based session store built and maintained by MongoDB. + +[connect-mongodb-session-url]: https://www.npmjs.com/package/connect-mongodb-session +[connect-mongodb-session-image]: https://img.shields.io/github/stars/mongodb-js/connect-mongodb-session.svg?label=%E2%98%85 + +[![★][connect-pg-simple-image] connect-pg-simple][connect-pg-simple-url] A PostgreSQL-based session store. + +[connect-pg-simple-url]: https://www.npmjs.com/package/connect-pg-simple +[connect-pg-simple-image]: https://img.shields.io/github/stars/voxpelli/node-connect-pg-simple.svg?label=%E2%98%85 + +[![★][connect-redis-image] connect-redis][connect-redis-url] A Redis-based session store. + +[connect-redis-url]: https://www.npmjs.com/package/connect-redis +[connect-redis-image]: https://img.shields.io/github/stars/tj/connect-redis.svg?label=%E2%98%85 + +[![★][connect-memcached-image] connect-memcached][connect-memcached-url] A memcached-based session store. + +[connect-memcached-url]: https://www.npmjs.com/package/connect-memcached +[connect-memcached-image]: https://img.shields.io/github/stars/balor/connect-memcached.svg?label=%E2%98%85 + +[![★][connect-session-knex-image] connect-session-knex][connect-session-knex-url] A session store using +[Knex.js](http://knexjs.org/), which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle. + +[connect-session-knex-url]: https://www.npmjs.com/package/connect-session-knex +[connect-session-knex-image]: https://img.shields.io/github/stars/llambda/connect-session-knex.svg?label=%E2%98%85 + +[![★][connect-session-sequelize-image] connect-session-sequelize][connect-session-sequelize-url] A session store using +[Sequelize.js](http://sequelizejs.com/), which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL. + +[connect-session-sequelize-url]: https://www.npmjs.com/package/connect-session-sequelize +[connect-session-sequelize-image]: https://img.shields.io/github/stars/mweibel/connect-session-sequelize.svg?label=%E2%98%85 + +[![★][express-mysql-session-image] express-mysql-session][express-mysql-session-url] A session store using native +[MySQL](https://www.mysql.com/) via the [node-mysql](https://github.com/felixge/node-mysql) module. + +[express-mysql-session-url]: https://www.npmjs.com/package/express-mysql-session +[express-mysql-session-image]: https://img.shields.io/github/stars/chill117/express-mysql-session.svg?label=%E2%98%85 + +[![★][connect-sqlite3-image] connect-sqlite3][connect-sqlite3-url] A [SQLite3](https://github.com/mapbox/node-sqlite3) session store modeled after the TJ's `connect-redis` store. + +[connect-sqlite3-url]: https://www.npmjs.com/package/connect-sqlite3 +[connect-sqlite3-image]: https://img.shields.io/github/stars/rawberg/connect-sqlite3.svg?label=%E2%98%85 + +[![★][express-nedb-session-image] express-nedb-session][express-nedb-session-url] A NeDB-based session store. + +[express-nedb-session-url]: https://www.npmjs.com/package/express-nedb-session +[express-nedb-session-image]: https://img.shields.io/github/stars/louischatriot/express-nedb-session.svg?label=%E2%98%85 + +[![★][level-session-store-image] level-session-store][level-session-store-url] A LevelDB-based session store. + +[level-session-store-url]: https://www.npmjs.com/package/level-session-store +[level-session-store-image]: https://img.shields.io/github/stars/scriptollc/level-session-store.svg?label=%E2%98%85 + +[![★][medea-session-store-image] medea-session-store][medea-session-store-url] A Medea-based session store. + +[medea-session-store-url]: https://www.npmjs.com/package/medea-session-store +[medea-session-store-image]: https://img.shields.io/github/stars/BenjaminVadant/medea-session-store.svg?label=%E2%98%85 + +[![★][mssql-session-store-image] mssql-session-store][mssql-session-store-url] A SQL Server-based session store. + +[mssql-session-store-url]: https://www.npmjs.com/package/mssql-session-store +[mssql-session-store-image]: https://img.shields.io/github/stars/jwathen/mssql-session-store.svg?label=%E2%98%85 + +[![★][nedb-session-store-image] nedb-session-store][nedb-session-store-url] An alternate NeDB-based (either in-memory or file-persisted) session store. + +[nedb-session-store-url]: https://www.npmjs.com/package/nedb-session-store +[nedb-session-store-image]: https://img.shields.io/github/stars/JamesMGreene/nedb-session-store.svg?label=%E2%98%85 + +[![★][sequelstore-connect-image] sequelstore-connect][sequelstore-connect-url] A session store using [Sequelize.js](http://sequelizejs.com/). + +[sequelstore-connect-url]: https://www.npmjs.com/package/sequelstore-connect +[sequelstore-connect-image]: https://img.shields.io/github/stars/MattMcFarland/sequelstore-connect.svg?label=%E2%98%85 + +[![★][session-file-store-image] session-file-store][session-file-store-url] A file system-based session store. + +[session-file-store-url]: https://www.npmjs.com/package/session-file-store +[session-file-store-image]: https://img.shields.io/github/stars/valery-barysok/session-file-store.svg?label=%E2%98%85 + +[![★][session-rethinkdb-image] session-rethinkdb][session-rethinkdb-url] A [RethinkDB](http://rethinkdb.com/)-based session store. + +[session-rethinkdb-url]: https://www.npmjs.com/package/session-rethinkdb +[session-rethinkdb-image]: https://img.shields.io/github/stars/llambda/session-rethinkdb.svg?label=%E2%98%85 + +## Example + +A simple example using `express-session` to store page views for a user. + +```js +var express = require('express') +var parseurl = require('parseurl') +var session = require('express-session') + +var app = express() + +app.use(session({ + secret: 'keyboard cat', + resave: false, + saveUninitialized: true +})) + +app.use(function (req, res, next) { + var views = req.session.views + + if (!views) { + views = req.session.views = {} + } + + // get the url pathname + var pathname = parseurl(req).pathname + + // count the views + views[pathname] = (views[pathname] || 0) + 1 + + next() +}) + +app.get('/foo', function (req, res, next) { + res.send('you viewed this page ' + req.session.views['/foo'] + ' times') +}) + +app.get('/bar', function (req, res, next) { + res.send('you viewed this page ' + req.session.views['/bar'] + ' times') +}) +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/express-session.svg +[npm-url]: https://npmjs.org/package/express-session +[travis-image]: https://img.shields.io/travis/expressjs/session/master.svg +[travis-url]: https://travis-ci.org/expressjs/session +[coveralls-image]: https://img.shields.io/coveralls/expressjs/session/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/session?branch=master +[downloads-image]: https://img.shields.io/npm/dm/express-session.svg +[downloads-url]: https://npmjs.org/package/express-session +[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg +[gratipay-url]: https://gratipay.com/dougwilson/ diff --git a/node_modules/express-session/index.js b/node_modules/express-session/index.js new file mode 100644 index 0000000..2241d97 --- /dev/null +++ b/node_modules/express-session/index.js @@ -0,0 +1,647 @@ +/*! + * express-session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var cookie = require('cookie'); +var crc = require('crc').crc32; +var debug = require('debug')('express-session'); +var deprecate = require('depd')('express-session'); +var parseUrl = require('parseurl'); +var uid = require('uid-safe').sync + , onHeaders = require('on-headers') + , signature = require('cookie-signature') + +var Session = require('./session/session') + , MemoryStore = require('./session/memory') + , Cookie = require('./session/cookie') + , Store = require('./session/store') + +// environment + +var env = process.env.NODE_ENV; + +/** + * Expose the middleware. + */ + +exports = module.exports = session; + +/** + * Expose constructors. + */ + +exports.Store = Store; +exports.Cookie = Cookie; +exports.Session = Session; +exports.MemoryStore = MemoryStore; + +/** + * Warning message for `MemoryStore` usage in production. + * @private + */ + +var warning = 'Warning: connect.session() MemoryStore is not\n' + + 'designed for a production environment, as it will leak\n' + + 'memory, and will not scale past a single process.'; + +/** + * Node.js 0.8+ async implementation. + * @private + */ + +/* istanbul ignore next */ +var defer = typeof setImmediate === 'function' + ? setImmediate + : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) } + +/** + * Setup session store with the given `options`. + * + * @param {Object} [options] + * @param {Object} [options.cookie] Options for cookie + * @param {Function} [options.genid] + * @param {String} [options.name=connect.sid] Session ID cookie name + * @param {Boolean} [options.proxy] + * @param {Boolean} [options.resave] Resave unmodified sessions back to the store + * @param {Boolean} [options.rolling] Enable/disable rolling session expiration + * @param {Boolean} [options.saveUninitialized] Save uninitialized sessions to the store + * @param {String|Array} [options.secret] Secret for signing session ID + * @param {Object} [options.store=MemoryStore] Session store + * @param {String} [options.unset] + * @return {Function} middleware + * @public + */ + +function session(options) { + var opts = options || {} + + // get the cookie options + var cookieOptions = opts.cookie || {} + + // get the session id generate function + var generateId = opts.genid || generateSessionId + + // get the session cookie name + var name = opts.name || opts.key || 'connect.sid' + + // get the session store + var store = opts.store || new MemoryStore() + + // get the trust proxy setting + var trustProxy = opts.proxy + + // get the resave session option + var resaveSession = opts.resave; + + // get the rolling session option + var rollingSessions = Boolean(opts.rolling) + + // get the save uninitialized session option + var saveUninitializedSession = opts.saveUninitialized + + // get the cookie signing secret + var secret = opts.secret + + if (typeof generateId !== 'function') { + throw new TypeError('genid option must be a function'); + } + + if (resaveSession === undefined) { + deprecate('undefined resave option; provide resave option'); + resaveSession = true; + } + + if (saveUninitializedSession === undefined) { + deprecate('undefined saveUninitialized option; provide saveUninitialized option'); + saveUninitializedSession = true; + } + + if (opts.unset && opts.unset !== 'destroy' && opts.unset !== 'keep') { + throw new TypeError('unset option must be "destroy" or "keep"'); + } + + // TODO: switch to "destroy" on next major + var unsetDestroy = opts.unset === 'destroy' + + if (Array.isArray(secret) && secret.length === 0) { + throw new TypeError('secret option array must contain one or more strings'); + } + + if (secret && !Array.isArray(secret)) { + secret = [secret]; + } + + if (!secret) { + deprecate('req.secret; provide secret option'); + } + + // notify user that this store is not + // meant for a production environment + if ('production' == env && store instanceof MemoryStore) { + /* istanbul ignore next: not tested */ + console.warn(warning); + } + + // generates the new session + store.generate = function(req){ + req.sessionID = generateId(req); + req.session = new Session(req); + req.session.cookie = new Cookie(cookieOptions); + + if (cookieOptions.secure === 'auto') { + req.session.cookie.secure = issecure(req, trustProxy); + } + }; + + var storeImplementsTouch = typeof store.touch === 'function'; + + // register event listeners for the store to track readiness + var storeReady = true + store.on('disconnect', function ondisconnect() { + storeReady = false + }) + store.on('connect', function onconnect() { + storeReady = true + }) + + return function session(req, res, next) { + // self-awareness + if (req.session) { + next() + return + } + + // Handle connection as if there is no session if + // the store has temporarily disconnected etc + if (!storeReady) { + debug('store is disconnected') + next() + return + } + + // pathname mismatch + var originalPath = parseUrl.original(req).pathname; + if (originalPath.indexOf(cookieOptions.path || '/') !== 0) return next(); + + // ensure a secret is available or bail + if (!secret && !req.secret) { + next(new Error('secret option required for sessions')); + return; + } + + // backwards compatibility for signed cookies + // req.secret is passed from the cookie parser middleware + var secrets = secret || [req.secret]; + + var originalHash; + var originalId; + var savedHash; + var touched = false + + // expose store + req.sessionStore = store; + + // get the session ID from the cookie + var cookieId = req.sessionID = getcookie(req, name, secrets); + + // set-cookie + onHeaders(res, function(){ + if (!req.session) { + debug('no session'); + return; + } + + if (!shouldSetCookie(req)) { + return; + } + + // only send secure cookies via https + if (req.session.cookie.secure && !issecure(req, trustProxy)) { + debug('not secured'); + return; + } + + if (!touched) { + // touch session + req.session.touch() + touched = true + } + + // set cookie + setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data); + }); + + // proxy end() to commit the session + var _end = res.end; + var _write = res.write; + var ended = false; + res.end = function end(chunk, encoding) { + if (ended) { + return false; + } + + ended = true; + + var ret; + var sync = true; + + function writeend() { + if (sync) { + ret = _end.call(res, chunk, encoding); + sync = false; + return; + } + + _end.call(res); + } + + function writetop() { + if (!sync) { + return ret; + } + + if (chunk == null) { + ret = true; + return ret; + } + + var contentLength = Number(res.getHeader('Content-Length')); + + if (!isNaN(contentLength) && contentLength > 0) { + // measure chunk + chunk = !Buffer.isBuffer(chunk) + ? new Buffer(chunk, encoding) + : chunk; + encoding = undefined; + + if (chunk.length !== 0) { + debug('split response'); + ret = _write.call(res, chunk.slice(0, chunk.length - 1)); + chunk = chunk.slice(chunk.length - 1, chunk.length); + return ret; + } + } + + ret = _write.call(res, chunk, encoding); + sync = false; + + return ret; + } + + if (shouldDestroy(req)) { + // destroy session + debug('destroying'); + store.destroy(req.sessionID, function ondestroy(err) { + if (err) { + defer(next, err); + } + + debug('destroyed'); + writeend(); + }); + + return writetop(); + } + + // no session to save + if (!req.session) { + debug('no session'); + return _end.call(res, chunk, encoding); + } + + if (!touched) { + // touch session + req.session.touch() + touched = true + } + + if (shouldSave(req)) { + req.session.save(function onsave(err) { + if (err) { + defer(next, err); + } + + writeend(); + }); + + return writetop(); + } else if (storeImplementsTouch && shouldTouch(req)) { + // store implements touch method + debug('touching'); + store.touch(req.sessionID, req.session, function ontouch(err) { + if (err) { + defer(next, err); + } + + debug('touched'); + writeend(); + }); + + return writetop(); + } + + return _end.call(res, chunk, encoding); + }; + + // generate the session + function generate() { + store.generate(req); + originalId = req.sessionID; + originalHash = hash(req.session); + wrapmethods(req.session); + } + + // wrap session methods + function wrapmethods(sess) { + var _save = sess.save; + + function save() { + debug('saving %s', this.id); + savedHash = hash(this); + _save.apply(this, arguments); + } + + Object.defineProperty(sess, 'save', { + configurable: true, + enumerable: false, + value: save, + writable: true + }); + } + + // check if session has been modified + function isModified(sess) { + return originalId !== sess.id || originalHash !== hash(sess); + } + + // check if session has been saved + function isSaved(sess) { + return originalId === sess.id && savedHash === hash(sess); + } + + // determine if session should be destroyed + function shouldDestroy(req) { + return req.sessionID && unsetDestroy && req.session == null; + } + + // determine if session should be saved to store + function shouldSave(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + debug('session ignored because of bogus req.sessionID %o', req.sessionID); + return false; + } + + return !saveUninitializedSession && cookieId !== req.sessionID + ? isModified(req.session) + : !isSaved(req.session) + } + + // determine if session should be touched + function shouldTouch(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + debug('session ignored because of bogus req.sessionID %o', req.sessionID); + return false; + } + + return cookieId === req.sessionID && !shouldSave(req); + } + + // determine if cookie should be set on response + function shouldSetCookie(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + return false; + } + + return cookieId != req.sessionID + ? saveUninitializedSession || isModified(req.session) + : rollingSessions || req.session.cookie.expires != null && isModified(req.session); + } + + // generate a session if the browser doesn't send a sessionID + if (!req.sessionID) { + debug('no SID sent, generating session'); + generate(); + next(); + return; + } + + // generate the session object + debug('fetching %s', req.sessionID); + store.get(req.sessionID, function(err, sess){ + // error handling + if (err) { + debug('error %j', err); + + if (err.code !== 'ENOENT') { + next(err); + return; + } + + generate(); + // no session + } else if (!sess) { + debug('no session found'); + generate(); + // populate req.session + } else { + debug('session found'); + store.createSession(req, sess); + originalId = req.sessionID; + originalHash = hash(sess); + + if (!resaveSession) { + savedHash = originalHash + } + + wrapmethods(req.session); + } + + next(); + }); + }; +}; + +/** + * Generate a session ID for a new session. + * + * @return {String} + * @private + */ + +function generateSessionId(sess) { + return uid(24); +} + +/** + * Get the session ID cookie from request. + * + * @return {string} + * @private + */ + +function getcookie(req, name, secrets) { + var header = req.headers.cookie; + var raw; + var val; + + // read from cookie header + if (header) { + var cookies = cookie.parse(header); + + raw = cookies[name]; + + if (raw) { + if (raw.substr(0, 2) === 's:') { + val = unsigncookie(raw.slice(2), secrets); + + if (val === false) { + debug('cookie signature invalid'); + val = undefined; + } + } else { + debug('cookie unsigned') + } + } + } + + // back-compat read from cookieParser() signedCookies data + if (!val && req.signedCookies) { + val = req.signedCookies[name]; + + if (val) { + deprecate('cookie should be available in req.headers.cookie'); + } + } + + // back-compat read from cookieParser() cookies data + if (!val && req.cookies) { + raw = req.cookies[name]; + + if (raw) { + if (raw.substr(0, 2) === 's:') { + val = unsigncookie(raw.slice(2), secrets); + + if (val) { + deprecate('cookie should be available in req.headers.cookie'); + } + + if (val === false) { + debug('cookie signature invalid'); + val = undefined; + } + } else { + debug('cookie unsigned') + } + } + } + + return val; +} + +/** + * Hash the given `sess` object omitting changes to `.cookie`. + * + * @param {Object} sess + * @return {String} + * @private + */ + +function hash(sess) { + return crc(JSON.stringify(sess, function (key, val) { + if (key !== 'cookie') { + return val; + } + })); +} + +/** + * Determine if request is secure. + * + * @param {Object} req + * @param {Boolean} [trustProxy] + * @return {Boolean} + * @private + */ + +function issecure(req, trustProxy) { + // socket is https server + if (req.connection && req.connection.encrypted) { + return true; + } + + // do not trust proxy + if (trustProxy === false) { + return false; + } + + // no explicit trust; try req.secure from express + if (trustProxy !== true) { + var secure = req.secure; + return typeof secure === 'boolean' + ? secure + : false; + } + + // read the proto from x-forwarded-proto header + var header = req.headers['x-forwarded-proto'] || ''; + var index = header.indexOf(','); + var proto = index !== -1 + ? header.substr(0, index).toLowerCase().trim() + : header.toLowerCase().trim() + + return proto === 'https'; +} + +/** + * Set cookie on response. + * + * @private + */ + +function setcookie(res, name, val, secret, options) { + var signed = 's:' + signature.sign(val, secret); + var data = cookie.serialize(name, signed, options); + + debug('set-cookie %s', data); + + var prev = res.getHeader('set-cookie') || []; + var header = Array.isArray(prev) ? prev.concat(data) + : Array.isArray(data) ? [prev].concat(data) + : [prev, data]; + + res.setHeader('set-cookie', header) +} + +/** + * Verify and decode the given `val` with `secrets`. + * + * @param {String} val + * @param {Array} secrets + * @returns {String|Boolean} + * @private + */ +function unsigncookie(val, secrets) { + for (var i = 0; i < secrets.length; i++) { + var result = signature.unsign(val, secrets[i]); + + if (result !== false) { + return result; + } + } + + return false; +} diff --git a/node_modules/express-session/package.json b/node_modules/express-session/package.json new file mode 100644 index 0000000..276e0d3 --- /dev/null +++ b/node_modules/express-session/package.json @@ -0,0 +1,131 @@ +{ + "_args": [ + [ + { + "raw": "express-session", + "scope": null, + "escapedName": "express-session", + "name": "express-session", + "rawSpec": "", + "spec": "latest", + "type": "tag" + }, + "C:\\Users\\punkryn\\dev\\js\\server_side_javascript" + ] + ], + "_from": "express-session@latest", + "_id": "express-session@1.14.1", + "_inCache": true, + "_installable": true, + "_location": "/express-session", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/express-session-1.14.1.tgz_1472059273028_0.5192838909570128" + }, + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "raw": "express-session", + "scope": null, + "escapedName": "express-session", + "name": "express-session", + "rawSpec": "", + "spec": "latest", + "type": "tag" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/express-session/-/express-session-1.14.1.tgz", + "_shasum": "600364f0f6bf5dce32649e006770bdeee80aec99", + "_shrinkwrap": null, + "_spec": "express-session", + "_where": "C:\\Users\\punkryn\\dev\\js\\server_side_javascript", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "bugs": { + "url": "https://github.com/expressjs/session/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Joe Wagner", + "email": "njwjs722@gmail.com" + } + ], + "dependencies": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.0", + "debug": "~2.2.0", + "depd": "~1.1.0", + "on-headers": "~1.0.1", + "parseurl": "~1.3.1", + "uid-safe": "~2.1.2", + "utils-merge": "1.0.0" + }, + "description": "Simple session middleware for Express", + "devDependencies": { + "after": "0.8.2", + "cookie-parser": "1.4.3", + "express": "4.14.0", + "istanbul": "0.4.5", + "mocha": "2.5.3", + "supertest": "1.1.0" + }, + "directories": {}, + "dist": { + "shasum": "600364f0f6bf5dce32649e006770bdeee80aec99", + "tarball": "https://registry.npmjs.org/express-session/-/express-session-1.14.1.tgz" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "session/", + "HISTORY.md", + "LICENSE", + "index.js" + ], + "gitHead": "19b8f725d924035574d71e22bcb0a7d06c09ae80", + "homepage": "https://github.com/expressjs/session", + "license": "MIT", + "maintainers": [ + { + "name": "defunctzombie", + "email": "shtylman@gmail.com" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "mscdex", + "email": "mscdex@mscdex.net" + } + ], + "name": "express-session", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/expressjs/session.git" + }, + "scripts": { + "test": "mocha --bail --reporter spec test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec test/" + }, + "version": "1.14.1" +} diff --git a/node_modules/express-session/session/cookie.js b/node_modules/express-session/session/cookie.js new file mode 100644 index 0000000..60ef22a --- /dev/null +++ b/node_modules/express-session/session/cookie.js @@ -0,0 +1,130 @@ +/*! + * Connect - session - Cookie + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + */ + +var merge = require('utils-merge') + , cookie = require('cookie'); + +/** + * Initialize a new `Cookie` with the given `options`. + * + * @param {IncomingMessage} req + * @param {Object} options + * @api private + */ + +var Cookie = module.exports = function Cookie(options) { + this.path = '/'; + this.maxAge = null; + this.httpOnly = true; + if (options) merge(this, options); + this.originalMaxAge = undefined == this.originalMaxAge + ? this.maxAge + : this.originalMaxAge; +}; + +/*! + * Prototype. + */ + +Cookie.prototype = { + + /** + * Set expires `date`. + * + * @param {Date} date + * @api public + */ + + set expires(date) { + this._expires = date; + this.originalMaxAge = this.maxAge; + }, + + /** + * Get expires `date`. + * + * @return {Date} + * @api public + */ + + get expires() { + return this._expires; + }, + + /** + * Set expires via max-age in `ms`. + * + * @param {Number} ms + * @api public + */ + + set maxAge(ms) { + this.expires = 'number' == typeof ms + ? new Date(Date.now() + ms) + : ms; + }, + + /** + * Get expires max-age in `ms`. + * + * @return {Number} + * @api public + */ + + get maxAge() { + return this.expires instanceof Date + ? this.expires.valueOf() - Date.now() + : this.expires; + }, + + /** + * Return cookie data object. + * + * @return {Object} + * @api private + */ + + get data() { + return { + originalMaxAge: this.originalMaxAge + , expires: this._expires + , secure: this.secure + , httpOnly: this.httpOnly + , domain: this.domain + , path: this.path + , sameSite: this.sameSite + } + }, + + /** + * Return a serialized cookie string. + * + * @return {String} + * @api public + */ + + serialize: function(name, val){ + return cookie.serialize(name, val, this.data); + }, + + /** + * Return JSON representation of this cookie. + * + * @return {Object} + * @api private + */ + + toJSON: function(){ + return this.data; + } +}; diff --git a/node_modules/express-session/session/memory.js b/node_modules/express-session/session/memory.js new file mode 100644 index 0000000..25252b6 --- /dev/null +++ b/node_modules/express-session/session/memory.js @@ -0,0 +1,185 @@ +/*! + * express-session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Store = require('./store') +var util = require('util') + +/** + * Shim setImmediate for node.js < 0.10 + * @private + */ + +/* istanbul ignore next */ +var defer = typeof setImmediate === 'function' + ? setImmediate + : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) } + +/** + * Module exports. + */ + +module.exports = MemoryStore + +/** + * A session store in memory. + * @public + */ + +function MemoryStore() { + Store.call(this) + this.sessions = Object.create(null) +} + +/** + * Inherit from Store. + */ + +util.inherits(MemoryStore, Store) + +/** + * Get all active sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.all = function all(callback) { + var sessionIds = Object.keys(this.sessions) + var sessions = Object.create(null) + + for (var i = 0; i < sessionIds.length; i++) { + var sessionId = sessionIds[i] + var session = getSession.call(this, sessionId) + + if (session) { + sessions[sessionId] = session; + } + } + + callback && defer(callback, null, sessions) +} + +/** + * Clear all sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.clear = function clear(callback) { + this.sessions = Object.create(null) + callback && defer(callback) +} + +/** + * Destroy the session associated with the given session ID. + * + * @param {string} sessionId + * @public + */ + +MemoryStore.prototype.destroy = function destroy(sessionId, callback) { + delete this.sessions[sessionId] + callback && defer(callback) +} + +/** + * Fetch session by the given session ID. + * + * @param {string} sessionId + * @param {function} callback + * @public + */ + +MemoryStore.prototype.get = function get(sessionId, callback) { + defer(callback, null, getSession.call(this, sessionId)) +} + +/** + * Commit the given session associated with the given sessionId to the store. + * + * @param {string} sessionId + * @param {object} session + * @param {function} callback + * @public + */ + +MemoryStore.prototype.set = function set(sessionId, session, callback) { + this.sessions[sessionId] = JSON.stringify(session) + callback && defer(callback) +} + +/** + * Get number of active sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.length = function length(callback) { + this.all(function (err, sessions) { + if (err) return callback(err) + callback(null, Object.keys(sessions).length) + }) +} + +/** + * Touch the given session object associated with the given session ID. + * + * @param {string} sessionId + * @param {object} session + * @param {function} callback + * @public + */ + +MemoryStore.prototype.touch = function touch(sessionId, session, callback) { + var currentSession = getSession.call(this, sessionId) + + if (currentSession) { + // update expiration + currentSession.cookie = session.cookie + this.sessions[sessionId] = JSON.stringify(currentSession) + } + + callback && defer(callback) +} + +/** + * Get session from the store. + * @private + */ + +function getSession(sessionId) { + var sess = this.sessions[sessionId] + + if (!sess) { + return + } + + // parse + sess = JSON.parse(sess) + + var expires = typeof sess.cookie.expires === 'string' + ? new Date(sess.cookie.expires) + : sess.cookie.expires + + // destroy expired session + if (expires && expires <= Date.now()) { + delete this.sessions[sessionId] + return + } + + return sess +} diff --git a/node_modules/express-session/session/session.js b/node_modules/express-session/session/session.js new file mode 100644 index 0000000..2eacde6 --- /dev/null +++ b/node_modules/express-session/session/session.js @@ -0,0 +1,142 @@ +/*! + * Connect - session - Session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Expose Session. + */ + +module.exports = Session; + +/** + * Create a new `Session` with the given request and `data`. + * + * @param {IncomingRequest} req + * @param {Object} data + * @api private + */ + +function Session(req, data) { + Object.defineProperty(this, 'req', { value: req }); + Object.defineProperty(this, 'id', { value: req.sessionID }); + + if (typeof data === 'object' && data !== null) { + // merge data into this, ignoring prototype properties + for (var prop in data) { + if (!(prop in this)) { + this[prop] = data[prop] + } + } + } +} + +/** + * Update reset `.cookie.maxAge` to prevent + * the cookie from expiring when the + * session is still active. + * + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'touch', function touch() { + return this.resetMaxAge(); +}); + +/** + * Reset `.maxAge` to `.originalMaxAge`. + * + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'resetMaxAge', function resetMaxAge() { + this.cookie.maxAge = this.cookie.originalMaxAge; + return this; +}); + +/** + * Save the session data with optional callback `fn(err)`. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'save', function save(fn) { + this.req.sessionStore.set(this.id, this, fn || function(){}); + return this; +}); + +/** + * Re-loads the session data _without_ altering + * the maxAge properties. Invokes the callback `fn(err)`, + * after which time if no exception has occurred the + * `req.session` property will be a new `Session` object, + * although representing the same session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'reload', function reload(fn) { + var req = this.req + , store = this.req.sessionStore; + store.get(this.id, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(new Error('failed to load session')); + store.createSession(req, sess); + fn(); + }); + return this; +}); + +/** + * Destroy `this` session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'destroy', function destroy(fn) { + delete this.req.session; + this.req.sessionStore.destroy(this.id, fn); + return this; +}); + +/** + * Regenerate this request's session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'regenerate', function regenerate(fn) { + this.req.sessionStore.regenerate(this.req, fn); + return this; +}); + +/** + * Helper function for creating a method on a prototype. + * + * @param {Object} obj + * @param {String} name + * @param {Function} fn + * @private + */ +function defineMethod(obj, name, fn) { + Object.defineProperty(obj, name, { + configurable: true, + enumerable: false, + value: fn, + writable: true + }); +}; diff --git a/node_modules/express-session/session/store.js b/node_modules/express-session/session/store.js new file mode 100644 index 0000000..387469c --- /dev/null +++ b/node_modules/express-session/session/store.js @@ -0,0 +1,94 @@ +/*! + * Connect - session - Store + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Cookie = require('./cookie') +var EventEmitter = require('events').EventEmitter +var Session = require('./session') +var util = require('util') + +/** + * Module exports. + * @public + */ + +module.exports = Store + +/** + * Abstract base class for session stores. + * @public + */ + +function Store () { + EventEmitter.call(this) +} + +/** + * Inherit from EventEmitter. + */ + +util.inherits(Store, EventEmitter) + +/** + * Re-generate the given requests's session. + * + * @param {IncomingRequest} req + * @return {Function} fn + * @api public + */ + +Store.prototype.regenerate = function(req, fn){ + var self = this; + this.destroy(req.sessionID, function(err){ + self.generate(req); + fn(err); + }); +}; + +/** + * Load a `Session` instance via the given `sid` + * and invoke the callback `fn(err, sess)`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +Store.prototype.load = function(sid, fn){ + var self = this; + this.get(sid, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(); + var req = { sessionID: sid, sessionStore: self }; + fn(null, self.createSession(req, sess)) + }); +}; + +/** + * Create session from JSON `sess` data. + * + * @param {IncomingRequest} req + * @param {Object} sess + * @return {Session} + * @api private + */ + +Store.prototype.createSession = function(req, sess){ + var expires = sess.cookie.expires + , orig = sess.cookie.originalMaxAge; + sess.cookie = new Cookie(sess.cookie); + if ('string' == typeof expires) sess.cookie.expires = new Date(expires); + sess.cookie.originalMaxAge = orig; + req.session = new Session(req, sess); + return req.session; +}; diff --git a/node_modules/express/History.md b/node_modules/express/History.md new file mode 100644 index 0000000..40a5ed7 --- /dev/null +++ b/node_modules/express/History.md @@ -0,0 +1,3142 @@ +4.14.0 / 2016-06-16 +=================== + + * Add `acceptRanges` option to `res.sendFile`/`res.sendfile` + * Add `cacheControl` option to `res.sendFile`/`res.sendfile` + * Add `options` argument to `req.range` + - Includes the `combine` option + * Encode URL in `res.location`/`res.redirect` if not already encoded + * Fix some redirect handling in `res.sendFile`/`res.sendfile` + * Fix Windows absolute path check using forward slashes + * Improve error with invalid arguments to `req.get()` + * Improve performance for `res.json`/`res.jsonp` in most cases + * Improve `Range` header handling in `res.sendFile`/`res.sendfile` + * deps: accepts@~1.3.3 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Many performance improvments + - deps: mime-types@~2.1.11 + - deps: negotiator@0.6.1 + * deps: content-type@~1.0.2 + - perf: enable strict mode + * deps: cookie@0.3.1 + - Add `sameSite` option + - Fix cookie `Max-Age` to never be a floating point number + - Improve error message when `encode` is not a function + - Improve error message when `expires` is not a `Date` + - Throw better error for invalid argument to parse + - Throw on invalid values provided to `serialize` + - perf: enable strict mode + - perf: hoist regular expression + - perf: use for loop in parse + - perf: use string concatination for serialization + * deps: finalhandler@0.5.0 + - Change invalid or non-numeric status code to 500 + - Overwrite status message to match set status code + - Prefer `err.statusCode` if `err.status` is invalid + - Set response headers from `err.headers` object + - Use `statuses` instead of `http` module for status messages + * deps: proxy-addr@~1.1.2 + - Fix accepting various invalid netmasks + - Fix IPv6-mapped IPv4 validation edge cases + - IPv4 netmasks must be contingous + - IPv6 addresses cannot be used as a netmask + - deps: ipaddr.js@1.1.1 + * deps: qs@6.2.0 + - Add `decoder` option in `parse` function + * deps: range-parser@~1.2.0 + - Add `combine` option to combine overlapping ranges + - Fix incorrectly returning -1 when there is at least one valid range + - perf: remove internal function + * deps: send@0.14.1 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Correctly inherit from `Stream` class + - Fix `Content-Range` header in 416 responses when using `start`/`end` options + - Fix `Content-Range` header missing from default 416 responses + - Fix redirect error when `path` contains raw non-URL characters + - Fix redirect when `path` starts with multiple forward slashes + - Ignore non-byte `Range` headers + - deps: http-errors@~1.5.0 + - deps: range-parser@~1.2.0 + - deps: statuses@~1.3.0 + - perf: remove argument reassignment + * deps: serve-static@~1.11.1 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Fix redirect error when `req.url` contains raw non-URL characters + - Ignore non-byte `Range` headers + - Use status code 301 for redirects + - deps: send@0.14.1 + * deps: type-is@~1.6.13 + - Fix type error when given invalid type to match against + - deps: mime-types@~2.1.11 + * deps: vary@~1.1.0 + - Only accept valid field names in the `field` argument + * perf: use strict equality when possible + +4.13.4 / 2016-01-21 +=================== + + * deps: content-disposition@0.5.1 + - perf: enable strict mode + * deps: cookie@0.1.5 + - Throw on invalid values provided to `serialize` + * deps: depd@~1.1.0 + - Support web browser loading + - perf: enable strict mode + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + * deps: finalhandler@0.4.1 + - deps: escape-html@~1.0.3 + * deps: merge-descriptors@1.0.1 + - perf: enable strict mode + * deps: methods@~1.1.2 + - perf: enable strict mode + * deps: parseurl@~1.3.1 + - perf: enable strict mode + * deps: proxy-addr@~1.0.10 + - deps: ipaddr.js@1.0.5 + - perf: enable strict mode + * deps: range-parser@~1.0.3 + - perf: enable strict mode + * deps: send@0.13.1 + - deps: depd@~1.1.0 + - deps: destroy@~1.0.4 + - deps: escape-html@~1.0.3 + - deps: range-parser@~1.0.3 + * deps: serve-static@~1.10.2 + - deps: escape-html@~1.0.3 + - deps: parseurl@~1.3.0 + - deps: send@0.13.1 + +4.13.3 / 2015-08-02 +=================== + + * Fix infinite loop condition using `mergeParams: true` + * Fix inner numeric indices incorrectly altering parent `req.params` + +4.13.2 / 2015-07-31 +=================== + + * deps: accepts@~1.2.12 + - deps: mime-types@~2.1.4 + * deps: array-flatten@1.1.1 + - perf: enable strict mode + * deps: path-to-regexp@0.1.7 + - Fix regression with escaped round brackets and matching groups + * deps: type-is@~1.6.6 + - deps: mime-types@~2.1.4 + +4.13.1 / 2015-07-05 +=================== + + * deps: accepts@~1.2.10 + - deps: mime-types@~2.1.2 + * deps: qs@4.0.0 + - Fix dropping parameters like `hasOwnProperty` + - Fix various parsing edge cases + * deps: type-is@~1.6.4 + - deps: mime-types@~2.1.2 + - perf: enable strict mode + - perf: remove argument reassignment + +4.13.0 / 2015-06-20 +=================== + + * Add settings to debug output + * Fix `res.format` error when only `default` provided + * Fix issue where `next('route')` in `app.param` would incorrectly skip values + * Fix hiding platform issues with `decodeURIComponent` + - Only `URIError`s are a 400 + * Fix using `*` before params in routes + * Fix using capture groups before params in routes + * Simplify `res.cookie` to call `res.append` + * Use `array-flatten` module for flattening arrays + * deps: accepts@~1.2.9 + - deps: mime-types@~2.1.1 + - perf: avoid argument reassignment & argument slice + - perf: avoid negotiator recursive construction + - perf: enable strict mode + - perf: remove unnecessary bitwise operator + * deps: cookie@0.1.3 + - perf: deduce the scope of try-catch deopt + - perf: remove argument reassignments + * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Always include entity length in ETags for hash length extensions + - Generate non-Stats ETags using MD5 only (no longer CRC32) + - Improve stat performance by removing hashing + - Improve support for JXcore + - Remove base64 padding in ETags to shorten + - Support "fake" stats objects in environments without fs + - Use MD5 instead of MD4 in weak ETags over 1KB + * deps: finalhandler@0.4.0 + - Fix a false-positive when unpiping in Node.js 0.8 + - Support `statusCode` property on `Error` objects + - Use `unpipe` module for unpiping requests + - deps: escape-html@1.0.2 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove argument reassignment + * deps: fresh@0.3.0 + - Add weak `ETag` matching support + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 + * deps: path-to-regexp@0.1.6 + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations + * deps: serve-static@~1.10.0 + - Add `fallthrough` option + - Fix reading options from options prototype + - Improve the default redirect response headers + - Malformed URLs now `next()` instead of 400 + - deps: escape-html@1.0.2 + - deps: send@0.13.0 + - perf: enable strict mode + - perf: remove argument reassignment + * deps: type-is@~1.6.3 + - deps: mime-types@~2.1.1 + - perf: reduce try block size + - perf: remove bitwise operations + * perf: enable strict mode + * perf: isolate `app.render` try block + * perf: remove argument reassignments in application + * perf: remove argument reassignments in request prototype + * perf: remove argument reassignments in response prototype + * perf: remove argument reassignments in routing + * perf: remove argument reassignments in `View` + * perf: skip attempting to decode zero length string + * perf: use saved reference to `http.STATUS_CODES` + +4.12.4 / 2015-05-17 +=================== + + * deps: accepts@~1.2.7 + - deps: mime-types@~2.0.11 + - deps: negotiator@0.5.3 + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: etag@~1.6.0 + - Improve support for JXcore + - Support "fake" stats objects in environments without `fs` + * deps: finalhandler@0.3.6 + - deps: debug@~2.2.0 + - deps: on-finished@~2.2.1 + * deps: on-finished@~2.2.1 + - Fix `isFinished(req)` when data buffered + * deps: proxy-addr@~1.0.8 + - deps: ipaddr.js@1.0.1 + * deps: qs@2.4.2 + - Fix allowing parameters like `constructor` + * deps: send@0.12.3 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: etag@~1.6.0 + - deps: ms@0.7.1 + - deps: on-finished@~2.2.1 + * deps: serve-static@~1.9.3 + - deps: send@0.12.3 + * deps: type-is@~1.6.2 + - deps: mime-types@~2.0.11 + +4.12.3 / 2015-03-17 +=================== + + * deps: accepts@~1.2.5 + - deps: mime-types@~2.0.10 + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + * deps: finalhandler@0.3.4 + - deps: debug@~2.1.3 + * deps: proxy-addr@~1.0.7 + - deps: ipaddr.js@0.1.9 + * deps: qs@2.4.1 + - Fix error when parameter `hasOwnProperty` is present + * deps: send@0.12.2 + - Throw errors early for invalid `extensions` or `index` options + - deps: debug@~2.1.3 + * deps: serve-static@~1.9.2 + - deps: send@0.12.2 + * deps: type-is@~1.6.1 + - deps: mime-types@~2.0.10 + +4.12.2 / 2015-03-02 +=================== + + * Fix regression where `"Request aborted"` is logged using `res.sendFile` + +4.12.1 / 2015-03-01 +=================== + + * Fix constructing application with non-configurable prototype properties + * Fix `ECONNRESET` errors from `res.sendFile` usage + * Fix `req.host` when using "trust proxy" hops count + * Fix `req.protocol`/`req.secure` when using "trust proxy" hops count + * Fix wrong `code` on aborted connections from `res.sendFile` + * deps: merge-descriptors@1.0.0 + +4.12.0 / 2015-02-23 +=================== + + * Fix `"trust proxy"` setting to inherit when app is mounted + * Generate `ETag`s for all request responses + - No longer restricted to only responses for `GET` and `HEAD` requests + * Use `content-type` to parse `Content-Type` headers + * deps: accepts@~1.2.4 + - Fix preference sorting to be stable for long acceptable lists + - deps: mime-types@~2.0.9 + - deps: negotiator@0.5.1 + * deps: cookie-signature@1.0.6 + * deps: send@0.12.1 + - Always read the stat size from the file + - Fix mutating passed-in `options` + - deps: mime@1.3.4 + * deps: serve-static@~1.9.1 + - deps: send@0.12.1 + * deps: type-is@~1.6.0 + - fix argument reassignment + - fix false-positives in `hasBody` `Transfer-Encoding` check + - support wildcard for both type and subtype (`*/*`) + - deps: mime-types@~2.0.9 + +4.11.2 / 2015-02-01 +=================== + + * Fix `res.redirect` double-calling `res.end` for `HEAD` requests + * deps: accepts@~1.2.3 + - deps: mime-types@~2.0.8 + * deps: proxy-addr@~1.0.6 + - deps: ipaddr.js@0.1.8 + * deps: type-is@~1.5.6 + - deps: mime-types@~2.0.8 + +4.11.1 / 2015-01-20 +=================== + + * deps: send@0.11.1 + - Fix root path disclosure + * deps: serve-static@~1.8.1 + - Fix redirect loop in Node.js 0.11.14 + - Fix root path disclosure + - deps: send@0.11.1 + +4.11.0 / 2015-01-13 +=================== + + * Add `res.append(field, val)` to append headers + * Deprecate leading `:` in `name` for `app.param(name, fn)` + * Deprecate `req.param()` -- use `req.params`, `req.body`, or `req.query` instead + * Deprecate `app.param(fn)` + * Fix `OPTIONS` responses to include the `HEAD` method properly + * Fix `res.sendFile` not always detecting aborted connection + * Match routes iteratively to prevent stack overflows + * deps: accepts@~1.2.2 + - deps: mime-types@~2.0.7 + - deps: negotiator@0.5.0 + * deps: send@0.11.0 + - deps: debug@~2.1.1 + - deps: etag@~1.5.1 + - deps: ms@0.7.0 + - deps: on-finished@~2.2.0 + * deps: serve-static@~1.8.0 + - deps: send@0.11.0 + +4.10.8 / 2015-01-13 +=================== + + * Fix crash from error within `OPTIONS` response handler + * deps: proxy-addr@~1.0.5 + - deps: ipaddr.js@0.1.6 + +4.10.7 / 2015-01-04 +=================== + + * Fix `Allow` header for `OPTIONS` to not contain duplicate methods + * Fix incorrect "Request aborted" for `res.sendFile` when `HEAD` or 304 + * deps: debug@~2.1.1 + * deps: finalhandler@0.3.3 + - deps: debug@~2.1.1 + - deps: on-finished@~2.2.0 + * deps: methods@~1.1.1 + * deps: on-finished@~2.2.0 + * deps: serve-static@~1.7.2 + - Fix potential open redirect when mounted at root + * deps: type-is@~1.5.5 + - deps: mime-types@~2.0.7 + +4.10.6 / 2014-12-12 +=================== + + * Fix exception in `req.fresh`/`req.stale` without response headers + +4.10.5 / 2014-12-10 +=================== + + * Fix `res.send` double-calling `res.end` for `HEAD` requests + * deps: accepts@~1.1.4 + - deps: mime-types@~2.0.4 + * deps: type-is@~1.5.4 + - deps: mime-types@~2.0.4 + +4.10.4 / 2014-11-24 +=================== + + * Fix `res.sendfile` logging standard write errors + +4.10.3 / 2014-11-23 +=================== + + * Fix `res.sendFile` logging standard write errors + * deps: etag@~1.5.1 + * deps: proxy-addr@~1.0.4 + - deps: ipaddr.js@0.1.5 + * deps: qs@2.3.3 + - Fix `arrayLimit` behavior + +4.10.2 / 2014-11-09 +=================== + + * Correctly invoke async router callback asynchronously + * deps: accepts@~1.1.3 + - deps: mime-types@~2.0.3 + * deps: type-is@~1.5.3 + - deps: mime-types@~2.0.3 + +4.10.1 / 2014-10-28 +=================== + + * Fix handling of URLs containing `://` in the path + * deps: qs@2.3.2 + - Fix parsing of mixed objects and values + +4.10.0 / 2014-10-23 +=================== + + * Add support for `app.set('views', array)` + - Views are looked up in sequence in array of directories + * Fix `res.send(status)` to mention `res.sendStatus(status)` + * Fix handling of invalid empty URLs + * Use `content-disposition` module for `res.attachment`/`res.download` + - Sends standards-compliant `Content-Disposition` header + - Full Unicode support + * Use `path.resolve` in view lookup + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + * deps: etag@~1.5.0 + - Improve string performance + - Slightly improve speed for weak ETags over 1KB + * deps: finalhandler@0.3.2 + - Terminate in progress response only on error + - Use `on-finished` to determine request status + - deps: debug@~2.1.0 + - deps: on-finished@~2.1.1 + * deps: on-finished@~2.1.1 + - Fix handling of pipelined requests + * deps: qs@2.3.0 + - Fix parsing of mixed implicit and explicit arrays + * deps: send@0.10.1 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: etag@~1.5.0 + - deps: on-finished@~2.1.1 + * deps: serve-static@~1.7.1 + - deps: send@0.10.1 + +4.9.8 / 2014-10-17 +================== + + * Fix `res.redirect` body when redirect status specified + * deps: accepts@~1.1.2 + - Fix error when media type has invalid parameter + - deps: negotiator@0.4.9 + +4.9.7 / 2014-10-10 +================== + + * Fix using same param name in array of paths + +4.9.6 / 2014-10-08 +================== + + * deps: accepts@~1.1.1 + - deps: mime-types@~2.0.2 + - deps: negotiator@0.4.8 + * deps: serve-static@~1.6.4 + - Fix redirect loop when index file serving disabled + * deps: type-is@~1.5.2 + - deps: mime-types@~2.0.2 + +4.9.5 / 2014-09-24 +================== + + * deps: etag@~1.4.0 + * deps: proxy-addr@~1.0.3 + - Use `forwarded` npm module + * deps: send@0.9.3 + - deps: etag@~1.4.0 + * deps: serve-static@~1.6.3 + - deps: send@0.9.3 + +4.9.4 / 2014-09-19 +================== + + * deps: qs@2.2.4 + - Fix issue with object keys starting with numbers truncated + +4.9.3 / 2014-09-18 +================== + + * deps: proxy-addr@~1.0.2 + - Fix a global leak when multiple subnets are trusted + - deps: ipaddr.js@0.1.3 + +4.9.2 / 2014-09-17 +================== + + * Fix regression for empty string `path` in `app.use` + * Fix `router.use` to accept array of middleware without path + * Improve error message for bad `app.use` arguments + +4.9.1 / 2014-09-16 +================== + + * Fix `app.use` to accept array of middleware without path + * deps: depd@0.4.5 + * deps: etag@~1.3.1 + * deps: send@0.9.2 + - deps: depd@0.4.5 + - deps: etag@~1.3.1 + - deps: range-parser@~1.0.2 + * deps: serve-static@~1.6.2 + - deps: send@0.9.2 + +4.9.0 / 2014-09-08 +================== + + * Add `res.sendStatus` + * Invoke callback for sendfile when client aborts + - Applies to `res.sendFile`, `res.sendfile`, and `res.download` + - `err` will be populated with request aborted error + * Support IP address host in `req.subdomains` + * Use `etag` to generate `ETag` headers + * deps: accepts@~1.1.0 + - update `mime-types` + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + * deps: finalhandler@0.2.0 + - Set `X-Content-Type-Options: nosniff` header + - deps: debug@~2.0.0 + * deps: fresh@0.2.4 + * deps: media-typer@0.3.0 + - Throw error when parameter format invalid on parse + * deps: qs@2.2.3 + - Fix issue where first empty value in array is discarded + * deps: range-parser@~1.0.2 + * deps: send@0.9.1 + - Add `lastModified` option + - Use `etag` to generate `ETag` header + - deps: debug@~2.0.0 + - deps: fresh@0.2.4 + * deps: serve-static@~1.6.1 + - Add `lastModified` option + - deps: send@0.9.1 + * deps: type-is@~1.5.1 + - fix `hasbody` to be true for `content-length: 0` + - deps: media-typer@0.3.0 + - deps: mime-types@~2.0.1 + * deps: vary@~1.0.0 + - Accept valid `Vary` header string as `field` + +4.8.8 / 2014-09-04 +================== + + * deps: send@0.8.5 + - Fix a path traversal issue when using `root` + - Fix malicious path detection for empty string path + * deps: serve-static@~1.5.4 + - deps: send@0.8.5 + +4.8.7 / 2014-08-29 +================== + + * deps: qs@2.2.2 + - Remove unnecessary cloning + +4.8.6 / 2014-08-27 +================== + + * deps: qs@2.2.0 + - Array parsing fix + - Performance improvements + +4.8.5 / 2014-08-18 +================== + + * deps: send@0.8.3 + - deps: destroy@1.0.3 + - deps: on-finished@2.1.0 + * deps: serve-static@~1.5.3 + - deps: send@0.8.3 + +4.8.4 / 2014-08-14 +================== + + * deps: qs@1.2.2 + * deps: send@0.8.2 + - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + * deps: serve-static@~1.5.2 + - deps: send@0.8.2 + +4.8.3 / 2014-08-10 +================== + + * deps: parseurl@~1.3.0 + * deps: qs@1.2.1 + * deps: serve-static@~1.5.1 + - Fix parsing of weird `req.originalUrl` values + - deps: parseurl@~1.3.0 + - deps: utils-merge@1.0.0 + +4.8.2 / 2014-08-07 +================== + + * deps: qs@1.2.0 + - Fix parsing array of objects + +4.8.1 / 2014-08-06 +================== + + * fix incorrect deprecation warnings on `res.download` + * deps: qs@1.1.0 + - Accept urlencoded square brackets + - Accept empty values in implicit array notation + +4.8.0 / 2014-08-05 +================== + + * add `res.sendFile` + - accepts a file system path instead of a URL + - requires an absolute path or `root` option specified + * deprecate `res.sendfile` -- use `res.sendFile` instead + * support mounted app as any argument to `app.use()` + * deps: qs@1.0.2 + - Complete rewrite + - Limits array length to 20 + - Limits object depth to 5 + - Limits parameters to 1,000 + * deps: send@0.8.1 + - Add `extensions` option + * deps: serve-static@~1.5.0 + - Add `extensions` option + - deps: send@0.8.1 + +4.7.4 / 2014-08-04 +================== + + * fix `res.sendfile` regression for serving directory index files + * deps: send@0.7.4 + - Fix incorrect 403 on Windows and Node.js 0.11 + - Fix serving index files without root dir + * deps: serve-static@~1.4.4 + - deps: send@0.7.4 + +4.7.3 / 2014-08-04 +================== + + * deps: send@0.7.3 + - Fix incorrect 403 on Windows and Node.js 0.11 + * deps: serve-static@~1.4.3 + - Fix incorrect 403 on Windows and Node.js 0.11 + - deps: send@0.7.3 + +4.7.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + * deps: send@0.7.2 + - deps: depd@0.4.4 + * deps: serve-static@~1.4.2 + +4.7.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + * deps: send@0.7.1 + - deps: depd@0.4.3 + * deps: serve-static@~1.4.1 + +4.7.0 / 2014-07-25 +================== + + * fix `req.protocol` for proxy-direct connections + * configurable query parser with `app.set('query parser', parser)` + - `app.set('query parser', 'extended')` parse with "qs" module + - `app.set('query parser', 'simple')` parse with "querystring" core module + - `app.set('query parser', false)` disable query string parsing + - `app.set('query parser', true)` enable simple parsing + * deprecate `res.json(status, obj)` -- use `res.status(status).json(obj)` instead + * deprecate `res.jsonp(status, obj)` -- use `res.status(status).jsonp(obj)` instead + * deprecate `res.send(status, body)` -- use `res.status(status).send(body)` instead + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + * deps: finalhandler@0.1.0 + - Respond after request fully read + - deps: debug@1.0.4 + * deps: parseurl@~1.2.0 + - Cache URLs based on original value + - Remove no-longer-needed URL mis-parse work-around + - Simplify the "fast-path" `RegExp` + * deps: send@0.7.0 + - Add `dotfiles` option + - Cap `maxAge` value to 1 year + - deps: debug@1.0.4 + - deps: depd@0.4.2 + * deps: serve-static@~1.4.0 + - deps: parseurl@~1.2.0 + - deps: send@0.7.0 + * perf: prevent multiple `Buffer` creation in `res.send` + +4.6.1 / 2014-07-12 +================== + + * fix `subapp.mountpath` regression for `app.use(subapp)` + +4.6.0 / 2014-07-11 +================== + + * accept multiple callbacks to `app.use()` + * add explicit "Rosetta Flash JSONP abuse" protection + - previous versions are not vulnerable; this is just explicit protection + * catch errors in multiple `req.param(name, fn)` handlers + * deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead + * fix `res.send(status, num)` to send `num` as json (not error) + * remove unnecessary escaping when `res.jsonp` returns JSON response + * support non-string `path` in `app.use(path, fn)` + - supports array of paths + - supports `RegExp` + * router: fix optimization on router exit + * router: refactor location of `try` blocks + * router: speed up standard `app.use(fn)` + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + * deps: finalhandler@0.0.3 + - deps: debug@1.0.3 + * deps: methods@1.1.0 + - add `CONNECT` + * deps: parseurl@~1.1.3 + - faster parsing of href-only URLs + * deps: path-to-regexp@0.1.3 + * deps: send@0.6.0 + - deps: debug@1.0.3 + * deps: serve-static@~1.3.2 + - deps: parseurl@~1.1.3 + - deps: send@0.6.0 + * perf: fix arguments reassign deopt in some `res` methods + +4.5.1 / 2014-07-06 +================== + + * fix routing regression when altering `req.method` + +4.5.0 / 2014-07-04 +================== + + * add deprecation message to non-plural `req.accepts*` + * add deprecation message to `res.send(body, status)` + * add deprecation message to `res.vary()` + * add `headers` option to `res.sendfile` + - use to set headers on successful file transfer + * add `mergeParams` option to `Router` + - merges `req.params` from parent routes + * add `req.hostname` -- correct name for what `req.host` returns + * deprecate things with `depd` module + * deprecate `req.host` -- use `req.hostname` instead + * fix behavior when handling request without routes + * fix handling when `route.all` is only route + * invoke `router.param()` only when route matches + * restore `req.params` after invoking router + * use `finalhandler` for final response handling + * use `media-typer` to alter content-type charset + * deps: accepts@~1.0.7 + * deps: send@0.5.0 + - Accept string for `maxage` (converted by `ms`) + - Include link in default redirect response + * deps: serve-static@~1.3.0 + - Accept string for `maxAge` (converted by `ms`) + - Add `setHeaders` option + - Include HTML link in redirect response + - deps: send@0.5.0 + * deps: type-is@~1.3.2 + +4.4.5 / 2014-06-26 +================== + + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +4.4.4 / 2014-06-20 +================== + + * fix `res.attachment` Unicode filenames in Safari + * fix "trim prefix" debug message in `express:router` + * deps: accepts@~1.0.5 + * deps: buffer-crc32@0.2.3 + +4.4.3 / 2014-06-11 +================== + + * fix persistence of modified `req.params[name]` from `app.param()` + * deps: accepts@1.0.3 + - deps: negotiator@0.4.6 + * deps: debug@1.0.2 + * deps: send@0.4.3 + - Do not throw un-catchable error on file open race condition + - Use `escape-html` for HTML escaping + - deps: debug@1.0.2 + - deps: finished@1.2.2 + - deps: fresh@0.2.2 + * deps: serve-static@1.2.3 + - Do not throw un-catchable error on file open race condition + - deps: send@0.4.3 + +4.4.2 / 2014-06-09 +================== + + * fix catching errors from top-level handlers + * use `vary` module for `res.vary` + * deps: debug@1.0.1 + * deps: proxy-addr@1.0.1 + * deps: send@0.4.2 + - fix "event emitter leak" warnings + - deps: debug@1.0.1 + - deps: finished@1.2.1 + * deps: serve-static@1.2.2 + - fix "event emitter leak" warnings + - deps: send@0.4.2 + * deps: type-is@1.2.1 + +4.4.1 / 2014-06-02 +================== + + * deps: methods@1.0.1 + * deps: send@0.4.1 + - Send `max-age` in `Cache-Control` in correct format + * deps: serve-static@1.2.1 + - use `escape-html` for escaping + - deps: send@0.4.1 + +4.4.0 / 2014-05-30 +================== + + * custom etag control with `app.set('etag', val)` + - `app.set('etag', function(body, encoding){ return '"etag"' })` custom etag generation + - `app.set('etag', 'weak')` weak tag + - `app.set('etag', 'strong')` strong etag + - `app.set('etag', false)` turn off + - `app.set('etag', true)` standard etag + * mark `res.send` ETag as weak and reduce collisions + * update accepts to 1.0.2 + - Fix interpretation when header not in request + * update send to 0.4.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: debug@0.8.1 + * update serve-static to 1.2.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: send@0.4.0 + +4.3.2 / 2014-05-28 +================== + + * fix handling of errors from `router.param()` callbacks + +4.3.1 / 2014-05-23 +================== + + * revert "fix behavior of multiple `app.VERB` for the same path" + - this caused a regression in the order of route execution + +4.3.0 / 2014-05-21 +================== + + * add `req.baseUrl` to access the path stripped from `req.url` in routes + * fix behavior of multiple `app.VERB` for the same path + * fix issue routing requests among sub routers + * invoke `router.param()` only when necessary instead of every match + * proper proxy trust with `app.set('trust proxy', trust)` + - `app.set('trust proxy', 1)` trust first hop + - `app.set('trust proxy', 'loopback')` trust loopback addresses + - `app.set('trust proxy', '10.0.0.1')` trust single IP + - `app.set('trust proxy', '10.0.0.1/16')` trust subnet + - `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list + - `app.set('trust proxy', false)` turn off + - `app.set('trust proxy', true)` trust everything + * set proper `charset` in `Content-Type` for `res.send` + * update type-is to 1.2.0 + - support suffix matching + +4.2.0 / 2014-05-11 +================== + + * deprecate `app.del()` -- use `app.delete()` instead + * deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead + - the edge-case `res.json(status, num)` requires `res.status(status).json(num)` + * deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead + - the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)` + * fix `req.next` when inside router instance + * include `ETag` header in `HEAD` requests + * keep previous `Content-Type` for `res.jsonp` + * support PURGE method + - add `app.purge` + - add `router.purge` + - include PURGE in `app.all` + * update debug to 0.8.0 + - add `enable()` method + - change from stderr to stdout + * update methods to 1.0.0 + - add PURGE + +4.1.2 / 2014-05-08 +================== + + * fix `req.host` for IPv6 literals + * fix `res.jsonp` error if callback param is object + +4.1.1 / 2014-04-27 +================== + + * fix package.json to reflect supported node version + +4.1.0 / 2014-04-24 +================== + + * pass options from `res.sendfile` to `send` + * preserve casing of headers in `res.header` and `res.set` + * support unicode file names in `res.attachment` and `res.download` + * update accepts to 1.0.1 + - deps: negotiator@0.4.0 + * update cookie to 0.1.2 + - Fix for maxAge == 0 + - made compat with expires field + * update send to 0.3.0 + - Accept API options in options object + - Coerce option types + - Control whether to generate etags + - Default directory access to 403 when index disabled + - Fix sending files with dots without root set + - Include file path in etag + - Make "Can't set headers after they are sent." catchable + - Send full entity-body for multi range requests + - Set etags to "weak" + - Support "If-Range" header + - Support multiple index paths + - deps: mime@1.2.11 + * update serve-static to 1.1.0 + - Accept options directly to `send` module + - Resolve relative paths at middleware setup + - Use parseurl to parse the URL from request + - deps: send@0.3.0 + * update type-is to 1.1.0 + - add non-array values support + - add `multipart` as a shorthand + +4.0.0 / 2014-04-09 +================== + + * remove: + - node 0.8 support + - connect and connect's patches except for charset handling + - express(1) - moved to [express-generator](https://github.com/expressjs/generator) + - `express.createServer()` - it has been deprecated for a long time. Use `express()` + - `app.configure` - use logic in your own app code + - `app.router` - is removed + - `req.auth` - use `basic-auth` instead + - `req.accepted*` - use `req.accepts*()` instead + - `res.location` - relative URL resolution is removed + - `res.charset` - include the charset in the content type when using `res.set()` + - all bundled middleware except `static` + * change: + - `app.route` -> `app.mountpath` when mounting an express app in another express app + - `json spaces` no longer enabled by default in development + - `req.accepts*` -> `req.accepts*s` - i.e. `req.acceptsEncoding` -> `req.acceptsEncodings` + - `req.params` is now an object instead of an array + - `res.locals` is no longer a function. It is a plain js object. Treat it as such. + - `res.headerSent` -> `res.headersSent` to match node.js ServerResponse object + * refactor: + - `req.accepts*` with [accepts](https://github.com/expressjs/accepts) + - `req.is` with [type-is](https://github.com/expressjs/type-is) + - [path-to-regexp](https://github.com/component/path-to-regexp) + * add: + - `app.router()` - returns the app Router instance + - `app.route()` - Proxy to the app's `Router#route()` method to create a new route + - Router & Route - public API + +3.21.2 / 2015-07-31 +=================== + + * deps: connect@2.30.2 + - deps: body-parser@~1.13.3 + - deps: compression@~1.5.2 + - deps: errorhandler@~1.4.2 + - deps: method-override@~2.3.5 + - deps: serve-index@~1.7.2 + - deps: type-is@~1.6.6 + - deps: vhost@~3.0.1 + * deps: vary@~1.0.1 + - Fix setting empty header from empty `field` + - perf: enable strict mode + - perf: remove argument reassignments + +3.21.1 / 2015-07-05 +=================== + + * deps: basic-auth@~1.0.3 + * deps: connect@2.30.1 + - deps: body-parser@~1.13.2 + - deps: compression@~1.5.1 + - deps: errorhandler@~1.4.1 + - deps: morgan@~1.6.1 + - deps: pause@0.1.0 + - deps: qs@4.0.0 + - deps: serve-index@~1.7.1 + - deps: type-is@~1.6.4 + +3.21.0 / 2015-06-18 +=================== + + * deps: basic-auth@1.0.2 + - perf: enable strict mode + - perf: hoist regular expression + - perf: parse with regular expressions + - perf: remove argument reassignment + * deps: connect@2.30.0 + - deps: body-parser@~1.13.1 + - deps: bytes@2.1.0 + - deps: compression@~1.5.0 + - deps: cookie@0.1.3 + - deps: cookie-parser@~1.3.5 + - deps: csurf@~1.8.3 + - deps: errorhandler@~1.4.0 + - deps: express-session@~1.11.3 + - deps: finalhandler@0.4.0 + - deps: fresh@0.3.0 + - deps: morgan@~1.6.0 + - deps: serve-favicon@~2.3.0 + - deps: serve-index@~1.7.0 + - deps: serve-static@~1.10.0 + - deps: type-is@~1.6.3 + * deps: cookie@0.1.3 + - perf: deduce the scope of try-catch deopt + - perf: remove argument reassignments + * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Always include entity length in ETags for hash length extensions + - Generate non-Stats ETags using MD5 only (no longer CRC32) + - Improve stat performance by removing hashing + - Improve support for JXcore + - Remove base64 padding in ETags to shorten + - Support "fake" stats objects in environments without fs + - Use MD5 instead of MD4 in weak ETags over 1KB + * deps: fresh@0.3.0 + - Add weak `ETag` matching support + * deps: mkdirp@0.5.1 + - Work in global strict mode + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations + +3.20.3 / 2015-05-17 +=================== + + * deps: connect@2.29.2 + - deps: body-parser@~1.12.4 + - deps: compression@~1.4.4 + - deps: connect-timeout@~1.6.2 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: errorhandler@~1.3.6 + - deps: finalhandler@0.3.6 + - deps: method-override@~2.3.3 + - deps: morgan@~1.5.3 + - deps: qs@2.4.2 + - deps: response-time@~2.3.1 + - deps: serve-favicon@~2.2.1 + - deps: serve-index@~1.6.4 + - deps: serve-static@~1.9.3 + - deps: type-is@~1.6.2 + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: proxy-addr@~1.0.8 + - deps: ipaddr.js@1.0.1 + * deps: send@0.12.3 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: etag@~1.6.0 + - deps: ms@0.7.1 + - deps: on-finished@~2.2.1 + +3.20.2 / 2015-03-16 +=================== + + * deps: connect@2.29.1 + - deps: body-parser@~1.12.2 + - deps: compression@~1.4.3 + - deps: connect-timeout@~1.6.1 + - deps: debug@~2.1.3 + - deps: errorhandler@~1.3.5 + - deps: express-session@~1.10.4 + - deps: finalhandler@0.3.4 + - deps: method-override@~2.3.2 + - deps: morgan@~1.5.2 + - deps: qs@2.4.1 + - deps: serve-index@~1.6.3 + - deps: serve-static@~1.9.2 + - deps: type-is@~1.6.1 + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + * deps: merge-descriptors@1.0.0 + * deps: proxy-addr@~1.0.7 + - deps: ipaddr.js@0.1.9 + * deps: send@0.12.2 + - Throw errors early for invalid `extensions` or `index` options + - deps: debug@~2.1.3 + +3.20.1 / 2015-02-28 +=================== + + * Fix `req.host` when using "trust proxy" hops count + * Fix `req.protocol`/`req.secure` when using "trust proxy" hops count + +3.20.0 / 2015-02-18 +=================== + + * Fix `"trust proxy"` setting to inherit when app is mounted + * Generate `ETag`s for all request responses + - No longer restricted to only responses for `GET` and `HEAD` requests + * Use `content-type` to parse `Content-Type` headers + * deps: connect@2.29.0 + - Use `content-type` to parse `Content-Type` headers + - deps: body-parser@~1.12.0 + - deps: compression@~1.4.1 + - deps: connect-timeout@~1.6.0 + - deps: cookie-parser@~1.3.4 + - deps: cookie-signature@1.0.6 + - deps: csurf@~1.7.0 + - deps: errorhandler@~1.3.4 + - deps: express-session@~1.10.3 + - deps: http-errors@~1.3.1 + - deps: response-time@~2.3.0 + - deps: serve-index@~1.6.2 + - deps: serve-static@~1.9.1 + - deps: type-is@~1.6.0 + * deps: cookie-signature@1.0.6 + * deps: send@0.12.1 + - Always read the stat size from the file + - Fix mutating passed-in `options` + - deps: mime@1.3.4 + +3.19.2 / 2015-02-01 +=================== + + * deps: connect@2.28.3 + - deps: compression@~1.3.1 + - deps: csurf@~1.6.6 + - deps: errorhandler@~1.3.3 + - deps: express-session@~1.10.2 + - deps: serve-index@~1.6.1 + - deps: type-is@~1.5.6 + * deps: proxy-addr@~1.0.6 + - deps: ipaddr.js@0.1.8 + +3.19.1 / 2015-01-20 +=================== + + * deps: connect@2.28.2 + - deps: body-parser@~1.10.2 + - deps: serve-static@~1.8.1 + * deps: send@0.11.1 + - Fix root path disclosure + +3.19.0 / 2015-01-09 +=================== + + * Fix `OPTIONS` responses to include the `HEAD` method property + * Use `readline` for prompt in `express(1)` + * deps: commander@2.6.0 + * deps: connect@2.28.1 + - deps: body-parser@~1.10.1 + - deps: compression@~1.3.0 + - deps: connect-timeout@~1.5.0 + - deps: csurf@~1.6.4 + - deps: debug@~2.1.1 + - deps: errorhandler@~1.3.2 + - deps: express-session@~1.10.1 + - deps: finalhandler@0.3.3 + - deps: method-override@~2.3.1 + - deps: morgan@~1.5.1 + - deps: serve-favicon@~2.2.0 + - deps: serve-index@~1.6.0 + - deps: serve-static@~1.8.0 + - deps: type-is@~1.5.5 + * deps: debug@~2.1.1 + * deps: methods@~1.1.1 + * deps: proxy-addr@~1.0.5 + - deps: ipaddr.js@0.1.6 + * deps: send@0.11.0 + - deps: debug@~2.1.1 + - deps: etag@~1.5.1 + - deps: ms@0.7.0 + - deps: on-finished@~2.2.0 + +3.18.6 / 2014-12-12 +=================== + + * Fix exception in `req.fresh`/`req.stale` without response headers + +3.18.5 / 2014-12-11 +=================== + + * deps: connect@2.27.6 + - deps: compression@~1.2.2 + - deps: express-session@~1.9.3 + - deps: http-errors@~1.2.8 + - deps: serve-index@~1.5.3 + - deps: type-is@~1.5.4 + +3.18.4 / 2014-11-23 +=================== + + * deps: connect@2.27.4 + - deps: body-parser@~1.9.3 + - deps: compression@~1.2.1 + - deps: errorhandler@~1.2.3 + - deps: express-session@~1.9.2 + - deps: qs@2.3.3 + - deps: serve-favicon@~2.1.7 + - deps: serve-static@~1.5.1 + - deps: type-is@~1.5.3 + * deps: etag@~1.5.1 + * deps: proxy-addr@~1.0.4 + - deps: ipaddr.js@0.1.5 + +3.18.3 / 2014-11-09 +=================== + + * deps: connect@2.27.3 + - Correctly invoke async callback asynchronously + - deps: csurf@~1.6.3 + +3.18.2 / 2014-10-28 +=================== + + * deps: connect@2.27.2 + - Fix handling of URLs containing `://` in the path + - deps: body-parser@~1.9.2 + - deps: qs@2.3.2 + +3.18.1 / 2014-10-22 +=================== + + * Fix internal `utils.merge` deprecation warnings + * deps: connect@2.27.1 + - deps: body-parser@~1.9.1 + - deps: express-session@~1.9.1 + - deps: finalhandler@0.3.2 + - deps: morgan@~1.4.1 + - deps: qs@2.3.0 + - deps: serve-static@~1.7.1 + * deps: send@0.10.1 + - deps: on-finished@~2.1.1 + +3.18.0 / 2014-10-17 +=================== + + * Use `content-disposition` module for `res.attachment`/`res.download` + - Sends standards-compliant `Content-Disposition` header + - Full Unicode support + * Use `etag` module to generate `ETag` headers + * deps: connect@2.27.0 + - Use `http-errors` module for creating errors + - Use `utils-merge` module for merging objects + - deps: body-parser@~1.9.0 + - deps: compression@~1.2.0 + - deps: connect-timeout@~1.4.0 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: express-session@~1.9.0 + - deps: finalhandler@0.3.1 + - deps: method-override@~2.3.0 + - deps: morgan@~1.4.0 + - deps: response-time@~2.2.0 + - deps: serve-favicon@~2.1.6 + - deps: serve-index@~1.5.0 + - deps: serve-static@~1.7.0 + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + * deps: send@0.10.0 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: etag@~1.5.0 + +3.17.8 / 2014-10-15 +=================== + + * deps: connect@2.26.6 + - deps: compression@~1.1.2 + - deps: csurf@~1.6.2 + - deps: errorhandler@~1.2.2 + +3.17.7 / 2014-10-08 +=================== + + * deps: connect@2.26.5 + - Fix accepting non-object arguments to `logger` + - deps: serve-static@~1.6.4 + +3.17.6 / 2014-10-02 +=================== + + * deps: connect@2.26.4 + - deps: morgan@~1.3.2 + - deps: type-is@~1.5.2 + +3.17.5 / 2014-09-24 +=================== + + * deps: connect@2.26.3 + - deps: body-parser@~1.8.4 + - deps: serve-favicon@~2.1.5 + - deps: serve-static@~1.6.3 + * deps: proxy-addr@~1.0.3 + - Use `forwarded` npm module + * deps: send@0.9.3 + - deps: etag@~1.4.0 + +3.17.4 / 2014-09-19 +=================== + + * deps: connect@2.26.2 + - deps: body-parser@~1.8.3 + - deps: qs@2.2.4 + +3.17.3 / 2014-09-18 +=================== + + * deps: proxy-addr@~1.0.2 + - Fix a global leak when multiple subnets are trusted + - deps: ipaddr.js@0.1.3 + +3.17.2 / 2014-09-15 +=================== + + * Use `crc` instead of `buffer-crc32` for speed + * deps: connect@2.26.1 + - deps: body-parser@~1.8.2 + - deps: depd@0.4.5 + - deps: express-session@~1.8.2 + - deps: morgan@~1.3.1 + - deps: serve-favicon@~2.1.3 + - deps: serve-static@~1.6.2 + * deps: depd@0.4.5 + * deps: send@0.9.2 + - deps: depd@0.4.5 + - deps: etag@~1.3.1 + - deps: range-parser@~1.0.2 + +3.17.1 / 2014-09-08 +=================== + + * Fix error in `req.subdomains` on empty host + +3.17.0 / 2014-09-08 +=================== + + * Support `X-Forwarded-Host` in `req.subdomains` + * Support IP address host in `req.subdomains` + * deps: connect@2.26.0 + - deps: body-parser@~1.8.1 + - deps: compression@~1.1.0 + - deps: connect-timeout@~1.3.0 + - deps: cookie-parser@~1.3.3 + - deps: cookie-signature@1.0.5 + - deps: csurf@~1.6.1 + - deps: debug@~2.0.0 + - deps: errorhandler@~1.2.0 + - deps: express-session@~1.8.1 + - deps: finalhandler@0.2.0 + - deps: fresh@0.2.4 + - deps: media-typer@0.3.0 + - deps: method-override@~2.2.0 + - deps: morgan@~1.3.0 + - deps: qs@2.2.3 + - deps: serve-favicon@~2.1.3 + - deps: serve-index@~1.2.1 + - deps: serve-static@~1.6.1 + - deps: type-is@~1.5.1 + - deps: vhost@~3.0.0 + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + * deps: fresh@0.2.4 + * deps: media-typer@0.3.0 + - Throw error when parameter format invalid on parse + * deps: range-parser@~1.0.2 + * deps: send@0.9.1 + - Add `lastModified` option + - Use `etag` to generate `ETag` header + - deps: debug@~2.0.0 + - deps: fresh@0.2.4 + * deps: vary@~1.0.0 + - Accept valid `Vary` header string as `field` + +3.16.10 / 2014-09-04 +==================== + + * deps: connect@2.25.10 + - deps: serve-static@~1.5.4 + * deps: send@0.8.5 + - Fix a path traversal issue when using `root` + - Fix malicious path detection for empty string path + +3.16.9 / 2014-08-29 +=================== + + * deps: connect@2.25.9 + - deps: body-parser@~1.6.7 + - deps: qs@2.2.2 + +3.16.8 / 2014-08-27 +=================== + + * deps: connect@2.25.8 + - deps: body-parser@~1.6.6 + - deps: csurf@~1.4.1 + - deps: qs@2.2.0 + +3.16.7 / 2014-08-18 +=================== + + * deps: connect@2.25.7 + - deps: body-parser@~1.6.5 + - deps: express-session@~1.7.6 + - deps: morgan@~1.2.3 + - deps: serve-static@~1.5.3 + * deps: send@0.8.3 + - deps: destroy@1.0.3 + - deps: on-finished@2.1.0 + +3.16.6 / 2014-08-14 +=================== + + * deps: connect@2.25.6 + - deps: body-parser@~1.6.4 + - deps: qs@1.2.2 + - deps: serve-static@~1.5.2 + * deps: send@0.8.2 + - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + +3.16.5 / 2014-08-11 +=================== + + * deps: connect@2.25.5 + - Fix backwards compatibility in `logger` + +3.16.4 / 2014-08-10 +=================== + + * Fix original URL parsing in `res.location` + * deps: connect@2.25.4 + - Fix `query` middleware breaking with argument + - deps: body-parser@~1.6.3 + - deps: compression@~1.0.11 + - deps: connect-timeout@~1.2.2 + - deps: express-session@~1.7.5 + - deps: method-override@~2.1.3 + - deps: on-headers@~1.0.0 + - deps: parseurl@~1.3.0 + - deps: qs@1.2.1 + - deps: response-time@~2.0.1 + - deps: serve-index@~1.1.6 + - deps: serve-static@~1.5.1 + * deps: parseurl@~1.3.0 + +3.16.3 / 2014-08-07 +=================== + + * deps: connect@2.25.3 + - deps: multiparty@3.3.2 + +3.16.2 / 2014-08-07 +=================== + + * deps: connect@2.25.2 + - deps: body-parser@~1.6.2 + - deps: qs@1.2.0 + +3.16.1 / 2014-08-06 +=================== + + * deps: connect@2.25.1 + - deps: body-parser@~1.6.1 + - deps: qs@1.1.0 + +3.16.0 / 2014-08-05 +=================== + + * deps: connect@2.25.0 + - deps: body-parser@~1.6.0 + - deps: compression@~1.0.10 + - deps: csurf@~1.4.0 + - deps: express-session@~1.7.4 + - deps: qs@1.0.2 + - deps: serve-static@~1.5.0 + * deps: send@0.8.1 + - Add `extensions` option + +3.15.3 / 2014-08-04 +=================== + + * fix `res.sendfile` regression for serving directory index files + * deps: connect@2.24.3 + - deps: serve-index@~1.1.5 + - deps: serve-static@~1.4.4 + * deps: send@0.7.4 + - Fix incorrect 403 on Windows and Node.js 0.11 + - Fix serving index files without root dir + +3.15.2 / 2014-07-27 +=================== + + * deps: connect@2.24.2 + - deps: body-parser@~1.5.2 + - deps: depd@0.4.4 + - deps: express-session@~1.7.2 + - deps: morgan@~1.2.2 + - deps: serve-static@~1.4.2 + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + * deps: send@0.7.2 + - deps: depd@0.4.4 + +3.15.1 / 2014-07-26 +=================== + + * deps: connect@2.24.1 + - deps: body-parser@~1.5.1 + - deps: depd@0.4.3 + - deps: express-session@~1.7.1 + - deps: morgan@~1.2.1 + - deps: serve-index@~1.1.4 + - deps: serve-static@~1.4.1 + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + * deps: send@0.7.1 + - deps: depd@0.4.3 + +3.15.0 / 2014-07-22 +=================== + + * Fix `req.protocol` for proxy-direct connections + * Pass options from `res.sendfile` to `send` + * deps: connect@2.24.0 + - deps: body-parser@~1.5.0 + - deps: compression@~1.0.9 + - deps: connect-timeout@~1.2.1 + - deps: debug@1.0.4 + - deps: depd@0.4.2 + - deps: express-session@~1.7.0 + - deps: finalhandler@0.1.0 + - deps: method-override@~2.1.2 + - deps: morgan@~1.2.0 + - deps: multiparty@3.3.1 + - deps: parseurl@~1.2.0 + - deps: serve-static@~1.4.0 + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + * deps: parseurl@~1.2.0 + - Cache URLs based on original value + - Remove no-longer-needed URL mis-parse work-around + - Simplify the "fast-path" `RegExp` + * deps: send@0.7.0 + - Add `dotfiles` option + - Cap `maxAge` value to 1 year + - deps: debug@1.0.4 + - deps: depd@0.4.2 + +3.14.0 / 2014-07-11 +=================== + + * add explicit "Rosetta Flash JSONP abuse" protection + - previous versions are not vulnerable; this is just explicit protection + * deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead + * fix `res.send(status, num)` to send `num` as json (not error) + * remove unnecessary escaping when `res.jsonp` returns JSON response + * deps: basic-auth@1.0.0 + - support empty password + - support empty username + * deps: connect@2.23.0 + - deps: debug@1.0.3 + - deps: express-session@~1.6.4 + - deps: method-override@~2.1.0 + - deps: parseurl@~1.1.3 + - deps: serve-static@~1.3.1 + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + * deps: methods@1.1.0 + - add `CONNECT` + * deps: parseurl@~1.1.3 + - faster parsing of href-only URLs + +3.13.0 / 2014-07-03 +=================== + + * add deprecation message to `app.configure` + * add deprecation message to `req.auth` + * use `basic-auth` to parse `Authorization` header + * deps: connect@2.22.0 + - deps: csurf@~1.3.0 + - deps: express-session@~1.6.1 + - deps: multiparty@3.3.0 + - deps: serve-static@~1.3.0 + * deps: send@0.5.0 + - Accept string for `maxage` (converted by `ms`) + - Include link in default redirect response + +3.12.1 / 2014-06-26 +=================== + + * deps: connect@2.21.1 + - deps: cookie-parser@1.3.2 + - deps: cookie-signature@1.0.4 + - deps: express-session@~1.5.2 + - deps: type-is@~1.3.2 + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +3.12.0 / 2014-06-21 +=================== + + * use `media-typer` to alter content-type charset + * deps: connect@2.21.0 + - deprecate `connect(middleware)` -- use `app.use(middleware)` instead + - deprecate `connect.createServer()` -- use `connect()` instead + - fix `res.setHeader()` patch to work with with get -> append -> set pattern + - deps: compression@~1.0.8 + - deps: errorhandler@~1.1.1 + - deps: express-session@~1.5.0 + - deps: serve-index@~1.1.3 + +3.11.0 / 2014-06-19 +=================== + + * deprecate things with `depd` module + * deps: buffer-crc32@0.2.3 + * deps: connect@2.20.2 + - deprecate `verify` option to `json` -- use `body-parser` npm module instead + - deprecate `verify` option to `urlencoded` -- use `body-parser` npm module instead + - deprecate things with `depd` module + - use `finalhandler` for final response handling + - use `media-typer` to parse `content-type` for charset + - deps: body-parser@1.4.3 + - deps: connect-timeout@1.1.1 + - deps: cookie-parser@1.3.1 + - deps: csurf@1.2.2 + - deps: errorhandler@1.1.0 + - deps: express-session@1.4.0 + - deps: multiparty@3.2.9 + - deps: serve-index@1.1.2 + - deps: type-is@1.3.1 + - deps: vhost@2.0.0 + +3.10.5 / 2014-06-11 +=================== + + * deps: connect@2.19.6 + - deps: body-parser@1.3.1 + - deps: compression@1.0.7 + - deps: debug@1.0.2 + - deps: serve-index@1.1.1 + - deps: serve-static@1.2.3 + * deps: debug@1.0.2 + * deps: send@0.4.3 + - Do not throw un-catchable error on file open race condition + - Use `escape-html` for HTML escaping + - deps: debug@1.0.2 + - deps: finished@1.2.2 + - deps: fresh@0.2.2 + +3.10.4 / 2014-06-09 +=================== + + * deps: connect@2.19.5 + - fix "event emitter leak" warnings + - deps: csurf@1.2.1 + - deps: debug@1.0.1 + - deps: serve-static@1.2.2 + - deps: type-is@1.2.1 + * deps: debug@1.0.1 + * deps: send@0.4.2 + - fix "event emitter leak" warnings + - deps: finished@1.2.1 + - deps: debug@1.0.1 + +3.10.3 / 2014-06-05 +=================== + + * use `vary` module for `res.vary` + * deps: connect@2.19.4 + - deps: errorhandler@1.0.2 + - deps: method-override@2.0.2 + - deps: serve-favicon@2.0.1 + * deps: debug@1.0.0 + +3.10.2 / 2014-06-03 +=================== + + * deps: connect@2.19.3 + - deps: compression@1.0.6 + +3.10.1 / 2014-06-03 +=================== + + * deps: connect@2.19.2 + - deps: compression@1.0.4 + * deps: proxy-addr@1.0.1 + +3.10.0 / 2014-06-02 +=================== + + * deps: connect@2.19.1 + - deprecate `methodOverride()` -- use `method-override` npm module instead + - deps: body-parser@1.3.0 + - deps: method-override@2.0.1 + - deps: multiparty@3.2.8 + - deps: response-time@2.0.0 + - deps: serve-static@1.2.1 + * deps: methods@1.0.1 + * deps: send@0.4.1 + - Send `max-age` in `Cache-Control` in correct format + +3.9.0 / 2014-05-30 +================== + + * custom etag control with `app.set('etag', val)` + - `app.set('etag', function(body, encoding){ return '"etag"' })` custom etag generation + - `app.set('etag', 'weak')` weak tag + - `app.set('etag', 'strong')` strong etag + - `app.set('etag', false)` turn off + - `app.set('etag', true)` standard etag + * Include ETag in HEAD requests + * mark `res.send` ETag as weak and reduce collisions + * update connect to 2.18.0 + - deps: compression@1.0.3 + - deps: serve-index@1.1.0 + - deps: serve-static@1.2.0 + * update send to 0.4.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: debug@0.8.1 + +3.8.1 / 2014-05-27 +================== + + * update connect to 2.17.3 + - deps: body-parser@1.2.2 + - deps: express-session@1.2.1 + - deps: method-override@1.0.2 + +3.8.0 / 2014-05-21 +================== + + * keep previous `Content-Type` for `res.jsonp` + * set proper `charset` in `Content-Type` for `res.send` + * update connect to 2.17.1 + - fix `res.charset` appending charset when `content-type` has one + - deps: express-session@1.2.0 + - deps: morgan@1.1.1 + - deps: serve-index@1.0.3 + +3.7.0 / 2014-05-18 +================== + + * proper proxy trust with `app.set('trust proxy', trust)` + - `app.set('trust proxy', 1)` trust first hop + - `app.set('trust proxy', 'loopback')` trust loopback addresses + - `app.set('trust proxy', '10.0.0.1')` trust single IP + - `app.set('trust proxy', '10.0.0.1/16')` trust subnet + - `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list + - `app.set('trust proxy', false)` turn off + - `app.set('trust proxy', true)` trust everything + * update connect to 2.16.2 + - deprecate `res.headerSent` -- use `res.headersSent` + - deprecate `res.on("header")` -- use on-headers module instead + - fix edge-case in `res.appendHeader` that would append in wrong order + - json: use body-parser + - urlencoded: use body-parser + - dep: bytes@1.0.0 + - dep: cookie-parser@1.1.0 + - dep: csurf@1.2.0 + - dep: express-session@1.1.0 + - dep: method-override@1.0.1 + +3.6.0 / 2014-05-09 +================== + + * deprecate `app.del()` -- use `app.delete()` instead + * deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead + - the edge-case `res.json(status, num)` requires `res.status(status).json(num)` + * deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead + - the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)` + * support PURGE method + - add `app.purge` + - add `router.purge` + - include PURGE in `app.all` + * update connect to 2.15.0 + * Add `res.appendHeader` + * Call error stack even when response has been sent + * Patch `res.headerSent` to return Boolean + * Patch `res.headersSent` for node.js 0.8 + * Prevent default 404 handler after response sent + * dep: compression@1.0.2 + * dep: connect-timeout@1.1.0 + * dep: debug@^0.8.0 + * dep: errorhandler@1.0.1 + * dep: express-session@1.0.4 + * dep: morgan@1.0.1 + * dep: serve-favicon@2.0.0 + * dep: serve-index@1.0.2 + * update debug to 0.8.0 + * add `enable()` method + * change from stderr to stdout + * update methods to 1.0.0 + - add PURGE + * update mkdirp to 0.5.0 + +3.5.3 / 2014-05-08 +================== + + * fix `req.host` for IPv6 literals + * fix `res.jsonp` error if callback param is object + +3.5.2 / 2014-04-24 +================== + + * update connect to 2.14.5 + * update cookie to 0.1.2 + * update mkdirp to 0.4.0 + * update send to 0.3.0 + +3.5.1 / 2014-03-25 +================== + + * pin less-middleware in generated app + +3.5.0 / 2014-03-06 +================== + + * bump deps + +3.4.8 / 2014-01-13 +================== + + * prevent incorrect automatic OPTIONS responses #1868 @dpatti + * update binary and examples for jade 1.0 #1876 @yossi, #1877 @reqshark, #1892 @matheusazzi + * throw 400 in case of malformed paths @rlidwka + +3.4.7 / 2013-12-10 +================== + + * update connect + +3.4.6 / 2013-12-01 +================== + + * update connect (raw-body) + +3.4.5 / 2013-11-27 +================== + + * update connect + * res.location: remove leading ./ #1802 @kapouer + * res.redirect: fix `res.redirect('toString') #1829 @michaelficarra + * res.send: always send ETag when content-length > 0 + * router: add Router.all() method + +3.4.4 / 2013-10-29 +================== + + * update connect + * update supertest + * update methods + * express(1): replace bodyParser() with urlencoded() and json() #1795 @chirag04 + +3.4.3 / 2013-10-23 +================== + + * update connect + +3.4.2 / 2013-10-18 +================== + + * update connect + * downgrade commander + +3.4.1 / 2013-10-15 +================== + + * update connect + * update commander + * jsonp: check if callback is a function + * router: wrap encodeURIComponent in a try/catch #1735 (@lxe) + * res.format: now includes charset @1747 (@sorribas) + * res.links: allow multiple calls @1746 (@sorribas) + +3.4.0 / 2013-09-07 +================== + + * add res.vary(). Closes #1682 + * update connect + +3.3.8 / 2013-09-02 +================== + + * update connect + +3.3.7 / 2013-08-28 +================== + + * update connect + +3.3.6 / 2013-08-27 +================== + + * Revert "remove charset from json responses. Closes #1631" (causes issues in some clients) + * add: req.accepts take an argument list + +3.3.4 / 2013-07-08 +================== + + * update send and connect + +3.3.3 / 2013-07-04 +================== + + * update connect + +3.3.2 / 2013-07-03 +================== + + * update connect + * update send + * remove .version export + +3.3.1 / 2013-06-27 +================== + + * update connect + +3.3.0 / 2013-06-26 +================== + + * update connect + * add support for multiple X-Forwarded-Proto values. Closes #1646 + * change: remove charset from json responses. Closes #1631 + * change: return actual booleans from req.accept* functions + * fix jsonp callback array throw + +3.2.6 / 2013-06-02 +================== + + * update connect + +3.2.5 / 2013-05-21 +================== + + * update connect + * update node-cookie + * add: throw a meaningful error when there is no default engine + * change generation of ETags with res.send() to GET requests only. Closes #1619 + +3.2.4 / 2013-05-09 +================== + + * fix `req.subdomains` when no Host is present + * fix `req.host` when no Host is present, return undefined + +3.2.3 / 2013-05-07 +================== + + * update connect / qs + +3.2.2 / 2013-05-03 +================== + + * update qs + +3.2.1 / 2013-04-29 +================== + + * add app.VERB() paths array deprecation warning + * update connect + * update qs and remove all ~ semver crap + * fix: accept number as value of Signed Cookie + +3.2.0 / 2013-04-15 +================== + + * add "view" constructor setting to override view behaviour + * add req.acceptsEncoding(name) + * add req.acceptedEncodings + * revert cookie signature change causing session race conditions + * fix sorting of Accept values of the same quality + +3.1.2 / 2013-04-12 +================== + + * add support for custom Accept parameters + * update cookie-signature + +3.1.1 / 2013-04-01 +================== + + * add X-Forwarded-Host support to `req.host` + * fix relative redirects + * update mkdirp + * update buffer-crc32 + * remove legacy app.configure() method from app template. + +3.1.0 / 2013-01-25 +================== + + * add support for leading "." in "view engine" setting + * add array support to `res.set()` + * add node 0.8.x to travis.yml + * add "subdomain offset" setting for tweaking `req.subdomains` + * add `res.location(url)` implementing `res.redirect()`-like setting of Location + * use app.get() for x-powered-by setting for inheritance + * fix colons in passwords for `req.auth` + +3.0.6 / 2013-01-04 +================== + + * add http verb methods to Router + * update connect + * fix mangling of the `res.cookie()` options object + * fix jsonp whitespace escape. Closes #1132 + +3.0.5 / 2012-12-19 +================== + + * add throwing when a non-function is passed to a route + * fix: explicitly remove Transfer-Encoding header from 204 and 304 responses + * revert "add 'etag' option" + +3.0.4 / 2012-12-05 +================== + + * add 'etag' option to disable `res.send()` Etags + * add escaping of urls in text/plain in `res.redirect()` + for old browsers interpreting as html + * change crc32 module for a more liberal license + * update connect + +3.0.3 / 2012-11-13 +================== + + * update connect + * update cookie module + * fix cookie max-age + +3.0.2 / 2012-11-08 +================== + + * add OPTIONS to cors example. Closes #1398 + * fix route chaining regression. Closes #1397 + +3.0.1 / 2012-11-01 +================== + + * update connect + +3.0.0 / 2012-10-23 +================== + + * add `make clean` + * add "Basic" check to req.auth + * add `req.auth` test coverage + * add cb && cb(payload) to `res.jsonp()`. Closes #1374 + * add backwards compat for `res.redirect()` status. Closes #1336 + * add support for `res.json()` to retain previously defined Content-Types. Closes #1349 + * update connect + * change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382 + * remove non-primitive string support for `res.send()` + * fix view-locals example. Closes #1370 + * fix route-separation example + +3.0.0rc5 / 2012-09-18 +================== + + * update connect + * add redis search example + * add static-files example + * add "x-powered-by" setting (`app.disable('x-powered-by')`) + * add "application/octet-stream" redirect Accept test case. Closes #1317 + +3.0.0rc4 / 2012-08-30 +================== + + * add `res.jsonp()`. Closes #1307 + * add "verbose errors" option to error-pages example + * add another route example to express(1) so people are not so confused + * add redis online user activity tracking example + * update connect dep + * fix etag quoting. Closes #1310 + * fix error-pages 404 status + * fix jsonp callback char restrictions + * remove old OPTIONS default response + +3.0.0rc3 / 2012-08-13 +================== + + * update connect dep + * fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds] + * fix `res.render()` clobbering of "locals" + +3.0.0rc2 / 2012-08-03 +================== + + * add CORS example + * update connect dep + * deprecate `.createServer()` & remove old stale examples + * fix: escape `res.redirect()` link + * fix vhost example + +3.0.0rc1 / 2012-07-24 +================== + + * add more examples to view-locals + * add scheme-relative redirects (`res.redirect("//foo.com")`) support + * update cookie dep + * update connect dep + * update send dep + * fix `express(1)` -h flag, use -H for hogan. Closes #1245 + * fix `res.sendfile()` socket error handling regression + +3.0.0beta7 / 2012-07-16 +================== + + * update connect dep for `send()` root normalization regression + +3.0.0beta6 / 2012-07-13 +================== + + * add `err.view` property for view errors. Closes #1226 + * add "jsonp callback name" setting + * add support for "/foo/:bar*" non-greedy matches + * change `res.sendfile()` to use `send()` module + * change `res.send` to use "response-send" module + * remove `app.locals.use` and `res.locals.use`, use regular middleware + +3.0.0beta5 / 2012-07-03 +================== + + * add "make check" support + * add route-map example + * add `res.json(obj, status)` support back for BC + * add "methods" dep, remove internal methods module + * update connect dep + * update auth example to utilize cores pbkdf2 + * updated tests to use "supertest" + +3.0.0beta4 / 2012-06-25 +================== + + * Added `req.auth` + * Added `req.range(size)` + * Added `res.links(obj)` + * Added `res.send(body, status)` support back for backwards compat + * Added `.default()` support to `res.format()` + * Added 2xx / 304 check to `req.fresh` + * Revert "Added + support to the router" + * Fixed `res.send()` freshness check, respect res.statusCode + +3.0.0beta3 / 2012-06-15 +================== + + * Added hogan `--hjs` to express(1) [nullfirm] + * Added another example to content-negotiation + * Added `fresh` dep + * Changed: `res.send()` always checks freshness + * Fixed: expose connects mime module. Closes #1165 + +3.0.0beta2 / 2012-06-06 +================== + + * Added `+` support to the router + * Added `req.host` + * Changed `req.param()` to check route first + * Update connect dep + +3.0.0beta1 / 2012-06-01 +================== + + * Added `res.format()` callback to override default 406 behaviour + * Fixed `res.redirect()` 406. Closes #1154 + +3.0.0alpha5 / 2012-05-30 +================== + + * Added `req.ip` + * Added `{ signed: true }` option to `res.cookie()` + * Removed `res.signedCookie()` + * Changed: dont reverse `req.ips` + * Fixed "trust proxy" setting check for `req.ips` + +3.0.0alpha4 / 2012-05-09 +================== + + * Added: allow `[]` in jsonp callback. Closes #1128 + * Added `PORT` env var support in generated template. Closes #1118 [benatkin] + * Updated: connect 2.2.2 + +3.0.0alpha3 / 2012-05-04 +================== + + * Added public `app.routes`. Closes #887 + * Added _view-locals_ example + * Added _mvc_ example + * Added `res.locals.use()`. Closes #1120 + * Added conditional-GET support to `res.send()` + * Added: coerce `res.set()` values to strings + * Changed: moved `static()` in generated apps below router + * Changed: `res.send()` only set ETag when not previously set + * Changed connect 2.2.1 dep + * Changed: `make test` now runs unit / acceptance tests + * Fixed req/res proto inheritance + +3.0.0alpha2 / 2012-04-26 +================== + + * Added `make benchmark` back + * Added `res.send()` support for `String` objects + * Added client-side data exposing example + * Added `res.header()` and `req.header()` aliases for BC + * Added `express.createServer()` for BC + * Perf: memoize parsed urls + * Perf: connect 2.2.0 dep + * Changed: make `expressInit()` middleware self-aware + * Fixed: use app.get() for all core settings + * Fixed redis session example + * Fixed session example. Closes #1105 + * Fixed generated express dep. Closes #1078 + +3.0.0alpha1 / 2012-04-15 +================== + + * Added `app.locals.use(callback)` + * Added `app.locals` object + * Added `app.locals(obj)` + * Added `res.locals` object + * Added `res.locals(obj)` + * Added `res.format()` for content-negotiation + * Added `app.engine()` + * Added `res.cookie()` JSON cookie support + * Added "trust proxy" setting + * Added `req.subdomains` + * Added `req.protocol` + * Added `req.secure` + * Added `req.path` + * Added `req.ips` + * Added `req.fresh` + * Added `req.stale` + * Added comma-delimited / array support for `req.accepts()` + * Added debug instrumentation + * Added `res.set(obj)` + * Added `res.set(field, value)` + * Added `res.get(field)` + * Added `app.get(setting)`. Closes #842 + * Added `req.acceptsLanguage()` + * Added `req.acceptsCharset()` + * Added `req.accepted` + * Added `req.acceptedLanguages` + * Added `req.acceptedCharsets` + * Added "json replacer" setting + * Added "json spaces" setting + * Added X-Forwarded-Proto support to `res.redirect()`. Closes #92 + * Added `--less` support to express(1) + * Added `express.response` prototype + * Added `express.request` prototype + * Added `express.application` prototype + * Added `app.path()` + * Added `app.render()` + * Added `res.type()` to replace `res.contentType()` + * Changed: `res.redirect()` to add relative support + * Changed: enable "jsonp callback" by default + * Changed: renamed "case sensitive routes" to "case sensitive routing" + * Rewrite of all tests with mocha + * Removed "root" setting + * Removed `res.redirect('home')` support + * Removed `req.notify()` + * Removed `app.register()` + * Removed `app.redirect()` + * Removed `app.is()` + * Removed `app.helpers()` + * Removed `app.dynamicHelpers()` + * Fixed `res.sendfile()` with non-GET. Closes #723 + * Fixed express(1) public dir for windows. Closes #866 + +2.5.9/ 2012-04-02 +================== + + * Added support for PURGE request method [pbuyle] + * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki] + +2.5.8 / 2012-02-08 +================== + + * Update mkdirp dep. Closes #991 + +2.5.7 / 2012-02-06 +================== + + * Fixed `app.all` duplicate DELETE requests [mscdex] + +2.5.6 / 2012-01-13 +================== + + * Updated hamljs dev dep. Closes #953 + +2.5.5 / 2012-01-08 +================== + + * Fixed: set `filename` on cached templates [matthewleon] + +2.5.4 / 2012-01-02 +================== + + * Fixed `express(1)` eol on 0.4.x. Closes #947 + +2.5.3 / 2011-12-30 +================== + + * Fixed `req.is()` when a charset is present + +2.5.2 / 2011-12-10 +================== + + * Fixed: express(1) LF -> CRLF for windows + +2.5.1 / 2011-11-17 +================== + + * Changed: updated connect to 1.8.x + * Removed sass.js support from express(1) + +2.5.0 / 2011-10-24 +================== + + * Added ./routes dir for generated app by default + * Added npm install reminder to express(1) app gen + * Added 0.5.x support + * Removed `make test-cov` since it wont work with node 0.5.x + * Fixed express(1) public dir for windows. Closes #866 + +2.4.7 / 2011-10-05 +================== + + * Added mkdirp to express(1). Closes #795 + * Added simple _json-config_ example + * Added shorthand for the parsed request's pathname via `req.path` + * Changed connect dep to 1.7.x to fix npm issue... + * Fixed `res.redirect()` __HEAD__ support. [reported by xerox] + * Fixed `req.flash()`, only escape args + * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie] + +2.4.6 / 2011-08-22 +================== + + * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode] + +2.4.5 / 2011-08-19 +================== + + * Added support for routes to handle errors. Closes #809 + * Added `app.routes.all()`. Closes #803 + * Added "basepath" setting to work in conjunction with reverse proxies etc. + * Refactored `Route` to use a single array of callbacks + * Added support for multiple callbacks for `app.param()`. Closes #801 +Closes #805 + * Changed: removed .call(self) for route callbacks + * Dependency: `qs >= 0.3.1` + * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808 + +2.4.4 / 2011-08-05 +================== + + * Fixed `res.header()` intention of a set, even when `undefined` + * Fixed `*`, value no longer required + * Fixed `res.send(204)` support. Closes #771 + +2.4.3 / 2011-07-14 +================== + + * Added docs for `status` option special-case. Closes #739 + * Fixed `options.filename`, exposing the view path to template engines + +2.4.2. / 2011-07-06 +================== + + * Revert "removed jsonp stripping" for XSS + +2.4.1 / 2011-07-06 +================== + + * Added `res.json()` JSONP support. Closes #737 + * Added _extending-templates_ example. Closes #730 + * Added "strict routing" setting for trailing slashes + * Added support for multiple envs in `app.configure()` calls. Closes #735 + * Changed: `res.send()` using `res.json()` + * Changed: when cookie `path === null` don't default it + * Changed; default cookie path to "home" setting. Closes #731 + * Removed _pids/logs_ creation from express(1) + +2.4.0 / 2011-06-28 +================== + + * Added chainable `res.status(code)` + * Added `res.json()`, an explicit version of `res.send(obj)` + * Added simple web-service example + +2.3.12 / 2011-06-22 +================== + + * \#express is now on freenode! come join! + * Added `req.get(field, param)` + * Added links to Japanese documentation, thanks @hideyukisaito! + * Added; the `express(1)` generated app outputs the env + * Added `content-negotiation` example + * Dependency: connect >= 1.5.1 < 2.0.0 + * Fixed view layout bug. Closes #720 + * Fixed; ignore body on 304. Closes #701 + +2.3.11 / 2011-06-04 +================== + + * Added `npm test` + * Removed generation of dummy test file from `express(1)` + * Fixed; `express(1)` adds express as a dep + * Fixed; prune on `prepublish` + +2.3.10 / 2011-05-27 +================== + + * Added `req.route`, exposing the current route + * Added _package.json_ generation support to `express(1)` + * Fixed call to `app.param()` function for optional params. Closes #682 + +2.3.9 / 2011-05-25 +================== + + * Fixed bug-ish with `../' in `res.partial()` calls + +2.3.8 / 2011-05-24 +================== + + * Fixed `app.options()` + +2.3.7 / 2011-05-23 +================== + + * Added route `Collection`, ex: `app.get('/user/:id').remove();` + * Added support for `app.param(fn)` to define param logic + * Removed `app.param()` support for callback with return value + * Removed module.parent check from express(1) generated app. Closes #670 + * Refactored router. Closes #639 + +2.3.6 / 2011-05-20 +================== + + * Changed; using devDependencies instead of git submodules + * Fixed redis session example + * Fixed markdown example + * Fixed view caching, should not be enabled in development + +2.3.5 / 2011-05-20 +================== + + * Added export `.view` as alias for `.View` + +2.3.4 / 2011-05-08 +================== + + * Added `./examples/say` + * Fixed `res.sendfile()` bug preventing the transfer of files with spaces + +2.3.3 / 2011-05-03 +================== + + * Added "case sensitive routes" option. + * Changed; split methods supported per rfc [slaskis] + * Fixed route-specific middleware when using the same callback function several times + +2.3.2 / 2011-04-27 +================== + + * Fixed view hints + +2.3.1 / 2011-04-26 +================== + + * Added `app.match()` as `app.match.all()` + * Added `app.lookup()` as `app.lookup.all()` + * Added `app.remove()` for `app.remove.all()` + * Added `app.remove.VERB()` + * Fixed template caching collision issue. Closes #644 + * Moved router over from connect and started refactor + +2.3.0 / 2011-04-25 +================== + + * Added options support to `res.clearCookie()` + * Added `res.helpers()` as alias of `res.locals()` + * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0` + * Changed; auto set Content-Type in res.attachement [Aaron Heckmann] + * Renamed "cache views" to "view cache". Closes #628 + * Fixed caching of views when using several apps. Closes #637 + * Fixed gotcha invoking `app.param()` callbacks once per route middleware. +Closes #638 + * Fixed partial lookup precedence. Closes #631 +Shaw] + +2.2.2 / 2011-04-12 +================== + + * Added second callback support for `res.download()` connection errors + * Fixed `filename` option passing to template engine + +2.2.1 / 2011-04-04 +================== + + * Added `layout(path)` helper to change the layout within a view. Closes #610 + * Fixed `partial()` collection object support. + Previously only anything with `.length` would work. + When `.length` is present one must still be aware of holes, + however now `{ collection: {foo: 'bar'}}` is valid, exposes + `keyInCollection` and `keysInCollection`. + + * Performance improved with better view caching + * Removed `request` and `response` locals + * Changed; errorHandler page title is now `Express` instead of `Connect` + +2.2.0 / 2011-03-30 +================== + + * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606 + * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606 + * Added `app.VERB(path)` as alias of `app.lookup.VERB()`. + * Dependency `connect >= 1.2.0` + +2.1.1 / 2011-03-29 +================== + + * Added; expose `err.view` object when failing to locate a view + * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann] + * Fixed; `res.send(undefined)` responds with 204 [aheckmann] + +2.1.0 / 2011-03-24 +================== + + * Added `some html
'); + * + * @param {string|number|boolean|object|Buffer} body + * @public + */ + +res.send = function send(body) { + var chunk = body; + var encoding; + var len; + var req = this.req; + var type; + + // settings + var app = this.app; + + // allow status / body + if (arguments.length === 2) { + // res.send(body, status) backwards compat + if (typeof arguments[0] !== 'number' && typeof arguments[1] === 'number') { + deprecate('res.send(body, status): Use res.status(status).send(body) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.send(status, body): Use res.status(status).send(body) instead'); + this.statusCode = arguments[0]; + chunk = arguments[1]; + } + } + + // disambiguate res.send(status) and res.send(status, num) + if (typeof chunk === 'number' && arguments.length === 1) { + // res.send(status) will set status message as text string + if (!this.get('Content-Type')) { + this.type('txt'); + } + + deprecate('res.send(status): Use res.sendStatus(status) instead'); + this.statusCode = chunk; + chunk = statusCodes[chunk]; + } + + switch (typeof chunk) { + // string defaulting to html + case 'string': + if (!this.get('Content-Type')) { + this.type('html'); + } + break; + case 'boolean': + case 'number': + case 'object': + if (chunk === null) { + chunk = ''; + } else if (Buffer.isBuffer(chunk)) { + if (!this.get('Content-Type')) { + this.type('bin'); + } + } else { + return this.json(chunk); + } + break; + } + + // write strings in utf-8 + if (typeof chunk === 'string') { + encoding = 'utf8'; + type = this.get('Content-Type'); + + // reflect this in content-type + if (typeof type === 'string') { + this.set('Content-Type', setCharset(type, 'utf-8')); + } + } + + // populate Content-Length + if (chunk !== undefined) { + if (!Buffer.isBuffer(chunk)) { + // convert chunk to Buffer; saves later double conversions + chunk = new Buffer(chunk, encoding); + encoding = undefined; + } + + len = chunk.length; + this.set('Content-Length', len); + } + + // populate ETag + var etag; + var generateETag = len !== undefined && app.get('etag fn'); + if (typeof generateETag === 'function' && !this.get('ETag')) { + if ((etag = generateETag(chunk, encoding))) { + this.set('ETag', etag); + } + } + + // freshness + if (req.fresh) this.statusCode = 304; + + // strip irrelevant headers + if (204 === this.statusCode || 304 === this.statusCode) { + this.removeHeader('Content-Type'); + this.removeHeader('Content-Length'); + this.removeHeader('Transfer-Encoding'); + chunk = ''; + } + + if (req.method === 'HEAD') { + // skip body for HEAD + this.end(); + } else { + // respond + this.end(chunk, encoding); + } + + return this; +}; + +/** + * Send JSON response. + * + * Examples: + * + * res.json(null); + * res.json({ user: 'tj' }); + * + * @param {string|number|boolean|object} obj + * @public + */ + +res.json = function json(obj) { + var val = obj; + + // allow status / body + if (arguments.length === 2) { + // res.json(body, status) backwards compat + if (typeof arguments[1] === 'number') { + deprecate('res.json(obj, status): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = stringify(val, replacer, spaces); + + // content-type + if (!this.get('Content-Type')) { + this.set('Content-Type', 'application/json'); + } + + return this.send(body); +}; + +/** + * Send JSON response with JSONP callback support. + * + * Examples: + * + * res.jsonp(null); + * res.jsonp({ user: 'tj' }); + * + * @param {string|number|boolean|object} obj + * @public + */ + +res.jsonp = function jsonp(obj) { + var val = obj; + + // allow status / body + if (arguments.length === 2) { + // res.json(body, status) backwards compat + if (typeof arguments[1] === 'number') { + deprecate('res.jsonp(obj, status): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = stringify(val, replacer, spaces); + var callback = this.req.query[app.get('jsonp callback name')]; + + // content-type + if (!this.get('Content-Type')) { + this.set('X-Content-Type-Options', 'nosniff'); + this.set('Content-Type', 'application/json'); + } + + // fixup callback + if (Array.isArray(callback)) { + callback = callback[0]; + } + + // jsonp + if (typeof callback === 'string' && callback.length !== 0) { + this.charset = 'utf-8'; + this.set('X-Content-Type-Options', 'nosniff'); + this.set('Content-Type', 'text/javascript'); + + // restrict callback charset + callback = callback.replace(/[^\[\]\w$.]/g, ''); + + // replace chars not allowed in JavaScript that are in JSON + body = body + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029'); + + // the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse" + // the typeof check is just to reduce client error noise + body = '/**/ typeof ' + callback + ' === \'function\' && ' + callback + '(' + body + ');'; + } + + return this.send(body); +}; + +/** + * Send given HTTP status code. + * + * Sets the response status to `statusCode` and the body of the + * response to the standard description from node's http.STATUS_CODES + * or the statusCode number if no description. + * + * Examples: + * + * res.sendStatus(200); + * + * @param {number} statusCode + * @public + */ + +res.sendStatus = function sendStatus(statusCode) { + var body = statusCodes[statusCode] || String(statusCode); + + this.statusCode = statusCode; + this.type('txt'); + + return this.send(body); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `callback(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * Examples: + * + * The following example illustrates how `res.sendFile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendFile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * app.get('/user/:uid/photos/:file', function(req, res){ + * var uid = req.params.uid + * , file = req.params.file; + * + * req.user.mayViewFilesFrom(uid, function(yes){ + * if (yes) { + * res.sendFile('/uploads/' + uid + '/' + file); + * } else { + * res.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @public + */ + +res.sendFile = function sendFile(path, options, callback) { + var done = callback; + var req = this.req; + var res = this; + var next = req.next; + var opts = options || {}; + + if (!path) { + throw new TypeError('path argument is required to res.sendFile'); + } + + // support function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + if (!opts.root && !isAbsolute(path)) { + throw new TypeError('path must be absolute or specify root to res.sendFile'); + } + + // create file stream + var pathname = encodeURI(path); + var file = send(req, pathname, opts); + + // transfer + sendfile(res, file, opts, function (err) { + if (done) return done(err); + if (err && err.code === 'EISDIR') return next(); + + // next() all but write errors + if (err && err.code !== 'ECONNABORTED' && err.syscall !== 'write') { + next(err); + } + }); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `callback(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * Examples: + * + * The following example illustrates how `res.sendfile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendfile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * app.get('/user/:uid/photos/:file', function(req, res){ + * var uid = req.params.uid + * , file = req.params.file; + * + * req.user.mayViewFilesFrom(uid, function(yes){ + * if (yes) { + * res.sendfile('/uploads/' + uid + '/' + file); + * } else { + * res.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @public + */ + +res.sendfile = function (path, options, callback) { + var done = callback; + var req = this.req; + var res = this; + var next = req.next; + var opts = options || {}; + + // support function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + // create file stream + var file = send(req, path, opts); + + // transfer + sendfile(res, file, opts, function (err) { + if (done) return done(err); + if (err && err.code === 'EISDIR') return next(); + + // next() all but write errors + if (err && err.code !== 'ECONNABORT' && err.syscall !== 'write') { + next(err); + } + }); +}; + +res.sendfile = deprecate.function(res.sendfile, + 'res.sendfile: Use res.sendFile instead'); + +/** + * Transfer the file at the given `path` as an attachment. + * + * Optionally providing an alternate attachment `filename`, + * and optional callback `callback(err)`. The callback is invoked + * when the data transfer is complete, or when an error has + * ocurred. Be sure to check `res.headersSent` if you plan to respond. + * + * This method uses `res.sendfile()`. + * + * @public + */ + +res.download = function download(path, filename, callback) { + var done = callback; + var name = filename; + + // support function as second arg + if (typeof filename === 'function') { + done = filename; + name = null; + } + + // set Content-Disposition when file is sent + var headers = { + 'Content-Disposition': contentDisposition(name || path) + }; + + // Resolve the full path for sendFile + var fullPath = resolve(path); + + return this.sendFile(fullPath, { headers: headers }, done); +}; + +/** + * Set _Content-Type_ response header with `type` through `mime.lookup()` + * when it does not contain "/", or set the Content-Type to `type` otherwise. + * + * Examples: + * + * res.type('.html'); + * res.type('html'); + * res.type('json'); + * res.type('application/json'); + * res.type('png'); + * + * @param {String} type + * @return {ServerResponse} for chaining + * @public + */ + +res.contentType = +res.type = function contentType(type) { + var ct = type.indexOf('/') === -1 + ? mime.lookup(type) + : type; + + return this.set('Content-Type', ct); +}; + +/** + * Respond to the Acceptable formats using an `obj` + * of mime-type callbacks. + * + * This method uses `req.accepted`, an array of + * acceptable types ordered by their quality values. + * When "Accept" is not present the _first_ callback + * is invoked, otherwise the first match is used. When + * no match is performed the server responds with + * 406 "Not Acceptable". + * + * Content-Type is set for you, however if you choose + * you may alter this within the callback using `res.type()` + * or `res.set('Content-Type', ...)`. + * + * res.format({ + * 'text/plain': function(){ + * res.send('hey'); + * }, + * + * 'text/html': function(){ + * res.send('hey
'); + * }, + * + * 'appliation/json': function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * In addition to canonicalized MIME types you may + * also use extnames mapped to these types: + * + * res.format({ + * text: function(){ + * res.send('hey'); + * }, + * + * html: function(){ + * res.send('hey
'); + * }, + * + * json: function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * By default Express passes an `Error` + * with a `.status` of 406 to `next(err)` + * if a match is not made. If you provide + * a `.default` callback it will be invoked + * instead. + * + * @param {Object} obj + * @return {ServerResponse} for chaining + * @public + */ + +res.format = function(obj){ + var req = this.req; + var next = req.next; + + var fn = obj.default; + if (fn) delete obj.default; + var keys = Object.keys(obj); + + var key = keys.length > 0 + ? req.accepts(keys) + : false; + + this.vary("Accept"); + + if (key) { + this.set('Content-Type', normalizeType(key).value); + obj[key](req, this, next); + } else if (fn) { + fn(); + } else { + var err = new Error('Not Acceptable'); + err.status = err.statusCode = 406; + err.types = normalizeTypes(keys).map(function(o){ return o.value }); + next(err); + } + + return this; +}; + +/** + * Set _Content-Disposition_ header to _attachment_ with optional `filename`. + * + * @param {String} filename + * @return {ServerResponse} + * @public + */ + +res.attachment = function attachment(filename) { + if (filename) { + this.type(extname(filename)); + } + + this.set('Content-Disposition', contentDisposition(filename)); + + return this; +}; + +/** + * Append additional header `field` with value `val`. + * + * Example: + * + * res.append('Link', ['' + statusCodes[status] + '. Redirecting to ' + u + '
'; + }, + + default: function(){ + body = ''; + } + }); + + // Respond + this.statusCode = status; + this.set('Content-Length', Buffer.byteLength(body)); + + if (this.req.method === 'HEAD') { + this.end(); + } else { + this.end(body); + } +}; + +/** + * Add `field` to Vary. If already present in the Vary set, then + * this call is simply ignored. + * + * @param {Array|String} field + * @return {ServerResponse} for chaining + * @public + */ + +res.vary = function(field){ + // checks for back-compat + if (!field || (Array.isArray(field) && !field.length)) { + deprecate('res.vary(): Provide a field name'); + return this; + } + + vary(this, field); + + return this; +}; + +/** + * Render `view` with the given `options` and optional callback `fn`. + * When a callback function is given a response will _not_ be made + * automatically, otherwise a response of _200_ and _text/html_ is given. + * + * Options: + * + * - `cache` boolean hinting to the engine it should cache + * - `filename` filename of the view being rendered + * + * @public + */ + +res.render = function render(view, options, callback) { + var app = this.req.app; + var done = callback; + var opts = options || {}; + var req = this.req; + var self = this; + + // support callback function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + // merge res.locals + opts._locals = self.locals; + + // default callback to respond + done = done || function (err, str) { + if (err) return req.next(err); + self.send(str); + }; + + // render + app.render(view, opts, done); +}; + +// pipe the send file stream +function sendfile(res, file, options, callback) { + var done = false; + var streaming; + + // request aborted + function onaborted() { + if (done) return; + done = true; + + var err = new Error('Request aborted'); + err.code = 'ECONNABORTED'; + callback(err); + } + + // directory + function ondirectory() { + if (done) return; + done = true; + + var err = new Error('EISDIR, read'); + err.code = 'EISDIR'; + callback(err); + } + + // errors + function onerror(err) { + if (done) return; + done = true; + callback(err); + } + + // ended + function onend() { + if (done) return; + done = true; + callback(); + } + + // file + function onfile() { + streaming = false; + } + + // finished + function onfinish(err) { + if (err && err.code === 'ECONNRESET') return onaborted(); + if (err) return onerror(err); + if (done) return; + + setImmediate(function () { + if (streaming !== false && !done) { + onaborted(); + return; + } + + if (done) return; + done = true; + callback(); + }); + } + + // streaming + function onstream() { + streaming = true; + } + + file.on('directory', ondirectory); + file.on('end', onend); + file.on('error', onerror); + file.on('file', onfile); + file.on('stream', onstream); + onFinished(res, onfinish); + + if (options.headers) { + // set headers on successful transfer + file.on('headers', function headers(res) { + var obj = options.headers; + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; i++) { + var k = keys[i]; + res.setHeader(k, obj[k]); + } + }); + } + + // pipe + file.pipe(res); +} + +/** + * Stringify JSON, like JSON.stringify, but v8 optimized. + * @private + */ + +function stringify(value, replacer, spaces) { + // v8 checks arguments.length for optimizing simple call + // https://bugs.chromium.org/p/v8/issues/detail?id=4730 + return replacer || spaces + ? JSON.stringify(value, replacer, spaces) + : JSON.stringify(value); +} diff --git a/node_modules/express/lib/router/index.js b/node_modules/express/lib/router/index.js new file mode 100644 index 0000000..dac2514 --- /dev/null +++ b/node_modules/express/lib/router/index.js @@ -0,0 +1,645 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Route = require('./route'); +var Layer = require('./layer'); +var methods = require('methods'); +var mixin = require('utils-merge'); +var debug = require('debug')('express:router'); +var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); +var parseUrl = require('parseurl'); + +/** + * Module variables. + * @private + */ + +var objectRegExp = /^\[object (\S+)\]$/; +var slice = Array.prototype.slice; +var toString = Object.prototype.toString; + +/** + * Initialize a new `Router` with the given `options`. + * + * @param {Object} options + * @return {Router} which is an callable function + * @public + */ + +var proto = module.exports = function(options) { + var opts = options || {}; + + function router(req, res, next) { + router.handle(req, res, next); + } + + // mixin Router class functions + router.__proto__ = proto; + + router.params = {}; + router._params = []; + router.caseSensitive = opts.caseSensitive; + router.mergeParams = opts.mergeParams; + router.strict = opts.strict; + router.stack = []; + + return router; +}; + +/** + * Map the given param placeholder `name`(s) to the given callback. + * + * Parameter mapping is used to provide pre-conditions to routes + * which use normalized placeholders. For example a _:user_id_ parameter + * could automatically load a user's information from the database without + * any additional code, + * + * The callback uses the same signature as middleware, the only difference + * being that the value of the placeholder is passed, in this case the _id_ + * of the user. Once the `next()` function is invoked, just like middleware + * it will continue on to execute the route, or subsequent parameter functions. + * + * Just like in middleware, you must either respond to the request or call next + * to avoid stalling the request. + * + * app.param('user_id', function(req, res, next, id){ + * User.find(id, function(err, user){ + * if (err) { + * return next(err); + * } else if (!user) { + * return next(new Error('failed to load user')); + * } + * req.user = user; + * next(); + * }); + * }); + * + * @param {String} name + * @param {Function} fn + * @return {app} for chaining + * @public + */ + +proto.param = function param(name, fn) { + // param logic + if (typeof name === 'function') { + deprecate('router.param(fn): Refactor to use path params'); + this._params.push(name); + return; + } + + // apply param functions + var params = this._params; + var len = params.length; + var ret; + + if (name[0] === ':') { + deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.substr(1)) + ', fn) instead'); + name = name.substr(1); + } + + for (var i = 0; i < len; ++i) { + if (ret = params[i](name, fn)) { + fn = ret; + } + } + + // ensure we end up with a + // middleware function + if ('function' !== typeof fn) { + throw new Error('invalid param() call for ' + name + ', got ' + fn); + } + + (this.params[name] = this.params[name] || []).push(fn); + return this; +}; + +/** + * Dispatch a req, res into the router. + * @private + */ + +proto.handle = function handle(req, res, out) { + var self = this; + + debug('dispatching %s %s', req.method, req.url); + + var search = 1 + req.url.indexOf('?'); + var pathlength = search ? search - 1 : req.url.length; + var fqdn = req.url[0] !== '/' && 1 + req.url.substr(0, pathlength).indexOf('://'); + var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : ''; + var idx = 0; + var removed = ''; + var slashAdded = false; + var paramcalled = {}; + + // store options for OPTIONS request + // only used if OPTIONS request + var options = []; + + // middleware and routes + var stack = self.stack; + + // manage inter-router variables + var parentParams = req.params; + var parentUrl = req.baseUrl || ''; + var done = restore(out, req, 'baseUrl', 'next', 'params'); + + // setup next layer + req.next = next; + + // for options requests, respond with a default if nothing else responds + if (req.method === 'OPTIONS') { + done = wrap(done, function(old, err) { + if (err || options.length === 0) return old(err); + sendOptionsResponse(res, options, old); + }); + } + + // setup basic req values + req.baseUrl = parentUrl; + req.originalUrl = req.originalUrl || req.url; + + next(); + + function next(err) { + var layerError = err === 'route' + ? null + : err; + + // remove added slash + if (slashAdded) { + req.url = req.url.substr(1); + slashAdded = false; + } + + // restore altered req.url + if (removed.length !== 0) { + req.baseUrl = parentUrl; + req.url = protohost + removed + req.url.substr(protohost.length); + removed = ''; + } + + // no more matching layers + if (idx >= stack.length) { + setImmediate(done, layerError); + return; + } + + // get pathname of request + var path = getPathname(req); + + if (path == null) { + return done(layerError); + } + + // find next matching layer + var layer; + var match; + var route; + + while (match !== true && idx < stack.length) { + layer = stack[idx++]; + match = matchLayer(layer, path); + route = layer.route; + + if (typeof match !== 'boolean') { + // hold on to layerError + layerError = layerError || match; + } + + if (match !== true) { + continue; + } + + if (!route) { + // process non-route handlers normally + continue; + } + + if (layerError) { + // routes do not match with a pending error + match = false; + continue; + } + + var method = req.method; + var has_method = route._handles_method(method); + + // build up automatic options response + if (!has_method && method === 'OPTIONS') { + appendMethods(options, route._options()); + } + + // don't even bother matching route + if (!has_method && method !== 'HEAD') { + match = false; + continue; + } + } + + // no match + if (match !== true) { + return done(layerError); + } + + // store route for dispatch on change + if (route) { + req.route = route; + } + + // Capture one-time layer values + req.params = self.mergeParams + ? mergeParams(layer.params, parentParams) + : layer.params; + var layerPath = layer.path; + + // this should be done for the layer + self.process_params(layer, paramcalled, req, res, function (err) { + if (err) { + return next(layerError || err); + } + + if (route) { + return layer.handle_request(req, res, next); + } + + trim_prefix(layer, layerError, layerPath, path); + }); + } + + function trim_prefix(layer, layerError, layerPath, path) { + var c = path[layerPath.length]; + if (c && '/' !== c && '.' !== c) return next(layerError); + + // Trim off the part of the url that matches the route + // middleware (.use stuff) needs to have the path stripped + if (layerPath.length !== 0) { + debug('trim prefix (%s) from url %s', layerPath, req.url); + removed = layerPath; + req.url = protohost + req.url.substr(protohost.length + removed.length); + + // Ensure leading slash + if (!fqdn && req.url[0] !== '/') { + req.url = '/' + req.url; + slashAdded = true; + } + + // Setup base URL (no trailing slash) + req.baseUrl = parentUrl + (removed[removed.length - 1] === '/' + ? removed.substring(0, removed.length - 1) + : removed); + } + + debug('%s %s : %s', layer.name, layerPath, req.originalUrl); + + if (layerError) { + layer.handle_error(layerError, req, res, next); + } else { + layer.handle_request(req, res, next); + } + } +}; + +/** + * Process any parameters for the layer. + * @private + */ + +proto.process_params = function process_params(layer, called, req, res, done) { + var params = this.params; + + // captured parameters from the layer, keys and values + var keys = layer.keys; + + // fast track + if (!keys || keys.length === 0) { + return done(); + } + + var i = 0; + var name; + var paramIndex = 0; + var key; + var paramVal; + var paramCallbacks; + var paramCalled; + + // process params in order + // param callbacks can be async + function param(err) { + if (err) { + return done(err); + } + + if (i >= keys.length ) { + return done(); + } + + paramIndex = 0; + key = keys[i++]; + + if (!key) { + return done(); + } + + name = key.name; + paramVal = req.params[name]; + paramCallbacks = params[name]; + paramCalled = called[name]; + + if (paramVal === undefined || !paramCallbacks) { + return param(); + } + + // param previously called with same value or error occurred + if (paramCalled && (paramCalled.match === paramVal + || (paramCalled.error && paramCalled.error !== 'route'))) { + // restore value + req.params[name] = paramCalled.value; + + // next param + return param(paramCalled.error); + } + + called[name] = paramCalled = { + error: null, + match: paramVal, + value: paramVal + }; + + paramCallback(); + } + + // single param callbacks + function paramCallback(err) { + var fn = paramCallbacks[paramIndex++]; + + // store updated value + paramCalled.value = req.params[key.name]; + + if (err) { + // store error + paramCalled.error = err; + param(err); + return; + } + + if (!fn) return param(); + + try { + fn(req, res, paramCallback, paramVal, key.name); + } catch (e) { + paramCallback(e); + } + } + + param(); +}; + +/** + * Use the given middleware function, with optional path, defaulting to "/". + * + * Use (like `.all`) will run for any http METHOD, but it will not add + * handlers for those methods so OPTIONS requests will not consider `.use` + * functions even if they could respond. + * + * The other difference is that _route_ path is stripped and not visible + * to the handler function. The main effect of this feature is that mounted + * handlers can operate without any code changes regardless of the "prefix" + * pathname. + * + * @public + */ + +proto.use = function use(fn) { + var offset = 0; + var path = '/'; + + // default path to '/' + // disambiguate router.use([fn]) + if (typeof fn !== 'function') { + var arg = fn; + + while (Array.isArray(arg) && arg.length !== 0) { + arg = arg[0]; + } + + // first arg is the path + if (typeof arg !== 'function') { + offset = 1; + path = fn; + } + } + + var callbacks = flatten(slice.call(arguments, offset)); + + if (callbacks.length === 0) { + throw new TypeError('Router.use() requires middleware functions'); + } + + for (var i = 0; i < callbacks.length; i++) { + var fn = callbacks[i]; + + if (typeof fn !== 'function') { + throw new TypeError('Router.use() requires middleware function but got a ' + gettype(fn)); + } + + // add the middleware + debug('use %s %s', path, fn.name || 'You are amazing
+Jade is a terse and simple templating language with a strong focus on performance and powerful features.
+Welcome to my super lame site.
+ + +