⛄ Sync 2026-04-23 20:32:35

This commit is contained in:
github-actions[bot] committed 2026-04-23 20:32:35 +08:00
1 parent ac97aa196d
commit 618f49f6ca
206 files changed
+725671

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
#
# Copyright (C) 2022 Jo-Philipp Wich <jo@mein.io>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-base
PKG_BUILD_FLAGS:=no-lto
LUCI_TYPE:=mod
LUCI_BASENAME:=base
LUCI_TITLE:=LuCI core runtime
LUCI_DEPENDS:=\
+rpcd \
+rpcd-mod-file \
+rpcd-mod-luci \
+rpcd-mod-ucode \
+cgi-io \
+ucode \
+ucode-mod-fs \
+ucode-mod-log \
+ucode-mod-uci \
+ucode-mod-ubus \
+ucode-mod-math \
+ucode-mod-html \
+liblucihttp-ucode
PKG_LICENSE:=Apache-2.0
PKG_LICENSE_FILES:=LICENSE NOTICE
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)
include $(INCLUDE_DIR)/host-build.mk
define Package/luci-base/conffiles
/etc/luci-uploads
/etc/config/luci
endef
define Package/luci-base/postinst
#!/bin/sh
if [ -z "$${PKG_INSTROOT}" ] && [ -f /etc/config/uhttpd ]; then
if ! uci -q get uhttpd.main.ucode_prefix | grep -sq /cgi-bin/luci; then
uci add_list uhttpd.main.ucode_prefix='/cgi-bin/luci=/usr/share/ucode/luci/uhttpd.uc'
uci commit uhttpd
service uhttpd reload
fi
fi
exit 0
endef
define Build/Prepare/luci-base
$(CP) ../../NOTICE $(PKG_BUILD_DIR)
$(CP) ../../LICENSE $(PKG_BUILD_DIR)
endef
include $(TOPDIR)/feeds/luci/luci.mk
define Host/Configure
endef
define Host/Compile
$(MAKE) -C src/ clean po2lmo jsmin
endef
define Host/Install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) src/po2lmo $(1)/bin/po2lmo
$(INSTALL_BIN) src/jsmin $(1)/bin/jsmin
endef
$(eval $(call HostBuild))
# call BuildPackage - OpenWrt buildroot signature
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env ucode
'use strict';
import { stdin, stdout } from 'fs';
import dispatch from 'luci.dispatcher';
import request from 'luci.http';
const input_bufsize = 4096;
let input_available = +getenv('CONTENT_LENGTH') || 0;
function read(len) {
if (input_available == 0) {
stdin.close();
return null;
}
let chunk = stdin.read(min(input_available, len ?? input_bufsize, input_bufsize));
if (chunk == null) {
input_available = 0;
stdin.close();
}
else {
input_available -= length(chunk);
}
return chunk;
}
function write(data) {
return stdout.write(data);
}
let req = request(getenv(), read, write);
dispatch(req);
req.close();
@@ -0,0 +1,969 @@
/*
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
*/
/**
* CBI (Configuration Bindings Interface) helper utilities and DOM helpers.
*
* Provides initialization for CBI UI elements, dependency handling,
* validation wiring and miscellaneous helpers used by LuCI forms. Functions
* defined here are registered as global `window.*` symbols.
* @module LuCI.cbi
*/
const cbi_d = [];
if (typeof window !== 'undefined')
window.cbi_d = cbi_d;
const cbi_strings = { path: {}, label: {} };
if (typeof window !== 'undefined')
window.cbi_strings = cbi_strings;
/**
* Read signed 8-bit integer from a byte array at the given offset.
* @param {Array<number>} bytes - Byte array.
* @param {number} off - Offset into the array.
* @returns {number} Signed 8-bit value (returned as unsigned number).
*/
function s8(bytes, off) {
const n = bytes[off];
return (n > 0x7F) ? (n - 256) >>> 0 : n;
}
/**
* Read unsigned 16-bit little-endian integer from a byte array at offset.
* @param {Array<number>} bytes - Byte array.
* @param {number} off - Offset into the array.
* @returns {number} Unsigned 16-bit integer.
*/
function u16(bytes, off) {
return ((bytes[off + 1] << 8) + bytes[off]) >>> 0;
}
/**
* Compute a stable 32-bit-ish string hash used for translation keys.
* Encodes UTF-8 surrogate pairs and mixes bytes into a hex hash string.
* @param {string|null} s - Input string.
* @returns {string|null} Hex hash string or null for empty input.
*/
function sfh(s) {
if (s === null || s.length === 0)
return null;
const bytes = [];
for (let i = 0; i < s.length; i++) {
let ch = s.charCodeAt(i);
// Handle surrogate pairs
if (ch >= 0xD800 && ch <= 0xDBFF && i + 1 < s.length) {
const next = s.charCodeAt(i + 1);
if (next >= 0xDC00 && next <= 0xDFFF) {
ch = 0x10000 + ((ch - 0xD800) << 10) + (next - 0xDC00);
i++;
}
}
if (ch <= 0x7F)
bytes.push(ch);
else if (ch <= 0x7FF)
bytes.push(((ch >>> 6) & 0x1F) | 0xC0,
( ch & 0x3F) | 0x80);
else if (ch <= 0xFFFF)
bytes.push(((ch >>> 12) & 0x0F) | 0xE0,
((ch >>> 6) & 0x3F) | 0x80,
( ch & 0x3F) | 0x80);
else if (ch <= 0x10FFFF)
bytes.push(((ch >>> 18) & 0x07) | 0xF0,
((ch >>> 12) & 0x3F) | 0x80,
((ch >> 6) & 0x3F) | 0x80,
( ch & 0x3F) | 0x80);
}
if (!bytes.length)
return null;
let hash = (bytes.length >>> 0);
let len = (bytes.length >>> 2);
let off = 0, tmp;
while (len--) {
hash += u16(bytes, off);
tmp = ((u16(bytes, off + 2) << 11) ^ hash) >>> 0;
hash = ((hash << 16) ^ tmp) >>> 0;
hash += hash >>> 11;
off += 4;
}
switch ((bytes.length & 3) >>> 0) {
case 3:
hash += u16(bytes, off);
hash = (hash ^ (hash << 16)) >>> 0;
hash = (hash ^ (s8(bytes, off + 2) << 18)) >>> 0;
hash += hash >>> 11;
break;
case 2:
hash += u16(bytes, off);
hash = (hash ^ (hash << 11)) >>> 0;
hash += hash >>> 17;
break;
case 1:
hash += s8(bytes, off);
hash = (hash ^ (hash << 10)) >>> 0;
hash += hash >>> 1;
break;
}
hash = (hash ^ (hash << 3)) >>> 0;
hash += hash >>> 5;
hash = (hash ^ (hash << 4)) >>> 0;
hash += hash >>> 17;
hash = (hash ^ (hash << 25)) >>> 0;
hash += hash >>> 6;
return (0x100000000 + hash).toString(16).slice(1);
}
var plural_function = null;
/**
* Trim whitespace and normalise internal whitespace sequences to single spaces.
* @param {*} s - Value to convert to string and trim.
* @returns {string} Trimmed and normalised string.
*/
function trimws(s) {
return String(s).trim().replace(/[ \t\n]+/g, ' ');
}
/**
* Lookup a translated string for the given message and optional context.
* Falls back to the source string when no translation found.
* @param {string} s - Source string.
* @param {string} [c] - Optional translation context.
* @returns {string} Translated string or original.
*/
function _(s, c) {
var k = (c != null ? trimws(c) + '\u0001' : '') + trimws(s);
return (window.TR && TR[sfh(k)]) || s;
}
/**
* Plural-aware translation lookup.
* @param {number} n - Quantity to evaluate plural form.
* @param {string} s - Singular string.
* @param {string} p - Plural string.
* @param {string} [c] - Optional context.
* @returns {string} Translated plural form or source string.
*/
function N_(n, s, p, c) {
if (plural_function == null && window.TR)
plural_function = new Function('n', (TR['00000000'] || 'plural=(n != 1);') + 'return +plural');
var i = plural_function ? plural_function(n) : (n != 1),
k = (c != null ? trimws(c) + '\u0001' : '') + trimws(s) + '\u0002' + i.toString();
return (window.TR && TR[sfh(k)]) || (i ? p : s);
}
/**
* Register a dependency entry for a field.
* @param {HTMLElement|string} field - Field element or its id.
* @param {Object} dep - Dependency specification object.
* @param {number} index - Order index of the dependent node.
*/
function cbi_d_add(field, dep, index) {
var obj = (typeof(field) === 'string') ? document.getElementById(field) : field;
if (obj) {
var entry
for (var i=0; i<cbi_d.length; i++) {
if (cbi_d[i].id == obj.id) {
entry = cbi_d[i];
break;
}
}
if (!entry) {
entry = {
"node": obj,
"id": obj.id,
"parent": obj.parentNode.id,
"deps": [],
"index": index
};
cbi_d.unshift(entry);
}
entry.deps.push(dep)
}
}
/**
* Check whether an input/select identified by target matches the given reference value.
* @param {string} target - Element id or name to query.
* @param {string} ref - Reference value to compare with.
* @returns {boolean} True if the current value matches ref.
*/
function cbi_d_checkvalue(target, ref) {
var value = null,
query = 'input[id="'+target+'"], input[name="'+target+'"], ' +
'select[id="'+target+'"], select[name="'+target+'"]';
document.querySelectorAll(query).forEach(function(i) {
if (value === null && ((i.type !== 'radio' && i.type !== 'checkbox') || i.checked === true))
value = i.value;
});
return (((value !== null) ? value : "") == ref);
}
/**
* Evaluate a list of dependency descriptors and return whether any match.
* @param {Array<Object>} deps - Array of dependency objects to evaluate.
* @returns {boolean} True when dependencies indicate the element should be shown.
*/
function cbi_d_check(deps) {
var reverse;
var def = false;
for (var i=0; i<deps.length; i++) {
var istat = true;
reverse = false;
for (var j in deps[i]) {
if (j == "!reverse") {
reverse = true;
} else if (j == "!default") {
def = true;
istat = false;
} else {
istat = (istat && cbi_d_checkvalue(j, deps[i][j]))
}
}
if (istat ^ reverse) {
return true;
}
}
return def;
}
/**
* Update DOM nodes based on registered dependencies, showing or hiding
* nodes and restoring their order when dependency state changes.
*/
function cbi_d_update() {
var state = false;
for (var i=0; i<cbi_d.length; i++) {
var entry = cbi_d[i];
var node = document.getElementById(entry.id);
var parent = document.getElementById(entry.parent);
if (node && node.parentNode && !cbi_d_check(entry.deps)) {
node.parentNode.removeChild(node);
state = true;
}
else if (parent && (!node || !node.parentNode) && cbi_d_check(entry.deps)) {
var next = undefined;
for (next = parent.firstChild; next; next = next.nextSibling) {
if (next.getAttribute && parseInt(next.getAttribute('data-index'), 10) > entry.index)
break;
}
if (!next)
parent.appendChild(entry.node);
else
parent.insertBefore(entry.node, next);
state = true;
}
// hide optionals widget if no choices remaining
if (parent && parent.parentNode && parent.getAttribute('data-optionals'))
parent.parentNode.style.display = (parent.options.length <= 1) ? 'none' : '';
}
if (entry && entry.parent)
cbi_tag_last(parent);
if (state)
cbi_d_update();
else if (parent)
parent.dispatchEvent(new CustomEvent('dependency-update', { bubbles: true }));
}
/**
* Initialize CBI widgets and wire up dependency and validation handlers.
* Walks the DOM looking for CBI-specific data attributes and replaces
* placeholders with interactive widgets.
*/
function cbi_init() {
let nodes;
document.querySelectorAll('.cbi-dropdown').forEach(function(node) {
cbi_dropdown_init(node);
node.addEventListener('cbi-dropdown-change', cbi_d_update);
});
nodes = document.querySelectorAll('[data-strings]');
for (let n of nodes) {
const str = JSON.parse(n.getAttribute('data-strings'));
for (let key in str) {
for (let key2 in str[key]) {
const dst = cbi_strings[key] || (cbi_strings[key] = { });
dst[key2] = str[key][key2];
}
}
}
nodes = document.querySelectorAll('[data-depends]');
for (let n of nodes) {
const index = parseInt(n.getAttribute('data-index'), 10);
const depends = JSON.parse(n.getAttribute('data-depends'));
if (!isNaN(index) && depends.length > 0) {
for (let a of depends)
cbi_d_add(n, a, index);
}
}
nodes = document.querySelectorAll('[data-update]');
for (let n of nodes) {
const events = n.getAttribute('data-update').split(' ');
for (let ev of events)
n.addEventListener(ev, cbi_d_update);
}
nodes = document.querySelectorAll('[data-choices]');
for (let node of nodes) {
const choices = JSON.parse(node.getAttribute('data-choices'));
const options = {};
for (let j = 0; j < choices[0].length; j++)
options[choices[0][j]] = choices[1][j];
const def = (node.getAttribute('data-optional') === 'true')
? node.placeholder || '' : null;
const cb = new L.ui.Combobox(node.value, options, {
name: node.getAttribute('name'),
sort: choices[0],
select_placeholder: def || _('-- Please choose --'),
custom_placeholder: node.getAttribute('data-manual') || _('-- custom --')
});
const n = cb.render();
n.addEventListener('cbi-dropdown-change', cbi_d_update);
node.parentNode.replaceChild(n, node);
}
nodes = document.querySelectorAll('[data-dynlist]');
for (let node of nodes) {
const choices = JSON.parse(node.getAttribute('data-dynlist'));
const values = JSON.parse(node.getAttribute('data-values') || '[]');
let options = null;
if (choices[0] && choices[0].length) {
options = {};
for (let j = 0; j < choices[0].length; j++)
options[choices[0][j]] = choices[1][j];
}
let dl = new L.ui.DynamicList(values, options, {
name: node.getAttribute('data-prefix'),
sort: choices[0],
datatype: choices[2],
optional: choices[3],
placeholder: node.getAttribute('data-placeholder')
});
let n = dl.render();
n.addEventListener('cbi-dynlist-change', cbi_d_update);
node.parentNode.replaceChild(n, node);
}
nodes = document.querySelectorAll('[data-type]');
for (let node of nodes) {
cbi_validate_field(node, node.getAttribute('data-optional') === 'true',
node.getAttribute('data-type'));
}
document.querySelectorAll('.cbi-tooltip:not(:empty)').forEach(function(s) {
s.parentNode.classList.add('cbi-tooltip-container');
});
document.querySelectorAll('.cbi-section-remove > input[name^="cbi.rts"]').forEach(function(i) {
let handler = function(ev) {
var bits = this.name.split(/\./),
section = document.getElementById('cbi-' + bits[2] + '-' + bits[3]);
section.style.opacity = (ev.type === 'mouseover') ? 0.5 : '';
};
i.addEventListener('mouseover', handler);
i.addEventListener('mouseout', handler);
});
var tasks = [];
document.querySelectorAll('[data-ui-widget]').forEach(function(node) {
const args = JSON.parse(node.getAttribute('data-ui-widget') || '[]');
const widget = new (Function.prototype.bind.apply(L.ui[args[0]], args));
const markup = widget.render();
tasks.push(Promise.resolve(markup).then(function(markup) {
markup.addEventListener('widget-change', cbi_d_update);
node.parentNode.replaceChild(markup, node);
}));
});
Promise.all(tasks).then(cbi_d_update);
}
/**
* Run all validators associated with a form and optionally show an error.
* @param {HTMLFormElement} form - Form element containing validators.
* @param {string} [errmsg] - Message to show when validation fails.
* @returns {boolean} True when form is valid.
*/
function cbi_validate_form(form, errmsg)
{
/* if triggered by a section removal or addition, don't validate */
if (form.cbi_state == 'add-section' || form.cbi_state == 'del-section')
return true;
if (form.cbi_validators) {
for (let fv of form.cbi_validators) {
const validator = fv;
if (!validator() && errmsg) {
if (typeof window !== 'undefined' && typeof window.alert === 'function')
window.alert(errmsg);
return false;
}
}
}
return true;
}
/**
* Enable/disable a named-section add button depending on input value.
* @param {HTMLInputElement} input - Input that contains the new section name.
*/
function cbi_validate_named_section_add(input)
{
var button = input.parentNode.parentNode.querySelector('.cbi-button-add');
button.disabled = input.value === '';
}
/**
* Trigger a delayed form validation (used to allow UI state to settle).
* @param {HTMLFormElement} form - Form to validate after a short delay.
* @returns {boolean} Always returns true.
*/
function cbi_validate_reset(form)
{
window.setTimeout(
function() { cbi_validate_form(form, null) }, 100
);
return true;
}
/**
* Attach a validator to a field and wire validation events.
* @param {HTMLElement|string} cbid - Element or element id to validate.
* @param {boolean} optional - Whether an empty value is allowed.
* @param {string} type - Validator type expression (passed to L.validation).
*/
function cbi_validate_field(cbid, optional, type)
{
var field = isElem(cbid) ? cbid : document.getElementById(cbid);
var validatorFn;
try {
var cbiValidator = L.validation.create(field, type, optional);
validatorFn = cbiValidator.validate.bind(cbiValidator);
}
catch(e) {
validatorFn = null;
};
if (validatorFn !== null) {
var form = findParent(field, 'form');
if (!form.cbi_validators)
form.cbi_validators = [ ];
form.cbi_validators.push(validatorFn);
field.addEventListener("blur", validatorFn);
field.addEventListener("keyup", validatorFn);
field.addEventListener("cbi-dropdown-change", validatorFn);
if (matchesElem(field, 'select')) {
field.addEventListener("change", validatorFn);
field.addEventListener("click", validatorFn);
}
validatorFn();
}
}
/**
* Move a table row up or down within a section and update the storage field.
* @param {HTMLElement} elem - Element inside the row that triggers the swap.
* @param {boolean} up - If true, move the row up; otherwise move down.
* @param {string} store - ID of the hidden input used to store the order.
* @returns {boolean} Always returns false to cancel default action.
*/
function cbi_row_swap(elem, up, store)
{
var tr = findParent(elem.parentNode, '.cbi-section-table-row');
if (!tr)
return false;
tr.classList.remove('flash');
if (up) {
var prev = tr.previousElementSibling;
if (prev && prev.classList.contains('cbi-section-table-row'))
tr.parentNode.insertBefore(tr, prev);
else
return;
}
else {
var next = tr.nextElementSibling ? tr.nextElementSibling.nextElementSibling : null;
if (next && next.classList.contains('cbi-section-table-row'))
tr.parentNode.insertBefore(tr, next);
else if (!next)
tr.parentNode.appendChild(tr);
else
return;
}
var ids = [ ];
for (var i = 0, n = 0; i < tr.parentNode.childNodes.length; i++) {
var node = tr.parentNode.childNodes[i];
if (node.classList && node.classList.contains('cbi-section-table-row')) {
node.classList.remove('cbi-rowstyle-1');
node.classList.remove('cbi-rowstyle-2');
node.classList.add((n++ % 2) ? 'cbi-rowstyle-2' : 'cbi-rowstyle-1');
if (/-([^-]+)$/.test(node.id))
ids.push(RegExp.$1);
}
}
var input = document.getElementById(store);
if (input)
input.value = ids.join(' ');
window.scrollTo(0, tr.offsetTop);
void tr.offsetWidth;
tr.classList.add('flash');
return false;
}
/**
* Mark the last visible value container child with class `cbi-value-last`.
* @param {HTMLElement} container - Parent container element.
*/
function cbi_tag_last(container)
{
let last;
for (let cn of container.childNodes) {
var c = cn;
if (matchesElem(c, 'div')) {
c.classList.remove('cbi-value-last');
last = c;
}
}
if (last)
last.classList.add('cbi-value-last');
}
/**
* Submit a form, optionally adding a hidden input to pass a name/value pair.
* @param {HTMLElement} elem - Element inside the form or an element with a form.
* @param {string} [name] - Name of hidden input to include, if any.
* @param {string} [value] - Value for the hidden input (defaults to '1').
* @param {string} [action] - Optional form action URL override.
* @returns {boolean} True on successful submit, false when no form found.
*/
function cbi_submit(elem, name, value, action)
{
const form = elem.form || findParent(elem, 'form');
if (!form)
return false;
if (action)
form.action = action;
if (name) {
var hidden = form.querySelector('input[type="hidden"][name="%s"]'.format(name)) ||
E('input', { type: 'hidden', name: name });
hidden.value = value || '1';
form.appendChild(hidden);
}
form.submit();
return true;
}
/**
* @external String
*/
/**
* Format a string using positional arguments.
* @function format
* @memberof external:String.prototype
* @param {...string} args
* @returns {string}
*/
String.prototype.format = function()
{
if (!RegExp)
return;
const html_esc = [/&/g, '&#38;', /"/g, '&#34;', /'/g, '&#39;', /</g, '&#60;', />/g, '&#62;'];
const quot_esc = [/"/g, '&#34;', /'/g, '&#39;'];
/**
* Escape a string.
* @private
* @function esc
* @param {string} s
* @param {string} r
* @returns {string}
*/
function esc(s, r) {
const t = typeof(s);
if (s == null || t === 'object' || t === 'function')
return '';
if (t !== 'string')
s = String(s);
for (let i = 0; i < r.length; i += 2)
s = s.replace(r[i], r[i+1]);
return s;
}
let str = this;
let subst, n, pad;
let out = '';
const re = /^(([^%]*)%('.|0|\x20)?(-)?(\d+)?(\.\d+)?(%|b|c|d|u|f|o|s|x|X|q|h|j|t|m))/;
let a = [], numSubstitutions = 0;
while ((a = re.exec(str)) !== null) {
const m = a[1];
let leftpart = a[2], pPad = a[3], pJustify = a[4], pMinLength = a[5];
let pPrecision = a[6], pType = a[7];
let precision;
if (pType == '%') {
subst = '%';
}
else {
if (numSubstitutions < arguments.length) {
let param = arguments[numSubstitutions++];
pad = '';
if (pPad && pPad.substr(0,1) == "'")
pad = pPad.substr(1,1);
else if (pPad)
pad = pPad;
else
pad = ' ';
precision = -1;
if (pPrecision && pType == 'f')
precision = +pPrecision.substring(1);
subst = param;
switch(pType) {
case 'b':
subst = Math.floor(+param || 0).toString(2);
break;
case 'c':
subst = String.fromCharCode(+param || 0);
break;
case 'd':
subst = Math.floor(+param || 0).toFixed(0);
break;
case 'u':
n = +param || 0;
subst = Math.floor((n < 0) ? 0x100000000 + n : n).toFixed(0);
break;
case 'f':
subst = (precision > -1)
? ((+param || 0.0)).toFixed(precision)
: (+param || 0.0);
break;
case 'o':
subst = Math.floor(+param || 0).toString(8);
break;
case 's':
subst = param;
break;
case 'x':
subst = Math.floor(+param || 0).toString(16).toLowerCase();
break;
case 'X':
subst = Math.floor(+param || 0).toString(16).toUpperCase();
break;
case 'h':
subst = esc(param, html_esc);
break;
case 'q':
subst = esc(param, quot_esc);
break;
case 't':
var td = 0;
var th = 0;
var tm = 0;
var ts = (param || 0);
if (ts > 59) {
tm = Math.floor(ts / 60);
ts = (ts % 60);
}
if (tm > 59) {
th = Math.floor(tm / 60);
tm = (tm % 60);
}
if (th > 23) {
td = Math.floor(th / 24);
th = (th % 24);
}
subst = (td > 0)
? String.format('%dd %dh %dm %ds', td, th, tm, ts)
: String.format('%dh %dm %ds', th, tm, ts);
break;
case 'm':
var mf = pMinLength ? +pMinLength : 1000;
var pr = pPrecision ? ~~(10 * +('0' + pPrecision)) : 2;
var i = 0;
var val = (+param || 0);
var units = [ ' ', ' K', ' M', ' G', ' T', ' P', ' E' ];
for (i = 0; (i < units.length) && (val > mf); i++)
val /= mf;
if (i)
subst = val.toFixed(pr) + units[i] + (mf == 1024 ? 'i' : '');
else
subst = val + ' ';
pMinLength = null;
break;
}
}
}
if (pMinLength) {
subst = subst.toString();
for (let i = subst.length; i < pMinLength; i++)
if (pJustify == '-')
subst = subst + ' ';
else
subst = pad + subst;
}
out += leftpart + subst;
str = str.substr(m.length);
}
return out + str;
}
/**
* Format a string using positional arguments.
* @function nobr
* @memberof external:String.prototype
* @param {...string} args
* @returns {string}
*/
String.prototype.nobr = function()
{
return this.replace(/[\s\n]+/g, '&#160;');
}
/**
* Format a string using positional arguments.
* @function format
* @memberof external:String
* @param {...string} args
* @returns {string}
*/
String.format = function()
{
const a = [ ];
for (let i = 1; i < arguments.length; i++) {
a.push(arguments[i]);
}
return ''.format.apply(arguments[0], a);
}
/**
* Format a string using positional arguments.
* @function nobr
* @memberof external:String
* @param {...string} args
* @returns {string}
*/
String.nobr = function()
{
const a = [ ];
for (let i = 1; i < arguments.length; i++)
a.push(arguments[i]);
return ''.nobr.apply(arguments[0], a);
}
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = function (callback, thisArg) {
thisArg = thisArg || window;
for (var i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this);
}
};
}
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(f) {
window.setTimeout(function() {
f(new Date().getTime())
}, 1000/30);
};
}
/**
* Return the element for input which may be an element or an id.
* @param {Element|string} e - Element or id.
* @returns {HTMLElement|null}
*/
function isElem(e) { return L.dom.elem(e) }
/**
* Test whether node matches a CSS selector.
* @param {Node} node - Node to test.
* @param {string} selector - CSS selector.
* @returns {boolean}
*/
function matchesElem(node, selector) { return L.dom.matches(node, selector) }
/**
* Find the parent matching selector from node upwards.
* @param {Node} node - Starting node.
* @param {string} selector - CSS selector to match ancestor.
* @returns {HTMLElement|null}
*/
function findParent(node, selector) { return L.dom.parent(node, selector) }
/**
* Create DOM elements using {@link L.dom.create} helper (convenience wrapper).
* @returns {HTMLElement}
*/
function E() { return L.dom.create.apply(L.dom, arguments) }
/**
* Initialize a dropdown element into an {@link L.ui.Dropdown} instance and bind it.
* If already bound, this is a no-op.
* @param {HTMLElement} sb - The select element to convert.
* @returns {L.ui.Dropdown|undefined} Dropdown instance or undefined when already bound.
*/
function cbi_dropdown_init(sb) {
if (sb && L.dom.findClassInstance(sb) instanceof L.ui.Dropdown)
return;
const dl = new L.ui.Dropdown(sb, null, { name: sb.getAttribute('name') });
return dl.bind(sb);
}
/**
* Update or initialize a table UI widget with new data.
* @param {HTMLElement|string} table - Table element or selector.
* @param {...Node[]} data - Data to update the table with.
* @param {string} [placeholder] - Placeholder text when empty.
*/
function cbi_update_table(table, data, placeholder) {
const target = isElem(table) ? table : document.querySelector(table);
if (!isElem(target))
return;
let t = L.dom.findClassInstance(target);
if (!(t instanceof L.ui.Table)) {
t = new L.ui.Table(target);
L.dom.bindClassInstance(target, t);
}
t.update(data, placeholder);
}
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('validation-failure', function(ev) {
if (ev.target === document.activeElement)
L.showTooltip(ev);
});
document.addEventListener('validation-success', function(ev) {
if (ev.target === document.activeElement)
L.hideTooltip(ev);
});
L.require('ui').then(function(ui) {
document.querySelectorAll('.table').forEach(cbi_update_table);
});
});
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<defs>
<radialGradient id="a" cx="0" cy="1" r="1">
<stop offset="0" stop-color="#89b"/>
<stop offset="1" stop-color="#def"/>
</radialGradient>
</defs>
<g stroke="#000" stroke-width="2">
<path d="M9 2h23l2 1 9 9 1 2v31l-2 1H9l-1-1V4l1-2z" fill="url(#a)"/>
<path d="M32 2v11l1 1h11" fill="url(#a)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 389 B

