www/nginx: release 1.0

This commit is contained in:
Franco Fichtner 2018-09-03 07:52:44 +02:00
parent a9a293dae2
commit 33b089f074
51 changed files with 6490 additions and 21 deletions

View file

@ -1,8 +1,7 @@
PLUGIN_NAME= nginx
PLUGIN_VERSION= 0.4
PLUGIN_COMMENT= Nginx HTTP server and reverse proxy
PLUGIN_DEPENDS= nginx
PLUGIN_MAINTAINER= franz.fabian.94@gmail.com
PLUGIN_DEVEL= yes
PLUGIN_NAME= nginx
PLUGIN_VERSION= 1.0
PLUGIN_COMMENT= Nginx HTTP server and reverse proxy
PLUGIN_DEPENDS= nginx
PLUGIN_MAINTAINER= franz.fabian.94@gmail.com
.include "../../Mk/plugins.mk"

View file

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Request Denied</title>
<title>Not Found</title>
<meta name="generator" content="OPNsense" />
<meta name="language" content="en-US" />
<style>

View file

@ -0,0 +1,82 @@
<?php
/*
Copyright (C) 2018 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Nginx\Api;
use OPNsense\Base\ApiControllerBase;
use OPNsense\Core\Backend;
use OPNsense\Nginx\Nginx;
class LogsController extends ApiControllerBase
{
private $nginx;
public function accessesAction($uuid = null) {
$this->nginx = new Nginx();
if (!isset($uuid)) {
// emulate REST API -> /accesses delivers a list of servers with access logs
return $this->list_vhosts();
} else {
// emulate REST call for a specific log /accesses/uuid
return $this->call_configd('access', $uuid);
}
}
public function errorsAction($uuid = null) {
$this->nginx = new Nginx();
if (!isset($uuid)) {
// emulate REST API -> /errors delivers a list of servers with error logs
return $this->list_vhosts();
} else {
// emulate REST call for a specific log /errors/uuid
return $this->call_configd('error', $uuid);
}
}
private function call_configd($type, $uuid) {
if (!$this->vhost_exists($uuid)) {
$this->response->setStatusCode(404, "Not Found");
}
$backend = new Backend();
$data = $backend->configdRun('nginx log ' . $type . ' ' . $uuid);
return json_decode($data, true);
}
private function list_vhosts() {
$data = [];
foreach ($this->nginx->http_server->__items as $item) {
$data[] = array('id' => $item->getAttributes()['uuid'], 'server_name' => (string)$item->servername);
}
return $data;
}
private function vhost_exists($uuid) {
$data = $this->nginx->getNodeByReference('http_server.'. $uuid);
return isset($data);
}
}

View file

@ -278,4 +278,31 @@ class SettingsController extends ApiMutableModelControllerBase
{
return $this->setBase('httprewrite', 'http_rewrite', $uuid);
}
// http security headers
public function searchsecurity_headerAction()
{
return $this->searchBase('security_header', array('description'));
}
public function getsecurity_headerAction($uuid = null)
{
$this->sessionClose();
return $this->getBase('security_header', 'security_header', $uuid);
}
public function addsecurity_headerAction()
{
return $this->addBase('security_header', 'security_header');
}
public function delsecurity_headerAction($uuid)
{
return $this->delBase('security_header', $uuid);
}
public function setsecurity_headerAction($uuid)
{
return $this->setBase('security_header', 'security_header', $uuid);
}
}

View file

@ -37,6 +37,10 @@ namespace OPNsense\Nginx;
*/
class IndexController extends \OPNsense\Base\IndexController
{
/**
* show the configuration page /ui/nginx
* @throws \Exception when a form cannot be loaded
*/
public function indexAction()
{
$this->view->settings = $this->getForm("settings");
@ -49,6 +53,14 @@ class IndexController extends \OPNsense\Base\IndexController
$this->view->httprewrite = $this->getForm("httprewrite");
$this->view->naxsi_rule = $this->getForm("naxsi_rule");
$this->view->naxsi_custom_policy = $this->getForm("naxsi_custom_policy");
$this->view->security_headers = $this->getForm("security_headers");
$this->view->pick('OPNsense/Nginx/index');
}
/**
* show the nginx logs page /ui/nginx/index/logs
*/
public function logsAction() {
$this->view->pick('OPNsense/Nginx/logs');
}
}

View file

@ -89,4 +89,9 @@
<type>checkbox</type>
<help>Allow the daemon to use the sendfile function.</help>
</field>
<field>
<id>httpserver.security_header</id>
<label>Security Header</label>
<type>dropdown</type>
</field>
</form>

View file

@ -59,7 +59,7 @@
<label>Upstream Servers</label>
<type>dropdown</type>
<style>selectpicker</style>
<help>Select an upstream to proxy to.</help>
<help>Select an upstream to proxy to or connect via FastCGI if chosen.</help>
</field>
<field>
<id>location.root</id>
@ -103,4 +103,16 @@
<type>checkbox</type>
<help>Force encrypted connections.</help>
</field>
<field>
<id>location.php_enable</id>
<label>Pass Request To Local PHP Interpreter / Threat Upstream As FastCGI</label>
<type>checkbox</type>
<help>Only use this setting if you know what you are doing. If not, expect your machine to get compromised. Use this setting when you want to run a local PHP application or call an external upstream, if selected, via FastCGI. Example upstreams are PHP-FPM or Rails via FastCGI API.</help>
</field>
<field>
<id>location.php_override_scriptname</id>
<label>(PHP) Router Script</label>
<type>text</type>
<help>If you set this setting, all requests are sent to this script instead of the request path (URL). Not using this setting on a remote instance can be dangerous.</help>
</field>
</form>

View file

@ -0,0 +1,547 @@
<form>
<field>
<id>security_header.description</id>
<label>Description</label>
<type>text</type>
<help>This is only for your reference.</help>
</field>
<field>
<id>security_header.referrer</id>
<label>Referrer</label>
<style>selectpicker</style>
<type>dropdown</type>
<help><![CDATA[
<ul>
<li>Same Origin: The header will be sent if you stay on the same server using the same protocol (no data leak)</li>
<li>No Referrer When Downgrade: Prevents sending a referrer when switching from HTTPS to HTTP</li>
<li>Origin, Strict-Origin: Always send the header but no path or query information. Strict Origin additionally suppressed the header on downgrades.</li>
<li>(Strict) Origin When Cross Origin: Full Referrer on the same origin, and like (Strict) Origin when cross domain.</li>
<li>Unsafe URL: Sends the full URL to all pages</li>
</ul> ]]></help>
</field>
<field>
<id>security_header.xssprotection</id>
<label>XSS Protection</label>
<style>selectpicker</style>
<type>dropdown</type>
<help><![CDATA[
<ul>
<li>Block: The browser should block the response</li>
<li>Off: Allow Anything</li>
<li>On: The Browser decides how to handle it.</li>
</ul> ]]></help>
</field>
<field>
<id>security_header.content_type_options</id>
<label>Don't Sniff Content Type</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.strict_transport_security_time</id>
<label>Strict Transport Security: Time</label>
<type>text</type>
<help>A time in seconds in which the transport security (TLS) should be enforced.</help>
</field>
<field>
<id>security_header.strict_transport_security_include_subdomains</id>
<label>Strict Transport Security: Include Subdomains</label>
<type>checkbox</type>
<help>If checked, also subdomains are affected.</help>
</field>
<field>
<id>security_header.hpkp_keys</id>
<label>HTTP Public Key Pinning: Fingerprints</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
<help><![CDATA[ Enter a comma separated list of public key fingerprints here.
You can find some documentetion about this feature in the
<a href="https://developer.mozilla.org/de/docs/Web/Security/Public_Key_Pinning">Mozilla Wiki</a>.
It is not recommended to use this feature with short lived certificates.]]></help>
</field>
<field>
<id>security_header.hpkp_report_only</id>
<label>HTTP Public Key Pinning: Report Only</label>
<type>checkbox</type>
<help>If you only want to test it, you can check this box (policy will be deployed but not enforced).</help>
</field>
<field>
<id>security_header.hpkp_time</id>
<label>HTTP Public Key Pinning: Max Age</label>
<type>text</type>
</field>
<field>
<id>security_header.hpkp_include_subdomains</id>
<label>HTTP Public Key Pinning: Include Subdomains</label>
<type>checkbox</type>
<help>If checked, also subdomains are affected.</help>
</field>
<field>
<id>security_header.enable_csp</id>
<label>Content Security Policy: Enable</label>
<type>checkbox</type>
<help>If checked, the CSP is enabled.</help>
</field>
<field>
<type>header</type>
<label>Content Security Policy: Default Source</label>
</field>
<field>
<id>security_header.csp_default_src_enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>If checked, this part of the CSP is enabled.</help>
</field>
<field>
<id>security_header.csp_default_src_data_urls</id>
<label>Enable Data URLs</label>
<help>Data URLs are used to embed files into HTML (for example images written directly into the src attribute).</help>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_default_src_http_urls</id>
<label>Enable HTTP(S) URLs</label>
<type>select_multiple</type>
<allownew>true</allownew>
<style>tokenize</style>
<help>Allow loading files over HTTP(S) allows downloading of content over other domains or CDNs.
You can use wildcards here like https://*.exmaple.com.</help>
</field>
<field>
<id>security_header.csp_default_src_inline</id>
<label>Enable Inline Scripting</label>
<type>checkbox</type>
<help>Checking this directive allows to use scripts or styles directly embedded in in the HTML content.
Examples are the script and the style tags.</help>
</field>
<field>
<id>security_header.csp_default_src_eval</id>
<label>Enable Eval</label>
<type>checkbox</type>
<help>Checking this box allows functions like eval or createFunction in JS, or style attributes for CSS.</help>
</field>
<field>
<id>security_header.csp_default_src_self</id>
<label>Enable Same Origin (recommended)</label>
<type>checkbox</type>
<help>Allows everything from the same site (path can differ, but host, protocol and port need to be the same).</help>
</field>
<field>
<id>security_header.csp_default_src_blob</id>
<label>Enable Blobs</label>
<type>checkbox</type>
<help>Allows to use blobs as a data source. This usually is content, which is somehow generated in JavaScript.</help>
</field>
<field>
<id>security_header.csp_default_src_mediastream</id>
<label>Enable Media Streams</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_default_src_filesystem</id>
<label>Enable File System URLs</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_default_src_none</id>
<label>Forbid Explicitly</label>
<type>checkbox</type>
<help>If this checkbox is checked, all other settings for this directive are ignored and everything will be forbidden.</help>
</field>
<field>
<type>header</type>
<label>Content Security Policy: Script Source</label>
</field>
<field>
<id>security_header.csp_script_src_enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>If checked, this part of the CSP is enabled.</help>
</field>
<field>
<id>security_header.csp_script_src_data_urls</id>
<label>Enable Data URLs</label>
<help>Data URLs are used to embed files into HTML (for example images written directly into the src attribute).</help>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_script_src_http_urls</id>
<label>Enable HTTP(S) URLs</label>
<type>select_multiple</type>
<allownew>true</allownew>
<style>tokenize</style>
<help>Allow loading files over HTTP(S) allows downloading of content over other domains or CDNs.
You can use wildcards here like https://*.exmaple.com.</help>
</field>
<field>
<id>security_header.csp_script_src_inline</id>
<label>Enable Inline Scripting</label>
<type>checkbox</type>
<help>Checking this directive allows to use scripts or styles directly embedded in in the HTML content.
Examples are the script and the style tags.</help>
</field>
<field>
<id>security_header.csp_script_src_eval</id>
<label>Enable Eval</label>
<type>checkbox</type>
<help>Checking this box allows functions like eval or createFunction in JS, or style attributes for CSS.</help>
</field>
<field>
<id>security_header.csp_script_src_self</id>
<label>Enable Same Origin (recommended)</label>
<type>checkbox</type>
<help>Allows everything from the same site (path can differ, but host, protocol and port need to be the same).</help>
</field>
<field>
<id>security_header.csp_script_src_blob</id>
<label>Enable Blobs</label>
<type>checkbox</type>
<help>Allows to use blobs as a data source. This usually is content, which is somehow generated in JavaScript.</help>
</field>
<field>
<id>security_header.csp_script_src_mediastream</id>
<label>Enable Media Streams</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_script_src_filesystem</id>
<label>Enable File System URLs</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_script_src_none</id>
<label>Forbid Explicitly</label>
<type>checkbox</type>
<help>If this checkbox is checked, all other settings for this directive are ignored and everything will be forbidden.</help>
</field>
<field>
<type>header</type>
<label>Content Security Policy: Image Source</label>
</field>
<field>
<id>security_header.csp_img_src_enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>If checked, this part of the CSP is enabled.</help>
</field>
<field>
<id>security_header.csp_img_src_data_urls</id>
<label>Enable Data URLs</label>
<help>Data URLs are used to embed files into HTML (for example images written directly into the src attribute).</help>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_img_src_http_urls</id>
<label>Enable HTTP(S) URLs</label>
<type>select_multiple</type>
<allownew>true</allownew>
<style>tokenize</style>
<help>Allow loading files over HTTP(S) allows downloading of content over other domains or CDNs.
You can use wildcards here like https://*.exmaple.com.</help>
</field>
<field>
<id>security_header.csp_img_src_inline</id>
<label>Enable Inline Scripting</label>
<type>checkbox</type>
<help>Checking this directive allows to use scripts or styles directly embedded in in the HTML content.
Examples are the script and the style tags.</help>
</field>
<field>
<id>security_header.csp_img_src_eval</id>
<label>Enable Eval</label>
<type>checkbox</type>
<help>Checking this box allows functions like eval or createFunction in JS, or style attributes for CSS.</help>
</field>
<field>
<id>security_header.csp_img_src_self</id>
<label>Enable Same Origin (recommended)</label>
<type>checkbox</type>
<help>Allows everything from the same site (path can differ, but host, protocol and port need to be the same).</help>
</field>
<field>
<id>security_header.csp_img_src_blob</id>
<label>Enable Blobs</label>
<type>checkbox</type>
<help>Allows to use blobs as a data source. This usually is content, which is somehow generated in JavaScript.</help>
</field>
<field>
<id>security_header.csp_img_src_mediastream</id>
<label>Enable Media Streams</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_img_src_filesystem</id>
<label>Enable File System URLs</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_img_src_none</id>
<label>Forbid Explicitly</label>
<type>checkbox</type>
<help>If this checkbox is checked, all other settings for this directive are ignored and everything will be forbidden.</help>
</field>
<field>
<type>header</type>
<label>Content Security Policy: Stylesheet Source</label>
</field>
<field>
<id>security_header.csp_style_src_enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>If checked, this part of the CSP is enabled.</help>
</field>
<field>
<id>security_header.csp_style_src_data_urls</id>
<label>Enable Data URLs</label>
<help>Data URLs are used to embed files into HTML (for example images written directly into the src attribute).</help>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_style_src_http_urls</id>
<label>Enable HTTP(S) URLs</label>
<type>select_multiple</type>
<allownew>true</allownew>
<style>tokenize</style>
<help>Allow loading files over HTTP(S) allows downloading of content over other domains or CDNs.
You can use wildcards here like https://*.exmaple.com.</help>
</field>
<field>
<id>security_header.csp_style_src_inline</id>
<label>Enable Inline Scripting</label>
<type>checkbox</type>
<help>Checking this directive allows to use scripts or styles directly embedded in in the HTML content.
Examples are the script and the style tags.</help>
</field>
<field>
<id>security_header.csp_style_src_eval</id>
<label>Enable Eval</label>
<type>checkbox</type>
<help>Checking this box allows functions like eval or createFunction in JS, or style attributes for CSS.</help>
</field>
<field>
<id>security_header.csp_style_src_self</id>
<label>Enable Same Origin (recommended)</label>
<type>checkbox</type>
<help>Allows everything from the same site (path can differ, but host, protocol and port need to be the same).</help>
</field>
<field>
<id>security_header.csp_style_src_blob</id>
<label>Enable Blobs</label>
<type>checkbox</type>
<help>Allows to use blobs as a data source. This usually is content, which is somehow generated in JavaScript.</help>
</field>
<field>
<id>security_header.csp_style_src_mediastream</id>
<label>Enable Media Streams</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_style_src_filesystem</id>
<label>Enable File System URLs</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_style_src_none</id>
<label>Forbid Explicitly</label>
<type>checkbox</type>
<help>If this checkbox is checked, all other settings for this directive are ignored and everything will be forbidden.</help>
</field>
<field>
<type>header</type>
<label>Content Security Policy: Media Source</label>
</field>
<field>
<id>security_header.csp_media_src_enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>If checked, this part of the CSP is enabled.</help>
</field>
<field>
<id>security_header.csp_media_src_data_urls</id>
<label>Enable Data URLs</label>
<help>Data URLs are used to embed files into HTML (for example images written directly into the src attribute).</help>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_media_src_http_urls</id>
<label>Enable HTTP(S) URLs</label>
<type>select_multiple</type>
<allownew>true</allownew>
<style>tokenize</style>
<help>Allow loading files over HTTP(S) allows downloading of content over other domains or CDNs.
You can use wildcards here like https://*.exmaple.com.</help>
</field>
<field>
<id>security_header.csp_media_src_inline</id>
<label>Enable Inline Scripting</label>
<type>checkbox</type>
<help>Checking this directive allows to use scripts or styles directly embedded in in the HTML content.
Examples are the script and the style tags.</help>
</field>
<field>
<id>security_header.csp_media_src_eval</id>
<label>Enable Eval</label>
<type>checkbox</type>
<help>Checking this box allows functions like eval or createFunction in JS, or style attributes for CSS.</help>
</field>
<field>
<id>security_header.csp_media_src_self</id>
<label>Enable Same Origin (recommended)</label>
<type>checkbox</type>
<help>Allows everything from the same site (path can differ, but host, protocol and port need to be the same).</help>
</field>
<field>
<id>security_header.csp_media_src_blob</id>
<label>Enable Blobs</label>
<type>checkbox</type>
<help>Allows to use blobs as a data source. This usually is content, which is somehow generated in JavaScript.</help>
</field>
<field>
<id>security_header.csp_media_src_mediastream</id>
<label>Enable Media Streams</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_media_src_filesystem</id>
<label>Enable File System URLs</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_media_src_none</id>
<label>Forbid Explicitly</label>
<type>checkbox</type>
<help>If this checkbox is checked, all other settings for this directive are ignored and everything will be forbidden.</help>
</field>
<field>
<type>header</type>
<label>Content Security Policy: Font Source</label>
</field>
<field>
<id>security_header.csp_font_src_enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>If checked, this part of the CSP is enabled.</help>
</field>
<field>
<id>security_header.csp_font_src_data_urls</id>
<label>Enable Data URLs</label>
<help>Data URLs are used to embed files into HTML (for example images written directly into the src attribute).</help>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_font_src_http_urls</id>
<label>Enable HTTP(S) URLs</label>
<type>select_multiple</type>
<allownew>true</allownew>
<style>tokenize</style>
<help>Allow loading files over HTTP(S) allows downloading of content over other domains or CDNs.
You can use wildcards here like https://*.exmaple.com.</help>
</field>
<field>
<id>security_header.csp_font_src_inline</id>
<label>Enable Inline Scripting</label>
<type>checkbox</type>
<help>Checking this directive allows to use scripts or styles directly embedded in in the HTML content.
Examples are the script and the style tags.</help>
</field>
<field>
<id>security_header.csp_font_src_eval</id>
<label>Enable Eval</label>
<type>checkbox</type>
<help>Checking this box allows functions like eval or createFunction in JS, or style attributes for CSS.</help>
</field>
<field>
<id>security_header.csp_font_src_self</id>
<label>Enable Same Origin (recommended)</label>
<type>checkbox</type>
<help>Allows everything from the same site (path can differ, but host, protocol and port need to be the same).</help>
</field>
<field>
<id>security_header.csp_font_src_blob</id>
<label>Enable Blobs</label>
<type>checkbox</type>
<help>Allows to use blobs as a data source. This usually is content, which is somehow generated in JavaScript.</help>
</field>
<field>
<id>security_header.csp_font_src_mediastream</id>
<label>Enable Media Streams</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_font_src_filesystem</id>
<label>Enable File System URLs</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_font_src_none</id>
<label>Forbid Explicitly</label>
<type>checkbox</type>
<help>If this checkbox is checked, all other settings for this directive are ignored and everything will be forbidden.</help>
</field>
<field>
<type>header</type>
<label>Content Security Policy: Form Action</label>
</field>
<field>
<id>security_header.csp_form_action_enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>If checked, this part of the CSP is enabled.</help>
</field>
<field>
<id>security_header.csp_form_action_data_urls</id>
<label>Enable Data URLs</label>
<help>Data URLs are used to embed files into HTML (for example images written directly into the src attribute).</help>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_form_action_http_urls</id>
<label>Enable HTTP(S) URLs</label>
<type>select_multiple</type>
<allownew>true</allownew>
<style>tokenize</style>
<help>Allow loading files over HTTP(S) allows downloading of content over other domains or CDNs.
You can use wildcards here like https://*.exmaple.com.</help>
</field>
<field>
<id>security_header.csp_form_action_inline</id>
<label>Enable Inline Scripting</label>
<type>checkbox</type>
<help>Checking this directive allows to use scripts or styles directly embedded in in the HTML content.
Examples are the script and the style tags.</help>
</field>
<field>
<id>security_header.csp_form_action_eval</id>
<label>Enable Eval</label>
<type>checkbox</type>
<help>Checking this box allows functions like eval or createFunction in JS, or style attributes for CSS.</help>
</field>
<field>
<id>security_header.csp_form_action_self</id>
<label>Enable Same Origin (recommended)</label>
<type>checkbox</type>
<help>Allows everything from the same site (path can differ, but host, protocol and port need to be the same).</help>
</field>
<field>
<id>security_header.csp_form_action_blob</id>
<label>Enable Blobs</label>
<type>checkbox</type>
<help>Allows to use blobs as a data source. This usually is content, which is somehow generated in JavaScript.</help>
</field>
<field>
<id>security_header.csp_form_action_mediastream</id>
<label>Enable Media Streams</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_form_action_filesystem</id>
<label>Enable File System URLs</label>
<type>checkbox</type>
</field>
<field>
<id>security_header.csp_form_action_none</id>
<label>Forbid Explicitly</label>
<type>checkbox</type>
<help>If this checkbox is checked, all other settings for this directive are ignored and everything will be forbidden.</help>
</field>
</form>

