Newer
Older
await this.saveSession();
return super.end();
}
/**
* Calls cozy-konnector-libs requestFactory forcing this._jar as the cookie
*
* @param {object} options - requestFactory option
* @returns {object} - The resulting request object
*/
requestFactory(options) {
this._jar = this._jar || requestFactory().jar();
return requestFactory({ ...options,
jar: this._jar
});
}
/**
* Reset cookie session with a new empty session and save it to the associated account
*
* @returns {Promise} empty promise
*/
async resetSession() {
log('debug', 'Reset cookie session...');
this._jar = requestFactory().jar();
return this.saveSession();
}
/**
* Get the cookie session from the account if any
*
* @returns {Promise} true or false if the session in the account exists or not
*/
async initSession() {
const accountData = this.getAccountData();
try {
if (this._account.state === 'RESET_SESSION') {
log('debug', 'RESET_SESSION state found');
await this.resetSession();
await this.updateAccountAttributes({
state: null
});
} catch (err) {
log('warn', 'Could not reset the session');
log('warn', err.message);
}
try {
let jar = null;
if (accountData && accountData.auth) {
jar = JSON.parse(accountData.auth[JAR_ACCOUNT_KEY]);
if (jar) {
log('debug', 'found saved session, using it...');
this._jar._jar = CookieJar.fromJSON(jar, this._jar._jar.store);
return true;
} catch (err) {
log('debug', 'Could not parse session');
log('debug', 'Found no session');
return false;
/**
* Saves the current cookie session to the account
*
* @returns {Promise} empty promise
*/
async saveSession(obj) {
const accountData = { ...this._account.data,
auth: {}
};
if (obj && obj.getCookieJar) {
this._jar._jar = obj.getCookieJar();
accountData.auth[JAR_ACCOUNT_KEY] = JSON.stringify(this._jar._jar.toJSON());
await this.saveAccountData(accountData);
log('debug', 'saved the session');
/**
* This is signin function from cozy-konnector-libs which is forced to use the current cookies
* and current request from CookieKonnector. It also automatically saves the session after
* signin if it is a success.
*
* @returns {Promise} resolve with an object containing form data
*/
async signin(options) {
const result = await super.signin({ ...options,
requestInstance: this.request
});
await this.saveSession();
return result;
/**
* This is saveFiles function from cozy-konnector-libs which is forced to use the current cookies
* and current request from CookieKonnector.
*
* @returns {Promise} resolves with the list of entries with file objects
*/
saveFiles(entries, fields, options) {
return super.saveFiles(entries, fields, { ...options,
requestInstance: this.request
});
/**
* This is saveBills function from cozy-konnector-libs which is forced to use the current cookies
* and current request from CookieKonnector.
*
* @returns {Promise} resolves with entries hydrated with db data
*/
saveBills(entries, fields, options) {
return super.saveBills(entries, fields, { ...options,
requestInstance: this.request
});
module.exports = CookieKonnector;
/***/ (function(module, exports, __webpack_require__) {
const {
URL
} = __webpack_require__(82);
const computeWidth = $table => {
let out = 0;
const tds = $table.find('tr').first().find('td,th');
for (var i = 0; i < tds.length; i++) {
out += parseInt(tds.eq(i).attr('colspan')) || 1;
}
const makeLinkOpts = ($el, opts) => {
if ($el.attr('href') === undefined) return undefined;
if ($el.attr('href').indexOf('javascript:') === 0) return undefined;
if ($el.attr('href').indexOf('#') === 0) return undefined;
return {
link: new URL($el.attr('href'), opts.baseURL).toString(),
color: '0x0000FF'
};
};
function htmlToPDF($, frag, $parent, opts) {
let pdf, helveticaBold, helveticaEm; // pdfjs is an optional dependency, this is why the requires are done in
// a try/catch. webpack detects this and does not crash when building
// if requires are done in a try/catch.
try {
pdf = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module 'pdfjs'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
helveticaBold = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module 'pdfjs/font/Helvetica-Bold'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
helveticaEm = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module 'pdfjs/font/Helvetica-Oblique'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
} catch (err) {
throw new Error('pdfjs dependency is missing. Please add it in your package.json');
opts = Object.assign({
baseURL: '',
filter: () => true,
txtOpts: {}
}, opts);
const children = $parent.contents();
let text = opts.text;
let parentDL = null;
const getText = () => {
if (!text) text = frag.text('', opts.txtOpts);
return text;
};
children.each((i, el) => {
if (el.nodeType === 3 && el.data.trim() !== '') {
getText().add(el.data);
} else if (el.nodeType === 1) {
const $el = $(el);
if (!opts.filter($el)) return;
switch (el.tagName) {
case 'a':
getText().add($el.text(), makeLinkOpts($el, opts));
break;
case 'strong':
case 'b':
getText().add($el.text(), {
font: helveticaBold
});
break;
case 'em':
getText().add($el.text(), {
font: helveticaEm
});
break;
case 'span':
htmlToPDF($, frag, $el, Object.assign({}, opts, {
text: text
}));
break;
case 'br':
getText().br();
break;
case 'i':
case 'select':
case 'input':
case 'label':
case 'form':
case 'fieldset':
case 'textarea':
case 'button':
case 'img':
case 'script':
case 'caption':
// ignore
break;
219244
219245
219246
219247
219248
219249
219250
219251
219252
219253
219254
219255
219256
219257
219258
case 'table':
{
text = null;
let width = computeWidth($el);
let tableState = {
tableWidth: width
};
htmlToPDF($, frag.table({
widths: Array.from(Array(width), () => '*'),
borderWidth: 1
}), $el, Object.assign({}, opts, {
tableState
}));
break;
}
case 'tr':
{
text = null;
opts.tableState.colRemaining = opts.tableState.tableWidth;
let row = frag.row();
htmlToPDF($, row, $el, opts);
if (opts.tableState.colRemaining > 0) {
row.cell({
colspan: opts.tableState.colRemaining
});
}
case 'dl':
text = null;
htmlToPDF($, frag.table({
widths: [5 * pdf.cm, null],
borderWidth: 1
}), $el, { ...opts,
tableState: {
tableWidth: 2,
colRemaining: 2
}
});
parentDL = null;
break;
case 'dt':
if (!parentDL) {
parentDL = frag;
} else {
frag = parentDL;
}
frag = frag.row();
// fall through the rest of the procedure
case 'dd':
case 'th':
case 'td':
{
text = null;
const colspan = Math.min(opts.tableState.tableWidth, parseInt($el.attr('colspan')) || 1);
opts.tableState.colRemaining -= colspan;
htmlToPDF($, frag.cell({
padding: 5,
colspan: colspan
}), $el, opts);
break;
}
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
text = null;
htmlToPDF($, frag, //.cell({ paddingTop: 1 * pdf.cm }),
$el, Object.assign({}, opts, {
txtOpts: {
fontSize: 30 - parseInt(el.tagName.replace('h', '')) * 2
}
}));
break;
case 'div':
case 'p':
case 'ul':
text = null;
htmlToPDF($, frag.cell(), $el, opts);
break;
case 'thead':
case 'tfoot':
case 'tbody':
case 'small':
case 'li':
text = null;
htmlToPDF($, frag, $el, opts);
break;
default:
text = null;
htmlToPDF($, frag, $el, opts);
function createCozyPDFDocument(headline, url) {
let pdf, helveticaBold; // pdfjs is an optional dependency, this is why the requires are done in
// a try/catch. webpack detects this and does not crash when building
// if requires are done in a try/catch.
try {
pdf = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module 'pdfjs'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
helveticaBold = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module 'pdfjs/font/Helvetica-Bold'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
} catch (err) {
throw new Error('pdfjs dependency is missing. Please add it in your package.json');
var doc = new pdf.Document();
const cell = doc.cell({
paddingBottom: 0.5 * pdf.cm
}).text();
cell.add(headline, {
font: helveticaBold,
fontSize: 14
});
cell.add(url, {
link: url,
color: '0x0000FF'
});
return doc;
module.exports = {
htmlToPDF,
createCozyPDFDocument
};
/***/ }),
/* 1731 */
/***/ (function(module, exports, __webpack_require__) {
const isEqualWith = __webpack_require__(1732);
const omit = __webpack_require__(902);
const maybeToISO = date => {
try {
return date.toISOString ? date.toISOString() : date;
} catch (e) {
return date;
const looseDates = (val, otherVal) => {
// Loose equality for dates since when coming from Couch, they
// are ISO strings whereas just after scraping they are `Date`s.
if (val instanceof Date) {
return maybeToISO(val) === maybeToISO(otherVal);
};
/**
* Simple Model for Documents. Allows to specify
* `shouldSave`, `shouldUpdate` as methods.
*
* Has useful `isEqual` method
*
*/
class Document {
constructor(attrs) {
if (this.validate) {
this.validate(attrs);
Object.assign(this, attrs, {
metadata: {
version: attrs.metadata && attrs.metadata.version || this.constructor.version
toJSON() {
return this;
/**
* Compares to another document deeply.
*
* `_id` and `_rev` are by default ignored in the comparison.
*
* By default, will compare dates loosely since you often
* compare existing documents (dates in ISO string) with documents
* that just have been scraped where dates are `Date`s.
*/
isEqual(other, ignoreAttrs = ['_id', '_rev'], strict = false) {
return isEqualWith(omit(this, ignoreAttrs), omit(other, ignoreAttrs), !strict && looseDates);
module.exports = Document;
/***/ (function(module, exports, __webpack_require__) {
var baseIsEqual = __webpack_require__(476);
219457
219458
219459
219460
219461
219462
219463
219464
219465
219466
219467
219468
219469
219470
219471
219472
219473
219474
219475
219476
219477
219478
219479
219480
219481
219482
219483
219484
219485
219486
219487
219488
219489
219490
219491
219492
219493
/**
* This method is like `_.isEqual` except that it accepts `customizer` which
* is invoked to compare values. If `customizer` returns `undefined`, comparisons
* are handled by the method instead. The `customizer` is invoked with up to
* six arguments: (objValue, othValue [, index|key, object, other, stack]).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @param {Function} [customizer] The function to customize comparisons.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* function isGreeting(value) {
* return /^h(?:i|ello)$/.test(value);
* }
*
* function customizer(objValue, othValue) {
* if (isGreeting(objValue) && isGreeting(othValue)) {
* return true;
* }
* }
*
* var array = ['hello', 'goodbye'];
* var other = ['hi', 'goodbye'];
*
* _.isEqualWith(array, other, customizer);
* // => true
*/
function isEqualWith(value, other, customizer) {
customizer = typeof customizer == 'function' ? customizer : undefined;
var result = customizer ? customizer(value, other) : undefined;
return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
}
module.exports = isEqualWith;
/***/ }),
/* 1733 */
/***/ (function(module, exports, __webpack_require__) {
const log = __webpack_require__(2).namespace('scrape');
/**
* Declarative scraping.
*
* Describe your items attributes and where to find/parse them
* instead of imperatively building them.
*
* Heavily inspired by [artoo] scraping method.
*
* [artoo]: https://medialab.github.io/artoo/
*/
const mkSpec = function (spec) {
if (typeof spec === 'string') {
return {
sel: spec
};
} else {
return spec;
219523
219524
219525
219526
219527
219528
219529
219530
219531
219532
219533
219534
219535
219536
219537
219538
219539
219540
219541
219542
219543
219544
219545
219546
219547
219548
219549
219550
219551
219552
219553
219554
219555
219556
219557
219558
219559
219560
219561
219562
219563
219564
219565
219566
219567
219568
219569
219570
219571
219572
219573
219574
219575
219576
};
/**
* Scrape a cheerio object for properties
*
* @param {object} $ - Cheerio node which will be scraped
* @param {object|string} specs - Options object describing what you want to scrape
* @param {string} [childSelector] - If passed, scrape will return an array of items
* @returns {object|Array} - Item(s) scraped
* @example
*
* `scrape` can be used to declaratively extract data :
*
* - For one object :
*
* ```
* const item = scrape($('#item'), {
* title: '.title',
* content: '.content'
* })
* ```
*
* - For a list of objects :
*
* ```
* const items = scrape($('#content'), {
* title: '.title',
* content: '.content'
* }, '.item')
* ```
*
* For more power, you can use `object`s for each retriever :
*
* ```
* const items = scrape($('#content'), {
* title: '.title',
* content: '.content',
* link: {
* sel: 'a',
* attr: 'href'
* },
* }, '.item')
* ```
*
* Here the `href` attribute of the `a` inside `.item`s would have been
* put into the `link` attribute of the items returned by `scrape`.
*
* Available options :
*
* - `sel`: the CSS selector used to target the HTML node from which data will be scraped
* - `attr`: the HTML attribute from which to extract data
* - `parse`: function applied to the value extracted (`{ sel: '.price', parse: parseAmount }`)
* - `fn`: if you need something more complicated than `attr`, you can use this function, it receives
* the complete DOM node. `{ sel: '.person', fn: $node => $node.attr('data-name') + $node.attr('data-firstname') }`
*/
const scrape = ($, specs, childSelector) => {
// Only one value shorthand
if (typeof specs === 'string' || specs.sel && typeof specs.sel === 'string') {
const {
val
} = scrape($, {
val: specs
});
return val;
} // Several items shorthand
if (childSelector !== undefined) {
return Array.from(($.find || $)(childSelector)).map(e => scrape($(e), specs));
} // Several properties "normal" case
const res = {};
Object.keys(specs).forEach(specName => {
try {
const spec = mkSpec(specs[specName]);
let data = spec.sel ? $.find(spec.sel) : $;
if (spec.index) {
data = data.get(spec.index);
}
if (spec.fn) {
val = spec.fn(data);
} else if (spec.attr) {
val = data.attr(spec.attr);
} else {
val = data;
val = val && val.text();
val = val && val.trim();
}
if (spec.parse) {
val = spec.parse(val);
}
res[specName] = val;
} catch (e) {
log('warn', 'Could not parse for', specName);
log('warn', e);
}
});
return res;
};
/* 1734 */
/***/ (function(module, exports) {
219637
219638
219639
219640
219641
219642
219643
219644
219645
219646
219647
219648
219649
219650
219651
219652
219653
219654
219655
219656
219657
219658
219659
219660
219661
219662
219663
219664
219665
219666
219667
219668
219669
219670
219671
/**
* Returns the given name, replacing characters that could be an issue when
* used in a filename with spaces.
*
* @module normalizeFilename
*/
const normalizableCharsRegExp = /[<>:"/\\|?*\0\s]+/g;
/**
* Returns the given name, replacing characters that could be an issue when
* used in a filename with spaces.
*
* Replaced characters include:
*
* - Those forbidden on one or many popular OS or filesystem: `<>:"/\|?*`
* - Those forbidden by the cozy-stack `\0`, `\r` and `\n`
* - Multiple spaces and/or tabs are replaced with a single space
* - Leading & trailing spaces and/or tabs are removed
*
* An exception will be thrown in case there is not any filename-compatible
* character in the given name.
*
* Parameters:
*
* - `basename` is whatever string you want to generate the filename from
* - `ext` is an optional file extension, with or without leading dot
*
* ```javascript
* const { normalizeFilename } = require('cozy-konnector-libs')
*
* const filename = normalizeFilename('*foo/bar: <baz> \\"qux"\t???', '.txt')
* // `filename` === `foo bar baz qux.txt`
* ```
*
* @alias module:normalizeFilename
*/
const normalizeFilename = (basename, ext) => {
const filename = basename.replace(normalizableCharsRegExp, ' ').trim();
if (filename === '') {
throw new Error('Cannot find any filename-compatible character in ' + JSON.stringify(filename) + '!');
if (ext == null) ext = '';else if (!ext.startsWith('.')) ext = '.' + ext;
return filename + ext;
};
module.exports = normalizeFilename;
/***/ }),
/* 1735 */
/***/ (function(module, exports, __webpack_require__) {
/**
* Use every possible means to solve a captcha. At the moment, Anticaptcha web service is used if
* any related secret key is found in COZY_PARAMETERS environment variable.
*
* @module solveCaptcha
*/
const log = __webpack_require__(2).namespace('solveCaptcha');
const errors = __webpack_require__(1654);
const request = __webpack_require__(24);
const sleep = __webpack_require__(9).promisify(global.setTimeout);
const connectorStartTime = Date.now();
const ms = 1;
const s = 1000 * ms;
const m = 60 * s;
const DEFAULT_TIMEOUT = connectorStartTime + 3 * m; // 3 minutes by default to let 1 min to the connector to fetch files
219710
219711
219712
219713
219714
219715
219716
219717
219718
219719
219720
219721
219722
219723
219724
219725
219726
219727
219728
219729
219730
219731
219732
219733
219734
219735
219736
219737
219738
219739
219740
/**
* Use every possible means to solve a captcha. At the moment, Anticaptcha web service is used if
* any related secret key is found in COZY_PARAMETERS environment variable.
* If you do not want to solve the captcha each time the connector is run, please also use
* CookieKonnector which will help you save the session.
*
* Parameters:
*
* - `params` is an array of objects with any attributes with some mandatory attributes :
* + `type` (String): (default recaptcha) type of captcha to solve. can be "recaptcha" or "image" at the moment
* + `timeout` (Number): (default 3 minutes after now) time when the solver should stop trying to
* solve the captcha
* + `websiteKey` (String): the key you can find on the targeted website (for recaptcha)
* + `websiteURL` (String): The URL of the page showing the captcha (for recaptcha)
* + `body` (String): The base64 encoded image (for image captcha)
* Returns: Promise with the solved captcha response as a string
*
* @example
*
* ```javascript
* const { solveCaptcha } = require('cozy-konnector-libs')
*
* const solvedKey = await solveCaptcha({
* websiteKey: 'the key in the webpage',
* websiteURL: 'http://quotes.toscrape.com/login',
* })
* // now use the solveKey to submit your form
* ```
*
* @alias module:solveCaptcha
*/
const solveCaptcha = async (params = {}) => {
const defaultParams = {
type: 'recaptcha',
timeout: DEFAULT_TIMEOUT
};
params = { ...defaultParams,
...params
};
const secrets = JSON.parse(process.env.COZY_PARAMETERS || '{}').secret;
219752
219753
219754
219755
219756
219757
219758
219759
219760
219761
219762
219763
219764
219765
219766
219767
219768
219769
219770
219771
219772
219773
219774
219775
219776
219777
219778
219779
219780
219781
219782
219783
if (params.type === 'recaptcha') {
checkMandatoryParams(params, ['websiteKey', 'websiteURL']);
const {
websiteKey,
websiteURL
} = params;
return solveWithAntiCaptcha({
websiteKey,
websiteURL,
type: 'NoCaptchaTaskProxyless'
}, params.timeout, secrets, 'gRecaptchaResponse');
} else if (params.type === 'recaptchav3') {
checkMandatoryParams(params, ['websiteKey', 'websiteURL', 'pageAction', 'minScore']);
const {
websiteKey,
websiteURL,
pageAction,
minScore
} = params;
return solveWithAntiCaptcha({
websiteKey,
websiteURL,
pageAction,
minScore,
type: 'RecaptchaV3TaskProxyless'
}, params.timeout, secrets, 'gRecaptchaResponse');
} else if (params.type === 'image') {
checkMandatoryParams(params, ['body']);
return solveWithAntiCaptcha({
body: params.body,
type: 'ImageToTextTask'
}, params.timeout, secrets, 'text');
function checkMandatoryParams(params = {}, mandatoryParams = []) {
const keys = Object.keys(params);
const missingKeys = mandatoryParams.filter(key => !keys.includes(key));
if (missingKeys.length) {
throw new Error(`${missingKeys.join(', ')} are mandatory to solve the captcha`);
async function solveWithAntiCaptcha(taskParams, timeout = DEFAULT_TIMEOUT, secrets, resultAttribute = 'gRecaptchaResponse') {
const antiCaptchaApiUrl = 'https://api.anti-captcha.com';
let gRecaptchaResponse = null;
const startTime = Date.now(); // we try to solve the captcha with anticaptcha
const clientKey = secrets.antiCaptchaClientKey;
if (clientKey) {
log('debug', ' Creating captcha resolution task...');
const task = await request.post(`${antiCaptchaApiUrl}/createTask`, {
body: {
clientKey,
task: taskParams
},
json: true
});
if (task && task.taskId) {
log('debug', ` Task id : ${task.taskId}`);
while (!gRecaptchaResponse) {
const resp = await request.post(`${antiCaptchaApiUrl}/getTaskResult`, {
body: {
clientKey,
taskId: task.taskId
},
json: true
});
if (resp.status === 'ready') {
if (resp.errorId) {
log('error', `Anticaptcha error: ${JSON.stringify(resp)}`);
throw new Error(errors.CAPTCHA_RESOLUTION_FAILED);
log('info', ` Found Recaptcha response : ${JSON.stringify(resp)}`);
return resp.solution[resultAttribute];
} else {
log('debug', ` ${Math.round((Date.now() - startTime) / 1000)}s...`);
if (Date.now() > timeout) {
log('warn', ` Captcha resolution timeout`);
throw new Error(errors.CAPTCHA_RESOLUTION_FAILED + '.TIMEOUT');
} else {
log('warn', 'Could not create anticaptcha task');
log('warn', JSON.stringify(task));
} else {
log('warn', 'Could not find any anticaptcha secret key');
}
throw new Error(errors.CAPTCHA_RESOLUTION_FAILED);
}
module.exports = solveCaptcha;
/***/ }),
/* 1736 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(module) {var require;//! moment.js
//! version : 2.29.1
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
;(function (global, factory) {
true ? module.exports = factory() :
undefined
}(this, (function () { 'use strict';
function hooks() {
return hookCallback.apply(null, arguments);
// This is done to register the method called with moment()
// without creating circular dependencies.
function setHookCallback(callback) {
hookCallback = callback;
function isArray(input) {
return (
input instanceof Array ||
Object.prototype.toString.call(input) === '[object Array]'
);
function isObject(input) {
// IE8 will treat undefined and null as object if it wasn't for
// input != null
return (
input != null &&
Object.prototype.toString.call(input) === '[object Object]'
);
function hasOwnProp(a, b) {
return Object.prototype.hasOwnProperty.call(a, b);
function isObjectEmpty(obj) {
if (Object.getOwnPropertyNames) {
return Object.getOwnPropertyNames(obj).length === 0;
} else {
var k;
for (k in obj) {
if (hasOwnProp(obj, k)) {
return false;
}
}
return true;
function isUndefined(input) {
return input === void 0;
}
function isNumber(input) {
return (
typeof input === 'number' ||
Object.prototype.toString.call(input) === '[object Number]'
);
}
function isDate(input) {
return (
input instanceof Date ||
Object.prototype.toString.call(input) === '[object Date]'
);
function map(arr, fn) {
var res = [],
i;
for (i = 0; i < arr.length; ++i) {
res.push(fn(arr[i], i));
}
return res;
function extend(a, b) {
for (var i in b) {
if (hasOwnProp(b, i)) {
a[i] = b[i];
}
}
if (hasOwnProp(b, 'toString')) {
a.toString = b.toString;
if (hasOwnProp(b, 'valueOf')) {
a.valueOf = b.valueOf;
function createUTC(input, format, locale, strict) {
return createLocalOrUTC(input, format, locale, strict, true).utc();
219967
219968
219969
219970
219971
219972
219973
219974
219975
219976
219977
219978
219979
219980
219981
219982
219983
219984
219985
219986
function defaultParsingFlags() {
// We need to deep clone this object.
return {
empty: false,
unusedTokens: [],
unusedInput: [],
overflow: -2,
charsLeftOver: 0,
nullInput: false,
invalidEra: null,
invalidMonth: null,
invalidFormat: false,
userInvalidated: false,
iso: false,
parsedDateParts: [],
era: null,
meridiem: null,
rfc2822: false,
weekdayMismatch: false,
};
function getParsingFlags(m) {
if (m._pf == null) {
m._pf = defaultParsingFlags();
}
return m._pf;
var some;
if (Array.prototype.some) {
some = Array.prototype.some;
} else {
some = function (fun) {