@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<defs>
<radialGradient id="a" cx="0" cy="0" r="1">
<stop offset="0" stop-color="#ddf"/>
<stop offset="1" stop-color="#46b"/>
</radialGradient>
</defs>
<g stroke="#024" stroke-width="2">
<path d="M44 14l1 2v25l-1 1H4l-1-1V18v0l1-6 1-2h17l2 2v1l1 1z" fill="url(#a)"/>
<path d="M3 18h21l1-1v-3" fill="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 415 B

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<defs>
<radialGradient id="a" cx="0" cy="1" r="1">
<stop offset="0" stop-color="#89b"/>
<stop offset="1" stop-color="#def"/>
</radialGradient>
</defs>
<g stroke="#000" stroke-width="2">
<path d="M9 2h23l2 1 9 9 1 2v31l-2 1H9l-1-1V4l1-2z" fill="url(#a)"/>
<path d="M32 2v11l1 1h11" fill="url(#a)"/>
</g>
<path d="M13 33h13v6l12-10-12-11v7H13z" fill="#035"/>
</svg>

After

Width:  |  Height:  |  Size: 444 B

@@ -0,0 +1,594 @@
'use strict';
'require uci';
'require rpc';
'require tools.prng as random';
/**
* Load the firewall configuration.
* @returns {Promise}
*/
function initFirewallState() {
return L.resolveDefault(uci.load('firewall'));
}
/**
* Parse an enum value.
* @param {?string} s
* @param {Array<string>} values
* @returns {string}
*/
function parseEnum(s, values) {
if (s == null)
return null;
s = String(s).toUpperCase();
if (s == '')
return null;
for (var i = 0; i < values.length; i++)
if (values[i].toUpperCase().indexOf(s) == 0)
return values[i];
return null;
}
/**
* Parse a policy value, or defaultValue if not found.
* @param {?string} s
* @param {Array<string>} [defaultValue=['DROP', 'REJECT', 'ACCEPT']]
* @returns {?string}
*/
function parsePolicy(s, defaultValue) {
return parseEnum(s, ['DROP', 'REJECT', 'ACCEPT']) || (arguments.length < 2 ? null : defaultValue);
}
var Firewall, AbstractFirewallItem, Defaults, Zone, Forwarding, Redirect, Rule;
/**
* Look up a firewall zone.
* @param {?string} name
* @returns {?Zone}
*/
function lookupZone(name) {
var z = uci.get('firewall', name);
if (z != null && z['.type'] == 'zone')
return new Zone(z['.name']);
var sections = uci.sections('firewall', 'zone');
for (var i = 0; i < sections.length; i++) {
if (sections[i].name != name)
continue;
return new Zone(sections[i]['.name']);
}
return null;
}
/**
* Generate a colour for a name.
* @param {?string} forName
* @returns {string}
*/
function getColorForName(forName) {
if (forName == null)
return '#eeeeee';
else if (forName == 'lan')
return '#90f090';
else if (forName == 'wan')
return '#f09090';
return random.derive_color(forName);
}
Firewall = L.Class.extend({
getDefaults: function() {
return initFirewallState().then(function() {
return new Defaults();
});
},
newZone: function() {
return initFirewallState().then(L.bind(async function() {
var name = 'newzone',
count = 1;
while ((await this.getZone(name)) != null)
name = 'newzone%d'.format(++count);
return this.addZone(name);
}, this));
},
addZone: function(name) {
return initFirewallState().then(L.bind(function() {
if (name == null || !/^[a-zA-Z0-9_]+$/.test(name))
return null;
if (lookupZone(name) != null)
return null;
var d = new Defaults(),
z = uci.add('firewall', 'zone');
uci.set('firewall', z, 'name', name);
uci.set('firewall', z, 'input', d.getInput() || 'DROP');
uci.set('firewall', z, 'output', d.getOutput() || 'DROP');
uci.set('firewall', z, 'forward', d.getForward() || 'DROP');
return new Zone(z);
}, this));
},
getZone: function(name) {
return initFirewallState().then(function() {
return lookupZone(name);
});
},
getZones: function() {
return initFirewallState().then(function() {
const sections = uci.sections('firewall', 'zone');
const zones = [];
for (let s of sections)
zones.push(new Zone(s['.name']));
zones.sort(function(a, b) { return L.naturalCompare(a.getName() || '', b.getName() || '') });
return zones;
});
},
getZoneByNetwork: function(network) {
return initFirewallState().then(function() {
const sections = uci.sections('firewall', 'zone');
for (let s of sections)
if (L.toArray(s.network).indexOf(network) != -1)
return new Zone(s['.name']);
return null;
});
},
deleteZone: function(name) {
return initFirewallState().then(function() {
const section = uci.get('firewall', name);
let found = false;
if (section != null && section['.type'] == 'zone') {
found = true;
name = section.name;
uci.remove('firewall', section['.name']);
}
else if (name != null) {
const sections = uci.sections('firewall', 'zone');
for (let s of sections) {
if (s.name != name)
continue;
found = true;
uci.remove('firewall', s['.name']);
}
}
if (found == true) {
const sections = uci.sections('firewall');
for (let s of sections) {
if (s['.type'] != 'rule' &&
s['.type'] != 'redirect' &&
s['.type'] != 'forwarding')
continue;
if (s.src == name || s.dest == name)
uci.remove('firewall', s['.name']);
}
}
return found;
});
},
renameZone: function(oldName, newName) {
return initFirewallState().then(L.bind(function() {
if (oldName == null || newName == null || !/^[a-zA-Z0-9_]+$/.test(newName))
return false;
if (lookupZone(newName) != null)
return false;
const sections = uci.sections('firewall', 'zone');
let found = false;
for (let s of sections) {
if (s.name != oldName)
continue;
uci.set('firewall', s['.name'], 'name', newName);
found = true;
}
if (found == true) {
const sections = uci.sections('firewall');
for (let s of sections) {
if (s['.type'] != 'rule' &&
s['.type'] != 'redirect' &&
s['.type'] != 'forwarding')
continue;
if (s.src == oldName)
uci.set('firewall', s['.name'], 'src', newName);
if (s.dest == oldName)
uci.set('firewall', s['.name'], 'dest', newName);
}
}
return found;
}, this));
},
deleteNetwork: function(network) {
return this.getZones().then(L.bind(function(zones) {
var rv = false;
for (var i = 0; i < zones.length; i++)
if (zones[i].deleteNetwork(network))
rv = true;
return rv;
}, this));
},
getColorForName: getColorForName,
getZoneColorStyle: function(zone) {
var hex = (zone instanceof Zone) ? zone.getColor() : getColorForName((zone != null && zone != '*') ? zone : null);
return '--zone-color-rgb:%d, %d, %d; background-color:rgb(var(--zone-color-rgb))'.format(
parseInt(hex.substring(1, 3), 16),
parseInt(hex.substring(3, 5), 16),
parseInt(hex.substring(5, 7), 16)
);
},
});
AbstractFirewallItem = L.Class.extend({
get: function(option) {
return uci.get('firewall', this.sid, option);
},
set: function(option, value) {
return uci.set('firewall', this.sid, option, value);
}
});
Defaults = AbstractFirewallItem.extend({
__init__: function() {
var sections = uci.sections('firewall', 'defaults');
for (var i = 0; i < sections.length; i++) {
this.sid = sections[i]['.name'];
break;
}
if (this.sid == null)
this.sid = uci.add('firewall', 'defaults');
},
isSynFlood: function() {
return (this.get('syn_flood') == '1');
},
isDropInvalid: function() {
return (this.get('drop_invalid') == '1');
},
getInput: function() {
return parsePolicy(this.get('input'), 'DROP');
},
getOutput: function() {
return parsePolicy(this.get('output'), 'DROP');
},
getForward: function() {
return parsePolicy(this.get('forward'), 'DROP');
}
});
Zone = AbstractFirewallItem.extend({
__init__: function(name) {
var section = uci.get('firewall', name);
if (section != null && section['.type'] == 'zone') {
this.sid = name;
this.data = section;
}
else if (name != null) {
var sections = uci.get('firewall', 'zone');
for (var i = 0; i < sections.length; i++) {
if (sections[i].name != name)
continue;
this.sid = sections[i]['.name'];
this.data = sections[i];
break;
}
}
},
isMasquerade: function() {
return (this.get('masq') == '1');
},
getName: function() {
return this.get('name');
},
getNetwork: function() {
return this.get('network');
},
getInput: function() {
return parsePolicy(this.get('input'), (new Defaults()).getInput());
},
getOutput: function() {
return parsePolicy(this.get('output'), (new Defaults()).getOutput());
},
getForward: function() {
return parsePolicy(this.get('forward'), (new Defaults()).getForward());
},
addNetwork: function(network) {
var section = uci.get('network', network);
if (section == null || section['.type'] != 'interface')
return false;
var newNetworks = this.getNetworks();
if (newNetworks.filter(function(net) { return net == network }).length)
return false;
newNetworks.push(network);
this.set('network', newNetworks);
return true;
},
deleteNetwork: function(network) {
var oldNetworks = this.getNetworks(),
newNetworks = oldNetworks.filter(function(net) { return net != network });
if (newNetworks.length > 0)
this.set('network', newNetworks);
else
this.set('network', null);
return (newNetworks.length < oldNetworks.length);
},
getNetworks: function() {
return L.toArray(this.get('network'));
},
clearNetworks: function() {
this.set('network', null);
},
getDevices: function() {
return L.toArray(this.get('device'));
},
getSubnets: function() {
return L.toArray(this.get('subnet'));
},
getForwardingsBy: function(what) {
var sections = uci.sections('firewall', 'forwarding'),
forwards = [];
for (var i = 0; i < sections.length; i++) {
if (sections[i].src == null || sections[i].dest == null)
continue;
if (sections[i][what] != this.getName())
continue;
forwards.push(new Forwarding(sections[i]['.name']));
}
return forwards;
},
addForwardingTo: function(dest) {
var forwards = this.getForwardingsBy('src'),
zone = lookupZone(dest);
if (zone == null || zone.getName() == this.getName())
return null;
for (var i = 0; i < forwards.length; i++)
if (forwards[i].getDestination() == zone.getName())
return null;
var sid = uci.add('firewall', 'forwarding');
uci.set('firewall', sid, 'src', this.getName());
uci.set('firewall', sid, 'dest', zone.getName());
return new Forwarding(sid);
},
addForwardingFrom: function(src) {
var forwards = this.getForwardingsBy('dest'),
zone = lookupZone(src);
if (zone == null || zone.getName() == this.getName())
return null;
for (var i = 0; i < forwards.length; i++)
if (forwards[i].getSource() == zone.getName())
return null;
var sid = uci.add('firewall', 'forwarding');
uci.set('firewall', sid, 'src', zone.getName());
uci.set('firewall', sid, 'dest', this.getName());
return new Forwarding(sid);
},
deleteForwardingsBy: function(what) {
var sections = uci.sections('firewall', 'forwarding'),
found = false;
for (var i = 0; i < sections.length; i++) {
if (sections[i].src == null || sections[i].dest == null)
continue;
if (sections[i][what] != this.getName())
continue;
uci.remove('firewall', sections[i]['.name']);
found = true;
}
return found;
},
deleteForwarding: function(forwarding) {
if (!(forwarding instanceof Forwarding))
return false;
var section = uci.get('firewall', forwarding.sid);
if (!section || section['.type'] != 'forwarding')
return false;
uci.remove('firewall', section['.name']);
return true;
},
addRedirect: function(options) {
var sid = uci.add('firewall', 'redirect');
if (options != null && typeof(options) == 'object')
for (var key in options)
if (options.hasOwnProperty(key))
uci.set('firewall', sid, key, options[key]);
uci.set('firewall', sid, 'src', this.getName());
return new Redirect(sid);
},
addRule: function(options) {
var sid = uci.add('firewall', 'rule');
if (options != null && typeof(options) == 'object')
for (var key in options)
if (options.hasOwnProperty(key))
uci.set('firewall', sid, key, options[key]);
uci.set('firewall', sid, 'src', this.getName());
return new Rule(sid);
},
getColor: function(forName) {
var name = (arguments.length > 0 ? forName : this.getName());
return getColorForName(name);
}
});
Forwarding = AbstractFirewallItem.extend({
__init__: function(sid) {
this.sid = sid;
},
getSource: function() {
return this.get('src');
},
getDestination: function() {
return this.get('dest');
},
getSourceZone: function() {
return lookupZone(this.getSource());
},
getDestinationZone: function() {
return lookupZone(this.getDestination());
}
});
Rule = AbstractFirewallItem.extend({
__init__: function(sid) {
this.sid = sid;
},
getSource: function() {
return this.get('src');
},
getDestination: function() {
return this.get('dest');
},
getSourceZone: function() {
return lookupZone(this.getSource());
},
getDestinationZone: function() {
return lookupZone(this.getDestination());
}
});
Redirect = AbstractFirewallItem.extend({
__init__: function(sid) {
this.sid = sid;
},
getSource: function() {
return this.get('src');
},
getDestination: function() {
return this.get('dest');
},
getSourceZone: function() {
return lookupZone(this.getSource());
},
getDestinationZone: function() {
return lookupZone(this.getDestination());
}
});
return Firewall;
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,469 @@
'use strict';
'require rpc';
'require request';
'require baseclass';
/**
* @typedef {Object} FileStatEntry
* @memberof LuCI.fs
*
* @property {string} name - Name of the directory entry
* @property {string} type - Type of the entry, one of `block`, `char`, `directory`, `fifo`, `symlink`, `file`, `socket` or `unknown`
* @property {number} size - Size in bytes
* @property {number} mode - Access permissions
* @property {number} atime - Last access time in seconds since epoch
* @property {number} mtime - Last modification time in seconds since epoch
* @property {number} ctime - Last change time in seconds since epoch
* @property {number} inode - Inode number
* @property {number} uid - Numeric owner id
* @property {number} gid - Numeric group id
* @property {string} user - User name of owner
* @property {string} group - Group name of owner
* @property {Object?} target - a dictionary of properties of any symlink target for `list` operation result entries
*/
/**
* @typedef {Object} FileExecResult
* @memberof LuCI.fs
*
* @property {number} code - The exit code of the invoked command
* @property {string} [stdout] - The stdout produced by the command, if any
* @property {string} [stderr] - The stderr produced by the command, if any
*/
const callFileList = rpc.declare({
object: 'file',
method: 'list',
params: [ 'path' ]
});
const callFileStat = rpc.declare({
object: 'file',
method: 'stat',
params: [ 'path' ]
});
const callFileLStat = rpc.declare({
object: 'file',
method: 'lstat',
params: [ 'path' ]
});
const callFileRead = rpc.declare({
object: 'file',
method: 'read',
params: [ 'path' ]
});
const callFileWrite = rpc.declare({
object: 'file',
method: 'write',
params: [ 'path', 'data', 'mode' ]
});
const callFileRemove = rpc.declare({
object: 'file',
method: 'remove',
params: [ 'path' ]
});
const callFileExec = rpc.declare({
object: 'file',
method: 'exec',
params: [ 'command', 'params', 'env' ]
});
const rpcErrors = [
null,
'InvalidCommandError',
'InvalidArgumentError',
'MethodNotFoundError',
'NotFoundError',
'NoDataError',
'PermissionError',
'TimeoutError',
'UnsupportedError'
];
/**
* Handle an RPC reply.
* @param {object} expect
* @param {number} rc
* @throws {Error}
* @returns {number}
*/
function handleRpcReply(expect, rc) {
if (typeof(rc) == 'number' && rc != 0) {
let e = new Error(rpc.getStatusText(rc)); e.name = rpcErrors[rc] || 'Error';
throw e;
}
if (expect) {
const type = Object.prototype.toString;
for (let key in expect) {
if (rc != null && key != '')
rc = rc[key];
if (rc == null || type.call(rc) != type.call(expect[key])) {
let e = new Error(_('Unexpected reply data format')); e.name = 'TypeError';
throw e;
}
break;
}
}
return rc;
}
/**
* Handle a CGI-IO reply.
* @param {object} res
* @throws {Error}
* @returns {string}
*/
function handleCgiIoReply(res) {
if (!res.ok || res.status != 200) {
var e = new Error(res.statusText);
switch (res.status) {
case 400:
e.name = 'InvalidArgumentError';
break;
case 403:
e.name = 'PermissionError';
break;
case 404:
e.name = 'NotFoundError';
break;
default:
e.name = 'Error';
}
throw e;
}
switch (this.type) {
case 'blob':
return res.blob();
case 'json':
return res.json();
default:
return res.text();
}
}
/**
* @class fs
* @memberof LuCI
* @hideconstructor
* @classdesc
*
* Provides high level utilities to wrap file system related RPC calls.
* To import the class in views, use `'require fs'`, to import it in
* external JavaScript, use `L.require("fs").then(...)`.
*/
var FileSystem = baseclass.extend(/** @lends LuCI.fs.prototype */ {
/**
* Obtains a listing of the specified directory.
*
* @param {string} path
* The directory path to list.
*
* @returns {Promise<LuCI.fs.FileStatEntry[]>}
* Returns a promise resolving to an array of stat detail objects or
* rejecting with an error stating the failure reason.
*/
list(path) {
return callFileList(path).then(handleRpcReply.bind(this, { entries: [] }));
},
/**
* Return file stat information on the specified path.
*
* @param {string} path
* The filesystem path to stat.
*
* @returns {Promise<LuCI.fs.FileStatEntry>}
* Returns a promise resolving to a stat detail object or
* rejecting with an error stating the failure reason.
*/
stat(path) {
return callFileStat(path).then(handleRpcReply.bind(this, { '': {} }));
},
/**
* Return symlink aware file stat information on the specified path. This
* call differs from stat in that it gives information about the symlink
* instead of following the symlink, whereby size is the length of the
* string of the symlink target path and file name.
*
* @param {string} path
* The filesystem path to lstat.
*
* @returns {Promise<LuCI.fs.FileStatEntry>}
* Returns a promise resolving to a stat detail object or
* rejecting with an error stating the failure reason.
*/
lstat(path) {
return callFileLStat(path).then(handleRpcReply.bind(this, { '': {} }));
},
/**
* Read the contents of the given file and return them.
* Note: this function is unsuitable for obtaining binary data.
*
* @param {string} path
* The file path to read.
*
* @returns {Promise<string>}
* Returns a promise resolving to a string containing the file contents or
* rejecting with an error stating the failure reason.
*/
read(path) {
return callFileRead(path).then(handleRpcReply.bind(this, { data: '' }));
},
/**
* Write the given data to the specified file path.
* If the specified file path does not exist, it will be created, given
* sufficient permissions.
*
* Note: `data` will be converted to a string using `String(data)` or to
* `''` when it is `null`.
*
* @param {string} path
* The file path to write to.
*
* @param {*} [data]
* The file data to write. If it is null, it will be set to an empty
* string.
*
* @param {number} [mode]
* The permissions to use on file creation. Default is 420 (0644).
*
* @returns {Promise<number>}
* Returns a promise resolving to `0` or rejecting with an error stating
* the failure reason.
*/
write(path, data, mode) {
data = (data != null) ? String(data) : '';
mode = (mode != null) ? mode : 420; // 0644
return callFileWrite(path, data, mode).then(handleRpcReply.bind(this, { '': 0 }));
},
/**
* Unlink the given file.
*
* @param {string} path
* The file path to remove.
*
* @returns {Promise<number>}
* Returns a promise resolving to `0` or rejecting with an error stating
* the failure reason.
*/
remove(path) {
return callFileRemove(path).then(handleRpcReply.bind(this, { '': 0 }));
},
/**
* Execute the specified command, optionally passing params and
* environment variables.
*
* Note: The `command` must be either the path to an executable,
* or a basename without arguments in which case it will be searched
* in $PATH. If specified, the values given in `params` will be passed
* as arguments to the command.
*
* The key/value pairs in the optional `env` table are translated to
* `setenv()` calls prior to running the command.
*
* @param {string} command
* The command to invoke.
*
* @param {string[]} [params]
* The arguments to pass to the command.
*
* @param {Object.<string, string>} [env]
* Environment variables to set.
*
* @returns {Promise<LuCI.fs.FileExecResult>}
* Returns a promise resolving to an object describing the execution
* results or rejecting with an error stating the failure reason.
*/
exec(command, params, env) {
if (!Array.isArray(params))
params = null;
if (!L.isObject(env))
env = null;
return callFileExec(command, params, env).then(handleRpcReply.bind(this, { '': {} }));
},
/**
* Read the contents of the given file, trim leading and trailing white
* space and return the trimmed result. In case of errors, return an empty
* string instead.
*
* Note: this function is useful to read single-value files in `/sys`
* or `/proc`.
*
* This function is guaranteed to not reject its promises, on failure,
* an empty string will be returned.
*
* @param {string} path
* The file path to read.
*
* @returns {Promise<string>}
* Returns a promise resolving to the file contents or the empty string
* on failure.
*/
trimmed(path) {
return L.resolveDefault(this.read(path), '').then(function(s) {
return s.trim();
});
},
/**
* Read the contents of the given file, split it into lines, trim
* leading and trailing white space of each line and return the
* resulting array.
*
* This function is guaranteed to not reject its promises, on failure,
* an empty array will be returned.
*
* @param {string} path
* The file path to read.
*
* @returns {Promise<string[]>}
* Returns a promise resolving to an array containing the stripped lines
* of the given file or `[]` on failure.
*/
lines(path) {
return L.resolveDefault(this.read(path), '').then(function(s) {
var lines = [];
s = s.trim();
if (s != '') {
var l = s.split(/\n/);
for (var i = 0; i < l.length; i++)
lines.push(l[i].trim());
}
return lines;
});
},
/**
* Read the contents of the given file and return them, bypassing ubus.
*
* This function will read the requested file through the cgi-io
* helper applet at `/cgi-bin/cgi-download` which bypasses the ubus rpc
* transport. This is useful to fetch large file contents which might
* exceed the ubus message size limits or which contain binary data.
*
* The cgi-io helper will enforce the same access permission rules as
* the ubus based read call.
*
* @param {string} path
* The file path to read.
*
* @param {"blob"|"text"|"json"} [type=text]
* The expected type of read file contents. Valid values are `text` to
* interpret the contents as string, `json` to parse the contents as JSON
* or `blob` to return the contents as Blob instance.
*
* @returns {Promise<*>}
* Returns a promise resolving with the file contents interpreted according
* to the specified type or rejecting with an error stating the failure
* reason.
*/
read_direct(path, type) {
var postdata = 'sessionid=%s&path=%s'
.format(encodeURIComponent(L.env.sessionid), encodeURIComponent(path));
return request.post(L.env.cgi_base + '/cgi-download', postdata, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: (type == 'blob') ? 'blob' : 'text'
}).then(handleCgiIoReply.bind({ type: type }));
},
/**
* Execute the specified command, bypassing ubus.
*
* Note: The `command` must be either the path to an executable,
* or a basename without arguments in which case it will be searched
* in $PATH. If specified, the values given in `params` will be passed
* as arguments to the command.
*
* This function will invoke the requested commands through the cgi-io
* helper applet at `/cgi-bin/cgi-exec` which bypasses the ubus rpc
* transport. This is useful to fetch large command outputs which might
* exceed the ubus message size limits or which contain binary data.
*
* The cgi-io helper will enforce the same access permission rules as
* the ubus based exec call.
*
* @param {string} command
* The command to invoke.
*
* @param {string[]} [params]
* The arguments to pass to the command.
*
* @param {"blob"|"text"|"json"} [type=text]
* The expected output type of the invoked program. Valid values are
* `text` to interpret the output as string, `json` to parse the output
* as JSON or `blob` to return the output as Blob instance.
*
* @param {boolean} [latin1=false]
* Whether to encode the command line as Latin1 instead of UTF-8. This
* is usually not needed but can be useful for programs that cannot
* handle UTF-8 input.
*
* @param {boolean} [stderr=false]
* Whether to include stderr output in command output. This is usually
* not needed but can be useful to execute a command and get full output.
*
* @param {function()} [responseProgress=null]
* An optional request callback function which receives ProgressEvent
* instances as sole argument during the HTTP response transfer. This is
* usually not needed but can be useful to receive realtime command
* output before command exit.
*
* @returns {Promise<*>}
* Returns a promise resolving with the command stdout output interpreted
* according to the specified type or rejecting with an error stating the
* failure reason.
*/
exec_direct(command, params, type, latin1, stderr, responseProgress) {
var cmdstr = String(command)
.replace(/\\/g, '\\\\').replace(/(\s)/g, '\\$1');
if (Array.isArray(params))
for (var i = 0; i < params.length; i++)
cmdstr += ' ' + String(params[i])
.replace(/\\/g, '\\\\').replace(/(\s)/g, '\\$1');
if (latin1)
cmdstr = escape(cmdstr).replace(/\+/g, '%2b');
else
cmdstr = encodeURIComponent(cmdstr);
var postdata = 'sessionid=%s&command=%s&stderr=%d'
.format(encodeURIComponent(L.env.sessionid), cmdstr, stderr ? 1 : 0);
return request.post(L.env.cgi_base + '/cgi-exec', postdata, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: (type == 'blob') ? 'blob' : 'text', responseProgress
}).then(handleCgiIoReply.bind({ type: type }));
}
});
return FileSystem;
@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><radialGradient id="radialGradient3390" cx="24.84" cy="30.78" r="23" gradientTransform="matrix(1.156 0 0 .5026 10.03 34.95)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#eeeeec" offset="1"/></radialGradient><linearGradient id="linearGradient9" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><radialGradient id="radialGradient4612-0" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-opacity="0" offset="1"/></radialGradient><filter id="filter4618-7" x="-.07545" y="-.06204" width="1.151" height="1.143"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient12" x1="322.3" x2="328.4" y1="62.62" y2="68.74" gradientTransform="matrix(.75 0 0 .8333 81.62 10.42)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient4206"><stop stop-color="#fff" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient13" x1="325.4" x2="328.4" y1="63.27" y2="68.74" gradientTransform="matrix(.5 0 0 .5 -489.8 -97.75)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient14" x1="-47.16" x2="-46.15" y1="39.38" y2="44.17" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#729fcf" offset="0"/><stop stop-color="#729fcf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient15" x1="-48" x2="-46.75" y1="40.38" y2="45.69" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#3465a4" offset="0"/><stop stop-color="#3465a4" stop-opacity="0" offset="1"/></linearGradient></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.9Line truncated

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><radialGradient id="radialGradient3390" cx="24.84" cy="30.78" r="23" gradientTransform="matrix(1.156 0 0 .5026 10.03 34.95)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#eeeeec" offset="1"/></radialGradient><linearGradient id="linearGradient7907" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 98.35 78.44)" gradientUnits="userSpaceOnUse"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient7909" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 102.2 81.36)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7919" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientUnits="userSpaceOnUse"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" stroke-width="2"/></mask><linearGradient id="C" x1="-112.3" x2="-112.3" y1="148.9" y2="164.5" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-color="#fff" offset=".2177"/><stop stop-color="#fff" offset=".7659"/><stop offset="1"/></linearGradient><filter id="D" x="-.0125" y="-.04971" width="1.026" height="1.099" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.001 0.244"/></filter><filter id="H" x="-.395" y="-.5737" width="1.79" height="2.147" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="2.8946329"/></filter><g opacity=".7"><g transform="matrix(1.297 0 0 1.297 -13.6 -.805)" enable-background="new"><rect x="14.5" y="1.5" width="32" height="29" rx="2.877" ry="2.781" fill="url(#linearGradient7887)" fill-rule="evenodd" stroke="#888a85" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".9924"/><path transform="matrix(2.143 0 0 2.087 44.43 -.6302)" d="m-12.5 1.498c-0.573 0-1.002 0Line truncated

After

Width:  |  Height:  |  Size: 8.3 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7822-4"><stop offset="0"/><stop stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient1643253" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><filter id="filter5386-58" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient9" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4175"/><linearGradient id="linearGradient4175"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><radialGradient id="radialGradient4612-0" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><filter id="filter4618-7" x="-.07545" y="-.06204" width="1.151" height="1.143"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient12" x1="322.3" x2="328.4" y1="62.62" y2="68.74" gradientTransform="matrix(.75 0 0 .8333 81.62 10.42)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient4206"><stop stop-color="#fff" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient13" x1="325.4" x2="328.4" y1="63.27" y2="68.74" gradientTransform="matrix(.5 0 0 .5 -489.8 -97.75)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient14" x1="-47.16" x2="-46.15" y1="39.38" y2="44.17" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7652-3"/><linearGradient id="linearGradient7652-3"><stop stop-color="#729fcf" offset="0"/><stop stop-color="#729fcf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient15" x1="-48" x2="-46.75" y1="40.38" y2="45.69" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#3465a4" offset="0"/><stop stop-color="#3465a4" stop-opacity="0" offset="1"/></linearGradient><radialGradient id="radialGradient81" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(1.058 -1.042 .4439 .4509 -55.95 372.2)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><filter id="filter4618" x="-.1134" y="-.08587" width="1.226" height="1.205"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient85" x1="-75.84" x2="-75.96" y1="48.62" y2="53.84" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7652-3"/></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="Line truncated

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889-6" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientTransform="matrix(2.779 0 0 2.707 11.17 99.85)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386-1" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7907" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 -55.24 83.65)" gradientUnits="userSpaceOnUse"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient7909" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 -51.37 86.57)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient1667502" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2.594 0 0 2.507 9.965 101.4)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7887"/><linearGradient id="linearGradient1667504" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientTransform="matrix(1.5 0 0 1.5 -51.37 85.07)" gradientUnits="userSpaceOnUse"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386-1-2" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" stroke-width="2"/></mask><linearGradient id="C" x1="-112.3" x2="-112.3" y1="148.9" y2="164.5" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-color="#fff" offset=".2177"/><stop stop-color="#fff" offset=".7659"/><stop offset="1"/></linearGradient><filter id="D" x="-.0125" y="-.04971" width="1.026" height="1.099" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.001 0.244"/></filter><filter id="H" x="-.395" y="-.5737" width="1.79" height="2.147" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="2.8946329"/></filter><g opacity=".7"><g transform="matrix(.5536 0 0 .5536 38.5 -31.69)"><rect x="-27.65" y="102.6" width="41.5" height="37.61" rx="3.731" ry="3.607" fill="url(#lineaLine truncated

After

Width:  |  Height:  |  Size: 8.4 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient9" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><radialGradient id="radialGradient4612-0" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-opacity="0" offset="1"/></radialGradient><filter id="filter4618-7" x="-.07545" y="-.06204" width="1.151" height="1.143"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient12" x1="322.3" x2="328.4" y1="62.62" y2="68.74" gradientTransform="matrix(.75 0 0 .8333 81.62 10.42)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient4206"><stop stop-color="#fff" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient13" x1="325.4" x2="328.4" y1="63.27" y2="68.74" gradientTransform="matrix(.5 0 0 .5 -489.8 -97.75)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient14" x1="-47.16" x2="-46.15" y1="39.38" y2="44.17" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#729fcf" offset="0"/><stop stop-color="#729fcf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient15" x1="-48" x2="-46.75" y1="40.38" y2="45.69" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#3465a4" offset="0"/><stop stop-color="#3465a4" stop-opacity="0" offset="1"/></linearGradient></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" strLine truncated

After

Width:  |  Height:  |  Size: 8.7 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7907" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 98.35 78.44)" gradientUnits="userSpaceOnUse"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient7909" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 102.2 81.36)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7919" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientUnits="userSpaceOnUse"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" stroke-width="2"/></mask><linearGradient id="C" x1="-112.3" x2="-112.3" y1="148.9" y2="164.5" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-color="#fff" offset=".2177"/><stop stop-color="#fff" offset=".7659"/><stop offset="1"/></linearGradient><filter id="D" x="-.0125" y="-.04971" width="1.026" height="1.099" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.001 0.244"/></filter><filter id="H" x="-.395" y="-.5737" width="1.79" height="2.147" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="2.8946329"/></filter><g opacity=".7"><g transform="matrix(1.297 0 0 1.297 -13.6 -.805)" enable-background="new"><rect x="14.5" y="1.5" width="32" height="29" rx="2.877" ry="2.781" fill="url(#linearGradient7887)" fill-rule="evenodd" stroke="#888a85" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".9924"/><path transform="matrix(2.143 0 0 2.087 44.43 -.6302)" d="m-12.5 1.498c-0.573 0-1.002 0.429-1.002 1.002v11c0 0.573 0.429 1.002 1.002 1.002h12c0.573 0 1.002-0.429 1.002-1.002v-11c0-0.573-0.429-1.002-1.002-1.002z" fill="none" stroke="url(#linearGradient7889)" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-Line truncated

After

Width:  |  Height:  |  Size: 6.1 KiB

@@ -0,0 +1,2 @@
<svg width="48" height="48" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g><rect x="11" y="1" width="2" height="5" opacity=".14"/><rect x="11" y="1" width="2" height="5" transform="rotate(30 12 12)" opacity=".29"/><rect x="11" y="1" width="2" height="5" transform="rotate(60 12 12)" opacity=".43"/><rect x="11" y="1" width="2" height="5" transform="rotate(90 12 12)" opacity=".57"/><rect x="11" y="1" width="2" height="5" transform="rotate(120 12 12)" opacity=".71"/><rect x="11" y="1" width="2" height="5" transform="rotate(150 12 12)" opacity=".86"/><rect x="11" y="1" width="2" height="5" transform="rotate(180 12 12)"/><animateTransform attributeName="transform" type="rotate" calcMode="discrete" dur="0.75s" values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12;360 12 12" repeatCount="indefinite"/></g></svg>
<!-- https://github.com/n3r4zzurr0/svg-spinners MIT License -->

After

Width:  |  Height:  |  Size: 958 B

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7907" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 98.35 78.44)" gradientUnits="userSpaceOnUse"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient7909" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 102.2 81.36)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7919" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientUnits="userSpaceOnUse"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" stroke-width="2"/></mask><linearGradient id="C" x1="-112.3" x2="-112.3" y1="148.9" y2="164.5" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-color="#fff" offset=".2177"/><stop stop-color="#fff" offset=".7659"/><stop offset="1"/></linearGradient><filter id="D" x="-.0125" y="-.04971" width="1.026" height="1.099" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.001 0.244"/></filter><filter id="H" x="-.395" y="-.5737" width="1.79" height="2.147" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="2.8946329"/></filter><g opacity=".7"><g transform="matrix(1.297 0 0 1.297 -13.6 -.805)" enable-background="new"><rect x="14.5" y="1.5" width="32" height="29" rx="2.877" ry="2.781" fill="url(#linearGradient7887)" fill-rule="evenodd" stroke="#888a85" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".9924"/><path transform="matrix(2.143 0 0 2.087 44.43 -.6302)" d="m-12.5 1.498c-0.573 0-1.002 0.429-1.002 1.002v11c0 0.573 0.429 1.002 1.002 1.002h12c0.573 0 1.002-0.429 1.002-1.002v-11c0-0.573-0.429-1.002-1.002-1.002z" fill="none" stroke="url(#linearGradient7889)" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-Line truncated

After

Width:  |  Height:  |  Size: 6.1 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7907" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 98.35 78.44)" gradientUnits="userSpaceOnUse"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient7909" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 102.2 81.36)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7919" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientUnits="userSpaceOnUse"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" stroke-width="2"/></mask><linearGradient id="C" x1="-112.3" x2="-112.3" y1="148.9" y2="164.5" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-color="#fff" offset=".2177"/><stop stop-color="#fff" offset=".7659"/><stop offset="1"/></linearGradient><filter id="D" x="-.0125" y="-.04971" width="1.026" height="1.099" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.001 0.244"/></filter><filter id="H" x="-.395" y="-.5737" width="1.79" height="2.147" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="2.8946329"/></filter><g opacity=".7"><g transform="matrix(1.297 0 0 1.297 -13.6 -.805)" enable-background="new"><rect x="14.5" y="1.5" width="32" height="29" rx="2.877" ry="2.781" fill="url(#linearGradient7887)" fill-rule="evenodd" stroke="#888a85" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".9924"/><path transform="matrix(2.143 0 0 2.087 44.43 -.6302)" d="m-12.5 1.498c-0.573 0-1.002 0.429-1.002 1.002v11c0 0.573 0.429 1.002 1.002 1.002h12c0.573 0 1.002-0.429 1.002-1.002v-11c0-0.573-0.429-1.002-1.002-1.002z" fill="none" stroke="url(#linearGradient7889)" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-Line truncated

After

Width:  |  Height:  |  Size: 6.3 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient9" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><radialGradient id="radialGradient4612-0" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-opacity="0" offset="1"/></radialGradient><filter id="filter4618-7" x="-.07545" y="-.06204" width="1.151" height="1.143"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient12" x1="322.3" x2="328.4" y1="62.62" y2="68.74" gradientTransform="matrix(.75 0 0 .8333 81.62 10.42)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient4206"><stop stop-color="#fff" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient13" x1="325.4" x2="328.4" y1="63.27" y2="68.74" gradientTransform="matrix(.5 0 0 .5 -489.8 -97.75)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient14" x1="-47.16" x2="-46.15" y1="39.38" y2="44.17" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#a04030" offset="0"/><stop stop-color="#a04030" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient15" x1="-48" x2="-46.75" y1="40.38" y2="45.69" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#d06447" offset="0"/><stop stop-color="#d06447" stop-opacity="0" offset="1"/></linearGradient></defs><g transform="matrix(1.297 0 0 1.297 -13.6 -.805)" enable-background="new"><g enable-background="new"><rect x="14.5" y="1.5" width="32" height="29" rx="2.877" ry="2.781" fill="url(#linearGradient7887)" fill-rule="evenodd" stroke="#888a85" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".9924"/><path transform="matrix(2.143 0 0 2.087 44.43 -.6302)" d="m-12.5 1.498c-0.573 0-1.002 0.429-1.002 1.002v11c0 0.573 0.429 1.002 1.002 1.002h12c0.573 0 1.002-0.429 1.002-1.002v-11c0-0.573-0.429-1.002-1.002-1.002z" fill="none" stroke="url(#linearGradient7889)" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".9924" stroke-width=".4729"/><rect transform="matrix(1.016 0 0 1.016 -.49 -.2715)" x="15.38" y="2.875" width="32" height="29" rx="3.723" ry="3.723" fill-rule="evenodd" filter="url(#filter5386)" opacity=".1205"/></g></g><g transform="matrix(1.785 0 0 1.785 -557 -94.28)" enable-background="new"><path d="m325 59.07c-0.64 0-1.16 0.516-1.16 1.154v0.288c0 0.293-0.23 0.543-0.54 0.543h-0.12c-0.64 0-1.16 0.704-1.16 1.342v5.445c0 0.638 0.52 1.154 1.16 1.154h6.56c0.64 0 1.16-0.516 1.16-1.154v-5.445c0-0.638-0.52-1.342-1.16-1.342h-0.14c-0.26 0.02-0.55-0.186-0.55-0.526v-0.305c0-0.638-0.51-1.154-1.15-1.154z" fill="url(#linearGradient9)" fill-rule="evenodd" stroke="#fff" stroke-width="2"/><path d="m325 59.07c-0.64 0-1.16 0.516-1.16 1.154v0.288c0 0.293-0.23 0.543-0.54 0.543h-0.12c-0.64 0-1.16 0.704-1.16 1.342v5.445c0 0.638 0.52 1.154 1.16 1.154h6.56c0.64 0 1.16-0.516 1.16-1.154v-5.445c0-0.638-0.52-1.342-1.16-1.342h-0.14c-0.26 0.02-0.55-0.186-0.55-0.526v-0.305c0-0.638-0.51-1.154-1.15-1.154z" fill="url(#linearGradient9)" fill-rule="evenodd"/><rect x="325" y="60" width="3" height="2" rx=".3978" ry=".3978" color="#000000" fill="url(#linearGradient11)"/><rect x="323.5" y="62.5" width="6" height="5" rx=".1768" ry=".1768" color="#000000" fill="#d3d7cf" stroke="url(#linearGradient12)"/><rect transform="scale(-1)" x="-328.5" y="-66.5" width="4" height="3" rx=".1768" ry=".1768" color="#000000" fill="#888a85" stroke="url(#linearGradient13)"/><path d="m325 63.81c-1.03 8.083-9.29 14.95-16.38 19.75-3.54 2.401-6.67 4.247-8.53 5.718-0.46 0.368-0.85 0.712-1.18 Line truncated

After

Width:  |  Height:  |  Size: 6.0 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient9" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><radialGradient id="radialGradient4612-0" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-opacity="0" offset="1"/></radialGradient><filter id="filter4618-7" x="-.07545" y="-.06204" width="1.151" height="1.143"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient12" x1="322.3" x2="328.4" y1="62.62" y2="68.74" gradientTransform="matrix(.75 0 0 .8333 81.62 10.42)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient4206"><stop stop-color="#fff" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient13" x1="325.4" x2="328.4" y1="63.27" y2="68.74" gradientTransform="matrix(.5 0 0 .5 -489.8 -97.75)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient14" x1="-47.16" x2="-46.15" y1="39.38" y2="44.17" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#729fcf" offset="0"/><stop stop-color="#729fcf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient15" x1="-48" x2="-46.75" y1="40.38" y2="45.69" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#3465a4" offset="0"/><stop stop-color="#3465a4" stop-opacity="0" offset="1"/></linearGradient></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" strLine truncated

After

Width:  |  Height:  |  Size: 8.7 KiB

@@ -0,0 +1 @@
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#b" y1="14" y2="-66"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v56c0 1.273179-.75249 2.326579-1.84375 2.78125 1.62807Line truncated

After

Width:  |  Height:  |  Size: 5.7 KiB

@@ -0,0 +1 @@
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#b" y1="14" y2="-66"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" y1="14" y2="-18"><stop offset="0" stop-color="#395d93"/><stop offset="1" stop-color="#6e92c7"/></linearGradient><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 Line truncated

After

Width:  |  Height:  |  Size: 5.8 KiB

@@ -0,0 +1 @@
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#395d93"/><stop offset="1" stop-color="#6e92c7"/></linearGradient><linearGradient id="c"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#c" y1="14" y2="-66"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#c" y1="14" y2="-50"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="k" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#d)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#e)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#f)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#g)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#h)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.031Line truncated

After

Width:  |  Height:  |  Size: 5.8 KiB

@@ -0,0 +1 @@
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#395d93"/><stop offset="1" stop-color="#6e92c7"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" y1="14" y2="-66"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 Line truncated

After

Width:  |  Height:  |  Size: 5.8 KiB

@@ -0,0 +1 @@
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#395d93"/><stop offset="1" stop-color="#6e92c7"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#b" y1="14" y2="-66"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v56c0 1.273179-.75249 2.326579-1.84375 2.78125 1.62Line truncated

After

Width:  |  Height:  |  Size: 5.7 KiB

@@ -0,0 +1 @@
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#b" y1="14" y2="-66"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.028"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.14"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.01"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.01"/><g transform="translate(0 74)"><path d="m74-67.97c-3.827 0-6.969 3.141-6.969 6.969v11.28c-1.274-1.359-3.036-2.25-5.031-2.25h-8c-3.827 0-6.969 3.141-6.969 6.969v11.28c-1.274-1.359-3.036-2.25-5.031-2.25h-8c-3.827 0-6.969 3.141-6.969 6.969v11.28c-1.274-1.359-3.036-2.25-5.031-2.25h-8c-3.827 0-6.969 3.141-6.969 6.969v24c0 3.827 3.141 6.969 6.969 6.969h8c2.611 0 4.808-1.512 6-3.656 1.192 2.144 3.389 3.656 6 3.656h8c2.611 0 4.808-1.512 6-3.656 1.192 2.144 3.389 3.656 6 3.656h8c2.611 0 4.808-1.512 6-3.656 1.192 2.144 3.389 3.656 6 3.656h8c3.827 0 6.969-3.141 6.969-6.969v-72c0-3.827-3.141-6.969-6.969-6.969h-8z" opacity=".08"/><path d="m74-66.97c-3.283 0-5.969 2.686-5.969 5.969v72c0 3.283 2.686 5.969 5.969 5.969h8c3.283 0 5.969-2.686 5.969-5.969v-72c0-3.283-2.686-5.969-5.969-5.969zm-20 16c-3.283 0-5.969 2.686-5.969 5.969v56c0 3.283 2.686 5.969 5.969 5.969h8c3.283 0 5.969-2.686 5.969-5.969v-56c0-3.283-2.686-5.969-5.969-5.969zm-20 16c-3.283 0-5.969 2.686-5.969 5.969v40c0 3.283 2.686 5.969 5.969 5.969h8c3.283 0 5.969-2.686 5.969-5.969v-40c0-3.283-2.686-5.969-5.969-5.969zm-20 16c-3.283 0-5.969 2.686-5.969 5.969v24c0 3.283 2.686 5.969 5.969 5.969h8c3.283 0 5.969-2.686 5.969-5.969v-24c0-3.283-2.686-5.969-5.969-5.969z" opacity=".1"/><path d="m74-66.03c-2.763 0-5.031 2.268-5.031 5.031v72c0 2.763 2.268 5.031 5.031 5.031h8c2.763 0 5.031-2.268 5.031-5.031v-72c0-2.763-2.268-5.031-5.031-5.031zm-20 16c-2.763 0-5.031 2.268-5.031 5.031v56c0 2.763 2.268 5.031 5.031 5.031h8c2.763 0 5.031-2.268 5.031-5.031v-56c0-2.763-2.268-5.031-5.031-5.031zm-20 16c-2.763 0-5.031 2.268-5.031 5.031v40c0 2.763 2.268 5.031 5.031 5.031h8c2.763 0 5.031-2.268 5.031-5.031v-40c0-2.763-2.268-5.031-5.031-5.031zm-20 16c-2.763 0-5.031 2.268-5.031 5.031v24c0 2.763 2.268 5.031 5.031 5.031h8c2.763 0 5.031-2.268 5.031-5.031v-24c0-2.763-2.268-5.031-5.031-5.031z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.799 1.184 3.275 2.812 3.781-1.091-.4547-1.844-1.508-1.844-2.781v-72c0-1.698 1.334-3.031 3.031-3.031h8c1.698 0 3.031 1.334 3.031 3.031v72c0 1.273-.7525 2.327-1.844 2.781 1.628-.5062 2.812-1.982 2.812-3.781v-72c0-2.216-1.784-4-4-4h-8z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.799 1.184 3.275 2.812 3.781-1.091-.4547-1.844-1.508-1.844-2.781v-56c0-1.698 1.334-3.031 3.031-3.031h8c1.698 0 3.031 1.334 3.031 3.031v56c0 1.273-.7525 2.327-1.844 2.781 1.628-.5062 2.812-1.982 2.812-3.781v-56c0-2.216-1.784-4-4-4h-8z" fill="url(#j)" opacity=".6"/><path d="m34-34c-2.216 0-4 1.784-4 4v40c0 1.799 1.184 3.275 2.812 3.781-1.091-.4547-1.844-1.508-1.844-2.781v-40c0-1.698 1.334-3.031 3.031-3.031h8c1.698 0 3.031 1.334 3.031 3.031v40c0 1.273-.7525 2.327-1.844 2.781 1.628-.5062 2.812-1.982 2.812-3.781v-40c0-2.216-1.784-4-4-4h-8z" fill="url(#i)" opacity=".6"/><path d="m14-18c-2.216 0-4 1.784-4 4v24c0 1.799 1.184 3.275 2.812 3.781-1.091-.4547-1.844-1.508-1.844-2.781v-24c0-1.698 1.334-3.031 3.031-3.031h8c1.698 0 3.031 1.334 3.031 3.031v24c0 1.273-.7525 2.327-1.844 2.781 1.628-.5062 2.812-1.982 2.812-3.781v-24c0-2.216-1.784-4-4-4h-8z" fill="url(#h)" opacity=".6"/><path d="m41.5-36.18c-3.9Line truncated

After

Width:  |  Height:  |  Size: 5.2 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient5940"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient4598"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7422"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient565184-2-0" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 98.35 78.44)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5940"/><linearGradient id="linearGradient565186-6-5" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 102.2 81.36)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient565196-0-2" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7422"/><linearGradient id="linearGradient576026-2" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.98 -63.51)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient576028-6" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientTransform="matrix(2.143 0 0 2.087 44.91 -64.67)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386-64-0" x="-.008195" y="-.02176" width="1.016" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient4206"><stop stop-color="#fff" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><radialGradient id="radialGradient4612-0" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-opacity="0" offset="1"/></radialGradient><filter id="filter4618-7" x="-.07545" y="-.06204" width="1.151" height="1.143"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient9" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><linearGradient id="linearGradient11" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient12" x1="322.3" x2="328.4" y1="62.62" y2="68.74" gradientTransform="matrix(.75 0 0 .8333 81.62 10.42)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient13" x1="325.4" x2="328.4" y1="63.27" y2="68.74" gradientTransform="matrix(.5 0 0 .5 -489.8 -97.75)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient14" x1="-47.16" x2="-46.15" y1="39.38" y2="44.17" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#729fcf" offset="0"/><stop stop-color="#729fcf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient15" x1="-48" x2="-46.75" y1="40.38" y2="45.69" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#3465a4" offset="0"/><stop stop-color="#3465a4" stop-opacity="0" offset="1"/></linearGradient></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152Line truncated

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient5940"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient4598"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7422"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient565184-2" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 98.35 78.44)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5940"/><linearGradient id="linearGradient565186-6" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 102.2 81.36)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient565196-0" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7422"/><linearGradient id="linearGradient576026-2" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.98 -63.51)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient576028-6" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientTransform="matrix(2.143 0 0 2.087 44.91 -64.67)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386-64-0" x="-.008195" y="-.02176" width="1.016" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" stroke-width="2"/></mask><linearGradient id="C" x1="-112.3" x2="-112.3" y1="148.9" y2="164.5" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-color="#fff" offset=".2177"/><stop stop-color="#fff" offset=".7659"/><stop offset="1"/></linearGradient><filter id="D" x="-.0125" y="-.04971" width="1.026" height="1.099" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.001 0.244"/></filter><filter id="H" x="-.395" y="-.5737" width="1.79" height="2.147" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="2.8946329"/></filter><g opacity=".7"><g transform="matrix(.5923 0 0 .5923 -7.406 54.4)" enable-background="new"><rect x="14.98" y="-62.54" width="77" height="29" rx="2.877" ry="2.781" fill="url(#linearGradient576026-2)" fill-rule="evenodd" stroke="#888a85" stroke-dashoffset=".7" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".9924"/><path d="m18.12-61.5Line truncated

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7822-4"><stop offset="0"/><stop stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient4598"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7652-3"><stop stop-color="#729fcf" offset="0"/><stop stop-color="#729fcf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient1643253" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><filter id="filter10631-9-19" x="-.0544" y="-.09756" width="1.109" height="1.195"><feGaussianBlur stdDeviation="0.5906498"/></filter><radialGradient id="radialGradient8346" cx="18.25" cy="15.72" r="29.99" gradientTransform="matrix(.4532 0 0 .452 115.9 33.56)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3e9ff" offset="0"/><stop stop-color="#f3f9ff" offset=".1552"/><stop stop-color="#376497" offset=".6311"/><stop stop-color="#273e5d" offset=".8155"/><stop stop-color="#526ea5" offset="1"/></radialGradient><linearGradient id="linearGradient8348" x1="145.2" x2="144.4" y1="-41.41" y2="46.08" gradientTransform="matrix(.08489 0 0 .08523 116.4 34.32)" gradientUnits="userSpaceOnUse"><stop stop-color="#acc5ed" offset="0"/><stop stop-color="#193b6e" offset="1"/></linearGradient><radialGradient id="radialGradient8350" cx="24.88" cy="23" r="19.19" gradientTransform="matrix(1 0 0 .9316 0 1.573)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><radialGradient id="radialGradient8380" cx="24.88" cy="23" r="19.19" gradientTransform="matrix(1 0 0 .9316 .6567 2.136)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><radialGradient id="radialGradient8410" cx="23.93" cy="14.66" r="19.19" gradientTransform="matrix(1.7 0 0 1.584 -16.91 -7.702)" gradientUnits="userSpaceOnUse"><stop stop-color="#f6f6f5" offset="0"/><stop stop-color="#ecece9" offset=".4992"/><stop stop-color="#9a9a8d" offset=".7619"/><stop stop-color="#fff" offset="1"/></radialGradient><radialGradient id="radialGradient8412" cx="24.14" cy="14.21" r="19.19" gradientTransform="matrix(1.7 0 0 1.584 -16.91 -7.702)" gradientUnits="userSpaceOnUse"><stop stop-color="#f6f6f5" offset="0"/><stop stop-color="#ecece9" offset=".381"/><stop stop-color="#c5c5be" offset=".7619"/><stop stop-color="#fff" offset="1"/></radialGradient><radialGradient id="radialGradient8440" cx="24.74" cy="17.35" r="19.19" gradientTransform="matrix(1.381 0 0 1.286 -9.42 -3.294)" gradientUnits="userSpaceOnUse"><stop stop-color="#f6f6f5" offset="0"/><stop stop-color="#ecece9" offset=".538"/><stop stop-color="#97978a" offset=".8543"/><stop stop-color="#fff" offset="1"/></radialGradient><radialGradient id="radialGradient8470" cx="77.56" cy="152.5" r="13.03" gradientTransform="matrix(1.963 0 0 1.094 -74.66 -21.12)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><filter id="filter5386-2" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient6175" x1="22.36" x2="28.25" y1="11.89" y2="11.89" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7652-3"/><linearGradient id="linearGradient6239" x1="22.69" x2="27.97" y1="11.85" y2="11.85" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient9" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4175"/><linearGradient id="linearGradient4175"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><radialGradient id="radialGradient4612-0" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><filter id="filter4618-7" x="-.07545" y="-.06204" width="1.151" height="1.143"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradienLine truncated

