Mukho

Add IP address in log

......@@ -122,6 +122,7 @@ io.sockets.on('connection', function(socket) {
})
})
server.listen(PORT, function(){
// 서버 가동(IPv4 형식으로 express 설정)
server.listen(PORT, '127.0.0.1', function(){
console.log(logString+"서버가 시작되었습니다.(Port: "+PORT+")");
});
\ No newline at end of file
......
The MIT License (MIT)
Copyright (c) 2014-2016 Aras Atasaygin
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.
is.js
=====
[![JS.ORG](https://img.shields.io/badge/js.org-is-ffb400.svg?style=flat-square)](http://js.org)
####This is a general-purpose check library.
- No dependencies
- AMD, Node & browser ready
####Usage:
Node.js:
```
npm install is_js
```
Bower:
```
bower install is_js
```
Build:
```
npm run build
```
Test:
```
npm test
```
####Contributing:
Thanks for considering to contribute. Check [here](CONTRIBUTING.md)
####Contributors:
Many thanks to our contributors: https://github.com/arasatasaygin/is.js/graphs/contributors
Type checks
===========
is.arguments(value:any)
-----------------------
####Checks if the given value type is arguments.
interfaces: not, all, any
```javascript
var getArguments = function() {
return arguments;
};
var arguments = getArguments();
is.arguments(arguments);
=> true
is.not.arguments({foo: 'bar'});
=> true
is.all.arguments(arguments, 'bar');
=> false
is.any.arguments(['foo'], arguments);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.arguments([arguments, 'foo', 'bar']);
=> false
```
is.array(value:any)
-------------------
####Checks if the given value type is array.
interfaces: not, all, any
```javascript
is.array(['foo', 'bar', 'baz']);
=> true
is.not.array({foo: 'bar'});
=> true
is.all.array(['foo'], 'bar');
=> false
is.any.array(['foo'], 'bar');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.array([[1, 2], 'foo', 'bar']);
=> false
```
is.boolean(value:any)
---------------------
####Checks if the given value type is boolean.
interfaces: not, all, any
```javascript
is.boolean(true);
=> true
is.not.boolean({foo: 'bar'});
=> true
is.all.boolean(true, 'bar');
=> false
is.any.boolean(true, 'bar');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.boolean([true, 'foo', 'bar']);
=> false
```
is.date(value:any)
------------------
####Checks if the given value type is date.
interfaces: not, all, any
```javascript
is.date(new Date());
=> true
is.not.date({foo: 'bar'});
=> true
is.all.date(new Date(), 'bar');
=> false
is.any.date(new Date(), 'bar');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.date([new Date(), 'foo', 'bar']);
=> false
```
is.domNode(value:any)
-----------------------------
####Checks if the given object is a dom node.
interfaces: not, all, any
```javascript
var obj = document.createElement('div');
is.domNode(obj);
=> true
is.domNode({nope: 'nope'});
=> false
is.not.domNode({});
=> true
is.all.domNode(obj, obj);
=> true
is.any.domNode(obj, {nope: 'nope'});
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.domNode([obj, {nope: 'nope'}]);
=> false
```
is.error(value:any)
-------------------
####Checks if the given value type is error.
interfaces: not, all, any
```javascript
is.error(new Error());
=> true
is.not.error({foo: 'bar'});
=> true
is.all.error(new Error(), 'bar');
=> false
is.any.error(new Error(), 'bar');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.error([new Error(), 'foo', 'bar']);
=> false
```
is.function(value:any)
----------------------
####Checks if the given value type is function.
interfaces: not, all, any
```javascript
is.function(toString);
=> true
is.not.function({foo: 'bar'});
=> true
is.all.function(toString, 'bar');
=> false
is.any.function(toString, 'bar');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.function([toString, 'foo', 'bar']);
=> false
```
is.nan(value:any)
-----------------
####Checks if the given value type is NaN.
interfaces: not, all, any
```javascript
is.nan(NaN);
=> true
is.not.nan(42);
=> true
is.all.nan(NaN, 1);
=> false
is.any.nan(NaN, 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.nan([NaN, 'foo', 1]);
=> false
```
is.null(value:any)
------------------
####Checks if the given value type is null.
interfaces: not, all, any
```javascript
is.null(null);
=> true
is.not.null(42);
=> true
is.all.null(null, 1);
=> false
is.any.null(null, 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.null([null, 'foo', 1]);
=> false
```
is.number(value:any)
--------------------
####Checks if the given value type is number.
interfaces: not, all, any
```javascript
is.number(42);
=> true
is.number(NaN);
=> false
is.not.number('42');
=> true
is.all.number('foo', 1);
=> false
is.any.number({}, 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.number([42, 'foo', 1]);
=> false
```
is.object(value:any)
--------------------
####Checks if the given value type is object.
interfaces: not, all, any
```javascript
is.object({foo: 'bar'});
=> true
// functions are also returning as true
is.object(toString);
=> true
is.not.object('foo');
=> true
is.all.object({}, 1);
=> false
is.any.object({}, 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.object([{}, new Object()]);
=> true
```
is.json(value:any)
--------------------
####Checks if the given value type is pure json object.
interfaces: not, all, any
```javascript
is.json({foo: 'bar'});
=> true
// functions are returning as false
is.json(toString);
=> false
is.not.json([]);
=> true
is.all.json({}, 1);
=> false
is.any.json({}, 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.json([{}, {foo: 'bar'}]);
=> true
```
is.regexp(value:any)
--------------------
####Checks if the given value type is RegExp.
interfaces: not, all, any
```javascript
is.regexp(/test/);
=> true
is.not.regexp(['foo']);
=> true
is.all.regexp(/test/, 1);
=> false
is.any.regexp(new RegExp('ab+c'), 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.regexp([{}, /test/]);
=> false
```
is.string(value:any)
--------------------
####Checks if the given value type is string.
interfaces: not, all, any
```javascript
is.string('foo');
=> true
is.not.string(['foo']);
=> true
is.all.string('foo', 1);
=> false
is.any.string('foo', 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.string([{}, 'foo']);
=> false
```
is.char(value:any)
--------------------
####Checks if the given value type is char.
interfaces: not, all, any
```javascript
is.char('f');
=> true
is.not.char(['foo']);
=> true
is.all.char('f', 1);
=> false
is.any.char('f', 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.char(['f', 'o', 'o']);
=> true
```
is.undefined(value:any)
-----------------------
####Checks if the given value type is undefined.
interfaces: not, all, any
```javascript
is.undefined(undefined);
=> true
is.not.undefined(null);
=> true
is.all.undefined(undefined, 1);
=> false
is.any.undefined(undefined, 2);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.undefined([{}, undefined]);
=> false
```
is.sameType(value:any, other:any)
---------------------------------
####Checks if the given value types are same type.
interface: not
```javascript
is.sameType(42, 7);
=> true
is.sameType(42, '7');
=> false
is.not.sameType(42, 7);
=> false
```
is.windowObject(value:any)
-----------------------------
####Checks if the given object is window object.
interfaces: not, all, any
```javascript
is.windowObject(window);
=> true
is.windowObject({nope: 'nope'});
=> false
is.not.windowObject({});
=> true
is.all.windowObject(window, {nope: 'nope'});
=> false
is.any.windowObject(window, {nope: 'nope'});
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.windowObject([window, {nope: 'nope'}]);
=> false
```
Presence checks
===============
is.empty(value:array|object|string)
-----------------------------------
####Checks if the given value is empty.
interfaces: not, all, any
```javascript
is.empty({});
=> true
is.empty([]);
=> true
is.empty('');
=> true
is.not.empty(['foo']);
=> true
is.all.empty('', {}, ['foo']);
=> false
is.any.empty([], 42);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.empty([{}, 'foo']);
=> false
```
is.existy(value:any)
--------------------
####Checks if the given value is existy. (not null or undefined)
interfaces: not, all, any
```javascript
is.existy({});
=> true
is.existy(null);
=> false
is.not.existy(undefined);
=> true
is.all.existy(null, ['foo']);
=> false
is.any.existy(undefined, 42);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.existy([{}, 'foo']);
=> true
```
is.truthy(value:any)
--------------------
####Checks if the given value is truthy. (existy and not false)
interfaces: not, all, any
```javascript
is.truthy(true);
=> true
is.truthy(null);
=> false
is.not.truthy(false);
=> true
is.all.truthy(null, true);
=> false
is.any.truthy(undefined, true);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.truthy([{}, true]);
=> true
```
is.falsy(value:any)
-------------------
####Checks if the given value is falsy.
interfaces: not, all, any
```javascript
is.falsy(false);
=> true
is.falsy(null);
=> true
is.not.falsy(true);
=> true
is.all.falsy(null, false);
=> true
is.any.falsy(undefined, true);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.falsy([false, true, undefined]);
=> false
```
is.space(value:any)
----------------------
####Checks if the given value is space.
interfaces: not, all, any
```javascript
is.space(' ');
=> true
is.space('foo');
=> false
is.not.space(true);
=> true
is.all.space(' ', 'foo');
=> false
is.any.space(' ', true);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.space([' ', 'foo', undefined]);
=> false
```
RegExp checks
=============
is.url(value:any)
-----------------
####Checks if the given value matches url regexp.
interfaces: not, all, any
```javascript
is.url('http://www.test.com');
=> true
is.url('foo');
=> false
is.not.url(true);
=> true
is.all.url('http://www.test.com', 'foo');
=> false
is.any.url('http://www.test.com', true);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.url(['http://www.test.com', 'foo', undefined]);
=> false
```
is.email(value:any)
-------------------
####Checks if the given value matches email regexp.
interfaces: not, all, any
```javascript
is.email('test@test.com');
=> true
is.email('foo');
=> false
is.not.email('foo');
=> true
is.all.email('test@test.com', 'foo');
=> false
is.any.email('test@test.com', 'foo');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.email(['test@test.com', 'foo', undefined]);
=> false
```
is.creditCard(value:any)
------------------------
####Checks if the given value matches credit card regexp.
interfaces: not, all, any
```javascript
is.creditCard(378282246310005);
=> true
is.creditCard(123);
=> false
is.not.creditCard(123);
=> true
is.all.creditCard(378282246310005, 123);
=> false
is.any.creditCard(378282246310005, 123);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.creditCard([378282246310005, 123, undefined]);
=> false
```
is.alphaNumeric(value:any)
--------------------------
####Checks if the given value matches alpha numeric regexp.
interfaces: not, all, any
```javascript
is.alphaNumeric('alphaNu3er1k');
=> true
is.alphaNumeric('*?');
=> false
is.not.alphaNumeric('*?');
=> true
is.all.alphaNumeric('alphaNu3er1k', '*?');
=> false
is.any.alphaNumeric('alphaNu3er1k', '*?');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.alphaNumeric(['alphaNu3er1k', '*?']);
=> false
```
is.timeString(value:any)
------------------------
####Checks if the given value matches time string regexp.
interfaces: not, all, any
```javascript
is.timeString('13:45:30');
=> true
is.timeString('90:90:90');
=> false
is.not.timeString('90:90:90');
=> true
is.all.timeString('13:45:30', '90:90:90');
=> false
is.any.timeString('13:45:30', '90:90:90');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.timeString(['13:45:30', '90:90:90']);
=> false
```
is.dateString(value:any)
------------------------
####Checks if the given value matches date string regexp.
interfaces: not, all, any
```javascript
is.dateString('11/11/2011');
=> true
is.dateString('10-21-2012');
=> true
is.dateString('90/11/2011');
=> false
is.not.dateString('90/11/2011');
=> true
is.all.dateString('11/11/2011', '90/11/2011');
=> false
is.any.dateString('11-11-2011', '90/11/2011');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.dateString(['11/11/2011', '90/11/2011']);
=> false
```
is.usZipCode(value:any)
-----------------------
####Checks if the given value matches US zip code regexp.
interfaces: not, all, any
```javascript
is.usZipCode('02201-1020');
=> true
is.usZipCode('123');
=> false
is.not.usZipCode('123');
=> true
is.all.usZipCode('02201-1020', '123');
=> false
is.any.usZipCode('02201-1020', '123');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.usZipCode(['02201-1020', '123']);
=> false
```
is.caPostalCode(value:any)
--------------------------
####Checks if the given value matches Canada postal code regexp.
interfaces: not, all, any
```javascript
is.caPostalCode('L8V3Y1');
=> true
is.caPostalCode('L8V 3Y1');
=> true
is.caPostalCode('123');
=> false
is.not.caPostalCode('123');
=> true
is.all.caPostalCode('L8V3Y1', '123');
=> false
is.any.caPostalCode('L8V3Y1', '123');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.caPostalCode(['L8V3Y1', '123']);
=> false
```
is.ukPostCode(value:any)
------------------------
####Checks if the given value matches UK post code regexp.
interfaces: not, all, any
```javascript
is.ukPostCode('B184BJ');
=> true
is.ukPostCode('123');
=> false
is.not.ukPostCode('123');
=> true
is.all.ukPostCode('B184BJ', '123');
=> false
is.any.ukPostCode('B184BJ', '123');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.ukPostCode(['B184BJ', '123']);
=> false
```
is.nanpPhone(value:any)
-----------------------
####Checks if the given value matches North American numbering plan phone regexp.
interfaces: not, all, any
```javascript
is.nanpPhone('609-555-0175');
=> true
is.nanpPhone('123');
=> false
is.not.nanpPhone('123');
=> true
is.all.nanpPhone('609-555-0175', '123');
=> false
is.any.nanpPhone('609-555-0175', '123');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.nanpPhone(['609-555-0175', '123']);
=> false
```
is.eppPhone(value:any)
----------------------
####Checks if the given value matches extensible provisioning protocol phone regexp.
interfaces: not, all, any
```javascript
is.eppPhone('+90.2322456789');
=> true
is.eppPhone('123');
=> false
is.not.eppPhone('123');
=> true
is.all.eppPhone('+90.2322456789', '123');
=> false
is.any.eppPhone('+90.2322456789', '123');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.eppPhone(['+90.2322456789', '123']);
=> false
```
is.socialSecurityNumber(value:any)
----------------------------------
####Checks if the given value matches social security number regexp.
interfaces: not, all, any
```javascript
is.socialSecurityNumber('017-90-7890');
=> true
is.socialSecurityNumber('017907890');
=> true
is.socialSecurityNumber('123');
=> false
is.not.socialSecurityNumber('123');
=> true
is.all.socialSecurityNumber('017-90-7890', '123');
=> false
is.any.socialSecurityNumber('017907890', '123');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.socialSecurityNumber(['017-90-7890', '123']);
=> false
```
is.affirmative(value:any)
-------------------------
####Checks if the given value matches affirmative regexp.
interfaces: not, all, any
```javascript
is.affirmative('yes');
=> true
is.affirmative('no');
=> false
is.not.affirmative('no');
=> true
is.all.affirmative('yes', 'no');
=> false
is.any.affirmative('yes', 'no');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.affirmative(['yes', 'y', 'true', 't', 'ok', 'okay']);
=> true
```
is.hexadecimal(value:any)
-------------------------
####Checks if the given value matches hexadecimal regexp.
interfaces: not, all, any
```javascript
is.hexadecimal('f0f0f0');
=> true
is.hexadecimal('0xf0f0f0');
=> true
is.hexadecimal(2.5);
=> false
is.not.hexadecimal('string');
=> true
is.all.hexadecimal('ff', 'f50');
=> true
is.any.hexadecimal('0xff5500', true);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.hexadecimal(['fff', '333', 'f50']);
=> true
```
is.hexColor(value:any)
-------------------------
####Checks if the given value matches hexcolor regexp.
interfaces: not, all, any
```javascript
is.hexColor('#333');
=> true
is.hexColor('#3333');
=> false
is.not.hexColor(0.5);
=> true
is.all.hexColor('fff', 'f50');
=> true
is.any.hexColor('ff5500', 0.5);
=> false
// 'all' and 'any' interfaces can also take array parameter
is.all.hexColor(['fff', '333', 'f50']);
=> true
```
is.ip(value:any)
-------------------------
####Checks if the given value matches ip regexp
interfaces: not, all, any
```javascript
is.ip('198.156.23.5');
=> true
is.ip('1.2..5');
=> false
is.not.ip('8:::::::7');
=> true
is.all.ip('0:1::4:ff5:54:987:C', '123.123.123.123');
=> true
is.any.ip('123.8.4.3', '0.0.0.0');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.ip(['123.123.23.12', 'A:B:C:D:E:F:0:0']);
=> true
```
is.ipv4(value:any)
-------------------------
####Checks if the given value matches ipv4 regexp
interfaces: not, all, any
```javascript
is.ipv4('198.12.3.142');
=> true
is.ipv4('1.2..5');
=> false
is.not.ipv4('8:::::::7');
=> true
is.all.ipv4('198.12.3.142', '123.123.123.123');
=> true
is.any.ipv4('255.255.255.255', '850..1.4');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.ipv4(['198.12.3.142', '1.2.3']);
=> false
```
is.ipv6(value:any)
-------------------------
####Checks if the given value matches ipv6 regexp
interfaces: not, all, any
```javascript
is.ipv6('2001:DB8:0:0:1::1');
=> true
is.ipv6('985.12.3.4');
=> true
is.not.ipv6('8:::::::7');
=> true
is.all.ipv6('2001:DB8:0:0:1::1', '1:50:198:2::1:2:8');
=> true
is.any.ipv6('255.255.255.255', '2001:DB8:0:0:1::1');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.ipv6(['2001:DB8:0:0:1::1', '1.2.3']);
=> false
```
String checks
=============
is.include(value:string, target:string)
-----------------------------------------
####Checks if the given string contains a substring.
interface: not
```javascript
is.include('Some text goes here', 'text');
=> true
is.include('test', 'text');
=> false
is.not.include('test', 'text');
=> true
```
is.upperCase(value:string)
--------------------------
####Checks if the given string is UPPERCASE.
interfaces: not, all, any
```javascript
is.upperCase('YEAP');
=> true
is.upperCase('nope');
=> false
is.not.upperCase('Nope');
=> true
is.all.upperCase('YEAP', 'nope');
=> false
is.any.upperCase('YEAP', 'nope');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.upperCase(['YEAP', 'ALL UPPERCASE']);
=> true
```
is.lowerCase(value:string)
--------------------------
####Checks if the given string is lowercase.
interfaces: not, all, any
```javascript
is.lowerCase('yeap');
=> true
is.lowerCase('NOPE');
=> false
is.not.lowerCase('Nope');
=> true
is.all.lowerCase('yeap', 'NOPE');
=> false
is.any.lowerCase('yeap', 'NOPE');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.lowerCase(['yeap', 'all lowercase']);
=> true
```
is.startWith(value:string, target:string)
-------------------------------------------
####Checks if the given string starts with substring.
interface: not
```javascript
is.startWith('yeap', 'ye');
=> true
is.startWith('nope', 'ye');
=> false
is.not.startWith('nope not that', 'not');
=> true
```
is.endWith(value:string, target:string)
-----------------------------------------
####Checks if the given string ends with substring.
interfaces: not
```javascript
is.endWith('yeap', 'ap');
=> true
is.endWith('nope', 'no');
=> false
is.not.endWith('nope not that', 'not');
=> true
is.endWith('yeap that one', 'one');
=> true
```
is.capitalized(value:string)
---------------------------------------------
####Checks if the given string is capitalized.
interfaces: not, all, any
```javascript
is.capitalized('Yeap');
=> true
is.capitalized('nope');
=> false
is.not.capitalized('nope not capitalized');
=> true
is.not.capitalized('nope Capitalized');
=> true
is.all.capitalized('Yeap', 'All', 'Capitalized');
=> true
is.any.capitalized('Yeap', 'some', 'Capitalized');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.capitalized(['Nope', 'not']);
=> false
```
is.palindrome(value:string)
---------------------------------------------
####Checks if the given string is palindrome.
interfaces: not, all, any
```javascript
is.palindrome('testset');
=> true
is.palindrome('A man, a plan, a canal - Panama!');
=> true
is.palindrome('nope');
=> false
is.not.palindrome('nope not palindrome');
=> true
is.not.palindrome('tt');
=> false
is.all.palindrome('testset', 'tt');
=> true
is.any.palindrome('Yeap', 'some', 'testset');
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.palindrome(['Nope', 'testset']);
=> false
```
Arithmetic checks
=================
is.equal(value:any, other:any)
------------------------------
####Checks if the given values are equal.
interfaces: not
```javascript
is.equal(42, 40 + 2);
=> true
is.equal('yeap', 'yeap');
=> true
is.equal(true, true);
=> true
is.not.equal('yeap', 'nope');
=> true
```
is.even(value:number)
---------------------
####Checks if the given value is even.
interfaces: not, all, any
```javascript
is.even(42);
=> true
is.not.even(41);
=> true
is.all.even(40, 42, 44);
=> true
is.any.even(39, 42, 43);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.even([40, 42, 43]);
=> false
```
is.odd(value:number)
--------------------
####Checks if the given value is odd.
interfaces: not, all, any
```javascript
is.odd(41);
=> true
is.not.odd(42);
=> true
is.all.odd(39, 41, 43);
=> true
is.any.odd(39, 42, 44);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.odd([40, 42, 43]);
=> false
```
is.positive(value:number)
-------------------------
####Checks if the given value is positive.
interfaces: not, all, any
```javascript
is.positive(41);
=> true
is.not.positive(-42);
=> true
is.all.positive(39, 41, 43);
=> true
is.any.positive(-39, 42, -44);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.positive([40, 42, -43]);
=> false
```
is.negative(value:number)
-------------------------
####Checks if the given value is negative.
interfaces: not, all, any
```javascript
is.negative(-41);
=> true
is.not.negative(42);
=> true
is.all.negative(-39, -41, -43);
=> true
is.any.negative(-39, 42, 44);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.negative([40, 42, -43]);
=> false
```
is.above(value:number, min:number)
---------------------------
####Checks if the given value is above minimum value.
interface: not
```javascript
is.above(41, 30);
=> true
is.not.above(42, 50);
=> true
```
is.under(value:number, max:number)
---------------------------
####Checks if the given value is under maximum value.
interface: not
```javascript
is.under(30, 35);
=> true
is.not.under(42, 30);
=> true
```
is.within(value:number, min:number, max:number)
---------------------------------
####Checks if the given value is within minimum and maximum values.
interface: not
```javascript
is.within(30, 20, 40);
=> true
is.not.within(40, 30, 35);
=> true
```
is.decimal(value:number)
------------------------
####Checks if the given value is decimal.
interfaces: not, all, any
```javascript
is.decimal(41.5);
=> true
is.not.decimal(42);
=> true
is.all.decimal(39.5, 41.5, -43.5);
=> true
is.any.decimal(-39, 42.5, 44);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.decimal([40, 42.5, -43]);
=> false
```
is.integer(value:number)
------------------------
####Checks if the given value is integer.
interfaces: not, all, any
```javascript
is.integer(41);
=> true
is.not.integer(42.5);
=> true
is.all.integer(39, 41, -43);
=> true
is.any.integer(-39, 42.5, 44);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.integer([40, 42.5, -43]);
=> false
```
is.finite(value:number)
-----------------------
####Checks if the given value is finite.
interfaces: not, all, any
```javascript
is.finite(41);
=> true
is.not.finite(42 / 0);
=> true
is.all.finite(39, 41, -43);
=> true
is.any.finite(-39, Infinity, 44);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.finite([Infinity, -Infinity, 42.5]);
=> false
```
is.infinite(value:number)
-------------------------
####Checks if the given value is infinite.
interfaces: not, all, any
```javascript
is.infinite(Infinity);
=> true
is.not.infinite(42);
=> true
is.all.infinite(Infinity, -Infinity, -43 / 0);
=> true
is.any.infinite(-39, Infinity, 44);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.infinite([Infinity, -Infinity, 42.5]);
=> false
```
Object checks
=============
is.propertyCount(value:object, count:number)
-------------------------------------
####Checks if objects' property count is equal to given count.
interface: not
```javascript
is.propertyCount({this: 'is', 'sample': object}, 2);
=> true
is.propertyCount({this: 'is', 'sample': object}, 3);
=> false
is.not.propertyCount({}, 2);
=> true
```
is.propertyDefined(value:object, property:string)
------------------------------------------
####Checks if the given property is defined on object.
interface: not
```javascript
is.propertyDefined({yeap: 'yeap'}, 'yeap');
=> true
is.propertyDefined({yeap: 'yeap'}, 'nope');
=> false
is.not.propertyDefined({}, 'nope');
=> true
```
Array checks
============
is.inArray(value:any, array)
---------------------
####Checks if the given item is in array?
interface: not
```javascript
is.inArray(2, [1, 2, 3]);
=> true
is.inArray(4, [1, 2, 3]);
=> false
is.not.inArray(4, [1, 2, 3]);
=> true
```
is.sorted(value:array, sign:string)
----------------------
####Checks if the given array is sorted. Sign is optional parameter.
interfaces: not, all, any
```javascript
is.sorted([1, 2, 3]);
=> true
is.sorted([1, 2, 4, 3]);
=> false
is.sorted([1, 1, 2, 2], '>=');
=> true
is.sorted([1, 2, 3, 4], '>');
=> true
is.sorted([4, 3, 3, 1], '<=');
=> true
is.sorted([4, 3, 2, 1], '<');
=> true
is.sorted([1, 2, 3, 3], '>');
=> false
is.not.sorted([5, 4, 3]);
=> true
is.not.sorted([5, 4, 3], '<');
=> false
is.all.sorted([1, 2], [3, 4]);
=> true
is.any.sorted([1, 2], [5, 4]);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.sorted([[1, 2], [5, 4]]);
=> false
```
Environment checks
==================
####Environment checks are not available as node module.
is.ie(range:number|string)
-------------------
####Checks if current browser is ie. Parameter is optional version range (or number) of browser.
interface: not
```javascript
is.ie();
=> true if current browser is ie
is.not.ie();
=> false if current browser is ie
// also supports version number
is.ie(10);
=> true if current version of ie is 10
is.ie('>=10');
=> true if current version of ie is greater than or equal to 10
is.not.ie('<9');
=> true if current version of ie is not less than 9
```
is.chrome(range:number|string)
-----------
####Checks if current browser is chrome. Parameter is optional version range (or number) of browser.
interface: not
```javascript
is.chrome();
=> true if current browser is chrome
is.not.chrome();
=> false if current browser is chrome
// also supports version number
is.chrome(50);
=> true if current version of chrome is 50
is.chrome('>=40');
=> true if current version of chrome is greater than or equal to 40
is.not.chrome('<30');
=> true if current version of chrome is not less than 30
```
is.firefox(range:number|string)
------------
####Checks if current browser is firefox. Parameter is optional version range (or number) of browser.
interface: not
```javascript
is.firefox();
=> true if current browser is firefox
is.not.firefox();
=> false if current browser is firefox
// also supports version number
is.firefox(41);
=> true if current version of firefox is 41
is.firefox('>=40');
=> true if current version of firefox is greater than or equal to 40
is.not.firefox('<30');
=> true if current version of firefox is not less than 30
```
is.edge(range:number|string)
------------
####Checks if current browser is edge. Parameter is optional version range (or number) of browser.
interface: not
```javascript
is.edge();
=> true if current browser is edge
is.not.edge();
=> false if current browser is edge
// also supports version number
is.edge(13);
=> true if current version of edge is 13
is.edge('>=12');
=> true if current version of edge is greater than or equal to 12
is.not.edge('<13');
=> true if current version of edge is not less than 13
```
is.opera(range:number|string)
----------
####Checks if current browser is opera. Parameter is optional version range (or number) of browser.
interface: not
```javascript
is.opera();
=> true if current browser is opera
is.not.opera();
=> false if current browser is opera
// also supports version number
is.opera(36);
=> true if current version of opera is 36
is.opera('>=35');
=> true if current version of opera is greater than or equal to 35
is.not.opera('<20');
=> true if current version of opera is not less than 20
```
is.safari(range:number|string)
-----------
####Checks if current browser is safari. Parameter is optional version range (or number) of browser.
interface: not
```javascript
is.safari();
=> true if current browser is safari
is.not.safari();
=> false if current browser is safari
// also supports version number
is.safari(9);
=> true if current version of safari is 9
is.safari('>=8');
=> true if current version of safari is greater than or equal to 8
is.not.safari('<7');
=> true if current version of safari is not less than 7
```
is.phantom(range:number|string)
-----------
####Checks if current browser is phantomjs. Parameter is optional version range (or number) of browser.
interface: not
```javascript
is.phantom();
=> true if current browser is phantomjs
is.not.phantom();
=> false if current browser is phantomjs
// also supports version number
is.phantom(2);
=> true if current version of phantom is 2
is.phantom('>=1');
=> true if current version of phantomjs is greater than or equal to 1
is.not.phantom('<2');
=> true if current version of phantomjs is not less than 2
```
is.ios()
--------
####Checks if current device has ios.
interface: not
```javascript
is.ios();
=> true if current device is iPhone, iPad or iPod
is.not.ios();
=> true if current device is not iPhone, iPad or iPod
```
is.iphone(range:number|string)
-----------
####Checks if current device is iPhone. Parameter is optional version range (or number) of browser.
interface: not
```javascript
is.iphone();
=> true if current device is iPhone
is.not.iphone();
=> true if current device is not iPhone
// also supports version number
is.iphone(9);
=> true if current version of iPhone is 9
is.iphone('>=7');
=> true if current version of iPhone is greater than or equal to 7
is.not.iphone('<8');
=> true if current version of iPhone is not less than 8
```
is.ipad(range:number|string)
---------
####Checks if current device is iPad.
interface: not
```javascript
is.ipad();
=> true if current device is iPad
is.not.ipad();
=> true if current device is not iPad
// also supports version number
is.ipad(9);
=> true if current version of iPad is 9
is.ipad('>=7');
=> true if current version of iPad is greater than or equal to 7
is.not.ipad('<8');
=> true if current version of iPad is not less than 8
```
is.ipod(range:number|string)
---------
####Checks if current device is iPod.
interface: not
```javascript
is.ipod();
=> true if current device is iPod
is.not.ipod();
=> true if current device is not iPod
// also supports version number
is.ipod(7);
=> true if current version of iPod is 7
is.ipod('>=5');
=> true if current version of iPod is greater than or equal to 5
is.not.ipod('<5');
=> true if current version of iPod is not less than 5
```
is.android()
------------
####Checks if current device has Android.
interface: not
```javascript
is.android();
=> true if current device has Android OS
is.not.android();
=> true if current device has not Android OS
```
is.androidPhone()
-----------------
####Checks if current device is Android phone.
interface: not
```javascript
is.androidPhone();
=> true if current device is Android phone
is.not.androidPhone();
=> true if current device is not Android phone
```
is.androidTablet()
------------------
####Checks if current device is Android tablet.
interface: not
```javascript
is.androidTablet();
=> true if current device is Android tablet
is.not.androidTablet();
=> true if current device is not Android tablet
```
is.blackberry()
---------------
####Checks if current device is Blackberry.
interface: not
```javascript
is.blackberry();
=> true if current device is Blackberry
is.not.blackberry();
=> true if current device is not Blackberry
```
is.windowsPhone()
-----------------
####Checks if current device is Windows phone.
interface: not
```javascript
is.windowsPhone();
=> true if current device is Windows phone
is.not.windowsPhone();
=> true if current device is not Windows Phone
```
is.windowsTablet()
------------------
####Checks if current device is Windows tablet.
interface: not
```javascript
is.windowsTablet();
=> true if current device is Windows tablet
is.not.windowsTablet();
=> true if current device is not Windows tablet
```
is.windows()
------------
####Checks if current OS is Windows.
interface: not
```javascript
is.windows();
=> true if current OS is Windows
is.not.windows();
=> true if current OS is not Windows
```
is.mac()
--------
####Checks if current OS is Mac OS X.
interface: not
```javascript
is.mac();
=> true if current OS is Mac OS X
is.not.mac();
=> true if current OS is not Mac OS X
```
is.linux()
----------
####Checks if current OS is linux.
interface: not
```javascript
is.linux();
=> true if current OS is linux
is.not.linux();
=> true if current OS is not linux
```
is.desktop()
------------
####Checks if current device is desktop.
interface: not
```javascript
is.desktop();
=> true if current device is desktop
is.not.desktop();
=> true if current device is not desktop
```
is.mobile()
-----------
####Checks if current device is mobile.
interface: not
iPhone, iPod, Android Phone, Windows Phone, Blackberry.
```javascript
is.mobile();
=> true if current device is mobile
is.not.mobile();
=> true if current device is not mobile
```
is.tablet()
-----------
####Checks if current device is tablet.
interface: not
iPad, Android Tablet, Windows Tablet
```javascript
is.tablet();
=> true if current device is tablet
is.not.tablet();
=> true if current device is not tablet
```
is.online()
-----------
####Checks if current device is online.
interface: not
```javascript
is.online();
=> true if current device is online
is.not.online();
=> true if current device is not online
```
is.offline()
------------
####Checks if current device is offline.
interface: not
```javascript
is.offline();
=> true if current device is offline
is.not.offline();
=> true if current device is not offline
```
is.touchDevice()
------------
####Checks if current device supports touch.
interface: not
```javascript
is.touchDevice();
=> true if current device supports touch
is.not.touchDevice();
=> true if current device does not support touch
```
Time checks
===========
is.today(value:date)
----------------------
####Checks if the given date object indicate today.
interfaces: not, all, any
```javascript
var today = new Date();
is.today(today);
=> true
var yesterday = new Date(new Date().setDate(new Date().getDate() - 1));
is.today(yesterday);
=> false
is.not.today(yesterday);
=> true
is.all.today(today, today);
=> true
is.any.today(today, yesterday);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.today([today, yesterday]);
=> false
```
is.yesterday(value:date)
--------------------------
####Checks if the given date object indicate yesterday.
interfaces: not, all, any
```javascript
var today = new Date();
is.yesterday(today);
=> false
var yesterday = new Date(new Date().setDate(new Date().getDate() - 1));
is.yesterday(yesterday);
=> true
is.not.yesterday(today);
=> true
is.all.yesterday(yesterday, today);
=> false
is.any.yesterday(today, yesterday);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.yesterday([today, yesterday]);
=> false
```
is.tomorrow(value:date)
-------------------------
####Checks if the given date object indicate tomorrow.
interfaces: not, all, any
```javascript
var today = new Date();
is.tomorrow(today);
=> false
var tomorrow = new Date(new Date().setDate(new Date().getDate() + 1));
is.tomorrow(tomorrow);
=> true
is.not.tomorrow(today);
=> true
is.all.tomorrow(tomorrow, today);
=> false
is.any.tomorrow(today, tomorrow);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.tomorrow([today, tomorrow]);
=> false
```
is.past(value:date)
---------------------
####Checks if the given date object indicate past.
interfaces: not, all, any
```javascript
var yesterday = new Date(new Date().setDate(new Date().getDate() - 1));
var tomorrow = new Date(new Date().setDate(new Date().getDate() + 1));
is.past(yesterday);
=> true
is.past(tomorrow);
=> false
is.not.past(tomorrow);
=> true
is.all.past(tomorrow, yesterday);
=> false
is.any.past(yesterday, tomorrow);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.past([yesterday, tomorrow]);
=> false
```
is.future(value:date)
-----------------------
####Checks if the given date object indicate future.
interfaces: not, all, any
```javascript
var yesterday = new Date(new Date().setDate(new Date().getDate() - 1));
var tomorrow = new Date(new Date().setDate(new Date().getDate() + 1));
is.future(yesterday);
=> false
is.future(tomorrow);
=> true
is.not.future(yesterday);
=> true
is.all.future(tomorrow, yesterday);
=> false
is.any.future(yesterday, tomorrow);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.future([yesterday, tomorrow]);
=> false
```
is.day(value:date, day:string)
-------------------------------
####Checks if the given date objects' day equal given dayString parameter.
interface: not
```javascript
var mondayObj = new Date('01/26/2015');
var tuesdayObj = new Date('01/27/2015');
is.day(mondayObj, 'monday');
=> true
is.day(mondayObj, 'tuesday');
=> false
is.not.day(mondayObj, 'tuesday');
=> true
```
is.month(value:date, month:string)
-----------------------------------
####Checks if the given date objects' month equal given monthString parameter.
interface: not
```javascript
var januaryObj = new Date('01/26/2015');
var februaryObj = new Date('02/26/2015');
is.month(januaryObj, 'january');
=> true
is.month(februaryObj, 'january');
=> false
is.not.month(februaryObj, 'january');
=> true
```
is.year(value:date, year:number)
---------------------------------
####Checks if the given date objects' year equal given yearNumber parameter.
interface: not
```javascript
var year2015 = new Date('01/26/2015');
var year2016 = new Date('01/26/2016');
is.year(year2015, 2015);
=> true
is.year(year2016, 2015);
=> false
is.not.year(year2016, 2015);
=> true
```
is.leapYear(value:number)
---------------------------------
####Checks if the given year number is a leap year
interfaces: not, all, any
```javascript
is.leapYear(2016);
=> true
is.leapYear(2015);
=> false
is.not.leapYear(2015);
=> true
is.all.leapYear(2015, 2016);
=> false
is.any.leapYear(2015, 2016);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.leapYear([2016, 2080]);
=> true
```
is.weekend(value:date)
------------------------
####Checks if the given date objects' day is weekend.
interfaces: not, all, any
```javascript
var monday = new Date('01/26/2015');
var sunday = new Date('01/25/2015');
var saturday = new Date('01/24/2015');
is.weekend(sunday);
=> true
is.weekend(monday);
=> false
is.not.weekend(monday);
=> true
is.all.weekend(sunday, saturday);
=> true
is.any.weekend(sunday, saturday, monday);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.weekend([sunday, saturday, monday]);
=> false
```
is.weekday(value:date)
------------------------
####Checks if the given date objects' day is weekday.
interfaces: not, all, any
```javascript
var monday = new Date('01/26/2015');
var sunday = new Date('01/25/2015');
var saturday = new Date('01/24/2015');
is.weekday(monday);
=> true
is.weekday(sunday);
=> false
is.not.weekday(sunday);
=> true
is.all.weekday(monday, saturday);
=> false
is.any.weekday(sunday, saturday, monday);
=> true
// 'all' and 'any' interfaces can also take array parameter
is.all.weekday([sunday, saturday, monday]);
=> false
```
is.inDateRange(value:date, start:date, end:date)
----------------------------------------------------
####Checks if date is within given range.
interface: not
```javascript
var saturday = new Date('01/24/2015');
var sunday = new Date('01/25/2015');
var monday = new Date('01/26/2015');
is.inDateRange(sunday, saturday, monday);
=> true
is.inDateRange(saturday, sunday, monday);
=> false
is.not.inDateRange(saturday, sunday, monday);
=> true
```
is.inLastWeek(value:date)
---------------------------
####Checks if the given date is between now and 7 days ago.
interface: not
```javascript
var twoDaysAgo = new Date(new Date().setDate(new Date().getDate() - 2));
var nineDaysAgo = new Date(new Date().setDate(new Date().getDate() - 9));
is.inLastWeek(twoDaysAgo);
=> true
is.inLastWeek(nineDaysAgo);
=> false
is.not.inLastWeek(nineDaysAgo);
=> true
```
is.inLastMonth(value:date)
----------------------------
####Checks if the given date is between now and a month ago.
interface: not
```javascript
var tenDaysAgo = new Date(new Date().setDate(new Date().getDate() - 10));
var fortyDaysAgo = new Date(new Date().setDate(new Date().getDate() - 40));
is.inLastMonth(tenDaysAgo);
=> true
is.inLastMonth(fortyDaysAgo);
=> false
is.not.inLastMonth(fortyDaysAgo);
=> true
```
is.inLastYear(value:date)
---------------------------
####Checks if the given date is between now and a year ago.
interface: not
```javascript
var twoMonthsAgo = new Date(new Date().setMonth(new Date().getMonth() - 2));
var thirteenMonthsAgo = new Date(new Date().setMonth(new Date().getMonth() - 13));
is.inLastYear(twoMonthsAgo);
=> true
is.inLastYear(thirteenMonthsAgo);
=> false
is.not.inLastYear(thirteenMonthsAgo);
=> true
```
is.inNextWeek(value:date)
---------------------------
####Checks if the given date is between now and 7 days later.
interface: not
```javascript
var twoDaysLater = new Date(new Date().setDate(new Date().getDate() + 2));
var nineDaysLater = new Date(new Date().setDate(new Date().getDate() + 9));
is.inNextWeek(twoDaysLater);
=> true
is.inNextWeek(nineDaysLater);
=> false
is.not.inNextWeek(nineDaysLater);
=> true
```
is.inNextMonth(value:date)
----------------------------
####Checks if the given date is between now and a month later.
interface: not
```javascript
var tenDaysLater = new Date(new Date().setDate(new Date().getDate() + 10));
var fortyDaysLater = new Date(new Date().setDate(new Date().getDate() + 40));
is.inNextMonth(tenDaysLater);
=> true
is.inNextMonth(fortyDaysLater);
=> false
is.not.inNextMonth(fortyDaysLater);
=> true
```
is.inNextYear(value:date)
---------------------------
####Checks if the given date is between now and a year later.
interface: not
```javascript
var twoMonthsLater = new Date(new Date().setMonth(new Date().getMonth() + 2));
var thirteenMonthsLater = new Date(new Date().setMonth(new Date().getMonth() + 13));
is.inNextYear(twoMonthsLater);
=> true
is.inNextYear(thirteenMonthsLater);
=> false
is.not.inNextYear(thirteenMonthsLater);
=> true
```
is.quarterOfYear(value:date, quarter:number)
---------------------------------------------
####Checks if the given date is in the parameter quarter.
interface: not
```javascript
var firstQuarter = new Date('01/26/2015');
var secondQuarter = new Date('05/26/2015');
is.quarterOfYear(firstQuarter, 1);
=> true
is.quarterOfYear(secondQuarter, 1);
=> false
is.not.quarterOfYear(secondQuarter, 1);
=> true
```
is.dayLightSavingTime(value:date)
--------------------------------------------------
####Checks if the given date is in daylight saving time.
interface: not
```javascript
// For Turkey Time Zone
var january1 = new Date('01/01/2015');
var june1 = new Date('06/01/2015');
is.dayLightSavingTime(june1);
=> true
is.dayLightSavingTime(january1);
=> false
is.not.dayLightSavingTime(january1);
=> true
```
Configuration methods
=====================
is.setNamespace()
-----------------
Change namespace of library to prevent name collisions.
```javascript
var customName = is.setNamespace();
customName.odd(3);
=> true
```
is.setRegexp(value:regexp, name:string)
----------------------------------------
Override RegExps if you think they suck.
```javascript
is.url('https://www.duckduckgo.com');
=> true
is.setRegexp(/quack/, 'url');
is.url('quack');
=> true
```
/*!
* is.js 0.8.0
* Author: Aras Atasaygin
*/
// AMD with global, Node, or global
;(function(root, factory) { // eslint-disable-line no-extra-semi
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(function() {
// Also create a global in case some scripts
// that are loaded still are looking for
// a global even when an AMD loader is in use.
return (root.is = factory());
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is self)
root.is = factory();
}
}(this, function() {
// Baseline
/* -------------------------------------------------------------------------- */
// define 'is' object and current version
var is = {};
is.VERSION = '0.8.0';
// define interfaces
is.not = {};
is.all = {};
is.any = {};
// cache some methods to call later on
var toString = Object.prototype.toString;
var slice = Array.prototype.slice;
var hasOwnProperty = Object.prototype.hasOwnProperty;
// helper function which reverses the sense of predicate result
function not(func) {
return function() {
return !func.apply(null, slice.call(arguments));
};
}
// helper function which call predicate function per parameter and return true if all pass
function all(func) {
return function() {
var params = getParams(arguments);
var length = params.length;
for (var i = 0; i < length; i++) {
if (!func.call(null, params[i])) {
return false;
}
}
return true;
};
}
// helper function which call predicate function per parameter and return true if any pass
function any(func) {
return function() {
var params = getParams(arguments);
var length = params.length;
for (var i = 0; i < length; i++) {
if (func.call(null, params[i])) {
return true;
}
}
return false;
};
}
// build a 'comparator' object for various comparison checks
var comparator = {
'<': function(a, b) { return a < b; },
'<=': function(a, b) { return a <= b; },
'>': function(a, b) { return a > b; },
'>=': function(a, b) { return a >= b; }
}
// helper function which compares a version to a range
function compareVersion(version, range) {
var string = (range + '');
var n = +(string.match(/\d+/) || NaN);
var op = string.match(/^[<>]=?|/)[0];
return comparator[op] ? comparator[op](version, n) : (version == n || n !== n);
}
// helper function which extracts params from arguments
function getParams(args) {
var params = slice.call(args);
var length = params.length;
if (length === 1 && is.array(params[0])) { // support array
params = params[0];
}
return params;
}
// Type checks
/* -------------------------------------------------------------------------- */
// is a given value Arguments?
is.arguments = function(value) { // fallback check is for IE
return toString.call(value) === '[object Arguments]' ||
(value != null && typeof value === 'object' && 'callee' in value);
};
// is a given value Array?
is.array = Array.isArray || function(value) { // check native isArray first
return toString.call(value) === '[object Array]';
};
// is a given value Boolean?
is.boolean = function(value) {
return value === true || value === false || toString.call(value) === '[object Boolean]';
};
// is a given value Char?
is.char = function(value) {
return is.string(value) && value.length === 1;
};
// is a given value Date Object?
is.date = function(value) {
return toString.call(value) === '[object Date]';
};
// is a given object a DOM node?
is.domNode = function(object) {
return is.object(object) && object.nodeType > 0;
};
// is a given value Error object?
is.error = function(value) {
return toString.call(value) === '[object Error]';
};
// is a given value function?
is['function'] = function(value) { // fallback check is for IE
return toString.call(value) === '[object Function]' || typeof value === 'function';
};
// is given value a pure JSON object?
is.json = function(value) {
return toString.call(value) === '[object Object]';
};
// is a given value NaN?
is.nan = function(value) { // NaN is number :) Also it is the only value which does not equal itself
return value !== value;
};
// is a given value null?
is['null'] = function(value) {
return value === null;
};
// is a given value number?
is.number = function(value) {
return is.not.nan(value) && toString.call(value) === '[object Number]';
};
// is a given value object?
is.object = function(value) {
return Object(value) === value;
};
// is a given value RegExp?
is.regexp = function(value) {
return toString.call(value) === '[object RegExp]';
};
// are given values same type?
// prevent NaN, Number same type check
is.sameType = function(value, other) {
var tag = toString.call(value);
if (tag !== toString.call(other)) {
return false;
}
if (tag === '[object Number]') {
return !is.any.nan(value, other) || is.all.nan(value, other);
}
return true;
};
// sameType method does not support 'all' and 'any' interfaces
is.sameType.api = ['not'];
// is a given value String?
is.string = function(value) {
return toString.call(value) === '[object String]';
};
// is a given value undefined?
is.undefined = function(value) {
return value === void 0;
};
// is a given value window?
// setInterval method is only available for window object
is.windowObject = function(value) {
return value != null && typeof value === 'object' && 'setInterval' in value;
};
// Presence checks
/* -------------------------------------------------------------------------- */
//is a given value empty? Objects, arrays, strings
is.empty = function(value) {
if (is.object(value)) {
var length = Object.getOwnPropertyNames(value).length;
if (length === 0 || (length === 1 && is.array(value)) ||
(length === 2 && is.arguments(value))) {
return true;
}
return false;
}
return value === '';
};
// is a given value existy?
is.existy = function(value) {
return value != null;
};
// is a given value falsy?
is.falsy = function(value) {
return !value;
};
// is a given value truthy?
is.truthy = not(is.falsy);
// Arithmetic checks
/* -------------------------------------------------------------------------- */
// is a given number above minimum parameter?
is.above = function(n, min) {
return is.all.number(n, min) && n > min;
};
// above method does not support 'all' and 'any' interfaces
is.above.api = ['not'];
// is a given number decimal?
is.decimal = function(n) {
return is.number(n) && n % 1 !== 0;
};
// are given values equal? supports numbers, strings, regexes, booleans
// TODO: Add object and array support
is.equal = function(value, other) {
// check 0 and -0 equity with Infinity and -Infinity
if (is.all.number(value, other)) {
return value === other && 1 / value === 1 / other;
}
// check regexes as strings too
if (is.all.string(value, other) || is.all.regexp(value, other)) {
return '' + value === '' + other;
}
if (is.all.boolean(value, other)) {
return value === other;
}
return false;
};
// equal method does not support 'all' and 'any' interfaces
is.equal.api = ['not'];
// is a given number even?
is.even = function(n) {
return is.number(n) && n % 2 === 0;
};
// is a given number finite?
is.finite = isFinite || function(n) {
return is.not.infinite(n) && is.not.nan(n);
};
// is a given number infinite?
is.infinite = function(n) {
return n === Infinity || n === -Infinity;
};
// is a given number integer?
is.integer = function(n) {
return is.number(n) && n % 1 === 0;
};
// is a given number negative?
is.negative = function(n) {
return is.number(n) && n < 0;
};
// is a given number odd?
is.odd = function(n) {
return is.number(n) && n % 2 === 1;
};
// is a given number positive?
is.positive = function(n) {
return is.number(n) && n > 0;
};
// is a given number above maximum parameter?
is.under = function(n, max) {
return is.all.number(n, max) && n < max;
};
// least method does not support 'all' and 'any' interfaces
is.under.api = ['not'];
// is a given number within minimum and maximum parameters?
is.within = function(n, min, max) {
return is.all.number(n, min, max) && n > min && n < max;
};
// within method does not support 'all' and 'any' interfaces
is.within.api = ['not'];
// Regexp checks
/* -------------------------------------------------------------------------- */
// Steven Levithan, Jan Goyvaerts: Regular Expressions Cookbook
// Scott Gonzalez: Email address validation
// dateString match m/d/yy and mm/dd/yyyy, allowing any combination of one or two digits for the day and month, and two or four digits for the year
// eppPhone match extensible provisioning protocol format
// nanpPhone match north american number plan format
// time match hours, minutes, and seconds, 24-hour clock
var regexes = {
affirmative: /^(?:1|t(?:rue)?|y(?:es)?|ok(?:ay)?)$/,
alphaNumeric: /^[A-Za-z0-9]+$/,
caPostalCode: /^(?!.*[DFIOQU])[A-VXY][0-9][A-Z]\s?[0-9][A-Z][0-9]$/,
creditCard: /^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/,
dateString: /^(1[0-2]|0?[1-9])([\/-])(3[01]|[12][0-9]|0?[1-9])(?:\2)(?:[0-9]{2})?[0-9]{2}$/,
email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i, // eslint-disable-line no-control-regex
eppPhone: /^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/,
hexadecimal: /^(?:0x)?[0-9a-fA-F]+$/,
hexColor: /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/,
ipv4: /^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/,
ipv6: /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i,
nanpPhone: /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/,
socialSecurityNumber: /^(?!000|666)[0-8][0-9]{2}-?(?!00)[0-9]{2}-?(?!0000)[0-9]{4}$/,
timeString: /^(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])$/,
ukPostCode: /^[A-Z]{1,2}[0-9RCHNQ][0-9A-Z]?\s?[0-9][ABD-HJLNP-UW-Z]{2}$|^[A-Z]{2}-?[0-9]{4}$/,
url: /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/i,
usZipCode: /^[0-9]{5}(?:-[0-9]{4})?$/
};
function regexpCheck(regexp, regexes) {
is[regexp] = function(value) {
return regexes[regexp].test(value);
};
}
// create regexp checks methods from 'regexes' object
for (var regexp in regexes) {
if (regexes.hasOwnProperty(regexp)) {
regexpCheck(regexp, regexes);
}
}
// simplify IP checks by calling the regex helpers for IPv4 and IPv6
is.ip = function(value) {
return is.ipv4(value) || is.ipv6(value);
};
// String checks
/* -------------------------------------------------------------------------- */
// is a given string or sentence capitalized?
is.capitalized = function(string) {
if (is.not.string(string)) {
return false;
}
var words = string.split(' ');
for (var i = 0; i < words.length; i++) {
var word = words[i];
if (word.length) {
var chr = word.charAt(0);
if (chr !== chr.toUpperCase()) {
return false;
}
}
}
return true;
};
// is string end with a given target parameter?
is.endWith = function(string, target) {
if (is.not.string(string)) {
return false;
}
target += '';
var position = string.length - target.length;
return position >= 0 && string.indexOf(target, position) === position;
};
// endWith method does not support 'all' and 'any' interfaces
is.endWith.api = ['not'];
// is a given string include parameter target?
is.include = function(string, target) {
return string.indexOf(target) > -1;
};
// include method does not support 'all' and 'any' interfaces
is.include.api = ['not'];
// is a given string all lowercase?
is.lowerCase = function(string) {
return is.string(string) && string === string.toLowerCase();
};
// is a given string palindrome?
is.palindrome = function(string) {
if (is.not.string(string)) {
return false;
}
string = string.replace(/[^a-zA-Z0-9]+/g, '').toLowerCase();
var length = string.length - 1;
for (var i = 0, half = Math.floor(length / 2); i <= half; i++) {
if (string.charAt(i) !== string.charAt(length - i)) {
return false;
}
}
return true;
};
// is a given value space?
// horizantal tab: 9, line feed: 10, vertical tab: 11, form feed: 12, carriage return: 13, space: 32
is.space = function(value) {
if (is.not.char(value)) {
return false;
}
var charCode = value.charCodeAt(0);
return (charCode > 8 && charCode < 14) || charCode === 32;
};
// is string start with a given target parameter?
is.startWith = function(string, target) {
return is.string(string) && string.indexOf(target) === 0;
};
// startWith method does not support 'all' and 'any' interfaces
is.startWith.api = ['not'];
// is a given string all uppercase?
is.upperCase = function(string) {
return is.string(string) && string === string.toUpperCase();
};
// Time checks
/* -------------------------------------------------------------------------- */
var days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
var months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
// is a given dates day equal given day parameter?
is.day = function(date, day) {
return is.date(date) && day.toLowerCase() === days[date.getDay()];
};
// day method does not support 'all' and 'any' interfaces
is.day.api = ['not'];
// is a given date in daylight saving time?
is.dayLightSavingTime = function(date) {
var january = new Date(date.getFullYear(), 0, 1);
var july = new Date(date.getFullYear(), 6, 1);
var stdTimezoneOffset = Math.max(january.getTimezoneOffset(), july.getTimezoneOffset());
return date.getTimezoneOffset() < stdTimezoneOffset;
};
// is a given date future?
is.future = function(date) {
var now = new Date();
return is.date(date) && date.getTime() > now.getTime();
};
// is date within given range?
is.inDateRange = function(date, start, end) {
if (is.not.date(date) || is.not.date(start) || is.not.date(end)) {
return false;
}
var stamp = date.getTime();
return stamp > start.getTime() && stamp < end.getTime();
};
// inDateRange method does not support 'all' and 'any' interfaces
is.inDateRange.api = ['not'];
// is a given date in last month range?
is.inLastMonth = function(date) {
return is.inDateRange(date, new Date(new Date().setMonth(new Date().getMonth() - 1)), new Date());
};
// is a given date in last week range?
is.inLastWeek = function(date) {
return is.inDateRange(date, new Date(new Date().setDate(new Date().getDate() - 7)), new Date());
};
// is a given date in last year range?
is.inLastYear = function(date) {
return is.inDateRange(date, new Date(new Date().setFullYear(new Date().getFullYear() - 1)), new Date());
};
// is a given date in next month range?
is.inNextMonth = function(date) {
return is.inDateRange(date, new Date(), new Date(new Date().setMonth(new Date().getMonth() + 1)));
};
// is a given date in next week range?
is.inNextWeek = function(date) {
return is.inDateRange(date, new Date(), new Date(new Date().setDate(new Date().getDate() + 7)));
};
// is a given date in next year range?
is.inNextYear = function(date) {
return is.inDateRange(date, new Date(), new Date(new Date().setFullYear(new Date().getFullYear() + 1)));
};
// is the given year a leap year?
is.leapYear = function(year) {
return is.number(year) && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
};
// is a given dates month equal given month parameter?
is.month = function(date, month) {
return is.date(date) && month.toLowerCase() === months[date.getMonth()];
};
// month method does not support 'all' and 'any' interfaces
is.month.api = ['not'];
// is a given date past?
is.past = function(date) {
var now = new Date();
return is.date(date) && date.getTime() < now.getTime();
};
// is a given date in the parameter quarter?
is.quarterOfYear = function(date, quarter) {
return is.date(date) && is.number(quarter) && quarter === Math.floor((date.getMonth() + 3) / 3);
};
// quarterOfYear method does not support 'all' and 'any' interfaces
is.quarterOfYear.api = ['not'];
// is a given date indicate today?
is.today = function(date) {
var now = new Date();
var todayString = now.toDateString();
return is.date(date) && date.toDateString() === todayString;
};
// is a given date indicate tomorrow?
is.tomorrow = function(date) {
var now = new Date();
var tomorrowString = new Date(now.setDate(now.getDate() + 1)).toDateString();
return is.date(date) && date.toDateString() === tomorrowString;
};
// is a given date weekend?
// 6: Saturday, 0: Sunday
is.weekend = function(date) {
return is.date(date) && (date.getDay() === 6 || date.getDay() === 0);
};
// is a given date weekday?
is.weekday = not(is.weekend);
// is a given dates year equal given year parameter?
is.year = function(date, year) {
return is.date(date) && is.number(year) && year === date.getFullYear();
};
// year method does not support 'all' and 'any' interfaces
is.year.api = ['not'];
// is a given date indicate yesterday?
is.yesterday = function(date) {
var now = new Date();
var yesterdayString = new Date(now.setDate(now.getDate() - 1)).toDateString();
return is.date(date) && date.toDateString() === yesterdayString;
};
// Environment checks
/* -------------------------------------------------------------------------- */
var freeGlobal = is.windowObject(typeof global == 'object' && global) && global;
var freeSelf = is.windowObject(typeof self == 'object' && self) && self;
var thisGlobal = is.windowObject(typeof this == 'object' && this) && this;
var root = freeGlobal || freeSelf || thisGlobal || Function('return this')();
var document = freeSelf && freeSelf.document;
var previousIs = root.is;
// store navigator properties to use later
var navigator = freeSelf && freeSelf.navigator;
var appVersion = (navigator && navigator.appVersion || '').toLowerCase();
var userAgent = (navigator && navigator.userAgent || '').toLowerCase();
var vendor = (navigator && navigator.vendor || '').toLowerCase();
// is current device android?
is.android = function() {
return /android/.test(userAgent);
};
// android method does not support 'all' and 'any' interfaces
is.android.api = ['not'];
// is current device android phone?
is.androidPhone = function() {
return /android/.test(userAgent) && /mobile/.test(userAgent);
};
// androidPhone method does not support 'all' and 'any' interfaces
is.androidPhone.api = ['not'];
// is current device android tablet?
is.androidTablet = function() {
return /android/.test(userAgent) && !/mobile/.test(userAgent);
};
// androidTablet method does not support 'all' and 'any' interfaces
is.androidTablet.api = ['not'];
// is current device blackberry?
is.blackberry = function() {
return /blackberry/.test(userAgent) || /bb10/.test(userAgent);
};
// blackberry method does not support 'all' and 'any' interfaces
is.blackberry.api = ['not'];
// is current browser chrome?
// parameter is optional
is.chrome = function(range) {
var match = /google inc/.test(vendor) ? userAgent.match(/(?:chrome|crios)\/(\d+)/) : null;
return match !== null && compareVersion(match[1], range);
};
// chrome method does not support 'all' and 'any' interfaces
is.chrome.api = ['not'];
// is current device desktop?
is.desktop = function() {
return is.not.mobile() && is.not.tablet();
};
// desktop method does not support 'all' and 'any' interfaces
is.desktop.api = ['not'];
// is current browser edge?
// parameter is optional
is.edge = function(range) {
var match = userAgent.match(/edge\/(\d+)/);
return match !== null && compareVersion(match[1], range);
};
// edge method does not support 'all' and 'any' interfaces
is.edge.api = ['not'];
// is current browser firefox?
// parameter is optional
is.firefox = function(range) {
var match = userAgent.match(/(?:firefox|fxios)\/(\d+)/);
return match !== null && compareVersion(match[1], range);
};
// firefox method does not support 'all' and 'any' interfaces
is.firefox.api = ['not'];
// is current browser internet explorer?
// parameter is optional
is.ie = function(range) {
var match = userAgent.match(/(?:msie |trident.+?; rv:)(\d+)/);
return match !== null && compareVersion(match[1], range);
};
// ie method does not support 'all' and 'any' interfaces
is.ie.api = ['not'];
// is current device ios?
is.ios = function() {
return is.iphone() || is.ipad() || is.ipod();
};
// ios method does not support 'all' and 'any' interfaces
is.ios.api = ['not'];
// is current device ipad?
// parameter is optional
is.ipad = function(range) {
var match = userAgent.match(/ipad.+?os (\d+)/);
return match !== null && compareVersion(match[1], range);
};
// ipad method does not support 'all' and 'any' interfaces
is.ipad.api = ['not'];
// is current device iphone?
// parameter is optional
is.iphone = function(range) {
// original iPhone doesn't have the os portion of the UA
var match = userAgent.match(/iphone(?:.+?os (\d+))?/);
return match !== null && compareVersion(match[1] || 1, range);
};
// iphone method does not support 'all' and 'any' interfaces
is.iphone.api = ['not'];
// is current device ipod?
// parameter is optional
is.ipod = function(range) {
var match = userAgent.match(/ipod.+?os (\d+)/);
return match !== null && compareVersion(match[1], range);
};
// ipod method does not support 'all' and 'any' interfaces
is.ipod.api = ['not'];
// is current operating system linux?
is.linux = function() {
return /linux/.test(appVersion);
};
// linux method does not support 'all' and 'any' interfaces
is.linux.api = ['not'];
// is current operating system mac?
is.mac = function() {
return /mac/.test(appVersion);
};
// mac method does not support 'all' and 'any' interfaces
is.mac.api = ['not'];
// is current device mobile?
is.mobile = function() {
return is.iphone() || is.ipod() || is.androidPhone() || is.blackberry() || is.windowsPhone();
};
// mobile method does not support 'all' and 'any' interfaces
is.mobile.api = ['not'];
// is current state offline?
is.offline = not(is.online);
// offline method does not support 'all' and 'any' interfaces
is.offline.api = ['not'];
// is current state online?
is.online = function() {
return !navigator || navigator.onLine === true;
};
// online method does not support 'all' and 'any' interfaces
is.online.api = ['not'];
// is current browser opera?
// parameter is optional
is.opera = function(range) {
var match = userAgent.match(/(?:^opera.+?version|opr)\/(\d+)/);
return match !== null && compareVersion(match[1], range);
};
// opera method does not support 'all' and 'any' interfaces
is.opera.api = ['not'];
// is current browser phantomjs?
// parameter is optional
is.phantom = function(range) {
var match = userAgent.match(/phantomjs\/(\d+)/);
return match !== null && compareVersion(match[1], range);
};
// phantom method does not support 'all' and 'any' interfaces
is.phantom.api = ['not'];
// is current browser safari?
// parameter is optional
is.safari = function(range) {
var match = userAgent.match(/version\/(\d+).+?safari/);
return match !== null && compareVersion(match[1], range);
};
// safari method does not support 'all' and 'any' interfaces
is.safari.api = ['not'];
// is current device tablet?
is.tablet = function() {
return is.ipad() || is.androidTablet() || is.windowsTablet();
};
// tablet method does not support 'all' and 'any' interfaces
is.tablet.api = ['not'];
// is current device supports touch?
is.touchDevice = function() {
return !!document && ('ontouchstart' in freeSelf ||
('DocumentTouch' in freeSelf && document instanceof DocumentTouch));
};
// touchDevice method does not support 'all' and 'any' interfaces
is.touchDevice.api = ['not'];
// is current operating system windows?
is.windows = function() {
return /win/.test(appVersion);
};
// windows method does not support 'all' and 'any' interfaces
is.windows.api = ['not'];
// is current device windows phone?
is.windowsPhone = function() {
return is.windows() && /phone/.test(userAgent);
};
// windowsPhone method does not support 'all' and 'any' interfaces
is.windowsPhone.api = ['not'];
// is current device windows tablet?
is.windowsTablet = function() {
return is.windows() && is.not.windowsPhone() && /touch/.test(userAgent);
};
// windowsTablet method does not support 'all' and 'any' interfaces
is.windowsTablet.api = ['not'];
// Object checks
/* -------------------------------------------------------------------------- */
// has a given object got parameterized count property?
is.propertyCount = function(object, count) {
if (is.not.object(object) || is.not.number(count)) {
return false;
}
var n = 0;
for (var property in object) {
if (hasOwnProperty.call(object, property) && ++n > count) {
return false;
}
}
return n === count;
};
// propertyCount method does not support 'all' and 'any' interfaces
is.propertyCount.api = ['not'];
// is given object has parameterized property?
is.propertyDefined = function(object, property) {
return is.object(object) && is.string(property) && property in object;
};
// propertyDefined method does not support 'all' and 'any' interfaces
is.propertyDefined.api = ['not'];
// Array checks
/* -------------------------------------------------------------------------- */
// is a given item in an array?
is.inArray = function(value, array) {
if (is.not.array(array)) {
return false;
}
for (var i = 0; i < array.length; i++) {
if (array[i] === value) {
return true;
}
}
return false;
};
// inArray method does not support 'all' and 'any' interfaces
is.inArray.api = ['not'];
// is a given array sorted?
is.sorted = function(array, sign) {
if (is.not.array(array)) {
return false;
}
var predicate = comparator[sign] || comparator['>='];
for (var i = 1; i < array.length; i++) {
if (!predicate(array[i], array[i - 1])) {
return false;
}
}
return true;
};
// API
// Set 'not', 'all' and 'any' interfaces to methods based on their api property
/* -------------------------------------------------------------------------- */
function setInterfaces() {
var options = is;
for (var option in options) {
if (hasOwnProperty.call(options, option) && is['function'](options[option])) {
var interfaces = options[option].api || ['not', 'all', 'any'];
for (var i = 0; i < interfaces.length; i++) {
if (interfaces[i] === 'not') {
is.not[option] = not(is[option]);
}
if (interfaces[i] === 'all') {
is.all[option] = all(is[option]);
}
if (interfaces[i] === 'any') {
is.any[option] = any(is[option]);
}
}
}
}
}
setInterfaces();
// Configuration methods
// Intentionally added after setInterfaces function
/* -------------------------------------------------------------------------- */
// change namespace of library to prevent name collisions
// var preferredName = is.setNamespace();
// preferredName.odd(3);
// => true
is.setNamespace = function() {
root.is = previousIs;
return this;
};
// set optional regexes to methods
is.setRegexp = function(regexp, name) {
for (var r in regexes) {
if (hasOwnProperty.call(regexes, r) && (name === r)) {
regexes[r] = regexp;
}
}
};
return is;
}));
/*!
* is.js 0.8.0
* Author: Aras Atasaygin
*/
(function(n,t){if(typeof define==="function"&&define.amd){define(function(){return n.is=t()})}else if(typeof exports==="object"){module.exports=t()}else{n.is=t()}})(this,function(){var n={};n.VERSION="0.8.0";n.not={};n.all={};n.any={};var t=Object.prototype.toString;var e=Array.prototype.slice;var r=Object.prototype.hasOwnProperty;function a(n){return function(){return!n.apply(null,e.call(arguments))}}function u(n){return function(){var t=c(arguments);var e=t.length;for(var r=0;r<e;r++){if(!n.call(null,t[r])){return false}}return true}}function o(n){return function(){var t=c(arguments);var e=t.length;for(var r=0;r<e;r++){if(n.call(null,t[r])){return true}}return false}}var i={"<":function(n,t){return n<t},"<=":function(n,t){return n<=t},">":function(n,t){return n>t},">=":function(n,t){return n>=t}};function f(n,t){var e=t+"";var r=+(e.match(/\d+/)||NaN);var a=e.match(/^[<>]=?|/)[0];return i[a]?i[a](n,r):n==r||r!==r}function c(t){var r=e.call(t);var a=r.length;if(a===1&&n.array(r[0])){r=r[0]}return r}n.arguments=function(n){return t.call(n)==="[object Arguments]"||n!=null&&typeof n==="object"&&"callee"in n};n.array=Array.isArray||function(n){return t.call(n)==="[object Array]"};n.boolean=function(n){return n===true||n===false||t.call(n)==="[object Boolean]"};n.char=function(t){return n.string(t)&&t.length===1};n.date=function(n){return t.call(n)==="[object Date]"};n.domNode=function(t){return n.object(t)&&t.nodeType>0};n.error=function(n){return t.call(n)==="[object Error]"};n["function"]=function(n){return t.call(n)==="[object Function]"||typeof n==="function"};n.json=function(n){return t.call(n)==="[object Object]"};n.nan=function(n){return n!==n};n["null"]=function(n){return n===null};n.number=function(e){return n.not.nan(e)&&t.call(e)==="[object Number]"};n.object=function(n){return Object(n)===n};n.regexp=function(n){return t.call(n)==="[object RegExp]"};n.sameType=function(e,r){var a=t.call(e);if(a!==t.call(r)){return false}if(a==="[object Number]"){return!n.any.nan(e,r)||n.all.nan(e,r)}return true};n.sameType.api=["not"];n.string=function(n){return t.call(n)==="[object String]"};n.undefined=function(n){return n===void 0};n.windowObject=function(n){return n!=null&&typeof n==="object"&&"setInterval"in n};n.empty=function(t){if(n.object(t)){var e=Object.getOwnPropertyNames(t).length;if(e===0||e===1&&n.array(t)||e===2&&n.arguments(t)){return true}return false}return t===""};n.existy=function(n){return n!=null};n.falsy=function(n){return!n};n.truthy=a(n.falsy);n.above=function(t,e){return n.all.number(t,e)&&t>e};n.above.api=["not"];n.decimal=function(t){return n.number(t)&&t%1!==0};n.equal=function(t,e){if(n.all.number(t,e)){return t===e&&1/t===1/e}if(n.all.string(t,e)||n.all.regexp(t,e)){return""+t===""+e}if(n.all.boolean(t,e)){return t===e}return false};n.equal.api=["not"];n.even=function(t){return n.number(t)&&t%2===0};n.finite=isFinite||function(t){return n.not.infinite(t)&&n.not.nan(t)};n.infinite=function(n){return n===Infinity||n===-Infinity};n.integer=function(t){return n.number(t)&&t%1===0};n.negative=function(t){return n.number(t)&&t<0};n.odd=function(t){return n.number(t)&&t%2===1};n.positive=function(t){return n.number(t)&&t>0};n.under=function(t,e){return n.all.number(t,e)&&t<e};n.under.api=["not"];n.within=function(t,e,r){return n.all.number(t,e,r)&&t>e&&t<r};n.within.api=["not"];var l={affirmative:/^(?:1|t(?:rue)?|y(?:es)?|ok(?:ay)?)$/,alphaNumeric:/^[A-Za-z0-9]+$/,caPostalCode:/^(?!.*[DFIOQU])[A-VXY][0-9][A-Z]\s?[0-9][A-Z][0-9]$/,creditCard:/^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/,dateString:/^(1[0-2]|0?[1-9])([\/-])(3[01]|[12][0-9]|0?[1-9])(?:\2)(?:[0-9]{2})?[0-9]{2}$/,email:/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,eppPhone:/^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/,hexadecimal:/^(?:0x)?[0-9a-fA-F]+$/,hexColor:/^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/,ipv4:/^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/,ipv6:/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i,nanpPhone:/^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/,socialSecurityNumber:/^(?!000|666)[0-8][0-9]{2}-?(?!00)[0-9]{2}-?(?!0000)[0-9]{4}$/,timeString:/^(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])$/,ukPostCode:/^[A-Z]{1,2}[0-9RCHNQ][0-9A-Z]?\s?[0-9][ABD-HJLNP-UW-Z]{2}$|^[A-Z]{2}-?[0-9]{4}$/,url:/^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/i,usZipCode:/^[0-9]{5}(?:-[0-9]{4})?$/};function d(t,e){n[t]=function(n){return e[t].test(n)}}for(var s in l){if(l.hasOwnProperty(s)){d(s,l)}}n.ip=function(t){return n.ipv4(t)||n.ipv6(t)};n.capitalized=function(t){if(n.not.string(t)){return false}var e=t.split(" ");for(var r=0;r<e.length;r++){var a=e[r];if(a.length){var u=a.charAt(0);if(u!==u.toUpperCase()){return false}}}return true};n.endWith=function(t,e){if(n.not.string(t)){return false}e+="";var r=t.length-e.length;return r>=0&&t.indexOf(e,r)===r};n.endWith.api=["not"];n.include=function(n,t){return n.indexOf(t)>-1};n.include.api=["not"];n.lowerCase=function(t){return n.string(t)&&t===t.toLowerCase()};n.palindrome=function(t){if(n.not.string(t)){return false}t=t.replace(/[^a-zA-Z0-9]+/g,"").toLowerCase();var e=t.length-1;for(var r=0,a=Math.floor(e/2);r<=a;r++){if(t.charAt(r)!==t.charAt(e-r)){return false}}return true};n.space=function(t){if(n.not.char(t)){return false}var e=t.charCodeAt(0);return e>8&&e<14||e===32};n.startWith=function(t,e){return n.string(t)&&t.indexOf(e)===0};n.startWith.api=["not"];n.upperCase=function(t){return n.string(t)&&t===t.toUpperCase()};var F=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"];var p=["january","february","march","april","may","june","july","august","september","october","november","december"];n.day=function(t,e){return n.date(t)&&e.toLowerCase()===F[t.getDay()]};n.day.api=["not"];n.dayLightSavingTime=function(n){var t=new Date(n.getFullYear(),0,1);var e=new Date(n.getFullYear(),6,1);var r=Math.max(t.getTimezoneOffset(),e.getTimezoneOffset());return n.getTimezoneOffset()<r};n.future=function(t){var e=new Date;return n.date(t)&&t.getTime()>e.getTime()};n.inDateRange=function(t,e,r){if(n.not.date(t)||n.not.date(e)||n.not.date(r)){return false}var a=t.getTime();return a>e.getTime()&&a<r.getTime()};n.inDateRange.api=["not"];n.inLastMonth=function(t){return n.inDateRange(t,new Date((new Date).setMonth((new Date).getMonth()-1)),new Date)};n.inLastWeek=function(t){return n.inDateRange(t,new Date((new Date).setDate((new Date).getDate()-7)),new Date)};n.inLastYear=function(t){return n.inDateRange(t,new Date((new Date).setFullYear((new Date).getFullYear()-1)),new Date)};n.inNextMonth=function(t){return n.inDateRange(t,new Date,new Date((new Date).setMonth((new Date).getMonth()+1)))};n.inNextWeek=function(t){return n.inDateRange(t,new Date,new Date((new Date).setDate((new Date).getDate()+7)))};n.inNextYear=function(t){return n.inDateRange(t,new Date,new Date((new Date).setFullYear((new Date).getFullYear()+1)))};n.leapYear=function(t){return n.number(t)&&(t%4===0&&t%100!==0||t%400===0)};n.month=function(t,e){return n.date(t)&&e.toLowerCase()===p[t.getMonth()]};n.month.api=["not"];n.past=function(t){var e=new Date;return n.date(t)&&t.getTime()<e.getTime()};n.quarterOfYear=function(t,e){return n.date(t)&&n.number(e)&&e===Math.floor((t.getMonth()+3)/3)};n.quarterOfYear.api=["not"];n.today=function(t){var e=new Date;var r=e.toDateString();return n.date(t)&&t.toDateString()===r};n.tomorrow=function(t){var e=new Date;var r=new Date(e.setDate(e.getDate()+1)).toDateString();return n.date(t)&&t.toDateString()===r};n.weekend=function(t){return n.date(t)&&(t.getDay()===6||t.getDay()===0)};n.weekday=a(n.weekend);n.year=function(t,e){return n.date(t)&&n.number(e)&&e===t.getFullYear()};n.year.api=["not"];n.yesterday=function(t){var e=new Date;var r=new Date(e.setDate(e.getDate()-1)).toDateString();return n.date(t)&&t.toDateString()===r};var D=n.windowObject(typeof global=="object"&&global)&&global;var h=n.windowObject(typeof self=="object"&&self)&&self;var v=n.windowObject(typeof this=="object"&&this)&&this;var b=D||h||v||Function("return this")();var g=h&&h.document;var m=b.is;var w=h&&h.navigator;var y=(w&&w.appVersion||"").toLowerCase();var x=(w&&w.userAgent||"").toLowerCase();var A=(w&&w.vendor||"").toLowerCase();n.android=function(){return/android/.test(x)};n.android.api=["not"];n.androidPhone=function(){return/android/.test(x)&&/mobile/.test(x)};n.androidPhone.api=["not"];n.androidTablet=function(){return/android/.test(x)&&!/mobile/.test(x)};n.androidTablet.api=["not"];n.blackberry=function(){return/blackberry/.test(x)||/bb10/.test(x)};n.blackberry.api=["not"];n.chrome=function(n){var t=/google inc/.test(A)?x.match(/(?:chrome|crios)\/(\d+)/):null;return t!==null&&f(t[1],n)};n.chrome.api=["not"];n.desktop=function(){return n.not.mobile()&&n.not.tablet()};n.desktop.api=["not"];n.edge=function(n){var t=x.match(/edge\/(\d+)/);return t!==null&&f(t[1],n)};n.edge.api=["not"];n.firefox=function(n){var t=x.match(/(?:firefox|fxios)\/(\d+)/);return t!==null&&f(t[1],n)};n.firefox.api=["not"];n.ie=function(n){var t=x.match(/(?:msie |trident.+?; rv:)(\d+)/);return t!==null&&f(t[1],n)};n.ie.api=["not"];n.ios=function(){return n.iphone()||n.ipad()||n.ipod()};n.ios.api=["not"];n.ipad=function(n){var t=x.match(/ipad.+?os (\d+)/);return t!==null&&f(t[1],n)};n.ipad.api=["not"];n.iphone=function(n){var t=x.match(/iphone(?:.+?os (\d+))?/);return t!==null&&f(t[1]||1,n)};n.iphone.api=["not"];n.ipod=function(n){var t=x.match(/ipod.+?os (\d+)/);return t!==null&&f(t[1],n)};n.ipod.api=["not"];n.linux=function(){return/linux/.test(y)};n.linux.api=["not"];n.mac=function(){return/mac/.test(y)};n.mac.api=["not"];n.mobile=function(){return n.iphone()||n.ipod()||n.androidPhone()||n.blackberry()||n.windowsPhone()};n.mobile.api=["not"];n.offline=a(n.online);n.offline.api=["not"];n.online=function(){return!w||w.onLine===true};n.online.api=["not"];n.opera=function(n){var t=x.match(/(?:^opera.+?version|opr)\/(\d+)/);return t!==null&&f(t[1],n)};n.opera.api=["not"];n.phantom=function(n){var t=x.match(/phantomjs\/(\d+)/);return t!==null&&f(t[1],n)};n.phantom.api=["not"];n.safari=function(n){var t=x.match(/version\/(\d+).+?safari/);return t!==null&&f(t[1],n)};n.safari.api=["not"];n.tablet=function(){return n.ipad()||n.androidTablet()||n.windowsTablet()};n.tablet.api=["not"];n.touchDevice=function(){return!!g&&("ontouchstart"in h||"DocumentTouch"in h&&g instanceof DocumentTouch)};n.touchDevice.api=["not"];n.windows=function(){return/win/.test(y)};n.windows.api=["not"];n.windowsPhone=function(){return n.windows()&&/phone/.test(x)};n.windowsPhone.api=["not"];n.windowsTablet=function(){return n.windows()&&n.not.windowsPhone()&&/touch/.test(x)};n.windowsTablet.api=["not"];n.propertyCount=function(t,e){if(n.not.object(t)||n.not.number(e)){return false}var a=0;for(var u in t){if(r.call(t,u)&&++a>e){return false}}return a===e};n.propertyCount.api=["not"];n.propertyDefined=function(t,e){return n.object(t)&&n.string(e)&&e in t};n.propertyDefined.api=["not"];n.inArray=function(t,e){if(n.not.array(e)){return false}for(var r=0;r<e.length;r++){if(e[r]===t){return true}}return false};n.inArray.api=["not"];n.sorted=function(t,e){if(n.not.array(t)){return false}var r=i[e]||i[">="];for(var a=1;a<t.length;a++){if(!r(t[a],t[a-1])){return false}}return true};function j(){var t=n;for(var e in t){if(r.call(t,e)&&n["function"](t[e])){var i=t[e].api||["not","all","any"];for(var f=0;f<i.length;f++){if(i[f]==="not"){n.not[e]=a(n[e])}if(i[f]==="all"){n.all[e]=u(n[e])}if(i[f]==="any"){n.any[e]=o(n[e])}}}}}j();n.setNamespace=function(){b.is=m;return this};n.setRegexp=function(n,t){for(var e in l){if(r.call(l,e)&&t===e){l[e]=n}}};return n});
\ No newline at end of file
{
"_from": "is_js@^0.9.0",
"_id": "is_js@0.9.0",
"_inBundle": false,
"_integrity": "sha1-CrlFQFArp6+iTIVqqYVWFmnpxS0=",
"_location": "/is_js",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "is_js@^0.9.0",
"name": "is_js",
"escapedName": "is_js",
"rawSpec": "^0.9.0",
"saveSpec": null,
"fetchSpec": "^0.9.0"
},
"_requiredBy": [
"/request-ip"
],
"_resolved": "https://registry.npmjs.org/is_js/-/is_js-0.9.0.tgz",
"_shasum": "0ab94540502ba7afa24c856aa985561669e9c52d",
"_spec": "is_js@^0.9.0",
"_where": "C:\\Users\\KoMoGoon\\Desktop\\oss_project\\Singer-Composer\\node_modules\\request-ip",
"bugs": {
"url": "https://github.com/arasatasaygin/is.js/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "micro check library",
"devDependencies": {
"chai": "^3.4.0",
"eslint": "^2.13.1",
"lodash": "^4.15.0",
"mocha": "^2.2.1",
"mocha-phantomjs": "^4.1.0",
"pre-commit": "^1.1.3",
"uglify-js": "^2.7.3"
},
"files": [
"is.js",
"is.min.js"
],
"homepage": "http://is.js.org/",
"license": "MIT",
"main": "is.js",
"name": "is_js",
"pre-commit": [
"lint"
],
"repository": {
"type": "git",
"url": "git+https://github.com/arasatasaygin/is.js.git"
},
"scripts": {
"build": "npm run lint && npm run min",
"lint": "eslint .",
"min": "uglifyjs is.js -m --comments \"/^!/\" -o is.min.js",
"test": "mocha --check-leaks -R dot",
"test:phantom": "mocha-phantomjs -R dot test/index.html"
},
"version": "0.9.0"
}
# Change Log
## [2.1.2](https://github.com/pbojinov/request-ip/tree/2.1.2) (2018-10-29)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/2.1.1...2.1.2)
**Closed issues:**
- Handle Firebase hosting header fastly-client-ip [\#37](https://github.com/pbojinov/request-ip/issues/37)
**Merged pull requests:**
- chore: improve packaging [\#40](https://github.com/pbojinov/request-ip/pull/40) ([pi0](https://github.com/pi0))
- fixed Cannot redefine property: clientIp error [\#39](https://github.com/pbojinov/request-ip/pull/39) ([karankohli13](https://github.com/karankohli13))
- Add firebase hosting header [\#38](https://github.com/pbojinov/request-ip/pull/38) ([vishalvijay](https://github.com/vishalvijay))
## [2.1.1](https://github.com/pbojinov/request-ip/tree/2.1.1) (2018-07-03)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/2.1.0...2.1.1)
## [2.1.0](https://github.com/pbojinov/request-ip/tree/2.1.0) (2018-07-03)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/2.0.2...2.1.0)
**Closed issues:**
- Not getting the right ip first time [\#28](https://github.com/pbojinov/request-ip/issues/28)
- Allow using node \> 6 [\#27](https://github.com/pbojinov/request-ip/issues/27)
**Merged pull requests:**
- Get client ip when using AWS Api Gateway + Lambda. [\#35](https://github.com/pbojinov/request-ip/pull/35) ([rafaelthemendes](https://github.com/rafaelthemendes))
- redefine attribute getter [\#34](https://github.com/pbojinov/request-ip/pull/34) ([isayme](https://github.com/isayme))
## [2.0.2](https://github.com/pbojinov/request-ip/tree/2.0.2) (2017-06-26)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/2.0.1...2.0.2)
**Closed issues:**
- azure web app adds port to x-forwarded-for [\#29](https://github.com/pbojinov/request-ip/issues/29)
**Merged pull requests:**
- handling x-forwarded-for with ip:port [\#30](https://github.com/pbojinov/request-ip/pull/30) ([luisrudge](https://github.com/luisrudge))
## [2.0.1](https://github.com/pbojinov/request-ip/tree/2.0.1) (2017-03-09)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/2.0.0...2.0.1)
**Implemented enhancements:**
- ES2015 Support [\#22](https://github.com/pbojinov/request-ip/issues/22)
## [2.0.0](https://github.com/pbojinov/request-ip/tree/2.0.0) (2017-03-07)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.3.0...2.0.0)
**Closed issues:**
- optimized your code a bit \(no need to evalutate every option before choosing first one that matches. just evaluate then return on first match\) [\#15](https://github.com/pbojinov/request-ip/issues/15)
**Merged pull requests:**
- Refactor to ES6 [\#23](https://github.com/pbojinov/request-ip/pull/23) ([fluxsauce](https://github.com/fluxsauce))
## [1.3.0](https://github.com/pbojinov/request-ip/tree/1.3.0) (2017-03-03)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.2.3...1.3.0)
**Closed issues:**
- Support Cloudflare? [\#20](https://github.com/pbojinov/request-ip/issues/20)
- How to receive IP in client [\#17](https://github.com/pbojinov/request-ip/issues/17)
**Merged pull requests:**
- Adding support for CF-Connecting-IP and True-Client-IP [\#21](https://github.com/pbojinov/request-ip/pull/21) ([fluxsauce](https://github.com/fluxsauce))
- Return once we find something and don't crash if req.headers is undefined [\#19](https://github.com/pbojinov/request-ip/pull/19) ([rokob](https://github.com/rokob))
- Ignore 'unknown' ip addresses in X-Forwarded-For header [\#18](https://github.com/pbojinov/request-ip/pull/18) ([raunc](https://github.com/raunc))
## [1.2.3](https://github.com/pbojinov/request-ip/tree/1.2.3) (2016-11-02)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.2.2...1.2.3)
**Closed issues:**
- Are there any security concerns when saving the IP directly to a database? [\#16](https://github.com/pbojinov/request-ip/issues/16)
- I'm not getting local host ip address 127.0.0.1 [\#14](https://github.com/pbojinov/request-ip/issues/14)
## [1.2.2](https://github.com/pbojinov/request-ip/tree/1.2.2) (2016-01-27)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.2.1...1.2.2)
## [1.2.1](https://github.com/pbojinov/request-ip/tree/1.2.1) (2016-01-27)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.2.0...1.2.1)
**Merged pull requests:**
- introduce a built-in default implementation for a connect-middleware [\#12](https://github.com/pbojinov/request-ip/pull/12) ([osherx](https://github.com/osherx))
## [1.2.0](https://github.com/pbojinov/request-ip/tree/1.2.0) (2016-01-27)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.1.4...1.2.0)
**Merged pull requests:**
- Cleanup [\#13](https://github.com/pbojinov/request-ip/pull/13) ([minecrawler](https://github.com/minecrawler))
- Got it working in a case that was returning null [\#11](https://github.com/pbojinov/request-ip/pull/11) ([andfaulkner](https://github.com/andfaulkner))
## [1.1.4](https://github.com/pbojinov/request-ip/tree/1.1.4) (2015-07-23)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.1.3...1.1.4)
**Merged pull requests:**
- Add case management where you can not find the IP address [\#10](https://github.com/pbojinov/request-ip/pull/10) ([sitexw](https://github.com/sitexw))
## [1.1.3](https://github.com/pbojinov/request-ip/tree/1.1.3) (2015-04-20)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.1.2...1.1.3)
## [1.1.2](https://github.com/pbojinov/request-ip/tree/1.1.2) (2015-04-04)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.1.1...1.1.2)
## [1.1.1](https://github.com/pbojinov/request-ip/tree/1.1.1) (2015-04-04)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/1.1.0...1.1.1)
**Closed issues:**
- needs semver [\#7](https://github.com/pbojinov/request-ip/issues/7)
## [1.1.0](https://github.com/pbojinov/request-ip/tree/1.1.0) (2015-04-04)
[Full Changelog](https://github.com/pbojinov/request-ip/compare/v0.0.4...1.1.0)
**Merged pull requests:**
- Update README.md [\#9](https://github.com/pbojinov/request-ip/pull/9) ([coolaj86](https://github.com/coolaj86))
- This deserves a production version number. [\#8](https://github.com/pbojinov/request-ip/pull/8) ([coolaj86](https://github.com/coolaj86))
## [v0.0.4](https://github.com/pbojinov/request-ip/tree/v0.0.4) (2015-01-16)
**Closed issues:**
- Invalid header [\#5](https://github.com/pbojinov/request-ip/issues/5)
- replace req.header\('X-Forwarded-For'\) for req.header\('X-Forwarder-For'\)\); [\#3](https://github.com/pbojinov/request-ip/issues/3)
- Nginx problems [\#2](https://github.com/pbojinov/request-ip/issues/2)
**Merged pull requests:**
- Add support for X-Real-IP Header [\#6](https://github.com/pbojinov/request-ip/pull/6) ([pmarques](https://github.com/pmarques))
- fix bug X-Forwarder-For [\#4](https://github.com/pbojinov/request-ip/pull/4) ([morello-cl](https://github.com/morello-cl))
- Add a Bitdeli Badge to README [\#1](https://github.com/pbojinov/request-ip/pull/1) ([bitdeli-chef](https://github.com/bitdeli-chef))
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
\ No newline at end of file
The MIT License (MIT)
Copyright (c) 2018 Petar Bojinov - petarbojinov@gmail.com
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.
# request-ip
A tiny Node.js module for retrieving a request's IP address.
![](https://nodei.co/npm/request-ip.png?downloads=true&cacheBust=2)
![](https://travis-ci.org/pbojinov/request-ip.svg?branch=master)
[![Coverage Status](https://coveralls.io/repos/pbojinov/request-ip/badge.svg)](https://coveralls.io/r/pbojinov/request-ip)
![](https://img.shields.io/npm/l/express.svg)
[![npm version](https://badge.fury.io/js/request-ip.svg)](https://badge.fury.io/js/request-ip)
## Installation
```bash
npm install request-ip --save
```
## Getting Started
```javascript
const requestIp = require('request-ip');
// inside middleware handler
const ipMiddleware = function(req, res, next) {
const clientIp = requestIp.getClientIp(req);
next();
};
// on localhost you'll see 127.0.0.1 if you're using IPv4
// or ::1, ::ffff:127.0.0.1 if you're using IPv6
```
### As Connect Middleware
```javascript
const requestIp = require('request-ip');
app.use(requestIp.mw())
app.use(function(req, res) {
const ip = req.clientIp;
res.end(ip);
});
```
To see a full working code for the middleware, check out the [examples](https://github.com/pbojinov/request-ip/tree/master/examples) folder.
The connect-middleware also supports retrieving the ip address under a custom attribute name, which also works as a container for any future settings.
## How It Works
It looks for specific headers in the request and falls back to some defaults if they do not exist.
The user ip is determined by the following order:
1. `X-Client-IP`
2. `X-Forwarded-For` (Header may return multiple IP addresses in the format: "client IP, proxy 1 IP, proxy 2 IP", so we take the the first one.)
3. `CF-Connecting-IP` (Cloudflare)
4. `Fastly-Client-Ip` (Fastly CDN and Firebase hosting header when forwared to a cloud function)
5. `True-Client-Ip` (Akamai and Cloudflare)
6. `X-Real-IP` (Nginx proxy/FastCGI)
7. `X-Cluster-Client-IP` (Rackspace LB, Riverbed Stingray)
8. `X-Forwarded`, `Forwarded-For` and `Forwarded` (Variations of #2)
9. `req.connection.remoteAddress`
10. `req.socket.remoteAddress`
11. `req.connection.socket.remoteAddress`
12. `req.info.remoteAddress`
If an IP address cannot be found, it will return `null`.
## Samples Use Cases
* Getting a user's IP for geolocation.
## Running the Tests
Make sure you have the necessary dev dependencies needed to run the tests:
```
npm install
```
Run the integration tests
```
npm test
```
## Release Notes
See the wonderful [changelog](https://github.com/pbojinov/request-ip/blob/master/CHANGELOG.md)
To easily generate a new changelog, install [github-changelog-generator](https://github.com/skywinder/github-changelog-generator) then run `npm run changelog`.
## Contributors
* Thanks to [@osherx](https://github.com/osherx) for adding the connect-middleware.
* Thanks to [@raunc](https://github.com/raunc) for adding Squid proxy support.
* Thanks to [@fluxsauce](https://github.com/fluxsauce) for adding `CF-Connecting-IP`, `True-Client-IP`, and ES6 support.
* Thanks to [@vishalvijay](https://github.com/vishalvijay) for adding Fastly/Firebase hosting support.
## License
The MIT License (MIT) - 2018
No preview for this file type
"use strict";
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
var is = require('is_js');
/**
* Parse x-forwarded-for headers.
*
* @param {string} value - The value to be parsed.
* @return {string|null} First known IP address, if any.
*/
function getClientIpFromXForwardedFor(value) {
if (!is.existy(value)) {
return null;
}
if (is.not.string(value)) {
throw new TypeError("Expected a string, got \"".concat(_typeof(value), "\""));
} // x-forwarded-for may return multiple IP addresses in the format:
// "client IP, proxy 1 IP, proxy 2 IP"
// Therefore, the right-most IP address is the IP address of the most recent proxy
// and the left-most IP address is the IP address of the originating client.
// source: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html
// Azure Web App's also adds a port for some reason, so we'll only use the first part (the IP)
var forwardedIps = value.split(',').map(function (e) {
var ip = e.trim();
if (ip.includes(':')) {
var splitted = ip.split(':'); // make sure we only use this if it's ipv4 (ip:port)
if (splitted.length === 2) {
return splitted[0];
}
}
return ip;
}); // Sometimes IP addresses in this header can be 'unknown' (http://stackoverflow.com/a/11285650).
// Therefore taking the left-most IP address that is not unknown
// A Squid configuration directive can also set the value to "unknown" (http://www.squid-cache.org/Doc/config/forwarded_for/)
return forwardedIps.find(is.ip);
}
/**
* Determine client IP address.
*
* @param req
* @returns {string} ip - The IP address if known, defaulting to empty string if unknown.
*/
function getClientIp(req) {
// Server is probably behind a proxy.
if (req.headers) {
// Standard headers used by Amazon EC2, Heroku, and others.
if (is.ip(req.headers['x-client-ip'])) {
return req.headers['x-client-ip'];
} // Load-balancers (AWS ELB) or proxies.
var xForwardedFor = getClientIpFromXForwardedFor(req.headers['x-forwarded-for']);
if (is.ip(xForwardedFor)) {
return xForwardedFor;
} // Cloudflare.
// @see https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
// CF-Connecting-IP - applied to every request to the origin.
if (is.ip(req.headers['cf-connecting-ip'])) {
return req.headers['cf-connecting-ip'];
} // Fastly and Firebase hosting header (When forwared to cloud function)
if (is.ip(req.headers['fastly-client-ip'])) {
return req.headers['fastly-client-ip'];
} // Akamai and Cloudflare: True-Client-IP.
if (is.ip(req.headers['true-client-ip'])) {
return req.headers['true-client-ip'];
} // Default nginx proxy/fcgi; alternative to x-forwarded-for, used by some proxies.
if (is.ip(req.headers['x-real-ip'])) {
return req.headers['x-real-ip'];
} // (Rackspace LB and Riverbed's Stingray)
// http://www.rackspace.com/knowledge_center/article/controlling-access-to-linux-cloud-sites-based-on-the-client-ip-address
// https://splash.riverbed.com/docs/DOC-1926
if (is.ip(req.headers['x-cluster-client-ip'])) {
return req.headers['x-cluster-client-ip'];
}
if (is.ip(req.headers['x-forwarded'])) {
return req.headers['x-forwarded'];
}
if (is.ip(req.headers['forwarded-for'])) {
return req.headers['forwarded-for'];
}
if (is.ip(req.headers.forwarded)) {
return req.headers.forwarded;
}
} // Remote address checks.
if (is.existy(req.connection)) {
if (is.ip(req.connection.remoteAddress)) {
return req.connection.remoteAddress;
}
if (is.existy(req.connection.socket) && is.ip(req.connection.socket.remoteAddress)) {
return req.connection.socket.remoteAddress;
}
}
if (is.existy(req.socket) && is.ip(req.socket.remoteAddress)) {
return req.socket.remoteAddress;
}
if (is.existy(req.info) && is.ip(req.info.remoteAddress)) {
return req.info.remoteAddress;
} // AWS Api Gateway + Lambda
if (is.existy(req.requestContext) && is.existy(req.requestContext.identity) && is.ip(req.requestContext.identity.sourceIp)) {
return req.requestContext.identity.sourceIp;
}
return null;
}
/**
* Expose request IP as a middleware.
*
* @param {object} [options] - Configuration.
* @param {string} [options.attributeName] - Name of attribute to augment request object with.
* @return {*}
*/
function mw(options) {
// Defaults.
var configuration = is.not.existy(options) ? {} : options; // Validation.
if (is.not.object(configuration)) {
throw new TypeError('Options must be an object!');
}
var attributeName = configuration.attributeName || 'clientIp';
return function (req, res, next) {
var ip = getClientIp(req);
Object.defineProperty(req, attributeName, {
get: function get() {
return ip;
},
configurable: true
});
next();
};
}
module.exports = {
getClientIpFromXForwardedFor: getClientIpFromXForwardedFor,
getClientIp: getClientIp,
mw: mw
};
{
"_from": "request-ip",
"_id": "request-ip@2.1.3",
"_inBundle": false,
"_integrity": "sha512-J3qdE/IhVM3BXkwMIVO4yFrvhJlU3H7JH16+6yHucadT4fePnR8dyh+vEs6FIx0S2x5TCt2ptiPfHcn0sqhbYQ==",
"_location": "/request-ip",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "request-ip",
"name": "request-ip",
"escapedName": "request-ip",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/request-ip/-/request-ip-2.1.3.tgz",
"_shasum": "99ab2bafdeaf2002626e28083cb10597511d9e14",
"_spec": "request-ip",
"_where": "C:\\Users\\KoMoGoon\\Desktop\\oss_project\\Singer-Composer",
"author": {
"name": "Petar Bojinov",
"email": "petarbojinov@gmail.com"
},
"bugs": {
"url": "https://github.com/pbojinov/request-ip/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Jon Peck",
"email": "jpeck@fluxsauce.com"
}
],
"dependencies": {
"is_js": "^0.9.0"
},
"deprecated": false,
"description": "A small node.js module to retrieve the request's IP address",
"devDependencies": {
"@babel/cli": "^7.0.0-beta.51",
"@babel/core": "^7.0.0-beta.51",
"@babel/preset-env": "^7.0.0-beta.51",
"coveralls": "^3.0.2",
"eslint": "^5.8.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.2.0",
"nyc": "^13.1.0",
"request": "^2.54.0",
"tap-spec": "^5.0.0",
"tape": "^4.9.1"
},
"files": [
"dist"
],
"homepage": "https://github.com/pbojinov/request-ip",
"keywords": [
"request ip",
"ip",
"address",
"request",
"proxy",
"client",
"header",
"X-Client-IP",
"X-Forwarded-For",
"CF-Connecting-IP",
"Fastly-Client-IP",
"True-Client-IP",
"X-Real-IP",
"X-Cluster-Client-IP",
"X-Forwarded",
"Forwarded-For",
"connection.remoteAddress",
"connection.socket.remoteAddress",
"req.info.remoteAddress",
"middleware",
"ipv4",
"ipv6"
],
"license": "MIT",
"main": "./dist/index.js",
"name": "request-ip",
"repository": {
"type": "git",
"url": "git+https://github.com/pbojinov/request-ip.git"
},
"scripts": {
"build": "babel ./src/index.js > ./dist/index.js",
"changelog": "github_changelog_generator -u pbojinov -p request-ip",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"test": "nyc --reporter=html --reporter=text --check-coverage --lines=100 --statements=100 tape ./test/index.js"
},
"version": "2.1.3"
}
......@@ -750,6 +750,11 @@
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
"is_js": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/is_js/-/is_js-0.9.0.tgz",
"integrity": "sha1-CrlFQFArp6+iTIVqqYVWFmnpxS0="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
......@@ -1154,6 +1159,14 @@
}
}
},
"request-ip": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/request-ip/-/request-ip-2.1.3.tgz",
"integrity": "sha512-J3qdE/IhVM3BXkwMIVO4yFrvhJlU3H7JH16+6yHucadT4fePnR8dyh+vEs6FIx0S2x5TCt2ptiPfHcn0sqhbYQ==",
"requires": {
"is_js": "^0.9.0"
}
},
"request-promise-core": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
......
......@@ -12,6 +12,7 @@
"ejs": "^3.1.6",
"express": "^4.17.1",
"mysql": "^2.18.1",
"request-ip": "^2.1.3",
"socket.io": "^4.4.0"
},
"devDependencies": {
......
......@@ -60,10 +60,10 @@ create table board(
>UPDATE board SET idx = @COUNT:=@COUNT+1;
---
### 최종 수정: 2021-11-23 01:53<br>
### 최종 수정: 2021-11-23 02:49<br>
### 수정 내용:
0. 채팅기능에 버그가 있는 것 같음-피드백 바람(undefined님이 나가셨습니다. -> 콘솔에 계속 출력됨)
1. 일부 수정
1. 로그에 IP 추가
2. 로그에 시간 추가
3. 시간 실시간 반영
4. 게시글 수정 및 삭제 세션+권한 연동/DB수정
......
......@@ -2,6 +2,7 @@ var express = require('express')
var app = express()
var router = express.Router();
var path = require('path') // 상대경로
var requestIp = require('request-ip');
// 로그용
var logString;
......@@ -24,14 +25,15 @@ init()
// main page는 login이 된 상태(세션정보가 있을때만) 접근이 가능하게 하자 -> info에 구현해놓음.
router.get('/', function(req, res){
var ip = requestIp.getClientIp(req);
var id = req.user;
if(!id){
console.log(logString+'익명의 유저가 about 페이지에서 작업 중입니다.')
console.log(logString+'익명의 유저가 about 페이지에서 작업 중입니다.('+ip+')')
res.sendFile(path.join(__dirname, "../../public/about.html"))
}
if(id){
var nickname = req.user.nickname;
console.log(logString+req.user.ID+'('+nickname+') 유저가 about 페이지에서 작업 중입니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 about 페이지에서 작업 중입니다.('+ip+')')
res.render('about.ejs', {'ID': id, 'nickname': nickname});
}
});
......
......@@ -7,6 +7,7 @@ var mysql = require('mysql');
var path = require('path') // 상대경로
var mysql_odbc = require('../../db/db_board')();
var board = mysql_odbc.init();
var requestIp = require('request-ip');
// 로그용
var logString;
......@@ -28,9 +29,10 @@ function init(){
init()
router.get('/list/:page', function(req, res, next) {
var ip = requestIp.getClientIp(req);
var id = req.user;
if(!id){
console.log(logString+'익명 유저의 게시판 접근을 거부했습니다.')
console.log(logString+'익명 유저의 게시판 접근을 거부했습니다.('+ip+')')
res.redirect('/board/list/1')
}
else{
......@@ -41,36 +43,39 @@ router.get('/list/:page', function(req, res, next) {
if (err) console.error("err : " + err);
var id = req.user.ID;
var nickname = req.user.nickname;
console.log(logString+req.user.ID+'('+nickname+') 유저가 게시판을 보고있습니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 게시판을 보고있습니다.('+ip+')')
res.render('list.ejs', {'ID':id, 'nickname': nickname, title: '게시판 리스트', rows: rows, page:page, length:rows.length-1,page_num:10,pass:true})
})
}
});
router.get('/list', function(req,res,next){
var ip = requestIp.getClientIp(req);
var id = req.user;
if(!id){
console.log(logString+'익명 유저의 게시판 접근을 거부했습니다.')
console.log(logString+'익명 유저의 게시판 접근을 거부했습니다.('+ip+')')
res.sendFile(path.join(__dirname, "../../public/login.html"))
}
else res.redirect('/board/list/1')
})
router.get('/write', function(req,res,next){
var ip = requestIp.getClientIp(req);
var id = req.user;
if(!id){
console.log(logString+'익명 유저의 글쓰기 시도를 거부했습니다.')
console.log(logString+'익명 유저의 글쓰기 시도를 거부했습니다.('+ip+')')
res.sendFile(path.join(__dirname, "../../public/login.html"))
}
else{
var id = req.user.ID;
var nickname = req.user.nickname;
console.log(logString+req.user.ID+'('+nickname+') 유저가 게시글 작성 중입니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 게시글 작성 중입니다.('+ip+')')
res.render('write.ejs', {'ID':id, 'nickname': nickname, title:"게시판 글 쓰기"})
}
})
router.post('/write', function(req,res,next){
var ip = requestIp.getClientIp(req);
var nickname = req.user.nickname // var name = req.body.name
var title = req.body.title
var content = req.body.content
......@@ -91,12 +96,13 @@ router.post('/write', function(req,res,next){
if(!idx_) // 글이 없으면 NULL
idx_ = 1;
console.log(logString+req.user.ID+'('+nickname+') 유저가 '+idx_+'번 게시글을 작성했습니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 '+idx_+'번 게시글을 작성했습니다.('+ip+')')
res.redirect('/board/read/'+idx_);
});
})
router.get('/read/:idx', function(req,res,next){
var ip = requestIp.getClientIp(req);
var idx = req.params.idx
var sql = "select idx, nickname, title, content, date_format(modidate,'%Y-%m-%d %H:%i:%s') modidate, " +
"date_format(regdate,'%Y-%m-%d %H:%i:%s') regdate, hit, ID from board where idx=?";
......@@ -105,7 +111,7 @@ router.get('/read/:idx', function(req,res,next){
var id = req.user;
if(!id){
console.log(logString+'익명 유저의 '+idx+'번 게시물 접근을 거부했습니다.')
console.log(logString+'익명 유저의 '+idx+'번 게시물 접근을 거부했습니다.('+ip+')')
res.redirect('/login')
}
else{
......@@ -118,13 +124,14 @@ router.get('/read/:idx', function(req,res,next){
if(err) console.error(err)
})
console.log(logString+req.user.ID+'('+nickname+') 유저가 '+idx+'번 게시글을 보고있습니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 '+idx+'번 게시글을 보고있습니다.('+ip+')')
res.render('read.ejs', {'ID':id, 'nickname': nickname, title:"글 상세", row:row[0]})
}
})
})
router.post('/update', function(req,res,next){
var ip = requestIp.getClientIp(req);
var ID = req.user.ID;
var idx = req.body.idx
var title = req.body.title
......@@ -135,19 +142,20 @@ router.post('/update', function(req,res,next){
board.query(sql,datas,function(err,result){
if(err) console.error(err)
if(result.affectedRows==0){
console.log(logString+req.user.ID+'('+nickname+') 유저의 '+idx+'번 게시글 수정을 거부했습니다.(권한없음)')
console.log(logString+req.user.ID+'('+req.user.nickname+') 유저의 '+idx+'번 게시글 수정을 거부했습니다.(권한없음 // '+ip+')')
res.send("<script>alert('게시글 작성자가 아닙니다.');history.back();</script>")
}
else{
var id = req.user.ID;
var nickname = req.user.nickname;
console.log(logString+req.user.ID+'('+nickname+') 유저가 '+idx+'번 게시글을 수정했습니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 '+idx+'번 게시글을 수정했습니다.('+ip+')')
res.redirect('/board/read/'+idx)
}
})
})
router.post('/delete', function(req,res,next){
var ip = requestIp.getClientIp(req);
var idx = req.body.idx
var ID = req.user.ID;
var datas = [idx,ID]
......@@ -170,12 +178,12 @@ router.post('/delete', function(req,res,next){
var nickname = req.user.nickname;
res.send("<script>alert('게시글이 운영자에 의해 삭제되었습니다.');window.location.href='/board/list/';</script>");
console.log(logString+"[Admin] "+req.user.ID+'('+nickname+') 유저가 '+idx+'번 게시글을 삭제했습니다.')
console.log(logString+"[Admin] "+req.user.ID+'('+nickname+') 유저가 '+idx+'번 게시글을 삭제했습니다.('+ip+')')
})
}
else{ // 작성자도, 운영자도 아니면
var nickname = req.user.nickname;
console.log(logString+req.user.ID+'('+nickname+') 유저의 '+idx+'번 게시글 삭제를 거부했습니다.(권한없음)')
console.log(logString+req.user.ID+'('+nickname+') 유저의 '+idx+'번 게시글 삭제를 거부했습니다.(권한없음 // '+ip+')')
res.send("<script>alert('게시글 작성자가 아닙니다');history.back();</script>");
}
})
......@@ -184,7 +192,7 @@ router.post('/delete', function(req,res,next){
var id = req.user.ID;
var nickname = req.user.nickname;
res.send("<script>alert('게시글이 삭제되었습니다.');window.location.href='/board/list/';</script>");
console.log(logString+req.user.ID+'('+nickname+') 유저가 '+idx+'번 게시글을 삭제했습니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 '+idx+'번 게시글을 삭제했습니다.('+ip+')')
}
})
})
......
......@@ -4,6 +4,7 @@ var router = express.Router();
var path = require('path') // 상대경로
var mysql_odbc = require('../../db/db_board')();
var myinfo = mysql_odbc.init();
var requestIp = require('request-ip');
// 로그용
var logString;
......@@ -25,14 +26,15 @@ function init(){
init()
router.get('/', function(req, res){
var ip = requestIp.getClientIp(req);
var id = req.user;
if(!id){
console.log(logString+'익명 유저의 채팅 접근을 거부했습니다.')
console.log(logString+'익명 유저의 채팅 접근을 거부했습니다.('+ip+')')
res.sendFile(path.join(__dirname, "../../public/login.html"))
}
if(id){
var nickname = req.user.nickname
console.log(logString+req.user.ID+'('+nickname+') 유저가 채팅 중입니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 채팅 중입니다.('+ip+')')
res.render('chat.ejs', {'nickname':nickname})
}
});
......
......@@ -2,6 +2,7 @@ var express = require('express')
var app = express()
var router = express.Router();
var path = require('path')
var requestIp = require('request-ip');
var main = require('./main/main')
var register = require('./register/index')
......@@ -12,10 +13,39 @@ var profile = require('./profile/index')
var about = require('./about/index')
var chat = require('./chat/chat')
// 로그용
var logString;
function getTime(){
var today = new Date();
var year = today.getFullYear();
var month = ('0' + (today.getMonth()+1)).slice(-2);
var day = ('0' + today.getDate()).slice(-2);
var hour = ('0' + today.getHours()).slice(-2);
var minute = ('0' + today.getMinutes()).slice(-2);
var second = ('0' + today.getSeconds()).slice(-2);
logString = '['+year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second+'] ';
}
// 시간 갱신용
function init(){
getTime();
setInterval(getTime, 1000)
}
init()
// URL routing
// req = request, res = respond
router.get('/', function(req, res){
res.sendFile(path.join(__dirname, "../public/main.html"));
var ip = requestIp.getClientIp(req);
var id = req.user;
if(!id){
console.log(logString+'익명의 유저가 작업 중입니다.('+ip+')')
res.sendFile(path.join(__dirname, "../public/main.html"))
}
if(id){
var nickname = req.user.nickname;
console.log(logString+req.user.ID+'('+nickname+') 유저가 작업 중입니다.('+ip+')')
res.render('main.ejs', {'ID': id, 'nickname': nickname});
}
});
// router 정의
......
......@@ -5,6 +5,7 @@ var path = require('path') // 상대경로
var mysql = require('mysql')
var passport = require('passport')
var LocalStrategy = require('passport-local').Strategy
var requestIp = require('request-ip');
// 로그용
var logString;
......@@ -39,7 +40,8 @@ router.get('/', function(req, res){
var msg;
var errMsg = req.flash('error')
if(errMsg) msg = errMsg;
console.log(logString+'익명의 유저가 로그인 중입니다.')
var ip = requestIp.getClientIp(req);
console.log(logString+'익명의 유저가 로그인 중입니다.('+ip+')')
res.render('login.ejs', {'message' : msg});
})
......@@ -62,18 +64,19 @@ passport.use('local-login', new LocalStrategy({
var query = connection.query('select * from userDB where ID=?', [ID], function(err, rows){
if(err) return done(err);
var ip = requestIp.getClientIp(req);
if(rows.length){ // database에 입력한 ID값이 있는가?
if(password == rows[0].password){ // 비밀번호와 확인이 같은가?
console.log(logString+"로그인 알림: "+ ID +"(" + rows[0].nickname + ")")
console.log(logString+"로그인 알림: "+ ID +"(" + rows[0].nickname +" // "+ip+')')
return done(null, {'ID' : ID, 'nickname' : rows[0].nickname});
}
else{
console.log(logString+"로그인 알림: 잘못된 비밀번호입니다.(시도된 아이디: "+ID+")")
console.log(logString+"로그인 알림: 잘못된 비밀번호입니다.(시도된 아이디: "+ID+" // "+ip+')')
return done(null, false, {message : '잘못된 비밀번호입니다.'})
}
}
else{
console.log(logString+"로그인 알림: ID를 찾을 수 없습니다.(시도된 아이디: "+ID+")")
console.log(logString+"로그인 알림: ID를 찾을 수 없습니다.(시도된 아이디: "+ID+" // "+ip+')')
return done(null, false, {message : 'ID를 찾을 수 없습니다.'})
}
})
......
......@@ -2,6 +2,7 @@ var express = require('express')
var app = express()
var router = express.Router();
var path = require('path')
var requestIp = require('request-ip');
// 로그용
var logString;
......@@ -23,13 +24,14 @@ function init(){
init()
router.get('/', function(req, res){
var ip = requestIp.getClientIp(req);
var id = req.user;
if(!id){
console.log(logString+"익명 유저의 로그아웃 시도를 거부했습니다.")
console.log(logString+"익명 유저의 로그아웃 시도를 거부했습니다.("+ip+')')
res.redirect('/main')
}
else{
console.log(logString+req.user.ID+"("+req.user.nickname+") 유저가 로그아웃합니다.")
console.log(logString+req.user.ID+"("+req.user.nickname+") 유저가 로그아웃합니다.("+ip+')')
req.logout();
req.session.save(function(){
res.redirect('/');
......
......@@ -2,6 +2,7 @@ var express = require('express')
var app = express()
var router = express.Router();
var path = require('path') // 상대경로
var requestIp = require('request-ip');
// 로그용
var logString;
......@@ -24,14 +25,15 @@ init()
// main page는 login이 된 상태(세션정보가 있을때만) 접근이 가능하게 하자 -> info에 구현해놓음.
router.get('/', function(req, res){
var ip = requestIp.getClientIp(req);
var id = req.user;
if(!id){
console.log(logString+'익명의 유저가 작업 중입니다.')
console.log(logString+'익명의 유저가 작업 중입니다.('+ip+')')
res.sendFile(path.join(__dirname, "../../public/main.html"))
}
if(id){
var nickname = req.user.nickname;
console.log(logString+req.user.ID+'('+nickname+') 유저가 작업 중입니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 작업 중입니다.('+ip+')')
res.render('main.ejs', {'ID': id, 'nickname': nickname});
}
});
......
......@@ -6,6 +6,7 @@ var mysql_odbc = require('../../db/db_board')();
var myinfo = mysql_odbc.init();
var passport = require('passport')
var LocalStrategy = require('passport-local').Strategy
var requestIp = require('request-ip');
// 로그용
var logString;
......@@ -39,6 +40,7 @@ passport.deserializeUser(function(user, done){
// main page는 login이 된 상태(세션정보가 있을때만) 접근이 가능하게 하자 -> info에 구현해놓음.
router.get('/', function(req, res){
var ip = requestIp.getClientIp(req);
try{
var id = req.session.passport.user.ID;
// if(!id){
......@@ -53,18 +55,19 @@ router.get('/', function(req, res){
var nickname = req.user.nickname;
var type = rows[0].type;
var profilemsg = rows[0].profilemsg;
console.log(logString+req.user.ID+'('+nickname+') 유저가 프로필을 보고있습니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 프로필을 보고있습니다.('+ip+')')
res.render('profile.ejs', {'ID':id, 'nickname': nickname, 'type': type, 'profilemsg': profilemsg})
})
}
catch{
console.log(logString+'익명 유저의 프로필 접근 시도를 거부했습니다.')
console.log(logString+'익명 유저의 프로필 접근 시도를 거부했습니다.('+ip+')')
res.sendFile(path.join(__dirname, "../../public/login.html"))
}
});
router.get('/update', function(req,res){
var ip = requestIp.getClientIp(req);
try{
var id = req.user.ID;
// if(!id){
......@@ -80,19 +83,20 @@ router.get('/update', function(req,res){
var nickname = req.user.nickname;
var type = req.user.type;
var profilemsg = rows[0].profilemsg;
console.log(logString+req.user.ID+'('+nickname+') 유저가 프로필 수정 중입니다.')
console.log(logString+req.user.ID+'('+nickname+') 유저가 프로필 수정 중입니다.('+ip+')')
res.render('profmsgedit.ejs', {'ID':id, 'nickname': nickname, 'type':type, 'profilemsg': profilemsg, 'message':''});
})
}
catch{
if(!id){
console.log(logString+'익명 유저의 프로필 수정 시도를 거부했습니다.')
console.log(logString+'익명 유저의 프로필 수정 시도를 거부했습니다.('+ip+')')
res.sendFile(path.join(__dirname, "../../public/login.html"))
}
}
})
router.post('/update', function(req,res,next){
var ip = requestIp.getClientIp(req);
var id = req.user.ID;
var profilemsg = req.body.profilemsg;
var nickname = req.body.nickname;
......@@ -127,7 +131,7 @@ router.post('/update', function(req,res,next){
myinfo.query(sql,datas,function(err,result){
if(err) console.error(err)
console.log(logString+req.user.ID+'('+req.session.passport.user.nickname+') 유저가 프로필을 수정했습니다.')
console.log(logString+req.user.ID+'('+req.session.passport.user.nickname+') 유저가 프로필을 수정했습니다.('+ip+')')
console.log(" ▷ 변경전: "+id+"("+req.user.nickname+") "+oldType+" // "+oldProfilemsg)
req.session.passport.user.nickname = nickname;
console.log(" ▶ 변경후: "+id+"("+nickname+") "+type+" // "+profilemsg)
......@@ -135,7 +139,7 @@ router.post('/update', function(req,res,next){
})
}
else{ // 다른 유저의 닉네임과 중복되는 경우
console.log(logString+id+" 유저가 중복된 닉네임으로 변경을 시도했습니다.(시도한 닉네임: "+req.body.nickname+")")
console.log(logString+id+" 유저가 중복된 닉네임으로 변경을 시도했습니다.(시도한 닉네임: "+req.body.nickname+" // ("+ip+')')
res.render('profmsgedit.ejs', {nickname: req.session.passport.user.nickname, profilemsg: oldProfilemsg, message : '중복된 닉네임입니다.'})
}
})
......
......@@ -5,6 +5,7 @@ var path = require('path') // 상대경로
var mysql = require('mysql')
var passport = require('passport')
var LocalStrategy = require('passport-local').Strategy
var requestIp = require('request-ip');
// 로그용
var logString;
......@@ -39,7 +40,8 @@ router.get('/', function(req, res){
var msg;
var errMsg = req.flash('error')
if(errMsg) msg = errMsg;
console.log(logString+'익명의 유저가 회원가입 중입니다.')
var ip = requestIp.getClientIp(req);
console.log(logString+'익명의 유저가 회원가입 중입니다.('+ip+')')
res.render('register.ejs', {'message' : msg});
})
......@@ -63,29 +65,30 @@ passport.use('local-join', new LocalStrategy({
passReqToCallback: true
}, function(req, ID, password, done){
var query = connection.query('select * from userDB where ID=?', [ID], function(err, rows){
if(err) return done(err);
var ip = requestIp.getClientIp(req);
if(err) return done(err);
if(rows.length){ // database에 입력한 ID값이 있는가?
console.log(logString+"회원가입 알림: 중복된 ID입니다.("+ID+")")
console.log(logString+"회원가입 알림: 중복된 ID입니다.("+ID+" // "+ip+')')
return done(null, false, {message : '중복된 ID입니다.'})
}
else{
if(password != req.body.pw_com){ // 비밀번호와 확인이 같지 않은가?
console.log(logString+"회원가입 알림: 비밀번호가 일치하지 않습니다.(시도 중인 아이디: "+ID+")")
console.log(logString+"회원가입 알림: 비밀번호가 일치하지 않습니다.(시도 중인 아이디: "+ID+" // "+ip+')')
return done(null, false, {message : '비밀번호가 일치하지 않습니다.'})
}
else{
var subqry = connection.query('select * from userDB where nickname=?', [req.body.nickname], function(err, rows_){
if(err) return done(err);
if(rows_.length){
console.log(logString+"회원가입 알림: 중복된 닉네임입니다.("+req.body.nickname+")")
console.log(logString+"회원가입 알림: 중복된 닉네임입니다.("+req.body.nickname+" // "+ip+')')
return done(null, false, {message : '중복된 닉네임입니다.'})
}
else{
var sql = {ID: ID, password: password, type:req.body.type, nickname:req.body.nickname};
var query = connection.query('insert into userDB set ?', sql, function(err, rows){
if(err) throw err
console.log(logString+"회원가입 알림: 사용자가 추가되었습니다.(" + ID +", " + req.body.nickname + ")")
console.log(logString+"회원가입 알림: 사용자가 추가되었습니다.(" + ID +", " + req.body.nickname + " // "+ip+')')
return done(null, {'ID' : ID, 'nickname' : req.body.nickname});
})
}
......