View file

@ -0,0 +1,43 @@
<?php
/*
Copyright (C) 2018 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Nginx;
class AccessLogLine
{
public $remote_ip;
public $username;
public $time;
public $status;
public $size;
public $user_agent;
public $request_line;
public $forwarded_for;
public $http_referer;
}

View file

@ -0,0 +1,65 @@
<?php
/*
Copyright (C) 2018 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Nginx;
class AccessLogParser
{
private $file_name;
private $lines;
private $result;
private const LogLineRegex = '/(\S+) - (\S+) \[([\d\sa-z\:\-\/\+]+)\] "([^"]+?)" (\d+) (\d+) "([^"]*?)" "([^"]*?)" "([^"]*?)"/i';
function __construct($file_name)
{
$this->file_name = $file_name;
$this->lines = file($this->file_name);
$this->result = array_map([$this, 'parse_line'], $this->lines);
}
private function parse_line($line) {
$container = new AccessLogLine();
if (preg_match(self::LogLineRegex, $line, $data)) {
$container->remote_ip = $data[1];
$container->username = $data[2];
$container->time = $data[3];
$container->request_line = $data[4];
$container->status = $data[5];
$container->size = $data[6];
$container->user_agent = $data[8];
$container->http_referer = $data[7];
$container->forwarded_for = $data[9];
}
return $container;
}
public function get_result() {
return $this->result;
}
}

View file

@ -0,0 +1,38 @@
<?php
/*
Copyright (C) 2018 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Nginx;
class ErrorLogLine
{
public $date;
public $time;
public $severity;
public $number;
public $message;
}

View file

@ -0,0 +1,60 @@
<?php
/*
Copyright (C) 2018 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Nginx;
class ErrorLogParser
{
private $file_name;
private $lines;
private $result;
private const LogLineRegex = '/(\S+) (\S+) \[([\d\sa-z\:\-\/\+\#]+)\] ([\S:]+): (.+)/i';
function __construct($file_name)
{
$this->file_name = $file_name;
$this->lines = file($this->file_name);
$this->result = array_map([$this, 'parse_line'], $this->lines);
}
private function parse_line($line) {
$container = new ErrorLogLine();
if (preg_match(self::LogLineRegex, $line, $data)) {
$container->date = $data[1];
$container->time = $data[2];
$container->severity = $data[3];
$container->number = $data[4];
$container->message = $data[5];
}
return $container;
}
public function get_result() {
return $this->result;
}
}

View file

@ -1,5 +1,8 @@
<menu>
<Services>
<Nginx cssClass="fa fa-shield fa-fw" url="/ui/nginx" />
<Nginx cssClass="fa fa-shield fa-fw">
<Configuration url="/ui/nginx" />
<Logs url="/ui/nginx/index/logs" />
</Nginx>
</Services>
</menu>

View file

@ -1,5 +1,6 @@
<model>
<mount>//OPNsense/Nginx</mount>
<version>1.1.0</version>
<description>nginx web server, reverse proxy and waf</description>
<items>
<general>
@ -247,6 +248,13 @@
<force_https type="TextField">
<Required>N</Required>
</force_https>
<php_enable type="BooleanField">
<Required>Y</Required>
<default>0</default>
</php_enable>
<php_override_scriptname type="TextField">
<Required>N</Required>
</php_override_scriptname>
</location>
<custom_policy type="ArrayField">
@ -459,6 +467,18 @@
<default>1</default>
<Required>Y</Required>
</sendfile>
<security_header type="ModelRelationField">
<Model>
<template>
<source>OPNsense.Nginx.Nginx</source>
<items>security_header</items>
<display>description</display>
</template>
</Model>
<ValidationMessage>Selected security rule not found</ValidationMessage>
<Required>N</Required>
<multiple>N</multiple>
</security_header>
</http_server>
<http_rewrite type="ArrayField">
@ -484,5 +504,336 @@
</flag>
</http_rewrite>
<security_header type="ArrayField">
<description type="TextField">
<Required>Y</Required>
</description>
<referrer type="OptionField">
<multiple>N</multiple>
<OptionValues>
<no-referrer>No Referrer</no-referrer>
<no-referrer-when-downgrade>No Referrer When Downgrading</no-referrer-when-downgrade>
<same-origin>Same Origin (recommended)</same-origin>
<origin>Origin</origin>
<strict-origin>Strict Origin</strict-origin>
<strict-origin-when-cross-origin>Strict Origin When Cross Origin</strict-origin-when-cross-origin>
<origin-when-cross-origin>Origin When Cross Origin</origin-when-cross-origin>
<unsafe-url>Unsafe URL</unsafe-url>
</OptionValues>
<Required>N</Required>
</referrer>
<xssprotection type="OptionField">
<multiple>N</multiple>
<OptionValues>
<val1 value="1; mode=block">Block</val1>
<val2 value="0">Off</val2>
<val3 value="1">On</val3>
</OptionValues>
<Required>N</Required>
</xssprotection>
<content_type_options type="BooleanField">
<Required>Y</Required>
</content_type_options>
<strict_transport_security_time type="IntegerField">
<Required>N</Required>
</strict_transport_security_time>
<strict_transport_security_include_subdomains type="BooleanField">
<Required>Y</Required>
<default>1</default>
</strict_transport_security_include_subdomains>
<hpkp_keys type="CSVListField">
<Required>N</Required>
<mask>/[a-z0-9\+\/=]+(,[a-z0-9\+\/=]+)*/i</mask>
</hpkp_keys>
<hpkp_report_only type="BooleanField">
<Required>Y</Required>
</hpkp_report_only>
<hpkp_time type="IntegerField">
<Required>N</Required>
</hpkp_time>
<hpkp_include_subdomains type="BooleanField">
<Required>Y</Required>
</hpkp_include_subdomains>
<enable_csp type="BooleanField">
<Required>Y</Required>
</enable_csp>
<csp_report_only type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_report_only>
<csp_default_src_enabled type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_enabled>
<csp_default_src_data_urls type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_data_urls>
<csp_default_src_http_urls type="CSVListField">
<Required>N</Required>
</csp_default_src_http_urls>
<csp_default_src_inline type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_inline>
<csp_default_src_eval type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_eval>
<csp_default_src_self type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_self>
<csp_default_src_blob type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_blob>
<csp_default_src_mediastream type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_mediastream>
<csp_default_src_filesystem type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_filesystem>
<csp_default_src_none type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_default_src_none>
<csp_script_src_enabled type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_enabled>
<csp_script_src_data_urls type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_data_urls>
<csp_script_src_http_urls type="CSVListField">
<Required>N</Required>
</csp_script_src_http_urls>
<csp_script_src_inline type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_inline>
<csp_script_src_eval type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_eval>
<csp_script_src_self type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_self>
<csp_script_src_blob type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_blob>
<csp_script_src_mediastream type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_mediastream>
<csp_script_src_filesystem type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_filesystem>
<csp_script_src_none type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_script_src_none>
<csp_img_src_enabled type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_enabled>
<csp_img_src_data_urls type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_data_urls>
<csp_img_src_http_urls type="CSVListField">
<Required>N</Required>
</csp_img_src_http_urls>
<csp_img_src_inline type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_inline>
<csp_img_src_eval type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_eval>
<csp_img_src_self type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_self>
<csp_img_src_blob type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_blob>
<csp_img_src_mediastream type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_mediastream>
<csp_img_src_filesystem type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_filesystem>
<csp_img_src_none type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_img_src_none>
<csp_style_src_enabled type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_enabled>
<csp_style_src_data_urls type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_data_urls>
<csp_style_src_http_urls type="CSVListField">
<Required>N</Required>
</csp_style_src_http_urls>
<csp_style_src_inline type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_inline>
<csp_style_src_eval type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_eval>
<csp_style_src_self type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_self>
<csp_style_src_blob type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_blob>
<csp_style_src_mediastream type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_mediastream>
<csp_style_src_filesystem type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_filesystem>
<csp_style_src_none type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_style_src_none>
<csp_media_src_enabled type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_enabled>
<csp_media_src_data_urls type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_data_urls>
<csp_media_src_http_urls type="CSVListField">
<Required>N</Required>
</csp_media_src_http_urls>
<csp_media_src_inline type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_inline>
<csp_media_src_eval type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_eval>
<csp_media_src_self type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_self>
<csp_media_src_blob type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_blob>
<csp_media_src_mediastream type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_mediastream>
<csp_media_src_filesystem type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_filesystem>
<csp_media_src_none type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_media_src_none>
<csp_font_src_enabled type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_enabled>
<csp_font_src_data_urls type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_data_urls>
<csp_font_src_http_urls type="CSVListField">
<Required>N</Required>
</csp_font_src_http_urls>
<csp_font_src_inline type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_inline>
<csp_font_src_eval type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_eval>
<csp_font_src_self type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_self>
<csp_font_src_blob type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_blob>
<csp_font_src_mediastream type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_mediastream>
<csp_font_src_filesystem type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_filesystem>
<csp_font_src_none type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_font_src_none>
<csp_form_action_enabled type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_enabled>
<csp_form_action_data_urls type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_data_urls>
<csp_form_action_http_urls type="CSVListField">
<Required>N</Required>
</csp_form_action_http_urls>
<csp_form_action_inline type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_inline>
<csp_form_action_eval type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_eval>
<csp_form_action_self type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_self>
<csp_form_action_blob type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_blob>
<csp_form_action_mediastream type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_mediastream>
<csp_form_action_filesystem type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_filesystem>
<csp_form_action_none type="BooleanField">
<Required>Y</Required>
<default>0</default>
</csp_form_action_none>
</security_header>
</items>
</model>

View file