After

Width:  |  Height:  |  Size: 26 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient36138"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7822-4"><stop offset="0"/><stop stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient5940"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient5911-7-1"><stop stop-color="#f6f6f5" offset="0"/><stop stop-color="#ecece9" offset=".381"/><stop stop-color="#c5c5be" offset=".7619"/><stop stop-color="#fff" offset="1"/></linearGradient><filter id="filter10631-9-19-8" x="-.05439" y="-.09755" width="1.109" height="1.195"><feGaussianBlur stdDeviation="0.5906498"/></filter><radialGradient id="radialGradient8346-8" cx="18.25" cy="15.72" r="29.99" gradientTransform="matrix(.43 0 0 .4288 2.023 23.88)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#eeeeec" offset=".1552"/><stop stop-color="#eeeeec" offset=".6311"/><stop stop-color="#babdb6" offset=".8155"/><stop stop-color="#888a85" offset="1"/></radialGradient><radialGradient id="radialGradient8350-2" cx="24.88" cy="23" r="19.19" gradientTransform="matrix(.4286 0 0 .3992 16.53 89.55)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><radialGradient id="radialGradient8380-4" cx="24.88" cy="23" r="19.19" gradientTransform="matrix(.4286 0 0 .3992 16.81 89.8)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><radialGradient id="radialGradient8410-6" cx="23.93" cy="14.66" r="19.19" gradientTransform="matrix(.7542 0 0 .7024 8.717 84.97)" gradientUnits="userSpaceOnUse"><stop stop-color="#f6f6f5" offset="0"/><stop stop-color="#ecece9" offset=".4992"/><stop stop-color="#9a9a8d" offset=".7619"/><stop stop-color="#fff" offset="1"/></radialGradient><radialGradient id="radialGradient8416-0" cx="24.14" cy="14.21" r="19.19" gradientTransform="matrix(.7542 0 0 .7024 8.717 84.97)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5911-7-1"/><radialGradient id="radialGradient8440-0" cx="24.74" cy="17.35" r="19.19" gradientTransform="matrix(.6124 0 0 .5703 12.04 86.93)" gradientUnits="userSpaceOnUse"><stop stop-color="#f6f6f5" offset="0"/><stop stop-color="#ecece9" offset=".538"/><stop stop-color="#97978a" offset=".8543"/><stop stop-color="#fff" offset="1"/></radialGradient><radialGradient id="radialGradient8470-2" cx="77.56" cy="152.5" r="13.03" gradientTransform="matrix(1.963 0 0 1.094 -74.66 -21.12)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></radialGradient><linearGradient id="linearGradient3387"><stop stop-color="#8f9388" offset="0"/><stop stop-color="#c6cac2" offset=".5"/><stop stop-color="#d3d7cf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient32908" x1="22.36" x2="28.25" y1="11.89" y2="11.89" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3387"/><linearGradient id="linearGradient36140" x1="22.36" x2="28.25" y1="11.89" y2="11.89" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient36138"/><linearGradient id="linearGradient36952" x1="22.36" x2="28.25" y1="11.89" y2="11.89" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient36138"/><filter id="filter5386-65" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><filter id="filter5386-2-2" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7422"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient2128329" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(.903 0 0 .9021 36.25 -116.5)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5940"/><linearGradient id="linearGradient2128331" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(.8304 0 0 .8304 38.39 -114.9)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient36138"/><linearGradient id="linearGradient2128333" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientTransform="matrix(.8304 0 0 .8304 38.39 -115.7)" gradientUnits="userSpaceOnULine truncated

