Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1512d2999b | ||
|
|
27e85c9bfd | ||
|
|
8f8fcb2ff0 | ||
|
|
1483f9063a | ||
|
|
0d2c12a034 | ||
|
|
888af9bf12 | ||
|
|
2e13110c3b | ||
|
|
950c4d4a9a | ||
|
|
bdf5e45c5b | ||
|
|
e4ca0558f7 | ||
|
|
5322a9105e | ||
|
|
3b0705edc1 | ||
|
|
2b799a524f | ||
|
|
783d27732d | ||
|
|
efb2768fa8 | ||
|
|
a8fc0b81ab | ||
|
|
66e6179332 | ||
|
|
6ad3a8c294 | ||
|
|
03db91c873 | ||
|
|
007c9bccd5 | ||
|
|
e8e90275a2 | ||
|
|
8e4590699b | ||
|
|
51ae186243 | ||
|
|
bbec425c51 | ||
|
|
e0aae47efc | ||
|
|
a31fb176c4 | ||
|
|
f19d10966d | ||
|
|
9ac276d443 | ||
|
|
c58eaf6ff5 | ||
|
|
f24a70b9d7 | ||
|
|
23a620274d | ||
|
|
e903200d66 | ||
|
|
57c74b0c9e | ||
|
|
caf5d5c34d | ||
|
|
ed64656a06 | ||
|
|
bbde4cb1e9 | ||
|
|
678cf43077 | ||
|
|
4bbd54dd06 | ||
|
|
eea08f529e | ||
|
|
d1ad6b0f43 | ||
|
|
570e14c1fa | ||
|
|
7b9da31db0 | ||
|
|
6552959ef3 | ||
|
|
14ee075853 | ||
|
|
c1955d7ca5 | ||
|
|
41ec81bed3 | ||
|
|
1557673db2 | ||
|
|
565f8c7ce0 | ||
|
|
163c46f4de | ||
|
|
a46ed4ea1a | ||
|
|
4d9372768f | ||
|
|
eed03f641d | ||
|
|
25effc0e2f | ||
|
|
dcec9598c1 | ||
|
|
f8527cc297 | ||
|
|
a4fc285be6 | ||
|
|
195594b8c4 | ||
|
|
405e95bff8 | ||
|
|
72b621e277 | ||
|
|
c089ac7834 | ||
|
|
ae648fbe66 | ||
|
|
68a1d3719f | ||
|
|
9cd86ccaa3 | ||
|
|
956a5ace26 | ||
|
|
15fe753a0f | ||
|
|
0d185f628b | ||
|
|
83977b55bf | ||
|
|
49decdfed1 | ||
|
|
227e15fe48 | ||
|
|
73b3d16ff6 | ||
|
|
c04256535d | ||
|
|
3c8ebcf710 | ||
|
|
9a19d2f4bf | ||
|
|
d3c5e4a02a | ||
|
|
a03cda0ef0 | ||
|
|
d25e7871ba | ||
|
|
fd6c3532d9 | ||
|
|
89745f3c3a | ||
|
|
266230f5f0 | ||
|
|
4c17623dff | ||
|
|
34e30d9873 | ||
|
|
1e190878dd | ||
|
|
874c122a62 | ||
|
|
fa984cfae6 | ||
|
|
a544f72db0 | ||
|
|
eea993c6cc | ||
|
|
a4a3734c30 | ||
|
|
a10e39b6f2 | ||
|
|
360d8d008d | ||
|
|
830938eac9 | ||
|
|
1a764ed104 | ||
|
|
b0c543b44b | ||
|
|
f85c0a87f9 | ||
|
|
67d7c5ea0f | ||
|
|
8576f81404 | ||
|
|
fa0ee2bf57 | ||
|
|
e9776b0e69 | ||
|
|
e01cc118dc | ||
|
|
784c40b153 | ||
|
|
6068a2ba17 | ||
|
|
ced526824f | ||
|
|
7d2a73bf2e | ||
|
|
51e2f664cd | ||
|
|
937b1ea90f | ||
|
|
b95d1945bf | ||
|
|
e8446cd52f | ||
|
|
6098f0fb1a | ||
|
|
fc89a76cc2 | ||
|
|
f290947b2c | ||
|
|
b3adc6b782 | ||
|
|
705a957606 | ||
|
|
a307ad7d19 | ||
|
|
ad95e00723 | ||
|
|
31330168f3 | ||
|
|
d9e8f8a7c1 | ||
|
|
08f15ebdc5 | ||
|
|
adb05818b9 | ||
|
|
4e73e8185e | ||
|
|
0fe01064a4 | ||
|
|
510567eaec | ||
|
|
503037c7e2 | ||
|
|
d75d5438a3 | ||
|
|
91f11dad76 | ||
|
|
fdc5abacfc | ||
|
|
388938e02b | ||
|
|
f912794068 | ||
|
|
6331d7d45b | ||
|
|
25f878a38a | ||
|
|
a8b9b2d00d | ||
|
|
dc3868998a | ||
|
|
75d06c8666 | ||
|
|
360252182d | ||
|
|
aa0ccd254c | ||
|
|
f7b2e7db42 | ||
|
|
052c75ef23 | ||
|
|
1f7827cc21 | ||
|
|
c236aee5dc | ||
|
|
fb3ecd1796 | ||
|
|
810f6a0d8a | ||
|
|
eddf37c413 | ||
|
|
8dfc6d4718 | ||
|
|
03446b8f29 | ||
|
|
6ab046be51 | ||
|
|
94708c588c | ||
|
|
144987bcf1 | ||
|
|
7e46b1062e | ||
|
|
71cadcfebe | ||
|
|
d96e711a34 | ||
|
|
5ebf076330 | ||
|
|
4a9f5adb6b | ||
|
|
59fa2d8eab |
@@ -0,0 +1,10 @@
|
||||
.git
|
||||
.github
|
||||
.idea
|
||||
*.sublime-workspace
|
||||
server/serverstatus
|
||||
web/json/stats.json
|
||||
web/json/stats.json~
|
||||
*.bak-*
|
||||
__pycache__
|
||||
*.pyc
|
||||
@@ -0,0 +1,42 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: server/go.mod
|
||||
cache-dependency-path: server/go.sum
|
||||
|
||||
- name: Test Go server
|
||||
working-directory: server
|
||||
run: |
|
||||
test -z "$(gofmt -l .)"
|
||||
go vet ./...
|
||||
go test -race ./...
|
||||
CGO_ENABLED=0 go build -trimpath -o /tmp/serverstatus .
|
||||
|
||||
- name: Check clients, WebUI and shell scripts
|
||||
run: |
|
||||
python3 -m py_compile clients/client-linux.py clients/client-psutil.py
|
||||
python3 -m unittest clients/test_client_args.py
|
||||
sh -n clients/entrypoint.sh
|
||||
bash -n status.sh
|
||||
node --check web/js/app.js
|
||||
|
||||
- name: Validate compose files
|
||||
run: |
|
||||
docker compose -f docker-compose-server.yml config
|
||||
docker compose -f docker-compose-client.yml config
|
||||
|
||||
- name: Build Docker images
|
||||
run: |
|
||||
docker build -f Dockerfile.server -t serverstatus-server:test .
|
||||
docker build -f Dockerfile.client -t serverstatus-client:test .
|
||||
@@ -1,29 +0,0 @@
|
||||
# The Dockerfile for build localhost source, not git repo
|
||||
FROM debian:buster as builder
|
||||
|
||||
MAINTAINER cppla https://cpp.la
|
||||
|
||||
RUN apt-get update -y && apt-get -y install gcc g++ make libcurl4-openssl-dev
|
||||
|
||||
COPY . .
|
||||
|
||||
WORKDIR /server
|
||||
|
||||
RUN make -j
|
||||
RUN pwd && ls -a
|
||||
|
||||
# glibc env run
|
||||
FROM nginx:latest
|
||||
|
||||
RUN mkdir -p /ServerStatus/server/
|
||||
|
||||
COPY --from=builder server /ServerStatus/server/
|
||||
COPY --from=builder web /usr/share/nginx/html/
|
||||
|
||||
# china time
|
||||
ENV TZ=Asia/Shanghai
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
EXPOSE 80 35601
|
||||
|
||||
CMD nohup sh -c '/etc/init.d/nginx start && /ServerStatus/server/sergate --config=/ServerStatus/server/config.json --web-dir=/usr/share/nginx/html'
|
||||
@@ -0,0 +1,28 @@
|
||||
FROM alpine:3.13
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Runtime deps for client-linux.py and client-psutil.py
|
||||
RUN apk add --no-cache python3 py3-psutil iproute2 procps
|
||||
|
||||
COPY clients/client-linux.py /app/client-linux.py
|
||||
COPY clients/client-psutil.py /app/client-psutil.py
|
||||
COPY clients/entrypoint.sh /app/entrypoint.sh
|
||||
|
||||
# Default client and defaults (can be overridden by docker env)
|
||||
ENV SERVER=127.0.0.1 \
|
||||
USER=s01 \
|
||||
PORT=35601 \
|
||||
INTERVAL=1 \
|
||||
PROBEPORT=80 \
|
||||
PROBE_PROTOCOL_PREFER=ipv4 \
|
||||
PING_PACKET_HISTORY_LEN=100 \
|
||||
CU=cu.tz.cloudcpp.com \
|
||||
CT=ct.tz.cloudcpp.com \
|
||||
CM=cm.tz.cloudcpp.com \
|
||||
CLIENT=psutil
|
||||
|
||||
RUN chmod +x /app/entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
CMD []
|
||||
@@ -0,0 +1,42 @@
|
||||
FROM golang:1.25-alpine AS builder
|
||||
|
||||
WORKDIR /src/server
|
||||
|
||||
COPY server/go.mod server/go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
COPY server/*.go ./
|
||||
|
||||
ARG VERSION=2.0.0
|
||||
ARG COMMIT=none
|
||||
ARG BUILD_TIME=unknown
|
||||
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build \
|
||||
-trimpath \
|
||||
-ldflags="-s -w -X main.version=${VERSION} -X main.commit=${COMMIT} -X main.buildTime=${BUILD_TIME}" \
|
||||
-o /out/serverstatus .
|
||||
|
||||
FROM alpine:3.22
|
||||
|
||||
LABEL maintainer="cppla <https://cpp.la>"
|
||||
|
||||
RUN apk add --no-cache ca-certificates tzdata \
|
||||
&& mkdir -p /app/config /app/data /app/web
|
||||
|
||||
COPY --from=builder /out/serverstatus /usr/local/bin/serverstatus
|
||||
COPY server/config.json /app/config/config.json
|
||||
COPY web /app/web/
|
||||
|
||||
ENV TZ=Asia/Shanghai \
|
||||
CONFIG_PATH=/app/config/config.json \
|
||||
STATS_PATH=/app/data/stats.json \
|
||||
WEB_DIR=/app/web \
|
||||
HTTP_ADDR=:80 \
|
||||
AGENT_ADDR=:35601
|
||||
|
||||
EXPOSE 80 35601
|
||||
|
||||
HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
|
||||
CMD wget -q -O /dev/null http://127.0.0.1/api/health || exit 1
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/serverstatus"]
|
||||
@@ -1,181 +1,340 @@
|
||||
# ServerStatus中文版:
|
||||
# ServerStatus 中文版
|
||||
|
||||
* ServerStatus中文版是一个酷炫高逼格的云探针、云监控、服务器云监控、多服务器探针~。
|
||||
* 在线演示:https://tz.cloudcpp.com
|
||||
ServerStatus 是一个轻量的服务器探针和云监控面板,支持多节点在线状态、资源占用、三网延迟、服务监测、SSL 证书检查、Watchdog 告警、HTTP API 和 Web 配置管理。
|
||||
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
在线演示:https://tz.cloudcpp.com
|
||||
|
||||

|
||||
[](https://go.dev/)
|
||||
[](https://github.com/cppla/ServerStatus/actions/workflows/ci.yml)
|
||||
[](LICENSE)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
|
||||
`Watchdog触发式告警,interval只是为了防止频繁收到报警信息造成的骚扰,并不是探测间隔。 同时为了防止海外机器闪断报警,也加入username、name、type等静态字符串参数的计算支持。`
|
||||

|
||||
|
||||
# 目录:
|
||||
|
||||
* clients 客户端文件
|
||||
* server 服务端文件
|
||||
* web 网站文件
|
||||
## 一、服务端
|
||||
|
||||
* server/config.json 探针配置文件
|
||||
* web/json 探针月流量
|
||||
|
||||
# 部署:
|
||||
|
||||
【服务端】:
|
||||
```bash
|
||||
|
||||
`Docker`:
|
||||
|
||||
wget --no-check-certificate -qO ~/serverstatus-config.json https://raw.githubusercontent.com/cppla/ServerStatus/master/server/config.json && mkdir ~/serverstatus-monthtraffic
|
||||
docker run -d --restart=always --name=serverstatus -v ~/serverstatus-config.json:/ServerStatus/server/config.json -v ~/serverstatus-monthtraffic:/usr/share/nginx/html/json -p 80:80 -p 35601:35601 cppla/serverstatus:latest
|
||||
|
||||
`Docker-compose(推荐)`: docker-compose up -d
|
||||
# Docker Compose,本地构建加:--build
|
||||
ADMIN_TOKEN='your-strong-token' docker compose -f docker-compose-server.yml up -d --build
|
||||
```
|
||||
|
||||
【客户端】:
|
||||
```bash
|
||||
wget --no-check-certificate -qO client-linux.py 'https://raw.githubusercontent.com/cppla/ServerStatus/master/clients/client-linux.py' && nohup python3 client-linux.py SERVER={$SERVER} USER={$USER} PASSWORD={$PASSWORD} >/dev/null 2>&1 &
|
||||
# Docker Run
|
||||
wget -qO ~/serverstatus-config.json \
|
||||
--header='Accept: application/vnd.github.raw' \
|
||||
'https://api.github.com/repos/cppla/ServerStatus/contents/server/config.json?ref=master'
|
||||
mkdir -p ~/serverstatus-data
|
||||
|
||||
eg:
|
||||
wget --no-check-certificate -qO client-linux.py 'https://raw.githubusercontent.com/cppla/ServerStatus/master/clients/client-linux.py' && nohup python3 client-linux.py SERVER=45.79.67.132 USER=s04 >/dev/null 2>&1 &
|
||||
docker run -d --restart=always --name=serverstatus-server \
|
||||
-e ADMIN_TOKEN='your-strong-token' \
|
||||
-v ~/serverstatus-config.json:/app/config/config.json \
|
||||
-v ~/serverstatus-data:/app/data \
|
||||
-p 8080:80 -p 35601:35601 \
|
||||
cppla/serverstatus:server
|
||||
```
|
||||
|
||||
# 主题:
|
||||
启动后访问:
|
||||
|
||||
* layui:https://github.com/zeyudada/StatusServerLayui ,预览:https://sslt.8zyw.cn
|
||||
<img src=https://dl.cpp.la/Archive/serverstatus_layui.png width=200 height=100 />
|
||||
- WebUI:http://127.0.0.1:8080/
|
||||
- 健康检查:http://127.0.0.1:8080/api/health
|
||||
- API 描述:http://127.0.0.1:8080/api/schema
|
||||
- OpenAPI 3.1:http://127.0.0.1:8080/api/openapi.json
|
||||
- 客户端上报端口:`35601/tcp`
|
||||
|
||||
* light:https://github.com/orilights/ServerStatus-Theme-Light ,预览:https://tz.cloudcpp.com/index3.html
|
||||
<img src=https://dl.cpp.la/Archive/serverstatus_light.png width=200 height=100 />
|
||||
`ADMIN_TOKEN` 不设置时,监控页面仍可读取,管理 API 返回 `503`,WebUI 的“配置”页不能修改数据。
|
||||
|
||||
## 二、客户端
|
||||
|
||||
# 手动安装教程:
|
||||
|
||||
**【服务端配置】**
|
||||
|
||||
#### 一、生成服务端程序
|
||||
```
|
||||
`Debian/Ubuntu`: apt-get -y install gcc g++ make libcurl4-openssl-dev
|
||||
`Centos/Redhat`: yum -y install gcc gcc-c++ make libcurl-devel
|
||||
|
||||
cd ServerStatus/server && make
|
||||
./sergate
|
||||
```
|
||||
如果没错误提示,OK,ctrl+c关闭;如果有错误提示,检查35601端口是否被占用
|
||||
|
||||
#### 二、修改配置文件
|
||||
```diff
|
||||
! watchdog rule 可以为任何已知字段的表达式
|
||||
! watchdog interval 最小通知间隔
|
||||
! watchdog callback 可自定义为Post方法的URL,告警内容将拼接其后并发起回调
|
||||
|
||||
! watchdog callback Telegram: https://api.telegram.org/bot你自己的密钥/sendMessage?parse_mode=HTML&disable_web_page_preview=true&chat_id=你自己的标识&text=
|
||||
! watchdog callback Server酱: https://sctapi.ftqq.com/你自己的密钥.send?title=ServerStatus&desp=
|
||||
! watchdog callback PushDeer: https://api2.pushdeer.com/message/push?pushkey=你自己的密钥&text=
|
||||
! watchdog callback BasicAuth: https://用户名:密码@你自己的域名/api/push?message=
|
||||
```bash
|
||||
# Docker Compose,本地构建加:--build
|
||||
SERVER=127.0.0.1 USER=s01 PASSWORD=USER_DEFAULT_PASSWORD \
|
||||
docker compose -f docker-compose-client.yml up -d --force-recreate
|
||||
```
|
||||
|
||||
```bash
|
||||
# Docker Run
|
||||
docker run -d --restart=always --name=serverstatus-client \
|
||||
--network=host --pid=host \
|
||||
-e SERVER=127.0.0.1 \
|
||||
-e USER=s01 \
|
||||
-e PASSWORD=USER_DEFAULT_PASSWORD \
|
||||
cppla/serverstatus:client
|
||||
```
|
||||
|
||||
```bash
|
||||
# Shell Run
|
||||
wget -qO client-linux.py --header='Accept: application/vnd.github.raw' \
|
||||
'https://api.github.com/repos/cppla/ServerStatus/contents/clients/client-linux.py?ref=master'
|
||||
nohup python3 client-linux.py SERVER=127.0.0.1 USER=s01 PASSWORD=USER_DEFAULT_PASSWORD >/dev/null 2>&1 &
|
||||
```
|
||||
|
||||
`USER` 是常见的宿主机环境变量名。如果没有显式传递或传递方式错误,Compose 可能会把系统中的 `$USER` 解析成本机用户名,而不是默认的 `s01`。推荐优先级:
|
||||
|
||||
1. 运行命令显式传递 `USER=s01`
|
||||
2. 修改 `docker-compose-client.yml` 中的 `USER` 默认值
|
||||
3. Docker 或系统环境中的 `USER`
|
||||
|
||||
| 变量 | 默认值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `SERVER` | `127.0.0.1` | Go 服务端地址 |
|
||||
| `USER` | `s01` | 客户端用户名,必须匹配服务端配置 |
|
||||
| `PORT` | `35601` | Agent TCP 上报端口 |
|
||||
| `PASSWORD` | `USER_DEFAULT_PASSWORD` | 客户端密码,必须匹配服务端配置 |
|
||||
| `INTERVAL` | `1` | 状态上报间隔,单位秒 |
|
||||
| `PROBEPORT` | `80` | 三网 TCP 探测端口 |
|
||||
| `PROBE_PROTOCOL_PREFER` | `ipv4` | 探测协议偏好,可选 `ipv4`、`ipv6` |
|
||||
| `PING_PACKET_HISTORY_LEN` | `100` | 丢包历史窗口 |
|
||||
| `CU` | `cu.tz.cloudcpp.com` | 联通探测地址 |
|
||||
| `CT` | `ct.tz.cloudcpp.com` | 电信探测地址 |
|
||||
| `CM` | `cm.tz.cloudcpp.com` | 移动探测地址 |
|
||||
| `CLIENT` | `psutil` | 客户端实现,可选 `psutil`、`linux` |
|
||||
|
||||
## 服务端参数
|
||||
|
||||
Docker 镜像中的默认路径为:
|
||||
|
||||
| 环境变量 | 默认值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `CONFIG_PATH` | `/app/config/config.json` | 主配置文件 |
|
||||
| `STATS_PATH` | `/app/data/stats.json` | 月流量与状态持久化文件 |
|
||||
| `WEB_DIR` | `/app/web` | WebUI 静态文件目录 |
|
||||
| `HTTP_ADDR` | `:80` | WebUI 与 HTTP API 监听地址 |
|
||||
| `AGENT_ADDR` | `:35601` | 客户端 TCP 上报监听地址 |
|
||||
| `ADMIN_TOKEN` | 空 | 管理 API Bearer Token;为空时禁用管理接口 |
|
||||
| `ADMIN_CORS_ORIGIN` | 空 | 可选的 API CORS Origin |
|
||||
| `INSECURE_CALLBACK_TLS` | `false` | 是否允许 Watchdog/证书回调使用不可信 TLS 证书 |
|
||||
| `VERBOSE` | `false` | 输出 Gin HTTP 请求日志 |
|
||||
| `TZ` | `Asia/Shanghai` | 容器时区 |
|
||||
|
||||
对应命令行参数:
|
||||
|
||||
```text
|
||||
--config, -c config.json 路径
|
||||
--stats stats.json 路径
|
||||
--web-dir, -d WebUI 目录
|
||||
--http HTTP 监听地址
|
||||
--agent Agent TCP 监听地址
|
||||
--verbose, -v 详细请求日志
|
||||
--version 输出构建版本
|
||||
```
|
||||
|
||||
旧参数 `--bind/-b` 和 `--port/-p` 仍可用于设置 Agent TCP 监听地址。
|
||||
|
||||
## HTTP 管理 API
|
||||
|
||||
管理接口使用 Bearer Token:
|
||||
|
||||
```http
|
||||
Authorization: Bearer <ADMIN_TOKEN>
|
||||
```
|
||||
|
||||
无需认证:
|
||||
|
||||
| 方法 | 路径 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| `GET` | `/api/health` | 进程、Agent TCP、版本和配置路径状态 |
|
||||
| `GET` | `/api/schema` | 机器可读的端点与配置集合描述 |
|
||||
| `GET` | `/api/openapi.json` | 可供 AI Agent 直接导入的 OpenAPI 3.1 文档 |
|
||||
| `GET` | `/json/stats.json` | WebUI 使用的实时状态快照 |
|
||||
|
||||
需要认证:
|
||||
|
||||
| 方法 | 路径 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| `GET/PUT` | `/api/config` | 读取或整体替换配置 |
|
||||
| `GET/POST` | `/api/servers` | 查询或新增节点 |
|
||||
| `PUT/DELETE` | `/api/servers/{username}` | 修改或删除节点 |
|
||||
| `POST` | `/api/servers/{username}/reset-traffic` | 将当前流量设为本月基线 |
|
||||
| `GET/POST` | `/api/monitors` | 查询或新增服务监测 |
|
||||
| `PUT/DELETE` | `/api/monitors/{index-or-name}` | 修改或删除服务监测 |
|
||||
| `GET/POST` | `/api/sslcerts` | 查询或新增证书监测 |
|
||||
| `PUT/DELETE` | `/api/sslcerts/{index-or-name}` | 修改或删除证书监测 |
|
||||
| `GET/POST` | `/api/watchdog` | 查询或新增 Watchdog |
|
||||
| `PUT/DELETE` | `/api/watchdog/{index-or-name}` | 修改或删除 Watchdog |
|
||||
| `POST` | `/api/reload` | 从磁盘重新读取配置 |
|
||||
| `POST` | `/api/restart` | 在进程内重启采集运行时 |
|
||||
|
||||
配置修改采用“校验 → 备份 → 持久化 → 原子切换”的顺序。成功后现有 Agent 连接会被关闭,Python 客户端约 3 秒后自动重连并获取新的 `monitors`。`/api/restart` 不退出 Go 进程,因此 Docker 和手动运行方式具有一致语义。
|
||||
|
||||
常用调用:
|
||||
|
||||
```bash
|
||||
TOKEN='请替换为 ADMIN_TOKEN'
|
||||
|
||||
curl http://127.0.0.1:8080/api/health
|
||||
|
||||
curl -H "Authorization: Bearer ${TOKEN}" \
|
||||
http://127.0.0.1:8080/api/config
|
||||
|
||||
curl -X POST http://127.0.0.1:8080/api/servers \
|
||||
-H "Authorization: Bearer ${TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"username":"s05","name":"node5","type":"kvm","host":"host5","location":"SG","password":"change-me","monthstart":1}'
|
||||
|
||||
curl -X DELETE \
|
||||
-H "Authorization: Bearer ${TOKEN}" \
|
||||
http://127.0.0.1:8080/api/servers/s05
|
||||
```
|
||||
|
||||
请求体最大为 `1 MiB`。AI Agent 可直接导入 `/api/openapi.json`;轻量客户端也可以先读取 `/api/schema`,再根据返回的集合字段调用 CRUD 接口。
|
||||
|
||||
## 配置文件
|
||||
|
||||
```json
|
||||
{
|
||||
"servers":
|
||||
[
|
||||
{
|
||||
"username": "s01",
|
||||
"name": "vps-1",
|
||||
"type": "kvm",
|
||||
"host": "chengdu",
|
||||
"location": "🇨🇳",
|
||||
"password": "USER_DEFAULT_PASSWORD",
|
||||
"monthstart": 1
|
||||
},
|
||||
],
|
||||
"watchdog":
|
||||
[
|
||||
{
|
||||
"name": "服务器负载高监控,排除内存大于32G物理机,同时排除俄勒冈机器",
|
||||
"rule": "cpu>90&load_1>4&memory_total<33554432&name!='俄勒冈'",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "服务器内存使用率过高监控",
|
||||
"rule": "(memory_used/memory_total)*100>90",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "服务器宕机告警,排出俄勒冈,排除s02",
|
||||
"rule": "online4=0&online6=0&name!='俄勒冈'&username!='s02'",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "DDOS和CC攻击监控",
|
||||
"rule": "tcp_count>600",
|
||||
"interval": 300,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "服务器月出口流量999GB告警",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>999",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "你可以组合任何已知字段的表达式",
|
||||
"rule": "(hdd_used/hdd_total)*100>95",
|
||||
"interval": 1800,
|
||||
"callback": "https://yourSMSurl"
|
||||
}
|
||||
]
|
||||
}
|
||||
"servers": [
|
||||
{
|
||||
"username": "s01",
|
||||
"name": "node1",
|
||||
"type": "kvm",
|
||||
"host": "host1",
|
||||
"location": "CN",
|
||||
"password": "USER_DEFAULT_PASSWORD",
|
||||
"monthstart": 1,
|
||||
"disabled": false
|
||||
}
|
||||
],
|
||||
"monitors": [
|
||||
{
|
||||
"name": "example",
|
||||
"host": "https://example.com",
|
||||
"interval": 600,
|
||||
"type": "https"
|
||||
}
|
||||
],
|
||||
"sslcerts": [
|
||||
{
|
||||
"name": "example",
|
||||
"domain": "https://example.com",
|
||||
"port": 443,
|
||||
"interval": 7200,
|
||||
"callback": "https://example.net/push?message="
|
||||
}
|
||||
],
|
||||
"watchdog": [
|
||||
{
|
||||
"name": "offline warning",
|
||||
"rule": "online4=0&online6=0",
|
||||
"interval": 600,
|
||||
"callback": "https://example.net/push?message="
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 三、拷贝ServerStatus/status到你的网站目录
|
||||
例如:
|
||||
```
|
||||
sudo cp -r ServerStatus/web/* /home/wwwroot/default
|
||||
约束:
|
||||
|
||||
- `servers.username` 必须唯一。
|
||||
- `monthstart` 自动限制在 `1-28`。
|
||||
- `port` 自动限制在 `1-65535`。
|
||||
- `interval` 最小为 1 秒;Watchdog 中表示通知冷却时间,不是客户端采集间隔。
|
||||
- 配置写入前会创建 `config.json.bak-*`,最多保留 10 份。
|
||||
- Docker 单文件 bind mount 无法被 `rename` 覆盖时,服务端会在完成备份后安全地写回原 inode。
|
||||
|
||||
使用 Docker 单文件挂载时,配置备份位于容器 `/app/config` 的可写层;如需长期保留历史版本,建议同时在宿主机备份 `server/config.json`。
|
||||
|
||||
### Watchdog 表达式
|
||||
|
||||
`rule` 由 Go `expr` 引擎执行,并兼容旧版 Exprtk 的常用写法。Go 服务会把字符串外的单个操作符自动转换:
|
||||
|
||||
```text
|
||||
& -> &&
|
||||
| -> ||
|
||||
= -> ==
|
||||
```
|
||||
|
||||
#### 四、运行服务端:
|
||||
web-dir参数为上一步设置的网站根目录,务必修改成自己网站的路径
|
||||
```
|
||||
./sergate --config=config.json --web-dir=/home/wwwroot/default
|
||||
例如以下两种写法等价:
|
||||
|
||||
```text
|
||||
cpu>90&load_1>5&username!='s01'
|
||||
cpu>90 && load_1>5 && username!='s01'
|
||||
```
|
||||
|
||||
**【客户端配置】**
|
||||
字符串值支持中文、Emoji 和其他 Unicode 字符,例如:
|
||||
|
||||
客户端有两个版本,client-linux为普通linux,client-psutil为跨平台版,普通版不成功,换成跨平台版即可。
|
||||
|
||||
#### 一、client-linux版配置:
|
||||
1、vim client-linux.py, 修改SERVER地址,username帐号, password密码
|
||||
2、python3 client-linux.py 运行即可。
|
||||
|
||||
#### 二、client-psutil版配置:
|
||||
1、安装psutil跨平台依赖库
|
||||
```text
|
||||
username='节点一号'&name='上海节点'&location='中国 🇨🇳'&type='云主机'
|
||||
```
|
||||
`Debian/Ubuntu`: apt -y install python3-pip && pip3 install psutil
|
||||
`Centos/Redhat`: yum -y install python3-pip gcc python3-devel && pip3 install psutil
|
||||
`Windows`: https://pypi.org/project/psutil/
|
||||
|
||||
字段名必须使用系统定义的英文名称。可用字段包括:`username`、`name`、`type`、`host`、`location`、`load_1`、`load_5`、`load_15`、`cpu`、`memory_total`、`memory_used`、`swap_total`、`swap_used`、`hdd_total`、`hdd_used`、`network_rx`、`network_tx`、`network_in`、`network_out`、`last_network_in`、`last_network_out`、`ping_10010`、`ping_189`、`ping_10086`、`time_10010`、`time_189`、`time_10086`、`tcp_count`、`udp_count`、`process_count`、`thread_count`、`io_read`、`io_write`、`online4`、`online6`。
|
||||
|
||||
客户端断开 25 秒后仍未重连,服务端才计算离线规则,避免短暂网络波动触发告警。每个节点、每条规则分别记录冷却时间。
|
||||
|
||||
### SSL 证书
|
||||
|
||||
证书检查使用 Go `crypto/tls`,不再调用外部 `openssl`。服务端记录到期时间、剩余天数和域名匹配状态,并保留原来的 7/3/1 天通知档位与冷却时间。
|
||||
|
||||
回调默认校验 HTTPS 证书。仅在必须兼容自签名回调服务时设置:
|
||||
|
||||
```bash
|
||||
INSECURE_CALLBACK_TLS=true
|
||||
```
|
||||
2、vim client-psutil.py, 修改SERVER地址,username帐号, password密码
|
||||
3、python3 client-psutil.py 运行即可。
|
||||
|
||||
服务器和客户端自行加入开机启动,或进程守护,或后台方式运行。 例如: nohup python3 client-linux.py &
|
||||
## 源码编译和运行
|
||||
|
||||
`extra scene (run web/ssview.py)`
|
||||

|
||||
需要 Go `1.25` 或更高版本:
|
||||
|
||||
```bash
|
||||
cd server
|
||||
go mod download
|
||||
go test ./...
|
||||
go build -trimpath -ldflags='-s -w' -o serverstatus .
|
||||
```
|
||||
|
||||
从 `server/` 目录启动:
|
||||
|
||||
```bash
|
||||
ADMIN_TOKEN='请替换为高强度随机字符串' \
|
||||
./serverstatus \
|
||||
--config=config.json \
|
||||
--stats=../web/json/stats.json \
|
||||
--web-dir=../web \
|
||||
--http=:8080 \
|
||||
--agent=:35601
|
||||
```
|
||||
|
||||
访问 http://127.0.0.1:8080/。发送 `SIGHUP` 可以重新读取配置:
|
||||
|
||||
```bash
|
||||
kill -HUP "$(pgrep -x serverstatus)"
|
||||
```
|
||||
|
||||
Systemd 示例位于 `service/status-server.service`。一键脚本 `status.sh` 也已切换到 Go 构建,但 Docker 仍是推荐部署方式。
|
||||
|
||||
## 构建和测试
|
||||
|
||||
```bash
|
||||
# Go 单元、协议、API、TLS 和回调测试
|
||||
cd server
|
||||
go test ./...
|
||||
go test -race ./...
|
||||
go vet ./...
|
||||
|
||||
# Docker 镜像
|
||||
cd ..
|
||||
docker build -f Dockerfile.server -t cppla/serverstatus:server .
|
||||
docker build -f Dockerfile.client -t cppla/serverstatus:client .
|
||||
|
||||
# Compose 配置
|
||||
docker compose -f docker-compose-server.yml config
|
||||
docker compose -f docker-compose-client.yml config
|
||||
```
|
||||
|
||||
CI 还会检查 Go 格式、Python 客户端、Shell 脚本、WebUI JavaScript、服务端/客户端 Compose 文件和两个 Docker 镜像。
|
||||
|
||||
## 从旧服务端迁移
|
||||
|
||||
1. 备份原来的 `config.json` 和 `web/json/stats.json`。
|
||||
2. 原配置结构和客户端账号无需转换。
|
||||
3. Docker 挂载目标改为 `/app/config/config.json` 和 `/app/data`。
|
||||
4. 删除旧的 nginx、`manage_api.py`、`sergate` 启动或监督配置。
|
||||
5. 启动 Go 服务端后检查 `/api/health`,再观察客户端自动重连。
|
||||
|
||||
`stats.json` 会按节点的 `name/type/host/location` 恢复月流量基线。修改这些身份字段会被视为新节点。
|
||||
|
||||
|
||||
# Make Better
|
||||
## 致谢
|
||||
|
||||
* BotoX:https://github.com/BotoX/ServerStatus
|
||||
* mojeda: https://github.com/mojeda
|
||||
* mojeda's ServerStatus: https://github.com/mojeda/ServerStatus
|
||||
* BlueVM's project: http://www.lowendtalk.com/discussion/comment/169690#Comment_169690
|
||||
|
||||
# Jetbrains
|
||||
|
||||
<a href="https://www.jetbrains.com/?from=ServerStatus"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_square.png" width="100px"></a>
|
||||
- BotoX:https://github.com/BotoX/ServerStatus
|
||||
- mojeda:https://github.com/mojeda/ServerStatus
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
# Update by : https://github.com/cppla/ServerStatus, Update date: 20220530
|
||||
# 版本:1.0.3, 支持Python版本:2.7 to 3.10
|
||||
# Update by : https://github.com/cppla/ServerStatus, Update date: 20250902
|
||||
# 版本:1.1.0, 支持Python版本:3.6+
|
||||
# 支持操作系统: Linux, OSX, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
|
||||
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
|
||||
|
||||
SERVER = "127.0.0.1"
|
||||
USER = "s01"
|
||||
SERVER = ""
|
||||
USER = ""
|
||||
|
||||
|
||||
PASSWORD = "USER_DEFAULT_PASSWORD"
|
||||
@@ -29,10 +29,44 @@ import json
|
||||
import errno
|
||||
import subprocess
|
||||
import threading
|
||||
try:
|
||||
from queue import Queue # python3
|
||||
except ImportError:
|
||||
from Queue import Queue # python2
|
||||
import platform
|
||||
from queue import Queue
|
||||
|
||||
def _env_str(name, default):
|
||||
value = os.getenv(name)
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return value
|
||||
|
||||
def _env_int(name, default):
|
||||
value = os.getenv(name)
|
||||
if value is None or value == "":
|
||||
return default
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return default
|
||||
|
||||
# Allow docker env overrides. 优先级:运行程序传递参数 > 用户修改的USER > Docker/系统
|
||||
SERVER = _env_str("SERVER", SERVER) if SERVER == "" else SERVER
|
||||
USER = _env_str("USER", USER) if USER == "" else USER
|
||||
PASSWORD = _env_str("PASSWORD", PASSWORD)
|
||||
PORT = _env_int("PORT", PORT)
|
||||
INTERVAL = _env_int("INTERVAL", INTERVAL)
|
||||
PROBEPORT = _env_int("PROBEPORT", PROBEPORT)
|
||||
PROBE_PROTOCOL_PREFER = _env_str("PROBE_PROTOCOL_PREFER", PROBE_PROTOCOL_PREFER)
|
||||
PING_PACKET_HISTORY_LEN = _env_int("PING_PACKET_HISTORY_LEN", PING_PACKET_HISTORY_LEN)
|
||||
CU = _env_str("CU", CU)
|
||||
CT = _env_str("CT", CT)
|
||||
CM = _env_str("CM", CM)
|
||||
|
||||
def parse_cli_args(arguments):
|
||||
overrides = {}
|
||||
for argument in arguments:
|
||||
key, separator, value = argument.partition('=')
|
||||
if separator and key in {'SERVER', 'PORT', 'USER', 'PASSWORD', 'INTERVAL'}:
|
||||
overrides[key] = value
|
||||
return overrides
|
||||
|
||||
def get_uptime():
|
||||
with open('/proc/uptime', 'r') as f:
|
||||
@@ -55,11 +89,34 @@ def get_memory():
|
||||
return int(MemTotal), int(MemUsed), int(SwapTotal), int(SwapFree)
|
||||
|
||||
def get_hdd():
|
||||
p = subprocess.check_output(['df', '-Tlm', '--total', '-t', 'ext4', '-t', 'ext3', '-t', 'ext2', '-t', 'reiserfs', '-t', 'jfs', '-t', 'ntfs', '-t', 'fat32', '-t', 'btrfs', '-t', 'fuseblk', '-t', 'zfs', '-t', 'simfs', '-t', 'xfs']).decode("Utf-8")
|
||||
total = p.splitlines()[-1]
|
||||
used = total.split()[3]
|
||||
size = total.split()[2]
|
||||
return int(size), int(used)
|
||||
valid_fs = {
|
||||
"ext4", "ext3", "ext2", "reiserfs", "jfs", "btrfs", "fuseblk",
|
||||
"zfs", "simfs", "ntfs", "fat32", "exfat", "xfs"
|
||||
}
|
||||
disks = {}
|
||||
size = 0
|
||||
used = 0
|
||||
try:
|
||||
with open("/proc/mounts", "r") as f:
|
||||
for line in f:
|
||||
parts = line.split()
|
||||
if len(parts) < 3:
|
||||
continue
|
||||
device = parts[0]
|
||||
mountpoint = parts[1]
|
||||
fstype = parts[2].lower()
|
||||
if fstype not in valid_fs or device in disks:
|
||||
continue
|
||||
disks[device] = mountpoint
|
||||
for mountpoint in disks.values():
|
||||
st = os.statvfs(mountpoint)
|
||||
total_bytes = st.f_blocks * st.f_frsize
|
||||
used_bytes = (st.f_blocks - st.f_bavail) * st.f_frsize
|
||||
size += total_bytes
|
||||
used += used_bytes
|
||||
except Exception:
|
||||
pass
|
||||
return int(size / 1024 / 1024), int(used / 1024 / 1024)
|
||||
|
||||
def get_time():
|
||||
with open("/proc/stat", "r") as f:
|
||||
@@ -84,12 +141,79 @@ def get_cpu():
|
||||
result = 100-(t[len(t)-1]*100.00/st)
|
||||
return round(result, 1)
|
||||
|
||||
def get_cpu_cores():
|
||||
try:
|
||||
with open('/proc/stat') as f:
|
||||
cores = sum(1 for line in f if re.match(r'^cpu\d+\s', line))
|
||||
if cores > 0:
|
||||
return cores
|
||||
except Exception:
|
||||
pass
|
||||
return os.cpu_count() or 0
|
||||
|
||||
def normalize_cpu_model(value):
|
||||
return re.sub(r'\s+', ' ', str(value or '')).strip()[:160]
|
||||
|
||||
def is_generic_cpu_model(value):
|
||||
v = normalize_cpu_model(value).lower().replace('-', '').replace('_', '').replace(' ', '')
|
||||
return v in ('', 'unknown', 'x8664', 'amd64', 'i386', 'i686', 'aarch64', 'arm64') or v.startswith('armv')
|
||||
|
||||
def get_lscpu_info():
|
||||
result = {}
|
||||
try:
|
||||
output = subprocess.check_output(['lscpu'], stderr=subprocess.DEVNULL, timeout=2).decode(errors='ignore')
|
||||
for line in output.splitlines():
|
||||
if ':' not in line:
|
||||
continue
|
||||
key, value = line.split(':', 1)
|
||||
key = key.strip().lower()
|
||||
value = normalize_cpu_model(value)
|
||||
if value and key not in result:
|
||||
result[key] = value
|
||||
except Exception:
|
||||
pass
|
||||
return result
|
||||
|
||||
def get_cpuinfo_values():
|
||||
result = {}
|
||||
try:
|
||||
with open('/proc/cpuinfo') as f:
|
||||
for line in f:
|
||||
if ':' not in line:
|
||||
continue
|
||||
key, value = line.split(':', 1)
|
||||
key = key.strip().lower()
|
||||
value = normalize_cpu_model(value)
|
||||
if value and key not in result:
|
||||
result[key] = value
|
||||
except Exception:
|
||||
pass
|
||||
return result
|
||||
|
||||
def get_cpu_model():
|
||||
cpuinfo = get_cpuinfo_values()
|
||||
lscpu = get_lscpu_info()
|
||||
for value in (
|
||||
cpuinfo.get('model name'),
|
||||
lscpu.get('model name'),
|
||||
cpuinfo.get('hardware'),
|
||||
cpuinfo.get('processor'),
|
||||
platform.processor(),
|
||||
):
|
||||
value = normalize_cpu_model(value)
|
||||
if value and not value.isdigit() and not is_generic_cpu_model(value):
|
||||
return value
|
||||
vendor = normalize_cpu_model(lscpu.get('vendor id') or cpuinfo.get('vendor_id'))
|
||||
if vendor:
|
||||
return vendor
|
||||
return normalize_cpu_model(lscpu.get('architecture') or platform.machine() or platform.processor())
|
||||
|
||||
def liuliang():
|
||||
NET_IN = 0
|
||||
NET_OUT = 0
|
||||
with open('/proc/net/dev') as f:
|
||||
for line in f.readlines():
|
||||
netinfo = re.findall('([^\s]+):[\s]{0,}(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)', line)
|
||||
netinfo = re.findall(r'([^\s]+):[\s]{0,}(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)', line)
|
||||
if netinfo:
|
||||
if netinfo[0][0] == 'lo' or 'tun' in netinfo[0][0] \
|
||||
or 'docker' in netinfo[0][0] or 'veth' in netinfo[0][0] \
|
||||
@@ -150,6 +274,7 @@ diskIO = {
|
||||
'read': 0,
|
||||
'write': 0
|
||||
}
|
||||
monitorServer = {}
|
||||
|
||||
def _ping_thread(host, mark, port):
|
||||
lostPacket = 0
|
||||
@@ -314,6 +439,70 @@ def get_realtime_data():
|
||||
ti.daemon = True
|
||||
ti.start()
|
||||
|
||||
|
||||
def _monitor_thread(name, host, interval, type):
|
||||
while True:
|
||||
if name not in monitorServer.keys():
|
||||
break
|
||||
try:
|
||||
# 1) 解析目标 host 与端口
|
||||
if type == 'http':
|
||||
addr = str(host).replace('http://','')
|
||||
addr = addr.split('/',1)[0]
|
||||
port = 80
|
||||
if ':' in addr and not addr.startswith('['):
|
||||
a, p = addr.rsplit(':',1)
|
||||
if p.isdigit():
|
||||
addr, port = a, int(p)
|
||||
elif type == 'https':
|
||||
addr = str(host).replace('https://','')
|
||||
addr = addr.split('/',1)[0]
|
||||
port = 443
|
||||
if ':' in addr and not addr.startswith('['):
|
||||
a, p = addr.rsplit(':',1)
|
||||
if p.isdigit():
|
||||
addr, port = a, int(p)
|
||||
elif type == 'tcp':
|
||||
addr = str(host)
|
||||
if addr.startswith('[') and ']' in addr:
|
||||
a = addr[1:addr.index(']')]
|
||||
rest = addr[addr.index(']')+1:]
|
||||
if rest.startswith(':') and rest[1:].isdigit():
|
||||
addr, port = a, int(rest[1:])
|
||||
else:
|
||||
raise Exception('bad tcp target')
|
||||
else:
|
||||
a, p = addr.rsplit(':',1)
|
||||
addr, port = a, int(p)
|
||||
else:
|
||||
time.sleep(interval)
|
||||
continue
|
||||
|
||||
# 2) 解析 IP(按偏好族)
|
||||
IP = addr
|
||||
if addr.count(':') < 1: # 非纯 IPv6
|
||||
try:
|
||||
if PROBE_PROTOCOL_PREFER == 'ipv4':
|
||||
IP = socket.getaddrinfo(addr, None, socket.AF_INET)[0][4][0]
|
||||
else:
|
||||
IP = socket.getaddrinfo(addr, None, socket.AF_INET6)[0][4][0]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 3) 建连耗时(timeout=1s),ECONNREFUSED 也计入
|
||||
try:
|
||||
b = timeit.default_timer()
|
||||
socket.create_connection((IP, port), timeout=1).close()
|
||||
monitorServer[name]["latency"] = int((timeit.default_timer() - b) * 1000)
|
||||
except socket.error as error:
|
||||
if getattr(error, 'errno', None) == errno.ECONNREFUSED:
|
||||
monitorServer[name]["latency"] = int((timeit.default_timer() - b) * 1000)
|
||||
else:
|
||||
monitorServer[name]["latency"] = 0
|
||||
except Exception:
|
||||
monitorServer[name]["latency"] = 0
|
||||
time.sleep(interval)
|
||||
|
||||
def byte_str(object):
|
||||
'''
|
||||
bytes to str, str to bytes
|
||||
@@ -328,17 +517,12 @@ def byte_str(object):
|
||||
print(type(object))
|
||||
|
||||
if __name__ == '__main__':
|
||||
for argc in sys.argv:
|
||||
if 'SERVER' in argc:
|
||||
SERVER = argc.split('SERVER=')[-1]
|
||||
elif 'PORT' in argc:
|
||||
PORT = int(argc.split('PORT=')[-1])
|
||||
elif 'USER' in argc:
|
||||
USER = argc.split('USER=')[-1]
|
||||
elif 'PASSWORD' in argc:
|
||||
PASSWORD = argc.split('PASSWORD=')[-1]
|
||||
elif 'INTERVAL' in argc:
|
||||
INTERVAL = int(argc.split('INTERVAL=')[-1])
|
||||
cli_args = parse_cli_args(sys.argv[1:])
|
||||
SERVER = cli_args.get('SERVER', SERVER)
|
||||
PORT = int(cli_args.get('PORT', PORT))
|
||||
USER = cli_args.get('USER', USER)
|
||||
PASSWORD = cli_args.get('PASSWORD', PASSWORD)
|
||||
INTERVAL = int(cli_args.get('INTERVAL', INTERVAL))
|
||||
socket.setdefaulttimeout(30)
|
||||
get_realtime_data()
|
||||
while True:
|
||||
@@ -360,6 +544,26 @@ if __name__ == '__main__':
|
||||
if data.find("You are connecting via") < 0:
|
||||
data = byte_str(s.recv(1024))
|
||||
print(data)
|
||||
monitorServer.clear()
|
||||
for i in data.split('\n'):
|
||||
if "monitor" in i and "type" in i and "{" in i and "}" in i:
|
||||
jdata = json.loads(i[i.find("{"):i.find("}")+1])
|
||||
monitorServer[jdata.get("name")] = {
|
||||
"type": jdata.get("type"),
|
||||
"host": jdata.get("host"),
|
||||
"latency": 0
|
||||
}
|
||||
t = threading.Thread(
|
||||
target=_monitor_thread,
|
||||
kwargs={
|
||||
'name': jdata.get("name"),
|
||||
'host': jdata.get("host"),
|
||||
'interval': jdata.get("interval"),
|
||||
'type': jdata.get("type")
|
||||
}
|
||||
)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
timer = 0
|
||||
check_ip = 0
|
||||
@@ -371,6 +575,8 @@ if __name__ == '__main__':
|
||||
print(data)
|
||||
raise socket.error
|
||||
|
||||
CPUCores = get_cpu_cores()
|
||||
CPUModel = get_cpu_model()
|
||||
while True:
|
||||
CPU = get_cpu()
|
||||
NET_IN, NET_OUT = liuliang()
|
||||
@@ -378,7 +584,6 @@ if __name__ == '__main__':
|
||||
Load_1, Load_5, Load_15 = os.getloadavg()
|
||||
MemoryTotal, MemoryUsed, SwapTotal, SwapFree = get_memory()
|
||||
HDDTotal, HDDUsed = get_hdd()
|
||||
|
||||
array = {}
|
||||
if not timer:
|
||||
array['online' + str(check_ip)] = get_network(check_ip)
|
||||
@@ -397,12 +602,12 @@ if __name__ == '__main__':
|
||||
array['hdd_total'] = HDDTotal
|
||||
array['hdd_used'] = HDDUsed
|
||||
array['cpu'] = CPU
|
||||
array['cpu_cores'] = CPUCores
|
||||
array['cpu_model'] = CPUModel
|
||||
array['network_rx'] = netSpeed.get("netrx")
|
||||
array['network_tx'] = netSpeed.get("nettx")
|
||||
array['network_in'] = NET_IN
|
||||
array['network_out'] = NET_OUT
|
||||
# todo:兼容旧版本,下个版本删除ip_status
|
||||
array['ip_status'] = True
|
||||
array['ping_10010'] = lostRate.get('10010') * 100
|
||||
array['ping_189'] = lostRate.get('189') * 100
|
||||
array['ping_10086'] = lostRate.get('10086') * 100
|
||||
@@ -412,16 +617,56 @@ if __name__ == '__main__':
|
||||
array['tcp'], array['udp'], array['process'], array['thread'] = tupd()
|
||||
array['io_read'] = diskIO.get("read")
|
||||
array['io_write'] = diskIO.get("write")
|
||||
|
||||
# report OS (normalized)
|
||||
try:
|
||||
sysname = platform.system().lower()
|
||||
if sysname.startswith('linux'):
|
||||
os_name = 'linux'
|
||||
# try distro from os-release
|
||||
try:
|
||||
with open('/etc/os-release') as f:
|
||||
for line in f:
|
||||
if line.startswith('ID='):
|
||||
val = line.strip().split('=',1)[1].strip().strip('"')
|
||||
if val: os_name = val
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
elif sysname.startswith('darwin'):
|
||||
os_name = 'darwin'
|
||||
elif sysname.startswith('freebsd'):
|
||||
os_name = 'freebsd'
|
||||
elif sysname.startswith('openbsd'):
|
||||
os_name = 'openbsd'
|
||||
elif sysname.startswith('netbsd'):
|
||||
os_name = 'netbsd'
|
||||
else:
|
||||
os_name = sysname or 'unknown'
|
||||
except Exception:
|
||||
os_name = 'unknown'
|
||||
array['os'] = os_name
|
||||
items = []
|
||||
for _n, st in monitorServer.items():
|
||||
key = str(_n)
|
||||
try:
|
||||
ms = int(st.get('latency') or 0)
|
||||
except Exception:
|
||||
ms = 0
|
||||
items.append((key, max(0, ms)))
|
||||
# 稳定顺序:按 key 排序
|
||||
items.sort(key=lambda x: x[0])
|
||||
array['custom'] = ';'.join(f"{k}={v}" for k,v in items)
|
||||
s.send(byte_str("update " + json.dumps(array) + "\n"))
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except socket.error:
|
||||
monitorServer.clear()
|
||||
print("Disconnected...")
|
||||
if 's' in locals().keys():
|
||||
del s
|
||||
time.sleep(3)
|
||||
except Exception as e:
|
||||
monitorServer.clear()
|
||||
print("Caught Exception:", e)
|
||||
if 's' in locals().keys():
|
||||
del s
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
# Update by : https://github.com/cppla/ServerStatus, Update date: 20220530
|
||||
# Update by : https://github.com/cppla/ServerStatus, Update date: 20250902
|
||||
# 依赖于psutil跨平台库
|
||||
# 版本:1.0.3, 支持Python版本:2.7 to 3.10
|
||||
# 版本:1.1.0, 支持Python版本:3.6+
|
||||
# 支持操作系统: Linux, Windows, OSX, Sun Solaris, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
|
||||
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
|
||||
|
||||
SERVER = "127.0.0.1"
|
||||
USER = "s01"
|
||||
SERVER = ""
|
||||
USER = ""
|
||||
|
||||
|
||||
PASSWORD = "USER_DEFAULT_PASSWORD"
|
||||
@@ -29,10 +29,44 @@ import json
|
||||
import errno
|
||||
import psutil
|
||||
import threading
|
||||
try:
|
||||
from queue import Queue # python3
|
||||
except ImportError:
|
||||
from Queue import Queue # python2
|
||||
import platform
|
||||
from queue import Queue
|
||||
|
||||
def _env_str(name, default):
|
||||
value = os.getenv(name)
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return value
|
||||
|
||||
def _env_int(name, default):
|
||||
value = os.getenv(name)
|
||||
if value is None or value == "":
|
||||
return default
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return default
|
||||
|
||||
# Allow docker env overrides. 优先级:运行程序传递参数 > 用户修改的USER > Docker/系统
|
||||
SERVER = _env_str("SERVER", SERVER) if SERVER == "" else SERVER
|
||||
USER = _env_str("USER", USER) if USER == "" else USER
|
||||
PASSWORD = _env_str("PASSWORD", PASSWORD)
|
||||
PORT = _env_int("PORT", PORT)
|
||||
INTERVAL = _env_int("INTERVAL", INTERVAL)
|
||||
PROBEPORT = _env_int("PROBEPORT", PROBEPORT)
|
||||
PROBE_PROTOCOL_PREFER = _env_str("PROBE_PROTOCOL_PREFER", PROBE_PROTOCOL_PREFER)
|
||||
PING_PACKET_HISTORY_LEN = _env_int("PING_PACKET_HISTORY_LEN", PING_PACKET_HISTORY_LEN)
|
||||
CU = _env_str("CU", CU)
|
||||
CT = _env_str("CT", CT)
|
||||
CM = _env_str("CM", CM)
|
||||
|
||||
def parse_cli_args(arguments):
|
||||
overrides = {}
|
||||
for argument in arguments:
|
||||
key, separator, value = argument.partition('=')
|
||||
if separator and key in {'SERVER', 'PORT', 'USER', 'PASSWORD', 'INTERVAL'}:
|
||||
overrides[key] = value
|
||||
return overrides
|
||||
|
||||
def get_uptime():
|
||||
return int(time.time() - psutil.boot_time())
|
||||
@@ -66,6 +100,52 @@ def get_hdd():
|
||||
def get_cpu():
|
||||
return psutil.cpu_percent(interval=INTERVAL)
|
||||
|
||||
def get_cpu_cores():
|
||||
return psutil.cpu_count(logical=True) or 0
|
||||
|
||||
def normalize_cpu_model(value):
|
||||
return " ".join(str(value or "").split())[:160]
|
||||
|
||||
def is_generic_cpu_model(value):
|
||||
v = normalize_cpu_model(value).lower().replace('-', '').replace('_', '').replace(' ', '')
|
||||
return v in ('', 'unknown', 'x8664', 'amd64', 'i386', 'i686', 'aarch64', 'arm64') or v.startswith('armv')
|
||||
|
||||
def get_platform_cpu_vendor():
|
||||
values = [
|
||||
platform.processor(),
|
||||
getattr(platform.uname(), 'processor', ''),
|
||||
platform.machine(),
|
||||
getattr(platform.uname(), 'machine', ''),
|
||||
platform.platform(),
|
||||
]
|
||||
text = " ".join(normalize_cpu_model(v).lower() for v in values)
|
||||
if 'genuineintel' in text:
|
||||
return 'GenuineIntel'
|
||||
if 'authenticamd' in text:
|
||||
return 'AuthenticAMD'
|
||||
if 'intel' in text:
|
||||
return 'Intel'
|
||||
if 'amd' in text:
|
||||
return 'AMD'
|
||||
if sys.platform.startswith('darwin') and platform.machine().lower() in ('arm64', 'aarch64'):
|
||||
return 'Apple'
|
||||
if any(token in text for token in ('aarch64', 'arm64', 'armv7', 'armv8', ' arm ')):
|
||||
return 'ARM'
|
||||
return ''
|
||||
|
||||
def get_platform_cpu_arch():
|
||||
return normalize_cpu_model(platform.machine() or platform.processor() or platform.architecture()[0])
|
||||
|
||||
def get_cpu_model():
|
||||
for value in (platform.processor(), getattr(platform.uname(), 'processor', '')):
|
||||
value = normalize_cpu_model(value)
|
||||
if value and not is_generic_cpu_model(value):
|
||||
return value
|
||||
vendor = normalize_cpu_model(get_platform_cpu_vendor())
|
||||
if vendor:
|
||||
return vendor
|
||||
return get_platform_cpu_arch()
|
||||
|
||||
def liuliang():
|
||||
NET_IN = 0
|
||||
NET_OUT = 0
|
||||
@@ -148,6 +228,7 @@ diskIO = {
|
||||
'read': 0,
|
||||
'write': 0
|
||||
}
|
||||
monitorServer = {}
|
||||
|
||||
def _ping_thread(host, mark, port):
|
||||
lostPacket = 0
|
||||
@@ -303,6 +384,72 @@ def get_realtime_data():
|
||||
ti.daemon = True
|
||||
ti.start()
|
||||
|
||||
def _monitor_thread(name, host, interval, type):
|
||||
# 参考 _ping_thread 风格:每轮解析一次目标,按协议族偏好解析 IP,测 TCP 建连耗时
|
||||
while True:
|
||||
if name not in monitorServer:
|
||||
break
|
||||
try:
|
||||
# 1) 解析目标 host 与端口
|
||||
if type == 'http':
|
||||
addr = str(host).replace('http://','')
|
||||
addr = addr.split('/',1)[0]
|
||||
port = 80
|
||||
if ':' in addr and not addr.startswith('['):
|
||||
a, p = addr.rsplit(':',1)
|
||||
if p.isdigit():
|
||||
addr, port = a, int(p)
|
||||
elif type == 'https':
|
||||
addr = str(host).replace('https://','')
|
||||
addr = addr.split('/',1)[0]
|
||||
port = 443
|
||||
if ':' in addr and not addr.startswith('['):
|
||||
a, p = addr.rsplit(':',1)
|
||||
if p.isdigit():
|
||||
addr, port = a, int(p)
|
||||
elif type == 'tcp':
|
||||
addr = str(host)
|
||||
if addr.startswith('[') and ']' in addr:
|
||||
# [v6]:port
|
||||
a = addr[1:addr.index(']')]
|
||||
rest = addr[addr.index(']')+1:]
|
||||
if rest.startswith(':') and rest[1:].isdigit():
|
||||
addr, port = a, int(rest[1:])
|
||||
else:
|
||||
raise Exception('bad tcp target')
|
||||
else:
|
||||
a, p = addr.rsplit(':',1)
|
||||
addr, port = a, int(p)
|
||||
else:
|
||||
time.sleep(interval)
|
||||
continue
|
||||
|
||||
# 2) 解析 IP(按偏好族),与 _ping_thread 保持一致的判定
|
||||
IP = addr
|
||||
if addr.count(':') < 1: # 非纯 IPv6,可能是 IPv4 或域名
|
||||
try:
|
||||
if PROBE_PROTOCOL_PREFER == 'ipv4':
|
||||
IP = socket.getaddrinfo(addr, None, socket.AF_INET)[0][4][0]
|
||||
else:
|
||||
IP = socket.getaddrinfo(addr, None, socket.AF_INET6)[0][4][0]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 3) 测 TCP 建连耗时(timeout=1s);ECONNREFUSED 也记为耗时
|
||||
try:
|
||||
b = timeit.default_timer()
|
||||
socket.create_connection((IP, port), timeout=1).close()
|
||||
monitorServer[name]['latency'] = int((timeit.default_timer() - b) * 1000)
|
||||
except socket.error as error:
|
||||
if getattr(error, 'errno', None) == errno.ECONNREFUSED:
|
||||
monitorServer[name]['latency'] = int((timeit.default_timer() - b) * 1000)
|
||||
else:
|
||||
monitorServer[name]['latency'] = 0
|
||||
except Exception:
|
||||
monitorServer[name]['latency'] = 0
|
||||
time.sleep(interval)
|
||||
|
||||
|
||||
def byte_str(object):
|
||||
'''
|
||||
bytes to str, str to bytes
|
||||
@@ -317,17 +464,12 @@ def byte_str(object):
|
||||
print(type(object))
|
||||
|
||||
if __name__ == '__main__':
|
||||
for argc in sys.argv:
|
||||
if 'SERVER' in argc:
|
||||
SERVER = argc.split('SERVER=')[-1]
|
||||
elif 'PORT' in argc:
|
||||
PORT = int(argc.split('PORT=')[-1])
|
||||
elif 'USER' in argc:
|
||||
USER = argc.split('USER=')[-1]
|
||||
elif 'PASSWORD' in argc:
|
||||
PASSWORD = argc.split('PASSWORD=')[-1]
|
||||
elif 'INTERVAL' in argc:
|
||||
INTERVAL = int(argc.split('INTERVAL=')[-1])
|
||||
cli_args = parse_cli_args(sys.argv[1:])
|
||||
SERVER = cli_args.get('SERVER', SERVER)
|
||||
PORT = int(cli_args.get('PORT', PORT))
|
||||
USER = cli_args.get('USER', USER)
|
||||
PASSWORD = cli_args.get('PASSWORD', PASSWORD)
|
||||
INTERVAL = int(cli_args.get('INTERVAL', INTERVAL))
|
||||
socket.setdefaulttimeout(30)
|
||||
get_realtime_data()
|
||||
while 1:
|
||||
@@ -349,6 +491,25 @@ if __name__ == '__main__':
|
||||
if data.find("You are connecting via") < 0:
|
||||
data = byte_str(s.recv(1024))
|
||||
print(data)
|
||||
for i in data.split('\n'):
|
||||
if "monitor" in i and "type" in i and "{" in i and "}" in i:
|
||||
jdata = json.loads(i[i.find("{"):i.find("}")+1])
|
||||
monitorServer[jdata.get("name")] = {
|
||||
"type": jdata.get("type"),
|
||||
"host": jdata.get("host"),
|
||||
"latency": 0
|
||||
}
|
||||
t = threading.Thread(
|
||||
target=_monitor_thread,
|
||||
kwargs={
|
||||
'name': jdata.get("name"),
|
||||
'host': jdata.get("host"),
|
||||
'interval': jdata.get("interval"),
|
||||
'type': jdata.get("type")
|
||||
}
|
||||
)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
timer = 0
|
||||
check_ip = 0
|
||||
@@ -360,6 +521,8 @@ if __name__ == '__main__':
|
||||
print(data)
|
||||
raise socket.error
|
||||
|
||||
CPUCores = get_cpu_cores()
|
||||
CPUModel = get_cpu_model()
|
||||
while 1:
|
||||
CPU = get_cpu()
|
||||
NET_IN, NET_OUT = liuliang()
|
||||
@@ -368,7 +531,6 @@ if __name__ == '__main__':
|
||||
MemoryTotal, MemoryUsed = get_memory()
|
||||
SwapTotal, SwapUsed = get_swap()
|
||||
HDDTotal, HDDUsed = get_hdd()
|
||||
|
||||
array = {}
|
||||
if not timer:
|
||||
array['online' + str(check_ip)] = get_network(check_ip)
|
||||
@@ -387,12 +549,12 @@ if __name__ == '__main__':
|
||||
array['hdd_total'] = HDDTotal
|
||||
array['hdd_used'] = HDDUsed
|
||||
array['cpu'] = CPU
|
||||
array['cpu_cores'] = CPUCores
|
||||
array['cpu_model'] = CPUModel
|
||||
array['network_rx'] = netSpeed.get("netrx")
|
||||
array['network_tx'] = netSpeed.get("nettx")
|
||||
array['network_in'] = NET_IN
|
||||
array['network_out'] = NET_OUT
|
||||
# todo:兼容旧版本,下个版本删除ip_status
|
||||
array['ip_status'] = True
|
||||
array['ping_10010'] = lostRate.get('10010') * 100
|
||||
array['ping_189'] = lostRate.get('189') * 100
|
||||
array['ping_10086'] = lostRate.get('10086') * 100
|
||||
@@ -402,16 +564,53 @@ if __name__ == '__main__':
|
||||
array['tcp'], array['udp'], array['process'], array['thread'] = tupd()
|
||||
array['io_read'] = diskIO.get("read")
|
||||
array['io_write'] = diskIO.get("write")
|
||||
|
||||
# report OS (normalized)
|
||||
try:
|
||||
sysname = platform.system().lower()
|
||||
if sysname.startswith('windows'):
|
||||
os_name = 'windows'
|
||||
elif sysname.startswith('darwin') or 'mac' in sysname:
|
||||
os_name = 'darwin'
|
||||
elif 'bsd' in sysname:
|
||||
os_name = 'bsd'
|
||||
elif sysname.startswith('linux'):
|
||||
# try distro from os-release
|
||||
try:
|
||||
with open('/etc/os-release') as f:
|
||||
for line in f:
|
||||
if line.startswith('ID='):
|
||||
val = line.strip().split('=',1)[1].strip().strip('"')
|
||||
if val: os_name = val
|
||||
break
|
||||
except Exception:
|
||||
os_name = 'linux'
|
||||
else:
|
||||
os_name = sysname or 'unknown'
|
||||
except Exception:
|
||||
os_name = 'unknown'
|
||||
array['os'] = os_name
|
||||
items = []
|
||||
for _n, st in monitorServer.items():
|
||||
key = str(_n)
|
||||
try:
|
||||
ms = int(st.get('latency') or 0)
|
||||
except Exception:
|
||||
ms = 0
|
||||
items.append((key, max(0, ms)))
|
||||
# 稳定顺序:按 key 排序
|
||||
items.sort(key=lambda x: x[0])
|
||||
array['custom'] = ';'.join(f"{k}={v}" for k,v in items)
|
||||
s.send(byte_str("update " + json.dumps(array) + "\n"))
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except socket.error:
|
||||
monitorServer.clear()
|
||||
print("Disconnected...")
|
||||
if 's' in locals().keys():
|
||||
del s
|
||||
time.sleep(3)
|
||||
except Exception as e:
|
||||
monitorServer.clear()
|
||||
print("Caught Exception:", e)
|
||||
if 's' in locals().keys():
|
||||
del s
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
case "${CLIENT:-linux}" in
|
||||
linux|client-linux|client-linux.py)
|
||||
exec python3 /app/client-linux.py
|
||||
;;
|
||||
psutil|client-psutil|client-psutil.py)
|
||||
exec python3 /app/client-psutil.py
|
||||
;;
|
||||
*)
|
||||
echo "Unknown CLIENT='$CLIENT'. Use 'linux' or 'psutil'." >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import importlib.util
|
||||
import runpy
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
CLIENT_DIR = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
class ClientArgumentTests(unittest.TestCase):
|
||||
def test_password_with_user_text_does_not_replace_username(self):
|
||||
if importlib.util.find_spec("psutil") is None:
|
||||
sys.modules["psutil"] = types.ModuleType("psutil")
|
||||
|
||||
arguments = [
|
||||
"SERVER=127.0.0.1",
|
||||
"PORT=35601",
|
||||
"USER=s01",
|
||||
"PASSWORD=USER_DEFAULT_PASSWORD",
|
||||
"INTERVAL=2",
|
||||
"NOTUSER=ignored",
|
||||
]
|
||||
expected = {
|
||||
"SERVER": "127.0.0.1",
|
||||
"PORT": "35601",
|
||||
"USER": "s01",
|
||||
"PASSWORD": "USER_DEFAULT_PASSWORD",
|
||||
"INTERVAL": "2",
|
||||
}
|
||||
|
||||
for filename in ("client-linux.py", "client-psutil.py"):
|
||||
with self.subTest(client=filename):
|
||||
namespace = runpy.run_path(str(CLIENT_DIR / filename))
|
||||
self.assertEqual(namespace["parse_cli_args"](arguments), expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
serverstatus-client:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.client
|
||||
image: cppla/serverstatus:client
|
||||
container_name: serverstatus-client
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
pid: host
|
||||
environment:
|
||||
SERVER: "${SERVER:-127.0.0.1}"
|
||||
# 注意:USER 会被 docker compose 在宿主机环境中先插值。
|
||||
# 如果运行时没有显式传递,或传递方式不正确,可能会被 Docker/系统环境中的 $USER
|
||||
# 替换成本机用户名,而不是期望的默认 s01。
|
||||
# 推荐优先级:运行程序时显式传递 USER > 用户修改这里的 USER 默认值 > Docker/系统环境。
|
||||
USER: "${USER:-s01}"
|
||||
PORT: "${PORT:-35601}"
|
||||
PASSWORD: "${PASSWORD:-USER_DEFAULT_PASSWORD}"
|
||||
INTERVAL: "${INTERVAL:-1}"
|
||||
PROBEPORT: "${PROBEPORT:-80}"
|
||||
PROBE_PROTOCOL_PREFER: "${PROBE_PROTOCOL_PREFER:-ipv4}"
|
||||
PING_PACKET_HISTORY_LEN: "${PING_PACKET_HISTORY_LEN:-100}"
|
||||
CU: "${CU:-cu.tz.cloudcpp.com}"
|
||||
CT: "${CT:-ct.tz.cloudcpp.com}"
|
||||
CM: "${CM:-cm.tz.cloudcpp.com}"
|
||||
CLIENT: "${CLIENT:-psutil}"
|
||||
@@ -0,0 +1,32 @@
|
||||
services:
|
||||
serverstatus-server:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.server
|
||||
image: cppla/serverstatus:server
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1/api/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
container_name: serverstatus-server
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
ADMIN_TOKEN: "${ADMIN_TOKEN:-}"
|
||||
HTTP_ADDR: ":80"
|
||||
AGENT_ADDR: ":35601"
|
||||
networks:
|
||||
serverstatus-network:
|
||||
ipv4_address: 172.23.0.2
|
||||
volumes:
|
||||
- ./server/config.json:/app/config/config.json
|
||||
- ./web/json:/app/data
|
||||
ports:
|
||||
- 35601:35601
|
||||
- 8080:80
|
||||
|
||||
networks:
|
||||
serverstatus-network:
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.23.0.0/24
|
||||
@@ -1,25 +0,0 @@
|
||||
version: "3"
|
||||
services:
|
||||
serverstatus:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: serverstatus_server
|
||||
container_name: serverstatus
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
serverstatus-network:
|
||||
ipv4_address: 172.23.0.2
|
||||
volumes:
|
||||
- ./server/config.json:/ServerStatus/server/config.json
|
||||
- ./web/json:/usr/share/nginx/html/json
|
||||
ports:
|
||||
- 35601:35601
|
||||
- 8080:80
|
||||
|
||||
networks:
|
||||
serverstatus-network:
|
||||
name: serverstatus-network
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.23.0.0/24
|
||||
@@ -1,10 +0,0 @@
|
||||
FROM python:alpine
|
||||
|
||||
LABEL maintainer="lidalao"
|
||||
LABEL version="0.0.1"
|
||||
LABEL description="Telegram Bot for ServerStatus"
|
||||
|
||||
WORKDIR /app
|
||||
RUN pip install requests
|
||||
COPY ./bot-telegram.py .
|
||||
CMD [ "python", "./bot-telegram.py" ]
|
||||
@@ -1,73 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
# Create by : https://github.com/lidalao/ServerStatus
|
||||
# 版本:0.0.1, 支持Python版本:2.7 to 3.9
|
||||
# 支持操作系统: Linux, OSX, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
|
||||
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
import time
|
||||
import traceback
|
||||
|
||||
NODE_STATUS_URL = 'http://serverstatus/json/stats.json'
|
||||
|
||||
offs = []
|
||||
counterOff = {}
|
||||
counterOn = {}
|
||||
|
||||
def _send(text):
|
||||
chat_id = os.getenv('TG_CHAT_ID')
|
||||
bot_token = os.environ.get('TG_BOT_TOKEN')
|
||||
url = f"https://api.telegram.org/bot{bot_token}/sendMessage?parse_mode=HTML&disable_web_page_preview=true&chat_id=" + chat_id + "&text=" + text
|
||||
try:
|
||||
requests.get(url)
|
||||
except Exception as e:
|
||||
print("catch exception: ", traceback.format_exc())
|
||||
|
||||
def send2tg(srv, flag):
|
||||
if srv not in counterOff:
|
||||
counterOff[srv] = 0
|
||||
if srv not in counterOn:
|
||||
counterOn[srv] = 0
|
||||
|
||||
if flag == 1 : # online
|
||||
if srv in offs:
|
||||
if counterOn[srv] < 10:
|
||||
counterOn[srv] += 1
|
||||
return
|
||||
#1. Remove srv from offs; 2. Send to tg: I am online
|
||||
offs.remove(srv)
|
||||
counterOn[srv] = 0
|
||||
text = '<b>Server Status</b>' + '\n主机上线: ' + srv
|
||||
_send(text)
|
||||
else: #offline
|
||||
if srv not in offs:
|
||||
if counterOff[srv] < 10:
|
||||
counterOff[srv] += 1
|
||||
return
|
||||
#1. Append srv to offs; 2. Send to tg: I am offline
|
||||
offs.append(srv)
|
||||
counterOff[srv] = 0
|
||||
text = '<b>Server Status</b>' + '\n主机下线: ' + srv
|
||||
_send(text)
|
||||
|
||||
def sscmd(address):
|
||||
while True:
|
||||
r = requests.get(url=address, headers={"User-Agent": "ServerStatus/20211116"})
|
||||
try:
|
||||
jsonR = r.json()
|
||||
except Exception as e:
|
||||
print('未发现任何节点')
|
||||
continue
|
||||
for i in jsonR["servers"]:
|
||||
if i["online4"] is False and i["online6"] is False:
|
||||
send2tg(i["name"], 0)
|
||||
else:
|
||||
send2tg(i["name"], 1)
|
||||
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sscmd(NODE_STATUS_URL)
|
||||
@@ -1,38 +0,0 @@
|
||||
version: "3"
|
||||
services:
|
||||
serverstatus:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile
|
||||
image: serverstatus_server
|
||||
container_name: serverstatus
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
serverstatus-network:
|
||||
ipv4_address: 172.23.0.2
|
||||
volumes:
|
||||
- ../server/config.json:/ServerStatus/server/config.json
|
||||
- ../web/json:/usr/share/nginx/html/json
|
||||
ports:
|
||||
- 35601:35601
|
||||
- 8080:80
|
||||
bot:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile-telegram
|
||||
image: serverstatus_bot
|
||||
container_name: bot4sss
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
serverstatus-network:
|
||||
ipv4_address: 172.23.0.3
|
||||
environment:
|
||||
- TG_CHAT_ID=${TG_CHAT_ID}
|
||||
- TG_BOT_TOKEN=${TG_BOT_TOKEN}
|
||||
|
||||
networks:
|
||||
serverstatus-network:
|
||||
name: serverstatus-network
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.23.0.0/24
|
||||
@@ -1,2 +1,4 @@
|
||||
sergate
|
||||
serverstatus
|
||||
*.test
|
||||
coverage.out
|
||||
.tags*
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
OUT = sergate
|
||||
|
||||
#CC = clang
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -O2
|
||||
|
||||
#CXX = clang++
|
||||
CXX = g++
|
||||
CXXFLAGS = -Wall -O2 -std=c++11
|
||||
|
||||
ODIR = obj
|
||||
SDIR = src
|
||||
LIBS = -pthread -lm
|
||||
INC = -Iinclude
|
||||
|
||||
C_SRCS := $(wildcard $(SDIR)/*.c)
|
||||
CXX_SRCS := $(wildcard $(SDIR)/*.cpp)
|
||||
C_OBJS := $(patsubst $(SDIR)/%.c,$(ODIR)/%.o,$(C_SRCS))
|
||||
CXX_OBJS := $(patsubst $(SDIR)/%.cpp,$(ODIR)/%.o,$(CXX_SRCS))
|
||||
OBJS := $(C_OBJS) $(CXX_OBJS)
|
||||
|
||||
$(ODIR)/%.o: $(SDIR)/%.c
|
||||
$(CC) -c $(INC) $(CFLAGS) $< -o $@
|
||||
|
||||
$(ODIR)/%.o: $(SDIR)/%.cpp
|
||||
$(CXX) -c $(INC) $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(OUT): $(OBJS)
|
||||
$(CXX) $(LIBS) $^ -o $(OUT) -lcurl
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f $(ODIR)/*.o $(OUT)
|
||||
@@ -0,0 +1,472 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
ConfigPath string
|
||||
StatsPath string
|
||||
WebDir string
|
||||
HTTPAddr string
|
||||
AgentAddr string
|
||||
AdminToken string
|
||||
CORSOrigin string
|
||||
InsecureCallbackTLS bool
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
type NodeState struct {
|
||||
Config ServerConfig
|
||||
Connected bool
|
||||
Connection net.Conn
|
||||
ConnectionID uint64
|
||||
Family int
|
||||
Online4 bool
|
||||
Online6 bool
|
||||
Stats AgentStats
|
||||
HasUpdate bool
|
||||
LastNetworkIn int64
|
||||
LastNetworkOut int64
|
||||
LastUpdate time.Time
|
||||
AlarmLast map[string]time.Time
|
||||
Pong bool
|
||||
}
|
||||
|
||||
type App struct {
|
||||
opts Options
|
||||
startedAt time.Time
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
|
||||
mutationMu sync.Mutex
|
||||
configMu sync.RWMutex
|
||||
document ConfigDocument
|
||||
runtime RuntimeConfig
|
||||
|
||||
nodeMu sync.RWMutex
|
||||
nodes map[string]*NodeState
|
||||
connectionID atomic.Uint64
|
||||
generation atomic.Uint64
|
||||
agentRunning atomic.Bool
|
||||
reloadWrites atomic.Int32
|
||||
|
||||
certMu sync.RWMutex
|
||||
certs map[string]*CertState
|
||||
|
||||
statsWake chan struct{}
|
||||
persistMu sync.Mutex
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
func NewApp(opts Options) (*App, error) {
|
||||
doc, runtime, err := readConfig(opts.ConfigPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
app := &App{
|
||||
opts: opts,
|
||||
startedAt: time.Now(),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
nodes: make(map[string]*NodeState),
|
||||
certs: make(map[string]*CertState),
|
||||
statsWake: make(chan struct{}, 1),
|
||||
logger: log.New(os.Stdout, "serverstatus ", log.LstdFlags|log.Lmicroseconds),
|
||||
}
|
||||
app.applyValidatedConfig(doc, runtime, false)
|
||||
app.restorePersistentState()
|
||||
return app, nil
|
||||
}
|
||||
|
||||
func (a *App) StartBackground() {
|
||||
go a.statsLoop()
|
||||
go a.sslLoop()
|
||||
a.wakeStatsWriter()
|
||||
}
|
||||
|
||||
func (a *App) Close() {
|
||||
a.cancel()
|
||||
a.disconnectAll("Server shutting down...")
|
||||
_ = a.PersistStats()
|
||||
}
|
||||
|
||||
func (a *App) ConfigSnapshot() ConfigDocument {
|
||||
a.configMu.RLock()
|
||||
defer a.configMu.RUnlock()
|
||||
clone, err := cloneDocument(a.document)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
func (a *App) RuntimeSnapshot() RuntimeConfig {
|
||||
a.configMu.RLock()
|
||||
defer a.configMu.RUnlock()
|
||||
result := a.runtime
|
||||
result.Servers = append([]ServerConfig(nil), a.runtime.Servers...)
|
||||
result.Monitors = append([]MonitorConfig(nil), a.runtime.Monitors...)
|
||||
result.SSLCerts = append([]SSLCertConfig(nil), a.runtime.SSLCerts...)
|
||||
result.Watchdogs = append([]CompiledWatchdog(nil), a.runtime.Watchdogs...)
|
||||
return result
|
||||
}
|
||||
|
||||
func (a *App) ReplaceConfig(input ConfigDocument) (ConfigDocument, *APIError) {
|
||||
a.mutationMu.Lock()
|
||||
defer a.mutationMu.Unlock()
|
||||
normalized, runtime, apiErr := normalizeConfig(input)
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
if err := writeConfig(a.opts.ConfigPath, normalized); err != nil {
|
||||
return nil, &APIError{Status: 500, Message: "config could not be written", Details: map[string]any{"error": err.Error()}}
|
||||
}
|
||||
a.applyValidatedConfig(normalized, runtime, true)
|
||||
return a.ConfigSnapshot(), nil
|
||||
}
|
||||
|
||||
func (a *App) MutateConfig(mutate func(ConfigDocument) *APIError) (ConfigDocument, *APIError) {
|
||||
a.mutationMu.Lock()
|
||||
defer a.mutationMu.Unlock()
|
||||
doc := a.ConfigSnapshot()
|
||||
if apiErr := mutate(doc); apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
normalized, runtime, apiErr := normalizeConfig(doc)
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
if err := writeConfig(a.opts.ConfigPath, normalized); err != nil {
|
||||
return nil, &APIError{Status: 500, Message: "config could not be written", Details: map[string]any{"error": err.Error()}}
|
||||
}
|
||||
a.applyValidatedConfig(normalized, runtime, true)
|
||||
return a.ConfigSnapshot(), nil
|
||||
}
|
||||
|
||||
func (a *App) ReloadConfig() *APIError {
|
||||
a.mutationMu.Lock()
|
||||
defer a.mutationMu.Unlock()
|
||||
doc, runtime, err := readConfig(a.opts.ConfigPath)
|
||||
if err != nil {
|
||||
if apiErr, ok := err.(*APIError); ok {
|
||||
return apiErr
|
||||
}
|
||||
return &APIError{Status: 500, Message: "config could not be reloaded", Details: map[string]any{"error": err.Error()}}
|
||||
}
|
||||
a.applyValidatedConfig(doc, runtime, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) applyValidatedConfig(doc ConfigDocument, runtime RuntimeConfig, disconnect bool) {
|
||||
a.configMu.Lock()
|
||||
a.nodeMu.Lock()
|
||||
oldNodes := a.nodes
|
||||
newNodes := make(map[string]*NodeState, len(runtime.Servers))
|
||||
connections := make([]net.Conn, 0)
|
||||
for _, server := range runtime.Servers {
|
||||
node := &NodeState{Config: server, AlarmLast: make(map[string]time.Time)}
|
||||
if old := oldNodes[server.Username]; old != nil && sameServerIdentity(old.Config, server) {
|
||||
node.LastNetworkIn = old.LastNetworkIn
|
||||
node.LastNetworkOut = old.LastNetworkOut
|
||||
node.Stats = old.Stats
|
||||
node.HasUpdate = old.HasUpdate
|
||||
node.AlarmLast = old.AlarmLast
|
||||
if !disconnect {
|
||||
node.Connected = old.Connected
|
||||
node.Connection = old.Connection
|
||||
node.ConnectionID = old.ConnectionID
|
||||
node.Family = old.Family
|
||||
node.Online4 = old.Online4
|
||||
node.Online6 = old.Online6
|
||||
}
|
||||
}
|
||||
newNodes[server.Username] = node
|
||||
}
|
||||
if disconnect {
|
||||
for _, node := range oldNodes {
|
||||
if node.Connection != nil {
|
||||
connections = append(connections, node.Connection)
|
||||
}
|
||||
}
|
||||
}
|
||||
a.document = doc
|
||||
a.runtime = runtime
|
||||
a.nodes = newNodes
|
||||
a.generation.Add(1)
|
||||
a.nodeMu.Unlock()
|
||||
a.configMu.Unlock()
|
||||
|
||||
a.reconcileCerts(runtime.SSLCerts)
|
||||
if disconnect {
|
||||
for _, conn := range connections {
|
||||
_, _ = conn.Write([]byte("Server reloading...\n"))
|
||||
_ = conn.Close()
|
||||
}
|
||||
}
|
||||
a.reloadWrites.Store(2)
|
||||
a.wakeStatsWriter()
|
||||
}
|
||||
|
||||
func sameServerIdentity(left, right ServerConfig) bool {
|
||||
return left.Username == right.Username && left.Name == right.Name && left.Type == right.Type && left.Host == right.Host && left.Location == right.Location
|
||||
}
|
||||
|
||||
func (a *App) disconnectAll(reason string) {
|
||||
a.nodeMu.Lock()
|
||||
connections := make([]net.Conn, 0)
|
||||
for _, node := range a.nodes {
|
||||
if node.Connection != nil {
|
||||
connections = append(connections, node.Connection)
|
||||
node.Connection = nil
|
||||
node.Connected = false
|
||||
node.Online4 = false
|
||||
node.Online6 = false
|
||||
}
|
||||
}
|
||||
a.nodeMu.Unlock()
|
||||
for _, conn := range connections {
|
||||
if reason != "" {
|
||||
_, _ = conn.Write([]byte(reason + "\n"))
|
||||
}
|
||||
_ = conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) statsLoop() {
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-a.ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
case <-a.statsWake:
|
||||
}
|
||||
if err := a.PersistStats(); err != nil {
|
||||
a.logger.Printf("write stats: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) wakeStatsWriter() {
|
||||
select {
|
||||
case a.statsWake <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) SnapshotStats() map[string]any {
|
||||
return a.snapshotStats(false)
|
||||
}
|
||||
|
||||
func (a *App) snapshotStats(consumeReload bool) map[string]any {
|
||||
runtime := a.RuntimeSnapshot()
|
||||
now := time.Now()
|
||||
servers := make([]any, 0, len(runtime.Servers))
|
||||
a.nodeMu.Lock()
|
||||
for _, server := range runtime.Servers {
|
||||
if server.Disabled {
|
||||
continue
|
||||
}
|
||||
node := a.nodes[server.Username]
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
base := map[string]any{
|
||||
"name": server.Name, "type": server.Type, "host": server.Host, "location": server.Location,
|
||||
"online4": false, "online6": false,
|
||||
}
|
||||
if node.Connected && node.HasUpdate {
|
||||
s := node.Stats
|
||||
updateTrafficBaselines(node, s.NetworkIn, s.NetworkOut, monthResetWindow(now, server.MonthStart))
|
||||
base["online4"] = node.Online4
|
||||
base["online6"] = node.Online6
|
||||
base["uptime"] = formatUptime(s.Uptime)
|
||||
base["load_1"], base["load_5"], base["load_15"] = round2(s.Load1), round2(s.Load5), round2(s.Load15)
|
||||
base["ping_10010"], base["ping_189"], base["ping_10086"] = round2(s.Ping10010), round2(s.Ping189), round2(s.Ping10086)
|
||||
base["time_10010"], base["time_189"], base["time_10086"] = s.Time10010, s.Time189, s.Time10086
|
||||
base["tcp_count"], base["udp_count"] = s.TCPCount, s.UDPCount
|
||||
base["process_count"], base["thread_count"] = s.ProcessCount, s.ThreadCount
|
||||
base["network_rx"], base["network_tx"] = s.NetworkRX, s.NetworkTX
|
||||
base["network_in"], base["network_out"] = s.NetworkIn, s.NetworkOut
|
||||
base["cpu"], base["cpu_cores"], base["cpu_model"] = int(s.CPU), s.CPUCores, s.CPUModel
|
||||
base["memory_total"], base["memory_used"] = s.MemoryTotal, s.MemoryUsed
|
||||
base["swap_total"], base["swap_used"] = s.SwapTotal, s.SwapUsed
|
||||
base["hdd_total"], base["hdd_used"] = s.HDDTotal, s.HDDUsed
|
||||
base["last_network_in"] = trafficBaseline(s.NetworkIn, node.LastNetworkIn)
|
||||
base["last_network_out"] = trafficBaseline(s.NetworkOut, node.LastNetworkOut)
|
||||
base["io_read"], base["io_write"] = s.IORead, s.IOWrite
|
||||
base["custom"], base["os"] = s.Custom, s.OS
|
||||
} else {
|
||||
base["last_network_in"] = node.LastNetworkIn
|
||||
base["last_network_out"] = node.LastNetworkOut
|
||||
base["os"] = node.Stats.OS
|
||||
base["cpu_model"] = node.Stats.CPUModel
|
||||
}
|
||||
servers = append(servers, base)
|
||||
}
|
||||
a.nodeMu.Unlock()
|
||||
|
||||
result := map[string]any{
|
||||
"servers": servers,
|
||||
"sslcerts": a.sslSnapshot(runtime.SSLCerts, now),
|
||||
"updated": strconv.FormatInt(now.Unix(), 10),
|
||||
}
|
||||
if a.reloadWrites.Load() > 0 {
|
||||
result["reload"] = true
|
||||
if consumeReload {
|
||||
a.reloadWrites.Add(-1)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (a *App) PersistStats() error {
|
||||
a.persistMu.Lock()
|
||||
defer a.persistMu.Unlock()
|
||||
return writeStatsFile(a.opts.StatsPath, a.snapshotStats(true))
|
||||
}
|
||||
|
||||
func monthResetWindow(now time.Time, monthStart int) bool {
|
||||
return now.Day() == clamp(monthStart, 1, 28) && now.Hour() == 0 && now.Minute() < 5
|
||||
}
|
||||
|
||||
func trafficBaseline(current, baseline int64) int64 {
|
||||
if current == 0 || baseline == 0 {
|
||||
return current
|
||||
}
|
||||
return baseline
|
||||
}
|
||||
|
||||
func updateTrafficBaselines(node *NodeState, currentIn, currentOut int64, reset bool) {
|
||||
if reset {
|
||||
node.LastNetworkIn = currentIn
|
||||
node.LastNetworkOut = currentOut
|
||||
return
|
||||
}
|
||||
if node.LastNetworkIn == 0 || (currentIn != 0 && node.LastNetworkIn > currentIn) {
|
||||
node.LastNetworkIn = currentIn
|
||||
}
|
||||
if node.LastNetworkOut == 0 || (currentOut != 0 && node.LastNetworkOut > currentOut) {
|
||||
node.LastNetworkOut = currentOut
|
||||
}
|
||||
}
|
||||
|
||||
func round2(value float64) float64 {
|
||||
return math.Round(value*100) / 100
|
||||
}
|
||||
|
||||
func formatUptime(seconds int64) string {
|
||||
days := seconds / 86400
|
||||
if days > 0 {
|
||||
return fmt.Sprintf("%d 天", days)
|
||||
}
|
||||
return fmt.Sprintf("%02d:%02d:%02d", seconds/3600, (seconds/60)%60, seconds%60)
|
||||
}
|
||||
|
||||
func (a *App) restorePersistentState() {
|
||||
data, err := os.ReadFile(a.opts.StatsPath)
|
||||
if err != nil {
|
||||
data, err = os.ReadFile(a.opts.StatsPath + "~")
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
decoder := json.NewDecoder(bytes.NewReader(data))
|
||||
decoder.UseNumber()
|
||||
var previous struct {
|
||||
Servers []map[string]any `json:"servers"`
|
||||
}
|
||||
if err := decoder.Decode(&previous); err != nil {
|
||||
a.logger.Printf("read previous stats: %v", err)
|
||||
return
|
||||
}
|
||||
a.nodeMu.Lock()
|
||||
defer a.nodeMu.Unlock()
|
||||
for _, node := range a.nodes {
|
||||
for _, saved := range previous.Servers {
|
||||
if fmt.Sprint(saved["name"]) != node.Config.Name || fmt.Sprint(saved["type"]) != node.Config.Type || fmt.Sprint(saved["host"]) != node.Config.Host || fmt.Sprint(saved["location"]) != node.Config.Location {
|
||||
continue
|
||||
}
|
||||
node.LastNetworkIn = anyInt64(saved["last_network_in"])
|
||||
node.LastNetworkOut = anyInt64(saved["last_network_out"])
|
||||
node.Stats.OS = anyString(saved["os"])
|
||||
node.Stats.CPUModel = anyString(saved["cpu_model"])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func anyString(value any) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(value)
|
||||
}
|
||||
|
||||
func anyInt64(value any) int64 {
|
||||
switch number := value.(type) {
|
||||
case json.Number:
|
||||
parsed, _ := number.Int64()
|
||||
return parsed
|
||||
case float64:
|
||||
return int64(number)
|
||||
case int64:
|
||||
return number
|
||||
case int:
|
||||
return int64(number)
|
||||
case string:
|
||||
parsed, _ := strconv.ParseInt(number, 10, 64)
|
||||
return parsed
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) ResetTraffic(username string) (map[string]any, *APIError) {
|
||||
a.nodeMu.Lock()
|
||||
node := a.nodes[username]
|
||||
if node == nil {
|
||||
a.nodeMu.Unlock()
|
||||
return nil, &APIError{Status: 404, Message: "server was not found", Details: map[string]any{"username": username}}
|
||||
}
|
||||
if !node.Connected || !node.HasUpdate {
|
||||
a.nodeMu.Unlock()
|
||||
return nil, &APIError{Status: 409, Message: "server has no current traffic counters; it may be offline", Details: map[string]any{"username": username}}
|
||||
}
|
||||
previousIn, previousOut := node.LastNetworkIn, node.LastNetworkOut
|
||||
networkIn, networkOut := node.Stats.NetworkIn, node.Stats.NetworkOut
|
||||
node.LastNetworkIn, node.LastNetworkOut = networkIn, networkOut
|
||||
server := node.Config
|
||||
a.nodeMu.Unlock()
|
||||
a.wakeStatsWriter()
|
||||
return map[string]any{
|
||||
"server": server,
|
||||
"stats": map[string]any{
|
||||
"network_in": networkIn, "network_out": networkOut,
|
||||
"previous_last_network_in": previousIn, "previous_last_network_out": previousOut,
|
||||
"last_network_in": networkIn, "last_network_out": networkOut,
|
||||
"month_in_before": max64(0, networkIn-previousIn), "month_out_before": max64(0, networkOut-previousOut),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func max64(left, right int64) int64 {
|
||||
if left > right {
|
||||
return left
|
||||
}
|
||||
return right
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTrafficBaselinesResetIndependently(t *testing.T) {
|
||||
node := &NodeState{LastNetworkIn: 100, LastNetworkOut: 0}
|
||||
updateTrafficBaselines(node, 150, 500, false)
|
||||
if node.LastNetworkIn != 100 || node.LastNetworkOut != 500 {
|
||||
t.Fatalf("missing outbound baseline was not initialized independently: %#v", node)
|
||||
}
|
||||
|
||||
node.LastNetworkOut = 700
|
||||
updateTrafficBaselines(node, 200, 50, false)
|
||||
if node.LastNetworkIn != 100 || node.LastNetworkOut != 50 {
|
||||
t.Fatalf("outbound counter reset changed the wrong baseline: %#v", node)
|
||||
}
|
||||
|
||||
updateTrafficBaselines(node, 900, 800, true)
|
||||
if node.LastNetworkIn != 900 || node.LastNetworkOut != 800 {
|
||||
t.Fatalf("monthly reset did not reset both baselines: %#v", node)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisconnectPreservesOfflineDisplayMetadata(t *testing.T) {
|
||||
app := newTestApp(t, minimalTestConfig())
|
||||
client, server := net.Pipe()
|
||||
defer client.Close()
|
||||
defer server.Close()
|
||||
|
||||
app.nodeMu.Lock()
|
||||
node := app.nodes["s01"]
|
||||
node.Connected = true
|
||||
node.Connection = server
|
||||
node.ConnectionID = 42
|
||||
node.HasUpdate = true
|
||||
node.Stats = AgentStats{OS: "linux", CPUModel: "Test CPU"}
|
||||
app.nodeMu.Unlock()
|
||||
|
||||
app.disconnectAgent("s01", server, 42)
|
||||
serverStats := app.SnapshotStats()["servers"].([]any)[0].(map[string]any)
|
||||
if serverStats["online4"] != false || serverStats["online6"] != false {
|
||||
t.Fatalf("disconnected node remained online: %#v", serverStats)
|
||||
}
|
||||
if serverStats["os"] != "linux" || serverStats["cpu_model"] != "Test CPU" {
|
||||
t.Fatalf("offline display metadata was discarded: %#v", serverStats)
|
||||
}
|
||||
}
|
||||
@@ -19,14 +19,14 @@
|
||||
"monthstart": 1
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"username": "s03",
|
||||
"name": "node3",
|
||||
"type": "hyper",
|
||||
"host": "host3",
|
||||
"location": "🇫🇷",
|
||||
"password": "USER_DEFAULT_PASSWORD",
|
||||
"monthstart": 1
|
||||
"monthstart": 1,
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"username": "s04",
|
||||
@@ -38,6 +38,43 @@
|
||||
"monthstart": 1
|
||||
}
|
||||
],
|
||||
"monitors": [
|
||||
{
|
||||
"name": "抖音",
|
||||
"host": "https://www.douyin.com",
|
||||
"interval": 600,
|
||||
"type": "https"
|
||||
},
|
||||
{
|
||||
"name": "百度",
|
||||
"host": "https://www.baidu.com",
|
||||
"interval": 600,
|
||||
"type": "https"
|
||||
}
|
||||
],
|
||||
"sslcerts": [
|
||||
{
|
||||
"name": "my.cloudcpp.com",
|
||||
"domain": "https://my.cloudcpp.com",
|
||||
"port": 443,
|
||||
"interval": 7200,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "tz.cloudcpp.com",
|
||||
"domain": "https://tz.cloudcpp.com",
|
||||
"port": 443,
|
||||
"interval": 7200,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "3.0.2.1",
|
||||
"domain": "https://3.0.2.1",
|
||||
"port": 443,
|
||||
"interval": 7200,
|
||||
"callback": "https://yourSMSurl"
|
||||
}
|
||||
],
|
||||
"watchdog": [
|
||||
{
|
||||
"name": "cpu high warning,exclude username s01",
|
||||
@@ -52,23 +89,35 @@
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "offline warning,exclude name node1",
|
||||
"rule": "online4=0&online6=0&name!='node1'",
|
||||
"name": "offline warning",
|
||||
"rule": "online4=0&online6=0",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "ddcc attack,limit type Oracle",
|
||||
"rule": "tcp_count>600&type='Oracle'",
|
||||
"interval": 300,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
"name": "ddcc attack,limit type Oracle",
|
||||
"rule": "tcp_count>600&type='Oracle'",
|
||||
"interval": 300,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "month traffic warning",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>999",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
"name": "month 999GB traffic warning",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>999",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "aliyun china free 18GB traffic warning",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>18&(username='aliyun1'|username='aliyun2')",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "packet loss rate warning",
|
||||
"rule": "(ping_10010>10|ping_189>10|ping_10086>10)&(host='sgp'|host='qqhk'|host='hk-21-x'|host='hk-31-x')",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "you can parse an expression combining any known field",
|
||||
"rule": "load_5>3",
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func readConfig(path string) (ConfigDocument, RuntimeConfig, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, RuntimeConfig{}, err
|
||||
}
|
||||
doc, err := decodeDocument(data)
|
||||
if err != nil {
|
||||
return nil, RuntimeConfig{}, fmt.Errorf("parse %s: %w", path, err)
|
||||
}
|
||||
normalized, runtime, apiErr := normalizeConfig(doc)
|
||||
if apiErr != nil {
|
||||
return nil, RuntimeConfig{}, apiErr
|
||||
}
|
||||
return normalized, runtime, nil
|
||||
}
|
||||
|
||||
func marshalIndented(value any) ([]byte, error) {
|
||||
data, err := jsonMarshalIndent(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(data, '\n'), nil
|
||||
}
|
||||
|
||||
// jsonMarshalIndent is a variable so file-writing failure paths can be tested.
|
||||
var jsonMarshalIndent = func(value any) ([]byte, error) {
|
||||
return json.MarshalIndent(value, "", "\t")
|
||||
}
|
||||
|
||||
func writeConfig(path string, doc ConfigDocument) error {
|
||||
data, err := marshalIndented(doc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
mode := os.FileMode(0o644)
|
||||
if info, statErr := os.Stat(path); statErr == nil {
|
||||
mode = info.Mode().Perm()
|
||||
backup := fmt.Sprintf("%s.bak-%s", path, time.Now().Format("20060102-150405.000000000"))
|
||||
if err := copyFile(path, backup, mode); err != nil {
|
||||
return fmt.Errorf("backup config: %w", err)
|
||||
}
|
||||
pruneBackups(path, 10)
|
||||
} else if !errors.Is(statErr, os.ErrNotExist) {
|
||||
return statErr
|
||||
}
|
||||
return atomicWrite(path, data, mode, true)
|
||||
}
|
||||
|
||||
func writeStatsFile(path string, value any) error {
|
||||
data, err := marshalIndented(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
return atomicWrite(path, data, 0o644, false)
|
||||
}
|
||||
|
||||
func atomicWrite(path string, data []byte, mode os.FileMode, allowBusyFallback bool) error {
|
||||
directory := filepath.Dir(path)
|
||||
tmp, err := os.CreateTemp(directory, ".serverstatus-*.tmp")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmpPath := tmp.Name()
|
||||
defer os.Remove(tmpPath)
|
||||
|
||||
if err := tmp.Chmod(mode); err != nil {
|
||||
tmp.Close()
|
||||
return err
|
||||
}
|
||||
if _, err := tmp.Write(data); err != nil {
|
||||
tmp.Close()
|
||||
return err
|
||||
}
|
||||
if err := tmp.Sync(); err != nil {
|
||||
tmp.Close()
|
||||
return err
|
||||
}
|
||||
if err := tmp.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Rename(tmpPath, path); err == nil {
|
||||
return syncDirectory(directory)
|
||||
} else if !allowBusyFallback || !errors.Is(err, syscall.EBUSY) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Docker cannot rename over a single-file bind mount. The backup above is
|
||||
// already durable, so truncate and sync the mounted inode as a fallback.
|
||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = file.Write(data); err == nil {
|
||||
err = file.Sync()
|
||||
}
|
||||
closeErr := file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return closeErr
|
||||
}
|
||||
|
||||
func copyFile(source, destination string, mode os.FileMode) error {
|
||||
in, err := os.Open(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
out, err := os.OpenFile(destination, os.O_CREATE|os.O_EXCL|os.O_WRONLY, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = io.Copy(out, in); err == nil {
|
||||
err = out.Sync()
|
||||
}
|
||||
closeErr := out.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return closeErr
|
||||
}
|
||||
|
||||
func pruneBackups(configPath string, keep int) {
|
||||
matches, err := filepath.Glob(configPath + ".bak-*")
|
||||
if err != nil || len(matches) <= keep {
|
||||
return
|
||||
}
|
||||
sort.Strings(matches)
|
||||
for _, path := range matches[:len(matches)-keep] {
|
||||
_ = os.Remove(path)
|
||||
}
|
||||
}
|
||||
|
||||
func syncDirectory(directory string) error {
|
||||
dir, err := os.Open(directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dir.Close()
|
||||
return dir.Sync()
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
module github.com/cppla/serverstatus/server
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/expr-lang/expr v1.17.8
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.59.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||
golang.org/x/arch v0.22.0 // indirect
|
||||
golang.org/x/crypto v0.52.0 // indirect
|
||||
golang.org/x/net v0.55.0 // indirect
|
||||
golang.org/x/sys v0.45.0 // indirect
|
||||
golang.org/x/text v0.37.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
)
|
||||
@@ -0,0 +1,91 @@
|
||||
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/expr-lang/expr v1.17.8 h1:W1loDTT+0PQf5YteHSTpju2qfUfNoBt4yw9+wOEU9VM=
|
||||
github.com/expr-lang/expr v1.17.8/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
|
||||
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.59.1 h1:0Gmua0HW1Tv7ANR7hUYwRyD0MG5OJfgvYSZasGZzBic=
|
||||
github.com/quic-go/quic-go v0.59.1/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
|
||||
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
|
||||
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -0,0 +1,397 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "2.0.0"
|
||||
commit = "none"
|
||||
buildTime = "unknown"
|
||||
)
|
||||
|
||||
func (a *App) HTTPServer() *http.Server {
|
||||
if !a.opts.Verbose {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
return &http.Server{
|
||||
Addr: a.opts.HTTPAddr,
|
||||
Handler: a.router(),
|
||||
ReadHeaderTimeout: 5 * time.Second,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 60 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) router() *gin.Engine {
|
||||
router := gin.New()
|
||||
router.Use(gin.Recovery(), a.securityHeaders(), a.corsMiddleware())
|
||||
if a.opts.Verbose {
|
||||
router.Use(gin.Logger())
|
||||
}
|
||||
|
||||
router.GET("/api/health", a.healthHandler)
|
||||
router.GET("/api/schema", a.schemaHandler)
|
||||
router.GET("/api/openapi.json", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, openAPISpec())
|
||||
})
|
||||
router.GET("/json/stats.json", func(c *gin.Context) {
|
||||
c.Header("Cache-Control", "no-store")
|
||||
c.JSON(http.StatusOK, a.SnapshotStats())
|
||||
})
|
||||
|
||||
api := router.Group("/api", a.authMiddleware())
|
||||
api.GET("/config", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true, "config": a.ConfigSnapshot()})
|
||||
})
|
||||
api.PUT("/config", func(c *gin.Context) {
|
||||
body, apiErr := decodeRequestObject(c)
|
||||
if apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
doc, apiErr := a.ReplaceConfig(ConfigDocument(body))
|
||||
if apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true, "reloaded": true, "pid": os.Getpid(), "generation": a.generation.Load(), "config": doc})
|
||||
})
|
||||
|
||||
for _, collection := range []string{"servers", "monitors", "sslcerts", "watchdog"} {
|
||||
key := collection
|
||||
api.GET("/"+key, func(c *gin.Context) { a.getCollectionHandler(c, key) })
|
||||
api.POST("/"+key, func(c *gin.Context) { a.createCollectionHandler(c, key) })
|
||||
api.PUT("/"+key+"/:id", func(c *gin.Context) { a.updateCollectionHandler(c, key) })
|
||||
api.DELETE("/"+key+"/:id", func(c *gin.Context) { a.deleteCollectionHandler(c, key) })
|
||||
}
|
||||
api.POST("/servers/:id/reset-traffic", a.resetTrafficHandler)
|
||||
api.POST("/reload", func(c *gin.Context) {
|
||||
if apiErr := a.ReloadConfig(); apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true, "operation": "reload", "pid": os.Getpid(), "generation": a.generation.Load()})
|
||||
})
|
||||
api.POST("/restart", func(c *gin.Context) {
|
||||
if apiErr := a.ReloadConfig(); apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusAccepted, gin.H{"ok": true, "operation": "restart", "mode": "in-process", "pid": os.Getpid(), "generation": a.generation.Load()})
|
||||
})
|
||||
|
||||
router.NoRoute(a.staticHandler)
|
||||
return router
|
||||
}
|
||||
|
||||
func (a *App) securityHeaders() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Header("X-Content-Type-Options", "nosniff")
|
||||
c.Header("X-Frame-Options", "SAMEORIGIN")
|
||||
c.Header("Referrer-Policy", "same-origin")
|
||||
if strings.HasPrefix(c.Request.URL.Path, "/api/") {
|
||||
c.Header("Cache-Control", "no-store")
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) corsMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if a.opts.CORSOrigin != "" {
|
||||
c.Header("Access-Control-Allow-Origin", a.opts.CORSOrigin)
|
||||
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Admin-Token")
|
||||
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
c.Header("Vary", "Origin")
|
||||
}
|
||||
if c.Request.Method == http.MethodOptions && strings.HasPrefix(c.Request.URL.Path, "/api/") {
|
||||
c.AbortWithStatus(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) authMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if a.opts.AdminToken == "" {
|
||||
a.writeAPIError(c, &APIError{Status: 503, Message: "management API is disabled; set ADMIN_TOKEN to enable it"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
token := ""
|
||||
authorization := c.GetHeader("Authorization")
|
||||
if len(authorization) >= 7 && strings.EqualFold(authorization[:7], "bearer ") {
|
||||
token = strings.TrimSpace(authorization[7:])
|
||||
}
|
||||
if token == "" {
|
||||
token = strings.TrimSpace(c.GetHeader("X-Admin-Token"))
|
||||
}
|
||||
if len(token) != len(a.opts.AdminToken) || subtle.ConstantTimeCompare([]byte(token), []byte(a.opts.AdminToken)) != 1 {
|
||||
a.writeAPIError(c, &APIError{Status: 401, Message: "invalid or missing admin token"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) healthHandler(c *gin.Context) {
|
||||
running := a.agentRunning.Load()
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"ok": true, "enabled": a.opts.AdminToken != "",
|
||||
"service": gin.H{"running": true, "pid": os.Getpid(), "version": version, "uptime": int64(time.Since(a.startedAt).Seconds()), "generation": a.generation.Load()},
|
||||
"agent": gin.H{"running": running, "address": a.opts.AgentAddr},
|
||||
"configPath": a.opts.ConfigPath,
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) schemaHandler(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true, "schema": apiSchema(a.opts.AdminToken != "")})
|
||||
}
|
||||
|
||||
func apiSchema(enabled bool) map[string]any {
|
||||
endpoints := []any{
|
||||
map[string]any{"method": "GET", "path": "/api/health", "auth": false},
|
||||
map[string]any{"method": "GET", "path": "/api/schema", "auth": false},
|
||||
map[string]any{"method": "GET", "path": "/api/openapi.json", "auth": false},
|
||||
map[string]any{"method": "GET", "path": "/api/config", "auth": true},
|
||||
map[string]any{"method": "PUT", "path": "/api/config", "auth": true, "body": "full config JSON"},
|
||||
}
|
||||
for _, key := range []string{"servers", "monitors", "sslcerts", "watchdog"} {
|
||||
spec := collectionSpecs[key]
|
||||
endpoints = append(endpoints,
|
||||
map[string]any{"method": "GET", "path": "/api/" + key, "auth": true},
|
||||
map[string]any{"method": "POST", "path": "/api/" + key, "auth": true, "body": spec.itemName + " JSON"},
|
||||
map[string]any{"method": "PUT", "path": "/api/" + key + "/{id}", "auth": true, "body": spec.itemName + " JSON"},
|
||||
map[string]any{"method": "DELETE", "path": "/api/" + key + "/{id}", "auth": true},
|
||||
)
|
||||
}
|
||||
endpoints = append(endpoints,
|
||||
map[string]any{"method": "POST", "path": "/api/servers/{username}/reset-traffic", "auth": true},
|
||||
map[string]any{"method": "POST", "path": "/api/reload", "auth": true},
|
||||
map[string]any{"method": "POST", "path": "/api/restart", "auth": true},
|
||||
)
|
||||
collections := make(map[string]any)
|
||||
for key, spec := range collectionSpecs {
|
||||
collections[key] = map[string]any{"item": spec.itemName, "idField": spec.idField, "required": spec.required, "optional": spec.optional}
|
||||
}
|
||||
return map[string]any{
|
||||
"version": version,
|
||||
"auth": map[string]any{"type": "bearer", "header": "Authorization: Bearer <ADMIN_TOKEN>", "enabled": enabled},
|
||||
"endpoints": endpoints, "collections": collections,
|
||||
}
|
||||
}
|
||||
|
||||
func decodeRequestObject(c *gin.Context) (map[string]any, *APIError) {
|
||||
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxRequestBody)
|
||||
decoder := json.NewDecoder(c.Request.Body)
|
||||
decoder.UseNumber()
|
||||
var object map[string]any
|
||||
if err := decoder.Decode(&object); err != nil {
|
||||
status := http.StatusBadRequest
|
||||
if strings.Contains(err.Error(), "request body too large") {
|
||||
status = http.StatusRequestEntityTooLarge
|
||||
}
|
||||
return nil, &APIError{Status: status, Message: "invalid JSON body", Details: map[string]any{"error": err.Error()}}
|
||||
}
|
||||
if object == nil {
|
||||
return nil, &APIError{Status: 400, Message: "request body must be an object"}
|
||||
}
|
||||
var trailing any
|
||||
if err := decoder.Decode(&trailing); !errors.Is(err, io.EOF) {
|
||||
return nil, &APIError{Status: 400, Message: "request body must contain one JSON value"}
|
||||
}
|
||||
return object, nil
|
||||
}
|
||||
|
||||
func (a *App) getCollectionHandler(c *gin.Context, key string) {
|
||||
doc := a.ConfigSnapshot()
|
||||
items, _ := doc[key].([]any)
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true, key: items})
|
||||
}
|
||||
|
||||
func (a *App) createCollectionHandler(c *gin.Context, key string) {
|
||||
item, apiErr := decodeRequestObject(c)
|
||||
if apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
doc, apiErr := a.MutateConfig(func(doc ConfigDocument) *APIError {
|
||||
items, _ := doc[key].([]any)
|
||||
doc[key] = append(items, item)
|
||||
return nil
|
||||
})
|
||||
if apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
items, _ := doc[key].([]any)
|
||||
created := items[len(items)-1]
|
||||
c.JSON(http.StatusCreated, gin.H{"ok": true, collectionSpecs[key].itemName: created, "reloaded": true, "pid": os.Getpid(), "config": doc})
|
||||
}
|
||||
|
||||
func (a *App) updateCollectionHandler(c *gin.Context, key string) {
|
||||
item, apiErr := decodeRequestObject(c)
|
||||
if apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
a.writeAPIError(c, &APIError{Status: 400, Message: "item id is required"})
|
||||
return
|
||||
}
|
||||
var updated any
|
||||
doc, apiErr := a.MutateConfig(func(doc ConfigDocument) *APIError {
|
||||
items, _ := doc[key].([]any)
|
||||
index, _, findErr := findCollectionItem(items, collectionSpecs[key].idField, id, key != "servers")
|
||||
if findErr != nil {
|
||||
return findErr
|
||||
}
|
||||
if index < 0 {
|
||||
return &APIError{Status: 404, Message: collectionSpecs[key].itemName + " was not found", Details: map[string]any{"id": id}}
|
||||
}
|
||||
items[index] = item
|
||||
doc[key] = items
|
||||
updated = item
|
||||
return nil
|
||||
})
|
||||
if apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
// Return the normalized item from the resulting document.
|
||||
items, _ := doc[key].([]any)
|
||||
if itemMap, ok := updated.(map[string]any); ok {
|
||||
idValue := fmt.Sprint(itemMap[collectionSpecs[key].idField])
|
||||
if index, normalized, _ := findCollectionItem(items, collectionSpecs[key].idField, idValue, key != "servers"); index >= 0 {
|
||||
updated = normalized
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true, collectionSpecs[key].itemName: updated, "reloaded": true, "pid": os.Getpid(), "config": doc})
|
||||
}
|
||||
|
||||
func (a *App) deleteCollectionHandler(c *gin.Context, key string) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
a.writeAPIError(c, &APIError{Status: 400, Message: "item id is required"})
|
||||
return
|
||||
}
|
||||
var removed any
|
||||
doc, apiErr := a.MutateConfig(func(doc ConfigDocument) *APIError {
|
||||
items, _ := doc[key].([]any)
|
||||
index, item, findErr := findCollectionItem(items, collectionSpecs[key].idField, id, key != "servers")
|
||||
if findErr != nil {
|
||||
return findErr
|
||||
}
|
||||
if index < 0 {
|
||||
return &APIError{Status: 404, Message: collectionSpecs[key].itemName + " was not found", Details: map[string]any{"id": id}}
|
||||
}
|
||||
removed = item
|
||||
doc[key] = append(items[:index], items[index+1:]...)
|
||||
return nil
|
||||
})
|
||||
if apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true, "removed": removed, "reloaded": true, "pid": os.Getpid(), "config": doc})
|
||||
}
|
||||
|
||||
func findCollectionItem(items []any, idField, id string, allowIndex bool) (int, any, *APIError) {
|
||||
if numeric, err := strconv.Atoi(id); allowIndex && err == nil {
|
||||
if numeric >= 0 && numeric < len(items) {
|
||||
return numeric, items[numeric], nil
|
||||
}
|
||||
return -1, nil, nil
|
||||
}
|
||||
matches := make([]int, 0, 1)
|
||||
for index, raw := range items {
|
||||
item, ok := raw.(map[string]any)
|
||||
if ok && fmt.Sprint(item[idField]) == id {
|
||||
matches = append(matches, index)
|
||||
}
|
||||
}
|
||||
if len(matches) > 1 {
|
||||
return -1, nil, &APIError{Status: 409, Message: "collection has duplicate " + idField + "; use numeric index instead", Details: map[string]any{"id": id}}
|
||||
}
|
||||
if len(matches) == 1 {
|
||||
return matches[0], items[matches[0]], nil
|
||||
}
|
||||
return -1, nil, nil
|
||||
}
|
||||
|
||||
func (a *App) resetTrafficHandler(c *gin.Context) {
|
||||
username := c.Param("id")
|
||||
if username == "" {
|
||||
a.writeAPIError(c, &APIError{Status: 400, Message: "username is required"})
|
||||
return
|
||||
}
|
||||
result, apiErr := a.ResetTraffic(username)
|
||||
if apiErr != nil {
|
||||
a.writeAPIError(c, apiErr)
|
||||
return
|
||||
}
|
||||
result["ok"] = true
|
||||
result["operation"] = "reset-traffic"
|
||||
result["pid"] = os.Getpid()
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (a *App) writeAPIError(c *gin.Context, apiErr *APIError) {
|
||||
payload := gin.H{"ok": false, "error": apiErr.Message}
|
||||
if apiErr.Details != nil {
|
||||
payload["details"] = apiErr.Details
|
||||
}
|
||||
c.JSON(apiErr.Status, payload)
|
||||
}
|
||||
|
||||
func (a *App) staticHandler(c *gin.Context) {
|
||||
if strings.HasPrefix(c.Request.URL.Path, "/api/") || strings.HasPrefix(c.Request.URL.Path, "/json/") {
|
||||
c.JSON(http.StatusNotFound, gin.H{"ok": false, "error": "endpoint was not found"})
|
||||
return
|
||||
}
|
||||
requestPath := filepath.Clean("/" + c.Request.URL.Path)
|
||||
if requestPath == "/" {
|
||||
requestPath = "/index.html"
|
||||
}
|
||||
root, err := filepath.Abs(a.opts.WebDir)
|
||||
if err != nil {
|
||||
c.Status(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
filePath := filepath.Join(root, strings.TrimPrefix(requestPath, "/"))
|
||||
if filePath != root && !strings.HasPrefix(filePath, root+string(os.PathSeparator)) {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
info, err := os.Stat(filePath)
|
||||
if err != nil || info.IsDir() {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if contentType := mime.TypeByExtension(filepath.Ext(filePath)); contentType != "" {
|
||||
c.Header("Content-Type", contentType)
|
||||
}
|
||||
if filepath.Base(filePath) == "index.html" {
|
||||
c.Header("Cache-Control", "no-cache")
|
||||
}
|
||||
http.ServeFile(c.Writer, c.Request, filePath)
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPAPIAndStaticUI(t *testing.T) {
|
||||
app := newTestApp(t, minimalTestConfig())
|
||||
router := app.router()
|
||||
|
||||
response := performRequest(router, http.MethodGet, "/", "", "")
|
||||
if response.Code != 200 || !strings.Contains(response.Body.String(), "test-ui") {
|
||||
t.Fatalf("static UI: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodGet, "/api/health", "", "")
|
||||
if response.Code != 200 || !strings.Contains(response.Body.String(), `"enabled":true`) {
|
||||
t.Fatalf("health: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodGet, "/api/openapi.json", "", "")
|
||||
if response.Code != 200 {
|
||||
t.Fatalf("openapi: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
var openapi map[string]any
|
||||
if err := json.Unmarshal(response.Body.Bytes(), &openapi); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
paths := openapi["paths"].(map[string]any)
|
||||
if openapi["openapi"] != "3.1.0" || paths["/api/servers/{username}"] == nil || paths["/api/watchdog/{id}"] == nil {
|
||||
t.Fatalf("OpenAPI document is incomplete: %#v", openapi)
|
||||
}
|
||||
monitorOperations := paths["/api/monitors"].(map[string]any)
|
||||
createResponses := monitorOperations["post"].(map[string]any)["responses"].(map[string]any)
|
||||
if createResponses["201"] == nil || createResponses["200"] != nil {
|
||||
t.Fatalf("OpenAPI create response must describe HTTP 201: %#v", createResponses)
|
||||
}
|
||||
listResponses := monitorOperations["get"].(map[string]any)["responses"].(map[string]any)
|
||||
listSchema := listResponses["200"].(map[string]any)["content"].(map[string]any)["application/json"].(map[string]any)["schema"].(map[string]any)
|
||||
if listSchema["properties"].(map[string]any)["monitors"] == nil {
|
||||
t.Fatalf("OpenAPI list response does not expose monitors: %#v", listSchema)
|
||||
}
|
||||
restartResponses := paths["/api/restart"].(map[string]any)["post"].(map[string]any)["responses"].(map[string]any)
|
||||
if restartResponses["202"] == nil {
|
||||
t.Fatalf("OpenAPI restart response must describe HTTP 202: %#v", restartResponses)
|
||||
}
|
||||
response = performRequest(router, http.MethodGet, "/api/config", "", "wrong")
|
||||
if response.Code != http.StatusUnauthorized {
|
||||
t.Fatalf("expected 401, got %d", response.Code)
|
||||
}
|
||||
response = performRequest(router, http.MethodGet, "/api/config", "", "test-token")
|
||||
if response.Code != 200 {
|
||||
t.Fatalf("config: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
|
||||
monitor := `{"name":"新增服务","host":"tcp://127.0.0.1:80","type":"tcp","interval":"30"}`
|
||||
response = performRequest(router, http.MethodPost, "/api/monitors", monitor, "test-token")
|
||||
if response.Code != http.StatusCreated || !strings.Contains(response.Body.String(), "新增服务") {
|
||||
t.Fatalf("create monitor: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
path := "/api/monitors/" + url.PathEscape("新增服务")
|
||||
monitor = `{"name":"更新服务","host":"https://example.org","type":"https","interval":45}`
|
||||
response = performRequest(router, http.MethodPut, path, monitor, "test-token")
|
||||
if response.Code != 200 || !strings.Contains(response.Body.String(), "更新服务") {
|
||||
t.Fatalf("update monitor: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodDelete, "/api/monitors/"+url.PathEscape("更新服务"), "", "test-token")
|
||||
if response.Code != 200 {
|
||||
t.Fatalf("delete monitor: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
percentMonitor := `{"name":"rate%check","host":"https://example.com","type":"https","interval":30}`
|
||||
response = performRequest(router, http.MethodPost, "/api/monitors", percentMonitor, "test-token")
|
||||
if response.Code != http.StatusCreated {
|
||||
t.Fatalf("create percent monitor: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodDelete, "/api/monitors/"+url.PathEscape("rate%check"), "", "test-token")
|
||||
if response.Code != 200 {
|
||||
t.Fatalf("delete percent monitor: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
|
||||
server := `{"username":"s02","name":"node2","type":"kvm","host":"host2","location":"JP","password":"secret","monthstart":31}`
|
||||
response = performRequest(router, http.MethodPost, "/api/servers", server, "test-token")
|
||||
if response.Code != http.StatusCreated || !strings.Contains(response.Body.String(), `"monthstart":28`) {
|
||||
t.Fatalf("create server: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodDelete, "/api/servers/s02", "", "test-token")
|
||||
if response.Code != 200 {
|
||||
t.Fatalf("delete server: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
numericServer := `{"username":"0","name":"numeric","type":"kvm","host":"host0","location":"US","password":"secret","monthstart":1}`
|
||||
response = performRequest(router, http.MethodPost, "/api/servers", numericServer, "test-token")
|
||||
if response.Code != http.StatusCreated {
|
||||
t.Fatalf("create numeric server: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
numericServer = `{"username":"0","name":"numeric-updated","type":"kvm","host":"host0","location":"US","password":"secret","monthstart":1}`
|
||||
response = performRequest(router, http.MethodPut, "/api/servers/0", numericServer, "test-token")
|
||||
if response.Code != 200 || !strings.Contains(response.Body.String(), "numeric-updated") {
|
||||
t.Fatalf("update numeric server: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodDelete, "/api/servers/0", "", "test-token")
|
||||
if response.Code != 200 || !strings.Contains(response.Body.String(), "numeric-updated") {
|
||||
t.Fatalf("delete numeric server: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
if app.RuntimeSnapshot().Servers[0].Username != "s01" {
|
||||
t.Fatal("numeric username operation modified the server at numeric index")
|
||||
}
|
||||
|
||||
response = performRequest(router, http.MethodPost, "/api/servers/s01/reset-traffic", "", "test-token")
|
||||
if response.Code != http.StatusConflict {
|
||||
t.Fatalf("offline reset should conflict: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodPost, "/api/reload", "", "test-token")
|
||||
if response.Code != 200 {
|
||||
t.Fatalf("reload: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodPost, "/api/restart", "", "test-token")
|
||||
if response.Code != http.StatusAccepted || !strings.Contains(response.Body.String(), "in-process") {
|
||||
t.Fatalf("restart: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(app.opts.ConfigPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var persisted map[string]any
|
||||
if err := json.Unmarshal(data, &persisted); err != nil {
|
||||
t.Fatalf("persisted config is invalid: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPRejectsInvalidAndOversizedBodies(t *testing.T) {
|
||||
app := newTestApp(t, minimalTestConfig())
|
||||
router := app.router()
|
||||
response := performRequest(router, http.MethodPost, "/api/servers", `{"name":`, "test-token")
|
||||
if response.Code != 400 {
|
||||
t.Fatalf("invalid JSON: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
response = performRequest(router, http.MethodPost, "/api/servers", `{"name":"x"}`, "test-token")
|
||||
if response.Code != 400 {
|
||||
t.Fatalf("missing fields: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
oversized := `{"name":"` + strings.Repeat("x", maxRequestBody) + `"}`
|
||||
response = performRequest(router, http.MethodPost, "/api/servers", oversized, "test-token")
|
||||
if response.Code != http.StatusRequestEntityTooLarge {
|
||||
t.Fatalf("oversized body: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
|
||||
doc := app.ConfigSnapshot()
|
||||
doc["watchdog"] = []any{map[string]any{"name": "broken", "rule": "cpu >", "interval": 10}}
|
||||
data, _ := json.Marshal(doc)
|
||||
response = performRequest(router, http.MethodPut, "/api/config", string(data), "test-token")
|
||||
if response.Code != 400 {
|
||||
t.Fatalf("invalid watchdog: status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
#ifndef ARGPARSE_H
|
||||
#define ARGPARSE_H
|
||||
|
||||
/**
|
||||
* Command-line arguments parsing library.
|
||||
*
|
||||
* This module is inspired by parse-options.c (git) and python's argparse
|
||||
* module.
|
||||
*
|
||||
* Arguments parsing is common task in cli program, but traditional `getopt`
|
||||
* libraries are not easy to use. This library provides high-level arguments
|
||||
* parsing solutions.
|
||||
*
|
||||
* The program defines what arguments it requires, and `argparse` will figure
|
||||
* out how to parse those out of `argc` and `argv`, it also automatically
|
||||
* generates help and usage messages and issues errors when users give the
|
||||
* program invalid arguments.
|
||||
*
|
||||
* Reserved namespaces:
|
||||
* argparse
|
||||
* OPT
|
||||
* Author: Yecheng Fu <cofyc.jackson@gmail.com>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct argparse;
|
||||
struct argparse_option;
|
||||
|
||||
typedef int argparse_callback(struct argparse *this_,
|
||||
const struct argparse_option *option);
|
||||
|
||||
enum argparse_flag {
|
||||
ARGPARSE_STOP_AT_NON_OPTION = 1,
|
||||
};
|
||||
|
||||
enum argparse_option_type {
|
||||
/* special */
|
||||
ARGPARSE_OPT_END,
|
||||
/* options with no arguments */
|
||||
ARGPARSE_OPT_BOOLEAN,
|
||||
ARGPARSE_OPT_BIT,
|
||||
/* options with arguments (optional or required) */
|
||||
ARGPARSE_OPT_INTEGER,
|
||||
ARGPARSE_OPT_STRING,
|
||||
};
|
||||
|
||||
enum argparse_option_flags {
|
||||
OPT_NONEG = 1, /* Negation disabled. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Argparse option struct.
|
||||
*
|
||||
* `type`:
|
||||
* holds the type of the option, you must have an ARGPARSE_OPT_END last in your
|
||||
* array.
|
||||
*
|
||||
* `short_name`:
|
||||
* the character to use as a short option name, '\0' if none.
|
||||
*
|
||||
* `long_name`:
|
||||
* the long option name, without the leading dash, NULL if none.
|
||||
*
|
||||
* `value`:
|
||||
* stores pointer to the value to be filled.
|
||||
*
|
||||
* `help`:
|
||||
* the short help message associated to what the option does.
|
||||
* Must never be NULL (except for ARGPARSE_OPT_END).
|
||||
*
|
||||
* `callback`:
|
||||
* function is called when corresponding argument is parsed.
|
||||
*
|
||||
* `data`:
|
||||
* associated data. Callbacks can use it like they want.
|
||||
*
|
||||
* `flags`:
|
||||
* option flags.
|
||||
*
|
||||
*/
|
||||
struct argparse_option {
|
||||
enum argparse_option_type type;
|
||||
const char short_name;
|
||||
const char *long_name;
|
||||
void *value;
|
||||
const char *help;
|
||||
argparse_callback *callback;
|
||||
intptr_t data;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* argpparse
|
||||
*/
|
||||
struct argparse {
|
||||
// user supplied
|
||||
const struct argparse_option *options;
|
||||
const char *usage;
|
||||
int flags;
|
||||
// internal context
|
||||
int argc;
|
||||
const char **argv;
|
||||
const char **out;
|
||||
int cpidx;
|
||||
const char *optvalue; // current option value
|
||||
};
|
||||
|
||||
// builtin callbacks
|
||||
int argparse_help_cb(struct argparse *this_,
|
||||
const struct argparse_option *option);
|
||||
|
||||
// builtin option macros
|
||||
#define OPT_END() { ARGPARSE_OPT_END, 0 }
|
||||
#define OPT_BOOLEAN(...) { ARGPARSE_OPT_BOOLEAN, __VA_ARGS__ }
|
||||
#define OPT_BIT(...) { ARGPARSE_OPT_BIT, __VA_ARGS__ }
|
||||
#define OPT_INTEGER(...) { ARGPARSE_OPT_INTEGER, __VA_ARGS__ }
|
||||
#define OPT_STRING(...) { ARGPARSE_OPT_STRING, __VA_ARGS__ }
|
||||
#define OPT_HELP() OPT_BOOLEAN('h', "help", 0, "Show this help message and exit", argparse_help_cb)
|
||||
|
||||
int argparse_init(struct argparse *this_, struct argparse_option *options,
|
||||
const char *usage, int flags);
|
||||
int argparse_parse(struct argparse *this_, int argc, const char **argv);
|
||||
void argparse_usage(struct argparse *this_);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,149 +0,0 @@
|
||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
#ifndef BASE_DETECT_H
|
||||
#define BASE_DETECT_H
|
||||
|
||||
/*
|
||||
this file detected the family, platform and architecture
|
||||
to compile for.
|
||||
*/
|
||||
|
||||
/* platforms */
|
||||
|
||||
/* windows Family */
|
||||
#if defined(WIN64) || defined(_WIN64)
|
||||
/* Hmm, is this IA64 or x86-64? */
|
||||
#define CONF_FAMILY_WINDOWS 1
|
||||
#define CONF_FAMILY_STRING "windows"
|
||||
#define CONF_PLATFORM_WIN64 1
|
||||
#define CONF_PLATFORM_STRING "win64"
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
#define CONF_FAMILY_WINDOWS 1
|
||||
#define CONF_FAMILY_STRING "windows"
|
||||
#define CONF_PLATFORM_WIN32 1
|
||||
#define CONF_PLATFORM_STRING "win32"
|
||||
#endif
|
||||
|
||||
/* unix family */
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#define CONF_FAMILY_UNIX 1
|
||||
#define CONF_FAMILY_STRING "unix"
|
||||
#define CONF_PLATFORM_FREEBSD 1
|
||||
#define CONF_PLATFORM_STRING "freebsd"
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
#define CONF_FAMILY_UNIX 1
|
||||
#define CONF_FAMILY_STRING "unix"
|
||||
#define CONF_PLATFORM_OPENBSD 1
|
||||
#define CONF_PLATFORM_STRING "openbsd"
|
||||
#endif
|
||||
|
||||
#if defined(__LINUX__) || defined(__linux__)
|
||||
#define CONF_FAMILY_UNIX 1
|
||||
#define CONF_FAMILY_STRING "unix"
|
||||
#define CONF_PLATFORM_LINUX 1
|
||||
#define CONF_PLATFORM_STRING "linux"
|
||||
#endif
|
||||
|
||||
#if defined(__GNU__) || defined(__gnu__)
|
||||
#define CONF_FAMILY_UNIX 1
|
||||
#define CONF_FAMILY_STRING "unix"
|
||||
#define CONF_PLATFORM_HURD 1
|
||||
#define CONF_PLATFORM_STRING "gnu"
|
||||
#endif
|
||||
|
||||
#if defined(MACOSX) || defined(__APPLE__) || defined(__DARWIN__)
|
||||
#define CONF_FAMILY_UNIX 1
|
||||
#define CONF_FAMILY_STRING "unix"
|
||||
#define CONF_PLATFORM_MACOSX 1
|
||||
#define CONF_PLATFORM_STRING "macosx"
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
#define CONF_FAMILY_UNIX 1
|
||||
#define CONF_FAMILY_STRING "unix"
|
||||
#define CONF_PLATFORM_SOLARIS 1
|
||||
#define CONF_PLATFORM_STRING "solaris"
|
||||
#endif
|
||||
|
||||
/* beos family */
|
||||
#if defined(__BeOS) || defined(__BEOS__)
|
||||
#define CONF_FAMILY_BEOS 1
|
||||
#define CONF_FAMILY_STRING "beos"
|
||||
#define CONF_PLATFORM_BEOS 1
|
||||
#define CONF_PLATFORM_STRING "beos"
|
||||
#endif
|
||||
|
||||
|
||||
/* use gcc endianness definitions when available */
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__MINGW32__) && !defined(__sun)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/endian.h>
|
||||
#else
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define CONF_ARCH_ENDIAN_BIG 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* architectures */
|
||||
#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(CONF_PLATFORM_WIN32)
|
||||
#define CONF_ARCH_IA32 1
|
||||
#define CONF_ARCH_STRING "ia32"
|
||||
#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
|
||||
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__ia64__) || defined(_M_IA64)
|
||||
#define CONF_ARCH_IA64 1
|
||||
#define CONF_ARCH_STRING "ia64"
|
||||
#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
|
||||
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__amd64__) || defined(__x86_64__) || defined(_M_X64)
|
||||
#define CONF_ARCH_AMD64 1
|
||||
#define CONF_ARCH_STRING "amd64"
|
||||
#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
|
||||
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__powerpc__) || defined(__ppc__)
|
||||
#define CONF_ARCH_PPC 1
|
||||
#define CONF_ARCH_STRING "ppc"
|
||||
#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
|
||||
#define CONF_ARCH_ENDIAN_BIG 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__sparc__)
|
||||
#define CONF_ARCH_SPARC 1
|
||||
#define CONF_ARCH_STRING "sparc"
|
||||
#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
|
||||
#define CONF_ARCH_ENDIAN_BIG 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef CONF_FAMILY_STRING
|
||||
#define CONF_FAMILY_STRING "unknown"
|
||||
#endif
|
||||
|
||||
#ifndef CONF_PLATFORM_STRING
|
||||
#define CONF_PLATFORM_STRING "unknown"
|
||||
#endif
|
||||
|
||||
#ifndef CONF_ARCH_STRING
|
||||
#define CONF_ARCH_STRING "unknown"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,269 +0,0 @@
|
||||
|
||||
/* vim: set et ts=3 sw=3 sts=3 ft=c:
|
||||
*
|
||||
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
|
||||
* https://github.com/udp/json-parser
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _JSON_H
|
||||
#define _JSON_H
|
||||
|
||||
#ifndef json_char
|
||||
#define json_char char
|
||||
#endif
|
||||
|
||||
#ifndef json_int_t
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#define json_int_t int64_t
|
||||
#else
|
||||
#define json_int_t __int64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long max_memory;
|
||||
int settings;
|
||||
|
||||
/* Custom allocator support (leave null to use malloc/free)
|
||||
*/
|
||||
|
||||
void * (* mem_alloc) (size_t, int zero, void * user_data);
|
||||
void (* mem_free) (void *, void * user_data);
|
||||
|
||||
void * user_data; /* will be passed to mem_alloc and mem_free */
|
||||
|
||||
} json_settings;
|
||||
|
||||
#define json_enable_comments 0x01
|
||||
|
||||
typedef enum
|
||||
{
|
||||
json_none,
|
||||
json_object,
|
||||
json_array,
|
||||
json_integer,
|
||||
json_double,
|
||||
json_string,
|
||||
json_boolean,
|
||||
json_null
|
||||
|
||||
} json_type;
|
||||
|
||||
extern const struct _json_value json_value_none;
|
||||
|
||||
typedef struct _json_value
|
||||
{
|
||||
struct _json_value * parent;
|
||||
|
||||
json_type type;
|
||||
|
||||
union
|
||||
{
|
||||
int boolean;
|
||||
json_int_t integer;
|
||||
double dbl;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
json_char * ptr; /* null terminated */
|
||||
|
||||
} string;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
struct
|
||||
{
|
||||
json_char * name;
|
||||
unsigned int name_length;
|
||||
|
||||
struct _json_value * value;
|
||||
|
||||
} * values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{ return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{ return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} object;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
struct _json_value ** values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{ return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{ return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} array;
|
||||
|
||||
} u;
|
||||
|
||||
union
|
||||
{
|
||||
struct _json_value * next_alloc;
|
||||
void * object_mem;
|
||||
|
||||
} _reserved;
|
||||
|
||||
|
||||
/* Some C++ operator sugar */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
public:
|
||||
|
||||
inline _json_value ()
|
||||
{ memset (this, 0, sizeof (_json_value));
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (int index) const
|
||||
{
|
||||
if (type != json_array || index < 0
|
||||
|| ((unsigned int) index) >= u.array.length)
|
||||
{
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
return *u.array.values [index];
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (const char * index) const
|
||||
{
|
||||
if (type != json_object)
|
||||
return json_value_none;
|
||||
|
||||
for (unsigned int i = 0; i < u.object.length; ++ i)
|
||||
if (!strcmp (u.object.values [i].name, index))
|
||||
return *u.object.values [i].value;
|
||||
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
inline operator const char * () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_string:
|
||||
return u.string.ptr;
|
||||
|
||||
default:
|
||||
return "";
|
||||
};
|
||||
}
|
||||
|
||||
inline operator json_int_t () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_integer:
|
||||
return u.integer;
|
||||
|
||||
case json_double:
|
||||
return (json_int_t) u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
inline operator bool () const
|
||||
{
|
||||
if (type != json_boolean)
|
||||
return false;
|
||||
|
||||
return u.boolean != 0;
|
||||
}
|
||||
|
||||
inline operator double () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_integer:
|
||||
return (double) u.integer;
|
||||
|
||||
case json_double:
|
||||
return u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} json_value;
|
||||
|
||||
json_value * json_parse (const json_char * json,
|
||||
size_t length);
|
||||
|
||||
#define json_error_max 128
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error);
|
||||
|
||||
void json_value_free (json_value *);
|
||||
|
||||
|
||||
/* Not usually necessary, unless you used a custom mem_alloc and now want to
|
||||
* use a custom mem_free.
|
||||
*/
|
||||
void json_value_free_ex (json_settings * settings,
|
||||
json_value *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,138 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var opts Options
|
||||
var legacyBind string
|
||||
var legacyPort int
|
||||
var printVersion bool
|
||||
|
||||
flag.StringVar(&opts.ConfigPath, "config", envOr("CONFIG_PATH", "config.json"), "configuration file")
|
||||
flag.StringVar(&opts.ConfigPath, "c", envOr("CONFIG_PATH", "config.json"), "configuration file (shorthand)")
|
||||
flag.StringVar(&opts.StatsPath, "stats", os.Getenv("STATS_PATH"), "persistent stats JSON file")
|
||||
flag.StringVar(&opts.WebDir, "web-dir", envOr("WEB_DIR", "../web"), "WebUI directory")
|
||||
flag.StringVar(&opts.WebDir, "d", envOr("WEB_DIR", "../web"), "WebUI directory (shorthand)")
|
||||
flag.StringVar(&opts.HTTPAddr, "http", envOr("HTTP_ADDR", ":8080"), "HTTP listen address")
|
||||
flag.StringVar(&opts.AgentAddr, "agent", envOr("AGENT_ADDR", ":35601"), "agent TCP listen address")
|
||||
flag.StringVar(&legacyBind, "bind", "", "agent bind address (legacy compatibility)")
|
||||
flag.StringVar(&legacyBind, "b", "", "agent bind address (legacy shorthand)")
|
||||
flag.IntVar(&legacyPort, "port", 0, "agent TCP port (legacy compatibility)")
|
||||
flag.IntVar(&legacyPort, "p", 0, "agent TCP port (legacy shorthand)")
|
||||
flag.BoolVar(&opts.Verbose, "verbose", envBool("VERBOSE", false), "verbose HTTP logging")
|
||||
flag.BoolVar(&opts.Verbose, "v", envBool("VERBOSE", false), "verbose HTTP logging (shorthand)")
|
||||
flag.BoolVar(&printVersion, "version", false, "print version and exit")
|
||||
flag.Parse()
|
||||
|
||||
if printVersion {
|
||||
fmt.Printf("serverstatus %s commit=%s built=%s\n", version, commit, buildTime)
|
||||
return
|
||||
}
|
||||
if opts.StatsPath == "" {
|
||||
opts.StatsPath = filepath.Join(opts.WebDir, "json", "stats.json")
|
||||
}
|
||||
if legacyPort != 0 || legacyBind != "" {
|
||||
if legacyPort == 0 {
|
||||
legacyPort = 35601
|
||||
}
|
||||
opts.AgentAddr = net.JoinHostPort(legacyBind, strconv.Itoa(legacyPort))
|
||||
}
|
||||
opts.AdminToken = os.Getenv("ADMIN_TOKEN")
|
||||
opts.CORSOrigin = os.Getenv("ADMIN_CORS_ORIGIN")
|
||||
opts.InsecureCallbackTLS = envBool("INSECURE_CALLBACK_TLS", false)
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(opts.StatsPath), 0o755); err != nil {
|
||||
fatalf("create stats directory: %v", err)
|
||||
}
|
||||
app, err := NewApp(opts)
|
||||
if err != nil {
|
||||
fatalf("start: %v", err)
|
||||
}
|
||||
app.StartBackground()
|
||||
|
||||
httpServer := app.HTTPServer()
|
||||
agentServer := NewAgentServer(app)
|
||||
errorsChannel := make(chan error, 2)
|
||||
go func() {
|
||||
app.logger.Printf("HTTP listening on %s", opts.HTTPAddr)
|
||||
if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
errorsChannel <- fmt.Errorf("HTTP server: %w", err)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
if err := agentServer.ListenAndServe(); err != nil {
|
||||
errorsChannel <- fmt.Errorf("agent server: %w", err)
|
||||
}
|
||||
}()
|
||||
|
||||
reloadSignals := make(chan os.Signal, 1)
|
||||
stopSignals := make(chan os.Signal, 1)
|
||||
signal.Notify(reloadSignals, syscall.SIGHUP)
|
||||
signal.Notify(stopSignals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
defer signal.Stop(reloadSignals)
|
||||
defer signal.Stop(stopSignals)
|
||||
|
||||
go func() {
|
||||
for range reloadSignals {
|
||||
if apiErr := app.ReloadConfig(); apiErr != nil {
|
||||
app.logger.Printf("reload config: %s", apiErr.Message)
|
||||
continue
|
||||
}
|
||||
app.logger.Printf("configuration reloaded; generation=%d", app.generation.Load())
|
||||
}
|
||||
}()
|
||||
|
||||
var fatalErr error
|
||||
select {
|
||||
case signalValue := <-stopSignals:
|
||||
app.logger.Printf("received %s; shutting down", signalValue)
|
||||
case fatalErr = <-errorsChannel:
|
||||
app.logger.Printf("fatal: %v", fatalErr)
|
||||
}
|
||||
app.cancel()
|
||||
shutdownContext, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
_ = httpServer.Shutdown(shutdownContext)
|
||||
cancel()
|
||||
app.Close()
|
||||
if fatalErr != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func envOr(name, fallback string) string {
|
||||
if value := strings.TrimSpace(os.Getenv(name)); value != "" {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func envBool(name string, fallback bool) bool {
|
||||
value := strings.TrimSpace(os.Getenv(name))
|
||||
if value == "" {
|
||||
return fallback
|
||||
}
|
||||
parsed, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return fallback
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
func fatalf(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, "serverstatus: "+format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/expr-lang/expr/vm"
|
||||
)
|
||||
|
||||
const maxRequestBody = 1 << 20
|
||||
|
||||
type ConfigDocument map[string]any
|
||||
|
||||
type ServerConfig struct {
|
||||
Username string `json:"username"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Host string `json:"host"`
|
||||
Location string `json:"location"`
|
||||
Password string `json:"password"`
|
||||
MonthStart int `json:"monthstart"`
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
}
|
||||
|
||||
type MonitorConfig struct {
|
||||
Name string `json:"name"`
|
||||
Host string `json:"host"`
|
||||
Interval int `json:"interval"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type SSLCertConfig struct {
|
||||
Name string `json:"name"`
|
||||
Domain string `json:"domain"`
|
||||
Port int `json:"port"`
|
||||
Interval int `json:"interval"`
|
||||
Callback string `json:"callback"`
|
||||
}
|
||||
|
||||
type WatchdogConfig struct {
|
||||
Name string `json:"name"`
|
||||
Rule string `json:"rule"`
|
||||
Interval int `json:"interval"`
|
||||
Callback string `json:"callback"`
|
||||
}
|
||||
|
||||
type CompiledWatchdog struct {
|
||||
WatchdogConfig
|
||||
Key string
|
||||
Normalized string
|
||||
Program *vm.Program
|
||||
}
|
||||
|
||||
type RuntimeConfig struct {
|
||||
Servers []ServerConfig
|
||||
Monitors []MonitorConfig
|
||||
SSLCerts []SSLCertConfig
|
||||
Watchdogs []CompiledWatchdog
|
||||
}
|
||||
|
||||
type AgentStats struct {
|
||||
Uptime int64 `json:"uptime"`
|
||||
Load1 float64 `json:"load_1"`
|
||||
Load5 float64 `json:"load_5"`
|
||||
Load15 float64 `json:"load_15"`
|
||||
Ping10010 float64 `json:"ping_10010"`
|
||||
Ping189 float64 `json:"ping_189"`
|
||||
Ping10086 float64 `json:"ping_10086"`
|
||||
Time10010 int64 `json:"time_10010"`
|
||||
Time189 int64 `json:"time_189"`
|
||||
Time10086 int64 `json:"time_10086"`
|
||||
TCPCount int64 `json:"tcp"`
|
||||
UDPCount int64 `json:"udp"`
|
||||
ProcessCount int64 `json:"process"`
|
||||
ThreadCount int64 `json:"thread"`
|
||||
NetworkRX int64 `json:"network_rx"`
|
||||
NetworkTX int64 `json:"network_tx"`
|
||||
NetworkIn int64 `json:"network_in"`
|
||||
NetworkOut int64 `json:"network_out"`
|
||||
MemoryTotal int64 `json:"memory_total"`
|
||||
MemoryUsed int64 `json:"memory_used"`
|
||||
SwapTotal int64 `json:"swap_total"`
|
||||
SwapUsed int64 `json:"swap_used"`
|
||||
HDDTotal int64 `json:"hdd_total"`
|
||||
HDDUsed int64 `json:"hdd_used"`
|
||||
IORead int64 `json:"io_read"`
|
||||
IOWrite int64 `json:"io_write"`
|
||||
CPU float64 `json:"cpu"`
|
||||
CPUCores int64 `json:"cpu_cores"`
|
||||
CPUModel string `json:"cpu_model"`
|
||||
Custom string `json:"custom"`
|
||||
OS string `json:"os"`
|
||||
Online4 *bool `json:"online4"`
|
||||
Online6 *bool `json:"online6"`
|
||||
}
|
||||
|
||||
type APIError struct {
|
||||
Status int
|
||||
Message string
|
||||
Details any
|
||||
}
|
||||
|
||||
func (e *APIError) Error() string {
|
||||
if e.Details != nil {
|
||||
return fmt.Sprintf("%s: %v", e.Message, e.Details)
|
||||
}
|
||||
return e.Message
|
||||
}
|
||||
|
||||
func decodeDocument(data []byte) (ConfigDocument, error) {
|
||||
decoder := json.NewDecoder(bytes.NewReader(data))
|
||||
decoder.UseNumber()
|
||||
var doc ConfigDocument
|
||||
if err := decoder.Decode(&doc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if doc == nil {
|
||||
return nil, fmt.Errorf("config must be a JSON object")
|
||||
}
|
||||
var extra any
|
||||
if err := decoder.Decode(&extra); !errors.Is(err, io.EOF) {
|
||||
return nil, fmt.Errorf("config contains more than one JSON value")
|
||||
}
|
||||
return doc, nil
|
||||
}
|
||||
|
||||
func cloneDocument(doc ConfigDocument) (ConfigDocument, error) {
|
||||
data, err := json.Marshal(doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return decodeDocument(data)
|
||||
}
|
||||
|
||||
type collectionSpec struct {
|
||||
itemName string
|
||||
idField string
|
||||
required []string
|
||||
optional []string
|
||||
defaults map[string]int
|
||||
}
|
||||
|
||||
var collectionSpecs = map[string]collectionSpec{
|
||||
"servers": {
|
||||
itemName: "server", idField: "username",
|
||||
required: []string{"username", "name", "type", "host", "location", "password"},
|
||||
optional: []string{"monthstart", "disabled"},
|
||||
defaults: map[string]int{"monthstart": 1},
|
||||
},
|
||||
"monitors": {
|
||||
itemName: "monitor", idField: "name",
|
||||
required: []string{"name", "host", "type"},
|
||||
optional: []string{"interval"},
|
||||
defaults: map[string]int{"interval": 600},
|
||||
},
|
||||
"sslcerts": {
|
||||
itemName: "sslcert", idField: "name",
|
||||
required: []string{"name", "domain"},
|
||||
optional: []string{"port", "interval", "callback"},
|
||||
defaults: map[string]int{"port": 443, "interval": 7200},
|
||||
},
|
||||
"watchdog": {
|
||||
itemName: "watchdog", idField: "name",
|
||||
required: []string{"name", "rule"},
|
||||
optional: []string{"interval", "callback"},
|
||||
defaults: map[string]int{"interval": 600},
|
||||
},
|
||||
}
|
||||
|
||||
func normalizeConfig(input ConfigDocument) (ConfigDocument, RuntimeConfig, *APIError) {
|
||||
doc, err := cloneDocument(input)
|
||||
if err != nil {
|
||||
return nil, RuntimeConfig{}, &APIError{Status: 400, Message: "config must be a JSON object", Details: map[string]any{"error": err.Error()}}
|
||||
}
|
||||
|
||||
for _, key := range []string{"servers", "monitors", "sslcerts", "watchdog"} {
|
||||
spec := collectionSpecs[key]
|
||||
raw, exists := doc[key]
|
||||
if !exists || raw == nil {
|
||||
raw = []any{}
|
||||
}
|
||||
items, ok := raw.([]any)
|
||||
if !ok {
|
||||
return nil, RuntimeConfig{}, &APIError{Status: 400, Message: key + " must be an array"}
|
||||
}
|
||||
normalized := make([]any, 0, len(items))
|
||||
seen := make(map[string]struct{})
|
||||
for index, rawItem := range items {
|
||||
item, ok := rawItem.(map[string]any)
|
||||
if !ok {
|
||||
return nil, RuntimeConfig{}, &APIError{Status: 400, Message: spec.itemName + " must be an object", Details: map[string]any{"index": index}}
|
||||
}
|
||||
missing := make([]string, 0)
|
||||
for _, field := range spec.required {
|
||||
value, ok := item[field]
|
||||
text := ""
|
||||
if ok && value != nil {
|
||||
text = strings.TrimSpace(fmt.Sprint(value))
|
||||
}
|
||||
if text == "" {
|
||||
missing = append(missing, field)
|
||||
} else {
|
||||
item[field] = text
|
||||
}
|
||||
}
|
||||
if len(missing) > 0 {
|
||||
return nil, RuntimeConfig{}, &APIError{Status: 400, Message: spec.itemName + " has missing required fields", Details: map[string]any{"missing": missing, "index": index}}
|
||||
}
|
||||
|
||||
for field, fallback := range spec.defaults {
|
||||
value, apiErr := normalizeInteger(item[field], field, index, fallback)
|
||||
if apiErr != nil {
|
||||
return nil, RuntimeConfig{}, apiErr
|
||||
}
|
||||
switch {
|
||||
case key == "servers" && field == "monthstart":
|
||||
value = clamp(value, 1, 28)
|
||||
case key == "sslcerts" && field == "port":
|
||||
value = clamp(value, 1, 65535)
|
||||
default:
|
||||
if value < 1 {
|
||||
value = 1
|
||||
}
|
||||
}
|
||||
item[field] = value
|
||||
}
|
||||
|
||||
if key == "servers" {
|
||||
if value, exists := item["disabled"]; exists {
|
||||
disabled, ok := normalizeBool(value)
|
||||
if !ok {
|
||||
return nil, RuntimeConfig{}, &APIError{Status: 400, Message: "disabled must be a boolean", Details: map[string]any{"index": index}}
|
||||
}
|
||||
item["disabled"] = disabled
|
||||
}
|
||||
username := item["username"].(string)
|
||||
if _, duplicate := seen[username]; duplicate {
|
||||
return nil, RuntimeConfig{}, &APIError{Status: 409, Message: "duplicate server username", Details: map[string]any{"username": username}}
|
||||
}
|
||||
seen[username] = struct{}{}
|
||||
}
|
||||
if key == "sslcerts" || key == "watchdog" {
|
||||
value := item["callback"]
|
||||
if value == nil {
|
||||
item["callback"] = ""
|
||||
} else {
|
||||
item["callback"] = strings.TrimSpace(fmt.Sprint(value))
|
||||
}
|
||||
}
|
||||
normalized = append(normalized, item)
|
||||
}
|
||||
doc[key] = normalized
|
||||
}
|
||||
|
||||
runtime, apiErr := buildRuntimeConfig(doc)
|
||||
if apiErr != nil {
|
||||
return nil, RuntimeConfig{}, apiErr
|
||||
}
|
||||
return doc, runtime, nil
|
||||
}
|
||||
|
||||
func buildRuntimeConfig(doc ConfigDocument) (RuntimeConfig, *APIError) {
|
||||
data, err := json.Marshal(doc)
|
||||
if err != nil {
|
||||
return RuntimeConfig{}, &APIError{Status: 400, Message: "config could not be encoded", Details: map[string]any{"error": err.Error()}}
|
||||
}
|
||||
var raw struct {
|
||||
Servers []ServerConfig `json:"servers"`
|
||||
Monitors []MonitorConfig `json:"monitors"`
|
||||
SSLCerts []SSLCertConfig `json:"sslcerts"`
|
||||
Watchdogs []WatchdogConfig `json:"watchdog"`
|
||||
}
|
||||
if err := json.Unmarshal(data, &raw); err != nil {
|
||||
return RuntimeConfig{}, &APIError{Status: 400, Message: "config has invalid field types", Details: map[string]any{"error": err.Error()}}
|
||||
}
|
||||
runtime := RuntimeConfig{Servers: raw.Servers, Monitors: raw.Monitors, SSLCerts: raw.SSLCerts}
|
||||
for index, rule := range raw.Watchdogs {
|
||||
compiled, err := compileWatchdog(rule, index)
|
||||
if err != nil {
|
||||
return RuntimeConfig{}, &APIError{Status: 400, Message: "watchdog rule is invalid", Details: map[string]any{"index": index, "name": rule.Name, "error": err.Error()}}
|
||||
}
|
||||
runtime.Watchdogs = append(runtime.Watchdogs, compiled)
|
||||
}
|
||||
return runtime, nil
|
||||
}
|
||||
|
||||
func normalizeInteger(raw any, field string, index, fallback int) (int, *APIError) {
|
||||
if raw == nil || raw == "" {
|
||||
return fallback, nil
|
||||
}
|
||||
var value int64
|
||||
var err error
|
||||
switch v := raw.(type) {
|
||||
case json.Number:
|
||||
value, err = strconv.ParseInt(v.String(), 10, 64)
|
||||
case float64:
|
||||
if math.Trunc(v) != v {
|
||||
err = fmt.Errorf("not an integer")
|
||||
} else {
|
||||
value = int64(v)
|
||||
}
|
||||
case float32:
|
||||
if math.Trunc(float64(v)) != float64(v) {
|
||||
err = fmt.Errorf("not an integer")
|
||||
} else {
|
||||
value = int64(v)
|
||||
}
|
||||
case int:
|
||||
value = int64(v)
|
||||
case int64:
|
||||
value = v
|
||||
case string:
|
||||
value, err = strconv.ParseInt(strings.TrimSpace(v), 10, 64)
|
||||
default:
|
||||
err = fmt.Errorf("unsupported value")
|
||||
}
|
||||
if err != nil || value > math.MaxInt || value < math.MinInt {
|
||||
return 0, &APIError{Status: 400, Message: field + " must be an integer", Details: map[string]any{"index": index}}
|
||||
}
|
||||
return int(value), nil
|
||||
}
|
||||
|
||||
func normalizeBool(raw any) (bool, bool) {
|
||||
switch value := raw.(type) {
|
||||
case bool:
|
||||
return value, true
|
||||
case string:
|
||||
parsed, err := strconv.ParseBool(strings.TrimSpace(value))
|
||||
return parsed, err == nil
|
||||
case json.Number:
|
||||
if value.String() == "0" {
|
||||
return false, true
|
||||
}
|
||||
if value.String() == "1" {
|
||||
return true, true
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func clamp(value, minimum, maximum int) int {
|
||||
if value < minimum {
|
||||
return minimum
|
||||
}
|
||||
if value > maximum {
|
||||
return maximum
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func secondsDuration(value int) time.Duration {
|
||||
if value < 1 {
|
||||
value = 1
|
||||
}
|
||||
maxDuration := time.Duration(1<<63 - 1)
|
||||
if int64(value) > int64(maxDuration/time.Second) {
|
||||
return maxDuration
|
||||
}
|
||||
return time.Duration(value) * time.Second
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/expr-lang/expr"
|
||||
)
|
||||
|
||||
func TestNormalizeConfigPreservesCompatibility(t *testing.T) {
|
||||
doc := minimalTestConfig()
|
||||
doc["future"] = map[string]any{"enabled": true}
|
||||
doc["watchdog"] = []any{
|
||||
map[string]any{"name": "legacy", "rule": "cpu>90&load_1>5&username!='s01'", "interval": "600", "callback": nil},
|
||||
map[string]any{"name": "type", "rule": "tcp_count>600&type='Oracle'", "interval": 60},
|
||||
}
|
||||
doc["servers"].([]any)[0].(map[string]any)["future_field"] = "kept"
|
||||
|
||||
normalized, runtime, apiErr := normalizeConfig(doc)
|
||||
if apiErr != nil {
|
||||
t.Fatal(apiErr)
|
||||
}
|
||||
if len(runtime.Watchdogs) != 2 || runtime.Watchdogs[0].Normalized != "cpu>90&&load_1>5&&username!='s01'" {
|
||||
t.Fatalf("legacy rules were not normalized: %#v", runtime.Watchdogs)
|
||||
}
|
||||
server := normalized["servers"].([]any)[0].(map[string]any)
|
||||
if server["future_field"] != "kept" || normalized["future"] == nil {
|
||||
t.Fatal("unknown config fields were discarded")
|
||||
}
|
||||
if server["monthstart"] != json.Number("1") && server["monthstart"] != 1 {
|
||||
t.Fatalf("monthstart not normalized: %#v", server["monthstart"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestWatchdogLegacyRulesEvaluate(t *testing.T) {
|
||||
rules := []string{
|
||||
"online4=0&online6=0",
|
||||
"(memory_used/memory_total)*100>90&memory_total>1048576",
|
||||
"tcp_count>600&type='Oracle'",
|
||||
"(network_out-last_network_out)/1024/1024/1024>18&(username='aliyun1'|username='aliyun2')",
|
||||
}
|
||||
for index, rule := range rules {
|
||||
compiled, err := compileWatchdog(WatchdogConfig{Name: "test", Rule: rule, Interval: 1}, index)
|
||||
if err != nil {
|
||||
t.Fatalf("rule %q: %v", rule, err)
|
||||
}
|
||||
environment := watchdogEnvironment(ServerConfig{Username: "aliyun1", Type: "Oracle"}, AgentStats{MemoryTotal: 2_000_000, MemoryUsed: 1_900_000, TCPCount: 700, NetworkOut: 30 << 30}, false, false, 0, 0)
|
||||
if _, err := expr.Run(compiled.Program, environment); err != nil {
|
||||
t.Fatalf("run %q: %v", rule, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigValidationErrors(t *testing.T) {
|
||||
doc := minimalTestConfig()
|
||||
doc["servers"] = append(doc["servers"].([]any), doc["servers"].([]any)[0])
|
||||
_, _, apiErr := normalizeConfig(doc)
|
||||
if apiErr == nil || apiErr.Status != 409 {
|
||||
t.Fatalf("expected duplicate username error, got %#v", apiErr)
|
||||
}
|
||||
|
||||
if _, err := decodeDocument([]byte(`{"servers":[]} {"servers":[]}`)); err == nil || !strings.Contains(err.Error(), "more than one") {
|
||||
t.Fatalf("expected trailing JSON error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormattingHelpers(t *testing.T) {
|
||||
if got := formatUptime(90061); got != "1 天" {
|
||||
t.Fatalf("formatUptime=%q", got)
|
||||
}
|
||||
if got := formatUptime(3661); got != "01:01:01" {
|
||||
t.Fatalf("formatUptime=%q", got)
|
||||
}
|
||||
if got, err := certificateHost("https://example.com/path"); err != nil || got != "example.com" {
|
||||
t.Fatalf("certificateHost=%q", got)
|
||||
}
|
||||
if got := secondsDuration(0); got != time.Second {
|
||||
t.Fatalf("secondsDuration(0)=%s", got)
|
||||
}
|
||||
if got := secondsDuration(int(^uint(0) >> 1)); got < 365*24*time.Hour {
|
||||
t.Fatalf("large interval overflowed or was truncated: %s", got)
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
*.o
|
||||
@@ -0,0 +1,223 @@
|
||||
package main
|
||||
|
||||
import "strings"
|
||||
|
||||
func openAPISpec() map[string]any {
|
||||
paths := map[string]any{
|
||||
"/api/health": map[string]any{
|
||||
"get": publicOperation("health", "服务健康状态", objectResponse("Go 服务、Agent TCP 与配置状态")),
|
||||
},
|
||||
"/api/schema": map[string]any{
|
||||
"get": publicOperation("schema", "ServerStatus API 简表", objectResponse("端点和集合描述")),
|
||||
},
|
||||
"/api/openapi.json": map[string]any{
|
||||
"get": publicOperation("openapi", "OpenAPI 3.1 文档", objectResponse("OpenAPI document")),
|
||||
},
|
||||
"/json/stats.json": map[string]any{
|
||||
"get": publicOperation("stats", "实时状态快照", objectResponse("WebUI 状态数据")),
|
||||
},
|
||||
"/api/config": map[string]any{
|
||||
"get": protectedOperation("getConfig", "读取完整配置", nil, configResponse("200", "配置文档")),
|
||||
"put": protectedOperation("replaceConfig", "整体校验并替换配置", requestBody("Config"), configResponse("200", "已保存并热重载的配置")),
|
||||
},
|
||||
"/api/reload": map[string]any{
|
||||
"post": protectedOperation("reloadConfig", "从磁盘热重载配置", nil, objectResponse("重载结果")),
|
||||
},
|
||||
"/api/restart": map[string]any{
|
||||
"post": protectedOperation("restartRuntime", "在进程内重启采集运行时", nil, statusResponse("202", "重启结果", map[string]any{
|
||||
"operation": map[string]any{"type": "string", "const": "restart"},
|
||||
"mode": map[string]any{"type": "string", "const": "in-process"},
|
||||
})),
|
||||
},
|
||||
"/api/servers/{username}/reset-traffic": map[string]any{
|
||||
"post": withParameters(protectedOperation("resetServerTraffic", "重置节点本月流量基线", nil, objectResponse("流量重置结果")), pathParameter("username", "节点用户名")),
|
||||
},
|
||||
}
|
||||
|
||||
for _, key := range []string{"servers", "monitors", "sslcerts", "watchdog"} {
|
||||
spec := collectionSpecs[key]
|
||||
schemaName := map[string]string{"servers": "Server", "monitors": "Monitor", "sslcerts": "SSLCert", "watchdog": "Watchdog"}[key]
|
||||
operationBase := strings.TrimSuffix(key, "s")
|
||||
if key == "sslcerts" {
|
||||
operationBase = "sslcert"
|
||||
}
|
||||
paths["/api/"+key] = map[string]any{
|
||||
"get": protectedOperation("list"+titleWord(key), "查询 "+key, nil, collectionResponse(key, schemaName, "配置集合")),
|
||||
"post": protectedOperation("create"+titleWord(operationBase), "新增 "+spec.itemName, requestBody(schemaName), itemResponse("201", spec.itemName, schemaName, "创建结果")),
|
||||
}
|
||||
parameterName := "id"
|
||||
parameterDescription := "数字下标或唯一的 " + spec.idField
|
||||
if key == "servers" {
|
||||
parameterName = "username"
|
||||
parameterDescription = "节点用户名"
|
||||
}
|
||||
paths["/api/"+key+"/{"+parameterName+"}"] = map[string]any{
|
||||
"put": withParameters(protectedOperation("update"+titleWord(operationBase), "修改 "+spec.itemName, requestBody(schemaName), itemResponse("200", spec.itemName, schemaName, "修改结果")), pathParameter(parameterName, parameterDescription)),
|
||||
"delete": withParameters(protectedOperation("delete"+titleWord(operationBase), "删除 "+spec.itemName, nil, itemResponse("200", "removed", schemaName, "删除结果")), pathParameter(parameterName, parameterDescription)),
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"openapi": "3.1.0",
|
||||
"info": map[string]any{
|
||||
"title": "ServerStatus HTTP API",
|
||||
"version": version,
|
||||
"description": "单进程 Go ServerStatus 的配置、运行状态和采集控制 API。",
|
||||
},
|
||||
"servers": []any{map[string]any{"url": "/", "description": "当前 ServerStatus 实例"}},
|
||||
"paths": paths,
|
||||
"components": map[string]any{
|
||||
"securitySchemes": map[string]any{
|
||||
"bearerAuth": map[string]any{"type": "http", "scheme": "bearer", "bearerFormat": "ADMIN_TOKEN"},
|
||||
},
|
||||
"schemas": openAPISchemas(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func openAPISchemas() map[string]any {
|
||||
stringProperty := func(description string) map[string]any {
|
||||
return map[string]any{"type": "string", "description": description}
|
||||
}
|
||||
integerProperty := func(description string, minimum, maximum int) map[string]any {
|
||||
property := map[string]any{"type": "integer", "description": description, "minimum": minimum}
|
||||
if maximum > 0 {
|
||||
property["maximum"] = maximum
|
||||
}
|
||||
return property
|
||||
}
|
||||
server := map[string]any{
|
||||
"type": "object", "required": collectionSpecs["servers"].required,
|
||||
"properties": map[string]any{
|
||||
"username": stringProperty("唯一客户端用户名"), "name": stringProperty("节点显示名称"),
|
||||
"type": stringProperty("虚拟化或节点类型"), "host": stringProperty("主机标识"),
|
||||
"location": stringProperty("位置"), "password": stringProperty("客户端密码"),
|
||||
"monthstart": integerProperty("月流量重置日", 1, 28), "disabled": map[string]any{"type": "boolean", "default": false},
|
||||
},
|
||||
}
|
||||
monitor := map[string]any{
|
||||
"type": "object", "required": collectionSpecs["monitors"].required,
|
||||
"properties": map[string]any{
|
||||
"name": stringProperty("监测名称"), "host": stringProperty("HTTP(S) URL 或 TCP 地址"),
|
||||
"type": stringProperty("https、http 或 tcp"), "interval": integerProperty("客户端探测间隔秒数", 1, 0),
|
||||
},
|
||||
}
|
||||
sslcert := map[string]any{
|
||||
"type": "object", "required": collectionSpecs["sslcerts"].required,
|
||||
"properties": map[string]any{
|
||||
"name": stringProperty("证书名称"), "domain": stringProperty("域名或 URL"),
|
||||
"port": integerProperty("TLS 端口", 1, 65535), "interval": integerProperty("检查间隔秒数", 1, 0),
|
||||
"callback": stringProperty("告警回调 URL 前缀"),
|
||||
},
|
||||
}
|
||||
watchdog := map[string]any{
|
||||
"type": "object", "required": collectionSpecs["watchdog"].required,
|
||||
"properties": map[string]any{
|
||||
"name": stringProperty("告警名称"), "rule": stringProperty("兼容 Exprtk 的状态表达式"),
|
||||
"interval": integerProperty("通知冷却秒数", 1, 0), "callback": stringProperty("告警回调 URL 前缀"),
|
||||
},
|
||||
}
|
||||
return map[string]any{
|
||||
"Server": server, "Monitor": monitor, "SSLCert": sslcert, "Watchdog": watchdog,
|
||||
"Config": map[string]any{
|
||||
"type": "object", "required": []string{"servers", "monitors", "sslcerts", "watchdog"},
|
||||
"properties": map[string]any{
|
||||
"servers": arraySchema("Server"), "monitors": arraySchema("Monitor"),
|
||||
"sslcerts": arraySchema("SSLCert"), "watchdog": arraySchema("Watchdog"),
|
||||
},
|
||||
},
|
||||
"Error": map[string]any{
|
||||
"type": "object", "required": []string{"ok", "error"},
|
||||
"properties": map[string]any{"ok": map[string]any{"type": "boolean", "const": false}, "error": map[string]any{"type": "string"}, "details": map[string]any{}},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func titleWord(value string) string {
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.ToUpper(value[:1]) + value[1:]
|
||||
}
|
||||
|
||||
func schemaRef(name string) map[string]any {
|
||||
return map[string]any{"$ref": "#/components/schemas/" + name}
|
||||
}
|
||||
func arraySchema(name string) map[string]any {
|
||||
return map[string]any{"type": "array", "items": schemaRef(name)}
|
||||
}
|
||||
|
||||
func requestBody(schemaName string) map[string]any {
|
||||
return map[string]any{
|
||||
"required": true,
|
||||
"content": map[string]any{"application/json": map[string]any{"schema": schemaRef(schemaName)}},
|
||||
}
|
||||
}
|
||||
|
||||
func objectResponse(description string) map[string]any {
|
||||
return map[string]any{"200": jsonResponse(description, map[string]any{"type": "object"}), "4XX": jsonResponse("请求错误", schemaRef("Error"))}
|
||||
}
|
||||
|
||||
func configResponse(status, description string) map[string]any {
|
||||
return statusResponse(status, description, map[string]any{"config": schemaRef("Config")})
|
||||
}
|
||||
|
||||
func collectionResponse(key, schemaName, description string) map[string]any {
|
||||
return statusResponse("200", description, map[string]any{key: arraySchema(schemaName)})
|
||||
}
|
||||
|
||||
func itemResponse(status, key, schemaName, description string) map[string]any {
|
||||
return statusResponse(status, description, map[string]any{
|
||||
key: schemaRef(schemaName),
|
||||
"reloaded": map[string]any{"type": "boolean", "const": true},
|
||||
"pid": map[string]any{"type": "integer", "minimum": 1},
|
||||
"config": schemaRef("Config"),
|
||||
})
|
||||
}
|
||||
|
||||
func statusResponse(status, description string, properties map[string]any) map[string]any {
|
||||
required := []string{"ok"}
|
||||
allProperties := map[string]any{"ok": map[string]any{"type": "boolean", "const": true}}
|
||||
for key, property := range properties {
|
||||
allProperties[key] = property
|
||||
required = append(required, key)
|
||||
}
|
||||
return map[string]any{
|
||||
status: jsonResponse(description, map[string]any{
|
||||
"type": "object", "required": required, "properties": allProperties,
|
||||
}),
|
||||
"4XX": jsonResponse("请求错误", schemaRef("Error")),
|
||||
}
|
||||
}
|
||||
|
||||
func jsonResponse(description string, schema map[string]any) map[string]any {
|
||||
return map[string]any{"description": description, "content": map[string]any{"application/json": map[string]any{"schema": schema}}}
|
||||
}
|
||||
|
||||
func publicOperation(operationID, summary string, responses map[string]any) map[string]any {
|
||||
return map[string]any{"operationId": operationID, "summary": summary, "security": []any{}, "responses": responses}
|
||||
}
|
||||
|
||||
func protectedOperation(operationID, summary string, body map[string]any, responses map[string]any) map[string]any {
|
||||
operation := map[string]any{
|
||||
"operationId": operationID, "summary": summary,
|
||||
"security": []any{map[string]any{"bearerAuth": []any{}}}, "responses": responses,
|
||||
}
|
||||
if body != nil {
|
||||
operation["requestBody"] = body
|
||||
}
|
||||
return operation
|
||||
}
|
||||
|
||||
func withParameters(operation map[string]any, parameters ...map[string]any) map[string]any {
|
||||
items := make([]any, 0, len(parameters))
|
||||
for _, parameter := range parameters {
|
||||
items = append(items, parameter)
|
||||
}
|
||||
operation["parameters"] = items
|
||||
return operation
|
||||
}
|
||||
|
||||
func pathParameter(name, description string) map[string]any {
|
||||
return map[string]any{"name": name, "in": "path", "required": true, "description": description, "schema": map[string]any{"type": "string"}}
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
#include "argparse.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OPT_UNSET 1
|
||||
|
||||
static const char *
|
||||
prefix_skip(const char *str, const char *prefix)
|
||||
{
|
||||
size_t len = strlen(prefix);
|
||||
return strncmp(str, prefix, len) ? NULL : str + len;
|
||||
}
|
||||
|
||||
int
|
||||
prefix_cmp(const char *str, const char *prefix)
|
||||
{
|
||||
for (;; str++, prefix++)
|
||||
if (!*prefix)
|
||||
return 0;
|
||||
else if (*str != *prefix)
|
||||
return (unsigned char)*prefix - (unsigned char)*str;
|
||||
}
|
||||
|
||||
static void
|
||||
argparse_error(struct argparse *this_, const struct argparse_option *opt,
|
||||
const char *reason)
|
||||
{
|
||||
if (!strncmp(this_->argv[0], "--", 2)) {
|
||||
fprintf(stderr, "error: option `%s` %s\n", opt->long_name, reason);
|
||||
exit(-1);
|
||||
} else {
|
||||
fprintf(stderr, "error: option `%c` %s\n", opt->short_name, reason);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_getvalue(struct argparse *this_, const struct argparse_option *opt,
|
||||
int flags)
|
||||
{
|
||||
const char *s = NULL;
|
||||
if (!opt->value)
|
||||
goto skipped;
|
||||
switch (opt->type) {
|
||||
case ARGPARSE_OPT_BOOLEAN:
|
||||
if (flags & OPT_UNSET) {
|
||||
*(int *)opt->value = *(int *)opt->value - 1;
|
||||
} else {
|
||||
*(int *)opt->value = *(int *)opt->value + 1;
|
||||
}
|
||||
if (*(int *)opt->value < 0) {
|
||||
*(int *)opt->value = 0;
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_BIT:
|
||||
if (flags & OPT_UNSET) {
|
||||
*(int *)opt->value &= ~opt->data;
|
||||
} else {
|
||||
*(int *)opt->value |= opt->data;
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_STRING:
|
||||
if (this_->optvalue) {
|
||||
*(const char **)opt->value = this_->optvalue;
|
||||
this_->optvalue = NULL;
|
||||
} else if (this_->argc > 1) {
|
||||
this_->argc--;
|
||||
*(const char **)opt->value = *++this_->argv;
|
||||
} else {
|
||||
argparse_error(this_, opt, "requires a value");
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_INTEGER:
|
||||
if (this_->optvalue) {
|
||||
*(int *)opt->value = strtol(this_->optvalue, (char **)&s, 0);
|
||||
this_->optvalue = NULL;
|
||||
} else if (this_->argc > 1) {
|
||||
this_->argc--;
|
||||
*(int *)opt->value = strtol(*++this_->argv, (char **)&s, 0);
|
||||
} else {
|
||||
argparse_error(this_, opt, "requires a value");
|
||||
}
|
||||
if (*s)
|
||||
argparse_error(this_, opt, "expects a numerical value");
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
skipped:
|
||||
if (opt->callback) {
|
||||
return opt->callback(this_, opt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
argparse_options_check(const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
switch (options->type) {
|
||||
case ARGPARSE_OPT_END:
|
||||
case ARGPARSE_OPT_BOOLEAN:
|
||||
case ARGPARSE_OPT_BIT:
|
||||
case ARGPARSE_OPT_INTEGER:
|
||||
case ARGPARSE_OPT_STRING:
|
||||
continue;
|
||||
default:
|
||||
fprintf(stderr, "wrong option type: %d", options->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_short_opt(struct argparse *this_, const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
if (options->short_name == *this_->optvalue) {
|
||||
this_->optvalue = this_->optvalue[1] ? this_->optvalue + 1 : NULL;
|
||||
return argparse_getvalue(this_, options, 0);
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_long_opt(struct argparse *this_, const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
const char *rest;
|
||||
int opt_flags = 0;
|
||||
if (!options->long_name)
|
||||
continue;
|
||||
|
||||
rest = prefix_skip(this_->argv[0] + 2, options->long_name);
|
||||
if (!rest) {
|
||||
// Negation allowed?
|
||||
if (options->flags & OPT_NONEG) {
|
||||
continue;
|
||||
}
|
||||
// Only boolean/bit allow negation.
|
||||
if (options->type != ARGPARSE_OPT_BOOLEAN && options->type != ARGPARSE_OPT_BIT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!prefix_cmp(this_->argv[0] + 2, "no-")) {
|
||||
rest = prefix_skip(this_->argv[0] + 2 + 3, options->long_name);
|
||||
if (!rest)
|
||||
continue;
|
||||
opt_flags |= OPT_UNSET;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (*rest) {
|
||||
if (*rest != '=')
|
||||
continue;
|
||||
this_->optvalue = rest + 1;
|
||||
}
|
||||
return argparse_getvalue(this_, options, opt_flags);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int
|
||||
argparse_init(struct argparse *this_, struct argparse_option *options,
|
||||
const char *usage, int flags)
|
||||
{
|
||||
memset(this_, 0, sizeof(*this_));
|
||||
this_->options = options;
|
||||
this_->usage = usage;
|
||||
this_->flags = flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
argparse_parse(struct argparse *this_, int argc, const char **argv)
|
||||
{
|
||||
this_->argc = argc - 1;
|
||||
this_->argv = argv + 1;
|
||||
this_->out = argv;
|
||||
|
||||
argparse_options_check(this_->options);
|
||||
|
||||
for (; this_->argc; this_->argc--, this_->argv++) {
|
||||
const char *arg = this_->argv[0];
|
||||
if (arg[0] != '-' || !arg[1]) {
|
||||
if (this_->flags & ARGPARSE_STOP_AT_NON_OPTION) {
|
||||
goto end;
|
||||
}
|
||||
// if it's not option or is a single char '-', copy verbatimly
|
||||
this_->out[this_->cpidx++] = this_->argv[0];
|
||||
continue;
|
||||
}
|
||||
// short option
|
||||
if (arg[1] != '-') {
|
||||
this_->optvalue = arg + 1;
|
||||
switch (argparse_short_opt(this_, this_->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
while (this_->optvalue) {
|
||||
switch (argparse_short_opt(this_, this_->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// if '--' presents
|
||||
if (!arg[2]) {
|
||||
this_->argc--;
|
||||
this_->argv++;
|
||||
break;
|
||||
}
|
||||
// long option
|
||||
switch (argparse_long_opt(this_, this_->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
continue;
|
||||
|
||||
unknown:
|
||||
fprintf(stderr, "error: unknown option `%s`\n", this_->argv[0]);
|
||||
argparse_usage(this_);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
end:
|
||||
memmove(this_->out + this_->cpidx, this_->argv,
|
||||
this_->argc * sizeof(*this_->out));
|
||||
this_->out[this_->cpidx + this_->argc] = NULL;
|
||||
|
||||
return this_->cpidx + this_->argc;
|
||||
}
|
||||
|
||||
void
|
||||
argparse_usage(struct argparse *this_)
|
||||
{
|
||||
fprintf(stdout, "Usage: %s\n", this_->usage);
|
||||
fputc('\n', stdout);
|
||||
|
||||
const struct argparse_option *options;
|
||||
|
||||
// figure out best width
|
||||
size_t usage_opts_width = 0;
|
||||
size_t len;
|
||||
options = this_->options;
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
len = 0;
|
||||
if ((options)->short_name) {
|
||||
len += 2;
|
||||
}
|
||||
if ((options)->short_name && (options)->long_name) {
|
||||
len += 2; // separator ", "
|
||||
}
|
||||
if ((options)->long_name) {
|
||||
len += strlen((options)->long_name) + 2;
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_INTEGER) {
|
||||
len += strlen("=<int>");
|
||||
} else if (options->type == ARGPARSE_OPT_STRING) {
|
||||
len += strlen("=<str>");
|
||||
}
|
||||
len = ceil((float)len / 4) * 4;
|
||||
if (usage_opts_width < len) {
|
||||
usage_opts_width = len;
|
||||
}
|
||||
}
|
||||
usage_opts_width += 4; // 4 spaces prefix
|
||||
|
||||
options = this_->options;
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
size_t pos;
|
||||
int pad;
|
||||
pos = fprintf(stdout, " ");
|
||||
if (options->short_name) {
|
||||
pos += fprintf(stdout, "-%c", options->short_name);
|
||||
}
|
||||
if (options->long_name && options->short_name) {
|
||||
pos += fprintf(stdout, ", ");
|
||||
}
|
||||
if (options->long_name) {
|
||||
pos += fprintf(stdout, "--%s", options->long_name);
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_INTEGER) {
|
||||
pos += fprintf(stdout, "=<int>");
|
||||
} else if (options->type == ARGPARSE_OPT_STRING) {
|
||||
pos += fprintf(stdout, "=<str>");
|
||||
}
|
||||
if (pos <= usage_opts_width) {
|
||||
pad = usage_opts_width - pos;
|
||||
} else {
|
||||
fputc('\n', stdout);
|
||||
pad = usage_opts_width;
|
||||
}
|
||||
fprintf(stdout, "%*s%s\n", pad + 2, "", options->help);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
argparse_help_cb(struct argparse *this_, const struct argparse_option *option)
|
||||
{
|
||||
(void)option;
|
||||
argparse_usage(this_);
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@@ -1,949 +0,0 @@
|
||||
/* vim: set et ts=3 sw=3 sts=3 ft=c:
|
||||
*
|
||||
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
|
||||
* https://github.com/udp/json-parser
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "json.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
const struct _json_value json_value_none; /* zero-d by ctor */
|
||||
#else
|
||||
const struct _json_value json_value_none = { 0 };
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef unsigned short json_uchar;
|
||||
|
||||
static unsigned char hex_value (json_char c)
|
||||
{
|
||||
if (isdigit(c))
|
||||
return c - '0';
|
||||
|
||||
switch (c) {
|
||||
case 'a': case 'A': return 0x0A;
|
||||
case 'b': case 'B': return 0x0B;
|
||||
case 'c': case 'C': return 0x0C;
|
||||
case 'd': case 'D': return 0x0D;
|
||||
case 'e': case 'E': return 0x0E;
|
||||
case 'f': case 'F': return 0x0F;
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long used_memory;
|
||||
|
||||
unsigned int uint_max;
|
||||
unsigned long ulong_max;
|
||||
|
||||
json_settings settings;
|
||||
int first_pass;
|
||||
|
||||
} json_state;
|
||||
|
||||
static void * default_alloc (size_t size, int zero, void * user_data)
|
||||
{
|
||||
return zero ? calloc (1, size) : malloc (size);
|
||||
}
|
||||
|
||||
static void default_free (void * ptr, void * user_data)
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
static void * json_alloc (json_state * state, unsigned long size, int zero)
|
||||
{
|
||||
if ((state->ulong_max - state->used_memory) < size)
|
||||
return 0;
|
||||
|
||||
if (state->settings.max_memory
|
||||
&& (state->used_memory += size) > state->settings.max_memory)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return state->settings.mem_alloc (size, zero, state->settings.user_data);
|
||||
}
|
||||
|
||||
static int new_value
|
||||
(json_state * state, json_value ** top, json_value ** root, json_value ** alloc, json_type type)
|
||||
{
|
||||
json_value * value;
|
||||
int values_size;
|
||||
|
||||
if (!state->first_pass)
|
||||
{
|
||||
value = *top = *alloc;
|
||||
*alloc = (*alloc)->_reserved.next_alloc;
|
||||
|
||||
if (!*root)
|
||||
*root = value;
|
||||
|
||||
switch (value->type)
|
||||
{
|
||||
case json_array:
|
||||
|
||||
if (! (value->u.array.values = (json_value **) json_alloc
|
||||
(state, value->u.array.length * sizeof (json_value *), 0)) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
value->u.array.length = 0;
|
||||
break;
|
||||
|
||||
case json_object:
|
||||
|
||||
values_size = sizeof (*value->u.object.values) * value->u.object.length;
|
||||
|
||||
if (! ((*(void **) &value->u.object.values) = json_alloc
|
||||
(state, values_size + ((unsigned long) value->u.object.values), 0)) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
|
||||
|
||||
value->u.object.length = 0;
|
||||
break;
|
||||
|
||||
case json_string:
|
||||
|
||||
if (! (value->u.string.ptr = (json_char *) json_alloc
|
||||
(state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
value->u.string.length = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
value = (json_value *) json_alloc (state, sizeof (json_value), 1);
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
if (!*root)
|
||||
*root = value;
|
||||
|
||||
value->type = type;
|
||||
value->parent = *top;
|
||||
|
||||
if (*alloc)
|
||||
(*alloc)->_reserved.next_alloc = value;
|
||||
|
||||
*alloc = *top = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define e_off \
|
||||
((int) (i - cur_line_begin))
|
||||
|
||||
#define whitespace \
|
||||
case '\n': ++ cur_line; cur_line_begin = i; \
|
||||
case ' ': case '\t': case '\r'
|
||||
|
||||
#define string_add(b) \
|
||||
do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
|
||||
|
||||
static const long
|
||||
flag_next = 1 << 0,
|
||||
flag_reproc = 1 << 1,
|
||||
flag_need_comma = 1 << 2,
|
||||
flag_seek_value = 1 << 3,
|
||||
flag_escaped = 1 << 4,
|
||||
flag_string = 1 << 5,
|
||||
flag_need_colon = 1 << 6,
|
||||
flag_done = 1 << 7,
|
||||
flag_num_negative = 1 << 8,
|
||||
flag_num_zero = 1 << 9,
|
||||
flag_num_e = 1 << 10,
|
||||
flag_num_e_got_sign = 1 << 11,
|
||||
flag_num_e_negative = 1 << 12,
|
||||
flag_line_comment = 1 << 13,
|
||||
flag_block_comment = 1 << 14;
|
||||
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error_buf)
|
||||
{
|
||||
json_char error [json_error_max];
|
||||
unsigned int cur_line;
|
||||
const json_char * cur_line_begin, * i, * end;
|
||||
json_value * top, * root, * alloc = 0;
|
||||
json_state state = { 0 };
|
||||
long flags;
|
||||
long num_digits = 0, num_e = 0;
|
||||
json_int_t num_fraction = 0;
|
||||
|
||||
/* Skip UTF-8 BOM
|
||||
*/
|
||||
if (length >= 3 && ((unsigned char) json [0]) == 0xEF
|
||||
&& ((unsigned char) json [1]) == 0xBB
|
||||
&& ((unsigned char) json [2]) == 0xBF)
|
||||
{
|
||||
json += 3;
|
||||
length -= 3;
|
||||
}
|
||||
|
||||
error[0] = '\0';
|
||||
end = (json + length);
|
||||
|
||||
memcpy (&state.settings, settings, sizeof (json_settings));
|
||||
|
||||
if (!state.settings.mem_alloc)
|
||||
state.settings.mem_alloc = default_alloc;
|
||||
|
||||
if (!state.settings.mem_free)
|
||||
state.settings.mem_free = default_free;
|
||||
|
||||
memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
|
||||
memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
|
||||
|
||||
state.uint_max -= 8; /* limit of how much can be added before next check */
|
||||
state.ulong_max -= 8;
|
||||
|
||||
for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
|
||||
{
|
||||
json_uchar uchar;
|
||||
unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
|
||||
json_char * string = 0;
|
||||
unsigned int string_length = 0;
|
||||
|
||||
top = root = 0;
|
||||
flags = flag_seek_value;
|
||||
|
||||
cur_line = 1;
|
||||
cur_line_begin = json;
|
||||
|
||||
for (i = json ;; ++ i)
|
||||
{
|
||||
json_char b = (i == end ? 0 : *i);
|
||||
|
||||
if (flags & flag_string)
|
||||
{
|
||||
if (!b)
|
||||
{ sprintf (error, "Unexpected EOF in string (at %d:%d)", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
if (string_length > state.uint_max)
|
||||
goto e_overflow;
|
||||
|
||||
if (flags & flag_escaped)
|
||||
{
|
||||
flags &= ~ flag_escaped;
|
||||
|
||||
switch (b)
|
||||
{
|
||||
case 'b': string_add ('\b'); break;
|
||||
case 'f': string_add ('\f'); break;
|
||||
case 'n': string_add ('\n'); break;
|
||||
case 'r': string_add ('\r'); break;
|
||||
case 't': string_add ('\t'); break;
|
||||
case 'u':
|
||||
|
||||
if (end - i < 4 ||
|
||||
(uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
|
||||
|| (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF)
|
||||
{
|
||||
sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
uc_b1 = uc_b1 * 16 + uc_b2;
|
||||
uc_b2 = uc_b3 * 16 + uc_b4;
|
||||
|
||||
uchar = ((json_char) uc_b1) * 256 + uc_b2;
|
||||
|
||||
if (sizeof (json_char) >= sizeof (json_uchar) || (uc_b1 == 0 && uc_b2 <= 0x7F))
|
||||
{
|
||||
string_add ((json_char) uchar);
|
||||
break;
|
||||
}
|
||||
|
||||
if (uchar <= 0x7FF)
|
||||
{
|
||||
if (state.first_pass)
|
||||
string_length += 2;
|
||||
else
|
||||
{ string [string_length ++] = 0xC0 | ((uc_b2 & 0xC0) >> 6) | ((uc_b1 & 0x7) << 2);
|
||||
string [string_length ++] = 0x80 | (uc_b2 & 0x3F);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (state.first_pass)
|
||||
string_length += 3;
|
||||
else
|
||||
{ string [string_length ++] = 0xE0 | ((uc_b1 & 0xF0) >> 4);
|
||||
string [string_length ++] = 0x80 | ((uc_b1 & 0xF) << 2) | ((uc_b2 & 0xC0) >> 6);
|
||||
string [string_length ++] = 0x80 | (uc_b2 & 0x3F);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
string_add (b);
|
||||
};
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == '\\')
|
||||
{
|
||||
flags |= flag_escaped;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == '"')
|
||||
{
|
||||
if (!state.first_pass)
|
||||
string [string_length] = 0;
|
||||
|
||||
flags &= ~ flag_string;
|
||||
string = 0;
|
||||
|
||||
switch (top->type)
|
||||
{
|
||||
case json_string:
|
||||
|
||||
top->u.string.length = string_length;
|
||||
flags |= flag_next;
|
||||
|
||||
break;
|
||||
|
||||
case json_object:
|
||||
|
||||
if (state.first_pass)
|
||||
(*(json_char **) &top->u.object.values) += string_length + 1;
|
||||
else
|
||||
{
|
||||
top->u.object.values [top->u.object.length].name
|
||||
= (json_char *) top->_reserved.object_mem;
|
||||
|
||||
top->u.object.values [top->u.object.length].name_length
|
||||
= string_length;
|
||||
|
||||
(*(json_char **) &top->_reserved.object_mem) += string_length + 1;
|
||||
}
|
||||
|
||||
flags |= flag_seek_value | flag_need_colon;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
string_add (b);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.settings.settings & json_enable_comments)
|
||||
{
|
||||
if (flags & (flag_line_comment | flag_block_comment))
|
||||
{
|
||||
if (flags & flag_line_comment)
|
||||
{
|
||||
if (b == '\r' || b == '\n' || !b)
|
||||
{
|
||||
flags &= ~ flag_line_comment;
|
||||
-- i; /* so null can be reproc'd */
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & flag_block_comment)
|
||||
{
|
||||
if (!b)
|
||||
{ sprintf (error, "%d:%d: Unexpected EOF in block comment", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
if (b == '*' && i < (end - 1) && i [1] == '/')
|
||||
{
|
||||
flags &= ~ flag_block_comment;
|
||||
++ i; /* skip closing sequence */
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (b == '/')
|
||||
{
|
||||
if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
|
||||
{
|
||||
sprintf (error, "%d:%d: Comment not allowed here", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
if (++ i == end)
|
||||
{ sprintf (error, "%d:%d: EOF unexpected", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
switch (b = *i)
|
||||
{
|
||||
case '/':
|
||||
flags |= flag_line_comment;
|
||||
continue;
|
||||
|
||||
case '*':
|
||||
flags |= flag_block_comment;
|
||||
continue;
|
||||
|
||||
default:
|
||||
sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", cur_line, e_off, b);
|
||||
goto e_failed;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & flag_done)
|
||||
{
|
||||
if (!b)
|
||||
break;
|
||||
|
||||
switch (b)
|
||||
{
|
||||
whitespace:
|
||||
continue;
|
||||
|
||||
default:
|
||||
sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b);
|
||||
goto e_failed;
|
||||
};
|
||||
}
|
||||
|
||||
if (flags & flag_seek_value)
|
||||
{
|
||||
switch (b)
|
||||
{
|
||||
whitespace:
|
||||
continue;
|
||||
|
||||
case ']':
|
||||
|
||||
if (top->type == json_array)
|
||||
flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
|
||||
else
|
||||
{ sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (flags & flag_need_comma)
|
||||
{
|
||||
if (b == ',')
|
||||
{ flags &= ~ flag_need_comma;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ sprintf (error, "%d:%d: Expected , before %c", cur_line, e_off, b);
|
||||
goto e_failed;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & flag_need_colon)
|
||||
{
|
||||
if (b == ':')
|
||||
{ flags &= ~ flag_need_colon;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ sprintf (error, "%d:%d: Expected : before %c", cur_line, e_off, b);
|
||||
goto e_failed;
|
||||
}
|
||||
}
|
||||
|
||||
flags &= ~ flag_seek_value;
|
||||
|
||||
switch (b)
|
||||
{
|
||||
case '{':
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_object))
|
||||
goto e_alloc_failure;
|
||||
|
||||
continue;
|
||||
|
||||
case '[':
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_array))
|
||||
goto e_alloc_failure;
|
||||
|
||||
flags |= flag_seek_value;
|
||||
continue;
|
||||
|
||||
case '"':
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_string))
|
||||
goto e_alloc_failure;
|
||||
|
||||
flags |= flag_string;
|
||||
|
||||
string = top->u.string.ptr;
|
||||
string_length = 0;
|
||||
|
||||
continue;
|
||||
|
||||
case 't':
|
||||
|
||||
if ((end - i) < 3 || *(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e')
|
||||
goto e_unknown_value;
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_boolean))
|
||||
goto e_alloc_failure;
|
||||
|
||||
top->u.boolean = 1;
|
||||
|
||||
flags |= flag_next;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
|
||||
if ((end - i) < 4 || *(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e')
|
||||
goto e_unknown_value;
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_boolean))
|
||||
goto e_alloc_failure;
|
||||
|
||||
flags |= flag_next;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
|
||||
if ((end - i) < 3 || *(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l')
|
||||
goto e_unknown_value;
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_null))
|
||||
goto e_alloc_failure;
|
||||
|
||||
flags |= flag_next;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (isdigit (b) || b == '-')
|
||||
{
|
||||
if (!new_value (&state, &top, &root, &alloc, json_integer))
|
||||
goto e_alloc_failure;
|
||||
|
||||
if (!state.first_pass)
|
||||
{
|
||||
while (isdigit (b) || b == '+' || b == '-'
|
||||
|| b == 'e' || b == 'E' || b == '.')
|
||||
{
|
||||
if ( (++ i) == end)
|
||||
{
|
||||
b = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
b = *i;
|
||||
}
|
||||
|
||||
flags |= flag_next | flag_reproc;
|
||||
break;
|
||||
}
|
||||
|
||||
flags &= ~ (flag_num_negative | flag_num_e |
|
||||
flag_num_e_got_sign | flag_num_e_negative |
|
||||
flag_num_zero);
|
||||
|
||||
num_digits = 0;
|
||||
num_fraction = 0;
|
||||
num_e = 0;
|
||||
|
||||
if (b != '-')
|
||||
{
|
||||
flags |= flag_reproc;
|
||||
break;
|
||||
}
|
||||
|
||||
flags |= flag_num_negative;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ sprintf (error, "%d:%d: Unexpected %c when seeking value", cur_line, e_off, b);
|
||||
goto e_failed;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (top->type)
|
||||
{
|
||||
case json_object:
|
||||
|
||||
switch (b)
|
||||
{
|
||||
whitespace:
|
||||
continue;
|
||||
|
||||
case '"':
|
||||
|
||||
if (flags & flag_need_comma)
|
||||
{
|
||||
sprintf (error, "%d:%d: Expected , before \"", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
flags |= flag_string;
|
||||
|
||||
string = (json_char *) top->_reserved.object_mem;
|
||||
string_length = 0;
|
||||
|
||||
break;
|
||||
|
||||
case '}':
|
||||
|
||||
flags = (flags & ~ flag_need_comma) | flag_next;
|
||||
break;
|
||||
|
||||
case ',':
|
||||
|
||||
if (flags & flag_need_comma)
|
||||
{
|
||||
flags &= ~ flag_need_comma;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
sprintf (error, "%d:%d: Unexpected `%c` in object", cur_line, e_off, b);
|
||||
goto e_failed;
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case json_integer:
|
||||
case json_double:
|
||||
|
||||
if (isdigit (b))
|
||||
{
|
||||
++ num_digits;
|
||||
|
||||
if (top->type == json_integer || flags & flag_num_e)
|
||||
{
|
||||
if (! (flags & flag_num_e))
|
||||
{
|
||||
if (flags & flag_num_zero)
|
||||
{ sprintf (error, "%d:%d: Unexpected `0` before `%c`", cur_line, e_off, b);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
if (num_digits == 1 && b == '0')
|
||||
flags |= flag_num_zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags |= flag_num_e_got_sign;
|
||||
num_e = (num_e * 10) + (b - '0');
|
||||
continue;
|
||||
}
|
||||
|
||||
top->u.integer = (top->u.integer * 10) + (b - '0');
|
||||
continue;
|
||||
}
|
||||
|
||||
num_fraction = (num_fraction * 10) + (b - '0');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == '+' || b == '-')
|
||||
{
|
||||
if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
|
||||
{
|
||||
flags |= flag_num_e_got_sign;
|
||||
|
||||
if (b == '-')
|
||||
flags |= flag_num_e_negative;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (b == '.' && top->type == json_integer)
|
||||
{
|
||||
if (!num_digits)
|
||||
{ sprintf (error, "%d:%d: Expected digit before `.`", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
top->type = json_double;
|
||||
top->u.dbl = (double) top->u.integer;
|
||||
|
||||
num_digits = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! (flags & flag_num_e))
|
||||
{
|
||||
if (top->type == json_double)
|
||||
{
|
||||
if (!num_digits)
|
||||
{ sprintf (error, "%d:%d: Expected digit after `.`", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
top->u.dbl += ((double) num_fraction) / (pow (10, (double) num_digits));
|
||||
}
|
||||
|
||||
if (b == 'e' || b == 'E')
|
||||
{
|
||||
flags |= flag_num_e;
|
||||
|
||||
if (top->type == json_integer)
|
||||
{
|
||||
top->type = json_double;
|
||||
top->u.dbl = (double) top->u.integer;
|
||||
}
|
||||
|
||||
num_digits = 0;
|
||||
flags &= ~ flag_num_zero;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!num_digits)
|
||||
{ sprintf (error, "%d:%d: Expected digit after `e`", cur_line, e_off);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
top->u.dbl *= pow (10, (double) (flags & flag_num_e_negative ? - num_e : num_e));
|
||||
}
|
||||
|
||||
if (flags & flag_num_negative)
|
||||
{
|
||||
if (top->type == json_integer)
|
||||
top->u.integer = - top->u.integer;
|
||||
else
|
||||
top->u.dbl = - top->u.dbl;
|
||||
}
|
||||
|
||||
flags |= flag_next | flag_reproc;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
if (flags & flag_reproc)
|
||||
{
|
||||
flags &= ~ flag_reproc;
|
||||
-- i;
|
||||
}
|
||||
|
||||
if (flags & flag_next)
|
||||
{
|
||||
flags = (flags & ~ flag_next) | flag_need_comma;
|
||||
|
||||
if (!top->parent)
|
||||
{
|
||||
/* root value done */
|
||||
|
||||
flags |= flag_done;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (top->parent->type == json_array)
|
||||
flags |= flag_seek_value;
|
||||
|
||||
if (!state.first_pass)
|
||||
{
|
||||
json_value * parent = top->parent;
|
||||
|
||||
switch (parent->type)
|
||||
{
|
||||
case json_object:
|
||||
|
||||
parent->u.object.values
|
||||
[parent->u.object.length].value = top;
|
||||
|
||||
break;
|
||||
|
||||
case json_array:
|
||||
|
||||
parent->u.array.values
|
||||
[parent->u.array.length] = top;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
if ( (++ top->parent->u.array.length) > state.uint_max)
|
||||
goto e_overflow;
|
||||
|
||||
top = top->parent;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
alloc = root;
|
||||
}
|
||||
|
||||
return root;
|
||||
|
||||
e_unknown_value:
|
||||
|
||||
sprintf (error, "%d:%d: Unknown value", cur_line, e_off);
|
||||
goto e_failed;
|
||||
|
||||
e_alloc_failure:
|
||||
|
||||
strcpy (error, "Memory allocation failure");
|
||||
goto e_failed;
|
||||
|
||||
e_overflow:
|
||||
|
||||
sprintf (error, "%d:%d: Too long (caught overflow)", cur_line, e_off);
|
||||
goto e_failed;
|
||||
|
||||
e_failed:
|
||||
|
||||
if (error_buf)
|
||||
{
|
||||
if (*error)
|
||||
strcpy (error_buf, error);
|
||||
else
|
||||
strcpy (error_buf, "Unknown error");
|
||||
}
|
||||
|
||||
if (state.first_pass)
|
||||
alloc = root;
|
||||
|
||||
while (alloc)
|
||||
{
|
||||
top = alloc->_reserved.next_alloc;
|
||||
state.settings.mem_free (alloc, state.settings.user_data);
|
||||
alloc = top;
|
||||
}
|
||||
|
||||
if (!state.first_pass)
|
||||
json_value_free_ex (&state.settings, root);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
json_value * json_parse (const json_char * json, size_t length)
|
||||
{
|
||||
json_settings settings = { 0 };
|
||||
return json_parse_ex (&settings, json, length, 0);
|
||||
}
|
||||
|
||||
void json_value_free_ex (json_settings * settings, json_value * value)
|
||||
{
|
||||
json_value * cur_value;
|
||||
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
value->parent = 0;
|
||||
|
||||
while (value)
|
||||
{
|
||||
switch (value->type)
|
||||
{
|
||||
case json_array:
|
||||
|
||||
if (!value->u.array.length)
|
||||
{
|
||||
settings->mem_free (value->u.array.values, settings->user_data);
|
||||
break;
|
||||
}
|
||||
|
||||
value = value->u.array.values [-- value->u.array.length];
|
||||
continue;
|
||||
|
||||
case json_object:
|
||||
|
||||
if (!value->u.object.length)
|
||||
{
|
||||
settings->mem_free (value->u.object.values, settings->user_data);
|
||||
break;
|
||||
}
|
||||
|
||||
value = value->u.object.values [-- value->u.object.length].value;
|
||||
continue;
|
||||
|
||||
case json_string:
|
||||
|
||||
settings->mem_free (value->u.string.ptr, settings->user_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
cur_value = value;
|
||||
value = value->parent;
|
||||
settings->mem_free (cur_value, settings->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
void json_value_free (json_value * value)
|
||||
{
|
||||
json_settings settings = { 0 };
|
||||
settings.mem_free = default_free;
|
||||
json_value_free_ex (&settings, value);
|
||||
}
|
||||
@@ -1,730 +0,0 @@
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
#include <time.h>
|
||||
#include <detect.h>
|
||||
#include <system.h>
|
||||
#include <argparse.h>
|
||||
#include <json.h>
|
||||
#include "server.h"
|
||||
#include "main.h"
|
||||
#include "exprtk.hpp"
|
||||
#include "curl/curl.h"
|
||||
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifndef PRId64
|
||||
#define PRId64 "I64d"
|
||||
#endif
|
||||
|
||||
static volatile int gs_Running = 1;
|
||||
static volatile int gs_ReloadConfig = 0;
|
||||
|
||||
static void ExitFunc(int Signal)
|
||||
{
|
||||
printf("[EXIT] Caught signal %d\n", Signal);
|
||||
gs_Running = 0;
|
||||
}
|
||||
|
||||
static void ReloadFunc(int Signal)
|
||||
{
|
||||
printf("[RELOAD] Caught signal %d\n", Signal);
|
||||
gs_ReloadConfig = 1;
|
||||
}
|
||||
|
||||
CConfig::CConfig()
|
||||
{
|
||||
// Initialize to default values
|
||||
m_Verbose = false; // -v, --verbose
|
||||
str_copy(m_aConfigFile, "config.json", sizeof(m_aConfigFile)); // -c, --config
|
||||
str_copy(m_aWebDir, "../web/", sizeof(m_aJSONFile)); // -d, --web-dir
|
||||
str_copy(m_aTemplateFile, "template.html", sizeof(m_aTemplateFile));
|
||||
str_copy(m_aJSONFile, "json/stats.json", sizeof(m_aJSONFile));
|
||||
str_copy(m_aBindAddr, "", sizeof(m_aBindAddr)); // -b, --bind
|
||||
m_Port = 35601; // -p, --port
|
||||
}
|
||||
|
||||
CMain::CMain(CConfig Config) : m_Config(Config)
|
||||
{
|
||||
mem_zero(m_aClients, sizeof(m_aClients));
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
m_aClients[i].m_ClientNetID = -1;
|
||||
}
|
||||
|
||||
CMain::CClient *CMain::ClientNet(int ClientNetID)
|
||||
{
|
||||
if(ClientNetID < 0 || ClientNetID >= NET_MAX_CLIENTS)
|
||||
return 0;
|
||||
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(Client(i)->m_ClientNetID == ClientNetID)
|
||||
return Client(i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMain::ClientNetToClient(int ClientNetID)
|
||||
{
|
||||
if(ClientNetID < 0 || ClientNetID >= NET_MAX_CLIENTS)
|
||||
return -1;
|
||||
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(Client(i)->m_ClientNetID == ClientNetID)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CMain::OnNewClient(int ClientNetID, int ClientID)
|
||||
{
|
||||
dbg_msg("main", "OnNewClient(ncid=%d, cid=%d)", ClientNetID, ClientID);
|
||||
Client(ClientID)->m_ClientNetID = ClientNetID;
|
||||
Client(ClientID)->m_ClientNetType = m_Server.Network()->ClientAddr(ClientNetID)->type;
|
||||
Client(ClientID)->m_TimeConnected = time_get();
|
||||
Client(ClientID)->m_Connected = true;
|
||||
|
||||
if(Client(ClientID)->m_ClientNetType == NETTYPE_IPV4)
|
||||
Client(ClientID)->m_Stats.m_Online4 = true;
|
||||
else if(Client(ClientID)->m_ClientNetType == NETTYPE_IPV6)
|
||||
Client(ClientID)->m_Stats.m_Online6 = true;
|
||||
}
|
||||
|
||||
void CMain::OnDelClient(int ClientNetID)
|
||||
{
|
||||
int ClientID = ClientNetToClient(ClientNetID);
|
||||
dbg_msg("main", "OnDelClient(ncid=%d, cid=%d)", ClientNetID, ClientID);
|
||||
//copy offline message for watchdog
|
||||
WatchdogMessage(ClientNetID,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,0, 0, 0,
|
||||
0, 0, 0, 0);
|
||||
if(ClientID >= 0 && ClientID < NET_MAX_CLIENTS)
|
||||
{
|
||||
Client(ClientID)->m_Connected = false;
|
||||
Client(ClientID)->m_ClientNetID = -1;
|
||||
Client(ClientID)->m_ClientNetType = NETTYPE_INVALID;
|
||||
mem_zero(&Client(ClientID)->m_Stats, sizeof(CClient::CStats));
|
||||
}
|
||||
}
|
||||
|
||||
int CMain::HandleMessage(int ClientNetID, char *pMessage)
|
||||
{
|
||||
CClient *pClient = ClientNet(ClientNetID);
|
||||
if(!pClient)
|
||||
return true;
|
||||
|
||||
if(str_comp_num(pMessage, "update", sizeof("update")-1) == 0)
|
||||
{
|
||||
char *pData = str_skip_whitespaces(&pMessage[sizeof("update")-1]);
|
||||
|
||||
// parse json data
|
||||
json_settings JsonSettings;
|
||||
mem_zero(&JsonSettings, sizeof(JsonSettings));
|
||||
char aError[256];
|
||||
json_value *pJsonData = json_parse_ex(&JsonSettings, pData, strlen(pData), aError);
|
||||
if(!pJsonData)
|
||||
{
|
||||
dbg_msg("main", "JSON Error: %s", aError);
|
||||
if(pClient->m_Stats.m_Pong)
|
||||
m_Server.Network()->Send(ClientNetID, "1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// extract data
|
||||
const json_value &rStart = (*pJsonData);
|
||||
if(rStart["uptime"].type)
|
||||
pClient->m_Stats.m_Uptime = rStart["uptime"].u.integer;
|
||||
if(rStart["load_1"].type)
|
||||
pClient->m_Stats.m_Load_1 = rStart["load_1"].u.dbl;
|
||||
if(rStart["load_5"].type)
|
||||
pClient->m_Stats.m_Load_5 = rStart["load_5"].u.dbl;
|
||||
if(rStart["load_15"].type)
|
||||
pClient->m_Stats.m_Load_15 = rStart["load_15"].u.dbl;
|
||||
if(rStart["ping_10010"].type)
|
||||
pClient->m_Stats.m_ping_10010 = rStart["ping_10010"].u.dbl;
|
||||
if(rStart["ping_189"].type)
|
||||
pClient->m_Stats.m_ping_189 = rStart["ping_189"].u.dbl;
|
||||
if(rStart["ping_10086"].type)
|
||||
pClient->m_Stats.m_ping_10086 = rStart["ping_10086"].u.dbl;
|
||||
if(rStart["time_10010"].type)
|
||||
pClient->m_Stats.m_time_10010 = rStart["time_10010"].u.integer;
|
||||
if(rStart["time_189"].type)
|
||||
pClient->m_Stats.m_time_189 = rStart["time_189"].u.integer;
|
||||
if(rStart["time_10086"].type)
|
||||
pClient->m_Stats.m_time_10086 = rStart["time_10086"].u.integer;
|
||||
if(rStart["tcp"].type)
|
||||
pClient->m_Stats.m_tcpCount = rStart["tcp"].u.integer;
|
||||
if(rStart["udp"].type)
|
||||
pClient->m_Stats.m_udpCount = rStart["udp"].u.integer;
|
||||
if(rStart["process"].type)
|
||||
pClient->m_Stats.m_processCount = rStart["process"].u.integer;
|
||||
if(rStart["thread"].type)
|
||||
pClient->m_Stats.m_threadCount = rStart["thread"].u.integer;
|
||||
if(rStart["network_rx"].type)
|
||||
pClient->m_Stats.m_NetworkRx = rStart["network_rx"].u.integer;
|
||||
if(rStart["network_tx"].type)
|
||||
pClient->m_Stats.m_NetworkTx = rStart["network_tx"].u.integer;
|
||||
if(rStart["network_in"].type)
|
||||
pClient->m_Stats.m_NetworkIN = rStart["network_in"].u.integer;
|
||||
if(rStart["network_out"].type)
|
||||
pClient->m_Stats.m_NetworkOUT = rStart["network_out"].u.integer;
|
||||
if(rStart["memory_total"].type)
|
||||
pClient->m_Stats.m_MemTotal = rStart["memory_total"].u.integer;
|
||||
if(rStart["memory_used"].type)
|
||||
pClient->m_Stats.m_MemUsed = rStart["memory_used"].u.integer;
|
||||
if(rStart["swap_total"].type)
|
||||
pClient->m_Stats.m_SwapTotal = rStart["swap_total"].u.integer;
|
||||
if(rStart["swap_used"].type)
|
||||
pClient->m_Stats.m_SwapUsed = rStart["swap_used"].u.integer;
|
||||
if(rStart["hdd_total"].type)
|
||||
pClient->m_Stats.m_HDDTotal = rStart["hdd_total"].u.integer;
|
||||
if(rStart["hdd_used"].type)
|
||||
pClient->m_Stats.m_HDDUsed = rStart["hdd_used"].u.integer;
|
||||
if(rStart["io_read"].type)
|
||||
pClient->m_Stats.m_IORead = rStart["io_read"].u.integer;
|
||||
if(rStart["io_write"].type)
|
||||
pClient->m_Stats.m_IOWrite = rStart["io_write"].u.integer;
|
||||
if(rStart["cpu"].type)
|
||||
pClient->m_Stats.m_CPU = rStart["cpu"].u.dbl;
|
||||
if(rStart["online4"].type && pClient->m_ClientNetType == NETTYPE_IPV6)
|
||||
pClient->m_Stats.m_Online4 = rStart["online4"].u.boolean;
|
||||
if(rStart["online6"].type && pClient->m_ClientNetType == NETTYPE_IPV4)
|
||||
pClient->m_Stats.m_Online6 = rStart["online6"].u.boolean;
|
||||
if(rStart["custom"].type == json_string)
|
||||
str_copy(pClient->m_Stats.m_aCustom, rStart["custom"].u.string.ptr, sizeof(pClient->m_Stats.m_aCustom));
|
||||
|
||||
//copy message for watchdog to analysis
|
||||
WatchdogMessage(ClientNetID,
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15,
|
||||
pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086,
|
||||
pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,
|
||||
pClient->m_Stats.m_tcpCount, pClient->m_Stats.m_udpCount, pClient->m_Stats.m_processCount,
|
||||
pClient->m_Stats.m_threadCount, pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx,
|
||||
pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT,pClient->m_Stats.m_MemTotal,
|
||||
pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed,
|
||||
pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_IORead,
|
||||
pClient->m_Stats.m_IOWrite, pClient->m_Stats.m_CPU, pClient->m_Stats.m_Online4,
|
||||
pClient->m_Stats.m_Online6);
|
||||
|
||||
if(m_Config.m_Verbose)
|
||||
{
|
||||
if(rStart["online4"].type)
|
||||
dbg_msg("main", "Online4: %s\nUptime: %" PRId64 "\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\nIORead: %" PRId64 "\nIOWrite: %" PRId64 "\n",
|
||||
rStart["online4"].u.boolean ? "true" : "false",
|
||||
pClient->m_Stats.m_Uptime,
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU, pClient->m_Stats.m_IORead, pClient->m_Stats.m_IOWrite);
|
||||
else if(rStart["online6"].type)
|
||||
dbg_msg("main", "Online6: %s\nUptime: %" PRId64 "\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\nIORead: %" PRId64 "\nIOWrite: %" PRId64 "\n",
|
||||
rStart["online6"].u.boolean ? "true" : "false",
|
||||
pClient->m_Stats.m_Uptime,
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU, pClient->m_Stats.m_IORead, pClient->m_Stats.m_IOWrite);
|
||||
else
|
||||
dbg_msg("main", "Uptime: %" PRId64 "\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\nIORead: %" PRId64 "\nIOWrite: %" PRId64 "\n",
|
||||
pClient->m_Stats.m_Uptime,
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU, pClient->m_Stats.m_IORead, pClient->m_Stats.m_IOWrite);
|
||||
}
|
||||
|
||||
// clean up
|
||||
json_value_free(pJsonData);
|
||||
|
||||
if(pClient->m_Stats.m_Pong)
|
||||
m_Server.Network()->Send(ClientNetID, "0");
|
||||
return 0;
|
||||
}
|
||||
else if(str_comp_num(pMessage, "pong", sizeof("pong")-1) == 0)
|
||||
{
|
||||
char *pData = str_skip_whitespaces(&pMessage[sizeof("pong")-1]);
|
||||
|
||||
if(!str_comp(pData, "0") || !str_comp(pData, "off"))
|
||||
pClient->m_Stats.m_Pong = false;
|
||||
else if(!str_comp(pData, "1") || !str_comp(pData, "on"))
|
||||
pClient->m_Stats.m_Pong = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(pClient->m_Stats.m_Pong)
|
||||
m_Server.Network()->Send(ClientNetID, "1");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, double load_15, double ping_10010, double ping_189, double ping_10086,
|
||||
double time_10010, double time_189, double time_10086, double tcp_count, double udp_count, double process_count, double thread_count,
|
||||
double network_rx, double network_tx, double network_in, double network_out, double memory_total, double memory_used,
|
||||
double swap_total, double swap_used, double hdd_total, double hdd_used, double io_read, double io_write, double cpu,
|
||||
double online4, double online6)
|
||||
{
|
||||
int ID = 0;
|
||||
while (strcmp(Watchdog(ID)->m_aName, "NULL"))
|
||||
{
|
||||
typedef exprtk::symbol_table<double> symbol_table_t;
|
||||
typedef exprtk::expression<double> expression_t;
|
||||
typedef exprtk::parser<double> parser_t;
|
||||
const std::string expression_string = Watchdog(ID)->m_aRule;
|
||||
int ClientID = ClientNetToClient(ClientNetID);
|
||||
std::string username = Client(ClientID)->m_aUsername;
|
||||
std::string name = Client(ClientID)->m_aName;
|
||||
std::string type = Client(ClientID)->m_aType;
|
||||
std::string host = Client(ClientID)->m_aHost;
|
||||
std::string location = Client(ClientID)->m_aLocation;
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_stringvar("username", username);
|
||||
symbol_table.add_stringvar("name", name);
|
||||
symbol_table.add_stringvar("type", type);
|
||||
symbol_table.add_stringvar("host", host);
|
||||
symbol_table.add_stringvar("location", location);
|
||||
symbol_table.add_variable("load_1",load_1);
|
||||
symbol_table.add_variable("load_5",load_5);
|
||||
symbol_table.add_variable("load_15",load_15);
|
||||
symbol_table.add_variable("ping_10010",ping_10010);
|
||||
symbol_table.add_variable("ping_189",ping_189);
|
||||
symbol_table.add_variable("ping_10086",ping_10086);
|
||||
symbol_table.add_variable("time_10010",time_10010);
|
||||
symbol_table.add_variable("time_189",time_189);
|
||||
symbol_table.add_variable("time_10086",time_10086);
|
||||
symbol_table.add_variable("tcp_count",tcp_count);
|
||||
symbol_table.add_variable("udp_count",udp_count);
|
||||
symbol_table.add_variable("process_count",process_count);
|
||||
symbol_table.add_variable("thread_count",thread_count);
|
||||
symbol_table.add_variable("network_rx",network_rx);
|
||||
symbol_table.add_variable("network_tx",network_tx);
|
||||
symbol_table.add_variable("network_in",network_in);
|
||||
symbol_table.add_variable("network_out",network_out);
|
||||
symbol_table.add_variable("memory_total",memory_total);
|
||||
symbol_table.add_variable("memory_used",memory_used);
|
||||
symbol_table.add_variable("swap_total",swap_total);
|
||||
symbol_table.add_variable("swap_used",swap_used);
|
||||
symbol_table.add_variable("hdd_total",hdd_total);
|
||||
symbol_table.add_variable("hdd_used",hdd_used);
|
||||
symbol_table.add_variable("io_read",io_read);
|
||||
symbol_table.add_variable("io_write",io_write);
|
||||
symbol_table.add_variable("cpu",cpu);
|
||||
symbol_table.add_variable("online4",online4);
|
||||
symbol_table.add_variable("online6",online6);
|
||||
symbol_table.add_constants();
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser_t parser;
|
||||
parser.compile(expression_string,expression);
|
||||
|
||||
if (expression.value() > 0)
|
||||
{
|
||||
time_t currentStamp = (long long)time(/*ago*/0);
|
||||
if ((currentStamp-Client(ClientID)->m_AlarmLastTime) > Watchdog(ID)->m_aInterval)
|
||||
{
|
||||
Client(ClientID)->m_AlarmLastTime = currentStamp;
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
//standard time
|
||||
char standardTime[32]= { 0 };
|
||||
strftime(standardTime, sizeof(standardTime), "%Y-%m-%d %H:%M:%S",localtime(¤tStamp));
|
||||
|
||||
//url encode, Rules conflict with url special characters,eg:&, del rules, by https://cpp.la, 2023-10-09
|
||||
char encodeBuffer[2048] = { 0 };
|
||||
sprintf(encodeBuffer, "【告警名称】 %s \n\n【告警时间】 %s \n\n【用户名】 %s \n\n【节点名】 %s \n\n【虚拟化】 %s \n\n【主机名】 %s \n\n【位 置】 %s",
|
||||
Watchdog(ID)->m_aName,
|
||||
standardTime,
|
||||
username.c_str(),
|
||||
name.c_str(),
|
||||
type.c_str(),
|
||||
host.c_str(),
|
||||
location.c_str());
|
||||
char *encodeUrl = curl_easy_escape(curl, encodeBuffer, strlen(encodeBuffer));
|
||||
|
||||
//standard url
|
||||
char urlBuffer[2048] = { 0 };
|
||||
sprintf(urlBuffer, "%s%s",Watchdog(ID)->m_aCallback, encodeUrl);
|
||||
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, urlBuffer);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,"signature=ServerStatus");
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 6L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK)
|
||||
fprintf(stderr, "watchdog failed: %s\n", curl_easy_strerror(res));
|
||||
if(encodeUrl)
|
||||
curl_free(encodeUrl);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
ID++;
|
||||
}
|
||||
}
|
||||
|
||||
void CMain::JSONUpdateThread(void *pUser)
|
||||
{
|
||||
CJSONUpdateThreadData *m_pJSONUpdateThreadData = (CJSONUpdateThreadData *)pUser;
|
||||
CClient *pClients = m_pJSONUpdateThreadData->pClients;
|
||||
CConfig *pConfig = m_pJSONUpdateThreadData->pConfig;
|
||||
|
||||
while(gs_Running)
|
||||
{
|
||||
char aFileBuf[2048*NET_MAX_CLIENTS];
|
||||
char *pBuf = aFileBuf;
|
||||
|
||||
str_format(pBuf, sizeof(aFileBuf), "{\n\"servers\": [\n");
|
||||
pBuf += strlen(pBuf);
|
||||
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(!pClients[i].m_Active || pClients[i].m_Disabled)
|
||||
continue;
|
||||
|
||||
if(pClients[i].m_Connected)
|
||||
{
|
||||
// Uptime
|
||||
char aUptime[16];
|
||||
int Days = pClients[i].m_Stats.m_Uptime/60.0/60.0/24.0;
|
||||
if(Days > 0)
|
||||
{
|
||||
if(Days > 1)
|
||||
str_format(aUptime, sizeof(aUptime), "%d 天", Days);
|
||||
else
|
||||
str_format(aUptime, sizeof(aUptime), "%d 天", Days);
|
||||
}
|
||||
else
|
||||
str_format(aUptime, sizeof(aUptime), "%02d:%02d:%02d", (int)(pClients[i].m_Stats.m_Uptime/60.0/60.0), (int)((pClients[i].m_Stats.m_Uptime/60)%60), (int)((pClients[i].m_Stats.m_Uptime)%60));
|
||||
|
||||
// track month network traffic, diff: 2021-10-01 00:05, 5minutes
|
||||
// last_network_in/out is last record flag.
|
||||
time_t currentStamp = (long long)time(/*ago*/0);
|
||||
if(0 == pClients[i].m_LastNetworkIN || (0 != pClients[i].m_Stats.m_NetworkIN && pClients[i].m_LastNetworkIN > pClients[i].m_Stats.m_NetworkIN) || (localtime(¤tStamp)->tm_mday == pClients[i].m_aMonthStart && localtime(¤tStamp)->tm_hour == 0 && localtime(¤tStamp)->tm_min < 5))
|
||||
{
|
||||
pClients[i].m_LastNetworkIN = pClients[i].m_Stats.m_NetworkIN;
|
||||
pClients[i].m_LastNetworkOUT = pClients[i].m_Stats.m_NetworkOUT;
|
||||
}
|
||||
|
||||
str_format(pBuf, sizeof(aFileBuf) - (pBuf - aFileBuf),
|
||||
"{ \"name\": \"%s\",\"type\": \"%s\",\"host\": \"%s\",\"location\": \"%s\",\"online4\": %s, \"online6\": %s, \"uptime\": \"%s\",\"load_1\": %.2f, \"load_5\": %.2f, \"load_15\": %.2f,\"ping_10010\": %.2f, \"ping_189\": %.2f, \"ping_10086\": %.2f,\"time_10010\": %" PRId64 ", \"time_189\": %" PRId64 ", \"time_10086\": %" PRId64 ", \"tcp_count\": %" PRId64 ", \"udp_count\": %" PRId64 ", \"process_count\": %" PRId64 ", \"thread_count\": %" PRId64 ", \"network_rx\": %" PRId64 ", \"network_tx\": %" PRId64 ", \"network_in\": %" PRId64 ", \"network_out\": %" PRId64 ", \"cpu\": %d, \"memory_total\": %" PRId64 ", \"memory_used\": %" PRId64 ", \"swap_total\": %" PRId64 ", \"swap_used\": %" PRId64 ", \"hdd_total\": %" PRId64 ", \"hdd_used\": %" PRId64 ", \"last_network_in\": %" PRId64 ", \"last_network_out\": %" PRId64 ",\"io_read\": %" PRId64 ", \"io_write\": %" PRId64 ",\"custom\": \"%s\" },\n",
|
||||
pClients[i].m_aName,pClients[i].m_aType,pClients[i].m_aHost,pClients[i].m_aLocation,
|
||||
pClients[i].m_Stats.m_Online4 ? "true" : "false",pClients[i].m_Stats.m_Online6 ? "true" : "false",
|
||||
aUptime, pClients[i].m_Stats.m_Load_1, pClients[i].m_Stats.m_Load_5, pClients[i].m_Stats.m_Load_15, pClients[i].m_Stats.m_ping_10010, pClients[i].m_Stats.m_ping_189, pClients[i].m_Stats.m_ping_10086,
|
||||
pClients[i].m_Stats.m_time_10010, pClients[i].m_Stats.m_time_189, pClients[i].m_Stats.m_time_10086,pClients[i].m_Stats.m_tcpCount,pClients[i].m_Stats.m_udpCount,pClients[i].m_Stats.m_processCount,pClients[i].m_Stats.m_threadCount,
|
||||
pClients[i].m_Stats.m_NetworkRx, pClients[i].m_Stats.m_NetworkTx, pClients[i].m_Stats.m_NetworkIN, pClients[i].m_Stats.m_NetworkOUT, (int)pClients[i].m_Stats.m_CPU, pClients[i].m_Stats.m_MemTotal, pClients[i].m_Stats.m_MemUsed,
|
||||
pClients[i].m_Stats.m_SwapTotal, pClients[i].m_Stats.m_SwapUsed, pClients[i].m_Stats.m_HDDTotal, pClients[i].m_Stats.m_HDDUsed,
|
||||
pClients[i].m_Stats.m_NetworkIN == 0 || pClients[i].m_LastNetworkIN == 0 ? pClients[i].m_Stats.m_NetworkIN : pClients[i].m_LastNetworkIN,
|
||||
pClients[i].m_Stats.m_NetworkOUT == 0 || pClients[i].m_LastNetworkOUT == 0 ? pClients[i].m_Stats.m_NetworkOUT : pClients[i].m_LastNetworkOUT,
|
||||
pClients[i].m_Stats.m_IORead, pClients[i].m_Stats.m_IOWrite,
|
||||
pClients[i].m_Stats.m_aCustom);
|
||||
pBuf += strlen(pBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// sava network traffic record to json when close client
|
||||
// last_network_in == last network in record, last_network_out == last network out record
|
||||
str_format(pBuf, sizeof(aFileBuf) - (pBuf - aFileBuf), "{ \"name\": \"%s\", \"type\": \"%s\", \"host\": \"%s\", \"location\": \"%s\", \"online4\": false, \"online6\": false, \"last_network_in\": %" PRId64 ", \"last_network_out\": %" PRId64 " },\n",
|
||||
pClients[i].m_aName, pClients[i].m_aType, pClients[i].m_aHost, pClients[i].m_aLocation, pClients[i].m_LastNetworkIN, pClients[i].m_LastNetworkOUT);
|
||||
pBuf += strlen(pBuf);
|
||||
}
|
||||
}
|
||||
if(!m_pJSONUpdateThreadData->m_ReloadRequired)
|
||||
str_format(pBuf - 2, sizeof(aFileBuf) - (pBuf - aFileBuf), "\n],\n\"updated\": \"%lld\"\n}", (long long)time(/*ago*/0));
|
||||
else
|
||||
{
|
||||
str_format(pBuf - 2, sizeof(aFileBuf) - (pBuf - aFileBuf), "\n],\n\"updated\": \"%lld\",\n\"reload\": true\n}", (long long)time(/*ago*/0));
|
||||
m_pJSONUpdateThreadData->m_ReloadRequired--;
|
||||
}
|
||||
pBuf += strlen(pBuf);
|
||||
|
||||
char aJSONFileTmp[1024];
|
||||
str_format(aJSONFileTmp, sizeof(aJSONFileTmp), "%s~", pConfig->m_aJSONFile);
|
||||
IOHANDLE File = io_open(aJSONFileTmp, IOFLAG_WRITE);
|
||||
if(!File)
|
||||
{
|
||||
dbg_msg("main", "Couldn't open %s", aJSONFileTmp);
|
||||
exit(1);
|
||||
}
|
||||
io_write(File, aFileBuf, (pBuf - aFileBuf));
|
||||
io_flush(File);
|
||||
io_close(File);
|
||||
fs_rename(aJSONFileTmp, pConfig->m_aJSONFile);
|
||||
thread_sleep(1000);
|
||||
}
|
||||
// support by: https://cpp.la. don't remove month traffic record, storage as "stats.json~", remark: 2021-10-18
|
||||
// fs_remove(pConfig->m_aJSONFile);
|
||||
char aJSONFileTmp[1024];
|
||||
str_format(aJSONFileTmp, sizeof(aJSONFileTmp), "%s~", pConfig->m_aJSONFile);
|
||||
fs_rename(pConfig->m_aJSONFile, aJSONFileTmp);
|
||||
}
|
||||
|
||||
int CMain::ReadConfig()
|
||||
{
|
||||
// read and parse config
|
||||
IOHANDLE File = io_open(m_Config.m_aConfigFile, IOFLAG_READ);
|
||||
if(!File)
|
||||
{
|
||||
dbg_msg("main", "Couldn't open %s", m_Config.m_aConfigFile);
|
||||
return 1;
|
||||
}
|
||||
int FileSize = (int)io_length(File);
|
||||
char *pFileData = (char *)mem_alloc(FileSize + 1, 1);
|
||||
|
||||
io_read(File, pFileData, FileSize);
|
||||
pFileData[FileSize] = 0;
|
||||
io_close(File);
|
||||
|
||||
// parse json data
|
||||
json_settings JsonSettings;
|
||||
mem_zero(&JsonSettings, sizeof(JsonSettings));
|
||||
char aError[256];
|
||||
json_value *pJsonData = json_parse_ex(&JsonSettings, pFileData, strlen(pFileData), aError);
|
||||
if(!pJsonData)
|
||||
{
|
||||
dbg_msg("main", "JSON Error in file %s: %s", m_Config.m_aConfigFile, aError);
|
||||
mem_free(pFileData);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// reset clients
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(!Client(i)->m_Active || !Client(i)->m_Connected)
|
||||
continue;
|
||||
|
||||
m_Server.Network()->Drop(Client(i)->m_ClientNetID, "Server reloading...");
|
||||
}
|
||||
mem_zero(m_aClients, sizeof(m_aClients));
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
m_aClients[i].m_ClientNetID = -1;
|
||||
|
||||
// extract data
|
||||
int ID = 0;
|
||||
const json_value &rStart = (*pJsonData)["servers"];
|
||||
if(rStart.type == json_array)
|
||||
{
|
||||
for(unsigned i = 0; i < rStart.u.array.length; i++)
|
||||
{
|
||||
if(ID < 0 || ID >= NET_MAX_CLIENTS)
|
||||
continue;
|
||||
|
||||
Client(ID)->m_Active = true;
|
||||
Client(ID)->m_Disabled = rStart[i]["disabled"].u.boolean;
|
||||
str_copy(Client(ID)->m_aName, rStart[i]["name"].u.string.ptr, sizeof(Client(ID)->m_aName));
|
||||
str_copy(Client(ID)->m_aUsername, rStart[i]["username"].u.string.ptr, sizeof(Client(ID)->m_aUsername));
|
||||
str_copy(Client(ID)->m_aType, rStart[i]["type"].u.string.ptr, sizeof(Client(ID)->m_aType));
|
||||
str_copy(Client(ID)->m_aHost, rStart[i]["host"].u.string.ptr, sizeof(Client(ID)->m_aHost));
|
||||
str_copy(Client(ID)->m_aLocation, rStart[i]["location"].u.string.ptr, sizeof(Client(ID)->m_aLocation));
|
||||
str_copy(Client(ID)->m_aPassword, rStart[i]["password"].u.string.ptr, sizeof(Client(ID)->m_aPassword));
|
||||
//if month start day > 28, diff: 3days(29,30,31)
|
||||
Client(ID)->m_aMonthStart = rStart[i]["monthstart"].u.integer;
|
||||
if(Client(ID)->m_aMonthStart > 28)
|
||||
{
|
||||
Client(ID)->m_aMonthStart = 28;
|
||||
}
|
||||
Client(ID)->m_LastNetworkIN = 0;
|
||||
Client(ID)->m_LastNetworkOUT = 0;
|
||||
|
||||
if(m_Config.m_Verbose)
|
||||
{
|
||||
if(Client(ID)->m_Disabled)
|
||||
dbg_msg("main", "[#%d: Name: \"%s\", Username: \"%s\", Type: \"%s\", Host: \"%s\", Location: \"%s\", Password: \"%s\", MonthStart: %\" PRId64 \"]",
|
||||
ID, Client(ID)->m_aName, Client(ID)->m_aUsername, Client(ID)->m_aType, Client(ID)->m_aHost, Client(ID)->m_aLocation, Client(ID)->m_aPassword, Client(ID)->m_aMonthStart);
|
||||
else
|
||||
dbg_msg("main", "#%d: Name: \"%s\", Username: \"%s\", Type: \"%s\", Host: \"%s\", Location: \"%s\", Password: \"%s\", MonthStart: %\" PRId64 \"",
|
||||
ID, Client(ID)->m_aName, Client(ID)->m_aUsername, Client(ID)->m_aType, Client(ID)->m_aHost, Client(ID)->m_aLocation, Client(ID)->m_aPassword, Client(ID)->m_aMonthStart);
|
||||
|
||||
}
|
||||
ID++;
|
||||
}
|
||||
}
|
||||
|
||||
// watch dog
|
||||
// support by: https://cpp.la
|
||||
ID = 0;
|
||||
const json_value &jStart = (*pJsonData)["watchdog"];
|
||||
if(jStart.type == json_array)
|
||||
{
|
||||
for(unsigned i = 0; i < jStart.u.array.length; i++)
|
||||
{
|
||||
if(ID < 0 || ID >= NET_MAX_CLIENTS)
|
||||
continue;
|
||||
|
||||
str_copy(Watchdog(ID)->m_aName, jStart[i]["name"].u.string.ptr, sizeof(Watchdog(ID)->m_aName));
|
||||
str_copy(Watchdog(ID)->m_aRule, jStart[i]["rule"].u.string.ptr, sizeof(Watchdog(ID)->m_aRule));
|
||||
Watchdog(ID)->m_aInterval = jStart[i]["interval"].u.integer;
|
||||
str_copy(Watchdog(ID)->m_aCallback, jStart[i]["callback"].u.string.ptr, sizeof(Watchdog(ID)->m_aCallback));
|
||||
|
||||
ID++;
|
||||
}
|
||||
str_copy(Watchdog(ID)->m_aName, "NULL", sizeof(Watchdog(ID)->m_aName));
|
||||
} else
|
||||
str_copy(Watchdog(ID)->m_aName, "NULL", sizeof(Watchdog(ID)->m_aName));
|
||||
|
||||
// if file exists, read last network traffic record,reset m_LastNetworkIN and m_LastNetworkOUT
|
||||
// support by: https://cpp.la
|
||||
IOHANDLE nFile = io_open(m_Config.m_aJSONFile, IOFLAG_READ);
|
||||
if(!nFile)
|
||||
{
|
||||
char aJSONFileTmp[1024];
|
||||
str_format(aJSONFileTmp, sizeof(aJSONFileTmp), "%s~", m_Config.m_aJSONFile);
|
||||
nFile = io_open(aJSONFileTmp, IOFLAG_READ);
|
||||
}
|
||||
if(nFile)
|
||||
{
|
||||
int nFileSize = (int)io_length(nFile);
|
||||
char *pNFileData = (char *)mem_alloc(nFileSize + 1, 1);
|
||||
|
||||
io_read(nFile, pNFileData, nFileSize);
|
||||
pNFileData[nFileSize] = 0;
|
||||
io_close(nFile);
|
||||
|
||||
json_settings nJsonSettings;
|
||||
mem_zero(&nJsonSettings, sizeof(nJsonSettings));
|
||||
json_value *pNJsonData = json_parse_ex(&nJsonSettings, pNFileData, strlen(pNFileData), aError);
|
||||
if(pNJsonData)
|
||||
{
|
||||
const json_value &cStart = (*pNJsonData)["servers"];
|
||||
if(rStart.type == json_array)
|
||||
{
|
||||
int ID = 0;
|
||||
for(unsigned i = 0; i < rStart.u.array.length; i++)
|
||||
{
|
||||
if(ID < 0 || ID >= NET_MAX_CLIENTS)
|
||||
continue;
|
||||
for(unsigned j = 0; j < cStart.u.array.length; j++)
|
||||
{
|
||||
if(strcmp(Client(ID)->m_aName, cStart[j]["name"].u.string.ptr)==0 &&
|
||||
strcmp(Client(ID)->m_aType, cStart[j]["type"].u.string.ptr)==0 &&
|
||||
strcmp(Client(ID)->m_aHost, cStart[j]["host"].u.string.ptr)==0 &&
|
||||
strcmp(Client(ID)->m_aLocation, cStart[j]["location"].u.string.ptr)==0)
|
||||
{
|
||||
Client(ID)->m_LastNetworkIN = cStart[j]["last_network_in"].u.integer;
|
||||
Client(ID)->m_LastNetworkOUT = cStart[j]["last_network_out"].u.integer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ID++;
|
||||
}
|
||||
}
|
||||
json_value_free(pNJsonData);
|
||||
}
|
||||
mem_free(pNFileData);
|
||||
}
|
||||
|
||||
// clean up
|
||||
json_value_free(pJsonData);
|
||||
mem_free(pFileData);
|
||||
|
||||
// tell clients to reload the page
|
||||
m_JSONUpdateThreadData.m_ReloadRequired = 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMain::Run()
|
||||
{
|
||||
if(m_Server.Init(this, m_Config.m_aBindAddr, m_Config.m_Port))
|
||||
return 1;
|
||||
|
||||
if(ReadConfig())
|
||||
return 1;
|
||||
|
||||
// Start JSON Update Thread
|
||||
m_JSONUpdateThreadData.m_ReloadRequired = 2;
|
||||
m_JSONUpdateThreadData.pClients = m_aClients;
|
||||
m_JSONUpdateThreadData.pConfig = &m_Config;
|
||||
void *LoadThread = thread_create(JSONUpdateThread, &m_JSONUpdateThreadData);
|
||||
//thread_detach(LoadThread);
|
||||
|
||||
while(gs_Running)
|
||||
{
|
||||
if(gs_ReloadConfig)
|
||||
{
|
||||
if(ReadConfig())
|
||||
return 1;
|
||||
m_Server.NetBan()->UnbanAll();
|
||||
gs_ReloadConfig = 0;
|
||||
}
|
||||
|
||||
m_Server.Update();
|
||||
|
||||
// wait for incomming data
|
||||
net_socket_read_wait(*m_Server.Network()->Socket(), 10);
|
||||
}
|
||||
|
||||
dbg_msg("server", "Closing.");
|
||||
m_Server.Network()->Close();
|
||||
thread_wait(LoadThread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
int RetVal;
|
||||
dbg_logger_stdout();
|
||||
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
signal(SIGINT, ExitFunc);
|
||||
signal(SIGTERM, ExitFunc);
|
||||
signal(SIGQUIT, ExitFunc);
|
||||
signal(SIGHUP, ReloadFunc);
|
||||
#endif
|
||||
|
||||
char aUsage[128];
|
||||
CConfig Config;
|
||||
str_format(aUsage, sizeof(aUsage), "%s [options]", argv[0]);
|
||||
const char *pConfigFile = 0;
|
||||
const char *pWebDir = 0;
|
||||
const char *pBindAddr = 0;
|
||||
|
||||
struct argparse_option aOptions[] = {
|
||||
OPT_HELP(),
|
||||
OPT_BOOLEAN('v', "verbose", &Config.m_Verbose, "Verbose output", 0),
|
||||
OPT_STRING('c', "config", &pConfigFile, "Config file to use", 0),
|
||||
OPT_STRING('d', "web-dir", &pWebDir, "Location of the web directory", 0),
|
||||
OPT_STRING('b', "bind", &pBindAddr, "Bind to address", 0),
|
||||
OPT_INTEGER('p', "port", &Config.m_Port, "Listen on port", 0),
|
||||
OPT_END(),
|
||||
};
|
||||
struct argparse Argparse;
|
||||
argparse_init(&Argparse, aOptions, aUsage, 0);
|
||||
argc = argparse_parse(&Argparse, argc, argv);
|
||||
|
||||
if(pConfigFile)
|
||||
str_copy(Config.m_aConfigFile, pConfigFile, sizeof(Config.m_aConfigFile));
|
||||
if(pWebDir)
|
||||
str_copy(Config.m_aWebDir, pWebDir, sizeof(Config.m_aWebDir));
|
||||
if(pBindAddr)
|
||||
str_copy(Config.m_aBindAddr, pBindAddr, sizeof(Config.m_aBindAddr));
|
||||
|
||||
if(Config.m_aWebDir[strlen(Config.m_aWebDir)-1] != '/')
|
||||
str_append(Config.m_aWebDir, "/", sizeof(Config.m_aWebDir));
|
||||
if(!fs_is_dir(Config.m_aWebDir))
|
||||
{
|
||||
dbg_msg("main", "ERROR: Can't find web directory: %s", Config.m_aWebDir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char aTmp[1024];
|
||||
str_format(aTmp, sizeof(aTmp), "%s%s", Config.m_aWebDir, Config.m_aJSONFile);
|
||||
str_copy(Config.m_aJSONFile, aTmp, sizeof(Config.m_aJSONFile));
|
||||
|
||||
CMain Main(Config);
|
||||
RetVal = Main.Run();
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "server.h"
|
||||
|
||||
class CConfig
|
||||
{
|
||||
public:
|
||||
bool m_Verbose;
|
||||
char m_aConfigFile[1024];
|
||||
char m_aWebDir[1024];
|
||||
char m_aTemplateFile[1024];
|
||||
char m_aJSONFile[1024];
|
||||
char m_aBindAddr[256];
|
||||
int m_Port;
|
||||
|
||||
CConfig();
|
||||
};
|
||||
|
||||
class CMain
|
||||
{
|
||||
CConfig m_Config;
|
||||
CServer m_Server;
|
||||
|
||||
struct CClient
|
||||
{
|
||||
bool m_Active;
|
||||
bool m_Disabled;
|
||||
bool m_Connected;
|
||||
int m_ClientNetID;
|
||||
int m_ClientNetType;
|
||||
char m_aUsername[128];
|
||||
char m_aName[128];
|
||||
char m_aType[128];
|
||||
char m_aHost[128];
|
||||
char m_aLocation[128];
|
||||
char m_aPassword[128];
|
||||
int m_aMonthStart; //track month network traffic. by: https://cpp.la
|
||||
|
||||
int64_t m_LastNetworkIN; //restore month traffic info.
|
||||
int64_t m_LastNetworkOUT; //restore month traffic info.
|
||||
int64_t m_TimeConnected;
|
||||
int64_t m_LastUpdate;
|
||||
int64_t m_AlarmLastTime; //record last alarm time.
|
||||
|
||||
struct CStats
|
||||
{
|
||||
bool m_Online4;
|
||||
bool m_Online6;
|
||||
// bool m_IpStatus, delete ip_status check, Duplicate packet loss rate detection
|
||||
// mh361 or mh370, mourn mh370, 2014-03-08 01:20 lost from all over the world. by:https://cpp.la
|
||||
int64_t m_Uptime;
|
||||
double m_Load_1;
|
||||
double m_Load_5;
|
||||
double m_Load_15;
|
||||
double m_ping_10010;
|
||||
double m_ping_189;
|
||||
double m_ping_10086;
|
||||
int64_t m_time_10010;
|
||||
int64_t m_time_189;
|
||||
int64_t m_time_10086;
|
||||
int64_t m_NetworkRx;
|
||||
int64_t m_NetworkTx;
|
||||
int64_t m_NetworkIN;
|
||||
int64_t m_NetworkOUT;
|
||||
int64_t m_MemTotal;
|
||||
int64_t m_MemUsed;
|
||||
int64_t m_SwapTotal;
|
||||
int64_t m_SwapUsed;
|
||||
int64_t m_HDDTotal;
|
||||
int64_t m_HDDUsed;
|
||||
int64_t m_tcpCount;
|
||||
int64_t m_udpCount;
|
||||
int64_t m_processCount;
|
||||
int64_t m_threadCount;
|
||||
int64_t m_IORead;
|
||||
int64_t m_IOWrite;
|
||||
double m_CPU;
|
||||
char m_aCustom[512];
|
||||
// Options
|
||||
bool m_Pong;
|
||||
} m_Stats;
|
||||
} m_aClients[NET_MAX_CLIENTS];
|
||||
|
||||
struct CWatchDog{
|
||||
char m_aName[128];
|
||||
char m_aRule[128];
|
||||
int m_aInterval;
|
||||
char m_aCallback[1024];
|
||||
} m_aCWatchDogs[NET_MAX_CLIENTS];
|
||||
|
||||
struct CJSONUpdateThreadData
|
||||
{
|
||||
CClient *pClients;
|
||||
CConfig *pConfig;
|
||||
volatile short m_ReloadRequired;
|
||||
} m_JSONUpdateThreadData;
|
||||
|
||||
static void JSONUpdateThread(void *pUser);
|
||||
public:
|
||||
CMain(CConfig Config);
|
||||
|
||||
void OnNewClient(int ClienNettID, int ClientID);
|
||||
void OnDelClient(int ClientNetID);
|
||||
int HandleMessage(int ClientNetID, char *pMessage);
|
||||
int ReadConfig();
|
||||
int Run();
|
||||
|
||||
CWatchDog *Watchdog(int ruleID) { return &m_aCWatchDogs[ruleID]; }
|
||||
void WatchdogMessage(int ClientNetID,
|
||||
double load_1, double load_5, double load_15, double ping_10010, double ping_189, double ping_10086,
|
||||
double time_10010, double time_189, double time_10086, double tcp_count, double udp_count, double process_count, double thread_count,
|
||||
double network_rx, double network_tx, double network_in, double network_out,double memory_total,
|
||||
double memory_used,double swap_total, double swap_used, double hdd_total,
|
||||
double hdd_used, double io_read, double io_write, double cpu,double online4, double online6);
|
||||
|
||||
CClient *Client(int ClientID) { return &m_aClients[ClientID]; }
|
||||
CClient *ClientNet(int ClientNetID);
|
||||
const CConfig *Config() const { return &m_Config; }
|
||||
int ClientNetToClient(int ClientNetID);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,463 +0,0 @@
|
||||
#include <math.h>
|
||||
#include "netban.h"
|
||||
|
||||
bool CNetBan::StrAllnum(const char *pStr)
|
||||
{
|
||||
while(*pStr)
|
||||
{
|
||||
if(!(*pStr >= '0' && *pStr <= '9'))
|
||||
return false;
|
||||
pStr++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CNetBan::CNetHash::CNetHash(const NETADDR *pAddr)
|
||||
{
|
||||
if(pAddr->type==NETTYPE_IPV4)
|
||||
m_Hash = (pAddr->ip[0]+pAddr->ip[1]+pAddr->ip[2]+pAddr->ip[3])&0xFF;
|
||||
else
|
||||
m_Hash = (pAddr->ip[0]+pAddr->ip[1]+pAddr->ip[2]+pAddr->ip[3]+pAddr->ip[4]+pAddr->ip[5]+pAddr->ip[6]+pAddr->ip[7]+
|
||||
pAddr->ip[8]+pAddr->ip[9]+pAddr->ip[10]+pAddr->ip[11]+pAddr->ip[12]+pAddr->ip[13]+pAddr->ip[14]+pAddr->ip[15])&0xFF;
|
||||
m_HashIndex = 0;
|
||||
}
|
||||
|
||||
CNetBan::CNetHash::CNetHash(const CNetRange *pRange)
|
||||
{
|
||||
m_Hash = 0;
|
||||
m_HashIndex = 0;
|
||||
for(int i = 0; pRange->m_LB.ip[i] == pRange->m_UB.ip[i]; ++i)
|
||||
{
|
||||
m_Hash += pRange->m_LB.ip[i];
|
||||
++m_HashIndex;
|
||||
}
|
||||
m_Hash &= 0xFF;
|
||||
}
|
||||
|
||||
int CNetBan::CNetHash::MakeHashArray(const NETADDR *pAddr, CNetHash aHash[17])
|
||||
{
|
||||
int Length = pAddr->type==NETTYPE_IPV4 ? 4 : 16;
|
||||
aHash[0].m_Hash = 0;
|
||||
aHash[0].m_HashIndex = 0;
|
||||
for(int i = 1, Sum = 0; i <= Length; ++i)
|
||||
{
|
||||
Sum += pAddr->ip[i-1];
|
||||
aHash[i].m_Hash = Sum&0xFF;
|
||||
aHash[i].m_HashIndex = i%Length;
|
||||
}
|
||||
return Length;
|
||||
}
|
||||
|
||||
|
||||
template<class T, int HashCount>
|
||||
typename CNetBan::CBan<T> *CNetBan::CBanPool<T, HashCount>::Add(const T *pData, const CBanInfo *pInfo, const CNetHash *pNetHash)
|
||||
{
|
||||
if(!m_pFirstFree)
|
||||
return 0;
|
||||
|
||||
// create new ban
|
||||
CBan<T> *pBan = m_pFirstFree;
|
||||
pBan->m_Data = *pData;
|
||||
pBan->m_Info = *pInfo;
|
||||
pBan->m_NetHash = *pNetHash;
|
||||
if(pBan->m_pNext)
|
||||
pBan->m_pNext->m_pPrev = pBan->m_pPrev;
|
||||
if(pBan->m_pPrev)
|
||||
pBan->m_pPrev->m_pNext = pBan->m_pNext;
|
||||
else
|
||||
m_pFirstFree = pBan->m_pNext;
|
||||
|
||||
// add it to the hash list
|
||||
if(m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash])
|
||||
m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]->m_pHashPrev = pBan;
|
||||
pBan->m_pHashPrev = 0;
|
||||
pBan->m_pHashNext = m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash];
|
||||
m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash] = pBan;
|
||||
|
||||
// insert it into the used list
|
||||
if(m_pFirstUsed)
|
||||
{
|
||||
for(CBan<T> *p = m_pFirstUsed; ; p = p->m_pNext)
|
||||
{
|
||||
if(p->m_Info.m_Expires == CBanInfo::EXPIRES_NEVER || (pInfo->m_Expires != CBanInfo::EXPIRES_NEVER && pInfo->m_Expires <= p->m_Info.m_Expires))
|
||||
{
|
||||
// insert before
|
||||
pBan->m_pNext = p;
|
||||
pBan->m_pPrev = p->m_pPrev;
|
||||
if(p->m_pPrev)
|
||||
p->m_pPrev->m_pNext = pBan;
|
||||
else
|
||||
m_pFirstUsed = pBan;
|
||||
p->m_pPrev = pBan;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!p->m_pNext)
|
||||
{
|
||||
// last entry
|
||||
p->m_pNext = pBan;
|
||||
pBan->m_pPrev = p;
|
||||
pBan->m_pNext = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstUsed = pBan;
|
||||
pBan->m_pNext = pBan->m_pPrev = 0;
|
||||
}
|
||||
|
||||
// update ban count
|
||||
++m_CountUsed;
|
||||
|
||||
return pBan;
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
int CNetBan::CBanPool<T, HashCount>::Remove(CBan<T> *pBan)
|
||||
{
|
||||
if(pBan == 0)
|
||||
return -1;
|
||||
|
||||
// remove from hash list
|
||||
if(pBan->m_pHashNext)
|
||||
pBan->m_pHashNext->m_pHashPrev = pBan->m_pHashPrev;
|
||||
if(pBan->m_pHashPrev)
|
||||
pBan->m_pHashPrev->m_pHashNext = pBan->m_pHashNext;
|
||||
else
|
||||
m_paaHashList[pBan->m_NetHash.m_HashIndex][pBan->m_NetHash.m_Hash] = pBan->m_pHashNext;
|
||||
pBan->m_pHashNext = pBan->m_pHashPrev = 0;
|
||||
|
||||
// remove from used list
|
||||
if(pBan->m_pNext)
|
||||
pBan->m_pNext->m_pPrev = pBan->m_pPrev;
|
||||
if(pBan->m_pPrev)
|
||||
pBan->m_pPrev->m_pNext = pBan->m_pNext;
|
||||
else
|
||||
m_pFirstUsed = pBan->m_pNext;
|
||||
|
||||
// add to recycle list
|
||||
if(m_pFirstFree)
|
||||
m_pFirstFree->m_pPrev = pBan;
|
||||
pBan->m_pPrev = 0;
|
||||
pBan->m_pNext = m_pFirstFree;
|
||||
m_pFirstFree = pBan;
|
||||
|
||||
// update ban count
|
||||
--m_CountUsed;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
void CNetBan::CBanPool<T, HashCount>::Update(CBan<CDataType> *pBan, const CBanInfo *pInfo)
|
||||
{
|
||||
pBan->m_Info = *pInfo;
|
||||
|
||||
// remove from used list
|
||||
if(pBan->m_pNext)
|
||||
pBan->m_pNext->m_pPrev = pBan->m_pPrev;
|
||||
if(pBan->m_pPrev)
|
||||
pBan->m_pPrev->m_pNext = pBan->m_pNext;
|
||||
else
|
||||
m_pFirstUsed = pBan->m_pNext;
|
||||
|
||||
// insert it into the used list
|
||||
if(m_pFirstUsed)
|
||||
{
|
||||
for(CBan<T> *p = m_pFirstUsed; ; p = p->m_pNext)
|
||||
{
|
||||
if(p->m_Info.m_Expires == CBanInfo::EXPIRES_NEVER || (pInfo->m_Expires != CBanInfo::EXPIRES_NEVER && pInfo->m_Expires <= p->m_Info.m_Expires))
|
||||
{
|
||||
// insert before
|
||||
pBan->m_pNext = p;
|
||||
pBan->m_pPrev = p->m_pPrev;
|
||||
if(p->m_pPrev)
|
||||
p->m_pPrev->m_pNext = pBan;
|
||||
else
|
||||
m_pFirstUsed = pBan;
|
||||
p->m_pPrev = pBan;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!p->m_pNext)
|
||||
{
|
||||
// last entry
|
||||
p->m_pNext = pBan;
|
||||
pBan->m_pPrev = p;
|
||||
pBan->m_pNext = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstUsed = pBan;
|
||||
pBan->m_pNext = pBan->m_pPrev = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
void CNetBan::CBanPool<T, HashCount>::Reset()
|
||||
{
|
||||
mem_zero(m_paaHashList, sizeof(m_paaHashList));
|
||||
mem_zero(m_aBans, sizeof(m_aBans));
|
||||
m_pFirstUsed = 0;
|
||||
m_CountUsed = 0;
|
||||
|
||||
for(int i = 1; i < MAX_BANS-1; ++i)
|
||||
{
|
||||
m_aBans[i].m_pNext = &m_aBans[i+1];
|
||||
m_aBans[i].m_pPrev = &m_aBans[i-1];
|
||||
}
|
||||
|
||||
m_aBans[0].m_pNext = &m_aBans[1];
|
||||
m_aBans[MAX_BANS-1].m_pPrev = &m_aBans[MAX_BANS-2];
|
||||
m_pFirstFree = &m_aBans[0];
|
||||
}
|
||||
|
||||
template<class T, int HashCount>
|
||||
typename CNetBan::CBan<T> *CNetBan::CBanPool<T, HashCount>::Get(int Index) const
|
||||
{
|
||||
if(Index < 0 || Index >= Num())
|
||||
return 0;
|
||||
|
||||
for(CNetBan::CBan<T> *pBan = m_pFirstUsed; pBan; pBan = pBan->m_pNext, --Index)
|
||||
{
|
||||
if(Index == 0)
|
||||
return pBan;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void CNetBan::MakeBanInfo(const CBan<T> *pBan, char *pBuf, unsigned BuffSize, int Type) const
|
||||
{
|
||||
if(pBan == 0 || pBuf == 0)
|
||||
{
|
||||
if(BuffSize > 0)
|
||||
pBuf[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// build type based part
|
||||
char aBuf[256];
|
||||
if(Type == MSGTYPE_PLAYER)
|
||||
str_copy(aBuf, "You have been banned", sizeof(aBuf));
|
||||
else
|
||||
{
|
||||
char aTemp[256];
|
||||
switch(Type)
|
||||
{
|
||||
case MSGTYPE_LIST:
|
||||
str_format(aBuf, sizeof(aBuf), "%s banned", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break;
|
||||
case MSGTYPE_BANADD:
|
||||
str_format(aBuf, sizeof(aBuf), "banned %s", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break;
|
||||
case MSGTYPE_BANREM:
|
||||
str_format(aBuf, sizeof(aBuf), "unbanned %s", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break;
|
||||
default:
|
||||
aBuf[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// add info part
|
||||
if(pBan->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER)
|
||||
{
|
||||
int Mins = ((pBan->m_Info.m_Expires-time_timestamp()) + 59) / 60;
|
||||
if(Mins <= 1)
|
||||
str_format(pBuf, BuffSize, "%s for 1 minute (%s)", aBuf, pBan->m_Info.m_aReason);
|
||||
else
|
||||
str_format(pBuf, BuffSize, "%s for %d minutes (%s)", aBuf, Mins, pBan->m_Info.m_aReason);
|
||||
}
|
||||
else
|
||||
str_format(pBuf, BuffSize, "%s for life (%s)", aBuf, pBan->m_Info.m_aReason);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int CNetBan::Ban(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason)
|
||||
{
|
||||
// do not ban localhost
|
||||
if(NetMatch(pData, &m_LocalhostIPV4) || NetMatch(pData, &m_LocalhostIPV6))
|
||||
{
|
||||
dbg_msg("net_ban", "ban failed (localhost)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Stamp = Seconds > 0 ? time_timestamp()+Seconds : CBanInfo::EXPIRES_NEVER;
|
||||
|
||||
// set up info
|
||||
CBanInfo Info = {0};
|
||||
Info.m_Expires = Stamp;
|
||||
str_copy(Info.m_aReason, pReason, sizeof(Info.m_aReason));
|
||||
|
||||
// check if it already exists
|
||||
CNetHash NetHash(pData);
|
||||
CBan<typename T::CDataType> *pBan = pBanPool->Find(pData, &NetHash);
|
||||
if(pBan)
|
||||
{
|
||||
// adjust the ban
|
||||
pBanPool->Update(pBan, &Info);
|
||||
char aBuf[128];
|
||||
MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_LIST);
|
||||
dbg_msg("net_ban", aBuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// add ban and print result
|
||||
pBan = pBanPool->Add(pData, &Info, &NetHash);
|
||||
if(pBan)
|
||||
{
|
||||
char aBuf[128];
|
||||
MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_BANADD);
|
||||
dbg_msg("net_ban", aBuf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
dbg_msg("net_ban", "ban failed (full banlist)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int CNetBan::Unban(T *pBanPool, const typename T::CDataType *pData)
|
||||
{
|
||||
CNetHash NetHash(pData);
|
||||
CBan<typename T::CDataType> *pBan = pBanPool->Find(pData, &NetHash);
|
||||
if(pBan)
|
||||
{
|
||||
char aBuf[256];
|
||||
MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_BANREM);
|
||||
pBanPool->Remove(pBan);
|
||||
dbg_msg("net_ban", aBuf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
dbg_msg("net_ban", "unban failed (invalid entry)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CNetBan::Init()
|
||||
{
|
||||
m_BanAddrPool.Reset();
|
||||
m_BanRangePool.Reset();
|
||||
|
||||
net_host_lookup("localhost", &m_LocalhostIPV4, NETTYPE_IPV4);
|
||||
net_host_lookup("localhost", &m_LocalhostIPV6, NETTYPE_IPV6);
|
||||
}
|
||||
|
||||
void CNetBan::Update()
|
||||
{
|
||||
int Now = time_timestamp();
|
||||
|
||||
// remove expired bans
|
||||
char aBuf[256], aNetStr[256];
|
||||
while(m_BanAddrPool.First() && m_BanAddrPool.First()->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER && m_BanAddrPool.First()->m_Info.m_Expires < Now)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "ban %s expired", NetToString(&m_BanAddrPool.First()->m_Data, aNetStr, sizeof(aNetStr)));
|
||||
dbg_msg("net_ban", aBuf);
|
||||
m_BanAddrPool.Remove(m_BanAddrPool.First());
|
||||
}
|
||||
while(m_BanRangePool.First() && m_BanRangePool.First()->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER && m_BanRangePool.First()->m_Info.m_Expires < Now)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "ban %s expired", NetToString(&m_BanRangePool.First()->m_Data, aNetStr, sizeof(aNetStr)));
|
||||
dbg_msg("net_ban", aBuf);
|
||||
m_BanRangePool.Remove(m_BanRangePool.First());
|
||||
}
|
||||
}
|
||||
|
||||
int CNetBan::BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason)
|
||||
{
|
||||
return Ban(&m_BanAddrPool, pAddr, Seconds, pReason);
|
||||
}
|
||||
|
||||
int CNetBan::BanRange(const CNetRange *pRange, int Seconds, const char *pReason)
|
||||
{
|
||||
if(pRange->IsValid())
|
||||
return Ban(&m_BanRangePool, pRange, Seconds, pReason);
|
||||
|
||||
dbg_msg("net_ban", "ban failed (invalid range)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CNetBan::UnbanByAddr(const NETADDR *pAddr)
|
||||
{
|
||||
return Unban(&m_BanAddrPool, pAddr);
|
||||
}
|
||||
|
||||
int CNetBan::UnbanByRange(const CNetRange *pRange)
|
||||
{
|
||||
if(pRange->IsValid())
|
||||
return Unban(&m_BanRangePool, pRange);
|
||||
|
||||
dbg_msg("net_ban", "ban failed (invalid range)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CNetBan::UnbanByIndex(int Index)
|
||||
{
|
||||
int Result;
|
||||
char aBuf[256];
|
||||
CBanAddr *pBan = m_BanAddrPool.Get(Index);
|
||||
if(pBan)
|
||||
{
|
||||
NetToString(&pBan->m_Data, aBuf, sizeof(aBuf));
|
||||
Result = m_BanAddrPool.Remove(pBan);
|
||||
}
|
||||
else
|
||||
{
|
||||
CBanRange *pBan = m_BanRangePool.Get(Index-m_BanAddrPool.Num());
|
||||
if(pBan)
|
||||
{
|
||||
NetToString(&pBan->m_Data, aBuf, sizeof(aBuf));
|
||||
Result = m_BanRangePool.Remove(pBan);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_msg("net_ban", "unban failed (invalid index)");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
char aMsg[256];
|
||||
str_format(aMsg, sizeof(aMsg), "unbanned index %i (%s)", Index, aBuf);
|
||||
dbg_msg("net_ban", aMsg);
|
||||
return Result;
|
||||
}
|
||||
|
||||
void CNetBan::UnbanAll()
|
||||
{
|
||||
m_BanAddrPool.Reset();
|
||||
m_BanRangePool.Reset();
|
||||
}
|
||||
|
||||
bool CNetBan::IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize) const
|
||||
{
|
||||
CNetHash aHash[17];
|
||||
int Length = CNetHash::MakeHashArray(pAddr, aHash);
|
||||
|
||||
// check ban adresses
|
||||
CBanAddr *pBan = m_BanAddrPool.Find(pAddr, &aHash[Length]);
|
||||
if(pBan)
|
||||
{
|
||||
MakeBanInfo(pBan, pBuf, BufferSize, MSGTYPE_PLAYER);
|
||||
return true;
|
||||
}
|
||||
|
||||
// check ban ranges
|
||||
for(int i = Length-1; i >= 0; --i)
|
||||
{
|
||||
for(CBanRange *pBan = m_BanRangePool.First(&aHash[i]); pBan; pBan = pBan->m_pHashNext)
|
||||
{
|
||||
if(NetMatch(&pBan->m_Data, pAddr, i, Length))
|
||||
{
|
||||
MakeBanInfo(pBan, pBuf, BufferSize, MSGTYPE_PLAYER);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
#ifndef NETBAN_H
|
||||
#define NETBAN_H
|
||||
|
||||
#include <system.h>
|
||||
|
||||
inline int NetComp(const NETADDR *pAddr1, const NETADDR *pAddr2)
|
||||
{
|
||||
return mem_comp(pAddr1, pAddr2, pAddr1->type==NETTYPE_IPV4 ? 8 : 20);
|
||||
}
|
||||
|
||||
class CNetRange
|
||||
{
|
||||
public:
|
||||
NETADDR m_LB;
|
||||
NETADDR m_UB;
|
||||
|
||||
bool IsValid() const { return m_LB.type == m_UB.type && NetComp(&m_LB, &m_UB) < 0; }
|
||||
};
|
||||
|
||||
inline int NetComp(const CNetRange *pRange1, const CNetRange *pRange2)
|
||||
{
|
||||
return NetComp(&pRange1->m_LB, &pRange2->m_LB) || NetComp(&pRange1->m_UB, &pRange2->m_UB);
|
||||
}
|
||||
|
||||
|
||||
class CNetBan
|
||||
{
|
||||
protected:
|
||||
bool NetMatch(const NETADDR *pAddr1, const NETADDR *pAddr2) const
|
||||
{
|
||||
return NetComp(pAddr1, pAddr2) == 0;
|
||||
}
|
||||
|
||||
bool NetMatch(const CNetRange *pRange, const NETADDR *pAddr, int Start, int Length) const
|
||||
{
|
||||
return pRange->m_LB.type == pAddr->type && (Start == 0 || mem_comp(&pRange->m_LB.ip[0], &pAddr->ip[0], Start) == 0) &&
|
||||
mem_comp(&pRange->m_LB.ip[Start], &pAddr->ip[Start], Length-Start) <= 0 && mem_comp(&pRange->m_UB.ip[Start], &pAddr->ip[Start], Length-Start) >= 0;
|
||||
}
|
||||
|
||||
bool NetMatch(const CNetRange *pRange, const NETADDR *pAddr) const
|
||||
{
|
||||
return NetMatch(pRange, pAddr, 0, pRange->m_LB.type==NETTYPE_IPV4 ? 4 : 16);
|
||||
}
|
||||
|
||||
const char *NetToString(const NETADDR *pData, char *pBuffer, unsigned BufferSize) const
|
||||
{
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(pData, aAddrStr, sizeof(aAddrStr), false);
|
||||
str_format(pBuffer, BufferSize, "'%s'", aAddrStr);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
const char *NetToString(const CNetRange *pData, char *pBuffer, unsigned BufferSize) const
|
||||
{
|
||||
char aAddrStr1[NETADDR_MAXSTRSIZE], aAddrStr2[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(&pData->m_LB, aAddrStr1, sizeof(aAddrStr1), false);
|
||||
net_addr_str(&pData->m_UB, aAddrStr2, sizeof(aAddrStr2), false);
|
||||
str_format(pBuffer, BufferSize, "'%s' - '%s'", aAddrStr1, aAddrStr2);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
// todo: move?
|
||||
static bool StrAllnum(const char *pStr);
|
||||
|
||||
class CNetHash
|
||||
{
|
||||
public:
|
||||
int m_Hash;
|
||||
int m_HashIndex; // matching parts for ranges, 0 for addr
|
||||
|
||||
CNetHash() {}
|
||||
CNetHash(const NETADDR *pAddr);
|
||||
CNetHash(const CNetRange *pRange);
|
||||
|
||||
static int MakeHashArray(const NETADDR *pAddr, CNetHash aHash[17]);
|
||||
};
|
||||
|
||||
struct CBanInfo
|
||||
{
|
||||
enum
|
||||
{
|
||||
EXPIRES_NEVER=-1,
|
||||
REASON_LENGTH=64,
|
||||
};
|
||||
int m_Expires;
|
||||
char m_aReason[REASON_LENGTH];
|
||||
};
|
||||
|
||||
template<class T> struct CBan
|
||||
{
|
||||
T m_Data;
|
||||
CBanInfo m_Info;
|
||||
CNetHash m_NetHash;
|
||||
|
||||
// hash list
|
||||
CBan *m_pHashNext;
|
||||
CBan *m_pHashPrev;
|
||||
|
||||
// used or free list
|
||||
CBan *m_pNext;
|
||||
CBan *m_pPrev;
|
||||
};
|
||||
|
||||
template<class T, int HashCount> class CBanPool
|
||||
{
|
||||
public:
|
||||
typedef T CDataType;
|
||||
|
||||
CBan<CDataType> *Add(const CDataType *pData, const CBanInfo *pInfo, const CNetHash *pNetHash);
|
||||
int Remove(CBan<CDataType> *pBan);
|
||||
void Update(CBan<CDataType> *pBan, const CBanInfo *pInfo);
|
||||
void Reset();
|
||||
|
||||
int Num() const { return m_CountUsed; }
|
||||
bool IsFull() const { return m_CountUsed == MAX_BANS; }
|
||||
|
||||
CBan<CDataType> *First() const { return m_pFirstUsed; }
|
||||
CBan<CDataType> *First(const CNetHash *pNetHash) const { return m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]; }
|
||||
CBan<CDataType> *Find(const CDataType *pData, const CNetHash *pNetHash) const
|
||||
{
|
||||
for(CBan<CDataType> *pBan = m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]; pBan; pBan = pBan->m_pHashNext)
|
||||
{
|
||||
if(NetComp(&pBan->m_Data, pData) == 0)
|
||||
return pBan;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
CBan<CDataType> *Get(int Index) const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
MAX_BANS=1024,
|
||||
};
|
||||
|
||||
CBan<CDataType> *m_paaHashList[HashCount][256];
|
||||
CBan<CDataType> m_aBans[MAX_BANS];
|
||||
CBan<CDataType> *m_pFirstFree;
|
||||
CBan<CDataType> *m_pFirstUsed;
|
||||
int m_CountUsed;
|
||||
};
|
||||
|
||||
typedef CBanPool<NETADDR, 1> CBanAddrPool;
|
||||
typedef CBanPool<CNetRange, 16> CBanRangePool;
|
||||
typedef CBan<NETADDR> CBanAddr;
|
||||
typedef CBan<CNetRange> CBanRange;
|
||||
|
||||
template<class T> void MakeBanInfo(const CBan<T> *pBan, char *pBuf, unsigned BuffSize, int Type) const;
|
||||
template<class T> int Ban(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason);
|
||||
template<class T> int Unban(T *pBanPool, const typename T::CDataType *pData);
|
||||
|
||||
CBanAddrPool m_BanAddrPool;
|
||||
CBanRangePool m_BanRangePool;
|
||||
NETADDR m_LocalhostIPV4, m_LocalhostIPV6;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MSGTYPE_PLAYER=0,
|
||||
MSGTYPE_LIST,
|
||||
MSGTYPE_BANADD,
|
||||
MSGTYPE_BANREM,
|
||||
};
|
||||
|
||||
virtual ~CNetBan() {}
|
||||
void Init();
|
||||
void Update();
|
||||
|
||||
virtual int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);
|
||||
virtual int BanRange(const CNetRange *pRange, int Seconds, const char *pReason);
|
||||
int UnbanByAddr(const NETADDR *pAddr);
|
||||
int UnbanByRange(const CNetRange *pRange);
|
||||
int UnbanByIndex(int Index);
|
||||
void UnbanAll();
|
||||
bool IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,144 +0,0 @@
|
||||
#include <system.h>
|
||||
#include "netban.h"
|
||||
#include "network.h"
|
||||
|
||||
bool CNetwork::Open(NETADDR BindAddr, CNetBan *pNetBan)
|
||||
{
|
||||
// zero out the whole structure
|
||||
mem_zero(this, sizeof(*this));
|
||||
m_Socket.type = NETTYPE_INVALID;
|
||||
m_Socket.ipv4sock = -1;
|
||||
m_Socket.ipv6sock = -1;
|
||||
m_pNetBan = pNetBan;
|
||||
|
||||
// open socket
|
||||
m_Socket = net_tcp_create(BindAddr);
|
||||
if(!m_Socket.type)
|
||||
return false;
|
||||
if(net_tcp_listen(m_Socket, NET_MAX_CLIENTS))
|
||||
return false;
|
||||
net_set_non_blocking(m_Socket);
|
||||
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
m_aSlots[i].m_Connection.Reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetwork::SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser)
|
||||
{
|
||||
m_pfnNewClient = pfnNewClient;
|
||||
m_pfnDelClient = pfnDelClient;
|
||||
m_UserPtr = pUser;
|
||||
}
|
||||
|
||||
int CNetwork::Close()
|
||||
{
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
m_aSlots[i].m_Connection.Disconnect("Closing connection.");
|
||||
|
||||
net_tcp_close(m_Socket);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CNetwork::Drop(int ClientID, const char *pReason)
|
||||
{
|
||||
if(m_pfnDelClient)
|
||||
m_pfnDelClient(ClientID, pReason, m_UserPtr);
|
||||
|
||||
m_aSlots[ClientID].m_Connection.Disconnect(pReason);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CNetwork::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr)
|
||||
{
|
||||
char aError[256] = { 0 };
|
||||
int FreeSlot = -1;
|
||||
|
||||
// look for free slot or multiple client
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(FreeSlot == -1 && m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
|
||||
FreeSlot = i;
|
||||
if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE)
|
||||
{
|
||||
if(net_addr_comp(pAddr, m_aSlots[i].m_Connection.PeerAddress()) == 0)
|
||||
{
|
||||
str_copy(aError, "Only one client per IP allowed.", sizeof(aError));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// accept client
|
||||
if(!aError[0] && FreeSlot != -1)
|
||||
{
|
||||
m_aSlots[FreeSlot].m_Connection.Init(Socket, pAddr);
|
||||
if(m_pfnNewClient)
|
||||
m_pfnNewClient(FreeSlot, m_UserPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// reject client
|
||||
if(!aError[0])
|
||||
str_copy(aError, "No free slot available.", sizeof(aError));
|
||||
|
||||
net_tcp_send(Socket, aError, str_length(aError));
|
||||
net_tcp_close(Socket);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CNetwork::Update()
|
||||
{
|
||||
NETSOCKET Socket;
|
||||
NETADDR Addr;
|
||||
|
||||
if(net_tcp_accept(m_Socket, &Socket, &Addr) > 0)
|
||||
{
|
||||
// check if we should just drop the packet
|
||||
char aBuf[128];
|
||||
if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf)))
|
||||
{
|
||||
// banned, reply with a message and drop
|
||||
net_tcp_send(Socket, aBuf, str_length(aBuf));
|
||||
net_tcp_close(Socket);
|
||||
}
|
||||
else
|
||||
AcceptClient(Socket, &Addr);
|
||||
}
|
||||
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ONLINE)
|
||||
m_aSlots[i].m_Connection.Update();
|
||||
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR)
|
||||
Drop(i, m_aSlots[i].m_Connection.ErrorString());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CNetwork::Recv(char *pLine, int MaxLength, int *pClientID)
|
||||
{
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ONLINE && m_aSlots[i].m_Connection.Recv(pLine, MaxLength))
|
||||
{
|
||||
if(pClientID)
|
||||
*pClientID = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CNetwork::Send(int ClientID, const char *pLine)
|
||||
{
|
||||
if(m_aSlots[ClientID].m_Connection.State() == NET_CONNSTATE_ONLINE)
|
||||
return m_aSlots[ClientID].m_Connection.Send(pLine);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
#ifndef NETWORK_H
|
||||
#define NETWORK_H
|
||||
|
||||
enum
|
||||
{
|
||||
NET_CONNSTATE_OFFLINE=0,
|
||||
NET_CONNSTATE_CONNECT=1,
|
||||
NET_CONNSTATE_PENDING=2,
|
||||
NET_CONNSTATE_ONLINE=3,
|
||||
NET_CONNSTATE_ERROR=4,
|
||||
|
||||
NET_MAX_PACKETSIZE = 1400,
|
||||
NET_MAX_CLIENTS = 256
|
||||
};
|
||||
|
||||
typedef int (*NETFUNC_DELCLIENT)(int ClientID, const char* pReason, void *pUser);
|
||||
typedef int (*NETFUNC_NEWCLIENT)(int ClientID, void *pUser);
|
||||
|
||||
class CNetworkClient
|
||||
{
|
||||
private:
|
||||
int m_State;
|
||||
|
||||
NETADDR m_PeerAddr;
|
||||
NETSOCKET m_Socket;
|
||||
|
||||
char m_aBuffer[NET_MAX_PACKETSIZE];
|
||||
int m_BufferOffset;
|
||||
|
||||
char m_aErrorString[256];
|
||||
|
||||
bool m_LineEndingDetected;
|
||||
char m_aLineEnding[3];
|
||||
|
||||
public:
|
||||
void Init(NETSOCKET Socket, const NETADDR *pAddr);
|
||||
void Disconnect(const char *pReason);
|
||||
|
||||
int State() const { return m_State; }
|
||||
const NETADDR *PeerAddress() const { return &m_PeerAddr; }
|
||||
const char *ErrorString() const { return m_aErrorString; }
|
||||
|
||||
void Reset();
|
||||
int Update();
|
||||
int Send(const char *pLine);
|
||||
int Recv(char *pLine, int MaxLength);
|
||||
};
|
||||
|
||||
class CNetwork
|
||||
{
|
||||
private:
|
||||
struct CSlot
|
||||
{
|
||||
CNetworkClient m_Connection;
|
||||
};
|
||||
|
||||
NETSOCKET m_Socket;
|
||||
class CNetBan *m_pNetBan;
|
||||
CSlot m_aSlots[NET_MAX_CLIENTS];
|
||||
|
||||
NETFUNC_NEWCLIENT m_pfnNewClient;
|
||||
NETFUNC_DELCLIENT m_pfnDelClient;
|
||||
void *m_UserPtr;
|
||||
|
||||
public:
|
||||
void SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
|
||||
|
||||
//
|
||||
bool Open(NETADDR BindAddr, CNetBan *pNetBan);
|
||||
int Close();
|
||||
|
||||
//
|
||||
int Recv(char *pLine, int MaxLength, int *pClientID = 0);
|
||||
int Send(int ClientID, const char *pLine);
|
||||
int Update();
|
||||
|
||||
//
|
||||
int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr);
|
||||
int Drop(int ClientID, const char *pReason);
|
||||
|
||||
// status requests
|
||||
const NETADDR *ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
|
||||
const NETSOCKET *Socket() const { return &m_Socket; }
|
||||
class CNetBan *NetBan() const { return m_pNetBan; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,184 +0,0 @@
|
||||
#include <system.h>
|
||||
#include "network.h"
|
||||
|
||||
void CNetworkClient::Reset()
|
||||
{
|
||||
m_State = NET_CONNSTATE_OFFLINE;
|
||||
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
|
||||
m_aErrorString[0] = 0;
|
||||
|
||||
m_Socket.type = NETTYPE_INVALID;
|
||||
m_Socket.ipv4sock = -1;
|
||||
m_Socket.ipv6sock = -1;
|
||||
m_aBuffer[0] = 0;
|
||||
m_BufferOffset = 0;
|
||||
|
||||
m_LineEndingDetected = false;
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
m_aLineEnding[0] = '\r';
|
||||
m_aLineEnding[1] = '\n';
|
||||
m_aLineEnding[2] = 0;
|
||||
#else
|
||||
m_aLineEnding[0] = '\n';
|
||||
m_aLineEnding[1] = 0;
|
||||
m_aLineEnding[2] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CNetworkClient::Init(NETSOCKET Socket, const NETADDR *pAddr)
|
||||
{
|
||||
Reset();
|
||||
|
||||
m_Socket = Socket;
|
||||
net_set_non_blocking(m_Socket);
|
||||
|
||||
m_PeerAddr = *pAddr;
|
||||
m_State = NET_CONNSTATE_ONLINE;
|
||||
}
|
||||
|
||||
void CNetworkClient::Disconnect(const char *pReason)
|
||||
{
|
||||
if(State() == NET_CONNSTATE_OFFLINE)
|
||||
return;
|
||||
|
||||
if(pReason && pReason[0])
|
||||
Send(pReason);
|
||||
|
||||
net_tcp_close(m_Socket);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
int CNetworkClient::Update()
|
||||
{
|
||||
if(State() == NET_CONNSTATE_ONLINE)
|
||||
{
|
||||
if((int)(sizeof(m_aBuffer)) <= m_BufferOffset)
|
||||
{
|
||||
m_State = NET_CONNSTATE_ERROR;
|
||||
str_copy(m_aErrorString, "too weak connection (out of buffer)", sizeof(m_aErrorString));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Bytes = net_tcp_recv(m_Socket, m_aBuffer+m_BufferOffset, (int)(sizeof(m_aBuffer))-m_BufferOffset);
|
||||
|
||||
if(Bytes > 0)
|
||||
{
|
||||
m_BufferOffset += Bytes;
|
||||
}
|
||||
else if(Bytes < 0)
|
||||
{
|
||||
if(net_would_block()) // no data received
|
||||
return 0;
|
||||
|
||||
m_State = NET_CONNSTATE_ERROR; // error
|
||||
str_copy(m_aErrorString, "connection failure", sizeof(m_aErrorString));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_State = NET_CONNSTATE_ERROR;
|
||||
str_copy(m_aErrorString, "remote end closed the connection", sizeof(m_aErrorString));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CNetworkClient::Recv(char *pLine, int MaxLength)
|
||||
{
|
||||
if(State() == NET_CONNSTATE_ONLINE)
|
||||
{
|
||||
if(m_BufferOffset)
|
||||
{
|
||||
// find message start
|
||||
int StartOffset = 0;
|
||||
while(m_aBuffer[StartOffset] == '\r' || m_aBuffer[StartOffset] == '\n')
|
||||
{
|
||||
// detect clients line ending format
|
||||
if(!m_LineEndingDetected)
|
||||
{
|
||||
m_aLineEnding[0] = m_aBuffer[StartOffset];
|
||||
if(StartOffset+1 < m_BufferOffset && (m_aBuffer[StartOffset+1] == '\r' || m_aBuffer[StartOffset+1] == '\n') &&
|
||||
m_aBuffer[StartOffset] != m_aBuffer[StartOffset+1])
|
||||
m_aLineEnding[1] = m_aBuffer[StartOffset+1];
|
||||
m_LineEndingDetected = true;
|
||||
}
|
||||
|
||||
if(++StartOffset >= m_BufferOffset)
|
||||
{
|
||||
m_BufferOffset = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// find message end
|
||||
int EndOffset = StartOffset;
|
||||
while(m_aBuffer[EndOffset] != '\r' && m_aBuffer[EndOffset] != '\n')
|
||||
{
|
||||
if(++EndOffset >= m_BufferOffset)
|
||||
{
|
||||
if(StartOffset > 0)
|
||||
{
|
||||
mem_move(m_aBuffer, m_aBuffer+StartOffset, m_BufferOffset-StartOffset);
|
||||
m_BufferOffset -= StartOffset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// extract message and update buffer
|
||||
if(MaxLength-1 < EndOffset-StartOffset)
|
||||
{
|
||||
if(StartOffset > 0)
|
||||
{
|
||||
mem_move(m_aBuffer, m_aBuffer+StartOffset, m_BufferOffset-StartOffset);
|
||||
m_BufferOffset -= StartOffset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
mem_copy(pLine, m_aBuffer+StartOffset, EndOffset-StartOffset);
|
||||
pLine[EndOffset-StartOffset] = 0;
|
||||
str_sanitize_cc(pLine);
|
||||
mem_move(m_aBuffer, m_aBuffer+EndOffset, m_BufferOffset-EndOffset);
|
||||
m_BufferOffset -= EndOffset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CNetworkClient::Send(const char *pLine)
|
||||
{
|
||||
if(State() != NET_CONNSTATE_ONLINE)
|
||||
return -1;
|
||||
|
||||
char aBuf[1024];
|
||||
str_copy(aBuf, pLine, (int)(sizeof(aBuf))-2);
|
||||
int Length = str_length(aBuf);
|
||||
aBuf[Length] = m_aLineEnding[0];
|
||||
aBuf[Length+1] = m_aLineEnding[1];
|
||||
aBuf[Length+2] = m_aLineEnding[2];
|
||||
Length += 3;
|
||||
const char *pData = aBuf;
|
||||
|
||||
while(1)
|
||||
{
|
||||
int Send = net_tcp_send(m_Socket, pData, Length);
|
||||
if(Send < 0)
|
||||
{
|
||||
m_State = NET_CONNSTATE_ERROR;
|
||||
str_copy(m_aErrorString, "failed to send packet", sizeof(m_aErrorString));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(Send >= Length)
|
||||
break;
|
||||
|
||||
pData += Send;
|
||||
Length -= Send;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
#include <system.h>
|
||||
#include "netban.h"
|
||||
#include "network.h"
|
||||
#include "main.h"
|
||||
#include "server.h"
|
||||
|
||||
int CServer::NewClientCallback(int ClientID, void *pUser)
|
||||
{
|
||||
CServer *pThis = (CServer *)pUser;
|
||||
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(pThis->m_Network.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
||||
if(pThis->Main()->Config()->m_Verbose)
|
||||
dbg_msg("server", "Connection accepted. ncid=%d addr=%s'", ClientID, aAddrStr);
|
||||
|
||||
pThis->m_aClients[ClientID].m_State = CClient::STATE_CONNECTED;
|
||||
pThis->m_aClients[ClientID].m_TimeConnected = time_get();
|
||||
pThis->m_Network.Send(ClientID, "Authentication required:");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
|
||||
{
|
||||
CServer *pThis = (CServer *)pUser;
|
||||
|
||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
||||
net_addr_str(pThis->m_Network.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
|
||||
if(pThis->Main()->Config()->m_Verbose)
|
||||
dbg_msg("server", "Client dropped. ncid=%d addr=%s reason='%s'", ClientID, aAddrStr, pReason);
|
||||
|
||||
if(pThis->m_aClients[ClientID].m_State == CClient::STATE_AUTHED)
|
||||
pThis->Main()->OnDelClient(ClientID);
|
||||
pThis->m_aClients[ClientID].m_State = CClient::STATE_EMPTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CServer::Init(CMain *pMain, const char *Bind, int Port)
|
||||
{
|
||||
m_pMain = pMain;
|
||||
m_NetBan.Init();
|
||||
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
m_aClients[i].m_State = CClient::STATE_EMPTY;
|
||||
|
||||
m_Ready = false;
|
||||
|
||||
if(Port == 0)
|
||||
{
|
||||
dbg_msg("server", "Will not bind to port 0.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
NETADDR BindAddr;
|
||||
if(Bind[0] && net_host_lookup(Bind, &BindAddr, NETTYPE_ALL) == 0)
|
||||
{
|
||||
// got bindaddr
|
||||
BindAddr.type = NETTYPE_ALL;
|
||||
BindAddr.port = Port;
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_zero(&BindAddr, sizeof(BindAddr));
|
||||
BindAddr.type = NETTYPE_ALL;
|
||||
BindAddr.port = Port;
|
||||
}
|
||||
|
||||
if(m_Network.Open(BindAddr, &m_NetBan))
|
||||
{
|
||||
m_Network.SetCallbacks(NewClientCallback, DelClientCallback, this);
|
||||
m_Ready = true;
|
||||
dbg_msg("server", "Bound to %s:%d", Bind, Port);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
dbg_msg("server", "Couldn't open socket. Port (%d) might already be in use.", Port);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CServer::Update()
|
||||
{
|
||||
if(!m_Ready)
|
||||
return;
|
||||
|
||||
m_NetBan.Update();
|
||||
m_Network.Update();
|
||||
|
||||
char aBuf[NET_MAX_PACKETSIZE];
|
||||
int ClientID;
|
||||
|
||||
while(m_Network.Recv(aBuf, (int)(sizeof(aBuf))-1, &ClientID))
|
||||
{
|
||||
dbg_assert(m_aClients[ClientID].m_State != CClient::STATE_EMPTY, "Got message from empty slot.");
|
||||
if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTED)
|
||||
{
|
||||
int ID = -1;
|
||||
char aUsername[128] = {0};
|
||||
char aPassword[128] = {0};
|
||||
const char *pTmp;
|
||||
|
||||
if(!(pTmp = str_find(aBuf, ":"))
|
||||
|| (unsigned)(pTmp - aBuf) > sizeof(aUsername) || (unsigned)(str_length(pTmp) - 1) > sizeof(aPassword))
|
||||
{
|
||||
m_Network.NetBan()->BanAddr(m_Network.ClientAddr(ClientID), 60, "You're an idiot, go away.");
|
||||
m_Network.Drop(ClientID, "Fuck off.");
|
||||
return;
|
||||
}
|
||||
|
||||
str_copy(aUsername, aBuf, pTmp - aBuf + 1);
|
||||
str_copy(aPassword, pTmp + 1, sizeof(aPassword));
|
||||
if(!*aUsername || !*aPassword)
|
||||
{
|
||||
m_Network.NetBan()->BanAddr(m_Network.ClientAddr(ClientID), 60, "You're an idiot, go away.");
|
||||
m_Network.Drop(ClientID, "Username and password must not be blank.");
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(!Main()->Client(i)->m_Active)
|
||||
continue;
|
||||
|
||||
if(str_comp(Main()->Client(i)->m_aUsername, aUsername) == 0 && str_comp(Main()->Client(i)->m_aPassword, aPassword) == 0)
|
||||
ID = i;
|
||||
}
|
||||
|
||||
if(ID == -1)
|
||||
{
|
||||
m_Network.NetBan()->BanAddr(m_Network.ClientAddr(ClientID), 60, "Wrong username and/or password.");
|
||||
m_Network.Drop(ClientID, "Wrong username and/or password.");
|
||||
}
|
||||
else if(Main()->Client(ID)->m_ClientNetID != -1)
|
||||
{
|
||||
m_Network.Drop(ClientID, "Only one connection per user allowed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_aClients[ClientID].m_State = CClient::STATE_AUTHED;
|
||||
m_aClients[ClientID].m_LastReceived = time_get();
|
||||
m_Network.Send(ClientID, "Authentication successful. Access granted.");
|
||||
|
||||
if(m_Network.ClientAddr(ClientID)->type == NETTYPE_IPV4)
|
||||
m_Network.Send(ClientID, "You are connecting via: IPv4");
|
||||
else if(m_Network.ClientAddr(ClientID)->type == NETTYPE_IPV6)
|
||||
m_Network.Send(ClientID, "You are connecting via: IPv6");
|
||||
|
||||
if(Main()->Config()->m_Verbose)
|
||||
dbg_msg("server", "ncid=%d authed", ClientID);
|
||||
Main()->OnNewClient(ClientID, ID);
|
||||
}
|
||||
}
|
||||
else if(m_aClients[ClientID].m_State == CClient::STATE_AUTHED)
|
||||
{
|
||||
m_aClients[ClientID].m_LastReceived = time_get();
|
||||
if(Main()->Config()->m_Verbose)
|
||||
dbg_msg("server", "ncid=%d cmd='%s'", ClientID, aBuf);
|
||||
|
||||
if(str_comp(aBuf, "logout") == 0)
|
||||
m_Network.Drop(ClientID, "Logout. Bye Bye ~");
|
||||
else
|
||||
Main()->HandleMessage(ClientID, aBuf);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; ++i)
|
||||
{
|
||||
if(m_aClients[i].m_State == CClient::STATE_CONNECTED &&
|
||||
time_get() > m_aClients[i].m_TimeConnected + 5 * time_freq())
|
||||
{
|
||||
m_Network.NetBan()->BanAddr(m_Network.ClientAddr(i), 30, "Authentication timeout.");
|
||||
m_Network.Drop(i, "Authentication timeout.");
|
||||
}
|
||||
else if(m_aClients[i].m_State == CClient::STATE_AUTHED &&
|
||||
time_get() > m_aClients[i].m_LastReceived + 15 * time_freq())
|
||||
m_Network.Drop(i, "Timeout.");
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::Send(int ClientID, const char *pLine)
|
||||
{
|
||||
if(!m_Ready)
|
||||
return;
|
||||
|
||||
if(ClientID == -1)
|
||||
{
|
||||
for(int i = 0; i < NET_MAX_CLIENTS; i++)
|
||||
{
|
||||
if(m_aClients[i].m_State == CClient::STATE_AUTHED)
|
||||
m_Network.Send(i, pLine);
|
||||
}
|
||||
}
|
||||
else if(ClientID >= 0 && ClientID < NET_MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_AUTHED)
|
||||
m_Network.Send(ClientID, pLine);
|
||||
}
|
||||
|
||||
void CServer::Shutdown()
|
||||
{
|
||||
if(!m_Ready)
|
||||
return;
|
||||
|
||||
m_Network.Close();
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#ifndef SERVER_H
|
||||
#define SERVER_H
|
||||
|
||||
#include "netban.h"
|
||||
#include "network.h"
|
||||
|
||||
class CServer
|
||||
{
|
||||
class CClient
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
STATE_EMPTY=0,
|
||||
STATE_CONNECTED,
|
||||
STATE_AUTHED,
|
||||
};
|
||||
|
||||
int m_State;
|
||||
int64 m_TimeConnected;
|
||||
int64 m_LastReceived;
|
||||
};
|
||||
CClient m_aClients[NET_MAX_CLIENTS];
|
||||
|
||||
CNetwork m_Network;
|
||||
CNetBan m_NetBan;
|
||||
|
||||
class CMain *m_pMain;
|
||||
|
||||
bool m_Ready;
|
||||
|
||||
static int NewClientCallback(int ClientID, void *pUser);
|
||||
static int DelClientCallback(int ClientID, const char *pReason, void *pUser);
|
||||
|
||||
public:
|
||||
int Init(CMain *pMain, const char *Bind, int Port);
|
||||
void Update();
|
||||
void Send(int ClientID, const char *pLine);
|
||||
void Shutdown();
|
||||
|
||||
CNetwork *Network() { return &m_Network; }
|
||||
CNetBan *NetBan() { return &m_NetBan; }
|
||||
CMain *Main() { return m_pMain; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,204 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CertState struct {
|
||||
Config SSLCertConfig
|
||||
ExpireTS int64
|
||||
Mismatch bool
|
||||
LastError string
|
||||
LastCheck time.Time
|
||||
Checking bool
|
||||
LastAlarm7 time.Time
|
||||
LastAlarm3 time.Time
|
||||
LastAlarm1 time.Time
|
||||
LastAlarmMismatch time.Time
|
||||
}
|
||||
|
||||
func certKey(config SSLCertConfig) string {
|
||||
return fmt.Sprintf("%s\x00%s\x00%d", config.Name, config.Domain, config.Port)
|
||||
}
|
||||
|
||||
func (a *App) reconcileCerts(configs []SSLCertConfig) {
|
||||
a.certMu.Lock()
|
||||
defer a.certMu.Unlock()
|
||||
next := make(map[string]*CertState, len(configs))
|
||||
for _, config := range configs {
|
||||
key := certKey(config)
|
||||
if existing := a.certs[key]; existing != nil {
|
||||
existing.Config = config
|
||||
next[key] = existing
|
||||
} else {
|
||||
next[key] = &CertState{Config: config}
|
||||
}
|
||||
}
|
||||
a.certs = next
|
||||
}
|
||||
|
||||
func (a *App) sslLoop() {
|
||||
a.runDueSSLChecks()
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-a.ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
a.runDueSSLChecks()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) runDueSSLChecks() {
|
||||
now := time.Now()
|
||||
type dueCheck struct {
|
||||
key string
|
||||
config SSLCertConfig
|
||||
}
|
||||
due := make([]dueCheck, 0)
|
||||
a.certMu.Lock()
|
||||
for key, state := range a.certs {
|
||||
interval := secondsDuration(state.Config.Interval)
|
||||
if !state.Checking && (state.LastCheck.IsZero() || now.Sub(state.LastCheck) >= interval) {
|
||||
state.Checking = true
|
||||
due = append(due, dueCheck{key: key, config: state.Config})
|
||||
}
|
||||
}
|
||||
a.certMu.Unlock()
|
||||
for _, check := range due {
|
||||
check := check
|
||||
go a.executeSSLCheck(check.key, check.config)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) executeSSLCheck(key string, config SSLCertConfig) {
|
||||
expireTS, mismatch, err := checkCertificate(config)
|
||||
now := time.Now()
|
||||
type notification struct {
|
||||
message string
|
||||
}
|
||||
alerts := make([]notification, 0, 2)
|
||||
|
||||
a.certMu.Lock()
|
||||
state := a.certs[key]
|
||||
if state == nil {
|
||||
a.certMu.Unlock()
|
||||
return
|
||||
}
|
||||
state.Checking = false
|
||||
state.LastCheck = now
|
||||
if err != nil {
|
||||
state.LastError = err.Error()
|
||||
a.certMu.Unlock()
|
||||
a.wakeStatsWriter()
|
||||
return
|
||||
}
|
||||
state.ExpireTS = expireTS
|
||||
state.Mismatch = mismatch
|
||||
state.LastError = ""
|
||||
if config.Callback != "" && mismatch && (state.LastAlarmMismatch.IsZero() || now.Sub(state.LastAlarmMismatch) >= 24*time.Hour) {
|
||||
state.LastAlarmMismatch = now
|
||||
alerts = append(alerts, notification{message: fmt.Sprintf("【SSL证书域名不匹配】%s(%s) 证书域名与配置不一致", config.Name, config.Domain)})
|
||||
}
|
||||
days := int((expireTS - now.Unix()) / 86400)
|
||||
if config.Callback != "" {
|
||||
var lastAlarm *time.Time
|
||||
switch {
|
||||
case days <= 7 && days > 3:
|
||||
lastAlarm = &state.LastAlarm7
|
||||
case days <= 3 && days > 1:
|
||||
lastAlarm = &state.LastAlarm3
|
||||
case days <= 1:
|
||||
lastAlarm = &state.LastAlarm1
|
||||
}
|
||||
if lastAlarm != nil && (lastAlarm.IsZero() || now.Sub(*lastAlarm) >= 20*time.Hour) {
|
||||
*lastAlarm = now
|
||||
expire := time.Unix(expireTS, 0).UTC().Format("2006-01-02 15:04:05")
|
||||
alerts = append(alerts, notification{message: fmt.Sprintf("【SSL证书提醒】%s(%s) 将在 %d 天后(%s UTC) 到期", config.Name, config.Domain, days, expire)})
|
||||
}
|
||||
}
|
||||
a.certMu.Unlock()
|
||||
a.wakeStatsWriter()
|
||||
|
||||
for _, alert := range alerts {
|
||||
if err := a.sendCallback(config.Callback, alert.message, "ServerStatusSSL"); err != nil {
|
||||
a.logger.Printf("SSL certificate %q callback: %v", config.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkCertificate(config SSLCertConfig) (int64, bool, error) {
|
||||
host, err := certificateHost(config.Domain)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
address := net.JoinHostPort(host, strconv.Itoa(config.Port))
|
||||
dialer := &net.Dialer{Timeout: 6 * time.Second}
|
||||
connection, err := tls.DialWithDialer(dialer, "tcp", address, &tls.Config{
|
||||
ServerName: host,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: true, // VerifyHostname below preserves the legacy chain-independent check.
|
||||
})
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
defer connection.Close()
|
||||
certificates := connection.ConnectionState().PeerCertificates
|
||||
if len(certificates) == 0 {
|
||||
return 0, false, fmt.Errorf("server returned no certificate")
|
||||
}
|
||||
leaf := certificates[0]
|
||||
mismatch := leaf.VerifyHostname(host) != nil
|
||||
return leaf.NotAfter.Unix(), mismatch, nil
|
||||
}
|
||||
|
||||
func certificateHost(raw string) (string, error) {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return "", fmt.Errorf("domain is empty")
|
||||
}
|
||||
if parsed, err := url.Parse(raw); err == nil && parsed.Hostname() != "" {
|
||||
return parsed.Hostname(), nil
|
||||
}
|
||||
withoutPath := strings.SplitN(raw, "/", 2)[0]
|
||||
if host, _, err := net.SplitHostPort(withoutPath); err == nil {
|
||||
return strings.Trim(host, "[]"), nil
|
||||
}
|
||||
host := strings.Trim(withoutPath, "[]")
|
||||
if host == "" {
|
||||
return "", fmt.Errorf("domain is invalid")
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func (a *App) sslSnapshot(configs []SSLCertConfig, now time.Time) []any {
|
||||
a.certMu.RLock()
|
||||
defer a.certMu.RUnlock()
|
||||
result := make([]any, 0, len(configs))
|
||||
for _, config := range configs {
|
||||
entry := map[string]any{
|
||||
"name": config.Name, "domain": config.Domain, "port": config.Port,
|
||||
"expire_ts": int64(0), "expire_days": 0, "mismatch": false,
|
||||
}
|
||||
if state := a.certs[certKey(config)]; state != nil {
|
||||
entry["expire_ts"] = state.ExpireTS
|
||||
if state.ExpireTS != 0 {
|
||||
entry["expire_days"] = int((state.ExpireTS - now.Unix()) / 86400)
|
||||
}
|
||||
entry["mismatch"] = state.Mismatch
|
||||
if state.LastError != "" {
|
||||
entry["error"] = state.LastError
|
||||
}
|
||||
}
|
||||
result = append(result, entry)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCertificateCheckAndSnapshot(t *testing.T) {
|
||||
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(204) }))
|
||||
defer server.Close()
|
||||
parsed, err := url.Parse(server.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
port, _ := strconv.Atoi(parsed.Port())
|
||||
config := SSLCertConfig{Name: "local", Domain: server.URL, Port: port, Interval: 1}
|
||||
expireTS, _, err := checkCertificate(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if expireTS <= time.Now().Unix() {
|
||||
t.Fatalf("unexpected expiration %d", expireTS)
|
||||
}
|
||||
|
||||
doc := minimalTestConfig()
|
||||
doc["sslcerts"] = []any{map[string]any{"name": config.Name, "domain": config.Domain, "port": config.Port, "interval": 1}}
|
||||
app := newTestApp(t, doc)
|
||||
app.runDueSSLChecks()
|
||||
eventually(t, 2*time.Second, func() bool {
|
||||
app.certMu.RLock()
|
||||
defer app.certMu.RUnlock()
|
||||
state := app.certs[certKey(config)]
|
||||
return state != nil && !state.LastCheck.IsZero() && state.ExpireTS > 0
|
||||
})
|
||||
certs := app.SnapshotStats()["sslcerts"].([]any)
|
||||
if certs[0].(map[string]any)["expire_ts"].(int64) <= time.Now().Unix() {
|
||||
t.Fatalf("certificate snapshot: %#v", certs[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallbackDelivery(t *testing.T) {
|
||||
var calls atomic.Int32
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, request *http.Request) {
|
||||
calls.Add(1)
|
||||
if request.Method != http.MethodPost || request.URL.Query().Get("message") == "" {
|
||||
t.Errorf("unexpected callback request: %s %s", request.Method, request.URL.String())
|
||||
}
|
||||
w.WriteHeader(204)
|
||||
}))
|
||||
defer server.Close()
|
||||
doc := minimalTestConfig()
|
||||
doc["watchdog"] = []any{map[string]any{
|
||||
"name": "cpu", "rule": "cpu>90", "interval": 60, "callback": server.URL + "?message=",
|
||||
}}
|
||||
app := newTestApp(t, doc)
|
||||
app.nodeMu.Lock()
|
||||
node := app.nodes["s01"]
|
||||
node.Connected = true
|
||||
node.Stats = AgentStats{CPU: 99}
|
||||
node.HasUpdate = true
|
||||
app.nodeMu.Unlock()
|
||||
app.evaluateWatchdogs("s01", false)
|
||||
eventually(t, time.Second, func() bool { return calls.Load() == 1 })
|
||||
app.evaluateWatchdogs("s01", false)
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
if calls.Load() != 1 {
|
||||
t.Fatalf("watchdog cooldown failed: calls=%d", calls.Load())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AgentServer struct {
|
||||
app *App
|
||||
}
|
||||
|
||||
func NewAgentServer(app *App) *AgentServer {
|
||||
return &AgentServer{app: app}
|
||||
}
|
||||
|
||||
func (s *AgentServer) ListenAndServe() error {
|
||||
listener, err := net.Listen("tcp", s.app.opts.AgentAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.app.logger.Printf("agent TCP listening on %s", listener.Addr())
|
||||
return s.Serve(listener)
|
||||
}
|
||||
|
||||
func (s *AgentServer) Serve(listener net.Listener) error {
|
||||
defer listener.Close()
|
||||
s.app.agentRunning.Store(true)
|
||||
defer s.app.agentRunning.Store(false)
|
||||
go func() {
|
||||
<-s.app.ctx.Done()
|
||||
_ = listener.Close()
|
||||
}()
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
if s.app.ctx.Err() != nil || errors.Is(err, net.ErrClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
go s.handleConnection(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AgentServer) handleConnection(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
if tcpConn, ok := conn.(*net.TCPConn); ok {
|
||||
_ = tcpConn.SetNoDelay(true)
|
||||
_ = tcpConn.SetKeepAlive(true)
|
||||
_ = tcpConn.SetKeepAlivePeriod(10 * time.Second)
|
||||
}
|
||||
_ = conn.SetDeadline(time.Now().Add(5 * time.Second))
|
||||
if _, err := io.WriteString(conn, "Authentication required:\n"); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
reader := bufio.NewReaderSize(conn, 64*1024)
|
||||
credentials, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
credentials = strings.TrimSpace(credentials)
|
||||
parts := strings.SplitN(credentials, ":", 2)
|
||||
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
|
||||
_, _ = io.WriteString(conn, "Wrong username and/or password.\n")
|
||||
return
|
||||
}
|
||||
family := remoteFamily(conn.RemoteAddr())
|
||||
connectionID, monitors, apiErr := s.app.connectAgent(parts[0], parts[1], conn, family)
|
||||
if apiErr != nil {
|
||||
_, _ = io.WriteString(conn, apiErr.Message+"\n")
|
||||
return
|
||||
}
|
||||
username := parts[0]
|
||||
defer s.app.disconnectAgent(username, conn, connectionID)
|
||||
|
||||
if _, err := io.WriteString(conn, "Authentication successful. Access granted.\n"); err != nil {
|
||||
return
|
||||
}
|
||||
// Existing Python agents use recv() instead of a line reader during the
|
||||
// handshake. Keep the auth and metadata packets separate for compatibility.
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
var metadata strings.Builder
|
||||
fmt.Fprintf(&metadata, "You are connecting via: IPv%d\n", family)
|
||||
for index, monitor := range monitors {
|
||||
payload := map[string]any{"name": monitor.Name, "host": monitor.Host, "interval": monitor.Interval, "type": monitor.Type, "monitor": index}
|
||||
data, _ := json.Marshal(payload)
|
||||
metadata.Write(data)
|
||||
metadata.WriteByte('\n')
|
||||
}
|
||||
if _, err := io.WriteString(conn, metadata.String()); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_ = conn.SetDeadline(time.Now().Add(20 * time.Second))
|
||||
scanner := bufio.NewScanner(reader)
|
||||
scanner.Buffer(make([]byte, 4096), maxRequestBody)
|
||||
for scanner.Scan() {
|
||||
_ = conn.SetDeadline(time.Now().Add(20 * time.Second))
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
switch {
|
||||
case strings.HasPrefix(line, "update"):
|
||||
body := strings.TrimSpace(strings.TrimPrefix(line, "update"))
|
||||
var update AgentStats
|
||||
if err := json.Unmarshal([]byte(body), &update); err != nil {
|
||||
if s.app.agentPong(username, connectionID) {
|
||||
_, _ = io.WriteString(conn, "1\n")
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !s.app.updateAgent(username, connectionID, update) {
|
||||
return
|
||||
}
|
||||
if s.app.agentPong(username, connectionID) {
|
||||
_, _ = io.WriteString(conn, "0\n")
|
||||
}
|
||||
case strings.HasPrefix(line, "pong"):
|
||||
value := strings.TrimSpace(strings.TrimPrefix(line, "pong"))
|
||||
s.app.setAgentPong(username, connectionID, value == "1" || strings.EqualFold(value, "on"))
|
||||
default:
|
||||
if s.app.agentPong(username, connectionID) {
|
||||
_, _ = io.WriteString(conn, "1\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func remoteFamily(address net.Addr) int {
|
||||
host, _, err := net.SplitHostPort(address.String())
|
||||
if err == nil {
|
||||
if ip := net.ParseIP(host); ip != nil && ip.To4() == nil {
|
||||
return 6
|
||||
}
|
||||
}
|
||||
return 4
|
||||
}
|
||||
|
||||
func (a *App) connectAgent(username, password string, conn net.Conn, family int) (uint64, []MonitorConfig, *APIError) {
|
||||
a.configMu.RLock()
|
||||
defer a.configMu.RUnlock()
|
||||
var config *ServerConfig
|
||||
for index := range a.runtime.Servers {
|
||||
if a.runtime.Servers[index].Username == username {
|
||||
server := a.runtime.Servers[index]
|
||||
config = &server
|
||||
break
|
||||
}
|
||||
}
|
||||
if config == nil || config.Password != password {
|
||||
return 0, nil, &APIError{Status: 401, Message: "Wrong username and/or password."}
|
||||
}
|
||||
if config.Disabled {
|
||||
return 0, nil, &APIError{Status: 403, Message: "Server is disabled."}
|
||||
}
|
||||
a.nodeMu.Lock()
|
||||
defer a.nodeMu.Unlock()
|
||||
node := a.nodes[username]
|
||||
if node == nil {
|
||||
return 0, nil, &APIError{Status: 404, Message: "Server is not configured."}
|
||||
}
|
||||
if node.Connected {
|
||||
return 0, nil, &APIError{Status: 409, Message: "Only one connection per user allowed."}
|
||||
}
|
||||
id := a.connectionID.Add(1)
|
||||
node.Connected = true
|
||||
node.Connection = conn
|
||||
node.ConnectionID = id
|
||||
node.Family = family
|
||||
node.HasUpdate = false
|
||||
node.Pong = false
|
||||
node.Online4 = family == 4
|
||||
node.Online6 = family == 6
|
||||
a.wakeStatsWriter()
|
||||
return id, append([]MonitorConfig(nil), a.runtime.Monitors...), nil
|
||||
}
|
||||
|
||||
func (a *App) disconnectAgent(username string, conn net.Conn, connectionID uint64) {
|
||||
a.nodeMu.Lock()
|
||||
node := a.nodes[username]
|
||||
if node == nil || node.ConnectionID != connectionID || node.Connection != conn {
|
||||
a.nodeMu.Unlock()
|
||||
return
|
||||
}
|
||||
node.Connected = false
|
||||
node.Connection = nil
|
||||
node.Online4 = false
|
||||
node.Online6 = false
|
||||
node.HasUpdate = false
|
||||
node.Pong = false
|
||||
a.nodeMu.Unlock()
|
||||
a.wakeStatsWriter()
|
||||
time.AfterFunc(25*time.Second, func() {
|
||||
if a.ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
a.nodeMu.RLock()
|
||||
current := a.nodes[username]
|
||||
stillOffline := current != nil && !current.Connected && current.ConnectionID == connectionID
|
||||
a.nodeMu.RUnlock()
|
||||
if stillOffline {
|
||||
a.evaluateWatchdogs(username, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) updateAgent(username string, connectionID uint64, update AgentStats) bool {
|
||||
a.nodeMu.Lock()
|
||||
node := a.nodes[username]
|
||||
if node == nil || !node.Connected || node.ConnectionID != connectionID {
|
||||
a.nodeMu.Unlock()
|
||||
return false
|
||||
}
|
||||
if update.Online4 != nil {
|
||||
node.Online4 = *update.Online4
|
||||
}
|
||||
if update.Online6 != nil {
|
||||
node.Online6 = *update.Online6
|
||||
}
|
||||
node.Stats = update
|
||||
node.HasUpdate = true
|
||||
node.LastUpdate = time.Now()
|
||||
a.nodeMu.Unlock()
|
||||
a.wakeStatsWriter()
|
||||
a.evaluateWatchdogs(username, false)
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *App) setAgentPong(username string, connectionID uint64, enabled bool) {
|
||||
a.nodeMu.Lock()
|
||||
defer a.nodeMu.Unlock()
|
||||
if node := a.nodes[username]; node != nil && node.ConnectionID == connectionID {
|
||||
node.Pong = enabled
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) agentPong(username string, connectionID uint64) bool {
|
||||
a.nodeMu.RLock()
|
||||
defer a.nodeMu.RUnlock()
|
||||
node := a.nodes[username]
|
||||
return node != nil && node.ConnectionID == connectionID && node.Pong
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAgentProtocolAndTrafficState(t *testing.T) {
|
||||
app := newTestApp(t, minimalTestConfig())
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
serveDone := make(chan error, 1)
|
||||
go func() { serveDone <- NewAgentServer(app).Serve(listener) }()
|
||||
|
||||
connection, err := net.DialTimeout("tcp", listener.Addr().String(), time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer connection.Close()
|
||||
reader := bufio.NewReader(connection)
|
||||
readContains(t, reader, "Authentication required")
|
||||
if _, err := fmt.Fprintln(connection, "s01:secret"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
readContains(t, reader, "Authentication successful")
|
||||
readContains(t, reader, "You are connecting via: IPv4")
|
||||
readContains(t, reader, `"monitor":0`)
|
||||
|
||||
if _, err := fmt.Fprintln(connection, "pong on"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
online6 := true
|
||||
update := AgentStats{
|
||||
Uptime: 90061, Load1: 1.25, Load5: 1, Load15: 0.75, CPU: 33.5, CPUCores: 4, CPUModel: "Test CPU",
|
||||
MemoryTotal: 1024, MemoryUsed: 512, SwapTotal: 128, SwapUsed: 2, HDDTotal: 10000, HDDUsed: 4000,
|
||||
NetworkRX: 123, NetworkTX: 456, NetworkIn: 1_000_000, NetworkOut: 2_000_000,
|
||||
Ping10010: 1, Ping189: 2, Ping10086: 3, Time10010: 10, Time189: 20, Time10086: 30,
|
||||
TCPCount: 10, UDPCount: 2, ProcessCount: 30, ThreadCount: 60, IORead: 1, IOWrite: 2,
|
||||
OS: "linux", Custom: "example=12", Online6: &online6,
|
||||
}
|
||||
payload, _ := json.Marshal(update)
|
||||
if _, err := fmt.Fprintf(connection, "update %s\n", payload); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
readContains(t, reader, "0")
|
||||
|
||||
eventually(t, time.Second, func() bool {
|
||||
servers := app.SnapshotStats()["servers"].([]any)
|
||||
server := servers[0].(map[string]any)
|
||||
return server["online4"] == true && server["online6"] == true && server["cpu_model"] == "Test CPU" && server["uptime"] == "1 天"
|
||||
})
|
||||
|
||||
result, apiErr := app.ResetTraffic("s01")
|
||||
if apiErr != nil {
|
||||
t.Fatal(apiErr)
|
||||
}
|
||||
stats := result["stats"].(map[string]any)
|
||||
if stats["last_network_in"] != int64(1_000_000) {
|
||||
t.Fatalf("traffic reset result: %#v", stats)
|
||||
}
|
||||
|
||||
duplicate, err := net.DialTimeout("tcp", listener.Addr().String(), time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
duplicateReader := bufio.NewReader(duplicate)
|
||||
readContains(t, duplicateReader, "Authentication required")
|
||||
_, _ = fmt.Fprintln(duplicate, "s01:secret")
|
||||
readContains(t, duplicateReader, "Only one connection per user")
|
||||
_ = duplicate.Close()
|
||||
|
||||
wrong, err := net.DialTimeout("tcp", listener.Addr().String(), time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wrongReader := bufio.NewReader(wrong)
|
||||
readContains(t, wrongReader, "Authentication required")
|
||||
_, _ = fmt.Fprintln(wrong, "s01:wrong")
|
||||
readContains(t, wrongReader, "Wrong username")
|
||||
_ = wrong.Close()
|
||||
|
||||
if apiErr := app.ReloadConfig(); apiErr != nil {
|
||||
t.Fatal(apiErr)
|
||||
}
|
||||
readContains(t, reader, "Server reloading")
|
||||
eventually(t, time.Second, func() bool {
|
||||
server := app.SnapshotStats()["servers"].([]any)[0].(map[string]any)
|
||||
return server["online4"] == false && server["online6"] == false
|
||||
})
|
||||
|
||||
app.cancel()
|
||||
_ = listener.Close()
|
||||
select {
|
||||
case err := <-serveDone:
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("agent server did not stop")
|
||||
}
|
||||
}
|
||||
|
||||
func readContains(t *testing.T, reader *bufio.Reader, expected string) string {
|
||||
t.Helper()
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("read %q: %v", expected, err)
|
||||
}
|
||||
if !strings.Contains(line, expected) {
|
||||
t.Fatalf("expected %q in %q", expected, line)
|
||||
}
|
||||
return line
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func minimalTestConfig() ConfigDocument {
|
||||
return ConfigDocument{
|
||||
"servers": []any{
|
||||
map[string]any{
|
||||
"username": "s01", "name": "node1", "type": "kvm", "host": "host1",
|
||||
"location": "CN", "password": "secret", "monthstart": 1,
|
||||
},
|
||||
},
|
||||
"monitors": []any{
|
||||
map[string]any{"name": "example", "host": "https://example.com", "interval": 60, "type": "https"},
|
||||
},
|
||||
"sslcerts": []any{},
|
||||
"watchdog": []any{},
|
||||
}
|
||||
}
|
||||
|
||||
func newTestApp(t *testing.T, doc ConfigDocument) *App {
|
||||
t.Helper()
|
||||
directory := t.TempDir()
|
||||
configPath := filepath.Join(directory, "config.json")
|
||||
statsPath := filepath.Join(directory, "data", "stats.json")
|
||||
webDir := filepath.Join(directory, "web")
|
||||
if err := os.MkdirAll(webDir, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(webDir, "index.html"), []byte("<!doctype html><title>test-ui</title>"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := json.MarshalIndent(doc, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(configPath, data, 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
app, err := NewApp(Options{
|
||||
ConfigPath: configPath,
|
||||
StatsPath: statsPath,
|
||||
WebDir: webDir,
|
||||
HTTPAddr: "127.0.0.1:0",
|
||||
AgentAddr: "127.0.0.1:0",
|
||||
AdminToken: "test-token",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(app.Close)
|
||||
return app
|
||||
}
|
||||
|
||||
func performRequest(handler http.Handler, method, path, body, token string) *httptest.ResponseRecorder {
|
||||
request := httptest.NewRequest(method, path, strings.NewReader(body))
|
||||
if body != "" {
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
if token != "" {
|
||||
request.Header.Set("Authorization", "Bearer "+token)
|
||||
}
|
||||
response := httptest.NewRecorder()
|
||||
handler.ServeHTTP(response, request)
|
||||
return response
|
||||
}
|
||||
|
||||
func eventually(t *testing.T, timeout time.Duration, condition func() bool) {
|
||||
t.Helper()
|
||||
deadline := time.Now().Add(timeout)
|
||||
for time.Now().Before(deadline) {
|
||||
if condition() {
|
||||
return
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
t.Fatal("condition was not met before timeout")
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/expr-lang/expr"
|
||||
)
|
||||
|
||||
func compileWatchdog(rule WatchdogConfig, index int) (CompiledWatchdog, error) {
|
||||
normalized := normalizeLegacyExpression(rule.Rule)
|
||||
program, err := expr.Compile(normalized, expr.Env(WatchdogEnvironment{}))
|
||||
if err != nil {
|
||||
return CompiledWatchdog{}, err
|
||||
}
|
||||
return CompiledWatchdog{
|
||||
WatchdogConfig: rule,
|
||||
Key: fmt.Sprintf("%d:%s", index, rule.Name),
|
||||
Normalized: normalized,
|
||||
Program: program,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func normalizeLegacyExpression(input string) string {
|
||||
var output strings.Builder
|
||||
var quote rune
|
||||
runes := []rune(input)
|
||||
for index := 0; index < len(runes); index++ {
|
||||
current := runes[index]
|
||||
if quote != 0 {
|
||||
output.WriteRune(current)
|
||||
if current == quote && (index == 0 || runes[index-1] != '\\') {
|
||||
quote = 0
|
||||
}
|
||||
continue
|
||||
}
|
||||
if current == '\'' || current == '"' {
|
||||
quote = current
|
||||
output.WriteRune(current)
|
||||
continue
|
||||
}
|
||||
switch current {
|
||||
case '&':
|
||||
output.WriteString("&&")
|
||||
if index+1 < len(runes) && runes[index+1] == '&' {
|
||||
index++
|
||||
}
|
||||
case '|':
|
||||
output.WriteString("||")
|
||||
if index+1 < len(runes) && runes[index+1] == '|' {
|
||||
index++
|
||||
}
|
||||
case '=':
|
||||
previousOperator := index > 0 && strings.ContainsRune("!<>=", runes[index-1])
|
||||
nextEqual := index+1 < len(runes) && runes[index+1] == '='
|
||||
if previousOperator || nextEqual {
|
||||
output.WriteRune(current)
|
||||
} else {
|
||||
output.WriteString("==")
|
||||
}
|
||||
default:
|
||||
output.WriteRune(current)
|
||||
}
|
||||
}
|
||||
return output.String()
|
||||
}
|
||||
|
||||
func (a *App) evaluateWatchdogs(username string, offline bool) {
|
||||
runtime := a.RuntimeSnapshot()
|
||||
now := time.Now()
|
||||
type pendingAlert struct {
|
||||
rule WatchdogConfig
|
||||
node ServerConfig
|
||||
}
|
||||
pending := make([]pendingAlert, 0)
|
||||
|
||||
a.nodeMu.Lock()
|
||||
node := a.nodes[username]
|
||||
if node == nil || (!offline && !node.Connected) || (offline && node.Connected) {
|
||||
a.nodeMu.Unlock()
|
||||
return
|
||||
}
|
||||
stats := node.Stats
|
||||
if offline {
|
||||
stats = AgentStats{}
|
||||
}
|
||||
environment := watchdogEnvironment(node.Config, stats, node.Online4, node.Online6, node.LastNetworkIn, node.LastNetworkOut)
|
||||
for _, rule := range runtime.Watchdogs {
|
||||
result, err := expr.Run(rule.Program, environment)
|
||||
if err != nil || !expressionTruthy(result) {
|
||||
continue
|
||||
}
|
||||
if last := node.AlarmLast[rule.Key]; !last.IsZero() && now.Sub(last) < secondsDuration(rule.Interval) {
|
||||
continue
|
||||
}
|
||||
node.AlarmLast[rule.Key] = now
|
||||
if rule.Callback != "" {
|
||||
pending = append(pending, pendingAlert{rule: rule.WatchdogConfig, node: node.Config})
|
||||
}
|
||||
}
|
||||
a.nodeMu.Unlock()
|
||||
|
||||
for _, alert := range pending {
|
||||
alert := alert
|
||||
go func() {
|
||||
message := fmt.Sprintf("【告警名称】 %s \n\n【告警时间】 %s \n\n【用户名】 %s \n\n【节点名】 %s \n\n【虚拟化】 %s \n\n【主机名】 %s \n\n【位 置】 %s",
|
||||
alert.rule.Name, now.Format("2006-01-02 15:04:05"), alert.node.Username, alert.node.Name, alert.node.Type, alert.node.Host, alert.node.Location)
|
||||
if err := a.sendCallback(alert.rule.Callback, message, "ServerStatus"); err != nil {
|
||||
a.logger.Printf("watchdog %q callback: %v", alert.rule.Name, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
type WatchdogEnvironment struct {
|
||||
Username string `expr:"username"`
|
||||
Name string `expr:"name"`
|
||||
NodeType string `expr:"type"`
|
||||
Host string `expr:"host"`
|
||||
Location string `expr:"location"`
|
||||
Load1 float64 `expr:"load_1"`
|
||||
Load5 float64 `expr:"load_5"`
|
||||
Load15 float64 `expr:"load_15"`
|
||||
Ping10010 float64 `expr:"ping_10010"`
|
||||
Ping189 float64 `expr:"ping_189"`
|
||||
Ping10086 float64 `expr:"ping_10086"`
|
||||
Time10010 float64 `expr:"time_10010"`
|
||||
Time189 float64 `expr:"time_189"`
|
||||
Time10086 float64 `expr:"time_10086"`
|
||||
TCPCount float64 `expr:"tcp_count"`
|
||||
UDPCount float64 `expr:"udp_count"`
|
||||
ProcessCount float64 `expr:"process_count"`
|
||||
ThreadCount float64 `expr:"thread_count"`
|
||||
NetworkRX float64 `expr:"network_rx"`
|
||||
NetworkTX float64 `expr:"network_tx"`
|
||||
NetworkIn float64 `expr:"network_in"`
|
||||
NetworkOut float64 `expr:"network_out"`
|
||||
LastNetworkIn float64 `expr:"last_network_in"`
|
||||
LastNetworkOut float64 `expr:"last_network_out"`
|
||||
MemoryTotal float64 `expr:"memory_total"`
|
||||
MemoryUsed float64 `expr:"memory_used"`
|
||||
SwapTotal float64 `expr:"swap_total"`
|
||||
SwapUsed float64 `expr:"swap_used"`
|
||||
HDDTotal float64 `expr:"hdd_total"`
|
||||
HDDUsed float64 `expr:"hdd_used"`
|
||||
IORead float64 `expr:"io_read"`
|
||||
IOWrite float64 `expr:"io_write"`
|
||||
CPU float64 `expr:"cpu"`
|
||||
Online4 float64 `expr:"online4"`
|
||||
Online6 float64 `expr:"online6"`
|
||||
}
|
||||
|
||||
func watchdogEnvironment(config ServerConfig, stats AgentStats, online4, online6 bool, lastNetworkIn, lastNetworkOut int64) WatchdogEnvironment {
|
||||
boolNumber := func(value bool) float64 {
|
||||
if value {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return WatchdogEnvironment{
|
||||
Username: config.Username, Name: config.Name, NodeType: config.Type, Host: config.Host, Location: config.Location,
|
||||
Load1: stats.Load1, Load5: stats.Load5, Load15: stats.Load15,
|
||||
Ping10010: stats.Ping10010, Ping189: stats.Ping189, Ping10086: stats.Ping10086,
|
||||
Time10010: float64(stats.Time10010), Time189: float64(stats.Time189), Time10086: float64(stats.Time10086),
|
||||
TCPCount: float64(stats.TCPCount), UDPCount: float64(stats.UDPCount),
|
||||
ProcessCount: float64(stats.ProcessCount), ThreadCount: float64(stats.ThreadCount),
|
||||
NetworkRX: float64(stats.NetworkRX), NetworkTX: float64(stats.NetworkTX),
|
||||
NetworkIn: float64(stats.NetworkIn), NetworkOut: float64(stats.NetworkOut),
|
||||
LastNetworkIn: float64(lastNetworkIn), LastNetworkOut: float64(lastNetworkOut),
|
||||
MemoryTotal: float64(stats.MemoryTotal), MemoryUsed: float64(stats.MemoryUsed),
|
||||
SwapTotal: float64(stats.SwapTotal), SwapUsed: float64(stats.SwapUsed),
|
||||
HDDTotal: float64(stats.HDDTotal), HDDUsed: float64(stats.HDDUsed),
|
||||
IORead: float64(stats.IORead), IOWrite: float64(stats.IOWrite), CPU: stats.CPU,
|
||||
Online4: boolNumber(online4), Online6: boolNumber(online6),
|
||||
}
|
||||
}
|
||||
|
||||
func expressionTruthy(result any) bool {
|
||||
switch value := result.(type) {
|
||||
case bool:
|
||||
return value
|
||||
case int:
|
||||
return value != 0
|
||||
case int64:
|
||||
return value != 0
|
||||
case float64:
|
||||
return value != 0
|
||||
case string:
|
||||
parsed, _ := strconv.ParseBool(value)
|
||||
return parsed
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) sendCallback(baseURL, message, signature string) error {
|
||||
requestURL := baseURL + url.QueryEscape(message)
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
if a.opts.InsecureCallbackTLS {
|
||||
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec -- explicit compatibility option
|
||||
}
|
||||
client := &http.Client{Timeout: 6 * time.Second, Transport: transport}
|
||||
response, err := client.Post(requestURL, "application/x-www-form-urlencoded", strings.NewReader("signature="+url.QueryEscape(signature)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode < 200 || response.StatusCode >= 300 {
|
||||
return fmt.Errorf("HTTP %s", response.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,9 +1,20 @@
|
||||
[Unit]
|
||||
Description=ServerStatus-Server
|
||||
After=network.target
|
||||
[Service]
|
||||
ExecStart=/usr/local/ServerStatus/server/sergate --config=/usr/local/ServerStatus/server/config.json --web-dir=/usr/local/ServerStatus/web
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
[Unit]
|
||||
Description=ServerStatus Go Server
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/usr/local/ServerStatus/server
|
||||
EnvironmentFile=-/usr/local/ServerStatus/server/config.conf
|
||||
ExecStart=/usr/local/ServerStatus/server/serverstatus --config=/usr/local/ServerStatus/server/config.json --web-dir=/usr/local/ServerStatus/web
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
ReadWritePaths=/usr/local/ServerStatus/server /usr/local/ServerStatus/web/json
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
sh_ver="1.0.0"
|
||||
sh_ver="2.0.0"
|
||||
|
||||
filepath=$(
|
||||
cd "$(dirname "$0")" || exit
|
||||
@@ -49,7 +49,7 @@ check_sys() {
|
||||
}
|
||||
|
||||
check_installed_server_status() {
|
||||
[[ ! -e "${server_file}/sergate" ]] && echo -e "${Error} $NAME 服务端没有安装,请检查 !" && exit 1
|
||||
[[ ! -x "${server_file}/serverstatus" ]] && echo -e "${Error} $NAME Go 服务端没有安装,请检查 !" && exit 1
|
||||
}
|
||||
|
||||
check_installed_client_status() {
|
||||
@@ -58,27 +58,24 @@ check_installed_client_status() {
|
||||
|
||||
Download_Server_Status_server() {
|
||||
cd "/tmp" || exit 1
|
||||
rm -rf "/tmp/ServerStatus-master" "/tmp/master.zip"
|
||||
wget -N --no-check-certificate https://github.com/cppla/ServerStatus/archive/refs/heads/master.zip
|
||||
[[ ! -e "master.zip" ]] && echo -e "${Error} ServerStatus 服务端下载失败 !" && exit 1
|
||||
[[ ! -e "master.zip" ]] && echo -e "${Error} ServerStatus 服务端下载失败 !" && exit 1
|
||||
unzip master.zip
|
||||
rm -rf master.zip
|
||||
[[ ! -d "/tmp/ServerStatus-master" ]] && echo -e "${Error} ServerStatus 服务端解压失败 !" && exit 1
|
||||
cd "/tmp/ServerStatus-master/server" || exit 1
|
||||
make
|
||||
[[ ! -e "sergate" ]] && echo -e "${Error} ServerStatus 服务端编译失败 !" && cd "${file_1}" && rm -rf "/tmp//ServerStatus-master" && exit 1
|
||||
go build -trimpath -ldflags="-s -w -X main.version=${sh_ver}" -o /tmp/serverstatus .
|
||||
[[ ! -x "/tmp/serverstatus" ]] && echo -e "${Error} ServerStatus Go 服务端编译失败,请确认 Go 版本满足 go.mod !" && cd "${file_1}" && rm -rf "/tmp/ServerStatus-master" && exit 1
|
||||
cd "${file_1}" || exit 1
|
||||
mkdir -p "${server_file}"
|
||||
mv "/tmp/ServerStatus-master/server" "${file}"
|
||||
mv "/tmp/ServerStatus-master/web" "${file}"
|
||||
mv "/tmp/ServerStatus-master/plugin" "${file}"
|
||||
mkdir -p "${server_file}" "${web_file}/json" "${plugin_file}"
|
||||
install -m 0755 /tmp/serverstatus "${server_file}/serverstatus"
|
||||
[[ ! -e "${server_conf}" ]] && install -m 0644 "/tmp/ServerStatus-master/server/config.json" "${server_conf}"
|
||||
cp -a "/tmp/ServerStatus-master/web/." "${web_file}/"
|
||||
cp -a "/tmp/ServerStatus-master/plugin/." "${plugin_file}/"
|
||||
rm -f /tmp/serverstatus
|
||||
rm -rf "/tmp/ServerStatus-master"
|
||||
if [[ ! -e "${server_file}/sergate" ]]; then
|
||||
echo -e "${Error} ServerStatus 服务端移动重命名失败 !"
|
||||
[[ -e "${server_file}/sergate1" ]] && mv "${server_file}/sergate1" "${server_file}/sergate"
|
||||
exit 1
|
||||
else
|
||||
[[ -e "${server_file}/sergate1" ]] && rm -rf "${server_file}/sergate1"
|
||||
fi
|
||||
[[ ! -x "${server_file}/serverstatus" ]] && echo -e "${Error} ServerStatus Go 服务端安装失败 !" && exit 1
|
||||
}
|
||||
|
||||
Download_Server_Status_client() {
|
||||
@@ -113,18 +110,27 @@ Installation_dependency() {
|
||||
if [[ ${release} == "centos" ]]; then
|
||||
yum makecache
|
||||
yum -y install unzip
|
||||
yum -y install python3 >/dev/null 2>&1 || yum -y install python
|
||||
[[ ${mode} == "server" ]] && yum -y groupinstall "Development Tools"
|
||||
if [[ ${mode} == "server" ]]; then
|
||||
yum -y install golang
|
||||
else
|
||||
yum -y install python3 >/dev/null 2>&1 || yum -y install python
|
||||
fi
|
||||
elif [[ ${release} == "debian" ]]; then
|
||||
apt -y update
|
||||
apt -y install unzip
|
||||
apt -y install python3 >/dev/null 2>&1 || apt -y install python
|
||||
[[ ${mode} == "server" ]] && apt -y install build-essential
|
||||
if [[ ${mode} == "server" ]]; then
|
||||
apt -y install golang-go
|
||||
else
|
||||
apt -y install python3 >/dev/null 2>&1 || apt -y install python
|
||||
fi
|
||||
elif [[ ${release} == "archlinux" ]]; then
|
||||
pacman -Sy python python-pip unzip --noconfirm
|
||||
[[ ${mode} == "server" ]] && pacman -Sy base-devel --noconfirm
|
||||
if [[ ${mode} == "server" ]]; then
|
||||
pacman -Sy go unzip --noconfirm
|
||||
else
|
||||
pacman -Sy python python-pip unzip --noconfirm
|
||||
fi
|
||||
fi
|
||||
[[ ! -e /usr/bin/python ]] && ln -s /usr/bin/python3 /usr/bin/python
|
||||
[[ ${mode} == "client" && ! -e /usr/bin/python ]] && ln -s /usr/bin/python3 /usr/bin/python
|
||||
}
|
||||
|
||||
Write_server_config() {
|
||||
@@ -147,7 +153,9 @@ EOF
|
||||
|
||||
Write_server_config_conf() {
|
||||
cat >${server_conf_1} <<-EOF
|
||||
PORT = ${server_port_s}
|
||||
AGENT_ADDR=:${server_port_s}
|
||||
HTTP_ADDR=:${server_http_port_s}
|
||||
ADMIN_TOKEN=${admin_token_s}
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -162,10 +170,19 @@ Read_config_client() {
|
||||
Read_config_server() {
|
||||
if [[ ! -e "${server_conf_1}" ]]; then
|
||||
server_port_s="35601"
|
||||
server_http_port_s="8080"
|
||||
admin_token_s=""
|
||||
Write_server_config_conf
|
||||
server_port="35601"
|
||||
server_http_port="8080"
|
||||
else
|
||||
server_port="$(grep "PORT = " ${server_conf_1} | awk '{print $3}')"
|
||||
agent_addr="$(grep '^AGENT_ADDR=' "${server_conf_1}" | head -1 | cut -d= -f2-)"
|
||||
http_addr="$(grep '^HTTP_ADDR=' "${server_conf_1}" | head -1 | cut -d= -f2-)"
|
||||
admin_token_s="$(grep '^ADMIN_TOKEN=' "${server_conf_1}" | head -1 | cut -d= -f2-)"
|
||||
server_port="${agent_addr##*:}"
|
||||
server_http_port="${http_addr##*:}"
|
||||
server_port_s="${server_port:-35601}"
|
||||
server_http_port_s="${server_http_port:-8080}"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -191,8 +208,8 @@ Set_server() {
|
||||
Set_server_http_port() {
|
||||
while true; do
|
||||
echo -e "请输入 $NAME 服务端中网站要设置的 域名/IP的端口[1-65535](如果是域名的话,一般用 80 端口)"
|
||||
read -erp "(默认: 8888):" server_http_port_s
|
||||
[[ -z "$server_http_port_s" ]] && server_http_port_s="8888"
|
||||
read -erp "(默认: 8080):" server_http_port_s
|
||||
[[ -z "$server_http_port_s" ]] && server_http_port_s="8080"
|
||||
if [[ "$server_http_port_s" =~ ^[0-9]*$ ]]; then
|
||||
if [[ ${server_http_port_s} -ge 1 ]] && [[ ${server_http_port_s} -le 65535 ]]; then
|
||||
echo && echo " ================================================"
|
||||
@@ -623,54 +640,16 @@ Install_jq() {
|
||||
fi
|
||||
}
|
||||
|
||||
Install_caddy() {
|
||||
echo
|
||||
echo -e "${Info} 是否由脚本自动配置HTTP服务(服务端的在线监控网站),如果选择 N,则请在其他HTTP服务中配置网站根目录为:${Green_font_prefix}${web_file}${Font_color_suffix} [Y/n]"
|
||||
read -erp "(默认: Y 自动部署):" caddy_yn
|
||||
[[ -z "$caddy_yn" ]] && caddy_yn="y"
|
||||
if [[ "${caddy_yn}" == [Yy] ]]; then
|
||||
caddy_file="/etc/caddy/Caddyfile" # Where is the default Caddyfile specified in Archlinux?
|
||||
[[ ! -e /usr/bin/caddy ]] && {
|
||||
if [[ ${release} == "debian" ]]; then
|
||||
apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
|
||||
curl -1sLf "https://dl.cloudsmith.io/public/caddy/stable/gpg.key" | tee /etc/apt/trusted.gpg.d/caddy-stable.asc
|
||||
curl -1sLf "https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt" | tee /etc/apt/sources.list.d/caddy-stable.list
|
||||
apt update && apt install caddy
|
||||
elif [[ ${release} == "centos" ]]; then
|
||||
yum install yum-plugin-copr -y
|
||||
yum copr enable @caddy/caddy -y
|
||||
yum install caddy -y
|
||||
elif [[ ${release} == "archlinux" ]]; then
|
||||
pacman -Sy caddy --noconfirm
|
||||
fi
|
||||
[[ ! -e "/usr/bin/caddy" ]] && echo -e "${Error} Caddy安装失败,请手动部署,Web网页文件位置:${web_file}" && exit 1
|
||||
systemctl enable caddy
|
||||
echo "" >${caddy_file}
|
||||
}
|
||||
Set_server "server"
|
||||
Set_server_http_port
|
||||
cat >>${caddy_file} <<-EOF
|
||||
http://${server_s}:${server_http_port_s} {
|
||||
root * ${web_file}
|
||||
encode gzip
|
||||
file_server
|
||||
}
|
||||
EOF
|
||||
systemctl restart caddy
|
||||
else
|
||||
echo -e "${Info} 跳过 HTTP服务部署,请手动部署,Web网页文件位置:${web_file} ,如果位置改变,请注意修改服务脚本文件 /etc/init.d/status-server 中的 WEB_BIN 变量 !"
|
||||
fi
|
||||
}
|
||||
|
||||
Install_ServerStatus_server() {
|
||||
[[ -e "${server_file}/sergate" ]] && echo -e "${Error} 检测到 $NAME 服务端已安装 !" && exit 1
|
||||
[[ -x "${server_file}/serverstatus" ]] && echo -e "${Error} 检测到 $NAME 服务端已安装 !" && exit 1
|
||||
Set_server_port
|
||||
Set_server_http_port
|
||||
admin_token_s="$(LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -c 32)"
|
||||
echo -e "${Info} 开始安装/配置 依赖..."
|
||||
Installation_dependency "server"
|
||||
Install_caddy
|
||||
echo -e "${Info} 开始下载/安装..."
|
||||
Download_Server_Status_server
|
||||
Install_jq
|
||||
Install_jq
|
||||
echo -e "${Info} 开始下载/安装 服务脚本..."
|
||||
Service_Server_Status_server
|
||||
echo -e "${Info} 开始写入 配置文件..."
|
||||
@@ -678,6 +657,8 @@ Install_jq
|
||||
Write_server_config_conf
|
||||
echo -e "${Info} 所有步骤 安装完毕,开始启动..."
|
||||
Start_ServerStatus_server
|
||||
echo -e "${Info} WebUI: http://127.0.0.1:${server_http_port_s}/"
|
||||
echo -e "${Info} ADMIN_TOKEN: ${admin_token_s}"
|
||||
}
|
||||
|
||||
Install_ServerStatus_client() {
|
||||
@@ -700,8 +681,9 @@ Install_ServerStatus_client() {
|
||||
|
||||
Update_ServerStatus_server() {
|
||||
check_installed_server_status
|
||||
systemctl stop status-server 2>/dev/null || true
|
||||
Download_Server_Status_server
|
||||
rm -rf /etc/init.d/status-server
|
||||
rm -f "${service}/status-server.service"
|
||||
Service_Server_Status_server
|
||||
Start_ServerStatus_server
|
||||
}
|
||||
@@ -723,12 +705,12 @@ Update_ServerStatus_client() {
|
||||
}
|
||||
|
||||
Start_ServerStatus_server() {
|
||||
port="$(grep "m_Port = " ${server_file}/src/main.cpp | awk '{print $3}' | sed '{s/;$//}')"
|
||||
check_installed_server_status
|
||||
Read_config_server
|
||||
systemctl -q is-active status-server && echo -e "${Error} $NAME 正在运行,请检查 !" && exit 1
|
||||
systemctl start status-server
|
||||
if (systemctl -q is-active status-server) then
|
||||
echo -e "${Info} $NAME 服务端启动成功[监听端口:${port}] !"
|
||||
echo -e "${Info} $NAME Go 服务端启动成功[Agent:${server_port},Web:${server_http_port}] !"
|
||||
else
|
||||
echo -e "${Error} $NAME 服务端启动失败 !"
|
||||
fi
|
||||
@@ -777,13 +759,6 @@ Uninstall_ServerStatus_server() {
|
||||
else
|
||||
rm -rf "${file}"
|
||||
fi
|
||||
if [[ -e "/usr/bin/caddy" ]]; then
|
||||
systemctl stop caddy
|
||||
systemctl disable caddy
|
||||
[[ ${release} == "debian" ]] && apt purge -y caddy
|
||||
[[ ${release} == "centos" ]] && yum -y remove caddy
|
||||
[[ ${release} == "archlinux" ]] && pacman -R caddy --noconfirm
|
||||
fi
|
||||
systemctl daemon-reload
|
||||
systemctl reset-failed
|
||||
echo && echo "ServerStatus 卸载完成 !" && echo
|
||||
@@ -977,7 +952,7 @@ menu_server() {
|
||||
${Green_font_prefix} 9.${Font_color_suffix} 查看 服务端日志
|
||||
————————————
|
||||
${Green_font_prefix}10.${Font_color_suffix} 切换为 客户端菜单" && echo
|
||||
if [[ -e "${server_file}/sergate" ]]; then
|
||||
if [[ -x "${server_file}/serverstatus" ]]; then
|
||||
if (systemctl -q is-active status-server) then
|
||||
echo -e " 当前状态: 服务端 ${Green_font_prefix}已安装${Font_color_suffix} 并 ${Green_font_prefix}已启动${Font_color_suffix}"
|
||||
else
|
||||
|
||||
|
Before Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,406 @@
|
||||
:root{color-scheme:dark;--bg:#0d1117;--bg-alt:#171d27;--surface:#1d2530;--surface-soft:#151b24;--border:#334155;--text:#f1f5f9;--text-dim:#a7b4c8;--accent:#3b82f6;--accent-glow:#7db5ff;--danger:#f05252;--warn:#fbbf24;--ok:#10b981;--radius:10px;--radius-sm:4px;--shadow:0 8px 22px -10px rgba(0,0,0,.75);--font:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,'Noto Sans SC',sans-serif;--trans:.25s cubic-bezier(.4,0,.2,1);--logo-start:#3b82f6;--logo-end:#2563eb;--logo-accent-grad-start:#8bc1ff;--logo-accent-grad-end:#d4e8ff}
|
||||
body.light{color-scheme:light;--bg:#f6f7f9;--bg-alt:#ffffff;--surface:#ffffff;--surface-soft:#f8fafc;--border:#e2e8f0;--text:#1e293b;--text-dim:#64748b;--accent:#2563eb;--accent-glow:#3b82f6;--shadow:0 4px 20px -4px rgba(0,0,0,.08);--logo-start:#2563eb;--logo-end:#1d4ed8;--logo-accent-grad-start:#1d4ed8;--logo-accent-grad-end:#60a5fa}
|
||||
*{box-sizing:border-box}
|
||||
html,body{height:100%;margin:0;padding:0;font-family:var(--font);background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased}
|
||||
html.light{background:var(--bg);color-scheme:light}
|
||||
body,button{font-size:14px;line-height:1.35}
|
||||
a{color:var(--accent);text-decoration:none}
|
||||
a:hover{color:var(--accent-glow)}
|
||||
.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:1rem;padding:.75rem 1.25rem;background:var(--bg-alt);border-bottom:1px solid var(--border)}
|
||||
.brand{font-weight:600;letter-spacing:.5px;font-size:15px}
|
||||
.nav{display:flex;gap:.5rem}
|
||||
.nav button{background:var(--surface-soft);border:1px solid var(--border);color:var(--text-dim);padding:.45rem .9rem;border-radius:var(--radius-sm);cursor:pointer;display:flex;align-items:center;gap:.35rem;transition:var(--trans);font-weight:600}
|
||||
.nav button.active,.nav button:hover{color:#fff;background:var(--accent);border-color:var(--accent);box-shadow:0 0 0 1px var(--accent-glow),0 4px 10px -2px rgba(0,0,0,.5)}
|
||||
.actions{margin-left:auto;display:flex;align-items:center;gap:.75rem}
|
||||
.actions button{background:var(--bg);border:1px solid var(--border);color:var(--text-dim);height:32px;width:38px;border-radius:8px;cursor:pointer;display:grid;place-items:center;transition:var(--trans)}
|
||||
.actions button:hover{color:#fff;border-color:var(--accent);background:var(--accent)}
|
||||
.wrapper{max-width:1680px;margin:1.2rem auto;padding:0 1.2rem;display:flex;flex-direction:column;gap:1.25rem}
|
||||
.notice{padding:.9rem 1rem;border:1px solid var(--border);background:linear-gradient(145deg,var(--bg-alt),var(--bg));border-radius:var(--radius);display:flex;align-items:center;gap:.75rem;font-size:13px}
|
||||
.notice.info:before{content:"";width:8px;height:8px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 20%,transparent)}
|
||||
.panel{display:none;flex-direction:column;gap:.75rem;animation:fade .4s ease}
|
||||
.panel.active{display:flex}
|
||||
.table-wrap{overflow:auto;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg-alt);box-shadow:var(--shadow)}
|
||||
table.data{width:100%;border-collapse:separate;border-spacing:0;min-width:960px}
|
||||
table.data thead th{position:sticky;top:0;background:var(--surface-soft);font-weight:700;text-align:left;font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:var(--text-dim);padding:.7rem .75rem;border-bottom:1px solid var(--border);white-space:nowrap}
|
||||
table.data tbody td{padding:.55rem .75rem;border-bottom:1px solid var(--border);font-size:13px;vertical-align:middle;white-space:nowrap}
|
||||
/* 防止数值变化导致列抖动 */
|
||||
table.data th,table.data td{font-variant-numeric:tabular-nums}
|
||||
/* 月流量胶囊 */
|
||||
.caps-traffic{display:inline-flex;align-items:center;gap:6px;background:linear-gradient(145deg,var(--bg),var(--bg-alt));border:1px solid var(--border);padding:3px 12px 3px 10px;border-radius:999px;font-size:12px;line-height:1;font-weight:500;position:relative;box-shadow:0 2px 4px -2px rgba(0,0,0,.35),0 0 0 1px rgba(255,255,255,.03);}
|
||||
.caps-traffic:before{content:"";position:absolute;inset:0;border-radius:inherit;background:radial-gradient(circle at 20% 20%,rgba(255,255,255,.06),transparent 70%);pointer-events:none;}
|
||||
.caps-traffic.sm{padding:2px 8px 2px 7px;font-size:11px;gap:5px;}
|
||||
/* 双色胶囊 */
|
||||
.caps-traffic.duo{background:none;border:0;gap:0;padding:0;box-shadow:none;position:relative;border-radius:999px;overflow:hidden;font-size:12px;}
|
||||
/* 宽度按内容自适应,每半边仅为其文本 + padding */
|
||||
.caps-traffic.duo .half{flex:0 0 auto;display:flex;align-items:center;justify-content:center;padding:2px 4px;font-variant-numeric:tabular-nums;font-weight:600;line-height:1.25; /* 与 .pill 保持一致高度 */ letter-spacing:.25px;color:#fff;font-size:12px;white-space:nowrap;}
|
||||
.caps-traffic.duo.normal .half.in{background:#d1fae5;color:#065f46;} /* emerald-100 / text-emerald-800 */
|
||||
.caps-traffic.duo.normal .half.out{background:#bfdbfe;color:#1e3a8a;} /* blue-200 / text-blue-900 */
|
||||
.caps-traffic.duo.heavy .half.in{background:#fde68a;color:#78350f;}
|
||||
.caps-traffic.duo.heavy .half.out{background:#fbbf24;color:#111827;}
|
||||
|
||||
/* 半之间分隔线 */
|
||||
.caps-traffic.duo .half + .half{border-left:1px solid rgba(0,0,0,.18);}
|
||||
body.light .caps-traffic.duo .half + .half{border-left:1px solid rgba(0,0,0,.08);}
|
||||
.caps-traffic.duo.sm .half{padding:1px 4px;font-size:10px;min-width:0;}
|
||||
table.data tbody tr:last-child td{border-bottom:none}
|
||||
table.data tbody tr:hover{background:rgba(59,130,246,.045)}
|
||||
.badge{display:inline-block;padding:2px 6px;font-size:11px;border-radius:12px;font-weight:500;line-height:1.2;background:var(--bg);border:1px solid var(--border);color:var(--text-dim)}
|
||||
.badge.ok{background:rgba(16,185,129,.15);color:var(--ok);border-color:rgba(16,185,129,.3)}
|
||||
.badge.warn{background:rgba(245,158,11,.15);color:var(--warn);border-color:rgba(245,158,11,.4)}
|
||||
.badge.err{background:rgba(239,68,68,.15);color:var(--danger);border-color:rgba(239,68,68,.4)}
|
||||
.footer{margin:2rem 0 2.5rem;display:flex;align-items:center;justify-content:center;gap:.5rem;font-size:12px;color:var(--text-dim)}
|
||||
.footer a{color:var(--text-dim)}
|
||||
.footer a:hover{color:var(--accent)}
|
||||
.muted{color:var(--text-dim)}
|
||||
/* 旧状态文字样式已不再使用(采用 pill) */
|
||||
@media (max-width:1100px){.nav{flex-wrap:wrap}.table-wrap{border-radius:8px}}
|
||||
@keyframes fade{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
|
||||
|
||||
/* modal styles */
|
||||
.modal-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.55);display:flex;align-items:flex-start;justify-content:center;padding:5vh 1rem;z-index:50;backdrop-filter:blur(4px)}
|
||||
.modal-box{position:relative;width:100%;max-width:560px;background:var(--bg-alt);border:1px solid var(--border);border-radius:16px;box-shadow:0 8px 30px -6px rgba(0,0,0,.6);padding:1.25rem 1.35rem;display:flex;flex-direction:column;gap:.9rem;animation:fade .25s ease}
|
||||
.modal-title{margin:0;font-size:16px;font-weight:600;letter-spacing:.5px}
|
||||
.modal-close{position:absolute;top:10px;right:12px;background:transparent;border:0;color:var(--text-dim);font-size:20px;line-height:1;cursor:pointer;padding:4px;border-radius:8px;transition:var(--trans)}
|
||||
.modal-close:hover{color:var(--text);background:var(--bg)}
|
||||
.modal-content{font-size:13px;line-height:1.5;display:grid;gap:.6rem}
|
||||
.kv{display:flex;justify-content:space-between;gap:1rem;padding:.5rem .75rem;background:linear-gradient(145deg,var(--bg),var(--bg-alt));border:1px solid var(--border);border-radius:10px}
|
||||
.kv span{white-space:nowrap}
|
||||
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}
|
||||
|
||||
/* 半圆仪表盘 */
|
||||
.gauge-half{--p:0;width:60px;height:34px;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;font-family:ui-monospace,monospace;font-size:10px;font-weight:600;gap:0;color:var(--text);}
|
||||
.gauge-half svg{width:100%;height:28px;overflow:visible;}
|
||||
.gauge-half path{fill:none;stroke-linecap:round;}
|
||||
/* 基础颜色 (暗色/亮色自动过渡) */
|
||||
.gauge-half path.track{stroke:color-mix(in srgb,var(--text-dim) 18%,transparent);stroke-width:6;}
|
||||
.gauge-half path.arc{stroke:var(--gauge-base,#3b82f6);stroke-width:8;stroke-dasharray:126;stroke-dashoffset:calc(126*(1 - var(--p)));transition:stroke-dashoffset .8s cubic-bezier(.4,0,.2,1),stroke .35s;filter:drop-shadow(0 1px 2px rgba(0,0,0,.45));}
|
||||
.gauge-half[data-type=mem] path.arc{--gauge-base:#10b981}
|
||||
.gauge-half[data-type=hdd] path.arc{--gauge-base:#06b6d4}
|
||||
/* 阈值颜色:CPU>=75%、内存>=80%、硬盘>=85% 警告黄,>=90% 危险红 */
|
||||
.gauge-half[data-warn] path.arc{stroke:var(--warn)}
|
||||
.gauge-half[data-bad] path.arc{stroke:var(--danger)}
|
||||
.gauge-half span{line-height:1;position:relative;top:-6px;font-size:12px;}
|
||||
/* 亮色模式细化对比度 */
|
||||
body.light .gauge-half path.track{stroke:color-mix(in srgb,var(--text-dim) 28%,transparent)}
|
||||
body.light .gauge-half path.arc{filter:none}
|
||||
|
||||
/* status pill */
|
||||
.pill{display:inline-block;padding:2px 8px;font-size:12px;font-weight:600;border-radius:999px;letter-spacing:.45px;min-width:48px;text-align:center;line-height:1.25;border:0;box-shadow:0 2px 4px -1px rgba(0,0,0,.4),0 0 0 1px rgba(255,255,255,.04);transition:var(--trans);color:#fff}
|
||||
.pill.on{background:var(--ok)}
|
||||
.pill.off{background:var(--danger)}
|
||||
.pill.on:hover{filter:brightness(1.1)}
|
||||
.pill.off:hover{filter:brightness(1.1)}
|
||||
.proto-signal{display:inline-grid;grid-template-columns:1fr 1fr;width:18px;height:18px;border-radius:50%;overflow:hidden;vertical-align:middle;border:1px solid color-mix(in srgb,var(--border) 80%,transparent);box-shadow:0 2px 5px -2px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.04)}
|
||||
.proto-signal i{display:block;min-width:0;background:color-mix(in srgb,var(--text-dim) 42%,var(--bg-alt));}
|
||||
.proto-signal[data-v4="1"] .v4,.proto-signal[data-v6="1"] .v6{background:#22c55e}
|
||||
.proto-signal[data-state="ipv4"] .v4{background:#22c55e}
|
||||
.proto-signal[data-state="ipv6"] .v6{background:#22c55e}
|
||||
.proto-signal[data-state="offline"] .v4,.proto-signal[data-state="offline"] .v6{background:var(--danger)}
|
||||
body.light .proto-signal{border-color:color-mix(in srgb,var(--border) 92%,#94a3b8);box-shadow:0 1px 3px rgba(15,23,42,.12)}
|
||||
body.light .proto-signal i{background:#cbd5e1}
|
||||
.virt-pill{--virt:var(--accent);display:inline-flex;align-items:center;justify-content:center;min-width:50px;padding:2px 9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--virt) 42%,var(--border));background:color-mix(in srgb,var(--virt) 14%,var(--bg-alt));color:color-mix(in srgb,var(--virt) 72%,#fff);font-size:12px;font-weight:650;line-height:1.2;letter-spacing:.25px;white-space:nowrap}
|
||||
body.light .virt-pill{background:color-mix(in srgb,var(--virt) 12%,#fff);color:color-mix(in srgb,var(--virt) 68%,#111827)}
|
||||
.node-name{display:inline-block;max-width:160px;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;font-weight:750;letter-spacing:.15px;color:var(--text)}
|
||||
.row-server[data-online="0"] .node-name{color:color-mix(in srgb,var(--text) 72%,var(--text-dim));font-weight:650}
|
||||
.row-server:hover .node-name{color:var(--accent)}
|
||||
.load-with-cores{display:inline-flex;align-items:flex-start;gap:.28rem;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-weight:700;line-height:1;white-space:nowrap}
|
||||
.load-value{display:inline-block;min-width:2.55rem}
|
||||
.load-core-bubble{display:inline-flex;align-items:center;justify-content:center;height:14px;min-width:24px;padding:0 5px;margin-top:-6px;border-radius:999px;border:1px solid color-mix(in srgb,var(--accent) 34%,var(--border));background:color-mix(in srgb,var(--accent) 13%,var(--bg-alt));color:color-mix(in srgb,var(--accent) 74%,#fff);font-size:9px;font-weight:800;line-height:1;letter-spacing:0;box-shadow:0 1px 3px rgba(0,0,0,.22)}
|
||||
body.light .load-core-bubble{background:color-mix(in srgb,var(--accent) 8%,#fff);color:color-mix(in srgb,var(--accent) 78%,#111827);box-shadow:0 1px 2px rgba(15,23,42,.08)}
|
||||
|
||||
/* buckets CU/CT/CM (simple version) */
|
||||
.buckets{display:flex;align-items:flex-end;gap:8px;min-width:140px}
|
||||
.bucket{position:relative;width:26px;height:34px;background:linear-gradient(145deg,var(--bg),var(--bg-alt));border:1px solid var(--border);border-radius:8px;padding:4px 4px 16px;box-sizing:border-box;display:flex;justify-content:flex-end}
|
||||
.bucket span{display:block;width:100%;background:var(--accent);border-radius:4px 4px 6px 6px;height:var(--h);align-self:flex-end;transition:height .8s cubic-bezier(.4,0,.2,1),background .3s}
|
||||
.bucket[data-lv=warn] span{background:var(--warn)}
|
||||
.bucket[data-lv=bad] span{background:var(--danger)}
|
||||
.bucket label{position:absolute;left:0;right:0;bottom:2px;font-size:10px;text-align:center;color:var(--text-dim);pointer-events:none}
|
||||
.bucket:hover label{color:var(--text)}
|
||||
|
||||
/* 调整“总流量”表头(第9列)padding 使标题文字居中,不受正文额外右 padding 影响 */
|
||||
#serversTable thead th:nth-child(9){padding-left:.75rem;padding-right:.75rem;}
|
||||
.buckets{justify-content:center}
|
||||
|
||||
/* 响应式隐藏非关键列,保持可读性 */
|
||||
@media (max-width:1100px){
|
||||
#serversTable{min-width:100%;}
|
||||
#serversTable thead th:nth-child(3),
|
||||
#serversTable tbody td:nth-child(3), /* 节点 */
|
||||
#serversTable thead th:nth-child(4),
|
||||
#serversTable tbody td:nth-child(4), /* 虚拟化 */
|
||||
#serversTable thead th:nth-child(8),
|
||||
#serversTable tbody td:nth-child(8) /* 当前网络 */ {display:none}
|
||||
}
|
||||
@media (max-width:820px){
|
||||
#serversTable thead th:nth-child(5),
|
||||
#serversTable tbody td:nth-child(5), /* 在线 */
|
||||
#serversTable thead th:nth-child(6),
|
||||
#serversTable tbody td:nth-child(6) /* 负载 */ {display:none}
|
||||
.buckets{gap:6px;min-width:100px}
|
||||
}
|
||||
@media (max-width:640px){
|
||||
#serversTable thead th:nth-child(4),
|
||||
#serversTable tbody td:nth-child(4) /* 位置 */ {display:none}
|
||||
.topbar{flex-wrap:wrap;padding:.6rem .8rem}
|
||||
.actions{width:100%;justify-content:flex-end;margin-top:.4rem}
|
||||
.wrapper{padding:0 .7rem}
|
||||
#panel-servers .table-wrap{display:none;}
|
||||
#serversCards{display:grid!important;grid-template-columns:1fr;gap:.75rem;margin-top:.5rem;}
|
||||
/* 服务与证书移动端卡片 */
|
||||
#panel-monitors .table-wrap, #panel-ssl .table-wrap{display:none;}
|
||||
#monitorsCards,#sslCards{display:grid!important;grid-template-columns:1fr;gap:.75rem;margin-top:.5rem;}
|
||||
.modal-box{max-width:100%;border-radius:14px;padding:1rem .95rem;}
|
||||
.modal-content{max-height:65vh;overflow:auto;}
|
||||
}
|
||||
|
||||
/* 三个数据表使用自动宽度,按关键列单独约束 */
|
||||
#serversTable,#monitorsTable,#sslTable{min-width:0;}
|
||||
#serversTable thead th,#serversTable tbody td,
|
||||
#monitorsTable thead th,#monitorsTable tbody td,
|
||||
#sslTable thead th,#sslTable tbody td{
|
||||
width:auto!important;min-width:0!important;max-width:none!important;
|
||||
padding:.55rem .7rem;
|
||||
}
|
||||
#sslTable th:nth-child(2),#sslTable td:nth-child(2){max-width:none;white-space:normal;overflow-wrap:anywhere;}
|
||||
#serversTable thead th:nth-child(13),#serversTable tbody td:nth-child(13){width:112px!important;min-width:112px!important;max-width:112px!important;padding-left:0!important;padding-right:0!important;text-align:center;}
|
||||
|
||||
#serversTable thead th:nth-child(8),#serversTable tbody td:nth-child(8),
|
||||
#serversTable thead th:nth-child(9),#serversTable tbody td:nth-child(9){
|
||||
min-width:20ch !important; /* 保留自动宽度,但不小于此值 */
|
||||
text-align:center;
|
||||
font-variant-numeric:tabular-nums;
|
||||
}
|
||||
#serversTable thead th:nth-child(2),#serversTable tbody td:nth-child(2){
|
||||
width:134px!important;min-width:134px!important;max-width:134px!important;text-align:center;padding-left:.35rem!important;padding-right:.35rem!important;font-variant-numeric:tabular-nums;
|
||||
}
|
||||
#serversTable thead th:nth-child(1),#serversTable tbody td:nth-child(1){
|
||||
width:46px!important;min-width:46px!important;max-width:46px!important;text-align:center;padding-left:0!important;padding-right:0!important;
|
||||
}
|
||||
#serversTable thead th:nth-child(3),#serversTable tbody td:nth-child(3){
|
||||
text-align:left;padding-left:18px!important;
|
||||
}
|
||||
#serversTable tbody td:nth-child(13) .buckets{
|
||||
min-width:112px;
|
||||
gap:6px;
|
||||
margin:0 auto;
|
||||
justify-content:center;
|
||||
}
|
||||
.cards .card{border:1px solid var(--border);border-radius:12px;padding:.75rem .85rem;background:linear-gradient(145deg,var(--bg),var(--bg-alt));display:flex;flex-direction:column;gap:.45rem;position:relative;}
|
||||
.cards .card.offline{filter:saturate(.92);}
|
||||
.cards .card.alert-critical{border-color:rgba(239,68,68,.6);background:linear-gradient(180deg, rgba(239,68,68,.22), rgba(239,68,68,.12)), var(--bg-alt);box-shadow:0 0 0 1px rgba(239,68,68,.48),0 6px 18px -6px rgba(239,68,68,.28);}
|
||||
.cards .card.alert-warning{border-color:rgba(245,158,11,.55);background:linear-gradient(180deg, rgba(245,158,11,.16), rgba(245,158,11,.08)), var(--bg-alt);box-shadow:0 0 0 1px rgba(245,158,11,.32),0 6px 18px -8px rgba(245,158,11,.22);}
|
||||
table.data tbody tr.alert-critical{background:rgba(239,68,68,.18) !important;}
|
||||
table.data tbody tr.alert-critical:hover{background:rgba(239,68,68,.21) !important;}
|
||||
table.data tbody tr.alert-warning{background:rgba(245,158,11,.12) !important;}
|
||||
table.data tbody tr.alert-warning:hover{background:rgba(245,158,11,.14) !important;}
|
||||
|
||||
/* SSL 域名告警底色:与高负载相同 */
|
||||
#sslTable td.alert-domain{background:rgba(239,68,68,.18) !important;}
|
||||
#sslTable tr:hover td.alert-domain{background:rgba(239,68,68,.26) !important;}
|
||||
|
||||
/* OS 着色(更明显):
|
||||
1) 为各 OS 类定义 --os-color 变量
|
||||
2) 行左侧使用 inset box-shadow 画 4px 彩条
|
||||
3) 行背景叠加轻度渐变以提示 OS
|
||||
*/
|
||||
table.data tbody tr[class*="os-"]{box-shadow:inset 4px 0 0 0 var(--os-color, transparent);background:linear-gradient(180deg, color-mix(in srgb, var(--os-color, transparent) 10%, transparent), transparent 60%);}
|
||||
table.data tbody tr[class*="os-"]:hover{background:linear-gradient(180deg, color-mix(in srgb, var(--os-color, transparent) 12%, transparent), transparent 65%);}
|
||||
.cards .card[class*="os-"]{border-color:color-mix(in srgb, var(--os-color, var(--accent)) 60%, transparent);box-shadow:0 0 0 1px color-mix(in srgb, var(--os-color, var(--accent)) 40%, transparent),0 4px 16px -6px color-mix(in srgb, var(--os-color, #000) 35%, transparent);}
|
||||
/* 弹窗 OS 着色:左侧彩条 + 渐变与卡片一致 */
|
||||
/* 取消弹窗背景着色,改为仅在标题展示系统胶囊 */
|
||||
.os-chip{display:inline-flex;align-items:center;padding:2px 8px;margin-left:.5rem;border-radius:999px;font-size:12px;font-weight:600;line-height:1.2;background:var(--os-color, var(--border));color:#fff;border:0;white-space:nowrap;}
|
||||
.spec-chip{display:inline-flex;align-items:center;padding:2px 8px;margin-left:.4rem;border-radius:999px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;font-weight:750;line-height:1.2;background:color-mix(in srgb,var(--accent) 16%,var(--bg-alt));color:color-mix(in srgb,var(--accent) 72%,#fff);border:1px solid color-mix(in srgb,var(--accent) 38%,var(--border));white-space:nowrap;}
|
||||
body.light .spec-chip{background:color-mix(in srgb,var(--accent) 10%,#fff);color:color-mix(in srgb,var(--accent) 78%,#111827)}
|
||||
.cpu-model-chip{display:inline-block;max-width:min(240px,58vw);overflow:hidden;text-overflow:ellipsis;vertical-align:middle;padding:2px 8px;margin-left:.4rem;border-radius:999px;border:1px solid color-mix(in srgb,var(--text-dim) 34%,var(--border));background:color-mix(in srgb,var(--text-dim) 12%,var(--bg-alt));color:color-mix(in srgb,var(--text) 84%,var(--text-dim));font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;font-weight:700;line-height:1.2;white-space:nowrap;}
|
||||
body.light .cpu-model-chip{background:color-mix(in srgb,var(--text-dim) 9%,#fff);color:color-mix(in srgb,var(--text) 82%,#111827)}
|
||||
|
||||
/* 为常见系统赋色 */
|
||||
.os-linux{--os-color: rgba(16,185,129,.85);} /* 绿色 (通用 Linux,保持不变) */
|
||||
.os-ubuntu{--os-color: rgba(221,72,20,.9);} /* Ubuntu 橙 (#dd4814) */
|
||||
.os-debian{--os-color: rgba(215,10,83,.9);} /* Debian 品红 (#d70a53) */
|
||||
.os-centos{--os-color: rgba(102,0,153,.9);} /* CentOS 紫 (#660099) */
|
||||
.os-rocky{--os-color: rgba(1,122,66,.9);} /* Rocky Linux 绿 (#017a42) */
|
||||
.os-almalinux{--os-color: rgba(0,92,170,.9);} /* AlmaLinux 蓝 (#005caa) */
|
||||
.os-rhel{--os-color: rgba(204,0,0,.9);} /* Red Hat 红 (#cc0000) */
|
||||
.os-arch{--os-color: rgba(23,147,209,.9);} /* Arch Linux 蓝 (#1793d1) */
|
||||
.os-alpine{--os-color: rgba(14,87,123,.9);} /* Alpine Linux 蓝 (#0e577b) */
|
||||
.os-fedora{--os-color: rgba(60,110,180,.9);} /* Fedora 蓝 (#3c6eb4) */
|
||||
.os-amazon{--os-color: rgba(255,153,0,.9);} /* Amazon Linux 橙 (#ff9900) */
|
||||
.os-suse{--os-color: rgba(0,150,0,.9);} /* openSUSE 绿 (#009600) */
|
||||
.os-freebsd{--os-color: rgba(166,31,47,.9);} /* FreeBSD 红 (#a61f2f) */
|
||||
.os-openbsd{--os-color: rgba(255,204,0,.9);} /* OpenBSD 黄 (#ffcc00) */
|
||||
.os-bsd{--os-color: rgba(166,31,47,.9);} /* BSD 系统一般跟 FreeBSD 接近 */
|
||||
.os-darwin{--os-color: rgba(29,29,31,.95);} /* macOS 深空灰 (#1d1d1f) */
|
||||
.os-windows{--os-color: rgba(0,120,215,.95);} /* Windows 蓝 (#0078d7) */
|
||||
|
||||
|
||||
|
||||
/* 旧进度条相关样式已清理 */
|
||||
.cards .card-header{display:flex;align-items:center;justify-content:space-between;gap:.5rem;}
|
||||
.cards .card-title{display:flex;align-items:center;flex-wrap:wrap;gap:.24rem .34rem;min-width:0;font-weight:600;font-size:.95rem;}
|
||||
.cards .card-spec-chip{display:inline-flex;align-items:center;justify-content:center;height:16px;padding:0 6px;border-radius:999px;border:1px solid color-mix(in srgb,var(--accent) 34%,var(--border));background:color-mix(in srgb,var(--accent) 13%,var(--bg-alt));color:color-mix(in srgb,var(--accent) 74%,#fff);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10px;font-weight:800;line-height:1;letter-spacing:0;white-space:nowrap}
|
||||
body.light .cards .card-spec-chip{background:color-mix(in srgb,var(--accent) 8%,#fff);color:color-mix(in srgb,var(--accent) 78%,#111827)}
|
||||
.cards .tag{font-size:.65rem;padding:.15rem .4rem;border-radius:4px;background:var(--surface);color:var(--text);letter-spacing:.5px;}
|
||||
.cards .status-pill{font-size:.6rem;padding:.2rem .45rem;border-radius:999px;font-weight:500;}
|
||||
.cards .status-pill.on{background:var(--ok);color:#fff;}
|
||||
.cards .status-pill.off{background:var(--danger);color:#fff;}
|
||||
.cards .kvlist{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.35rem .75rem;font-size:.7rem;line-height:1.25;}
|
||||
.cards .kvlist div{display:flex;flex-direction:column;}
|
||||
.cards .kvlist span.key{opacity:.6;}
|
||||
.cards .buckets{margin-top:.25rem;}
|
||||
/* 证书卡片:域名告警底色(与高负载卡片风格一致) */
|
||||
.cards .kvlist .alert-domain{background:rgba(239,68,68,.18);border:1px solid rgba(239,68,68,.35);border-radius:8px;padding:.4rem .5rem;}
|
||||
.cards .kvlist .alert-domain .key{opacity:.85}
|
||||
/* 移除移动端卡片展开箭头与展开区域(已按需简化交互) */
|
||||
/* 旧移动端 latency spark 样式移除 */
|
||||
|
||||
/* 简易信号格,用于服务连通性延迟展示 */
|
||||
.sig{display:inline-flex;gap:2px;vertical-align:baseline;margin:0 4px 0 6px;align-items:flex-end;line-height:1}
|
||||
.sig .b{width:3px;background:color-mix(in srgb,var(--text-dim) 35%,transparent);border-radius:2px;display:inline-block}
|
||||
.sig .b:nth-child(1){height:7px}
|
||||
.sig .b:nth-child(2){height:9px}
|
||||
.sig .b:nth-child(3){height:11px}
|
||||
.sig .b:nth-child(4){height:13px}
|
||||
.sig .b:nth-child(5){height:15px}
|
||||
.sig .b.on{background:var(--ok)}
|
||||
.sig .b.off{opacity:.35}
|
||||
|
||||
/* 服务监测项:不同组竖排,同一组横排;不考虑自动换行 */
|
||||
.mon-items{display:flex;flex-direction:column;gap:6px;align-items:flex-start}
|
||||
.mon-item{display:inline-flex;align-items:center;white-space:nowrap;line-height:1}
|
||||
.mon-item .name{margin-right:6px}
|
||||
.mon-item .ms{margin-left:6px;font-variant-numeric:tabular-nums}
|
||||
.mon-item .sig{margin:0 6px;transform:translateY(-1px)}
|
||||
|
||||
/* 新 Logo 样式 */
|
||||
.brand{display:flex;align-items:center;gap:.55rem;font-weight:600;letter-spacing:.5px;font-size:16px;position:relative}
|
||||
.brand .logo-mark{display:inline-flex;width:34px;height:34px;border-radius:10px;background:linear-gradient(145deg,var(--logo-start) 0%,var(--logo-end) 90%);color:#fff;align-items:center;justify-content:center;box-shadow:0 4px 12px -2px rgba(0,0,0,.45),0 0 0 1px rgba(255,255,255,.08);transition:var(--trans)}
|
||||
.brand .logo-mark svg{display:block}
|
||||
.brand .logo-text{font-size:17px;font-weight:700;line-height:1;display:flex;align-items:baseline;gap:2px;letter-spacing:1px}
|
||||
.brand .logo-text .logo-accent{background:linear-gradient(90deg,var(--logo-accent-grad-start),var(--logo-accent-grad-end));-webkit-background-clip:text;background-clip:text;color:transparent;filter:drop-shadow(0 2px 4px rgba(0,0,0,.3))}
|
||||
.brand:hover .logo-mark{transform:translateY(-2px) scale(1.05)}
|
||||
.brand:hover .logo-text{color:var(--text)}
|
||||
@media (max-width:640px){.brand .logo-text{font-size:15px}.brand .logo-mark{width:30px;height:30px}}
|
||||
|
||||
/* 运维控制台增强 */
|
||||
.ops-overview{display:grid;grid-template-columns:repeat(5,minmax(140px,1fr));gap:.75rem}
|
||||
.overview-card{border:1px solid var(--border);background:linear-gradient(180deg,var(--surface-soft),var(--bg-alt));border-radius:8px;padding:.8rem .9rem;display:flex;flex-direction:column;gap:.25rem;min-height:82px}
|
||||
.overview-card .label{font-size:12px;color:var(--text-dim)}
|
||||
.overview-card .value{font-size:24px;line-height:1;font-weight:700;font-variant-numeric:tabular-nums}
|
||||
.overview-card .hint{font-size:12px;color:var(--text-dim);line-height:1.3}
|
||||
.overview-card.ok{border-color:rgba(16,185,129,.35)}
|
||||
.overview-card.warn{border-color:rgba(245,158,11,.45)}
|
||||
.overview-card.err{border-color:rgba(239,68,68,.5)}
|
||||
.overview-card.traffic-down{border-color:rgba(16,185,129,.38)}
|
||||
.overview-card.traffic-up{border-color:rgba(59,130,246,.38)}
|
||||
.ops-toolbar{display:flex;align-items:end;gap:.75rem;flex-wrap:wrap;border:1px solid var(--border);background:var(--bg-alt);border-radius:8px;padding:.75rem}
|
||||
.search-field,.select-field{display:flex;flex-direction:column;gap:.3rem;color:var(--text-dim);font-size:12px}
|
||||
.search-field input,.select-field select,.config-form input,.config-form textarea{border:1px solid var(--border);background:var(--bg);color:var(--text);border-radius:6px;padding:0 .65rem;outline:none;transition:var(--trans)}
|
||||
.search-field input::placeholder,.config-form input::placeholder,.config-form textarea::placeholder{color:color-mix(in srgb,var(--text-dim) 78%,transparent);opacity:1}
|
||||
.search-field input,.select-field select,.config-form input{height:36px}
|
||||
.config-form textarea{min-height:92px;resize:vertical;padding:.55rem .65rem;line-height:1.45;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
|
||||
.search-field input:focus,.select-field select:focus,.config-form input:focus,.config-form textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 18%,transparent)}
|
||||
.search-field input{min-width:280px}
|
||||
.segmented{display:inline-flex;border:1px solid var(--border);border-radius:7px;overflow:hidden;background:var(--surface-soft)}
|
||||
.segmented button{height:36px;border:0;border-right:1px solid var(--border);background:transparent;color:var(--text-dim);padding:0 .8rem;cursor:pointer}
|
||||
.segmented button:last-child{border-right:0}
|
||||
.segmented button.active,.segmented button:hover{background:var(--accent);color:#fff}
|
||||
.icon-text,.primary-btn,.warn-btn,.danger-btn{height:36px;border:1px solid var(--border);border-radius:6px;background:var(--bg);color:var(--text);padding:0 .75rem;cursor:pointer;transition:var(--trans);font-weight:600}
|
||||
.icon-text:hover{border-color:var(--accent);color:var(--accent)}
|
||||
.primary-btn{background:var(--accent);border-color:var(--accent);color:#fff}
|
||||
.primary-btn:hover{filter:brightness(1.08)}
|
||||
.warn-btn{background:rgba(245,158,11,.14);border-color:rgba(245,158,11,.42);color:var(--warn)}
|
||||
.warn-btn:hover{background:var(--warn);border-color:var(--warn);color:#111827}
|
||||
.danger-btn{background:rgba(239,68,68,.14);border-color:rgba(239,68,68,.38);color:var(--danger)}
|
||||
.danger-btn:hover{background:var(--danger);color:#fff}
|
||||
th[data-sort]{cursor:pointer;user-select:none}
|
||||
th[data-sort]:after{content:"";display:inline-block;margin-left:6px;border:4px solid transparent;border-top-color:color-mix(in srgb,var(--text-dim) 70%,transparent);transform:translateY(2px);opacity:.45}
|
||||
th[data-sort].sorted-asc:after{border-top-color:transparent;border-bottom-color:var(--accent);transform:translateY(-2px)}
|
||||
th[data-sort].sorted-desc:after{border-top-color:var(--accent);opacity:1}
|
||||
.section-head h2{margin:0;font-size:18px}
|
||||
.section-head p{margin:.25rem 0 0}
|
||||
.empty-state{border:1px dashed var(--border);border-radius:8px;background:var(--bg-alt);padding:1.25rem;color:var(--text-dim);text-align:center}
|
||||
|
||||
/* 右侧详情抽屉 */
|
||||
.drawer-backdrop{align-items:stretch;justify-content:flex-end;padding:0;background:rgba(0,0,0,.48)}
|
||||
.detail-drawer{height:100dvh;max-height:100dvh;width:min(620px,100vw);max-width:min(620px,100vw);border-radius:0;border-top:0;border-right:0;border-bottom:0;padding:1.1rem;overflow:auto;animation:slideIn .24s ease}
|
||||
.detail-drawer.alert-critical{border-color:rgba(239,68,68,.6);background:linear-gradient(180deg, rgba(239,68,68,.16), rgba(239,68,68,.08)), var(--bg-alt);box-shadow:0 0 0 1px rgba(239,68,68,.38),0 10px 28px -10px rgba(239,68,68,.28)}
|
||||
.detail-drawer.alert-warning{border-color:rgba(245,158,11,.55);background:linear-gradient(180deg, rgba(245,158,11,.14), rgba(245,158,11,.06)), var(--bg-alt);box-shadow:0 0 0 1px rgba(245,158,11,.28),0 10px 28px -10px rgba(245,158,11,.2)}
|
||||
.modal-title{padding-right:2.2rem;display:flex;align-items:center;flex-wrap:wrap;gap:.32rem .4rem}
|
||||
.modal-title .os-chip,.modal-title .spec-chip,.modal-title .cpu-model-chip{margin-left:0}
|
||||
.detail-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.55rem}
|
||||
.detail-section{border:1px solid var(--border);border-radius:8px;background:linear-gradient(145deg,var(--bg),var(--bg-alt));padding:.75rem;display:flex;flex-direction:column;gap:.65rem}
|
||||
.detail-section h4{margin:0;font-size:13px;color:var(--text-dim);font-weight:700;letter-spacing:.4px}
|
||||
.detail-section .kv{display:grid;grid-template-columns:max-content minmax(0,1fr);align-items:flex-start;gap:.6rem;min-width:0}
|
||||
.detail-section .kv span{min-width:0;white-space:normal}
|
||||
.detail-section .kv>span:last-child{text-align:right;overflow-wrap:anywhere;word-break:break-word}
|
||||
.detail-section .mono{display:block;white-space:normal;overflow-wrap:anywhere;word-break:break-word;line-height:1.45}
|
||||
.detail-inline{display:inline-flex;align-items:center;justify-content:flex-end;gap:.45rem;white-space:nowrap!important}
|
||||
.detail-inline .mono{display:inline!important;white-space:nowrap!important;line-height:1}
|
||||
.detail-values{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:.15rem .55rem}
|
||||
.detail-values span{white-space:nowrap!important}
|
||||
.resource-section{gap:.5rem}
|
||||
.resource-meter{display:flex;flex-direction:column;gap:.26rem;min-width:0}
|
||||
.resource-meter-head,.resource-mini{display:flex;align-items:center;justify-content:space-between;gap:.55rem;font-size:12px;min-width:0}
|
||||
.resource-meter-head span,.resource-mini span{color:var(--text-dim);white-space:nowrap}
|
||||
.resource-meter-head strong,.resource-mini strong{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;font-weight:700;text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.resource-track{height:7px;border-radius:999px;background:color-mix(in srgb,var(--text-dim) 16%,transparent);overflow:hidden;border:1px solid color-mix(in srgb,var(--border) 75%,transparent)}
|
||||
.resource-track i{display:block;height:100%;width:var(--p);border-radius:inherit;background:var(--accent);transition:width .5s ease}
|
||||
.resource-meter[data-kind=mem] .resource-track i{background:var(--ok)}
|
||||
.resource-meter[data-kind=swap] .resource-track i{background:#14b8a6}
|
||||
.resource-meter[data-kind=hdd] .resource-track i{background:#06b6d4}
|
||||
.resource-meter[data-level=warn] .resource-track i{background:var(--warn)}
|
||||
.resource-meter[data-level=bad] .resource-track i{background:var(--danger)}
|
||||
.resource-mini{border-top:1px solid var(--border);padding-top:.45rem}
|
||||
.chart-section{gap:.55rem}
|
||||
.chart-head{display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex-wrap:wrap}
|
||||
.chart-head h4{margin:0}
|
||||
.chart-legend{display:inline-flex;align-items:center;justify-content:flex-end;gap:.7rem;flex-wrap:wrap;font-size:11px;color:var(--text-dim)}
|
||||
.chart-legend span{display:inline-flex;align-items:center;gap:.28rem;white-space:nowrap}
|
||||
.chart-legend i{display:inline-block;width:10px;height:3px;border-radius:999px;box-shadow:0 0 0 1px rgba(0,0,0,.16)}
|
||||
.detail-chart{width:100%;border:1px solid var(--border);border-radius:8px;background:var(--bg)}
|
||||
@keyframes slideIn{from{transform:translateX(22px);opacity:.7}to{transform:translateX(0);opacity:1}}
|
||||
|
||||
/* 管理配置 */
|
||||
.config-grid{display:grid;grid-template-columns:minmax(320px,.95fr) minmax(320px,1.05fr);gap:.9rem;align-items:start}
|
||||
.admin-card{border:1px solid var(--border);border-radius:8px;background:var(--bg-alt);padding:1rem;display:flex;flex-direction:column;gap:.85rem}
|
||||
.section-head{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem}
|
||||
.section-actions{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;justify-content:flex-end}
|
||||
.admin-status{border:1px solid var(--border);border-radius:8px;background:var(--bg);padding:.75rem;font-size:13px;color:var(--text-dim)}
|
||||
.admin-status.ok{border-color:rgba(16,185,129,.35);color:var(--ok)}
|
||||
.admin-status.err{border-color:rgba(239,68,68,.45);color:var(--danger)}
|
||||
.admin-login,.config-actions,.form-actions{display:flex;align-items:end;gap:.65rem;flex-wrap:wrap}
|
||||
.config-tabs{align-self:flex-start;max-width:100%}
|
||||
.config-list{display:flex;flex-direction:column;gap:.5rem}
|
||||
.config-row{display:grid;grid-template-columns:1fr auto;gap:.75rem;align-items:center;border:1px solid var(--border);border-radius:8px;background:var(--bg);padding:.7rem;cursor:pointer}
|
||||
.config-row:hover,.config-row.active{border-color:var(--accent)}
|
||||
.config-row .name{font-weight:700}
|
||||
.config-row .meta{font-size:12px;color:var(--text-dim);margin-top:.2rem;word-break:break-all}
|
||||
.config-form{display:flex;flex-direction:column;gap:.75rem}
|
||||
.config-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.75rem}
|
||||
.config-form label{display:flex;flex-direction:column;gap:.3rem;color:var(--text-dim);font-size:12px}
|
||||
.config-form label.wide{grid-column:1/-1}
|
||||
.config-form .check-row{flex-direction:row;align-items:center;gap:.5rem}
|
||||
.config-form .check-row input{height:auto}
|
||||
.config-form .form-actions{grid-column:1/-1}
|
||||
.config-form input[name=password],.config-form textarea[name=rule]{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
|
||||
.config-form button:disabled{opacity:.5;cursor:not-allowed}
|
||||
|
||||
@media (max-width:980px){
|
||||
.ops-overview{grid-template-columns:repeat(2,minmax(0,1fr))}
|
||||
.config-grid{grid-template-columns:1fr}
|
||||
.search-field input{min-width:220px}
|
||||
}
|
||||
@media (max-width:700px){
|
||||
.ops-overview{display:none}
|
||||
}
|
||||
@media (max-width:640px){
|
||||
.ops-toolbar{align-items:stretch}
|
||||
.search-field,.select-field,.search-field input,.select-field select,.segmented,.icon-text,.primary-btn,.warn-btn,.danger-btn{width:100%}
|
||||
.segmented button{flex:1;padding:0 .35rem}
|
||||
.section-head{flex-direction:column}
|
||||
.section-actions{width:100%;justify-content:stretch}
|
||||
.detail-grid,.config-fields{grid-template-columns:1fr}
|
||||
.detail-drawer{width:100vw;height:100dvh;max-height:100dvh;padding:calc(.95rem + env(safe-area-inset-top)) .95rem calc(.95rem + env(safe-area-inset-bottom));}
|
||||
.detail-drawer .modal-content{max-height:none;overflow:visible;}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
body { background: #212e36 url('../img/dark.png'); color: #dcdcdc; }
|
||||
.navbar { min-height: 40px; }
|
||||
.navbar-brand { color: #FFF !important; padding: 10px; font-size: 20px; }
|
||||
.dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; }
|
||||
.dropdown-menu > li > a { color: #FFF !important; background-color: #222222 !important; }
|
||||
.dropdown-menu > li > a:hover { color: #FFF !important; background: #000 !important; }
|
||||
.dropdown-menu { background: #222 !important; background-color: #222222 !important; }
|
||||
.navbar-inverse .navbar-inner { background-color:#1B1B1B; background-image:-moz-linear-gradient(top, #222222, #111111); background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); background-image:-webkit-linear-gradient(top, #222222, #111111); background-image:-o-linear-gradient(top, #222222, #111111); background-image:linear-gradient(to bottom, #212e36, #212e36); background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); border-color: #252525; }
|
||||
.content { background: #212e36; padding: 20px; border-radius: 5px; border: 1px #212e36 solid; -webkit-box-shadow: 0 0px 0px rgba(0, 0, 0, 0); -moz-box-shadow: 0 0px 0px rgba(0, 0, 0, 0); box-shadow: 0 0px 0px rgba(0, 0, 0, 0); margin-bottom: 20px; }
|
||||
.table { background: #363b40; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
|
||||
.table th { text-align: center; }
|
||||
.table-striped tbody > tr.even > td, .table-striped tbody > tr.even > th { background-color: #212e36; }
|
||||
.table-striped tbody > tr.odd > td, .table-striped tbody > tr.odd > th { background-color: #212e36; }
|
||||
.table td { text-align: center; border-color: #2F2F2F; }
|
||||
.progress { margin-bottom: 0; background: #363b40; }
|
||||
.table-hover > tbody > tr:hover > td { background: #414141; }
|
||||
tr.even.expandRow > :hover { background: #212e36 !important; }
|
||||
tr.odd.expandRow > :hover { background: #212e36 !important; }
|
||||
.expandRow > td { padding: 0 !important; border-top: 0px !important; }
|
||||
#month_traffic { min-width: 85px; max-width: 95px;}
|
||||
#network { min-width: 110px; }
|
||||
#cpu, #ram, #hdd { min-width: 45px; max-width: 90px; }
|
||||
#ping { max-width: 110px; }
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 720px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 620px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 533px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 450px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#name, tr td:nth-child(3) { min-width: 55px; max-width: 85px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#cpu, #ram, #hdd { min-width: 25px; max-width: 50px; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
body { background: #ebebeb url('../img/light.png'); }
|
||||
.navbar { min-height: 40px; }
|
||||
.navbar-brand { color: #fff; padding: 10px; font-size: 20px; }
|
||||
.dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; }
|
||||
.navbar-inverse .navbar-brand { color: #fff; padding: 10px; font-size: 20px; }
|
||||
.content { background: #ffffff; padding: 20px; border-radius: 5px; border: 1px #cecece solid; -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); box-shadow: 0 1px 10px rgba(0, 0, 0, .1); margin-bottom: 20px; }
|
||||
.table { background: #ffffff; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
|
||||
.table th, .table td { text-align: center; }
|
||||
.table-striped tbody > tr.even > td, .table-striped tbody > tr.even > th { background-color: #F9F9F9; }
|
||||
.table-striped tbody > tr.odd > td, .table-striped tbody > tr.odd > th { background-color: #FFF; }
|
||||
.progress { margin-bottom: 0; }
|
||||
.progress-bar { color: #000; }
|
||||
.table-hover > tbody > tr:hover > td { background: #E6E6E6; }
|
||||
tr.even.expandRow > :hover { background: #F9F9F9 !important; }
|
||||
tr.odd.expandRow > :hover { background: #FFF !important; }
|
||||
.expandRow > td { padding: 0 !important; border-top: 0px !important; }
|
||||
#month_traffic { min-width: 85px; max-width: 95px;}
|
||||
#network { min-width: 110px; }
|
||||
#cpu, #ram, #hdd { min-width: 45px; max-width: 90px; }
|
||||
#ping { max-width: 110px; }
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 720px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 620px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 533px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 450px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#name, tr td:nth-child(3) { min-width: 55px; max-width: 85px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#cpu, #ram, #hdd { min-width: 25px; max-width: 50px; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
|
Before Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 86" fill="none">
|
||||
<path d="M4 46H28L38 34L55 82L65 4L74 47H88M100 47H110M122 47H126"
|
||||
stroke="#111827"
|
||||
stroke-width="8"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 266 B |
@@ -1,76 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ac" viewBox="0 0 640 480">
|
||||
<path fill="#006" d="M640 480V0H0v480h640z"/>
|
||||
<path fill="#8fc5ff" stroke="#fff" stroke-width="4.3" d="M574.5 199.7c0 63.7-10.2 132.5-93 165.3-82.6-32.8-92.7-101.6-93.1-165.3z"/>
|
||||
<path fill="#366cc9" stroke="#000" stroke-width="4.3" d="M481.4 364.7A134.1 134.1 0 0 0 555 302h-7.8c-2.3-.4-79.4-7.8-88.7-11.7-7.9-2.8-38.4 2.7-52.4 7.8a133 133 0 0 0 75.4 66.5z"/>
|
||||
<path fill="#5d3100" stroke="#000" stroke-width=".4" d="M423.6 325.6h4.7c1.1 0 1.1 0 1.5-1.2.4-1.2 1.6-.8 2.4-.4.7.4 2.3 0 3-.8.9-.8.9-.8 1.7 0 .7.8 1.1.4 2 0 .3 0 1.9-.8 2.3-2 .3-1.1 1.5-1.5 2-.7.3.8 1 .8 1.9.8.7 0 .7.3.7 1.5 0 .8 0 1.2 2-.4 1.6 1.6 2 .8 2-.8 0-1.5 0-7.8-.8-8.2-.8-.4-1.2-3.1-1.6-5 0-4 0-4-3.9-6 0-1-.8-1.5-4-1.5.5-.4 0-1.5-.7-2-.8-.3-.8-.7 0-2.3.8 0 2.4 0 2.7-1.2.8-.7 3.2-.7 4.7 0 1.6.8 3.2.8 5.9 0l4.7-2.3c2-1.2 2.3-1.6 2.3-3.1 0-4-1.1-7.8-2-9.8-1-2-1-4-2.7-7.4-1.5-3.2-1.5-4-3-5.9-.9-.8-1.3-1.2-1.3-2.3a5.9 5.9 0 0 0-2-4c-3-2.7-3.8-11.7-5.4-18.3-.8-4 0-13-1.5-14.5-2.8-2-4-1.6-6-2.3-1.5-2-1.9-5.5-3.4-9-2 .4-3.2 2.3-4.3 3-1.2.9-1.6.9-1.6 2.8 0 1.6-1.2 4-2.7 7-1.6 3.2-5.1 2-7.9 6.3-5.4-6.6-5.4-8.6-5.8-10.5 0-2-1.2-2.4-4.3-5.1v-6c-2.8-2-4.3-1.5-5.5 0-1.2 1.2-2 3.1-3.9 4-.8 1.5-4 4.6-6.3 9 2.4 35.1 10.2 70.3 34 98.5z"/>
|
||||
<path fill="#ff0" stroke="#fff" stroke-width="4.3" d="M574.5 199.7c0-24.3-1.2-47.8-.8-68a248.7 248.7 0 0 0-92.3-16.9c-20.7 0-61.4 3.1-92.2 16.8.7 20.3-.8 43.8-.8 68z"/>
|
||||
<path fill="#cf6200" d="M393.5 227.4c1 1.6 2.9 4.3 3 6 .8-1.6 1.4-2.2 1.5-3.1 0-1 1.3-2.7.8-3.7-.4-1-.7-1.7.4-1s.9 2 .7 3.8c-.7 5-2.7 6-3 9.3 2.9 7 .7 9.6 4 16.6.5.2 1.8-.3 2.2-.2 1.8-1.2 3-.9 5.5-.3 2.4.5 3.7 2.2 3.7 3.8 0 1.6 0 1.9.6 2.8.5.8 1.4 2.3 1.3 3.4-.3 1 .1 1.6.5 2 .3.5-.2 1.8-.4 2.4-.3.6-.2 1.7 1 3.2 1.2 1.5 4 7.9 4 11.6 0 3.9.3 5.6 1.8 6.3 1.5.7 2 1.3 1.8 2.9-.2 1.5.7 10 .9 11.4.1 1.3.7 1 1.4 1.7.6.7 1 1.5 3 1.5 2.1 0 4-.2 5.2 0 2 2.5 3 6 3.5 8.1.5 2.2.4 5 1 5 .8 0 1.5 0 1.3-2.5-.2-2.6-.4-3-1.3-4.4-1-1.3-1.5-2-1-2.7.5-.8.6-2 .5-3.1-.2-1-.6-2.6 1.2-.6l2.7 3.3c.5.6.7 2 .6 3.3-.1 1.2 0 1.7.9 1 .7-.6 1.5.5 1 1.8-.3 1.3.3 2.1 1.5 2.6 1.2.4 1.7.7 2 1.6.3.8 1.3 1.3 1.3-.6a27 27 0 0 0-1.2-6.9c-.5-1.2-.9-3.8-1-5.4-.2-1.5-.4-1.9-1.1-2.1-.7-.3-1.4-1-1.5-1.6 0-.7-.7-1-1.1-1-.5 0-.9-.3-1.2-.8-.2-.6-.5-.6-1-.6-.5-.1-1.3.2-1.6-.6-.2-.8-.6-2-1.1-2.6-.5-.6-.9-.9-1-3.2 0-2.3 0-2.6-.8-3.4-.8-.8-2-3-2.5-3.8-.4-1-1-1.9-1 0 0 2 0 3 1.3 3.7 1.2.7 1.5.7 1 1.8-.6 1 0 1.7.2 2.4.3.7.6 1.4 0 2-.6.8-1.2.6-1.1-.5a6.4 6.4 0 0 0-.9-3.3c-.4-1-.9-1.6-1.5-1-.6.4-1.1-.2-.7-.6.5-.4.3-.7 0-1-.2-.2-.4-.6.1-1.2s.5-.9.2-2.3-2.5-8.6-3.5-10.2c-1-1.7-.9-2.8.3-1.3 1.3 1.6 2.5 3 2.7 4.4 0 1.4.3 2.2.7 2.6.5.5.7.4 1-.8 0-1.1 1-.7-.4-2.8-1.5-2.1-4.1-5.7-5.2-12.2-1-6.4-1.4-10.5-2.4-12.2-1-1.8-1.3-2.2-1.4-3.8-.1-1.6 0-3.3-.7-4.5-.7-1.2-1.2-1.4-1.3.4-.1 1.8 0 6 .6 6.6.6.7.2 2.6 0 3.5-.2 1-1.7 2.1 1.7 4.1 1.3.9 1 2 1 2.6-.3.8-.5.7-1.2-.4s-1.4-2.1-2.1-2.6c-.7-.5-.9-1-.7-2.5.2-1.5.3-2.5 0-3-.4-.4-.6-.1-.9.8-.2.8-.3 3-.9 3.6-.5.6-.5.2-.8-1.1-.4-1.3.1-3.4.8-5.7.7-2.2 1.2-4.8.6-7.8s-.4-4-2.6-6.5c-2.4-2.6-5.1-5-6.1-8.1-1.2-3.2-1.4-6-2.7-7.4a17 17 0 0 0-4-3.7v-4.7c0-1.2-.5-1.8-1.8-1.6-1.3.2-2.2 1.3-3 2.8-.8 1.6-1.4.9-2.6 3.5-1.2 2.6-2.6 4-2.6 6.8z"/>
|
||||
<path fill="#cf6200" d="M400.8 257.1c1 .6 1.7.9 3 .3 1.1-.6 2.5-2.4 4.3-.6a11 11 0 0 1 2.4 6.7c0 2.3 0 6.5 2.6 8.8 2.6 2.3 3.9 4.8 4 7.8a53.2 53.2 0 0 0 1.4 9c.4 1.2 1 2.6 1.9 3.5.7.8 1.4 3.1 1.5 5.5.1 2.5-.3 4.1 0 5.4.4 1.2 0 2.2-.8 1.7-1-.5-1.2-1-1.8-2-.6-1-1-.9-.5.7s2 3 3.3 3c1.3 0 1.7.1 2.6 1 .8.8.9 1.2 2.3 1.2s1.6 0 3 .4c1.3.3 1.3.2 2 0 .7-.3 1.4.4 1.9 1.7.4 1.3 1.7 5 1.7 6s0 2 .7 3c.7 1.1.5 2-.3 1.5-.7-.6-.8-.5-1.3-.3-.6.2-1-.2-1.9-.8-.8-.4-.3-.3-1.1-1.5-.8-1.3-1.3-1.7-1.3-.7s-.2 2-.8 1.4c-.6-.5-.9-.5-1.4 0-.5.6-.7 1-1.3 0-.6-1-1.3-1-2-1.3-.5-.1-.5-.1-.8-1-.3-1-1.3-1.2-2-1.2-.9 0-1.3-.4-1.4-1 0-.6-.6-1-1-1.3-.5-.3-.2-1-.3-1.7 0-.7-.7-.5-1.1-.6-.5-.2-.7-.1-.7-1.2 0-1-.5-1.3-.7-2-.4-.8 0-1.5.2-2.2.1-1 0-1.4-.6-2-.6-.8 0-1.5-1.7-3-1.7-1.3-2.5-.1-3-3.4a43.7 43.7 0 0 0-2.4-11.4c-1-1-1.5-2-2.5-2.3-1-.3-1.4 0-1.5-2-.1-2-.7-4.4-2-5.6l-2.3-2.2c-.6-.4-.9-1.4 0-3 .9-1.8.5-4.2.4-5.3-.1-1-.4-2.6-.2-3.8.2-1.2 0-2.7-.2-3.5-.3-.7-.7-1-.2-1.7zm24.5-28.8a22.1 22.1 0 0 1-4.7 4.6c-1.9 1.4-4.3 2.4-3 4.7 1.4 2.3 2.5 2.6 2.7 4.3.3 1.8.8 3.3 2 3.7 1.5.4 2 .2 2 3 0 2.7 0 4 1.2 5s1 2.2 1.6 4.7c.6 2.6.6 8.2 2.2 12 1.5 3.7 5.3 11 4.8 12.4-.4 1.5-.8 2.6.7 4.4 1.7 1.7 2.7 4.3 3 5.8 0 1.5.3 2 2 1.5a6 6 0 0 0 2.9-1.7c.5-.7 1.6-.6 3.1.2 1.5.9 3.8 1.6 5.2.9 1.3-.9 2-2.1 3.2-2.1 1.9-1.4 2.6-4.2 3-5 .4-.8.1-.8-.7-1.6-.8-.8-.4-2.2-.5-3.5-.2-1.4-.7-3.5-2.3-6.5-1.6-3-2.7-6.6-3.7-7.5-1-1-1.6-3.3-1.7-4.4-.1-1-1.4-2-2.2-2.8-.9-.9-1.6-2-2.6-6.8-1-4.7-1.6-8-1.6-9 0-.8-.2-.8-1-1.2-.8-.3-1.2-1.6-.8-2.2.1-.7-.4-1.4-.7-2.2-.2-.8 0-2.3.6-3.2.5-.8.4-3-.1-5-.5-1.8-1.1-3.4-3.3-3.8-2.1-.2-2.6-.8-3.3-2.6-1-1.7-1.8-4.8-2-5.5-.2-.7-.7-.8-2.3.6-1.6 1.3-2.2 1.7-2.2 4.3 0 1.7.4 2.2.9 3.1.5 1 .7 1.3 1 3.8.4 2.5 2.7 6.6-.2 9-3 2.2-2.6 2.8-2.5 4.4.2 1.7-.8 2.7-1.3.5-.6-2.4 0-3.7 1.6-4.8 1.6-1 3.1-2.5 2-4a19 19 0 0 1-1.7-6.6c-.1-1.6-.3-2.2-1.3-.9z"/>
|
||||
<path fill="#00b800" d="m401.2 262.8.3 3.3c0 1.1.4 3.5-.5 5.2-.8 1.7-.6 2.6 0 3.1h.1c1.7-.5 2-2.3 1.5-3.2a3.2 3.2 0 0 1 .2-3c.5-1 .5-1.5 0-2.2-.5-.7-.5-.7 0-2.6.6-1.7-.7-1.7-1.6-.6zm17.4 26.3c-.3-1.2-1.5-6-1.5-9-.1-3-1.5-5.5-4-7.8-2-1.8-2.4-4.7-2.6-7-1.5-.9-2-.5-1.9 1.2 0 1.8 2 2.6 1.7 5.3-.3 2.6-.3 2 1 3.3 1.1 1.2 1.7 2.6 1 3-.7.5-.7 1.5.2 1.8 1 .4 1 1.4.9 2.4-.1.9.9 1.1 1.3 1.7.6.7.6 2.4 0 3.3-.4 1-.5 2.5.4 1.7 1-.9 1.4 0 2.1 1.2.6 1 1.2.7 2 .5a8.5 8.5 0 0 1-.7-1.6zm13 23.6c-.4 1.2-1.1.9-1.7.3-.6-.6-1.3-.6-1-1.8.2-1.1 0-1.3-.7-1.9l-.3-.3h-.8c-1.5 0-1.6-.3-2.5-1.2a6.8 6.8 0 0 0-.5-.4v.8c0 1.1 0 .8-1 1.2-1 .3-1-1.1-1.2-2a3.4 3.4 0 0 0-.1-.6 4 4 0 0 1-3-2.9c-.5-1.6 0-1.7.6-.7s.7 1.3 1.6 2c.8.5 1.2-.5.8-1.7a5.2 5.2 0 0 1 0-1.3 2 2 0 0 0-.8-1c-1.8-.7-1.2-.8-1.2-2.2.2-1.3-.1-1.3-1.2-.6-1 .7-1 0-1-2.2 0-2-1.4-2-1.7-.6-.3 1.5-.9.5-1.4-1.5-.5-2-1.5-2.6-1.5-.6 0 1.7-.6 2-1.6 1.2l.4 3.1c.5 3.3 1.3 2 3 3.5 1.6 1.4 1.1 2.2 1.7 2.9.6.7.7 1.2.6 2-.3.8-.6 1.5-.3 2.2.3.8.8 1 .8 2.1 0 1 .2.9.7 1.2h.8l.7-1c1.3-1.2 3 0 3.7 1.7.6 1.5 1.3 1.9 2.3.6 1-1.2.6-1 1.6.1 1 1.2 1.4 1 1.4 1s1-.4 1.8.2c.7.6 1 .5 2.4-1.4 1.3-2-.6-1.4-1.2-.2zm3.8-55.8c.4-3 .1-5.9 1.3-7 1.3-1 2.7-3.3 2.7 1.4-.2 4.6-.4 4.3-1.3 5.4-1 1.1-1.8 1.4-1 3.1 1.1 1.7 1.2 2 1.1 4.6-.1 2.7-.1 3.9.9 5.2 1.1 1.4 1.4 1.4 1.7 3a8.4 8.4 0 0 0 2.4 4.5c1.2 1.2 2.6 4.2 2.7 6.4.2 2.2 2 2.7 3.8 4.3 1.8 1.5-.4 2.5-1.7 1.8-1.4-.6-.9 0-1.7 1-.8 1-1 1.1-1.7-.6-.7-1.6-3-2.7-4.1-3.1-1.1-.4-2-2.2-3-4a5.2 5.2 0 0 0-3.9-2.6c.4 1.1.6 2 .5 2.4-.4 1.5-.8 2.6.7 4.4 1.7 1.7 2.7 4.3 3 5.8 0 1.5.3 2 2 1.5a7.2 7.2 0 0 0 2.9-1.7c.5-.7 1.6-.7 3.1.2 1.5.8 3.8 1.6 5.2.8 1.3-.9 2-2 3.2-2 1.9-1.4 2.6-4.3 3-5 .4-1 .1-1-.7-1.7-.8-.8-.4-2.2-.6-3.5 0-1.4-.6-3.4-2.2-6.4-1.7-3-2.7-6.6-3.7-7.5-1-1-1.7-3.3-1.7-4.4-.2-1-1.4-2-2.2-2.9-.9-.8-1.7-2-2.6-6.7-.7-3.7-1.4-6.6-1.5-8-1 1.5-1.7 2-2 .8-.5-1.2-.9-1.8-1.5-1-.5.8-.7-.8-.7-1.5s0-.7-.9-.7c-.8 0 0-1-.3-3.2-.3-2-.7-2.2-.9.2-.3 2.4-1.7 4-1.1 4.4.5.6.2 1.7-.3 3.3a5.1 5.1 0 0 0 0 3.6c.4 1-.2 3.2-.4 4.9-.3 1.7 1.1 3.5 1.5.6zm-24.8-24.2c-1 0-1.7 1-1.1 4 .4 2-1 1.6-1.6.6-.5-1-1-3-2-4.7-1.1-1.7-.6 1.1-.7 2.8-.2 1.7.9 1.7 1.8 3 1 1.4.2 1.9-.8 1.9s-.7 2.2-.4 3.6c.3 1.5-.3 1.8-1 .6-1-1.3-.3-3-.2-5.4.2-2.3.3-1.8-1.2-2.3-1.5-.6-1.3-.9-.6-2.2.5-1.4 1-2 .3-2.7-.6-.7-.5-1.1.6-1.2 1-.2.6-1 1.6-1.2 1-.3 1.4 0 1.5-1.7.1-1.5.6-2.3 1.7-1.9.7 2.3 1.5 5.8 2.1 6.8zm13.7 16c0 2.8 0 4 1.2 5s1 2.2 1.6 4.7c.6 2.6.6 8.2 2.2 12l1.8 4a7.7 7.7 0 0 0 2-2.6c.3-.8-.9-2.8-1.8-4.3-1-1.8.1-2.3 1-4.4 1-1.9 0-2-1.6-2.6-1.4-.5-1.4-2-2.2-4.1-.8-2.2-.7-3.1-.2-4.4.5-1.2.2-2.1-.9-2.4-1.1-.3-.8-1-.4-2.4.4-1.3.7-1.6-1-1.3-1.2.4-1.5.7-1.9 1z"/>
|
||||
<path fill="#5d3100" d="M439.9 254.3c-.2 1.6-.2 2.5-.6 3-.4.5-.1 1.3.3 2.2.5.8.6 1.8.3 3.4-.4 1.5.2 2.6 1 3 .8.4 1.2 0 1 2a5.8 5.8 0 0 0 1.7 4.7c1 .8 1.7 2.1 1.5 3 0 .8.7 1.5 1.7 2 1 .4.8.5.8 1s.4.6 1.4.9c1 .3 2 .9 3.2 2.4 1.2 1.6 3 2.3 2.7.7-.3-1.5 0-2.8-1.6-3.5-1.7-.8-2.9-4.7-3.5-7.4a17 17 0 0 0-4-7.1c-.3-2 0-2.9-1.2-3.8a4 4 0 0 1-1.7-3.2c0-.8-.6-2-1.2-2.4-.5-.3-.8-.9-.8-1.8 0-.8-.8-.7-1 1z"/>
|
||||
<path fill="#00d860" d="M432.7 327a39.2 39.2 0 0 0 9.7-2.8c1.7 1.1 4.5 2.6 5.7 2.6-2.3.5-3.9.3-4.4-.2.3.7 1 1.9 1.6 2-2.3 0-4.8-.6-5.6-1.4-2 .8-5.2 1-7-.2zm4.3 3c.9.3 5.2 1 5.8 1-1.4 1.2-.2 2.4 2.1 2.2-1 .2-2.4.6-1.5.8a24.4 24.4 0 0 0 8.9-1.8c-2 2.5-11.4 4.8-15.3-2.2zm4 6.1a9 9 0 0 1 5.3.3c-1.4.6-4.5.6-5.4-.2z"/>
|
||||
<path d="M445.3 336.1c2-.3 8 1 10-.2-.7 1.9-4.3 2.2-5.7 1.7-1.3-.3-2.5-.8-3.4-.8.6-.3-.2-.3-1-.7z"/>
|
||||
<path fill="#00d860" d="M447.4 339a30.5 30.5 0 0 0 9-1.1c1.7.6 5.4 1.6 6.2 1.5-1.7 1-5 .4-6 0a10.9 10.9 0 0 1-9.2-.4z"/>
|
||||
<path fill="#00d860" d="M450 339.9c2.3.5 4.3.2 6.5-.5.7.2 2.3.6 3.9.6 1 .5 2.3 1.3 3.7 1.5a16.6 16.6 0 0 1-7.5-.7 19.2 19.2 0 0 0-8 1.5 3 3 0 0 1 1.5-2.3z"/>
|
||||
<path d="M447.4 328.6c1.7.5 8.2.2 11.3-1.3 1.4-.7 2.2.4.7.8-5.2 2-9.5 2.6-12.5 1-1.2-.6-1.4-1.2.5-.6z"/>
|
||||
<path fill="#00d860" d="M478.6 319.8c-7.9 3.7-13 4.8-23.9 1.4-1-.2-1.7 0-.6.7a40 40 0 0 0 8.5 2.6c1.4.1.9.7 0 1-.8.2-1 .8.1.4 1.1-.5 7.8-.7 10.5.7 1.1.7 1.4.5 1.3 0-.1-.4.5-.7 1.4-.8.8-.1 1.4-.4.7-.6-.7-.3-.8-.5-.3-.7.5-.3.6-.6-.2-.7-.7-.2-1.3-.4-.6-.7a9 9 0 0 1 2.6-.7c.2-.5-.1-2 .5-2.6z"/>
|
||||
<path d="M465.6 320.7a26 26 0 0 0 17-6c1.6 1 3.7 2 4.9 2.2 1.1.2 2 1.2.3 1.2s-4-.7-5.2-1.2a29.5 29.5 0 0 1-17 4.3c-1.1 0-1.4-.5 0-.4z"/>
|
||||
<path fill="#00d860" d="M452.3 296.3c1.6 1.1 4.3 2.9 7.8 2.6a17 17 0 0 0 5.7 3c-2.4.8-5 1.7-5.6 2.4-1-1-2.5-.8-2.8-1.4-1 1-.9 1.3-.2 1.8a22 22 0 0 0 7 .9c1.2-.4 1.7.7.6 1-2.7 1-8 0-9.8-2.9-2-2.9-3.5-4-8.5-1.3-.5-1.5-.5-1.7-1.5-1.7s-2.8-1.3-1.4-1.3 5.4-.6 8.7-3z"/>
|
||||
<path fill="#00d860" d="M453.6 303c-1 .1-3.3 1.4-4.1 1.5-.9.2-2.4 1.4-.9 1.4 1.7 0 3.7-1.7 4.8-1.7 1.1 0 1.2-1.5.2-1.3zm5 5c-.7.2-3.3.8-4 .8-.7 0-1.5 0-1.4.6.1.5.3.9-.9.7-1-.2-1.9.3-2.1.6-.3.3-.5.6.6.7 1 0 1.6.3 2.9-.4 1.2-.6 2.3-1.3 3.6-1.4 1.3 0 2.6-1.8 1.2-1.5z"/>
|
||||
<path d="M454.9 311.1c1.1.9 6.6 2.6 8.5 2.6 2-.1 1.7.7.2 1a12.2 12.2 0 0 1-9.6-2.7c-1.2-1 0-1.4.8-.9z"/>
|
||||
<path fill="#00d860" d="M480.8 314a21 21 0 0 1-10.2.3c-1.7-.6-3.3-.6-2 .6 1 1.1 4.8 1.8 7 1.3-7.6 1.7-9.6 1.6-11.4 1.3a38 38 0 0 0-7-.2 6 6 0 0 1-3.3-.4c-.7-.5-.9-1.1 1.1-.9 2 .1 2.3-.2.6-.5-1.8-.3-4.1.4-1.8 2 2.4 1.4 7.4-.2 10.7.8a18.6 18.6 0 0 0 16.7-3.8c.3-.2.9-1-.4-.6zm-20.6-6.3c.2.6.2 1 0 1.4-.2.4-.1.9.5.4s1-1.2 1.8-.8c.7.3 2.3.3 3 .2.8 0 1-.3 0-.7a7.4 7.4 0 0 0-2.9-.6c-.6.1-1.4 0-1.9-.3s-.6 0-.5.4z"/>
|
||||
<path fill="#00d860" d="M471 309.7c-.8 0-2.4-.6-3.1-1-.8-.3-2-.3-1.2 1 .9 1.2 4.6 1.7 6 1.2 1.3-.6.8-1.2 2-.4 1.4.8 2.7 1.3 3.7 1.3s1.3 0 .3-.6-1.6-.7-1.8-1.2c-.2-.5-.2-.9.9-.5 1 .3 2 .8 2.8.4.8-.4 2.2-1.3 3.5-1.3l.2-.8c-1.8 0-3 .5-3.5.6-.4.2-1.4.4-2.4.2s-2.2-.3-2.5-.5c-.4-.3-.3-.5.5-.6.8-.2 1-.7 0-.6-1 .2-4.2.2-5.8-.3-1.5-.5-2.2-.6-2.8-.3-.7.2-.6 1 .3 1 1 0 3.2.3 4 1 .6.7.6.7-.2.4-.9-.4-2.5-.2-.9 1z"/>
|
||||
<path fill="#00d860" d="m484.3 307.8-.3.8c1.9 0 6.4.4 8 1.3 1.4-1.1 1.1-1.5 2-1.2 1 .3 2.4.5 3 .3a2 2 0 0 1 1.5-.2c.6 0 2-.2 2.7-.6.8-.5 2.4-1 3.3-1 .8 0 2-.3.3-.6-1.6-.3-4.2.3-5 .6-1 .3-3.5.5-5 .5s-3.6.7-5.3.3c-1.8-.4-4.2-.2-5.3-.2z"/>
|
||||
<path d="M507.9 307c-3 2.2-6.8 2.7-11.1 3-1.3 0-.9.4.2.5 4.6.5 9.8-1.2 11.6-3 .5-.6.4-1.4-.7-.6z"/>
|
||||
<path fill="#00d860" d="M487.1 312.2a47 47 0 0 1 7.3 1.7c1.2-.2 1.5-.4 1.3-.9-.3-.4-.4-.8 1.7-.6h7.5c.8-.3 2.3-1.5 3-1.5-1.8 0-9.5.4-10.4.3-1 0-1.5 0-2.1.4-.6.3-.9.5-1.7.1-1-.3-2.1-.7-3-.1-.6.4-2.3 0-3.6.6z"/>
|
||||
<path fill="#00d860" d="M504.9 312.4c.7-.3 2.3-1.5 3-1.6 1.4-.1 2.8.4 3.5.6.7.2 1.5 0 1-.6-.4-.5 0-1.6 2-1.3 2.2.2 3.2.6 5.3.4 2.1-.2 2.9 1.3 6.7-.2-.2 1.5.5 1.6 1.2 1.3.7-.2 1.5-.2 2.7.7 1.3 1 8.7 1 10.4.7 1.8-.3 2.6.6 1.3 1s-1.6 1-1.3 1.5c.3.4.6.9-1 .7-1.7-.2-2 .3-2.7.8-.8.6-1 1-3.3.5-2.2-.4-2.7-.1-3.9 0-1.2.2-1.5.3-2.8-.1a9.6 9.6 0 0 0-5.5-.3c-1.6.6-2.7 1-4.2.6-1.5-.3-1.5-.2-.6-1 .8-1 1-1 2.8-1.1 1.8-.2 3-.7 1.9-1.4-1.3-.7-1.6-.6-3.3.1-1.6.8-2.4 1.4-4.3.4-1.8-1-2.6-.9-4-.5-1.2.3-3.2-.5-4.9-1.2zm6.1 3c-2.4.4-3-1.1-5.4-.9-.8.2-2.2 1.2-.3 1 1.9-.1 4 .9 5.8.8 1.8-.1 1-1 0-.9zm-2.6 1.7c1.1-.4 3.6.5 4.8.3 1.1-.2 2 .4.8.9-1.2.4-3.7-.7-5-.4-1.1.4-2.4-.1-.7-.8zm-24.4 6.7c1.7 0 7.8-.3 10.2-5.3.2-.4.3-.6 1 0 .7.5 3.6 2.1 8.8 2.6 1.5 0 3 .8.1.7-3-.2-7.6-1-9.1-2-2.7 4.1-7.4 4.6-11 4.5-2.1 0-1.6-.6 0-.5z"/>
|
||||
<path fill="#00d860" d="M497.1 316.8c-.8 1.1-3.6 3-4.8 3.2-1.3 0-5.2-.2-6.1-.6-1-.3-2.1-.3-.8.7a11 11 0 0 0 6 1.3c1.6-.3 3.1-.8 4.2 0 1 .6 3 1.8 4.2 1.6 1.2-.3 3.5-.3 4.3 0 .8.4 2.1 1.6.1 1-2-.7-3.6-.2-4.5-.6 1 1.4 3.3 3.7 5.2 3.7.5 0 .9.9 0 1.3.8.4 3 .9 4.3-.3-.4.5-.2.7.3.9.5.2 1.1.6.2.8-1 .2-3 .3-3.6 0 2 1.3 7 3.4 12.3 2.3 1-.1 1.6-.6 0-.5-3.5 0-3.7 0-4.3-.3-.6-.4-.4-.7.6-1a24 24 0 0 1 4.3-.7c1 0 2.1-.3 0-.3-2 0-4.6 0-5.7-.4-1-.3-1.7-.9-.6-1.6 1-.7 2.1-.5 2.6-1-3.3 0-7.4-2-5.2-3.6.5-.3.4-.4-.4-.5a22 22 0 0 1-4.5-1.4c-1-.5-.4-1.1.5-1.3-2 .3-6-.7-8.6-2.6zm29.8 0c-1.8 1.3-5.3 2-6.8 2-1.4 0-1.7.4-.5.5 1.2.1 2.5.4 3 .2s.9-.2 1.6.2a6 6 0 0 0 3.8 0c1.5-.4 3.7-.6 4.7-.6 1 .1 2 .1 0-.4-1.8-.5-5-.2-5.8 0-.7.2-2.8 0-1.7-.2 1.1-.3 2-1 2.6-1.4l-.9-.3zm-1 4a11.8 11.8 0 0 1-6.1 2.3c2 .8 3.8 3 5.2 2.8-.7.5-1.5 1-2.3 1.2a8 8 0 0 0 5.4-1c3 .8 7 .2 8.3-1-2 0-4.3-.6-5.4-1.6 1 0 1.9-.5 2.3-1.1-2.3.4-6-.7-7.3-1.8z"/>
|
||||
<path fill="#00d860" d="M522.7 327c.8 0 1.7-.6 2.3-1a19.2 19.2 0 0 1-11.1-2.6c-2.2-1.9-2.2-.4-.7.9a11 11 0 0 0 9.6 2.8zm5.4 4.7c-.9.5-5.3.9-6.7.5-1.5-.3-2-.2-1.8.5.3.6.6 1-.6.8a12 12 0 0 0-4 .5c-1 .2-2 1-.2.7 1.9-.2 3.5-.6 5-.3 1.3.3 6.1.4 7 0 1-.4.4-.3 0-.3-.5 0-.7-.3 0-.7.7-.3 1.1-1 1.3-1.7zm-42.3-5.8a62 62 0 0 1-9.6 2.5c-2 .9-3.6 1.4-4.6 1.4.7.6 3.5 1.2 4.5.9-.6.7-2 1.3-2.5 1.7 1.7-.3 3.5.2 4.4.3a12.2 12.2 0 0 1-6.7 1.4c.6.6 1.3 1.3 2.2 1.3a11.3 11.3 0 0 1-5.5.2c.6 1 1 1.6 1.8 1.8-1.7.1-3.7.4-5.4-.6 1.3 1.8 4.2 2.3 8.6 1.8 4.4-.5 8-2.4 9-3.2-1.8.2-4.3.3-5.4 0a32.2 32.2 0 0 0 8.6-3.7 4.9 4.9 0 0 1-2.8-.9 27 27 0 0 0 8-.8 5.8 5.8 0 0 1-3.5-2.3 34.2 34.2 0 0 0 17 .5c.8-.2.8-1.3-.7-1.1-2.8.2-8.3-.6-9.8-1.3a10.1 10.1 0 0 0 4 1.7c-2.5.8-6.2 1.3-11.6-1.7z"/>
|
||||
<path fill="#00d860" d="M473.6 332.4c.5-.4 2-1 2.5-1.7-1.1.3-3.8-.3-4.5-1 1 0 2.6-.4 4.6-1.3-3.6-.1-6-.1-7.5-.9-1.4-.8-3.7-.4-4.7-.2-1 .1-.6 1.7 3.3 1.3a13.4 13.4 0 0 1-7.6 1c.4 1.4.7 2.7.3 3.5 2.1 1.2 7.7 2.7 10.5 2.5-2.5-.9-3.8-1.9-1.8-2.2 2-.2 3.2-.6 5-1z"/>
|
||||
<path d="M467.3 339c4.8-.4 11.4-.5 16.6-5 1.3-1 2.2-.6.9.5a28.8 28.8 0 0 1-16 6c-2.7 0-3.9-1.3-1.5-1.6z"/>
|
||||
<path fill="#00d860" d="M503.7 331a19 19 0 0 1-5.6.8 6 6 0 0 0-3.3.2c-.8.5-.9 1 .2 1l3.3.2a5.4 5.4 0 0 0-1.8 1.5c1.8-.4 4.7.3 5.6.8a2.6 2.6 0 0 1-2-.4c2.7 3 10.9 3 12.2 2.4-.6.5-1.2 1-1.7 1 2.2.5 4.8.4 7.5-1l-4.2-.2a4.9 4.9 0 0 1 2-1.2c-1-.2-4.2-.1-5 .3a3.5 3.5 0 0 1 1.5-1.7c-4 0-8.9 0-10.6-1 2.7.4 5.9-1.3 7.2-1.3-2.2 0-4.6-.5-5.2-1.5zm-10.1 2c-2 .5-5 1.4-5.9 1.8-.8.5-1.6.7.1.7a109.4 109.4 0 0 1 .6-.1c-.7 0-1.5 0-.1-.5 1.3-.4 3-1.3 5.2-1.7zm-4 4.9c.7 0 3.7 0 5-1 1.2.8 3.7 2.2 5.2 2.2 1.6 0 1.4.4 0 .6a10.5 10.5 0 0 1-5.4-1.7c-1.8.7-3.3.1-5-.1zM466 351.6a17 17 0 0 0 10.3 1.1c1.8 1.5 5.3 1.6 7.2 1.2 2-.4 3.7-.6 5.9 0 2 .8 6.4.9 7.7 1.9l-4.1.1c-.6.2-.3.5.8 1a22 22 0 0 0-11.3 3 6.4 6.4 0 0 1 6-3.8c-1.8-.6-7.7-.7-9.7.5a5.8 5.8 0 0 1-1.2-2c-3.1 1.7-9.2-.9-11.7-3zm-8-5.8a14 14 0 0 0 7.3-2.8c.7.6 3.5 1.2 6.5.3-.6.4-.7 1.3-.5 1.7a22.8 22.8 0 0 0-7 1.8c-1.2.6-5 1.1-6.2.4-1.2-.6-1.2-1.2-.2-1.4z"/>
|
||||
<path fill="#00d860" d="M471.3 345.1a22.8 22.8 0 0 0-7 1.8l.5 1.7a44.4 44.4 0 0 1 15.3-1.6c-1.6.1-4.5 1.8-6.1 1.9 4-.3 7.8.5 8.8.8 1 .2 1.3 1 .5 1.8-.8.9-1.1.7.5.9 1.6 0 5-.3 6.5-1.8-.7-.6-2.2-.3-2.7-.9a7 7 0 0 0 2.7-1.6 25.3 25.3 0 0 1-4.6-.3c-.8-.2-1.5-.5-.4-1.1a6.6 6.6 0 0 0 2-1.5c-2 .5-5.1 1-7.8-1 1 .2 3.3 0 4.1-.3a5.2 5.2 0 0 0-2.2-.8c2-1 6-1.9 11.3.1a27 27 0 0 1 7.1.4c1-.8 2.6-2.8 3.5-3.2-6 .4-16.8-.6-16.5-3.8-2 2.6-6.5 4-8.4 3.6-.2.8.6 2 1.3 2.6-2 .4-5.5.8-7.1.4 1 .9 2.6 1.7 3.6 1.7-2 0-3.2.4-4.9.2z"/>
|
||||
<path fill="#00d860" d="M483.7 352.3c1.8 0 5-.2 6.6-1.7-.7-.6-2.2-.3-2.7-.9a7 7 0 0 0 2.7-1.6c4.4-.4 8.1-.2 10-.7 1.8-.5 6.5-.3 7.4-.5-4.1.7-4.9 1-5 1.7-.2.7 1.2 1.1 2.2 1.1-1.7 0-4.1 1.9-4.4 2.7-2.4-1.4-3.4.2-3.8.8-1-.4-4.4-.3-6.1 1.2-2.2-.7-3.7-1-6-.7 1.5-.3 1.2-1.3-.8-1.4zm19.5-12c1.4 0 4.4.2 5.5 0a6.5 6.5 0 0 0-1.8 1.3c3.5-.4 8.2-.7 9.6-.4-1.8-.3-3.5.9-4.4 1.4-.8.5-.3.9.9 1 1.2.2 2.7 1 .6.8-2-.2-6.4-.3-7.4-.2-1 .2-1.6-.3 0-.6a10 10 0 0 0 3.1-1c-1.2.3-3.5.3-4.3 0-.8-.3-1.1-.5-.3-.8.9-.3.3-.4-.6-.3-.9 0-3 1-4.3 2.1 1.3-1.4 2.6-2.6 3.4-3.2z"/>
|
||||
<path d="M487.8 342.7a8.7 8.7 0 0 0 6.8 3c.6 0 2 .9.3 1-4.3.2-6.4-.9-8.3-3.6-.4-.6.3-1.4 1.2-.4zm25.5-35.6c2.2 1 6.7 2 10.2 1.9.7 0 1.8.6.3.7a18.3 18.3 0 0 1-10.8-2c-.9-.5-.6-1 .3-.6z"/>
|
||||
<path fill="#00d860" d="M515.5 307.1c3.5 0 6.1 0 7 .9 2-.5 5.7-.9 6.4-.7.8.2 1.8-.3-.1-.7-2-.4-6.2-.6-7.6-.3-1.4.2-5.7.4-7 .2.5 0 .9.2 1.3.6zm13.4 1.3c1.6-.8 6.3 0 7.7-.6-1 1.2 3.3 1.3 7 .4-1.4.8-4.5 1-5.8 1.6-1.3.6-2 .1-3-.3a11 11 0 0 0-5.9-1z"/>
|
||||
<path fill="#00d860" d="M543.6 308.2c-3.7.8-8 .8-7-.4-1.4.6-6-.2-7.7.6 1.8-1 3-.1 4.2-2.2.8.1 2.6.2 3.2-.6 1 .3 3 .7 3.5 1.3.5.6 1.3-.2.7-1 1.7-.6.6.7 4.5-.3.9-.2 2.8-.6 3.5-.6a24 24 0 0 1-5 3.2z"/>
|
||||
<path fill="#ff0" stroke="#000" stroke-width=".4" d="m471.6 291.1-.7-86.8c0-3.9-2-3-2 0v86zm28.2-91.4 3.1 91.4-.4.8h-2l-1.9-92.2zm26.6 77.4-1.6-74.3c0-2.4-2-2-2 .4l1.6 73.9z"/>
|
||||
<path fill="#fff" stroke="#000" stroke-width=".4" d="m484.2 214.9-27.4-.4c-1.2 5.5 5.5 5 7.8 4 3.1 1.9 5.5 1.9 7 0 2.4 1.9 5.5 1.5 6.7 0 3.1 2.7 6.6 0 5.9-4zm2 13.3h-27.5c-5 4.7 1.2 7 6.7 3.9.8 1.6 3.9 2.3 6.2 1.2 2.4 1.5 5.5.4 7-1.2 2.8 1.2 6.3 1.6 7.9-4zm-.9 17.6h-26.6c-.3 4.3 5.1 3.9 7 2.7 2 3.2 6.7 2.4 8.3.4 2.7 2 5 1.6 6.2 0 2.8 2.4 5.5-.8 5.1-3.1zM487 263l-30.1-.4c-1.6 5 3.1 5.9 5 4.7.9 2.7 4.8 2 6 0 1.5 1.2 3.5.4 4.2-.8.4 2.7 4 3.1 6.7.8 5.5 3.9 10.5-.8 7.8-4.3zm26.2-7h-24.6c1.1 4.6 3.5 5.8 7.4 3 3.1 3.2 7.8 2 9 .5 5.5 4.3 8.2-.8 8.2-4zm-2.4-17.2-24.2-.8c.4 6.2 6.3 5.8 9.4 3.5 2 2.7 5.9 2 7.8 0 2.7 3.1 7.8 1.2 7-2.7zm3.2-19.2h-26c0 4.3 5.8 6.6 10.1 2.7 1.2 5.1 5.9 3.5 7.9 1.6 3 3.9 9.7-.8 7.8-4zm-1.6-13-23.5.5c0 3.9 5.5 5.5 7.5 2.3 1.2 2 5 1.6 6.2 0 1.6 2.8 4 .8 4.7 0 2.8 2 5.5.8 5.1-2.7zm27 8.7-28.2-.4c0 2.7 2.8 4 4.7 2.7 0 3.2 4 4 6.7 1.6 1.5 2.7 6.6 3.1 8.6 0 3.9 3.5 8.6.8 7.8-4zm-.4 23h-27.4c0 4 4.3 5.1 7 3.2.5 3.1 4 3.5 6 1.6 2.7 2.7 6.6 3 9 0 3 1.1 5.8-1.6 5.4-4.7zm-1.6 20.8h-21.9c0 3.9 4.7 3.9 6.7 2 2.3 2.7 5.5 2.7 7.4.7 2.7 2.4 7.4 1.6 7.8-2.7z"/>
|
||||
<path stroke="#000" stroke-width=".4" d="M502.5 292c-11.7 0-23.8 0-32-.9-8.2-.7-10.6-2.3-16.4-5.8L432 272c-1.9-.8-3.8.4-1.1 2l21.9 14.4a60 60 0 0 1 13.3 11.7c4.7 5.1 7.8 5.1 10.1 4.3 2.4-.7 5.5-2 9-1.1 3.2.7 7.8 1.1 10.2.7 2 2 7 1.6 9.8.8 2.7-.8 4.7-.8 6.6-.4h6.7c2 0 7-1.1 10.5-.7 4 .7 7.4 0 9.8 0a19.5 19.6 0 0 1 7.8-.4c2.4-1.6 3.1-3.6 4-5.5 2.3-.4 3-.8 3.4-2l2.4-6.2h.8v-2.4l-1.6-2.3.8-4 2-.7-.8-4-34.4.9a7.8 7.8 0 0 0-2.4 4.3l-10.2 1.5c-1.1.4-2.3.4-3.5 2z"/>
|
||||
<path stroke="#000" stroke-width=".4" d="m543.6 276.7 5-19.2c.8-2-1.1-2.3-1.9 0l-5 19.2z"/>
|
||||
<path fill="#fff" stroke="#000" stroke-width=".4" d="M563.5 255.2c-4.3 2-6.6 3.1-8.6 2.3-2-.8-4.3-1.2-5.8-.4a2 2 0 0 1 0 .4 1928.6 1928.8 0 0 1-4.3 14.9c3 1.2 8.6 1.2 9.7 0 1.6-1.6 5.1-1.2 7-1.2 1.2-1.6 1.6-3.5 1.2-4.3-.4-.8 0-2.7 0-4 0-1 1.6-5.4.8-7.7z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".4" d="M465 218.4a208 208 0 0 1-31.3 54.8m7.8 4.7a213 213.1 0 0 0 44.6-49.3m-27.4 16.8c-1.1 10.6-4.3 29.3-5.8 39.1m10.1-15.6c-3.9 3.9-9 10.1-13.2 13.6m49.6-34.8c-3.1 3.2-6.6 7-10.2 7.9m12.2-7a27.4 27.4 0 0 0 10.5 7.4m-12.5-24.3a33.2 33.2 0 0 1-11.7 6.7M501 232c2.3 2.3 5 5 8.6 6.7m-21.1-19.2a27.4 27.4 0 0 0 10.5-5.9m1.2 0a30 30 0 0 0 10.5 6.3m-21.5-13a15.6 15.6 0 0 0 9.4-5.4m1.2-.8c2.7 2.4 7.8 5.5 10.6 5.9m12.5 3.1c-1.6 2-5.9 5.1-8.6 5.1m10.5-5c1.2 1.9 4.3 5 6.3 5m-18.8 23.5a28.1 28.2 0 0 0 11-7.5m2 .4a21.9 21.9 0 0 0 7.3 7m-16 20.4c1.6 0 5.9-2.4 7-5m2.4-1.3a27.4 27.4 0 0 0 7.8 6.7m-73.1 3.5c5-1.6 14.9-7.8 20-13.7m-9.4 7.4c3.9 2.8 9 6 12.5 6.7m-24.3-17.6a31.3 31.3 0 0 0 9.4-5.9m2-.4c1.1 1.6 9.3 6.7 12.9 6.7m-14.9-23a38.3 38.3 0 0 1-9.8 5.4m11.8-5.5c2.7 2 8.6 5.5 12 5.5M469 207c-2.3 2.3-6.2 6.2-9.4 7.4m11.4-7c1.5 2.7 6.2 6.6 9.3 7m31.3 10.2c7.5 12.9 20.7 29 34 37.5m-55-52c10.9 15.6 32 49.7 52.3 62.2m4-13.3a72 72 0 0 1-19.2 18m17.5-13.7c-6.6-11-10.1-24.6-15.6-43m-54.7 48.5 7.8 23.4m-9.4-23.8 7.4 23.4m-9.3-24.6 7 24.2m-7.8-23.8 5.4 23.8m0-.7h6.7m-.8-2.4h-6.2m5.4-2h-6.2m5.4-1.9H474m5-2.3h-5m-.4-2h5m-5.4-1.6h5m-5.4-2h4.7m-5-1.5h4.2m-4.7-2h4m-4.4-1.5h4m-4.3-1.2h3.9m-4-1.5h3.6m-10.2 0-4.7 19.5m5.9-19.5-4 20.3M467 268l-3.2 21.5m4.7-22-2.3 22.8m2.7-1.6h-7.8m7.8-2h-9m9-2.3h-8.2m7.8-2h-7.4m7.8-2h-7.4m7.4-2.3h-6.6m6.6-2h-6.6m6.2-1.9h-5.8m5.8-2h-5m5-1.9h-4.7m4.7-1.2h-4.3m4 21.6v-23.1m25.3-7.8L478 291.5m16.8-32-13.3 32.4m14.1-32.8L485 291.9m11.8-32-8.6 32m.4-1.1h-9.8m10.5-3.2H480m9.7-2.3h-7.8m9.4-2.4h-7.8m8.2-2.3h-7.4m8.2-2.4h-7m7.7-2.7H487m6.6-2h-5.8m6.6-2.3h-5.5m6-1.6h-5.2m5.5-1.5h-5.5m5.1-1.6h-3.9m4-1.2h-3.6m3.9-1.5H492m3.9-1.6h-3.1m3-1.2h-2.7m13.3-.4 6.7 22m-5.5-21.6 8.2 21.2m-7-21.2 9.8 20.8m2.3-2-11-19.2m11 19.6h-7.8m7-3.1h-7.8m6.7-2.4h-7.5m5.9-2.7h-6.7m5.1-2.4H510m4.3-2.7h-5.1m3.9-2.7h-4.7m3.1-2.4h-3.9m12.5.4-7 20.3m9-21-6.3 20.7m2.8-.4 4.7-19.6m1.1.8-3.9 18.4m-6.6-1.2h6.6m-5.8-2.3h6.6m-5.9-2.8h6.3m-5-2.3h5.8m-5.1-2.8h5.5m-4.7-2.3h5m-3.9-2.8h4.7m-3.9-2.3h4m3.5.4 3 14m-1.9-14.8 4.3 14.5m-2.7-14.5 4.7 14.5m-2.8-13.7 5.1 13.7m-.4-1.2h-6.6m5.9-2h-6.3m5.5-1.9h-5.9m5-2.4h-5.8m4.7-2H528m4.7-1.9h-5m4.3-2h-4.7"/>
|
||||
<path fill="#00b800" d="M467.6 299.2c3.1-2 8.5-1.7 11.3.4 3.3-1.8 9.2-1.3 11.9 1.2 4.2-3 7.7-3.4 11.7-.6a10.5 10.5 0 0 1 11.9.2c3.7-1.7 7.7-3.1 11.2.6a9.3 9.3 0 0 0-11.3.7c-3.5-3.5-9.7-2.2-11.8.3a7.7 7.7 0 0 0-11.5.2c-3.7-3-9.1-3.2-12-1a13 13 0 0 0-11.4-2z"/>
|
||||
<path fill="#cf6200" d="M523.1 294.8c-16.1 2.8-51.4 1-59-1.1-2.7-.6-2-1.6.3-1 8.9 2 27.9 2 38.3 1.4l6.2-8.5c1-1.3 1.4-1.4 3.5-1.7l8.7-1.5v1.2c-.2.3-.4.6-.7.7 0 2 .4 7.1.9 9l1.1-.3c.7-.2 1.4 1.7.7 1.8z"/>
|
||||
<path fill="#cf6200" d="M549.6 295.6h2.2c.6 0 1.6-.5 1.9-1.5l2.2-6.3-1.7-2.5.9-5.3 2-.9c.2-.3 0-1.6-.4-2l-31.6 1c-1 0-1.4 0-1.7 1.3a23.5 23.5 0 0 0 8 23.2c.5.4 1.2 0 .3-.7a26 26 0 0 1-4.3-5.7h5.2c.4 1.7 1.7 5.2 2 5.9.2.7.8.7.4-.3-.6-2-1-4.5-1.3-5.7h5.3l.4 5.2c0 .7.6.7.6-.1V296l4.8-.2-.4 5.2c-.1.9.3 1.2.5 0l.7-5.2 3.3-.2c0 1.2-1.1 4.4-1.4 5.2-.3 1 .2 1 .5.1a30.5 30.5 0 0 0 1.6-5.2z"/>
|
||||
<path d="M526.5 294.8c-.5-1.1-2.3-5.1-2.4-8h7c.2 2.1.8 6.8 1.2 7.9zm5.8-8.2c.1 1.8 1 7.5 1.2 8h5.6l-.4-8.1zm-7.9-7a33.1 33.1 0 0 0-.2 6l6.7-.3-.6-5.9zm7.3-.2.4 6 6.6-.2-.3-6zm8-.3.2 6 5.7-.1c0-1.3.3-5.2.2-6.1zm7.2-.2-.2 6 6.2-.2c.3-1.3.9-4.7.9-6zm6.3 7.2-6.6.2-.6 8 6.3-.2a53.7 53.7 0 0 0 2.3-6c-.5-1-.9-1.3-1.4-2zm-13.3.4.2 8 4.8-.2.6-8zm-27-1.6-2.6.4a196 196 0 0 1-6.3 8.8l9.3-.2-.3-9zm1.2-.3.4 9.2 5.6-.4-1-9.6z"/>
|
||||
<path stroke="#000" stroke-width=".4" d="M486.9 263h-30.1v-.8l30 .4zm23.5-24.2c.3 0 .3 0 0 0l-23.5-.4c-.4 0-.4 0 0 0h23.5zm-25 6.6c.3 0 .3.4 0 .4h-26.7c-.3 0 0-.4 0-.4zm.7-17.2c.4 0 .4.4 0 .4h-27.7c-.4 0-.4-.4 0-.4zm-2-13.7c.4 0 .4.4 0 .4h-27c-.3 0 0-.8 0-.8l27.4.4z"/>
|
||||
<path fill="#fff" stroke="#000" stroke-width=".4" d="m512.3 206.7-23.5.4z"/>
|
||||
<path stroke="#000" stroke-width=".4" d="M513.5 220c.4 0 .4 0 0 0H488c-.4 0-.4 0 0 0zm25.4 18v.4h-27.4c-.8 0-.8 0 0 0H539zm0-23.1c.8 0 .8.4 0 .4H511c-.4 0-.4-.4 0-.4h28.2zM513 255.6c.4 0 .4.4 0 .4h-25v-.4zm24.2 3.5c.4 0 .4 0 0 0h-21.9z"/>
|
||||
<path fill="#ef072d" stroke="#000" stroke-width=".4" d="M557.3 263a11.7 11.7 0 0 0 0-5.5 4.3 4.3 0 0 1-2.4 0 11.7 11.7 0 0 0-1.2-.8 25 25 0 0 1-1.5 7.5c-1.2 0-4 0-5.1-.8l-1.2 3.9a13.7 13.7 0 0 0 5.9 0c0 2.3-.4 4.3-1.6 5.9 2 0 4 0 4.3-1.2 1.2-1.6 1.2-4 1.6-5.1l2-.4 1.9-.8 2.7-.4V263l.8-1.6-6.2 2z"/>
|
||||
<path stroke="#000" stroke-width=".4" d="M460.3 130.8c-3.1 0-10.2 0-11.7.8-1.2.8-1.6 1.2.8 1.6 2.3.4 6.6 2 9 3.1 2.3 1.6 3.9 4 3.9 7.8a23.5 23.5 0 0 0 11.7 24.7c.4.4.8.7.4 2.3l-1.2 4.3c0 .8-.4 1.6.8 1.2a78.2 78.2 0 0 1-4 6.2c-6.2-.7-11.6 0-11.6 7 0 .9 0 1.6.7 0 1.2-1.5 2.4-3 5.1-3.8-1.5 2.7-2.3 5-2 6.6 0 1.2.8 2 1.6 0 .4-1.6 2-3.1 3.2-4.3.7-.4.7-.4.3.8a6 6 0 0 0 1.2 4.3c.8.8 1.2.4.8-.8 0-1.6 0-4.3 2-5 2.3-1.6 4.6-.9 5.4.7 1.2 2 2 0 .8-1.6-1.2-1.5-2.3-3.5-3.9-3.5l4-6.6c0-.8.7-1.2 1.5-.8 0 .4.8.4 1.1-.8l2.8-5.5 2.3-.7 4 5.8v2.4c0 1.5-1.6 5-2 6.2-4.7 0-7 0-8.6 2.8-.8 1.1.4 1.5 1.5 1.1a7.8 7.8 0 0 1 4-1.1c.7 0 1.1.7 0 1.1-2.8 1.2-4.7 3.2-4.7 5.9 0 .8.7 1.2 1.1 0a9 9 0 0 1 5.1-4c0 2 .4 5.2 2 6 1.1.7 1.1 0 .8-1.2-.8-2 0-4 1.1-5.1 2-2.3 6.7.8 7.9 1.6.7.7 1.5 1.1.7-1.2-.4-2.7-4.3-4-7.8-4.7l4.7-16.4c2 1.2 4-2 7-.8a83.4 83.4 0 0 1 14.9 8.6c1.6 1.2 2 .8 2.7 0 .8-.4 2 0 3.2 0 .7.4 1.5.8.4-1.6a28.1 28.2 0 0 0-9.4-10.1c3.1 0 7 0 7-.8s-4.7-2.4-6.6-2.4a12.9 12.9 0 0 0 6.2-3c.8-.9 0-1.3-3.1-1.3-8.2 0-12.5 0-16.8-2.3-7-4-11.4-8.6-14.9-10.2-1.5-1.1-2.7-3.5-3.9-5.4-2-6-2-9-7-11-5.1-2-11.8.4-14.5 3.1z"/>
|
||||
<path fill="#fff" stroke="#000" stroke-width=".4" d="M460.7 132.4h-6.6s-.8 0 0 0l5.8 1.6c1.2 0 .8 1.1 0 .7-.8-.3-1.5 0-.8.8 4 2.8 4.7 4 4 14.5l1.9 1.6c.8 0 .4.7 0 .3-.4-.3-2 0-.8.8s2 .8.8.8-2.3.8 0 .4c2 0 3.1.8 0 1.2-2.3 0-1.6.8 0 .8 2.7 0 2 .7 1.2.7s-1.2.8.8.8h2.7c.4 0 .8 0 0 .4-.8 0-.8.8.4.8 1.2 0 2 0 .8.4-.4 0-1.2.4 0 .8 2.7 0 3 .7 2.3 1.1-.8.4-1.2.4 0 .4s2.4.4 1.2.8c-.8 0-1.2.8 0 .8s2 .8 1.2 1.2c-.8.4-1.2.8 0 .8 1.1 0 1.5.3.7.7-.7.8-1.1.8-2 0 0-.7-.7-.7-.7 0l-.8-1.1c-.4-1.2-1.2-1.2-1.2 0 0 1.1-.7.4-1.5 0a12.9 12.9 0 0 0 15.6 3c.4 0 .8 0 1.2 1.3l2.3 4.3c.4.7 1.2 0 1.2-.8l2.4-6.7c0-1.1 1.5-2 1.1 1.2 1.2-.8 5.9-1.2 9.8 0a47.7 47.7 0 0 1 10.6 5.9 2.3 2.3 0 0 0 2 .4c1 0 1.5 0-.5-2s-1.1-2.7 0-2c1.2.8 2 .4.8-.7l-3.9-3.5c-.4 0-.4-.8-2.3-.8h-6c-.7 0-1.5 0 .9.8 2.3.7 6.6 3.9 7.8 4.6 1.2.8 1.6 2.4-.4.8a102 102 0 0 0-14-7.8c-10.6 1.2-19.2 2.4-25.5-4.3-3.1-3.5-3.1-11 2-14-.8-.9-.8-1.6-.4-1.6v-2.4c-.8-.4-1.6-1.2-1.6-2-1.2 0-2-1.9-3.9-1.1-2 .8-2.3 0-3.1-.4-.4-.8-.8-.8-2-.8s-2 0-2-.8c0-.7.8-.7 2.4 0 2.7 1.2 5 2 7-.7 1.6-2.4-.7-4.3-3.9-5.1-3.5-.8-5.8 2-7.4 3.1z"/>
|
||||
<path fill="#fff" stroke="#000" stroke-width=".4" d="M477.9 131.2a11 11 0 0 0-4-2.3c-1 0-1 .8-.7 1.2v2.3c.8.4 1.2 1.2 0 1.2-.8.8 0 3.5 1.2 2.7h.8s0 1.2.7 1.2c.8 0 0 .8 0 1.2h.8c.8 0 .4 1.5-.4 2 1.2 0 1.6 0 1.6.7.4.8 1.6 1.2 1.6 2.3 0 1.2 0 1.2-1.6.8-1.6-.4-1.6 0-2 .8-.3.8-.7 1.2 0 1.2.8 0 1.6.4.4.8-1.1.3-2.3 0-2.7 1.1 0 1.2 0 1.6.8 1.2l2.7-1.6 2 .4c.8.4 0 2-.8 1.2s-1.6 0-2 .4l-2 .8c-.7 0-1.5 0-1 2 0 5.4 4.2 9.3 12 9.3h13c-2.4-1.6-4-2.3-5.2-2.3H492c.4-.4 0-1.2-.4-1.2s-1.2-.8-2 0l-3.9 2c-.8 0-2 0-.8-.8l3.6-1.6c.7 0 .3-.8.3-.8s0-1.2 1.2-.8c2.4 1.6 5.9 3.6 7 3.6 1.2 0 1.6-.8.8-1.2-.7-.4-1.1-1.2-1.1-1.6 0-.4.4-.8 2 0 1.5 1.2 3.8 2 5 2.4 1.2.4 2 .4 0-.8l-9-6.7c-1.2-1.1-1.2 0-.8.8.4.8-1.1 1.2-2 .4-.7-.8-1.1-1.2 0-1.6 1.2-.3.9-.7-.3-2-1.6-1-2-1-1.6 0 .4 1.3.4 2-.8 1.7-1.1-.4-2.3-1.2-1.1-1.6.7-.8 2-1.2 0-2.4-2-1.1-.8 0-1.2.8-.4.8-1.6.8-2 0-.4-.8-1.1-1.1-.7-1.5.3-.4.3-.8 1.1 0 .8.7 1.6 0 .4-1.2-1.2-1.2-1.5-.8-1.2 0 .4.8-.7 1.6-2.3 0-.8-.4-.8-1.2 0-1.6.8 0 .8-.4 0-1.1-2.7-4.7-1.6-8.3-4.7-11.8z"/>
|
||||
<path fill="#cf6200" d="M478 132c-.2.4-.3.3-.8.7-.5.4-.7 1.5.3 1.4a2 2 0 0 0 1.4-.8 8.7 8.7 0 0 0-.8-1.3zm-3-2.6c-.9.8-1 1.2-.6 1.2.5 0 .3 0 0 .6-.4.5.6.8 1 .3.5-.4.5-.5.7 0 .1.5 1 0 1.3-.3-.7-.7-1.7-1.3-2.5-1.8zm-1.5 4.4c-1 .5-.7 3.2.9 2.4.5-.2.9 0 .9.3v.7a4.7 4.7 0 0 0 1.7-1.2c.9-1.2 0-1-1.4-1s-1.7-.3-.4-1.1c1.2-.8.3-1.2-1.3-1 .2.3.1.6-.4.9zm5.9 6c-.8-.9-.3-1.2.5-1.7a1 1 0 0 0 .4-.3l-.7-2.6c-.3.2-.8 1.1-1 1.5-.2.7-.4 1.1-1 1-.7-.3-1.3.4-1.4 1.1h.5c.2.1.3.6.2 1 1.9 0 2.2 1.1 2.5 2 .4 1 .7.9 1 .3.3-.6-.3-1.5-1-2.3z"/>
|
||||
<path fill="#ff0" d="M479.9 150.4c-.4.8-.4.7-1.5.7-1 .1-2.4.3-3 .9-.3.3-2.2.5-2.2 1.3 0 .9 0 1.5.8 1.6.8 0 1 .2.7.8-.4.6-.6 1.5.8 1.7 1.4 0 2.5-.3 2.8.4.4 1 0 2.1.3 2.7.2.5 1.2.7 2.7 1.2 1 .2 4.8.5 6 .3 1-.2.6-.8-.5-.8-1.2-.2-2-.4-2.3-1.2-.3-.9-.5-1.3.2-2 .6-.8 1.2-1.3.8-2.5-.3-1.1-1-2.5-2.3-2.9-1.3-.4-.9-2.3-2.3-2.4-.5 0-.8 0-1 .2z"/>
|
||||
<path fill="#cf6200" d="M473.3 161.4c1.2.2 2.1.5 1.2.8-.9.3-1.5.8-.3.9 1.2 0 2.3.6 1.3.8-1 .3-1 1 .1 1s1.7.4.9 1c-.9.4-1.4.7-2-.1-.5-.9-.8-1-.9-.5-.2.6-.5.2-.9-.7-.3-.8-1.2-1.2-1-.5.3.7-.6.9-1.5.5a11 11 0 0 0 2.9 2.4c1.2-.4 2.6 0 3 0 .6 0 2.1.4 3 .9.9.4 1.5-.4 1.1-1.3-.4-1-.4-.7-.8 0-.6.4-.6-.3-.6-1.4 0-.8-.6-.7-.7-.1-.2.5-.7-.4-.5-.9.3-.5 0-.8-.4-.6-.5.2-.5 0-.6-1-.1-1.1-.5-1-.6-.5-.1.4-.6-.2-1.3-1-.5-.6-1-.2-2.1.1z"/>
|
||||
<path fill="#ff0" d="M485.6 167.8c-5.5 2.2-9.5 1.2-12.5-.8 1.2-.4 2.6 0 3.1 0s2.1.4 2.9.9c.8.4 1.5-.4 1.1-1.3.7 1 1.3 1.6 2.2 1.5l3.2-.3zM473.8 142c-.4-1.2-.7-1.4-1.3-1.3-.6 0-.9-.1-1.6-.4-.6-.3-1.5 0-1.6 1.3-.2 1.3-1 1.8-2 2.6-1 .7-1.5 1.3-1.5 2.6 0 1.2-.3 1.4-1 2.4l-1.1 1.3 1.2.7c.8.4.5.9-.2.7-.7-.2-1.5.2-.2.4 1.2.3 1.7 1 .6 1-1.3-.3-2.6.8-.3.5 2.3-.2 3.1.9.5.9-2.7 0-1.7.9-.2.9 2.5 0 1.7.7 1 .7-.6 0-.9 1 .8.7l.6-1c.3-.8.5-3.1 1.5-3.8.9-.6 1.4-1.7 1.4-2.3 0-.6 1.5-3.7 2.3-4.4 1-.7 1.4-2.3 1-3.4z"/>
|
||||
<path fill="#cf6200" d="M471.8 142.2c-.9-.7-1.9-.2-1.9 1 0 1-.6 1.5-1.4 2a3.5 3.5 0 0 0-1.8 2.3c0 1 .2 1.5-.4 2.3-.7.7-.8 1.3-.4 1.8.6.4.6.4.7 1 .3.6 1.4 0 1.4-.7s.3-.7 1-1.1c.8-.4 2-2.4 1.7-2.9-.2-.5-1-1 0-1.7 1-.8 1.8-1 1.8-1.6 0-.8.2-1 .5-1.3.3-.3-.6-.7-1.2-1z"/>
|
||||
<path d="M471.8 141.2c-.6-.2-1 1.1-.1 1.3.9.2 1-.9 0-1.2zm-.1 1.7c-.7.1-1.5 1-.4 1 1.2-.2 1.6-1 .3-1zm-1.4 1.7c-.7.3-.5 1.3.5.6 1-.7 1.2-1.5-.5-.6zm-1 1.4c-.7.3-.7 1.3.4.6 1-.6 1.3-1.5-.4-.6z"/>
|
||||
<path d="M467.9 146.7c-.7.3-.3 1.2.7.6s1-1.5-.7-.6zm.8.9c-.8.3-.3 1.2.7.6s1-1.5-.8-.6z"/>
|
||||
<path d="M467.4 147.9c-.6.4-.2 1.2.9.6 1-.6.9-1.5-.9-.6zm.9 1c-.8.3-.4 1.2.7.6 1-.7 1-1.5-.8-.6z"/>
|
||||
<path d="M467 149.5c-.6.3-.2 1.2.9.6 1-.6.8-1.5-.8-.6z"/>
|
||||
<path d="M467 150.3c-.5.4-.1 1.4 1 .7 1-.7.8-1.5-1-.7z"/>
|
||||
<path fill="#cf6200" d="M466.6 158.9c-.7 0-1.2 1.1-.3 1.3.9.2 1.1.3 1.1.9 0 .6.3 1.7 1.2 1.7 1 0 1.8-1 1-1.3-.9-.3-1.6-.6-1.7-1.4 0-.7-.8-1.2-1.3-1.2z"/>
|
||||
<path fill="#ff0" d="m491.5 153 .5.6c.7.5 2 0 1.7-.5-.1-.4-.8-2 1-.8l9.2 6.5c1.9 1.4.6 1.6-.2 1.1l-5-2.3c-1.5-.9-1.7-.5-2-.3 0 .3 0 .9.6 1.4-.9.1-2.3 0-2.8-1-.5-1.2-1.7-2.6-2.6-3.7-.3-.4-.4-.7-.3-.9z"/>
|
||||
<path fill="#00d860" d="M542 319.5c-1.3.9-3 2.4-1.9 4.5l.4-.1a124.1 124.1 0 0 0 12.9-19v-.6a17.9 17.9 0 0 1-4.5 2.7c.6 1.7-2.3 3.8-3.7 4.4.6 1 .4 2.6-1 2.9.3.8-.7.8-2 1.4-1.1.5-1.7.8-2.1 1.5.6-.4 1.6-.7 2-.5.4.2.6.9-.3 1.1-.8.3-1.4.7-1.8 1 1.3-.3 3.2-.2 2 .7z"/>
|
||||
<path stroke="#000" stroke-width=".4" d="M481.8 151.2c-1.6-1.2-2-.4-1.6 0 .4.4 0 1.5-1.1 2h-4c-.7 0-1.9 1.5 0 1l6.3-1c.8 0 1.6-.9 0-2zm2.7 2.3c-1.1-1.2-1.5-.8-1.1 0 .4.8-.4 1.2-1.2 1.2l-5.5 1.5c-1.5 0-1.5 1.2.4 1.2 2 0 5.9-2 6.3-2 .4 0 .8-1.1 1.1-.7.4.4 1.2 0 0-1.2zm1.2 3.1-3.9 2c-1.2 0-2 1.2 0 1.2s4-2 4.7-2.4l1.6-.8s1.5-.4 0-1.5c-1.6-1.2-3.2 0-2.4.4.8.4 0 1.1 0 1.1z"/>
|
||||
<path d="M469.7 131.2c-2.5-1.7-5.2 1.7-2.5 3.6 2.4 1.7 5-2 2.6-3.6z"/>
|
||||
<path fill="#fff" d="M466.6 132.7h.7c0 .8.7 2 1.8 1.7-.9.7-2.6-.2-2.5-1.7zm9.6 37c.8.3 3.4.5 4.4.5l-1.2 2.2c-.3.7-.4.8-.5-.3 0-1-.6-1.7-1.1-.6l-1 2c-.3.4-.7.5-.6-.6.2-1.1.1-2.3 0-3.2z"/>
|
||||
<path fill="none" stroke="#000" stroke-width="1.2" d="M574.5 199.7c0 63.7-10.2 132.5-93 165.3-82.6-32.8-92.7-101.6-93.1-165.3zm0 0c0-24.3-1.2-47.8-.8-68a248.7 248.7 0 0 0-92.3-16.9c-20.7 0-61.4 3.1-92.2 16.8.7 20.3-.8 43.8-.8 68z"/>
|
||||
<path fill="#012169" d="M0 0h320v240H0Z"/>
|
||||
<path fill="#fff" d="m37.5 0 122 90.5L281 0h39v31l-120 89.5 120 89V240h-40l-120-89.5L40.5 240H0v-30l119.5-89L0 32V0Z"/>
|
||||
<path fill="#c8102e" d="M212 140.5 320 220v20l-135.5-99.5Zm-92 10 3 17.5-96 72H0ZM320 0v1.5l-124.5 94 1-22L295 0ZM0 0l119.5 88h-30L0 21Z"/>
|
||||
<path fill="#fff" d="M120.5 0v240h80V0ZM0 80v80h320V80Z"/>
|
||||
<path fill="#c8102e" d="M0 96.5v48h320v-48zM136.5 0v240h48V0Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 30 KiB |
@@ -1,150 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="flag-icons-ad" viewBox="0 0 640 480">
|
||||
<path fill="#d0103a" d="M0 0h640v480H0z"/>
|
||||
<path fill="#fedf00" d="M0 0h435.2v480H0z"/>
|
||||
<path fill="#0018a8" d="M0 0h204.8v480H0z"/>
|
||||
<path fill="#c7b37f" d="M300.4 136.6c7.7 0 10.9 6.6 18.6 6.6 4.7 0 7.5-1.5 11.7-3.9 2.9-1.6 4.7-2.5 8-2.5 3.4 0 5.5 1 7.3 4 1 1.6 1.8 4.9 1.3 6.7a40 40 0 0 1-2.7 8.3c-.7 1.6-1.3 2.5-1.3 4.2 0 4.1 5.6 5.5 9.4 5.6.8 0 7.7 0 12-4.2-2.3-.1-4.9-2-4.9-4.3 0-2.6 1.8-4.3 4.3-5.1.5-.1 1.3.3 1.7 0 .7-.3.4-1 1-1.4 1.2-1 2-1.6 3.6-1.6 1 0 1.6.1 2.5.7.4.4.6.8 1 .8 1.2 0 1.8-.8 3-.8a5 5 0 0 1 2.3.6c.6.3.6 1.5 1.4 1.5.4 0 2.4-.9 3.5-.9 2.2 0 3.4.8 4.8 2.5.4.5.6 1.4 1 1.4a6.2 6.2 0 0 1 4.8 3c.3.4.7 1.4 1.1 1.5.6.3 1 .2 1.7.7a6 6 0 0 1 2.8 4.8c0 .7-.3 1.6-.5 2.2-1.8 6.5-6.3 8.6-10.8 14.3-2 2.4-3.5 4.3-3.5 7.4 0 .7 1 2.1 1.3 2.7-.2-1.4.5-3.2 2-3.3a4 4 0 0 1 4 3.6 4.5 4.5 0 0 1-.3 1.8 9.6 9.6 0 0 1 4-1.4h1.9c3.3 0 7 1.9 9.3 3.8a21 21 0 0 1 7.3 16.8c-.8 5.2-.3 14.8-13.8 18.6 2.5 1 4.2 3 4.2 5.2a4.5 4.5 0 0 1-4.4 4.7 4.4 4.4 0 0 1-3.5-1.4c-2.8 2.8-3.3 5.7-3.3 9.7 0 2.4.4 3.8 1.4 6 1 2.2 1.8 3.5 3.7 5.1 1-1.5 2.1-2.6 4-2.6 1.7 0 3.2.6 3.9 2.2.2.5 0 .9.3 1.4.3.6.8.7 1.1 1.3.5 1 0 1.8.5 2.7.3.7.9.8 1.2 1.4.4 1 .5 1.6.5 2.7 0 3-2.7 5.2-5.7 5.2-1 0-1.4-.4-2.3-.3 1.7 1.7 3 2.5 4.3 4.5a17.7 17.7 0 0 1 3 10.3 22 22 0 0 1-2.8 11.2 20 20 0 0 1-7 8.5 35 35 0 0 1-16 6.4 74.4 74.4 0 0 1-11 1.4l-14.1.8c-7.2.4-12.2 1.5-17.3 6.6 2.4 1.7 4 3.5 4 6.4 0 3-1.8 5.3-4.7 6.2-.7.2-1.2 0-1.9.4s-.7 1.3-1.4 1.7a6.2 6.2 0 0 1-3.8 1 8 8 0 0 1-6.4-2.5c-2.2 1.8-3 3.4-5.5 4.9-.8.4-1.2 1-2.1 1-1.5 0-2.2-1-3.4-1.8a23 23 0 0 1-4.4-4c-2.3 1.3-3.6 2.4-6.3 2.4a7 7 0 0 1-4-1c-.6-.5-.8-1.2-1.5-1.6-.7-.5-1.3-.3-2.1-.7-3-1.3-5-3.5-5-6.8 0-2.9 1.8-4.7 4.4-6-5-5-10-5.8-17-6.2l-14-.8c-4.4-.3-6.8-.7-11-1.4-3.3-.5-5.2-.7-8.2-2.1-10.2-4.8-16.8-11.3-18-22.5-.2-1-.2-1.5-.2-2.5 0-5.8 2.3-9.4 6.4-13.5-1-.3-1.7 0-2.8-.3-2.5-1-4.4-2.7-4.4-5.5 0-1 0-1.7.5-2.6.4-.6 1-.7 1.2-1.4.2-1 0-1.6.4-2.5.3-.5.8-.6 1-1.2 1-1.9 2-3.4 4.1-3.4 1.8 0 3 1 3.8 2.5 1.8-.8 2.2-2.1 3.2-3.7a15.5 15.5 0 0 0 1.4-13.3c-.4-1.5-.6-2.5-1.8-3.7-1 1-2 1.4-3.4 1.4-2.9 0-5-2.5-5-5.3a4.8 4.8 0 0 1 3-4.6c-1.6-1.4-3-1.5-4.7-2.6-2.6-1.6-3.5-3.4-5.2-6-1.2-1.6-1.5-2.8-2-4.7a19 19 0 0 1-1-7.8c.6-5 1.5-8 4.6-11.9 1.8-2.3 3-3.7 5.8-4.9 2.3-1 3.7-1.7 6.2-1.7l2 .1a6.9 6.9 0 0 1 2.8.8c.4.2 1.1.9 1.1.4s-.3-.8-.3-1.3c0-2 1.5-4 3.6-4 1.5 0 2.1 1.4 2.9 2.7.4-.8.7-1.4.7-2.3 0-3.4-1.9-5.2-4-7.9-4.7-5.8-10.5-8.5-10.5-16 0-2.2 1-3.7 3-4.9.5-.3 1.3 0 1.8-.3s.4-1 .7-1.4c.5-.7 1-1 1.6-1.6 1-1 2-.6 3.1-1.5.6-.4.8-1 1.2-1.4 1.3-1.6 2.5-2.4 4.6-2.4 1 0 1.6 0 2.5.4l1 .5c.3-.2.8-.8 1.5-1.1a4 4 0 0 1 2.2-.6c1.1 0 1.8.6 3 .6.3 0 .4-.4.8-.6 1-.7 1.5-1 2.7-1 1.2 0 1.8.3 2.8 1 1 .5 1 1.3 2 1.8.5.3 1 .2 1.5.4 2.6.9 4.5 2.6 4.5 5.3 0 1.5-.3 2.5-1.4 3.5-.9.7-1.7.6-2.8 1a16 16 0 0 0 11.3 3.5c4.2 0 9.3-1.7 9.3-5.9 0-2-1-3-1.8-4.8a18.8 18.8 0 0 1-2.1-8.5c0-2.8.3-4.5 1.9-6.7 1.6-2.3 3.6-2.9 6.5-2.9z"/>
|
||||
<g fill="none" stroke="#703d29">
|
||||
<path stroke-linejoin="round" stroke-width=".7" d="M272.4 159a3.6 3.6 0 0 0 2.4 2.4c.8.3 2.7.2 3.8-1.4 1-1.2 1-2.8.6-4a4.7 4.7 0 0 0-1.7-2.2l-5.1 5.2z"/>
|
||||
<path stroke-linecap="round" stroke-width=".7" d="M401 236.1c-1.2-2.9-4.3-1.6-4.4 0-.5 3.7 2.7 4.8 5 4.2a4 4 0 0 0 2.5-2c.6-1 .8-2.4.4-3.7a4.9 4.9 0 0 0-.8-1.6 5 5 0 0 0-1.3-1.2c-.9-.6-1.9-.6-3.4-.6-5.5 0-10.4 6.5-12 13.4-.6 2.2-1.3 7.3-.3 12a22.4 22.4 0 0 0 5.9 11.3 25.7 25.7 0 0 0 9.9 5.8 7.9 7.9 0 0 0 4 .1c3.2-.7 4.7-3.8 3-7-1.3-2.5-5.3-4-7.2-.6-.1.3-.4.9-.4 1.5 0 .9.4 2 1 2.4 1.5.9 3.8.6 3.7-2"/>
|
||||
<path stroke-width=".8" d="M383.8 274a11.3 11.3 0 0 1 6.6-3.7c3-.4 5.6.5 8.2 2a18.5 18.5 0 0 1 10.8 17c0 3.6-1 7.5-2 9.4-.8 1.7-3 9-15.3 14-7.1 3-18 3.6-25.7 4-10.4.3-20 .7-25.5 7.6"/>
|
||||
<g stroke-width=".7">
|
||||
<path d="M386.4 285.7c-.3-1 0-2.1.8-3.3 1.2-1.6 3.7-2.1 6-1a7.4 7.4 0 0 1 2.5 2.2l1.1 1.6c.7 1.1 1 2 1 2.5 2.5 7-1.4 14.5-6.5 17.6-4 2.4-8.7 3.4-14.4 4-2.5.4-4 .3-6.5.5h-9.6a70.1 70.1 0 0 0-7.2 0c-2.9.3-5 .4-7.6.8-1.6.2-3.4.5-5.4 1-.6 0-1.2.2-1.8.4l-1.2.3c-3.6 1.1-7 2.4-9.8 4.2-.8.5-1.8 1-2.5 1.7l-1.3 1.2c-2 2-3.9 4-4.4 6.7v1.6c0 1.8 1.4 4.3 5.4 5m5.5-170c.8 1.4 1.3 2.3.8 3.9-.6 1.7-1.8 2.8-3.6 2.8-4 0-6.3-4.8-4.5-7.8 3.2-5.3 9.3-2.3 15 .3-.3-1.3-.8-1.8-.7-3.5.1-4.2 3.2-6 4.5-10 .7-2.3 1-4.3-.7-6-1.5-1.3-3.2-1.3-5.1-.6-3.8 1.5-8.5 5.9-16.6 6-8.2-.1-12.8-4.5-16.7-6-2-.7-3.6-.7-5.1.7-1.7 1.6-1.4 3.6-.7 6 1.3 3.8 4.4 5.7 4.5 10 0 1.6-.4 2-.7 3.4 5.7-2.6 12-5.9 15-.3 1.7 3.2-.5 7.7-4.5 7.7-1.8 0-3-1-3.6-2.7-.4-1.5 0-2.8.8-4"/>
|
||||
<path stroke-linecap="round" d="M314.6 159.9a5.3 5.3 0 0 1 2.4 5c-.2 2.5-.8 3.1-2.8 4.5m2.4-3.8c-.1 1.5-.7 2.5-2.3 3.1"/>
|
||||
</g>
|
||||
<path fill="#c7b37f" stroke="none" d="m276.7 153.3.7.5.8.8.5 1 .2.8v1.9l-.2.8-.5.6-.6.6-.9.5-1 .2-1 .2-1-.5-.9-.6-.5-.8-.4-1v-.4l4.8-4.6z"/>
|
||||
<path stroke-linecap="round" stroke-width=".7" d="M275.2 157.2c-.3-1.7-2.2-2-3-1-1.1 1.5-.3 4 2 4.7a4 4 0 0 0 3.9-1.4c1-1.3.9-2.8.5-4a4.5 4.5 0 0 0-1.7-2.2c-2.7-2-7.1-1.6-8.6 2-1.8 4.4 2.2 7.8 6 10.3 4.6 3.2 10 3.8 14 3.8 9.2-.1 16.2-4.5 20.7-7 1-.6 2.1-.5 2.7.2a2 2 0 0 1-.3 2.7"/>
|
||||
<path stroke-width=".7" d="m248 281.2-2 .7-2 1.6-1 1.3-1.1 2-.5 1.5-.4 1.8-.2 1.4m19-10.1-.1 1.8-.3 1.2-1 2.2-1.3 1.8-1.5 1.2-1.1.5-1.6.4"/>
|
||||
<path stroke-width=".8" d="M319.7 329.1c-.3 1.7-1.9 3.6-5.3 4.2l-.6.2"/>
|
||||
<path stroke-width=".9" d="M404.2 276.2a18.3 18.3 0 0 1 5.6 13.5c0 3.6-1 7.5-2 9.4-.8 1.7-3 9-15.3 14a85 85 0 0 1-25.6 4c-10.3.3-19.8.7-25.4 7.3"/>
|
||||
<path stroke-width=".6" d="M387.5 282.9c.8-1 3.5-2.4 5.8-1.1a6.2 6.2 0 0 1 2.3 2"/>
|
||||
<path stroke-width=".9" d="m401.6 273.8 1.4.5a7 7 0 0 0 4 0c2.8-.8 4.6-3.4 3.2-6.9a6 6 0 0 0-1.8-2.1"/>
|
||||
<path stroke-linecap="round" stroke-width=".7" d="M240.3 199.8c-2 1.1-3.3 1.4-4.8 3.1a28.1 28.1 0 0 0-2.6 6.8m46-51.7c0 1.8-1.2 2.8-3 3.2"/>
|
||||
<path stroke-width=".6" d="M397.1 192a19 19 0 0 1 18.6 19.8c0 16-9.9 18.5-13.8 19.6"/>
|
||||
<path stroke-width=".7" d="M398.4 192c8.1-.3 16.5 5.7 16.9 20.7.3 11.7-8 17-12 18"/>
|
||||
<path stroke-width=".6" d="m393.8 248.4.1-1.6.6-2.5.7-2 .9-1.6 1-1.3m7.8-3.4v1.5l-.5 1-.7 1.1-.8.6-1.2.5h-1.1l-.8-.1m-14.3-52.8.3-1.7.8-1.6 1-1.5 1.6-2.2 1.4-1.4 2-2.2 2-1.9 1.1-1.3 1.5-1.9 1.4-2 .8-1.7.5-2.2.1-2.7-.2-.8m-12.3 128.2 1.6-.4 1.2-.6.7-.7.5-.8.3-1.2v-.9m-158.2-12.1h2.7l1.6-.6m5-36.5-.2 1.4-.4.6-.4.6-.7.5-.7.3-1 .1h-.6m9.9-15.5-.3 2.1-.5 1-.8 1.2-1.2.9-1.2.6-2.3.5m15.3-39.7-.5 1.3-.5 1-.8 1-1 1-1.2.5-1.1.3-.6-.1m.3-6.2v1"/>
|
||||
<g stroke-width=".6">
|
||||
<path stroke-linecap="round" d="M254.3 224a6.9 6.9 0 0 1-2.1 1.4m150.5 44.8.5.2c1.4.8 4.2-.2 3.4-2.4"/>
|
||||
<path d="M397.8 239.6c1 1.3 2.9 1.7 4.4 1.3a4 4 0 0 0 2.5-2c.6-1 .8-2.4.4-3.7a4.9 4.9 0 0 0-.9-1.6 6.8 6.8 0 0 0-1.3-1.5l-.4-.2m6.4 34a4 4 0 0 0 .1-.7 4 4 0 0 0-1.3-3l-.8-.8m.4.5c0-1.8-1.5-3.2-3.4-3.5m-4.2 2.8-1.3-1a15.7 15.7 0 0 1-4.3-10.7c0-4.2 1.6-8.4 3.6-10M341.2 324l1.8-1.6 1.2-1 2.3-1.4 2.2-1 1.6-.5 3-.6 3.6-.6m-29.5 19.4a17 17 0 0 1-7.6 6.1 17.7 17.7 0 0 1-7.6-6.1"/>
|
||||
<path stroke-linecap="round" d="M314.4 332.6a10 10 0 0 1-2.2 4.2"/>
|
||||
<path d="m314.7 330.5-.4 2.2M312 337l-1 1-1.7.9-2 .6m-5.6-177.8c.3-.8.5-1.4.5-2.6-.1-4.2-3.2-6.1-4.5-10-.7-2.3-1-4.3.7-6 1.4-1.4 3.2-1.4 5-.6 4 1.5 8.6 5.8 16.7 6-8.1-.2-12.8-4.5-16.6-6-2-.8-3.8-1-5.3.5-1.7 1.6-1.2 3.8-.5 6.1 1.3 3.9 4.2 5.8 4.3 10 0 1.2-.3 1.8-.5 2.6M320 148c8-.4 14.9-5.8 17.1-6.3 2-.4 3-.2 4.5 1.1-1.4-1.3-3-1.2-5-.5-3.8 1.5-8.4 5.8-16.6 6m79.6 112.9a15.5 15.5 0 0 1-6.2-12.4c0-4.1 1.7-8.4 3.6-10m-70 97.6c-1.3 2-4.3 5-7.6 6.2a17.7 17.7 0 0 1-7.6-6.2"/>
|
||||
<path stroke-linecap="round" d="m306.7 163.7 2.3-1.3c1-.6 2.3-.5 2.9.2.6.7.7 2-.2 2.8"/>
|
||||
<path d="M294.7 169.3c5.5-1.2 10-3.6 13.4-5.5M340.3 328c.5.3.8 1 .8 1 .1.2.3.5.3.8.3 1.5-.7 2.4-2 2.6-1.7.2-3-.8-3.5-2M294.4 169c5.5-1.1 10-3.6 13.4-5.5m97.6 106.9c-1 .4-1.6.3-3-.2l-1.8-1a20.7 20.7 0 0 1-8.4-9 18.8 18.8 0 0 1-1.7-4.6 12 12 0 0 1-.5-3.3 25.6 25.6 0 0 1 4.7-15.3c1.1-1.6 2.1-2.5 4.2-2.6m-143.7-39.3a7.1 7.1 0 0 1 2.7 5.7c0 3.1-2.6 8.2-9 10a8.3 8.3 0 0 1-6.3-.8"/>
|
||||
<path d="M256.3 205.6c1.1.8 1.6 1.7 1.6 3.3 0 1-.7 2.4-1.9 3.7a12.4 12.4 0 0 1-8.8 4c-2 0-4-.4-6-1.7a9 9 0 0 1-3.8-5.4"/>
|
||||
<path d="M256.2 212.3c1.3 1.2 1.7 2.7 1.7 4.6 0 2.7-1.1 4.8-3.7 7-.6.6-1.2 1-2 1.5m129.5-22.1v3.5m-.3-4.4v5m.3-15.8v6.6m-.3-8v8.9m-1.9 82a18.7 18.7 0 0 1-4.2 5.6 19.6 19.6 0 0 1-5.8 4.1 24.6 24.6 0 0 1-6.6 2.2 33 33 0 0 1-6.8.9c-2.5 0-3.9 0-6.4-.2-2.6-.2-4-.6-6.7-.8-2.2-.2-3.4-.4-5.6-.3a28.3 28.3 0 0 0-11 1.8c-2.6 1-5.7 3-6.3 3.8a22 22 0 0 0-6.4-3.8 22 22 0 0 0-5.1-1.4c-2.3-.4-3.5-.4-5.8-.4-2.2 0-3.4.1-5.6.3-2.6.3-4 .6-6.7.8-2.5.2-3.9.3-6.4.2a33 33 0 0 1-13.4-3 19.5 19.5 0 0 1-6.4-4.8m42.1 53.4 1.8-.2m30.3-2.4 1.8-.1 1.7-.7 1.2-.8 1.7-2 .3-.6.3-1.7v-.8m47-136.7c.7-2.6-.2-5.4-2.8-5.3m-132 46.5a8.2 8.2 0 0 1-3.5 4.7m3.6-46.7a6.5 6.5 0 0 1-3.6 4c-1.9.8-4 0-5.2-.8"/>
|
||||
<path stroke-linecap="round" d="M243.8 202.4c1.5.8 3.1-.4 2.8-2.4a2.9 2.9 0 0 0-2.5-2.2"/>
|
||||
<path d="M250.2 286.6c.3.3.4.7.8.8.7.2 1.2.4 1.9-.5.8-1.1.3-2.8-.5-3.9a5 5 0 0 0-5.8-1c-.8.5-1.7 1-2.6 2.2l-1.1 1.6c-.7 1.1-1 2-1.1 2.4-2 5.9.4 12 4.1 15.7"/>
|
||||
<path stroke-linecap="round" d="m340.2 327.8.7.8.2.9c.3 1.5-.7 2.4-2 2.6-1.6.2-2.8-.8-3.3-2"/>
|
||||
<path d="M389.4 154.8a7.4 7.4 0 0 1 6.3 7c0 4.4-1.5 6-3.8 9.2-2.5 3.4-10.7 9.6-10.7 16.7 0 4.3 1.2 7 4.3 8.4 2 1 4.3 0 5.4-1 2.6-2.4 1.5-6.5-1.2-7-3.2-.6-3.9 4.6-.7 4.3m17.9 69a3.7 3.7 0 0 0-3.6-3 3.7 3.7 0 0 0-3.7 3.7c0 1 .4 2 1 2.6"/>
|
||||
<path d="M383.9 195.1a7.1 7.1 0 0 0-2.7 5.7c0 3.1 2.6 8.2 9 10 2.4.7 4.8.6 6.2-.3m-156-10.3a9.4 9.4 0 0 0-4.8 3.5 16.9 16.9 0 0 0-2.2 12.7 15.8 15.8 0 0 0 2.3 5.6 8 8 0 0 0 1 1.2l1.2 1m64 92c4.9 2.1 8.4 3.7 11.4 8.5a10 10 0 0 1 1.2 4.9c0 2.7-1 5.7-3.3 7.6a8.3 8.3 0 0 1-6.7 2c-1.9-.2-3.7-1.6-4-2.6M254 224.1c2.7 2.2 3.9 4.2 3.9 7.5a8.4 8.4 0 0 1-4 7.5"/>
|
||||
<path stroke-linecap="round" d="M251.5 236.4c4 5.1 6.3 8.1 6.4 14.1.1 5.7-1.7 9.6-5 13.7"/>
|
||||
<path d="M329.8 169.3a4.1 4.1 0 0 0 1.5-2.2c.5-1.5.5-2.8-.2-4 1 1.4 1 2.5.7 4-.1 1-.8 1.5-1.6 2.3m51.5 86.1v16.2l-.1 2.5a34.4 34.4 0 0 1-.3 1.7"/>
|
||||
<path d="M381.4 254v19.9l-.5 2.6m.5-43v14.6m.3-13.4v11.8m0-26.8v8.8m-.3-9.9v11m.3-19v3.5m-.3-4.2v5m-1.8 65.2-.4.7a18.7 18.7 0 0 1-4.1 5.7 19.6 19.6 0 0 1-5.9 4 24.6 24.6 0 0 1-6.5 2.2c-2.7.6-4.2.8-6.9.9-2.5 0-3.9 0-6.3-.2-2.7-.2-4.1-.5-6.8-.8-2.2-.2-3.4-.3-5.6-.3-2.2 0-3.5 0-5.7.4a22 22 0 0 0-5.2 1.4c-2.7 1.1-5.7 3-6.4 3.8-.6-.8-3.7-2.7-6.3-3.8a22 22 0 0 0-5.2-1.4c-2.2-.4-3.5-.4-5.8-.4-2.2 0-3.4.1-5.6.3-2.6.3-4 .6-6.7.8-2.5.2-3.9.3-6.3.2a33 33 0 0 1-13.5-3 19.5 19.5 0 0 1-5.8-4.1 22 22 0 0 1-2.5-2.8m-2-3.2a10.1 10.1 0 0 1-2.3 7.7c-.8.9-2.6 2.6-5 2.6-3.7 0-4.8-2.5-5-3.2"/>
|
||||
<path d="M255.6 278.9c.7.7 1.3 1.5 1.9 2.5 1 1.8.6 4.8-.1 6.2a4.4 4.4 0 0 1-.3.4m-20.3 18c2.3 2.4 5.7 5 10.9 7.1 7.1 3 18.1 3.6 25.7 4 10 .3 19.3.7 25 7m17.3-4a12 12 0 0 1 4 5.5m-7.3 11.5a8.2 8.2 0 0 1-.7.7 8.3 8.3 0 0 1-6.6 2c-2-.2-3.8-1.6-4.3-2.6m-5.4-2.9.3.4a7.6 7.6 0 0 0 5.1 2.4m27 0a18 18 0 0 1-7.7 6.1 17.7 17.7 0 0 1-7.6-6.1l-.3-.5m15.6.4.7.7a8.3 8.3 0 0 0 6.7 2 5.5 5.5 0 0 0 4-2.5l.5-.7"/>
|
||||
<path d="m339 336.6-.7 1.2-1.1 1-1.7.7h-1.6"/>
|
||||
<path d="M343 325.3a7.7 7.7 0 0 1 2.4 2.9c.3.7.4 1.5.5 2.3a5.8 5.8 0 0 1-1.5 4.2 7.5 7.5 0 0 1-5.4 2.4 5.5 5.5 0 0 1-.4 0m.2-.2a6.8 6.8 0 0 1-5.2-2.2m63.7-67.9a23.8 23.8 0 0 1-4.8-6.4 18.8 18.8 0 0 1-1.7-4.5 12 12 0 0 1-.5-3.3 26 26 0 0 1 4.6-15.3c.7-.8 1.4-1.8 2.1-2.2m-1.3-75.9c2.5.2 4.8 3 4.8 5.7 0 3.8-1.3 5.5-4.4 9.3-2.6 3.2-10.6 9-10.3 14.5 0 1 .5 2 1.1 2.8m-3.2 3.5a7 7 0 0 0 2 1.4 5 5 0 0 0 4.3-.3M369 153a6 6 0 0 1 2.2 2.6c1.8 4.5-2.2 7.9-6 10.4a21.3 21.3 0 0 1-8.3 3.3"/>
|
||||
<path d="M364.6 161.6a4.2 4.2 0 0 1-3.1-1.5 3.4 3.4 0 0 1-.7-1m-15 4.9a4.6 4.6 0 0 1-1.2-1c-1-1-1.5-2.3-.8-4.4.6-1.9 3.7-7.2 3.8-10.9.2-5.6-2-9-5.3-10.2"/>
|
||||
<path stroke-linecap="round" d="m347.3 146.5-.1 2-.6 2.2-1 3-1 1.9-.8 1.9-.4 1.3-.2 1 .1.9m38 126.3.6.8c.7 1 3.2 3 5.5 3 3.7 0 4.6-2.6 4.7-3.2.5-2.9-.5-3.6-2-4.5 0 0-.8-.4-1.9-.2"/>
|
||||
<path d="M237 274.4a6.9 6.9 0 0 1-3.7 0c-2.9-.9-5.2-3.6-4-7m13.4-31.8c.3.3.4.7.4 1 .4 3.8-2.8 4.8-5 4.2a5.6 5.6 0 0 1-3-2.3 4.7 4.7 0 0 1-.7-2.3m22-23.6c.6.5 1 1 1.3 1.7m-1.1-8.5c.5.4.9.9 1.1 1.3"/>
|
||||
<path stroke-linecap="round" d="M257.9 210.5a8.5 8.5 0 0 1-1.6 2.4 12.4 12.4 0 0 1-8.8 4c-2 0-4-.4-6-1.7a9.5 9.5 0 0 1-4-5.6"/>
|
||||
<path d="M255.4 195.3a7.8 7.8 0 0 1 2.4 3.4"/>
|
||||
<path stroke-linecap="round" d="M257.8 203.2c-.9 3-3.5 6.6-8.6 7.9-2.4.6-5.6-.2-6.6-1"/>
|
||||
<path d="M240 202.6c.3 2.6 2 4.6 5.4 4.6 4.7.1 7.6-6.7 3.4-11.5"/>
|
||||
<path stroke-linecap="round" d="M229.4 225.5c.7.9 1.5 1.7 2.4 2.4a16.8 16.8 0 0 0 6 3.3m5.2.5c4.2-.5 6.6-3.7 6-7.3-.3-2.8-2.8-5-4.6-5.1"/>
|
||||
<path d="M249.8 188.1c1.9 0 3 1.6 2.9 3"/>
|
||||
<path stroke-linecap="round" d="M249.4 163a11.5 11.5 0 0 0 5 5.9m144.2 31c1.7 2.3.6 7-4 7a5.2 5.2 0 0 1-4.5-2.5"/>
|
||||
<path d="M381.7 169.1V185"/>
|
||||
<path stroke-linecap="round" d="M243.8 202.3c1.4 1 3.3-.7 2.5-2.6-.5-1.2-2.2-2.6-4.7-.9-2.8 1.9-2 7.8 3.2 7.9 4.7 0 7.6-6.8 3.4-11.6-4-4.6-11.3-3.6-16 .2A21.4 21.4 0 0 0 225 207a22.5 22.5 0 0 0 0 9.2 20.9 20.9 0 0 0 3 7.5l1.3 1.7c.8.8 1 1.2 2 2a15 15 0 0 0 10.4 3.7c4.6-.2 7.3-3.4 6.8-7.3-.4-3.8-4.2-5.7-6.7-3.9-1.7 1.2-2.3 4.9.7 5.8 1.6.5 3.1-1.7 2-3M374 150.9c2.7-1.4 4.8-1.2 6.3 1a9.9 9.9 0 0 1 1.6 7.2 9.2 9.2 0 0 1-3.5 5.8"/>
|
||||
<path stroke-linecap="round" d="M380.5 152c3.1-2 6.5-1.1 8.3 1.6 1.3 2 1.7 3.6 1.6 6.1a11.2 11.2 0 0 1-5.7 9.2"/>
|
||||
<path d="M395 159.2c2.6.2 4.6 2.5 4.6 5.1 0 3.8-1 5.5-4 9.3-2.7 3.3-10.6 9-10.4 14.6 0 2.1 1.8 4 3.3 4.2"/>
|
||||
<path stroke-linecap="round" d="M395.4 202.3c-1.5 1-3.3-.6-2.5-2.4.5-1.2 2.2-2.8 4.7-1.1 2.7 1.9 2 7.8-3.3 7.9-4.7 0-8-6.6-3.4-11.6 4-4.6 11.7-3.7 16.5.1 2 1.6 6.1 6 7 12 1 7 .9 15.6-6.4 21-3 2.1-7 3.1-10.6 3-4.6-.2-7.3-3.5-6.8-7.4.5-3.8 4-5.4 6.7-3.9 2.8 1.5 2.3 5.4-.7 5.8-1.7.2-3.1-1.7-2-3"/>
|
||||
<path d="M392.9 199.9c.8-3.5 3.7-3.8 6.2-3.8 6.5.1 11.1 8 11.2 15.5 0 9.5-4 15.2-11 15.5-1.9 0-5-.8-5-3"/>
|
||||
<path stroke-linecap="square" d="M397 198.3c6.9 1.6 9.3 7.8 9.3 13.8 0 4.9-.5 11.6-10 13.9"/>
|
||||
<path d="M408.4 265.3a3.9 3.9 0 1 0-6.3 2.4"/>
|
||||
<path stroke-linecap="round" d="M394.4 259.4c1.4 2 3 4.1 6.3 6m-1.3 10.5c-3.2-2.2-9.5-5-15-2.2a7.6 7.6 0 0 0-4.4 4.4 10 10 0 0 0 1.8 9.5c.9 1 2.7 2.6 5 2.7 3.8 0 4.7-2.6 4.8-3.2.4-2.8-1.2-3.9-2-4.1-.7-.3-2.8-.2-3.2 1.3-.2.5-.2 1.3.2 2"/>
|
||||
<path stroke-linecap="round" d="M340.5 328.4c1 2.2-.2 3.2-1.6 3.4-2.2.3-3.3-1.4-3.4-3a4.4 4.4 0 0 1 4.3-4.7c2.3 0 4.1 1.5 5 3.5.3.7.5 1.5.5 2.4a5.8 5.8 0 0 1-1.4 4.1 7.5 7.5 0 0 1-5.4 2.5c-4.2.1-7.5-3.8-7.5-7.8 0-7.7 11.4-12 16-13a84 84 0 0 1 17.9-2.4c3.5-.1 6.2 0 10.1-.5 3.5-.3 5.4-.5 9-1.3a27.2 27.2 0 0 0 12.6-6.4c2.9-2.7 4.5-4.5 5.9-8.2a17 17 0 0 0-1.3-13.9 14.3 14.3 0 0 0-10.3-6.8c-3.7-.5-7 1.1-9 4.8-1 1.8-.6 4.8.1 6.2a6 6 0 0 0 4.8 3c3.8 0 4.7-2.6 4.8-3.2.4-2.8-1.2-3.9-2-4.2-.7-.2-2.8-.1-3.2 1.4-.2.5-.2 1.3.2 2"/>
|
||||
<path stroke-linecap="round" d="M337.2 316.2c-4.8 2.1-8.4 3.7-11.4 8.5a9.9 9.9 0 0 0-1.2 4.9c0 2.7 1.1 5.7 3.3 7.6a8.3 8.3 0 0 0 6.7 2c2-.2 3.7-1.6 4-2.6"/>
|
||||
<path d="M385.1 224.1c-2.3.8-3.9 4.2-3.9 7.5a8.4 8.4 0 0 0 4 7.5"/>
|
||||
<path stroke-linecap="round" d="M387.6 236.4c-4 5.1-6.3 8.1-6.4 14.1 0 5.7 1.7 9.6 5.1 13.7"/>
|
||||
<path d="m365.9 152 .3-.5c1.7-2.4 4.7-3.1 6.9-1.5 2.6 2 3.3 5.4 2.6 9-.5 2.2-2 4.1-4 5.5"/>
|
||||
<path stroke-linecap="round" d="M265.1 150.8c-2.6-1.2-4.7-1-6.3 1a8.7 8.7 0 0 0-1.6 7.2c.6 2.7 1.4 3.8 3.5 5.8"/>
|
||||
<path d="M258.6 152a5.8 5.8 0 0 0-8.3 1.6 9.1 9.1 0 0 0-1.6 6.1c.2 4.2 2.8 7.6 5.8 9.2"/>
|
||||
<path d="M249.7 154.8a6.8 6.8 0 0 0-6 6.6c0 4.5 1 6.3 3.5 9.6 2.5 3.4 10.7 9.6 10.7 16.7 0 4.3-1.2 7-4.3 8.4-2 1-4.3 0-5.4-1-2.6-2.4-1.5-6.5 1.2-7 3.3-.6 3.9 4.6.7 4.3"/>
|
||||
<path d="M244 159.2c-2.5.2-5 2.3-5 5 0 3.8 1.5 5.6 4.6 9.4 2.6 3.3 10.1 9 9.9 14.5 0 2-1.5 4.6-2.9 4.3"/>
|
||||
<path stroke-linecap="round" d="M238 236.1c1.3-2.9 4.4-1.6 4.6 0 .4 3.7-2.8 4.8-5.1 4.2a4 4 0 0 1-2.5-2 4.8 4.8 0 0 1-.4-3.7 4.9 4.9 0 0 1 .9-1.6 5 5 0 0 1 1.2-1.2c1-.6 1.9-.6 3.4-.6 5.5 0 10.4 6.5 12 13.4.6 2.2 1.3 7.3.3 12a22.4 22.4 0 0 1-5.8 11.3 25.8 25.8 0 0 1-10 5.8 7 7 0 0 1-3.9.1c-2.8-.9-4.6-3.5-3.2-7 1.2-2.6 5.4-4 7.3-.6.2.3.4.9.4 1.5 0 .9-.4 2-1 2.4-1.4.9-3.7.6-3.6-2"/>
|
||||
<path d="M233.8 270.4c1 .4 1.6.3 2.9-.2l1.8-1c2.6-1.5 5.6-3.8 8.4-9.1a18.8 18.8 0 0 0 1.7-4.5c.3-1 .5-2.2.6-3.3a25.6 25.6 0 0 0-4.8-15.3c-1.1-1.6-2-2.5-4.2-2.6m-9.5 31a3.9 3.9 0 1 1 6.3 2.3"/>
|
||||
<path d="M232.2 261.4a3.7 3.7 0 0 1 3.7-3 3.7 3.7 0 0 1 3.6 3.7 3.8 3.8 0 0 1-1 2.6"/>
|
||||
<path d="M239.4 261.3a15.5 15.5 0 0 0 6.2-12.4c0-4.1-1.6-8.4-3.6-10"/>
|
||||
<path stroke-linecap="round" d="M244.7 259.4a16.5 16.5 0 0 1-6.3 6"/>
|
||||
<path d="M254.6 273.7c-1-2.2-2.8-3.2-5.8-3.5-3-.3-5.5.5-8.2 1.9a18.6 18.6 0 0 0-10.8 17 25 25 0 0 0 2 9.5c.9 1.6 3 9 15.3 14a86.1 86.1 0 0 0 25.7 3.9c10.4.4 20 .8 25.6 7.6"/>
|
||||
<path stroke-linecap="round" d="M239.7 275.9c3.3-2.2 9.5-5 15.1-2.2a8 8 0 0 1 4.3 4.4 10 10 0 0 1-1.8 9.5c-.9 1-2.7 2.6-5 2.7-3.8 0-4.7-2.6-4.8-3.2-.4-2.8 1.2-3.9 2-4.2.7-.2 2.8-.1 3.2 1.4.2.5.2 1.3-.2 2"/>
|
||||
<path d="M252.7 285.7c.3-1 .2-2.2-.8-3.3a5.1 5.1 0 0 0-6-1c-.7.5-1.6 1-2.4 2.2-.4.4-1 1.1-1.2 1.6-.7 1.1-1 2-1 2.5-2.5 7 1.5 14.4 6.5 17.6 4.4 2.8 8.8 3.6 14.4 4 2.5.3 4 .3 6.5.5h9.6a70.1 70.1 0 0 1 7.2 0c3 .3 5.1.4 7.6.8 1.6.2 3.5.5 5.4 1 .6 0 1.2.2 1.8.4l1.2.3c3.6 1.1 7 2.4 9.8 4.2.8.5 1.8 1 2.5 1.7l1.3 1.2c2 2 4 4 4.4 6.7v1.6c0 1.8-1.4 4.3-5.3 5"/>
|
||||
<path d="M298.6 328.4c-1 2.2.2 3.2 1.6 3.4 2.2.3 3.3-1.4 3.5-3a4.4 4.4 0 0 0-4.4-4.7 5.5 5.5 0 0 0-5 3.5 6.9 6.9 0 0 0-.5 2.4 5.8 5.8 0 0 0 1.4 4.1 7.5 7.5 0 0 0 5.4 2.5c4.2.1 7.5-3.8 7.5-7.8 0-7.7-11.4-12-16-13a84 84 0 0 0-17.9-2.4c-3.5-.1-6.2 0-10.1-.5-3.5-.3-5.4-.5-9-1.3a27.2 27.2 0 0 1-12.5-6.4 17 17 0 0 1-4.7-22 14.3 14.3 0 0 1 10.3-6.9c3.8-.5 7 1.1 9 4.8 1 1.8.6 4.8-.1 6.2a6 6 0 0 1-4.8 3c-3.8 0-4.7-2.6-4.8-3.2-.4-2.8 1.2-3.9 2-4.2.7-.2 2.8-.1 3.2 1.4.2.5.2 1.3-.2 2"/>
|
||||
<path stroke-linecap="round" d="m273.3 152-.4-.5c-1.7-2.4-4.7-3.1-6.9-1.5-2.6 2-3.3 5.4-2.5 9a9 9 0 0 0 4 5.5"/>
|
||||
<path d="M366.8 159.6c-4 4.4-8.1 5.8-14.1 6-2 0-5.5-.6-7.6-2.1-1.3-1-2.8-2.6-1.9-5.5.6-1.9 3.7-7.2 3.8-10.9.3-5.6-1.9-8.7-5.3-9.9-6.2-2.2-13 4-17 5.4-2.1.7-3.2.8-5.1.8-2 0-3-.1-5.2-.8-4-1.4-10.7-7.6-17-5.4-3.4 1.2-5.5 4.3-5.3 10 .1 3.6 3.2 9 3.8 10.8 1 2.9-.5 4.5-1.9 5.5-2 1.5-5.7 2.1-7.5 2-6-.1-10.1-1.5-14.1-5.9"/>
|
||||
<path stroke-linecap="round" d="M297.3 314.4c.8.3.2-.2 5.3 2a22 22 0 0 1 11.3 8.9 10.5 10.5 0 0 1 .9 7.3"/>
|
||||
<path d="M297.7 336a8 8 0 0 0 3.2.9c4.2.1 7.5-3.8 7.5-7.8 0-2.8-1.5-5.2-3.6-7"/>
|
||||
<path stroke-linecap="round" d="M298.6 328.4c-1 2.3.4 3.5 1.8 3.7 2.2.2 3.4-1.4 3.6-3a4.5 4.5 0 0 0-2.2-4.2"/>
|
||||
<path d="M390.1 154.8c3.2 0 6 3.6 6 7.2 0 4.3-2.2 6.9-3.9 8.8-1.3 1.6-2.7 3-4.4 4.7"/>
|
||||
<path stroke-linecap="round" d="M386.3 151.4a9 9 0 0 1 2.8 2.4c1.3 2 1.7 3.7 1.6 6.2-.2 4.2-3.2 7.1-6 9m-4.7-17.6.6.7c1.9 2.2 2 5.4 1.6 7.2a8.2 8.2 0 0 1-3.8 5.4m-5-14.4c2.6 2 3.4 5.4 2.5 9-.6 2.5-2.2 4-4.2 5.2m11.1 41.1c.3 1 .9 1.3 1.5 2a13.5 13.5 0 0 0 6.2 3.5c2.4.7 4.6.2 6.3-.9m-163 54c1.2 0 2.5.9 3.3 2.3.1.2.4.8.4 1.5 0 .9-.4 1.8-1 2.2-1.5 1-4 .5-4-2"/>
|
||||
<path d="M241.5 231.3c5 1 9.7 6.9 11.2 13.3.6 2.3 1.3 7.3.3 12a22.4 22.4 0 0 1-6 11.4 16.5 16.5 0 0 1-2.1 1.9l-1 .7m-8-12.1c2 0 3.8 1.9 3.8 4a3.8 3.8 0 0 1-1 2.6"/>
|
||||
<path d="M234.6 260.7c2.1 0 4.1 2 4.1 4.2a3.9 3.9 0 0 1-1.4 3"/>
|
||||
<path stroke-linecap="round" d="M254 239.5a18 18 0 0 1 3.8 7.7m0 8.5a17.3 17.3 0 0 1-1.5 4 17.8 17.8 0 0 1-3.6 4.7"/>
|
||||
<path d="M254.3 224.3c1.8 1.5 3 3 3.5 4.8"/>
|
||||
<path stroke-linecap="round" d="M257.9 219.5a10 10 0 0 1-3.4 4.6m-9.2-17.2 2.2-.6 1.3-1 .8-1.1.7-1.8.3-1.5"/>
|
||||
<path d="M241 199.3c-.7.2-1.6.4-2.5.8a9 9 0 0 0-3.5 3 17 17 0 0 0-2.2 12.7 15.8 15.8 0 0 0 2.3 5.6l1 1.4c1.4 1.3 2.6 2 4.6 1.7"/>
|
||||
<path stroke-linecap="round" d="M253 189.8c-.3 1.3-1 2.9-3 2.7"/>
|
||||
<path d="M245.7 198.5c-2-1.9-6-2.4-10.1.2L234 200a8.8 8.8 0 0 0-1.4 1.6 17.5 17.5 0 0 0-2.4 5c-.7 3-.7 5.6-.6 6.3 0 1 .2 1.9.3 2.7.6 2.8 1.4 4.8 2.3 6.2.9 1.5 3 5 7.7 5.4 1.8.1 4.8-.7 5-3"/>
|
||||
<path stroke-linecap="round" d="M363.8 157c.3-1.6 2.3-1.9 3-1 1.2 1.6.4 4.2-2 4.9a4 4 0 0 1-3.8-1.4c-1-1.3-.9-2.8-.5-4 .2-.8.9-1.5 1.7-2.2 2.7-2 7.1-1.6 8.6 2 1.8 4.4-2.2 7.8-6 10.3-4.6 3.2-10 3.8-14 3.7-9.2 0-16.1-4.4-20.7-7-1-.5-2.1-.4-2.7.3a2 2 0 0 0 .3 2.7"/>
|
||||
<path stroke-linecap="round" d="M365.6 155.5c1 0 1.2.4 1.5.8 1.2 1.5.3 4.1-2 4.9m17.8 51.5c-3.5 3.8-.2 10.3 2.4 11.8.9.7 1.3.3 2 .7"/>
|
||||
<path d="M383.1 205.4c-1.1.8-1.5 1.7-1.6 3.3a5.3 5.3 0 0 0 1.4 4 14 14 0 0 0 9.3 3.7c2 0 4-.4 6-1.7a9 9 0 0 0 3.8-5.4m-20.8 61.8-.2 2.5a18.9 18.9 0 0 1-2 7 18.7 18.7 0 0 1-4.2 5.6 19.6 19.6 0 0 1-5.9 4 24.6 24.6 0 0 1-6.5 2.3 43.8 43.8 0 0 1-13.2.6c-2.7-.2-4.1-.5-6.8-.8-2.2-.1-3.4-.3-5.6-.3a28.3 28.3 0 0 0-10.9 1.9c-2.7 1-5.7 3-6.4 3.8-.6-.9-3.7-2.8-6.3-3.8a22 22 0 0 0-5.2-1.5c-2.2-.4-3.5-.4-5.8-.4-2.2 0-3.4.2-5.6.4-2.6.2-4 .6-6.7.7-2.5.2-3.9.3-6.3.2a33 33 0 0 1-7-.8 24.6 24.6 0 0 1-6.5-2.2 19.6 19.6 0 0 1-5.8-4.1 18.7 18.7 0 0 1-4.2-5.7 19 19 0 0 1-2-6.9c-.2-1-.2-2.5-.2-2.5V169.3h123.2v101.8z"/>
|
||||
</g>
|
||||
<g fill="#c7b37f" stroke="#c7b37f">
|
||||
<path stroke-width=".3" d="M248 285.6a2.5 2.5 0 1 1 5 0 2.5 2.5 0 0 1-5 0zM232.5 268c0-1.3.8-2.3 1.8-2.3s1.7 1 1.7 2.3c0 1.2-.8 2.2-1.7 2.2-1 0-1.8-1-1.8-2.2z"/>
|
||||
<path stroke="none" d="M241.3 223.6c0-1 .8-1.8 1.7-1.8 1 0 1.7.8 1.7 1.8s-.7 1.8-1.7 1.8-1.7-.8-1.7-1.8zM272 158c0-1 .5-2 1.4-2 .9-.1 1.7.6 1.8 1.6 0 1-.5 2-1.4 2-.9.1-1.6-.6-1.8-1.6z"/>
|
||||
</g>
|
||||
<g stroke="#c7b37f" stroke-linecap="round" stroke-width=".6">
|
||||
<path d="M239.3 234c-.4.1-.6.2-.8.5-.3.3-.4.4-.6.9l-.2 1.2m4.7 26.7 1-1 .6-1 .5-1 .7-1.3m-1.3 14-1.5.7-1.1.6a17.4 17.4 0 0 0-1.3.8l-1.2 1m15-37.9-.8-.8-1-.8-.9-.8"/>
|
||||
<path stroke-linecap="butt" d="m254.2 225-1.2.5a5.1 5.1 0 0 1-1.5.3"/>
|
||||
<path d="M237.4 208.4c.2.6.2 1 .5 1.5.2.7.5 1.1.9 1.7a8.3 8.3 0 0 0 2.6 2.7l1.5.8m-1-5.8 1.3.6a7.4 7.4 0 0 0 3 .6l1.8-.1m7.2-40.7-2-1.2c-.9-.5-1.3-.9-2-1.5a9.3 9.3 0 0 1-1.1-1.3l-.8-1.3m7.5-4.6.6 1.7a7.8 7.8 0 0 0 1.4 2c1 1 1.7 1.3 2.8 2.2m1.4-6c.3.7.3 1 .7 1.6.2.5.4.8.8 1.2l1.3 1.3c.7.6 1.2.7 2 1.1"/>
|
||||
</g>
|
||||
<path fill="#703d29" stroke-width=".2" d="M333.3 151.6c0-1.7-1.7-1.8-2.4-1.8-1.8 0-2.3 1.1-4.6 2.3a11.9 11.9 0 0 1-6.7 2 12 12 0 0 1-6.7-2c-2.3-1.2-2.7-2.3-4.6-2.3a2.3 2.3 0 0 0-2.2 2.4v.9l.3.2c0-.8.1-1.2.5-1.7a2.2 2.2 0 0 1 1.6-.8c1.8 0 2.5 1.2 4.8 2.4 3 1.6 4.2 1.9 6.7 2a12 12 0 0 0 6.8-2c2.3-1.2 3-2.5 4.8-2.5.6 0 1 .4 1.3 1v.9l.2.1c0-.3.2-.4.2-1z"/>
|
||||
</g>
|
||||
<g fill="#703d29">
|
||||
<path d="M264.4 294c.5-.5.9-.3 1-.6 0-.2 0-.2-.3-.3l-.9-.2-.8-.4c-.1 0-.4-.2-.5 0-.1.4 1 .4.6 1.4a3.7 3.7 0 0 1-.8 1.2l-2.6 3-.2.1v-4.3l.1-1.8c.2-.4.8 0 .9-.4 0-.1 0-.2-.3-.3-.2 0-.5 0-1.1-.3l-1-.5c-.2 0-.5-.2-.6 0l.1.3c.4.2.5.4.5 1v7.4c0 .5.1.6.2.7.1 0 .2 0 .4-.3l5.3-5.7z"/>
|
||||
<path d="M267.5 295.2c.3-1.1 1-.4 1-.8.1-.2 0-.2-.2-.3l-1.3-.4c-.4 0-.8-.3-1.2-.4 0 0-.3-.1-.4 0-.1.5 1.1.5.8 1.5l-1.7 5.5c-.3 1-1 .6-1.1 1v.1l1.2.4 1.6.5h.3c.2-.4-1.2-.3-.7-1.7l1.7-5.4zm3.7 1c.2-.6.5-.5.9-.4 1 .3 1.4 1.3 1 2.5-.2.6-.4 1.2-2 .8-.3-.1-.7-.2-.6-.5l.7-2.3zm-2.8 5c-.5 1.4-1.2.8-1.3 1.2 0 .2.2.2.3.3l1.6.4.8.3h.4c.1-.5-1-.3-.7-1.5l.6-2c.1-.4.1-.5.6-.3.6.1.7.3.8.8l.3 2c.2.9.3 1.7 1 2 .5 0 1.2 0 1.4-.4l-.2-.2h-.3s-.3 0-.3-.3l-.7-3.6c0-.2.4-.2.8-.3a2 2 0 0 0 1-1.3c.1-.5.4-2.2-1.8-2.9l-2.1-.5-1.2-.4h-.3c-.1.5 1.1.4.7 1.7l-1.5 5zm8.4 2.5c-.4 1.4-1.4.5-1.5 1 0 .2.1.3.3.3l1.5.3 1.4.4c.3 0 .5.2.6-.1 0-.3-1.3-.3-1-1.8l1.3-5.2c0-.6.2-.6.6-.5l1 .2c1.1.3.5 1.5 1 1.6.2 0 .2-.4.2-.6l.1-1v-.4l-3.3-.7-3.2-.8c-.1 0-.2 0-.2.2l-.5 1.5c-.1.1-.2.4 0 .4.5.1.5-1.5 1.7-1.2l.9.2c.4.1.5.2.4.8l-1.3 5.4zm12.7-3.3c.4-.6.8-.5.9-.7 0-.2-.2-.2-.4-.3h-.9l-.9-.3c-.1 0-.4-.1-.4.1-.1.4 1 .2.8 1.3 0 .2-.1.6-.6 1.3l-2 3.3-.3.2v-.2l-.7-4a5.4 5.4 0 0 1-.1-1.8c0-.5.7-.2.7-.5 0-.2 0-.2-.4-.3l-1.1-.1c-.4 0-.7-.2-1-.3-.2 0-.5-.1-.6.1l.1.2c.5.2.6.4.7.9l1.3 7.3c.1.5.2.7.3.7.1 0 .2 0 .4-.3l4.2-6.6zm.6 6.8c0 .3 0 .3.2.5.6.2 1 .6 1.7.7 1.4.2 2.6-.7 2.8-2.2.3-1.5-.3-2.1-1.4-2.9-1.3-.9-1.8-1.1-1.7-2 .1-.7.7-1 1.4-1 1.8.3 1.6 2.6 1.8 2.6.3 0 .3-.1.3-.4l.2-1.6v-.4h-.6c-.4 0-.7-.5-1.6-.7-1.2-.2-2.3.7-2.5 2-.2 1.2.4 1.8 1.2 2.4 1.6 1.1 2.2 1.4 2 2.4-.1 1-.9 1.4-1.7 1.3-1.2-.2-1.6-1.4-1.8-2.6 0-.2 0-.3-.2-.3s-.2.3-.2.5v1.7zm15.8-4.5c.3-.7.8-.6.8-.9 0-.2-.1-.1-.4-.2h-.9l-.9-.1c-.1 0-.4 0-.4.2 0 .4 1 0 1 1.1 0 .2-.1.6-.5 1.4l-1.8 3.5-.1.3-.1-.3-1.1-4a5.4 5.4 0 0 1-.3-1.6c0-.5.7-.3.7-.6 0-.2 0-.2-.4-.2h-1.2l-1-.2c-.2 0-.5-.1-.6.1l.2.2c.4.2.6.3.7.8l2.1 7.1.4.7c.1 0 .2 0 .3-.4l3.5-7z"/>
|
||||
<path d="M307.6 308.5c0 1.2-1 1-1 1.5 0 .2.1.1.3.1h2.2l.4-.1c0-.6-1.4.2-1.4-2v-4.2l.1-.1.2.1 5.1 6.3.3.1.2-.3v-6.7c0-1.3 1-1 1-1.3 0 0 0-.2-.3-.2h-2.3c-.2 0-.2.1-.2.2 0 .4 1.3.2 1.3 1.3v4l-.1.4-.4-.3-4.2-5.3c-.2-.3-.1-.3-.4-.3h-1.8l-.2.1c0 .6 1.2-.2 1.2 2.1v4.6zM318 303c0-1.1.8-.7.8-1.1 0-.1 0-.2-.4-.2h-2.6s-.3 0-.3.2c0 .4 1.1 0 1.1 1.2v5.7c0 1.1-.8.8-.8 1.2 0 0 0 .2.2.2h2.8c.2 0 .3 0 .3-.2 0-.4-1.2.2-1.2-1.3l.1-5.7zm4.5 5.5c0 1.5-1.2 1-1.2 1.4 0 .2.2.2.4.2h3c.3 0 .5 0 .5-.3s-1.4 0-1.4-1.4V303c0-.6 0-.6.5-.6h1c1.2-.1.8 1.2 1.3 1.2.2 0 .1-.4.1-.6l-.1-1c0-.2 0-.4-.2-.4l-3.3.1h-3.3l-.2.3-.1 1.6.1.4c.5 0 .2-1.6 1.4-1.6h.9c.4 0 .5 0 .6.6v5.6zm6.3-2.2h-.4l.1-.5.7-2.2v-.2l.2.1 1 2.1.2.4c0 .2-.2.2-.4.2h-1.4zm1.8.5c.3 0 .3 0 .8 1l.2.8c0 .7-.7.6-.7 1 0 .1.2.1.4 0h1.2l1.3-.1c.3 0 .4 0 .4-.2 0-.4-.6 0-1-.7l-3.4-7-.3-.4c-.2 0-.2.2-.3.4L327 309c-.2.7-.8.7-.7 1h2.3c.2-.1.5 0 .5-.3s-1.2 0-1.3-.9l.2-1c.2-.8.4-.8.6-.8l2.1-.2zm8.3-5c-.1-.8 0-.8 1.2-1 2-.2 1.4 1.3 2 1.2.2 0 0-.4 0-.6l-.1-1.1c0-.1-.1-.2-.3-.2-1 0-1.7.2-2.4.3l-2.8.4c-.2 0-.3 0-.3.2.1.5 1.3 0 1.4 1l.7 5.5c.2 1.5-.7 1-.6 1.5 0 0 0 .1.2 0l1.4-.1 1.2-.1c.3 0 .5 0 .5-.3s-1.2.1-1.4-1.2l-.2-1.7c-.1-.7-.1-.9.3-1h.8c1.1-.2 1 1.1 1.3 1 .3 0 .2-.4.1-.5l-.3-2.1c0-.3-.2-.3-.2-.3-.3 0-.1 1.1-1 1.2l-.7.1c-.5.1-.5 0-.6-.5l-.2-1.7zm4 2.8c.4 2.3 2.1 3.7 4.2 3.3 3.4-.7 3.5-3.6 3.2-5.3-.5-2.5-2.3-3.7-4.4-3.3-2.5.5-3.5 2.7-3 5.3zm1.1-1c-.3-1.6 0-3.4 1.7-3.7 1.4-.3 3 .8 3.4 3.4.3 2 0 3.6-1.8 4-1.9.4-3-2-3.3-3.6zm8.3-4.1c-.1-.7.2-.8.6-.9 1-.2 1.8.5 2.1 1.6.2.7.3 1.4-1.3 1.8-.3 0-.7.1-.8-.2l-.5-2.3zm0 5.7c.4 1.4-.5 1.3-.5 1.6.1.3.3.2.4.1.6 0 1-.3 1.6-.4l1-.2c.2 0 .2-.1.2-.2 0-.4-1 .3-1.3-1l-.5-2c0-.4-.2-.4.4-.5.5-.2.7-.1 1.1.3l1.3 1.6c.5.6 1 1.3 1.8 1.1.5-.1 1-.5 1-.9l-.2-.1-.3.1s-.3.1-.4 0l-2.4-2.9.5-.6c.2-.4.4-.9.2-1.6-.1-.5-.7-2.1-3-1.6l-2.1.6-1.2.2c-.2 0-.3.1-.2.2 0 .5 1.1-.2 1.4 1l1.2 5.2zm8.7-2c.3 1.4-1 1.2-.9 1.6 0 .3.3.2.5.2l1.4-.5 1.5-.3c.3 0 .5 0 .4-.4 0-.3-1.3.4-1.7-1l-1.3-5.3c-.2-.5 0-.6.3-.7l1-.2c1.1-.4 1.1 1 1.5.9.3 0 0-.5 0-.7l-.4-1s0-.3-.2-.2l-3.2.9-3.2.7v.3l.1 1.6c0 .2 0 .4.3.4.5-.1-.3-1.6 1-1.9l.8-.2c.4-.1.6 0 .7.5l1.4 5.3zm5.5-7.3c-.3-1 .6-.9.4-1.3h-.3l-1.4.4-1.2.3s-.3 0-.3.2c.1.4 1.2-.2 1.5.8l1.6 5.6c.2 1-.6 1-.5 1.3 0 .1 0 .2.2.1l1.1-.3 1.6-.4c.3 0 .3-.1.3-.3-.1-.3-1.1.5-1.5-.9l-1.5-5.5zm2.3 2.7c.7 2.3 2.6 3.4 4.7 2.7 3.2-1.1 3-4.1 2.4-5.7-.8-2.4-2.8-3.3-4.8-2.7-2.4.9-3.2 3.2-2.3 5.7zm1-1c-.6-1.7-.6-3.5 1.1-4 1.3-.5 3 .4 3.9 2.9.6 1.8.5 3.6-1.2 4.2-1.8.6-3.2-1.5-3.8-3.2zm7.6-5.5c-.2-.7 0-.8.4-1 1-.3 2 .3 2.4 1.4.2.6.4 1.3-1.1 1.9-.3 0-.7.2-.8 0l-.9-2.3zm.8 5.6c.6 1.4-.4 1.4-.2 1.7 0 .3.2.1.4.1l1.5-.7.9-.2c.2-.1.2-.2.2-.3-.2-.4-1 .4-1.4-.8l-.8-1.9c-.2-.4-.2-.5.3-.7.5-.2.7-.1 1.1.3l1.6 1.4c.5.5 1.1 1.1 2 .8.3-.2.9-.7.7-1l-.2-.1-.2.2h-.5l-2.8-2.5.4-.7a2 2 0 0 0 0-1.6c-.1-.6-1-2-3.1-1.2l-2 .9-1.2.4-.2.2c.2.4 1.1-.4 1.6.8l2 5z"/>
|
||||
</g>
|
||||
<g fill="#fedf00" transform="matrix(.64 0 0 .64 0 16)">
|
||||
<path fill="#d52b1e" d="M412.7 249.3h82.1v82h-82.1z"/>
|
||||
<path id="a" fill="#fff" d="M451.2 313.8s0 3-.8 5.3c-1 2.7-1 2.7-1.9 4a13.2 13.2 0 0 1-3.8 4c-2 1.2-4 1.8-6 1.6-5.4-.4-8-6.4-9.2-11.2-1.3-5.1-5-8-7.5-6-1.4 1-1.4 2.8-.3 4.6a9 9 0 0 0 4.1 2.8l-2.9 3.7s-6.3-.8-7.5-7.4c-.5-2.5.7-7.1 4.9-8.5 5.3-1.8 8.6 2 10.3 5.2 2.2 4.4 3.2 12.4 9.4 11.2 3.4-.7 5-5.6 5-7.9l2.4-2.6 3.7 1.2h.1z"/>
|
||||
<use xlink:href="#a" width="100%" height="100%" transform="matrix(-1 0 0 1 907.5 0)"/>
|
||||
<path d="m461.1 279 10.8-11.7s1.6-1.3 1.6-3.4l-2.2.4-.5-1.2-.1-1.1 3-.7V260l.3-1.3-3.2.2.3-1.4.5-1 1.9-.4h1.9c1.8-3.4 9.2-6.4 14.4-1 3.8 4 3 11.2-2 13.2a6.3 6.3 0 0 1-6.8-1.1l2-4c2.7 1.7 5-.3 4.8-2.4-.2-2.7-2-4.3-4.3-4.5-2.3-.2-4 1-5 3-.6 1.3-.3 2.2-.5 3.6-.2 1.5 0 2.3-.5 3.8a8.8 8.8 0 0 1-2.4 3.6l-11 12-43 46.4-3.2-3 43.2-46.7z"/>
|
||||
<path fill="#fff" d="M429.5 283s2.7 13.4 11.9 33.5c4.7-1.7 7.4-2.8 12.4-2.8 4.9 0 7.6 1 12.3 2.8A171 171 0 0 0 478 283l-24.2-31-24.4 31z"/>
|
||||
<path d="m456.1 262.4 16.8 21.7s-2.2 10.5-9 26.3c-2.7-.6-5-1.1-7.8-1.3v-46.7zm-4.7 0-16.8 21.7s2.2 10.5 9 26.3c2.7-.6 5-1.1 7.8-1.3v-46.7z"/>
|
||||
</g>
|
||||
<g fill="#d52b1e">
|
||||
<path fill="#fedf00" d="M322.3 175.5h52.6V228h-52.6z"/>
|
||||
<path d="M329.7 175.5h7.8V228h-7.8zm15 0h7.8V228h-7.8zm15 0h7.9V228h-7.9z"/>
|
||||
</g>
|
||||
<g fill="#d52b1e" stroke="#d52b1e" stroke-width=".5">
|
||||
<path fill="#fedf00" stroke="none" d="M264.3 273.5c.1 1 .5 2.6 1.4 4.3 1 1.5.6 1.4 2.7 3.8a15.3 15.3 0 0 0 4 2.9 32.7 32.7 0 0 0 15 2.6c2.7-.1 4.8-.4 6.6-.7a71 71 0 0 1 11-.6c1.5 0 3 .3 4.7.6 3.5.7 7 2 7 2v-54.7h-52.6V271l.2 2.4z"/>
|
||||
<path stroke-width=".3" d="m270.4 283.1 2.5 1.5 3.4 1.2v-52.2h-5.9zm29.2 2.4v-51.9h-5.8v52.8l5.8-.7zm11.7-51.9h-5.8v52.1c1.9.2 3.8.6 5.8 1v-53zm-23.4 0V287s-3.8.2-5.8 0v-53.4z"/>
|
||||
</g>
|
||||
<g transform="matrix(.64 0 0 .64 0 16)">
|
||||
<path fill="#fedf00" d="M585.5 402.4a20.8 20.8 0 0 1-2.2 6.6c-1.5 2.3-1 2.3-4.3 6a26.3 26.3 0 0 1-13 7 51.8 51.8 0 0 1-16.6 1.6c-4.3-.2-7.5-.7-10.3-1-3.8-.6-6.7-.9-11-1a62.9 62.9 0 0 0-6.2 0 83.3 83.3 0 0 0-18.3 4.2V340h82.2v58.5l-.3 3.8z"/>
|
||||
<g id="b">
|
||||
<path fill="#d52b1e" d="m524.6 347-.6.2-.8.8c-.4.4-.7.5-1.2.8l-.6.5c-.3.3 0 .6-.3 1-.1.4-.3.6-.6 1-.4.4-.7.5-1 1l-1.2 1-.3.1h-.6c-.4.2-.5.6-.8.8l.3.6.8 1.4c.2.3.2.7.5.8.5.2.9.2 1.3.1.8.2 1.3.2 2 .5l1.5.8c.5.3.8.4 1.3.5h1.8v.3l2 1a1.7 1.7 0 0 0-.1.4c-.1.3-.2.7-.1.8.6 1.9 1.2 3 1.5 3.2.6.2.8.9 1.1 1.5l-.3.3c-.6.6-1.2 1-1.7 1.8-.7 1.2-1.2 1.2-.3 2.8l1.5 2.4c.4.7.6 1.2.8 2 .2.7.3 1.2.3 2l1 .3.7-.6.6-1.2v-1c-.2-.1-.3-.4-.2-.7 0-.4.5-.3.7-.6.3-.5-.4-.8-.7-1.1-.6-.7-1.4-.9-1.6-1.9 0-.2 0-.4.4-.7l2-1.8c.2.1.6.2 1 .1l1.3.4c.6.2.9 0 1.2 0h.4l.1.6c.1 1-.1 3 .2 3.5l.3.6.2.6v2l-.2 1.7c0 .4-.2.7-.5 1-.2.4-.6.4-1 .7v1l1.1.5 1.3.3.7-.3.1-.6.5-.5c.4-.2.8 0 .9-.1.2-.3 0-.4 0-.8 0-.6-.2-1-.3-1.6a11.8 11.8 0 0 1-.1-2.8c0-.6 0-1 .2-1.5.1-1 .4-1.4.6-2.2.3-1 .3-1.6.4-2.5a24.4 24.4 0 0 0 10.1-.6c.8.7 1.7 1.2 2.7 1.6v1c0 .3 0 .4.2.7l.3.3c.3 0 .5 0 .7-.2.2-.2.2-.4.2-.7v-.7h1.8v1.1c.1.3.3.4.5.4a.7.7 0 0 0 .6 0c.3-.2.2-.6.3-1v-.7l1-.4a5.1 5.1 0 0 1 0 .9l-.3.9c-.2.6-.5.8-.8 1.4-.4.6-.5 1-1 1.5l-.6.7-.6.9-.9 1c-.7.6-1.2.2-2 .9l-.3 1 1.4.6 1.3.2.4-.2c0-.3 0-.6.3-.8.2-.3.4-.3.7-.4.4 0 .8 0 1-.2.4-.3.4-1 .7-1.5a12.7 12.7 0 0 1 3-3.9l1.7-1.4c.2-.4.5-.5.5-1l-.2-.6-.2-1c1.5.7 1 .7 1.2 1.4.3.6 0 1 .1 1.7.1.8.5 1.1.5 1.9.1.9-.1 1.4-.3 2.3-.1.8-.1 1.3-.5 2a3.8 3.8 0 0 1-1.1 1.5l-.6.5-.1 1 1.1.4 1.6.4.4-.3c.2-.7 0-1.7.4-1.7.4-.1.7 0 .8-.3v-.7l.7-4.5.4-1.9.4-1.7c.7-2-.2-2.3-1-3.6-.5-.7-.7-1-.7-1.5V362a42.7 42.7 0 0 1 0-2.8l.4-.2c1.2-.7 1.7-.9 2.4-2.5a3.4 3.4 0 0 0 .3-1.5v-1l-.4-1a3.2 3.2 0 0 0-.6-.8c-.7-1-1.7-1.1-2.7-1.5-1.5-.5-2.5-.4-4-.5-1.8-.2-2.7-.2-4.4 0-2 0-3.1.4-5.1.7l-4.9.4c-2.3 0-4.4-.5-5.8-.4-2.4.2-2.5.8-6.2 1.1a67 67 0 0 1-3.8.2l-2.2-.7c.9-.3 1.1-.5 1.5-1 .3-.4.2-.7.6-1.1l.7-1a2.2 2.2 0 0 0-.9-.4h-1a3 3 0 0 0-1.2.3l-.8.6-2.2-1.2a8.8 8.8 0 0 0-3-.9zm2 11.8z"/>
|
||||
<g fill="none" stroke="#fedf00" stroke-linecap="round">
|
||||
<path d="m568.8 359.5-.8.3c-.9.4-1.6.4-2.6.5-2.6.2-4.3-1.1-7-.9-1.4.1-2 1.2-3.5 1.6a9.3 9.3 0 0 1-1.7.2l.5-1s-1.2.3-2 .3a7.5 7.5 0 0 1-1.6-.2l1-1-1.3-.2a4 4 0 0 1-1-.7 20.5 20.5 0 0 0 1.7-.3c1.5-.4 2-1.2 3.9-1.4 1.1 0 3 0 7.6.8 3 .5 4.4.2 5.5-.3.8-.3 1-1 1.1-1.8.1-.8-.4-1.4-.8-1.8-.1 0-.5-.3-1.1-.4"/>
|
||||
<path fill="#fcd900" stroke-linecap="butt" stroke-width=".5" d="M524.8 350.6c-.5 0-.9 0-1.3.3-.5.3-.6.7-1 1.1.5.1.8.4 1.2.3.4 0 .5-.2.8-.5.3-.4.4-.7.4-1.2h-.1z"/>
|
||||
<path d="M536 363.8a13.6 13.6 0 0 0 1 2.3c.2.8 0 1.2.2 2v1.6m6.8-7-.3 1.3-1 3.5v.7m-11-4c.9.2.6 3.3 1.9 4"/>
|
||||
<path stroke-linecap="butt" d="m560.1 369.8.4-.3a8.2 8.2 0 0 0 2.7-1.8"/>
|
||||
<path d="M552.4 368c3.5-.9 5.9-2.6 7.6-2.9m-4-1.5h.8c1.5-.3 1.7.6 2.7 1.2 1.9 1 2.1 2.3 4.3 3.4l.4.1.8.4"/>
|
||||
<path fill="#fcd900" stroke-linecap="butt" stroke-width=".5" d="M517.7 354.5h.7l.8-.2c.3 0 .5 0 .7.2.2 0 .2.1.3.3 0 .2.2.3.1.5 0 .2-.3.4-.6.4-.2 0-.4 0-.5-.3a.5.5 0 0 1 0-.4 1 1 0 0 1-.9 0 1 1 0 0 1-.6-.5z"/>
|
||||
</g>
|
||||
<path fill="#0065bd" d="m525.1 364.2-2-.9c.4-.2.7-.2 1-.5.3-.4.3-.8.5-1.3s.2-1 .7-1.4c.3-.2.8-.2 1.1-.1.4 0 .8.4.9.7 0 .6-.2 1-.3 1.5 0 .6-.3.9-.2 1.4 0 .4.2.6.4 1l-2-.4zm-1 1a.6.6 0 1 1 .7.5.6.6 0 0 1-.7-.6zm-1.7-16.6h-.2c-.4-.4-.4-.8-.6-1.2a4 4 0 0 1-.3-1.2v-2c0-.3 0-.6-.2-.9 0-.2-.4-.3-.3-.4 0-.1.3 0 .4 0 .4 0 .6.1 1 .4.3.3.5.6.6 1l.4 1.5.3.8.5.6-.7.8-.9.6zm3.6 10.6 2.2 1a9.2 9.2 0 0 0 3.5-3.8c.9-1.8 1-2.7 1.4-4.4l-1.8-.5h-.4c-.5 1.8-.7 2.7-1.6 4.2-.8 1.3-1.7 2.3-2.6 3l-.7.5zm5 18.2.8-1.3 1.4-1.1h.4a8.7 8.7 0 0 1-.5 2.8l-.4 1-.5.5c-.5-.8-1.3-1.3-1.3-2zm33 1.8 1.4.6 1.5.9v.5l-1.5.2a8.4 8.4 0 0 1-1.3 0h-1l-.6-.4c.5-.7.8-1.6 1.4-1.8zm-9.8-2 1.4.5 1.5 1c0 .1.1.3 0 .4a9 9 0 0 1-2.7.3l-1-.1-.7-.3c.6-.7.9-1.7 1.5-1.8zm-17.4 2.1 1.5.5 1.5 1v.5a9 9 0 0 1-2.8.2h-1l-.6-.4c.5-.7.8-1.6 1.4-1.8zm-9-29.8c-.6-.3-1-1-.6-1.6.1-.2.4-.2.6-.4.2-.3.1-.5 0-.8l-.1-1-.2-1c0-.6 0-1 .4-1.6.2-.3.7-.6.8-.6.2.1 0 .5 0 .8 0 .5.1.7.3 1.2l.7 1.3c.2.6.4.8.4 1.4 0 .5 0 .7-.2 1.2a2 2 0 0 1-.6.8 2 2 0 0 1-.8.4 1.1 1.1 0 0 1-.6 0z"/>
|
||||
</g>
|
||||
<use xlink:href="#b" width="100%" height="100%" y="36.6"/>
|
||||
</g>
|
||||
<path fill="none" stroke="#703d29" stroke-width=".5" d="M264.1 175.5h52.6V228h-52.6zm58.2 0h52.6V228h-52.6zm-58 98c.1 1 .5 2.6 1.4 4.3 1 1.5.6 1.4 2.7 3.8a15.3 15.3 0 0 0 4 2.9 32.7 32.7 0 0 0 15 2.6c2.7-.1 4.8-.4 6.6-.7a71 71 0 0 1 11-.6c1.5 0 3 .3 4.7.6 3.5.7 7 2 7 2v-54.7h-52.6V271l.2 2.4zm110.4 0a13 13 0 0 1-1.4 4.3c-1 1.5-.6 1.4-2.7 3.8a15.4 15.4 0 0 1-4 2.9c-1.3.7-2.3 1-4.4 1.6a32.6 32.6 0 0 1-10.6 1c-2.7-.1-4.8-.5-6.5-.7a71 71 0 0 0-7.2-.6 40.5 40.5 0 0 0-3.9 0c-1.5 0-3 .3-4.7.6-3.5.7-7 2-7 2v-54.8H375v37.5l-.2 2.4z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 33 KiB |
@@ -1,6 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ae" viewBox="0 0 640 480">
|
||||
<path fill="#00732f" d="M0 0h640v160H0z"/>
|
||||
<path fill="#fff" d="M0 160h640v160H0z"/>
|
||||
<path d="M0 320h640v160H0z"/>
|
||||
<path fill="red" d="M0 0h220v480H0z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 251 B |
@@ -1,81 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="flag-icons-af" viewBox="0 0 640 480">
|
||||
<g fill-rule="evenodd" stroke-width="1pt">
|
||||
<path d="M0 0h640v480H0z"/>
|
||||
<path fill="#090" d="M426.7 0H640v480H426.7z"/>
|
||||
<path fill="#bf0000" d="M213.3 0h213.4v480H213.3z"/>
|
||||
</g>
|
||||
<g fill="#fff" fill-rule="evenodd" stroke="#bd6b00" stroke-width=".5" transform="translate(1 27.3) scale(1.06346)">
|
||||
<path d="M319.5 225.8h8.3c0 3.2 2 6.6 4.5 8.5h-16c2.5-2.2 3.2-5 3.2-8.5z"/>
|
||||
<path stroke="none" d="m266.7 178.5 4.6 5 57 .2 4.6-5-14.6-.3-7-5h-23l-6.6 5.1h-15z"/>
|
||||
<path d="M290 172.7h19.7c2.6-1.4 3.5-5.9 3.5-8.4 0-7.4-5.3-11-10.5-11.2-.8 0-1.7-.6-1.9-1.3-.5-1.6-.4-2.7-1-2.6-.4 0-.3 1-.7 2.4-.3.8-1.1 1.5-2 1.6-6.4.3-10.6 5-10.5 11.1.1 4 .6 6.4 3.4 8.4z"/>
|
||||
<path stroke="none" d="M257.7 242.8H342l-7.5-6.1h-69.4l-7.5 6.1z"/>
|
||||
<path d="m296.4 219.7 1.5 4.6h3.5l-2.8-4.6h-2.2zm-2 4.6 1 4.6h4l-1.5-4.6h-3.5zm7 0 2.8 4.6h5.9l-4.6-4.6h-4.1zm-34.5 10.4c3.1-2.9 5.1-5.3 5.1-8.8h7.6c0 2 .7 3.1 1.8 3h7.7v-4.5h-5.6v-24.7c-.2-8.8 10.6-13.8 15-13.8h-26.3v-.8h55.3v.8H301c7.9 0 15.5 7.5 15.6 13.8v7h-1l-.1-6.9c0-6.9-8.7-13.3-15.7-13.1-6 .1-15.4 5.9-15.3 13v2.2l14.3.1-.1 2.5 2.2 1.4 4.5 1.4v3.8l3.2.9v3.7l3.8 1.7v3.8l2.5 1.5-.1 3.9 3.3 2.3h-7.8l4.9 5.5h-7.3l-3.6-5.5h-4.7l2.1 5.4h-5l-1.3-5.4h-6.2v5.8H267zm22.2-15v4.6h5.3l-1-4.6H289z"/>
|
||||
<path fill="none" d="M289.4 211.7h3.3v7.6h-3.3z"/>
|
||||
<path fill="none" d="M284.7 219.8h3.2v-5.6c0-2.4 2.2-4.9 3.2-5 1.2 0 2.9 2.3 3 4.8v5.8h3.4v-14.4h-12.8v14.4zm25.6 3.3h4v3.2h-4zm-2.4-5.3h4v3.1h-4zm-3.9-5.4h4v3.1h-4zm-3.3-4.5h4v3.1h-4z"/>
|
||||
<path fill="none" d="m298 219.8 4.2.2 7.3 6.4v-3.8l-2.5-1.8v-3l-3.6-2v-3.3l-3.5-1.2V207l-1.7-1.5-.1 14.4z"/>
|
||||
<path d="M315.4 210.3h1v7.1h-1z"/>
|
||||
<g id="a">
|
||||
<path d="M257.3 186.5c-1.2-2-2.7 2.8-7.8 6.3-2.3 1.6-4 5.9-4 8.7 0 2 .2 3.9 0 5.8-.1 1.1-1.4 3.8-.5 4.5 2.2 1.6 5.1 5.4 6.4 6.7 1.2 1 2.2-5.3 3-8 1-3 .6-6.7 3.2-9.4 1.8-2 6.4-3.8 6-4.6l-6.3-10z"/>
|
||||
<path fill="#bf0000" d="M257 201.9a10 10 0 0 0-1.6-2.6 6.1 6.1 0 0 0-2.4-1.8 5.3 5.3 0 0 1-2.4-1.5 3.6 3.6 0 0 1-.8-1.5 5.9 5.9 0 0 1 0-2l-.3.3c-2.3 1.6-4 5.9-4 8.7a28.5 28.5 0 0 0 0 2.3c.2.5.3 1 .6 1.3l1.1.8 2.7.7a7.1 7.1 0 0 1 2.6 2 10.5 10.5 0 0 1 1.8 2.6l.2-.8c.8-2.7.7-5.9 2.6-8.5z"/>
|
||||
<path fill="none" d="M249.8 192.4c-.5 3.3 1.4 4.5 3.2 5.1 1.8.7 3.3 2.6 4 4.4m-11.7 1.5c.8 3 2.8 2.6 4.6 3.2 1.8.7 3.7 3 4.5 4.8"/>
|
||||
<path d="m255.6 184.5 1-.6 17.7 29.9-1 .6-17.7-30z"/>
|
||||
<path d="M257.5 183.3a2 2 0 1 1-4 0 2 2 0 1 1 4 0zm15.2-24h7.2v1.6h-7.2zm0 3.1h7.2v13.8h-7.2zm-.4-5h8c.2-2.7-2.5-5.6-4-5.6-1.6.1-4.1 3-4 5.6z"/>
|
||||
<path fill="#bd6b00" stroke="none" d="M292.6 155.8c-1.5.6-2.7 2.3-3.4 4.3-.7 2-1 4.3-.6 6.1 0 .7.3 1.1.5 1.5.2.3.4.5.6.5.3 0 .6 0 .7-.3l.2-.8c-.1-2-.1-3.8.3-5.4a7.7 7.7 0 0 1 3-4.4c.3-.2.4-.5.5-.7a1 1 0 0 0-.3-.7c-.4-.3-1-.4-1.5-.1zm.2.4c.4-.2.8 0 1 .1l.1.2c0 .1 0 .2-.3.4a8.2 8.2 0 0 0-3.1 4.6 16.7 16.7 0 0 0-.3 5.6 1 1 0 0 1-.2.6s0 .1-.2 0c0 0-.2 0-.4-.3a3.9 3.9 0 0 1-.4-1.2c-.3-1.8 0-4 .7-6 .7-1.8 1.8-3.4 3-4z"/>
|
||||
<path fill="#bd6b00" stroke="none" d="M295.2 157.7c-1.5.7-2.5 2.3-3 4.2a13.6 13.6 0 0 0-.3 5.9c.2 1.3 1 2 1.6 2 .3.1.6 0 .8-.3.2-.3.3-.6.2-1-.4-1.6-.5-3.4-.3-5.1.3-1.7 1-3.2 2.2-4.1.3-.3.5-.5.5-.8a.8.8 0 0 0-.2-.6c-.4-.3-1-.4-1.5-.2zm.2.5c.4-.2.8-.1 1 0l.1.3-.3.4a6.5 6.5 0 0 0-2.4 4.4c-.3 1.8-.1 3.7.2 5.2.1.4 0 .6 0 .8l-.5.1c-.3 0-1-.5-1.2-1.7-.3-1.7-.2-3.9.3-5.7.5-1.8 1.5-3.3 2.8-3.8z"/>
|
||||
<path d="M272.3 187.4h8v11h-8zm.5 17.4h7.7v2.4h-7.7zm-.2 4.1h8v8.7h-8zm-.6 10.5h8.7v4.9H272zm1.1-16.6h7l1.4-2.4h-9.6l1.2 2.4zm9.4-8.6.1-6h4.8a17.4 17.4 0 0 0-4.9 6z"/>
|
||||
<path fill="none" d="M273.6 196.7c0 1.3 1.5.8 1.5.1v-5.6c0-1 2.4-.8 2.4-.1v6c0 1 1.7.9 1.6 0v-7c0-2.2-5.5-2.1-5.5-.1v6.7zm0 13.3h5.7v7h-5.7z"/>
|
||||
<path d="M277.2 213h2v1h-2zm-3.5 0h2v1h-2zm2-3h1.5v3h-1.5zm0 4h1.5v3.1h-1.5zM244 139c.4 5.5-1.4 8.6-4.3 8.1-.8-3 1-5.1 4.3-8.1zm-6.5 12.3c-2.6-1.3-.7-11.5.3-15.8.7 5.5 2 13.3-.3 15.8z"/>
|
||||
<path d="M238.4 151.8c4.4 1.5 8-3.2 9.1-8.7-3.6 5-9.5 5-9 8.7zm-3.3 5.1c-3.4-.9-1.4-11.7-.7-16 .7 4.5 3.1 14.5.7 16zm1.2-.3c.2-3.7 3.9-2.7 6.5-4.7-.5 2-2 5.2-6.5 4.7zm-4.2 5c-3.4-1-1.4-12.6-1.6-17.4 1 4.2 4.2 16.3 1.6 17.4zm1.6-.5c2.8.9 6.5-1 6.8-4.3-2.5 1.7-6.3.4-6.8 4.3z"/>
|
||||
<path d="M229.5 166.7c-3.2.3-1.8-9.6-1.8-18.8 1.2 8.6 4.5 16.5 1.8 18.8z"/>
|
||||
<path d="M230.7 166.3c2.2 1 6.1-.7 7.2-4.4-4 1.7-6.6 0-7.2 4.4zm25.6-22.2c-.6 4.9-2.6 7.7-5.5 7.2-.8-3 1.6-5 5.5-7.2zm-7.8 12.4c4.9.7 6.6-3 10-7.9-4.7 3.4-10.2 4-10 8z"/>
|
||||
<path d="M247 156c-2.6-3.2 0-7.3 2-10.7-.4 5.1 1.3 8-2 10.7zm-1 5.3c-.4-3.2 5-3.9 7.4-5.6-.9 1.8-2 6.7-7.5 5.6z"/>
|
||||
<path d="M244.8 161.3c-3.7-.4-2.2-6.7.5-10.1-1.1 4.8 2 8.1-.5 10.1z"/>
|
||||
<path d="M242 166.6c-4.2-2-1.5-7.2 0-10.3-.6 4.1 2.8 7.2 0 10.2z"/>
|
||||
<path d="M242.8 166c2.2 3 6.5-.8 7.4-5.2-3.7 3.1-6.5 2.6-7.4 5.3zm-9.6 20.3c-.4-4.3 2.8-12 .5-16.2-.3-.6.7-2.1 1.4-1.2 1 1.5 2 5.7 2.5 4.1.4-1.7.5-4.6 2-5.2 1-.3 2.3-.6 1.9 1-.4 1.4-1.2 3.4-.3 3.5.5 0 2-2 3.3-3 1-.8 2.6.6 1 1.8-4.8 4-9.5 5.9-12.3 15.2zm-8.7 64.5c-.6 0-1.3-.3-.6.6 5.7 7 7.3 9 15.6 8 8.3-1.1 10.3-3.4 16.2-6.7a14.6 14.6 0 0 1 11.2-1c1.6.5 2.6.5 1.4-.7-1.2-1.1-2.5-2.7-4-3.8a17.5 17.5 0 0 0-12.7-2.7c-6 1-11.1 4.9-17.2 6.4a25 25 0 0 1-9.9 0zm47.8 12.5c1 .2 1.7 2.2 2.3.9.8-2.3.2-4-.8-3.9-1.2.3-3.1 3-1.5 3z"/>
|
||||
<path stroke="none" d="M220.6 183c-1.2-1.4-.9-1.8 1-1.9 1.4 0 4.2 1 5.3.1 1-.7.5-3.7 1-5 .2-.9.7-2 2-.2 3.6 5.8 8 12.8 10 19.6 1 3.8 0 9.8-3.4 13.8 0-3.4-1.2-5.7-2.7-8.6-2-3.7-9.1-14-13.2-17.9z"/>
|
||||
<path d="M235.5 213.4c4 0 4.7-5.3 4.7-6.8-2 .4-5.4 3.7-4.7 6.8zm34.5 51.9c2.8.6 2.7-6.2-.2-9.1 1.3 4.4-2 8.4.1 9zm-1.2-.1c.2 3.2-8-.4-10-3 4.8 2.1 9.8.4 10 3zm-3.5-4.6c.3 3.1-7 .3-9.3-2.1 4.9 1.6 9-.5 9.3 2zm1.3.4c2.9.7 2.4-6.4-.4-8.8 1.4 4.7-1.8 8.1.4 8.8zm-3-4.3c2.9.7 1.2-5.4-.9-7.8.4 4.4-1 7.5 1 7.8zm-1.5 0c.3 3.2-5.4.8-7.6-2.3 4.8 1.5 7.3-.3 7.6 2.3zm-1.5-2.5c1.8-1.3-.1-4.8-3.7-4.6.4 2.1 1.6 5.9 3.7 4.6zm14 14.7c.1 3.2-8 1.6-10.6-1.8 5.2 1 10.3-.8 10.5 1.8zm-32.4-5.8c.3 3.2-8.6-.4-10.8-3.4 4.7 1.6 10.5.8 10.8 3.4zm5.4 1.3c1.9-1.3-1.9-4.7-5-5.5.4 2.1 3 6.8 5 5.6zm.6 2.3c.2 2.9-9.5 1.3-12-1.4 8.3 1.5 11.7-1.1 12 1.4z"/>
|
||||
<path d="M252.8 268.6c1 2.7-8.3 2-11.6.5 5.3 0 10.8-2.4 11.6-.5z"/>
|
||||
<path d="M257.1 270.6c1 2.4-7.6 2.4-11.8 1 5.6 0 10.8-3.4 11.8-1zm6.3 1.3c1.6 2.9-7.6 3.1-10.5 1.7 5.2-.7 9.2-4 10.5-1.7zm-10.7-4.9c-2.9 1.8-2.7-3.6-5-7.3 3.6 3.3 7 5.6 5 7.3z"/>
|
||||
<path d="M257.9 269c-2.4 2.1-4.4-5.3-6.6-9.5 3.6 4 8.8 7.7 6.6 9.4zm6.8 2c-2 2.4-8-7-10.2-12 3.3 3.9 11.8 10 10.2 12zm-5.8 7.2c-1 3.6-16.2-3.4-18-7.1 8.8 4.6 18.2 3.6 18 7zm-48.7-73.8c-.4-.5-1.4 0-1.2 1.1.3 1.5 2.5 9.2 6.3 11.8 2.7 2 17 5.1 23.4 6.5 3.6.7 6.5 2.5 8.9 5.3a94.4 94.4 0 0 0-3-9.8c-1.2-3-4.4-6.2-7.8-6.3-6.1-.3-14.1-.8-20-3.3a16 16 0 0 1-6.7-5.3z"/>
|
||||
<path d="M245.5 234.9c2 1.4 4.1-3.7 1.7-8.6-.1 4.7-3.8 6.3-1.7 8.6z"/>
|
||||
<path d="M247.4 239.6c2.7.8 3.5-4 1.8-7.8.3 4.1-4.3 6.6-1.8 7.8z"/>
|
||||
<path d="M249.5 243.4c2.6 1.3 3.5-3.6 1.7-7.1.2 4.5-3.7 5.9-1.7 7z"/>
|
||||
<path d="M248.4 243.7c-1 3-7-2.7-8-5.8 3.7 3.7 8.7 3.2 8 5.7z"/>
|
||||
<path d="M245.7 239c-1.2 3-8.7-5-10.4-8.7 3.7 3.7 11.2 6.5 10.4 8.6z"/>
|
||||
<path d="M244.2 234.3c-1.2 3.5-9.3-5.8-11.7-9.1 4 3.6 12.6 6.6 11.7 9.1zm-.3-3.4c3-.6-.1-3-3.7-6.9-.1 4.1.5 7 3.7 6.9z"/>
|
||||
<path d="M239 228.5c1.3-1.3-1.1-1.9-4.1-5.3-.5 2.3 2.8 6.5 4.2 5.3zm14 15.2c1.6 1 2.6-2.3.7-5.2-.5 3.2-2.1 4-.7 5.2zm-34.2-20.3c-3.3 2-8.6-6-10-9.3 2.9 3.8 10.6 7.2 10 9.3z"/>
|
||||
<path d="M221.7 228c-1.9 2-7.7-3.5-9.7-6.3 3 2.7 10.5 3 9.7 6.3z"/>
|
||||
<path d="M224.8 232.2c-.6 2.8-9-3.5-11-6.5 3.6 3.5 11.6 3.2 11 6.5z"/>
|
||||
<path d="M223.5 235.3c-1.3 2.5-8.2-3.8-9.9-7 4.3 3.6 11 4.5 10 7zM220 223c2.1-2.3 1.2-3.4-.4-7-.8 3.7-2.1 5.2.4 7zm2.9 4.3c4 .2 0-4.6-1-8.7.4 4.6-1 8.3 1 8.7z"/>
|
||||
<path d="M225.4 231.1c2.7-.6 2-4.5-.2-9.2.5 5.1-2.3 8 .2 9.2zm-1 7.7c-1 3-8.8-4-10-6.8 4 3.4 10.7 4.5 10 6.8z"/>
|
||||
<path d="M229.1 243.6c-1.1 3-9.3-3.2-11.8-6.6 4.9 4 12.4 3.6 11.8 6.6z"/>
|
||||
<path d="M233.9 248.5c-1.3 4.3-9.9-2.6-12.4-6 5.4 4.2 13 3 12.4 6zm-8-11c2.3 1.1 3.2-5.4 1.9-10.1 0 5-4.7 8.8-2 10z"/>
|
||||
<path d="M229.8 242.7c2.8.8 2-6.3-.5-11-.3 4.7-2.3 9 .5 11zm5 4.9c3 .1 1-6.1-1.6-9.6.4 4.5-1 9 1.6 9.6zm-5.5 2.6c-1 1.6-3.2-1.3-7-3.5 3.4 1 7.4 2 7 3.5zm-1.8-52.7c3-2.2.7-6.2 0-10-1 3.6-3.4 8.4 0 10zm0 5.3c-4.5-.5-3.8-6.1-4-9.7 1.4 4.9 5 5.7 4 9.8zm.6-.7c3.7-.2 3.5-4.4 3.7-8.6-1.9 3.9-4 4.5-3.7 8.6z"/>
|
||||
<path d="M228 207.3c-3 .3-4.4-2.6-5-7 2.7 4.1 5.1 2.8 5 7zm1-.3c3.7.5 3-3.8 3-7-1.2 3-4.2 4-3 7z"/>
|
||||
<path d="M223.2 205.2c.3 2.8 2.1 7.6 5 6.5 1.1-3.4-2.6-4.1-5-6.5z"/>
|
||||
<path d="M229 212c-1.2-2.4 3-3.7 3.8-6.9.5 4.6.1 7.6-3.8 7zm-11.9-29.2c2.3-2.4.3-6.4-.4-10.2-1 3.6-2.5 8.4.4 10.2zm0 4.6c-4 .5-5-7.7-5.5-11.3 1.4 4.9 6 7 5.5 11.4zm.8 0c2.8-1.5 2.2-4.7 3-7-1.8 2.9-3.6 3.3-3 7z"/>
|
||||
<path d="M217 192.8c-4.1.3-6.6-8.8-6.8-12.4 1.3 4.9 7.4 7.5 6.9 12.4zm.9-.2c4-.9 3.5-3.5 2.9-7.6-1.3 4.2-3.5 3.3-2.9 7.6z"/>
|
||||
<path d="M217 198c-4.6.8-4.3-6.6-8-11.9 3.2 4 9 9 8 11.9zm1-.3c3.6.2 4-5.1 3.8-7.3-.9 2.2-5 4.2-3.7 7.4z"/>
|
||||
<path d="M209.8 192.3c1.7 5.7 4.2 11.4 7.2 11 1.5-3.3-2.9-3.7-7.2-11z"/>
|
||||
<path d="M218.1 202.4c-1.2-2.5 3-3.7 3.8-6.9.5 4.6.1 7.6-3.8 6.9zm-7.1-3.6c2.5 5.1 3.6 11 7 10.1 1.3-4-3.8-4.8-7-10.1z"/>
|
||||
<path d="M218.7 208c-1.5-2.8 2.7-3.7 3.8-7.4.5 4.8 0 8.3-3.8 7.3zm7.2-34.5c2.4.6 5-2.1 4.1-6.2-2.8.6-4 3.2-4.1 6.2zm-7.9-2.1c.2 1.2 1.7 1.3 1.2-.4a5.3 5.3 0 0 1 0-3.4 7.5 7.5 0 0 0 0-4.6c-.4-1-1.8-.4-1.2.4.6.9.7 2.8.2 3.7-.6 1.3-.4 3-.2 4.3zm22.9 16c-1 1.3-2.9.4-1.4-1.5 1.2-1.5 3-2.8 3-4.4.2-2 1.3-5 2.4-6.1 1.1-1.1 2.4.4 1.2 1.2-1.3.8-2.2 4.4-2.1 5.8-.1 2-2 3.5-3.1 5zm-3-2.3c-1 1.4-2.4.5-1.6-1.7.7-1.5.8-3.5 1.6-4.6 1.2-1.7 3-3.1 4.1-4.2 1.2-1 2 0 1 1a27 27 0 0 0-3.3 4c-1.4 2.2-.8 4-1.8 5.5zm-15.7-7.2c-.1 2 1.5 2.4 1.4-.4 0-3-2.2-5.8-1-10.3.8-2.2.8-6.3.4-8.4-.4-2.2-2-.8-1.3.9.6 2-.1 5.6-.6 7.5-1.5 5.4 1.2 8 1 10.7zm4.3-11c-.2 1.9-1.8 2-1.3-.5.4-2 .4-3.6 0-5.3-.6-2.1-.4-5.7 0-7.2.5-1.6 2-.7 1.4.5a9.9 9.9 0 0 0-.3 5.9c.6 2 .5 4.8.2 6.7zM210.9 204c.8.9 2 .3 1-1-1-1-.7-1.2-1.3-2.4-.6-1.4-.5-2.1-1.2-3-.7-1-1.6 0-1 .7.8 1 .6 1.6 1 2.5 1 1.5.7 2.3 1.5 3.2zm20.4 24.6a8.6 8.6 0 0 1 4.4 6.7 16 16 0 0 0 2 7.1c-2-.5-3-3.7-3.3-6.8-.3-3.2-2-4.5-3-7zm5.1 5.9c1.7 3.1 4 4.3 4.2 6.6.2 2.7.4 2.8 1.1 5.4-2-.5-2.5-.7-3-4.7-.3-2.8-2.6-4.7-2.3-7.3z"/>
|
||||
<path stroke="none" d="M289 263.3c1 1.8 2 4.5 4 4 0-1.3-2.1-2.3-4-4zm3 .6c3.7 1.6 7 1.2 7.5 3.6-3.6.4-5-1-7.6-3.6zm-16.1-12.7a14 14 0 0 1 5 7.7 29 29 0 0 0 3.6 7.8 13 13 0 0 1-5.3-7.4c-.7-3-1.6-5.3-3.3-8zm3.1 0c2.8 2.2 5.4 4.8 6.2 7.9.8 2.9 1.3 5.1 3.2 8-3-1.9-4.1-4.7-5-7.8-.7-3-2.5-5.2-4.4-8zm9.2 7.3a1.1 1.1 0 0 1 .7-1.2 33.4 33.4 0 0 1 2.6-.8c1-.3 1.6.4 1.6.9v2c0 .7-.2.8-.7.9-.7.1-1.7.2-2.4.7-.6.4-1.2.1-1.5-.5l-.3-2zm10.6 0c0-.6-.2-1.1-.6-1.2a5.4 5.4 0 0 0-2.4-.4c-1 0-1.1.2-1.1.6v2.1c0 .8 0 .8.4 1 .7 0 1.8 0 2.5.6.5.3 1 0 1.1-.6l.1-2.1z"/>
|
||||
</g>
|
||||
<use xlink:href="#a" width="100%" height="100%" x="-600" transform="scale(-1 1)"/>
|
||||
<g stroke="none">
|
||||
<path d="M328.5 286.6c0 1.2.2 2.2 1 3.1a19 19 0 0 0-13.8 1.1c-1.8.8-4-1-1.9-2.7 3-2.3 9.7-1 14.7-1.5zm-57.5 0a7 7 0 0 1-.4 3c4.4-1.7 9.1-.2 13.6 1.6 3 1.3 3.3-1 2.8-1.7a6.5 6.5 0 0 0-5-2.9h-11zm3.8-21.7c-1.3-.5-2.7 0-4 1.4-4.3 4.2-9.4 8.3-13.5 11.6-1.5 1.3-3 3.7 3.4 6 .3.2 5 2 8 2 1.3 0 1.3 1.8 1 2.3-.5 1-.1 1.4-1.1 2.3-1.1 1 0 2.1 1 1.3 3.6-3.2 9.6-1.1 15.3.7 1.4.4 3.8.3 3.8-1.6 0-2 1.5-3.4 2.4-3.5 2.4.4 14 .5 17.5.1 2-.3 2.2 2.9 3.3 4 .8.9 3.7 1.1 5.8.2 4-1.8 10-1.8 12.5 0 1 .7 1.9 0 1.3-.7-.8-1-.7-1.6-1.1-2.4-1-2-.2-2.4.8-2.5 11-1.5 14.6-5.2 11.2-8.3-4.4-3.8-9.2-7.7-13.4-12.2-1.2-1.2-2-1.7-4.3-.7a66.5 66.5 0 0 1-25.3 5.9 76 76 0 0 1-24.6-5.8z"/>
|
||||
<path fill="#bd6b00" d="m326.6 265.5-1.6.4c-9 3.2-17.2 5.4-25.7 5.4-8.3 0-17-2.4-24.9-5.6a2.3 2.3 0 0 0-1.5 0c-.5.1-1 .4-1.3.7a115.5 115.5 0 0 1-11.8 10.3c-.7.5-.6 1.8.5 2.2 8.3 3 16.4 8.5 39.6 8.3 23.5-.2 31.8-5.6 39.2-8.1.5-.2 1-.5 1.3-1a1 1 0 0 0 .1-.8 2 2 0 0 0-.6-.8c-4.3-3.5-8.8-6.3-11.8-10.4-.3-.5-.9-.6-1.5-.5zm0 .5c.5 0 1 0 1.1.3 3 4.3 7.7 7 11.9 10.5l.4.7a.5.5 0 0 1 0 .4c-.1.3-.6.6-1 .7-7.6 2.6-15.7 8-39 8.2-23.2.2-31.2-5.3-39.5-8.3-.8-.4-.7-1.2-.4-1.4 4.2-3.2 8.2-6.8 11.8-10.4a2.5 2.5 0 0 1 1.1-.6h1.2a68 68 0 0 0 25 5.6c8.7 0 17-2.2 26-5.3a6.7 6.7 0 0 1 1.5-.4z"/>
|
||||
<path d="M269.7 114.6c0-1.4 2-1.5 1.8.4-.3 2.3 4.5 8.3 4.9 12 .3 2.5-1.5 4.6-3.2 6a6.6 6.6 0 0 1-6.8.5c-.9-.8-1.7-3.3-1-4.3.2-.3 1.3 3.7 3.7 3.7 3.3 0 6-2.5 6-4.7.2-3.8-5.3-9.8-5.4-13.6zm9.5 9.4c.6-.4 1.4 1.3.8 1.7-.5.3-1.5-1.3-.8-1.8zm1.5-3.5c-.3.2-.8 0-.7-.2a12 12 0 0 1 3.6-3.3c.4-.2 1 .4.8.7a11 11 0 0 1-3.7 2.8zm12.6-10c.3-.6 2.1-1.3 2.6-1.7.4-.5.6.4.4.7-.3.7-1.9 1.7-2.6 1.8-.3 0-.6-.4-.4-.7zm4.3.3a8.3 8.3 0 0 1 2.5-3.4c.5-.3 1.3 0 1.1.4a9 9 0 0 1-2.9 3.3c-.3.3-.8 0-.7-.3zm-3.7 2.7c-.3.2-.1.7.1.8.6.2 1.5.2 2 0 .6-.4.3-2.9-.5-1.6-.6.8-1 .6-1.6.8zm-7.3 5.6c-1.3-1 .4-2.4 1.7-1.4 2.7 2-4 9.8-7.6 13.4-.7.7-1.3-1-.4-1.9a33.7 33.7 0 0 0 6.7-7.6c.4-.5.7-1.6-.4-2.5zm15.3-6.6c.1-1-1.6 0-1.6-1.3 0-.7 1.9-1.2 2.7-.4 1.3 1.4.3 3.7-2 3.9-1.8 0-5 2.7-4.5 3.2.5.7 5.4 1.1 8.3.7 1.8-.3 1.4 1.3-.4 1.5-1.8.2-3.2 0-4.8.6-2 .5-2.8 3-3.9 4-.2.2-.8-.8-.6-1.2.8-1.2 2-3 3.4-3.6.8-.3-2.4-.4-3.4-.7-.8-.2-.6-1.3-.3-1.9.4-.8 3.4-3.9 4.7-3.8 1.1 0 2.3-.3 2.4-1zm5 .2c.6-.5 1-1.3 1.5-1.8.3-.3.9 0 .8.8-.1.7-1 1.2-1.5 1.7-.5.3-1-.4-.7-.7zm6.5-2.3c.9 0 1 1.6.2 1.8-.6.2-1-1.7-.2-1.8zm-2.1 5c0 1.5.7 1.4 2 1.3 1.3 0 2.4 0 2.4-1.2 0-1.3-.7-2.5-1-1.6-.1.8-.3 2.2-.8 1.6-.4-.5-.2-.6-1 .2-.5.5-.5-.2-.8-.6-.2-.3-.8.2-.8.4zm-9.2 7.2c-.3 1.9 0 4.5.9 4.5 1.2 0 3.6-4 4.8-6.2.7-1.2 1.8-1.4 1.3-.1-.7 1.9-.6 6 0 7.2.4.6 3-.6 3.4-1.5.8-1.7.1-4.8.4-6.7.1-1.2 1.3-1.5 1.2-.3a75.6 75.6 0 0 0-.1 7.5c0 1 2.9 2.4 3.3-.6.2-1.8 1.2-3.7 0-5.7-.8-1.3 1.1-1.2 2.1.6.7 1.2-.6 3.2-.5 4.7 0 2.4-1.8 3.8-3.1 3.8-1.2 0-2-1.5-3-1.5s-2.2 1.7-3 1.6c-3.6-.2-1.7-5.3-2.8-5.4-1.2 0-2.5 5-4 4.9-1.4-.2-3-4.2-2.3-5.8.5-1.6 1.5-2 1.4-1zm16.9-8c-1.7-1 0-3.7.9-2.8 1.6 2 3.2 6.5 4.4 6.9.7.2.6-3.4 1.1-5 .4-1.3 1.8-.9 1.6.7-.1.5-2 6.4-1.8 6.6a47.1 47.1 0 0 1 3.3 7.8c.3 1.2-1.1.4-1.3.2-.9-1.4-2.4-6.5-2.4-6.2l-1.7 7.7c-.2 1-1.7.8-1.3-1 .3-1.4 2.3-8.3 2.2-8.6a17.2 17.2 0 0 0-5-6.3z"/>
|
||||
<path d="M322 131.2c-.4 0-1.2 1 1.2 1.5 3.1.6 6.6-.5 7.6-3.6 1.3-3.7 2-7.2 2.7-8.5.8-1.5 1.8-1.4 1-3.6-.5-1.7-1.5-1.2-1.7-.3-.5 2.3-2.6 10-3.3 11.3-1.2 2.6-3.7 3.6-7.5 3.2z"/>
|
||||
<path d="M328.4 119c-.4-.7-1.2 0-1 .7a1.2 1.2 0 0 0 1.2 1c.7 0 2.2.1 2.2-1 0-.8-.7-1.5-1.1-.6-.5.8-1 .7-1.3 0zm.7-3c-.2.2 0 1.1.3 1a7 7 0 0 0 3.3-.8c.2-.2.1-.7-.2-.7-1 0-2.6 0-3.4.5zm8.8 2.3c.8-1.2 2.8-1.3 2 .4a614.3 614.3 0 0 1-6.3 12.3c-.8 1.4-1.4.7-.8-.4.7-1.4 4.9-12 5.1-12.3z"/>
|
||||
<path d="M330.2 133c-.2-.8-1.5-2-1.3.2.2 3.8 5.5 2.6 7 1.3s.3 4.3 2.2 4.9c1 .3 3-1.1 4-2.4 2.7-3.5 4.5-8.6 7-12 1-1.4-.5-2.4-1-1.3-2.4 3.8-5.2 11.6-8.3 13.6-2.5 1.6-1.7-2-1.8-3.2-.1-.8-1.1-2-2.4-.9a5.5 5.5 0 0 1-3.7 1.2c-.7 0-1.4 0-1.7-1.4z"/>
|
||||
<path d="M339.6 126c0-.3-1.1-.4-1 .7 0 .8 1 1 1.1 1 1.5-1.2-.3-.6-.1-1.8zm-2.3 4.4c-.3 0-.6 1 .2 1.1l3.9-.2c.4 0 .6-.9-.4-.8-1.2 0-2.7-.3-3.7 0zm-62-16.6c.5 0 1.6 1.4 1.5 1.9 0 .2-1.2 0-1.5-.3-.3-.3-.2-1.6 0-1.6zm-5.3 10.4c-1 .6.2 1.7 1 1.2 2.8-1.9 7-3.8 8-7.5.3-1.2 1.4-3.1 2.5-3.5 1-.5 2.6 1.9 3.6 0 .6-1 2.7.7 3.2-.4.6-1.3.3-2 .3-3.4 0-.8-.7-1-1.2.3-.2.6 0 1.2-.1 1.6-.2.2-.6.4-1 .2-.2-.2 0-.7-.6-1-.2 0-.6-.1-.8.2-.7 1.3-1 2.5-2.1 1-.9-1-1.4-3.1-2-.3-.2 1-1.7 2.4-2.6 2.4-1.1 0-.8-3-3.2-2.5-1.3.3-1.2 2.7-1 3.5.3 1.3 4 .4 3.7 1.2-.6 2.7-4.4 5.4-7.7 7zm-22.7 13.2c-.1.5.5 1.7 1.1 1.8.6 0 1-1.3.8-1.8-.2-.3-1.8-.3-1.9 0zm3.3 4.9c-.4-.4-1.6.7-.6 1.5.5.5 2.5 1.1 3 .2.8-1.2-.7-5.5 0-6 .5-.5 2.8 2.8 4 3 2.7.4 2-4.6 5-4.2 1.9.2 2.1-2.2 1.8-3.8-.2-1.5-2.6-3.6-3.7-4.6-1.4-1.2-2.1 1-1.2 1.6 1.2 1 3.3 2.9 3.6 4.1.1.6-1.4 1.8-2 1.5-1.4-.8-2.6-4-3.8-4.7-.4-.2-1.4.3-1 1.3.6 1.1 3 2.7 3.1 3.9.1 1-1 3.2-1.8 3.2-.9 0-3-2.7-3.7-4-.4-.5-1.5-.5-1.7.4a22 22 0 0 0 .5 5.5c.2 1.6-.9 1.7-1.5 1.1zm-4-8.6c-.4.4.8 1.2 1 1 .4-.4 2.1-2.3 1.8-3-.3-.6-2.6-2-3-1.3-.7 1.1 2.2 1.7 1.7 2a7 7 0 0 0-1.5 1.3zm4.1-8.4s.8 2.5 1.4 1.4c.4-.7-1.4-1.4-1.4-1.4zm1.2 4c-.2 0-1 .7-.5 1 .8.4 2.9.8 2.4-.7-.3-.9 3.2 0 2.3-2.4a3.7 3.7 0 0 0-1.7-1.7c-.4 0-1.5.5-.8.9.5.2 2 1.1 1.5 1.7-.7.6-1.1-.3-1.9-.1-.4 0-.1 1.2-.4 1.5 0 .2-.7-.4-.9-.3zm5.5-9.5a3.5 3.5 0 0 0-1.2 2c0 .2.3.6.5.5a3.2 3.2 0 0 0 1.2-1.9c0-.3-.2-.8-.5-.6zm2.8-.3c-.8-1 1-2.6 1.7-.5.5 1.3 5.5 7.9 6.5 10.1.8 1.5 0 2.1-.9 1-2.5-3.2-4.6-7.2-7.3-10.6zm5.2.1c.9-1 2.7-3 2.2-4-.4-1-1.5-1-1.7-.7-1 1.3.8 1 .5 1.4-.5 1-1 1.6-1.3 2.6-.1.3.1.9.3.7zm77.8 3.2c-.7-.5.6-3 1.5-2 2.3 2.7 3.4 11.6 4.1 18.3 0 0-1 .9-1 .7 0-3.5-1.5-14.4-4.6-17zm-53.1-8.6c-.8-1.8 1.1-2.4 1.4-1.2 1.3 5.8 4.5 10.2 7 14.1.7 1.2 0 2-1.7.8-1.2-.8-2.5-3.9-3-4-1.2-.2-3.8 5-9.1 3.5-1.4-.4-1.3-4.5-1.4-6.3 0-.9 1-1 1 0 0 1.7 0 5.2 2.1 5.4 1.8 0 5.6-2.4 6.4-4.4.8-2-1.9-5.9-2.7-8z"/>
|
||||
<path d="M344.6 138.4c.4-1.2 6.1-10.8 6.9-12.9.4-1 2 1.8.4 3.3-1.4 1.2-5.5 8-6.3 10.4-.4 1-1.4.5-1-.8z"/>
|
||||
<path d="M354.3 129.3c1-4 3.6.6 1.3 2.8-3.4 3.4-4.5 9.9-10 10.9-1.4.3-4-.7-4.8-1.3-.3-.2.2-1.6 1.1-.9 1.3 1 4.1 1.3 5.6.1a25.4 25.4 0 0 0 6.8-11.6zm-57 12.7c-.3.3-1 .3-1.1.7-.3 1.4 0 2.2-.3 3.6s-1.3 1.4-1.2.3c0-1.4 1.3-3.5.4-3.6-.6-.1-1-.9-.4-1.3 1.1-.7 1.7-.6 2.4-.4.3.1.4.5.2.7z"/>
|
||||
<path d="M296.5 140c-1.4 1.4-2.8 1.9-4.1 3.5-.6.6-.5 1.5-.9 2.4-.3.9-1.4 1-1.7.9-.5-.4-.4-2-1-1.2-.6.9-.9 2-1.7 2-.7 0-2-1.5-1.3-1.5 2.3-.3 2.2-2 3-2.2 1-.1 1 1.5 1.7 1.2.4-.2.7-2.1 1.2-2.6 1.5-1.6 2.7-2.4 4.3-3.6.7-.6 1.3.5.5 1.2zm5.3 5c-1.2.2-1 1.7-.6 1.8.5.3 1.4.4 1.7-1.3.2-.7.3 3.5 1.8 1.9 1-1 3.1.2 4-1 .7-.9 1-1.5.4-2.7-.2-.3-1-.2-1 .7 0 .8-.5 1.7-1.3 1.6-.4-.1.2-1.9-.2-2.4a.5.5 0 0 0-.7 0c-.3.4.3 2.2-.6 2.4-1.2.2-.6-1.2-1-1.4-1.7-.8-1.8.2-2.5.3zm9-3c.9-.2.6-.2 2-1.3.5-.4.6.8.5 1.3 0 .7-1 .2-1.3.9-.4.9-.2 3-.4 3.8 0 .4-.8.4-.8 0-.2-1 .1-2 0-3.3 0-.4-.5-1.1 0-1.3zm-5-2.5c-.2.9-.2 1.6-.2 2.3 0 .5 1 .2 1 .1 0-.8.2-2 0-2.3-.2-.1-.7-.3-.8-.1z"/>
|
||||
<path d="m299.5 130.2-1.4 5.6-2-3.8v3.9l-4.4-5.2 1.5 5.6-4-3.4 2.2 3.8-7-4.5 4.4 5.2-5.6-2.8 4 3.4-9-3.4 8.7 4.3a29 29 0 0 1 12.6-2.6c4.9 0 9.3 1 12.5 2.6l8.8-4.3-9 3.4 4-3.4-5.5 2.8 4.3-5.2-7 4.5 2.2-3.8-4 3.3 1.5-5.5-4.3 5.2V132l-2 3.8-1.5-5.6z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path fill="#fff" d="m311.3 295-.3 2.6h-.4l-.1-1.8a9.3 9.3 0 0 0-.5-1.6 7.3 7.3 0 0 0-.5-1.3l-1-1.4.8-2.2a6.6 6.6 0 0 1 1.5 2.4 9.4 9.4 0 0 1 .5 3.2m7-4.2c0 .7-.2 1.2-.5 1.5-.2.3-.6.6-1.3.7l.4 1.5a6.7 6.7 0 0 1 0 2 22.5 22.5 0 0 1-.1 1.3h-.4a8.2 8.2 0 0 0-.1-1.3 5.5 5.5 0 0 0-.2-1l-.4-1a10.5 10.5 0 0 0-.7-1.4l-1-1.7.6-2 1 1c.3.2.6.3 1 .3.8 0 1.2-.4 1.2-1.3h.4v1.4m6.4 4.8-.5 2.1c-.4 0-.6-.3-.8-.7l-.4-1.3a12.4 12.4 0 0 1-.1-1.7 4 4 0 0 1-1 .2 2 2 0 0 1-1.3-.4 1.3 1.3 0 0 1-.5-1c0-.9.3-1.7.7-2.3.5-.7 1-1 1.5-1.1.5 0 .8.1 1 .4a2 2 0 0 1 .3.9v2c0 .9.1 1.5.3 1.9 0 .3.3.6.8 1m-2-3.5c0-.6-.3-.8-.8-.8a1 1 0 0 0-.6.1c-.2.1-.2.2-.2.3 0 .3.3.5 1 .5l.6-.1m8.7 3-.3 2.6c-.5-.4-1-1-1.4-2a25.4 25.4 0 0 1-1.3-4.1 52.8 52.8 0 0 1-1.8 5.5 2.9 2.9 0 0 1-.8.7v-2.5c.6-.7.9-1.1 1-1.5a7.6 7.6 0 0 0 .8-1.7l.5-2.7h.4l.9 2.7c.2.6.5 1.2.9 1.6l1 1.4"/>
|
||||
<path fill="#bf0000" d="M350.8 319.4c.4.4.6.8.7 1.2l.4 1.6-.8.1a7.8 7.8 0 0 0-1-1.5 18.8 18.8 0 0 0-1.1-1.2 46 46 0 0 0-1.7-1.5 34.4 34.4 0 0 0-2-1.7c-.4-.2-.6-.4-.6-.5a1.9 1.9 0 0 1-.3-.8 11.2 11.2 0 0 1-.2-1.6l2.7 2.2a44.3 44.3 0 0 1 2.5 2.2l1.4 1.5m-9.5-5.8-.2 2H338l.3-2h3m8.4 8.9-7.6 2.3-1.3-2 6.5-2-.7-.8a2.8 2.8 0 0 0-.9-.6 1.4 1.4 0 0 1-.4 1 2 2 0 0 1-1 .6 3.4 3.4 0 0 1-1.8 0 2 2 0 0 1-1.3-.7 4 4 0 0 1-.7-2.2c0-1 .3-1.6.9-1.8.7-.2 1.8 0 3 .7a8.1 8.1 0 0 1 3 2.4l2.3 3.1m-5.8-4a3.8 3.8 0 0 0-.8-.3 1.1 1.1 0 0 0-.6 0 .7.7 0 0 0-.5.3.5.5 0 0 0 0 .6l.5.2h.6l.4-.3.4-.5m-8-1.6-.5 2-3.2-.3.5-2 3.1.3m7.5 7.7-1.7.4a5.3 5.3 0 0 1-1.7 0 3.6 3.6 0 0 1-1.5-.4c-.3.5-.8 1-1.5 1.2a7.4 7.4 0 0 1-1.6.6l-1.2.3-1-2 1.1-.3a9.1 9.1 0 0 0 1.3-.4l.9-.5-1-.5h-.7a.4.4 0 0 0-.2 0 .6.6 0 0 0-.2.3h-.5c-.5-.8-.6-1.5-.3-2s.9-.8 2-1a6.8 6.8 0 0 1 2.6-.2c.8.1 1.3.4 1.5.9.2.2.2.5.2.7l-.4 1.2h.5a2 2 0 0 0 .6 0l1.7-.3 1 2m-8 1.8-1.6.3a3 3 0 0 1-2.2-.4 5.5 5.5 0 0 1-1.7-2.6l-.8-2.2a2 2 0 0 0-.8-1 4.6 4.6 0 0 0-.9-.5l.6-2.1c.6.3 1 .6 1.4 1l1 1.7.5 1.5 1.1 2.2c.3.3.7.4 1 .3l1.7-.2.7 2m-7-7.5-1 1.9-3-.7 1-1.9 3 .7m1.8 8.4-7.5.7-.4-2 6.2-.7a2.3 2.3 0 0 0-.6-.8 8.3 8.3 0 0 0-1-.6l.5-2c.7.4 1.2.9 1.6 1.3.3.5.6 1.2.8 2.1l.4 2m-6 1a17 17 0 0 1-2.2-.2 10.5 10.5 0 0 1-1.7-.5 5.6 5.6 0 0 1-1.3.4 9.9 9.9 0 0 1-1.7 0h-2a2.5 2.5 0 0 1-1.2-.3c-.3-.2-.5-.5-.8-1a4.1 4.1 0 0 1-1.5 1l-1.7.1h-1.7l.2-2.1h1.7c.8 0 1.5 0 2.1-.4a2 2 0 0 0 1.3-1.8l.7.1a30.2 30.2 0 0 0-.1 1.3c0 .3 0 .5.3.7.3.2.6.3 1 .3h1.5c1 0 1.6 0 2-.2.6-.2.9-.5 1-1.1l.1-.4s.3 0 .5-.2l.5-.2v.4a8.9 8.9 0 0 1 0 .3l-.3 1.1a12.4 12.4 0 0 0 2 .5c.1-.2 0-.4-.1-.7l-.3-.6a.5.5 0 0 1 .1-.3l.3-.2 1-.9.5 1v1l-.2 2.9m-11.3-8.7-2 1.3-1.3-.9-1.4 1-1.9-1 1.8-1.3 1.5.8 1.5-1 1.8 1m-3 8.2-7.3-1.2.8-2 6.2 1c0-.4 0-.7-.2-1a5.2 5.2 0 0 0-.5-.8l1.6-1.7c.4.6.6 1 .7 1.6 0 .5-.2 1.2-.5 2.1l-.8 2m-6.1-1-1.6-.3c-.9-.2-1.4-.6-1.5-1.2-.2-.6.1-1.5.8-2.8l1.2-2c.3-.5.4-.9.3-1.2a2.2 2.2 0 0 0-.3-.7l2.2-1.6c.3.5.3 1 .3 1.4 0 .5-.3 1.1-.7 1.8l-.8 1.4a5.8 5.8 0 0 0-.9 2.2c0 .4.2.6.5.7l1.6.4-1.1 2m-3.8-8-2.5 1.1-1.8-1.7 2.6-1 1.7 1.7m-1 6.6a6.8 6.8 0 0 1-1.6 1.4 4.2 4.2 0 0 1-1.7.6l-2.4-.1a14.8 14.8 0 0 1-2.8-.7 7.7 7.7 0 0 1-3.4-2c-.6-.8-.6-1.5 0-2.2a7 7 0 0 1 2-1.6c.8-.5 2-1 3.8-1.6l.4.5-2.8 1.2c-.5.3-1 .6-1.3 1-.4.4-.3 1 .2 1.6a10.5 10.5 0 0 0 6.3 2.2c1.2 0 2-.3 2.3-.7.3-.3.4-.6.5-1l.2-1.6 2.5-1.5a8 8 0 0 1-.1 1.5 4.4 4.4 0 0 1-1 1.6l-1.2 1.4"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 21 KiB |
@@ -1,14 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ag" viewBox="0 0 640 480">
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill-opacity=".7" d="M-79.7 0H603v512H-79.7z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g fill-rule="evenodd" clip-path="url(#a)" transform="translate(74.7) scale(.9375)">
|
||||
<path fill="#fff" d="M-120 0h763.3v511.5H-120z"/>
|
||||
<path d="M-118.3.6h760.9v216.1h-761z"/>
|
||||
<path fill="#0061ff" d="M21.3 203.2h505V317h-505z"/>
|
||||
<path fill="#e20000" d="M642.8 1.8V512H262L642.8 1.7zm-761.5 0V512H262L-118.7 1.7z"/>
|
||||
<path fill="#ffd600" d="M440.4 203.3 364 184l64.9-49-79.7 11.4 41-69.5-70.7 41L332.3 37l-47.9 63.8-19.3-74-21.7 76.3-47.8-65 13.7 83.2L138.5 78l41 69.5-77.4-12.5 63.8 47.8L86 203.3h354.3z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 740 B |
@@ -1,758 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ai" viewBox="0 0 640 480">
|
||||
<path fill="#012169" d="M0 0h640v480H0z"/>
|
||||
<path fill="#49497d" d="m484.3 180.4 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m486.3 180.4 2 2z"/>
|
||||
<path fill="#262678" d="m480.2 182.4 2 2z"/>
|
||||
<path fill="#808067" d="m482.3 182.4 2 2z"/>
|
||||
<path fill="#58587b" d="m488.3 182.4 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m413.2 184.5 2 2z"/>
|
||||
<path fill="#1b1b74" d="m476.2 184.5 2 2z"/>
|
||||
<path fill="#6e6c70" d="m478.2 184.5 2 2z"/>
|
||||
<path fill="#cc3" d="M416.8 188c0 52.6-6 111.7 33 152.8 8 8.4 23.4 27.7 36.5 27 13.7-.8 31.4-21.1 39.2-31 34-44.8 28.7-98.2 29.8-150.2-15.3 6.9-23 9.2-36.4 9-10 1-25.3-5.5-34.5-10-6 4-14.7 8.9-30.4 9.4-18 .8-23.8-2.3-37.2-7z"/>
|
||||
<path fill="#99994e" d="m490.4 184.5 2 2z"/>
|
||||
<path fill="#49497d" d="m492.4 184.5 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m555.3 184.5 2 2z"/>
|
||||
<path fill="#a4a43d" d="m415.3 186.5 2 2z"/>
|
||||
<path fill="#6e6c70" d="m417.3 186.5 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m419.3 186.5 2 2z"/>
|
||||
<path fill="#1b1b74" d="m472 186.5 2 2z"/>
|
||||
<path fill="#6e6c70" d="m474 186.5 2 2z"/>
|
||||
<path fill="#a4a43d" d="m476.2 186.5 2 2z"/>
|
||||
<path fill="#d0d045" d="m484.3 186.5 2 2z"/>
|
||||
<path fill="#a4a43d" d="m492.4 186.5 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m494.4 186.5 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m496.5 186.5 2 2z"/>
|
||||
<path fill="#262678" d="m549.2 186.5 2 2z"/>
|
||||
<path fill="#53527c" d="m551.3 186.5 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m553.3 186.5 2 2z"/>
|
||||
<path fill="#737370" d="m423.4 188.6 2 2z"/>
|
||||
<path fill="#53527c" d="m425.4 188.6 2 2z"/>
|
||||
<path fill="#1b1b74" d="m427.4 188.6 2 2z"/>
|
||||
<path fill="#262678" d="m468 188.6 2 2z"/>
|
||||
<path fill="#6e6c70" d="m470 188.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m472 188.6 2 2z"/>
|
||||
<path fill="#e5e59d" d="m482.3 188.6 2 2z"/>
|
||||
<path fill="#fff" d="M420.9 193.8c-1 27.6-.2 58.6 4 88 4.9 15.5 4.2 24 11.3 33.2l99-.8c6-9.7 10.5-24.4 11-30.3 5.6-29.7 5.7-62.6 5.9-92a62 62 0 0 1-35.7 7.4 69 69 0 0 1-30.5-9.2c-9.5 5.6-12.8 8.2-28.4 8.9-12.2.6-22 1.6-36.6-5.2z"/>
|
||||
<path fill="#f2f1d7" d="m486.3 188.6 2 2z"/>
|
||||
<path fill="#d9d868" d="m488.3 188.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m496.5 188.6 2 2z"/>
|
||||
<path fill="#99994e" d="m498.5 188.6 2 2z"/>
|
||||
<path fill="#49497d" d="m500.5 188.6 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m502.5 188.6 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m543.2 188.6 2 2z"/>
|
||||
<path fill="#667" d="m545.2 188.6 2 2z"/>
|
||||
<path fill="#99994e" d="m547.2 188.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m549.2 188.6 2 2-2-2m-121.8 2 2 2z"/>
|
||||
<path fill="#99994e" d="m429.5 190.6 2 2z"/>
|
||||
<path fill="#6e6c70" d="m431.5 190.6 2 2z"/>
|
||||
<path fill="#49497d" d="m433.5 190.6 2 2z"/>
|
||||
<path fill="#1b1b74" d="m435.5 190.6 2 2-2-2m26.4 0 2 2z"/>
|
||||
<path fill="#53527c" d="m463.9 190.6 2 2-2-2z"/>
|
||||
<path fill="#8d8d5b" d="m466 190.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m468 190.6 2 2z"/>
|
||||
<path fill="#e5e59d" d="m478.2 190.6 2 2z"/>
|
||||
<path fill="#fbfaf2" d="m480.2 190.6 2 2z"/>
|
||||
<path fill="#f2f1d2" d="m490.4 190.6 2 2z"/>
|
||||
<path fill="#d9d868" d="m492.4 190.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m502.5 190.6 2 2z"/>
|
||||
<path fill="#6e6c70" d="m504.6 190.6 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m506.6 190.6 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m533 190.6 2 2z"/>
|
||||
<path fill="#32327b" d="m535 190.6 2 2z"/>
|
||||
<path fill="#58587b" d="m537 190.6 2 2z"/>
|
||||
<path fill="#808067" d="m539 190.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m542.5 191.2 1.3.7z"/>
|
||||
<path fill="#dddc7a" d="m419.3 192.6 2 2z"/>
|
||||
<path fill="#d0d045" d="m421.3 192.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m436.9 193.2 1.4.7z"/>
|
||||
<path fill="#808067" d="m439.6 192.6 2 2z"/>
|
||||
<path fill="#667" d="m441.6 192.6 2 2z"/>
|
||||
<path fill="#58587b" d="m443.7 192.6 2 2z"/>
|
||||
<path fill="#49497d" d="m445.7 192.6 2 2z"/>
|
||||
<path fill="#737370" d="m457.9 192.6 2 2z"/>
|
||||
<path fill="#99994e" d="m459.9 192.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m461.9 192.6 2 2z"/>
|
||||
<path fill="#e5e59d" d="m474 192.6 2 2z"/>
|
||||
<path fill="#fbfaf2" d="m476.2 192.6 2 2z"/>
|
||||
<path fill="#f2f1d2" d="m494.4 192.6 2 2z"/>
|
||||
<path fill="#d9d868" d="m496.5 192.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m507.9 193.2 1.4.7-1.3-.7z"/>
|
||||
<path fill="#808067" d="m510.7 192.6 2 2z"/>
|
||||
<path fill="#667" d="m512.7 192.6 2 2z"/>
|
||||
<path fill="#58587b" d="m514.7 192.6 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m516.8 192.6 2 2z"/>
|
||||
<path fill="#58587b" d="m526.2 193.2 1.4.7z"/>
|
||||
<path fill="#737370" d="m528.9 192.6 2 2z"/>
|
||||
<path fill="#99994e" d="m530.9 192.6 2 2-2-2z"/>
|
||||
<path fill="#a4a43d" d="m533 192.6 2 2z"/>
|
||||
<path fill="#dddc7a" d="m549.2 192.6 2 2z"/>
|
||||
<path fill="#d0d045" d="m551.3 192.6 2 2z"/>
|
||||
<path fill="#f2f1d7" d="m423.4 194.6 2 2z"/>
|
||||
<path fill="#e0dea1" d="m425.4 194.6 2 2z"/>
|
||||
<path fill="#dddc7a" d="m427.4 194.6 2 2z"/>
|
||||
<path fill="#d9d868" d="m468 194.6 2 2z"/>
|
||||
<path fill="#e5e3af" d="m470 194.6 2 2z"/>
|
||||
<path fill="#f6f6e4" d="m498.5 194.6 2 2z"/>
|
||||
<path fill="#e1e18c" d="m500.5 194.6 2 2z"/>
|
||||
<path fill="#d4d456" d="m541 194.6 2 2z"/>
|
||||
<path fill="#e1e18c" d="m543.2 194.6 2 2z"/>
|
||||
<path fill="#eeedc1" d="m545.2 194.6 2 2z"/>
|
||||
<path fill="#f2f1d2" d="m431.5 196.6 2 2z"/>
|
||||
<path fill="#e0dea1" d="m433.5 196.6 2 2z"/>
|
||||
<path fill="#dddc7a" d="m435.5 196.6 2 2z"/>
|
||||
<path fill="#d0d045" d="m437.6 196.6 2 2z"/>
|
||||
<path fill="#dddc7a" d="m461.9 196.6 2 2z"/>
|
||||
<path fill="#e5e3af" d="m463.9 196.6 2 2-2-2z"/>
|
||||
<path fill="#f6f6e4" d="m466 196.6 2 2z"/>
|
||||
<path fill="#eeedc1" d="m504.6 196.6 2 2z"/>
|
||||
<path fill="#e1e18c" d="m506.6 196.6 2 2z"/>
|
||||
<path fill="#d4d456" d="m508.6 196.6 2 2z"/>
|
||||
<path fill="#d9d868" d="m533 196.6 2 2z"/>
|
||||
<path fill="#e1e18c" d="m535 196.6 2 2z"/>
|
||||
<path fill="#eeedc1" d="m537 196.6 2 2z"/>
|
||||
<path fill="#f6f6e4" d="m539 196.6 2 2z"/>
|
||||
<path fill="#f2f1d7" d="m441.6 198.6 2 2-2-2z"/>
|
||||
<path fill="#f2f1d2" d="m443.7 198.6 2 2-2-2z"/>
|
||||
<path fill="#eeedc1" d="m445.7 198.6 2 2-2-2z"/>
|
||||
<path fill="#f2f1d2" d="m455.2 199.3 1.3.7z"/>
|
||||
<path fill="#fbfaf2" d="m457.9 198.6 2 2-2-2z"/>
|
||||
<path fill="#fef8f1" d="m468 198.6 4 4v-4h-4z"/>
|
||||
<path fill="#f2f1d7" d="m512.7 198.6 2 2-2-2z"/>
|
||||
<path fill="#f2f1d2" d="m514.7 198.6 2 2-2-2z"/>
|
||||
<path fill="#e5e3af" d="m516.8 198.6 2 2-2-2z"/>
|
||||
<path fill="#e5e59d" d="m520.2 199.3 1.3.7-1.4-.7z"/>
|
||||
<path fill="#e0dea1" d="m522.9 198.6 2 2-2-2z"/>
|
||||
<path fill="#f2f1d2" d="m526.2 199.3 1.4.7z"/>
|
||||
<path fill="#fbfaf2" d="m528.9 198.6 2 2-2-2z"/>
|
||||
<path fill="#fef8f1" d="m463.9 200.7 2 2-2-2z"/>
|
||||
<path fill="#fbbe66" d="m466 200.7 2 2z"/>
|
||||
<path fill="#fbc477" d="m463.9 202.7 2 2-2-2z"/>
|
||||
<path fill="#fcb144" d="m468 202.7 2 2z"/>
|
||||
<path fill="#fe9f11" d="m463.9 204.8 2 2-2-2z"/>
|
||||
<path fill="#fea522" d="m468 204.8 2 2z"/>
|
||||
<path fill="#fae3c9" d="m461.9 206.8 2 2-2-2m8.2 0 2 2z"/>
|
||||
<path fill="#fbead6" d="m480.2 206.8 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m482.3 206.8 2 2z"/>
|
||||
<path fill="#fae3c9" d="m490.4 206.8 2 2z"/>
|
||||
<path fill="#fef8f1" d="m492.4 206.8 2 2z"/>
|
||||
<path fill="#f9d099" d="m461.9 208.8 2 2z"/>
|
||||
<path fill="#fdab33" d="m470 208.8 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m474 208.8 2 2z"/>
|
||||
<path fill="#fbc477" d="m476.2 208.8 2 2z"/>
|
||||
<path fill="#fea522" d="m478.2 208.8 2 2z"/>
|
||||
<path fill="#fcb755" d="m494.4 208.8 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m496.5 208.8 2 2z"/>
|
||||
<path fill="#faca88" d="m461.9 210.9 2 2z"/>
|
||||
<path fill="#fea522" d="m472 210.9 2 2-2-2m26.5 0 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m500.5 210.9 2 2z"/>
|
||||
<path fill="#f6f6e4" d="m419.3 212.9 2 2z"/>
|
||||
<path fill="#fbc477" d="m461.9 212.9 2 2z"/>
|
||||
<path fill="#fbbe66" d="m502.5 212.9 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m504.6 212.9 2 2z"/>
|
||||
<path fill="#faca88" d="m461.9 214.9 2 2z"/>
|
||||
<path fill="#fcb755" d="m508.6 214.9 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m510.7 214.9 2 2z"/>
|
||||
<path fill="#fef8f1" d="m459.9 217 2 2z"/>
|
||||
<path fill="#fe9f11" d="m461.9 217 2 2z"/>
|
||||
<path fill="#fdab33" d="m518.8 217 2 2z"/>
|
||||
<path fill="#fcb144" d="m520.9 217 2 2z"/>
|
||||
<path fill="#fbc477" d="m522.9 217 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m524.9 217 4 4z"/>
|
||||
<path fill="#fef8f1" d="m526.9 217 2 2z"/>
|
||||
<path fill="#fcb144" d="m459.9 219 2 2z"/>
|
||||
<path fill="#fdab33" d="m488.3 219 2 2z"/>
|
||||
<path fill="#fbc477" d="m490.4 219 2 2zm8 0 2 2-2-2z"/>
|
||||
<path fill="#fea522" d="m500.5 219 2 2z"/>
|
||||
<path fill="#fae3c9" d="m457.9 221 2 2z"/>
|
||||
<path fill="#fcb144" d="m484.3 221 2 2z"/>
|
||||
<path fill="#fae3c9" d="m486.3 221 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m502.5 221 2 2z"/>
|
||||
<path fill="#fdab33" d="m504.6 221 2 2z"/>
|
||||
<path fill="#fe9f11" d="m516.8 221 2 2z"/>
|
||||
<path fill="#fcb755" d="m518.8 221 2 2z"/>
|
||||
<path fill="#f9d099" d="m520.9 221 2 2z"/>
|
||||
<path fill="#fbead6" d="m522.9 221 2 2z"/>
|
||||
<path fill="#fcb144" d="m457.9 223 2 2z"/>
|
||||
<path fill="#fbbe66" d="m482.3 223 2 2z"/>
|
||||
<path fill="#f9d099" d="m506.6 223 2 2z"/>
|
||||
<path fill="#fbead6" d="m514.7 223 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m455.9 225 2 2z"/>
|
||||
<path fill="#fbbe66" d="m480.2 225 2 2z"/>
|
||||
<path fill="#f9d099" d="m508.6 225 2 2z"/>
|
||||
<path fill="#fae3c9" d="m514.7 225 2 2z"/>
|
||||
<path fill="#fbc477" d="m455.9 227 2 2z"/>
|
||||
<path fill="#fcb144" d="m478.2 227 2 2-2-2m32.5 0 2 2z"/>
|
||||
<path fill="#fbbe66" d="m514.7 227 2 2z"/>
|
||||
<path fill="#f6f6e4" d="m419.3 229 2 2z"/>
|
||||
<path fill="#fea522" d="m455.9 229 2 2z"/>
|
||||
<path fill="#fbead6" d="m478.2 229 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m510.7 229 2 2z"/>
|
||||
<path fill="#fef8f1" d="m516.8 229 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m453.9 231.2 2 2z"/>
|
||||
<path fill="#fbbe66" d="m476.2 231.2 2 2z"/>
|
||||
<path fill="#faca88" d="m512.7 231.2 2 2z"/>
|
||||
<path fill="#f9d099" d="m516.8 231.2 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m453.9 233.2 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m476.2 233.2 2 2z"/>
|
||||
<path fill="#fae3c9" d="m486.3 233.2 2 2z"/>
|
||||
<path fill="#fea522" d="m488.3 233.2 2 2z"/>
|
||||
<path fill="#fcb144" d="m490.4 233.2 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m492.4 233.2 2 2z"/>
|
||||
<path fill="#fef8f1" d="m512.7 233.2 2 2z"/>
|
||||
<path fill="#fea522" d="m514.7 233.2 2 2z"/>
|
||||
<path fill="#fdab33" d="m516.8 233.2 2 2z"/>
|
||||
<path fill="#faca88" d="m453.9 235.2-2.1 6 2-6z"/>
|
||||
<path fill="#fea522" d="m474 235.2 2 2z"/>
|
||||
<path fill="#fef8f1" d="m476.2 235.2 2 2z"/>
|
||||
<path fill="#f9d099" d="m486.3 235.2 2 2z"/>
|
||||
<path fill="#fdab33" d="m494.4 235.2 2 2z"/>
|
||||
<path fill="#fae3c9" d="m496.5 235.2 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m514.7 235.2 2 2z"/>
|
||||
<path fill="#f90" d="m516.8 235.2 2 2z"/>
|
||||
<path fill="#fbead6" d="m519.5 236.6.6 1.3z"/>
|
||||
<path fill="#fea522" d="m478.2 237.2 2 2z"/>
|
||||
<path fill="#fbbe66" d="m480.2 237.2 2 2z"/>
|
||||
<path fill="#faca88" d="m482.3 237.2 2 2z"/>
|
||||
<path fill="#fcb144" d="m484.3 237.2 2 2z"/>
|
||||
<path fill="#fae3c9" d="m486.3 237.2 2 2z"/>
|
||||
<path fill="#fe9f11" d="m488.3 237.2 2 2z"/>
|
||||
<path fill="#fdab33" d="m498.5 237.2 2 2z"/>
|
||||
<path fill="#fbc477" d="m500.5 237.2 2 2z"/>
|
||||
<path fill="#faca88" d="m502.5 237.2 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m504.6 237.2 2 2z"/>
|
||||
<path fill="#fae3c9" d="m507.9 237.9 1.4.7-1.3-.7z"/>
|
||||
<path fill="#fef8f1" d="m510.7 237.2 2 2z"/>
|
||||
<path fill="#fbc477" d="m516.8 237.2 2 2z"/>
|
||||
<path fill="#fef8f1" d="m429.5 239.3 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m431.5 239.3 2 2z"/>
|
||||
<path fill="#fcb755" d="m484.3 239.3 2 2z"/>
|
||||
<path fill="#fbead6" d="m488.3 239.3 2 2z"/>
|
||||
<path fill="#fea522" d="m490.4 239.3 2 2z"/>
|
||||
<path fill="#fe9f11" d="m506.6 239.3 2 2z"/>
|
||||
<path fill="#fcb144" d="m508.6 239.3-2 4z"/>
|
||||
<path fill="#fe9f11" d="m512.7 239.3 2 2z"/>
|
||||
<path fill="#fbbe66" d="m514.7 239.3 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m516.8 239.3 2 2z"/>
|
||||
<path fill="#fae3c9" d="m429.5 241.3 2 2z"/>
|
||||
<path fill="#fe9f11" d="m431.5 241.3 4 4z"/>
|
||||
<path fill="#fbead6" d="m433.5 241.3 2 2zm18.3 0 2 2z"/>
|
||||
<path fill="#fae3c9" d="m453.9 241.3 2 2z"/>
|
||||
<path fill="#fe9f11" d="m472 241.3 2 2z"/>
|
||||
<path fill="#fbc477" d="m474 241.3 2 2z"/>
|
||||
<path fill="#fea522" d="m476.2 241.3 2 2z"/>
|
||||
<path fill="#fbc477" d="m482.3 241.3 2 2z"/>
|
||||
<path fill="#fef8f1" d="m484.3 241.3 2 2z"/>
|
||||
<path fill="#fbc477" d="m492.4 241.3 2 2z"/>
|
||||
<path fill="#fff" d="m508.6 241.3 2 2z"/>
|
||||
<path fill="#fdab33" d="m510.7 241.3 2 2z"/>
|
||||
<path fill="#fbc477" d="m518.8 241.3 2 2z"/>
|
||||
<path fill="#fef8f1" d="m429.5 243.3 2 2z"/>
|
||||
<path fill="#fbead6" d="m435.5 243.3 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m445.7 243.3 2 2z"/>
|
||||
<path fill="#fe9f11" d="m455.9 243.3 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m459.2 244 1.4.7z"/>
|
||||
<path fill="#f8dcbb" d="m472 243.3 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m478.2 243.3 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m494.4 243.3 2 2z"/>
|
||||
<path fill="#fdab33" d="m508.6 243.3 2 2z"/>
|
||||
<path fill="#fcb755" d="m520.9 243.3 2 2z"/>
|
||||
<path fill="#fef8f1" d="m522.9 243.3 2 2z"/>
|
||||
<path fill="#53527c" d="m413.2 245.4 2 2z"/>
|
||||
<path fill="#fcb755" d="m431.5 245.4 2 2z"/>
|
||||
<path fill="#fea522" d="m435.5 245.4 2 2z"/>
|
||||
<path fill="#fbead6" d="m443.7 245.4 2 2z"/>
|
||||
<path fill="#fe9f11" d="m447.7 245.4 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m449.8 245.4 2 2z"/>
|
||||
<path fill="#fbbe66" d="m455.9 245.4 2 2z"/>
|
||||
<path fill="#fbc477" d="m457.9 245.4 2 2z"/>
|
||||
<path fill="#fbbe66" d="m459.9 245.4 2 2z"/>
|
||||
<path fill="#fea522" d="m470 245.4 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m496.5 245.4 2 2z"/>
|
||||
<path fill="#fcb144" d="m522.9 245.4 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m555.3 245.4 2 2z"/>
|
||||
<path fill="#e5e3af" d="m419.3 247.4 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m431.5 247.4 2 2z"/>
|
||||
<path fill="#fdab33" d="m437.6 247.4 2 2z"/>
|
||||
<path fill="#fe9f11" d="m443.7 247.4 2 2z"/>
|
||||
<path fill="#faca88" d="m447.7 247.4 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m455.9 247.4 2 2z"/>
|
||||
<path fill="#f9d099" d="m470 247.4 2 2-2-2m28.5 0 2 2z"/>
|
||||
<path fill="#fbbe66" d="m524.9 247.4 2 2z"/>
|
||||
<path fill="#fea522" d="m433.5 249.4 2 2z"/>
|
||||
<path fill="#fdab33" d="m439.6 249.4 2 2z"/>
|
||||
<path fill="#fea522" d="m441.6 249.4 2 2z"/>
|
||||
<path fill="#fe9f11" d="m445.7 249.4 2 2z"/>
|
||||
<path fill="#fef8f1" d="m447.7 249.4 2 2z"/>
|
||||
<path fill="#fbbe66" d="m457.9 249.4 2 2z"/>
|
||||
<path fill="#fef8f1" d="m470 249.4 2 2z"/>
|
||||
<path fill="#fbbe66" d="m500.5 249.4 2 2z"/>
|
||||
<path fill="#f9d099" d="m526.9 249.4 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m433.5 251.5 2 2z"/>
|
||||
<path fill="#f9d099" d="m445.7 251.5 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m457.9 251.5 2 2z"/>
|
||||
<path fill="#fdab33" d="m468 251.5 2 2-2-2m34.5 0 2 2z"/>
|
||||
<path fill="#fbead6" d="m528.9 251.5 2 2z"/>
|
||||
<path fill="#fea522" d="m435.5 253.5 2 2z"/>
|
||||
<path fill="#fe9f11" d="m443.7 253.5 2 2z"/>
|
||||
<path fill="#fcb144" d="m459.9 253.5 2 2z"/>
|
||||
<path fill="#faca88" d="m468 253.5 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m502.5 253.5 2 2z"/>
|
||||
<path fill="#fcb144" d="m528.9 253.5 2 2z"/>
|
||||
<path fill="#d3d079" d="m419.3 255.6 2 2z"/>
|
||||
<path fill="#faca88" d="m435.5 255.6 2 2zm24.4 0 2 2z"/>
|
||||
<path fill="#fae3c9" d="m468 255.6 2 2-2-2m34.5 0 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m530.9 255.6 2 2-2-2z"/>
|
||||
<path fill="#f2f1d7" d="m549.2 255.6 2 2z"/>
|
||||
<path fill="#58587b" d="m556 256.9.7 1.3z"/>
|
||||
<path fill="#d9d868" d="m419.9 258.9.8 1.4-.7-1.4z"/>
|
||||
<path fill="#f8dcbb" d="m435.5 257.6 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m500.5 257.6 2 2z"/>
|
||||
<path fill="#fe9f11" d="m502.5 257.6 2 2z"/>
|
||||
<path fill="#fcb144" d="m530.9 257.6 2 2-2-2z"/>
|
||||
<path fill="#f2f1d2" d="m549.9 258.9.7 1.4z"/>
|
||||
<path fill="#fcf1e4" d="m435.5 259.6 2 2z"/>
|
||||
<path fill="#fef8f1" d="m498.5 259.6 2 2z"/>
|
||||
<path fill="#fe9f11" d="m500.5 259.6 2 2z"/>
|
||||
<path fill="#fdab33" d="m506.6 259.6-2 4z"/>
|
||||
<path fill="#fcb755" d="m508.6 259.6 2 2z"/>
|
||||
<path fill="#fea522" d="m533 259.6 2 2z"/>
|
||||
<path fill="#f9d099" d="m535 259.6 2 2z"/>
|
||||
<path fill="#53527c" d="m555.3 259.6 2 2z"/>
|
||||
<path fill="#808067" d="m415.9 263 .7 1.3z"/>
|
||||
<path fill="#fea522" d="m437.6 261.6 2 2-2-2m6 0 2 2-2-2z"/>
|
||||
<path fill="#fe9f11" d="m466 261.6 2 2z"/>
|
||||
<path fill="#fae3c9" d="m498.5 261.6 2 2z"/>
|
||||
<path fill="#fef8f1" d="m506.6 261.6 2 2z"/>
|
||||
<path fill="#fcb144" d="m510.7 261.6 2 2z"/>
|
||||
<path fill="#fcb755" d="m537 261.6 2 2z"/>
|
||||
<path fill="#fef8f1" d="m539 261.6 4 4z"/>
|
||||
<path fill="#e5e59d" d="m549.9 263 .7 1.3z"/>
|
||||
<path fill="#32327b" d="m556 263 .7 1.3z"/>
|
||||
<path fill="#fcb755" d="m438.3 265 .6 1.4z"/>
|
||||
<path fill="#fef8f1" d="m445.7 263.6 2 2z"/>
|
||||
<path fill="#fbbe66" d="m466 263.6 2 2z"/>
|
||||
<path fill="#fbead6" d="m498.5 263.6 2 2z"/>
|
||||
<path fill="#fe9f11" d="m502.5 263.6 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m504.6 263.6 2 2z"/>
|
||||
<path fill="#fbead6" d="m510.7 263.6 2 2z"/>
|
||||
<path fill="#fdab33" d="m539 263.6 2 2z"/>
|
||||
<path fill="#667" d="m415.3 265.6 2 2-2-2z"/>
|
||||
<path fill="#f6f6e4" d="m421.3 265.6 2 2-2-2z"/>
|
||||
<path fill="#f9d6aa" d="m445.7 265.6 2 2-2-2z"/>
|
||||
<path fill="#fdab33" d="m461.9 265.6 2 2-2-2z"/>
|
||||
<path fill="#fe9f11" d="m463.9 265.6 2 2-2-2z"/>
|
||||
<path fill="#fcf1e4" d="m466 265.6 2 2-2-2z"/>
|
||||
<path fill="#fea522" d="m500.5 265.6 2 2-2-2z"/>
|
||||
<path fill="#faca88" d="m502.5 265.6 2 2-2-2m10.2 0 2 2z"/>
|
||||
<path fill="#fcb144" d="m541 265.6 2 2-2-2z"/>
|
||||
<path fill="#dddc7a" d="m549.2 265.6 2 2-2-2z"/>
|
||||
<path fill="#58587b" d="m415.3 267.7 2 2z"/>
|
||||
<path fill="#f2f1d2" d="m421.3 267.7 2 2z"/>
|
||||
<path fill="#fcb144" d="m438.3 269 .6 1.4z"/>
|
||||
<path fill="#fea522" d="m445.7 267.7 2 2z"/>
|
||||
<path fill="#fef8f1" d="m466 267.7 2 2z"/>
|
||||
<path fill="#fea522" d="m468 267.7 2 2z"/>
|
||||
<path fill="#fcb144" d="m472 267.7 2 2z"/>
|
||||
<path fill="#fbead6" d="m474 267.7 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m500.5 267.7 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m502.5 267.7 2 2z"/>
|
||||
<path fill="#fef8f1" d="m512.7 267.7 2 2z"/>
|
||||
<path fill="#fe9f11" d="m514.7 267.7 2 2z"/>
|
||||
<path fill="#fbead6" d="m543.2 267.7 2 2z"/>
|
||||
<path fill="#d9d868" d="m549.2 267.7 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m415.3 269.7 2 2z"/>
|
||||
<path fill="#e5e3af" d="m421.3 269.7 2 2z"/>
|
||||
<path fill="#faca88" d="m447.7 269.7 2 2z"/>
|
||||
<path fill="#fbead6" d="m468 269.7 2 2z"/>
|
||||
<path fill="#fe9f11" d="m474 269.7 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m476.2 269.7 2 2z"/>
|
||||
<path fill="#fbead6" d="m498.5 269.7 2 2z"/>
|
||||
<path fill="#fae3c9" d="m500.5 269.7 2 2z"/>
|
||||
<path fill="#fbead6" d="m502.5 269.7 2 2z"/>
|
||||
<path fill="#fbbe66" d="m514.7 269.7 2 2-2-2m16.3 0 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m533 269.7 2 2z"/>
|
||||
<path fill="#fef8f1" d="m535 269.7 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m537 269.7 2 2z"/>
|
||||
<path fill="#fcb755" d="m539 269.7 2 2z"/>
|
||||
<path fill="#fae3c9" d="m543.2 269.7 2 2z"/>
|
||||
<path fill="#808067" d="m553.3 269.7 2 2z"/>
|
||||
<path fill="#32327b" d="m415.3 271.8 2 2z"/>
|
||||
<path fill="#a4a43d" d="m417.9 273 .7 1.5-.6-1.4z"/>
|
||||
<path fill="#e5e59d" d="m421.3 271.8 2 2z"/>
|
||||
<path fill="#fbc477" d="m437.6 271.8 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m449.8 271.8 2 2z"/>
|
||||
<path fill="#fbbe66" d="m470 271.8 2 2z"/>
|
||||
<path fill="#f9d099" d="m476.2 271.8 2 2z"/>
|
||||
<path fill="#fae3c9" d="m494.4 271.8 2 2z"/>
|
||||
<path fill="#fcb144" d="m496.5 271.8 2 2z"/>
|
||||
<path fill="#fae3c9" d="m504.6 271.8 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m514.7 271.8 2 2z"/>
|
||||
<path fill="#f9d099" d="m530.9 271.8 2 2-2-2z"/>
|
||||
<path fill="#fbc477" d="m541 271.8 2 2z"/>
|
||||
<path fill="#fbead6" d="m543.2 271.8 2 2z"/>
|
||||
<path fill="#737370" d="m553.3 271.8 2 2z"/>
|
||||
<path fill="#d9d868" d="m421.3 273.8 2 2z"/>
|
||||
<path fill="#f9d099" d="m437.6 273.8 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m451.8 273.8 2 2-2-2m18.3 0 2 2z"/>
|
||||
<path fill="#fbc477" d="m476.2 273.8 2 2z"/>
|
||||
<path fill="#fef8f1" d="m486.3 273.8 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m488.3 273.8 2 2z"/>
|
||||
<path fill="#fbc477" d="m490.4 273.8 2 2z"/>
|
||||
<path fill="#fea522" d="m492.4 273.8 2 2z"/>
|
||||
<path fill="#fbead6" d="m504.6 273.8 2 2z"/>
|
||||
<path fill="#f2f1d2" d="m547.2 273.8 2 2z"/>
|
||||
<path fill="#58587b" d="m553.3 273.8 2 2z"/>
|
||||
<path fill="#99994e" d="m417.3 275.8 2 2z"/>
|
||||
<path fill="#d0d045" d="m421.3 275.8 2 2z"/>
|
||||
<path fill="#fcb144" d="m453.9 275.8 2 2z"/>
|
||||
<path fill="#fae3c9" d="m455.9 275.8 2 2z"/>
|
||||
<path fill="#fef8f1" d="m470 275.8 2 2z"/>
|
||||
<path fill="#fcb755" d="m478.2 275.8 2 2z"/>
|
||||
<path fill="#fbc477" d="m480.2 275.8 2 2z"/>
|
||||
<path fill="#fcb144" d="m482.3 275.8 2 2z"/>
|
||||
<path fill="#fea522" d="m484.3 275.8 2 2z"/>
|
||||
<path fill="#fe9f11" d="m500.5 275.8 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m502.5 275.8 2 2z"/>
|
||||
<path fill="#fef8f1" d="m530.9 275.8 2 2-2-2z"/>
|
||||
<path fill="#e0dea1" d="m547.2 275.8 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m553.3 275.8 2 2z"/>
|
||||
<path fill="#737370" d="m417.3 277.9 2 2z"/>
|
||||
<path fill="#fbfaf2" d="m423.4 277.9 2 2z"/>
|
||||
<path fill="#fea522" d="m439.6 277.9 2 2z"/>
|
||||
<path fill="#fe9f11" d="m457.9 277.9 2 2z"/>
|
||||
<path fill="#fcb144" d="m459.9 277.9 2 2z"/>
|
||||
<path fill="#fbc477" d="m461.9 277.9 2 2z"/>
|
||||
<path fill="#faca88" d="m463.9 277.9 2 2-2-2z"/>
|
||||
<path fill="#fbc477" d="m466 277.9 2 2z"/>
|
||||
<path fill="#fcb144" d="m468 277.9 2 2z"/>
|
||||
<path fill="#fdab33" d="m470 277.9 2 2z"/>
|
||||
<path fill="#fbc477" d="m498.5 277.9 2 2z"/>
|
||||
<path fill="#fef8f1" d="m500.5 277.9 2 2z"/>
|
||||
<path fill="#fdab33" d="m528.9 277.9 2 2z"/>
|
||||
<path fill="#e1e18c" d="m547.2 277.9 2 2z"/>
|
||||
<path fill="#a4a43d" d="m551.9 279.2.7 1.4z"/>
|
||||
<path fill="#262678" d="m553.3 277.9 2 2z"/>
|
||||
<path fill="#58587b" d="m417.3 279.9 2 2z"/>
|
||||
<path fill="#f2f1d2" d="m423.4 279.9 2 2z"/>
|
||||
<path fill="#faca88" d="m439.6 279.9 2 2z"/>
|
||||
<path fill="#fe9f11" d="m494.4 279.9 2 2z"/>
|
||||
<path fill="#fbead6" d="m496.5 279.9 2 2z"/>
|
||||
<path fill="#fbc477" d="m514.7 279.9 2 2z"/>
|
||||
<path fill="#faca88" d="m528.9 279.9 2 2z"/>
|
||||
<path fill="#d4d456" d="m547.2 279.9 2 2z"/>
|
||||
<path fill="#32327b" d="m417.3 281.9 2 2z"/>
|
||||
<path fill="#e5e59d" d="m423.4 281.9 2 2z"/>
|
||||
<path fill="#fef8f1" d="m439.6 281.9 2 2z"/>
|
||||
<path fill="#fe9f11" d="m441.6 281.9 2 2z"/>
|
||||
<path fill="#fbead6" d="m494.4 281.9 2 2z"/>
|
||||
<path fill="#fea522" d="m514.7 281.9 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m528.9 281.9 2 2z"/>
|
||||
<path fill="#808067" d="m551.3 281.9 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m417.3 283.9 2 2z"/>
|
||||
<path fill="#a4a43d" d="m419.3 283.9 2 2z"/>
|
||||
<path fill="#d9d868" d="m423.4 283.9 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m441.6 283.9 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m512.7 283.9 2 2z"/>
|
||||
<path fill="#faca88" d="m526.9 283.9 2 2z"/>
|
||||
<path fill="#f2f1d2" d="m545.2 283.9 2 2z"/>
|
||||
<path fill="#58587b" d="m551.3 283.9 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m419.3 286 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m443.7 286 2 2z"/>
|
||||
<path fill="#fdab33" d="m484.3 286 2 2z"/>
|
||||
<path fill="#fff" d="m486.3 286 2 2z"/>
|
||||
<path fill="#fcb144" d="m489.7 286.6 1.4.7z"/>
|
||||
<path fill="#fef8f1" d="m510.7 286-2 4z"/>
|
||||
<path fill="#fe9f11" d="m512.7 286 2 2z"/>
|
||||
<path fill="#fdab33" d="m524.9 286-2 4z"/>
|
||||
<path fill="#e5e59d" d="m545.2 286 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m551.3 286 2 2z"/>
|
||||
<path fill="#667" d="m419.3 288 2 2z"/>
|
||||
<path fill="#f2f1d2" d="m425.4 288 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m445.7 288 2 2z"/>
|
||||
<path fill="#fe9f11" d="m484.3 288 2 2z"/>
|
||||
<path fill="#faca88" d="m486.3 288 2 2z"/>
|
||||
<path fill="#fea522" d="m488.3 288 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m490.4 288 2 2z"/>
|
||||
<path fill="#fdab33" d="m510.7 288 2 2z"/>
|
||||
<path fill="#fef8f1" d="m524.9 288 2 2z"/>
|
||||
<path fill="#d9d868" d="m545.2 288 2 2z"/>
|
||||
<path fill="#a4a43d" d="m549.2 288 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m551.3 288 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m419.3 290 2 2z"/>
|
||||
<path fill="#e5e59d" d="m425.4 290 2 2z"/>
|
||||
<path fill="#fae3c9" d="m447.7 290 4 4z"/>
|
||||
<path fill="#fe9f11" d="m449.8 290 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m488.3 290 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m506.6 290 2 2z"/>
|
||||
<path fill="#fdab33" d="m508.6 290 2 2z"/>
|
||||
<path fill="#fcb144" d="m520.9 290 2 2z"/>
|
||||
<path fill="#fef8f1" d="m522.9 290 2 2z"/>
|
||||
<path fill="#fbfaf2" d="m543.2 290 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m549.2 290 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m419.3 292 2 2z"/>
|
||||
<path fill="#a4a43d" d="m421.3 292 2 2z"/>
|
||||
<path fill="#d4d456" d="m425.4 292 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m486.3 292 2 2z"/>
|
||||
<path fill="#f9d099" d="m504.6 292 2 2z"/>
|
||||
<path fill="#fe9f11" d="m506.6 292 2 2z"/>
|
||||
<path fill="#faca88" d="m518.8 292 2 2z"/>
|
||||
<path fill="#eeedc1" d="m543.2 292 2 2z"/>
|
||||
<path fill="#58587b" d="m549.2 292 2 2z"/>
|
||||
<path fill="#737370" d="m421.3 294 2 2z"/>
|
||||
<path fill="#f6f6e4" d="m427.4 294 2 2z"/>
|
||||
<path fill="#fbbe66" d="m449.8 294 2 2z"/>
|
||||
<path fill="#fcb144" d="m482.3 294 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m484.9 295.5.7 1.3z"/>
|
||||
<path fill="#fbbe66" d="m500.5 294 2 2z"/>
|
||||
<path fill="#fe9f11" d="m502.5 294 2 2z"/>
|
||||
<path fill="#fbc477" d="m514.7 294 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m516.8 294 2 2z"/>
|
||||
<path fill="#d3d079" d="m543.2 294 2 2z"/>
|
||||
<path fill="#a4a43d" d="m547.2 294 2 2z"/>
|
||||
<path fill="#262678" d="m549.2 294 2 2z"/>
|
||||
<path fill="#49497d" d="m421.3 296 2 2z"/>
|
||||
<path fill="#e0dea1" d="m427.4 296 2 2z"/>
|
||||
<path fill="#fae3c9" d="m447.7 296 2 2z"/>
|
||||
<path fill="#fdab33" d="m476.2 296 2 2z"/>
|
||||
<path fill="#fbc477" d="m478.2 296 2 2z"/>
|
||||
<path fill="#fbead6" d="m480.2 296 2 2z"/>
|
||||
<path fill="#fcb144" d="m486.3 296 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m512.7 296 2 2z"/>
|
||||
<path fill="#99994e" d="m547.2 296 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m421.3 298.2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m423.4 298.2 2 2z"/>
|
||||
<path fill="#d4d456" d="m427.4 298.2 2 2z"/>
|
||||
<path fill="#f9d099" d="m445.7 298.2 2 2z"/>
|
||||
<path fill="#fe9f11" d="m447.7 298.2 2 2-2-2m10.2 0 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m459.9 298.2 2 2z"/>
|
||||
<path fill="#f9d099" d="m461.9 298.2 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m470 298.2 2 2z"/>
|
||||
<path fill="#fae3c9" d="m472 298.2 2 2z"/>
|
||||
<path fill="#fef8f1" d="m474 298.2 2 2z"/>
|
||||
<path fill="#fbead6" d="m490.4 298.2 2 2z"/>
|
||||
<path fill="#fae3c9" d="m492.4 298.2 2 2z"/>
|
||||
<path fill="#faca88" d="m494.4 298.2 2 2z"/>
|
||||
<path fill="#fbc477" d="m496.5 298.2 2 2z"/>
|
||||
<path fill="#fdab33" d="m498.5 298.2 2 2z"/>
|
||||
<path fill="#fe9f11" d="m508.6 298.2 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m510.7 298.2 2 2z"/>
|
||||
<path fill="#e5e3af" d="m541 298.2 2 2z"/>
|
||||
<path fill="#667" d="m547.2 298.2 2 2z"/>
|
||||
<path fill="#737370" d="m423.4 300.2 2 2z"/>
|
||||
<path fill="#f2f1d7" d="m429.5 300.2 2 2z"/>
|
||||
<path fill="#fea522" d="m443.7 300.2 2 2z"/>
|
||||
<path fill="#fe9f11" d="m453.9 300.2 2 2z"/>
|
||||
<path fill="#fbbe66" d="m455.9 300.2 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m457.9 300.2 2 2z"/>
|
||||
<path fill="#fea522" d="m506.6 300.2 2 2z"/>
|
||||
<path fill="#fbead6" d="m508.6 300.2 2 2z"/>
|
||||
<path fill="#dddc7a" d="m541 300.2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m545.2 300.2 2 2z"/>
|
||||
<path fill="#262678" d="m547.2 300.2 2 2z"/>
|
||||
<path fill="#49497d" d="m423.4 302.2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m426 303.6.8 1.3z"/>
|
||||
<path fill="#d3d079" d="m429.5 302.2 2 2z"/>
|
||||
<path fill="#f9d099" d="m445.7 302.2 2 2z"/>
|
||||
<path fill="#fcb144" d="m447.7 302.2 2 2z"/>
|
||||
<path fill="#faca88" d="m449.8 302.2 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m451.8 302.2 2 2z"/>
|
||||
<path fill="#fef8f1" d="m453.9 302.2 2 2z"/>
|
||||
<path fill="#f8dcbb" d="m498.5 302.2 2 2z"/>
|
||||
<path fill="#fcf1e4" d="m506.6 302.2 2 2z"/>
|
||||
<path fill="#f6f6e4" d="m539 302.2 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m545.2 302.2 2 2z"/>
|
||||
<path fill="#fbfaf2" d="m431.5 304.2 2 2z"/>
|
||||
<path fill="#fbbe66" d="m498.5 304.2 2 2z"/>
|
||||
<path fill="#faca88" d="m504.6 304.2 2 2z"/>
|
||||
<path fill="#e1e18c" d="m539 304.2 2 2z"/>
|
||||
<path fill="#49497d" d="m545.2 304.2 2 2z"/>
|
||||
<path fill="#58587b" d="m425.4 306.3 2 2z"/>
|
||||
<path fill="#e5e59d" d="m431.5 306.3 2 2z"/>
|
||||
<path fill="#fe9f11" d="m498.5 306.3 2 2z"/>
|
||||
<path fill="#fdab33" d="m502.5 306.3 2 2z"/>
|
||||
<path fill="#fbfaf2" d="m537 306.3 2 2z"/>
|
||||
<path fill="#a4a43d" d="m543.2 306.3 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m545.2 306.3 2 2z"/>
|
||||
<path fill="#1b1b74" d="m425.4 308.3 2 2z"/>
|
||||
<path fill="#a4a43d" d="m427.4 308.3 2 2z"/>
|
||||
<path fill="#d0d045" d="m431.5 308.3 2 2z"/>
|
||||
<path fill="#fbead6" d="m496.5 308.3 2 2z"/>
|
||||
<path fill="#fe9f11" d="m500.5 308.3 2 2z"/>
|
||||
<path fill="#fbead6" d="m502.5 308.3 2 2z"/>
|
||||
<path fill="#e5e59d" d="m537 308.3 2 2z"/>
|
||||
<path fill="#667" d="m543.2 308.3 2 2z"/>
|
||||
<path fill="#6e6c70" d="m427.4 310.3 2 2z"/>
|
||||
<path fill="#e5e3af" d="m433.5 310.3 2 2z"/>
|
||||
<path fill="#faca88" d="m497 311.7.8 1.4z"/>
|
||||
<path fill="#fae3c9" d="m500.5 310.3 2 2z"/>
|
||||
<path fill="#fbfaf2" d="m535 310.3 2 2z"/>
|
||||
<path fill="#a4a43d" d="m541 310.3 2 2z"/>
|
||||
<path fill="#1b1b74" d="m543.2 310.3 2 2-2-2m-115.8 2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m429.5 312.4 2 2z"/>
|
||||
<path fill="#d0d045" d="m433.5 312.4 2 2z"/>
|
||||
<path fill="#fbfaf2" d="m435.5 312.4 2 2z"/>
|
||||
<path fill="#f9d6aa" d="m498.5 312.4 2 2z"/>
|
||||
<path fill="#e5e59d" d="m535 312.4 2 2z"/>
|
||||
<path fill="#6e6c70" d="m541 312.4 2 2-2-2m-111.5 2 2 2z"/>
|
||||
<path fill="#8cbf84" d="m435.5 314.4 2 2z"/>
|
||||
<path fill="#0cf" d="M436.4 314.4c7 14.8 32 49.8 51 49.2 18.6-.7 39.5-35 47.6-49.2z"/>
|
||||
<path fill="#a4a43d" d="m539 314.4 2 2z"/>
|
||||
<path fill="#1b1b74" d="m541 314.4 2 2-2-2m-111.5 2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m431.5 316.4 2 2z"/>
|
||||
<path fill="#adb333" d="m435.5 316.4 2 2z"/>
|
||||
<path fill="#1ac5b5" d="m437.6 316.4 2 2z"/>
|
||||
<path fill="#68b070" d="m533 316.4 2 2z"/>
|
||||
<path fill="#667" d="m539 316.4 2 2z"/>
|
||||
<path fill="#58587b" d="m431.5 318.5 2 2z"/>
|
||||
<path fill="#7fb15c" d="m437.6 318.5 2 2z"/>
|
||||
<path fill="#27c2aa" d="m530.9 318.5 2 2-2-2z"/>
|
||||
<path fill="#a4a43d" d="m537 318.5-2 4z"/>
|
||||
<path fill="#0e0e6e" d="m539 318.5 2 2-2-2m-107.5 2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m433.5 320.5 4 4z"/>
|
||||
<path fill="#34be9e" d="m439.6 320.5 2 2z"/>
|
||||
<path fill="#96b247" d="m530.9 320.5 2 2-2-2z"/>
|
||||
<path fill="#53527c" d="m537 320.5 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m433.5 322.6 2 2z"/>
|
||||
<path fill="#a2b23d" d="m439.6 322.6 2 2z"/>
|
||||
<path fill="#0dc9c1" d="m441.6 322.6 2 2z"/>
|
||||
<path fill="#5bb47c" d="m528.9 322.6 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m535 322.6 2 2z"/>
|
||||
<path fill="#737370" d="m435.5 324.6 2 2z"/>
|
||||
<path fill="#74b166" d="m441.6 324.6 2 2z"/>
|
||||
<path fill="#27c2aa" d="m526.9 324.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m533 324.6-2 4z"/>
|
||||
<path fill="#262678" d="m535 324.6 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m435.5 326.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m437.6 326.6 4 4z"/>
|
||||
<path fill="#42bb92" d="m443.7 326.6 2 2z"/>
|
||||
<path fill="#0dc9c1" d="m524.9 326.6 2 2z"/>
|
||||
<path fill="#96b247" d="m526.9 326.6 2 2z"/>
|
||||
<path fill="#58587b" d="m533 326.6 2 2z"/>
|
||||
<path fill="#3a3a7c" d="m437.6 328.6 2 2z"/>
|
||||
<path fill="#adb333" d="m443.7 328.6 2 2z"/>
|
||||
<path fill="#27c2aa" d="m445.7 328.6 2 2z"/>
|
||||
<path fill="#74b166" d="m524.9 328.6 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m530.9 328.6 2 2-2-2z"/>
|
||||
<path fill="#6e6c70" d="m439.6 330.6 2 2z"/>
|
||||
<path fill="#96b247" d="m445.7 330.6 2 2z"/>
|
||||
<path fill="#0dc9c1" d="m447.7 330.6 2 2z"/>
|
||||
<path fill="#42bb92" d="m522.9 330.6 2 2z"/>
|
||||
<path fill="#a4a43d" d="m528.9 330.6-4 6 4-6z"/>
|
||||
<path fill="#1b1b74" d="m530.9 330.6 2 2-2-2z"/>
|
||||
<path fill="#0e0e6e" d="m439.6 332.6 2 2-2-2z"/>
|
||||
<path fill="#8d8d5b" d="m441.6 332.6 2 2-2-2z"/>
|
||||
<path fill="#7fb15c" d="m447.7 332.6 2 2-2-2z"/>
|
||||
<path fill="#34be9e" d="m520.9 332.6 2 2-2-2z"/>
|
||||
<path fill="#3a3a7c" d="m528.9 332.6 2 2-2-2z"/>
|
||||
<path fill="#1b1b74" d="m441.6 334.7 2 2z"/>
|
||||
<path fill="#a4a43d" d="M443.7 334.7 466 357z"/>
|
||||
<path fill="#74b166" d="m449.8 334.7 2 2z"/>
|
||||
<path fill="#27c2aa" d="m518.8 334.7 2 2z"/>
|
||||
<path fill="#adb333" d="m520.9 334.7 2 2z"/>
|
||||
<path fill="#667" d="m526.9 334.7 2 2z"/>
|
||||
<path fill="#32327b" d="m443.7 336.7 2 2z"/>
|
||||
<path fill="#42bb92" d="m451.8 336.7 2 2z"/>
|
||||
<path fill="#0dc9c1" d="m516.8 336.7-8.2 10.2 8.3-10.3z"/>
|
||||
<path fill="#adb333" d="m518.8 336.7 2 2z"/>
|
||||
<path fill="#737370" d="m524.9 336.7 2 2z"/>
|
||||
<path fill="#49497d" d="m445.7 338.8 2 2z"/>
|
||||
<path fill="#42bb92" d="m453.9 338.8 2 2z"/>
|
||||
<path fill="#96b247" d="m516.8 338.8 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m522.9 338.8-2 4z"/>
|
||||
<path fill="#0e0e6e" d="m524.9 338.8 2 2z"/>
|
||||
<path fill="#53527c" d="m447.7 340.8 2 2z"/>
|
||||
<path fill="#42bb92" d="m455.9 340.8 2 2z"/>
|
||||
<path fill="#96b247" d="m514.7 340.8 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m522.9 340.8 2 2z"/>
|
||||
<path fill="#6e6c70" d="m449.8 342.8 2 2z"/>
|
||||
<path fill="#42bb92" d="m457.9 342.8 2 2z"/>
|
||||
<path fill="#96b247" d="m512.7 342.8 2 2z"/>
|
||||
<path fill="#a4a43d" d="m518.8 342.8-4 6 4-6z"/>
|
||||
<path fill="#262678" d="m520.9 342.8 2 2z"/>
|
||||
<path fill="#6e6c70" d="m451.8 344.9 2 2z"/>
|
||||
<path fill="#42bb92" d="m459.9 344.9 2 2z"/>
|
||||
<path fill="#96b247" d="m510.7 344.9 2 2z"/>
|
||||
<path fill="#262678" d="m518.8 344.9 2 2z"/>
|
||||
<path fill="#6e6c70" d="m453.9 346.9 2 2z"/>
|
||||
<path fill="#68b070" d="m461.9 346.9 2 2z"/>
|
||||
<path fill="#27c2aa" d="m506.6 346.9 2 2z"/>
|
||||
<path fill="#adb333" d="m508.6 346.9 2 2z"/>
|
||||
<path fill="#262678" d="m516.8 346.9 2 2z"/>
|
||||
<path fill="#667" d="m455.9 348.9 2 2z"/>
|
||||
<path fill="#74b166" d="m463.9 348.9 2 2-2-2z"/>
|
||||
<path fill="#34be9e" d="m504.6 348.9 2 2z"/>
|
||||
<path fill="#adb333" d="m506.6 348.9 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m512.7 348.9-2 4z"/>
|
||||
<path fill="#262678" d="m514.7 348.9 2 2z"/>
|
||||
<path fill="#49497d" d="m457.9 350.9 2 2z"/>
|
||||
<path fill="#96b247" d="m466 350.9 2 2z"/>
|
||||
<path fill="#0dc9c1" d="m468 350.9 2 2z"/>
|
||||
<path fill="#42bb92" d="m502.5 350.9 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m512.7 350.9 2 2z"/>
|
||||
<path fill="#49497d" d="m459.9 353 2 2z"/>
|
||||
<path fill="#a2b23d" d="m468 353 2 2z"/>
|
||||
<path fill="#27c2aa" d="m470 353 2 2z"/>
|
||||
<path fill="#74b166" d="m500.5 353 2 2z"/>
|
||||
<path fill="#a4a43d" d="m506.6 353-6 8z"/>
|
||||
<path fill="#808067" d="m508.6 353 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m510.7 353 2 2z"/>
|
||||
<path fill="#262678" d="m461.9 355 2 2z"/>
|
||||
<path fill="#adb333" d="m470 355 2 2z"/>
|
||||
<path fill="#42bb92" d="m472 355 2 2z"/>
|
||||
<path fill="#0dc9c1" d="m496.5 355 2 2z"/>
|
||||
<path fill="#96b247" d="m498.5 355 2 2z"/>
|
||||
<path fill="#6e6c70" d="m506.6 355 2 2z"/>
|
||||
<path fill="#1b1b74" d="m463.9 357 2 2-2-2z"/>
|
||||
<path fill="#8d8d5b" d="m466 357 2 2z"/>
|
||||
<path fill="#74b166" d="m474 357 2 2z"/>
|
||||
<path fill="#0dc9c1" d="m476.2 357 2 2z"/>
|
||||
<path fill="#34be9e" d="m494.4 357 2 2z"/>
|
||||
<path fill="#adb333" d="m496.5 357 2 2z"/>
|
||||
<path fill="#49497d" d="m504.6 357 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m466 359 2 2z"/>
|
||||
<path fill="#6e6c70" d="m468 359 2 2z"/>
|
||||
<path fill="#a4a43d" d="m470 359 4 4z"/>
|
||||
<path fill="#96b247" d="m476.2 359 2 2z"/>
|
||||
<path fill="#27c2aa" d="m478.2 359 2 2z"/>
|
||||
<path fill="#68b070" d="m492.4 359 2 2z"/>
|
||||
<path fill="#32327b" d="m502.5 359 2 2z"/>
|
||||
<path fill="#49497d" d="m470 361 2 2z"/>
|
||||
<path fill="#5bb47c" d="m480.2 361 2 2z"/>
|
||||
<path fill="#27c2aa" d="m488.3 361 2 2z"/>
|
||||
<path fill="#96b247" d="m490.4 361 2 2z"/>
|
||||
<path fill="#a4a43d" d="m496.5 361-2 4z"/>
|
||||
<path fill="#808067" d="m498.5 361 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m500.5 361 2 2z"/>
|
||||
<path fill="#262678" d="m472 363 2 2z"/>
|
||||
<path fill="#8d8d5b" d="m474 363 2 2z"/>
|
||||
<path fill="#8bb252" d="m482.3 363 2 2z"/>
|
||||
<path fill="#1ac5b5" d="m484.3 363 2 2z"/>
|
||||
<path fill="#5bb47c" d="m486.3 363 2 2z"/>
|
||||
<path fill="#58587b" d="m496.5 363 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m474 365.2 2 2z"/>
|
||||
<path fill="#667" d="m476.2 365.2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m478.2 365.2 2 2z"/>
|
||||
<path fill="#99994e" d="m492.4 365.2 2 2z"/>
|
||||
<path fill="#32327b" d="m494.4 365.2 2 2-2-2m-16.2 2 2 2z"/>
|
||||
<path fill="#99994e" d="m480.2 367.2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m488.3 367.2 2 2z"/>
|
||||
<path fill="#667" d="m490.4 367.2 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m492.4 367.2 2 2-2-2m-12.2 2 2 2z"/>
|
||||
<path fill="#667" d="m482.3 369.2 2 2z"/>
|
||||
<path fill="#a4a43d" d="m484.3 369.2 2 2z"/>
|
||||
<path fill="#99994e" d="m486.3 369.2 2 2z"/>
|
||||
<path fill="#32327b" d="m488.3 369.2 2 2z"/>
|
||||
<path fill="#262678" d="m484.3 371.2 2 2z"/>
|
||||
<path fill="#0e0e6e" d="m486.3 371.2 2 2z"/>
|
||||
<path fill="#f90" d="M488.3 235.2c3.2 7.4 13.2 15.5 16 19.5-3.5 4-4.2 3.6-3.8 11 6-6.4 6.2-7 10.2-6.1 8.6 8.6 1.5 27-5.6 31-7.1 4.3-5.8-.1-16.5 5.2 4.9 4.2 10.6-.6 15.2.7 2.5 3-1.2 8.4.7 13.6 4-.4 3.6-8.7 4.6-11.7 3-11 21-18.6 21.9-28.7 3.8-1.7 7.5-.5 12 2-2.2-9.4-9.7-9.3-11.8-12.2-4.8-7.4-9.1-15.8-19.4-18-8-1.7-7.3.5-12.3-3-3.2-2.4-12.7-7-11.2-3.3z"/>
|
||||
<path fill="#fff" fill-rule="evenodd" d="M510.9 243.6a1.6 1.6 0 1 1-3.3 0 1.6 1.6 0 0 1 3.3 0z"/>
|
||||
<path fill="#f90" d="M463.2 266.5c5-6.2 7.6-19 9.8-23.2 5.2 1.2 5 2 11.5-1.8-8.5-2.4-9.2-2.2-10.2-6.1 3.6-11.7 23.2-14 30-9.6 7.2 4.3 2.7 5.2 12.4 12 1.4-6.2-5.5-9-6.5-13.6 1.5-3.7 8-3 11.6-7-2.2-3.5-9.3.8-12.4 1.4-11 2.5-26.3-9.8-35.6-6-3.3-2.5-4-6.4-4-11.7-7.1 6.5-3.5 13-5.2 16.3-4.2 7.7-9.7 15.5-6.8 25.6 2.2 7.8 3.8 6.2 3.2 12.3-.7 3.9-.4 14.5 2.2 11.4z"/>
|
||||
<path fill="#fff" fill-rule="evenodd" d="M460 242.6c.9-.4 1.9-.1 2.3.7a1.6 1.6 0 1 1-2.2-.7z"/>
|
||||
<path fill="#f90" d="M504.3 270.8c-8-1-20.1 3.3-25 3.7-1.5-5.1-.8-5.5-7.4-9 2.3 8.6 2.8 9 0 12-11.8 2.9-24-12.7-23.8-20.8 0-8.3 3.2-5 4-17-6 2-4.8 9.5-8.3 12.8-4 .6-6.6-5.3-12-6.3-1.8 3.7 5.5 7.5 7.6 9.9 7.9 8.2 5.2 27.5 13.3 33.5-.4 4.2-3.4 6.8-8 9.4 9.3 2.9 13-3.7 16.7-4 8.8-.2 18.3.4 25.5-7.3 5.4-6 3.3-6.5 8.8-9 3.7-1.4 12.6-7.2 8.6-8z"/>
|
||||
<path fill="#fff" fill-rule="evenodd" d="M485.5 285.9a1.6 1.6 0 1 1 1.7-2.8 1.6 1.6 0 0 1-1.7 2.8z"/>
|
||||
<path fill="#012169" d="M0 0h320v240H0z"/>
|
||||
<path fill="#fff" d="m37.5 0 122 90.5L281 0h39v31l-120 89.5 120 89V240h-40l-120-89.5L40.5 240H0v-30l119.5-89L0 32V0z"/>
|
||||
<path fill="#c8102e" d="M212 140.5 320 220v20l-135.5-99.5zm-92 10 3 17.5-96 72H0zM320 0v1.5l-124.5 94 1-22L295 0zM0 0l119.5 88h-30L0 21z"/>
|
||||
<path fill="#fff" d="M120.5 0v240h80V0zM0 80v80h320V80z"/>
|
||||
<path fill="#c8102e" d="M0 96.5v48h320v-48zM136.5 0v240h48V0z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 36 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="flag-icons-al" viewBox="0 0 640 480">
|
||||
<path fill="#f00" d="M0 0h640v480H0z"/>
|
||||
<path id="a" d="M272 93.3c-4.6 0-12.3 1.5-12.2 5-13-2.1-14.3 3.2-13.5 8 1.2-1.9 2.7-3 3.9-3.1 1.7-.3 3.5.3 5.4 1.4a21.6 21.6 0 0 1 4.8 4.1c-4.6 1.1-8.2.4-11.8-.2a16.5 16.5 0 0 1-5.7-2.4c-1.5-1-2-2-4.3-4.3-2.7-2.8-5.6-2-4.7 2.3 2.1 4 5.6 5.8 10 6.6 2.1.3 5.3 1 8.9 1 3.6 0 7.6-.5 9.8 0-1.3.8-2.8 2.3-5.8 2.8-3 .6-7.5-1.8-10.3-2.4.3 2.3 3.3 4.5 9.1 5.7 9.6 2 17.5 3.6 22.8 6.5a37.3 37.3 0 0 1 10.9 9.2c4.7 5.5 5 9.8 5.2 10.8 1 8.8-2.1 13.8-7.9 15.4-2.8.7-8-.7-9.8-2.9-2-2.2-3.7-6-3.2-12 .5-2.2 3.1-8.3.9-9.5a273.7 273.7 0 0 0-32.3-15.1c-2.5-1-4.5 2.4-5.3 3.8a50.2 50.2 0 0 1-36-23.7c-4.2-7.6-11.3 0-10.1 7.3 1.9 8 8 13.8 15.4 18 7.5 4.1 17 8.2 26.5 8 5.2 1 5.1 7.6-1 8.9-12.1 0-21.8-.2-30.9-9-6.9-6.3-10.7 1.2-8.8 5.4 3.4 13.1 22.1 16.8 41 12.6 7.4-1.2 3 6.6 1 6.7-8 5.7-22.1 11.2-34.6 0-5.7-4.4-9.6-.8-7.4 5.5 5.5 16.5 26.7 13 41.2 5 3.7-2.1 7.1 2.7 2.6 6.4-18.1 12.6-27.1 12.8-35.3 8-10.2-4.1-11 7.2-5 11 6.7 4 23.8 1 36.4-7 5.4-4 5.6 2.3 2.2 4.8-14.9 12.9-20.8 16.3-36.3 14.2-7.7-.6-7.6 8.9-1.6 12.6 8.3 5.1 24.5-3.3 37-13.8 5.3-2.8 6.2 1.8 3.6 7.3a53.9 53.9 0 0 1-21.8 18c-7 2.7-13.6 2.3-18.3.7-5.8-2-6.5 4-3.3 9.4 1.9 3.3 9.8 4.3 18.4 1.3 8.6-3 17.8-10.2 24.1-18.5 5.5-4.9 4.9 1.6 2.3 6.2-12.6 20-24.2 27.4-39.5 26.2-6.7-1.2-8.3 4-4 9 7.6 6.2 17 6 25.4-.2 7.3-7 21.4-22.4 28.8-30.6 5.2-4.1 6.9 0 5.3 8.4-1.4 4.8-4.8 10-14.3 13.6-6.5 3.7-1.6 8.8 3.2 9 2.7 0 8.1-3.2 12.3-7.8 5.4-6.2 5.8-10.3 8.8-19.9 2.8-4.6 7.9-2.4 7.9 2.4-2.5 9.6-4.5 11.3-9.5 15.2-4.7 4.5 3.3 6 6 4.1 7.8-5.2 10.6-12 13.2-18.2 2-4.4 7.4-2.3 4.8 5-6 17.4-16 24.2-33.3 27.8-1.7.3-2.8 1.3-2.2 3.3l7 7c-10.7 3.2-19.4 5-30.2 8l-14.8-9.8c-1.3-3.2-2-8.2-9.8-4.7-5.2-2.4-7.7-1.5-10.6 1 4.2 0 6 1.2 7.7 3.1 2.2 5.7 7.2 6.3 12.3 4.7 3.3 2.7 5 4.9 8.4 7.7l-16.7-.5c-6-6.3-10.6-6-14.8-1-3.3.5-4.6.5-6.8 4.4 3.4-1.4 5.6-1.8 7.1-.3 6.3 3.7 10.4 2.9 13.5 0l17.5 1.1c-2.2 2-5.2 3-7.5 4.8-9-2.6-13.8 1-15.4 8.3a17 17 0 0 0-1.2 9.3c.8-3 2.3-5.5 4.9-7 8 2 11-1.3 11.5-6.1 4-3.2 9.8-3.9 13.7-7.1 4.6 1.4 6.8 2.3 11.4 3.8 1.6 5 5.3 6.9 11.3 5.6 7 .2 5.8 3.2 6.4 5.5 2-3.3 1.9-6.6-2.5-9.6-1.6-4.3-5.2-6.3-9.8-3.8-4.4-1.2-5.5-3-9.9-4.3 11-3.5 18.8-4.3 29.8-7.8l7.7 6.8c1.5.9 2.9 1.1 3.8 0 6.9-10 10-18.7 16.3-25.3 2.5-2.8 5.6-6.4 9-7.3 1.7-.5 3.8-.2 5.2 1.3 1.3 1.4 2.4 4.1 2 8.2-.7 5.7-2.1 7.6-3.7 11-1.7 3.5-3.6 5.6-5.7 8.3-4 5.3-9.4 8.4-12.6 10.5-6.4 4.1-9 2.3-14 2-6.4.7-8 3.8-2.8 8.1 4.8 2.6 9.2 2.9 12.8 2.2 3-.6 6.6-4.5 9.2-6.6 2.8-3.3 7.6.6 4.3 4.5-5.9 7-11.7 11.6-19 11.5-7.7 1-6.2 5.3-1.2 7.4 9.2 3.7 17.4-3.3 21.6-8 3.2-3.5 5.5-3.6 5 1.9-3.3 9.9-7.6 13.7-14.8 14.2-5.8-.6-5.9 4-1.6 7 9.6 6.6 16.6-4.8 19.9-11.6 2.3-6.2 5.9-3.3 6.3 1.8 0 6.9-3 12.4-11.3 19.4 6.3 10.1 13.7 20.4 20 30.5l19.2-214L320 139c-2-1.8-8.8-9.8-10.5-11-.7-.6-1-1-.1-1.4.9-.4 3-.8 4.5-1-4-4.1-7.6-5.4-15.3-7.6 1.9-.8 3.7-.4 9.3-.6a30.2 30.2 0 0 0-13.5-10.2c4.2-3 5-3.2 9.2-6.7a86.3 86.3 0 0 1-19.5-3.8 37.4 37.4 0 0 0-12-3.4zm.8 8.4c3.8 0 6.1 1.3 6.1 2.9 0 1.6-2.3 2.9-6.1 2.9s-6.2-1.5-6.2-3c0-1.6 2.4-2.8 6.2-2.8z"/>
|
||||
<use xlink:href="#a" width="100%" height="100%" transform="matrix(-1 0 0 1 640 0)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-am" viewBox="0 0 640 480">
|
||||
<path fill="#d90012" d="M0 0h640v160H0z"/>
|
||||
<path fill="#0033a0" d="M0 160h640v160H0z"/>
|
||||
<path fill="#f2a800" d="M0 320h640v160H0z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 228 B |
@@ -1,13 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ao" viewBox="0 0 640 480">
|
||||
<g fill-rule="evenodd" stroke-width="1pt">
|
||||
<path fill="red" d="M0 0h640v243.6H0z"/>
|
||||
<path d="M0 236.4h640V480H0z"/>
|
||||
</g>
|
||||
<path fill="#ffec00" fill-rule="evenodd" d="M228.7 148.2c165.2 43.3 59 255.6-71.3 167.2l-8.8 13.6c76.7 54.6 152.6 10.6 174-46.4 22.2-58.8-7.6-141.5-92.6-150l-1.3 15.6z"/>
|
||||
<path fill="#ffec00" fill-rule="evenodd" d="m170 330.8 21.7 10.1-10.2 21.8-21.7-10.2zm149-99.5h24v24h-24zm-11.7-38.9 22.3-8.6 8.7 22.3-22.3 8.7zm-26-29.1 17.1-16.9 16.9 17-17 16.9zm-26.2-39.8 22.4 8.4-8.5 22.4-22.4-8.4zM316 270l22.3 8.9-9 22.2-22.2-8.9zm-69.9 70 22-9.3 9.5 22-22 9.4zm-39.5 2.8h24v24h-24zm41.3-116-20.3-15-20.3 14.6 8-23-20.3-15h24.5l8.5-22.6 7.8 22.7 24.7-.3-19.6 15.3 7 23.4z"/>
|
||||
<path fill="#fe0" fill-rule="evenodd" d="M336 346.4c-1.2.4-6.2 12.4-9.7 18.2l3.7 1c13.6 4.8 20.4 9.2 26.2 17.5a7.9 7.9 0 0 0 10.2.7s2.8-1 6.4-5c3-4.5 2.2-8-1.4-11.1-11-8-22.9-14-35.4-21.3z"/>
|
||||
<path fill-rule="evenodd" d="M365.3 372.8a4.3 4.3 0 1 1-8.7 0 4.3 4.3 0 0 1 8.6 0zm-21.4-13.6a4.3 4.3 0 1 1-8.7 0 4.3 4.3 0 0 1 8.7 0zm10.9 7a4.3 4.3 0 1 1-8.7 0 4.3 4.3 0 0 1 8.7 0z"/>
|
||||
<path fill="#fe0" fill-rule="evenodd" d="M324.5 363.7c-42.6-24.3-87.3-50.5-130-74.8-18.7-11.7-19.6-33.4-7-49.9 1.2-2.3 2.8-1.8 3.4-.5 1.5 8 6 16.3 11.4 21.5A5288 5288 0 0 1 334 345.6c-3.4 5.8-6 12.3-9.5 18z"/>
|
||||
<path fill="#ffec00" fill-rule="evenodd" d="m297.2 305.5 17.8 16-16 17.8-17.8-16z"/>
|
||||
<path fill="none" stroke="#000" stroke-width="3" d="m331.5 348.8-125-75.5m109.6 58.1L274 304.1m18.2 42.7L249.3 322"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-aq" viewBox="0 0 640 480">
|
||||
<path fill="#3a7dce" d="M0 0h640v480H0z"/>
|
||||
<path fill="#fff" d="M157.7 230.8c-3.5-7.8-3.5-7.8-3.5-15.6-1.8 0-2 .3-3 0-1.1-.3-1.5 7.2-4.8 5.8-.5-.8 2.4-6.2-.7-8.5-1-.7.2-5.2-.2-7.2 0 0-4 2.4-7-5.8-1.5-2.2-3.5 2-3.5 2s.9 2.4-.7 3c-2.2-1.8-3.9-.8-6.7-3.4-2.8-2.5.6-5.4-4.8-7.5 3.5-9.8 3.5-7.9 12.2-11.8-5.2-4-5.2-4-8.7-9.8-5.2-2-7-4-12.2-7.8-7-9.9-10.5-29.5-10.5-43.2 4.4-4.6 10.5 15.7 19.2 21.6l12.2 5.9c7 3.9 8.7 7.8 14 11.7l15.6 6c7 5.8 10.5 13.6 15.7 15.6 5.7 0 6.8-3.7 8.6-3.9 10.3-.6 15.5-2 17.5-5.5 2.1-2.8 7 1.6 21-4.3l-1.7-7.9s3.7-3.4 8.7-2c-.1-3.5-.5-13 4.5-17.4-3-3.5 1.8-9 2-10.7-1.4-8.6 1.4-8.7 2-11.3.6-2.5-2.4-1.7-1.6-5.2.9-3.5 6-4.3 6.6-7.2.7-2.9-1.1-14.3-1.3-16.8 9.4-2.8 12.4-11.4 15.7-7.8C264 70 265.8 66 276.3 66c1.4-3.6-3.9-6.7-1.8-7.9 3.5-.5 6.1-.2 10.2 5.7 1.3 2 1.6-2.7 2.9-3.2 1.3-.5 4.4-.5 4.9-2.8.5-2.4 1.2-5.6 3-9.5 1.4-3.2 2.5 1.3 3.8 7.5 7.4.3 24 2.1 31 4.3 5.2 1.5 8.7-1.5 13.7-2.2 3.7 4.2 7.2 1 9.2 10 2.7 4.8 7.3.4 8.3 1.8 5.8 18.1 25.8 5.9 27.4 6.2 2.5 0 5.6 8 7.7 7.9 3.2-.6 2.3-3.1 5.2-2.1-.8 6.8 5.6 14.6 5.6 19.7 0 0 1.5.9 3-.6 1.4-1.6 2.7-5.4 4-5.3 3 .5 22 6 25.8 7.9 1.7 3.5 3.3 5.3 6.8 4.7 2.8 2.1.8 5 2.4 5.1 3.5-2 4.7-4 8.2-2.1 3.5 2 7 5.9 8.7 9.8 0 2-1.8 9.8 0 21.6.9 3.9 9.7 32.3 9.7 35.2 0 4-2.7 6-4.5 9.9 7 5.9 0 15.7-3.5 21.6 26.2 5.9 14 17.6 34.9 11.7-5.2 13.8-3.4 12.7 1.8 26.4-10.4 7.8-.2 10.2-7.1 20-.5.7 4.1 8.6 10.5 8.6-1.7 15.6-7 9.8-5.2 33.3-13.7-.3-8.2 17.6-17.4 15.7.5 11.2 5.2 12.2 3.4 23.5-7 2-7 2-10.4 7.9l-5.2-2c-1.8 9.8-5.3 11.8 0 21.6 0 0-6.8.2-8.8 0-.1 3.4 3 4.3 3.5 7.8-.2 1.4-9.9 7.6-17.4 7.9-2 4.8 5.2 10 4.8 12.4-8.2 1.8-11.8 13-11.8 13s4.2 2 3.5 4c-2.2-1.8-3.5-2-7-2-1.7.5-6 0-10 7.7-4.5 1.6-6.6 1-10 6-1.5-4.7-3.7.1-6.3 2-2.7 1.8-6.2 6.5-6.7 6.3.1-1.4 1.6-6.3 1.6-6.3L399 437c-.7.1-.5-5.7-2.2-5.5-1.7.2-6.4 7.3-8 7.5-1.6.2-2.1-2.2-3.5-2-1.4.2-4 7.5-5 7.7-1 .1-5-4.5-8.3-3.8-17.1 6.8-19.9-13.4-22.5-2-3.6-2.2-3-1-6.7.1-2.3.7-2.5-3.4-4.6-3.4-4.1.2-4 4.6-6.2 3.3-1.8-9.2-13-7.6-14-11.5-1-4 4.8-4 6.6-6.8 1.4-4-1.5-5.6 4.3-9.4 7.5-5.7 6.8-19.8 4.9-25.3 0 0-5.9-17.7-7-17.7-3.5-1-3.5 6.5-8.6 8.6-10.5 4-29-9.9-32.2-9.9-2.9 0-16.5 3.6-16-4-2 7.4-9.5 1.7-10 1.7-7 0-4.3 6.1-9 5.9-2.1-.8-23.6-2.3-23.6-2.3v4l-26.1-11.8c-10.5-4-5.3-13.7-22.7-7.8v-11.8h-8.7c3.5-23.6 0-11.8-1.8-33.4l-7 2c-7-10.6 9.8-8.6-5.2-15.7 0 0 .3-11.7-3.5-7.8-.7.5 1.8 5.8 1.8 5.8-14-2-17.4-5.8-17.4-21.5 0 0 11.4 1.8 10.4 0-1.6-3-3.7-22-3.4-23.4-.1-2.6 10.7-9 8.6-15.2 1.4-.6 5.3-.7 5.3-.7"/>
|
||||
<path fill="none" stroke="#fff" stroke-linejoin="round" stroke-width="2.5" d="M595.5 297.6c-.6 1.3-.5 2.6.1 3.6 1.1-1.7.2-2.4 0-3.6zm-476-149.4s-3-.4-2.4 2.3c1-2 2.3-2.2 2.4-2.3zm-.3-6.4c-1.7 0-3.8-.2-3 2.5 1-2.1 3-2.4 3-2.5zm12.7 36.3s2.6-.2 2 2.5c-1-2-2-2.4-2-2.5z" transform="scale(.86021 .96774)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,32 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="flag-icons-ar" viewBox="0 0 640 480">
|
||||
<path fill="#74acdf" d="M0 0h640v480H0z"/>
|
||||
<path fill="#fff" d="M0 160h640v160H0z"/>
|
||||
<g id="c" transform="translate(-64) scale(.96)">
|
||||
<path id="a" fill="#f6b40e" stroke="#85340a" stroke-width="1.1" d="m396.8 251.3 28.5 62s.5 1.2 1.3.9c.8-.4.3-1.6.3-1.6l-23.7-64m-.7 24.2c-.4 9.4 5.4 14.6 4.7 23-.8 8.5 3.8 13.2 5 16.5 1 3.3-1.2 5.2-.3 5.7 1 .5 3-2.1 2.4-6.8-.7-4.6-4.2-6-3.4-16.3.8-10.3-4.2-12.7-3-22"/>
|
||||
<use xlink:href="#a" width="100%" height="100%" transform="rotate(22.5 400 250)"/>
|
||||
<use xlink:href="#a" width="100%" height="100%" transform="rotate(45 400 250)"/>
|
||||
<use xlink:href="#a" width="100%" height="100%" transform="rotate(67.5 400 250)"/>
|
||||
<path id="b" fill="#85340a" d="M404.3 274.4c.5 9 5.6 13 4.6 21.3 2.2-6.5-3.1-11.6-2.8-21.2m-7.7-23.8 19.5 42.6-16.3-43.9"/>
|
||||
<use xlink:href="#b" width="100%" height="100%" transform="rotate(22.5 400 250)"/>
|
||||
<use xlink:href="#b" width="100%" height="100%" transform="rotate(45 400 250)"/>
|
||||
<use xlink:href="#b" width="100%" height="100%" transform="rotate(67.5 400 250)"/>
|
||||
</g>
|
||||
<use xlink:href="#c" width="100%" height="100%" transform="rotate(90 320 240)"/>
|
||||
<use xlink:href="#c" width="100%" height="100%" transform="rotate(180 320 240)"/>
|
||||
<use xlink:href="#c" width="100%" height="100%" transform="rotate(-90 320 240)"/>
|
||||
<circle cx="320" cy="240" r="26.7" fill="#f6b40e" stroke="#85340a" stroke-width="1.4"/>
|
||||
<path id="h" fill="#843511" stroke-width="1" d="M329 234.3c-1.7 0-3.5.8-4.5 2.4 2 1.9 6.6 2 9.7-.2a7 7 0 0 0-5.1-2.2zm0 .4c1.8 0 3.5.8 3.7 1.6-2 2.3-5.3 2-7.4.4 1-1.4 2.4-2 3.8-2z"/>
|
||||
<use xlink:href="#d" width="100%" height="100%" transform="matrix(-1 0 0 1 640.2 0)"/>
|
||||
<use xlink:href="#e" width="100%" height="100%" transform="matrix(-1 0 0 1 640.2 0)"/>
|
||||
<use xlink:href="#f" width="100%" height="100%" transform="translate(18.1)"/>
|
||||
<use xlink:href="#g" width="100%" height="100%" transform="matrix(-1 0 0 1 640.2 0)"/>
|
||||
<path fill="#85340a" d="M316 243.7a1.8 1.8 0 1 0 1.8 2.9 4 4 0 0 0 2.2.6h.2c.6 0 1.6-.1 2.3-.6.3.5.9.7 1.5.7a1.8 1.8 0 0 0 .3-3.6c.5.2.8.6.8 1.2a1.2 1.2 0 0 1-2.4 0 3 3 0 0 1-2.6 1.7 3 3 0 0 1-2.5-1.7c0 .7-.6 1.2-1.3 1.2-.6 0-1.2-.6-1.2-1.2s.3-1 .8-1.2zM318 249.1c-2.1 0-3 2-4.8 3.1 1-.4 1.8-1.2 3.3-2 1.4-.8 2.6.2 3.5.2.8 0 2-1 3.5-.2 1.4.8 2.3 1.6 3.3 2-1.9-1.2-2.7-3-4.8-3-.4 0-1.2.2-2 .6l-2-.7z"/>
|
||||
<path fill="#85340a" d="M317.2 251.6c-.8 0-1.8.2-3.4.6 3.7-.8 4.5.5 6.2.5 1.6 0 2.5-1.3 6.1-.5-4-1.2-4.9-.4-6.1-.4-.8 0-1.4-.3-2.8-.2z"/>
|
||||
<path fill="#85340a" d="M314 252.2h-.8c4.3.5 2.3 3 6.8 3s2.5-2.5 6.8-3c-4.5-.4-3.1 2.3-6.8 2.3-3.5 0-2.4-2.3-6-2.3z"/>
|
||||
<path fill="#85340a" d="M323.7 258.9a3.7 3.7 0 0 0-7.4 0 3.8 3.8 0 0 1 7.4 0z"/>
|
||||
<path id="e" fill="#85340a" stroke-width="1" d="M303.4 234.3c4.7-4.1 10.7-4.8 14-1.7a8 8 0 0 1 1.5 3.4c.4 2.4-.3 4.9-2.1 7.5l.8.4c1.6-3.1 2.2-6.3 1.6-9.4l-.6-2.3c-4.5-3.7-10.7-4-15.2 2z"/>
|
||||
<path id="d" fill="#85340a" stroke-width="1" d="M310.8 233c2.7 0 3.3.6 4.5 1.7 1.2 1 1.9.8 2 1 .3.2 0 .8-.3.6-.5-.2-1.3-.6-2.5-1.6s-2.5-1-3.7-1c-3.7 0-5.7 3-6.1 2.8-.5-.2 2-3.5 6.1-3.5z"/>
|
||||
<use xlink:href="#h" width="100%" height="100%" transform="translate(-18.4)"/>
|
||||
<circle id="f" cx="310.9" cy="236.3" r="1.8" fill="#85340a" stroke-width="1"/>
|
||||
<path id="g" fill="#85340a" stroke-width="1" d="M305.9 237.5c3.5 2.7 7 2.5 9 1.3 2-1.3 2-1.7 1.6-1.7-.4 0-.8.4-2.4 1.3-1.7.8-4.1.8-8.2-.9z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -1,72 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-as" viewBox="0 0 640 480">
|
||||
<path fill="#006" d="M0 0h640v480H0Z"/>
|
||||
<path fill="#bd1021" d="m-.6 240 640-240v480Z"/>
|
||||
<path fill="#fff" d="m59.7 240 580-214.3v428.6"/>
|
||||
<path d="M474 270.4c5.1.3 5 5.4 5 5.4l18 .4c2.3-6.3 4.8-5.6 9.2-2.4a32.9 32.9 0 0 0 8.7 4.2c1.7-9 14.5-7.2 14.5-7.2 5.6-13 6-12.9 2.7-14.5a10.7 10.7 0 0 1-4.6-4.5c-3-3.7-4.6-9.1-5-12.4-.4-3.3-4.2 1.6-5 .6-.6-1-6.3-.4-6.3-.4 1.4 1.5-3.4.6-3.4.6.5.4 0 1.7 0 1.7-.4-.6-4.1-1.2-4.1-1.2a6.1 6.1 0 0 1-1.1 1.6c-2-.8-6-.7-6-.7a20 20 0 0 0-10.9 2.8c-1.6.9-7.4 3.8-12.3 8.5-4.7 4.6-7.4 4-7.4 4-1.4 5.2-12.8 11.5-12.8 11.5-1.8 1.6-7.6 2.4-10.5 0-2.9-2.4 0-6.9 0-6.9 1.2-2 2.2-1.9 2.3-9 .1-4.7 5-8.5 10-14 6.3-6.8 15-18 15-18 0 3.4 1.8 4 1.8 4 1.7-3.5 4.2-6.3 4.2-6.3.1.3.5.4.5.4 2-2.6 3-3.6 3-3.6-.5-.3-6 0-11 4.4s-8.4 3-8.4 3c-3.5-1.2-3.8-4-3.8-4-2.5-10.9 7.4-18.7 7.4-18.7-13.4-3.2-3.7-20.3 13-27.5 16.6-7.2 16.4-10.5 16.4-10.5a13 13 0 0 1 1.8 3c.1 0 1.4-1.9 11-6.1 9.6-4.3 14.2-8 14.2-8 1.2 2.4 1 4 1 4 26.3-9.1 52-30.2 52-30.2.8 1.7.5 4.4.5 4.4 4.2-4 19.7-13.2 19.7-13.2a8.6 8.6 0 0 1-4.6 8.2 7.7 7.7 0 0 1 .8 2.3 360 360 0 0 0 14.4-9.5c4.3 3.7.4 9.8.4 9.8 1.6-.3 2.6-1.6 2.6-1.6 1.2 6.4-5.9 12-5.9 12 1.3 0 3.3-1.3 3.3-1.3-1.3 7-14.4 14.6-14.4 14.6 1.9 1.8 0 4-1.6 5-1.5 1-4.3 3.3-3.4 4.2.8 1 6.7-3.2 6.7-3.2 1 2.9-6.5 8.6-6.5 8.6 5.2.7 19.6-5.9 19.6-5.9-1.1 5.6-6.6 10-13.3 12.5-6.7 2.5-6.4 3-6.4 3 1.2.8 10.5-1.8 10.5-1.8-2.8 6.2-12.5 10.5-12.5 10.5 2.7 2.3 6.3-.4 10-2.9a58.2 58.2 0 0 1 14-6.4c5.3-1.9 9.2-.5 9.2-.5 4.6-1.4 8.4.6 8.4.6 8.7.7 9.6 3.9 9.6 3.9 1 .2 1.7.6 4 2.3 2.1 1.6 2 6.6 2 9.2-.2 2.4-.9 2.4-1.3 3-.4.8-.5 1.6-.5 2.5 0 1-2.2 6.9-15.7 6.9h-20.3c-1.2 0-2.5.7-2.5.7-5.7 2.8-2.7-2-9.4 3.6-6.8 5.5-10.2 4.6-10.2 4.6A90.1 90.1 0 0 1 568 221c-4 2.6-3.3 2.3.3 3.8s8.8 0 8.8 0c-3.4 2.3-1 3.4-1 3.4 4.4-2.7 7.2-1.7 7.2-1.7 1.4 3.9-3.8 10-3.8 10 2 .3 5.8 0 5.8 0-1 2.7-4.6 5.6-7.4 6.4-2.7 1-2.3 1.3-1.4 3 .7 1.6.1 3.3.1 3.3-4.8-3.3-5-.4-5-.4-.5 4-.4 9.6-.4 9.6-3.4-1.7-3.5.5-3.5.5-1 3.6-5.1 7.7-5.1 7.7-.2-2.2-2.2-2.8-2.2-2.8-2.2 4.2-6.1 6.7-6.1 6.7-.5 3.5.5 8.6.5 8.6-2.6-.6-3.5-.6-4 0-.3.7.6 1 .6 1l33.4.8c.5 0 2.5.3 2.5 3.8 0 3.7-3 3.9-3 3.9l-36.4-.9s.1 1-1.8 2-1.2-1.1-1.7 3.4c-.6 4.4-7.8-.4-7.8-.4-1.2 1.8-4 4-4 4-1.7-5-3.4-6.4-6-2.2-2.6 4.3 4.8 3.6 4.8 3.6s42.8-6.3 45.1-6.5c2.3-.3 4.9-.1 6 3.1 1 3.3-5.3 3.8-5.3 3.8l-44 4.8c-.9 2.6-4.5 2.4-4.5 2.4.3 2.5-2.3 4-3.6 5-1.4.8-5.6.5-5.6.5-5 3.4-7.6.7-7.6.7-3.3 1.4-5.4.8-8.1-.4-2.8-1.2-2.5-4.5-2.5-4.5l-27.8 3a6.7 6.7 0 0 0-2.2 1.2c1 1.3-2 4.3-2 4.3.9.5 2.5 2.1 2.7 5.5.2 3.7-4.5 4.3-2.2 7 2.3 2.5 6.7.3 11.5-2s9.5-2 11.5-2 7.8 1.6 11.4 2.8c3.6 1.2 4.8.4 5-1.4.2-1.7 1.9-2.3 1.9-2.3-.5 1.8.5 2.6.5 2.6a11 11 0 0 0 3.7-1.3c-.2 1.4-2 2.2-2 2.2-3.4 2.3 1.4 1.5 1.4 1.5 9.5-2 13-1.8 15.4-1.5a122.5 122.5 0 0 1 14.3 5.2c.4-1.2.1-4 .1-4 3 .8 4.2 2.5 4.2 2.5 1.2-1.2.4-3.4.4-3.4 9.7 5.5-2 8-5.1 9-3 1-3 2.3-3 2.3 2.5-.8 4.3-1.1 6.4-1.3 2.2-.2 1.4 0 6.5-1 5.2-1 7.8 1.2 7.8 1.2-4.3.2-5.5 1.5-5.5 1.5 2.6 1.7 0 3.4 0 3.4-3.8-5-7.2.1-7.2.1a15.3 15.3 0 0 1 6.4 1.4l5.4 2.7c3.6 1.6 2.9.6 5.6 1.6 2.8 1 1.7 3.7 1.7 3.7-1.1-2.2-3.7-3-3.7-3-.2 3-3.1 3.5-3.1 3.5 3.6-4-4.1-5.8-7.8-5.7-3.6 0-6.3 2.4-6.3 2.4 7.3 6.9 12.3 4.6 12.3 4.6-.9 2.5-6.9 1.5-6.9 1.5 2.8 2.2 2.5 3.6 2.5 3.6-1.5-1.4-4-.7-9.2-4-5.2-3.5-9.9-2.3-9.9-2.3 5.2 5.3-1.8 8.6-1.8 8.6-2.6 1.6 1 3.5 1 3.5-3.2.6-3.6-2.6-3.6-2.6-1.7-.4-4.2 1.6-4.2 1.6.2-3.2 4.6-1.6 4.6-5 .2-3.5-4-6.2-16.3-4.5-12.4 1.7-16-2.2-16-2.2-1 0-1.2 1-1.2 1 2 2 2.9 2.8 2.6 4.2-.4 1.3.6 1.8.6 1.8-2.3-.2-2.4-2.8-2.4-2.8 0 1.1-.5 1.2-1.3 2.3s0 2.7 0 2.7c-1-.8-2.7-1.8-1-4.3 1.2-1.8-2.7-4.2-2.7-4.2-1.5-1.5-5.6 0-5.6 0a14.9 14.9 0 0 1-13.3-3.7c-1 0-2.9-.6-2.9-.6-8.9 4-16.7-4.6-16.7-4.6-6.7 1.3-9.8-2-11.8-5.2a11.5 11.5 0 0 0-5.2-5c-2.6-1.6-5.2-6.2-2.6-8.7 2-2.1 1.5-2.6 1.5-2.6-3.5-5.9 6.1-7.7 6.3-9.2.3-2 2.3-3.3 4.5-3.4 2.2-.2 2.2 0 3.7-1.4 1.3-1.5 4 .3 4 .3.7-.4 5.5-4.1 9.7-2.2 4.3 1.9 7.9.6 7.9.6 3-.7 28-4 28-4 1.5-2.5 2.7-5.4 9.6-7s12-6 12-6c-1.2-1.2-3.2-1.2-4.2-1.3-1.1 0-3.2-2-3.2-2-1.3.6-2 .3-11 5.8-8.1 5-8.3-4.8-8.3-4.8H479c-.3 3.7-3 5.2-3 5.2l-6.5.3c-3.6-1.8-3.6-8.2-3.6-8.2-19.4.3-30.1 7.2-30.1 7.2-22-11.2-39.2-13.8-39.2-13.8a122.4 122.4 0 0 0 40.8-10.2 63.3 63.3 0 0 0 28.5 9c.5-5.4 4.1-6.7 4.1-6.7z"/>
|
||||
<path fill="#ffc221" d="M442.3 314.6c-5.5 3.2-4.5 5-4 6s.5 2-1 3.6c-1.5 1.5-1.4 2-1.4 2 .3 5.4 4 6.6 5.7 8 1.4 1 3.6 4.5 3.6 4.5 2.9 4.1 5.9 4.2 8.1 4.2 2.3 0 2-.3 1-1.3l-3.4-2.7a17.6 17.6 0 0 1 5.9 4.1c5.6 6.2 10.8 5.4 13.1 5.2 2.3-.3 2-1.7 2-1.7a9 9 0 0 0-2.4-.4c-8.5-.8-11-6.4-11-6.4a24.1 24.1 0 0 0 15.6 6c2.4-.1 2.3.6 1.7.8l-2.4-.2c-1.1 0-1.1.3-.9.8.3.4 1.4.4 2.7.4 1.4 0 .3.1 3.8 2.8 3.6 2.8 12.3.5 12.3.5-5.7-1.3-6.4-4-6.4-4-7.7 1-10.8-3.6-10.8-3.6a32.5 32.5 0 0 0-5.6-3.5c-4.2-1.9-5-5.8-5-5.8 1.3 1.8 3.7 3.8 6.7 4.6 3 .8 3.8 1.2 3.8 1.2a3.8 3.8 0 0 1-2.3-.2c-3-1-1.3.3-1.3.3 3.4 2.7 4.3 2.5 4.3 2.5 8.6.9 4.3-2.6 4.3-2.6 6.2 1.5 7.2-.8 7.2-.8 1.3 2.7 6 1.7 6 1.7-6.2 3-1.5 2.1-1.5 2.1 6.3-1.1 7.6.5 7.6.5 1.6 1.5 3.4 1.4 3.4 1.4s1.2 0 3.5.4c2.4.5 6.2 2.5 9.6 2.2 3.5-.5 4 .6 4 .6-.6-.3-2.2-.5-4.8.7-2.7 1.3-7.4 1.6-14.2 0s-7.4-1.3-7.4-1.3c1.7 1.1 3.1 2.9 3.4 4 .3 1.2 1.5 1.2 1.5 1.2.5-1.5 2.5-2.1 2.5-2.1a27 27 0 0 0 5 2.8c.4-.7 0-1.3 0-1.3 2.6 2.5 5.6 1.7 5.6 1.7.8-.5.6-2 .6-2 1 0 1.2.6 2 1.2.7.4 3 .1 3 .1-.8-.4-1.5-1.7-1.5-1.7 3.5-2.3 11-1.3 11-1.3 5.3 1 4.7 4.5 4.7 4.5a10 10 0 0 1 2.5 2.1c.5-1.2 0-2.5 0-2.5 2.6 1.2 3 4 3 4 3-3.2-2.7-6.8-2.7-6.8 2.7-.4 5.7-.2 7.5 0a13.8 13.8 0 0 1 6.6 3.1c2.1 1.7 5.9 2.5 5.9 2.5-.1-.7-2.2-2-2.7-2.2-.4-.2-.6-.9-.6-.9 1.9.4 3.1.2 3.1.2-6.4-4-8.1-5.9-8.1-5.9 2.4.3 3.8-1.2 3.8-1.2-5.1 0-5.4-1.2-5.4-1.2.7.1 3.1.7 6.2.1s7.2 0 7.2 0c-2.2-3.6-10.7-3-13.5-2.8-2.8.2-3.8-.2-3.8-.2.4-.2.9-.6 3-.7 2.2 0 4.3.2 6.8-1.6 2.3-1.6 5.7-1 5.7-1-.8-1.6-4.7-2.2-8 0-3.5 2.1-6.5 1.5-6.5 1.5 5.3-.8 6.9-2.7 6.9-2.7-1.6-.4-2.5.1-5.8.8-3.2.6-4-.5-4-.5 3.5-2.1 6-3 6-3-3-.6-5.8-2-5.8-2-3.2 3-5.6 4.6-11.7 1.6-6-3.2-9.2-2.8-9.2-2.8 5.4-3.1 10.8-1.8 14.8.6 4 2.3 5 .4 5 .4-1.2-.7-1-1.5-1-1.5 9.6 4.9 13.8 2 15.9.5 2.1-1.5-1-3.4-1-3.4-.2 3-4 4.6-7.2 3.5-3-1-6-2.4-10.4-4.3-4.4-1.8-10-.8-15.1.2-5.2 1.1-5.9.6-6.4.2-.5-.4-.7-1.7-3.4-.6-2.6 1.1-8.8-1.8-12.6-2.7-3.8-1-10.1-.5-15.5 2.5-5.4 3.1-8.2 2.3-9.8 1.6-1.6-.8-2.7-2.8-.9-4.6s2-2.3 1.8-5c-.2-2.6-2.8-4.2-2.8-4.2 2.4-2.5 3-3 2.2-4-.8-1.2.4-1.2 1.8-1.8 1.4-.6.8-.7.5-1.5-.4-.8-1.2-.6-1.2-.6-3.1.1-4.9-.8-4.9-.8-5.2-2.4-10.1 2.3-10.1 2.3-3-2.3-3.7-.7-4.2-.2-.5.5-1.6 1-3 1-1.2.2-3.1.7-3.8 1.9 0 0-.6 1 .1 2 0 0 .8 1.2-.6 2.7-1.5 1.5-2 1.8-1.5 3.3.4 1.3.3 2.4-.3 3.3 0 0-.7-.7-.5-1.7.2-1 .2-1.6 0-2 0 0-1.5 1.4-1.8 2.4 0 0-.6-1.6 1.6-3.7 2-2 3-3.2 2.4-4-.4-.6-2 .4-2.3.6z"/>
|
||||
<path d="M448.4 338s-2.7-2-2.4-4.9c.3-2.7.3-3 0-3.7 0 0-.5.3-.4 1.4 0 1-.2 2.1-.3 2.3 0 0-1.3-2.3-2-2.8 0 0 .6-2.4-.2-3.4-.7-1.1-1.5-1.2-2.4-.8-1.2.4-2.1 1.5 2 4.8 0 0 1.5 1.3 2.5 3.9 1 2.6 2.8 3 3.1 3.2zm13-7.8s-.1-1.5 1.3-4.3a6.1 6.1 0 0 0 .3-5.6c-.3-.8-.6-.5.9-1.7 1.7-1.5-.7-3.4 2.3-6 0 0 1.8-1.6 2.3-2.3 0 0-3 1.6-5.2 2.5-2 .8-9.6 4.6-8 7.1 1.8 2.5 1.6 2.7 1.3 3.8 0 0-4.6-2.5-3-6.4 0 0 .8-1.5 2.7-3.4 1.8-1.6.8.4 4.3-1.7 0 0 2.7-1.6 4.3-3.9 0 0-2 1.2-2.6 1.4 0 0-4 .8-5.8 2.5-1.6 1.7-5.1 4.7-4 8 0 0-4-.4-5-4.7 0 0-7.6 9.4 8.4 13.8 0 0 3 .8 5.6 1z"/>
|
||||
<path fill="#ffc221" d="M531.6 299c6-1 40.4-6.2 43.6-6.5 3.4-.3 4.7-.8 5.9 2 1.3 3-4.8 3.1-4.8 3.1l-41.1 4.7c-2 .2-2.5-.6-2.5-.6l-1.5-2s-.5-.6.4-.8z"/>
|
||||
<path fill="#5a3719" d="M447.3 317.7s-4.4 9.3 13 11.6c0 0 .1-1 .8-2.5.8-1.5 2.3-4.5.8-6.4-1.4-1.9 1.2-.9 1.5-3.4.5-2.5-.2-2.2 1-3.8 0 0-5.4 2-7.6 4.5-2 2.4 2.9 4.2 0 6.9 0 0-2.5-1-4-3.6 0 0-3.3 0-5.5-3.3z"/>
|
||||
<path d="M464.5 329.2s4.3 3.7 9.4 3.6c5.1-.3 7.4-1.6 8.7-3.6 0 0 1 1.5 1 2.6 0 0 4.4-3.7 12-.5s5.4 2.3 7.1 2.5c0 0-3.3-.5-10.7 2.9-7.7 3.5-27.7 2.3-27.6-7.5z"/>
|
||||
<path fill="#5a3719" d="M457.3 312.6s1.9.3 3.8-1.9c0 0-2.6.5-3.8 2zM442.6 330s-3.6-2.8-1.3-3.4c0 0 1.7-.3 1.3 3.4z"/>
|
||||
<path d="M521.2 347.8s2-3.5 7.5-3.5 6.1 2.6 13.1 3c0 0-8.4 2.4-14.2.3-3-1.1-5.8-.2-6.4.2z"/>
|
||||
<path fill="#5a3719" d="M466.3 331.7s8.4 5 15.7-.5c0 0 .6.6 1.2 2 0 0 5.6-5.4 15.5.4 0 0-1.2-.1-5.9 1.8-6.1 2.7-21.4 4.5-26.5-3.8z"/>
|
||||
<path d="M498.3 336.7s8 1 14.7.6c4.1-.2 8.6-1 6.4.4-2.3 1.3-1.1 1.5 8.4.7 9.4-1-.1 1.7 6.4 2.6 0 0-15.9 8-35.9-4.3z"/>
|
||||
<path fill="#5a3719" d="M519.2 331.7s4.6-1.7 9 .3c4.3 2 3.6 2.2 6.5 2.5 0 0-2 2.9-6.7.6-4.8-2.3-6-2.8-8.8-3.4zm5.2 14.3s4.6-2.3 9.6 0c.6.4 2 1 3.3 1.2 0 0-3.8 1.3-7.8 0-1.7-.5-3-.9-5.1-1.2zm-22.7-8.2s10.3 1 15.8-.1c0 0-6.4 3 9.7 1.7 0 0 3.5-.4 3 .1-.3.5-.6 1 1.2 1.5 0 0-12 5.4-29.7-3.2z"/>
|
||||
<path d="M450.7 329.2s.2.7 2.4 1.7c2.3 1.1 3.5 2.9 4 3.9a5.6 5.6 0 0 0 3.5 2.9s-8 1.7-11.6-2.6c0 0-2.7-3 1.6-6"/>
|
||||
<path fill="#5a3719" d="M513.7 347.6s-3.1-.2-7.5-1.7c-4.3-1.5-5.4-.2-7.9-2-2.4-1.9-7.3-.7-8.2-.6-1 .1-3.6 0-.3-2.1 0 0-2.6 0-3.6-1.4 0 0-1.2 1.2-5.6.8 0 0 2 3-6 2.1a10.3 10.3 0 0 0 11.1 3c0 .2-.5 2.5 3 3.5 3.8.9 4.5 1.6 6.4 2.3 0 0 .3-1.5-4.6-5 0 0 2.6-.2 6.4.7s12.2 3.1 16.8.4zm2 3.7s.8 1.8 3.2 1.4c2.4-.4 6.4-1 10.2.8 0 0 .7-3.2-7-3.4 0 0-4.8.2-6.4 1.2zm-65.2-21s-3 2.5-.3 5c2.4 2.3 6.2 2.1 8 2 0 0-1-.6-2-2-1-1.5-1-2.5-3-3.4-2.1-.9-2.3-1.1-2.7-1.6zm-3-12.6s-4.6 9.3 13 11.6c0 0 0-1 .7-2.5.6-1.5 2.1-4.5.8-6.4-1.6-1.9 1.1-.9 1.5-3.4.4-2.5-.3-2.2 1-3.8 0 0-5.5 2-7.7 4.5-2 2.4 2.9 4.2 0 6.9 0 0-2.5-1-4-3.6 0 0-3.3 0-5.5-3.3z"/>
|
||||
<path d="M493.3 339.3s3.7-.6 13 2.9c9.4 3.4 13.3 2.6 14.6 2.5 0 0-5.2 2.8-13.4-.8-7.2-3.2-7.6-2-14.2-4.6z"/>
|
||||
<path fill="#ffc221" d="M551.8 337.2s2 0 3.4.5c0 0 .7-.7 2.7-1 0 0-1.3-1.2-6.1.5zm-6.4-5.2s2.1 0 2.8-1.2c0 0-1.1-1.3-2.8-2 0 0 .4 1.6 0 3.2zm-71.7-23.8s-.5-1 1.8-1.4l31.3-4.5s1.5 0 1.7 1c.3 1.1-.1 1.9-7.2 2.7l-25.6 3.2s-1.9.3-2-1z"/>
|
||||
<path fill="#ffc221" d="M502 306.9s0 4.1 4.2 4.7c4 .6 5.5-.2 6.5-2.3.3-.7 1.6-5-.2-5.3-.8-.1-2 0-2.9.3-1.4.7-2.7 1.4-2.3 2 1 1.6 1.2 2 1 2-1.2.3-1.8-.6-2-1.2-.3-.8.5-1.2-2.2-.8-1.2.1-2 .1-2 .6zM519.5 303.7c2 .3 1.9 4.8-.6 6.9-2.8 2.2-5.4 1.3-5.4 1.3-1.4-.5-1.2-.4-.1-2 1-1.5 1.5-3.6.9-5-.2-.5.3-.9 1-1 0 0 2-.4 4.2-.2z"/>
|
||||
<path fill="#ffc221" d="M521.3 304.1s1.6 2-.4 5.5c0 0-.8 1 1.1.9 1.8-.2 6.1-2.2 5.7-4.8 0 0-.2-.6-1.3-.6s-.2-.5.3-.8c.4 0 1.9-.6-1.9-3 0 0-.6-.6-1.3-.3-.6.2-2.6 1-2.6 2.2 0 .5.4 1 .4 1z"/>
|
||||
<path fill="#ffc221" d="M525.4 300.9s3 2.1 3 2.8c0 .6-.3 1.5.5 1.3.8 0 4-.7 3-2.8-.8-2.1-1.7-3-3.2-3.4-1.5-.6-1.9.1-3.2 1.1 0 0-.9.6-.1 1zm-16.1 3s.5-1.5-2.2-2.2c0 0 1.1-1 3.4-.4 2.2.4 2 2 2 2.1 0 0-1.8 0-3.2.5zm5.8-.4s3-.5 4.5-.4c0 0-1.6-3.3-5.7-2.3 0 0 1.5 1.8 1.2 2.7zm5.3-.8s0-1.1 2.6-2.1c0 0-1.2-1.2-3-1-2 0-2.5.7-2.5.7s2.3.8 2.9 2.4zm1-3.6s1.7.4 2.7 1.3c0 0 1.5-1.7 2.8-2 0 0-2.5-1.4-5.5.7z"/>
|
||||
<path fill="#5a3719" d="M435.8 290.9s7.2-6.2 11.2-5.4c4 .8 2 .2 6.4-.5 4.4-.6 9-1.1 10.8-.9 0 0-5.4-3.8-14.9-3.7 0 0-6.6 2.3-11.3 5.3 0 0-8.9-4.9-18-2 0 0 9.9 3.7 15.8 7.2z"/>
|
||||
<path fill="#ffc221" d="m512.2 301.4 1.2-.2s2 2.5.6 2.5c-1.2 0-.8-.3-1-1a2.3 2.3 0 0 0-.8-1.3zm-9 .2s-.8 1 .6.8c1.7-.3 1.4 0 3.1-1.3 0 0 1.2-1.1 3.2-.4 0 0 1.8.6 3.2-.1 1.4-.8 1.7-.7 2.5-.6.8 0 .8.2 1.7-.6 1-.7 2.8-.1 3.9-1 1.1-1 2.5-.2 0-2 0 0-.5-.5-.5-1 0 0 1 .4 1.8 1 .8.8 2 .5 2.2.4 0 0 .2-2.3 2.3-4.3 2.3-2 2.3-2.2 1-2.2s-3.5-.6-4.3 0-7.2 4.8-11 5.5c-3.8.7-7.3 1.8-9.7 5.8zm-101.3-23.4s11.7 3 14.3 4.2c0 0 .6-1.9-4.7-3.4 0 0 12.9-.4 26.4 5.8 0 0 6.6-5.6 27.7-3.9 0 0 0-1.8.2-3.3 0 0-14.8-.4-28.4-8.7 0 0-12.3 6-35.5 9.3zm64.7 5.6c-.7-11.8 3.8-13 3.8-13s2.1 0 4.4.5c0 0-3.6 4.3-2.6 12.8 0 0 .4 1.3-2.7 1.3s-2.9-1.5-2.9-1.5z"/>
|
||||
<path fill="#5a3719" d="M469.8 291.7s-2.3-2.3-2.5-4.9c0 0 0-.6 2.2-.6 2.3 0 2.5-.2 3 1.1.6 1.3 2 4 2.3 4.3z"/>
|
||||
<path fill="#ffc221" d="M474.5 285.7a28.3 28.3 0 0 1-.2-4.5c.1-6.6 1.2-6 1.7-5.2h2.3s-1.7-7.4-3.7-3a19 19 0 0 0-1.5 10.4c.1 2 .3 3.3.6 4z"/>
|
||||
<path fill="#5a3719" d="M500.2 285.7s4.3.8-2.3 2.3c0 0 .3 8.2 8.2 2.5 0 0 4.7-3 8-4.2 0 0 1.6-.6 1.4-1.8 0 0 .2-1.5-1.5-1.1 0 0-1.4 0-2.3-.3 0 0-1-1.2-1.6-.8-.6.5-2.1.2-.9 1.7 1.2 1.4 1.5 1 2 .6.6-.4 3.1-1.4.9.7s-4.2-1.2-5-1.8zm-22 1h-2s-1 1.6-1.7-1l-.7 1.6s2.3 8.8 4.4-.6z"/>
|
||||
<path fill="#ffc221" d="M475.4 276.6s-1 5.8.3 9.2l21.1.5s-.2-4 0-9.7H494s-.5 4.6 0 7.5h-.5s-.4-4 0-7.5h-2.5s-.4 4.3 0 7.5h-.5s-.4-3.7 0-7.5H488s-.5 3.9 0 7.5h-.6s-.5-3.9 0-7.5h-2.7s-.6 3.6 0 7.5h-.5s-.6-3.6 0-7.5h-2.7s-.6 4.2 0 7.5h-.6s-.4-4 .1-7.5h-2.5s-.7 3.5 0 7.5h-.7s-.4-3 .2-7.5h-2.6zm22.3 10.4s-.5-10.2 1.4-13c2-2.6 2.5-2 5.8 0 3.4 2.2 7.7 4.5 8.5 4.8.6.3 1.6.5 1.6 2.4s.3 2.4-2.6 0c-.3-.3-1.7-1.5-2.7-1.8-2.6-.9.6.5 1.5 1.9.8 1 1.5 1-.6 1.5a219 219 0 0 0-12.9 4.2z"/>
|
||||
<path d="M505 279.6s-1.5-1.8.5-2.3c2-.4 2.1 3 2.5 5.1.3 2.2-2.5-2.1-2.8-2.7zm-2.7 9s-2.3.9-.7 1.6c1.4.7 5.5-2.7 4.2-2.5-1.6.3-3.5 1-3.5 1zm3-3s2-.3 1.6.5c-.3 1-1 .4-1.4.2-.3-.2-1.6-.7-.1-.8z"/>
|
||||
<path fill="#ffc221" d="M516 282.8s.6 4 4 5c0 0 2 .4 1.5-1.3 0 0-.3-1.5-.6-2-.3-.7-1.6-1-1.8-1.1-.2 0-.3-.5.6-.2 1 .3 1 .4 1-.3s-.6-.4-1.4-.8c-.4-.2 0-.4.3-.3.4 0 1.3.3 1.3-1 0 0 .1-.8-.9-.8-1.1 0-1-.6-.7-.7.3 0 1.5.8 1.9-.6.3-1.3-1.6-.5-1.4-1.2.3-.8 1.7.3 1.7-.5.2-.8 1.3-1.1-.6-1.4-.9-.1 0-.6 1-.4 1 .1 1.6-1.2 2.3-1.6.6-.5 4.2-2.6-.6-1.9-4.7.7-6.1 3-6.3 3.5a13 13 0 0 0-1.3 7.6z"/>
|
||||
<path fill="#ffc221" d="M527 285.8c.7 0 1.2 0 1.4.5.8 1.6-1 1-2 2.2s-1 1-2.4.5c-1.4-.4-2-2.5-2-2.5 0-.7.5-.8 1.2-.6 0 0 2.3.2 3.9 0zm-5-.8s0 .4.9.5c.7 0 3 .3 4.5-.1 0 0 .4-.1.2-1 0 0 0-.7-1.2-.4-1.3.2-3 0-3.7-.1-.6-.2-1 0-.8 1zm-.2-2.9s-.1 1.3 1.1 1.4c1.3.2 2.9.2 3.5 0 .5 0 1.4-.2 1.5-1 0-.7.2-1.2-1.3-.8s-3.4 0-3.6 0c-.1 0-1.2-.3-1.2.4zm.5-2.5s-.3.6-.2 1.2c0 .5.9.7 2.5.7s3-.2 3.2-.7c.1-.7.5-1.3-.7-1-1.3.1-3 .2-3.6 0-.6-.3-1.1-.4-1.2-.2z"/>
|
||||
<path fill="#5a3719" d="M582.1 286s0 1 .9 2.2l-45.2-1.3s.6-.4.8-2.2z"/>
|
||||
<path fill="#ffc221" d="M522.7 277.8s-.4 1.1.4 1.4c.7.2 2.2.4 4 .1 0 0 1 0 1.3-1 .3-1 .3-.4-2.3-.8 0 0-.8-.3 1.5-.3 0 0 1.4 0 1.5-.2.3-.2 2-1.7-.3-1.5-2.3 0-1.1-.5 0-.5 1.2 0 1.6.3 2 0s0-.2-.7-.8-.1-.5.3-.1c.5.3.8.5 1.3 0s-.4-1.2 0-1c.3 0 .6.8 2 0 1.6-.7 3.5-.3 4 0 .6.5 2.2 1 3.1 0 1-.8-1.1-1.7-.3-1.8 1-.1 1.6.2 1.9-.5.4-.8-1.4-1.4.3-1.8 1.6-.5.2-5-.3-5.5 0 0-1.9 1.1-3.8 4.3-2.1 3.3-3.3 5.2-6 4.2-3.9-1.5-6 .6-6.5 1-1 .6 2 .8.2.9-1.7 0-1.7.2-1.8.4-.2.3 0 .5.3.6.3 0 .9.6-.1.6s-1.8-.3-1.5.9c0 0 0 .2.6.3.6 0 .8.8-.3.8-.8 0-.8.2-.8.3zm4.1 11.3s-.7.5.3.6c1.2 0 1.7.3 2.1-.3s1.8-.4.8-1.2c-1-.8-1.6-.3-3.2 1z"/>
|
||||
<path fill="#ffc221" d="M531.5 275.5s3.8-3.5 6.9-1.2c3.2 2.5 3.4 2.8 3.5 2.9 0 0 .4.3-.4 1-.9.8 0 .8.9.3s1 0 1.4.5c.5.5 1.1.8-.3.8h-4.6s-2.1.2-1-.7c1-.9.8-1.9.3-2-.6 0 0 .6-.3 1-.4.4-1.1.7-1.9.7s-1.4.6-.2 1c1.1.4-.2.7-.8.7s-3.5.2-.5.6c3 .3-.3.3 2 1.5 2.4 1.4.6 4.3-.3 4.6 0 0-1 .5.2.4 1.3-.2 2-.3 1 .4-.8.6-2.6 2.9-5 1.2 0 0-1.2-.6.8-.7 2 0-1.6-.5-2.3-1-.5-.3-3-2.7-1.5-2.5 1.6.4 1-.5.1-.8-.8-.3-1-1.6 0-1.4 1 .3 2 .9 3 .8.7 0 .5-.3-1.2-.8-1.7-.6-2.4-.7-2-2 .4-1.5 2.3.5 1.8-.6-.4-1-2-.5-1.2-1.9s1-.8 1.5-.6c.3.1 1 0-.1-.8-.8-.5 0-1.3.2-1.4z"/>
|
||||
<path d="M534.2 276.5s0-.5.8-.4c.6 0 .4-.2.6-.4.2 0 1.9.5.3 1-.6.3-1.6.2-1.6-.2z"/>
|
||||
<path fill="#ffc221" d="M537.9 280.5s-1.3.6-.2 2c1 1 1 1.5 1 2.2-.1.8 43.4 1.3 43.4 1.3s0-2.9 1.8-4.5l-46-1z"/>
|
||||
<path fill="#5a3719" d="M582.8 285.2s.2-2.4 1.6-3.1c.7-.5 1.6-.3 2 1.6.6 2.7-1.7 5.1-2.7 4-1-1-.8-2.5-.8-2.5z"/>
|
||||
<path fill="#7b3c20" d="M532.9 295.4s2.9-2.5 3.4-3.6c0 0 7.8 5.6 7.3.4l.2-2.6s2.9.3 3.3-2l-7.3-.3s-.8-.1-2 1.1c-1 1.2-3.4 2.5-5.5 1.4 0 0-1-.8-1.9 0-1 .5-1 .7-.2 1.5s2.4 2.9 2.7 4zm16.8-15.4-4.3-.2s-1.5-2.2-4.6-4.6c0 0-.9-.4.8-1.8 1.8-1.4 2.3-2.8 2.3-3.5 0-.6 0-1.7.6-1 .6.8 5 4.9 5.8 3.7.6-1.2.7-1.7.7-2.1.2-.4.3-1.5 1-.3.6 1.1 1 .8 1.1 3.8 0 0 0 3 .5 4 0 0-5.6-1.7-3.8 2zm-18.6-9.2s3.3 2 5-.6c1.5-2.5 2.6-2.8 1.4-5.3-1.2-2.3 0-3.4.9-4.4 1-1 1.8-.8 1.8-4.6.2-3.9 2.8-5 4-6.3 1.2-1.2 4.2-3-.4-3.7-4.4-.8-13.4-3-15.7-6.5-2.3-3.5-3.3-1.5-3.3-1.3 0 .2-.8 2.7 1.5 7.3s4.2 7.6 6.5 9c2.2 1.5 4.2 2.3 3 5.4s-3 8.6-4.7 11z"/>
|
||||
<path fill="#5a3719" d="M543.2 261s.6 8 6.3 10.8c0 0 1.3-3 .8-6.1 0 0 1.9.1 2.4 1 0 0 0-2.3-2.6-3.2-2.7-.7-1.4-6-.4-6.5.9-.6.6-1.7 0-2.6-.7-1-.8-2.3 1.4-1.7 2.3.6 2-.6.5-1.7-1.3-1.1-1.3-2.5.7-2.5s5-1.9 3.2-2.4c-2-.6-2.5-1.3 0-2 2.7-.8 4-1.7 2-2-2-.2-3.3-.9-1.4-1.2 1.9-.3-.3-2.3-2.5-2.3-2.3-.2-7 .7-3.3-2.3 3.8-3-5.4-.8-1.6-2.8 3.8-2-1.3-1.1-2-1.1s-.7 0-.4-1c.2-1-.5-1.6-1.7-.9-1 .6-1 .6-1-.7 0-1.5-1.3-.4-2.1 0-.9.3-3 1.9-3.9 1-.7-.9-1.2-1.7-3.8-.2-2.6 1.5-2 .2-2-.5s1-3.4-2.4-.5-.7-3-3.5-1c-2.7 2-3 2.4-3.5 1.5-.5-1-1-1.7-4 .3-3.1 1.9-.8-1.3-.5-2 .5-.6 1.8-5-.9-1.6 0 0-1.3 2.4-4.2-1.9 0 0-3 4.3-3.9 2.4-.8-2-1.5-2-2.6-.8-1 1.2-.2-.1-.7-1.2-.4-1-.7-2.9-5.8.8-5.1 3.8 1.8 1-2.1 2.7s-13.5 7-4.8 5.9c8.7-1.3-4.2 3.3-1.2 4.2 3 .8 2 3.5 13.4.3 11.2-3 9.4-.4 15.2-3 5.8-2.4-1.4.9 6.4.8 7.7-.2 1.3 0 2.8 1.6 1.5 1.6 8 5.3 14.1 6 6.1.6 7.7-1.7 5.9 1-1.8 2.6-2.4 3.6-3.4 4.6-1 .8-4 3-4 6.6 0 3.7-4.8 4.3-3 8.3l4.1-4z"/>
|
||||
<path fill="#5a3719" d="M553.3 269.9s-1.4-1-1.4-2.8c0 0 1 .2 1.4.8 0 0 3.5-4-.8-5.4-4.1-1.4-2-5.3-.6-5.3s1.7-.3.4-2c-1.2-1.5-1-1.6 1.3-2 2.3-.4 2.1-1 1-1.5a7.7 7.7 0 0 1-1.9-1.6s6.8-2.9 4.6-4.3c-2.2-1.3 0-1 2-2.3 2-1.4 2.2-1.7 2.5-2.3 0 0-2 .3-3.4 0 0 0 1.7-.9 0-2.3s-2.3-2.6-5-2c-2.7.7-1.8-.2-.8-1.3s.6-1.7-1.3-2c0 0 .2-1.2 1.7-2.5 0 0-3.7.2-5-.4 0 0 1.6-1 1.6-2.3 0 0-2 .7-4.5.5 0 0 1.5-1.3 1.5-2.4 0 0-4.4 1-6.4 2.5 0 0-.5 0-.8-.6-.4-.4-.6-1-5.5.6 0 0 .5-2.2 1.7-3 1.2-.8 1-2.6-6.5 2.1 0 0-1-.6-1.9-2.9 0 0-1.7 2.3-2.9 3.1 0 0-1 .5-1-1 .2-1.5-.7-.5-1.4 0-.8.4-1.3 1.5-1-1.5s-1-3.6-1-3.6-2.3 3.3-3.7 3.7c0 0-2.5-2.4-3.4-4-.8-1.6-.8-2.2-1.7.6-.9 2.7-2 3-2 3s-1.5-1.3-1.6-2c0 0-.3.7-.8 1 0 0-1.3-1.5-1.2-3.7 0 0-8.2 4.5-9.2 7.2 0 0-7.7-.5-10.8.1 0 0 .7-2.4 2.7-3.7 0 0-2-.2-2-2.3 0 0 1.6.2 2.6 0s-1.4-3.1 1.1-3.2c2.5-.1 4.2 1.2 3-2.2-1-3.3-.6-3.3-.6-3.3s4.4 2.6 5.1 1.9c.8-.6-.5-2 3.4-1.4 3.9.7 2.8-1.5 4.4-1.7 1.5 0 2.3 1 1.3-6.1s4.8 3.5.9-7.2c0 0-1-3.3-3.3-4.7 0 0-.6 2.3-3.2.3-2.6-2-7.8-2.8-5.6-4.4 2.2-1.7 3.2-3.9 2.6-5.2 0 0-2.6 2.6-7 .7-3.6-1.5-4.4 1.3-8 .5 0 0 0-1 3.1-3.4 3-2.3-1.8.8-3.6 1.3-1.9.4-2.4 0 1.5-3.1 4-3 12-8.5 11-13 0 0 1.8 2.3 6.7.6 5-1.7 8.6-2.3 10-5 1.6-2.5 5.4-5 6.4-5.6 1.1-.5 2.4-1 .9 1.5-1.6 2.4-4 6.6-10.8 9.4-6.8 2.8-9.5 4.8-10.7 6.3-1.2 1.5-7.4 4.8-3.3 4.3 4-.7 10.9 0 7.6-1-3.2-.9-6.9.6-3.9-2.1 3-2.7 3.5-3.6 7.9-5.4 4.4-1.9 9.2-6.1 8.7-1.6-.5 4.4-8.6 9.1-10.6 10.6-2 1.4-1.2 1.2-1.2 1.8 0 .6-.4 1.8-1.2 2.3-.8.6-.5 1.2-.3 2.4.2 1.3-.2 1.8.4 2 .6.1 1.2.2 1.4 1.1.2 1 .6 1 1.8 1 1.1-.2 2 0 2 .6 0 .7 1.2 1.7 1.3-.4.1-2.2 1-2.5-1.2-1.5-2.2.9-2.6.6-2.6-.4s-.2-.8-1-.9c-1 0-1.3-1.3.3-2.2 1.6-.8 1.6 0 3.6-1.6 2-1.7 2-2 2.3-3 .3-.7-2.9 2.4-4.4 3-1.5.8-1-.5-.8-2.1.3-1.7 4-4 5.7-4 1.8 0 5.6 1 4 3.3-1.7 2.3-6.4 5.2-4.5 5.4 2.1.2 2.4-.6 3.6.4 1.2 1 0 3.2-.4 4.4a8.4 8.4 0 0 1-2.2 2.7s-2.2-3.8-2.1-.8c0 3.1-.5 4.2 0 4.3.5.1 2.8 1.7 3.6 1.7s-4.1 2.3-2 2.5c2 .1 5.3-1 6.4-3 0 0-4.2-1-5.9-2.6 0 0 4.9-1.2 3.5-5.8 0 0 4.9 1.3 2.7 3.5-2 2.1-3.3 1.8-1.5 2.4 1.9.6 2.7 1.2 2.7 1.2s1.3.6.5 1.6c-.7 1-.7 2.6 0 2.5.5 0 2.6-1 .9-2-1.8-1 1.9-.8.4-1.7-1.6-1-2-1.1-2.4-1.6-.5-.3 19.7-12.2 9.5-7.8 0 0 2.1-4.6 5.1-4.6 3 0 3.2 2.3 1.5 4.2-1.7 1.7-2.8 4.6-6.7 5.2 0 0 5.6 2.7-1 7.2 0 0-1.5.7-1 1.2s4.5-1.7 5-3a5.5 5.5 0 0 1 3-3c1.5-.7 9-5.8 11.2-9.6 2.3-3.9 2.8-4 7.2-7.5s3.6-2.8 4.2-3.6c.5-.9.7-2.3 2.7-3.4 2-1.2 9.8-5.4 12.3-7.2 2.4-1.8 7.4-5 9.6-7.8 2.1-2.7 8-6.2 9.4-5.6 1.4.7-.2 2.8-3.5 5.4-3.5 2.5-12 9.3-13.3 10.4a44.7 44.7 0 0 1-11.2 6.6c-2.7.3-2.4 1.3-4 3s-5.3 5.4-6.5 6.4c-1.3 1-4.3 3-4.4 4.5-.2 1.5.5 1.6-1.9 3.8a50 50 0 0 1-11.9 8.1s4.5 1.6 1.8 4.6c-2.6 3-2.5 2.6-2.6 2.8 0 0 6.7-1 2 4.3 0 0-1 1.5 1.1 0 2.3-1.9 1.4-4.1 1-4.5 0 0 3.7-2.3 7.9-2.3 4.1 0 4-.3.2-1.4 0 0 2.7-3.2 5-1.6 2.2 1.5 1.4 2.5-.9 3.8-2.4 1.2-5.8 1.7-8.5 3.2 0 0 5 1 7.6-1.1 2.6-2 2.8-1 3-.6.5.4.8 1-.4 2.6-1.2 1.7-1.3 1.8-1.2 2.2 0 .4-.1 1.5-2.5 2-2.3.3-3.5 1.3-2.6 2.4.7 1.2.7 4-1.2 3.7-2-.3-1.6-1.9-2.3-2.5-.8-.6-1.9-1.5-5.4.2-3.6 1.9-3.8-.3-3.7-1.5 0 0-2.3 2-4.2.2-2-1.9-.2-2.6 1-3.5 1-1 5.5-3 2.8-2.5-2.7.3-6.7.4-7.6-1.6-1-2.1 2-1.9 2.4-1.7.5.2 2.3 1.7 2.5-.3 0-2 3-2.3 2-2.6-1-.4-2.5.9-2.9 1.3 0 0-2-2.9-5.4-2-3.4 1 1 .7 2 .8.8.2.3 1.8-2.7 4.6-3 2.7-1.7 1.8.5 1.8 2.3 0 7.9 0 4.6 2.6-3.2 2.7-4.5 4-6 3.6-1.8-.5 0-1.6.8-2.1s1.2-1.2-.4-.6c-1.6.5-2.1.7-3.4-1.5-1.2-2.3-.8-1.6-.2-3.1.6-1.5 1.8-3 .4-2.5-1.6.6-1.4.7-1.3-1 .1-1.7-1.7-2.1-1.7-2.1s.8 1.7.1 2.8c-.6 1-.7 1.4.4 1.6 1 .4 2 1.3.6 2.3-1.4.9-1.2.7-.4 1.3 1 .7 2.3 1.3.9 2.7-1.4 1.4-.3 1 .4 1 .8 0 2.3.6 2.3 2 0 1.2 0 1.5 2.3.3 2.3-1.3 6.7-1.1 6.7.6 0 1.8-.6 2.3 1.8.8 2.4-1.5 3.5 1.4 5.2 0 1.6-1.5 2.6-2.8 4.6-.4 1.9 2.4 1.3 3-1 4.8-2.3 1.7 1.1.4 2.9-.5s6.7-1.5 9.5-.2c2.9 1.2 3.7 1 5.8 0 2.1-.8 3.2-1 6.3 1.1 3.3 2.2 5.7 2.6 7.4 2.5 0 0-3.5 1.4-7.5 1.6-4 .3-6 1-6.7 1.6 0 0 2.3 1.5 2.8 3.2 0 0 2.6-.3 3.8.2 0 0-.6 1.9 1 2.9s2.7 1.4 1.5 2.7c-1.2 1.4 1.9.8.1 2.7-1.7 2-2.1 3-2.2 4.5 0 1.6.4 1.8-1.1 2-1.6.1.2 1.9-.5 4-.7 2-5 1.7-4.8 7.2 0 0 1.2-2.7 3.8-5 2.5-2.4 2.6-2.6 2.5-4 0-1.4-.1-1.1 1.2-2.2 1.4-1-.6-2 .8-3.6 1.3-1.5.2-1.2 1.8-2.7 1.5-1.6-1.5-1.7.2-3.3 1.5-1.6-4-3.5-2.3-4.5 1.5-1 4.3-2.4-5-2.3 0 0 2.3-3.6 10-2.9 0 0-2 1.6-2.2 3l1.6.5s-.4 1.1-1.9 2.3c0 0 4.2 2.3 4.9 3.8 0 0-2.6.8-3.3 1.8 0 0 1.2 1.3 1.6 3 0 0-2.9-.4-3.2 1.7-.4 2.1-1.3.7-1.3 2s.1 1.7-.9 2c-1 0-.1 1.1 0 1.8.2.7.6 2.3.4 2.8 0 0-1.5 0-2.1.2 0 0 .4 3-1.3 3.5-1.7.4 1 1-.9 1.3-1.8.3-1.5.5-3.7 4.5 0 0 1.9-1 3.8-2.4 2-1.3-.2-1 3-4 3.3-3.3 2.7-3.5 2.4-5.1-.2-1.6-.3-3 .9-4.5s1.5-3.2 5.7-3c0 0-1.2-2.8-2.7-3.5 0 0 2-1.3 4-1.5 0 0-1.8-2.3-5.6-4.4 0 0 3-2.6 3.9-3.9 0 0-1.5.3-2.7 0 0 0 .6-1.3 3.4-3.1 0 0 1.5 1.4 1.4 2.9 0 0 4.8-2.7 7.5-2.4 0 0 1.4 3.4-5.3 10 0 0 4.2.3 6 0 0 0-1 3.2-6 5-5 2 1 4.2-4.1 3.8-5-.4-3.5 1.3-3.4 3.9.2 2.6.3 5.3.2 6 0 0-4-1.3-4 2.6.1 4-2 4.8-2.5 5.1 0 0-1.2-1-3-1.7 0 0-2.5 4.9-6.5 7.7z"/>
|
||||
<path fill="#7b3c20" d="M547.4 220.5s1.4-.2 3.8 1.2c2.3 1.5 4.6-1.5 2-2.3-2.6-.8 0-1.8 2.4.2 2.4 1.9 3.3.9 4.2.3.8-.7 1.9-1.1.3-2.2-1.6-1.1 1-.6 2.3.3 1.2.7.7 1.5.6 1.7-.2.2-.3 2.9 2 .5 2.4-2.5 3.7-4.8 3.6-6 0 0 1.3.8 1.5 2.3.2 1.5 2-.8 2.6-1.6.6-.8 1.6-3 1.5-4.4 0 0 1.6 2.5 4 0s1.4-1 4.2-1.7a17.6 17.6 0 0 0 8.5-5.2c2-2.5 2.1-.8 4.6-1.4s7.7-4.2 8.2-6.1c.4-1.9.3-3.1-.4-2.4-.7.6-.4 0-1.5-.6-1.1-.7-2.7.9-2.7.9s1.6 1.2.3 1.7c-1.2.6-2.3 2.3-4.6 1.6-2.3-.6-4.8 2.2-4.8 2.2s2 1.6-.7 2.7c-2.7 1-2.3 1.4-3.9.2 0 0-2.9 3.7-4.6 4.5 0 0-.7 0-1.2-.8 0 0-2 2.1-2.8 2.5 0 0-1.3-1-2.3-1.5 0 0-2.3 2.9-4.2 3.7 0 0-.6-1-1.8-1.7 0 0-.6 3.6-4.6 5.8 0 0 .2-1-1.8-2.3 0 0-5 4.3-6.9 4.7-2 .4-.2-.9 0-1.5.4-.5 1.6-2.3-.8-3s-2 .5-2.5.7c-.6.2-.6-.4-2.2-.2s-1.3.9-2 1.2c-.8.2-3.6-.5-3.4 1.4.1 1.8 1.5 3.1-1 4.2-2.5 1 1 .8 4.1.4z"/>
|
||||
<path fill="#5a3719" d="M557.5 215.3s.6-2.5-1.5-3.5c0 0 13.2-2.1 3.2-7.2 0 0 11.9-2.3 9-6.1-2.7-3.8-5.4-3-5.8-3-.4 0 2.5-2.1 3.3-1.8.7.3 10.2 3.9 7.8.7-2.4-3-2.2-2.9-2.6-3.8 0 0 3.1 0 7.9 4.6 0 0 1-1 .9-2.9 0 0 3.3 1 4.4 2 0 0 .6-1.2.3-1.8 0 0 3 1.5 4 3.2 0 0 1.3-1.2 1.5-2.6 0 0 3 1.3 3.7 2.2 0 0 1-1.3.6-3 0 0 4.9 1.3 5.5-1.6 0 0 4.9 1 1.7 2.9-4 2.5-.4-.6-4.6 2.3-3.2 2.3-5 4.9-6.6 4.4-1.1-.5-2.5 2.9-4 1.3-1.5-1.7-1.5-1-2.7.7a24.5 24.5 0 0 1-2.8 3.5s-.8-.5-1.6-1.2c0 0-.8 1.6-2 2.8 0 0-1-1.3-2.6-2 0 0-2.3 2.7-3.8 3.7 0 0-1.4-1.4-2.9-1.9 0 0-.2 3.8-3.1 5.7 0 0-.6-1.2-2.6-2 0 0-1.4 2.3-4.6 4.3z"/>
|
||||
<path fill="#5a3719" d="M550.6 209.5s-1.6 1.2-.6 2.5c1 1.4 1.1-.2 2.4-.3 1.3-.2 17.5-3 2.8-7.3 0 0 .7-.6 3.1-.8 2.6-.3 11.8-2.7 7.5-6-4.3-3.2-7.9 1.1-4.3-2.8 3-3.1.6-4.6.6-4.6s-8.5 5.6-10.4 6.7c-1.8 1-4.6 3-1.4 4 3.3 1 5.4-3.4 5.7-2.4.3 1-6.4 4.8-5.4 6.4.9 1.8.7 3.3 2.4 2.9 1.6-.3 6 .8 2.5.7-3.7-.1-5 1-5 1z"/>
|
||||
<path d="M556.4 201.3s-1.5 1.1.5.6 5.9-1.4 5.2-2.4c-.8-1-3.4.2-5.7 1.8z"/>
|
||||
<path fill="#7b3c20" d="M582.4 184.5s7.5-.2 10.5 1.9c3 2 4.6 3.4 5.5 3.8 0 0-.1 2.8-5 .7 0 0 .4 1.4-.2 2.8 0 0-1.7-1.2-3.8-1.7 0 0-.4 1-1 1.7 0 0-2.1-2.2-4.6-2.9 0 0-.4 1.1-.8 1.6 0 0-2.6-1.6-4.6-1.6 0 0 .4 1.7 0 2.3 0 0-5.4-4.3-10.3-3.8 0 0 2.3 3.5 3.8 5.1 0 0-9.8-.7-8-6 1.5-5.3-.2-4 6.2-4h12.3z"/>
|
||||
<path fill="#5a3719" d="M536.3 199.1s-1.1 1 0 1.7c1.1.8 5-2 5.5-2.4.6-.4 2-.4 0 1.1s-3.8 3-5 4.6c0 0 6.4-1.8 10.6-5.4 4.3-3.7-.1-1.3 7-4.8 7.3-3.5 11.1-9.1 7.2-8.5-3.8.6-7.3 5-10.4 6.7-3 1.7-4.7 2-4.2 1 .4-1 2.7-.6 6.9-4 4.1-3.3 3.2-3 3.2-4.2 0-1.2-1.5-4 4.7-7.4 6.2-3.3 25.6-14.5 27.3-18.5 0 0-5.7.6-13.2 6.1a69.7 69.7 0 0 1-13.4 8.8c-2 .8-1.8.2-3.1 1.9a171.8 171.8 0 0 1-10.1 9.8c-1.3 1-1.8 1.6-1.9 3.8 0 1-8.4 7.3-11 9.7z"/>
|
||||
<path fill="#5a3719" d="M562 184.3s-1.5.6-3 0c-1.3-.7-.8-3.6 2.5-5.5a50 50 0 0 1 12.6-4.8s-.5 3.8-10.1 7.1c0 0 .6 2-2 3.2z"/>
|
||||
<path fill="#aa5323" d="M565.4 181.8s.3 1 0 1.8c0 0 17.9 1.7 27.1-9.2 0 0-12.7 1.2-17.7 4.3 0 0 3.2-4 12.7-7.3s13.4-7.4 14.2-9.7c0 0-12 4.3-17.7 4.3 0 0-1.2 0-2.3.5-1.1.7-8.8 6.2-10.8 7.2 0 0 4.3-.4 5.9-1.8 0 0-3 8-11.4 10z"/>
|
||||
<path fill="#5a3719" d="M531 192s-2.3 1.7-1.3 2.4c1 .9 2.6 1 6-1.9 3.6-3 12.1-10.2 6.8-10.5 0 0-7-.4-6.7 3.8.2 4.2-4.4 6-4.8 6.2zm-15.9-2.5s4.6 2.7 2.8 4.9c0 0 14-11.8 10-14.4-3.8-2.6-6.9 2.3-6 2.7 1 .6 3-.4 2.3.6a77.4 77.4 0 0 1-9 6.2zm-3.6-3.8s3 1 3.2 2.3c.1 1.2 9.2-6.4 6.8-9.7-1.1-1.5-6-2-6.4.8-.2 3 4.6-.3 3 1.8-2.2 2.7-5.9 4.4-6.6 4.8zm32.6-6.4s-1.9 1.4-.1 2.3c1.8.7 2.8-.6 3.7-1.3.9-.8 5.3-4 6.2-6 1-2 2.5-2.7 4.1-3.7 1.5-1 12.6-6.6 19.5-12.7 6.8-6.1 4-4.5 11-8.4s11.7-7.5 13.2-11.8c0 0-3.3 1-6.2 3a243 243 0 0 1-10.7 6.5c-1.3.5-3 .6-4 1.6s-1 2.3-4.3 5c-3.5 2.9-21 15.3-23.2 17a334.7 334.7 0 0 0-9.2 8.5z"/>
|
||||
<path fill="#aa5323" d="M530 183.4s2-1 5.6-.8c3.6.2 17.8-13.6 22-16.3a341.6 341.6 0 0 0 18.7-13.8c1.8-1.8 2-3.6 3.6-4.6 1.5-1 3-.9 6.4-2.9 3.5-2 20.3-12 19.3-17.8 0 0-25 15-30.7 19.8a375 375 0 0 1-24.7 17.7c-2.8 1.9-5 5-9.9 8.8-4.7 3.9-9.5 7.2-10.3 10z"/>
|
||||
<path fill="#aa5323" d="M524.8 178s4.6-.4 5.2 1.9c0 0 10-6.8 12.2-9.6 2.2-2.8-.8-1.2 4.9-4.9a594.3 594.3 0 0 0 27-19.1c2.7-2.3 7.8-5.5 11.9-8.2 4-2.8 19.9-10.6 18.1-17l-14.2 9.5c-2.7 1.8-3.9.8-6.5 2.9-2.6 2.1-8.5 6.3-9.5 7.6a161.3 161.3 0 0 1-14.4 11c-4.4 3-14.1 8.6-18.9 12.8a602.8 602.8 0 0 1-15.8 13.2z"/>
|
||||
<path fill="#aa5323" d="M510.4 176.8s2.3 0 3.1.9c0 0 4.3-3.9 8.9 0 0 0 16.8-11.5 18.5-14.4 1.7-2.8 4.5-2.9 11-7.6 6.6-4.8 10.7-6.9 15-10.2 4.4-3.4 8.1-7.3 11.2-9.3 3.1-2 11-7.2 9.8-11.7 0 0-6.5 3.6-10.6 8.2-4.2 4.6-3.8.7-8.1 4.5a82.7 82.7 0 0 1-16.3 11.7c-5.5 2.7-2.2 2.4-6.2 5-3.9 2.5-3.6 2-5 2.5a10 10 0 0 0-5.1 3c-1.6 1.7-5.4 4-9.6 6.5a106.5 106.5 0 0 0-16.6 10.9z"/>
|
||||
<path fill="#aa5323" d="M515.5 168s-1-1.9.7-3.3c1.6-1.3 4.6-4.8 5-7 .5-2.3.1-1.9 4.8-3.8a188.2 188.2 0 0 0 38.2-21.6c1.8-1.5 6.4-4.6 8.3-6.2 0 0 .8 2.5-1.2 4.2a222.1 222.1 0 0 1-21.5 14.9c-2.2 1.1-7.6 3.9-9.6 5.5-1.9 1.6-1.6 2-10.2 6.3-8.5 4.1-9 4.6-8.7 4.9.3.4 4.2-1.3 6-2.4 1.8-1 8.8-4.3 11-6a69 69 0 0 1 7-5 296 296 0 0 0 18-11.2c3.5-2.7 4.5-3.5 5.3-3 .7.4 2 .4.4 2s-6.7 6-8.7 7.3c-2 1.3-8.1 5-9.8 5.8-1.7 1-2.4 2.5-3.4 3.2-.9.8-3.7 2.7-7 3.5s-4 3.3-6.3 4.8c-2.3 1.4-18 10-18.5 10.3 0 0 .9-1 .2-3.2z"/>
|
||||
<path fill="#aa5323" d="M570.3 132.4s-.9.8-.4 1.2c.6.6 2.8 2.2 5.6-.6a106.5 106.5 0 0 1 12.5-10c2.3-1.5 3.6-2.8 3.5-4.7 0 0-11.4 6-21.2 14.1zm15.6-1s1.7-2.9 6-5.7c4.3-2.7 10.8-6.7 11.5-7.6 0 0 1.6 1.7-1.7 3.8a311.7 311.7 0 0 0-10.8 7c-.7.7-2 1.6-5 2.5z"/>
|
||||
<path fill="#7b3c20" d="M499 163s-4.8 2.6-3.1 4.2c1.7 1.5 4.2 1 5.4.6l3.2-1c.4 0 4.5-1.3 5.6-3.2 1-2 3.8-4.2 6-5.8 2.2-1.5 3-3.2 2.7-4.3L499 163zm-28.4 22s3.4-2 8-.7c0 0-.2-1.1-1-1.7 0 0 5.7-1.5 6.9-4 1.2-2.5 1.5-2 2.5-2.6 1.2-.8 8.7-6.8 7.8-8.1-.9-1.3-1-3.1-1.7-3.7 0 0-1.5 2.1-9 5.7-7.2 3.6-15.4 6.2-21.4 14.2-5.9 8-5.3 12.6 2 14.7 0 0 5-3.2 17.6-2.1 12.4 1.1 16.6 5.8 17.4 6.6.8.9 3.3 4 .9 9.1 0 0 2.5 1.1 2.6-1.3.3-2.3.4-1.8 1-1.5.6.4 1.3.5 1-1.4a18 18 0 0 0-2.3-7.2c-1.1-1.5.2-.8.9-.6.7.3 3.3 2.5 1.8-1.5-1.5-3.8-2-2-2-1.8 0 .3-.4 1.2-3.8-1.4a26.8 26.8 0 0 0-8.8-4.4c-2.3-.6-.7-.6.7-1 1.4-.6 3.1-.8 3.8-2.4 0 0-1.4.3-3.8-.6a13.2 13.2 0 0 0-11.5 2s1.2-4.5-2.5-4.3c-3.6.3-6.2.2-10 3.2 0 0-.3-4.6 3.4-7 3.7-2.5 3.2-1 5.2-1.6 2-.6 2.3-2.7 1.4-3.4 0 0 4.8.9 12.8-5.8 0 0-4.3 5.7-9.5 6.8 0 0-.9 3-5.7 3.7-4.8.7-4.6 3.4-4.6 4.1z"/>
|
||||
<path fill="#5a3719" d="M457 212.7s2.2-14.1 15.5-15.1c11.4-1 15.1.5 17.4 1.3s8 2.4 5.8 4.2c-2.2 1.8-3.5 1.5-3.5 1.5s2.5-2.9.2-3.3c-2.3-.5-2.4.9-2.7 2-.4 1.3-.5 2.6-1.6 3.6 0 0-1.2-1.4-2.9-.2s-.2 1.2.5 1c.6-.2 1.5-.5 1.3.5-.1 1-1 2.8-3.8 4.2-2.7 1.4-2.6 1.3-5.8 1.9-3.3.5-6.3 1.8-10.5 5.3-4.2 3.6-8.7 2.4-9.6-1.5-.8-3.4-.4-5.4-.4-5.4z"/>
|
||||
<path d="M472 212.2s1.2-2.7-1-4c0 0-6.9 1.2-9-.9 0 0 7.5-.4 12.2-2.3 4.6-1.7 3.3-3 1.7-3.4-1.6-.3-4.6.5-4.9 2 0 0-1-1.6.2-2.6 1.3-1.1 3-1.3 4.7-.8 1.7.4 3.1 1.2 8.6-1.6 0 0 3.1.7 3.3 2.8 0 2.2-.3 3-.6 3.3-.2.4-.6 1-1.3 1-.6-.2-1.5-.3-2.3 1.2-.7 1.5-1.3 2.7-2.6 3.7 0 0 1.5-4.6-2.5-5.7 0 0-3.3 2-5.8 2.1 0 0 3.2 3-.8 5.2z"/>
|
||||
<path fill="#5a3719" d="M479.3 203.8s-1.6-1.6.4-1.9c2-.1 4.6 1.4 4.2 2.7-.6 1.2-3 1.1-4.6-.8z"/>
|
||||
<path fill="#fff" d="M592.6 181.6s-3.7 1-.2 3.3c3.4 2.3 5 4.2 7.5 4.8 2.5.7 5 1.5 5 4s-.5 3.5-1.9 5.2c-1.3 1.7.8 2.4 2.6 1.5 1.8-1 3.3-1.5 4.5-2.2 1.1-.7 3-.6 1.4.3-1.9 1-3.7 1.5-1.4 1.5 2.3.1 16.2.4 19.1-.6 3-.9 6.8-1.2 7-5 0 0 .2-1.6 1.3-2.4 1-.7 1.8-2.3.2-1.2-1.5 1.1-2.7 1.7-3 1.3-.3-.3-.5-.6.7-1.1 1.2-.5 1.8 0 2.9-1.5 1-1.6 1-1.4.4-2-.6-.6-1.8-1-1.2-1.8.6-.8 1.2-3-1.4-1.7-2.5 1.3-7.6 4.8-10 5.3-2.2.5-4 1.2-7.1 1.8-3 .7-5 1.4-8.5 3.3-3.3 1.8-3-1.1-2.5-1.5 0 0 1.3 2.3 4.7-.7 3.4-2.9 2.3-.1 10.6-2.9 8.3-2.7 6.3-3.1 9.5-4.8 3.3-1.7 6.4-1.8 4-4-2.2-2.4-2.4-2.5-5.3 0a34.5 34.5 0 0 1-16 6.4s18.8-8 16.9-9.2a20.8 20.8 0 0 0-5.3-2.5c-1.3-.3-1.7-.6-4.7.8-3 1.3-3.5 1.6-4.3 1.7-1 0-3.5.6-7 2.4-3.6 1.9-5.5 2.6-8 4 0 0 1.7-3.3 9.1-5.5 7.4-2.2 11.1-4.2 10.4-4.6s-2.7-.8-4-.5c-1.5.3-1-.1-5.6 1.7-4.5 1.8-2.6 1.4-6.2 2.2-3.7.7-5.1 1.5-6.9 2.3 0 0 .8-1 3.1-1.9 1.3-.4-1.3-.9 2.2-1h1a32.2 32.2 0 0 0 8.6-3.3c-.7-.1-5.1-.6-9.5 1.6-4.5 2-2.5 1.3-4 1.5-1.6.4-5 2.4-6 3.4-1.1.9-2.7 1.5-2.7 1.5z"/>
|
||||
<path fill="#5a3719" d="M482.7 201.8s1.8.5 2.2 1.8c.5 1.2 1.6-.6 1.6-1.1-.1-.6-1.2-3-3-1.9-2 1.1-1 1.1-.8 1.2z"/>
|
||||
<path fill="#7b3c20" d="M477.9 226s3.7-1.8 6.9-1.5c0 0-1.3-4.4.9-3.7 2.1.8 1.5.4 2 .4 0 0 .1-2.9-.5-4 0 0 2.3.5 4.6.5 0 0-2.2-4.1.2-7a6.9 6.9 0 0 0 4.2 3.4v-2.3s1.7-.3 3 .4c1.4.8 2.5-7.6-1.5-9.3 0 0-1 1.5-4.7 2.3s-3.7 1.5-5.2 4.3-3 2.9-6.2 5c-3 2-5 6-5 6.4 0 0 1.5 2 1.3 5.1z"/>
|
||||
<path fill="#999" d="M603.1 177.8c1.3-.2-1.4-.9 2-1h1a32.2 32.2 0 0 0 8.7-3.3c-.7-.1-5.1-.6-9.5 1.5s-2.5 1.4-4 1.7c-1.6.3-5 2.3-6 3.3-1.1.9-2.7 1.5-2.7 1.5s-3.7 1-.2 3.4c3.4 2.3 5 4.2 7.5 4.8 2.5.7 5 1.5 5 4a7 7 0 0 1-1.9 5.2c-1.3 1.7.8 2.4 2.6 1.5 1.8-1 3.3-1.5 4.5-2.2 1.1-.7 3-.6 1.3.3-1.8 1-3.6 1.5-1.3 1.5 2.3.1 16.2.4 19.1-.6 3-.9 6.8-1.2 7-5 0 0 .2-1.6 1.3-2.4 1-.7 1.8-2.3.2-1.2-1.5 1.1-2.8 1.7-3 1.3-.3-.3-.5-.6.7-1.1 1.2-.5 1.8 0 2.9-1.5 1-1.6 1-1.4.4-2l-1-.9s-.9-.7-1.9-.1a27.6 27.6 0 0 1-7 2.7c-1.6.1-3.5.9-6.5 2.4s-8.2 4.6-9 1.7l-2.8 1c-3.4 1.8-3-.7-2.5-1.4 0 0-1.8 2-1.7.2 0-1.8 1.2-1.5 3.3-2.1 2-.6 5-2 3.8-3-1.3-1-2.7 1-4.2 1.8-1.4.7-4.3 1.2-4.8-.9-.4-2.1-.4-3.6-4.3-3.8-4-.2-3.9-2.7-2.8-3.8 1.1-1 2-2.8 5.7-3.5z"/>
|
||||
<path d="M615.6 196.9s6.1-2.8 11.7-4.1c5.7-1.3 1.2.2.3.4-1 .3-9.7 3.2-11.8 4.2-2 1-1.7.2-.2-.4zm1.4 1.3s6.9-2.3 8.2-1.4c1.3 1 .2.6-1.3.8-1.6.1-5.7.8-6.8.8-1.1 0-.1-.2-.1-.2zm11-2.5s1.4-.2 1.5.4c.1.4-.6.5-1.3.4-.7-.1-1.3-.5-.1-.8z"/>
|
||||
<path fill="#fff" d="M446 255.9s-.3-6.2 2.8-9.2 17.8-18.5 20.1-22.8c0 0 2 1.3 2 3.8 0 0 2.5-4.3 4.5-6 0 0 1.7 1.8 1.5 5.4 0 0 3.5-1.9 9-1.9 0 0-2 2.4-2.1 3.9 0 0 7.6-1 11.7-.3 0 0-10.6 6-7.7 6.5 3.1.5 6.2 0 6.2 0s-3.4 3.3-8.8 4c0 0 6.9 0 8.2 1.5 0 0-6.6 1-12 5 0 0-.4-.2-.4-1.7 0 0-.3 1.4-1.8 2.7-1.5 1.2-5.1 4-6.5 5.3-1.4 1.3-3.8 4-6.6 4 0 0 .6-2.1-1.4-2.8a5.7 5.7 0 0 0-6 1.5s-7 .1-9.4.5c0 0 1.6-2.6 3-2.6 1.6 0 7.6 1 8.1-3.2.6-4-3.8-3-2.2-5.4 1.7-2.4 1.3-2.2 1.4-2.6 0 0-1.4.8-2.2 3a10.7 10.7 0 0 1-4.2 6 15 15 0 0 0-4.8 5s-1.3 0-2.4.4z"/>
|
||||
<path fill="#fff" d="M452.8 252.2s.3-.8 2.3-1.2c2.2-.3 2.3-1.3 2-1.8-.3-.4-1.5-.4.5-2.8 0 0 .8.3 1.2.8.6.6 2.9 5.5-6 5z"/>
|
||||
<path fill="#999" d="M447.9 247.9c0 4 5.3 2.5 5.3 2.5a21.4 21.4 0 0 0-3.8 3.6c.4-2-3-2.5-3-2.5a12.3 12.3 0 0 1 1.5-3.6zm19.3-21.5 1.7-2.5s2 1.3 2 3.8c0 0 2.5-4.3 4.5-6 0 0 1.7 1.8 1.5 5.4 0 0 3.5-1.9 9-1.9 0 0-2 2.4-2.1 3.9 0 0 7.6-1 11.7-.3 0 0-10.6 6-7.7 6.5 3.1.5 6.2 0 6.2 0s-3.4 3.3-8.8 4c0 0 6.9 0 8.2 1.5 0 0-2 .3-4.6 1.2 0 0-1.9-1.8-7.6-1.5 0 0 4.4-2.6 8-3.4 0 0-1.6-2-4-.1 0 0-4.9-3.3-.8-6.2 0 0-2.8-.5-4.7.8 0 0 0-2.3 2.1-3.3 0 0-5.4-1-6.7 3 0 0-1-1.5-.5-3.4 0 0-3.3 1.9-4.8 4 0 0-.5-4-2.6-5.5M456.8 252c-.9.2-2.3.3-4 .2 0 0 .2-.5 1.3-1 0 0 .4.8 2.7.8"/>
|
||||
<path d="M466.6 236.7s2.5 2 3.3 3c0 0 2.3-1.4 3-2.7 0 0 1.9 1.1 2.4 2.8 0 0 1.3-.8 1.5-2 0 0 3 .6 4.2 1.6 0 0 .4-3 0-4.8 0 0 2.1.2 3.4.7 0 0-1.2-2 5-4.5 0 0-4.7 1.1-6.5 3 0 0-2 .2-2.9-.4v4.5s-1.2-.6-3.5-1.1c0 0-.6 1-1 1.2 0 0-1.5-1.2-2.1-2.7 0 0-2.3 2.1-3 3 0 0-2.3-1.6-3.8-1.6z"/>
|
||||
<path fill="#ffc221" d="M452.5 267.3s1 .4 3.3-1.4 8.7-5.9 9.2-9.2c.7-3.3-2-3.4-4-2.5-2.2 1-1.3 2.7-1.2 3.4 0 .6.2 2.9-3.3 6l-4 3.7z"/>
|
||||
<path fill="#ffc221" d="M451.9 268.3s-5.2-2.2-.6-4.5 6.7-2.9 7.2-4.9c.6-1.9.2-1.5-1.5-.7-1.7.7-8.2 3.8-9.2 1 0 0 2.7 1 6-.6 3.4-1.7 6.2-2.1 4-2.8a37 37 0 0 0-11 .5c-1.4.4-1 .3-1.3 1.6-.2 1.3-1.6 4-2.2 4.7-.5.8-1.8 4 .6 5.5a8.6 8.6 0 0 0 8 .2z"/>
|
||||
<path d="M449.9 257s-1.3.2-1 .7c.2.5.5.4 1 .4.3 0 1-.2 1.1-.5 0-.3-.8-.7-1.1-.5z"/>
|
||||
<path fill="#fff" d="M451.5 267.1s-2.4-1.1.4-2.6c2.7-1.5 5.6-3 6-3.6 0 0-1.3 1.9-6.4 6.2z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 32 KiB |
@@ -1,6 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-at" viewBox="0 0 640 480">
|
||||
<g fill-rule="evenodd">
|
||||
<path fill="#fff" d="M640 480H0V0h640z"/>
|
||||
<path fill="#c8102e" d="M640 480H0V320h640zm0-319.9H0V.1h640z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 237 B |
@@ -1,8 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-au" viewBox="0 0 640 480">
|
||||
<path fill="#00008B" d="M0 0h640v480H0z"/>
|
||||
<path fill="#fff" d="m37.5 0 122 90.5L281 0h39v31l-120 89.5 120 89V240h-40l-120-89.5L40.5 240H0v-30l119.5-89L0 32V0z"/>
|
||||
<path fill="red" d="M212 140.5 320 220v20l-135.5-99.5zm-92 10 3 17.5-96 72H0zM320 0v1.5l-124.5 94 1-22L295 0zM0 0l119.5 88h-30L0 21z"/>
|
||||
<path fill="#fff" d="M120.5 0v240h80V0h-80ZM0 80v80h320V80H0Z"/>
|
||||
<path fill="red" d="M0 96.5v48h320v-48zM136.5 0v240h48V0z"/>
|
||||
<path fill="#fff" d="m527 396.7-20.5 2.6 2.2 20.5-14.8-14.4-14.7 14.5 2-20.5-20.5-2.4 17.3-11.2-10.9-17.5 19.6 6.5 6.9-19.5 7.1 19.4 19.5-6.7-10.7 17.6 17.4 11.1Zm-3.7-117.2 2.7-13-9.8-9 13.2-1.5 5.5-12.1 5.5 12.1 13.2 1.5-9.8 9 2.7 13-11.6-6.6-11.6 6.6Zm-104.1-60-20.3 2.2 1.8 20.3-14.4-14.5-14.8 14.1 2.4-20.3-20.2-2.7 17.3-10.8-10.5-17.5 19.3 6.8L387 178l6.7 19.3 19.4-6.3-10.9 17.3 17.1 11.2ZM623 186.7l-20.9 2.7 2.3 20.9-15.1-14.7-15 14.8 2.1-21-20.9-2.4 17.7-11.5-11.1-17.9 20 6.7 7-19.8 7.2 19.8 19.9-6.9-11 18 17.8 11.3Zm-96.1-83.5-20.7 2.3 1.9 20.8-14.7-14.8-15.1 14.4 2.4-20.7-20.7-2.8 17.7-11L467 73.5l19.7 6.9 7.3-19.5 6.8 19.7 19.8-6.5-11.1 17.6 17.4 11.5ZM234 385.7l-45.8 5.4 4.6 45.9-32.8-32.4-33 32.2 4.9-45.9-45.8-5.8 38.9-24.8-24-39.4 43.6 15 15.8-43.4 15.5 43.5 43.7-14.7-24.3 39.2 38.8 25.1Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,186 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-aw" viewBox="0 0 640 480">
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill-opacity=".7" d="M0 0h288v216H0z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#a)" transform="scale(2.2222)">
|
||||
<path fill="#39c" d="M0 0v216h324V0H0z"/>
|
||||
<path fill="#ff0" d="M0 144v12h324v-12H0zm0 24v12h324v-12H0z"/>
|
||||
</g>
|
||||
<path fill="#9cc" d="m142.7 28 2.9 3-3-3zm-3 6 3 3-3-3m5.9 0 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m139.7 37 3 2.9-3-3m5.9 0 3 3-3-3z"/>
|
||||
<path fill="#6cc" d="m136.7 42.8 3 3-3-3z"/>
|
||||
<path fill="#c66" d="m142.7 42.8 2.9 3-3-3z"/>
|
||||
<path fill="#6cc" d="m148.6 42.8 2.9 3-3-3z"/>
|
||||
<path fill="#ccf" d="m136.7 45.8 3 3-3-3zm11.9 0 2.9 3-3-3z"/>
|
||||
<path fill="#fcc" d="m139.7 48.7 3 3-3-3m5.9 0 3 3-3-3z"/>
|
||||
<path fill="#6cc" d="m133.8 51.7 3 3-3-3z"/>
|
||||
<path fill="#c00" stroke="#fff" stroke-width="3.7" d="m142.2 34-20.7 78.5L42.8 134l78.4 20.5 21 78.4 20.9-78.4 78.4-21-78.4-20.9-21-78.4z"/>
|
||||
<path fill="#6cc" d="m151.5 51.7 3 3-3-3z"/>
|
||||
<path fill="#9cf" d="m133.8 54.6 3 3-3-3m17.7 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m136.7 57.6 3 3-3-3m11.9 0 2.9 3-3-3z"/>
|
||||
<path fill="#69c" d="m130.8 60.5 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m137.7 62.5 1 2-1-2m11.8 0 1 2-1-2z"/>
|
||||
<path fill="#69c" d="m154.5 60.5 3 3-3-3z"/>
|
||||
<path fill="#9cf" d="m130.8 63.5 3 3-3-3m23.7 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m133.8 66.4 3 3-3-3m17.7 0 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m127.9 69.4 3 3-3-3zm29.5 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m127.9 72.3 3 3-3-3m29.5 0 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m127.9 75.3 3 3-3-3m29.5 0 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m125 78.3 2.9 2.9-3-3z"/>
|
||||
<path fill="#fcc" d="m130.8 78.3 3 2.9-3-3m23.7 0 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m160.4 78.3 3 2.9-3-3z"/>
|
||||
<path fill="#9cc" d="m125 81.2 2.9 3-3-3z"/>
|
||||
<path fill="#c33" d="m131.8 83.2 1 2-1-2m23.6 0 1 2-1-2z"/>
|
||||
<path fill="#9cc" d="m160.4 81.2 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m125 84.2 2.9 3-3-3m35.5 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m127.9 87.1 3 3-3-3m29.5 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m122 90 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m128.9 92 1 2-1-2m29.5 0 1 2-1-2z"/>
|
||||
<path fill="#9cc" d="m163.3 90 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m122 93 3 3-3-3m41.3 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m125 96 2.9 3-3-3m35.5 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m119 99 3 2.9-3-3z"/>
|
||||
<path fill="#c33" d="m126 100.9.9 2-1-2m35.4 0 1 2-1-2z"/>
|
||||
<path fill="#9cc" d="m166.3 99 3 2.9-3-3z"/>
|
||||
<path fill="#ccf" d="m119 101.9 3 3-3-3m47.3 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m122 104.8 3 3-3-3m41.3 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m116 107.8 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m122 107.8 3 3-3-3m41.3 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m169.2 107.8 3 3-3-3m-62 3 3 2.9-3-3z"/>
|
||||
<path fill="#ccf" d="m110.2 110.7 3 3-3-3m65 0 2.9 3-3-3z"/>
|
||||
<path fill="#9cc" d="m178 110.7 3 3-3-3m-79.6 3 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m101.3 113.7 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m113.1 113.7 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m116 113.7 3 3-3-3m53.2 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m172.2 113.7 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m184 113.7 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m187 113.7 2.9 3-3-3z"/>
|
||||
<path fill="#69c" d="m86.6 116.6 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m89.5 116.6 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m92.5 116.6 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m104.3 116.6 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m109.2 117.6 2 1-2-1m67.9 0 2 1-2-1z"/>
|
||||
<path fill="#fcc" d="m181 116.6 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m192.8 116.6 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m195.8 116.6 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m198.7 116.6 3 3-3-3m-121 3 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m80.7 119.6 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m83.6 119.6 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m95.4 119.6 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m100.3 120.6 2 1-2-1m85.6 0 2 1-2-1z"/>
|
||||
<path fill="#fcc" d="m189.9 119.6 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m201.7 119.6 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m204.6 119.6 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m207.6 119.6 3 3-3-3m-138.8 3 3 2.9-3-3z"/>
|
||||
<path fill="#9cf" d="m71.8 122.5 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m86.6 122.5 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m91.5 123.5 2 1-2-1m103.3 0 2 1-2-1z"/>
|
||||
<path fill="#fcc" d="m198.7 122.5 3 3-3-3z"/>
|
||||
<path fill="#9cf" d="m213.5 122.5 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m216.4 122.5 3 3-3-3z"/>
|
||||
<path fill="#6cc" d="m60 125.5 3 3-3-3z"/>
|
||||
<path fill="#9cf" d="m63 125.5 2.9 3-3-3z"/>
|
||||
<path fill="#fcc" d="m74.8 125.5 2.9 3-3-3zm135.8 0 2.9 3-3-3z"/>
|
||||
<path fill="#9cf" d="m222.3 125.5 3 3-3-3z"/>
|
||||
<path fill="#6cc" d="m225.3 125.5 3 3-3-3m-174.2 3 3 2.9-3-3z"/>
|
||||
<path fill="#ccf" d="m54 128.4 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m65.9 128.4 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m70.8 129.4 2 1-2-1m144.7 0 2 1-2-1z"/>
|
||||
<path fill="#fcc" d="m219.4 128.4 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m231.2 128.4 3 3-3-3z"/>
|
||||
<path fill="#6cc" d="m234.2 128.4 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m42.3 131.4 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m45.2 131.4 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m57 131.4 3 3-3-3zm171.3 0 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m240 131.4 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m243 131.4 3 3-3-3m-206.6 3 3 2.9-3-3z"/>
|
||||
<path fill="#c66" d="m51.1 134.3 3 3-3-3zm183 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m249 134.3 2.9 3-3-3m-206.6 3 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m45.2 137.3 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m57 137.3 3 3-3-3m171.3 0 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m240 137.3 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m243 137.3 3 3-3-3z"/>
|
||||
<path fill="#6cc" d="m51.1 140.3 3 2.9-3-3z"/>
|
||||
<path fill="#ccf" d="m54 140.3 3 2.9-3-3z"/>
|
||||
<path fill="#fcc" d="m65.9 140.3 3 2.9-3-3z"/>
|
||||
<path fill="#c33" d="m70.8 141.2 2 1-2-1m144.7 0 2 1-2-1z"/>
|
||||
<path fill="#fcc" d="m219.4 140.3 3 2.9-3-3z"/>
|
||||
<path fill="#ccf" d="m231.2 140.3 3 2.9-3-3z"/>
|
||||
<path fill="#6cc" d="m234.2 140.3 3 2.9-3-3m-174.2 3 3 3-3-3z"/>
|
||||
<path fill="#9cf" d="m63 143.2 2.9 3-3-3z"/>
|
||||
<path fill="#fcc" d="m74.8 143.2 2.9 3-3-3zm135.8 0 2.9 3-3-3z"/>
|
||||
<path fill="#9cf" d="m222.3 143.2 3 3-3-3z"/>
|
||||
<path fill="#6cc" d="m225.3 143.2 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m68.8 146.2 3 2.9-3-3z"/>
|
||||
<path fill="#9cf" d="m71.8 146.2 3 2.9-3-3z"/>
|
||||
<path fill="#fcc" d="m86.6 146.2 3 2.9-3-3z"/>
|
||||
<path fill="#c33" d="m91.5 147.1 2 1-2-1m103.3 0 2 1-2-1z"/>
|
||||
<path fill="#fcc" d="m198.7 146.2 3 2.9-3-3z"/>
|
||||
<path fill="#9cf" d="m213.5 146.2 3 2.9-3-3z"/>
|
||||
<path fill="#69c" d="m216.4 146.2 3 2.9-3-3m-138.7 3 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m80.7 149.1 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m83.6 149.1 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m95.4 149.1 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m100.3 150 2 1-2-1m85.6 0 2 1-2-1z"/>
|
||||
<path fill="#fcc" d="m189.9 149.1 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m201.7 149.1 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m204.6 149.1 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m207.6 149.1 3 3-3-3m-121 3 2.9 2.9-3-3z"/>
|
||||
<path fill="#9cc" d="m89.5 152 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m92.5 152 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m104.3 152 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m109.2 153 2 1-2-1m67.9 0 2 1-2-1z"/>
|
||||
<path fill="#fcc" d="m181 152 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m192.8 152 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m195.8 152 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m198.7 152 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m98.4 155 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m101.3 155 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m113.1 155 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m116 155 3 3-3-3m53.2 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m172.2 155 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m184 155 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m187 155 2.9 3-3-3m-79.7 3 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m110.2 158 3 3-3-3m65 0 2.9 3-3-3z"/>
|
||||
<path fill="#9cc" d="m178 158 3 3-3-3m-62 3 3 2.9-3-3z"/>
|
||||
<path fill="#c33" d="m122 161 3 2.9-3-3m41.3 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m169.2 161 3 2.9-3-3z"/>
|
||||
<path fill="#fcc" d="m122 163.9 3 3-3-3m41.3 0 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m119 166.8 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m126 168.8.9 2-1-2m35.4 0 1 2-1-2z"/>
|
||||
<path fill="#ccf" d="m166.3 166.8 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m119 169.8 3 3-3-3m47.3 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m125 172.7 2.9 3-3-3m35.5 0 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m122 175.7 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m128.9 177.6 1 2-1-2m29.5 0 1 2-1-2z"/>
|
||||
<path fill="#ccf" d="m163.3 175.7 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m122 178.6 3 3-3-3m41.3 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m127.9 181.6 3 3-3-3m29.5 0 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m125 184.5 2.9 3-3-3z"/>
|
||||
<path fill="#c33" d="m131.8 186.5 1 2-1-2m23.6 0 1 2-1-2z"/>
|
||||
<path fill="#cff" d="m160.4 184.5 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m125 187.5 2.9 3-3-3m35.5 0 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m125 190.4 2.9 3-3-3z"/>
|
||||
<path fill="#fcc" d="m130.8 190.4 3 3-3-3m23.7 0 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m160.4 190.4 3 3-3-3z"/>
|
||||
<path fill="#cff" d="m127.9 193.4 3 3-3-3zm29.5 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m127.9 196.3 3 3-3-3m29.5 0 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m127.9 199.3 3 3-3-3m29.5 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m133.8 202.2 3 3-3-3m17.7 0 3 3-3-3z"/>
|
||||
<path fill="#9cf" d="m130.8 205.2 3 3-3-3z"/>
|
||||
<path fill="#c33" d="m137.7 207.2 1 2-1-2m11.8 0 1 2-1-2z"/>
|
||||
<path fill="#9cf" d="m154.5 205.2 3 3-3-3z"/>
|
||||
<path fill="#69c" d="m130.8 208.2 3 2.9-3-3m23.7 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m136.7 211.1 3 3-3-3m11.9 0 2.9 3-3-3z"/>
|
||||
<path fill="#9cf" d="m133.8 214 3 3-3-3zm17.7 0 3 3-3-3z"/>
|
||||
<path fill="#6cc" d="m133.8 217 3 3-3-3m17.7 0 3 3-3-3z"/>
|
||||
<path fill="#fcc" d="m139.7 220 3 3-3-3m5.9 0 3 3-3-3z"/>
|
||||
<path fill="#ccf" d="m136.7 222.9 3 3-3-3m11.9 0 2.9 3-3-3z"/>
|
||||
<path fill="#6cc" d="m136.7 225.9 3 3-3-3z"/>
|
||||
<path fill="#c66" d="m142.7 225.9 2.9 3-3-3z"/>
|
||||
<path fill="#6cc" d="m148.6 225.9 2.9 3-3-3z"/>
|
||||
<path fill="#ccf" d="m139.7 231.8 3 3-3-3m5.9 0 3 3-3-3z"/>
|
||||
<path fill="#9cc" d="m139.7 234.7 3 3-3-3m5.9 0 3 3-3-3m-3 6 3 2.9-3-3z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 9.7 KiB |
@@ -1,18 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ax" viewBox="0 0 640 480">
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill-opacity=".7" d="M106.3 0h1133.3v850H106.3z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#a)" transform="matrix(.56472 0 0 .56482 -60 -.1)">
|
||||
<path fill="#0053a5" d="M0 0h1300v850H0z"/>
|
||||
<g fill="#ffce00">
|
||||
<path d="M400 0h250v850H400z"/>
|
||||
<path d="M0 300h1300v250H0z"/>
|
||||
</g>
|
||||
<g fill="#d21034">
|
||||
<path d="M475 0h100v850H475z"/>
|
||||
<path d="M0 375h1300v100H0z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 550 B |
@@ -1,8 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-az" viewBox="0 0 640 480">
|
||||
<path fill="#3f9c35" d="M.1 0h640v480H.1z"/>
|
||||
<path fill="#ed2939" d="M.1 0h640v320H.1z"/>
|
||||
<path fill="#00b9e4" d="M.1 0h640v160H.1z"/>
|
||||
<circle cx="304" cy="240" r="72" fill="#fff"/>
|
||||
<circle cx="320" cy="240" r="60" fill="#ed2939"/>
|
||||
<path fill="#fff" d="m384 200 7.7 21.5 20.6-9.8-9.8 20.7L424 240l-21.5 7.7 9.8 20.6-20.6-9.8L384 280l-7.7-21.5-20.6 9.8 9.8-20.6L344 240l21.5-7.7-9.8-20.6 20.6 9.8L384 200z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 509 B |
@@ -1,12 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ba" viewBox="0 0 640 480">
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill-opacity=".7" d="M-85.3 0h682.6v512H-85.3z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g fill-rule="evenodd" clip-path="url(#a)" transform="translate(80) scale(.9375)">
|
||||
<path fill="#009" d="M-85.3 0h682.6v512H-85.3V0z"/>
|
||||
<path fill="#FC0" d="m56.5 0 511 512.3V.3L56.5 0z"/>
|
||||
<path fill="#FFF" d="M439.9 481.5 412 461.2l-28.6 20.2 10.8-33.2-28.2-20.5h35l10.8-33.2 10.7 33.3h35l-28 20.7 10.4 33zm81.3 10.4-35-.1-10.7-33.3-10.8 33.2h-35l28.2 20.5-10.8 33.2 28.6-20.2 28 20.3-10.5-33 28-20.6zM365.6 384.7l28-20.7-35-.1-10.7-33.2-10.8 33.2-35-.1 28.2 20.5-10.8 33.3 28.6-20.3 28 20.4-10.5-33zm-64.3-64.5 28-20.6-35-.1-10.7-33.3-10.9 33.2h-34.9l28.2 20.5-10.8 33.2 28.6-20.2 27.9 20.3-10.4-33zm-63.7-63.6 28-20.7h-35L220 202.5l-10.8 33.2h-35l28.2 20.4-10.8 33.3 28.6-20.3 28 20.4-10.5-33zm-64.4-64.3 28-20.6-35-.1-10.7-33.3-10.9 33.2h-34.9L138 192l-10.8 33.2 28.6-20.2 27.9 20.3-10.4-33zm-63.6-63.9 27.9-20.7h-35L91.9 74.3 81 107.6H46L74.4 128l-10.9 33.2L92.1 141l27.8 20.4-10.3-33zm-64-64 27.9-20.7h-35L27.9 10.3 17 43.6h-35L10.4 64l-11 33.3L28.1 77l27.8 20.4-10.3-33zm-64-64L9.4-20.3h-35l-10.7-33.3L-47-20.4h-35L-53.7 0l-10.8 33.2L-35.9 13l27.8 20.4-10.3-33z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,6 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="flag-icons-bb" viewBox="0 0 640 480">
|
||||
<path fill="#00267f" d="M0 0h640v480H0z"/>
|
||||
<path fill="#ffc726" d="M213.3 0h213.4v480H213.3z"/>
|
||||
<path id="a" d="M319.8 135.5c-7 19-14 38.6-29.2 53.7 4.7-1.6 13-3 18.2-2.8v79.5l-22.4 3.3c-.8 0-1-1.3-1-3-2.2-24.7-8-45.5-14.8-67-.5-2.9-9-14-2.4-12 .8 0 9.5 3.6 8.2 1.9a85 85 0 0 0-46.4-24c-1.5-.3-2.4.5-1 2.2 22.4 34.6 41.3 75.5 41.1 124 8.8 0 30-5.2 38.7-5.2v56.1H320l2.5-156.7z"/>
|
||||
<use xlink:href="#a" width="100%" height="100%" transform="matrix(-1 0 0 1 639.5 0)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 607 B |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bd" viewBox="0 0 640 480">
|
||||
<path fill="#006a4e" d="M0 0h640v480H0z"/>
|
||||
<circle cx="280" cy="240" r="160" fill="#f42a41"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 187 B |
@@ -1,7 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-be" viewBox="0 0 640 480">
|
||||
<g fill-rule="evenodd" stroke-width="1pt">
|
||||
<path d="M0 0h213.3v480H0z"/>
|
||||
<path fill="#ffd90c" d="M213.3 0h213.4v480H213.3z"/>
|
||||
<path fill="#f31830" d="M426.7 0H640v480H426.7z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 287 B |
@@ -1,7 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bf" viewBox="0 0 640 480">
|
||||
<g fill-rule="evenodd">
|
||||
<path fill="#de0000" d="M640 479.6H.4V0H640z"/>
|
||||
<path fill="#35a100" d="M639.6 480H0V240.2h639.6z"/>
|
||||
<path fill="#fff300" d="m254.6 276.2-106-72.4h131L320 86.6 360.4 204l131-.1-106 72.4 40.5 117.3-106-72.6L214 393.4"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 353 B |
@@ -1,7 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bg" viewBox="0 0 640 480">
|
||||
<g fill-rule="evenodd" stroke-width="1pt">
|
||||
<path fill="#d62612" d="M0 320h640v160H0z"/>
|
||||
<path fill="#fff" d="M0 0h640v160H0z"/>
|
||||
<path fill="#00966e" d="M0 160h640v160H0z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 283 B |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bh" viewBox="0 0 640 480">
|
||||
<path fill="#fff" d="M0 0h640v480H0"/>
|
||||
<path fill="#ce1126" d="M640 0H96l110.7 48L96 96l110.7 48L96 192l110.7 48L96 288l110.7 48L96 384l110.7 48L96 480h544"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 252 B |
@@ -1,15 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bi" viewBox="0 0 640 480">
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill-opacity=".7" d="M-90.5 0H592v512H-90.5z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g fill-rule="evenodd" clip-path="url(#a)" transform="translate(84.9) scale(.9375)">
|
||||
<path fill="#18b637" d="m-178 0 428.8 256L-178 512zm857.6 0L250.8 256l428.8 256z"/>
|
||||
<path fill="#cf0921" d="m-178 0 428.8 256L679.6 0zm0 512 428.8-256 428.8 256z"/>
|
||||
<path fill="#fff" d="M679.6 0h-79.9L-178 464.3V512h79.9L679.6 47.7z"/>
|
||||
<path fill="#fff" d="M398.9 256a148 148 0 1 1-296.1 0 148 148 0 0 1 296 0z"/>
|
||||
<path fill="#fff" d="M-178 0v47.7L599.7 512h79.9v-47.7L-98.1 0z"/>
|
||||
<path fill="#cf0921" stroke="#18b637" stroke-width="3.9" d="m280 200.2-19.3.3-10 16.4-9.9-16.4-19.2-.4 9.3-16.9-9.2-16.8 19.2-.4 10-16.4 9.9 16.5 19.2.4-9.3 16.8zm-64.6 111.6-19.2.3-10 16.4-9.9-16.4-19.2-.4 9.3-16.9-9.2-16.8 19.2-.4 10-16.4 9.9 16.5 19.2.4-9.3 16.8zm130.6 0-19.2.3-10 16.4-10-16.4-19.1-.4 9.3-16.9-9.3-16.8 19.2-.4 10-16.4 10 16.5 19.2.4-9.4 16.8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,14 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bj" viewBox="0 0 640 480">
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill="gray" d="M67.6-154h666v666h-666z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#a)" transform="matrix(.961 0 0 .7207 -65 111)">
|
||||
<g fill-rule="evenodd" stroke-width="1pt">
|
||||
<path fill="#319400" d="M0-154h333v666H0z"/>
|
||||
<path fill="#ffd600" d="M333-154h666v333H333z"/>
|
||||
<path fill="#de2110" d="M333 179h666v333H333z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 493 B |
@@ -1,7 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bl" viewBox="0 0 640 480">
|
||||
<g fill-rule="evenodd" stroke-width="1pt">
|
||||
<path fill="#fff" d="M0 0h640v480H0z"/>
|
||||
<path fill="#00267f" d="M0 0h213.3v480H0z"/>
|
||||
<path fill="#f31830" d="M426.7 0H640v480H426.7z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 289 B |
@@ -1,97 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bm" viewBox="0 0 640 480">
|
||||
<path fill="#cf142b" d="M0 0h640v480H0z"/>
|
||||
<path fill="#fff" d="M559.7 130.6v161.6c0 43.1-86.2 57.2-86.2 57.2s-86.4-14-86.4-57.4V130.6h172.5z"/>
|
||||
<path fill="#2f8f22" d="M559.7 292.2c0 43.1-86.2 57.2-86.2 57.2s-86.4-14-86.4-57.4c0 0 0-3.5 1.8-5.4 0 0-1 7.1 4.5 12.6 0 0-4.3-7.8 0-15.3 0 0-1.7 9.8 4.4 15.3 0 0-3.3-7.9.4-16.7 0 0-1.8 14.3 4.7 17.3 0 0 1.8-8.4-.8-13.6 0 0 4.5 1.8 4.3 13.8 0 0 1.4-1.8 1.8-10.5 0 0 .2 10 3.5 12.3 0 0 1.2-1-.3-5.5-1.6-4.4.6-6 1-6 0 0-.8 5 3.4 8.8 0 0-1.8-7.9.7-9 0 0-.6 6.7 4.8 8.1 0 0 .3-1.9-.8-4 0 0-1-2.5-.3-4.5 0 0 1.7 6 4 7 0 0-1.4-3.6 0-7 0 0 .2 5 4.7 7.1 0 0-3-4-1.9-8.2l28.7 1.4 15 .7 44.7-3 7.6-6.7s3.1 4.1-1.8 10.8c0 0 4.8-.8 6.3-8.3 0 0 2 4.1-.7 8.8 0 0 5.3-5.4 6-11.3 0 0 2.1 5.8-2.9 12 0 0 4.4-1.6 6.3-8.1 0 0 1.6 4-2.7 9.5 0 0 8.1-4.1 7.9-13 0 0 3.3 4.8-.5 11.6 0 0 4-3.7 4.5-9.3 0 0 2.3 2.5-.2 9.4 0 0 5-4.8 5.8-9.9 0 0 1 4.8-3.2 10.8 0 0 2.9-.8 5.7-6.6 0 0 .7 2.4-1.8 6.6 0 0 2.8-.5 4.6-5.9 0 0 .3 3.2-.5 6 0 0 2.1-1.3 2.6-7.3a9 9 0 0 0 1.2 4.4v.8z"/>
|
||||
<path fill="#d40000" stroke="#000" stroke-linejoin="round" stroke-width="1.2" d="M515.4 198.7s-3 .6-7-.6c-3.8-1.2-5.3-.7-6.5 0 0 0 1.5-3.1-2.3-5.6 0 0 1.2 3.2-.5 4.6 0 0-.7.7-1.6-.3 0 0-1.3-1.5-2.8-2.4 0 0 3.3-1.2 2.7-4.5-.6-3.3-2.4-3.6-3.3-4.1a6 6 0 0 0 0 2.4s-3.5-2 1.2-4.7c4.8-2.7 4-4.4 3.1-5.8a13.1 13.1 0 0 0-3.5-3.6s1 1.6.7 2.9c-.1 1.2-2.4 2-2-.1.5-2.4 0-2 0-4.3 0 0 4.2 1.4 6-2.8 0 0 1.6-4.3-3.8-6.4 0 0 1.3 1.8.7 3 0 0-1.2 2.2-2.5.6-1.3-1.7-2.2-2.2-2.1-4.2 0 0 4.9.7 3.6-4.7 0 0-.9 3.6-7.2-1.2 0 0 4.2-4.2 2.5-7.6 0 0-.5-1.5-4.9-.7 0 0 3.8-2.4 2.3-4.5 0 0-.9-1.3-4.6.4 0 0 1.5-2.3-2.1-5 0 0-2.4 1.2-3.6 2.4 0 0-2.4-3-4-4.3 0 0-2.8 1.1-3.5 4.3 0 0-1.3-1.5-4.3-2.4 0 0-1.4 2.8.5 5 0 0-1.4 0-4-1.1 0 0-2.8-1.2-2.3 1.1.3 2.4.6 3 1.2 4.2 0 0-6.5-1.5-6.2 2a8.8 8.8 0 0 0 3 6.2s-3.5 4.8-6.6 1.2c0 0-1.2 1.2 1.2 4.2 0 0 2.4 2.5.3 4.2 0 0-2.5 2-3.7-2 0 0-4.1 4.1.8 7.2 0 0 3 1.8 6.3-1 0 0-1 8-4 6.4 0 0-1.9-1.2 1.4-2.9 0 0-4.8-.6-5.5 4 0 0-.6 3.5 3.5 5 0 0 3.1 1.2 0 3.6 0 0-2.5 1.7-.9 4.4 0 0 1.8 2.8-2.9 3.2 0 0-2.4 0-3.3-.4 0 0-1 2-.4 4 0 0-2.3-1.7-7.5.2-5.2 2-4.9.6-5.2 1.2l-1.6 2.4s2.8 3.6 2.9 3.3l-.6 4 1.4.6 10.8-4.8 11-5.7 8.9.4 5.6 1.3 7.2.6 5.4-2.8h7.6l8.4 4.2 9.5 5.7 5 1 3.9-.3v-7.8z"/>
|
||||
<path fill="#d40000" stroke="#000" stroke-linejoin="round" stroke-width="1.2" d="M428.2 207.7s4.2 2.2 6-.3c0 0 2.2-4.4-2.8-6 0 0 2.8-3.2-.2-6.2 0 0-1.6-1.6-4.2-.5 0 0-1.2-2.3-3.7-2.2 0 0-2.4 0-3 2.5 0 0-3.2-1.2-4.9.6 0 0-3 3.2 1.1 5.8l2.9.3 2.8-1.4 3.3.9s-.9 3.2 2.7 6.5z"/>
|
||||
<path fill="#64b4d1" stroke="#000" stroke-width="1.2" d="M521.6 200.1a6.7 6.7 0 0 1 6.9 3.8c2.6 6.2-3 9.6-3 9.6.4 1.3.5 3.2.5 3.2 7.8 1 6.4 9.8 6.4 9.8l-2.6-2.2c-4.5-1.8-9.3 2.2-12.6 8.6-3.4 6.6-1.8 9.5-1.2 17.3.6 7.7 13 12.4 13 12.4l-9.7 25c-3.8 10-12 5.9-14.3 3.7-2.3-2-2.9-.8-4 0-1.1 1 5.3 6-6.5 10.8-11.7 4.7-13.7 8.3-15.7 9.5-2 1.2-10 .5-10.8-.6-1-1-.4-1-3.5-2.9-3-1.7-8.2-3.5-13.8-6.2-5.6-2.7-5.4-6.2-5.3-6.9 0-.7 1.9-6.5-4.7-1.9-6.5 4.7-12.1-2.2-12.1-2.2-1.2-1.7-6.8-16.4-6.8-16.4a92.4 92.4 0 0 0-4.3-12s-.4.8 4.5-2c4.8-2.7 7-7.3 8.7-11.9 1.7-4.6 0-12.5-.6-14-.6-1.6-4.2-8.9-8.7-10.4-4.4-1.6-7.5 2.4-7.5 2.4s-1.3-9 6.6-10c0 0 0-1.8.4-3.1 0 0-5.6-3.4-3-9.6 0 0 1.8-4.3 6.8-3.8l-1.1 2.4s-1.2 12.6 17.2 4.2c18.5-8.6 18-10.2 28.7-4.8l7.6-.1s11-5.3 14.7-3c3.5 2.3 16.3 9.4 16.3 9.4s12.4 4.7 14.9-4z"/>
|
||||
<path fill="#fff" stroke="#00247d" stroke-miterlimit="10" stroke-width="1.2" d="M465.8 255s-.6-3.9-1.2-6.4c0 0-1.5-3.9 1-6.8l2.8-3.3s1.8-2.4 4-2.7c0 0 2.3 0 2.4-.5.3-.5 2.8-4.5 8.6 0 0 0 1.8-3 4.8-3.6 0 0 3-.8 4.5 1.4 0 0 3.5-2.6 6.4 1.7 0 0 4.1-2.4 7.2 2.3 0 0 4-2 6.4 2.1 2.5 4.3 2 6 2 6l2 6.8 6.5 8-15.2 5.8h-7l-13.7 3.6-24.3 1.9-6.7-8 9.6-8.3z"/>
|
||||
<path fill="#d40000" stroke="#000" stroke-linejoin="round" stroke-width="1.2" d="M445.3 295.5s-3.6.1-5.5 1.2c-1.8.8-3.3 1.8-5.4 3.2 0 0-1 1.3-5.2.5 0 0-7.2-1.7-7.2 4 0 0-8.8.6-5.2 8.3 0 0 2.3 6 7.3 1.8 0 0-3.2 4.5 3 6.3 0 0 4.4 1.2 5.8-3.5 0 0 .7-1.8-1-4 0 0 2.1-.4 3.6-2.7 0 0-4.6 5.8.5 8 0 0 6.3 1.5 6.6-5 0 0-.6-3.2 2-4.3 0 0 5-1.2 7-6.6 0 0-7-3.9-6.3-7.2zM430.6 238s-5.6-2.5-8.4 0c0 0-3.5-2.2-7.5 0 0 0-3.7 2.4-6.3 5.2 0 0-1.8 1.5-1.2 6.4 0 0 1 3.5.5 5.1 0 0-1.2-.2-3.7 2.8 0 0-3.1 3.5-6 .3 0 0 1 4.6 6.1 3.8 0 0-2.5 2-.3 7 0 0 1.6 3.6-1 8.2 0 0 4.5-1.8 4.4-7.2 0 0-.5-3.6 1-6 0 0-1.5 2.2 1.6 7.1 0 0 2.4 3.6.5 7.2 0 0 4.4-1.6 4-7-.4-5.4-3-3.2-1.4-8.2 0 0 .5 2.6 1.8 4a7.2 7.2 0 0 1 2.4 7s2.6-3.4 2-6.8a13.1 13.1 0 0 0-1.3-4.4l8.4-4.8 4.3-7.5z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="M417.8 259.5s-3.5-.2-4-3m-6.1-1.8s1.2 0 2.4 1.2c0 0 .7 1.2 1.9 1"/>
|
||||
<path d="M423 249.2s-1.8 0-3-.8c0 0-.9-.7-1.5.4 0 0-1 1.6.8 2.3 0 0 2.2 1.2-1.2 3.4 0 0 4-1.6 2.4-3.6 0 0-1.8-1.2-1.2-1.7 0 0 .2-.4 1 0 .6.6 2 .4 2.7 0z"/>
|
||||
<path fill="#784421" stroke="#000" stroke-width="1.2" d="m477.6 259 2.1-.6-14-48h-.4z"/>
|
||||
<path d="M431.2 312.3s-3.2-1.9-6 .3c0 0 .4-1.2 2.4-1.7 0 0 1.2-3.2 4.3-2.9 0 0-1.3 1.6-3 2.8 0 0 1.8.2 2.4 1.5z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M419.7 319.8s-5.2-3.2-2.3-8.7c0 0 .8-1.5 2.3-1.2 0 0 3.3 1 .8 5.5 0 0-1.4 2.9-.8 4.5zm10.5 5.3s-7.4-3.4-5.1-9.2c0 0 .7-2 2.4-1.8 0 0 2.8.2 2.3 4 0 0-.9 3.6.4 7z"/>
|
||||
<path d="M428.7 303.6s-2.3 1.7-3.1 2.8c0 0-1-1.2-2.2-1.8 0 0 1.5-.3 2.2.3 0 0 1.2-1 3-1.3z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M435.2 323.6s6-1.4 4.8-7.5c0 0-.6-2.6-3-2.2 0 0-3 .8-1 4.6 0 0 1.1 2.6-.8 5.1z"/>
|
||||
<path fill="#f5ce00" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="m461.6 196.7 5.7 1.9s5.4 2.3 12.3 0l5.2-2-3.5 5.4v2.9l2.1 3.2s-1.3.6-5.4-2c0 0-4.4-3.4-9.6 0 0 0-3 2-5.4 2l3.5-3.8-1.3-3.5-3.6-4.3z"/>
|
||||
<path fill="#fff" d="M437.5 316.5s.2-.4 0-.5l-.5.2s-.6 1 0 2.4c0 0 .5.9.3 1.8v.4s.3-.1.3-.4c0 0 .4-.8-.2-1.8 0 0-.6-1.4.1-2.1z"/>
|
||||
<path fill="#d40000" stroke="#000" stroke-linejoin="round" stroke-width="1.2" d="M518 207.7s-4.2 2.2-6-.3c0 0-2.1-4.4 2.9-6 0 0-2.8-3.2.1-6.2 0 0 1.6-1.6 4.2-.5 0 0 1.2-2.3 3.7-2.2 0 0 2.4 0 3 2.5 0 0 3.3-1.2 5 .6 0 0 2.8 3.2-1.2 5.8l-2.9.3-2.9-1.4-3 .9s.8 3.2-3 6.5z"/>
|
||||
<path fill="#f5ce00" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M484.8 204.4s0 .8-.8 1c0 0-1 .3-1.5-.9v-.3c0-.5-.3-2 1.4-3.3 0 0 2.6-2.1 7.6.5a192 192 0 0 0 14.8 7.5s3.1 1.6 7.9 1.8c0 0 6.5.5 9.3-4.1 0 0 2.1-3.5 0-5.8 0 0-.9-1-2.3-.8a3 3 0 0 0-1.8 1.2s-1 1.4.1 2.5c0 0 1.6 1 2.2-1 0 .2.5 1.7-.4 2.9 0 0-4 6-14.9-.1l-14.3-8.1s-7.1-3.7-11.6 2.1c0 0-3.4 4.8 1.1 7.9 0 0 3.4 2 5.4-1.2 0 0 1.8-3.1-1-4.4 0 0-2.4-1.2-3.3 1.2-1 2.4 1.8 3 2 1.3 0 0 0-.4.3 0z"/>
|
||||
<path fill="#e4cb5e" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M428 229.2v-9c0-.8 0-1.2 1.2-2.2 1-.8 2.1-2.3 3.7 1.7 0 0 3.2-3.5 4.2-4 0 0 2-1.5 3.3.7 0 0 1.6-2.6 3-3.2 0 0 3.2-2 3.3 4.2l2.5-2.4s2-1.5 4.2.7c0 0 3.5 3.6 4 4.6 0 0 .8 1 1 2.7 0 0 0 2 1 3 0 0 1.1 1 2.2 1.2 0 0 2.5.1 3.6 2.6 0 0 .3-.5 1.6 11.2v21.5l-14.4 17.1-23.1-6.6-9.2-3.9-2.2-6.6 9-5.9 4.8-13-1.5-9.3-2.2-5.2z"/>
|
||||
<path fill="#784421" stroke="#000" stroke-width="1.2" d="m491.6 240.4 1.2-1.5 2.5-2s4 10.4 4.2 12.7v3.2s6 1.6 7.2 10.7l-5 9.2-7.8-4.4-2.3-1.5v-26.3z"/>
|
||||
<path fill="#fff" d="M418.3 312.4s.2-.3 0-.6l-.5.4s-1.5 1.7-.2 4.4c0 0 0 .4.3.2 0 0 .3 0 0-.3 0 0-1.1-2.4.4-4z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="M441.7 310.6s.1-.8-.4-1.6c0 0-.3-.6-.2-1.5M446.7 217.4s0 2.3.7 4c.6 1.6 2.9 4.5 3 5.9"/>
|
||||
<path fill="#d40000" stroke="#000" stroke-linejoin="round" stroke-width="1.2" d="M501 295.5s3.6.1 5.5 1.2c2 .8 3.4 1.8 5.5 3.2 0 0 1 1.3 5.2.5 0 0 7.2-1.7 7.2 4 0 0 8.7.6 5.2 8.3 0 0-2.4 6-7.4 1.8 0 0 3.2 4.5-3 6.3 0 0-4.4 1.2-5.7-3.5 0 0-.8-1.8 1-4 0 0-2.1-.4-3.5-2.7 0 0 4.5 5.8-.5 8 0 0-6.3 1.5-6.7-5 0 0 .5-3.2-2-4.3 0 0-5-1.2-7.2-6.6 0 0 7.2-3.9 6.5-7.2z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="m443.8 227.4 6 47.8m-4.5-47.9 6.6 44.6m-5.5-44.8 7.8 44.2"/>
|
||||
<path fill="#784421" stroke="#000" stroke-width="1.2" d="m458.6 267.5 2.2-.7-14-48h-.5z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="m450.7 225.3 14.1 35.5m-15-35 13.6 37"/>
|
||||
<path fill="#fff" d="M427.6 321.6s-1.7-1.5-1.4-4.3c0 0 0-.6-.3-.7 0 0-.3-.1-.3.6 0 0-.5 2.9 1.5 4.5 0 0 .1.3.4.2 0 0 .2 0 0-.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="m451.5 224.8 14.3 32.4m-18.3-30.4 9 43.7"/>
|
||||
<path fill="#f5ce00" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M520 259c-6.3-3.6-7.7-11.4-7.7-11.4a24.6 24.6 0 0 1 1.6-14.3c4-8.6 11.1-10.3 11.1-10.3s-6.9 4.8-8.8 11.2c0 0-1.4 5.5-.6 10.7.8 5.5.5 4.1 1.8 8.3l2.6 6z"/>
|
||||
<path fill="#784421" stroke="#000" stroke-width="1.2" d="m492.7 238.7-26.6 8.5-1.4 12c-6.3 9.1-19.2 10.7-19.2 10.7l10 10.7 19 4 10.2-7.8 9.2-8.4c-1-4.5-.5-11.2-.5-11.2 0-1.2.5-3.8.5-3.8s-1.5-10.7-1.2-14.5z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="M465 256.2s17.6-5.5 28-10m-36.4 20s22-4 37.3-12.8l5.6-3.8"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="m499.5 252.8-6 4.4s-24.5 11.2-43.2 11.6m43.1-3.6S474.6 275 464 275"/>
|
||||
<path fill="#d40000" stroke="#000" stroke-linejoin="round" stroke-width="1.2" d="M515.8 238s5.6-2.5 8.4 0c0 0 3.6-2.2 7.6 0 0 0 3.6 2.4 6.2 5.2 0 0 1.8 1.5 1.2 6.4 0 0-1 3.5-.3 5.1 0 0 1.1-.2 3.5 2.8 0 0 3.3 3.5 6 .3 0 0-.8 4.6-6 3.8 0 0 2.4 2 .3 7 0 0-1.6 3.6 1 8.2 0 0-4.6-1.8-4.4-7.2 0 0 .4-3.6-1-6 0 0 1.4 2.2-1.7 7.1 0 0-2.4 3.6-.4 7.2 0 0-4.5-1.6-4-7 .3-5.4 3-3.2 1.3-8.2 0 0-.4 2.6-1.7 4a7.2 7.2 0 0 0-2.4 7s-2.6-3.4-2-6.8c.6-3.5 1.2-4.4 1.2-4.4l-8.3-4.8-4.2-7.5z"/>
|
||||
<path fill="#fff" stroke="#00247d" stroke-miterlimit="10" stroke-width="1.2" d="M420.6 268.4s.8-3.7 4.3-2.4c0 0 1.2-6 7.7-6.2 6.5-.2 6.8 6.4 6.8 6.8 0 0 2-2.8 5.1-2.5 0 0 5.5-.3 3.6 8.5l1 1.2s4.1-9.9 12.7-7.4c0 0 8.4 2.6 3 10.7 0 0 4.2 5.5 7.6 5 3.6-.5 6.7-1.6 10.2-7.8 3.6-6.2 11.7-7.2 13.7-6.8 2 .3 3.7 1.8 4 3.2 0 0 4.3-14.3 19.8-12.2l6.2 3.3 2.4 1-3.6 10-8.4 19.2-6.6 2-6.8-3.9-2.4 1.2v5.9l-9 6.4-6.2 2.5-6.8 4.8-1.7 4.2s-3.7-1.7-8 0l-1.4-3.6-4-3.7-15.6-7.4-2.7-9-2.9-1.3-3.2 3.6-4.5.6-7-4.8-7.4-21z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M488.2 198s-6-.2-5.7 6"/>
|
||||
<path fill="#f5ce00" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M527 263.3c-10.2-3.2-13-14.3-13-14.3a25.5 25.5 0 0 1 1.2-15.5c4.8-11 12.7-11 12.7-11a4 4 0 0 1 4.5 3.2c.4 2.4-1.3 3.3-1.3 3.3-2.7 1.5-4.5-.5-4.5-.5-1.2-1.6-.3-2.9-.3-2.9.7-1 2-.4 2-.4 1.3.2 1 1.6 1 1.6s.4-1.6-1.2-1.8c0 0-3.2-.7-6.8 3.8 0 0-4.7 6.1-4.7 14.1 0 0-.6 14.8 14.7 18.6 0 0-1.6 2.4-4.6 11.1 0 0-3.3 11.2-6.4 17.3 0 0-4.3 8.6-13.9 5.1 0 0-5.6-2.5-5.6-6.5 0 0-.3-3.8 3-4 0 0 3.3-.3 3.3 2.5 0 0 0 3-3.5 2.4 0 0-1.2-.3-1.1-1.5 0 0 .2-1.2 1.8-.6 1.5.6 0 0 0-.1 0 0-.6-.3-1.2 0 0 0-.6 0-.6 1 0 0 0 .6.7 1.1l1.7.2s1 2 3 2.7a8 8 0 0 0 7.1-1.2 10.7 10.7 0 0 0 3-4.3 113.3 113.3 0 0 0 5.2-13.5s1.8-5.7 3.4-8.7z"/>
|
||||
<path fill="#f5ce00" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M498 291.4s2-.2 2 1.5c0 0-.1 2.4-3.2 1.9 0 0-3-.6-2-4 0 0 .8-2.3 3.6-2 0 0 2.8 0 4 3.8 0 0 1 3.3-.7 6-1.8 3-6.2 5-8.4 6 0 0-8.7 3.3-11.3 5.3 0 0-4 2.9-2.2 5.6 0 0 .7 1.1 1.7 1.1 0 0 1.2 0 1.3-1.2 0 0 0 .7-.7 1 0 0-.8.4-1.7-.3 0 0-1-1-.2-2.4 0 0 1-1.6 3.6-.6 0 0 2 1.1 1.2 3.3 0 0-.9 2.1-3.4 2 0 0-1.9 0-3.2-1.2-2-2.1-2-6-.2-8 0 0 1.5-2.1 4.7-3.6l9-3.5c2.6-1.1 4.9-2.3 6.4-4.1 0 0 1.3-1.4 1.8-4 0 0 .4-2-.8-2.4l-1.2-.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M498.2 291.4s2.1-.4 3.5 2.2c0 0 .7 1.5.8 2.5m.7-9s-2.1.3-1 3.4c1.1 2.9 3 3.7 3.5 4.2"/>
|
||||
<path fill="#f5ce00" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M461.6 204.4s0 .8 1 1c0 0 .8.2 1.3-.9v-.3c0-.5.3-2-1.2-3.3 0 0-2.8-2.1-7.8.5 0 0-4 2-6.7 3.6 0 0-7.1 3.8-8 4 0 0-3.2 1.6-8 1.8 0 0-6.5.5-9.2-4.1 0 0-2.2-3.5 0-5.8 0 0 .8-1 2.2-.8.6.1 1.2.4 1.8 1.2 0 0 1 1.4-.1 2.5 0 0-1.6 1-2.2-1 0 .2-.3 1.6.5 3 0 0 4 5.9 14.8-.3l14.3-8s7.2-3.7 11.6 2c0 0 3.4 4.8-1 8 0 0-3.3 2-5.5-1.2 0 0-1.6-3 1-4.4 0 0 2.4-1.2 3.5 1.2 1 2.4-2 3-2.2 1.3 0 0 0-.4-.1 0zm-35.2 54.7c6.3-3.5 7.8-11.5 7.8-11.5 1.4-8-1.7-14.3-1.7-14.3-4-8.6-11-10.3-11-10.3s6.8 4.8 8.7 11.2c0 0 1.6 5.5.6 10.7-.8 5.5-.5 4.1-1.8 8.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M458.4 198s6-.2 5.6 6"/>
|
||||
<path fill="#f5ce00" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M419.3 263.3c10.3-3.2 13-14.3 13-14.3a25.5 25.5 0 0 0-1.1-15.5c-4.8-11-12.7-11-12.7-11a4 4 0 0 0-4.5 3.2c-.3 2.4 1.3 3.3 1.3 3.3 2.8 1.5 4.6-.5 4.6-.5 1.1-1.6.2-2.9.2-2.9-.7-1-2-.4-2-.4-1.2.2-1 1.6-1 1.6s-.3-1.6 1.2-1.8c0 0 3.2-.7 6.8 3.8 0 0 4.8 6.1 4.8 14.1 0 0 .6 14.8-14.8 18.6 0 0 1.7 2.4 4.6 11.1 0 0 3.4 11.2 6.6 17.3 0 0 4.2 8.6 13.7 5.1 0 0 5.6-2.5 5.6-6.5 0 0 .4-3.8-3-4 0 0-3.3-.3-3.3 2.5 0 0 0 3 3.6 2.4 0 0 1.2-.3 1-1.5 0 0-.2-1.2-1.7-.6-1.6.6 0 0 0-.1 0 0 .5-.3 1.1 0 0 0 .6 0 .6 1 0 0 0 .6-.7 1.1l-1.5.2s-1 2-3.2 2.7a7.5 7.5 0 0 1-7-1.2 10.7 10.7 0 0 1-3-4.3 113.5 113.5 0 0 1-5.3-13.5s-1.8-5.7-3.2-8.7l-.6-1.2z"/>
|
||||
<path fill="#f5ce00" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M448.5 291.4s-2-.2-2 1.5c0 0 0 2.4 3.2 1.9 0 0 3-.6 1.9-4 0 0-.7-2.3-3.6-2 0 0-2.7 0-4 3.8 0 0-.9 3.3.8 6 1.8 3 6.2 5 8.3 6 0 0 8.7 3.3 11.4 5.3 0 0 3.9 2.9 2.1 5.6 0 0-.6 1.1-1.7 1.1 0 0-1.2 0-1.3-1.2 0 0 0 .7.7 1 0 0 .9.4 1.7-.3 0 0 1-1 .2-2.4 0 0-1-1.6-3.4-.6 0 0-2.2 1.1-1.2 3.3 0 0 .7 2.1 3.2 2 0 0 2 0 3.2-1.2 2-2.1 2-6 .4-8 0 0-1.7-2.1-4.8-3.6-1.9-.6-5.5-2.1-9-3.5-2.7-1.1-5-2.3-6.5-4.1 0 0-1.3-1.4-1.8-4 0 0-.3-2 .9-2.4l1.2-.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M448.2 291.4s-2.1-.4-3.4 2.2c0 0-.7 1.5-.9 2.5m-.7-9s2.2.3 1.1 3.4c-1.2 2.9-3 3.7-3.6 4.2m27.4-91.1s5.2-3.3 10.4.3M438.8 235.2s.7-3-2.6-8c0 0-2.2-4.7-3.2-7.5m7.4-3.3 2.3 6.6 3 6.8"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="M441.2 238.3s2 2.1 1.8 5.6m-8.1-7.9s2.1 1 1.9 6.8c0 0-.1 4 3 6.2m-5.3 1.4s6.7-.7 7.2 3.5c0 0 0 4 2.4 4.3 0 0 3.3.3 4 3.6m-11.4-6.8s1.2 1.7 2.4 2.6m6.2-7s1.6 2.7 2 4.1m5.3-35s1.6 2.1 3.1 3m3.1 9.6s3.4 1.6 3 10c0 0-.6 5 .9 7.7"/>
|
||||
<path fill="#784421" stroke="#000" stroke-width="1.2" d="m443.1 226.6.4.8s6 .3 9.1-3.8l-.3-.8s-5.3-.3-9 3.8z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="M464.7 258.5s20.6-6 28.6-9.6"/>
|
||||
<path fill="#784421" stroke="#000" stroke-width="1.2" d="m462.5 220.5-.2-.6 10.1-4 .3.8z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="m463.4 220.1 6.8 33.3m-5.6-33.6 7.7 33m-6.4-33.6 8.4 32.9m-5-34.1 11.5 24.6m-10-25 12.3 24.2M471.8 217l13.4 24.3m-15.5 12.4 5.2-1.6m-9.1-1.6s15.2-4.5 27-9.2M465.4 252s19.5-5 27.2-8.8m-21.2 24.6 1 3.3 2.8-1-1-3.1m5-1.3 1 3 2.8-.9-1-3m-16-17.6-.2-4.2 25.5-7.7 1.3 3.6m-16 .8 1.3 3.8m7.6-6.4 1.6 3.6m.5-4.3 1.6 3.3m.4-4 1.6 3.6m0-4 2.8-1.6 1.2 3.1m-2.6-2.3 1.4 3.3"/>
|
||||
<path fill="none" stroke="#00247d" stroke-miterlimit="10" stroke-width="1.2" d="M429.5 283.1s-5-5.1 0-10c0 0-5.5-2.6-4.6-7m13.6 21s-5.3.7-3.7-9.4c0 0-2.2 4-2.9 6a4.7 4.7 0 0 0 2 5.4c.9.6 5.5 1.8 7-1.2m-8.3-16.2s-2.1 1.9-.6 5.4m2.8-5s.2 3.5 2 5.4m-.5-6.7s0 4 2.9 6.6m-1.5-8s0 4.5 3.4 7.4m13.5-.7s1.6-3.9 5.2-3.6c0 0-1.7.8-1.7 2.5 0 0-.2 3 2.9 3.2 0 0 2.5.4 3.8-1"/>
|
||||
<path fill="none" stroke="#00247d" stroke-miterlimit="10" stroke-width="1.2" d="M463.1 293.1s-8.9-4.2-8-10.1c0 0 .4-3.6 4-5.4m-2 3.8s-.8 2.5 1 4.3m1.1-6s-1.2 2.8.7 4.8m1.5-6.3s-1.4 2.4.2 4.5m-8.4 11s4.8 4.3 8.6 4.3m-10.1-2.9s4.5 3.6 7.4 4.2m-9-3.2s5.5 4.9 9 5.2m13.7 4.6s-5.5 3-1.2 6.2m-2.4-9.4 9-4.6m-6.7 6.2s9-5.5 11.7-6.7m-7 7.2s7.7-5.2 11.9-7.5m-6.8 7.1s5.3-4 10.5-7.1m1.7-5.1s-2.6-3.9-11.2 0c0 0 3.3-2.9 9.5-5.2m8.5-16.3s.8 3.1 0 5"/>
|
||||
<path fill="none" stroke="#00247d" stroke-miterlimit="10" stroke-width="1.2" d="M486.5 285.7s1.8-2.6 6.3-4c0 0 1.2 3 4.8 2.5 0 0 5.2-1.1 3.6-7 0 0-1.1-4.2-7.2-4.7m18.1-7.3s6.1 1.2 6 6.1c0 0 .6 7.6-7.4 9m6.6-12s1.6-3.7 5.5-5.2m-4.6-2.2s1.7 2.8 2.8 3.1m-3.6-1s1.5 2.1 2 2.5m-2.6-.5a8 8 0 0 0 1.5 1.6M485 235.8s1.2-2 4.3-1.2m12.1 15.8s2-7.8 8.5-5m-2.6-.6s.6-3.6-1-5.5m-3.6 5.2s.9 1.5.1 2.7"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M516.2 325s7.4-3.3 5.1-9.1c0 0-.7-2-2.4-1.8 0 0-2.8.1-2.3 4 0 0 1 3.8-.5 7z"/>
|
||||
<path fill="#fff" d="M518.8 321.6s1.7-1.5 1.5-4.3c0 0-.2-.6 0-.7 0 0 .4-.1.4.6 0 0 .5 2.9-1.4 4.5 0 0-.1.3-.4.2 0 0-.2 0 0-.3z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M526.7 319.8s5.2-3.2 2.4-8.7c0 0-.9-1.5-2.4-1.2 0 0-3.2 1-.7 5.5 0 0 1.2 2.9.7 4.5z"/>
|
||||
<path fill="#fff" d="M528 312.4s-.2-.3 0-.6l.4.4s1.5 1.7.3 4.4c0 0-.1.4-.5.2v-.3s1.2-2.4-.2-4z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M511 323.6s-5.8-1.4-4.7-7.5c0 0 .6-2.6 3.1-2.2 0 0 3 .8 1 4.6 0 0-1.1 2.6.7 5.1z"/>
|
||||
<path fill="#fff" d="M508.8 316.5v-.5s.4 0 .5.2c0 0 .6 1 .1 2.4 0 0-.5.9-.2 1.8 0 0 0 .3-.3.4l-.2-.4s-.3-.8.2-1.8c0 0 .6-1.4 0-2.1z"/>
|
||||
<path d="M515.2 312.3s3.4-1.9 6 .3c0 0-.2-1.2-2.4-1.7 0 0-1-3.2-4.2-2.9 0 0 1.2 1.6 3 2.8 0 0-1.8.2-2.4 1.5zm2.4-8.7s2.4 1.7 3.2 2.8c0 0 .9-1.2 2-1.8 0 0-1.2-.3-2 .3 0 0-1.1-1-3-1.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="M504.8 310.6s-.3-.8.3-1.6c0 0 .4-.6.2-1.5m23.4-48s3.5-.2 4-3m6-1.8s-1.2 0-2.2 1.2c0 0-.9 1.2-2 1"/>
|
||||
<path d="M523.6 249.2s1.8 0 2.7-.8c0 0 1.1-.7 1.7.4 0 0 1 1.6-.8 2.3 0 0-2.2 1.2 1.3 3.4 0 0-4.2-1.6-2.4-3.6 0 0 1.8-1.2 1-1.7 0 0-.2-.4-.9 0-.7.6-2.1.4-2.6 0z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M526 205.6s.8-1.2.5-4.4c-.4-3.2 2.6-3.7 3.6-2.8 0 0 1.2 1 0 3.1a8.3 8.3 0 0 1-4.1 4.1z"/>
|
||||
<path fill="#fff" d="M527 203s1.2-1.1.6-3.6l.2-.2h.3s.6 2.8-.6 4.2c0 0-.2.3-.5 0z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M525.1 204.4s0-1.4-2.3-3.6c-2.4-2.4-.5-4.4 1-4.4 0 0 1.3 0 2 2.3a8.3 8.3 0 0 1-.7 5.7z"/>
|
||||
<path fill="#fff" d="M524.8 201.4s0-1.6-2.2-3.3v-.4h.4s2.3 1.8 2.3 3.8c0 0 0 .3-.3.3 0 0-.2 0-.2-.4z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M522 203.3s-.7-1-3.5-2.1c-2.9-1-2.2-3.5-1-4 0 0 1.3-.5 2.6 1.1a7.6 7.6 0 0 1 1.8 5z"/>
|
||||
<path fill="#fff" d="M520.6 201.3s-.6-1.4-3.2-2.1c0 0-.2 0-.2-.3 0 0 0-.2.3-.1 0 0 2.9.6 3.7 2.4l-.1.3s-.3 0-.4-.2z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M523.7 204.4s-1.3.5-4.4-1c-3.1-1.5-4.4 1.1-3.8 2.3 0 0 .5 1.6 2.8 1.2a8.3 8.3 0 0 0 5.4-2.4z"/>
|
||||
<path fill="#fff" d="M516.6 205.4s1.4 1 3.9 0h.3s0 .2-.2.3c0 0-2.6 1.2-4.4.1 0 0-.2 0 0-.3h.4z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M519.3 194.7s1.4.8 1.2 2.5"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="M526 195s.6 1.9 0 3"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M420.2 205.6s-.8-1.2-.5-4.4c.4-3.4-2.5-3.7-3.5-2.8 0 0-1.2 1-.2 3.1a8.3 8.3 0 0 0 4.2 4.1z"/>
|
||||
<path fill="#fff" d="M419.1 203s-1-1.1-.6-3.6v-.2h-.4s-.5 2.8.7 4.2c0 0 .2.3.3 0z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M421.2 204.4s0-1.4 2.4-3.6c2.3-2.4.4-4.4-1-4.4 0 0-1.6 0-2 2.3a8.3 8.3 0 0 0 .6 5.7z"/>
|
||||
<path fill="#fff" d="M421.5 201.4s0-1.6 2-3.3c0 0 .3-.3 0-.4h-.2s-2.4 1.8-2.4 3.8c0 0 0 .3.4.3 0 0 .2 0 .2-.4z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M424.3 203.3s.6-1 3.5-2.1c2.8-1 2-3.5.9-4 0 0-1.2-.5-2.6 1.1a7.6 7.6 0 0 0-1.8 5z"/>
|
||||
<path fill="#fff" d="M425.6 201.3s.6-1.4 3.2-2.1c0 0 .2 0 .2-.3 0 0 0-.2-.2-.1 0 0-2.9.6-3.7 2.4v.3s.4 0 .5-.2z"/>
|
||||
<path fill="#64b4d1" stroke="#00247d" stroke-miterlimit="2.6" stroke-width="1.2" d="M422.5 204.4s1.4.5 4.4-1c3-1.5 4.4 1.1 4 2.3 0 0-.7 1.6-3 1.2a8.3 8.3 0 0 1-5.4-2.4z"/>
|
||||
<path fill="#fff" d="M429.6 205.4s-1.3 1-3.9 0h-.2v.3s2.8 1.2 4.5.1c0 0 .2 0 0-.3h-.4z"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="2.6" stroke-width="1.2" d="M427 194.7s-1.5.8-1.2 2.5"/>
|
||||
<path fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="1.2" d="M420.2 195s-.6 1.9 0 3"/>
|
||||
<path d="M486.7 177.6s1 2.7.6 5.2c-.3 2.4.2 2.9 1 3.4.7.3 2.4-.4 2.5-2.2 0 0 2 3.8-1.8 6.3 0 0-2.7 1.7-5-.4-.8-.9-1.2-3-.7-5 0 0 .6-2.7-.5-5.5 0 0 1.6 1.6 1.2 4.9 0 0-.8 6 3.6 5.6 0 0 3 0 3-3.6 0 0-1.1 1.2-2.4.8a2.4 2.4 0 0 1-1.8-2.8c.1-1.6.6-4.3.3-6.7zM482 187s-.4 4.8-4.6 5.9c0 0 .6-.9-.3-3.3 0 0-1-1.2-1-3.3 0 0-1.2 1 .3 3.8 1 1.7 0 3.6-.1 3.7-.4.1 6.9-1 5.6-6.7zm-5.6-4.5s-1.1-1.2-1.2-3.8c0-2.7-.5-3.4-.9-3.6 0 0 .5 2.3.4 3.6a7 7 0 0 0 .4 3s-2.4.3-3.9-3c-1.3-3.3-2.7-3-3.4-3 0 0 .8.1 2.4 3 1.6 3 2.1 3.7 6.2 3.7zm-10.8-7s1.2 3.2 1.4 4.8c0 0-3.1-1-4-3.5 0 0-3.2 1-2 4.7 0 0-2.9-1-4.2-3.2 0 0 1.6 1.2 3.1 1.7 0 0-.2-3.1 3.6-4.2 0 0 .6 2.7 2.6 3.3zm5-5.4s1.2 1.5 3.4 1.5a3.6 3.6 0 0 0 3.2-1.5s-.1 2.6-3.2 2.7c0 0-3.3 0-3.3-2.7zm-13.4 18.5 2 1.9s1.2 1.2 2-.3c0 0 1.3-2.4 2.9-2.2 0 0-1.2.7-2.4 3 0 0-.2.7-1.2.8-.5 0-1 .2-1.8-.7 0 0-.7-.9-1.5-2.4zm16.7-29.4c-3.2 0-.5 2.4-.5 2.4 0 4-3.1 5.4-5.3 4.2-2.2-1.2-.4-4-.4-4s-2.4 1.5-1 3.9c1.6 2.4 5.7 1.2 7.2-.9 1.5 2.2 5.7 3.3 7.1.9 1.7-2.4-.8-4-.8-4s1.8 2.9-.5 4c-2.1 1.3-5.4 0-5.2-4 0 0 2.7-2.5-.5-2.5zm2-4.4s1.2 2 1 5c0 0 .9-3-1-4.9zm-10 4.7s-.3-2.2-2.4-2.4c0 0 1.9 1.3 2.4 2.4zm16 0s.3-2.2 2.5-2.4c0 0-1.8 1.3-2.4 2.4zm-19.2 3.2s1.6.5 2.6-.7zm-5.4-13.1s1.9-.1 3.8 2.7c0 0-1.9 1-2.4 1.6 0 0 0-1 1-1.7 0 0-.4-1.4-2.4-2.5zm32 0s-2-.1-3.9 2.7c0 0 2 1 2.4 1.6 0 0 0-1-1-1.7 0 0 .4-1.4 2.5-2.5zm-14.7 2.2s1.7.5 3.8-.7c0 0 2.6-1.4 4.3 0 0 0-1.4-.7-4.3.7 0 0-2.7 1.6-3.8 0z"/>
|
||||
<path fill="#fff" d="M476.4 153.6s1.4-2.5 6-2c0 0-1.3 3.6-6 2z"/>
|
||||
<ellipse cx="479.4" cy="152.8" fill="#784421" rx=".8" ry="1.1"/>
|
||||
<ellipse cx="479.4" cy="152.8" rx=".5" ry=".7"/>
|
||||
<path d="M466.8 148.1s2.8.3 4.6 1.2c0 0 1.8 1.2 3.8-.3 0 0 2.2-1.4 3.7-3.1 0 0-3.5 2.3-4.8 2.7 0 0-1.2-1-1.5-2.3 0 0 0-1 2-2.7 0 0-2.5.8-3 2.9a7.2 7.2 0 0 0 1.4 2.3s-.4.3-1.6-.6c0 0-2.8-.8-4.6 0zm7.2 17c-2.4 2.1 0 1.9 0 1.9s2.4.2 0-2zm-1.4-13.2s-1.8.5-4-.7c0 0-2.6-1.4-4.3 0 0 0 1.5-.7 4.3.7 0 0 2.9 1.6 4 0z"/>
|
||||
<path fill="#fff" d="M470.8 153.6s-1.5-2.5-6-2c0 0 1.2 3.6 6 2z"/>
|
||||
<ellipse cx="467.7" cy="152.8" fill="#784421" rx=".8" ry="1.1"/>
|
||||
<ellipse cx="467.7" cy="152.8" rx=".5" ry=".7"/>
|
||||
<path fill="none" stroke="#000" stroke-width="1.2" d="M560 130.6v161.6c0 43.1-86.2 57.2-86.2 57.2s-86.4-14-86.4-57.2V130.6h172.7z"/>
|
||||
<path fill="#006" d="M0 0h320v240H0z"/>
|
||||
<path fill="#fff" d="m37.5 0 122 90.5L281 0h39v31l-120 89.5 120 89V240h-40l-120-89.5L40.5 240H0v-30l119.5-89L0 32V0z"/>
|
||||
<path fill="#c8102e" d="M212 140.5 320 220v20l-135.5-99.5zm-92 10 3 17.5-96 72H0zM320 0v1.5l-124.5 94 1-22L295 0zM0 0l119.5 88h-30L0 21z"/>
|
||||
<path fill="#fff" d="M120.5 0v240h80V0zM0 80v80h320V80z"/>
|
||||
<path fill="#c8102e" d="M0 96.5v48h320v-48zM136.5 0v240h48V0z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,36 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="flag-icons-bn" viewBox="0 0 640 480">
|
||||
<path fill="#f7e017" d="M0 0h640v480H0z"/>
|
||||
<path fill="#fff" d="M0 33.3v213.4l640 100V233.3z"/>
|
||||
<path d="M0 146.7v100l640 200v-100z"/>
|
||||
<g fill="#cf1126" transform="translate(-160) scale(.66667)">
|
||||
<path d="M695.7 569.7a117.2 117.2 0 0 1-49.4-17.2c-2.4-1.6-4.6-3-5-3-.4 0-.6 1.9-.6 4.1 0 6.4-2.6 9.6-9 11.3-6.2 1.6-15.6-1.6-23.2-8a68.3 68.3 0 0 0-24.7-13.5 39.9 39.9 0 0 0-28 3.6 8.7 8.7 0 0 1-2.8 1.3c-1.1 0-1-6.9.2-9 1.5-3 5.1-5.8 9.4-7.3 2.2-.8 4-1.8 4-2.3 0-.4-.8-2-1.7-3.6-2.9-5.1-1.7-10 3.4-13.9 5.2-4 14-4.6 21.7-1.7a32 32 0 0 0 4 1.4c1 0 .4-1.5-2.4-5.6-3.2-4.7-3.9-7-3.5-12.7a14.7 14.7 0 0 1 13.5-13.5c5.8-.4 9.4 1.6 18 9.7a144 144 0 0 0 86 41.6c8.3 1 24.8.5 34.5-1a156 156 0 0 0 81.8-40.8c6.4-6 9.4-7.6 14.7-7.6 4.5 0 7.7 1.4 11 5 3 3.3 4 6.4 3.6 11.5-.2 3.2-.7 4.7-2.6 7.9-2.8 4.5-2.3 5 3.2 2.8 7.6-3 16.9-1.6 21.9 3.2 4.4 4.2 4.8 8.4 1.4 14-1.3 2.1-2.3 4-2.3 4.4 0 .6 1 .8 5.5 1.6 6 1 9.5 5.4 9.5 12.2 0 2-.3 3.7-.6 3.7s-2.6-.9-5-1.9c-7-2.9-11-3.6-19.2-3.5-6.2 0-8.3.3-12.6 1.7a57.5 57.5 0 0 0-19.5 11.5c-6.4 5.7-10.4 7.5-16.6 7.4-5.8 0-9.7-1.7-11.8-5-1.1-1.8-1.3-2.8-1-6.8.2-2.6.1-4.7 0-4.7-.3 0-2.5 1.4-5 3.1A80.5 80.5 0 0 1 778 560a181.6 181.6 0 0 1-82.3 9.7z"/>
|
||||
<path d="M706.3 525.2a136.4 136.4 0 0 1-97.9-55.7c-24.4-33.2-32-77.1-24.6-117.2 4-18.3 12-36.6 25.5-49.6a114.6 114.6 0 0 0-8.7 74.3c9 49.8 51 91.9 101.3 99.2 20 5.7 40.5-.4 59.5-6.5 42-14.8 74-54.6 77.8-99.1 3.3-24-.3-49.1-11.2-71 6.2 3.3 14 16.2 18.6 24.8 16 31 16.7 68.1 7.3 101.2-12.8 42.1-45 79-87.5 92.4a165.7 165.7 0 0 1-60 7.2z"/>
|
||||
<g id="a">
|
||||
<path d="M512 469.9c-2.5-.4-5.3 2.1-4.3 4.7 1.8 2.6 5 4 7.8 5.2a54.2 54.2 0 0 0 23.2 3.6 49.6 49.6 0 0 0 17-3c3-1 6.8-2 8-5.4 1.3-2.1-1-4.3-3.1-3.9-3 .7-6 2-9 2.9a57.7 57.7 0 0 1-20.3 2 54 54 0 0 1-14.4-4.2c-1.6-.7-3.1-1.7-4.9-1.9z"/>
|
||||
<path d="M514.8 459.5c-2.5-.4-4.7 2.6-3.7 5 2 2.8 5.3 4.3 8.4 5.6a42.4 42.4 0 0 0 17 2.9h1.5a37.6 37.6 0 0 0 14.4-2.8c2.7-1.1 6.1-2.2 7.3-5.2.9-1.7.2-4.1-2-4.3-1.8 0-3.5 1.2-5.3 1.7a44.3 44.3 0 0 1-20.6 3.2c-4.4-.5-8.5-2.1-12.5-4-1.5-.7-2.8-1.8-4.5-2z"/>
|
||||
<path d="M518.3 449.6c-2.2-.3-3.7 2.2-3.3 4.1.3 1.8 1.8 3 3.1 4a30 30 0 0 0 18.6 5.3h1.6a28 28 0 0 0 12-2.8c2.5-1 5.4-2.3 6.3-5.2.4-1.3.6-3.2-.9-4-1.6-.8-3.1.5-4.5 1a34 34 0 0 1-15.5 3.9 27 27 0 0 1-13.1-4c-1.5-.7-2.7-2-4.3-2.3z"/>
|
||||
<path d="M481.5 302.7c-3.2 3.3-.7 9.3-1 13.5 1.8 13.2 3.9 26.5 8.8 39 6 12 18.8 18.5 26.5 29.2 2.8 5.1 1.8 11.3 2.4 17 .4 15.3.3 30.7 0 46 7 3.6 14.5 7 22.5 5.7 4.7-1.1 13.5-1.8 14.5-6.5l-1-79.5c-2.7-8.1-11-12.3-17.1-17.5a155.5 155.5 0 0 1-14.2-16.1c-2.6-4.5-12.9-6-9.2 1.6 2.2 6.7 7.7 11.6 9.1 18.6.3 3.9 5 11 1 13.2a24.5 24.5 0 0 0-10.7-10c-4.4-3.3-11.7-4.7-13.3-10.5a42.9 42.9 0 0 0-11-22c1.5-7.4 0-16.7-6.4-21.5l-.9-.2z"/>
|
||||
<path d="M491.4 304.2c-3 .5-2.8 4.2-1.5 6.2a27.2 27.2 0 0 1 1.1 13.4 44.1 44.1 0 0 1 10.6 21.7c0 3 3.2 4 5.3 5.5 4.9 3.1 10.3 5.4 14.7 9.3.9 1 1.6 2 1 0-.7-2.6-1-5.4-3-7.3-2.8-3-6.2-5.6-10.2-6.4-.3-4.2-2.3-8-4.1-11.6-2-3.5-4.1-7.2-7.5-9.4 0-6.1 0-12.5-2.6-18.2-.8-1.4-2-3.1-3.8-3.2z"/>
|
||||
<path d="M499.7 306.6c-2 .6-1.6 3.2-1 4.7a54 54 0 0 1 1 13.2c3.9 3 6.2 7.4 8.4 11.6 1.4 2.8 2.6 5.8 3.1 8.9 3.1 1 5.8 3 8.2 5-1-2.8-3-5-4.5-7.7s-3-5.6-3.7-8.7c-3-3.1-4.6-7.6-4-12 .2-4.7-1.3-9.6-4.5-13.2-.8-.8-1.8-1.7-3-1.8z"/>
|
||||
<path d="M509.2 308c-1.2.2-1.8 1.2-2.4 2.1-.3.9.8 1.8 1 2.8a21.8 21.8 0 0 1 1.4 10.4c-.1 2.5.8 5 2 7a3.9 3.9 0 0 1 3.5-2.8c.5 0 1.4.2 1-.7-.4-4.8-1.1-9.6-2.8-14a9.6 9.6 0 0 0-2.8-4.5c-.2-.2-.6-.4-1-.3z"/>
|
||||
</g>
|
||||
<use xlink:href="#a" width="100%" height="100%" transform="matrix(-1 0 0 1 1440 0)"/>
|
||||
<path d="M715.7 476a35.6 35.6 0 0 1-29.9-24c.3-2.2 3 1.2 4.3 1.5a19 19 0 0 0 8 2.6c3.5 1.5 5.7 5 9.1 6.9 1.6 1.2 7.2 3.6 6.1-.3-1.3-2-2.2-4.6-1-7 1.8-4.1 4.7-7.7 7.7-11.2 2.1-.7 3.6 3.6 5.1 5 2.1 3.3 4.7 7.3 3.4 11.3-1.2 1.5-2 6 1.3 4.6 4-1.8 7.3-4.8 10.6-7.6 3-2 6.7-2.1 9.7-4 1.5-.3 4.4-3.1 5-1.6a44.9 44.9 0 0 1-7.4 12.3 32.1 32.1 0 0 1-18.8 10.9c-4.4.8-8.8 1-13.2.6z"/>
|
||||
<path d="M731.5 460.2c.3-2.7-.3-5.4-1.7-8-2.1-4.2-5-8-8-11.9-2.8-1.6-4.3 3.7-6.1 5.2-2.9 4.3-6.5 8.7-6.7 14-1.6 2.5-4.6-2-5.9-3.5a19 19 0 0 1-4-12 50.8 50.8 0 0 1 3.6-20.6c2-5.6 5.1-11 4.8-17 .2-4.7-.7-9.7-4.4-12.8-3.6-2.8 2.3-3.4 4.1-2 3.2.3 4.9 5.5 7.8 4.2 1.1-2.7 1.4-6 3.8-8.1 2.3-3.2 4.7 1.3 5.5 3.5 1.7 1.8 0 6.5 2.6 6.6 3.2-2.3 5.5-6 9.6-6.9 1.7-1 4.5 0 2.3 1.8-3 2.9-5.6 6.4-6.2 10.7-.9 5.3.4 10.7 2.7 15.4 4.5 9.4 8 20 5.7 30.5-1 4.6-4.2 8.6-8 11.3-.5.3-1.3.3-1.5-.4z"/>
|
||||
<path d="M726.7 389.6a21.2 21.2 0 0 0-5.6-7c-2.4 0-3.9 3-5.5 4.6-1.1 2.1-2.5 5.6-5.3 2.9-4.5-2.6-5.2-8.3-5.2-13-.3-7.6 2.8-14.7 5.5-21.6 1.7-4.3 1.3-9.2.2-13.6-1.3-5-5.4-8.6-8.5-12.6.2-1.5 4.2-.7 5.7-.4 3.4.9 5.4 3.8 7.9 6 1.8-.6 1-4.2 1.9-5.9 0-2.4 3.2-5.5 4.5-2.1 2 2.2 0 6.5 2.5 7.8 2.4-.9 3.6-3.5 5.8-4.7a8 8 0 0 1 7.8-.5c.9 2.2-2.6 4-3.6 6a20.4 20.4 0 0 0-3.8 18c1.4 5 3.8 9.5 4.7 14.5a40.1 40.1 0 0 1-.5 17.2c-.9 3.4-3.8 5.6-6.8 7-.8-.7-1.2-1.7-1.7-2.6z"/>
|
||||
<path d="M711.6 326.9c-3.4-2.5-4.5-4.8-4.5-9.5 0-2.3.5-3.6 2-5.8 2.4-3.2 2-4.2-1.3-3.3-5.3 1.5-7.8.2-8-4.3 0-2.2.4-3.1 3.3-6.7 2.4-2.8 3.3-4.3 2.8-4.8-.5-.4-3.3 2-9 7.8a124 124 0 0 1-11.4 10.6c-9.8 6.6-19.2 7.6-23.5 2.5-2.2-2.6-2.1-4 .4-5.6a27.4 27.4 0 0 0 4.4-3.7 86 86 0 0 1 16.1-11.6c3.6-1.8 4.4-3 2.1-3-3 0-12.5 6.2-19.8 12.8-2.1 2-5.2 4.2-6.8 5a25.4 25.4 0 0 1-13.9 1c-2.2-.7-6.3-4.5-6.3-5.9 0-.3 1-1.1 2-1.8a30 30 0 0 0 4.6-3.2c5.8-5 16.8-10.3 25.5-12.2 2.8-.5 1.7-2-1.4-1.8a56 56 0 0 0-25 11.7c-8.3 6.9-20.8 6.2-24.8-1.3-.7-1.3-1.2-2.5-1-2.7a92.8 92.8 0 0 0 20.4-7.8 51.5 51.5 0 0 1 18.1-6.5c2.8-.5 3-1.9.3-2.2-3.6-.4-9 1.4-18.5 6-12.3 6.1-15.8 7.2-22.2 6.8-6-.4-9.3-1.9-14-6.4-3.2-3-7.6-10.5-6.8-11.4a63.5 63.5 0 0 0 15.8 1.3c8.3 0 10.6-.2 15-1.5a84.3 84.3 0 0 0 24-12.1 57.5 57.5 0 0 1 36.8-13.6c12.4 0 20.2 2.8 27.2 9.9 2.4 2.4 4.4 3.9 4.7 3.6.3-.3.6-4.5.7-9.3 0 0 3.7-.4 4.5.7 0 7.7 0 8.4 1.2 8.4.7 0 1.5-.8 2-2 1-2.5 5-6 9.2-8.2 9-4.5 24.7-4.7 37.3-.3a62.4 62.4 0 0 1 16.7 9.5 90.2 90.2 0 0 0 24 12c6.8 2 19 2.5 25.1 1a61.9 61.9 0 0 1 5.4-1c2.3 0-1.6 7.6-6.2 12.1-8.4 8.2-19.3 8.1-34.6-.1-9.6-5.2-21-8-21-5.2 0 .6.6 1 1.5 1 3.3 0 9.7 2.2 18.7 6.5a53.7 53.7 0 0 0 18.3 6.5c2.3 0 2.4 1.5.2 4.7-2.3 3.4-6.2 5-11.7 5-5.3 0-8.3-1.1-13-5-8-6.6-27.6-14-26.9-10 .2.7 1.1 1.2 3.2 1.5a56 56 0 0 1 23.1 11l5.9 4.3c1.1.6 1.1.8.2 2.5-1.4 2.8-5.2 4.9-9.2 5.3-5.2.6-9.8-1-14.5-5-10-8.3-19.3-14.3-22.3-14.3-2.5 0-1.4 1.4 3 3.7a79.7 79.7 0 0 1 15.8 11c2 1.9 4.3 3.7 5 4.1 1.9 1 1.8 2.4-.2 5s-5.4 3.8-9.7 3.3c-8.6-.9-15.4-5-26-16a70.7 70.7 0 0 0-8.2-7.8c-1.4 0-.5 1.9 2.2 5 3.4 3.7 4 5.8 2.7 9-1.1 2.6-3 3.3-6.8 2.2-4-1-4.6 0-2 3.1 3.8 4.9 3.3 10.7-1.5 14.8a12 12 0 0 1-3.4 2.3c-.4 0-1.4-1-2.3-2.4-3-4.6-5.7-4.6-8.7 0a53.6 53.6 0 0 1-2 3 113.1 113.1 0 0 1-3-2.2z"/>
|
||||
<path d="m726.7 233-5.2 4-4.6-3.4v27.8h9.8z"/>
|
||||
<path d="M694.9 204.3a88.3 88.3 0 0 1-9 32.3l11.1-10.3 7.7 9.2 8.4-9.4 8.5 8 8.2-8.3 8.5 10 7.4-8.2 12.6 9c-4.6-10-10.7-18.6-10-32.8-12.1 9-41 10.6-53.4.4z"/>
|
||||
<path d="M717 197.6c-4.5 0-9.2.1-13.4 1a20.1 20.1 0 0 0-7.8 3c.3 8.6 41 12.1 51.9.2a20 20 0 0 0-8.2-3.3c-4-.8-8.6-.8-12.9-1v7.1H717v-7z"/>
|
||||
<path d="M724.9 154h-6.3v49.4h6.4z"/>
|
||||
<path d="m724.9 155.2-2.4 23.7 24.3 11.9-12.3-16.5 16.8-5.5zm-2.7-6.1c-3.7 0-6.4 1.4-6.4 3s2.7 3 6.4 3 6.4-1.4 6.4-3-2.7-3-6.4-3z"/>
|
||||
</g>
|
||||
<g fill="#f7e017">
|
||||
<path d="M314 375.9c2.7-.9 4.2-2.5 5.3-5.6.5-1.6.9-3.2.8-3.6-.2-1-1.4-1-2.6.1-.9.7-1 1.1-.8 2.6.7 3.7-.7 4.7-7.7 5.4-.7 0-2.8 0-4.5-.3-3.4-.4-4.6 0-3.4 1a7 7 0 0 0 2.1.9c1.9.5 8.8.2 10.8-.5zm14.7-.6c.4-.4 1.7-1 3-1.5 1.7-.5 2.6-1 3.3-2.2 2.1-3 1.7-5.7-1.3-9.3-1.7-2-2.4-1.9-3.7.3-1.2 1.8-1.1 2 .5 2.4.9.2 1.7.8 2.1 1.6 1.8 3.1 1.3 5-1.4 5-2.4 0-3 .4-3.7 2l-.6 1.9c0 .6 1 .5 1.8-.2zm-4.8-3.5c.4-1.3.6-3.5.5-8a33 33 0 0 0-.3-6.4c-.4-.4-2.3.8-2.6 1.7a3 3 0 0 0 .5 2.1c.6 1.2.7 2.4.5 7-.3 6 .1 7 1.4 3.6z"/>
|
||||
<path d="m312.6 369 .7-5c.1-1.7.5-3.8.7-4.7.7-2.3 0-2.9-1.8-1.6l-1.3 1 .2 3.3c.3 3-.2 8.5-.9 10.7-.2.6.1.4.9-.5.6-.7 1.3-2.2 1.5-3.3zm-10 1.6c2.4-2 2.1-5.6 2.7-8.4 0-1.9 1.2-4.1.4-5.8-2.3.4-3.7 2.6-2.5 4.7 0 2.5 0 5.2-1.3 7.4-1 1.5-4.4 1.1-4.2-1 .8-3-2.9-1.5-4.3-.7-1.1.8-3.5.9-2.6-1-.6-2.7-3.9-1-5.7-1-1.7 0-.1-3.5-2.6-3-4.5-.3-9.5.1-13.5-2.6-2.3-1.1-2-3.9-.7-5.7 1.4-2.4 1.8-5.5 4-7.4 2.3-2.1-2-1.2-3-.5-2.2 1.2-.2 4.3-2 6-1 1.8-2.4 4.2-4.8 3.9-3.5-.7-5.5-4-8-6-2.2-.5-1 3.4.2 4.2a21.9 21.9 0 0 0 7.4 3.6c2.6-.5 2.7 3 5 3.5 4 2 8.6 2.5 13.1 2.8 1.8.1.8 3.3 3.1 2.6 1.3.4 4.3-.5 4.4 1-2 2.4 1.9 2.3 3.3 2 1.9-.4 4.2-1 4.7 1.4 1.5 1.7 4.3 1.4 6.2.5l.7-.5z"/>
|
||||
<path d="M262.8 350.4a23.9 23.9 0 0 0 2.4-4.2 16 16 0 0 1 2-3.6c1.2-1.2.5-2-1.4-1.6-1 .2-1.4.6-1.5 1.5a23 23 0 0 1-2.5 7c-1.7 2.5-1.7 2.6-1 2.6.3 0 1.2-.8 2-1.7zm-25-15.7c-1.9 0-2 1.2-.2 1.8 1 .3 1.7 1 2.3 2.3 1.7 3.5 2.8 4.2 7.5 4.6l3 .2.2 1.9c0 1 .3 1.8.5 1.8l2.6-1c2.2-1.2 4.3-3.8 4.3-5.5 0-1-1.8-2.2-3.4-2.2-.7 0-2 .6-3.1 1.4-3.4 2.4-7 2-9-1.2-1.5-2.6-3.2-4-4.7-4zm16.3 6.5c.9 0 1 .7.6 2a.9.9 0 0 1-1.7 0c-.4-1 .1-2 1-2zm126.5-4c-1.3 0-1.6.2-2.4 1.4-1.3 1.9-1.4 6-.2 7.4.7.9.8.9 2.3.2 2.2-.9 2.6-.8 2.5.3 0 3-4.2 8.7-8.6 11.7a9.7 9.7 0 0 0-2.4 2c-.3.8 1.3.7 3.3-.4a21 21 0 0 0 7.9-8c1.1-2.3 1.3-3 1.5-7 0-3.8 0-5-.6-6.2-.8-1.4-1-1.5-2.8-1.5h-.5zm.1 2.5c1 0 1 .2 1.2 1.6 0 1-.1 1.7-.7 2.3-.8.7-1 .7-1.6-.4-1-1.6-.4-3.5 1.1-3.5zm-20.2 28.5c3.9-2 6.2-4.1 7.6-7.2a20 20 0 0 0 1.3-3.1c0-.6-1.9-1.5-3-1.5s-1.4-.8-1-3c.5-2.1 0-4.8-1-4.8-.3 0-1 .5-1.3 1.1-.6 1-.7 1.4-.2 2.7.7 2 .1 3.6-1.7 4.9-.9.6-1.3 1.3-1.3 2l.1 1 2.1-1 2-1.2 1.1 1c.7.4 1.2 1.2 1.2 1.7 0 2.4-6.8 6.4-11.4 6.8-2.5.2-3 0-3.8-.8-.7-.7-.9-1.3-.7-2l.5-2.6c.4-2.1-.4-1.8-2 .6-1.2 2-1.6 4.1-.9 5.2.6 1 4.4 1.8 7.2 1.6 1.7 0 3.4-.5 5.2-1.4zm26-14.5c2.4-2.5 3.5-5.5 3.5-10v-3.5l2-1c2.7-1.2 5.2-3.7 5.2-5.1 0-1.4-.7-1.4-1.8.2-.9 1.1-2 1.8-6 3.7-1 .4-1.1.7-1.4 5-.2 5-1 6.8-3.7 10.2-1.7 2-1.8 2.4-.6 2.4.5 0 1.8-.9 2.8-2zm-26.7-2.8c.2-.7-1.2-1.2-1.7-.6-.3.2-.4.6-.2.9.4.6 1.6.4 1.9-.3zm36.8-9.5c.3-.8-1.1-1.3-1.7-.7-.2.3-.3.7-.1 1 .4.6 1.6.4 1.8-.3zm-44.3-25.9c-1 .5-1.5 1.5-2.1 2.3-.5.3-.1.6.1 1 1.7 1.7 2.4 4.2 3.2 6.5.8 2.7 1.8 5.6 1 8.4-.3 1-1.2 2.1-2.4 1.8-2-.1-4-.7-6-.7-1.9.1-3.3 1.8-5.1 1.6-1.2 0-1.2-2.4-2.2-1.7-.6 1.3-.3 2.7-.4 4 .2.3.8.1 1.1.2h3.7c.2 1.2.2 2.7 1 3.7 1.3.4 2.8 0 4-.5 1.2-.6 1.4-2.1 1.8-3.3.4-1.3 2-1 3-1.5a5.7 5.7 0 0 0 4-5.7c-.2-3.9-1.6-7.4-2.8-11-.5-1.6-.9-3.3-1.5-4.9l-.4-.2zm-6 21.8c1.3 0 1.9 1.6 1.6 2.7-.5 1.5-2.4.6-2.7-.5-.7-1-.3-2.3 1-2.2z"/>
|
||||
<path d="M296 324.8c-.6 0-1.3.2-2 .7-3.5 2.5-4.5 5.4-2 6.6 1.7.8 1.3 1.8-1.5 3.2-4 2-7.5 1.7-14.2-1-1.6-.7-2-.4-1.7 1 .4 1.5 1.8 2.3 5.1 3 3.6 1 8 .7 10.8-.5a14 14 0 0 0 4.3-3.4l2.2-2.3 2.5.3c3.1.4 3.2.4 3.2 1.9 0 1.2 0 1.2 2.9 1.5l4.7.2c1.3 0 2 .3 2.4.9.6.7.9.8 5.6.4 4.4-.4 5.2-.4 7.2.3 1.4.4 3 .6 4.1.5 3.4-.4 8-3.1 8.7-5.1 0-.3 1.3-.7 2.7-1 3.4-.7 3.5-1.4.4-1.8a22.9 22.9 0 0 1-4.6-1.1 12.2 12.2 0 0 0-3.5-.9c-1.7 0-3.3 1-3.3 2.2 0 .7.2.8 2.3.6 1.8-.2 2.4-.1 3.4.7.7.5 1.1 1.1 1 1.3-.5.8-4.5 2.6-6.2 2.9a4.7 4.7 0 0 1-3-.5c-1.6-.8-3.8-.9-4.3-.2-.2.3-.6.1-1.3-.5l-1-1-2.4 1c-2.4 1-3.3 1-3.3-.2 0-.5-.7-.6-4.2-.3-3.9.2-4.3.1-5-.7-.7-.7-.7-1-.2-1.7.4-.8.4-1 0-1.5-.4-.4-1-.4-2.5 0-3.9 1-5 .5-5-2.5 0-1.9-1-3-2.3-3zm-1 2.8c.2 0 .4.1.7.4.3.3.5 1 .3 1.3-.3.9-2 .9-2.3 0-.2-.5 0-1 .5-1.3l.8-.4z"/>
|
||||
<path d="M288 330.4c2.4-1.5 2.4-1.4 2.7-5.5.2-3 .2-3.2-.6-3.2-1.2 0-1.8 1.3-1.8 3.7 0 1.6-.2 2.3-1 3-2 2-6.8 1.1-7.5-1.3-.2-.8.1-1.6 1.1-3 2.1-3 1.7-3.8-1-1.5-1.7 1.6-2 1.6-1.7.3.3-1.3-.3-1.8-1.8-1.4-.7.2-1.2.6-1.3 1.6-.2.8-.6 1.3-1.3 1.5-1.2.3-3.2-.8-3.2-1.8 0-.7 3-4.4 6.9-8.4 1.4-1.5 2.6-3 2.6-3.1 0-.2-.8-.4-1.7-.4-1.4 0-1.8.2-1.8.8 0 .4-1.9 3-4.3 5.7-5 5.6-5.4 6.7-3 8.2a6 6 0 0 0 6.6-.2l1.6-1.1v2c0 2.5.5 3.5 2.5 4.5a8 8 0 0 0 8-.4zm104.4-34.6c-1.8 1.1-.4 3.4 0 5-.8 2-3.5 2.6-5.5 3-2.8.5-4.8 2.8-5.8 5.3-.6 1.6-2 4-3.5 1.6-1.3-1.3-3.7-2.4-5.2-.8-1.2 1.1-1.5 2.7-2 4.2-.7-1.1-1-2.8-2.4-3.2-2.4.3-1.5 3.3-.4 4.5 1 1.5 2 3.3 1 5-1 2-4 3.4-5.7 1.7-1.6-.9-.5-4-2.2-4.2-.8.6-.8 3.9-2.1 2.1-1-1.5-.4-3.6-1.6-4.9-1.3.2-2.4 2.5-2 3.7 1.8 2.4 2.6 5.4 3.3 8.3.4 1.2-.1 3.5 1 4 .7-1.9 0-4 .6-5.9 1.8-.2 3.7.6 5.5.2 2.7-.3 4.7-2.6 5.6-4.9.3-1.8 0-3.6-.1-5.4 2 .4 4.2.4 6.2 1 1 1.5-.3 3.7-.6 5.3-1 3.4-3.7 5.8-6.2 8-1.1.7-1.2 2.4.3 1.5a15 15 0 0 0 7.5-8c1.1-2.6.2-5.5 1-8.1 1-2 3.5-1.6 5.4-1.6 1.9 0 3.5-2.3 2.9-4.2-.6-2.2 1.7-3.2 3.2-4 2.1-1 3.7-3.1 3.5-5.5 0-1.3 0-3.6-1.7-3.7zm-7.3 12.5c2.2.6-.4 4.8-1.6 2.1-.4-1 .5-2.1 1.6-2.1zm-10.3 3c2.9-.1 1.8 4-.6 2.2-1.3-.7-.9-2.2.6-2.2zM270 327.6c0-.4-.2-.7-.6-.7-.7 0-1.2.7-.9 1.3.4.7 1.3.3 1.5-.6zm34-3.6c0-.7-.3-.9-.8-.8-1.1.2-1.3 1.7-.1 1.7.6 0 .9-.3.9-1zm-42-20.4c-1.3-.3-2.2.9-2.7 2-1 1.7-2.2 3.4-4 4.3-1.3.4-2.7-.1-3.9-.8-1.3-.7-1-2.3-1.6-3.4-1-.8-2.7.3-2.6 1.5-.1 1.6 1.3 2.5 2.6 3.1 1 .7 2.6 1 3 2.3 0 1.1.4 2.4 1.7 2 1.5 0 2 1.8 1.3 2.9a6.3 6.3 0 0 0-.7 4c.7.7 1.4-1 2-1.4l1-1.4c2.7.1 5.3.5 8 .4 2 0 3.5-1.2 4.7-2.6 1.8-1.8 3.2-3.9 5.1-5.4 1.4-.4.7-3-.8-2.2-1.3.5-1.7 2-2.6 2.9a31 31 0 0 1-5 5.2c-1.5.6-3.1.3-4.6 0-.6-.5 1.2-1 1.5-1.6.8-.8 1.8-1.6 2.3-2.7-.5-1-1.9-1-2.9-1-2.4.2-4.3 2.3-6.8 2.5-1.9 0-.9-2 0-2.7 1.6-2 3.4-3.8 5.1-5.7.5-.6 2.3-1.2 1.2-2-.4-.2-.9-.2-1.3-.2zm1.2 10c1.3.7-.8 1.8-1.6 1.7-1.1.3-1.2-.8-.2-1 .6-.4 1.2-.7 1.8-.7zm-3.8 2.6c.7 0 2.2.7.8 1.1-1 .8-2-.8-.8-1.1z"/>
|
||||
<path d="M289.4 317.8c0-1-1.6-.8-1.8.2-.2.6 0 .7.8.6.6 0 1-.4 1-.8zm74.7-6.6c.2-.9-1-1.5-1.7-.8-.7.6 0 1.9.8 1.7.4 0 .8-.5 1-.9zM248 302.1c1.1-1 1.2-1.1.7-3.3-.8-3.1-.7-3.5.5-3.8 1.5-.3 5.3 1.7 6 3.3.8 1.3.7 1.4-.4 2.4-1.2 1.1-1.2 2.4 0 2.4 1 0 3.7-2.6 3.7-3.5 0-1.3-3-4.4-5.4-5.5a10.7 10.7 0 0 0-4.6-1c-3.1 0-3.5.7-2.7 4.2 1 4.2-.3 4.8-3.7 1.6a10.4 10.4 0 0 1-3.5-8.6c0-4 1.6-6.1 5.1-6.6 2.4-.3 2.3-.9 0-1.2-3.6-.6-6.6 1.8-7.7 6-1.3 4.7 1.6 10.4 6.7 13.3 2.7 1.5 3.7 1.6 5.3.3zm139.2-5.2c.3-.2.5-.9.5-1.4s.5-1.6 1.1-2.4c.6-.8 1-1.6 1-1.8 0-.8-1.3-.8-2.3 0-1.1.9-2 1-2 0l1.2-.9c1.6-.7 1.7-1.5.4-2.1-1.7-.8-3.5.6-3.6 3-.1 1.6 0 1.8 1.2 2.5 1.1.7 1.3 1 1.1 2-.3 1.6.4 2.2 1.4 1.1zm13-1.4c1-1 1.8-1.9 1.8-2.2 0-.3.9-1.2 1.9-2 2.8-2 3.5-4 2.2-7.3-.5-1.3-2-3-5.5-6a26 26 0 0 0-5.4-4.4c-.9 0-.7 3.4.2 3.7 1.7.6 2.8 1.3 5.4 3.7 3.2 2.8 4.6 5.5 3.8 7-.7 1.4-1.7 1-4.5-2a13.8 13.8 0 0 0-3.2-2.9c-.3 0-.5.6-.5 1.4 0 1 .5 2 2 3.5 2.3 2.6 2.5 4.1.7 5.5a5 5 0 0 1-1.4 1 33.2 33.2 0 0 0-9-10c-.3 0-.5.4-.5 1.4 0 1.3.2 1.7 1.2 2.2a38 38 0 0 1 7 7l1.8 2a9 9 0 0 0 2-1.7zm6-16.8c-.5-1.2-8.4-9.4-9.3-9.4-.4 0-.5.5-.4 1.8 0 1.6.3 1.8 1.4 2.1a20 20 0 0 1 4.6 3.7 17 17 0 0 0 3.7 3v-1.2zm-47.8 92.6a1.2 1 0 1 1-2.3 0 1.2 1 0 1 1 2.3 0zm4.2-1.4a1.2 1 0 1 1-2.4 0 1.2 1 0 1 1 2.4 0z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,676 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bo" viewBox="0 0 640 480">
|
||||
<path fill="#007934" d="M0 0h640v480H0z"/>
|
||||
<path fill="#ffe000" d="M0 0h640v320H0z"/>
|
||||
<path fill="#d52b1e" d="M0 0h640v160H0z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m368.6 210.7-98 97.9a91.8 91.8 0 0 0-1.3-1l98-97.8a6.3 6.3 0 0 1 1.3 1z"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M374.7 204.5c-.4.7-1.4 2.5-1 3.8l-2-1.5c.5 1 .4 1.4-.1 1.8-.3.4-1.4.3-2.1.2.7.4 1.5.8 2.4 1h2c-.7.3-2.2.8-3.3 1-.5.1-1.6.2-2 0-.6.5-1.9-.4-1.3-1-.3-.3-.3-.8-.4-1.4 0-.7.1-1.9.7-3l.5 1.7c.2.5.7 1 1.1 1.4-.2-.5-.4-1.2.1-1.8.5-.5 1.3-.5 2-.2l-1.9-1.3c.8 0 3.3-1 4.1-1.5a62.3 62.3 0 0 0 4.9-3.8 57 57 0 0 0-3.7 4.6z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m387 222.8-125.7 70.9a85 85 0 0 0-.9-1.2l125.7-71a5.6 5.6 0 0 1 1 1.3z"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M394.9 218.3c-.6.6-2.2 2-2.2 3.4l-1.4-2c.2 1-.1 1.5-.7 1.7-.4.4-1.4 0-2-.3a5.1 5.1 0 0 0 2 1.5l1.7.6c-.6.1-2.3.3-3.4.2-.5 0-1.5-.2-1.9-.6-.7.4-1.6-.8-1-1.2 0-.4 0-.8.2-1.4.2-.7.7-1.8 1.6-2.8a7.8 7.8 0 0 0 0 1.8c0 .5.3 1 .5 1.6 0-.5 0-1.3.7-1.7.7-.4 1.4-.2 2 .3l-1.4-1.7c.8.1 3.5-.2 4.4-.5 1-.2 4.1-1.6 6-2.5-1.7 1-4.6 3-5.1 3.6z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m376.3 217.5-113 85.2-1-1.1 112.9-85.2a6 6 0 0 1 1.1 1z"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M383.4 212.1c-.5.6-1.8 2.3-1.6 3.6L380 214c.3 1 .1 1.5-.4 1.7-.4.4-1.5.2-2.1 0 .6.5 1.3 1 2.2 1.2l1.9.3c-.7.3-2.3.6-3.4.6-.5 0-1.6 0-2-.3-.6.5-1.7-.6-1.1-1.1-.2-.3-.1-.8-.1-1.4a6 6 0 0 1 1.1-3 7.8 7.8 0 0 0 .2 1.8c.2.6.5 1 .9 1.6-.2-.5-.2-1.3.4-1.8.6-.4 1.3-.3 2 0l-1.6-1.5c.7 0 3.3-.6 4.2-1 1-.4 3.8-2 5.5-3.1-1.4 1.2-4 3.5-4.4 4z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m271.4 210.7 98 97.9 1.3-1-98-97.8a6.3 6.3 0 0 0-1.3 1z"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M265.3 204.5c.4.7 1.4 2.5 1 3.8l2-1.5c-.5 1-.4 1.4.1 1.8.3.4 1.4.3 2.1.2-.7.4-1.5.8-2.4 1h-2c.7.3 2.2.8 3.3 1 .5.1 1.6.2 2 0 .6.5 1.9-.4 1.3-1 .3-.3.3-.8.4-1.4 0-.7-.1-1.9-.7-3a8 8 0 0 1-.5 1.7c-.2.5-.7 1-1.1 1.4.2-.5.4-1.2-.1-1.8-.5-.5-1.3-.5-2-.2l1.9-1.3c-.8 0-3.3-1-4.1-1.5a62.3 62.3 0 0 1-4.9-3.8 57 57 0 0 1 3.7 4.6z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m253 222.8 125.7 70.9c.2-.3.6-1 .9-1.2l-125.7-71a5.6 5.6 0 0 0-1 1.3z"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M245.1 218.3c.6.6 2.2 2 2.2 3.4l1.4-2c-.2 1 .1 1.5.7 1.7.4.4 1.4 0 2-.3a5.1 5.1 0 0 1-2 1.5l-1.8.6c.7.1 2.3.3 3.4.2.6 0 1.6-.2 2-.6.7.4 1.6-.8 1-1.2 0-.4 0-.8-.2-1.4a6.3 6.3 0 0 0-1.6-2.8v1.8c0 .5-.3 1-.5 1.6 0-.5 0-1.3-.7-1.7-.7-.4-1.4-.2-2 .3l1.4-1.7a17 17 0 0 1-4.4-.5 70.5 70.5 0 0 1-6-2.5c1.7 1 4.6 3 5.1 3.6z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m263.7 217.5 113 85.2 1-1.1-112.9-85.2a6 6 0 0 0-1.1 1z"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M256.6 212.1c.5.6 1.8 2.3 1.6 3.6l1.7-1.7c-.3 1-.1 1.5.4 1.7.4.4 1.5.2 2.1 0a5.4 5.4 0 0 1-2.2 1.2l-1.9.3c.7.3 2.3.6 3.4.6.5 0 1.6 0 2-.3.6.5 1.7-.6 1.1-1.1.2-.3.1-.8.1-1.4a6 6 0 0 0-1.1-3 7.8 7.8 0 0 1-.2 1.8c-.2.6-.5 1-.9 1.6.2-.5.2-1.3-.4-1.8-.6-.4-1.3-.3-2 0l1.6-1.5a15 15 0 0 1-4.2-1c-1-.4-3.8-2-5.5-3.1 1.4 1.2 4 3.5 4.4 4z"/>
|
||||
<path fill="#00e519" stroke="#000" stroke-width=".1" d="M300.1 283.4c4-2.6 15.1-4 16.7-3.6-8 6-16 6.3-16.7 3.7z"/>
|
||||
<path fill="#ffe533" stroke="#000" stroke-width=".1" d="M300.2 283.5c.7 2.6 8.7 2.4 16.6-3.6a69 69 0 0 1-16.6 3.6z"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M300.2 283.5c.7 2.6 8.7 2.4 16.6-3.6a69 69 0 0 1-16.6 3.6z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M300.1 283.4a40.6 40.6 0 0 1 16.7-3.6c-8 6-16 6.3-16.7 3.6z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="M347.6 220.2 322 272.5c-1.3 1-2.3-.3-2.7-.2-1.5 1.7-3.6 2-4 2.5-1.8 2.4-.8 4.3-.7 4.5 1.3 1.8-1.6 3.5-1.5 4-.6 1-2.7.9-3.1 2l-4.8 9.3c-.6.5-3.7 6.1-3.7 6.1-2 0-10.2-5.2-10.4-5.1 4.6-7.3 15.6-18.5 15.3-19.2 3.1-5.2 8-10.9 10.1-10.8 3-1.6 4.5-5.7 4-6.6 2.2 0 3.5-1.4 3.6-1.5l18.8-37.6c1.6-.5 1.4.1 1.9 1 0 0 1-1.2.9-1.3.9-.4 1.8.2 1.8.6z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M348.6 208.8c-.6 1 .2 1 .5 1.1l1 .3c1.3 0 2 .7 2 1l-30 61.3c-1.3 1-2.5-.3-2.9-.1l20.6-41.8 10-18.8-2.8-1.2c-.8-.2-1-.8-.7-1.6l12.6-21.6-10.2 21-.1.4"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M348.6 208.8c-.6 1 .2 1 .5 1.1l1 .3c1.3 0 2 .7 2 1l-30 61.3c-1.3 1-2.5-.3-2.9-.1l20.6-41.8 10-18.8-2.8-1.2c-.8-.2-1-.8-.7-1.6l12.6-21.6-10.2 21-.1.4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M308.8 272.4c-3 0-4.6 2-2.7 4.7m1.4-2.4c-1 .6-1.7-.3-1.7-.3m15.2-13c-1.5 5.6-4.3 9.3-5 10.4-2 2.2-3.9 7.2-3.5 8.1l-8.1 13.3"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M322 272.7c-1.4-.5-5.7-4.5-10-3.8-3.3 3.8-5.3 7.7-5.9 8.2 4 3.3 6.7 5 7.6 5.4.7-.4 1-1.5 1-1.5.9-1-.2-1.7-.2-1.7.2-2.5 2-4.2 3.8-4.3 2.2-.2 1.6-.4 1.9-.4 1-.6 1.8-1.9 1.8-1.9z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M322 272.7c-1.4-.5-5.7-4.5-10-3.8-3.3 3.8-5.3 7.7-5.9 8.2 4 3.3 6.7 5 7.6 5.4.7-.4 1-1.5 1-1.5.9-1-.2-1.7-.2-1.7.2-2.5 2-4.2 3.8-4.3 2.2-.2 1.6-.4 1.9-.4 1-.6 1.8-1.9 1.8-1.9z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M317.6 272.8c-2 0-4 .9-4.8 2.6l4.8-2.6"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M317.6 272.8c-2 0-4 .9-4.8 2.6m-3.5.7c.1.4.7.6 1.1.5.6-.2.8-.7.6-1-.2-.5-.7-.7-1.2-.5-.5.1-.7.6-.5 1zm2.5-3.4c.1.4.7.6 1.2.4.5-.1.7-.6.5-1-.2-.4-.7-.6-1.2-.5-.5.2-.7.7-.5 1z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M345.3 226.1c.8-.2 1.2-1.1.8-2l-4.7-1.7s-.6 0-1 .7c-.5.7.1 1.2.1 1.2l4.8 1.8"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M345.3 226.1c.8-.2 1.2-1.1.8-2l-4.7-1.7s-.6 0-1 .7c-.5.7.1 1.2.1 1.2l4.8 1.8"/>
|
||||
<path fill="#00e519" stroke="#000" stroke-width=".1" d="M294.5 286c3.9-2.7 15-4.2 16.6-3.8-7.8 6.2-15.8 6.5-16.6 3.9z"/>
|
||||
<path fill="#ffe533" stroke="#000" stroke-width=".1" d="M294.6 286c.7 2.7 8.7 2.3 16.5-3.8a62.4 62.4 0 0 1-16.5 3.9z"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M294.6 286c.7 2.7 8.7 2.3 16.5-3.8a62.4 62.4 0 0 1-16.5 3.9z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M294.6 286a40 40 0 0 1 16.6-3.9c-7.9 6.2-16 6.6-16.6 4z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m340.7 222-24.4 52.8c-1.3 1-2.4-.3-2.7-.2-1.5 1.7-3.6 2.1-4 2.5-1.8 2.5-.7 4.4-.6 4.6 1.3 1.8-1.5 3.5-1.4 4-.6 1-2.7.9-3.1 2.1-.1-.1-4.2 8.4-4.6 9.3-.6.5-3.5 6.2-3.5 6.2-2.1 0-10.3-5-10.5-5 4.4-7.3 15.1-18.7 14.9-19.4 3-5.3 7.7-11 9.9-11 3-1.6 4.3-5.7 3.7-6.6 2.3-.1 3.5-1.5 3.7-1.6l18-37.8c1.6-.6 1.3 0 1.9 1 0 0 1-1.2.9-1.4.9-.4 1.7.2 1.8.6z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m340.7 222-24.4 52.8c-1.3 1-2.4-.3-2.7-.2-1.5 1.7-3.6 2.1-4 2.5-1.8 2.5-.7 4.4-.6 4.6 1.3 1.8-1.5 3.5-1.4 4-.6 1-2.7.9-3.1 2.1-.1-.1-4.2 8.4-4.6 9.3-.6.5-3.5 6.2-3.5 6.2-2.1 0-10.3-5-10.5-5 4.4-7.3 15.1-18.7 14.9-19.4 3-5.3 7.7-11 9.9-11 3-1.6 4.3-5.7 3.7-6.6 2.3-.1 3.5-1.5 3.7-1.6l18-37.8c1.6-.6 1.3 0 1.9 1 0 0 1-1.2.9-1.4.9-.4 1.7.2 1.8.6z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M341.4 210.6c-.5 1 .3 1 .6 1.2l1 .3c1.3 0 2 .6 2 1l-28.7 61.7c-1.3 1-2.5-.3-2.9 0l19.7-42.2 9.6-19-2.8-1c-.8-.3-1-.8-.7-1.7l12-21.8-9.6 21.1-.2.4"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M341.4 210.6c-.5 1 .3 1 .6 1.2l1 .3c1.3 0 2 .6 2 1l-28.7 61.7c-1.3 1-2.5-.3-2.9 0l19.7-42.2 9.6-19-2.8-1c-.8-.3-1-.8-.7-1.7l12-21.8-9.6 21.1-.2.4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M303 275c-3-.2-4.6 2-2.6 4.6m1.3-2.4c-1 .6-1.7-.3-1.7-.3m15-13.3c-1.5 5.7-4.2 9.4-4.7 10.6-2.2 2.2-3.9 7.3-3.5 8.1l-7.8 13.4"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M316.1 275c-1.3-.5-5.8-4.5-10-3.7-3.3 3.9-5.1 7.8-5.7 8.3a50 50 0 0 0 7.7 5.3c.7-.4 1-1.5 1-1.5.8-1-.2-1.8-.2-1.8 0-2.4 1.8-4.2 3.6-4.3 2.2-.2 1.6-.4 1.9-.4 1-.6 1.7-2 1.7-2z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M316.1 275c-1.3-.5-5.8-4.5-10-3.7-3.3 3.9-5.1 7.8-5.7 8.3a50 50 0 0 0 7.7 5.3c.7-.4 1-1.5 1-1.5.8-1-.2-1.8-.2-1.8 0-2.4 1.8-4.2 3.6-4.3 2.2-.2 1.6-.4 1.9-.4 1-.6 1.7-2 1.7-2z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M311.8 275.1c-2 0-4 1-4.7 2.7l4.7-2.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M311.8 275.1c-2 0-4 1-4.7 2.7m-3.6.8c.2.4.7.6 1.2.4.5-.2.7-.6.5-1-.2-.5-.7-.6-1.2-.5-.5.2-.7.6-.5 1zm2.4-3.5c.2.4.8.6 1.3.5.5-.2.7-.7.5-1-.2-.5-.7-.7-1.2-.5-.5.1-.8.6-.6 1z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M338.5 228c.8-.2 1.1-1.1.7-2l-4.7-1.6s-.5 0-1 .7c-.4.7.2 1.2.2 1.2l4.8 1.8"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M338.5 228c.8-.2 1.1-1.1.7-2l-4.7-1.6s-.5 0-1 .7c-.4.7.2 1.2.2 1.2l4.8 1.8"/>
|
||||
<path fill="#00e519" stroke="#000" stroke-width=".1" d="M340.6 283.3a39 39 0 0 0-16.8-3.7c8 6.1 16.1 6.3 16.8 3.7z"/>
|
||||
<path fill="#ffe533" stroke="#000" stroke-width=".1" d="M340.6 283.3c-.7 2.7-8.8 2.4-16.8-3.6a63.4 63.4 0 0 0 16.8 3.6z"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M340.6 283.3c-.7 2.7-8.8 2.4-16.8-3.6a63.4 63.4 0 0 0 16.8 3.6z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M340.6 283.3c-4.2-3-15.8-4-16.9-3.7 8 6 16.2 6.3 16.9 3.6z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m292.7 219.3 25.7 52.9c1.3 1 2.4-.3 2.7-.2 1.6 1.7 3.7 2.1 4.2 2.5 1.8 2.4.8 4.4.7 4.6-1.4 1.8 1.5 3.5 1.4 4.1.6 1 2.7.8 3.2 2l4.8 9.3c.7.5 3.7 6.2 3.7 6.2 2.1 0 10.3-5.3 10.5-5.2-4.6-7.3-15.7-18.7-15.4-19.4-3.1-5.2-8.1-11-10.2-10.9-3-1.6-4.5-5.7-4-6.6-2.3 0-3.6-1.5-3.7-1.6l-19-37.9c-1.6-.5-1.3.1-1.9 1 0 0-1-1.2-.9-1.3-.9-.5-1.8.2-1.8.5z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M291.7 207.8c.5 1-.2 1-.5 1.2l-1.1.3c-1.2 0-1.9.7-1.9 1l30.2 61.9c1.3 1 2.5-.3 3-.1l-20.8-42.3-10-19 2.7-1.1c.8-.2 1-.8.7-1.6l-12.7-21.9 10.2 21.2.2.4"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M291.7 207.8c.5 1-.2 1-.5 1.2l-1.1.3c-1.2 0-1.9.7-1.9 1l30.2 61.9c1.3 1 2.5-.3 3-.1l-20.8-42.3-10-19 2.7-1.1c.8-.2 1-.8.7-1.6l-12.7-21.9 10.2 21.2.2.4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M331.9 272.1c3 0 4.6 2.1 2.7 4.7m-1.4-2.3c1 .6 1.7-.4 1.7-.4M319.5 261c1.6 5.7 4.4 9.5 5 10.6 2.2 2.2 4 7.3 3.7 8.2l8.1 13.4"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M318.6 272.4c1.3-.4 5.7-4.6 10-3.8 3.4 3.8 5.4 7.7 6 8.2-4 3.4-6.7 5-7.7 5.5-.7-.4-1-1.5-1-1.5-.9-1 .2-1.8.2-1.8-.1-2.4-2-4.2-3.8-4.3-2.3-.2-1.6-.4-2-.4-1-.6-1.7-1.9-1.7-1.9z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M318.6 272.4c1.3-.4 5.7-4.6 10-3.8 3.4 3.8 5.4 7.7 6 8.2-4 3.4-6.7 5-7.7 5.5-.7-.4-1-1.5-1-1.5-.9-1 .2-1.8.2-1.8-.1-2.4-2-4.2-3.8-4.3-2.3-.2-1.6-.4-2-.4-1-.6-1.7-1.9-1.7-1.9z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M323 272.5c2 0 4 1 4.8 2.7l-4.8-2.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M323 272.5c2 0 4 1 4.8 2.7m3.6.6a1 1 0 0 1-1.2.5.7.7 0 0 1-.5-1c.1-.5.7-.6 1.2-.5.5.2.7.6.5 1zm-2.5-3.4c-.2.4-.8.6-1.3.5-.4-.2-.7-.7-.5-1 .2-.5.7-.7 1.2-.5.5.1.8.6.6 1z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M295 225.4a1.4 1.4 0 0 1-.8-2l4.8-1.8s.5.1 1 .7c.5.7-.2 1.2-.2 1.2l-4.8 1.9"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M295 225.4a1.4 1.4 0 0 1-.8-2l4.8-1.8s.5.1 1 .7c.5.7-.2 1.2-.2 1.2l-4.8 1.9"/>
|
||||
<path fill="#00e519" stroke="#000" stroke-width=".1" d="M345.6 286a38 38 0 0 0-16.6-3.8c7.9 6.2 15.9 6.5 16.6 3.9z"/>
|
||||
<path fill="#ffe533" stroke="#000" stroke-width=".1" d="M345.6 286c-.8 2.7-8.7 2.3-16.5-3.8a62.4 62.4 0 0 0 16.5 3.9z"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M345.6 286c-.8 2.7-8.7 2.3-16.5-3.8a62.4 62.4 0 0 0 16.5 3.9z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M345.6 286a40.1 40.1 0 0 0-16.6-3.9c7.8 6.2 15.9 6.6 16.6 4z"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m299.5 222 24.4 52.8c1.3 1 2.3-.3 2.7-.2 1.5 1.7 3.6 2.1 4 2.5 1.7 2.5.7 4.4.6 4.6-1.4 1.7 1.5 3.5 1.4 4 .5 1 2.6.9 3 2.1.2-.1 4.2 8.4 4.7 9.3.6.5 3.5 6.2 3.5 6.2 2 0 10.3-5 10.5-5-4.4-7.4-15.2-18.7-15-19.4-2.9-5.3-7.7-11-9.8-11-3-1.6-4.3-5.7-3.7-6.6-2.3-.1-3.6-1.5-3.7-1.6L304 222c-1.6-.6-1.4 0-2 1 0 0-.9-1.2-.8-1.4-.9-.4-1.8.2-1.8.6z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m299.5 222 24.4 52.8c1.3 1 2.3-.3 2.7-.2 1.5 1.7 3.6 2.1 4 2.5 1.7 2.5.7 4.4.6 4.6-1.4 1.7 1.5 3.5 1.4 4 .5 1 2.6.9 3 2.1.2-.1 4.2 8.4 4.7 9.3.6.5 3.5 6.2 3.5 6.2 2 0 10.3-5 10.5-5-4.4-7.4-15.2-18.7-15-19.4-2.9-5.3-7.7-11-9.8-11-3-1.6-4.3-5.7-3.7-6.6-2.3-.1-3.6-1.5-3.7-1.6L304 222c-1.6-.6-1.4 0-2 1 0 0-.9-1.2-.8-1.4-.9-.4-1.8.2-1.8.6z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M298.8 210.6c.4 1-.3 1-.6 1.2l-1 .3c-1.3 0-2 .6-2 1l28.7 61.7c1.3 1 2.5-.3 2.9 0L307 232.5l-9.6-19 2.7-1c.9-.3 1.2-.8.8-1.7L288.8 189l9.7 21.1.2.4"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M298.8 210.6c.4 1-.3 1-.6 1.2l-1 .3c-1.3 0-2 .6-2 1l28.7 61.7c1.3 1 2.5-.3 2.9 0L307 232.5l-9.6-19 2.7-1c.9-.3 1.2-.8.8-1.7L288.8 189l9.7 21.1.2.4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M337.2 275c3-.2 4.5 2 2.6 4.6m-1.4-2.4c1 .6 1.8-.3 1.8-.3m-15-13.3c1.4 5.7 4.2 9.4 4.7 10.6 2.1 2.2 3.8 7.3 3.5 8.1l7.8 13.4"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M324 275c1.4-.5 5.8-4.5 10.1-3.7 3.2 3.9 5.1 7.8 5.7 8.3a54.1 54.1 0 0 1-7.8 5.3c-.6-.4-1-1.5-1-1.5-.7-1 .3-1.8.3-1.8 0-2.4-1.8-4.2-3.6-4.3-2.3-.2-1.6-.4-2-.4-1-.6-1.7-2-1.7-2z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M324 275c1.4-.5 5.8-4.5 10.1-3.7 3.2 3.9 5.1 7.8 5.7 8.3a54.1 54.1 0 0 1-7.8 5.3c-.6-.4-1-1.5-1-1.5-.7-1 .3-1.8.3-1.8 0-2.4-1.8-4.2-3.6-4.3-2.3-.2-1.6-.4-2-.4-1-.6-1.7-2-1.7-2z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M328.4 275.1c2 0 4 1 4.7 2.7l-4.7-2.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M328.4 275.1c2 0 4 1 4.7 2.7m3.6.8a1 1 0 0 1-1.2.4c-.5-.2-.8-.6-.6-1 .2-.5.8-.6 1.3-.5.4.2.7.6.5 1zm-2.5-3.5c-.2.4-.7.6-1.2.5-.5-.2-.7-.7-.5-1 .2-.5.7-.7 1.2-.5.5.1.7.6.5 1z"/>
|
||||
<path fill="#cce5e5" stroke="#000" stroke-width=".1" d="M301.6 228c-.8-.2-1-1.1-.7-2l4.7-1.6s.6 0 1 .7c.5.7-.2 1.2-.2 1.2l-4.8 1.8"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M301.6 228c-.8-.2-1-1.1-.7-2l4.7-1.6s.6 0 1 .7c.5.7-.2 1.2-.2 1.2l-4.8 1.8"/>
|
||||
<path fill="#a05a2c" stroke="#000" stroke-width=".1" d="m315.3 250.7 35.5-38a97.4 97.4 0 0 1-1.4-.9l-35.6 38a7.5 7.5 0 0 0 1.5.9z"/>
|
||||
<path fill="#e7e7e7" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M349.8 212.2c-1.2-1-3.4-2.2-5-1.8-.5-2.2 2.5-4.4 3.8-4-.3 2.3 3.2 3.8 3.1 3.8l-1.9 2z"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M352.1 210.4c1 .8 1.4.8 2.8 1.6 1.4.7 3.2-1.1 4.1-1.7 0 0 1 3.4-1.1 5.6-2 2.3-4.6 2.8-6.5 2.1 0 0 2.6-2.5 1.5-3.6-1-1.1-1.4-1.2-2.5-1.9"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M-27.7-406.5h4.1v2.2h-4.1z" transform="matrix(-.67726 .73575 -.82314 -.56784 0 0)"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m308.2 290.3-1 9 1.8-2.2c.3-.6 1.5-2.1 1.8-7.4 0 0-1-2.9-1.4-2.9-.7-.4-1.2 3.5-1.2 3.5zm2.2-20.1-2.7 15.8c0 .5 1.3 1.6 2.1-1.2l1.5-10.5-1-4.1z"/>
|
||||
<path fill="#d52b1e" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M315.9 284.6a8.7 8.7 0 0 1-1.4-2l-.4 3.1s2 1.5 1.7 4.3l.4-.6.2-1s.5-2 .5-3.1c0 0-.5-.2-1-.7z"/>
|
||||
<path fill="#ffe000" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M307.3 299.4s3.3-3 3.5-9.7l.4-1.9s0 1.5.8.4c.6-1.5.6-2.8.6-2.8s1.2-1.6 1.6.3l-1.2 9.6a51.4 51.4 0 0 1-.3 2s-.7-1-1.4.1c-.7 1.2-1.8 2.7-4 2zm4-25.1-1.5 10.5s1.2.6 1.4 3c.1 1.2.6.6.8.4.2-.8 0-2.3 0-2.3l.6-7.3s-1.2-3.4-1.3-4.3z"/>
|
||||
<path fill="#ffe000" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m310.1 298.8-.2 2.6s1 0 1.7-1.2c.8-1.1 1-2.8 1-2.8s-.7-1.1-1.3 0c-.5 1-1.2 1.4-1.2 1.4zm1.8-10.6c.6-1 .8-2.6.7-2.8l-.7.5c.2 1.2 0 2.3 0 2.3z"/>
|
||||
<path fill="#d52b1e" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M315.3 287.1a4.4 4.4 0 0 0-1.3-1.5l-1.5 12s-.4 3-2.3 3.7c0 0 1.1 10.3 4.5 7.5.4-.4 1-3.6.9-5.5l-.9-6a26.8 26.8 0 0 1 .5-4.7l.6-2.6c.2-.2 0-1.8-.5-2.9z"/>
|
||||
<path fill="#d52b1e" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m316.9 285.3 1 1c.3 0-2.3 19.3-2.3 19.3s0-2-.7-6c-.6-3.2.2-7.5.9-9.6 0 0 .8-.5 1-4.7z"/>
|
||||
<path fill="#f7e214" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m312.6 278.8-.7 7.1s1.8-2.4 2.2-.2l.4-3.2s-1.5-2.4-2-3.7z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M311.3 287.8s-.6-6.1-3.6-1.8a10 10 0 0 0 0 3c0 .8.9 1.8 1.2 2.3.7 1 1.3-.2 1.3-.2s.7-1 1-3.3z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M287.8 237c-.1-3.5-1.2-9.3-1.3-13.3l-12-12.2s-1.4 9.9-5.8 15.5l19 10"/>
|
||||
<path fill="#ffe000" stroke="#000" stroke-width=".1" d="M288.7 237.3c.5-2.4 1-5 1.5-10.2l-7.7-7.6c0 3.2-3.6 8.1-3.9 14"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M295.3 244.7c1-4.3-1.3-4.8 2-10.8l-7.2-6.8c-1.3 4-2.2 6.6-2 10l6 4.4"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M267.6 270c-1.5-4.2.5-12.7.2-18-.1-3.5 2.5-16.7 2.4-20.6l-14.1-8.8s-.6 14.3-2.3 29.9c-1.4 8-1.4 15.3-.4 21.5 1.5 8.7 3 12.2 6.5 15.9 6.3 6.5 19.7 2.7 19.7 2.7 11.3-2.3 17.8-9.4 17.8-9.4s-3.7.8-9.6 1.4c-13-.9-18.2 2.4-18.6-11"/>
|
||||
<path fill="#f7e214" stroke="#000" stroke-width=".1" d="m305.4 278.8.2-.1-5.9 1.9-8 .6c-17.2.4-15-10.3-14.3-27.5.1-6.6 1.4-14.8 1-17.7l-11.5-6.6c-3.8 10.6-2.6 18-3.3 23.5-.4 6-1.7 17.4.2 22.4 2.7 11.6 11.8 11.2 24.2 10.1 6.1-.5 9.4-2 9.4-2l8-4.6"/>
|
||||
<path fill="#007a3d" stroke="#000" stroke-width=".1" d="M305.6 278.5a34.4 34.4 0 0 1-6 2.2l-8 .8c-12.5 1-19.8-7.7-18.2-27.6 0-7 .2-10.2 2.6-19.5l7 4v.7c-.5 2-1.5 7-1.5 9.2 0 16 10.1 28.2 23.9 30.3h.2"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M260 230.6c1 2 8 12.5 12 14.5m-11-7.6c1.3 2 9.8 14 13.6 14.6m-15.5 3.6c2 2.4 4 7 9.7 10m-7 3.3c4 3.7 13.6 11.6 23 12m-23-6c2 2.3 6.2 13.3 24 8.3m-26.7-6.3c1.2 2.6 10.1 17.3 26 11.6"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M277.8 264.8c-1.5-4.3.5-12.7.2-18.1-.1-3.5 1.5-15.5 1.5-19.5l-13.2-9.9s-.6 14.3-2.3 30a84 84 0 0 0-1.5 23.9c1.8 10 6.6 12.8 7.5 13.6 6.7 6 22 5.4 23.5 4.9 10.8-4 15.6-10.8 15.6-10.8s-5.2-.1-11.1.5c-13-1-19.7-.4-20.1-13.8"/>
|
||||
<path fill="#ffe000" stroke="#000" stroke-width=".1" d="M315.6 273.5h.2l-5.9 1.8-8 .6c-17.2.5-15-10.2-14.3-27.5.1-6.5.3-12.4 0-15.3l-10.3-7.6c-3.8 10.7-2.8 16.7-3.5 22.2-.4 5.8-1.7 17.3.2 22.3 2.7 11.7 11.8 11.2 24.2 10.2 6.1-.5 9.4-2.1 9.4-2.1l8-4.6"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M315.9 273.4c-2.4 1.2-6 2.1-6 2.1l-8 .8c-12.5 1-19.8-7.7-18.2-27.6 0-7-.3-7.5 2.2-16.9 3.8 2.5 11.1 8.8 11.1 8.8s-2 2.8-1.5 6.7c0 16 6.4 24 20.2 26.1l1.5-13"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M270.1 225.3c1.2 2 8.1 12.6 12 14.6m-10.8-7.7c1.2 2 9.7 14 13.5 14.7m-15.5 3.6c2 2.3 4 7 9.7 10m-7 3.3c4 3.6 13.6 11.6 23 12m-23-6c2 2.3 6.2 13.2 24 8.3m-26.7-6.4c1.2 2.7 10.1 17.3 26 11.7"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="m256.2 224-.7 6c-.2 4.4-.1 7.7.1 9.8 0 .2.9 5.5.6 5.8-1 1.1-1.1 1.2-2.2.4-.1-.2.5-5.6.5-6.3l.4-9.9c0-1 1-6.4 1-6.4s0-1.2.3.5"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m256.2 224-.7 6c-.2 4.4-.1 7.7.1 9.8l.7 5.8c-1 1.1-1.2 1.6-2.3.7-.1-.2.5-5.9.5-6.6l.4-9.9c0-1 1-6.4 1-6.4s0-1.2.3.5z"/>
|
||||
<path fill="#f7e214" stroke="#000" stroke-width=".1" d="M256 222.2s-1 6-1.2 9.6l-.3 7.9-.5 4.5c-.1.7.1.2 0 .2-.9.5-1.5.1-2-.3-.2-.1 1.4-3.8 1.4-4.5.9-10.8 2.4-17 2.4-17s-.6 3.7.3-.4"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M256 222.2s-1 6-1.2 9.6l-.3 7.9-.5 4.5c-.1.7.1.2 0 .2-.9.5-1.5.1-2-.3-.1-.1 1.4-3.8 1.5-4.5.8-10.8 2.3-17.1 2.3-17.1s-.6 3.8.3-.3zm-.4 17.3s-1 .4-1 .2m0-1.3s.7 0 .8-.2m0-1s-.6.3-.8 0m.8-1.6h-.6m.6-1.5h-.6m.5-2.1s-.3.1-.4-.1m.5-1.7h-.5m-.5 9.5s-.9.2-1-.1m1.1-2s-.9.1-1-.1m1-1.3h-.7m.9-1.5h-.7m.7-1.7h-.5m.7-1.5h-.6m.6-1.7s-.4.3-.4 0m0 9s-.9 0-.9-.3m12.8-19.8-.7 6a63.4 63.4 0 0 0 0 9.8c0 .3 1 5.5.7 5.8-1 1.2-1.1 1.3-2.2.4-.1-.1.5-5.5.5-6.3l.4-9.8c0-1.1 1-6.5 1-6.5s0-1.1.3.6"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m266.4 218.7-.7 6a73 73 0 0 0 .1 9.8l.7 5.8c-1 1.2-1.2 1.6-2.3.7-.1-.1.5-5.8.5-6.6l.4-9.8c0-1.1 1-6.5 1-6.5s0-1.1.3.6z"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M266.3 217s-1.2 6-1.3 9.5l-.3 8-.5 4.4v.3c-.9.5-1.5 0-2-.4-.2 0 1.4-3.7 1.4-4.5a127 127 0 0 1 2.4-17l.3-.4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M266.3 217s-1.2 6-1.3 9.5l-.3 8-.5 4.4v.3c-.9.5-1.5 0-2-.4-.2 0 1.4-3.7 1.4-4.5.9-10.8 2.4-17 2.4-17l.3-.4zm-.5 17.2s-1 .5-1 .2m0-1.2s.7 0 .8-.3m0-1s-.6.4-.8.1m.7-1.7h-.5m.6-1.5h-.6m.5-2s-.4 0-.4-.2m.5-1.7h-.5m-.5 9.6s-.9.1-1-.2m1.1-1.9s-.9 0-1-.2m1-1.3h-.7m.9-1.4h-.7m.7-1.7-.5-.1m.7-1.4-.6-.1m.6-1.6s-.4.2-.4 0m0 9s-.9 0-.9-.4"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M274.3 211.3s.5 5.1.2 8c-.3 3.5-.3 4.5-.6 6.6v3.9c.8.5 1.5.2 2 0 .3-.1-1-3.3-1-4 .5-8.9-.4-14.3-.4-14.3l-.2-.2"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M274.3 211.3s.5 5.1.2 8c-.3 3.5-.3 4.5-.6 6.6v3.8c0 .5-.1 0 0 .1.8.5 1.4.2 2 0 .2-.1-1-3.3-1-4 .5-9-.4-14.3-.4-14.3l-.2-.2zm-.3 14.6s.9.2 1 0m-.8-1.7s.9.2 1 0m-1-1.2h.9m-.8-1.2h.7m-.5-1.4h.5m-.5-1.3h.5m-.4-1.4s.4.2.4 0m-1 7.4s1 .1 1-.1"/>
|
||||
<path fill="#005000" stroke="#000" stroke-width=".1" d="M306 221.7h.8-.8z"/>
|
||||
<path fill="#fff" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M316.7 256.4s-.3-.2-.4 0l.1.2.3-.2zm-1 1.1 2.1-.1"/>
|
||||
<path fill="#e8a30e" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M292.2 284.2c-.2 3-7.4 6.6-12.7.1-5.7-4.5-4.5-11.4 0-12.3l54.7-53.3c2.2-1.2 2.4-2.3 3.5-3.5 2.3 2.5 7 6.8 9.6 9-1.6 1.2-2.9 2.5-3.2 3.5l-52 56.5z"/>
|
||||
<path fill="#e7e7e7" fill-rule="evenodd" stroke="#000" stroke-linejoin="round" stroke-width=".1" d="M337.8 215c2.6-3.5 12.8 5.8 10 8.7-2.6 2.8-12.4-5-10-8.6z"/>
|
||||
<path fill="#cccccf" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M347 223c-2 1.4-9.3-4.8-8.1-7.2 2-2.2 10.1 5.7 8 7.2z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M344 227.9a15.8 15.8 0 0 1-9.9-9m-23 44.8a16.3 16.3 0 0 1-11.4-11.6m9.1 14.3a16.3 16.3 0 0 1-11.4-11.6m-2.1 25.8c-5.8-1.8-10.4-6-12.2-12.1m9.8 14.8a18 18 0 0 1-12.3-12.2"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M279.4 285c-.3 1.4-1 1.8-2.1 1.4m13.7-2c-2.1 3.5-4.5 2.4-6.5 2.5"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M276.4 285.2c0 1 .8 1.6 1.7 1.6a1.7 1.7 0 0 0 1.7-1.6c0-1-.7-1.6-1.7-1.6s-1.7 1-1.7 1.9"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M279.5 284.9c-.3 1.3-1 1.7-2 1.3m13.5-1.7c-2.1 3.4-4.5 2.3-6.5 2.4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m331.8 290.3 1 9-1.8-2.2c-.3-.6-1.5-2.1-1.8-7.4 0 0 1-2.9 1.4-2.9.7-.4 1.2 3.5 1.2 3.5zm-2.2-20.1 2.7 15.8c0 .5-1.3 1.6-2.1-1.2l-1.5-10.5 1-4.1z"/>
|
||||
<path fill="#d52b1e" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m324.1 284.6 1.4-2 .4 3.1s-2 1.5-1.7 4.3l-.4-.6-.2-1s-.5-2-.5-3.1c0 0 .5-.2 1-.7z"/>
|
||||
<path fill="#ffe000" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M332.8 299.4s-3.4-3-3.6-9.7l-.4-1.9s0 1.5-.8.4c-.6-1.5-.6-2.8-.6-2.8s-1.2-1.6-1.6.3l1.2 9.6.3 2s.7-1 1.4.1c.7 1.2 1.8 2.7 4 2zm-4.1-25.1 1.5 10.5s-1.2.6-1.4 3c-.1 1.2-.6.6-.8.4-.2-.8 0-2.3 0-2.3l-.6-7.3s1.2-3.4 1.3-4.3z"/>
|
||||
<path fill="#ffe000" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m329.9 298.8.2 2.6s-1 0-1.7-1.2c-.8-1.1-1-2.8-1-2.8s.7-1.1 1.3 0c.5 1 1.2 1.4 1.2 1.4zm-1.8-10.6a6 6 0 0 1-.7-2.8l.7.5c-.2 1.2 0 2.3 0 2.3z"/>
|
||||
<path fill="#d52b1e" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M324.8 287.1a4.4 4.4 0 0 1 1.2-1.5l1.5 12s.4 3 2.3 3.7c0 0-1.1 10.3-4.5 7.5-.4-.4-1-3.6-.9-5.5l.9-6a26.8 26.8 0 0 0-.5-4.7 31 31 0 0 0-.6-2.6c-.2-.2 0-1.8.5-2.9z"/>
|
||||
<path fill="#d52b1e" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m323.1 285.3-1 1c-.3 0 2.3 19.3 2.3 19.3s0-2 .7-6c.6-3.2-.2-7.5-.9-9.6 0 0-.8-.5-1-4.7z"/>
|
||||
<path fill="#f7e214" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m327.4 278.8.7 7.1s-1.8-2.4-2.2-.2l-.4-3.2s1.5-2.4 2-3.7z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M328.7 287.8s.6-6.1 3.6-1.8c0 0 .2 2.4 0 3 0 .8-.9 1.8-1.2 2.3-.7 1-1.3-.2-1.3-.2s-.7-1-1-3.3z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M352.2 237c.1-3.5 1.2-9.3 1.3-13.3l12-12.2s1.4 9.9 5.8 15.5l-19 10"/>
|
||||
<path fill="#ffe000" stroke="#000" stroke-width=".1" d="M351.3 237.3c-.5-2.4-1-5-1.5-10.2l7.7-7.6c0 3.2 3.6 8.1 3.9 14"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M344.7 244.7c-1-4.3 1.3-4.8-2-10.8l7.2-6.8c1.3 4 2.2 6.6 2 10l-6 4.4"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M372.4 270c1.5-4.2-.5-12.7-.2-18 .1-3.5-2.5-16.7-2.4-20.6l14.1-8.8s.6 14.3 2.3 29.9c1.4 8 1.4 15.3.4 21.5-1.5 8.7-3 12.2-6.5 15.9-6.3 6.5-19.7 2.7-19.7 2.7-11.3-2.3-17.8-9.4-17.8-9.4s3.7.8 9.6 1.4c13-.9 18.2 2.4 18.6-11"/>
|
||||
<path fill="#f7e214" stroke="#000" stroke-width=".1" d="m334.6 278.8-.2-.1 5.9 1.9 8 .6c17.2.4 15-10.3 14.3-27.5-.1-6.6-1.4-14.8-1-17.7l11.5-6.6c3.8 10.6 2.6 18 3.3 23.5.4 6 1.7 17.4-.2 22.4-2.7 11.6-11.8 11.2-24.2 10.1-6.1-.5-9.4-2-9.4-2l-8-4.6"/>
|
||||
<path fill="#007a3d" stroke="#000" stroke-width=".1" d="M334.4 278.5a34.4 34.4 0 0 0 6 2.2l8 .8c12.5 1 19.8-7.7 18.2-27.6 0-7-.2-10.2-2.6-19.5l-7 4v.7c.5 2 1.5 7 1.5 9.2 0 16-10.1 28.2-23.9 30.3h-.2"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M380 230.6c-1 2-8 12.5-12 14.5m11-7.6c-1.3 2-9.8 14-13.6 14.6m15.5 3.6c-2 2.4-4 7-9.7 10m7 3.3c-4 3.7-13.6 11.6-23 12m23-6c-2 2.3-6.2 13.3-24 8.3m26.7-6.3c-1.2 2.6-10.1 17.3-26 11.6"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M362.3 264.8c1.4-4.3-.6-12.7-.4-18.1.2-3.5-1.4-15.5-1.4-19.5l13.2-9.9s.6 14.3 2.3 30a84 84 0 0 1 1.5 23.9c-1.8 10-6.6 12.8-7.5 13.6-6.7 6-22 5.4-23.5 4.9-10.8-4-15.6-10.8-15.6-10.8s5.2-.1 11.1.5c13-1 19.7-.4 20.1-13.8"/>
|
||||
<path fill="#ffe000" stroke="#000" stroke-width=".1" d="M324.4 273.5h-.2l5.9 1.8 8 .6c17.2.5 15-10.2 14.3-27.5-.1-6.5-.3-12.4 0-15.3l10.3-7.6c3.8 10.7 2.8 16.7 3.5 22.2.4 5.8 1.7 17.3-.2 22.3-2.7 11.7-11.8 11.2-24.2 10.2-6.1-.5-9.4-2.1-9.4-2.1l-8-4.6"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M324.1 273.4a34.4 34.4 0 0 0 6 2.1l8 .8c12.5 1 19.8-7.7 18.2-27.6 0-7 .3-7.5-2.2-16.9-3.8 2.5-11.1 8.8-11.1 8.8s2 2.8 1.5 6.7c0 16-6.4 24-20.2 26.1l-1.5-13"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M369.9 225.3c-1.2 2-8.1 12.6-12 14.6m10.8-7.7c-1.2 2-9.7 14-13.5 14.7m15.5 3.6c-2 2.3-4 7-9.7 10m7 3.3c-4 3.6-13.6 11.6-23 12m23-6c-2 2.3-6.2 13.2-24 8.3m26.7-6.4c-1.2 2.7-10.1 17.3-26 11.7"/>
|
||||
<path fill="#f7e214" stroke="#000" stroke-width=".1" d="m383.8 224 .7 6c.2 4.4.1 7.7-.1 9.8 0 .2-.8 5.5-.6 5.8 1 1.1 1.1 1.2 2.2.4.1-.2-.5-5.6-.5-6.3l-.4-9.9c0-1-1-6.4-1-6.4s0-1.2-.3.5"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="m383.8 224 .7 6c.2 4.4.1 7.7-.1 9.8l-.7 5.8c1 1.1 1.2 1.6 2.3.7.1-.2-.5-5.9-.5-6.6l-.4-9.9c0-1-1-6.4-1-6.4s0-1.2-.3.5z"/>
|
||||
<path fill="#f7e214" stroke="#000" stroke-width=".1" d="M384 222.2s1 6 1.2 9.6l.3 7.9.5 4.5c.1.7 0 .2 0 .2.9.5 1.5.1 2-.3.2-.1-1.4-3.8-1.4-4.5-.9-10.8-2.4-17-2.4-17s.6 3.7-.3-.4"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M384 222.2s1 6 1.2 9.6l.3 7.9.5 4.5c.1.7-.1.2 0 .2.9.5 1.5.1 2-.3.2-.1-1.4-3.8-1.4-4.5-.9-10.8-2.4-17.1-2.4-17.1s.6 3.8-.3-.3zm.4 17.3s1 .4 1 .2m0-1.3s-.7 0-.8-.2m0-1s.6.3.8 0m-.7-1.6h.5m-.6-1.5h.6m-.5-2.1s.4.1.4-.1m-.5-1.7h.5m.5 9.5s.9.2 1-.1m-1.1-2s.9.1 1-.1m-1-1.3h.7m-.9-1.5h.7m-.7-1.7h.5m-.7-1.5h.6m-.6-1.7s.4.3.4 0m0 9s.9 0 .9-.3"/>
|
||||
<path fill="#f7e214" stroke="#000" stroke-width=".1" d="m373.6 218.7.7 6a73 73 0 0 1-.1 9.8c0 .3-.8 5.5-.6 5.8 1 1.2 1.1 1.3 2.2.4.1-.1-.5-5.5-.5-6.3l-.4-9.8c0-1.1-1-6.5-1-6.5s0-1.1-.3.6"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="m373.6 218.7.7 6a73 73 0 0 1-.1 9.8l-.7 5.8c1 1.2 1.2 1.6 2.3.7.1-.1-.5-5.8-.5-6.6l-.4-9.8c0-1.1-1-6.5-1-6.5s0-1.1-.3.6z"/>
|
||||
<path fill="#f7e214" stroke="#000" stroke-width=".1" d="M373.7 217s1.2 6 1.3 9.5l.3 8 .5 4.4v.3c.9.5 1.5 0 2-.4.2 0-1.4-3.7-1.4-4.5a127 127 0 0 0-2.4-17l-.3-.4"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M373.7 217s1.2 6 1.3 9.5l.3 8 .5 4.4v.3c.9.5 1.5 0 2-.4.2 0-1.4-3.7-1.4-4.5-.9-10.8-2.4-17-2.4-17l-.3-.4zm.5 17.2s1 .5 1 .2m0-1.2s-.7 0-.8-.3m0-1s.6.4.8.1m-.7-1.7h.5m-.6-1.5h.6m-.5-2s.4 0 .4-.2m-.5-1.7h.5m.5 9.6s.9.1 1-.2m-1.1-1.9s.9 0 1-.2m-1-1.3h.7m-.9-1.4h.7m-.7-1.7.5-.1m-.7-1.4.6-.1m-.6-1.6s.4.2.4 0m0 9s.9 0 .9-.4m-10.5-22s-.5 5.2-.2 8.1c.3 3.5.3 4.5.6 6.6v3.9c-.8.5-1.4.2-2 0-.2-.1 1-3.3 1-4-.5-8.9.4-14.3.4-14.3l.2-.2"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M365.7 211.3s-.5 5.1-.2 8c.3 3.5.3 4.5.6 6.6v3.8c0 .5.1 0 0 .1-.8.5-1.4.2-2 0-.2-.1 1-3.3 1-4-.5-9 .4-14.3.4-14.3l.2-.2zm.3 14.6s-.9.2-1 0m.8-1.7s-.9.2-1 0m1-1.2h-.9m.8-1.2h-.7m.5-1.4h-.5m.5-1.3h-.5m.4-1.4s-.4.2-.4 0m1 7.4s-1 .1-1-.1"/>
|
||||
<path fill="#005000" stroke="#000" stroke-width=".1" d="M334 221.7h-.8.8z"/>
|
||||
<path fill="#fff" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M323.3 256.4s.3-.2.4 0l-.1.2-.3-.2zm1 1.1-2.1-.1"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M291.7 215.5c0-2.1 2-3.3 2.2-3.6 1-.6 1.7-1.2 3.7-1.5l.2.9c0 .3-.5 1.6-2 2.7a11.5 11.5 0 0 1-4.1 1.5z"/>
|
||||
<path fill="#a05a2c" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m291.6 214.7 29.7 38.4 1.4-1.3-30.2-39.1-.9 2z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M291.2 207.2s3.2-.4 2.8-2.2c-.5-1.8-2.6-1.8-3.5-1.9-1 0-4 .7-4.8 1.5-.9 1-2.7 2.5-2.1 5s1.3 4.4 2.3 6c.9 1.6.7 3.2.4 3.9 0 .3-.4 1.3.4 1.6 1.2.5 1.5.5 2.5-.6s2.5-3 2.5-5c0-2.1 2-3.3 2.2-3.6 1-.6 1.7-1.2 3.7-1.5 0 0-.7-1.2-1.8-1-1.1 0-3.4-1-4.6-2.2z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M291.2 207.2s3.2-.4 2.8-2.2c-.5-1.8-2.6-1.8-3.5-1.9-1 0-4 .7-4.8 1.5-.9 1-2.7 2.5-2.1 5s1.3 4.4 2.3 6c.9 1.6.7 3.2.4 3.9 0 .3-.4 1.3.4 1.6 1.2.5 1.5.5 2.5-.6s2.5-3 2.5-5c0-2.1 2-3.3 2.2-3.6 1-.6 1.7-1.2 3.7-1.5 0 0-.7-1.2-1.8-1-1.1 0-3.4-1-4.6-2.2z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M291.2 207.2c-.4 0-1.7-.6-2.6-.3-.9.4-2.7 1.4-2.4 3m10.4-.3s-1.8.8-3.1 1.7c-.6.3-2.4 2-3.5 3.2-1 1-1.3 2.4-3.5 3.9m9-9-1.4 1c-.7.3-.9.9-1.2 1.3"/>
|
||||
<path fill="#e8a30e" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M347.8 284.2c.2 3 7.4 6.6 12.7.1 5.7-4.5 4.5-11.4 0-12.3l-54.7-53.3c-2.2-1.2-2.4-2.3-3.5-3.5a133 133 0 0 1-9.6 9 9.9 9.9 0 0 1 3.2 3.5l51.9 56.5z"/>
|
||||
<path fill="#e7e7e7" fill-rule="evenodd" stroke="#000" stroke-linejoin="round" stroke-width=".1" d="M302.2 215c-2.6-3.5-12.8 5.8-10 8.7 2.6 2.8 12.4-5 10-8.6z"/>
|
||||
<path fill="#cccccf" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M293 223c2 1.4 9.3-4.8 8.1-7.2-2-2.2-10.1 5.7-8 7.2z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M296 227.9a16 16 0 0 0 9.9-9m23 44.8c5.7-1.7 9.6-5.5 11.4-11.6m-9.1 14.3c5.7-1.8 9.7-5.5 11.4-11.6m2.1 25.8c5.8-1.8 10.4-6 12.2-12.1m-9.8 14.8a18 18 0 0 0 12.3-12.2"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M360.6 285c.3 1.4 1 1.8 2.1 1.4m-13.7-2c2.1 3.5 4.5 2.4 6.5 2.5"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="M363.6 285.2c0 1-.8 1.6-1.7 1.6a1.7 1.7 0 0 1-1.7-1.6c0-1 .7-1.6 1.7-1.6s1.7 1 1.7 1.9"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M360.5 284.9c.3 1.3 1 1.7 2 1.3m-13.5-1.7c2.1 3.4 4.5 2.3 6.5 2.4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M339.6 175.5c1.8 2.9 4.4 8 5.2 12a22.5 22.5 0 0 1-7 20.8c-5.2 4.7-13.3 6-16.7 6.8-3.3.7-5.7 1.8-6.3 2.5 0-.5 0-1 .5-1.6 1.6-.7 4.1-1 7.8-1.8 7.2-1.5 14.8-4.2 19-12.2 5.4-10.3 2.2-18.4-2.5-26.4z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M341.6 206.2a.4.6 49.9 0 1-.6-.6.4.6 49.9 1 1 .6.6z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M346.6 205c-1.1.6-2.2.7-3 1a65.7 65.7 0 0 0-3.7 1.4c-.8.3-1.6 1.3-1.6 1.3s1.2 1.3 2.6 1.1c1.2-.1 1.7-.4 2.3-.7.6-.3.6-.6 1.4-1.2 1-.7 1.6-2 2-3zm-5.7 1.1c-.3.6-1.1.5-1.6.5l-.2.2c.6 0 1.5 0 2-.5l-.2-.2z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M346.6 205c-1 1-2.8 2-4.7 2.8a14 14 0 0 1-5 1l-.2.3c1.4-.1 3.4-.4 5-1.1a14.9 14.9 0 0 0 4.9-3zm-2.4 4.6c-2-.1-3 .5-4.8.9-1.7.4-3.7-.5-4.8 1.1 4.4 2.9 7.6 1 9.6-2z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M340.2 213.6c-.8-.8-8-3.2-9.2-.5 1.7 2 6.8 2.4 9.2.5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m338.5 215.5-2.5-.4c-1-.1-1.3-.3-1.9-.4-1-.1-2.3-1.6-6-.5 1.4 3.4 6.4 4 10.4 1.3zm1.6-1.9c-3.8.8-8.3 0-10.1-1l-.3.2a16.3 16.3 0 0 0 10.4.8zm4-4c-2.2 1.5-5.2 2.6-11.4 1.8v.2c8.5.7 9.3-.8 11.4-2z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M338.5 215.5c-3 .1-4.7 1.4-10.3-1.3l-1.4-.6-.5.2 1.4.4c7 3 6.8 1.6 10.8 1.3z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M327.3 211.6a.4.6 66.2 1 0 .4.7.4.6 66.2 0 0-.4-.7z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M327.1 212.3c-.6.1-.8.9-.8 1.3l-.4.2c.2-.6.4-1.4 1.2-1.7v.1z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M346 186.8a.4.6 15.8 1 1-1-.2.4.6 15.8 0 1 1 .2z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M341.6 203.2c-.1-2.1-1.1.8-3.2-3.9-.6-1.4-.6-2.2-1-4.3 1.2 1.8 3 2.3 3.8 3.6.7 1.4.5 3.5.4 4.6z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M337.5 195.2s1 2.4 2.4 4a7.9 7.9 0 0 1 1.8 3.7"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M338.5 197.2c1.3 1.7 3 3.8 3 6h.3c-.3-2.8-2-4.1-3-5.6l-.3-.4zm10.8 2.7c-1 .7-2 1-2.7 1.4l-1.4.9c-.4.2-1 .2-1.4.5-.7.5-2 2-2 2s1.3 1.1 2 1c2.4-.5 3.1-1.4 4.3-2.3 1-.8 1-2.5 1.2-3.5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m340.7 204.8-.2.4c1.3-.2 3.5-1.5 5-2.2 1.8-1 3-1.7 3.7-3a8.9 8.9 0 0 1-3.9 3c-1.5.7-3.7 2-4.6 1.8zm9.4-9.5c-.8.9-1.7 1.3-2.4 1.8l-1.3 1.1-1.2.8c-.6.6-1.5 2.2-1.5 2.2s.7.7 1.4.4c2.4-.3 3.1-1.4 4-3.5.5-1 1-1.8 1-2.8z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M341.5 199.4a.6.4 62 1 0 .8-.3.6.4 62 0 0-.8.3z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m342.5 201.6-.2.3c2.9-1.3 6.6-3.9 7.8-6.5a17.2 17.2 0 0 1-7.6 6.2zm8.3-10.7c-.7 1-1.6 1.4-2.2 2l-1 1.1-1.2.9c-.5.6-1.2 2.2-1.2 2.2s.8.9 1.5.5a12 12 0 0 0 2.1-1.6c.5-.4.6-1.4 1.2-2.2.7-1 .8-1.9.8-2.9z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M348.7 193.8c-1.4 1.6-3 3.1-4.6 3.8l-.2.4c2.6-1.5 3.7-2.8 4.9-4.1zm1-5.6c-.4 1-1 1.5-1.6 2l-.8 1.2-1 .9-.7 2.1s.6.6 1.2.2a12 12 0 0 0 1.8-1.6c.4-.5.6-1.4 1-2.2a4 4 0 0 0 .2-2.6zm-4.3-1.1-.5 1.6v-.4c0-.4.2-.9.4-1.3l.1.1z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M348.4 191a13 13 0 0 1-3.8 4v.3c2.2-1.6 3-3 3.8-4.2zm-5.6 10c-.2-.6-.3-1-.6-1.4.2.5.4 1 .4 1.6l.1-.3z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M341.9 181.3a.4.3 39.5 0 1-.5.5.4.3 39.5 0 1 .5-.5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m343.1 182.5-1.2-.8 1.3 1v-.2zm5.6.4c-1.2 2.4-3.9 4-2.8 7.5 2.8 2.6 3-4.5 2.8-7.5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M346.1 177.7c-.5 2.4-2.6 4.4-1.2 7.6 4 1 2-4.3 1.2-7.6z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M343.7 174c2 3.7 2.5 5.9.2 8.3 0 0-1.3-1.1-1.6-3.3-.2-1.8 1.2-4 1.4-5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M340.4 171.8c.5 2.4-1.5 3.5 1.4 6.5 2.1-2.4 1.1-3-1.4-6.5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M339.6 176c-3.3.3-2-2.6-3-5.3 2 1.5 4.7 2.1 3 5.3zm2.2 4.4c-1-4.4-4-2.6-5.6-4.6.9 2.9 2.1 4.8 5.6 4.6zm1.4 4.1c-2.6-.1-4.8-1.4-6.2-4.4 2.7 1.2 5.7 1.4 6.2 4.4z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M343.6 188.3c-1-1.2-1-2-1.5-2.7a9 9 0 0 0-3-3.7c0 3 .4 6.5 4.5 6.4z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M344.2 191.6a20 20 0 0 0-5.6-5.7c1 2.2.6 6.3 5.6 5.7z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M343.7 196c-5-.1-4.5-4.8-4.5-7 .9 1.4 2 2.5 2.8 3.5.9 1 1.8 2.2 1.7 3.5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M343.1 198.8c-.4-1 0-1.4-1-2.3-1-1-2.8-2.7-3.7-4.6-.1 1.7-.2 4.4 1.2 5.3 1 .7 2 .9 3.5 1.6zm-4.3 7.3c-3.9-3-1.6-5.6-1.2-7.9 1 2.6 3.7 4.8 1.2 7.9zm1.6-29.2c-1.3-2.3-2-3.6-3.7-6 2 2.7 2.8 4.5 3.9 6.4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M338.9 206.8c.1-3-.7-5.7-1.3-8.5.5 3 1.3 6 1 8.8l.3-.3zm4.6-7.4c-.4-1.8-4.1-3-5-7.5.7 4.4 4.5 5.5 4.8 8l.2-.5zm.8-2.5-.1.5c-.6-3-4-4.4-5-8.4 1.5 4.3 4.3 4.9 5.1 7.9zm.7-4.4c-1.7-2.6-4.1-3.6-6.4-6.7 2.1 3 4.8 4.4 6.4 7v-.3zm0-3.5c-2-.8-3.9-3-6-7.1 1.4 3 3 5.8 6 7.6v-.5zm-1-4c-2.1-1.7-5-2.8-7-4.9 1.7 2 5 3.3 7.1 5.2v-.3zm-1.6-4.3c-2.2-1.5-4.4-2-6.2-4.8 1.5 2.8 3.8 3.5 6.3 5l-.1-.2zm6.3 2.2c-.8 3.1-1.5 6.3-3.6 8.4v-.4c1-.5 2.5-3.7 3.6-8zm-2.6-5.1c-.1 3.2 0 6.5-1.7 8.3l-.1-.3c1.6-1.4 1.5-5 1.8-8zm-2.2-3.6c.5 2.8.6 5.3-.2 9.5l-.1-.3c.4-2.4 1-5 .3-9.2zm-3.4-2.3c1.1 2.4 2 4.8 1.2 7.4l-.2-.3c.9-2.4-.1-4.7-1-7zm-4.4 31.2c1.4 3.2-.4 5.6-2.5 7-1.6-4.7 1.8-4.2 2.5-7z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M336.2 203.1c.2 2-2 4.2-2.6 7.6l-.3.2c1-4 3-5.6 2.9-7.8z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M343.7 181.2a.3.4 1.9 1 1-.6-.1.3.4 1.9 0 1 .6.1z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M343.5 183v-1.6h-.2v1.7l.2-.1z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M342.8 180.9a.3.4 2 0 1-.5.2.3.4 2 0 1 .5-.2z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m343.2 182.3-.5-1.1.4 1.4v-.2z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M344.7 186.9a.4.3 80.5 1 1-.7 0 .4.3 80.5 0 1 .7 0z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M344.9 188.6a9.3 9.3 0 0 0-.4-1.4h-.1l.4 1.6v-.2z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M343.6 187.2a.4.3 57 1 1-.5.5.4.3 57 0 1 .5-.5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M344.8 188.6a8.8 8.8 0 0 0-1.2-1v.1l1.3 1.1-.1-.2z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M343.4 199.1a.3.4 12.7 1 1-.7-.2.3.4 12.7 0 1 .7.2z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M342.8 200.8c.2-.5.2-1 .2-1.5a9 9 0 0 1-.4 1.7l.2-.2z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M344 199.9a.3.4 50.5 1 0 .5.4.3.4 50.5 1 0-.5-.4z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m342.7 201 1.3-.8v.1a8.7 8.7 0 0 0-1.3 1v-.2z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M340.7 205a.3.4 40.4 1 1-.4-.6.3.4 40.4 0 1 .4.5z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m339.5 206.2.9-1.3h-.1l-1 1.3h.2z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M338.8 204.5a.5.6 10 0 0 1 .1.5.6 10 1 0-1 0z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M339.4 205c-.3.7 0 1 0 1.2l-.1.3c-.2-.4-.3-.8-.1-1.5h.2zm-12.1 9.5c-.7 0-1-.4-1.3-.8h-.3c.4.5.8 1 1.5 1v-.3z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M327.3 215.2a.6.4 9.5 0 1 .2-.9.6.4 9.5 1 1-.2.8z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M332.7 206a5.5 5.5 0 0 1-4 6.4c-.9-4 2.8-4 4-6.3z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M332.7 206.1a21 21 0 0 1-4.8 7.2h-.5c2.7-2.1 4.2-4.9 5.3-7.2z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M327.8 213.3a.5.4 9.8 1 1-.4-.7.5.4 9.8 0 1 .4.7z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M326 213.8a8 8 0 0 0 1.4-.7h-.1l-1.7.6h.3zm2.5-5c0 1.2-1 2.4-2 3.2-.9.9-1 1.2-2.2 1.6-1.2-2.8 2.8-3.3 4.2-4.8z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M328.5 208.8c-1.3 2.5-3.5 3.8-4.7 5.4h-.1c1.6-2.2 3-2.7 4.8-5.4z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M300.4 175.5c-1.7 2.9-4.4 8-5.1 12a22.5 22.5 0 0 0 7 20.8c5.2 4.7 13.3 6 16.6 6.8 3.4.7 5.8 1.8 6.4 2.5 0-.5 0-1-.5-1.6-1.6-.7-4.2-1-7.8-1.8-7.2-1.5-14.9-4.2-19-12.2-5.4-10.3-2.2-18.4 2.5-26.4z"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M314.1 213.6c-.2.4-4 3.7-7.5 3.5-2.5-.2-2.9-.8-2.9-.8s-.2-.7 2-1.1c2.3-.5 6.2-2 8.4-1.6z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M303.8 216.3c2.7.3 5.5-.8 7.7-1.6"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M311.2 208.7a11 11 0 0 1 4.6 3.7c.9 1.5.7 1.9.7 1.9s-.2.3-1.3-1c-1-1.2-3.4-3.3-4-4.6z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M316.5 214.2c-.9-1.7-2.5-3-3.7-4.2"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M300.3 175.8c-.1-.3.3-3.4 2-4.4 1.3-.7 1.8-.5 1.8-.5s.3.3-.5 1.3c-1 1-2.1 3.2-3.3 3.7z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M304 171c-1.4.7-2.3 2.2-3 3.4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M299.4 177.4c-.2-.2-1-3-.2-4.7.5-1.3.9-1.4.9-1.4s.3 0 .1 1.3c-.2 1.3-.2 3.8-.8 4.8z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M300 171.4c-.6 1.3-.6 3-.6 4.4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M299.4 177.5c.2 0 2.7-.8 3.9-2.1.8-1 .8-1.3.8-1.3s-.2-.2-1.1.5c-1 .8-3 2-3.6 2.9z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M304 174.1c-.9 1.1-2.2 2-3.3 2.6"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M298.2 179.6a10 10 0 0 1-.9-5.2c.3-1.6.6-1.7.6-1.7s.4 0 .4 1.4c0 1.5.3 4.2-.1 5.5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M298 172.7c-.5 1.7-.2 3.6 0 5"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M297.3 181.6c-.3-.2-2.3-3-2-5.2 0-1.7.5-2 .5-2s.3-.1.6 1.4c.3 1.6 1.2 4.3.9 5.8z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M295.7 174.5c-.2 1.8.5 3.7 1 5.2"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M296.2 184.1a9.9 9.9 0 0 1-2.4-4.7c-.2-1.5 0-1.8 0-1.8s.4-.1.8 1.3c.4 1.4 1.6 3.9 1.6 5.2z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M293.9 177.7c.1 1.7 1 3.4 1.5 4.8"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M298.2 179.6c.3 0 3.2-.2 4.6-1.7 1-1 1-1.5 1-1.5s-.2-.3-1.4.4c-1.1.8-3.4 1.8-4.2 2.8z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M303.7 176.5c-1 1.2-2.7 1.9-4 2.5"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M297.3 181.6c.2 0 3.2 0 4.6-1.4 1.1-1 1-1.4 1-1.4s0-.3-1.2.3c-1.2.7-3.6 1.5-4.4 2.5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M303 178.9c-1.2 1-2.8 1.7-4.1 2.2"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M296.4 184.2c.2 0 3.4-.2 4.9-1.7 1-1.1 1-1.5 1-1.5s-.1-.4-1.4.3c-1.2.8-3.7 1.8-4.5 2.9z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M302.3 181c-1.2 1.3-2.9 2-4.3 2.5"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M296.8 183s-.3-.5-.3-1c0-.6.2-.8.2-.8l-.2-.2-.1.9v.3l-.5-.5a10.8 10.8 0 0 1-.1-.4h-.2l.3.7c.5.4.8 1.1.8 1.1"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295.6 180.3a.5.4 83.5 1 1 .1 1 .5.4 83.5 1 1-.1-1z" overflow="visible" style="marker:none"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M296.8 180.3a.4.5 19.3 1 1-.3 1 .4.5 19.3 1 1 .3-1z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m296.7 183 1-.7c.3-.4.3-.7.3-.7h.2l-.4.8-.2.2.6-.1.4-.2.1.1-.6.4c-.6 0-1.3.3-1.3.3"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M299.4 181.6a.4.5 45.6 1 0-.8.8.4.5 45.6 1 0 .8-.8z" overflow="visible" style="marker:none"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M298.4 180.8a.4.5 19.8 1 0-.3 1 .4.5 19.8 1 0 .3-1z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295.4 186.9c-.2-.2-2.4-2.6-2.8-4.8-.3-1.6 0-1.9 0-1.9s.3-.1.8 1.3c.6 1.5 2 4 2 5.4z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M292.6 180.3c.2 1.8 1.2 3.5 2 4.9"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295.6 186.9c.3 0 3.5-.4 5-2 1-1.3 1-1.7 1-1.7s-.2-.4-1.4.5-3.8 2-4.6 3.2z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M301.5 183.2c-1 1.4-2.8 2.2-4.2 3"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295.2 189.6c.3 0 3.5-.9 5-2.6 1.1-1.3 1-1.7 1-1.7s-.1-.2-1.4.7c-1.2 1-3.8 2.5-4.6 3.6z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M301.2 185.4c-1.1 1.4-3 2.4-4.3 3.2"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295 189.6c-.3 0-3.3-2.2-3.8-4.5-.3-1.7 0-2 0-2s.5-.3 1.2 1.2c.7 1.4 2.5 3.8 2.7 5.3z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M291.3 183.2c.3 1.8 1.5 3.5 2.5 4.8"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295.2 193a11 11 0 0 0 4.6-3.6c.9-1.5.7-1.8.7-1.8s-.2-.3-1.3 1c-1 1.2-3.4 3.1-4 4.5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M300.5 187.7c-1 1.6-2.5 3-3.8 4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295 193.2c-.3 0-3.6-1.7-4.4-4-.7-1.6-.4-2-.4-2s.4-.4 1.3 1c1 1.3 3.1 3.5 3.5 5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M290.3 187.2c.5 1.8 2 3.4 3.2 4.6"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295 191.6s-.4-.5-.5-1c-.2-.6 0-.9 0-.9h-.3v.8l.2.4-.6-.4-.3-.5-.2.2.5.6c.6.2 1.1 1 1.1 1"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M293 189a.6.4 69.4 1 1 .4 1.2.6.4 69.4 1 1-.4-1.1z" overflow="visible" style="marker:none"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M294.3 188.7a.4.6 5.2 1 1 0 1.2.4.6 5.2 1 1 0-1.2z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295 191.6s.6-.5.8-1c.3-.5.2-.8.2-.8h.3l-.3.8-.1.4.6-.3.4-.4.1.2-.6.5c-.6.1-1.2.7-1.2.7"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M297.5 189.4a.4.6 31.5 1 0-.6 1 .4.6 31.5 1 0 .6-1z" overflow="visible" style="marker:none"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M296.3 188.9a.4.6 5.7 1 0-.1 1.1.4.6 5.7 1 0 0-1.1z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295.4 196.2a12 12 0 0 1-5.1-4c-1-1.7-.8-2.1-.8-2.1s.2-.3 1.4 1c1.3 1.4 3.8 3.6 4.5 5.1z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M289.5 190.2c1 1.8 2.8 3.3 4.2 4.6"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295.6 196.2c.4 0 4-1.9 5-4.4.6-1.8.3-2.3.3-2.3s-.4-.3-1.4 1.2c-1 1.4-3.4 3.8-3.9 5.5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M300.9 189.6c-.7 2-2.3 3.7-3.6 5"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M296.6 199.3c.3-.1 3.7-2.3 4.5-4.8.7-1.9.4-2.3.4-2.3s-.4-.3-1.3 1.3c-1 1.5-3.2 4-3.6 5.7z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M301.5 192.3c-.7 2-2.2 3.8-3.4 5.2"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M296.3 199.3c-.4 0-4.7-1.3-6.2-3.8-1-2-.9-2.5-.9-2.5s.4-.4 1.8 1c1.5 1.4 4.5 3.5 5.3 5.2z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M289.3 193.1c1.1 2 3.3 3.6 5 4.8"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M300.1 205.7c.3-.2 2.6-3 2.8-5.6.2-1.8-.2-2-.2-2s-.3-.2-.8 1.4c-.5 1.7-1.8 4.6-1.8 6.2z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M302.8 198.1c-.1 2-1 4-1.8 5.6"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M300 205.6c-.5.2-5.4 0-7.7-2.1-1.6-1.6-1.5-2.2-1.5-2.2s.2-.5 2.1.5c2 1 5.7 2.3 7 3.8z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M290.9 201.4c1.7 1.7 4.4 2.6 6.5 3.4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M298.2 203c-.4.1-4.8-1-6.8-3.1-1.6-1.6-1.5-2.1-1.5-2.1s.2-.4 2 .8c1.6 1.2 5 3 6.3 4.5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M290 197.9c1.6 1.7 4 3 5.8 4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M298.4 203c.4-.2 3.6-2.9 4-5.6.2-2-.2-2.5-.2-2.5s-.5-.2-1.2 1.5c-.7 1.8-2.6 4.7-2.6 6.5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M302.2 195c-.2 2.2-1.5 4.3-2.5 6"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="m297.4 201.5-1-.8c-.4-.5-.5-.9-.5-.9h-.3a8 8 0 0 0 .8 1.2l-.8-.1-.5-.3v.2l.7.4c.7 0 1.6.5 1.6.5"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M294.2 199.8a.7.5 45.9 1 1 1 1 .7.5 45.9 1 1-1-1z" overflow="visible" style="marker:none"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M295.4 198.8a.7.5 71.6 1 1 .4 1.3.7.5 71.6 1 1-.4-1.3z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M297.5 201.4s.4-.6.4-1.3l-.1-1h.2a7.8 7.8 0 0 0 .1 1.3l.6-.5.2-.6.2.1-.4.8c-.6.5-1 1.4-1 1.4"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M299.1 198.2a.5.7 8 1 0-.2 1.3.5.7 8 1 0 .2-1.3z" overflow="visible" style="marker:none"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M297.6 198.1a.7.5 72.2 1 0 .4 1.3.7.5 72.2 1 0-.4-1.3z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M301.8 207.6c-.3.2-4.3 1-6.8-.3-1.8-.9-2-1.4-2-1.4s0-.5 2 0c1.8.4 5.2.7 6.8 1.7z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M293.1 206c2 1 4.4 1.2 6.3 1.4"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M302 207.5c.2-.1 2-2.5 1.9-4.8 0-1.7-.4-2-.4-2s-.3-.2-.6 1.3c-.2 1.5-1 4-.9 5.5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M303.5 200.8c.2 1.8-.4 3.6-.9 5"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M305.5 210.3c-.3.3-5 1.5-8 .3-2-1-2.1-1.5-2.1-1.5s0-.5 2.2-.1c2.1.3 6.2.4 8 1.3z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M295.5 209.2c2.2 1 5 1 7.3 1.1"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M305.8 210.3c.2-.3 1.2-3.8 0-5.6-1-1.4-1.5-1.3-1.5-1.3s-.4 0 0 1.5c.3 1.5.5 4.3 1.5 5.4z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M304.4 203.4c1 1.4 1.1 3.4 1.3 5"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M303.3 208.7s-.5.4-1.2 0c-.6-.3-.8-.7-.8-.7l-.3.2 1 .7.3.2-.9.2-.6-.1v.3h1a13.6 13.6 0 0 0 1.5-.5"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M299.5 208.7a.8.5 24.1 1 1 1.4.7.8.5 24.1 1 1-1.4-.7z" overflow="visible" style="marker:none"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M300.3 207.2a.8.5 49.9 1 1 1 1.2.8.5 49.9 1 1-1-1.2z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M303.4 209s.6-.5.2-1.2l-.6-.9.1-.2.7 1 .2.3.2-.9v-.6h.2v1l-.5 1.5"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M303.7 205.1a.8.5 69.5 1 0 .6 1.5.8.5 69.5 1 0-.6-1.5zm-1.5.8a.8.5 43.7 1 0 1 1 .8.5 43.7 1 0-1-1z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M308.3 211.8c-.3.4-4.2 3-7.4 2.3-2.3-.4-2.6-1-2.6-1s-.1-.6 2-.8c2.2-.1 6-1 8-.5z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M298.4 213.1c2.5.6 5.2 0 7.3-.5"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M310.8 212.6s-.5.7-1.3.5a3 3 0 0 1-1.2-.5l-.3.3 1.3.4.5.1-.9.6-.7.1v.3l1.2-.3c.2 0 1.4-1 1.4-1"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M306.6 214a.9.6 5.4 1 1 1.7.2.9.6 5.4 1 1-1.7-.1zm.4-2a.9.6 31.2 1 1 1.5 1 .9.6 31.2 1 1-1.5-1z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M309.5 212.2c.2-.3.7-4-1-5.6-1.1-1.2-1.7-1-1.7-1s-.5.1.1 1.5c.7 1.4 1.4 4.2 2.6 5.1z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M306.8 205.6c1.4 1.2 1.9 3.2 2.3 4.7"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M311.4 213s.2-.7-.5-1.2c-.6-.5-1.1-.6-1.1-.6v-.4l1.2.7.4.3c.4.3 0-.8-.2-1l-.4-.7.3-.2.5 1 .2 2"/>
|
||||
<path fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M309.7 209a.9.6 42.7 1 0 1.3 1.1.9.6 42.7 1 0-1.3-1.2zm-1.2 1.5a.9.6 17 1 0 1.7.6.9.6 17 1 0-1.7-.6z" overflow="visible" style="marker:none"/>
|
||||
<path fill="#452c25" d="M319.1 209s-2.3 5.4-1.5 6c0 0 2.4-4.3 4.4-5.8 1.1-1 1.8 0 2-1 0-.8-3-2.1-3-2.1l-1.8 2.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".2" d="M319.1 209s-2.3 5.4-1.5 6c0 0 2.4-4.3 4.4-5.8 1.1-1 1.8 0 2-1 0-.8-3-2.1-3-2.1l-1.8 2.7"/>
|
||||
<path fill="#452c25" d="M310.6 213.1s-3.4 6-2.5 6c.8 0 4.5-7.5 4.5-7.5l-1.3.2-.7 1.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M310.6 213.1s-3.4 6-2.5 6c.8 0 4.5-7.5 4.5-7.5l-1.3.2-.7 1.3z"/>
|
||||
<path fill="#452c25" d="M311.6 211.5s-3.6 5.8-2.7 5.9c1 .1 4.8-7.4 4.8-7.4l-1.3.1-.8 1.4z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M311.6 211.5s-3.6 5.8-2.7 5.9c1 .1 4.8-7.4 4.8-7.4l-1.3.1-.8 1.4z"/>
|
||||
<path fill="#452c25" d="M312.3 210.5s-4 5.4-3.2 5.6c1 .2 5.4-7 5.4-7l-1.3.1-.9 1.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M312.3 210.5s-4 5.4-3.2 5.6c1 .2 5.4-7 5.4-7l-1.3.1-.9 1.3z"/>
|
||||
<path fill="#452c25" d="M313.4 209.5s-4.8 4.9-3.9 5.2c.8.3 6.2-6.2 6.2-6.2l-1.2-.1-1.1 1.1z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M313.4 209.5s-4.8 4.9-3.9 5.2c.8.3 6.2-6.2 6.2-6.2l-1.2-.1-1.1 1.1z"/>
|
||||
<path fill="#452c25" d="M313.6 207.7s-4.2 5.4-3.3 5.6c.9.2 5.5-6.9 5.5-6.9l-1.3.1-1 1.2z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M313.6 207.7s-4.2 5.4-3.3 5.6c.9.2 5.5-6.9 5.5-6.9l-1.3.1-1 1.2z"/>
|
||||
<path fill="#452c25" d="M312.5 212.4s-4 5.5-3.2 5.6c1 .2 5.4-7 5.4-7l-1.3.1-.9 1.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M312.5 212.4s-4 5.5-3.2 5.6c1 .2 5.4-7 5.4-7l-1.3.1-.9 1.3z"/>
|
||||
<path fill="#452c25" d="M314.8 211.3s-2.4 4.5-2.1 4.6c.3.2 3.1-2.5 4.6-5.2 1.4-2.6-2.6.5-2.6.5"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M314.8 211.3s-2.4 4.5-2.1 4.6c.3.2 3.1-2.5 4.6-5.2 1.4-2.6-2.6.5-2.6.5"/>
|
||||
<path fill="#452c25" d="M315 210.8s-2.3 5.5-1.5 6c0 0 3-3.3 3.7-5.9.8-2.6 0-.1 0-.1l-.2-2.9-2 2.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".2" d="M315 210.8s-2.3 5.5-1.5 6c0 0 3-3.3 3.7-5.9.8-2.6 0-.1 0-.1l-.2-2.9-2 2.7"/>
|
||||
<path fill="#452c25" d="M313.8 210.4s-4.7 4.8-3.9 5.1c.9.3 6.3-6.1 6.3-6.1l-1.3-.1-1 1z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M313.8 210.4s-4.7 4.8-3.9 5.1c.9.3 6.3-6.1 6.3-6.1l-1.3-.1-1 1z"/>
|
||||
<path fill="#452c25" d="M314.2 211s-4.7 5-3.9 5.2c.8.3 6.2-6.2 6.2-6.2h-1.2l-1.1 1z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M314.2 211s-4.7 5-3.9 5.2c.8.3 6.2-6.2 6.2-6.2h-1.2l-1.1 1z"/>
|
||||
<path fill="#452c25" d="M314.6 211.8s-4.8 4.9-4 5.2c1 .3 6.3-6.2 6.3-6.2h-1.2l-1.1 1z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M314.6 211.8s-4.8 4.9-4 5.2c1 .3 6.3-6.2 6.3-6.2h-1.2l-1.1 1z"/>
|
||||
<path fill="#452c25" d="M315 205.1s-3.6 4.5-3 5.3c.4.8 3.6-2 4.7-4 1-2-1.7-1.4-1.7-1.4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M315 205.1s-3.6 4.5-3 5.3c.4.8 3.6-2 4.7-4 1-2-1.7-1.4-1.7-1.4"/>
|
||||
<path fill="#452c25" d="M314.8 209.9s-3 5.8-2.2 5.5c.8-.4 3.8-4.7 4.2-5.7.3-1 .2-2 .2-2l-2.3 1.5.2 1.1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M314.8 209.9s-3 5.8-2.2 5.5c.8-.4 3.8-4.7 4.2-5.7.3-1 .2-2 .2-2l-2.3 1.5.2 1.1"/>
|
||||
<path fill="#452c25" d="M314.8 208s2.5-4.6 0 .9-3.4 4.5-3.4 4.5c-.2-.3 2.2-4 2.2-4s1.7-2.8 2.1-3.1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M314.8 208s2.5-4.6 0 .9-3.4 4.5-3.4 4.5c-.2-.3 2.2-4 2.2-4s1.7-2.8 2.1-3.1"/>
|
||||
<path fill="#452c25" d="M317.5 207.4s2.8-4.6 0 .9c-2.8 5.4-3.9 4.5-3.9 4.5-.2-.3 2.5-4 2.5-4s2-2.8 2.4-3.1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M317.5 207.4s2.8-4.6 0 .9c-2.8 5.4-3.9 4.5-3.9 4.5-.2-.3 2.5-4 2.5-4s2-2.8 2.4-3.1"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M316.5 205.5s-3.5 4.5-3 5.2c.5.8 3.7-2 4.7-4s-1.7-1.4-1.7-1.4"/>
|
||||
<path fill="#e8a30e" d="M352.8 251a32.8 37 0 1 1-65.6 0 32.8 37 0 1 1 65.6 0z"/>
|
||||
<path fill="none" stroke="#390" stroke-width=".8" d="M293.7 251c0-17 12-30.2 26.3-30.2s26.3 13.1 26.3 30.3" color="#000" font-family="Sans" font-weight="400" overflow="visible" style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;marker:none"/>
|
||||
<path fill="#007934" stroke="#eee" stroke-width=".1" d="M287.2 253c1 19.5 15.3 35 32.8 35s31.9-15.5 32.8-35h-65.6z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".4" d="M352.8 251a32.8 37 0 1 1-65.6 0 32.8 37 0 1 1 65.6 0z"/>
|
||||
<path fill="#d52b1e" stroke="#000" stroke-width=".1" d="M314.5 225.4c-.3 1.4 0 2.5.7 3.6.6.9 1 1.8.9 2.7a7.9 7.9 0 0 0-.7.5l-5.5-3.7 3.7 5.5a8 8 0 0 0-.2.2 4.9 4.9 0 0 0-3-.3 5 5 0 0 1-3.7-.8 4.5 4.5 0 0 0 3.1 2.1 5 5 0 0 1 2.6 1.3 8 8 0 0 0-.2.8l-6.6 1.3 6.6 1.3v.3a4.9 4.9 0 0 0-2.4 1.9 5 5 0 0 1-3 2c1.3.4 2.5 0 3.6-.7a5 5 0 0 1 2.7-.9l.4.7-3.6 5.6 5.4-3.7.3.2a4.9 4.9 0 0 0-.4 3 5 5 0 0 1-.7 3.6 4.5 4.5 0 0 0 2-3.1 4.9 4.9 0 0 1 1.4-2.5l.8.2 1.3 6.5 1.3-6.5h.3a4.9 4.9 0 0 0 1.8 2.3 5 5 0 0 1 2.1 3.1 4.4 4.4 0 0 0-.7-3.6 4.9 4.9 0 0 1-.9-2.8l.7-.4 5.5 3.7-3.7-5.5.2-.3c1 .5 2 .6 3 .4a5 5 0 0 1 3.7.7 4.5 4.5 0 0 0-3.1-2 4.9 4.9 0 0 1-2.6-1.4l.2-.8 6.6-1.3-6.6-1.2a7.9 7.9 0 0 0 0-.4 4.9 4.9 0 0 0 2.4-1.8 5 5 0 0 1 3-2 4.5 4.5 0 0 0-3.6.7 4.9 4.9 0 0 1-2.7.8 7.9 7.9 0 0 0-.4-.7l3.7-5.5-5.5 3.7a8 8 0 0 0-.3-.2c.5-1 .6-2 .4-3a5 5 0 0 1 .7-3.6 4.5 4.5 0 0 0-2 3 5 5 0 0 1-1.4 2.6 8 8 0 0 0-.8-.2l-1.3-6.5-1.2 6.5h-.4a4.9 4.9 0 0 0-1.8-2.3 5 5 0 0 1-2-3.1z" overflow="visible" style="marker:none"/>
|
||||
<use width="330" height="330" fill="#fcbf49" stroke-width="1.1" transform="rotate(22.5 -417.9 955.8) scale(.14262)"/>
|
||||
<use width="330" height="330" fill="#fcbf49" stroke-width="1.1" transform="matrix(-.14262 0 0 .14262 334 232.7)"/>
|
||||
<path d="M325.9 236.7c-1.7-1.4-3.8-1.6-4.9-.6-.8 1.1-.8 2.4.2 3.8a.5.5 0 0 0-.3.2 4.9 4.9 0 0 1-.3-4.1c1.5-1.3 3.7-1.4 5.2.7"/>
|
||||
<path d="M323.3 236.3c-1 0-1.2.2-1.6.5-.4.4-.6.3-.7.4 0 0 0 .3.1.2.2 0 .5-.2.9-.6.4-.3.8-.3 1.3-.3 1.3 0 2 1 2.1 1 .2 0-.7-1.2-2.1-1.2"/>
|
||||
<path d="M325 237.5c-1-1-2.7-1-3.4 0h.2c.8-1 2.5-.6 2.6 0"/>
|
||||
<circle cx="323.1" cy="237.4" r=".6"/>
|
||||
<path d="M321.6 237.6c.7.6 2.2.7 3.3-.1h-.5c-.7.7-1.8.6-2.5 0"/>
|
||||
<path d="M325 237.8c-1.2 1-2.4.9-3.1.5-.7-.5-.7-.6-.6-.6l.8.4c.6.3 1.5.3 2.9-.2m-3.5 2a.4.4 0 1 1-.6.5c0 .1-.3.6-.9.6h-.1l.1.2c.1 0 .6 0 .9-.2a.6.6 0 1 0 .6-1m.9 3c-.7-.5-1-1-1.7-1a2 2 0 0 0-.7.1h-.1l.1.2c.3 0 .7-.3 1.2 0l1.2.7m-.3 0c-1.4-.5-1.7-.2-2.1-.2h-.1l.1.3c.6 0 .9-.4 2.1-.1"/>
|
||||
<path d="M322.4 243c-1.6-.2-1.1.8-2.4.8h-.1l.1.2c1.6 0 .9-.9 2.4-1m-8.2-6.3c1.6-1.4 3.7-1.6 4.8-.6.8 1.1.8 2.4-.2 3.8a.5.5 0 0 1 .3.2 5 5 0 0 0 .3-4.1c-1.5-1.3-3.7-1.4-5.2.7"/>
|
||||
<path d="M316.7 236.3c1 0 1.2.2 1.6.5.4.4.6.3.7.4 0 0 0 .3-.1.2a4.1 4.1 0 0 1-.9-.6c-.4-.3-.8-.3-1.3-.3-1.3 0-2 1-2.1 1-.2 0 .7-1.2 2.1-1.2"/>
|
||||
<path d="M315 237.5c1-1 2.7-1 3.4 0h-.2c-.8-1-2.5-.6-2.6 0"/>
|
||||
<circle cx="-316.9" cy="237.4" r=".6" transform="scale(-1 1)"/>
|
||||
<path d="M318.4 237.6c-.7.6-2.2.7-3.3-.1h.5c.7.7 1.8.6 2.5 0"/>
|
||||
<path d="M315 237.8c1.2 1 2.4.9 3.1.5.8-.5.8-.6.6-.6l-.8.4c-.5.2-1.5.3-2.9-.2m3.5 2a.4.4 0 1 0 .6.5c0 .1.3.6.9.6h.1l-.1.2c-.1 0-.6 0-.9-.2a.6.6 0 1 1-.6-1m-.9 3c.7-.5 1-1 1.7-1l.7.1h.1l-.1.2c-.3 0-.7-.3-1.2 0l-1.2.7m.3 0c1.4-.5 1.7-.2 2.1-.2h.1l-.1.3c-.6 0-.9-.4-2.1-.1"/>
|
||||
<path d="M317.6 243c1.6-.2 1.1.8 2.4.8h.1l-.1.2c-1.6 0-.9-.9-2.4-1"/>
|
||||
<path fill="#007934" stroke="#000" stroke-linecap="round" stroke-width=".1" d="M323.2 258.4c1.6.2 3.3.2 4.7-.3a9.9 9.9 0 0 1 4.2-.6c0-.2.5-.3.2-.5-.5-.3-1.2-.3-1.8-.6-1-.5-1.7-1.3-2.7-2-.1 0-.6-.3-.6-.5 2.2 3.2 7.5 1.5 12 1.2.4.1 1.5-.2 2.4-.5 1-.4 3.6 0 4.3-.5l-1.3-1c-.6-.8-2.3-.7-3-1.5-1.3-1.5-3.3-1.9-4.9-3-.3-.3-1-.2-1.6-.3-.6-.6 0-.5-5-4.7-4.5-1.8-4.2-3.2-7-4.3-1-.5-1.9-1.4-2.7-1.1a30 30 0 0 0-6.3 3c-1.2.6-2.7 2-3.8 2.8-.2.2-3.4 2.9-7 4.8a115 115 0 0 1-9.2 4.8c8-.4-7.3 2.3 29.1 4.8z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M303.3 249c2-1 10-5.3 12.4-8.4-.4 0 .6 1 .5 1.4.8 0 .4-1 1-1 .5 0 .9-.1 1.3-.3.5 0 .2.2.2.4-.7 1.2-2 2-3.2 2.9l.2.4c.4 0 .9 0 1.1-.2l.1-.3c.4.1.3.5.1.7-.3.6-1.4.5-1.8 1a6.2 6.2 0 0 1-1.5 1.7c.5-.4 1-1 1.7-1 1 0 1.3-.7 2.2-.9.9-.1 1.5-.9 2.2-1.4-.3.4-.9.7-.7 1.2a.6.6 0 0 0 .6.2c-.7.8-2 1.4-2.4 2.4-.4-.2-.7.2-1 .2-.4.1-.3.8-.6 1-1.2.7-1.8 1.8-2.3 2.7l-1.3.7c-.7.3-4.6 3.4-4.7 3-.3-2.1-4.3 1.6-13.3-1.6m30.6-.1-.2-.2c.1-.3-.5-.4-.5-.7 1 0 1.8 1.2 2.5.5.1-.1-.3-.4.4-.6 0 0-.2-.1-.1-.2h-.8l-.8-.3c-.3-.1-.5-.5 0-.6 1-.1 1.9.5 2.6.2.6-.3 1.1-.3 1.7-.5.3-.1 1.2 0 .9.2-.2.2-.7.1-1 .2-.5.1-1 .4-1.4.6.3 0 .2.3.7.2a6 6 0 0 1 2-.4v-.5h.3c-.3-.5.6-.2 1-.6l.1.1c-.5.2-.3.5-.4.8 0 0-.3 0-.2.2.2.2.2-.2.5 0h.6c.3 0 .7-.1.5-.4-.3-.2-.6-.5-.6-.8l-.1-.1c.5 0 1 .2 1.1.4.3.3.3.6.8.7.8.2.7-.2.7-.6.7 0 1.6.3 1.4.6 0 .3-.6.5-1 .5s-.2.3-.4.3c-.4 0-.9 0-1 .2-.2.2 0 .7.3.9.4.2 1.2 0 1.8 0 .1-.3.5-.4.9-.6.4-.3-.2-.5-.5-.7-.3 0 0-.1 0-.3.3-.3.9 0 1-.2.1-.3-.1-.6.1-.8.2-.1.5.1.4.3l.7-.2c.3 0 .5.3.4.4-.5.2-.8.4-.7.8 0 .2-.5.3-.3.5.4.3.4.5.5.9.2.3 1 .4 1.6.3-.2-.7 1.4-.4 2-.5.1 0 .1-.1 0-.2-.3-.2-.3-.3-.3-.6l-.1-.1c1 .3 2.8.8 3.6 1.4-1 .2-2.8-.2-3.8 0a15 15 0 0 1-3.7.6c-.5 0-1-.3-1.6-.3m-11.3-.7-.4-.1"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M321.2 259.1c2 0 2.2 1.4 3.5.1 1.1.2 2.2-.2 2.2-.3 2.7.6 11.1-.2 10.6-.8-.9-1-2.3-1.4-3.4-2.2l-1.1-.4c-.7-.2-1.5 0-2-.3l-2.6-1.5c-.5-.4-.7-1-1.2-1.4-.6-.4-1.4-.5-2-.7-.9-.4-1.4-1.2-2.2-1.9l-1.1-.4c-.7-.3-1.2-1.1-1.9-1-1 .2-1.7 1-2.8 1.6-1 .4-1.4 1.1-2.2 1.6-.2.2-2.6 1.8-5.3 2.9a72.6 72.6 0 0 1-6.6 2.5s2.4 1.7 8 1.5l3.4 1 1.9-.3h4.8z"/>
|
||||
<path fill="#007934" stroke="#000" stroke-width=".1" d="M309.8 254.8c1.2-.6 6-2.9 7.4-4.5-.1 0 .5.5.4.7.5 0 .2-.4.6-.5l.8-.1c.3 0 .1 0 .1.2-.4.6-1.3 1-2 1.5l.2.2h.7v-.3c.3.1.2.3.1.4-.2.4-.9.3-1.1.6a3 3 0 0 1-1 .9c.4-.2.7-.5 1.1-.5.6 0 .8-.4 1.3-.5.6-.1 1-.5 1.4-.8-.2.2-.5.4-.4.7l.4.1c-.4.4-1.2.7-1.5 1.2l-.6.1c-.3.1-.2.5-.4.6-.7.3-1 1-1.4 1.4l-.8.4c-.4.2-2.8 1.8-2.8 1.6-.2-1.1-2.6.5-8-1.2"/>
|
||||
<path fill="#00a6de" stroke="#000" stroke-width=".1" d="M320 214.2c-18.1 0-32.8 16.5-32.8 36.9S301.9 288 320 288s32.8-16.5 32.8-37c0-20.3-14.7-36.9-32.8-36.9zm0 8.2c13.2 0 24.7 12.3 24.7 28.7s-11.5 28.6-24.7 28.6-24.7-12.2-24.7-28.6c0-16.4 11.5-28.7 24.7-28.7z" color="#000" font-family="Sans" font-weight="400" overflow="visible" style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;marker:none"/>
|
||||
<path fill="#e8a30e" d="M324.7 266.8c0 .2 0 .2-.4.3-.4 0-.5 0-.5-.2s.1-.2.5-.2c.3-.1.4-.1.4 0z"/>
|
||||
<path fill="#e8a30e" d="m324.8 266.8-.5.2h-.5c0-.2.2-.2.5-.3h.5zm-2.8 9c.8-2.2 1-3.8-.2-6 2-1.9 3.3-1.2 4.6 0-1.2 2.3-1 4-.2 6a4 4 0 0 1-4.2 0z"/>
|
||||
<path fill="#e8a30e" d="M324 268.6v7.7h.1v-7.7z"/>
|
||||
<path fill="#e8a30e" d="M324.4 268.6a44.6 44.6 0 0 0-.3 7.7c0-2.9.2-5.3.4-7.6zm.7-2.4c-.4.4-.6.4-.4 1 .4-.3.4-.5.4-1z"/>
|
||||
<path fill="#e8a30e" d="M324.3 266.4c.2.3.6.4.3 1-.4-.3-.3-.4-.3-1z"/>
|
||||
<path fill="#e8a30e" d="M324.3 267c.2.3.5.3.3.9-.3-.3-.4-.3-.4-.8z"/>
|
||||
<path fill="#e8a30e" d="M324.2 267.4c.2.2.5.4.3 1-.4-.4-.3-.4-.3-1z"/>
|
||||
<path fill="#e8a30e" d="M324 267.9c.3.2.7.3.4 1-.4-.4-.2-.5-.4-1z"/>
|
||||
<path fill="#e8a30e" d="M324 268.4c.2.2.6.3.4 1-.3-.4-.4-.4-.4-1zm1.3-1.7c-.2.1-.6.1-.6.8.5-.3.5-.3.6-.8z"/>
|
||||
<path fill="#e8a30e" d="M325.3 267.1c-.2.2-.7.2-.7.7.6-.2.5-.2.7-.7z"/>
|
||||
<path fill="#e8a30e" d="M325.2 267.6c-.2.1-.6 0-.7.7.6-.3.6-.2.7-.8z"/>
|
||||
<path fill="#e8a30e" d="M325.2 268.1c-.2 0-.7 0-.7.7.4-.1.4-.3.7-.7z"/>
|
||||
<path fill="#e8a30e" d="M325 268.6c-.4.1-.5 0-.6.7.5-.3.4-.2.5-.7zm.2.3c-.7 2.1-.8 4-.7 7.4h.1c0-3.4.1-5.2.8-7.3a2.8 2.8 0 0 0-.1 0zm1.2-2.2c-.4.3-.6.2-.5.8.4-.1.4-.3.5-.8z"/>
|
||||
<path fill="#e8a30e" d="M325.6 266.8c.2.2.5.4.1 1-.3-.4-.2-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M325.4 267.4c.3.3.5.3.2.8-.2-.3-.3-.3-.2-.8z"/>
|
||||
<path fill="#e8a30e" d="M325.3 267.7c.1.3.4.4.1 1-.3-.4-.3-.4-.1-1z"/>
|
||||
<path fill="#e8a30e" d="M325 268.1c.3.3.6.5.3 1-.4-.4-.2-.5-.3-1z"/>
|
||||
<path fill="#e8a30e" d="M324.9 268.6c.2.3.5.5.2 1-.3-.4-.3-.4-.2-1zm1.6-1.4c-.2.2-.6 0-.7.7.5-.2.5-.2.7-.6z"/>
|
||||
<path fill="#e8a30e" d="M326.4 267.7c-.2 0-.6 0-.8.5.6-.1.6 0 .8-.5z"/>
|
||||
<path fill="#e8a30e" d="M326.3 268c-.3.2-.7 0-.9.7.7-.2.6-.2.9-.6z"/>
|
||||
<path fill="#e8a30e" d="M326.1 268.6c-.2 0-.6-.2-.8.5.4 0 .4-.2.8-.5z"/>
|
||||
<path fill="#e8a30e" d="M325.8 269c-.3 0-.5 0-.7.6.5-.2.5-.1.7-.6zm.1.4c-1 1.9-1.1 3.6-.7 6.8l.2-.1c-.4-3-.2-4.7.6-6.6zm1.6-2.2c-.5.2-.7.2-.7.8.4-.2.5-.4.7-.8z"/>
|
||||
<path fill="#e8a30e" d="M326.7 267.2c.1.3.4.5 0 1-.3-.5-.2-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M326.4 267.8c.2.2.4.4 0 .8 0-.4-.2-.4 0-.9z"/>
|
||||
<path fill="#e8a30e" d="M326.2 268c.1.3.4.5 0 1-.3-.4-.2-.4 0-1z"/>
|
||||
<path fill="#e8a30e" d="M326 268.5c0 .3.4.5 0 1-.3-.5 0-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M325.7 268.9c.2.3.5.5 0 1-.1-.4-.2-.5 0-1zm1.8-1.1c-.2 0-.6-.1-.8.5.6-.1.5 0 .8-.5z"/>
|
||||
<path fill="#e8a30e" d="M327.3 268.2c-.2 0-.6-.1-.8.4.6 0 .6 0 .8-.4z"/>
|
||||
<path fill="#e8a30e" d="M327.1 268.5c-.2 0-.6 0-.8.5.6 0 .5 0 .8-.5z"/>
|
||||
<path fill="#e8a30e" d="M327 269c-.3 0-.7-.3-1 .4.5 0 .5-.1 1-.4zm-.5.4c-.3 0-.4 0-.7.5.5-.1.5 0 .7-.5zm-3-.7c.2 2.4.4 4.8.4 7.6h.1c.1-2.9 0-5.3-.4-7.6zm-.6-2.6c.4.4.5.4.4 1-.4-.3-.4-.5-.4-1z"/>
|
||||
<path fill="#e8a30e" d="M323.7 266.4c-.3.2-.6.4-.4 1 .4-.3.4-.4.4-1z"/>
|
||||
<path fill="#e8a30e" d="M323.7 267c-.3.3-.5.3-.3.8.2-.3.3-.2.3-.7z"/>
|
||||
<path fill="#e8a30e" d="M323.8 267.4c-.2.2-.5.3-.3 1 .4-.4.3-.4.3-1z"/>
|
||||
<path fill="#e8a30e" d="M324 267.9c-.3.2-.7.3-.5 1 .5-.4.2-.5.4-1z"/>
|
||||
<path fill="#e8a30e" d="M324 268.4c-.3.2-.6.3-.4.9.3-.3.4-.4.4-.9zm-1.3-1.8c.2.2.6.2.6.8-.5-.3-.5-.2-.6-.8z"/>
|
||||
<path fill="#e8a30e" d="M322.7 267.1c.2.1.6.1.6.7-.5-.3-.5-.2-.6-.7z"/>
|
||||
<path fill="#e8a30e" d="M322.8 267.5c.2.1.6.1.6.8-.5-.3-.5-.3-.6-.8z"/>
|
||||
<path fill="#e8a30e" d="M322.8 268c.2.1.7 0 .7.8-.4-.1-.4-.4-.7-.7z"/>
|
||||
<path fill="#e8a30e" d="M323 268.5c.3.2.5.1.5.8-.4-.3-.4-.3-.5-.8zm-.2.5a3.8 3.8 0 0 0-.2.1c.7 2 1 3.9.9 7.2h.1a19 19 0 0 0-.8-7.3zm-1.2-2.4c.4.3.5.3.5.8-.4-.1-.4-.3-.5-.8z"/>
|
||||
<path fill="#e8a30e" d="M322.4 266.7c-.2.3-.5.4-.2 1 .3-.4.3-.4.2-1z"/>
|
||||
<path fill="#e8a30e" d="M322.6 267.3c-.3.3-.6.4-.2.9.2-.4.3-.4.2-.9z"/>
|
||||
<path fill="#e8a30e" d="M322.7 267.6c-.2.3-.5.5-.1 1 .3-.4.2-.4.1-1z"/>
|
||||
<path fill="#e8a30e" d="M323 268.1c-.3.3-.6.4-.3 1 .4-.5.1-.5.2-1z"/>
|
||||
<path fill="#e8a30e" d="M323 268.6c-.1.2-.5.4-.1 1 .2-.4.3-.5.2-1zm-1.5-1.5c.2.1.6 0 .7.7-.6-.2-.5-.2-.7-.7z"/>
|
||||
<path fill="#e8a30e" d="M321.6 267.6c.2 0 .6 0 .7.5-.5-.1-.5 0-.7-.5z"/>
|
||||
<path fill="#e8a30e" d="M321.7 268c.2 0 .7 0 .8.6-.6-.2-.6-.2-.8-.7z"/>
|
||||
<path fill="#e8a30e" d="M321.9 268.5c.2 0 .6-.2.8.6-.4 0-.5-.3-.8-.6z"/>
|
||||
<path fill="#e8a30e" d="M322.2 269c.3 0 .4 0 .6.5-.5-.2-.4-.1-.6-.6zm0 .5a4.1 4.1 0 0 0-.2 0c.9 2 1 3.6.7 6.6h.2c.3-3 .2-4.6-.8-6.6zm-1.7-2.5c.4.3.6.2.6.8-.4-.1-.5-.3-.6-.8z"/>
|
||||
<path fill="#e8a30e" d="M321.3 267c-.1.3-.4.6 0 1 .3-.4.2-.4 0-1z"/>
|
||||
<path fill="#e8a30e" d="M321.6 267.6c-.2.3-.5.4-.1.9.1-.4.3-.4 0-.9z"/>
|
||||
<path fill="#e8a30e" d="M321.8 268c-.2.2-.4.4 0 1 .2-.5.2-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M322 268.4c-.1.3-.4.5 0 1 .3-.5 0-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M322.3 268.8c-.2.3-.5.5-.1 1 .2-.4.2-.5 0-1zm-1.8-1.2c.2 0 .6 0 .8.5-.6 0-.6 0-.8-.5z"/>
|
||||
<path fill="#e8a30e" d="M320.6 268c.3 0 .7 0 .9.5-.6-.1-.6 0-.9-.5z"/>
|
||||
<path fill="#e8a30e" d="M320.8 268.4c.3 0 .7 0 1 .5-.7-.1-.7 0-1-.5z"/>
|
||||
<path fill="#e8a30e" d="M321 268.9c.3 0 .7-.3 1 .5-.5 0-.5-.3-1-.5z"/>
|
||||
<path fill="#e8a30e" d="M321.4 269.3c.3 0 .5 0 .7.5-.5-.1-.4 0-.7-.5zm2.2-3.2c.3.4.5.4.3 1-.4-.3-.3-.5-.3-1z"/>
|
||||
<path fill="#e8a30e" d="M324.3 266.4c-.2.2-.5.3-.4 1 .5-.3.4-.4.4-1z"/>
|
||||
<path fill="#e8a30e" d="M324.4 267c-.3.2-.6.3-.4.8.2-.3.3-.2.4-.7z"/>
|
||||
<path fill="#e8a30e" d="M324.4 267.4c-.2.2-.5.3-.4 1 .4-.4.4-.4.4-1z"/>
|
||||
<path fill="#e8a30e" d="M324.5 268c-.3.1-.6.2-.5.8.5-.3.3-.4.5-.9z"/>
|
||||
<path fill="#e8a30e" d="M324.5 268.4c-.2.2-.6.3-.4.9.3-.3.4-.3.4-.9zm-1.2-1.8c.2.2.6.2.6.8-.5-.3-.5-.3-.6-.8z"/>
|
||||
<path fill="#e8a30e" d="M323.3 267c.2.2.6.2.6.8-.5-.3-.5-.3-.6-.8z"/>
|
||||
<path fill="#e8a30e" d="M323.4 267.4c.2.2.6.2.6.9-.5-.4-.5-.3-.6-.9z"/>
|
||||
<path fill="#e8a30e" d="M323.4 268c.2.1.7 0 .6.8-.4-.2-.3-.4-.6-.8z"/>
|
||||
<path fill="#e8a30e" d="M323.6 268.5c.2.1.4.1.4.8-.4-.4-.4-.3-.4-.8zm-.4.3a2.7 2.7 0 0 0-.1 0c.5 2.5.7 4.7.6 7.5h.2c0-2.5 0-5-.7-7.5zm-1-2.4c.4.4.6.3.5 1-.4-.3-.4-.5-.5-1z"/>
|
||||
<path fill="#e8a30e" d="M323 266.6c-.2.2-.5.4-.2 1 .3-.4.3-.4.2-1z"/>
|
||||
<path fill="#e8a30e" d="M323.1 267.2c-.2.2-.5.3-.2.8.2-.3.3-.3.2-.8z"/>
|
||||
<path fill="#e8a30e" d="M323.3 267.5c-.2.3-.5.4-.2 1 .3-.3.3-.4.2-1z"/>
|
||||
<path fill="#e8a30e" d="M323.5 268c-.3.3-.6.4-.3 1 .4-.4.2-.5.3-1z"/>
|
||||
<path fill="#e8a30e" d="M323.6 268.5c-.2.3-.6.4-.3 1 .3-.4.3-.5.3-1zM322 267c.3 0 .7 0 .8.6-.6-.2-.6-.1-.8-.6z"/>
|
||||
<path fill="#e8a30e" d="M322.1 267.4c.2.1.7 0 .8.6-.6-.2-.6-.1-.8-.6z"/>
|
||||
<path fill="#e8a30e" d="M322.3 267.8c.2.1.6 0 .7.7-.6-.2-.6-.2-.7-.7z"/>
|
||||
<path fill="#e8a30e" d="M322.4 268.3c.2 0 .6-.1.8.7-.5-.1-.5-.3-.8-.7z"/>
|
||||
<path fill="#e8a30e" d="M322.7 268.8c.3 0 .4 0 .6.6-.5-.2-.5-.1-.6-.6zm-.8.9c.6 1.4.8 2.6.7 3.7l-.3 2.5h.1c.6-2.5.5-4.4-.5-6.2z"/>
|
||||
<path fill="#e8a30e" d="m322.5 269.2-.1.1c.8 2.1.9 4 .7 7h.1c.2-3 .1-5-.7-7zm-1.4-2.4c.4.3.5.2.5.8-.4-.1-.4-.3-.5-.8z"/>
|
||||
<path fill="#e8a30e" d="M321.8 266.9c-.1.2-.4.4 0 1 .3-.4.2-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M322 267.4c-.1.3-.4.4 0 1 .1-.4.2-.4 0-1z"/>
|
||||
<path fill="#e8a30e" d="M322.3 267.8c-.2.2-.5.4 0 1 .2-.5.1-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M322.5 268.2c-.2.3-.5.5 0 1 .2-.5 0-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M322.7 268.7c-.1.2-.5.5-.1 1 .2-.4.3-.5.1-1zm-1.7-1.3c.2 0 .6 0 .8.5-.6-.1-.6 0-.8-.5z"/>
|
||||
<path fill="#e8a30e" d="M321.1 267.8c.3 0 .7 0 .8.5-.5-.1-.5 0-.8-.5z"/>
|
||||
<path fill="#e8a30e" d="M321.3 268.1c.2.1.7 0 .9.6-.6-.1-.6 0-.9-.6z"/>
|
||||
<path fill="#e8a30e" d="M321.5 268.7c.2 0 .6-.3.9.5-.5 0-.5-.2-.9-.5z"/>
|
||||
<path fill="#e8a30e" d="M321.9 269c.3.1.4 0 .6.6-.4-.1-.4 0-.6-.5zm-2-1.6c.5.2.7.2.8.7-.4 0-.5-.2-.7-.7z"/>
|
||||
<path fill="#e8a30e" d="M320.7 267.4c0 .3-.3.5.2 1 .2-.5.1-.5-.2-1z"/>
|
||||
<path fill="#e8a30e" d="M321 267.9c0 .3-.3.5.1.9.1-.4.2-.4 0-.9z"/>
|
||||
<path fill="#e8a30e" d="M321.3 268.2c0 .3-.3.5.1 1 .2-.5.2-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M321.6 268.6c0 .3-.4.5.1 1 .2-.6 0-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M322 269c-.2.3-.5.6 0 1 .1-.4.2-.5 0-1zm-2-1c.2 0 .6-.1.9.4-.6 0-.6 0-1-.4z"/>
|
||||
<path fill="#e8a30e" d="M320.2 268.4c.2 0 .6-.2.9.4-.6 0-.6 0-.9-.4z"/>
|
||||
<path fill="#e8a30e" d="M320.4 268.7c.3 0 .7-.1 1 .4-.6 0-.6 0-1-.4z"/>
|
||||
<path fill="#e8a30e" d="M320.7 269.2c.2 0 .6-.3 1 .4-.5 0-.5-.2-1-.4z"/>
|
||||
<path fill="#e8a30e" d="M321.1 269.5c.3 0 .5 0 .8.5-.5 0-.5 0-.8-.5zm3.8-.7a25.9 25.9 0 0 0-.7 7.5 2.5 2.5 0 0 0 .2 0c0-2.8 0-5 .7-7.4a2.8 2.8 0 0 0-.2-.1zm1-2.3c-.4.3-.5.3-.5.9.4-.2.5-.4.5-.9z"/>
|
||||
<path fill="#e8a30e" d="M325.1 266.6c.2.3.5.5.2 1-.3-.4-.3-.4-.2-1z"/>
|
||||
<path fill="#e8a30e" d="M325 267.3c.3.2.5.3.2.8-.2-.3-.3-.3-.2-.9z"/>
|
||||
<path fill="#e8a30e" d="M324.9 267.6c.2.2.5.4.2 1-.4-.4-.3-.5-.2-1z"/>
|
||||
<path fill="#e8a30e" d="M324.7 268c.2.3.5.5.2 1-.4-.4-.1-.5-.2-1z"/>
|
||||
<path fill="#e8a30e" d="M324.5 268.5c.2.3.6.5.3 1-.3-.4-.3-.4-.3-1zm1.6-1.5c-.2.2-.6 0-.7.7.5-.2.5-.2.7-.7z"/>
|
||||
<path fill="#e8a30e" d="M326 267.5c-.2 0-.6 0-.7.6.5-.2.5-.1.7-.6z"/>
|
||||
<path fill="#e8a30e" d="M325.9 267.9c-.2 0-.7 0-.8.6.6-.2.6-.1.8-.6z"/>
|
||||
<path fill="#e8a30e" d="M325.7 268.4c-.2 0-.6-.2-.7.6.4 0 .4-.3.7-.6z"/>
|
||||
<path fill="#e8a30e" d="M325.4 268.8c-.2.1-.4 0-.5.7.4-.2.4-.2.5-.7zm.2.4c-.9 2.1-1 4.1-.8 7h.2c-.2-3-.1-4.9.7-7zm1.5-2.3c-.5.3-.6.2-.6.8.4-.1.4-.3.6-.8z"/>
|
||||
<path fill="#e8a30e" d="M326.3 267c.1.2.4.5 0 1-.3-.5-.2-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M326 267.5c.3.3.5.5.1 1-.1-.5-.2-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M325.9 267.8c.1.3.4.5 0 1-.3-.4-.2-.4 0-1z"/>
|
||||
<path fill="#e8a30e" d="M325.6 268.3c.2.3.5.5.1 1-.3-.5 0-.5-.1-1z"/>
|
||||
<path fill="#e8a30e" d="M325.4 268.7c.2.3.5.5.1 1-.2-.4-.3-.4-.1-1zm1.7-1.2c-.2.1-.6 0-.8.5.6 0 .6 0 .8-.5z"/>
|
||||
<path fill="#e8a30e" d="M327 268c-.2 0-.6-.1-.8.4.6-.1.5 0 .8-.5z"/>
|
||||
<path fill="#e8a30e" d="M326.8 268.3c-.2 0-.7 0-.8.5.6-.1.5 0 .8-.5z"/>
|
||||
<path fill="#e8a30e" d="M326.6 268.8c-.2 0-.6-.3-.8.5.4 0 .4-.3.8-.5z"/>
|
||||
<path fill="#e8a30e" d="M326.3 269.2c-.4 0-.5 0-.7.5.4-.1.4 0 .6-.5zm0 .5c-1.1 2-1 4-.6 6.3h.2l-.3-2.9a6 6 0 0 1 .8-3.3h-.1zm1.9-2c-.5.1-.7 0-.8.6.5 0 .5-.2.8-.7z"/>
|
||||
<path fill="#e8a30e" d="M327.4 267.5c0 .3.3.6-.2 1-.2-.5-.1-.5.2-1z"/>
|
||||
<path fill="#e8a30e" d="M327 268c.2.3.4.5 0 .9-.1-.4-.2-.4 0-.9z"/>
|
||||
<path fill="#e8a30e" d="M326.8 268.3c.1.3.3.5-.1 1-.2-.5-.2-.5.1-1z"/>
|
||||
<path fill="#e8a30e" d="M326.5 268.7c0 .3.4.6-.1 1-.2-.6 0-.5 0-1z"/>
|
||||
<path fill="#e8a30e" d="M326.2 269c.1.4.4.7 0 1-.2-.4-.2-.4 0-1zm2-.8c-.3 0-.6-.2-1 .4.6 0 .6 0 1-.4z"/>
|
||||
<path fill="#e8a30e" d="M327.9 268.6c-.2 0-.6-.2-.9.3.6 0 .6 0 .9-.3z"/>
|
||||
<path fill="#e8a30e" d="M327.7 268.9c-.3 0-.7-.2-1 .4.7 0 .6 0 1-.4z"/>
|
||||
<path fill="#e8a30e" d="M327.4 269.4c-.2 0-.6-.4-1 .3.5 0 .6-.2 1-.3z"/>
|
||||
<path fill="#e8a30e" d="M327 269.7c-.3 0-.5-.1-.8.4.5 0 .5 0 .8-.4zm-3.5 2.7h1.1c.7 0 1.2.2 1.2.4s-.5.3-1.2.3h-1.1c-.7 0-1.3-.2-1.3-.4s.6-.3 1.3-.3z"/>
|
||||
<path fill="#e8a30e" d="m322.7 272.4-.4.6a.3.3 0 0 0 .2 0h.2l.4-.6h-.4zm.9 0-.4.6h.4l.4-.6h-.4zm.9 0-.4.7h.4l.4-.7h-.4zm.8 0-.3.7h.4l.3-.6a.3.3 0 0 0-.2 0h-.2z"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="m316.5 268.8.5 2.7.2.2v1.1c.3.5.3 1.1.5 1.6l.3.6h.4l.1.2-.2.2h-.6l-.3-.1v-.3h-.2l-.1-.6-.8-1c0-.1 0-.4-.2-.5l-.3-.3c-.5-1-1-3-1-3m-6.4-1 1.8.4-.5 2.6c-.3.8-.3.9-.2 1 .2.5.4 1.2 1.1 2.3l.6.4.5.3h.5l.1-.2c0-.1-.3 0-.5-.2 0-.3-.5-.8-.5-1.2-.3-.7-.2-.7-.2-1.5l.5-1.6c.2-.5.5-1.4.5-2l-.8-1.7-.5-.7m-1.6-1.1c-2.9 1-1.7 3.5-.9 3.6m9.2-8.1.4-1v-.4l-.7.9"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M319.2 262.4c.2 0 .4.1.4 0v-.6c-.6-.4-1-.4-1-.7v-.2c0-.2-.8-.3-1-.4l-.4-.2h-.2c-.8 0-1.1.7-1.2 1.2 0 0-.2 2.1-.5 3a.7.7 0 0 1-.2.3l-.2.2c-2-.2-3.4-.2-4.2-.2-.8 0-1.8.7-1.8.7s-1 .6-1.1 1.6c-.1.3 0 .7.1 1 1 2.7 1.8 0 2.1.1h.4c.5 0 1.4 1.5 2.7 1.8 4 .9 5-1.2 5-5.8v-.2l.2-.4v-.8l1-.2.2-.1"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="m317.3 261 .4-1v-.4l-.9 1m-8.9 7.6c.3.8.7 1.5.7 1.8 0 .4-.3.6-.3.7h-.2l-.2.6a1.3 1.3 0 0 0 0 .6c0 .7.4 2.2.4 2.3 0 0 .3 0 .3.2v1.2c0 .2.3.3.3.3h.6l-.4-.4a.4.4 0 0 1 0-.2c0-.2.2-.4.3-.5v-.3l-.1-.2a8.3 8.3 0 0 1-.1-.9v-1.1l.2-.2.1-.2 1-.6.8-1 .2-.5a.5.5 0 0 0 0-.2 3.8 3.8 0 0 0-.3-.9 3.2 3.2 0 0 0-.6-.8m5.9 1.8c-.5.4-1.8.7-1.8 1 0 0 0 1.6-.2 2.2l-.3.6-.2.7-.3 1v.3l.4.3h-.4l-.6-.2V274l-.2-1.4.1-1-.1-3.6m4.7-5.4c.2.2.6.4 1.3.1.2.1.3.2.6-.2m-.3-.5h.2s.1 0 0 0c0 0 0-.1 0 0h-.2z"/>
|
||||
<path d="M317.8 261.4c.2.3.4.3.6.1-.2-.3-.4-.1-.5-.1h-.1z"/>
|
||||
<path fill="#e7e7e7" fill-rule="evenodd" stroke="#000" stroke-width=".1" d="M329.1 272.9a2 2 0 0 0 0 .7v.8a2 2 0 0 0 0 .7 2 2 0 0 0 0 .7c.2.2 1 .2 1.2 0a2.2 2.2 0 0 0 0-.7v-.7a2 2 0 0 0 0-.7v-.8a2.3 2.3 0 0 0 0-.8v-.7a2.2 2.2 0 0 0 0-.8v-.8a2.4 2.4 0 0 0 0-.8v-.7a2.2 2.2 0 0 0 0-.8 1.9 1.9 0 0 0 0-.8 2.5 2.5 0 0 0 0-.8 2.3 2.3 0 0 0 0-.8 3.3 3.3 0 0 0 0-.8 2.9 2.9 0 0 0 0-.7v-.8a2.6 2.6 0 0 0 0-.8 2.7 2.7 0 0 0 0-.8v-.8a2.3 2.3 0 0 0 0-.8v-.7a2 2 0 0 0 0-.3h-.9v1a2.3 2.3 0 0 0 0 .8v.8a2.7 2.7 0 0 0 0 .8 2.6 2.6 0 0 0 0 .8 3 3 0 0 0 0 .7l-.1.8v.8a2.4 2.4 0 0 0 0 .8 2.5 2.5 0 0 0 0 .8 1.9 1.9 0 0 0 0 .8c-.1.3-.1.5 0 .8v.7a2.4 2.4 0 0 0-.1.8 2.6 2.6 0 0 0 0 .8 2.2 2.2 0 0 0 0 .8 2 2 0 0 0 0 .7 2.3 2.3 0 0 0 0 .8z"/>
|
||||
<path fill="#e7e7e7" fill-rule="evenodd" stroke="#000" stroke-linejoin="round" stroke-width=".1" d="M329.1 273.6c.3.2 1 .1 1.2 0m-1.2-.7h1.2m-1.2-.8h1.2m-1.1-.7h1.1m-1.1-.8h1.1m-1.1-.8h1.1m-1-.8h1m-1-.7h1m-1-.8h1m-1-.8h1m-1-.8h1m-1-.8h1m-1-.8h1m-1-.7h1m-1-.8h1m-1-.8h1m-.9-.8h.8m-.8-.8h.8m-.8-.8h.8m-.8-.7h.8m-1 15.5h1.1m-1.2.7h1.2"/>
|
||||
<path fill="#007934" fill-rule="evenodd" stroke="#e7e7e7" stroke-width=".1" d="M331.5 257a13 13 0 0 1 2.1 0 13.7 13.7 0 0 0-.8-.3h2.2a5 5 0 0 0-1-.5 8 8 0 0 1 2.2.1l-1-.5c.9 0 1.2 0 2 .2a2.6 2.6 0 0 0-.9-.5 8 8 0 0 1 2.5-.2 8.6 8.6 0 0 0-8 .8 6 6 0 0 1 1-1.1 2.5 2.5 0 0 0-.7 0c.3-.3.8-.8 1.2-1l-.7.1 1.4-1a3.1 3.1 0 0 0-.9.1 5.2 5.2 0 0 1 1.6-1.1 4 4 0 0 0-1 0 8.7 8.7 0 0 1 2-1.3c-3.3.4-5.1 2.8-5.3 4.8a7 7 0 0 0-6.6-3.6c1 .3 1.8.7 2.4 1a4.4 4.4 0 0 0-1 .1c.7.2 1.5.6 2 1a3.4 3.4 0 0 0-1 0l1.8.8-.8.1a5 5 0 0 1 1.5.8h-.8c1 .4 1.1.6 1.3.7a8 8 0 0 0-7.3 3 10 10 0 0 1 2.2-1l-.5.8c.5-.4 1.3-.8 2-1a4.8 4.8 0 0 0-.4.7l1.8-1-.4.8 1.7-.7-.5.7 1-.4a6.2 6.2 0 0 0-2.9 5.8l.9-2v1a8.5 8.5 0 0 1 1-2v1l1-2v1l1.1-1.9v.8l.3-.6.7-.9.2.3c.3.4.4 1.1.5 1.8a3.2 3.2 0 0 0 .2-.9c.3.7.7 1.8.7 2.4a3.6 3.6 0 0 0 .2-1c.3.5.6 1.8.7 2.3l.3-.9c.3.8.4 1.7.5 2.3.8-3-.4-4.9-1.8-6.3.4.1.8.5 1.3 1a4.9 4.9 0 0 0-.3-.9l1.5 1.4-.2-.8c.6.4 1.1 1.2 1.5 1.6a5.4 5.4 0 0 0-.2-1 6 6 0 0 1 1.3 1.8l-.1-1c.7.6 1 1.3 1.3 1.7 0-2.7-3.1-5-6-5.3z"/>
|
||||
<path fill="none" stroke="#e7e7e7" stroke-linecap="round" stroke-linejoin="round" stroke-width=".1" d="M330.3 257.1c3.1-.5 7.2 2.3 7.2 5.3-.3-.4-.6-1.1-1.3-1.8l.1 1a6 6 0 0 0-1.3-1.7l.2 1c-.4-.4-.9-1.2-1.5-1.6l.2.8-1.5-1.4.3 1c-.5-.6-1-1-1.3-1.1m-1.8-1.5c-1.9-1.2-5.8-1-8.7 2.3a10 10 0 0 1 2.2-.9l-.5.8c.5-.4 1.3-.8 2-1a4.8 4.8 0 0 0-.4.7l1.8-1-.4.8 1.7-.7-.5.7 1-.4"/>
|
||||
<path fill="none" stroke="#e7e7e7" stroke-linecap="round" stroke-linejoin="round" stroke-width=".1" d="M329.7 256.6c-.4-2.2-3-4.8-6.9-4.6 1 .3 1.8.7 2.4 1a4.3 4.3 0 0 0-1 .1c.7.2 1.5.6 2 1a3.4 3.4 0 0 0-1 0l1.8.8a3.2 3.2 0 0 0-.8.1 5 5 0 0 1 1.5.7l-.7.1c1 .4 1 .6 1.2.7m1.5 1c-2.6.8-5.1 3.3-4.7 6.7 0-.4.5-1.5.8-2v1l1-2v1l1-2v1a13.3 13.3 0 0 1 1.1-1.9v.8a5 5 0 0 1 1-1.5m-1.6.2a8.7 8.7 0 0 0-.5 1.4m-.5-.8a9.7 9.7 0 0 0-.5 1.9m-.5-1a9 9 0 0 0-.5 2"/>
|
||||
<path fill="none" stroke="#e7e7e7" stroke-linecap="round" stroke-linejoin="round" stroke-width=".1" d="M329.9 258.6v-.6" class="fil1 str2"/>
|
||||
<path fill="none" stroke="#e7e7e7" stroke-linecap="round" stroke-linejoin="round" stroke-width=".1" d="M332.6 261.3v1.3m-1-3 .1 1.6m-1-2.7.1 1.3m4.8-.4.6 1.2m-2-2.1.8 1.4m-2-1.8c.3.3.5.7.7 1.2m-10.6-.8a4.7 4.7 0 0 1 1.7-1.2m-.2 1c.4-.6.6-.9 1.6-1.3m-.2 1c.4-.4.9-.8 1.7-1.1m-.4 1.2c.5-.5 1-.7 1.6-1m-3.7-4c.7 0 1.6.2 2.2.6m-1.2.4c.6 0 1.4.2 1.8.4m-1 .4c.6 0 1.3.3 2 .6m-1.3.2a4 4 0 0 1 1.7.6m.9.2a8.6 8.6 0 0 1 8.5-1.2 8 8 0 0 0-2.4.2c.4 0 .7.3.8.4h-2c.4 0 .7.2 1 .4a7.3 7.3 0 0 0-2.2 0l1 .3h-2.2l.8.3c-1 0-1.6 0-2 .2m4.8-1.6a6 6 0 0 0-2.2-.4m1 .7a5.8 5.8 0 0 0-2.5-.2m1.3.6a6.8 6.8 0 0 0-2.5-.2m1.3.7a5 5 0 0 0-2-.1m.8 1c.4.3.6.7.8 1.1m-3-3.1c.2-2 2-4.4 5.3-4.8a9 9 0 0 0-2 1.3h1c-.5.2-1.2.7-1.6 1.1a3.1 3.1 0 0 1 .9 0 6.7 6.7 0 0 0-1.4 1l.7-.1a4.1 4.1 0 0 0-1.2.9h.7l-1 1.1m2-4c-.5.1-1.1.4-1.6.7m1 .4a4.5 4.5 0 0 0-1.5.5m.9.4c-.5.1-1 .4-1.5.7m1 .2a3.2 3.2 0 0 0-1.4.8m-.5 2.4a6 6 0 0 0-.3 1.1m1.2-2c1.8 1.6 4.1 3.7 3 7.6a6 6 0 0 0-.4-2.2l-.3.9a6.8 6.8 0 0 0-.7-2.4 3.5 3.5 0 0 1-.2 1 8.3 8.3 0 0 0-.7-2.4c0 .2 0 .6-.2.9 0-.9-.3-1.7-.7-2"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-width=".1" d="m293.3 233.5 1.3.7.3-.6c.1-.3.2-.5.1-.6 0-.2-.2-.4-.5-.5-.3-.2-.6-.3-.7-.2-.2 0-.4.2-.5.4l-.2.5c0 .1 0 .2.2.3m1.6 1 1.7.8h.3l.3-.5.3-.6a.6.6 0 0 0 0-.4.7.7 0 0 0-.2-.2 1.9 1.9 0 0 0-.3-.2c-.8-.4-1.3-.3-1.7.3l-.4.7m-2.6-.8a33 33 0 0 0 .6-1.2 3.3 3.3 0 0 1 .6-.7l.6-.4h.9c.2.1.3.3.4.6.1.2.2.5.1.7a2 2 0 0 1 1-.6l1 .1c.3.2.5.6.6 1 .1.5 0 1-.4 1.7a32.4 32.4 0 0 1-.7 1.3l-.3.7-1.4-.9-1.8-1-1.5-.7.3-.6m9-10.8c-.8.6-.7 1.5.3 2.6.5.6 1 1 1.5 1 .4.2.9 0 1.3-.3.3-.3.5-.6.4-1a3.1 3.1 0 0 0-.8-1.5c-.5-.7-1-1-1.4-1.2-.5 0-1 0-1.4.4m3.8-.2c.5.6.7 1.3.7 2a2.8 2.8 0 0 1-1.2 2 2.9 2.9 0 0 1-2 .7 2.4 2.4 0 0 1-1.8-1 2.8 2.8 0 0 1-.7-2c0-.7.4-1.4 1-2a2.9 2.9 0 0 1 2-.7c.8 0 1.4.4 2 1m8-2.6.3 1a14.4 14.4 0 0 0 1.9-.7h.3a4.5 4.5 0 0 0 .3.7l-.5.1-2.4.7-.7.2-.4-1.6-.5-2a12 12 0 0 0-.5-1.5l.6-.2.7-.2.3 1.6.6 2m9.2-3a12.2 12.2 0 0 0 0-1.6h.8l.7.1c-.2.5-.2 1-.3 1.7l-.2 2a11.9 11.9 0 0 0-.1 1.6h-.7l-.7-.1.3-1.7.2-2m9.9 5.3c1.6-1.3 2.7-2.2 3.1-2.7l.4.2.4.2a230 230 0 0 0-4.7 3.6l-.5-.3a316.2 316.2 0 0 1 .2-2 362.5 362.5 0 0 0 .4-3.8 7.7 7.7 0 0 0 1.2.7 34.8 34.8 0 0 0-.5 4m8.4 4 1.2-1.3.4.6.5.4a11.1 11.1 0 0 0-1.3 1.1l-1.5 1.4a12 12 0 0 0-1.1 1.1l-.5-.5-.5-.5 1.3-1 1.5-1.4m5 10 1.3-1.4h-2a18 18 0 0 0 .7 1.4m-1.1-1.3-2 .1a1.9 1.9 0 0 0-.1-.3 2.6 2.6 0 0 0-.2-.4h5.9l.3.6a82.5 82.5 0 0 0-4 4.3l-.2-.7a5.4 5.4 0 0 0-.3-.6 23.9 23.9 0 0 0 1.4-1.3 35 35 0 0 0-.4-.8 39.5 39.5 0 0 0-.4-1" font-family="Linux Biolinum" font-size="100" font-weight="700" letter-spacing="60" style="line-height:125%;text-align:center" text-anchor="middle" word-spacing="0"/>
|
||||
<path fill="#e8a30e" stroke="#000" stroke-linecap="square" stroke-linejoin="round" stroke-width=".1" d="m325 280.6-.8 2.2h-2.4l1.9 1.5-.7 2.2 2-1.3 1.8 1.3-.6-2.2 1.8-1.4h-2.3zm9-3.9-.7 2.2H331l1.8 1.5-.7 2.2 2-1.3 1.9 1.3-.7-2.2 1.9-1.4h-2.4zm14.2-25-.8 2.3h-2.3l1.8 1.4-.6 2.3 1.9-1.4 1.9 1.4-.7-2.3 1.9-1.4h-2.4zm-6.7 17.9.7 2.2h2.4l-1.9 1.4.7 2.3-2-1.4-1.9 1.4.7-2.3-1.8-1.4h2.3zm4.7-8.2.8 2.2h2.3l-1.9 1.5.7 2.2-1.9-1.3-2 1.3.8-2.2-1.9-1.4h2.3zm-31.1 19.2.8 2.2h2.3l-1.9 1.5.7 2.2-2-1.3-1.8 1.3.6-2.2-1.8-1.4h2.3zm-9.2-3.9.8 2.2h2.4l-2 1.5.8 2.2-2-1.3-1.9 1.3.7-2.2-1.9-1.4h2.4zm-14-25 .7 2.3h2.3l-1.8 1.4.6 2.3-1.9-1.4-1.9 1.4.7-2.3-1.9-1.4h2.4zm6.6 17.9-.7 2.2h-2.4l1.9 1.4-.7 2.3 2-1.4 1.9 1.4-.7-2.3 1.8-1.4h-2.3zm-4.7-8.2-.8 2.2h-2.3l1.9 1.5-.7 2.2 1.9-1.3 2 1.3-.8-2.2 1.9-1.4h-2.3z"/>
|
||||
<path fill="#e7e7e7" d="M321 248.1v-.5h.1l-.8-.5h-.7l-.8.5v.5h2.3"/>
|
||||
<path fill="#e7e7e7" d="M321 248.1v-.5h.1l-.8-.5v-.7h-.6v.7l-.9.5v.5h2.3zm.3.6v.2h-2.6v-.2h2.6"/>
|
||||
<path fill="#e7e7e7" d="M321.3 248.7v.2h-2.6v-.2h2.6zm-2.5 0v-.5h.1v.5-.5h-.1v-.1h2.4v.1h-.2v.5-.5h.1v.5"/>
|
||||
<path fill="#e7e7e7" d="M318.9 248.7v-.5.5-.5h-.1v-.1h2.4v.1h-.2v.5-.5h.1v.5"/>
|
||||
<path fill="#e7e7e7" d="M319.4 248.6v-.4h-.4v.4h.4"/>
|
||||
<path fill="#e7e7e7" d="M319.1 248.3v.2h.2v-.2h-.2m1.8.3v-.4h-.3v.4h.3"/>
|
||||
<path fill="#e7e7e7" d="M320.7 248.3v.2h.1v-.2h-.1m.2-.3v-.3h-.3v.3h.3z"/>
|
||||
<path fill="#e7e7e7" d="M320.7 247.7v.2h.1v-.2h-.1m-1.3.3v-.3h-.4v.3h.4z"/>
|
||||
<path fill="#e7e7e7" d="M319.1 247.7v.2h.2v-.2h-.2m.8.3v-.3h-.3v.3h.3"/>
|
||||
<path fill="#e7e7e7" d="M319.7 247.7v.2h.1v-.2h-.1m.7.3v-.3h-.3v.3h.3"/>
|
||||
<path fill="#e7e7e7" d="M320.1 247.7v.2h.2v-.2h-.2m.4.2v.8h-1v-.8h1"/>
|
||||
<path fill="#e7e7e7" d="M320.5 247.9v.8h-1v-.8h1zm-1 .2h1m-.9.6v-.6m.7.6v-.6m.5-.5-.5-.4h-.6l-.5.4h1.6m-1-.5h.4m-.3-.1h.2-.2m0 1zm.1 0h.1zm.3 0h.1"/>
|
||||
<path fill="#e7e7e7" fill-rule="evenodd" d="M319.8 246h.4v.4h-.4v-.4z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M320 245.6v.4m-.2-.2h.4"/>
|
||||
<path fill="#452c25" d="M317.1 210.3s-2.3 5.4-1.5 6c0 0 3-3.3 3.7-5.9.8-2.6 0-.2 0-.2l-.2-2.8-2 2.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".2" d="M317.1 210.3s-2.3 5.4-1.5 6c0 0 3-3.3 3.7-5.9.8-2.6 0-.2 0-.2l-.2-2.8-2 2.7"/>
|
||||
<path fill="#452c25" d="M317.6 207.7s-2.8 6-2.1 6.4c0 0 2.3-2.7 3-4.8.5-2.1 0-.1 0-.1l.7-3.9"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M317.6 207.7s-2.8 6-2.1 6.4c0 0 2.3-2.7 3-4.8.5-2.1 0-.1 0-.1l.7-3.9"/>
|
||||
<path fill="#452c25" d="M320.5 206.4s-2.8 6-2.1 6.4c0 0 2.3-2.7 3-4.8.5-2.2 0-.2 0-.2l.7-3.8"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M320.5 206.4s-2.8 6-2.1 6.4c0 0 2.3-2.7 3-4.8.5-2.2 0-.2 0-.2l.7-3.8"/>
|
||||
<path fill="#452c25" d="m356.8 195.6 3.4 1.9s.8.7-1 .3a42 42 0 0 1-12.8-6.4c-3.3-2-4.3-2-4.3-2l4.5.1 10.2 6.1z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m356.8 195.6 3.4 1.9s.8.7-1 .3a42 42 0 0 1-12.8-6.4c-3.3-2-4.3-2-4.3-2l4.5.1 10.2 6.1z"/>
|
||||
<path fill="#452c25" d="m358 194.8 3.3 1.9s.8.7-1 .3a45 45 0 0 1-12.8-6.4c-3.3-2.1-.6 1.7-.6 1.7l.5-2.5 10.5 5z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m358 194.8 3.3 1.9s.8.7-1 .3a45 45 0 0 1-12.8-6.4c-3.3-2.1-.6 1.7-.6 1.7l.5-2.5 10.5 5z"/>
|
||||
<path fill="#452c25" d="M363.5 196.6s-4-.7-5.4-1.8c0 0 .2.5-1.7-.4 0 0 .7 1.7-4.8-2-5.5-3.8-3.6-2-3.6-2l1.6-.3 9.3 3.7a53 53 0 0 1 4.6 2.8"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M363.5 196.6s-4-.7-5.4-1.8c0 0 .2.5-1.7-.4 0 0 .7 1.7-4.8-2-5.5-3.8-3.6-2-3.6-2l1.6-.3 9.3 3.7a53 53 0 0 1 4.6 2.8z"/>
|
||||
<path fill="#452c25" d="m342.6 198.1 1.4 1.9s-.5 1.8-5.1-1.7-4.4-3.2-4.4-3.2l2.6-.3 5.6 3.2"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m342.6 198.1 1.4 1.9s-.5 1.8-5.1-1.7-4.4-3.2-4.4-3.2l2.6-.3 5.6 3.2"/>
|
||||
<path fill="#452c25" d="M336.6 199s2.2 2.9 1.7 3.2c-.5.4-3 .2-4.8-2.5-1.9-2.8 0-.2 0-.2v-4.4l3.2 3.8"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M336.6 199s2.2 2.9 1.7 3.2c-.5.4-3 .2-4.8-2.5-1.9-2.8 0-.2 0-.2v-4.4l3.2 3.8"/>
|
||||
<path fill="#452c25" d="M338.8 197.8s2.1 2.6 1.9 3c-.2.4-3.2.2-5.5-2.5-2.3-2.6-.3-3.4-.3-3.4l3.9 2.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M338.8 197.7s2.1 2.7 1.9 3.1c-.2.4-3.2.2-5.5-2.5-2.3-2.6-.3-3.4-.3-3.4l4 2.8z"/>
|
||||
<path fill="#452c25" d="M350.6 196.2s6 2.5 1.6 2.4c0 0-8.6-2.3-13-6.2l1.2-1.6 10.2 5.2"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M350.6 196.2s6 2.5 1.6 2.4c0 0-8.6-2.3-13-6.2l1.2-1.6 10.2 5.2"/>
|
||||
<path fill="#452c25" d="M353.8 195.4s3.1 2 3.4 2.7c.2.8-10-1.9-15.3-6.3l2.4-1.2 9.4 4.8z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M353.8 195.4s3.1 2 3.4 2.7c.2.8-10-1.9-15.3-6.3l2.4-1.2 9.4 4.8z"/>
|
||||
<path fill="#452c25" d="M344.5 197.2s2.3 1.9 2 2.1c-.3.2-5-.5-8.6-3.3l.4-1.7 6.2 2.8"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M344.5 197.2s2.3 1.9 2 2.1c-.3.2-5-.5-8.6-3.3l.4-1.7 6.2 2.8"/>
|
||||
<path fill="#452c25" d="M348.4 197s2.3 1.6 1.8 1.8c-.4.1-2.2 1.6-10.7-3.4l-1-.6 1.3-2 8.6 4.1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M348.4 197s2.3 1.6 1.8 1.8c-.4.1-2.2 1.6-10.7-3.4l-1-.6 1.3-2 8.6 4.2z"/>
|
||||
<path fill="#452c25" d="M339.7 192.4s2.8 2.4 2.4 2.8c-.4.4-3.6-.4-5-1.5-1.5-1-2.6-2.4-2.6-2.4l3-.7 2.2 1.8z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M339.7 192.4s2.8 2.4 2.4 2.8c-.4.4-3.6-.4-5-1.5-1.5-1-2.6-2.4-2.6-2.4l3-.7 2.2 1.8z"/>
|
||||
<path fill="#452c25" d="m336.4 188.3 5 3s4.1 2.8 3.7 3.1c-.4.3-3.7-.8-6-2-2.2-1.3-5-4-5-4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m336.4 188.3 5 3s4.1 2.8 3.7 3.1c-.4.3-3.7-.8-6-2-2.2-1.3-5-4-5-4"/>
|
||||
<path fill="#452c25" d="M333.2 202.4s1 2.4.4 2.6c-.6.3-2-.2-3-2.3-1.2-2.2 1-1.3 1-1.3l1.6 1z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M333.2 202.4s1 2.4.4 2.6c-.6.3-2-.2-3-2.3-1.2-2.2.7-1.3.7-1.3l2 1z"/>
|
||||
<path fill="#452c25" d="M334.9 200.9s1.4 2.3 1.1 2.6c-.3.2-2.2 1-4.2-2s2.1-2.3 2.1-2.3l1 1.7z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M334.9 200.9s1.4 2.3 1.1 2.6c-.3.2-2.2 1-4.2-2s2.1-2.3 2.1-2.3l1 1.7z"/>
|
||||
<path fill="#452c25" d="M330.7 190.4s4.8 9.3 4.4 9.8c-.4.5-2.3 0-3.4-2.5s-1.9-5.6-1.9-5.6l.9-1.7z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M330.7 190.4s4.8 9.3 4.4 9.8c-.4.5-2.3 0-3.4-2.5s-1.9-5.6-1.9-5.6l.9-1.7z"/>
|
||||
<path fill="#452c25" d="M336.3 192.8s4 3.3 3.2 3.8c-.8.4-2.4-.2-4.8-2.5-2.3-2.3 1.6-1.5 1.6-1.5"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M336.3 192.7s4 3.5 3.2 3.9c-.9.4-2.5-.2-4.8-2.5s1.6-1.4 1.6-1.4z"/>
|
||||
<path fill="#452c25" d="M334.4 192.8s2.8 5.3 2.5 5.8c-.4.5-2.5-1.3-3.6-2.7-1-1.3-1.9-3.3-1.9-3.3"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M334.4 192.8s2.8 5.3 2.5 5.8c-.4.5-2.5-1.3-3.6-2.7-1-1.3-1.9-3.3-1.9-3.3"/>
|
||||
<path fill="#452c25" d="M312.9 203.6s-.2 3.1 0 3.3c.2.3 1.7.3 1.8-2 .1-2.4-.3-2.5-.3-2.5l-1.5 1.1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M312.9 203.6s-.2 3.1 0 3.3c.2.3 1.7.3 1.8-2 .1-2.4-.3-2.5-.3-2.5l-1.5 1.1"/>
|
||||
<path fill="#452c25" d="M313.8 199.9s-1 3.4 0 4.1c1 .7 1.9-3.4 2-4.3 0-1-2 .2-2 .2"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M313.8 199.9s-1 3.4 0 4.1c1 .7 1.9-3.4 2-4.3 0-1-2 .2-2 .2z"/>
|
||||
<path fill="#452c25" d="M314.6 204.3s.2 3.2.8 3.4c.6.1 1.6-1 1.6-1.8s-1-2.8-1-2.8l-1.4 1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M314.6 204.3s.2 3.2.8 3.4c.6.1 1.6-1 1.6-1.8s-1-2.8-1-2.8l-1.4 1"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M314.6 200.4s-1 3.5 0 4.2c1 .7 1.9-3.4 2-4.4 0-.9-2 .2-2 .2z"/>
|
||||
<path fill="#452c25" d="M314.7 194.8s-1.6 1.7-1.6 2.6c0 1 2.4-1.2 2.6-1.6.2-.4-1-1-1-1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M314.7 194.8s-1.6 1.7-1.6 2.6c0 1 2.4-1.2 2.6-1.6.2-.4-1-1-1-1z"/>
|
||||
<path fill="#452c25" d="M313.6 194s-1.3 2.3-1 3c.4.8 1.6-.5 2.2-1.4.6-.8-1.2-1.7-1.2-1.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M313.6 194s-1.3 2.3-1 3c.4.8 1.6-.5 2.2-1.4.6-.8-1.2-1.7-1.2-1.7z"/>
|
||||
<path fill="#452c25" d="M331.5 190.8s2 3.8 1.5 4c-.6.2-1.4-.7-2.3-1.9-.8-1.1.8-2.1.8-2.1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M331.5 190.8s2 3.8 1.5 4c-.6.2-1.4-.7-2.3-1.9-.8-1.1.8-2.1.8-2.1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M331.6 198.6s.7 3.3 0 3.6c-1.2.5-2-2.3-2-3.4 0-1.2 2-.2 2-.2zm-2.6 5.1s.2 2.5-.2 2.7c-.3.2-1.2.2-2.1-1.8-1-2-.5-1.2-.5-1.2l2.3-1.2.5 1.3"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M331.4 203.2s.2 2.5-.3 2.6c-.5 0-1.9-.8-2.5-2.3-.6-1.8 2.4-1.3 2.4-1.3l.4 1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M329 195.3s2.6 6 2.1 6.7c-.8 1.7-3.2-3.5-3.9-5.6-.8-2.2 1.7-1 1.7-1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M327.7 196.3s3.6 6.5 2.1 6.6c-1.5.2-4.3-4.6-4.7-5.8-.5-1 2.6-.8 2.6-.8z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M327.5 197.7s1.8 6.2.6 5.6c-1-.5-2.5-5.2-2.6-6.2-.2-1 2 .6 2 .6zm6.2-8.8s2.7 4.1 1.8 4.2c-.8.2-4-2.7-4-3.2-.1-.5 2.2-1 2.2-1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M332 189s3.5 4.8 2.4 5c-1 .2-1.1-.5-1.1-.5s-2.8-2.5-3-3.1c-.1-.6 1.6-1.4 1.6-1.4m3.5.1s2.4 2.5 1.8 3.3c-.6.8-4-3.1-4.4-3.6-.4-.5 2.9.2 2.9.2m-6 3.5s3.8 7.5 3 8.2c-.6.8-4.9-5.6-5-6.5-.2-.9 2-1.8 2-1.8"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M327.5 193.2s1.5 2.3 1.4 3.6c0 1.2-2.3-1.8-2.5-2.4-.2-.6 1-1.2 1-1.2zm3.1-1.2s1.2 2.4.8 3.1c-.3.8-2-1.4-2.5-2.3-.6-.8 1.7-.8 1.7-.8z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".2" d="M325 194.4s2 2 1.9 3.1c-.1 1.1-2.8-1.6-3-2-.3-.6 1.2-1.1 1.2-1.1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M337.2 188.4s2.8 2.5 2.4 3c-.5.3-4.3-2.4-4.9-3-.6-.5 2.5 0 2.5 0z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="m334.8 188.2 2.2 1.9s2 1.3 1.7 1.7c-.3.3-3.6-1.1-4.1-1.8-.6-.7-.6-1.4-.6-1.4l.8-.4zm7.3.6s8.4 3.4 8 4.2c-.3.8-8.8-2.7-10-3.7-1.4-.9 1.8-.6 1.8-.6"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M342.4 189.8s6.3 3.6 5.5 4c-.7.3-5.2-1-7.5-2.5a36.6 36.6 0 0 1-3.3-2.5l2.8-.6 2.5 1.7zm-15.5 4.4s1.2 2.4.8 3c-.4.8-1.5-.5-2.1-1.4-.6-.8 1.3-1.6 1.3-1.6zm.3 5.4s1 3.5-.1 4.2c-1.1.6-1.8-3.6-1.8-4.5 0-.9 1.9.3 1.9.3z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M322.3 193.8s3.5-1.5 4.1-1.4c0 0 .8-.2 1.1-.5l1.3-1s-.6-4.3 3.9-3.8l11.5 1.1a45 45 0 0 1 6.5 2l9 3.9a30 30 0 0 1 4 2.3c.8.5-.1.1-.1.1s-10.7-5.7-14.5-6.4c-1-.2 0 1 0 1l-3.4-1.3a6 6 0 0 0-2.9-.6 5.8 5.8 0 0 1-2.2-.3c-.6-.2-3.8-.3-4.4-.4a7.3 7.3 0 0 1-1-.2l.3.4-1.6-.2-.5.6s-1.5.3-1.6-.2c-.1-.4-1 2.3-1.3 3-.4.9-1.9.9-2.3 1.4l-1 .9c-.2.1-1.3.8-1.7.8l-2.9.2-.6-1 .3-.4zm4.6 10-.1 3.3c-.2.2-1.8.1-1.8-2.2s.5-2.4.5-2.4l1.5 1.2"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M327.3 201.4s-.3-1.4-.5-1.6c-.3-.2 0-.3 0-.3s-.5-1.4-.9-1.6c-.3-.2.1-.4.1-.4s-.6-1-1-1.2c-.4-.3 0-.4 0-.4s-.5-1.2-1.5-1.8c0 0-.7-.7-1.4-.9-.7-.2-2.4-.4-4.5-.3-2.2 0-3.2 1.5-3.2 1.5l-.1 1.8.3-.2-.5 2.2c0 .5.5 1.4.5 2.5v1c.1 1 .4 2 .8 2.9v.2c.2-.2.5.6.7 1 0 0 0 1 .2.6l.6 1.1c0 .2.5 1.4.5.9 0-.6.4 1.3.4 1.5l.5-.7.2.8h.5l-.2.8s1.2-1 1.3-1.4v-.6l.4-.4.6-1s1.5 1.2 1.7 1.7l.3.7.4-.3.3.8.3-.4.2.6.1.3c.1.1.4.2.8-.6.6-1 .6-1.9.6-2 0-.3.3.2.3.2s.6-1 .5-1.6c0-.7.3-.4.3-.4v-2.2c0-.4.3-.3.3-.3l-.2-2.3c-.2-.2.3-.2.3-.2z"/>
|
||||
<path d="M324.3 196.7c.3 0 .4.4.6.6-.1-.4-.3-.7-.6-.8v.2m.3 1.2c.5.5.6 1.1.5 1.8v.1c0-.7 0-1.5-.5-2v.1m1.1.7a3 3 0 0 1 .4 1.6c0-.6 0-1.2-.4-1.7m.4 2.5c0 .4 0 .7-.2 1a.4.4 0 0 0 0 .2 11 11 0 0 0 .2-1.2m-.4 1.9v.7a3.8 3.8 0 0 0 0-.8m.7 0c.2.1.3.3.3.6a.4.4 0 0 0 0-.1 1.2 1.2 0 0 0-.3-.7v.2m0-2.6.4.5v-.2a3.1 3.1 0 0 0-.5-.5v.2m-1.4 2a5.9 5.9 0 0 1 0 1 6.6 6.6 0 0 0 0-1m-.7.7a5.2 5.2 0 0 1 0 1 6.2 6.2 0 0 0 0-1.1v.1"/>
|
||||
<path fill="#452c25" d="M310.7 194.3s-.8 3.2-.2 3.5c1.3.7 2-2.2 2.2-3.2.1-1.2-2-.3-2-.3"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M310.7 194.3s-.8 3.2-.2 3.5c1.3.7 2-2.2 2.2-3.2.1-1.2-2-.3-2-.3z"/>
|
||||
<path fill="#452c25" d="M312.6 194.3s-1.6 1.7-1.6 2.6c0 1 2.4-1.3 2.6-1.7.2-.4-1-.9-1-.9"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M312.6 194.3s-1.6 1.7-1.6 2.6c0 1 2.4-1.3 2.6-1.7.2-.4-1-.9-1-.9z"/>
|
||||
<path fill="#452c25" d="M285 194.5s-3.3 1.7-3.6 2.4c-.3.7 10-1 15.8-5l-2.3-1.4-9.8 4z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M285 194.5s-3.3 1.7-3.6 2.4c-.3.7 10-1 15.8-5l-2.3-1.4-9.8 4z"/>
|
||||
<path fill="#452c25" d="M289 195.2s-6 2.2-1.7 2.3c0 0 8.7-1.8 13.3-5.4l-1.1-1.7-10.5 4.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M289 195.1s-6 2.3-1.7 2.4c0 0 8.7-1.8 13.3-5.4l-1.1-1.7-10.5 4.7z"/>
|
||||
<path fill="#452c25" d="M298 189s-6.5 3.4-5.8 3.7c.7.4 5.3-.6 7.7-2l3.4-2.4-2.9-.8-2.5 1.6z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M298 189s-6.5 3.4-5.8 3.7c.7.4 5.3-.6 7.7-2l3.4-2.4-2.9-.8-2.5 1.6z"/>
|
||||
<path fill="#452c25" d="M295.5 196.3s-2.3 1.9-2 2.1c.2.2 5-.5 8.6-3.4l-.5-1.7-6.2 2.9"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M295.5 196.3s-2.3 1.9-2 2.1c.2.2 5-.5 8.6-3.4l-.5-1.7-6.2 2.9"/>
|
||||
<path fill="#452c25" d="M291.5 196s-2.2 1.7-1.7 1.8c.5.1 2.3 1.5 10.6-3.9l1-.6-1.5-2-8.4 4.5"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M291.5 196s-2.2 1.7-1.7 1.8c.5.1 2.3 1.5 10.6-3.9l1-.6-1.5-2-8.4 4.6z"/>
|
||||
<path fill="#452c25" d="M289.8 189.6a66 66 0 0 0-13.9 7.2l17.9-7m11.2 10.6s-1.5 2.3-1.2 2.5c.3.3 2.1 1.2 4.3-1.7 2-3-2-2.5-2-2.5l-1.1 1.7z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M305 200.4s-1.5 2.3-1.2 2.5c.3.3 2.1 1.2 4.3-1.7 2-3-2-2.5-2-2.5l-1.1 1.7z"/>
|
||||
<path fill="#452c25" d="M306.6 202s-1 2.4-.5 2.6c.6.3 2-.1 3.2-2.2 1.2-2.2-.6-1.1-.6-1.1l-2 .7zm-3.3-3.5s-2.2 2.7-1.7 3.1c.4.4 3 .3 4.9-2.4 1.9-2.6 0 0 0 0l-.5-2.5-2.7 1.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M306.6 202s-1 2.4-.5 2.6c.6.3 2-.1 3.2-2.2 1.2-2.2-.6-1.1-.6-1.1l-2 .7zm-3.3-3.5s-2.2 2.7-1.7 3.1c.4.4 3 .3 4.9-2.4 1.9-2.6 0 0 0 0l-.5-2.5-2.7 1.7"/>
|
||||
<path fill="#452c25" d="M301.2 197.1s-2.2 2.6-2 3c.2.5 3.2.3 5.6-2.2s.5-3.5.5-3.5l-4 2.6"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M301.2 197.1s-2.2 2.6-2 3c.2.5 3.2.3 5.6-2.2s.5-3.5.5-3.5l-4 2.6"/>
|
||||
<path fill="#452c25" d="m297.4 197.3-1.4 1.9s.3 1.8 5.1-1.5l4.5-3-2.5-.5-5.8 3"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m297.3 197.2-1.3 2s.3 1.8 5.1-1.5l4.5-3-2.6-.5-5.7 3z"/>
|
||||
<path fill="#452c25" d="m282.2 194.5-3 1.3s-.7.6 1 .7c1.8 0 5.5-.5 11.9-4 2.8-1.7 4.7-3.3 4.7-3.3l-2.4-.8-12.2 6z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m282.2 194.5-3 1.3s-.7.6 1 .7c1.8 0 5.5-.5 11.9-4 2.8-1.7 4.7-3.3 4.7-3.3l-2.4-.8-12.2 6z"/>
|
||||
<path fill="#452c25" d="M277 196.4s4.4-.5 6-1.6c0 0-.3.5 2-.4 0 0-1.2 2 5.3-2 6.5-3.8 0 0 0 0l7.2-4.1-.4-.8-14.7 6.2c-1 .3-5.4 2.7-5.4 2.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m290.3 192.4 7.2-4.1-.4-.8-14.7 6.2c-1 .3-5.4 2.7-5.4 2.7s4.4-.5 6-1.6c0 0-.3.5 2-.4 0 0-1.1 2 5.3-2z"/>
|
||||
<path fill="#452c25" d="M308.5 202s-.4 3.4.1 3.5c.5.1 2-1 2.6-3 .6-2.2-2.4-2-2.4-2l-.4 1.3"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".2" d="M308.5 202s-.4 3.4.1 3.5c.5.1 2-1 2.6-3 .6-2.2-2.4-2-2.4-2l-.4 1.3"/>
|
||||
<path fill="#452c25" d="M310.8 203.5s-.3 2.4 0 2.6c.4.3 1.3.4 2.3-1.6 1-2 .5-1.3.5-1.3l-2.3-1.2-.5 1.3"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M310.8 203.4s-.3 2.5 0 2.7c.4.3 1.3.4 2.3-1.6 1-2 .5-1.3.5-1.3l-2.3-1.2-.5 1.4z"/>
|
||||
<path fill="#452c25" d="M311.4 199s-1.9 4-.8 4c1 0 2.5-3 2.7-3.7.2-.7-1.9-.3-1.9-.3"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M311.4 199s-1.9 4-.8 4c1 0 2.5-3 2.7-3.7.2-.7-1.9-.3-1.9-.3z"/>
|
||||
<path fill="#452c25" d="M311.3 199s-.8 4.5.2 4c1-.3 1.6-3.7 1.7-4.4 0-.7-2 .4-2 .4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M311.3 199s-.8 4.5.2 4c1-.3 1.6-3.7 1.7-4.4 0-.7-2 .4-2 .4z"/>
|
||||
<path fill="#452c25" d="M312.8 199.4s-1.1 3.5 0 4.2c1 .7 1.8-3.4 1.9-4.3 0-1-2 .1-2 .1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M312.8 199.4s-1.1 3.5 0 4.2c1 .7 1.8-3.4 1.9-4.3 0-1-2 .1-2 .1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M308.4 198.3s-1 3.2-.4 3.5c1.2.6 2.3-2.2 2.4-3.3.1-1.2-2-.2-2-.2zm-7.9-6.6s-2.8 2.4-2.5 2.7c.3.4 3.6-.2 5.1-1.3l2.1-1.5-2.5-1.6-2.2 1.7z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M303 189.3s-1.8 1.5-1.5 1.9c.4.3 3.6-1 4.2-1.7.6-.6.6-1.3.6-1.3l-3.3 1.1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M304.9 189s-2.5 2.1-1.9 2.9c.6.7 4-2.6 4.5-3 .5-.4-2.9 0-2.9 0"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="m303.8 188.2-5 2.3s-4.2 2.7-3.8 3c.4.3 3.7-.6 6-1.7a37.9 37.9 0 0 0 5-3.1m-.9 2.1s-5.3 4.7-4.5 5.1c.8.5 4.4-1.4 6.8-3.7"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M305.8 192.4s-3 5-2.7 5.6c.4.5 2.6-1.2 3.7-2.5s2-3.2 2-3.2"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M307.6 192.8s-3.3 6.1-3 6.6c.4.5 2.4.1 3.5-2.3 1.2-2.4 1-4 1-4l-1.5-.3z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M309.5 193.1s-3.7 7.6-3 8.3c.8.8 4.8-5.7 5-6.6.3-1.6-2-1.8-2-1.8m-7.7-4.9s-3.3 1.6-2.7 2c.7.2 3.8-1.2 4.2-1.3.5-.1-1.5-.7-1.5-.7z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M302.3 188.6s-2 1.6-1.6 2c.4.5 3.5-1.2 4-1.7.7-.5-2.4-.3-2.4-.3zm4.3.2s-2.8 3.7-2 3.8c.9.2 4.1-2.4 4.2-2.8 0-.5-2.2-1-2.2-1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M307.8 189.6s-3 3.7-2.1 4c.8.2 1-.4 1-.4s2.3-2 2.4-2.5c.2-.5-1.2-1.2-1.2-1.2"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M308.7 190.5s-2.1 3.7-1.6 4c.6.2 1.5-.8 2.4-1.9.9-1-.8-2.1-.8-2.1z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M309.3 192.2s-1.3 2.3-1 3c.4.8 1.6-.5 2.2-1.3.6-.8-1.2-1.7-1.2-1.7zm.5 6.5s-.8 3.2-.2 3.5c1.3.7 2-2.2 2.2-3.2.1-1.2-2-.3-2-.3z"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M315.7 194.4s-.9-.3-1.5-.3c0 0-1.9-1.4-3-1.6-1-.1 0-.2 0-.2s-.2-2.4-.5-2.6c0 0-.1-2.5-1.7-2.6-1.6-.2-5.1.1-5.7-.1-.7-.3-2.6-1-6.3 0-3.8 1-11.2 4.3-11.6 4.4-.4 0 8.5-2 11-3l3.3-.5s-2.8 1.4-.2.8c2.6-.6 2 0 2 0s-.2.6 1.3.3c1.4-.4 1.4 0 1.4 0s1.7.6 3-.2c0 0 .7 2.3 1.6 2.6 0 0 1 2.2 3.1 2.6l1.2.9 1.2.4 1.3-1"/>
|
||||
<path fill="#452c25" stroke="#000" stroke-width=".1" d="M298.3 188s-8.6 3-8.3 3.9c.4.8 9-2.4 10.3-3.2 1.4-1-2-.7-2-.7"/>
|
||||
<path d="m321.8 194.6.5.2a1.5 1.5 0 0 0-.3-.3l-.7-.3.1.2.4.2M315 201c.2.2.2.5.3.8v-.2c-.1-.2-.1-.5-.3-.7v.1m1.2-6.5.9-.2v-.1l-.9.1v.2m1.7-.2.8-.1a.3.3 0 0 0 0-.1 2 2 0 0 0-.8.1v.1m-3 1.5a.3.3 0 0 0 0 .2v-.2m-.1 4.6a4.8 4.8 0 0 0 0 .7.4.4 0 0 0 0-.1v-.6"/>
|
||||
<path fill="#bd8759" d="M316.6 213.9s-1 .7-1 1a3.8 3.8 0 0 0-.2.8s.8-.1.7.3c0 0 .3.2.8-.8.4-1 .8-1.5 1.1-1.5.4 0 .8.4 1 .6.2.2.4.4.8.3 0 0-.4-.6-.2-.7l.6-.1s-.3-.7-.9-.8c-.6-.1-1-.3-1-.6.2-.2 1-2.4 1-2.4l-1-1.5-.5 1.3.2 1-1 2.1c0 .1-2.4 1-2.7 1l-.8.9v.5s.3-.4.4-.2c0 0 .3-.3.6-.2.2.1.1.2.1.2l.5-.4.1-.1.6-.1"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M316.6 213.9s-1 .7-1 1a3.8 3.8 0 0 0-.2.8s.8-.1.7.3c0 0 .3.2.8-.8.4-1 .8-1.5 1.1-1.5.4 0 .8.4 1 .6.2.2.4.4.8.3 0 0-.4-.6-.2-.7l.6-.1s-.3-.7-.9-.8c-.6-.1-1-.3-1-.6.2-.2 1-2.4 1-2.4l-1-1.5-.5 1.3.2 1-1 2.1c0 .1-2.4 1-2.7 1l-.8.9v.5s.3-.4.4-.2c0 0 .3-.3.6-.2.2.1.1.2.1.2l.5-.4.1-.1.6-.1"/>
|
||||
<path fill="#bd8759" d="M323.1 209.2v2.1c0 .3 0 .8-.2 1.1-.2.3-.4.5-.7.5-.3 0-1 0-1.2.3l-.3.4s.5-.3.6 0l-.2.6.9-.2.8-.3.4.2v1c0 .4 0 1.2.3 1.2l.4-.5.5.5-.1-1.2a6.7 6.7 0 0 1-.3-1l1.5.6c0 .2.4.5.5.5.1 0 0-.5.2-.5.3-.1.4 0 .4 0s-.4-.8-1-1c-.5-.4-1-.4-1.2-.6l-.3-.9v-2.8l-1-.2"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M323.1 209v2.3c0 .3 0 .8-.2 1.1-.2.3-.4.5-.7.5-.3 0-1 0-1.2.3l-.3.4s.5-.3.6 0l-.2.6.9-.2.8-.3.4.2v1c0 .4 0 1.2.3 1.2l.4-.5.5.5-.1-1.2-.3-1s1.4.5 1.5.7l.5.4c.1 0 0-.5.2-.5.3-.1.4 0 .4 0s-.4-.8-1-1c-.5-.4-1-.4-1.2-.6l-.3-.9v-2.8l-1-.2z"/>
|
||||
<path fill="#dcddde" d="M315 197.3s0-1.3.3-1.4c0 0 .1-1.2 1.7-1 0 0 .5-.9 1.4-.4 0 0 .8-.4 1.3-.2l1 .7s.7-.1 1 .1c.3.3.2 1.1.2 1.1s.8.6.8 1.1v.9s.3.3.2.7c0 .4-.4 1-.4 1-.1 0 0 1-.3 1.3l-.8.5c-.2 0-.6.6-1 .6-.3 0-.8-.5-.8-.7 0-.2-.6-.4-.6-.4s-1 1.2-1.8 1c-.8-.2-1.1-.8-1.2-1l-.3-1s-.8-.4-.7-.9c0-.4.4-1 .4-1l-.3-1z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m317.8 212-.2-.1m.6-.9a.8.8 0 0 1-.3-.1m0 .6h.2m5.5.5.5.2m-.2-.6h-.3m.4-.5a.9.9 0 0 1-.5 0m0 1.8.4.1m-.4.5a.2.2 0 0 1 .2 0m-.1 1.6a.4.4 0 0 1 .3 0m-5.1-2a.3.3 0 0 0-.3.1m1-.1c-.1.1-.3.2-.3.4m-4.5.5.4.3m10-1a.3.3 0 0 0-.3.3m.7-.1a.2.2 0 0 0 0 .2"/>
|
||||
<path fill="#d9c0b9" d="M313.4 215h.6s-.3.7-.2.8c0 .2-.5-.3-.3-.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M313.4 215h.6s-.3.7-.2.8c0 .2-.5-.3-.3-.7z"/>
|
||||
<path fill="#d9c0b9" d="M315.6 215.5s-.7 1 .1 1.5c0 0 0-1 .6-1.1l-.8-.4z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M315.6 215.5s-.7 1 .1 1.5c0 0 0-1 .6-1.1l-.8-.4z"/>
|
||||
<path fill="#d9c0b9" d="m319.6 214.5-.2-.5.2-.3h.6s.4.9 0 1.3c0 0 0-.5-.2-.5h-.4"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m319.6 214.5-.2-.5.2-.3h.6s.4.9 0 1.3c0 0 0-.5-.2-.5h-.4z"/>
|
||||
<path fill="#d9c0b9" d="M321 213.4h.3l.1.3v.3l-.3.2s-.5-.2-.4.5c0 0-.3-1.2.2-1.3"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M321 213.4h.3l.1.3v.3l-.3.2s-.5-.2-.4.5c0 0-.3-1.2.2-1.3z"/>
|
||||
<path fill="#d9c0b9" d="m323.5 215.9.4-.4.4.2-.3 1.2-.2-.3-.3-.7"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m323.5 215.9.4-.4.4.2-.3 1.2-.2-.3-.3-.7z"/>
|
||||
<path fill="#d9c0b9" d="m326 214.8.5 1s.6-.6-.2-1.5l-.4.5z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m326 214.8.5 1s.6-.6-.2-1.5l-.4.5z"/>
|
||||
<path d="m323.3 195.9.2.2v-.1l-.2-.2m.1 2.2.4.7v-.2a1.7 1.7 0 0 0-.4-.7v.2m-.4-1.6.5.6v-.2l-.5-.5v.1m.5 3.5c0 .3 0 .6-.2.8v.2c.2-.4.2-.7.2-1.1a.5.5 0 0 0 0 .1m.5 1v.5a.4.4 0 0 0 0 .1 2.2 2.2 0 0 0 0-.6m1.8 3.9a4.8 4.8 0 0 1 .1 1.3l-.1-1.5v.2m-.3.8-.4 1 .4-.8v-.2m-10.3-2.9.7 1.2v-.1l-.7-1.2v.1m1.8 0c-.2 0-.3-.3-.5-.4v.2c.2 0 .3.4.5.4v-.2m-1 1.8.5 1v-.2l-.5-1v.2m1.2.4.5.8v-.1c0-.3-.3-.6-.5-.8m0 1.3.2.7v-.1l-.3-.7v.1m1.1.3a2.8 2.8 0 0 1 .1.7 3.3 3.3 0 0 0 0-.9v.2m-.5 1c0 .3.1.7.3 1v-.2a3.2 3.2 0 0 1-.3-.9.4.4 0 0 0 0 .1m.2-4.4.8.3v-.1a8 8 0 0 1-.8-.3v.1m.2 1.2 1 .4c-.3-.3-.7-.4-1-.6v.2m.3 1.2.6.6v-.1a4.5 4.5 0 0 1-.6-.6v.1m.4 1.6.2.7a1.8 1.8 0 0 0-.2-.8v.1m1-4v.5a10 10 0 0 1 0-.5m2.3-.9a3.6 3.6 0 0 1-.2.5v.1l.2-.4v-.2m1 0v.8a.4.4 0 0 0 0 .1 4.2 4.2 0 0 0 0-1m.2 1.6v.7a3.7 3.7 0 0 0 0-.8m.7 1.5c0 .3-.2.6-.5.8v.1c.3-.2.5-.4.5-.8m-2.4-1.5-.2.4v.1l.2-.4m.3 1.8a1.9 1.9 0 0 1-.4.4v.1c.2 0 .3-.2.4-.3v-.1m-.9 1c-.3-.4-.4-.8-.3-1.3v-.1c-.2.5 0 1 .3 1.5v-.2m-1-1-.1.5v-.6m2.6 1.3c0 .3-.2.5-.3.7v.1l.3-.6v-.2m1.7.7a9.2 9.2 0 0 1-.5.7v.2l.5-.8m.8.8a17 17 0 0 0-.2 1.3v.1l.2-1.3a.6.6 0 0 0 0-.1m1-1.6v.5-.5M315 202l.1 1.3v-.2a2.2 2.2 0 0 1-.1-1 .6.6 0 0 0 0-.1"/>
|
||||
<path fill="#fff" d="M318.8 196.3c.7-.6 1.7-1.3 2.7-1v-.2c-1-.2-2 .5-2.7 1.1v.1m3.5.8c-.8-.5-2-.6-2.7 0 .7-.5 2-.3 2.7.2v-.2m-2.8 1.1c.3 1 .7 2 .5 3 .2-1-.2-2-.5-3m-1.1.6v3c0-1 .2-2 0-3.1a.4.4 0 0 0 0 .1m1.5-.7c1 .2 1.9.9 2.4 1.7v-.1a3.9 3.9 0 0 0-2.4-1.7v.1m-.8 1.3c0 .6 0 1.2-.2 1.8.2-.5.2-1.2.2-1.8m1.4-.1a3.1 3.1 0 0 1 1.2 2v-.1a3.2 3.2 0 0 0-1.2-2m-4.3 1.7c.2-.3.4-.6.8-.7v-.1c-.4 0-.6.4-.8.7v.1m1.4-5c-.1-.6-.5-1-1-1.2v.1c.5.3.9.6 1 1.2v-.2m-.8 0c-.5-.2-1-.2-1.5-.2a.3.3 0 0 0 0 .1c.5 0 1 0 1.5.3v-.2m1.5 0c0-.6 0-1-.4-1.3.3.3.5.7.4 1.2m1.8.7c.5-.3 1-.2 1.5-.2v-.2c-.5 0-1 0-1.5.2v.2m.9 1.2a2.6 2.6 0 0 1 1.7 1v-.3a2.6 2.6 0 0 0-1.7-1v.3m-3.1 2c-.2.6 0 1.5-.9 1.8v.2c.8-.3.7-1.1.9-1.8v-.3"/>
|
||||
<path fill="#fff" d="M319.5 199c.3.7.7 1.4.5 2.2a.9.9 0 0 0 0 .3c.2-1-.1-1.8-.5-2.7v.2m1-.1c.7 0 1.3.7 1.4 1.4a1 1 0 0 0 0-.2 1.7 1.7 0 0 0-1.4-1.5v.3m0 1c.1.6.3 1.2.1 1.8v.2c.3-.7 0-1.5 0-2.2a1 1 0 0 0 0 .2m-.4-2.6c.7-.1 1.5-.2 2.2.3v-.3c-.7-.5-1.5-.4-2.2-.2v.2m-1.4-1.5c0-.6.6-1 1.2-1.3v-.2c-.6.2-1.2.6-1.3 1.3a1 1 0 0 0 0 .2m-.6.4c0-.7-.4-1.3-.7-1.9v.2c.3.6.6 1.1.6 1.8v-.1m-.6.4a2 2 0 0 0-1-1.4v.3c.5.3.9.7 1 1.3a.8.8 0 0 0 0-.2m-1-.3a2.9 2.9 0 0 0-1.2-.5v.2c.5 0 .8.3 1.2.5v-.2m2.2 3c0 .6.2 1.3-.2 1.9v.2c.4-.7.3-1.6.2-2.3v.1"/>
|
||||
<path fill="#fff" d="M319.4 198.9c.2.6.5 1.3.4 2a5.8 5.8 0 0 0-.4-2.3v.3m.5-1c.6.3 1.3.5 1.7 1v-.3a3.6 3.6 0 0 0-1.7-.9v.3m-1.7-1.4a14.8 14.8 0 0 0 0-1.7 11.8 11.8 0 0 1 0 1.7m-1.2-.4a5.6 5.6 0 0 1-1.2-.8v.2l1.2.9v-.3m-.2 3.3c-.3.2-.5.5-.6.8v.2a1.6 1.6 0 0 1 .6-.7v-.3m.9.5c0 .5-.3.9-.6 1.2v.2c.4-.4.6-.8.6-1.3 0 0 0-.3 0 0m2.1-3.6c.4-.6 1.3-.7 1.9-.9v-.2c-.6.2-1.5.2-2 .8v.3m-4 0a2 2 0 0 1-.5-.3v.2l.4.2v-.2m.1 3-.4.3v.1a.7.7 0 0 0 0 .1.8.8 0 0 1 .4-.2.7.7 0 0 0 0-.2m.5.1-.6.6v.2l.6-.6v-.2m1 .3c-.1.6-.8 1.2-.3 1.8v-.2c-.3-.5.2-1 .4-1.4v-.2m.7 0c0 .6 0 1.1-.2 1.7a.9.9 0 0 0 0 .2 9.8 9.8 0 0 0 .2-2m1.9-.6c.4.5.8 1.1 1 1.8v-.2a5 5 0 0 0-1-1.9v.3m.2-.5c.7.6 1.5 1 2 1.8v-.2c-.5-.8-1.3-1.3-2-1.8v.2"/>
|
||||
<path fill="#fff" d="M320.5 197.8h.8l.6.5.6.4c.2.2.2.6.3.9a.7.7 0 0 0 0-.2l-.2-.7c0-.2-.3-.4-.5-.5l-.7-.4a1.4 1.4 0 0 0-.9-.2v.2"/>
|
||||
<path fill="#fff" d="m322.3 199.3.2.6v-.1l-.2-.7v.2m-2-3.6 1.5-.4v-.3l-1.5.4v.3m-2 .2c0-.2.1-.5.3-.7l.4-.8v-.3l-.4.7c0 .3-.3.5-.4.9v.2m-1.7 4.6.1 1.3v-.2a1.4 1.4 0 0 1 0-.8.7.7 0 0 0 0-.2s0-.1 0 0m1 .7c-.2.3-.2.6-.1 1a.3.3 0 0 0 0-.2v-.7m.8-.5-.2.7v.2l.2-.8s0-.2 0 0m0-1.5v.4-.5.1m-.3.2v.1a.7.7 0 0 0 0 .3v-.7.4m-.5-.2-.1.5a.8.8 0 0 0 0 .2 3.3 3.3 0 0 1 .1-.4v-.2m-.4 0-.8.6v.3l.8-.7v-.2m-.6 0a1.6 1.6 0 0 1-.5.3v.3c.2 0 .3-.2.5-.3v-.2m-1-.3-.4.2v.2c.2 0 .3 0 .4-.2v-.2m2.9 0v.4a.8.8 0 0 0 0-.2v-.4.1m.4-.2.1.6v-.3a1 1 0 0 1 0-.3v-.1.1m.3 0v.3h.1a.8.8 0 0 0-.1-.6v.2m.4-.2.4.2v-.2a.8.8 0 0 0-.4-.2v.2m.2-.3.6.3v-.3a1.2 1.2 0 0 1-.6-.3v.2m.5-1h.4v-.2a2.3 2.3 0 0 0-.4-.1v.3m-.3-.6.4-.3v-.3l-.4.4v.2m-.4-.5a1 1 0 0 1 .2-.5v-.2a1 1 0 0 0-.2.7m-.3-.2.4-.8v-.2l-.4.7v.2"/>
|
||||
<path fill="#fff" d="M318.6 195.3v.9a.7.7 0 0 0 0-.3 3.7 3.7 0 0 1 0-.7v.1m-1.3.2.2.3v.6l.1-.5-.3-.6v.2m-.2.5a4.5 4.5 0 0 0-.6-.4v.2l.6.5v-.2m.8.2c0-.6 0-1.2-.2-1.7v.3c.2.4.3.7.2 1.2a.8.8 0 0 0 0 .1m1.2-.7v-.2.2"/>
|
||||
<path fill="#fff" d="m317.7 196.3.2-1v-.2l-.2 1v.2m3.5 2c.3 0 .6.3.7.6v-.4c-.1-.3-.4-.5-.7-.6v.4m-1 2a1 1 0 0 1 0 .4 1.2 1.2 0 0 0 0 .3h.1v-1 .3m-.8-.5v1.2s0 .2 0 0v-1.4.2m-.4.4-.3 1.2a1 1 0 0 0 0 .3s0 .1 0 0l.3-1.2v-.3m.5.2v1.1a1.3 1.3 0 0 0 0 .3v-1.6.2m-2.6.2a.6.6 0 0 1 0 .1v.4c.1-.2.1-.6 0-.8 0-.1 0 0 0 0v.3m1.2-.8v.4c0-.3.1-.6 0-.8v.3m.3 0a.4.4 0 0 1 .1 0v.1a.8.8 0 0 0 0 .1v-.2l-.1-.5a1.3 1.3 0 0 0 0 .2v.2m.4-.3.1.3v-.3l-.1-.4a.9.9 0 0 0 0 .1v.2m.8-.2.5.6v-.4a9.3 9.3 0 0 1-.5-.6v.4m.5-.8.3.6v-.4a4.1 4.1 0 0 1-.3-.5v.3m-4.3-2a1.7 1.7 0 0 0-.4-.2 1.1 1.1 0 0 0 0 .2v.2l.4.3v-.4m1.3-.5a.5.5 0 0 1 0 .1.8.8 0 0 0 0 .2v-.3a1 1 0 0 0 0-.4.8.8 0 0 0 0 .2v.2m1-1v.8c-.1 0-.1.1 0 .2v.1l.1-1.2a.6.6 0 0 0 0-.1v.2m.2 1.5.5-.7v-.3l-.5.6v.4m.7 0 .2-.3v-.4l-.2.2a1.3 1.3 0 0 0 0 .2v.2m1 .2a7.6 7.6 0 0 1-.8 0v.4h.8v-.4m-.3.9 1 .6v-.4l-1-.6v.4"/>
|
||||
<path fill="#fff" d="m320 198 .8.5v-.4l-.8-.5a2 2 0 0 0 0 .2v.2m-2-1.4.1-.5v-.2.6m-2.3-1c.2.3.5.6.9.8l.6.7s.1-.4 0-.4l-.6-.6-1-.9c.1 0 0 .3 0 .4m.6 1a7.7 7.7 0 0 1-.4-.4 1.6 1.6 0 0 0 0 .2v.1l.4.5v-.3m-.3 2.5-.3.6v.4l.3-.6v-.4m.3.4-.1.6a1.3 1.3 0 0 0 0 .3l.1-.8v-.2a.6.6 0 0 0 0 .1m1 1.8c.2-.6.2-1.3.2-2v.2c0 .5 0 1-.2 1.4v.4m.6-1.5v.6a1.3 1.3 0 0 0 0 .3v-1.3a.6.6 0 0 0 0 .2v.2m.6-.2c.2.2.3.6.2 1v.1c.1-.5.1-1-.2-1.5v.4"/>
|
||||
<path fill="#fff" d="M318.6 199.3a12.6 12.6 0 0 1 .3 1.7v-.3l-.2-1.7v.3m.5-.1.6 1v-.3l-.6-1v.3m1.1-1c0-.1-.3-.2-.5-.1v.3c.2 0 .4 0 .5.2v-.3"/>
|
||||
<path fill="#fff" d="M319.7 198.1a7.5 7.5 0 0 1 1.1 0v-.4a7.5 7.5 0 0 0-1 0c-.1 0 0 .4 0 .4m.6-3c-.3.4-.4.9-.5 1.3v.3s0 .1 0 0c0-.4.2-.8.5-1.1v-.5m-1.5.4.2 1a.7.7 0 0 0 0-.2v-.2l-.2-1v.4m-.3.5a1.6 1.6 0 0 1-.3-.5.8.8 0 0 0 0 .2v.2l.2.5v-.3m-.5.2a4 4 0 0 1-1.2-.6v.4l1.2.6s.1-.4 0-.4"/>
|
||||
<path fill="#dba05f" d="m318.5 196.2-2.2.4-1.8.2-1.3-.4c-.3 0-1.6-.2-2 .3l-.9.8c-.1.1-.7.6-.7.9 0 .2.1.5.4.5.3 0 .9.6.9.7 0 .3.8.5 1.5.5 1.3 0 2-.7 4-.5 1 .2 3-.7 3.4-1.2.4-.5.6-1 .2-1.7-.3-.6-1.4-.5-1.5-.5"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="m318.5 196.2-2.2.4-1.8.2-1.3-.4c-.3 0-1.6-.2-2 .3l-.9.8c-.1.1-.7.6-.7.9 0 .2.1.5.4.5.3 0 .9.6.9.7 0 .3.8.5 1.5.5 1.3 0 2-.7 4-.5 1 .2 3-.7 3.4-1.2.4-.5.6-1 .2-1.7-.3-.6-1.4-.5-1.5-.5z"/>
|
||||
<path d="M311.4 198.1v-.1l.1-.1.1-.2a.8.8 0 0 1 .4-.3h.5-.2.2-.2l-.3.1c-.3 0-.3.4-.6.6"/>
|
||||
<path fill="none" d="m311.3 198 .4-.4.6-.3h.3"/>
|
||||
<path fill="none" d="m312 197.4-.4.3c0 .2-.3.3-.3.3m.7-.5h.5m-.6 0h.5"/>
|
||||
<path d="M312.4 197.9v-.1l-.2.1-.1.1-.3.2-.3.1.4-.2-.4.2.4-.1-.3.1h.1s.3 0 .7-.4"/>
|
||||
<path fill="none" d="m312.3 197.8-.3.2-.3.2-.2.1m.4-.1.2-.2.2-.2m-.4.4-.3.1m.4-.1-.3.1"/>
|
||||
<path fill="#c6262c" d="M312.9 196.5s0-.6-.6-.8c-.5-.2-1-.2-1.3-.2l-.5.2a2.5 2.5 0 0 0-.6.2l-.1.2c-.1.2-.4.4-.3.6.2.3 0 .3.2.3s-1 .3-.8.8c.3.6.5.4.6.3l.5-.2.7-.7 1-.4h.5l.7-.3z"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M312.9 196.5s0-.6-.6-.8c-.5-.2-1-.2-1.3-.2l-.5.2a2.5 2.5 0 0 0-.6.2l-.1.2c-.1.2-.4.4-.3.6.2.3 0 .3.2.3s-1 .3-.8.8c.3.6.5.4.6.3l.5-.2.7-.7 1-.4h.5l.7-.3z"/>
|
||||
<path d="M312.2 197.8c0 .1-.1.3-.3.3h-.3s.1-.4.3-.4h.3"/>
|
||||
<path fill="#d9c0b9" d="M308.6 200.2s-.7-1.2 1.2-1.8c0 0 .6.3.8.6 0 0-.4.5-1.5.7 0 0-.5.1-.5.5"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M308.6 200.2s-.7-1.2 1.2-1.8c0 0 .6.3.8.6 0 0-.4.5-1.5.7 0 0-.5.1-.5.5z"/>
|
||||
<path fill="#d9c0b9" d="M308.8 200s.8.2 1.3-.2c.5-.3.6-.2.7-.1 0 0 0-.4-.2-.7l-1 .5c-.4.2-.7.1-.8.5"/>
|
||||
<path fill="none" stroke="#000" stroke-width=".1" d="M308.8 200s.8.2 1.3-.2c.5-.3.6-.2.7-.1 0 0 0-.4-.2-.7l-1 .5c-.4.2-.7.1-.8.5z"/>
|
||||
<path fill="#7a2e26" d="M311 199.6h.5v-.1h-.5a.3.3 0 0 0 0 .1m-.3-2-.1.2v.1l.1-.2v-.1m.5.2.3-.2v-.1c-.2 0-.3 0-.3.2v.1m.5.8a.3.3 0 0 0 .2-.2.3.3 0 0 1-.2 0v.2m.4-.2a.8.8 0 0 0 .4-.3v-.1a.7.7 0 0 1-.4.3v.1m-.7-.7c0 .2-.2.2-.3.4v.1c0-.1.3-.2.3-.4m.3 2c.4 0 .7 0 1-.2a3.1 3.1 0 0 1-1 0v.2m1.6 0c.4-.4.8-.7 1-1.3a2 2 0 0 1-1 1v.2m.3-.8c.3-.2.5-.4.6-.8v-.1a1.6 1.6 0 0 1-.6.8v.1m-.2-2 .7.4v-.1l-.7-.4v.2m6.3 1c.2-.5 0-1-.2-1.4.2.4.4.8.2 1.2v.2m-4.8-.7c.3.2 1 .7.8 1.2.3-.5-.4-1-.8-1.3v.1m2.1 2a1.4 1.4 0 0 0 .1-.3 1.3 1.3 0 0 1 0 .3"/>
|
||||
<path fill="#5e3f17" d="m317.9 199.2.5-.2m-8.5-.3c-.3.2-.8.2-1 .7.2-.5.7-.5 1-.6"/>
|
||||
<path fill="#842116" d="M309.7 197.3c.1 0 .3 0 .3.2a.4.4 0 0 0 0 .1.7.7 0 0 0 0-.3l-.3-.1m.7.4a.7.7 0 0 0-.1-.6v.5m.6-.5c0-.3-.1-.5-.3-.6v.1c.2.1.3.4.3.6a.4.4 0 0 0 0-.1m.5-.1c0-.3 0-.5-.2-.6v.1l.2.3a.4.4 0 0 0 0 .1m-.8-.7c.4-.2 1.4-.3 1.8.2v-.2c-.4-.4-1.4-.3-1.8 0"/>
|
||||
<path fill="#7a2e26" d="M309.5 198.1v-.5s-.1 0 0 .1v.4m4.7 1.4a.6.6 0 0 0 .3-.5.6.6 0 0 1-.3.3v.2m.7 0a.4.4 0 0 0 .1-.3v-.1.3m4.3-2.4a1 1 0 0 1 0 .7.4.4 0 0 0 0 .1v-.9.1m-.5.5v.7c.1-.3.2-.6 0-.9v.2m-.4.3"/>
|
||||
<path fill="#452c25" d="M324.3 210.5v.2l.1.1-.1-.4z"/>
|
||||
<path fill="#dcddde" d="M314.4 195c-1.7 0-3.3-1-3.3-1a2.7 2.7 0 0 1-2.3-2.4c-.8-.4-1.6-2.5-1.6-2.5-1.3.7-3 0-3 0s0-.4-1.4 0c-1.5.3-1.3-.3-1.3-.3s.6-.6-2 0 .2-.8.2-.8c-.8.2-3.3.4-3.3.4-.9 0-1.8.5-2.8.8l-2.3.6-6.8 3-5.5 2.1c.2 0 3.4-2.1 7.5-4a87.8 87.8 0 0 1 10.3-3.9 9.9 9.9 0 0 1 6.5 0c.6.2 4.2 0 5.7 0 1.6.3 1.8 2.9 1.8 2.9.3.1.4 2.6.4 2.6s-1 0 .1.1c1 .2 2.9 1.7 2.9 1.7h.7s.4-.5.9-.7l1.5-.5a11.6 11.6 0 0 1 2 0l2 .3 1.2.3h.5c1-.5 3-1.2 3.4-1.1 0 0 .7-.2 1.1-.5a105 105 0 0 0 1.3-1s-.6-4.5 3.9-4l11.5 1.2a43.9 43.9 0 0 1 6.5 1.8l5.2 2.4 4 1.7c2.3 1 4 2.4 4 2.4-1.5-.6-2.6-1.3-3.7-1.8-.9-.4-1.8-.5-2.6-.9l-3.6-1.7c-3.5-1.6-3.5-1.7-4.9-1.8-1 0 .7 1.2.7 1.2l-4.1-1.7a6 6 0 0 0-2.9-.5 5.8 5.8 0 0 1-2.2-.3c-.6-.2-3.8-.3-4.4-.4a7.3 7.3 0 0 1-1-.2l.2.4-1.5-.3-.5.7s-1.5.3-1.6-.2c-.1-.5-1 2.2-1.3 3-.4.8-2.2.6-2.7 1-.4.5-1.4.9-1.6 1h-1.3c-.6 0-.1 0-1 .3 0 0-.9 0-1.2-.2l-1.4-.4a27.5 27.5 0 0 0-3.5-.2 5.4 5.4 0 0 0-2.7 1.1"/>
|
||||
<path fill="#e7e7e7" stroke="#000" stroke-width=".1" d="M314.4 195c-1.7 0-3.3-1-3.3-1a2.7 2.7 0 0 1-2.3-2.4c-.8-.4-1.6-2.5-1.6-2.5-1.3.7-3 0-3 0s0-.4-1.4 0c-1.5.3-1.3-.3-1.3-.3s.6-.6-2 0 .2-.8.2-.8c-.8.2-3.3.4-3.3.4-.9 0-1.8.5-2.8.8l-2.3.6-6.8 3-5.5 2.1c.2 0 3.4-2.1 7.5-4a87.8 87.8 0 0 1 10.3-3.9 9.9 9.9 0 0 1 6.5 0c.6.2 4.2 0 5.7 0 1.6.3 1.8 2.9 1.8 2.9.3.1.4 2.6.4 2.6s-1 0 .1.1c1 .2 2.9 1.7 2.9 1.7h.7s.4-.5.9-.7l1.5-.5a11.6 11.6 0 0 1 2 0l2 .3 1.2.3h.5c1-.5 3-1.2 3.4-1.1 0 0 .7-.2 1.1-.5l1.3-1s-.6-4.5 3.9-4l11.5 1.2a43.9 43.9 0 0 1 6.5 1.8l5.2 2.4 4 1.7c2.3 1 4 2.4 4 2.4-1.5-.6-2.6-1.3-3.7-1.8-.9-.4-1.8-.5-2.6-.9l-3.6-1.7c-3.5-1.6-3.5-1.7-4.9-1.8-1 0 .7 1.2.7 1.2l-4.1-1.7a6 6 0 0 0-2.9-.5 5.8 5.8 0 0 1-2.2-.3c-.6-.2-3.8-.3-4.4-.4a7.3 7.3 0 0 1-1-.2l.2.4-1.5-.3-.5.7s-1.5.3-1.6-.2c-.1-.5-1 2.2-1.3 3-.4.8-2.2.6-2.7 1-.4.5-1.4.9-1.6 1h-1.3c-.6 0-.1 0-1 .3 0 0-.9 0-1.2-.2a17.9 17.9 0 0 0-1.4-.4c-.5-.2-3.1-.2-3.5-.2a5.4 5.4 0 0 0-2.7 1.1"/>
|
||||
<path fill="#452c25" d="M314.6 194.4s-.2.2-.2.5v.2"/>
|
||||
<path fill="#574f4c" d="m323.3 194 .7.5a.5.5 0 0 0-.1-.1 6.5 6.5 0 0 0-.7-.6.6.6 0 0 0 0 .1"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 111 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-bq" viewBox="0 0 640 480">
|
||||
<path fill="#21468b" d="M0 0h640v480H0z"/>
|
||||
<path fill="#fff" d="M0 0h640v320H0z"/>
|
||||
<path fill="#ae1c28" d="M0 0h640v160H0z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 221 B |
@@ -1,45 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-br" viewBox="0 0 640 480">
|
||||
<g stroke-width="1pt">
|
||||
<path fill="#229e45" fill-rule="evenodd" d="M0 0h640v480H0z"/>
|
||||
<path fill="#f8e509" fill-rule="evenodd" d="m321.4 436 301.5-195.7L319.6 44 17.1 240.7 321.4 436z"/>
|
||||
<path fill="#2b49a3" fill-rule="evenodd" d="M452.8 240c0 70.3-57.1 127.3-127.6 127.3A127.4 127.4 0 1 1 452.8 240z"/>
|
||||
<path fill="#ffffef" fill-rule="evenodd" d="m283.3 316.3-4-2.3-4 2 .9-4.5-3.2-3.4 4.5-.5 2.2-4 1.9 4.2 4.4.8-3.3 3m86 26.3-3.9-2.3-4 2 .8-4.5-3.1-3.3 4.5-.5 2.1-4.1 2 4.2 4.4.8-3.4 3.1m-36.2-30-3.4-2-3.5 1.8.8-3.9-2.8-2.9 4-.4 1.8-3.6 1.6 3.7 3.9.7-3 2.7m87-8.5-3.4-2-3.5 1.8.8-3.9-2.7-2.8 3.9-.4 1.8-3.5 1.6 3.6 3.8.7-2.9 2.6m-87.3-22-4-2.2-4 2 .8-4.6-3.1-3.3 4.5-.5 2.1-4.1 2 4.2 4.4.8-3.4 3.2m-104.6-35-4-2.2-4 2 1-4.6-3.3-3.3 4.6-.5 2-4.1 2 4.2 4.4.8-3.3 3.1m13.3 57.2-4-2.3-4 2 .9-4.5-3.2-3.3 4.5-.6 2.1-4 2 4.2 4.4.8-3.3 3.1m132-67.3-3.6-2-3.6 1.8.8-4-2.8-3 4-.5 1.9-3.6 1.7 3.8 4 .7-3 2.7m-6.7 38.3-2.7-1.6-2.9 1.4.6-3.2-2.2-2.3 3.2-.4 1.5-2.8 1.3 3 3 .5-2.2 2.2m-142.2 50.4-2.7-1.5-2.7 1.3.6-3-2.1-2.2 3-.4 1.4-2.7 1.3 2.8 3 .6-2.3 2M419 299.8l-2.2-1.1-2.2 1 .5-2.3-1.7-1.6 2.4-.3 1.2-2 1 2 2.5.5-1.9 1.5"/>
|
||||
<path fill="#ffffef" fill-rule="evenodd" d="m219.3 287.6-2.7-1.5-2.7 1.3.6-3-2.1-2.2 3-.4 1.4-2.7 1.3 2.8 3 .6-2.3 2"/>
|
||||
<path fill="#ffffef" fill-rule="evenodd" d="m219.3 287.6-2.7-1.5-2.7 1.3.6-3-2.1-2.2 3-.4 1.4-2.7 1.3 2.8 3 .6-2.3 2m42.3 3-2.6-1.4-2.7 1.3.6-3-2.1-2.2 3-.4 1.4-2.7 1.3 2.8 3 .5-2.3 2.1m-4.8 17-2.6-1.5-2.7 1.4.6-3-2.1-2.3 3-.4 1.4-2.7 1.3 2.8 3 .6-2.3 2m87.4-22.2-2.6-1.6-2.8 1.4.6-3-2-2.3 3-.3 1.4-2.7 1.2 2.8 3 .5-2.2 2.1m-25.1 3-2.7-1.5-2.7 1.4.6-3-2-2.3 3-.3 1.4-2.8 1.2 2.9 3 .5-2.2 2.1m-68.8-5.8-1.7-1-1.7.8.4-1.9-1.3-1.4 1.9-.2.8-1.7.8 1.8 1.9.3-1.4 1.3m167.8 45.4-2.6-1.5-2.7 1.4.6-3-2.1-2.3 3-.4 1.4-2.7 1.3 2.8 3 .6-2.3 2m-20.8 6-2.2-1.4-2.3 1.2.5-2.6-1.7-1.8 2.5-.3 1.2-2.3 1 2.4 2.5.4-1.9 1.8m10.4 2.3-2-1.2-2.1 1 .4-2.3-1.6-1.7 2.3-.3 1.1-2 1 2 2.3.5-1.7 1.6m29.1-22.8-2-1-2 1 .5-2.3-1.6-1.7 2.3-.3 1-2 1 2.1 2.1.4-1.6 1.6m-38.8 41.8-2.5-1.4-2.7 1.2.6-2.8-2-2 3-.3 1.3-2.5 1.2 2.6 3 .5-2.3 1.9m.6 14.2-2.4-1.4-2.4 1.3.6-2.8-1.9-2 2.7-.4 1.2-2.5 1.1 2.6 2.7.5-2 2m-19-23.1-1.9-1.2-2 1 .4-2.2-1.5-1.7 2.2-.2 1-2 1 2 2.2.4-1.6 1.6m-17.8 2.3-2-1.2-2 1 .5-2.2-1.6-1.7 2.3-.2 1-2 1 2 2.1.4-1.6 1.6m-30.4-24.6-2-1.1-2 1 .5-2.3-1.6-1.6 2.2-.3 1-2 1 2 2.2.5-1.6 1.5m3.7 57-1.6-.9-1.8.9.4-2-1.3-1.4 1.9-.2.9-1.7.8 1.8 1.9.3-1.4 1.3m-46.2-86.6-4-2.3-4 2 .9-4.5-3.2-3.3 4.5-.6 2.2-4 1.9 4.2 4.4.8-3.3 3.1"/>
|
||||
<path fill="#fff" fill-rule="evenodd" d="M444.4 285.8a124.6 124.6 0 0 0 5.8-19.8c-67.8-59.5-143.3-90-238.7-83.7a124.5 124.5 0 0 0-8.5 20.9c113-10.8 196 39.2 241.4 82.6z"/>
|
||||
<path fill="#309e3a" d="m414 252.4 2.3 1.3a3.4 3.4 0 0 0-.3 2.2 3 3 0 0 0 1.4 1.7c.7.5 1.4.8 2 .7.6 0 1-.3 1.3-.7a1.3 1.3 0 0 0 .2-.9 2.3 2.3 0 0 0-.5-1c-.2-.3-.7-1-1.5-1.8a7.7 7.7 0 0 1-1.8-3 3.7 3.7 0 0 1 2-4.4 3.8 3.8 0 0 1 2.3-.2 7 7 0 0 1 2.6 1.2c1.4 1 2.3 2 2.6 3.2a4.1 4.1 0 0 1-.6 3.3l-2.4-1.5c.3-.6.4-1.2.2-1.7-.1-.5-.5-1-1.2-1.4a3.2 3.2 0 0 0-1.8-.7 1 1 0 0 0-.9.5c-.2.3-.2.6-.1 1s.6 1.2 1.6 2.2c1 1 1.6 1.9 2 2.5a3.9 3.9 0 0 1-.3 4.2 4.1 4.1 0 0 1-1.9 1.5 4 4 0 0 1-2.4.3c-.9-.2-1.8-.6-2.8-1.3-1.5-1-2.4-2.1-2.7-3.3a5.4 5.4 0 0 1 .6-4zm-11.6-7.6 2.5 1.3a3.4 3.4 0 0 0-.2 2.2 3 3 0 0 0 1.4 1.6c.8.5 1.4.7 2 .6.6 0 1-.3 1.3-.8a1.3 1.3 0 0 0 .2-.8c0-.3-.2-.7-.5-1a34.6 34.6 0 0 0-1.6-1.8c-1.1-1.1-1.8-2-2-2.8a3.7 3.7 0 0 1 .4-3.1 3.6 3.6 0 0 1 1.6-1.4 3.8 3.8 0 0 1 2.2-.3 7 7 0 0 1 2.6 1c1.5 1 2.4 2 2.7 3.1a4.1 4.1 0 0 1-.4 3.4l-2.5-1.4c.3-.7.4-1.2.2-1.7s-.6-1-1.3-1.4a3.2 3.2 0 0 0-1.9-.6 1 1 0 0 0-.8.5c-.2.3-.2.6-.1 1s.7 1.2 1.7 2.2c1 1 1.7 1.8 2 2.4a3.9 3.9 0 0 1 0 4.2 4.2 4.2 0 0 1-1.8 1.6 4 4 0 0 1-2.4.3 8 8 0 0 1-2.9-1.1 6 6 0 0 1-2.8-3.2 5.4 5.4 0 0 1 .4-4zm-14.2-3.8 7.3-12 8.8 5.5-1.2 2-6.4-4-1.6 2.7 6 3.7-1.3 2-6-3.7-2 3.3 6.7 4-1.2 2-9-5.5zm-20.7-17 1.1-2 5.4 2.7-2.5 5c-.8.2-1.8.3-3 .2a9.4 9.4 0 0 1-3.3-1 7.7 7.7 0 0 1-3-2.6 6 6 0 0 1-1-3.5 8.6 8.6 0 0 1 1-3.7 8 8 0 0 1 2.6-3 6.2 6.2 0 0 1 3.6-1.1c1 0 2 .3 3.2 1 1.6.7 2.6 1.7 3.1 2.8a5 5 0 0 1 .3 3.5l-2.7-.8a3 3 0 0 0-.2-2c-.3-.6-.8-1-1.6-1.4a3.8 3.8 0 0 0-3.1-.3c-1 .3-1.9 1.2-2.6 2.6-.7 1.4-1 2.7-.7 3.8a3.7 3.7 0 0 0 2 2.4c.5.3 1.1.5 1.7.5a6 6 0 0 0 1.8 0l.8-1.6-2.9-1.5zm-90.2-22.3 2-14 4.2.7 1.1 9.8 3.9-9 4.2.6-2 13.8-2.7-.4 1.7-10.9-4.4 10.5-2.7-.4-1.1-11.3-1.6 11-2.6-.4zm-14.1-1.7 1.3-14 10.3 1-.2 2.4-7.5-.7-.3 3 7 .7-.3 2.4-7-.7-.3 3.8 7.8.7-.2 2.4-10.6-1z"/>
|
||||
<g stroke-opacity=".5">
|
||||
<path fill="#309e3a" d="M216.5 191.3c0-1.5.3-2.6.7-3.6a6.7 6.7 0 0 1 1.4-1.9 5.4 5.4 0 0 1 1.8-1.2c1-.3 2-.5 3-.5 2.1 0 3.7.8 5 2a7.4 7.4 0 0 1 1.6 5.5c0 2.2-.7 4-2 5.3a6.5 6.5 0 0 1-5 1.7 6.6 6.6 0 0 1-4.8-2 7.3 7.3 0 0 1-1.7-5.3z"/>
|
||||
<path fill="#f7ffff" d="M219.4 191.3c0 1.5.3 2.7 1 3.6.7.8 1.6 1.3 2.8 1.3a3.5 3.5 0 0 0 2.8-1.1c.7-.8 1-2 1.1-3.7 0-1.6-.2-2.8-1-3.6a3.5 3.5 0 0 0-2.7-1.3 3.6 3.6 0 0 0-2.8 1.2c-.8.8-1.1 2-1.2 3.6z"/>
|
||||
</g>
|
||||
<g stroke-opacity=".5">
|
||||
<path fill="#309e3a" d="m233 198.5.2-14h6c1.5 0 2.5.2 3.2.5.7.2 1.2.7 1.6 1.3s.6 1.4.6 2.3a3.8 3.8 0 0 1-1 2.6 4.5 4.5 0 0 1-2.7 1.2l1.5 1.2c.4.4.9 1.2 1.5 2.3l1.7 2.8h-3.4l-2-3.2-1.4-2a2.1 2.1 0 0 0-.9-.6 5 5 0 0 0-1.4-.2h-.6v5.8H233z"/>
|
||||
<path fill="#fff" d="M236 190.5h2c1.4 0 2.3 0 2.6-.2.3 0 .6-.3.8-.5s.3-.7.3-1c0-.6-.1-1-.4-1.2-.2-.3-.6-.5-1-.6h-2l-2.3-.1v3.5z"/>
|
||||
</g>
|
||||
<g stroke-opacity=".5">
|
||||
<path fill="#309e3a" d="m249 185.2 5.2.3c1.1 0 2 .1 2.6.3a4.7 4.7 0 0 1 2 1.4 6 6 0 0 1 1.2 2.4c.3.9.4 2 .3 3.3a9.3 9.3 0 0 1-.5 3c-.4 1-1 1.8-1.7 2.4a5 5 0 0 1-2 1c-.6.2-1.5.2-2.5.2l-5.3-.3.7-14z"/>
|
||||
<path fill="#fff" d="m251.7 187.7-.5 9.3h3.8c.5 0 .9-.2 1.2-.5.3-.3.6-.7.8-1.3.2-.6.4-1.5.4-2.6l-.1-2.5a3.2 3.2 0 0 0-.8-1.4 2.7 2.7 0 0 0-1.2-.7 13 13 0 0 0-2.3-.3h-1.3z"/>
|
||||
</g>
|
||||
<g stroke-opacity=".5">
|
||||
<path fill="#309e3a" d="m317.6 210.2 3.3-13.6 4.4 1 3.2 1c.7.4 1.3 1 1.6 1.9.4.8.4 1.7.2 2.8-.2.8-.5 1.5-1 2a3.9 3.9 0 0 1-3 1.4c-.7 0-1.7-.2-3-.5l-1.7-.5-1.2 5.2-2.8-.7z"/>
|
||||
<path fill="#fff" d="m323 199.6-.8 3.8 1.5.4c1 .2 1.8.4 2.2.3a1.9 1.9 0 0 0 1.6-1.5c0-.5 0-.9-.2-1.3a2 2 0 0 0-1-.9l-1.9-.5-1.3-.3z"/>
|
||||
</g>
|
||||
<g stroke-opacity=".5">
|
||||
<path fill="#309e3a" d="m330.6 214.1 4.7-13.2 5.5 2c1.5.5 2.4 1 3 1.4.5.5.9 1 1 1.8s.2 1.5 0 2.3c-.4 1-1 1.7-1.8 2.2-.8.4-1.8.5-3 .3.4.5.8 1 1 1.6l.8 2.7.6 3.1-3.1-1.1-1-3.6a19.5 19.5 0 0 0-.7-2.4 2.1 2.1 0 0 0-.6-.8c-.2-.3-.6-.5-1.3-.7l-.5-.2-2 5.6-2.6-1z"/>
|
||||
<path fill="#fff" d="m336 207.4 1.9.7c1.3.5 2.1.7 2.5.7.3 0 .6 0 .9-.3.3-.2.5-.5.6-.9.2-.4.2-.8 0-1.2a1.7 1.7 0 0 0-.8-.9l-2-.7-2-.7-1.2 3.3z"/>
|
||||
</g>
|
||||
<g stroke-opacity=".5">
|
||||
<path fill="#309e3a" d="M347 213.6a9 9 0 0 1 1.7-3.2 6.6 6.6 0 0 1 1.8-1.5 6 6 0 0 1 2-.7c1 0 2 0 3.1.4a6.5 6.5 0 0 1 4.2 3.3c.8 1.6.8 3.5.2 5.7a7.4 7.4 0 0 1-3.4 4.5c-1.5.9-3.3 1-5.2.4a6.6 6.6 0 0 1-4.2-3.3 7.3 7.3 0 0 1-.2-5.6z"/>
|
||||
<path fill="#fff" d="M349.8 214.4c-.4 1.5-.5 2.8 0 3.8s1.2 1.6 2.3 2c1 .3 2 .2 3-.4 1-.5 1.6-1.6 2.1-3.2.5-1.5.5-2.7 0-3.7a3.5 3.5 0 0 0-2.2-2 3.6 3.6 0 0 0-3 .3c-1 .6-1.7 1.6-2.2 3.2z"/>
|
||||
</g>
|
||||
<g stroke-opacity=".5">
|
||||
<path fill="#309e3a" d="m374.3 233.1 6.4-12.4 5.3 2.7a10 10 0 0 1 2.7 1.9c.5.5.8 1.1.8 1.9s0 1.5-.4 2.2a3.8 3.8 0 0 1-2 2c-1 .2-2 .2-3.1-.2.4.6.6 1.2.8 1.7.2.6.3 1.5.4 2.8l.2 3.2-3-1.5-.4-3.7a20 20 0 0 0-.3-2.5 2 2 0 0 0-.5-1l-1.2-.7-.5-.3-2.7 5.2-2.5-1.3z"/>
|
||||
<path fill="#fff" d="m380.5 227.2 1.9 1c1.2.6 2 1 2.3 1 .3 0 .7 0 1-.2.3-.1.5-.4.7-.8.2-.4.3-.8.2-1.2a2 2 0 0 0-.7-1 23.7 23.7 0 0 0-1.8-1l-2-1-1.6 3.2z"/>
|
||||
</g>
|
||||
<g stroke-opacity=".5">
|
||||
<path fill="#309e3a" d="M426.1 258.7a8.9 8.9 0 0 1 2.5-2.6 6.6 6.6 0 0 1 2.2-.9 5.5 5.5 0 0 1 2.2 0c1 .2 1.9.6 2.8 1.2a6.6 6.6 0 0 1 3 4.4c.3 1.7-.2 3.6-1.4 5.5a7.3 7.3 0 0 1-4.5 3.3 6.5 6.5 0 0 1-5.2-1.1 6.6 6.6 0 0 1-3-4.4c-.3-1.8.2-3.6 1.4-5.4z"/>
|
||||
<path fill="#fff" d="M428.6 260.3c-1 1.3-1.3 2.5-1.1 3.6a3.6 3.6 0 0 0 1.6 2.5c1 .7 2 .9 3 .6 1-.3 2-1 2.9-2.4.9-1.4 1.3-2.6 1.1-3.6-.1-1-.7-1.9-1.6-2.6s-2-.8-3-.5c-1 .2-2 1-3 2.4z"/>
|
||||
</g>
|
||||
<path fill="#309e3a" d="m301.8 204.5 2.3-9.8 7.2 1.7-.3 1.6-5.3-1.2-.5 2.2 4.9 1.1-.4 1.7-4.9-1.2-.6 2.7 5.5 1.3-.4 1.6-7.5-1.7z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 8.0 KiB |