@ -96,6 +96,7 @@ $( document ).ready(function() {
'httpserver',
'httprewrite',
'custompolicy',
'security_header',
'naxsirule'].forEach(function(element) {
$("#grid-" + element).UIBootgrid(
{ 'search':'/api/nginx/settings/search' + element,
@ -149,6 +150,9 @@ $( document ).ready(function() {
<li>
<a data-toggle="tab" id="subtab_item_nginx-http-naxsirule" href="#subtab_nginx-http-naxsirule">{{ lang._('Naxsi WAF Rule')}}</a>
</li>
<li>
<a data-toggle="tab" id="subtab_item_nginx-http-security_header" href="#subtab_nginx-http-security_header">{{ lang._('Security Headers')}}</a>
</li>
</ul>
</li>
</ul>
@ -367,6 +371,27 @@ $( document ).ready(function() {
</tfoot>
</table>
</div>
<div id="subtab_nginx-http-security_header" class="tab-pane fade">
<table id="grid-security_header" class="table table-condensed table-hover table-striped table-responsive" data-editDialog="security_headersdlg">
<thead>
<tr>
<th data-column-id="description" data-type="string" data-sortable="true" data-visible="true">{{ lang._('Description') }}</th>
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<button type="button" class="btn btn-xs reload_btn btn-primary"><span class="fa fa-refresh reloadAct_progress"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
@ -380,3 +405,4 @@ $( document ).ready(function() {
{{ partial("layout_partials/base_dialog",['fields': httprewrite,'id':'httprewritedlg', 'label':lang._('Edit URL Rewrite')]) }}
{{ partial("layout_partials/base_dialog",['fields': naxsi_custom_policy,'id':'custompolicydlg', 'label':lang._('Edit WAF Policy')]) }}
{{ partial("layout_partials/base_dialog",['fields': naxsi_rule,'id':'naxsiruledlg', 'label':lang._('Edit Naxsi Rule')]) }}
{{ partial("layout_partials/base_dialog",['fields': security_headers,'id':'security_headersdlg', 'label':lang._('Edit Security Headers')]) }}

View file

@ -0,0 +1,32 @@
{#
# Copyright (C) 2017-2018 Fabian Franz
# Copyright (C) 2014-2015 Deciso B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#}
<div id="logapplication"></div>
<script src="/ui/js/nginx/lib/lodash.min.js"></script>
<script src="/ui/js/nginx/lib/backbone-min.js"></script>
<script src="/ui/js/nginx/dist/bundle.js"></script>

View file

@ -0,0 +1,49 @@
<?php
/*
* Copyright (C) 2018 Fabian Franz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
$log_file = '/var/log/nginx/csp_violations.log';
// make sure we don't have any formatting issues here
if (stristr($_SERVER['CONTENT_TYPE'], 'json') === false) {
http_response_code(400);
echo "This endpoint expects JSON data. Please send data using a json mime time (for example application/json)";
exit(0);
}
if ($json_data = json_decode(file_get_contents('php://input'), true)) {
http_response_code(204);
// inject some data for a log viewer to get a relation with the server entry
$json_data['server_time'] = time();
$json_data['server_uuid'] = $_SERVER['SERVER-UUID'];
$json_data = json_encode($json_data);
file_put_contents($log_file, $json_data . PHP_EOL, FILE_APPEND | LOCK_EX);
} else {
http_response_code(400);
echo "Your request data cannot be decoded. Please send compliant JSON data.";
exit(0);
}

View file

@ -0,0 +1,74 @@
#!/usr/local/bin/php
<?php
/*
* Copyright (C) 2018 Fabian Franz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
require_once 'config.inc';
use OPNsense\Nginx\Nginx;
use OPNsense\Nginx\ErrorLogParser;
use OPNsense\Nginx\AccessLogParser;
$log_prefix = '/var/log/nginx/';
$log_suffix = '.log';
if ($_SERVER['argc'] != 3) die('{"error": "Incorrect amount of parameters given"}');
// first parameter: error|access
$mode = $_SERVER['argv'][1];
// second parameter: uuid of server
$server = $_SERVER['argv'][2];
$nginx = new Nginx();
if ($data = $nginx->getNodeByReference('http_server.'. $server)) {
$server_names = (string)$data->servername;
if (empty($server_names)) {
die('{"error": "The server entry has no server name"}');
}
$lines = [];
foreach (explode(',', $server_names) as $server_name) {
$log_file_name = $log_prefix . basename($server_name) . '.' . $mode . $log_suffix;
// this entry has no log file, ignore it
if (!file_exists($log_file_name)) continue;
$logparser = null;
if ($mode == 'error') {
$logparser = new ErrorLogParser($log_file_name);
}
elseif ($mode == 'access') {
$logparser = new AccessLogParser($log_file_name);
}
// we cannot parse the file - something went wrong
if ($logparser == null) continue;
$lines = array_merge($lines, $logparser->get_result());
}
if (empty($lines)) {
$lines['error'] = 'no lines found';
}
echo json_encode($lines);
}
else {
die('{"error": "UUID not found"}');
}

View file

@ -1,6 +1,32 @@
#!/usr/local/bin/php
<?php
/*
* Copyright (C) 2018 Fabian Franz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
require_once('config.inc');
require_once('certs.inc');
use \OPNsense\Nginx\Nginx;

View file

@ -25,3 +25,9 @@ type:script_output
command:/usr/local/etc/rc.d/php-fpm status; exit 0
parameters:
type:script_output
[log]
command:/usr/local/opnsense/scripts/nginx/read_log.php
parameters: %s %s
type:script_output
message:restarting nginx

View file

@ -29,11 +29,6 @@ default_type application/octet-stream;
keepalive_timeout {{ OPNsense.Nginx.http.keepalive_timeout }};
{% endif %}
#add_header X-Frame-Options SAMEORIGIN;
#add_header X-Content-Type-Options nosniff;
#add_header X-XSS-Protection "1; mode=block";
#add_header Referrer-Policy "same-origin";
# TODO add when core is ready for allowing nginx to serve the web interface
# include nginx_web.conf;
@ -84,9 +79,19 @@ server {
server_name {{ server.servername }};
charset {{ server.charset }};
access_log /var/log/nginx/{{ server.servername }}.access.log {{ server.access_log_format }};
error_log /var/log/nginx/{{ server.servername }}.error.log;
{% if server.root is defined and server.root != '' %}
root "{{server.root}}";
{% endif %}
#include tls.conf;
error_page 404 /opnsense_error_404.html;
error_page 500 501 502 503 504 /opnsense_server_error.html;
{% if server.security_header is defined and server.security_header != '' %}
{% set security_rule = helpers.getUUID(server.security_header) %}
{% if security_rule is defined %}
{% include "OPNsense/Nginx/security_rule.conf" ignore missing with context %}
{% endif %}
{% endif %}
# location to ban the host permanently
set $naxsi_extensive_log {% if server.naxsi_extensive_log is defined and server.naxsi_extensive_log == '1' %}1{% else %}0{% endif %};
location @permanentban {
@ -123,6 +128,24 @@ server {
{
return 418;
}
location = /opnsense-report-csp-violation {
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param SCRIPT_FILENAME /usr/local/opnsense/scripts/nginx/csp_report.php;
fastcgi_param TLS-Cipher $ssl_cipher;
fastcgi_param TLS-Protocol $ssl_protocol;
fastcgi_param TLS-SNI-Host $ssl_server_name;
{% if helpers._template_in_data['__uuid__'] is defined %}
{% for uuid in helpers._template_in_data['__uuid__'] %}
{% if helpers._template_in_data['__uuid__'][uuid] == server %}
fastcgi_param SERVER-UUID "{{ uuid }}";
{% endif %}
{% endfor %}
{% endif %}
fastcgi_intercept_errors on;
fastcgi_pass unix:/var/run/php-webgui.socket;
}
location /opnsense-auth-request {
internal;
fastcgi_pass unix:/var/run/php-webgui.socket;

View file

@ -55,8 +55,34 @@ location {{ location.matchtype }} {{ location.urlpattern }} {
auth_request /opnsense-auth-request;
{% endif %}
{% endif %}
{% if location.upstream is defined %}
{% if location.php_enable is defined and location.php_enable == '1' %}
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param TLS-Cipher $ssl_cipher;
fastcgi_param TLS-Protocol $ssl_protocol;
fastcgi_param TLS-SNI-Host $ssl_server_name;
fastcgi_intercept_errors off;
{% if location.upstream is not defined %}
fastcgi_pass unix:/var/run/php-www.socket;
{% if location.php_override_scriptname is defined and location.php_override_scriptname != '' %}
fastcgi_param SCRIPT_FILENAME $document_root/{{ location.php_override_scriptname }};
{% else %}
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
{% endif %}
{% else %}
fastcgi_pass upstream{{ location.upstream.replace('-','') }};
fastcgi_connect_timeout 10s;
{% if location.php_override_scriptname is defined and location.php_override_scriptname != '' %}
fastcgi_param SCRIPT_FILENAME {{ location.php_override_scriptname }};
{% else %}
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
{% endif %}
{% endif %}
{% endif%}
{% if location.upstream is defined and (location.php_enable is not defined or location.php_enable != '1') %}
{% set upstream = helpers.getUUID(location.upstream) %}
proxy_set_header Host $host;
proxy_pass http{% if upstream.tls_enable == '1' %}s{% endif %}://upstream{{ location.upstream.replace('-','') }};
{% if upstream.tls_enable == '1' %}
{% if upstream.tls_client_certificate is defined and upstream.tls_client_certificate != '' %}

View file

@ -5,8 +5,7 @@ load_module /usr/local/libexec/nginx/ngx_mail_module.so;
load_module /usr/local/libexec/nginx/ngx_http_brotli_filter_module.so;
load_module /usr/local/libexec/nginx/ngx_http_brotli_static_module.so;
# TODO enable root when running the web interface
#user root wheel;
user www staff;
worker_processes 1;
error_log /var/log/nginx/error.log;

View file

@ -4,13 +4,13 @@ user = root
group = wheel
listen = /var/run/php-webgui.socket
listen.owner = root
listen.group = wheel
listen.group = staff
listen.mode = 0660
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_value[error_log] = /var/log/fpm-php.webgui.log
php_admin_flag[log_errors] = on
{% endraw %}

View file

@ -3,8 +3,8 @@
user = www
group = www
listen = /var/run/php-www.socket
listen.owner = www
listen.group = www
listen.owner = root
listen.group = staff
listen.mode = 0660
pm = dynamic
pm.max_children = 5

View file

@ -0,0 +1,65 @@
{% if security_rule.referrer is defined %}
add_header Referrer-Policy "{{ security_rule.referrer }}" always;
{% endif %}
{% if security_rule.xssprotection is defined %}
add_header X-XSS-Protection "{{ security_rule.xssprotection }}" always;
{% endif %}
{% if security_rule.content_type_options is defined and security_rule.content_type_options == '1' %}
add_header X-Content-Type-Options "nosniff" always;
{% endif %}
{% if security_rule.strict_transport_security_time is defined %}
add_header Strict-Transport-Security "{{ security_rule.strict_transport_security_time }}{%
if security_rule.strict_transport_security_include_subdomains is defined and
security_rule.strict_transport_security_include_subdomains == '1' %}; includeSubDomains{% endif %}" always;
{% endif %}
{% if security_rule.hpkp_keys is defined and security_rule.hpkp_time is defined %}
add_header Public-Key-Pins{% if security_rule.hpkp_report_only is defined and security_rule.hpkp_report_only == '1'
%}-Report-Only{% endif %} "{% for key in security_rule.hpkp_keys.split(',')
%}pin-sha256={{ key }}; {% endfor %}max-age={{ security_rule.hpkp_time }}{%
if security_rule.hpkp_include_subdomains is defined and
security_rule.hpkp_include_subdomains == '1' %}; includeSubDomains{% endif %}" always;
{% endif %}
{% if security_rule.enable_csp is defined and security_rule.enable_csp == '1' %}
{% set hash_csp = {} %}
{% for csp_category in ['default-src', 'script-src', 'img-src', 'style-src', 'media-src', 'font-src', 'form-action'] %}
{% set prefix = 'csp_' + csp_category.replace('-', '_') + '_' %}
{% if security_rule[prefix + 'enabled'] == '1' %}
{% set current_list = [] %}
{% if security_rule[prefix + 'none'] is defined and security_rule[prefix + 'none'] == '1' %}
{% do current_list.append("'none'") %}
{% else %}
{% if security_rule[prefix + 'data_urls'] is defined and security_rule[prefix + 'data_urls'] == '1' %}
{% do current_list.append('data:') %}
{% endif %}
{% if security_rule[prefix + 'inline'] is defined and security_rule[prefix + 'inline'] == '1' %}
{% do current_list.append("'unsafe-inline'") %}
{% endif %}
{% if security_rule[prefix + 'eval'] is defined and security_rule[prefix + 'eval'] == '1' %}
{% do current_list.append("'unsafe-eval'") %}
{% endif %}
{% if security_rule[prefix + 'self'] is defined and security_rule[prefix + 'self'] == '1' %}
{% do current_list.append("'self'") %}
{% endif %}
{% if security_rule[prefix + 'blob'] is defined and security_rule[prefix + 'blob'] == '1' %}
{% do current_list.append("blob:") %}
{% endif %}
{% if security_rule[prefix + 'mediastream'] is defined and security_rule[prefix + 'mediastream'] == '1' %}
{% do current_list.append("mediastream:") %}
{% endif %}
{% if security_rule[prefix + 'filesystem'] is defined and security_rule[prefix + 'filesystem'] == '1' %}
{% do current_list.append("filesystem:") %}
{% endif %}
{% if security_rule[prefix + 'http_urls'] is defined and security_rule[prefix + 'http_urls'] != '' %}
{% do current_list.append(security_rule[prefix + 'http_urls'].replace(',', ' ')) %}
{% endif %}
{% endif %}
{% if current_list|length > 0 %}
{# only append non-empty #}
{% do hash_csp.update({csp_category: current_list}) %}
{% endif %}
{% endif %}
{% endfor %}
add_header Content-Security-Policy{% if security_rule.csp_report_only %}-Report-Only{% endif %} "{%
for key, value in hash_csp.items() %}{{ key }} {{ value|join(' ') }}; {% endfor %}{#
#} report-uri /opnsense-report-csp-violation" always;
{% endif %}

View file

@ -0,0 +1,10 @@
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"rules": {
"semi": "warn",
"no-extra-semi": "error"
}
}

View file

@ -0,0 +1 @@
node_modules

View file

@ -0,0 +1,3 @@
This file contains the build result of webpack.
Please do not delete it.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,22 @@
Copyright (c) 2010-2017 Jeremy Ashkenas, DocumentCloud
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.

View file

@ -0,0 +1,137 @@
/**
* @license
* Lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
*/
;(function(){function n(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function t(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u<i;){var o=n[u];t(e,o,r(o),n)}return e}function r(n,t){for(var r=-1,e=null==n?0:n.length;++r<e&&false!==t(n[r],r,n););return n}function e(n,t){for(var r=null==n?0:n.length;r--&&false!==t(n[r],r,n););return n}function u(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(!t(n[r],r,n))return false;
return true}function i(n,t){for(var r=-1,e=null==n?0:n.length,u=0,i=[];++r<e;){var o=n[r];t(o,r,n)&&(i[u++]=o)}return i}function o(n,t){return!(null==n||!n.length)&&-1<v(n,t,0)}function f(n,t,r){for(var e=-1,u=null==n?0:n.length;++e<u;)if(r(t,n[e]))return true;return false}function c(n,t){for(var r=-1,e=null==n?0:n.length,u=Array(e);++r<e;)u[r]=t(n[r],r,n);return u}function a(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function l(n,t,r,e){var u=-1,i=null==n?0:n.length;for(e&&i&&(r=n[++u]);++u<i;)r=t(r,n[u],u,n);
return r}function s(n,t,r,e){var u=null==n?0:n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r}function h(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(t(n[r],r,n))return true;return false}function p(n,t,r){var e;return r(n,function(n,r,u){if(t(n,r,u))return e=r,false}),e}function _(n,t,r,e){var u=n.length;for(r+=e?1:-1;e?r--:++r<u;)if(t(n[r],r,n))return r;return-1}function v(n,t,r){if(t===t)n:{--r;for(var e=n.length;++r<e;)if(n[r]===t){n=r;break n}n=-1}else n=_(n,d,r);return n}function g(n,t,r,e){
--r;for(var u=n.length;++r<u;)if(e(n[r],t))return r;return-1}function d(n){return n!==n}function y(n,t){var r=null==n?0:n.length;return r?m(n,t)/r:F}function b(n){return function(t){return null==t?T:t[n]}}function x(n){return function(t){return null==n?T:n[t]}}function j(n,t,r,e,u){return u(n,function(n,u,i){r=e?(e=false,n):t(r,n,u,i)}),r}function w(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].c;return n}function m(n,t){for(var r,e=-1,u=n.length;++e<u;){var i=t(n[e]);i!==T&&(r=r===T?i:r+i)}return r;
}function A(n,t){for(var r=-1,e=Array(n);++r<n;)e[r]=t(r);return e}function k(n,t){return c(t,function(t){return[t,n[t]]})}function E(n){return function(t){return n(t)}}function S(n,t){return c(t,function(t){return n[t]})}function O(n,t){return n.has(t)}function I(n,t){for(var r=-1,e=n.length;++r<e&&-1<v(t,n[r],0););return r}function R(n,t){for(var r=n.length;r--&&-1<v(t,n[r],0););return r}function z(n){return"\\"+Cn[n]}function W(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n];
}),r}function B(n,t){return function(r){return n(t(r))}}function L(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r];o!==t&&"__lodash_placeholder__"!==o||(n[r]="__lodash_placeholder__",i[u++]=r)}return i}function U(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=n}),r}function C(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=[n,n]}),r}function D(n){if(Rn.test(n)){for(var t=On.lastIndex=0;On.test(n);)++t;n=t}else n=Qn(n);return n}function M(n){return Rn.test(n)?n.match(On)||[]:n.split("");
}var T,$=1/0,F=NaN,N=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],P=/\b__p\+='';/g,Z=/\b(__p\+=)''\+/g,q=/(__e\(.*?\)|\b__t\))\+'';/g,V=/&(?:amp|lt|gt|quot|#39);/g,K=/[&<>"']/g,G=RegExp(V.source),H=RegExp(K.source),J=/<%-([\s\S]+?)%>/g,Y=/<%([\s\S]+?)%>/g,Q=/<%=([\s\S]+?)%>/g,X=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,nn=/^\w*$/,tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,rn=/[\\^$.*+?()[\]{}|]/g,en=RegExp(rn.source),un=/^\s+|\s+$/g,on=/^\s+/,fn=/\s+$/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,ln=/,? & /,sn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,hn=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_n=/\w*$/,vn=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,dn=/^\[object .+?Constructor\]$/,yn=/^0o[0-7]+$/i,bn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,wn=/['\n\r\u2028\u2029\\]/g,mn="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*",An="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,kn="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",En=RegExp("['\u2019]","g"),Sn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),On=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+kn+mn,"g"),In=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])|\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])|\\d+",An].join("|"),"g"),Rn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),zn=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Bn={};
Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true,Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object Boolean]"]=Bn["[object DataView]"]=Bn["[object Date]"]=Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object WeakMap]"]=false;
var Ln={};Ln["[object Arguments]"]=Ln["[object Array]"]=Ln["[object ArrayBuffer]"]=Ln["[object DataView]"]=Ln["[object Boolean]"]=Ln["[object Date]"]=Ln["[object Float32Array]"]=Ln["[object Float64Array]"]=Ln["[object Int8Array]"]=Ln["[object Int16Array]"]=Ln["[object Int32Array]"]=Ln["[object Map]"]=Ln["[object Number]"]=Ln["[object Object]"]=Ln["[object RegExp]"]=Ln["[object Set]"]=Ln["[object String]"]=Ln["[object Symbol]"]=Ln["[object Uint8Array]"]=Ln["[object Uint8ClampedArray]"]=Ln["[object Uint16Array]"]=Ln["[object Uint32Array]"]=true,
Ln["[object Error]"]=Ln["[object Function]"]=Ln["[object WeakMap]"]=false;var Un,Cn={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Dn=parseFloat,Mn=parseInt,Tn=typeof global=="object"&&global&&global.Object===Object&&global,$n=typeof self=="object"&&self&&self.Object===Object&&self,Fn=Tn||$n||Function("return this")(),Nn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Pn=Nn&&typeof module=="object"&&module&&!module.nodeType&&module,Zn=Pn&&Pn.exports===Nn,qn=Zn&&Tn.process;
n:{try{Un=qn&&qn.binding&&qn.binding("util");break n}catch(n){}Un=void 0}var Vn=Un&&Un.isArrayBuffer,Kn=Un&&Un.isDate,Gn=Un&&Un.isMap,Hn=Un&&Un.isRegExp,Jn=Un&&Un.isSet,Yn=Un&&Un.isTypedArray,Qn=b("length"),Xn=x({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I",
"\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C",
"\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i",
"\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S",
"\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe",
"\u0149":"'n","\u017f":"s"}),nt=x({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}),tt=x({"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"}),rt=function x(mn){function An(n){if(du(n)&&!of(n)&&!(n instanceof Un)){if(n instanceof On)return n;if(ii.call(n,"__wrapped__"))return $e(n)}return new On(n)}function kn(){}function On(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=T}function Un(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,
this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Cn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Tn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function $n(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Nn(n){var t=-1,r=null==n?0:n.length;for(this.__data__=new $n;++t<r;)this.add(n[t])}function Pn(n){
this.size=(this.__data__=new Tn(n)).size}function qn(n,t){var r,e=of(n),u=!e&&uf(n),i=!e&&!u&&cf(n),o=!e&&!u&&!i&&pf(n),u=(e=e||u||i||o)?A(n.length,Xu):[],f=u.length;for(r in n)!t&&!ii.call(n,r)||e&&("length"==r||i&&("offset"==r||"parent"==r)||o&&("buffer"==r||"byteLength"==r||"byteOffset"==r)||Se(r,f))||u.push(r);return u}function Qn(n){var t=n.length;return t?n[ir(0,t-1)]:T}function et(n,t){return Ce(Ur(n),pt(t,0,n.length))}function ut(n){return Ce(Ur(n))}function it(n,t,r){(r===T||au(n[t],r))&&(r!==T||t in n)||st(n,t,r);
}function ot(n,t,r){var e=n[t];ii.call(n,t)&&au(e,r)&&(r!==T||t in n)||st(n,t,r)}function ft(n,t){for(var r=n.length;r--;)if(au(n[r][0],t))return r;return-1}function ct(n,t,r,e){return eo(n,function(n,u,i){t(e,n,r(n),i)}),e}function at(n,t){return n&&Cr(t,zu(t),n)}function lt(n,t){return n&&Cr(t,Wu(t),n)}function st(n,t,r){"__proto__"==t&&mi?mi(n,t,{configurable:true,enumerable:true,value:r,writable:true}):n[t]=r}function ht(n,t){for(var r=-1,e=t.length,u=Vu(e),i=null==n;++r<e;)u[r]=i?T:Iu(n,t[r]);return u;
}function pt(n,t,r){return n===n&&(r!==T&&(n=n<=r?n:r),t!==T&&(n=n>=t?n:t)),n}function _t(n,t,e,u,i,o){var f,c=1&t,a=2&t,l=4&t;if(e&&(f=i?e(n,u,i,o):e(n)),f!==T)return f;if(!gu(n))return n;if(u=of(n)){if(f=me(n),!c)return Ur(n,f)}else{var s=_o(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(cf(n))return Ir(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Ae(n),!c)return a?Mr(n,lt(f,n)):Dr(n,at(f,n))}else{if(!Ln[s])return i?n:{};f=ke(n,s,c)}}if(o||(o=new Pn),
i=o.get(n))return i;if(o.set(n,f),hf(n))return n.forEach(function(r){f.add(_t(r,t,e,r,n,o))}),f;if(lf(n))return n.forEach(function(r,u){f.set(u,_t(r,t,e,u,n,o))}),f;var a=l?a?ve:_e:a?Wu:zu,p=u?T:a(n);return r(p||n,function(r,u){p&&(u=r,r=n[u]),ot(f,u,_t(r,t,e,u,n,o))}),f}function vt(n){var t=zu(n);return function(r){return gt(r,n,t)}}function gt(n,t,r){var e=r.length;if(null==n)return!e;for(n=Yu(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===T&&!(u in n)||!i(o))return false}return true}function dt(n,t,r){if(typeof n!="function")throw new ni("Expected a function");
return yo(function(){n.apply(T,r)},t)}function yt(n,t,r,e){var u=-1,i=o,a=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=c(t,E(r))),e?(i=f,a=false):200<=t.length&&(i=O,a=false,t=new Nn(t));n:for(;++u<l;){var p=n[u],_=null==r?p:r(p),p=e||0!==p?p:0;if(a&&_===_){for(var v=h;v--;)if(t[v]===_)continue n;s.push(p)}else i(t,_,e)||s.push(p)}return s}function bt(n,t){var r=true;return eo(n,function(n,e,u){return r=!!t(n,e,u)}),r}function xt(n,t,r){for(var e=-1,u=n.length;++e<u;){var i=n[e],o=t(i);if(null!=o&&(f===T?o===o&&!ju(o):r(o,f)))var f=o,c=i;
}return c}function jt(n,t){var r=[];return eo(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function wt(n,t,r,e,u){var i=-1,o=n.length;for(r||(r=Ee),u||(u=[]);++i<o;){var f=n[i];0<t&&r(f)?1<t?wt(f,t-1,r,e,u):a(u,f):e||(u[u.length]=f)}return u}function mt(n,t){return n&&io(n,t,zu)}function At(n,t){return n&&oo(n,t,zu)}function kt(n,t){return i(t,function(t){return pu(n[t])})}function Et(n,t){t=Sr(t,n);for(var r=0,e=t.length;null!=n&&r<e;)n=n[De(t[r++])];return r&&r==e?n:T}function St(n,t,r){return t=t(n),
of(n)?t:a(t,r(n))}function Ot(n){if(null==n)n=n===T?"[object Undefined]":"[object Null]";else if(wi&&wi in Yu(n)){var t=ii.call(n,wi),r=n[wi];try{n[wi]=T;var e=true}catch(n){}var u=ci.call(n);e&&(t?n[wi]=r:delete n[wi]),n=u}else n=ci.call(n);return n}function It(n,t){return n>t}function Rt(n,t){return null!=n&&ii.call(n,t)}function zt(n,t){return null!=n&&t in Yu(n)}function Wt(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=Vu(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,E(t))),s=Ui(p.length,s),
l[a]=!r&&(t||120<=u&&120<=p.length)?new Nn(a&&p):T}var p=n[0],_=-1,v=l[0];n:for(;++_<u&&h.length<s;){var g=p[_],d=t?t(g):g,g=r||0!==g?g:0;if(v?!O(v,d):!e(h,d,r)){for(a=i;--a;){var y=l[a];if(y?!O(y,d):!e(n[a],d,r))continue n}v&&v.push(d),h.push(g)}}return h}function Bt(n,t,r){var e={};return mt(n,function(n,u,i){t(e,r(n),u,i)}),e}function Lt(t,r,e){return r=Sr(r,t),t=2>r.length?t:Et(t,hr(r,0,-1)),r=null==t?t:t[De(qe(r))],null==r?T:n(r,t,e)}function Ut(n){return du(n)&&"[object Arguments]"==Ot(n)}function Ct(n){
return du(n)&&"[object ArrayBuffer]"==Ot(n)}function Dt(n){return du(n)&&"[object Date]"==Ot(n)}function Mt(n,t,r,e,u){if(n===t)t=true;else if(null==n||null==t||!du(n)&&!du(t))t=n!==n&&t!==t;else n:{var i=of(n),o=of(t),f=i?"[object Array]":_o(n),c=o?"[object Array]":_o(t),f="[object Arguments]"==f?"[object Object]":f,c="[object Arguments]"==c?"[object Object]":c,a="[object Object]"==f,o="[object Object]"==c;if((c=f==c)&&cf(n)){if(!cf(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Pn),t=i||pf(n)?se(n,t,r,e,Mt,u):he(n,t,f,r,e,Mt,u);else{
if(!(1&r)&&(i=a&&ii.call(n,"__wrapped__"),f=o&&ii.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Pn),t=Mt(n,t,r,e,u);break n}if(c)t:if(u||(u=new Pn),i=1&r,f=_e(n),o=f.length,c=_e(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:ii.call(t,l))){t=false;break t}}if((c=u.get(n))&&u.get(t))t=c==t;else{c=true,u.set(n,t),u.set(t,n);for(var s=i;++a<o;){var l=f[a],h=n[l],p=t[l];if(e)var _=i?e(p,h,l,t,n,u):e(h,p,l,n,t,u);if(_===T?h!==p&&!Mt(h,p,r,e,u):!_){c=false;break}s||(s="constructor"==l);
}c&&!s&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(c=false)),u.delete(n),u.delete(t),t=c}}else t=false;else t=false}}return t}function Tt(n){return du(n)&&"[object Map]"==_o(n)}function $t(n,t,r,e){var u=r.length,i=u,o=!e;if(null==n)return!i;for(n=Yu(n);u--;){var f=r[u];if(o&&f[2]?f[1]!==n[f[0]]:!(f[0]in n))return false}for(;++u<i;){var f=r[u],c=f[0],a=n[c],l=f[1];if(o&&f[2]){if(a===T&&!(c in n))return false;
}else{if(f=new Pn,e)var s=e(a,l,c,n,t,f);if(s===T?!Mt(l,a,3,e,f):!s)return false}}return true}function Ft(n){return!(!gu(n)||fi&&fi in n)&&(pu(n)?si:dn).test(Me(n))}function Nt(n){return du(n)&&"[object RegExp]"==Ot(n)}function Pt(n){return du(n)&&"[object Set]"==_o(n)}function Zt(n){return du(n)&&vu(n.length)&&!!Bn[Ot(n)]}function qt(n){return typeof n=="function"?n:null==n?Tu:typeof n=="object"?of(n)?Jt(n[0],n[1]):Ht(n):Pu(n)}function Vt(n){if(!ze(n))return Bi(n);var t,r=[];for(t in Yu(n))ii.call(n,t)&&"constructor"!=t&&r.push(t);
return r}function Kt(n,t){return n<t}function Gt(n,t){var r=-1,e=lu(n)?Vu(n.length):[];return eo(n,function(n,u,i){e[++r]=t(n,u,i)}),e}function Ht(n){var t=xe(n);return 1==t.length&&t[0][2]?We(t[0][0],t[0][1]):function(r){return r===n||$t(r,n,t)}}function Jt(n,t){return Ie(n)&&t===t&&!gu(t)?We(De(n),t):function(r){var e=Iu(r,n);return e===T&&e===t?Ru(r,n):Mt(t,e,3)}}function Yt(n,t,r,e,u){n!==t&&io(t,function(i,o){if(gu(i)){u||(u=new Pn);var f=u,c="__proto__"==o?T:n[o],a="__proto__"==o?T:t[o],l=f.get(a);
if(l)it(n,o,l);else{var l=e?e(c,a,o+"",n,t,f):T,s=l===T;if(s){var h=of(a),p=!h&&cf(a),_=!h&&!p&&pf(a),l=a;h||p||_?of(c)?l=c:su(c)?l=Ur(c):p?(s=false,l=Ir(a,true)):_?(s=false,l=zr(a,true)):l=[]:bu(a)||uf(a)?(l=c,uf(c)?l=Su(c):(!gu(c)||r&&pu(c))&&(l=Ae(a))):s=false}s&&(f.set(a,l),Yt(l,a,r,e,f),f.delete(a)),it(n,o,l)}}else f=e?e("__proto__"==o?T:n[o],i,o+"",n,t,u):T,f===T&&(f=i),it(n,o,f)},Wu)}function Qt(n,t){var r=n.length;if(r)return t+=0>t?r:0,Se(t,r)?n[t]:T}function Xt(n,t,r){var e=-1;return t=c(t.length?t:[Tu],E(ye())),
n=Gt(n,function(n){return{a:c(t,function(t){return t(n)}),b:++e,c:n}}),w(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e<o;){var c=Wr(u[e],i[e]);if(c){e=e>=f?c:c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function nr(n,t){return tr(n,t,function(t,r){return Ru(n,r)})}function tr(n,t,r){for(var e=-1,u=t.length,i={};++e<u;){var o=t[e],f=Et(n,o);r(f,o)&&lr(i,Sr(o,n),f)}return i}function rr(n){return function(t){return Et(t,n)}}function er(n,t,r,e){var u=e?g:v,i=-1,o=t.length,f=n;
for(n===t&&(t=Ur(t)),r&&(f=c(n,E(r)));++i<o;)for(var a=0,l=t[i],l=r?r(l):l;-1<(a=u(f,l,a,e));)f!==n&&bi.call(f,a,1),bi.call(n,a,1);return n}function ur(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;Se(u)?bi.call(n,u,1):xr(n,u)}}}function ir(n,t){return n+Oi(Mi()*(t-n+1))}function or(n,t){var r="";if(!n||1>t||9007199254740991<t)return r;do t%2&&(r+=n),(t=Oi(t/2))&&(n+=n);while(t);return r}function fr(n,t){return bo(Be(n,t,Tu),n+"")}function cr(n){return Qn(Lu(n))}function ar(n,t){
var r=Lu(n);return Ce(r,pt(t,0,r.length))}function lr(n,t,r,e){if(!gu(n))return n;t=Sr(t,n);for(var u=-1,i=t.length,o=i-1,f=n;null!=f&&++u<i;){var c=De(t[u]),a=r;if(u!=o){var l=f[c],a=e?e(l,c,f):T;a===T&&(a=gu(l)?l:Se(t[u+1])?[]:{})}ot(f,c,a),f=f[c]}return n}function sr(n){return Ce(Lu(n))}function hr(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Vu(u);++e<u;)r[e]=n[e+t];return r}function pr(n,t){var r;return eo(n,function(n,e,u){return r=t(n,e,u),
!r}),!!r}function _r(n,t,r){var e=0,u=null==n?e:n.length;if(typeof t=="number"&&t===t&&2147483647>=u){for(;e<u;){var i=e+u>>>1,o=n[i];null!==o&&!ju(o)&&(r?o<=t:o<t)?e=i+1:u=i}return u}return vr(n,t,Tu,r)}function vr(n,t,r,e){t=r(t);for(var u=0,i=null==n?0:n.length,o=t!==t,f=null===t,c=ju(t),a=t===T;u<i;){var l=Oi((u+i)/2),s=r(n[l]),h=s!==T,p=null===s,_=s===s,v=ju(s);(o?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?s<=t:s<t)?u=l+1:i=l}return Ui(i,4294967294)}function gr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){
var o=n[r],f=t?t(o):o;if(!r||!au(f,c)){var c=f;i[u++]=0===o?0:o}}return i}function dr(n){return typeof n=="number"?n:ju(n)?F:+n}function yr(n){if(typeof n=="string")return n;if(of(n))return c(n,yr)+"";if(ju(n))return to?to.call(n):"";var t=n+"";return"0"==t&&1/n==-$?"-0":t}function br(n,t,r){var e=-1,u=o,i=n.length,c=true,a=[],l=a;if(r)c=false,u=f;else if(200<=i){if(u=t?null:lo(n))return U(u);c=false,u=O,l=new Nn}else l=t?[]:a;n:for(;++e<i;){var s=n[e],h=t?t(s):s,s=r||0!==s?s:0;if(c&&h===h){for(var p=l.length;p--;)if(l[p]===h)continue n;
t&&l.push(h),a.push(s)}else u(l,h,r)||(l!==a&&l.push(h),a.push(s))}return a}function xr(n,t){return t=Sr(t,n),n=2>t.length?n:Et(n,hr(t,0,-1)),null==n||delete n[De(qe(t))]}function jr(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++i<u)&&t(n[i],i,n););return r?hr(n,e?0:i,e?i+1:u):hr(n,e?i+1:0,e?u:i)}function wr(n,t){var r=n;return r instanceof Un&&(r=r.value()),l(t,function(n,t){return t.func.apply(t.thisArg,a([n],t.args))},r)}function mr(n,t,r){var e=n.length;if(2>e)return e?br(n[0]):[];for(var u=-1,i=Vu(e);++u<e;)for(var o=n[u],f=-1;++f<e;)f!=u&&(i[u]=yt(i[u]||o,n[f],t,r));
return br(wt(i,1),t,r)}function Ar(n,t,r){for(var e=-1,u=n.length,i=t.length,o={};++e<u;)r(o,n[e],e<i?t[e]:T);return o}function kr(n){return su(n)?n:[]}function Er(n){return typeof n=="function"?n:Tu}function Sr(n,t){return of(n)?n:Ie(n,t)?[n]:xo(Ou(n))}function Or(n,t,r){var e=n.length;return r=r===T?e:r,!t&&r>=e?n:hr(n,t,r)}function Ir(n,t){if(t)return n.slice();var r=n.length,r=vi?vi(r):new n.constructor(r);return n.copy(r),r}function Rr(n){var t=new n.constructor(n.byteLength);return new _i(t).set(new _i(n)),
t}function zr(n,t){return new n.constructor(t?Rr(n.buffer):n.buffer,n.byteOffset,n.length)}function Wr(n,t){if(n!==t){var r=n!==T,e=null===n,u=n===n,i=ju(n),o=t!==T,f=null===t,c=t===t,a=ju(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&n<t||a&&r&&u&&!e&&!i||f&&r&&u||!o&&u||!c)return-1}return 0}function Br(n,t,r,e){var u=-1,i=n.length,o=r.length,f=-1,c=t.length,a=Li(i-o,0),l=Vu(c+a);for(e=!e;++f<c;)l[f]=t[f];for(;++u<o;)(e||u<i)&&(l[r[u]]=n[u]);for(;a--;)l[f++]=n[u++];
return l}function Lr(n,t,r,e){var u=-1,i=n.length,o=-1,f=r.length,c=-1,a=t.length,l=Li(i-f,0),s=Vu(l+a);for(e=!e;++u<l;)s[u]=n[u];for(l=u;++c<a;)s[l+c]=t[c];for(;++o<f;)(e||u<i)&&(s[l+r[o]]=n[u++]);return s}function Ur(n,t){var r=-1,e=n.length;for(t||(t=Vu(e));++r<e;)t[r]=n[r];return t}function Cr(n,t,r,e){var u=!r;r||(r={});for(var i=-1,o=t.length;++i<o;){var f=t[i],c=e?e(r[f],n[f],f,r,n):T;c===T&&(c=n[f]),u?st(r,f,c):ot(r,f,c)}return r}function Dr(n,t){return Cr(n,ho(n),t)}function Mr(n,t){return Cr(n,po(n),t);
}function Tr(n,r){return function(e,u){var i=of(e)?t:ct,o=r?r():{};return i(e,n,ye(u,2),o)}}function $r(n){return fr(function(t,r){var e=-1,u=r.length,i=1<u?r[u-1]:T,o=2<u?r[2]:T,i=3<n.length&&typeof i=="function"?(u--,i):T;for(o&&Oe(r[0],r[1],o)&&(i=3>u?T:i,u=1),t=Yu(t);++e<u;)(o=r[e])&&n(t,o,e,i);return t})}function Fr(n,t){return function(r,e){if(null==r)return r;if(!lu(r))return n(r,e);for(var u=r.length,i=t?u:-1,o=Yu(r);(t?i--:++i<u)&&false!==e(o[i],i,o););return r}}function Nr(n){return function(t,r,e){
var u=-1,i=Yu(t);e=e(t);for(var o=e.length;o--;){var f=e[n?o:++u];if(false===r(i[f],f,i))break}return t}}function Pr(n,t,r){function e(){return(this&&this!==Fn&&this instanceof e?i:n).apply(u?r:this,arguments)}var u=1&t,i=Vr(n);return e}function Zr(n){return function(t){t=Ou(t);var r=Rn.test(t)?M(t):T,e=r?r[0]:t.charAt(0);return t=r?Or(r,1).join(""):t.slice(1),e[n]()+t}}function qr(n){return function(t){return l(Du(Cu(t).replace(En,"")),n,"")}}function Vr(n){return function(){var t=arguments;switch(t.length){
case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=ro(n.prototype),t=n.apply(r,t);return gu(t)?t:r}}function Kr(t,r,e){function u(){for(var o=arguments.length,f=Vu(o),c=o,a=de(u);c--;)f[c]=arguments[c];return c=3>o&&f[0]!==a&&f[o-1]!==a?[]:L(f,a),
o-=c.length,o<e?ue(t,r,Jr,u.placeholder,T,f,c,T,T,e-o):n(this&&this!==Fn&&this instanceof u?i:t,this,f)}var i=Vr(t);return u}function Gr(n){return function(t,r,e){var u=Yu(t);if(!lu(t)){var i=ye(r,3);t=zu(t),r=function(n){return i(u[n],n,u)}}return r=n(t,r,e),-1<r?u[i?t[r]:r]:T}}function Hr(n){return pe(function(t){var r=t.length,e=r,u=On.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if(typeof i!="function")throw new ni("Expected a function");if(u&&!o&&"wrapper"==ge(i))var o=new On([],true)}for(e=o?e:r;++e<r;)var i=t[e],u=ge(i),f="wrapper"==u?so(i):T,o=f&&Re(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?o[ge(f[0])].apply(o,f[3]):1==i.length&&Re(i)?o[u]():o.thru(i);
return function(){var n=arguments,e=n[0];if(o&&1==n.length&&of(e))return o.plant(e).value();for(var u=0,n=r?t[u].apply(this,n):e;++u<r;)n=t[u].call(this,n);return n}})}function Jr(n,t,r,e,u,i,o,f,c,a){function l(){for(var d=arguments.length,y=Vu(d),b=d;b--;)y[b]=arguments[b];if(_){var x,j=de(l),b=y.length;for(x=0;b--;)y[b]===j&&++x}if(e&&(y=Br(y,e,u,_)),i&&(y=Lr(y,i,o,_)),d-=x,_&&d<a)return j=L(y,j),ue(n,t,Jr,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[n]:n,d=y.length,f){x=y.length;for(var w=Ui(f.length,x),m=Ur(y);w--;){
var A=f[w];y[w]=Se(A,x)?m[A]:T}}else v&&1<d&&y.reverse();return s&&c<d&&(y.length=c),this&&this!==Fn&&this instanceof l&&(b=g||Vr(b)),b.apply(j,y)}var s=128&t,h=1&t,p=2&t,_=24&t,v=512&t,g=p?T:Vr(n);return l}function Yr(n,t){return function(r,e){return Bt(r,n,t(e))}}function Qr(n,t){return function(r,e){var u;if(r===T&&e===T)return t;if(r!==T&&(u=r),e!==T){if(u===T)return e;typeof r=="string"||typeof e=="string"?(r=yr(r),e=yr(e)):(r=dr(r),e=dr(e)),u=n(r,e)}return u}}function Xr(t){return pe(function(r){
return r=c(r,E(ye())),fr(function(e){var u=this;return t(r,function(t){return n(t,u,e)})})})}function ne(n,t){t=t===T?" ":yr(t);var r=t.length;return 2>r?r?or(t,n):t:(r=or(t,Si(n/D(t))),Rn.test(t)?Or(M(r),0,n).join(""):r.slice(0,n))}function te(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=Vu(l+c),h=this&&this!==Fn&&this instanceof i?f:t;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++r];return n(h,o?e:this,s)}var o=1&r,f=Vr(t);return i}function re(n){return function(t,r,e){
e&&typeof e!="number"&&Oe(t,r,e)&&(r=e=T),t=mu(t),r===T?(r=t,t=0):r=mu(r),e=e===T?t<r?1:-1:mu(e);var u=-1;r=Li(Si((r-t)/(e||1)),0);for(var i=Vu(r);r--;)i[n?r:++u]=t,t+=e;return i}}function ee(n){return function(t,r){return typeof t=="string"&&typeof r=="string"||(t=Eu(t),r=Eu(r)),n(t,r)}}function ue(n,t,r,e,u,i,o,f,c,a){var l=8&t,s=l?o:T;o=l?T:o;var h=l?i:T;return i=l?T:i,t=(t|(l?32:64))&~(l?64:32),4&t||(t&=-4),u=[n,t,u,h,s,i,o,f,c,a],r=r.apply(T,u),Re(n)&&go(r,u),r.placeholder=e,Le(r,n,t)}function ie(n){
var t=Ju[n];return function(n,r){if(n=Eu(n),r=null==r?0:Ui(Au(r),292)){var e=(Ou(n)+"e").split("e"),e=t(e[0]+"e"+(+e[1]+r)),e=(Ou(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return t(n)}}function oe(n){return function(t){var r=_o(t);return"[object Map]"==r?W(t):"[object Set]"==r?C(t):k(t,n(t))}}function fe(n,t,r,e,u,i,o,f){var c=2&t;if(!c&&typeof n!="function")throw new ni("Expected a function");var a=e?e.length:0;if(a||(t&=-97,e=u=T),o=o===T?o:Li(Au(o),0),f=f===T?f:Au(f),a-=u?u.length:0,64&t){
var l=e,s=u;e=u=T}var h=c?T:so(n);return i=[n,t,r,e,u,l,s,i,o,f],h&&(r=i[1],n=h[1],t=r|n,e=128==n&&8==r||128==n&&256==r&&i[7].length<=h[8]||384==n&&h[7].length<=h[8]&&8==r,131>t||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Br(e,r,h[4]):r,i[4]=e?L(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Lr(e,r,h[6]):r,i[6]=e?L(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Ui(i[8],h[8])),null==i[9]&&(i[9]=h[9]),i[0]=h[0],i[1]=t),n=i[0],t=i[1],
r=i[2],e=i[3],u=i[4],f=i[9]=i[9]===T?c?0:n.length:Li(i[9]-a,0),!f&&24&t&&(t&=-25),Le((h?fo:go)(t&&1!=t?8==t||16==t?Kr(n,t,f):32!=t&&33!=t||u.length?Jr.apply(T,i):te(n,t,r,e):Pr(n,t,r),i),n,t)}function ce(n,t,r,e){return n===T||au(n,ri[r])&&!ii.call(e,r)?t:n}function ae(n,t,r,e,u,i){return gu(n)&&gu(t)&&(i.set(t,n),Yt(n,t,T,ae,i),i.delete(t)),n}function le(n){return bu(n)?T:n}function se(n,t,r,e,u,i){var o=1&r,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return false;if((c=i.get(n))&&i.get(t))return c==t;var c=-1,a=true,l=2&r?new Nn:T;
for(i.set(n,t),i.set(t,n);++c<f;){var s=n[c],p=t[c];if(e)var _=o?e(p,s,c,t,n,i):e(s,p,c,n,t,i);if(_!==T){if(_)continue;a=false;break}if(l){if(!h(t,function(n,t){if(!O(l,t)&&(s===n||u(s,n,r,e,i)))return l.push(t)})){a=false;break}}else if(s!==p&&!u(s,p,r,e,i)){a=false;break}}return i.delete(n),i.delete(t),a}function he(n,t,r,e,u,i,o){switch(r){case"[object DataView]":if(n.byteLength!=t.byteLength||n.byteOffset!=t.byteOffset)break;n=n.buffer,t=t.buffer;case"[object ArrayBuffer]":if(n.byteLength!=t.byteLength||!i(new _i(n),new _i(t)))break;
return true;case"[object Boolean]":case"[object Date]":case"[object Number]":return au(+n,+t);case"[object Error]":return n.name==t.name&&n.message==t.message;case"[object RegExp]":case"[object String]":return n==t+"";case"[object Map]":var f=W;case"[object Set]":if(f||(f=U),n.size!=t.size&&!(1&e))break;return(r=o.get(n))?r==t:(e|=2,o.set(n,t),t=se(f(n),f(t),e,u,i,o),o.delete(n),t);case"[object Symbol]":if(no)return no.call(n)==no.call(t)}return false}function pe(n){return bo(Be(n,T,Pe),n+"")}function _e(n){
return St(n,zu,ho)}function ve(n){return St(n,Wu,po)}function ge(n){for(var t=n.name+"",r=Ki[t],e=ii.call(Ki,t)?r.length:0;e--;){var u=r[e],i=u.func;if(null==i||i==n)return u.name}return t}function de(n){return(ii.call(An,"placeholder")?An:n).placeholder}function ye(){var n=An.iteratee||$u,n=n===$u?qt:n;return arguments.length?n(arguments[0],arguments[1]):n}function be(n,t){var r=n.__data__,e=typeof t;return("string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t)?r[typeof t=="string"?"string":"hash"]:r.map;
}function xe(n){for(var t=zu(n),r=t.length;r--;){var e=t[r],u=n[e];t[r]=[e,u,u===u&&!gu(u)]}return t}function je(n,t){var r=null==n?T:n[t];return Ft(r)?r:T}function we(n,t,r){t=Sr(t,n);for(var e=-1,u=t.length,i=false;++e<u;){var o=De(t[e]);if(!(i=null!=n&&r(n,o)))break;n=n[o]}return i||++e!=u?i:(u=null==n?0:n.length,!!u&&vu(u)&&Se(o,u)&&(of(n)||uf(n)))}function me(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&ii.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function Ae(n){
return typeof n.constructor!="function"||ze(n)?{}:ro(gi(n))}function ke(n,t,r){var e=n.constructor;switch(t){case"[object ArrayBuffer]":return Rr(n);case"[object Boolean]":case"[object Date]":return new e(+n);case"[object DataView]":return t=r?Rr(n.buffer):n.buffer,new n.constructor(t,n.byteOffset,n.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":
case"[object Uint16Array]":case"[object Uint32Array]":return zr(n,r);case"[object Map]":return new e;case"[object Number]":case"[object String]":return new e(n);case"[object RegExp]":return t=new n.constructor(n.source,_n.exec(n)),t.lastIndex=n.lastIndex,t;case"[object Set]":return new e;case"[object Symbol]":return no?Yu(no.call(n)):{}}}function Ee(n){return of(n)||uf(n)||!!(xi&&n&&n[xi])}function Se(n,t){var r=typeof n;return t=null==t?9007199254740991:t,!!t&&("number"==r||"symbol"!=r&&bn.test(n))&&-1<n&&0==n%1&&n<t;
}function Oe(n,t,r){if(!gu(r))return false;var e=typeof t;return!!("number"==e?lu(r)&&Se(t,r.length):"string"==e&&t in r)&&au(r[t],n)}function Ie(n,t){if(of(n))return false;var r=typeof n;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=n&&!ju(n))||(nn.test(n)||!X.test(n)||null!=t&&n in Yu(t))}function Re(n){var t=ge(n),r=An[t];return typeof r=="function"&&t in Un.prototype&&(n===r||(t=so(r),!!t&&n===t[0]))}function ze(n){var t=n&&n.constructor;return n===(typeof t=="function"&&t.prototype||ri)}function We(n,t){
return function(r){return null!=r&&(r[n]===t&&(t!==T||n in Yu(r)))}}function Be(t,r,e){return r=Li(r===T?t.length-1:r,0),function(){for(var u=arguments,i=-1,o=Li(u.length-r,0),f=Vu(o);++i<o;)f[i]=u[r+i];for(i=-1,o=Vu(r+1);++i<r;)o[i]=u[i];return o[r]=e(f),n(t,this,o)}}function Le(n,t,r){var e=t+"";t=bo;var u,i=Te;return u=(u=e.match(an))?u[1].split(ln):[],r=i(u,r),(i=r.length)&&(u=i-1,r[u]=(1<i?"& ":"")+r[u],r=r.join(2<i?", ":" "),e=e.replace(cn,"{\n/* [wrapped with "+r+"] */\n")),t(n,e)}function Ue(n){
var t=0,r=0;return function(){var e=Ci(),u=16-(e-r);if(r=e,0<u){if(800<=++t)return arguments[0]}else t=0;return n.apply(T,arguments)}}function Ce(n,t){var r=-1,e=n.length,u=e-1;for(t=t===T?e:t;++r<t;){var e=ir(r,u),i=n[e];n[e]=n[r],n[r]=i}return n.length=t,n}function De(n){if(typeof n=="string"||ju(n))return n;var t=n+"";return"0"==t&&1/n==-$?"-0":t}function Me(n){if(null!=n){try{return ui.call(n)}catch(n){}return n+""}return""}function Te(n,t){return r(N,function(r){var e="_."+r[0];t&r[1]&&!o(n,e)&&n.push(e);
}),n.sort()}function $e(n){if(n instanceof Un)return n.clone();var t=new On(n.__wrapped__,n.__chain__);return t.__actions__=Ur(n.__actions__),t.__index__=n.__index__,t.__values__=n.__values__,t}function Fe(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Au(r),0>r&&(r=Li(e+r,0)),_(n,ye(t,3),r)):-1}function Ne(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==T&&(u=Au(r),u=0>r?Li(e+u,0):Ui(u,e-1)),_(n,ye(t,3),u,true)}function Pe(n){return(null==n?0:n.length)?wt(n,1):[]}function Ze(n){
return n&&n.length?n[0]:T}function qe(n){var t=null==n?0:n.length;return t?n[t-1]:T}function Ve(n,t){return n&&n.length&&t&&t.length?er(n,t):n}function Ke(n){return null==n?n:Ti.call(n)}function Ge(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){if(su(n))return t=Li(n.length,t),true}),A(t,function(t){return c(n,b(t))})}function He(t,r){if(!t||!t.length)return[];var e=Ge(t);return null==r?e:c(e,function(t){return n(r,T,t)})}function Je(n){return n=An(n),n.__chain__=true,n}function Ye(n,t){
return t(n)}function Qe(){return this}function Xe(n,t){return(of(n)?r:eo)(n,ye(t,3))}function nu(n,t){return(of(n)?e:uo)(n,ye(t,3))}function tu(n,t){return(of(n)?c:Gt)(n,ye(t,3))}function ru(n,t,r){return t=r?T:t,t=n&&null==t?n.length:t,fe(n,128,T,T,T,T,t)}function eu(n,t){var r;if(typeof t!="function")throw new ni("Expected a function");return n=Au(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=T),r}}function uu(n,t,r){return t=r?T:t,n=fe(n,8,T,T,T,T,T,t),n.placeholder=uu.placeholder,
n}function iu(n,t,r){return t=r?T:t,n=fe(n,16,T,T,T,T,T,t),n.placeholder=iu.placeholder,n}function ou(n,t,r){function e(t){var r=c,e=a;return c=a=T,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===T||r>=t||0>r||g&&n>=l}function i(){var n=Ko();if(u(n))return o(n);var r,e=yo;r=n-_,n=t-(n-p),r=g?Ui(n,l-r):n,h=e(i,r)}function o(n){return h=T,d&&c?e(n):(c=a=T,s)}function f(){var n=Ko(),r=u(n);if(c=arguments,a=this,p=n,r){if(h===T)return _=n=p,h=yo(i,t),v?e(n):s;if(g)return h=yo(i,t),e(p)}return h===T&&(h=yo(i,t)),
s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ni("Expected a function");return t=Eu(t)||0,gu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Li(Eu(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==T&&ao(h),_=0,c=p=a=h=T},f.flush=function(){return h===T?s:o(Ko())},f}function fu(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e),r.cache=i.set(u,e)||i,e)}if(typeof n!="function"||null!=t&&typeof t!="function")throw new ni("Expected a function");
return r.cache=new(fu.Cache||$n),r}function cu(n){if(typeof n!="function")throw new ni("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function au(n,t){return n===t||n!==n&&t!==t}function lu(n){return null!=n&&vu(n.length)&&!pu(n)}function su(n){return du(n)&&lu(n)}function hu(n){if(!du(n))return false;var t=Ot(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!bu(n);
}function pu(n){return!!gu(n)&&(n=Ot(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function _u(n){return typeof n=="number"&&n==Au(n)}function vu(n){return typeof n=="number"&&-1<n&&0==n%1&&9007199254740991>=n}function gu(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function du(n){return null!=n&&typeof n=="object"}function yu(n){return typeof n=="number"||du(n)&&"[object Number]"==Ot(n)}function bu(n){return!(!du(n)||"[object Object]"!=Ot(n))&&(n=gi(n),
null===n||(n=ii.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&ui.call(n)==ai))}function xu(n){return typeof n=="string"||!of(n)&&du(n)&&"[object String]"==Ot(n)}function ju(n){return typeof n=="symbol"||du(n)&&"[object Symbol]"==Ot(n)}function wu(n){if(!n)return[];if(lu(n))return xu(n)?M(n):Ur(n);if(ji&&n[ji]){n=n[ji]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}return t=_o(n),("[object Map]"==t?W:"[object Set]"==t?U:Lu)(n)}function mu(n){return n?(n=Eu(n),
n===$||n===-$?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function Au(n){n=mu(n);var t=n%1;return n===n?t?n-t:n:0}function ku(n){return n?pt(Au(n),0,4294967295):0}function Eu(n){if(typeof n=="number")return n;if(ju(n))return F;if(gu(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=gu(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(un,"");var t=gn.test(n);return t||yn.test(n)?Mn(n.slice(2),t?2:8):vn.test(n)?F:+n}function Su(n){return Cr(n,Wu(n))}function Ou(n){return null==n?"":yr(n);
}function Iu(n,t,r){return n=null==n?T:Et(n,t),n===T?r:n}function Ru(n,t){return null!=n&&we(n,t,zt)}function zu(n){return lu(n)?qn(n):Vt(n)}function Wu(n){if(lu(n))n=qn(n,true);else if(gu(n)){var t,r=ze(n),e=[];for(t in n)("constructor"!=t||!r&&ii.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in Yu(n))t.push(r);n=t}return n}function Bu(n,t){if(null==n)return{};var r=c(ve(n),function(n){return[n]});return t=ye(t),tr(n,r,function(n,r){return t(n,r[0])})}function Lu(n){return null==n?[]:S(n,zu(n));
}function Uu(n){return Tf(Ou(n).toLowerCase())}function Cu(n){return(n=Ou(n))&&n.replace(xn,Xn).replace(Sn,"")}function Du(n,t,r){return n=Ou(n),t=r?T:t,t===T?zn.test(n)?n.match(In)||[]:n.match(sn)||[]:n.match(t)||[]}function Mu(n){return function(){return n}}function Tu(n){return n}function $u(n){return qt(typeof n=="function"?n:_t(n,1))}function Fu(n,t,e){var u=zu(t),i=kt(t,u);null!=e||gu(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=kt(t,zu(t)));var o=!(gu(e)&&"chain"in e&&!e.chain),f=pu(n);return r(i,function(r){
var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Ur(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function Nu(){}function Pu(n){return Ie(n)?b(De(n)):rr(n)}function Zu(){return[]}function qu(){return false}mn=null==mn?Fn:rt.defaults(Fn.Object(),mn,rt.pick(Fn,Wn));var Vu=mn.Array,Ku=mn.Date,Gu=mn.Error,Hu=mn.Function,Ju=mn.Math,Yu=mn.Object,Qu=mn.RegExp,Xu=mn.String,ni=mn.TypeError,ti=Vu.prototype,ri=Yu.prototype,ei=mn["__core-js_shared__"],ui=Hu.prototype.toString,ii=ri.hasOwnProperty,oi=0,fi=function(){
var n=/[^.]+$/.exec(ei&&ei.keys&&ei.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),ci=ri.toString,ai=ui.call(Yu),li=Fn._,si=Qu("^"+ui.call(ii).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),hi=Zn?mn.Buffer:T,pi=mn.Symbol,_i=mn.Uint8Array,vi=hi?hi.f:T,gi=B(Yu.getPrototypeOf,Yu),di=Yu.create,yi=ri.propertyIsEnumerable,bi=ti.splice,xi=pi?pi.isConcatSpreadable:T,ji=pi?pi.iterator:T,wi=pi?pi.toStringTag:T,mi=function(){try{var n=je(Yu,"defineProperty");
return n({},"",{}),n}catch(n){}}(),Ai=mn.clearTimeout!==Fn.clearTimeout&&mn.clearTimeout,ki=Ku&&Ku.now!==Fn.Date.now&&Ku.now,Ei=mn.setTimeout!==Fn.setTimeout&&mn.setTimeout,Si=Ju.ceil,Oi=Ju.floor,Ii=Yu.getOwnPropertySymbols,Ri=hi?hi.isBuffer:T,zi=mn.isFinite,Wi=ti.join,Bi=B(Yu.keys,Yu),Li=Ju.max,Ui=Ju.min,Ci=Ku.now,Di=mn.parseInt,Mi=Ju.random,Ti=ti.reverse,$i=je(mn,"DataView"),Fi=je(mn,"Map"),Ni=je(mn,"Promise"),Pi=je(mn,"Set"),Zi=je(mn,"WeakMap"),qi=je(Yu,"create"),Vi=Zi&&new Zi,Ki={},Gi=Me($i),Hi=Me(Fi),Ji=Me(Ni),Yi=Me(Pi),Qi=Me(Zi),Xi=pi?pi.prototype:T,no=Xi?Xi.valueOf:T,to=Xi?Xi.toString:T,ro=function(){
function n(){}return function(t){return gu(t)?di?di(t):(n.prototype=t,t=new n,n.prototype=T,t):{}}}();An.templateSettings={escape:J,evaluate:Y,interpolate:Q,variable:"",imports:{_:An}},An.prototype=kn.prototype,An.prototype.constructor=An,On.prototype=ro(kn.prototype),On.prototype.constructor=On,Un.prototype=ro(kn.prototype),Un.prototype.constructor=Un,Cn.prototype.clear=function(){this.__data__=qi?qi(null):{},this.size=0},Cn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n],
this.size-=n?1:0,n},Cn.prototype.get=function(n){var t=this.__data__;return qi?(n=t[n],"__lodash_hash_undefined__"===n?T:n):ii.call(t,n)?t[n]:T},Cn.prototype.has=function(n){var t=this.__data__;return qi?t[n]!==T:ii.call(t,n)},Cn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=qi&&t===T?"__lodash_hash_undefined__":t,this},Tn.prototype.clear=function(){this.__data__=[],this.size=0},Tn.prototype.delete=function(n){var t=this.__data__;return n=ft(t,n),!(0>n)&&(n==t.length-1?t.pop():bi.call(t,n,1),
--this.size,true)},Tn.prototype.get=function(n){var t=this.__data__;return n=ft(t,n),0>n?T:t[n][1]},Tn.prototype.has=function(n){return-1<ft(this.__data__,n)},Tn.prototype.set=function(n,t){var r=this.__data__,e=ft(r,n);return 0>e?(++this.size,r.push([n,t])):r[e][1]=t,this},$n.prototype.clear=function(){this.size=0,this.__data__={hash:new Cn,map:new(Fi||Tn),string:new Cn}},$n.prototype.delete=function(n){return n=be(this,n).delete(n),this.size-=n?1:0,n},$n.prototype.get=function(n){return be(this,n).get(n);
},$n.prototype.has=function(n){return be(this,n).has(n)},$n.prototype.set=function(n,t){var r=be(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Nn.prototype.add=Nn.prototype.push=function(n){return this.__data__.set(n,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(n){return this.__data__.has(n)},Pn.prototype.clear=function(){this.__data__=new Tn,this.size=0},Pn.prototype.delete=function(n){var t=this.__data__;return n=t.delete(n),this.size=t.size,n},Pn.prototype.get=function(n){
return this.__data__.get(n)},Pn.prototype.has=function(n){return this.__data__.has(n)},Pn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Tn){var e=r.__data__;if(!Fi||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new $n(e)}return r.set(n,t),this.size=r.size,this};var eo=Fr(mt),uo=Fr(At,true),io=Nr(),oo=Nr(true),fo=Vi?function(n,t){return Vi.set(n,t),n}:Tu,co=mi?function(n,t){return mi(n,"toString",{configurable:true,enumerable:false,value:Mu(t),writable:true})}:Tu,ao=Ai||function(n){
return Fn.clearTimeout(n)},lo=Pi&&1/U(new Pi([,-0]))[1]==$?function(n){return new Pi(n)}:Nu,so=Vi?function(n){return Vi.get(n)}:Nu,ho=Ii?function(n){return null==n?[]:(n=Yu(n),i(Ii(n),function(t){return yi.call(n,t)}))}:Zu,po=Ii?function(n){for(var t=[];n;)a(t,ho(n)),n=gi(n);return t}:Zu,_o=Ot;($i&&"[object DataView]"!=_o(new $i(new ArrayBuffer(1)))||Fi&&"[object Map]"!=_o(new Fi)||Ni&&"[object Promise]"!=_o(Ni.resolve())||Pi&&"[object Set]"!=_o(new Pi)||Zi&&"[object WeakMap]"!=_o(new Zi))&&(_o=function(n){
var t=Ot(n);if(n=(n="[object Object]"==t?n.constructor:T)?Me(n):"")switch(n){case Gi:return"[object DataView]";case Hi:return"[object Map]";case Ji:return"[object Promise]";case Yi:return"[object Set]";case Qi:return"[object WeakMap]"}return t});var vo=ei?pu:qu,go=Ue(fo),yo=Ei||function(n,t){return Fn.setTimeout(n,t)},bo=Ue(co),xo=function(n){n=fu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(tn,function(n,r,e,u){
t.push(e?u.replace(hn,"$1"):r||n)}),t}),jo=fr(function(n,t){return su(n)?yt(n,wt(t,1,su,true)):[]}),wo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),ye(r,2)):[]}),mo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),T,r):[]}),Ao=fr(function(n){var t=c(n,kr);return t.length&&t[0]===n[0]?Wt(t):[]}),ko=fr(function(n){var t=qe(n),r=c(n,kr);return t===qe(r)?t=T:r.pop(),r.length&&r[0]===n[0]?Wt(r,ye(t,2)):[]}),Eo=fr(function(n){var t=qe(n),r=c(n,kr);return(t=typeof t=="function"?t:T)&&r.pop(),
r.length&&r[0]===n[0]?Wt(r,T,t):[]}),So=fr(Ve),Oo=pe(function(n,t){var r=null==n?0:n.length,e=ht(n,t);return ur(n,c(t,function(n){return Se(n,r)?+n:n}).sort(Wr)),e}),Io=fr(function(n){return br(wt(n,1,su,true))}),Ro=fr(function(n){var t=qe(n);return su(t)&&(t=T),br(wt(n,1,su,true),ye(t,2))}),zo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return br(wt(n,1,su,true),T,t)}),Wo=fr(function(n,t){return su(n)?yt(n,t):[]}),Bo=fr(function(n){return mr(i(n,su))}),Lo=fr(function(n){var t=qe(n);return su(t)&&(t=T),
mr(i(n,su),ye(t,2))}),Uo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return mr(i(n,su),T,t)}),Co=fr(Ge),Do=fr(function(n){var t=n.length,t=1<t?n[t-1]:T,t=typeof t=="function"?(n.pop(),t):T;return He(n,t)}),Mo=pe(function(n){function t(t){return ht(t,n)}var r=n.length,e=r?n[0]:0,u=this.__wrapped__;return!(1<r||this.__actions__.length)&&u instanceof Un&&Se(e)?(u=u.slice(e,+e+(r?1:0)),u.__actions__.push({func:Ye,args:[t],thisArg:T}),new On(u,this.__chain__).thru(function(n){return r&&!n.length&&n.push(T),
n})):this.thru(t)}),To=Tr(function(n,t,r){ii.call(n,r)?++n[r]:st(n,r,1)}),$o=Gr(Fe),Fo=Gr(Ne),No=Tr(function(n,t,r){ii.call(n,r)?n[r].push(t):st(n,r,[t])}),Po=fr(function(t,r,e){var u=-1,i=typeof r=="function",o=lu(t)?Vu(t.length):[];return eo(t,function(t){o[++u]=i?n(r,t,e):Lt(t,r,e)}),o}),Zo=Tr(function(n,t,r){st(n,r,t)}),qo=Tr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Vo=fr(function(n,t){if(null==n)return[];var r=t.length;return 1<r&&Oe(n,t[0],t[1])?t=[]:2<r&&Oe(t[0],t[1],t[2])&&(t=[t[0]]),
Xt(n,wt(t,1),[])}),Ko=ki||function(){return Fn.Date.now()},Go=fr(function(n,t,r){var e=1;if(r.length)var u=L(r,de(Go)),e=32|e;return fe(n,e,t,r,u)}),Ho=fr(function(n,t,r){var e=3;if(r.length)var u=L(r,de(Ho)),e=32|e;return fe(t,e,n,r,u)}),Jo=fr(function(n,t){return dt(n,1,t)}),Yo=fr(function(n,t,r){return dt(n,Eu(t)||0,r)});fu.Cache=$n;var Qo=fr(function(t,r){r=1==r.length&&of(r[0])?c(r[0],E(ye())):c(wt(r,1),E(ye()));var e=r.length;return fr(function(u){for(var i=-1,o=Ui(u.length,e);++i<o;)u[i]=r[i].call(this,u[i]);
return n(t,this,u)})}),Xo=fr(function(n,t){return fe(n,32,T,t,L(t,de(Xo)))}),nf=fr(function(n,t){return fe(n,64,T,t,L(t,de(nf)))}),tf=pe(function(n,t){return fe(n,256,T,T,T,t)}),rf=ee(It),ef=ee(function(n,t){return n>=t}),uf=Ut(function(){return arguments}())?Ut:function(n){return du(n)&&ii.call(n,"callee")&&!yi.call(n,"callee")},of=Vu.isArray,ff=Vn?E(Vn):Ct,cf=Ri||qu,af=Kn?E(Kn):Dt,lf=Gn?E(Gn):Tt,sf=Hn?E(Hn):Nt,hf=Jn?E(Jn):Pt,pf=Yn?E(Yn):Zt,_f=ee(Kt),vf=ee(function(n,t){return n<=t}),gf=$r(function(n,t){
if(ze(t)||lu(t))Cr(t,zu(t),n);else for(var r in t)ii.call(t,r)&&ot(n,r,t[r])}),df=$r(function(n,t){Cr(t,Wu(t),n)}),yf=$r(function(n,t,r,e){Cr(t,Wu(t),n,e)}),bf=$r(function(n,t,r,e){Cr(t,zu(t),n,e)}),xf=pe(ht),jf=fr(function(n,t){n=Yu(n);var r=-1,e=t.length,u=2<e?t[2]:T;for(u&&Oe(t[0],t[1],u)&&(e=1);++r<e;)for(var u=t[r],i=Wu(u),o=-1,f=i.length;++o<f;){var c=i[o],a=n[c];(a===T||au(a,ri[c])&&!ii.call(n,c))&&(n[c]=u[c])}return n}),wf=fr(function(t){return t.push(T,ae),n(Sf,T,t)}),mf=Yr(function(n,t,r){
null!=t&&typeof t.toString!="function"&&(t=ci.call(t)),n[t]=r},Mu(Tu)),Af=Yr(function(n,t,r){null!=t&&typeof t.toString!="function"&&(t=ci.call(t)),ii.call(n,t)?n[t].push(r):n[t]=[r]},ye),kf=fr(Lt),Ef=$r(function(n,t,r){Yt(n,t,r)}),Sf=$r(function(n,t,r,e){Yt(n,t,r,e)}),Of=pe(function(n,t){var r={};if(null==n)return r;var e=false;t=c(t,function(t){return t=Sr(t,n),e||(e=1<t.length),t}),Cr(n,ve(n),r),e&&(r=_t(r,7,le));for(var u=t.length;u--;)xr(r,t[u]);return r}),If=pe(function(n,t){return null==n?{}:nr(n,t);
}),Rf=oe(zu),zf=oe(Wu),Wf=qr(function(n,t,r){return t=t.toLowerCase(),n+(r?Uu(t):t)}),Bf=qr(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Lf=qr(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),Uf=Zr("toLowerCase"),Cf=qr(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}),Df=qr(function(n,t,r){return n+(r?" ":"")+Tf(t)}),Mf=qr(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),Tf=Zr("toUpperCase"),$f=fr(function(t,r){try{return n(t,T,r)}catch(n){return hu(n)?n:new Gu(n)}}),Ff=pe(function(n,t){
return r(t,function(t){t=De(t),st(n,t,Go(n[t],n))}),n}),Nf=Hr(),Pf=Hr(true),Zf=fr(function(n,t){return function(r){return Lt(r,n,t)}}),qf=fr(function(n,t){return function(r){return Lt(n,r,t)}}),Vf=Xr(c),Kf=Xr(u),Gf=Xr(h),Hf=re(),Jf=re(true),Yf=Qr(function(n,t){return n+t},0),Qf=ie("ceil"),Xf=Qr(function(n,t){return n/t},1),nc=ie("floor"),tc=Qr(function(n,t){return n*t},1),rc=ie("round"),ec=Qr(function(n,t){return n-t},0);return An.after=function(n,t){if(typeof t!="function")throw new ni("Expected a function");
return n=Au(n),function(){if(1>--n)return t.apply(this,arguments)}},An.ary=ru,An.assign=gf,An.assignIn=df,An.assignInWith=yf,An.assignWith=bf,An.at=xf,An.before=eu,An.bind=Go,An.bindAll=Ff,An.bindKey=Ho,An.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return of(n)?n:[n]},An.chain=Je,An.chunk=function(n,t,r){if(t=(r?Oe(n,t,r):t===T)?1:Li(Au(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Vu(Si(r/t));e<r;)i[u++]=hr(n,e,e+=t);return i},An.compact=function(n){for(var t=-1,r=null==n?0:n.length,e=0,u=[];++t<r;){
var i=n[t];i&&(u[e++]=i)}return u},An.concat=function(){var n=arguments.length;if(!n)return[];for(var t=Vu(n-1),r=arguments[0];n--;)t[n-1]=arguments[n];return a(of(r)?Ur(r):[r],wt(t,1))},An.cond=function(t){var r=null==t?0:t.length,e=ye();return t=r?c(t,function(n){if("function"!=typeof n[1])throw new ni("Expected a function");return[e(n[0]),n[1]]}):[],fr(function(e){for(var u=-1;++u<r;){var i=t[u];if(n(i[0],this,e))return n(i[1],this,e)}})},An.conforms=function(n){return vt(_t(n,1))},An.constant=Mu,
An.countBy=To,An.create=function(n,t){var r=ro(n);return null==t?r:at(r,t)},An.curry=uu,An.curryRight=iu,An.debounce=ou,An.defaults=jf,An.defaultsDeep=wf,An.defer=Jo,An.delay=Yo,An.difference=jo,An.differenceBy=wo,An.differenceWith=mo,An.drop=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),hr(n,0>t?0:t,e)):[]},An.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0,0>t?0:t)):[]},An.dropRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true,true):[];
},An.dropWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true):[]},An.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&Oe(n,t,r)&&(r=0,e=u),u=n.length,r=Au(r),0>r&&(r=-r>u?0:u+r),e=e===T||e>u?u:Au(e),0>e&&(e+=u),e=r>e?0:ku(e);r<e;)n[r++]=t;return n},An.filter=function(n,t){return(of(n)?i:jt)(n,ye(t,3))},An.flatMap=function(n,t){return wt(tu(n,t),1)},An.flatMapDeep=function(n,t){return wt(tu(n,t),$)},An.flatMapDepth=function(n,t,r){return r=r===T?1:Au(r),
wt(tu(n,t),r)},An.flatten=Pe,An.flattenDeep=function(n){return(null==n?0:n.length)?wt(n,$):[]},An.flattenDepth=function(n,t){return null!=n&&n.length?(t=t===T?1:Au(t),wt(n,t)):[]},An.flip=function(n){return fe(n,512)},An.flow=Nf,An.flowRight=Pf,An.fromPairs=function(n){for(var t=-1,r=null==n?0:n.length,e={};++t<r;){var u=n[t];e[u[0]]=u[1]}return e},An.functions=function(n){return null==n?[]:kt(n,zu(n))},An.functionsIn=function(n){return null==n?[]:kt(n,Wu(n))},An.groupBy=No,An.initial=function(n){
return(null==n?0:n.length)?hr(n,0,-1):[]},An.intersection=Ao,An.intersectionBy=ko,An.intersectionWith=Eo,An.invert=mf,An.invertBy=Af,An.invokeMap=Po,An.iteratee=$u,An.keyBy=Zo,An.keys=zu,An.keysIn=Wu,An.map=tu,An.mapKeys=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,t(n,e,u),n)}),r},An.mapValues=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,e,t(n,e,u))}),r},An.matches=function(n){return Ht(_t(n,1))},An.matchesProperty=function(n,t){return Jt(n,_t(t,1))},An.memoize=fu,
An.merge=Ef,An.mergeWith=Sf,An.method=Zf,An.methodOf=qf,An.mixin=Fu,An.negate=cu,An.nthArg=function(n){return n=Au(n),fr(function(t){return Qt(t,n)})},An.omit=Of,An.omitBy=function(n,t){return Bu(n,cu(ye(t)))},An.once=function(n){return eu(2,n)},An.orderBy=function(n,t,r,e){return null==n?[]:(of(t)||(t=null==t?[]:[t]),r=e?T:r,of(r)||(r=null==r?[]:[r]),Xt(n,t,r))},An.over=Vf,An.overArgs=Qo,An.overEvery=Kf,An.overSome=Gf,An.partial=Xo,An.partialRight=nf,An.partition=qo,An.pick=If,An.pickBy=Bu,An.property=Pu,
An.propertyOf=function(n){return function(t){return null==n?T:Et(n,t)}},An.pull=So,An.pullAll=Ve,An.pullAllBy=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,ye(r,2)):n},An.pullAllWith=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,T,r):n},An.pullAt=Oo,An.range=Hf,An.rangeRight=Jf,An.rearg=tf,An.reject=function(n,t){return(of(n)?i:jt)(n,cu(ye(t,3)))},An.remove=function(n,t){var r=[];if(!n||!n.length)return r;var e=-1,u=[],i=n.length;for(t=ye(t,3);++e<i;){var o=n[e];t(o,e,n)&&(r.push(o),
u.push(e))}return ur(n,u),r},An.rest=function(n,t){if(typeof n!="function")throw new ni("Expected a function");return t=t===T?t:Au(t),fr(n,t)},An.reverse=Ke,An.sampleSize=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Au(t),(of(n)?et:ar)(n,t)},An.set=function(n,t,r){return null==n?n:lr(n,t,r)},An.setWith=function(n,t,r,e){return e=typeof e=="function"?e:T,null==n?n:lr(n,t,r,e)},An.shuffle=function(n){return(of(n)?ut:sr)(n)},An.slice=function(n,t,r){var e=null==n?0:n.length;return e?(r&&typeof r!="number"&&Oe(n,t,r)?(t=0,
r=e):(t=null==t?0:Au(t),r=r===T?e:Au(r)),hr(n,t,r)):[]},An.sortBy=Vo,An.sortedUniq=function(n){return n&&n.length?gr(n):[]},An.sortedUniqBy=function(n,t){return n&&n.length?gr(n,ye(t,2)):[]},An.split=function(n,t,r){return r&&typeof r!="number"&&Oe(n,t,r)&&(t=r=T),r=r===T?4294967295:r>>>0,r?(n=Ou(n))&&(typeof t=="string"||null!=t&&!sf(t))&&(t=yr(t),!t&&Rn.test(n))?Or(M(n),0,r):n.split(t,r):[]},An.spread=function(t,r){if(typeof t!="function")throw new ni("Expected a function");return r=null==r?0:Li(Au(r),0),
fr(function(e){var u=e[r];return e=Or(e,0,r),u&&a(e,u),n(t,this,e)})},An.tail=function(n){var t=null==n?0:n.length;return t?hr(n,1,t):[]},An.take=function(n,t,r){return n&&n.length?(t=r||t===T?1:Au(t),hr(n,0,0>t?0:t)):[]},An.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0>t?0:t,e)):[]},An.takeRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),false,true):[]},An.takeWhile=function(n,t){return n&&n.length?jr(n,ye(t,3)):[]},An.tap=function(n,t){return t(n),
n},An.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ni("Expected a function");return gu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ou(n,t,{leading:e,maxWait:t,trailing:u})},An.thru=Ye,An.toArray=wu,An.toPairs=Rf,An.toPairsIn=zf,An.toPath=function(n){return of(n)?c(n,De):ju(n)?[n]:Ur(xo(Ou(n)))},An.toPlainObject=Su,An.transform=function(n,t,e){var u=of(n),i=u||cf(n)||pf(n);if(t=ye(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:gu(n)&&pu(o)?ro(gi(n)):{};
}return(i?r:mt)(n,function(n,r,u){return t(e,n,r,u)}),e},An.unary=function(n){return ru(n,1)},An.union=Io,An.unionBy=Ro,An.unionWith=zo,An.uniq=function(n){return n&&n.length?br(n):[]},An.uniqBy=function(n,t){return n&&n.length?br(n,ye(t,2)):[]},An.uniqWith=function(n,t){return t=typeof t=="function"?t:T,n&&n.length?br(n,T,t):[]},An.unset=function(n,t){return null==n||xr(n,t)},An.unzip=Ge,An.unzipWith=He,An.update=function(n,t,r){return null==n?n:lr(n,t,Er(r)(Et(n,t)),void 0)},An.updateWith=function(n,t,r,e){
return e=typeof e=="function"?e:T,null!=n&&(n=lr(n,t,Er(r)(Et(n,t)),e)),n},An.values=Lu,An.valuesIn=function(n){return null==n?[]:S(n,Wu(n))},An.without=Wo,An.words=Du,An.wrap=function(n,t){return Xo(Er(t),n)},An.xor=Bo,An.xorBy=Lo,An.xorWith=Uo,An.zip=Co,An.zipObject=function(n,t){return Ar(n||[],t||[],ot)},An.zipObjectDeep=function(n,t){return Ar(n||[],t||[],lr)},An.zipWith=Do,An.entries=Rf,An.entriesIn=zf,An.extend=df,An.extendWith=yf,Fu(An,An),An.add=Yf,An.attempt=$f,An.camelCase=Wf,An.capitalize=Uu,
An.ceil=Qf,An.clamp=function(n,t,r){return r===T&&(r=t,t=T),r!==T&&(r=Eu(r),r=r===r?r:0),t!==T&&(t=Eu(t),t=t===t?t:0),pt(Eu(n),t,r)},An.clone=function(n){return _t(n,4)},An.cloneDeep=function(n){return _t(n,5)},An.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,5,t)},An.cloneWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,4,t)},An.conformsTo=function(n,t){return null==t||gt(n,t,zu(t))},An.deburr=Cu,An.defaultTo=function(n,t){return null==n||n!==n?t:n},An.divide=Xf,An.endsWith=function(n,t,r){
n=Ou(n),t=yr(t);var e=n.length,e=r=r===T?e:pt(Au(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},An.eq=au,An.escape=function(n){return(n=Ou(n))&&H.test(n)?n.replace(K,nt):n},An.escapeRegExp=function(n){return(n=Ou(n))&&en.test(n)?n.replace(rn,"\\$&"):n},An.every=function(n,t,r){var e=of(n)?u:bt;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.find=$o,An.findIndex=Fe,An.findKey=function(n,t){return p(n,ye(t,3),mt)},An.findLast=Fo,An.findLastIndex=Ne,An.findLastKey=function(n,t){return p(n,ye(t,3),At);
},An.floor=nc,An.forEach=Xe,An.forEachRight=nu,An.forIn=function(n,t){return null==n?n:io(n,ye(t,3),Wu)},An.forInRight=function(n,t){return null==n?n:oo(n,ye(t,3),Wu)},An.forOwn=function(n,t){return n&&mt(n,ye(t,3))},An.forOwnRight=function(n,t){return n&&At(n,ye(t,3))},An.get=Iu,An.gt=rf,An.gte=ef,An.has=function(n,t){return null!=n&&we(n,t,Rt)},An.hasIn=Ru,An.head=Ze,An.identity=Tu,An.includes=function(n,t,r,e){return n=lu(n)?n:Lu(n),r=r&&!e?Au(r):0,e=n.length,0>r&&(r=Li(e+r,0)),xu(n)?r<=e&&-1<n.indexOf(t,r):!!e&&-1<v(n,t,r);
},An.indexOf=function(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Au(r),0>r&&(r=Li(e+r,0)),v(n,t,r)):-1},An.inRange=function(n,t,r){return t=mu(t),r===T?(r=t,t=0):r=mu(r),n=Eu(n),n>=Ui(t,r)&&n<Li(t,r)},An.invoke=kf,An.isArguments=uf,An.isArray=of,An.isArrayBuffer=ff,An.isArrayLike=lu,An.isArrayLikeObject=su,An.isBoolean=function(n){return true===n||false===n||du(n)&&"[object Boolean]"==Ot(n)},An.isBuffer=cf,An.isDate=af,An.isElement=function(n){return du(n)&&1===n.nodeType&&!bu(n)},An.isEmpty=function(n){
if(null==n)return true;if(lu(n)&&(of(n)||typeof n=="string"||typeof n.splice=="function"||cf(n)||pf(n)||uf(n)))return!n.length;var t=_o(n);if("[object Map]"==t||"[object Set]"==t)return!n.size;if(ze(n))return!Vt(n).length;for(var r in n)if(ii.call(n,r))return false;return true},An.isEqual=function(n,t){return Mt(n,t)},An.isEqualWith=function(n,t,r){var e=(r=typeof r=="function"?r:T)?r(n,t):T;return e===T?Mt(n,t,T,r):!!e},An.isError=hu,An.isFinite=function(n){return typeof n=="number"&&zi(n)},An.isFunction=pu,
An.isInteger=_u,An.isLength=vu,An.isMap=lf,An.isMatch=function(n,t){return n===t||$t(n,t,xe(t))},An.isMatchWith=function(n,t,r){return r=typeof r=="function"?r:T,$t(n,t,xe(t),r)},An.isNaN=function(n){return yu(n)&&n!=+n},An.isNative=function(n){if(vo(n))throw new Gu("Unsupported core-js use. Try https://npms.io/search?q=ponyfill.");return Ft(n)},An.isNil=function(n){return null==n},An.isNull=function(n){return null===n},An.isNumber=yu,An.isObject=gu,An.isObjectLike=du,An.isPlainObject=bu,An.isRegExp=sf,
An.isSafeInteger=function(n){return _u(n)&&-9007199254740991<=n&&9007199254740991>=n},An.isSet=hf,An.isString=xu,An.isSymbol=ju,An.isTypedArray=pf,An.isUndefined=function(n){return n===T},An.isWeakMap=function(n){return du(n)&&"[object WeakMap]"==_o(n)},An.isWeakSet=function(n){return du(n)&&"[object WeakSet]"==Ot(n)},An.join=function(n,t){return null==n?"":Wi.call(n,t)},An.kebabCase=Bf,An.last=qe,An.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==T&&(u=Au(r),u=0>u?Li(e+u,0):Ui(u,e-1)),
t===t){for(r=u+1;r--&&n[r]!==t;);n=r}else n=_(n,d,u,true);return n},An.lowerCase=Lf,An.lowerFirst=Uf,An.lt=_f,An.lte=vf,An.max=function(n){return n&&n.length?xt(n,Tu,It):T},An.maxBy=function(n,t){return n&&n.length?xt(n,ye(t,2),It):T},An.mean=function(n){return y(n,Tu)},An.meanBy=function(n,t){return y(n,ye(t,2))},An.min=function(n){return n&&n.length?xt(n,Tu,Kt):T},An.minBy=function(n,t){return n&&n.length?xt(n,ye(t,2),Kt):T},An.stubArray=Zu,An.stubFalse=qu,An.stubObject=function(){return{}},An.stubString=function(){
return""},An.stubTrue=function(){return true},An.multiply=tc,An.nth=function(n,t){return n&&n.length?Qt(n,Au(t)):T},An.noConflict=function(){return Fn._===this&&(Fn._=li),this},An.noop=Nu,An.now=Ko,An.pad=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return!t||e>=t?n:(t=(t-e)/2,ne(Oi(t),r)+n+ne(Si(t),r))},An.padEnd=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return t&&e<t?n+ne(t-e,r):n},An.padStart=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return t&&e<t?ne(t-e,r)+n:n},An.parseInt=function(n,t,r){
return r||null==t?t=0:t&&(t=+t),Di(Ou(n).replace(on,""),t||0)},An.random=function(n,t,r){if(r&&typeof r!="boolean"&&Oe(n,t,r)&&(t=r=T),r===T&&(typeof t=="boolean"?(r=t,t=T):typeof n=="boolean"&&(r=n,n=T)),n===T&&t===T?(n=0,t=1):(n=mu(n),t===T?(t=n,n=0):t=mu(t)),n>t){var e=n;n=t,t=e}return r||n%1||t%1?(r=Mi(),Ui(n+r*(t-n+Dn("1e-"+((r+"").length-1))),t)):ir(n,t)},An.reduce=function(n,t,r){var e=of(n)?l:j,u=3>arguments.length;return e(n,ye(t,4),r,u,eo)},An.reduceRight=function(n,t,r){var e=of(n)?s:j,u=3>arguments.length;
return e(n,ye(t,4),r,u,uo)},An.repeat=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Au(t),or(Ou(n),t)},An.replace=function(){var n=arguments,t=Ou(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},An.result=function(n,t,r){t=Sr(t,n);var e=-1,u=t.length;for(u||(u=1,n=T);++e<u;){var i=null==n?T:n[De(t[e])];i===T&&(e=u,i=r),n=pu(i)?i.call(n):i}return n},An.round=rc,An.runInContext=x,An.sample=function(n){return(of(n)?Qn:cr)(n)},An.size=function(n){if(null==n)return 0;if(lu(n))return xu(n)?D(n):n.length;
var t=_o(n);return"[object Map]"==t||"[object Set]"==t?n.size:Vt(n).length},An.snakeCase=Cf,An.some=function(n,t,r){var e=of(n)?h:pr;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.sortedIndex=function(n,t){return _r(n,t)},An.sortedIndexBy=function(n,t,r){return vr(n,t,ye(r,2))},An.sortedIndexOf=function(n,t){var r=null==n?0:n.length;if(r){var e=_r(n,t);if(e<r&&au(n[e],t))return e}return-1},An.sortedLastIndex=function(n,t){return _r(n,t,true)},An.sortedLastIndexBy=function(n,t,r){return vr(n,t,ye(r,2),true);
},An.sortedLastIndexOf=function(n,t){if(null==n?0:n.length){var r=_r(n,t,true)-1;if(au(n[r],t))return r}return-1},An.startCase=Df,An.startsWith=function(n,t,r){return n=Ou(n),r=null==r?0:pt(Au(r),0,n.length),t=yr(t),n.slice(r,r+t.length)==t},An.subtract=ec,An.sum=function(n){return n&&n.length?m(n,Tu):0},An.sumBy=function(n,t){return n&&n.length?m(n,ye(t,2)):0},An.template=function(n,t,r){var e=An.templateSettings;r&&Oe(n,t,r)&&(t=T),n=Ou(n),t=yf({},t,e,ce),r=yf({},t.imports,e.imports,ce);var u,i,o=zu(r),f=S(r,o),c=0;
r=t.interpolate||jn;var a="__p+='";r=Qu((t.escape||jn).source+"|"+r.source+"|"+(r===Q?pn:jn).source+"|"+(t.evaluate||jn).source+"|$","g");var l="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,o,f,l){return e||(e=o),a+=n.slice(c,l).replace(wn,z),r&&(u=true,a+="'+__e("+r+")+'"),f&&(i=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+t.length,t}),a+="';",(t=t.variable)||(a="with(obj){"+a+"}"),a=(i?a.replace(P,""):a).replace(Z,"$1").replace(q,"$1;"),
a="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",t=$f(function(){return Hu(o,l+"return "+a).apply(T,f)}),t.source=a,hu(t))throw t;return t},An.times=function(n,t){if(n=Au(n),1>n||9007199254740991<n)return[];var r=4294967295,e=Ui(n,4294967295);for(t=ye(t),n-=4294967295,e=A(e,t);++r<n;)t(r);return e},An.toFinite=mu,An.toInteger=Au,An.toLength=ku,An.toLower=function(n){
return Ou(n).toLowerCase()},An.toNumber=Eu,An.toSafeInteger=function(n){return n?pt(Au(n),-9007199254740991,9007199254740991):0===n?n:0},An.toString=Ou,An.toUpper=function(n){return Ou(n).toUpperCase()},An.trim=function(n,t,r){return(n=Ou(n))&&(r||t===T)?n.replace(un,""):n&&(t=yr(t))?(n=M(n),r=M(t),t=I(n,r),r=R(n,r)+1,Or(n,t,r).join("")):n},An.trimEnd=function(n,t,r){return(n=Ou(n))&&(r||t===T)?n.replace(fn,""):n&&(t=yr(t))?(n=M(n),t=R(n,M(t))+1,Or(n,0,t).join("")):n},An.trimStart=function(n,t,r){
return(n=Ou(n))&&(r||t===T)?n.replace(on,""):n&&(t=yr(t))?(n=M(n),t=I(n,M(t)),Or(n,t).join("")):n},An.truncate=function(n,t){var r=30,e="...";if(gu(t))var u="separator"in t?t.separator:u,r="length"in t?Au(t.length):r,e="omission"in t?yr(t.omission):e;n=Ou(n);var i=n.length;if(Rn.test(n))var o=M(n),i=o.length;if(r>=i)return n;if(i=r-D(e),1>i)return e;if(r=o?Or(o,0,i).join(""):n.slice(0,i),u===T)return r+e;if(o&&(i+=r.length-i),sf(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=Qu(u.source,Ou(_n.exec(u))+"g")),
u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===T?i:c)}}else n.indexOf(yr(u),i)!=i&&(u=r.lastIndexOf(u),-1<u&&(r=r.slice(0,u)));return r+e},An.unescape=function(n){return(n=Ou(n))&&G.test(n)?n.replace(V,tt):n},An.uniqueId=function(n){var t=++oi;return Ou(n)+t},An.upperCase=Mf,An.upperFirst=Tf,An.each=Xe,An.eachRight=nu,An.first=Ze,Fu(An,function(){var n={};return mt(An,function(t,r){ii.call(An.prototype,r)||(n[r]=t)}),n}(),{chain:false}),An.VERSION="4.17.5",r("bind bindKey curry curryRight partial partialRight".split(" "),function(n){
An[n].placeholder=An}),r(["drop","take"],function(n,t){Un.prototype[n]=function(r){r=r===T?1:Li(Au(r),0);var e=this.__filtered__&&!t?new Un(this):this.clone();return e.__filtered__?e.__takeCount__=Ui(r,e.__takeCount__):e.__views__.push({size:Ui(r,4294967295),type:n+(0>e.__dir__?"Right":"")}),e},Un.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Un.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({
iteratee:ye(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){var r="take"+(t?"Right":"");Un.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Un.prototype[n]=function(){return this.__filtered__?new Un(this):this[r](1)}}),Un.prototype.compact=function(){return this.filter(Tu)},Un.prototype.find=function(n){return this.filter(n).head()},Un.prototype.findLast=function(n){return this.reverse().find(n);
},Un.prototype.invokeMap=fr(function(n,t){return typeof n=="function"?new Un(this):this.map(function(r){return Lt(r,n,t)})}),Un.prototype.reject=function(n){return this.filter(cu(ye(n)))},Un.prototype.slice=function(n,t){n=Au(n);var r=this;return r.__filtered__&&(0<n||0>t)?new Un(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==T&&(t=Au(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Un.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Un.prototype.toArray=function(){return this.take(4294967295);
},mt(Un.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=An[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(An.prototype[t]=function(){function t(n){return n=u.apply(An,a([n],f)),e&&h?n[0]:n}var o=this.__wrapped__,f=e?[1]:arguments,c=o instanceof Un,l=f[0],s=c||of(o);s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false);var h=this.__chain__,p=!!this.__actions__.length,l=i&&!h,c=c&&!p;return!i&&s?(o=c?o:new Un(this),o=n.apply(o,f),o.__actions__.push({
func:Ye,args:[t],thisArg:T}),new On(o,h)):l&&c?n.apply(this,f):(o=this.thru(t),l?e?o.value()[0]:o.value():o)})}),r("pop push shift sort splice unshift".split(" "),function(n){var t=ti[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);An.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(of(u)?u:[],n)}return this[r](function(r){return t.apply(of(r)?r:[],n)})}}),mt(Un.prototype,function(n,t){var r=An[t];if(r){var e=r.name+"";
(Ki[e]||(Ki[e]=[])).push({name:t,func:r})}}),Ki[Jr(T,2).name]=[{name:"wrapper",func:T}],Un.prototype.clone=function(){var n=new Un(this.__wrapped__);return n.__actions__=Ur(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Ur(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Ur(this.__views__),n},Un.prototype.reverse=function(){if(this.__filtered__){var n=new Un(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n;
},Un.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=of(t),u=0>r,i=e?t.length:0;n=i;for(var o=this.__views__,f=0,c=-1,a=o.length;++c<a;){var l=o[c],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":n-=s;break;case"take":n=Ui(n,f+s);break;case"takeRight":f=Li(f,n-s)}}if(n={start:f,end:n},o=n.start,f=n.end,n=f-o,o=u?f:o-1,f=this.__iteratees__,c=f.length,a=0,l=Ui(n,this.__takeCount__),!e||!u&&i==n&&l==n)return wr(t,this.__actions__);e=[];n:for(;n--&&a<l;){for(o+=r,
u=-1,i=t[o];++u<c;){var h=f[u],s=h.type,h=(0,h.iteratee)(i);if(2==s)i=h;else if(!h){if(1==s)continue n;break n}}e[a++]=i}return e},An.prototype.at=Mo,An.prototype.chain=function(){return Je(this)},An.prototype.commit=function(){return new On(this.value(),this.__chain__)},An.prototype.next=function(){this.__values__===T&&(this.__values__=wu(this.value()));var n=this.__index__>=this.__values__.length;return{done:n,value:n?T:this.__values__[this.__index__++]}},An.prototype.plant=function(n){for(var t,r=this;r instanceof kn;){
var e=$e(r);e.__index__=0,e.__values__=T,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},An.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Un?(this.__actions__.length&&(n=new Un(this)),n=n.reverse(),n.__actions__.push({func:Ye,args:[Ke],thisArg:T}),new On(n,this.__chain__)):this.thru(Ke)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return wr(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,ji&&(An.prototype[ji]=Qe),
An}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Fn._=rt, define(function(){return rt})):Pn?((Pn.exports=rt)._=rt,Nn._=rt):Fn._=rt}).call(this);

View file

@ -0,0 +1,47 @@
Copyright JS Foundation and other contributors <https://js.foundation/>
Based on Underscore.js, copyright Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/lodash/lodash
The following license applies to all parts of this software except as
documented below:
====
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.
====
Copyright and related rights for sample code are waived via CC0. Sample
code is defined as all source code displayed within the prose of the
documentation.
CC0: http://creativecommons.org/publicdomain/zero/1.0/
====
Files located in the node_modules and vendor directories are externally
maintained libraries used by this software which have their own
licenses; we recommend you read them, as their terms may differ from the
terms above.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,17 @@
{
"name": "nginx",
"version": "0.0.1",
"dependencies": {
"eslint": "^5.4.0",
"raw-loader": "^0.5.1",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0"
},
"devDependencies": {
"lodash-template-webpack-loader": "^1.0.2"
},
"scripts": {
"webpack-cli": "webpack-cli",
"build": "webpack-cli --config webpack.conf.js"
}
}

View file

@ -0,0 +1,10 @@
export const defaultEndpoints = new Backbone.Collection([
{
"name": 'Access Logs',
"logType" : 'accesses'
},
{
"name": 'Error Logs',
"logType" : 'errors'
}
]);

View file

@ -0,0 +1,37 @@
import LogCollection from "../models/LogCollection";
import TabLogList from "./TabLogList";
let LogCategoryList = Backbone.View.extend({
tagName: "ul",
className: "nav nav-tabs",
initialize: function(data) {
this.listenTo(this.collection, "sync", this.render);
this.listenTo(this.collection, "update", this.render);
this.logview = data.logview;
},
render: function() {
this.$el.attr('role', 'tablist');
this.$el.html('');
this.collection.forEach((element) => this.render_one(element));
},
render_one: function(element) {
const servers = new LogCollection(
{
uuid: element.get('url'),
logType: element.get('logType')
}
);
const logList = new TabLogList({
collection: servers,
model: element,
logview: this.logview
});
this.$el.append(logList.$el);
servers.fetch();
}
});
export default LogCategoryList;

View file

@ -0,0 +1,77 @@
import accessLogLine from '../templates/AccessLogLine.html';
import errorLogLine from '../templates/ErrorLogLine.html';
import logViewer from '../templates/logviewer.html';
import LogLinesCollection from "../models/LogLinesCollection";
const LogViewLine = Backbone.View.extend({
tagName: 'tr',
initialize: function (data) {
this.type = data.type;
},
render: function () {
this.$el.html(this.get_template()({model: this.model}));
},
get_template: function() {
if (this.type === 'accesses') {
return accessLogLine;
} else {
return errorLogLine;
}
},
});
const LogView = Backbone.View.extend({
tagName: 'div',
className: 'content-box tab-content',
events: {
"keyup .filter input": "update_filter"
},
initialize: function() {
this.collection = new LogLinesCollection();
this.filter_model = new Backbone.Model();
this.listenTo(this.collection, "sync", this.render);
this.listenTo(this.collection, "update", this.render);
this.listenTo(this.filter_model, "change", this.render);
this.type = '';
},
render: function() {
let tbody = this.$el.find('tbody');
if (tbody.length < 1) {
this.$el.html(logViewer({log_type: this.type, model: this.filter_model}));
tbody = this.$el.find('tbody');
}
else {
tbody.html('');
}
this.collection.filter_collection(this.filter_model).forEach(
(model) => this.render_one(tbody, model)
);
},
render_one: function(parent_element, model) {
const logline = new LogViewLine({type: this.type, model: model});
logline.render();
parent_element.append(logline.$el);
},
get_log: function(type, uuid) {
this.collection.uuid = uuid;
this.collection.logType = type;
this.type = type;
this.$el.html('');
this.filter_model.clear();
this.update();
},
update: function () {
this.collection.fetch();
},
update_filter: function (event) {
const element = event.target;
this.filter_model.set(element.name, $(element).val());
}
});
export default LogView;

View file

@ -0,0 +1,43 @@
import TabTemplateCollection from '../templates/TabCollection.html';
let TabLogList = Backbone.View.extend({
tagName: 'li',
events: {
"click .mainentry": "mainMenuClick",
"click .menuEntry": "menuEntryClick"
},
initialize: function(data) {
this.listenTo(this.collection, "sync", this.render);
this.listenTo(this.collection, "update", this.render);
this.logview = data.logview;
},
render: function() {
this.$el.html('');
this.renderCollection();
},
renderCollection: function() {
this.$el.addClass('dropdown');
this.$el.html('');
this.$el.append(
TabTemplateCollection({model: this.collection, name: this.model.attributes.name})
);
},
mainMenuClick: function () {
if (this.collection.models[0]) {
this.handleElementClick(this.collection.models[0].id);
}
},
menuEntryClick: function (event) {
this.handleElementClick(event.target.dataset['modelUuid']);
},
handleElementClick: function (uuid) {
console.log(uuid);
console.log(this.logview);
this.logview.get_log(this.model.get('logType'), uuid);
}
});
export default TabLogList;

View file

@ -0,0 +1,15 @@
import {defaultEndpoints} from './config';
import LogCategoryList from './controller/LogCategoryList';
import LogView from './controller/LogView';
const logview = new LogView();
const menu = new LogCategoryList({
collection: defaultEndpoints,
logview: logview
});
$(document.getElementById('logapplication'))
.append(menu.$el)
.append(logview.$el);
menu.render();

View file

@ -0,0 +1,13 @@
import LogFileMenuEntry from './LogFileMenuEntry';
const LogCollection = Backbone.Collection.extend({
model: LogFileMenuEntry,
url: function () {
return '/api/nginx/logs/' + this.logType;
},
initialize: function (params) {
this.logType = params.logType;
}
});
export default LogCollection;

View file

@ -0,0 +1,2 @@
export default Backbone.Model.extend({
});

View file

@ -0,0 +1,5 @@
const LogLine = Backbone.Model.extend({
});
export default LogLine;

View file

@ -0,0 +1,33 @@
import LogLine from "./LogLine";
const LogLinesCollection = Backbone.Collection.extend({
model: LogLine,
url: function () {
return `/api/nginx/logs/${this.logType}/${this.uuid}`;
},
initialize: function () {
this.logType = 'none';
this.uuid = 'none';
},
filter_collection: function(filter_model) {
const filter_model_keys = filter_model.keys();
return this.filter(function (model) {
if (!model) {
return false;
}
for (let i = 0; i < filter_model_keys.length; i++) {
const property = filter_model_keys[i];
if (typeof(filter_model.get(property)) !== "string"
|| filter_model.get(property).length === 0) {
continue;
}
if (!model.get(property).includes(filter_model.get(property))) {
return false;
}
}
return true;
});
}
});
export default LogLinesCollection;

View file

@ -0,0 +1,9 @@
<td class="time"><%= model.escape('time') %></td>
<td class="remote_ip"><%= model.escape('remote_ip') %></td>
<td class="username"><%= model.escape('username') %></td>
<td class="status"><%= model.escape('status') %></td>
<td class="size"><%= model.escape('size') %></td>
<td class="referer"><%= model.escape('http_referer') %></td>
<td class="user_agent"><%= model.escape('user_agent') %></td>
<td class="forwarded_for"><%= model.escape('forwarded_for') %></td>
<td class="request_line"><%= model.escape('request_line') %></td>

View file

@ -0,0 +1,5 @@
<td class="date"><%= model.escape('date') %></td>
<td class="time"><%= model.escape('time') %></td>
<td class="severity"><%= model.escape('severity') %></td>
<td class="number"><%= model.escape('number') %></td>
<td class="message"><%= model.escape('message') %></td>

View file

@ -0,0 +1,51 @@
<%
/*
# Copyright (c) 2017 Franco Fichtner <franco@opnsense.org>
# Copyright (c) 2017 Fabian Franz
# Copyright (c) 2014-2015 Deciso B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
*/
%>
<a data-toggle="dropdown"
href="#"
class="dropdown-toggle pull-right visible-lg-inline-block visible-md-inline-block visible-xs-inline-block visible-sm-inline-block"
role="button">
<b><span class="caret"></span></b>
</a>
<a data-toggle="tab"
class="visible-lg-inline-block visible-md-inline-block visible-xs-inline-block visible-sm-inline-block mainentry"
style="border-right: 0px;"><b><%= _.escape(name) %></b></a>
<ul class="dropdown-menu" role="menu">
<% model.forEach(function(row) { %>
<li>
<a data-toggle="tab"
class="menuEntry"
data-model-cid="<%= row.cid %>"
data-model-uuid="<%= row.escape('id') %>"
id="subtab_item_<%= row.escape('id') %>"
href="#subtab_<%= row.escape('id') %>"><%= row.escape('server_name') %></a>
</li>
<% }) %>
</ul>

View file

@ -0,0 +1,33 @@
<%
/*
# Copyright (c) 2017 Franco Fichtner <franco@opnsense.org>
# Copyright (c) 2017 Fabian Franz
# Copyright (c) 2014-2015 Deciso B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
*/
%>
<a data-toggle="tab" href="#subtab_item_<%= model.escape('id') %>">
<b><%= model.escape("server_name") %></b>
</a>

View file

@ -0,0 +1,44 @@
<table class="table table-striped">
<thead>
<tr>
<% if (log_type === 'errors') { %>
<th>Date</th>
<th>Time</th>
<th>Severity</th>
<th>Number</th>
<th>Message</th>
<% } else { %>
<th>Time</th>
<th>Remote IP</th>
<th>Username</th>
<th>Status</th>
<th>Size</th>
<th>Referer</th>
<th>User Agent</th>
<th>Forwarded For</th>
<th>Request Line</th>
<% } %>
</tr>
<tr class="filter">
<% if (log_type === 'errors') { %>
<td><input type="text" value="<%= model.escape('date') %>" name="date" /></td>
<td><input type="text" value="<%= model.escape('time') %>" name="time" /></td>
<td><input type="text" value="<%= model.escape('severity') %>" name="severity" /></td>
<td><input type="text" value="<%= model.escape('number') %>" name="number" /></td>
<td><input type="text" value="<%= model.escape('message') %>" name="message" /></td>
<% } else { %>
<td><input type="text" value="<%= model.escape('time') %>" name="time" /></td>
<td><input type="text" value="<%= model.escape('remote_ip') %>" name="remote_ip" /></td>
<td><input type="text" value="<%= model.escape('username') %>" name="username" /></td>
<td><input type="text" value="<%= model.escape('status') %>" name="status" /></td>
<td><input type="text" value="<%= model.escape('size') %>" name="size" /></td>
<td><input type="text" value="<%= model.escape('http_referer') %>" name="http_referer" /></td>
<td><input type="text" value="<%= model.escape('user_agent') %>" name="user_agent" /></td>
<td><input type="text" value="<%= model.escape('forwarded_for') %>" name="forwarded_for" /></td>
<td><input type="text" value="<%= model.escape('request_line') %>" name="request_line" /></td>
<% } %>
</tr>
</thead>
<tbody>
</tbody>
</table>

View file

@ -0,0 +1,29 @@
const path = require('path'), webpack = require('webpack');
module.exports = {
entry: './src/logviewer.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'production',
module: {
rules: [
{
test: /\.(txt)$/,
use: "raw-loader"
},
{
test: /(\.html)$/,
use: 'lodash-template-webpack-loader'
}
],
},
plugins: [
new webpack.LoaderOptionsPlugin({
options: {
lodashTemplateLoader: {}
}
})
]
};