After

Width:  |  Height:  |  Size: 23 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient5940"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient4598"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7422"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient565184-2" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 98.35 78.44)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5940"/><linearGradient id="linearGradient565186-6" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 102.2 81.36)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient565196-0" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7422"/><linearGradient id="linearGradient576026-2" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.98 -63.51)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient576028-6" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientTransform="matrix(2.143 0 0 2.087 44.91 -64.67)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386-64-0" x="-.008195" y="-.02176" width="1.016" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient12756"><stop stop-color="#5789ca" offset="0"/><stop stop-color="#023c88" offset="1"/></linearGradient><linearGradient id="linearGradient8813" x1="88" x2="178" y1="44.5" y2="202.5" gradientTransform="matrix(.04808 0 0 .04032 303.9 219.1)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient11544" x1="110.5" x2="110.5" y1="406.4" y2="381.4" gradientUnits="userSpaceOnUse"><stop stop-color="#4b4d49" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11542" x1="169.5" x2="169.5" y1="406.3" y2="381.7" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#d3d7cf" offset="1"/></linearGradient><linearGradient id="linearGradient3830" x1="306.6" x2="306.6" y1="233.9" y2="232.7" gradientTransform="matrix(.7656 0 0 .7656 786.1 -36.93)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><filter id="filter10920" x="-.2043" y="-.379" width="1.41" height="1.811" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.5435346"/></filter><linearGradient id="linearGradient3880" x1="306.6" x2="306.6" y1="233.9" y2="232.7" gradientTransform="matrix(.7656 0 0 .7656 779.2 -36.93)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><radialGradient id="radialGradient3908" cx="326" cy="58" r="12.5" gradientTransform="matrix(-.5241 2.303e-7 .02554 -.3735 476.1 243.7)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><radialGradient id="radialGradient3906" cx="327.5" cy="58" r="12.5" gradientTransform="matrix(2.031 1.561e-8 0 .3864 -353.1 199.6)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient3900" x1="317.3" x2="298.3" y1="86.37" y2="-18.47" gradientTransform="matrix(.2223 0 0 .2385 239.4 207.3)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5538"/><radialGradient id="radialGradient3898" cx="314.2" cy="56.92" r="23" gradientTransform="matrix(.2107 .7334 -.2821 .08108 259.3 -13.83)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient8702"/><linearGradient id="linearGradient3712" x1="316.2" x2="316.2" y1="83.21" y2="92.05" gradientTransform="matrix(.248 0 0 .4 231.7 197.2)" gradientUnits="userSpaceOnUse"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient3698" x1="317.9" x2="298.3" y1="92.35" y2="-18.47" gradientTransform="matrix(.2904 0 0 .3002 218 204.1)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5538"/><radialGradient id="radialGradient3696" cx="314.2" cy="56.92" r="23" gradientTransform="matrix(.2753 .9228 -.3686 .102 244.1 -74.18)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient8702"/><linearGradient id="linearGradient3694" x1="307.7" x2="307.7" y1="229.2" y2="230.5" gradientTransform="translate(0,1)" gradientUnits="userSpaceOnUse"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#555753Line truncated

After

Width:  |  Height:  |  Size: 22 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient3983"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient5940"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient4598"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7422"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient565184-2" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 98.35 78.44)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5940"/><linearGradient id="linearGradient565186-6" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 102.2 81.36)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient565196-0" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7422"/><linearGradient id="linearGradient576026-2" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.98 -63.51)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient576028-6" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientTransform="matrix(2.143 0 0 2.087 44.91 -64.67)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386-64-0" x="-.008195" y="-.02176" width="1.016" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient11596"><stop stop-color="#fff" offset="0"/><stop offset="1"/></linearGradient><linearGradient id="linearGradient8813" x1="88" x2="178" y1="44.5" y2="202.5" gradientTransform="matrix(.04808 0 0 .04032 303.9 219.1)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient11544" x1="110.5" x2="110.5" y1="406.4" y2="381.4" gradientUnits="userSpaceOnUse"><stop stop-color="#4b4d49" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11542" x1="169.5" x2="169.5" y1="406.3" y2="381.7" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#d3d7cf" offset="1"/></linearGradient><linearGradient id="linearGradient3830" x1="306.6" x2="306.6" y1="233.9" y2="232.7" gradientTransform="matrix(.7656 0 0 .7656 786.1 -36.93)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><filter id="filter10920" x="-.2043" y="-.379" width="1.41" height="1.811" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.5435346"/></filter><linearGradient id="linearGradient3880" x1="306.6" x2="306.6" y1="233.9" y2="232.7" gradientTransform="matrix(.7656 0 0 .7656 779.2 -36.93)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3983"/><radialGradient id="radialGradient3908" cx="326" cy="58" r="12.5" gradientTransform="matrix(-.5241 2.303e-7 .02554 -.3735 476.1 243.7)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><radialGradient id="radialGradient3906" cx="327.5" cy="58" r="12.5" gradientTransform="matrix(2.031 1.561e-8 0 .3864 -353.1 199.6)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient3900" x1="317.3" x2="298.3" y1="86.37" y2="-18.47" gradientTransform="matrix(.1702 0 0 .2029 963.2 123.1)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5538"/><radialGradient id="radialGradient3898" cx="314.2" cy="56.92" r="23" gradientTransform="matrix(.1613 .6239 -.216 .06897 986.9 -65.02)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient8702"/><radialGradient id="radialGradient3926" cx="314.2" cy="56.92" r="23" gradientTransform="matrix(.1613 .6239 -.216 .06897 978.5 -65.02)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient8702"/><linearGradient id="linearGradient3712" x1="316.2" x2="316.2" y1="83.21" y2="92.05" gradientTransform="matrix(.1899 0 0 .3063 961.2 118.6)" gradientUnits="userSpaceOnUse"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient3698" x1="317.9" x2="298.3" y1="92.35" y2="-18.47" gradientTransform="matrix(.2223 0 0 .2298 950.8 124)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5538"/><radialGradient id="radialGradient3696" cx="314.2" cy="56.92" r="23" gradientTransform="matrix(.2108 .7066 -.2822 .07812 970.7 -89.13)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient8702"/><linearGradient id="linearGradienLine truncated

After

Width:  |  Height:  |  Size: 22 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7822-4"><stop offset="0"/><stop stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient1643253" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><filter id="filter5386-58" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient9" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient11" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><radialGradient id="radialGradient4612-0" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><filter id="filter4618-7" x="-.07545" y="-.06204" width="1.151" height="1.143"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient12" x1="322.3" x2="328.4" y1="62.62" y2="68.74" gradientTransform="matrix(.75 0 0 .8333 81.62 10.42)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient4206"><stop stop-color="#fff" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient13" x1="325.4" x2="328.4" y1="63.27" y2="68.74" gradientTransform="matrix(.5 0 0 .5 -489.8 -97.75)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient14" x1="-47.16" x2="-46.15" y1="39.38" y2="44.17" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7652-3"/><linearGradient id="linearGradient7652-3"><stop stop-color="#729fcf" offset="0"/><stop stop-color="#729fcf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient15" x1="-48" x2="-46.75" y1="40.38" y2="45.69" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#3465a4" offset="0"/><stop stop-color="#3465a4" stop-opacity="0" offset="1"/></linearGradient><radialGradient id="radialGradient81" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(1.058 -1.042 .4439 .4509 -55.95 372.2)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><filter id="filter4618" x="-.1134" y="-.08588" width="1.226" height="1.205"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient85" x1="-75.84" x2="-75.96" y1="48.62" y2="53.84" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7652-3"/></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.Line truncated

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889-6" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientTransform="matrix(2.779 0 0 2.707 11.17 99.85)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386-1" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7907" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(1.631 0 0 1.63 -55.24 83.65)" gradientUnits="userSpaceOnUse"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient7909" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(1.5 0 0 1.5 -51.37 86.57)" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient1667502" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2.594 0 0 2.507 9.965 101.4)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7887"/><linearGradient id="linearGradient1667504" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientTransform="matrix(1.5 0 0 1.5 -51.37 85.07)" gradientUnits="userSpaceOnUse"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient><filter id="filter5386-1-2" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.913 0.83-5.293 1.22-6.473 1.13 0.62-0.95 2.3-2.56 4.16-4.1 3.721-3.08 7.969-6.37 7.969-6.37z"/></clipPath><mask id="B" maskUnits="userSpaceOnUse"><rect x="-115.6" y="147" width="51.28" height="17.34" rx=".6657" fill="url(#C)" fill-rule="evenodd" stroke-width="2"/></mask><linearGradient id="C" x1="-112.3" x2="-112.3" y1="148.9" y2="164.5" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-color="#fff" offset=".2177"/><stop stop-color="#fff" offset=".7659"/><stop offset="1"/></linearGradient><filter id="D" x="-.0125" y="-.04971" width="1.026" height="1.099" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.001 0.244"/></filter><filter id="H" x="-.395" y="-.5737" width="1.79" height="2.147" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="2.8946329"/></filter><g transform="matrix(.01359 0 0 .01359 12.37 35.5)" fill="#999" stroke-width="75"><path d="m-328.5-519h-150v150h150z"/><path d="m-328.5-219h-150v150h150z"/><patLine truncated

After

Width:  |  Height:  |  Size: 9.0 KiB

@@ -0,0 +1 @@
<svg height="32.011" viewBox="0 0 24.892 32.011" width="24.892" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="10.28" cy="8.071" gradientTransform="matrix(1 0 0 .8274 0 1.122)" gradientUnits="userSpaceOnUse" r="4.525" xlink:href="#e"/><radialGradient id="b" cx="10.28" cy="9.842" gradientTransform="matrix(4.681 0 0 1.277 -37.84 -3.301)" gradientUnits="userSpaceOnUse" r="4.525" xlink:href="#g"/><radialGradient id="c" cx="10.74" cy="19.5" gradientTransform="matrix(1 0 0 .3026 0 13.6)" gradientUnits="userSpaceOnUse" r="8.263" xlink:href="#d"/><linearGradient id="d"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="e"><stop offset="0" stop-color="#729fcf"/><stop offset="1" stop-color="#729fcf" stop-opacity="0"/></linearGradient><radialGradient id="f" cx="10.28" cy="10.02" gradientTransform="matrix(4.681 0 0 1.277 -37.84 -3.301)" gradientUnits="userSpaceOnUse" r="4.525" xlink:href="#g"/><linearGradient id="g"><stop offset="0" stop-color="#3465a4"/><stop offset="1" stop-color="#3465a4" stop-opacity="0"/></linearGradient><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="11.22" x2="11.22" xlink:href="#d" y1="43.14" y2="23.04"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="24.84" x2="21.04" y1="44.53" y2="21.04"><stop offset="0" stop-color="#babdb6"/><stop offset="1" stop-color="#fff"/></linearGradient><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="39.07" x2="39.42" y1="28.5" y2="10.94"><stop offset="0" stop-color="#888a85"/><stop offset="1" stop-color="#555753"/></linearGradient><radialGradient id="k" cx="10.28" cy="7.825" gradientTransform="matrix(.6984 0 0 .5779 3.1 2.744)" gradientUnits="userSpaceOnUse" r="4.525" xlink:href="#e"/><radialGradient id="l" cx="8.906" cy="1.729" gradientTransform="matrix(.7375 0 0 .7202 2.434 .6617)" gradientUnits="userSpaceOnUse" r="1.995"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#d3d7cf"/></radialGradient><radialGradient id="m" cx="8.305" cy="1.126" gradientTransform="matrix(1.86 0 0 1.817 -7.14 -.8942)" gradientUnits="userSpaceOnUse" r="2.051"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><g enable-background="new" transform="matrix(.6237 0 0 .6237 -2.5201 3.0118)"><ellipse cx="10.74" cy="19.5" fill="url(#c)" opacity=".1" rx="8.263" ry="2.5" stroke-linecap="round" stroke-linejoin="round" transform="matrix(2.305 0 0 2.378 -1.198 -5.82)"/><ellipse cx="10.28" cy="6.5" rx="4.281" ry="3.5" style="opacity:.6;stroke-width:.1997;stroke-linecap:round;stroke-linejoin:round;fill:url(#a);stroke:url(#f)" transform="matrix(4.555 0 0 5.507 -22.83 -20.8)"/><path d="m24 12.55a.4507.4507 0 0 0 -.4.244l-16 31a.4507.4507 0 0 0 .4004.658h3.4996a.4507.4507 0 0 0 .406-.256l2.416-5.007 21.06 3.531.711 1.476a.4507.4507 0 0 0 .406.256h3.5a.4507.4507 0 0 0 .4-.658l-16-31a.4507.4507 0 0 0 -.4-.244zm0 6.465 3.172 6.619-5.627-1.463zm-3.756 7.826 5.738 1.478-8.398 4.088zm9.201 3.545 3.864 8.027-15.18-2.531z" fill="url(#h)" fill-rule="evenodd" opacity=".153" transform="matrix(1 0 0 .4005 0 26.14)"/><ellipse cx="10.28" cy="6.5" rx="4.281" ry="3.5" style="opacity:.8;stroke-width:.2685;stroke-linecap:round;stroke-linejoin:round;stroke:url(#b);fill:url(#a)" transform="matrix(3.387 0 0 4.094 -10.82 -11.61)"/><g transform="translate(0 -.5)"><path d="m24 13-16 31h3.5l2.563-5.312 21.62 3.625.812 1.687h3.5zm0 4.969 4 8.343-7.094-1.843zm-4 8.343 7.281 1.875-10.66 5.188zm9.656 3.469 4.438 9.219-17.44-2.906z" fill="url(#i)" fill-rule="evenodd" stroke="url(#j)"/><g fill="none" stroke="#fff" stroke-linecap="round"><path d="m38.41 43.03-14.41-27.91-14.41 27.91"/><path d="m15.78 34.91 13.03-6.344"/><path d="m15.09 36.84 19.66 3.281"/></g></g><g stroke-linecap="round" stroke-linejoin="round"><ellipse cx="10.28" cy="6.5" fill="url(#k)" rx="4.281" ry="3.5" stroke="url(#b)" stroke-width=".4075" transform="matrix(2.219 0 0 2.714 1.186 -2.643)"/><g transform="matrix(2.24 0 0 2.23 -19.68 9.389)"><ellipse cx="9.203" cy="2.25" fill="url(#l)" rx="1.797" ry="1.75" stroke="#555753" stroke-width=".3967" transform="matrix(1.113 0 0 1.143 9.256 -.07143)"/><circle cx="18.874" cy="1.7892" fill="#fff" r=".906" stroke-width="1.812"/></g><ellipse cx="9.203" cy="2.25" fill="none" rx="1.797" ry="1.75" stroke="url(#m)" stroke-width=".5078" transform="matrix(1.948 0 0 1.991 6.074 10.48)"/></g></g></svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

@@ -0,0 +1 @@
<svg height="32.011" viewBox="0 0 24.892 32.011" width="24.892" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="10.74" cy="19.5" gradientTransform="matrix(1 0 0 .3026 0 13.6)" gradientUnits="userSpaceOnUse" r="8.263" xlink:href="#b"/><linearGradient id="b"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="11.22" x2="11.22" xlink:href="#b" y1="43.14" y2="23.04"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="24.84" x2="21.04" y1="44.53" y2="21.04"><stop offset="0" stop-color="#babdb6"/><stop offset="1" stop-color="#fff"/></linearGradient><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="39.07" x2="39.42" y1="28.5" y2="10.94"><stop offset="0" stop-color="#888a85"/><stop offset="1" stop-color="#555753"/></linearGradient><radialGradient id="f" cx="8.906" cy="1.729" gradientTransform="matrix(.7375 0 0 .7202 2.434 .6617)" gradientUnits="userSpaceOnUse" r="1.995"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#d3d7cf"/></radialGradient><radialGradient id="g" cx="8.305" cy="1.126" gradientTransform="matrix(1.86 0 0 1.817 -7.14 -.8942)" gradientUnits="userSpaceOnUse" r="2.051"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><g enable-background="new" transform="matrix(.6237 0 0 .6237 -2.5201 3.0118)"><ellipse cx="10.74" cy="19.5" fill="url(#a)" opacity=".1" rx="8.263" ry="2.5" stroke-linecap="round" stroke-linejoin="round" transform="matrix(2.305 0 0 2.378 -1.198 -5.82)"/><path d="m24 12.55a.4507.4507 0 0 0 -.4.244l-16 31a.4507.4507 0 0 0 .4004.658h3.4996a.4507.4507 0 0 0 .406-.256l2.416-5.007 21.06 3.531.711 1.476a.4507.4507 0 0 0 .406.256h3.5a.4507.4507 0 0 0 .4-.658l-16-31a.4507.4507 0 0 0 -.4-.244zm0 6.465 3.172 6.619-5.627-1.463zm-3.756 7.826 5.738 1.478-8.398 4.088zm9.201 3.545 3.864 8.027-15.18-2.531z" fill="url(#c)" fill-rule="evenodd" opacity=".153" transform="matrix(1 0 0 .4005 0 26.14)"/><g transform="translate(0 -.5)"><path d="m24 13-16 31h3.5l2.563-5.312 21.62 3.625.812 1.687h3.5zm0 4.969 4 8.343-7.094-1.843zm-4 8.343 7.281 1.875-10.66 5.188zm9.656 3.469 4.438 9.219-17.44-2.906z" fill="url(#d)" fill-rule="evenodd" stroke="url(#e)"/><g fill="none" stroke="#fff" stroke-linecap="round"><path d="m38.41 43.03-14.41-27.91-14.41 27.91"/><path d="m15.78 34.91 13.03-6.344"/><path d="m15.09 36.84 19.66 3.281"/></g></g><g stroke-linecap="round" stroke-linejoin="round"><g transform="matrix(2.24 0 0 2.23 -19.68 9.389)"><ellipse cx="9.203" cy="2.25" fill="url(#f)" rx="1.797" ry="1.75" stroke="#555753" stroke-width=".3967" transform="matrix(1.113 0 0 1.143 9.256 -.07143)"/><circle cx="18.874" cy="1.7892" fill="#fff" r=".906" stroke-width="1.812"/></g><ellipse cx="9.203" cy="2.25" fill="none" rx="1.797" ry="1.75" stroke="url(#g)" stroke-width=".5078" transform="matrix(1.948 0 0 1.991 6.074 10.48)"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient7822-4"><stop offset="0"/><stop stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient4598"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7652-3"><stop stop-color="#729fcf" offset="0"/><stop stop-color="#729fcf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient6175" x1="22.36" x2="28.25" y1="11.89" y2="11.89" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7652-3"/><linearGradient id="linearGradient6239" x1="22.69" x2="27.97" y1="11.85" y2="11.85" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><filter id="filter4684" x="-.09275" y="-.106" width="1.186" height="1.212"><feGaussianBlur stdDeviation="0.71917802"/></filter><linearGradient id="linearGradient3278" x1="-6.411" x2="-10.07" y1="25.76" y2="1.873" gradientTransform="matrix(1.5 0 0 1.4 336.2 52.8)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient6991"/><linearGradient id="linearGradient6991"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient4307" x1="25.05" x2="27.76" y1="16.17" y2="24.54" gradientTransform="matrix(1.088 0 0 1.086 294.4 40.06)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7340-2"/><linearGradient id="linearGradient7340-2"><stop stop-color="#555753" offset="0"/><stop stop-color="#888a85" offset="1"/></linearGradient><linearGradient id="linearGradient4182" x1="326.5" x2="326.5" y1="61.7" y2="60.69" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4175"/><linearGradient id="linearGradient4175"><stop stop-color="#babdb6" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><radialGradient id="radialGradient4612" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(2.238 -.5404 .1485 .615 -392 204.4)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><filter id="filter4618" x="-.1134" y="-.08587" width="1.226" height="1.205"><feGaussianBlur stdDeviation="0.89652215"/></filter><linearGradient id="linearGradient4212" x1="322.3" x2="328.4" y1="62.62" y2="68.74" gradientTransform="matrix(.75 0 0 .8333 81.62 10.42)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient4206"><stop stop-color="#fff" offset="0"/><stop stop-color="#babdb6" offset="1"/></linearGradient><linearGradient id="linearGradient4231" x1="325.4" x2="328.4" y1="63.27" y2="68.74" gradientTransform="matrix(.5 0 0 .5 -489.8 -97.75)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4206"/><linearGradient id="linearGradient4380" x1="320" x2="330.2" y1="60.75" y2="87.75" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4598"/><linearGradient id="linearGradient3248-0" x1="-47.16" x2="-46.15" y1="39.38" y2="44.17" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7652-3"/><linearGradient id="linearGradient3250-1" x1="-48" x2="-46.75" y1="40.38" y2="45.69" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse"><stop stop-color="#3465a4" offset="0"/><stop stop-color="#3465a4" stop-opacity="0" offset="1"/></linearGradient><radialGradient id="radialGradient81" cx="306.5" cy="86.38" r="21.91" gradientTransform="matrix(1.058 -1.042 .4439 .4509 -55.95 372.2)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7822-4"/><linearGradient id="linearGradient85" x1="-75.84" x2="-75.96" y1="48.62" y2="53.84" gradientTransform="translate(386,50)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7652-3"/></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter Line truncated

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="linearGradient36138"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient7887" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse"><stop stop-color="#d3d7cf" offset="0"/><stop stop-color="#fff" offset="1"/></linearGradient><linearGradient id="linearGradient7889" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse"><stop stop-color="#fff" offset="0"/><stop stop-color="#fff" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient5940"><stop stop-color="#2e3436" offset="0"/><stop stop-color="#555753" offset="1"/></linearGradient><linearGradient id="linearGradient3387"><stop stop-color="#8f9388" offset="0"/><stop stop-color="#c6cac2" offset=".5"/><stop stop-color="#d3d7cf" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient32908" x1="22.36" x2="28.25" y1="11.89" y2="11.89" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3387"/><linearGradient id="linearGradient36140" x1="22.36" x2="28.25" y1="11.89" y2="11.89" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient36138"/><linearGradient id="linearGradient36952" x1="22.36" x2="28.25" y1="11.89" y2="11.89" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient36138"/><filter id="filter5386-65" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><filter id="filter5386-2-2" x="-.01972" y="-.02176" width="1.039" height="1.044" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="0.26293105"/></filter><linearGradient id="linearGradient7422"><stop stop-color="#edd400" offset="0"/><stop stop-color="#edd400" stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient2128329" x1="32.81" x2="32.81" y1="21" y2="26.2" gradientTransform="matrix(.903 0 0 .9021 36.25 -116.5)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5940"/><linearGradient id="linearGradient2128331" x1="28.88" x2="29" y1="29" y2="16" gradientTransform="matrix(.8304 0 0 .8304 38.39 -114.9)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient36138"/><linearGradient id="linearGradient2128333" x1="30.31" x2="30.31" y1="27.31" y2="24.69" gradientTransform="matrix(.8304 0 0 .8304 38.39 -115.7)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7422"/><linearGradient id="linearGradient50053" x1="-7.975" x2="-11.01" y1="25.36" y2="-6.568" gradientTransform="matrix(2 0 0 1.933 43.5 .5333)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7887"/><linearGradient id="linearGradient50055" x1="-7.852" x2="-5.51" y1="3.755" y2="18.94" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient7889"/></defs><clipPath id="b"><rect x="68.78" y="-.0933" width="58.26" height="58.26" rx="2.648"/></clipPath><filter id="c" x="-.021" y="-.021" width="1.042" height="1.042" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".28282197"/></filter><clipPath id="h"><path d="m-6.562 24.53c-0.3877 0-0.6917 0.219-0.9062 0.469l-0.031-0.03-0.031 0.06-0.3438 0.313-4.25 1.218c-0.03 0-0.06 0.02-0.09 0.03-0.549 0.274-0.902 0.554-1.094 0.937-0.192 0.384-0.116 0.867 0.125 1.156 0.329 0.394 0.858 0.553 1.407 0.657l-0.407 0.437c-0.06 0.05-0.1 0.116-0.125 0.188-0.03 0.121-0.07 0.316-0.125 0.5-0.02 0.04-0.03 0.08-0.03 0.125v6.656c0 0.299 0.113 0.582 0.313 0.813 0.199 0.23 0.511 0.406 0.875 0.406h7.843c0.3236 0 0.6569-0.116 0.9063-0.375l4.651-4.81c0.2259-0.235 0.3437-0.539 0.3437-0.875v-6.625c0-0.335-0.1178-0.64-0.3437-0.875-0.2227-0.229-0.5504-0.375-0.874-0.375z"/></clipPath><filter id="i" x="-.03844" y="-.04352" width="1.077" height="1.087" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".1491362"/></filter><filter id="p" x="-.02026" y="-.02354" width="1.04" height="1.047" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".071069152"/></filter><filter id="x" x="-.03625" y="-.04222" width="1.071" height="1.083" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation=".16679387"/></filter><clipPath id="A"><path d="m-95.3 143.8s-4.189 3.27-8.1 6.5c-1.95 1.62-3.69 3.22-4.72 4.78-0.51 0.78-0.98 1.62-0.65 2.78 0.16 0.58 0.61 1.12 1.09 1.41 0.48 0.28 0.96 0.4 1.5 0.47 2.13 0.24 4.73-0.4 7.849-1.28 3.113-0.89 6.669-2.09 10.25-3.25 3.581-1.17 7.196-2.31 10.34-3 3.147-0.7 5.835-0.89 7.375-0.5 0.729 0.18 0.745 0.3 0.75 0.31 0 0 0.06 0.33-0.219 0.94-0.567 1.2-2.245 3.11-4.187 4.93-3.885 3.64-8.844 7.13-8.844 7.13l1.75 2.44s5.041-3.52 9.156-7.38c2.058-1.93 3.879-3.89 4.813-5.87 0.466-1 0.776-2.12 0.343-3.25-0.433-1.14-1.541-1.87-2.812-2.19-2.46-0.62-5.444-0.21-8.781 0.53-3.337 0.73-7.019 1.85-10.62 3.03-3.607 1.18-7.129 2.4-10.12 3.25-2.Line truncated

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,42 @@
'use strict';
'require rpc';
'require form';
'require network';
var callFileRead = rpc.declare({
object: 'file',
method: 'read',
params: [ 'path' ],
expect: { data: '' },
filter: function(value) { return value.trim() }
});
return network.registerProtocol('dhcp', {
getI18n: function() {
return _('DHCP client');
},
renderFormOptions: function(s) {
var o;
o = s.taboption('general', form.Value, 'hostname', _('Hostname to send when requesting DHCP'));
o.default = '';
o.value('', _('Send the hostname of this device'));
o.value('*', _('Do not send a hostname'));
o.datatype = 'or(hostname, "*")';
o.load = function(section_id) {
return callFileRead('/proc/sys/kernel/hostname').then(L.bind(function(hostname) {
this.placeholder = hostname;
return form.Value.prototype.load.apply(this, [section_id]);
}, this));
};
o = s.taboption('advanced', form.Flag, 'broadcast', _('Use broadcast flag'), _('Required for certain ISPs, e.g. Charter with DOCSIS 3'));
o.default = o.disabled;
o = s.taboption('advanced', form.Value, 'clientid', _('Client ID to send when requesting DHCP'));
o.datatype = 'hexstring';
s.taboption('advanced', form.Value, 'vendorid', _('Vendor Class to send when requesting DHCP'));
}
});
@@ -0,0 +1,8 @@
'use strict';
'require network';
return network.registerProtocol('none', {
getI18n: function() {
return _('Unmanaged');
}
});
@@ -0,0 +1,222 @@
'use strict';
'require form';
'require network';
'require validation';
/**
* Determine whether a provided value is a CIDR format IP string.
* @param {string} value the IP string to test.
* @returns {boolean}
*/
function isCIDR(value) {
return Array.isArray(value) || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/(\d{1,2}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.test(value);
}
/**
* Calculate the broadcast IP for a given IP.
* @param {Node} s the ui element to test.
* @param {boolean} use_cfgvalue whether to use the config or form value.
* @returns {string}
*/
function calculateBroadcast(s, use_cfgvalue) {
const readfn = use_cfgvalue ? 'cfgvalue' : 'formvalue';
const addropt = s.children.find(o => o.option == 'ipaddr');
const addrvals = addropt ? L.toArray(addropt[readfn](s.section)) : [];
const maskopt = s.children.find(o => o.option == 'netmask');
const maskval = maskopt ? maskopt[readfn](s.section) : null;
let firstsubnet = null;
/* only form a subnet if both parts exist */
if (addrvals.length && addrvals[0] && maskval)
firstsubnet = addrvals[0] + '/' + maskval;
else if (addrvals.length)
firstsubnet = addrvals.find(a => a.indexOf('/') > 0);
if (!firstsubnet)
return null;
const [addr_str, mask_str] = firstsubnet.split('/');
const addr = validation.parseIPv4(addr_str);
if (!addr)
return null;
let mask = mask_str;
if (!isNaN(mask))
mask = validation.parseIPv4(network.prefixToMask(+mask));
else
mask = validation.parseIPv4(mask);
if (!mask)
return null;
const bc = [
addr[0] | (~mask[0] >>> 0 & 255),
addr[1] | (~mask[1] >>> 0 & 255),
addr[2] | (~mask[2] >>> 0 & 255),
addr[3] | (~mask[3] >>> 0 & 255)
];
return bc.join('.');
}
/**
* Validate a broadcast IP for a section value.
* @param {string} section_id
* @param {string} value
* @returns {boolean}
*/
function validateBroadcast(section_id, value) {
const opt = this.map.lookupOption('broadcast', section_id);
const node = opt ? this.map.findElement('id', opt[0].cbid(section_id)) : null;
const addr = node ? calculateBroadcast(this.section, false) : null;
if (node != null) {
if (addr != null)
node.querySelector('input').setAttribute('placeholder', addr);
else
node.querySelector('input').removeAttribute('placeholder');
}
return true;
}
return network.registerProtocol('static', {
CBIIPValue: form.Value.extend({
handleSwitch(section_id, option_index, ev) {
const maskopt = this.map.lookupOption('netmask', section_id);
if (maskopt == null || !this.isValid(section_id))
return;
const maskval = maskopt[0].formvalue(section_id);
const addrval = this.formvalue(section_id);
const prefix = maskval ? network.maskToPrefix(maskval) : 32;
if (prefix == null)
return;
this.datatype = 'or(cidr4,ipmask4)';
let parent = L.dom.parent(ev.target, '.cbi-value-field');
L.dom.content(parent, form.DynamicList.prototype.renderWidget.apply(this, [
section_id,
option_index,
addrval ? '%s/%d'.format(addrval, prefix) : ''
]));
const masknode = this.map.findElement('id', maskopt[0].cbid(section_id));
if (masknode) {
parent = L.dom.parent(masknode, '.cbi-value');
parent.parentNode.removeChild(parent);
}
},
renderWidget(section_id, option_index, cfgvalue) {
const widget = isCIDR(cfgvalue) ? 'DynamicList' : 'Value';
if (widget == 'DynamicList') {
this.datatype = 'or(cidr4,ipmask4)';
this.placeholder = _('Add IPv4 address…');
}
else {
this.datatype = 'ip4addr("nomask")';
}
const node = form[widget].prototype.renderWidget.apply(this, [ section_id, option_index, cfgvalue ]);
if (widget == 'Value')
L.dom.append(node, E('button', {
'class': 'cbi-button cbi-button-neutral',
'title': _('Switch to CIDR list notation'),
'aria-label': _('Switch to CIDR list notation'),
'click': L.bind(this.handleSwitch, this, section_id, option_index)
}, '…'));
return node;
},
validate: validateBroadcast
}),
CBINetmaskValue: form.Value.extend({
render(option_index, section_id, in_table) {
var addropt = this.section.children.filter(function(o) { return o.option == 'ipaddr' })[0],
addrval = addropt ? addropt.cfgvalue(section_id) : null;
if (addrval != null && isCIDR(addrval))
return E([]);
this.value('255.255.255.0');
this.value('255.255.0.0');
this.value('255.0.0.0');
return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
},
datatype: 'ip4addr("true")',
validate: validateBroadcast
}),
CBIGatewayValue: form.Value.extend({
datatype: 'ip4addr("nomask")',
render(option_index, section_id, in_table) {
return network.getWANNetworks().then(L.bind(function(wans) {
if (wans.length == 1) {
var gwaddr = wans[0].getGatewayAddr();
this.placeholder = gwaddr ? '%s (%s)'.format(gwaddr, wans[0].getName()) : '';
}
return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
}, this));
},
validate(section_id, value) {
const addropt = this.section.children.filter(function(o) { return o.option == 'ipaddr' })[0];
const addrval = addropt ? L.toArray(addropt.cfgvalue(section_id)) : null;
if (addrval != null) {
for (let a of addrval) {
const addr = a.split('/')[0];
if (value == addr)
return _('The gateway address must not be a local IP address');
}
}
return true;
}
}),
CBIBroadcastValue: form.Value.extend({
datatype: 'ip4addr("nomask")',
render(option_index, section_id, in_table) {
this.placeholder = calculateBroadcast(this.section, true);
return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
}
}),
getI18n() {
return _('Static address');
},
renderFormOptions(s) {
let o;
s.taboption('general', this.CBIIPValue, 'ipaddr', _('IPv4 address'));
s.taboption('general', this.CBINetmaskValue, 'netmask', _('IPv4 netmask'));
s.taboption('general', this.CBIGatewayValue, 'gateway', _('IPv4 gateway'));
s.taboption('general', this.CBIBroadcastValue, 'broadcast', _('IPv4 broadcast'));
o = s.taboption('general', form.DynamicList, 'ip6addr', _('IPv6 address'));
o.datatype = 'ip6addr';
o.placeholder = _('Add IPv6 address…');
o = s.taboption('general', form.Value, 'ip6gw', _('IPv6 gateway'));
o.datatype = 'ip6addr("nomask")';
o = s.taboption('general', form.Value, 'ip6prefix', _('IPv6 routed prefix'), _('Public prefix routed to this device for distribution to clients.'));
o.datatype = 'ip6addr';
}
});
@@ -0,0 +1,496 @@
'use strict';
'require baseclass';
'require request';
let rpcRequestID = 1;
let rpcSessionID = L.env.sessionid ?? '00000000000000000000000000000000';
let rpcBaseURL = L.url('admin/ubus');
const rpcInterceptorFns = [];
/**
* @class rpc
* @memberof LuCI
* @hideconstructor
* @classdesc
*
* The `LuCI.rpc` class provides high level ubus JSON-RPC abstractions
* and means for listing and invoking remove RPC methods.
*/
return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
/* privates */
call(req, cb, nobatch) {
let q = '';
if (Array.isArray(req)) {
if (req.length == 0)
return Promise.resolve([]);
for (let i = 0; i < req.length; i++)
if (req[i].params)
q += '%s%s.%s'.format(
q ? ';' : '/',
req[i].params[1],
req[i].params[2]
);
}
return request.post(rpcBaseURL + q, req, {
timeout: (L.env.rpctimeout ?? 20) * 1000,
nobatch,
credentials: true
}).then(cb, cb);
},
parseCallReply(req, res) {
let msg = null;
if (res instanceof Error)
return req.reject(res);
try {
if (!res.ok)
L.raise('RPCError', 'RPC call to %s/%s failed with HTTP error %d: %s',
req.object, req.method, res.status, res.statusText || '?');
msg = res.json();
}
catch (e) {
return req.reject(e);
}
/*
* The interceptor args are intentionally swapped.
* Response is passed as first arg to align with Request class interceptors
*/
Promise.all(rpcInterceptorFns.map(fn => fn(msg, req)))
.then(this.handleCallReply.bind(this, req, msg))
.catch(req.reject);
},
handleCallReply(req, msg) {
const type = Object.prototype.toString;
let ret = null;
try {
/* verify message frame */
if (!L.isObject(msg) || msg.jsonrpc != '2.0')
L.raise('RPCError', 'RPC call to %s/%s returned invalid message frame',
req.object, req.method);
/* check error condition */
if (L.isObject(msg.error) && msg.error.code && msg.error.message)
L.raise('RPCError', 'RPC call to %s/%s failed with error %d: %s',
req.object, req.method, msg.error.code, msg.error.message || '?');
}
catch (e) {
return req.reject(e);
}
if (!req.object && !req.method) {
ret = msg.result;
}
else if (Array.isArray(msg.result)) {
if (req.raise && msg.result[0] !== 0)
L.raise('RPCError', 'RPC call to %s/%s failed with ubus code %d: %s',
req.object, req.method, msg.result[0], this.getStatusText(msg.result[0]));
ret = (msg.result.length > 1) ? msg.result[1] : msg.result[0];
}
if (req.expect) {
for (const key in req.expect) {
if (ret != null && key != '')
ret = ret[key];
if (ret == null || type.call(ret) != type.call(req.expect[key]))
ret = req.expect[key];
break;
}
}
/* apply filter */
if (typeof(req.filter) == 'function') {
req.priv[0] = ret;
req.priv[1] = req.params;
ret = req.filter.apply(this, req.priv);
}
req.resolve(ret);
},
/**
* Lists available remote ubus objects or the method signatures of
* specific objects.
*
* This function has two signatures and is sensitive to the number of
* arguments passed to it:
* - `list()` -
* Returns an array containing the names of all remote `ubus` objects
* - `list("objname", ...)`
* Returns method signatures for each given `ubus` object name.
*
* @param {...string} [args] (objectNames)
* If any object names are given, this function will return the method
* signatures of each given object.
*
* @returns {Promise<Array<string>|Object<string, Object<string, Object<string, string>>>>}
* When invoked without arguments, this function will return a promise
* resolving to an array of `ubus` object names. When invoked with one or
* more arguments, a promise resolving to an object describing the method
* signatures of each requested `ubus` object name will be returned.
*/
list(...args) {
const msg = {
jsonrpc: '2.0',
id: rpcRequestID++,
method: 'list',
params: args.length ? args : undefined
};
return new Promise(L.bind(function(resolve, reject) {
/* store request info */
const req = { resolve, reject };
/* call rpc */
this.call(msg, this.parseCallReply.bind(this, req));
}, this));
},
/**
* @typedef {Object} DeclareOptions
* @memberof LuCI.rpc
*
* @property {string} object
* The name of the remote `ubus` object to invoke.
*
* @property {string} method
* The name of the remote `ubus` method to invoke.
*
* @property {string[]} [params]
* Lists the named parameters expected by the remote `ubus` RPC method.
* The arguments passed to the resulting generated method call function
* will be mapped to named parameters in the order they appear in this
* array.
*
* Extraneous parameters passed to the generated function will not be
* sent to the remote procedure but are passed to the
* {@link LuCI.rpc.filterFn filter function} if one is specified.
*
* Examples:
* - `params: [ "foo", "bar" ]` -
* When the resulting call function is invoked with `fn(true, false)`,
* the corresponding args object sent to the remote procedure will be
* `{ foo: true, bar: false }`.
* - `params: [ "test" ], filter: function(reply, args, extra) { ... }` -
* When the resulting generated function is invoked with
* `fn("foo", "bar", "baz")` then `{ "test": "foo" }` will be sent as
* argument to the remote procedure and the filter function will be
* invoked with `filterFn(reply, [ "foo" ], "bar", "baz")`
*
* @property {Object<string,*>} [expect]
* Describes the expected return data structure. The given object is
* supposed to contain a single key selecting the value to use from
* the returned `ubus` reply object. The value of the sole key within
* the `expect` object is used to infer the expected type of the received
* `ubus` reply data.
*
* If the received data does not contain `expect`'s key, or if the
* type of the data differs from the type of the value in the expect
* object, the expect object's value is returned as default instead.
*
* The key in the `expect` object may be an empty string (`''`) in which
* case the entire reply object is selected instead of one of its subkeys.
*
* If the `expect` option is omitted, the received reply will be returned
* as-is, regardless of its format or type.
*
* Examples:
* - `expect: { '': { error: 'Invalid response' } }` -
* This requires the entire `ubus` reply to be a plain JavaScript
* object. If the reply isn't an object but e.g. an array or a numeric
* error code instead, it will get replaced with
* `{ error: 'Invalid response' }` instead.
* - `expect: { results: [] }` -
* This requires the received `ubus` reply to be an object containing
* a key `results` with an array as value. If the received reply does
* not contain such a key, or if `reply.results` points to a non-array
* value, the empty array (`[]`) will be used instead.
* - `expect: { success: false }` -
* This requires the received `ubus` reply to be an object containing
* a key `success` with a boolean value. If the reply does not contain
* `success` or if `reply.success` is not a boolean value, `false` will
* be returned as default instead.
*
* @property {LuCI.rpc.filterFn} [filter]
* Specifies an optional filter function which is invoked to transform the
* received reply data before it is returned to the caller.
*
* @property {boolean} [reject=false]
* If set to `true`, non-zero ubus call status codes are treated as fatal
* error and lead to the rejection of the call promise. The default
* behaviour is to resolve with the call return code value instead.
*/
/**
* The filter function is invoked to transform a received `ubus` RPC call
* reply before returning it to the caller.
*
* @callback LuCI.rpc.filterFn
*
* @param {*} data
* The received `ubus` reply data or a subset of it as described in the
* `expect` option of the RPC call declaration. In case of remote call
* errors, `data` is numeric `ubus` error code instead.
*
* @param {Array<*>} args
* The arguments the RPC method has been invoked with.
*
* @param {...*} extraArgs
* All extraneous arguments passed to the RPC method exceeding the number
* of arguments describes in the RPC call declaration.
*
* @returns {*}
* The return value of the filter function will be returned to the caller
* of the RPC method as-is.
*/
/**
* The generated invocation function is returned by
* {@link LuCI.rpc#declare rpc.declare()} and encapsulates a single
* RPC method call.
*
* Calling this function will execute a remote `ubus` HTTP call request
* using the arguments passed to it as arguments and return a promise
* resolving to the received reply values.
*
* @callback LuCI.rpc.invokeFn
*
* @param {...*} params
* The parameters to pass to the remote procedure call. The given
* positional arguments will be named to named RPC parameters according
* to the names specified in the `params` array of the method declaration.
*
* Any additional parameters exceeding the amount of arguments in the
* `params` declaration are passed as private extra arguments to the
* declared filter function.
*
* @returns {Promise<*>}
* Returns a promise resolving to the result data of the remote `ubus`
* RPC method invocation, optionally substituted and filtered according
* to the `expect` and `filter` declarations.
*/
/**
* Describes a remote RPC call procedure and returns a function
* implementing it.
*
* @param {LuCI.rpc.DeclareOptions} options
* If any object names are given, this function will return the method
* signatures of each given object.
*
* @returns {LuCI.rpc.invokeFn}
* Returns a new function implementing the method call described in
* `options`.
*/
declare(options) {
return Function.prototype.bind.call(function(rpc, options, ...args) {
return new Promise((resolve, reject) => {
/* build parameter object */
let p_off = 0;
const params = { };
if (Array.isArray(options.params)) {
// Array style: parameter names are positional
for (p_off = 0; p_off < options.params.length; p_off++)
params[options.params[p_off]] = args[p_off];
} else if (typeof(options.params) === 'object') {
// Object style: first arg is an object with the parameter keys
const argObj = args[0];
if (argObj && typeof(argObj) === 'object') {
for (let key in options.params)
if (key in argObj)
params[key] = argObj[key];
}
p_off = 1;
}
/* all remaining arguments are private args */
const priv = [ undefined, undefined ];
for (; p_off < args.length; p_off++)
priv.push(args[p_off]);
/* store request info */
const req = {
expect: options.expect,
filter: options.filter,
resolve,
reject,
params,
priv,
object: options.object,
method: options.method,
raise: options.reject
};
/* build message object */
const msg = {
jsonrpc: '2.0',
id: rpcRequestID++,
method: 'call',
params: [
rpcSessionID,
options.object,
options.method,
params
]
};
/* call rpc */
rpc.call(msg, rpc.parseCallReply.bind(rpc, req), options.nobatch);
});
}, this, this, options);
},
/**
* Returns the current RPC session id.
*
* @returns {string}
* Returns the 32 byte session ID string used for authenticating remote
* requests.
*/
getSessionID() {
return rpcSessionID;
},
/**
* Set the RPC session id to use.
*
* @param {string} sid
* Sets the 32 byte session ID string used for authenticating remote
* requests.
*/
setSessionID(sid) {
rpcSessionID = sid;
},
/**
* Returns the current RPC base URL.
*
* @returns {string}
* Returns the RPC URL endpoint to issue requests against.
*/
getBaseURL() {
return rpcBaseURL;
},
/**
* Set the RPC base URL to use.
*
* @param {string} url
* Sets the RPC URL endpoint to issue requests against.
*/
setBaseURL(url) {
rpcBaseURL = url;
},
/**
* Translates a numeric `ubus` error code into a human readable
* description.
*
* @param {number} statusCode
* The numeric status code.
*
* @returns {string}
* Returns the textual description of the code.
*/
getStatusText(statusCode) {
switch (statusCode) {
case 0: return _('Command OK');
case 1: return _('Invalid command');
case 2: return _('Invalid argument');
case 3: return _('Method not found');
case 4: return _('Resource not found');
case 5: return _('No data received');
case 6: return _('Permission denied');
case 7: return _('Request timeout');
case 8: return _('Not supported');
case 9: return _('Unspecified error');
case 10: return _('Connection lost');
default: return _('Unknown error code');
}
},
/**
* Registered interceptor functions are invoked before the standard reply
* parsing and handling logic.
*
* By returning rejected promises, interceptor functions can cause the
* invocation function to fail, regardless of the received reply.
*
* Interceptors may also modify their message argument in-place to
* rewrite received replies before they're processed by the standard
* response handling code.
*
* A common use case for such functions is to detect failing RPC replies
* due to expired authentication in order to trigger a new login.
*
* @callback LuCI.rpc~interceptorFn
*
* @param {*} msg
* The unprocessed, JSON decoded remote RPC method call reply.
*
* Since interceptors run before the standard parsing logic, the reply
* data is not verified for correctness or filtered according to
* `expect` and `filter` specifications in the declarations.
*
* @param {Object} req
* The related request object which is an extended variant of the
* declaration object, allowing access to internals of the invocation
* function such as `filter`, `expect` or `params` values.
*
* @returns {Promise<*>|*}
* Interceptor functions may return a promise to defer response
* processing until some delayed work completed. Any values the returned
* promise resolves to are ignored.
*
* When the returned promise rejects with an error, the invocation
* function will fail too, forwarding the error to the caller.
*/
/**
* Registers a new interceptor function.
*
* @param {LuCI.rpc.interceptorFn} interceptorFn
* The interceptor function to register.
*
* @returns {LuCI.rpc.interceptorFn}
* Returns the given function value.
*/
addInterceptor(interceptorFn) {
if (typeof(interceptorFn) == 'function')
rpcInterceptorFns.push(interceptorFn);
return interceptorFn;
},
/**
* Removes a registered interceptor function.
*
* @param {LuCI.rpc.interceptorFn} interceptorFn
* The interceptor function to remove.
*
* @returns {boolean}
* Returns `true` if the given function has been removed or `false`
* if it has not been found.
*/
removeInterceptor(interceptorFn) {
const oldlen = rpcInterceptorFns.length;
let i = oldlen;
while (i--)
if (rpcInterceptorFns[i] === interceptorFn)
rpcInterceptorFns.splice(i, 1);
return (rpcInterceptorFns.length < oldlen);
}
});
@@ -0,0 +1,183 @@
'use strict';
var s = [0x0000, 0x0000, 0x0000, 0x0000];
/**
* Multiply two 64-bit values represented as arrays of four 16-bit words.
*
* Arrays use little-endian word order (least-significant 16-bit word first).
* The result is truncated to the lower 64 bits and returned as a 4-element
* array of 16-bit words.
*
* @param {Array<number>} a - Multiplicand (4 × 16-bit words, little-endian)
* @param {Array<number>} b - Multiplier (4 × 16-bit words, little-endian)
* @returns {Array<number>} Product as 4 × 16-bit words (little-endian)
*/
function mul(a, b) {
var r = [0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000];
for (var j = 0; j < 4; j++) {
var k = 0;
for (var i = 0; i < 4; i++) {
var t = a[i] * b[j] + r[i+j] + k;
r[i+j] = t & 0xffff;
k = t >>> 16;
}
r[j+4] = k;
}
r.length = 4;
return r;
}
/**
* Add a small integer to a 64-bit value represented as four 16-bit words.
*
* Treats `a` as a little-endian 64-bit value (4 × 16-bit words). Adds the
* integer `n` to the least-significant word and propagates carry across
* subsequent 16-bit words. The result is truncated to 64 bits and returned
* as a 4-element array of 16-bit words (little-endian).
*
* @param {Array<number>} a - Addend as 4 × 16-bit words (little-endian)
* @param {number} n - Value to add (integer carry)
* @returns {Array<number>} Sum as 4 × 16-bit words (little-endian)
*/
function add(a, n) {
var r = [0x0000, 0x0000, 0x0000, 0x0000],
k = n;
for (var i = 0; i < 4; i++) {
var t = a[i] + k;
r[i] = t & 0xffff;
k = t >>> 16;
}
return r;
}
/**
* Shift a 64-bit value (4 × 16-bit words, little-endian) right by `n` bits.
*
* The input array is treated as little-endian 16-bit words. Bits shifted out
* on the right are discarded; the returned array contains the lower 64-bit
* result after the logical right shift.
*
* @param {Array<number>} a - Source value as 4 × 16-bit words (little-endian)
* @param {number} n - Number of bits to shift right (non-negative integer)
* @returns {Array<number>} Shifted value as 4 × 16-bit words (little-endian)
*/
function shr(a, n) {
var r = [a[0], a[1], a[2], a[3], 0x0000],
i = 4,
k = 0;
for (; n > 16; n -= 16, i--)
for (var j = 0; j < 4; j++)
r[j] = r[j+1];
for (; i > 0; i--) {
var s = r[i-1];
r[i-1] = (s >>> n) | k;
k = ((s & ((1 << n) - 1)) << (16 - n));
}
r.length = 4;
return r;
}
return L.Class.extend({
/**
* Seed the PRNG state.
*
* The seed is treated as a 32-bit integer; the lower 16 bits are stored
* in `s[0]`, the upper 16 bits in `s[1]`. `s[2]` and `s[3]` are zeroed.
*
* @param {number} n - Seed value (32-bit integer)
* @returns {void}
*/
seed: function(n) {
n = (n - 1)|0;
s[0] = n & 0xffff;
s[1] = n >>> 16;
s[2] = 0;
s[3] = 0;
},
/**
* Produce the next PRNG 32-bit integer.
*
* Advances the internal state and returns a 32-bit pseudo-random integer
* derived from the current state.
*
* @returns {number} 32-bit pseudo-random integer (JS number)
*/
int: function() {
s = mul(s, [0x7f2d, 0x4c95, 0xf42d, 0x5851]);
s = add(s, 1);
var r = shr(s, 33);
return (r[1] << 16) | r[0];
},
/**
* Return a pseudo-random value.
*
* Overloads:
* - get() -> number in [0, 1]
* - get(upper) -> integer in [1, upper]
* - get(lower, upper) -> integer in [lower, upper]
*
* @param {number} [lower=0] - Lower bound (when two args supplied)
* @param {number} [upper=0] - Upper bound (when one or two args supplied)
* @returns {number} Random value (float in [0,1] or integer in requested range)
*/
get: function() {
var r = (this.int() % 0x7fffffff) / 0x7fffffff, l, u;
switch (arguments.length) {
case 0:
return r;
case 1:
l = 1;
u = arguments[0]|0;
break;
case 2:
l = arguments[0]|0;
u = arguments[1]|0;
break;
}
return Math.floor(r * (u - l + 1)) + l;
},
/**
* Derive a deterministic hex color from an input string.
*
* The color is produced by seeding the PRNG from a string-derived
* hash and producing RGB components. Returns a `#rrggbb` hex string.
*
* @param {string} string - Input string used to derive the color
* @returns {string} Hex color string in `#rrggbb` format
*/
derive_color: function(string) {
this.seed(parseInt(sfh(string), 16));
var r = this.get(128),
g = this.get(128),
min = 0,
max = 128;
if ((r + g) < 128)
min = 128 - r - g;
else
max = 255 - r - g;
var b = min + Math.floor(this.get() * (max - min));
return '#%02x%02x%02x'.format(0xff - r, 0xff - g, 0xff - b);
}
});
@@ -0,0 +1,295 @@
'use strict';
'require poll';
'require rpc';
'require uci';
'require fs';
'require ui';
'require view';
/* Note that any view implementing this log reader requires the log read
acl permission */
const callLogRead = rpc.declare({
object: 'log',
method: 'read',
params: [ 'lines', 'stream', 'oneshot' ],
expect: { log: [] }
});
var CBILogreadBox = function(logtag, name) {
return L.view.extend({
logFacilityFilter: 'any',
invertLogFacilitySearch: false,
logSeverityFilter: 'any',
invertLogSeveritySearch: false,
logTextFilter: '',
invertLogTextSearch: false,
logTagFilter: logtag ? logtag : '',
logName: name ? name : _('System Log'),
fetchMaxRows: 1000,
facilities: [
['any', 'any', _('Any')],
['0', 'kern', _('Kernel')],
['1', 'user', _('User')],
['2', 'mail', _('Mail')],
['3', 'daemon', _('Daemon')],
['4', 'auth', _('Auth')],
['5', 'syslog', _('Syslog')],
['6', 'lpr', _('LPR')],
['7', 'news', _('News')],
['8', 'uucp', _('UUCP')],
['9', 'cron', _('Cron')],
['10', 'authpriv', _('Auth Priv')],
['11', 'ftp', _('FTP')],
['12', 'ntp', _('NTP')],
['13', 'security', _('Log audit')],
['14', 'console', _('Log alert')],
['15', 'cron', _('Scheduling daemon')],
['16', 'local0', _('Local 0')],
['17', 'local1', _('Local 1')],
['18', 'local2', _('Local 2')],
['19', 'local3', _('Local 3')],
['20', 'local4', _('Local 4')],
['21', 'local5', _('Local 5')],
['22', 'local6', _('Local 6')],
['23', 'local7', _('Local 7')]
],
severity: [
['any','any', _('Any')],
['0', 'emerg', _('Emergency')],
['1', 'alert', _('Alert')],
['2', 'crit', _('Critical')],
['3', 'err', _('Error')],
['4', 'warn', _('Warning')],
['5', 'notice', _('Notice')],
['6', 'info', _('Info')],
['7', 'debug', _('Debug')]
],
async retrieveLog() {
try {
const tz = uci.get('system', '@system[0]', 'zonename')?.replaceAll(' ', '_');
const ts = uci.get('system', '@system[0]', 'clock_timestyle') || 0;
const hc = uci.get('system', '@system[0]', 'clock_hourcycle') || 0;
let loglines = await callLogRead(this.fetchMaxRows, false, true)
.then((logEntries) => {
const dateObj = new Intl.DateTimeFormat(undefined, {
dateStyle: 'medium',
timeStyle: (ts == 0) ? 'long' : 'full',
hourCycle: (hc == 0) ? undefined : hc,
timeZone: tz
});
return logEntries.map(entry => {
const time = new Date(entry?.time);
const datestr = dateObj.format(time);
/* remember to add one since the 'any' entry occupies 1st position i.e. [0] */
const facility = this.facilities[Math.floor(entry?.priority / 8) + 1][1] ?? 'unknown';
const severity = this.severity[(entry?.priority % 8) + 1][1] ?? 'unknown';
return `[${datestr}] ${facility}.${severity}: ${entry?.msg}`;
});
})
.catch(function (){
return Promise.all([
L.resolveDefault(fs.stat('/usr/libexec/syslog-wrapper'), null),
]).then((stat) => {
const logger = stat[0]?.path;
return fs.exec_direct(logger)
.then(logdata => {
return logdata.trim().split(/\n/);
});
});
});
loglines = loglines.filter(line => {
const sevMatch = this.logSeverityFilter === 'any' || line.includes(`.${this.logSeverityFilter}`);
const facMatch = this.logFacilityFilter === 'any' || line.includes(`${this.logFacilityFilter}.`);
return (this.invertLogSeveritySearch != sevMatch)
&& (this.invertLogFacilitySearch != facMatch);
});
loglines = loglines.filter(line => {
return line.toLowerCase().includes(this.logTagFilter?.toLowerCase());
});
loglines = loglines.filter(line => {
const match = line.includes(this.logTextFilter);
return this.invertLogTextSearch ? !match : match;
});
return {
value: loglines?.join('\n'),
rows: loglines?.length + 1
};
}
catch (err) {
ui.addNotification(null, E('p', {}, _('Unable to load log data: ' + err.message)));
return {
value: '',
rows: 0
};
}
},
async pollLog() {
const element = document.getElementById('syslog');
if (element) {
const log = await this.retrieveLog();
element.value = log?.value;
element.rows = log?.rows;
}
},
async load() {
poll.add(this.pollLog.bind(this));
return Promise.all([
uci.load('system'),
]).then(() => this.retrieveLog());
},
render(loglines) {
const scrollDownButton = E('button', {
'id': 'scrollDownButton',
'class': 'cbi-button cbi-button-neutral'
}, _('Scroll to tail', 'scroll to bottom (the tail) of the log file')
);
scrollDownButton.addEventListener('click', () => {
scrollUpButton.scrollIntoView();
scrollDownButton.blur();
});
const scrollUpButton = E('button', {
'id' : 'scrollUpButton',
'class': 'cbi-button cbi-button-neutral'
}, _('Scroll to head', 'scroll to top (the head) of the log file')
);
scrollUpButton.addEventListener('click', () => {
scrollDownButton.scrollIntoView();
scrollUpButton.blur();
});
const self = this;
// Create facility invert checkbox
const facilityInvert = E('input', {
'id': 'invertLogFacilitySearch',
'type': 'checkbox',
'class': 'cbi-input-checkbox',
});
// Create facility select-dropdown from facilities map
const facilitySelect = E('select', {
'id': 'logFacilitySelect',
'class': 'cbi-input-select',
'style': 'margin-bottom:10px',
},
this.facilities.map(([ , val, label]) =>
(val == 'any') ? E('option', { value: val, selected: '' }, label) : E('option', { value: val }, label)
));
// Create severity invert checkbox
const severityInvert = E('input', {
'id': 'invertLogSeveritySearch',
'type': 'checkbox',
'class': 'cbi-input-checkbox',
});
// Create severity select-dropdown from facilities map
const severitySelect = E('select', {
'id': 'logSeveritySelect',
'class': 'cbi-input-select',
},
this.severity.map(([ , val, label]) =>
(val == 'any') ? E('option', { value: val, selected: '' }, label) : E('option', { value: val }, label)
));
// Create raw text search invert checkbox
const filterTextInvert = E('input', {
'id': 'invertLogTextSearch',
'type': 'checkbox',
'class': 'cbi-input-checkbox',
});
// Create raw text search text input
const filterTextInput = E('input', {
'id': 'logTextFilter',
'class': 'cbi-input-text',
});
// Create max rows input
const filterMaxRows = E('input', {
'id': 'logMaxRows',
'type': 'number',
'class': 'cbi-input',
});
/**
* Update the form when log filter parameters change
*/
function handleLogFilterChange() {
self.logFacilityFilter = facilitySelect.value;
self.invertLogFacilitySearch = facilityInvert.checked;
self.logSeverityFilter = severitySelect.value;
self.invertLogSeveritySearch = severityInvert.checked;
self.logTextFilter = filterTextInput.value;
self.invertLogTextSearch = filterTextInvert.checked;
self.fetchMaxRows = Number.parseInt(filterMaxRows.value);
self.pollLog();
}
facilitySelect.addEventListener('change', handleLogFilterChange);
facilityInvert.addEventListener('change', handleLogFilterChange);
severitySelect.addEventListener('change', handleLogFilterChange);
severityInvert.addEventListener('change', handleLogFilterChange);
filterTextInput.addEventListener('input', handleLogFilterChange);
filterTextInvert.addEventListener('change', handleLogFilterChange);
filterMaxRows.addEventListener('change', handleLogFilterChange);
return E([], [
E('h2', {}, [ this.logName ]),
E('div', { 'id': 'content_syslog' }, [
E('div', { class: 'cbi-section-descr' }, this.logTagFilter ? _('The syslog output, pre-filtered for messages related to: ' + this.logTagFilter) : '') ,
E('div', { 'style': 'margin-bottom:10px' }, [
E('label', { 'for': 'invertLogFacilitySearch', 'style': 'margin-right:5px' }, _('Not')),
facilityInvert,
E('label', { 'for': 'logFacilitySelect', 'style': 'margin: 0 5px' }, _('facility:')),
facilitySelect,
E('label', { 'for': 'invertLogSeveritySearch', 'style': 'margin: 0 5px' }, _('Not')),
severityInvert,
E('label', { 'for': 'logSeveritySelect', 'style': 'margin: 0 5px' }, _('severity:')),
severitySelect,
]),
E('div', { 'style': 'margin-bottom:10px' }, [
E('label', { 'for': 'invertLogTextSearch', 'style': 'margin-right:5px' }, _('Not')),
filterTextInvert,
E('label', { 'for': 'logTextFilter', 'style': 'margin: 0 5px' }, _('including:')),
filterTextInput,
E('label', { 'for': 'logMaxRows', 'style': 'margin: 0 5px' }, _('Max rows:')),
filterMaxRows,
]),
E('div', {'style': 'padding-bottom: 20px'}, [scrollDownButton]),
E('textarea', {
'id': 'syslog',
'style': 'font-size:12px',
'readonly': 'readonly',
'wrap': 'off',
'rows': loglines?.rows,
}, [ loglines?.value ]),
E('div', {'style': 'padding-bottom: 20px'}, [scrollUpButton])
])
]);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});
};
return L.Class.extend({
LogreadBox: CBILogreadBox,
});
@@ -0,0 +1,855 @@
'use strict';
'require ui';
'require form';
'require network';
'require firewall';
'require fs';
'require uci';
/**
* Get users found in `/etc/passwd`.
* @returns {string[]}
*/
function getUsers() {
return fs.lines('/etc/passwd').then(function(lines) {
return lines.map(function(line) { return line.split(/:/)[0] });
});
}
/**
* Get users found in `/etc/group`.
* @returns {string[]}
*/
function getGroups() {
return fs.lines('/etc/group').then(function(lines) {
return lines.map(function(line) { return line.split(/:/)[0] });
});
}
/**
* Get bridge devices or Layer 3 devices of a network object.
* @param {object} network
* @returns {string[]}
*/
function getDevices(network) {
if (network.isBridge()) {
var devices = network.getDevices();
return devices ? devices : [];
} else {
return L.toArray(network.getL3Device());
}
}
var CBIZoneSelect = form.ListValue.extend({
__name__: 'CBI.ZoneSelect',
load(section_id) {
return Promise.all([ firewall.getZones(), network.getNetworks() ]).then(L.bind(function(zn) {
this.zones = zn[0];
this.networks = zn[1];
return this.super('load', section_id);
}, this));
},
filter(section_id, value) {
return true;
},
lookupZone(name) {
return this.zones.filter(function(zone) { return zone.getName() == name })[0];
},
lookupNetwork(name) {
return this.networks.filter(function(network) { return network.getName() == name })[0];
},
renderWidget(section_id, option_index, cfgvalue) {
const values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
let isOutputOnly = false;
const choices = {};
let datatype_str = 'ucifw4zonename';
if (!L.hasSystemFeature('firewall4'))
datatype_str = `and(${datatype_str},maxlength(11))`;
if (this.allowany && this.nocreate)
datatype_str = `or(${datatype_str},"*")`;
if (this.multiple)
datatype_str = `list(${datatype_str})`;
if (this.option == 'dest') {
for (let c of this.section.children) {
const opt = c;
if (opt.option == 'src') {
const val = opt.cfgvalue(section_id) || opt.default;
isOutputOnly = (val == null || val == '');
break;
}
}
this.title = isOutputOnly ? _('Output zone') : _('Destination zone');
}
if (this.allowlocal) {
choices[''] = E('span', {
'class': 'zonebadge',
'style': firewall.getZoneColorStyle(null)
}, [
E('strong', _('Device')),
(this.allowany || this.allowlocal)
? E('span', ' (%s)'.format(this.option != 'dest' ? _('output') : _('input'))) : ''
]);
}
else if (!this.multiple && (this.rmempty || this.optional)) {
choices[''] = E('span', {
'class': 'zonebadge',
'style': firewall.getZoneColorStyle(null)
}, E('em', _('unspecified')));
}
if (this.allowany) {
choices['*'] = E('span', {
'class': 'zonebadge',
'style': firewall.getZoneColorStyle(null)
}, [
E('strong', _('Any zone')),
(this.allowany && this.allowlocal && !isOutputOnly) ? E('span', ' (%s)'.format(_('forward'))) : ''
]);
}
for (let zone of this.zones) {
const name = zone.getName();
const networks = zone.getNetworks();
const ifaces = [];
if (!this.filter(section_id, name))
continue;
for (let n of networks) {
const network = this.lookupNetwork(n);
if (!network)
continue;
const span = E('span', {
'class': 'ifacebadge' + (network.isUp() ? ' ifacebadge-active' : '')
}, network.getName() + ': ');
const devices = getDevices(network);
for (let d of devices) {
span.appendChild(E('img', {
'title': d.getI18n(),
'src': L.resource('icons/%s%s.svg'.format(d.getType(), d.isUp() ? '' : '_disabled'))
}));
}
if (!devices.length)
span.appendChild(E('em', _('(empty)')));
ifaces.push(span);
}
if (!ifaces.length)
ifaces.push(E('em', _('(empty)')));
choices[name] = E('span', {
'class': 'zonebadge',
'style': firewall.getZoneColorStyle(zone)
}, [ E('strong', name) ].concat(ifaces));
}
const widget = new ui.Dropdown(values, choices, {
id: this.cbid(section_id),
sort: true,
multiple: this.multiple,
optional: this.optional || this.rmempty,
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
select_placeholder: E('em', _('unspecified')),
display_items: this.display_size || this.size || 3,
dropdown_items: this.dropdown_size || this.size || 5,
validate: L.bind(this.validate, this, section_id),
datatype: datatype_str,
create: !this.nocreate,
create_markup: '' +
'<li data-value="{{value}}">' +
'<span class="zonebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">' +
'<strong>{{value}}:</strong> <em>('+_('create')+')</em>' +
'</span>' +
'</li>'
});
const elem = widget.render();
if (this.option == 'src') {
elem.addEventListener('cbi-dropdown-change', L.bind(function(ev) {
const opt = this.map.lookupOption('dest', section_id);
const val = ev.detail.instance.getValue();
if (opt == null)
return;
const cbid = opt[0].cbid(section_id);
const label = document.querySelector('label[for="widget.%s"]'.format(cbid));
const node = document.getElementById(cbid);
L.dom.content(label, val == '' ? _('Output zone') : _('Destination zone'));
if (val == '') {
if (L.dom.callClassMethod(node, 'getValue') == '')
L.dom.callClassMethod(node, 'setValue', '*');
const emptyval = node.querySelector('[data-value=""]');
const anyval = node.querySelector('[data-value="*"]');
L.dom.content(anyval.querySelector('span'), E('strong', _('Any zone')));
if (emptyval != null)
emptyval.parentNode.removeChild(emptyval);
}
else {
const anyval = node.querySelector('[data-value="*"]') || '';
let emptyval = node.querySelector('[data-value=""]') || '';
if (emptyval == null && anyval) {
emptyval = anyval.cloneNode(true);
emptyval.removeAttribute('display');
emptyval.removeAttribute('selected');
emptyval.setAttribute('data-value', '');
}
if (opt[0]?.allowlocal && emptyval)
L.dom.content(emptyval.querySelector('span'), [
E('strong', _('Device')), E('span', ' (%s)'.format(_('input')))
]);
if (opt[0]?.allowany && anyval && emptyval) {
L.dom.content(anyval.querySelector('span'), [
E('strong', _('Any zone')), E('span', ' (%s)'.format(_('forward')))
]);
anyval.parentNode.insertBefore(emptyval, anyval);
}
}
}, this));
}
else if (isOutputOnly) {
const emptyval = elem.querySelector('[data-value=""]');
emptyval.parentNode.removeChild(emptyval);
}
return elem;
},
});
var CBIZoneForwards = form.DummyValue.extend({
__name__: 'CBI.ZoneForwards',
load(section_id) {
return Promise.all([
firewall.getDefaults(),
firewall.getZones(),
network.getNetworks(),
network.getDevices()
]).then(L.bind(function(dznd) {
this.defaults = dznd[0];
this.zones = dznd[1];
this.networks = dznd[2];
this.devices = dznd[3];
return this.super('load', section_id);
}, this));
},
renderZone(zone) {
const name = zone.getName();
const networks = zone.getNetworks();
const devices = zone.getDevices();
const subnets = zone.getSubnets();
const ifaces = [];
for (let n of networks) {
const network = this.networks.filter(function(net) { return net.getName() == n })[0];
if (!network)
continue;
const span = E('span', {
'class': 'ifacebadge' + (network.isUp() ? ' ifacebadge-active' : '')
}, network.getName() + ': ');
const subdevs = getDevices(network);
for (let s of subdevs) {
span.appendChild(E('img', {
'title': s.getI18n(),
'src': L.resource('icons/%s%s.svg'.format(s.getType(), s.isUp() ? '' : '_disabled'))
}));
}
if (!subdevs.length)
span.appendChild(E('em', _('(empty)')));
ifaces.push(span);
}
for (let d of devices) {
const device = this.devices.filter(function(dev) { return dev.getName() == d })[0];
const title = device ? device.getI18n() : _('Absent Interface');
const type = device ? device.getType() : 'ethernet';
const up = device ? device.isUp() : false;
ifaces.push(E('span', { 'class': 'ifacebadge' }, [
E('img', {
'title': title,
'src': L.resource('icons/%s%s.svg'.format(type, up ? '' : '_disabled'))
}),
device ? device.getName() : d
]));
}
if (subnets.length > 0)
ifaces.push(E('span', { 'class': 'ifacebadge' }, [ '{ %s }'.format(subnets.join('; ')) ]));
if (!ifaces.length)
ifaces.push(E('span', { 'class': 'ifacebadge' }, E('em', _('(empty)'))));
return E('label', {
'class': 'zonebadge cbi-tooltip-container',
'style': firewall.getZoneColorStyle(zone)
}, [
E('strong', name),
E('div', { 'class': 'cbi-tooltip' }, ifaces)
]);
},
renderWidget(section_id, option_index, cfgvalue) {
const value = (cfgvalue != null) ? cfgvalue : this.default;
const zone = this.zones.filter(function(z) { return z.getName() == value })[0];
if (!zone)
return E([]);
const forwards = zone.getForwardingsBy('src');
const dzones = [];
for (var i = 0; i < forwards.length; i++) {
const dzone = forwards[i].getDestinationZone();
if (!dzone)
continue;
dzones.push(this.renderZone(dzone));
}
if (!dzones.length)
dzones.push(E('label', { 'class': 'zonebadge zonebadge-empty' },
E('strong', this.defaults.getForward())));
else
dzones.push(E('label', { 'class': 'zonebadge zonebadge-empty' },
E('strong', '%s %s'.format(this.defaults.getForward(), ('all others')))));
return E('div', { 'class': 'zone-forwards' }, [
E('div', { 'class': 'zone-src' }, this.renderZone(zone)),
E('span', '⇒'),
E('div', { 'class': 'zone-dest' }, dzones)
]);
},
});
const CBIIPSelect = form.ListValue.extend({
__name__: 'CBI.IPSelect',
load(section_id) {
return network.getDevices().then(L.bind(function(devices) {
this.devices = devices;
return this.super('load', section_id);
}, this));
},
filter(section_id, value) {
return true;
},
renderIfaceBadge(device, ip) {
return E('div', {}, [
ip,
' ',
E('span', { 'class': 'ifacebadge', }, [ device.getName(),
E('img', {
'title': device.getI18n(),
'src': L.resource('icons/%s%s.svg'.format(device.getType(), device.isUp() ? '' : '_disabled'))
})
]),
]);
},
renderWidget(section_id, option_index, cfgvalue) {
let values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
const choices = {};
const checked = {};
for (const val of values)
checked[val] = true;
values = [];
if (!this.multiple && (this.rmempty || this.optional))
choices[''] = E('em', _('unspecified'));
for (const device of (this.devices || [])) {
const name = device.getName();
if (name == this.exclude || !this.filter(section_id, name))
continue;
if (name == 'loopback' && !this.loopback)
continue;
if (this.novirtual && device.isVirtual())
continue;
for (const ip of [...device.getIPAddrs(), ...device.getIP6Addrs()]) {
const iponly = ip.split('/')?.[0]
if (checked[iponly])
values.push(iponly);
choices[iponly] = this.renderIfaceBadge(device, iponly);
}
}
const widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
id: this.cbid(section_id),
sort: true,
multiple: this.multiple,
optional: this.optional || this.rmempty,
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
select_placeholder: E('em', _('unspecified')),
display_items: this.display_size || this.size || 2,
dropdown_items: this.dropdown_size || this.size || 5,
datatype: this.multiple ? 'list(ipaddr)' : 'ipaddr',
validate: L.bind(this.validate, this, section_id),
create: false,
});
return widget.render();
},
textvalue(section_id) {
const cfgvalue = this.cfgvalue(section_id);
const values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
const rv = E([]);
for (const device of (this.devices || [])) {
for (const ip of [...device.getIPAddrs(), ...device.getIP6Addrs()]) {
const iponly = ip.split('/')[0];
if (values.indexOf(iponly) === -1)
continue;
if (rv.childNodes.length)
rv.appendChild(document.createTextNode(' '));
rv.appendChild(this.renderIfaceBadge(device, iponly));
}
}
if (!rv.firstChild)
rv.appendChild(E('em', _('unspecified')));
return rv;
},
});
var CBINetworkSelect = form.ListValue.extend({
__name__: 'CBI.NetworkSelect',
load(section_id) {
return network.getNetworks().then(L.bind(function(networks) {
this.networks = networks;
return this.super('load', section_id);
}, this));
},
filter(section_id, value) {
return true;
},
renderIfaceBadge(network) {
const span = E('span', { 'class': 'ifacebadge' }, network.getName() + ': ');
const devices = getDevices(network);
for (let d of devices) {
span.appendChild(E('img', {
'title': d.getI18n(),
'src': L.resource('icons/%s%s.svg'.format(d.getType(), d.isUp() ? '' : '_disabled'))
}));
}
if (!devices.length) {
span.appendChild(E('em', { 'class': 'hide-close' }, _('(no interfaces attached)')));
span.appendChild(E('em', { 'class': 'hide-open' }, '-'));
}
return span;
},
renderWidget(section_id, option_index, cfgvalue) {
let values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
const choices = {};
const checked = {};
for (var i = 0; i < values.length; i++)
checked[values[i]] = true;
values = [];
if (!this.multiple && (this.rmempty || this.optional))
choices[''] = E('em', _('unspecified'));
for (let network of this.networks) {
const name = network.getName();
if (name == this.exclude || !this.filter(section_id, name))
continue;
if (name == 'loopback' && !this.loopback)
continue;
if (this.novirtual && network.isVirtual())
continue;
if (checked[name])
values.push(name);
choices[name] = this.renderIfaceBadge(network);
}
const widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
id: this.cbid(section_id),
sort: true,
multiple: this.multiple,
optional: this.optional || this.rmempty,
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
select_placeholder: E('em', _('unspecified')),
display_items: this.display_size || this.size || 3,
dropdown_items: this.dropdown_size || this.size || 5,
datatype: this.multiple ? 'list(uciname)' : 'uciname',
validate: L.bind(this.validate, this, section_id),
create: !this.nocreate,
create_markup: '' +
'<li data-value="{{value}}">' +
'<span class="ifacebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">' +
'{{value}}: <em>('+_('create')+')</em>' +
'</span>' +
'</li>'
});
return widget.render();
},
textvalue(section_id) {
const cfgvalue = this.cfgvalue(section_id);
const values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
const rv = E([]);
for (let network of this.networks) {
const name = network.getName();
if (values.indexOf(name) == -1)
continue;
if (rv.length)
L.dom.append(rv, ' ');
L.dom.append(rv, this.renderIfaceBadge(network));
}
if (!rv.firstChild)
rv.appendChild(E('em', _('unspecified')));
return rv;
},
});
var CBIDeviceSelect = form.ListValue.extend({
__name__: 'CBI.DeviceSelect',
load(section_id) {
return Promise.all([
network.getDevices(),
this.noaliases ? null : network.getNetworks()
]).then(L.bind(function(data) {
this.devices = data[0];
this.networks = data[1];
return this.super('load', section_id);
}, this));
},
filter(section_id, value) {
return true;
},
renderWidget(section_id, option_index, cfgvalue) {
var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
choices = {},
checked = {},
order = [];
for (var i = 0; i < values.length; i++)
checked[values[i]] = true;
values = [];
if (!this.multiple && (this.rmempty || this.optional))
choices[''] = E('em', _('unspecified'));
for (let device of this.devices) {
const name = device.getName();
const type = device.getType();
if (name == 'lo' || name == this.exclude || !this.filter(section_id, name))
continue;
if (this.noaliases && type == 'alias')
continue;
if (this.nobridges && type == 'bridge')
continue;
if (this.noinactive && device.isUp() == false)
continue;
const item = E([
E('img', {
'title': device.getI18n(),
'src': L.resource('icons/%s%s.svg'.format(type, device.isUp() ? '' : '_disabled'))
}),
E('span', { 'class': 'hide-open' }, [ name ]),
E('span', { 'class': 'hide-close'}, [ device.getI18n() ])
]);
const networks = device.getNetworks();
if (networks.length > 0)
L.dom.append(item.lastChild, [ ' (', networks.map(function(n) { return n.getName() }).join(', '), ')' ]);
if (checked[name])
values.push(name);
choices[name] = item;
order.push(name);
}
if (this.networks != null) {
for (let net of this.networks) {
const device = network.instantiateDevice('@%s'.format(net.getName()), net);
const name = device.getName();
if (name == '@loopback' || name == this.exclude || !this.filter(section_id, name))
continue;
if (this.noinactive && net.isUp() == false)
continue;
const item = E([
E('img', {
'title': device.getI18n(),
'src': L.resource('icons/alias%s.svg'.format(device.isUp() ? '' : '_disabled'))
}),
E('span', { 'class': 'hide-open' }, [ name ]),
E('span', { 'class': 'hide-close'}, [ device.getI18n() ])
]);
if (checked[name])
values.push(name);
choices[name] = item;
order.push(name);
}
}
if (this.includeips) {
this.devices.forEach(net_dev => {
['getIPAddrs', 'getIP6Addrs'].forEach(fn => {
net_dev[fn]().forEach(addr => {
const name = addr.split('/')[0];
if (checked[name]) values.push(name);
choices[name] = E([], [name, ' (', E('strong', net_dev.getName()), ')']);
order.push(name);
});
});
});
}
if (!this.nocreate) {
const keys = Object.keys(checked).sort(L.naturalCompare);
for (let k of keys) {
if (choices.hasOwnProperty(k))
continue;
choices[k] = E([
E('img', {
'title': _('Absent Interface'),
'src': L.resource('icons/ethernet_disabled.svg')
}),
E('span', { 'class': 'hide-open' }, [ k ]),
E('span', { 'class': 'hide-close'}, [ '%s: "%h"'.format(_('Absent Interface'), k) ])
]);
values.push(k);
order.push(k);
}
}
const widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
id: this.cbid(section_id),
sort: order,
multiple: this.multiple,
optional: this.optional || this.rmempty,
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
select_placeholder: E('em', _('unspecified')),
display_items: this.display_size || this.size || 3,
dropdown_items: this.dropdown_size || this.size || 5,
validate: L.bind(this.validate, this, section_id),
create: !this.nocreate,
create_markup: '' +
'<li data-value="{{value}}">' +
'<img title="'+_('Custom Interface')+': &quot;{{value}}&quot;" src="'+L.resource('icons/ethernet_disabled.svg')+'" />' +
'<span class="hide-open">{{value}}</span>' +
'<span class="hide-close">'+_('Custom Interface')+': "{{value}}"</span>' +
'</li>'
});
return widget.render();
},
});
var CBIUserSelect = form.ListValue.extend({
__name__: 'CBI.UserSelect',
load(section_id) {
return getUsers().then(L.bind(function(users) {
delete this.keylist;
delete this.vallist;
for (var i = 0; i < users.length; i++) {
this.value(users[i]);
}
return this.super('load', section_id);
}, this));
},
filter(section_id, value) {
return true;
},
});
var CBIGroupSelect = form.ListValue.extend({
__name__: 'CBI.GroupSelect',
load(section_id) {
return getGroups().then(L.bind(function(groups) {
for (var i = 0; i < groups.length; i++) {
this.value(groups[i]);
}
return this.super('load', section_id);
}, this));
},
filter(section_id, value) {
return true;
},
});
var CBIWifidogxGroupSelect = form.ListValue.extend({
__name__: 'CBI.WifidogxGroupSelect',
// group_type: 1: Domain Group, 2: MAC Group
// add a new property to store the group type
group_type: '1',
load: function(section_id) {
this.sappList = [];
var sections = uci.sections('wifidogx', 'group');
for (var i = 0; i < sections.length; i++) {
if (sections[i]['g_type'] == this.group_type)
this.sappList.push(sections[i]['.name']);
}
return this.super('load', section_id);
},
setGroupType: function(group_type) {
if (group_type == 'mac') {
this.group_type = '2';
} else if (group_type == 'wildcard') {
this.group_type = '3';
}
},
filter: function(section_id, value) {
return true;
},
renderWidget: function(section_id, option_index, cfgvalue) {
var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
choices = {},
checked = {};
for (var i = 0; i < values.length; i++)
checked[values[i]] = true;
values = [];
if (!this.multiple && (this.rmempty || this.optional))
choices[''] = E('em', _('unspecified'));
for (var i = 0; i < this.sappList.length; i++) {
var name = this.sappList[i];
if (checked[name])
values.push(name);
choices[name] = E('span', { 'class': 'ifacebadge' }, name);
}
var widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
id: this.cbid(section_id),
sort: true,
multiple: this.multiple,
optional: this.optional || this.rmempty,
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
select_placeholder: E('em', _('unspecified')),
display_items: this.display_size || this.size || 3,
dropdown_items: this.dropdown_size || this.size || 5,
validate: L.bind(this.validate, this, section_id),
create: !this.nocreate,
create_markup: '' +
'<li data-value="{{value}}">' +
'<span class="ifacebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">' +
'{{value}}: <em>('+_('create')+')</em>' +
'</span>' +
'</li>'
});
return widget.render();
}
});
return L.Class.extend({
ZoneSelect: CBIZoneSelect,
ZoneForwards: CBIZoneForwards,
IPSelect: CBIIPSelect,
NetworkSelect: CBINetworkSelect,
DeviceSelect: CBIDeviceSelect,
UserSelect: CBIUserSelect,
GroupSelect: CBIGroupSelect,
WifidogxGroupSelect: CBIWifidogxGroupSelect,
});
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1 @@
/* replaced by luci.js */
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+1
View File
@@ -0,0 +1 @@
zh_Hans
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+31
View File
@@ -0,0 +1,31 @@
config core main
option lang auto
option mediaurlbase /luci-static/bootstrap
option resourcebase /luci-static/resources
option ubuspath /ubus/
config extern flash_keep
option uci "/etc/config/"
option dropbear "/etc/dropbear/"
option openvpn "/etc/openvpn/"
option passwd "/etc/passwd"
option opkg "/etc/opkg.conf"
option firewall "/etc/firewall.user"
option uploads "/lib/uci/upload/"
config internal languages
config internal sauth
option sessionpath "/tmp/luci-sessions"
option sessiontime 3600
config internal ccache
option enable 1
config internal themes
config internal apply
option rollback 90
option holdoff 4
option timeout 5
option display 1.5
Loaded 100 of 206 files, more files were not shown because too many files have changed in this diff. Show more