chore: 初始提交 - 移除所有硬编码凭据,统一从环境变量读取

This commit is contained in:
yangxiangyuan
2026-06-11 17:10:58 +08:00
commit c223c79b36
1699 changed files with 313940 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
# ===== 开发依赖 =====
node_modules/
# ===== Windows 独有 =====
winform/
.DS_Store
Thumbs.db
desktop.ini
# ===== 运行时数据(服务器重新生成)=====
data/
logs/
temp/
.dbg/
exports/
backups/
Toolbox-Weekly-Backup/
# ===== 前端大文件/素材(服务器不需要)=====
public/images/korean_references/
public/images/zhihu/
public/images/wave_references/
public/images/x_fashion/
public/images/style_check_images/
public/home-bg/
public/tools/apple_watch/apple_health_export/
public/download_files/
# ===== 上传文件 =====
uploads/
# ===== 脚本 =====
scripts/
# ===== 本地凭证(含密码/密钥,不上传)=====
*.env.local
config/
public/tools/markets/auth_config.json
# ===== SSL 证书(服务器另有自己的)=====
umersoft.com_OV_SSL/
# ===== 调试/临时文件 =====
*.md
*.txt
cookies.txt
_fix_*.js
_verify*.js
_verify2*.js
check_*.js
debug-*.md
example_auto_*.js
get_cookie_*.js
OSS权限.txt
.tmp_db_path.js
tmp_*.js
reproduce_issue.js
verify_db*.js
~\$*.docx
# ===== IIS/构建配置(服务器不需要)=====
web.config
webpack.config.js
install_service_8977.bat
uninstall_service_8977.bat
# ===== 杂项 =====
.vscode/
query
service/
/tools/
+11029
View File
File diff suppressed because it is too large Load Diff
+54
View File
@@ -0,0 +1,54 @@
{
"name": "yangs-toolbox",
"version": "0.1.0",
"private": true,
"main": "src/server/index.js",
"engines": {
"node": ">=22 <24"
},
"scripts": {
"start": "\"D:\\ProgramData\\nodejs_22\\node.exe\" src/server/index.js",
"start22": "\"D:\\ProgramData\\nodejs_22\\node.exe\" src/server/index.js",
"start:5051": "set PORT=5051&& \"D:\\ProgramData\\nodejs_22\\node.exe\" src/server/index.js",
"start:8976": "set PORT=8976&& \"D:\\ProgramData\\nodejs_22\\node.exe\" src/server/index.js",
"start:8977": "set PORT=8977&& \"D:\\ProgramData\\nodejs_22\\node.exe\" src/server/index.js",
"upgrade:expense": "\"D:\\ProgramData\\nodejs_22\\node.exe\" scripts/upgrade_expense_db.js",
"test": "\"D:\\ProgramData\\nodejs_22\\node.exe\" src/server/test_weekly_modular.js",
"lint": "powershell -NoProfile -Command \"Get-ChildItem -Recurse -Filter *.js -Path src,public | Where-Object { $_.FullName -notmatch '\\\\node_modules\\\\' -and $_.FullName -notmatch '\\\\public\\\\lib\\\\' -and $_.FullName -notmatch '\\\\public\\\\tools\\\\cloud_notes\\\\tinymce\\\\' -and $_.FullName -notmatch '\\\\public\\\\tools\\\\rebalance\\\\lib\\\\' -and $_.Name -notmatch '\\.min\\.js$' } | ForEach-Object { & 'D:\\\\ProgramData\\\\nodejs_22\\\\node.exe' --check $_.FullName }\"",
"typecheck": "npm run lint"
},
"dependencies": {
"@alicloud/pop-core": "^1.8.0",
"@univerjs/presets": "^0.19.0",
"@univerjs/protocol": "^0.1.48",
"@univerjs/ui": "^0.19.0",
"archiver": "^7.0.1",
"axios": "^1.7.5",
"better-sqlite3": "^9.4.5",
"cors": "^2.8.5",
"express": "^4.21.1",
"iconv-lite": "^0.6.3",
"imapflow": "^1.3.3",
"mailparser": "^3.9.8",
"mammoth": "^1.12.0",
"multer": "^2.0.2",
"nodemailer": "^6.9.8",
"pdf-parse": "^2.4.5",
"puppeteer": "^24.40.0",
"puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"qrcode": "^1.5.4",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"unzipper": "^0.10.14",
"word-extractor": "^1.0.4",
"ws": "^8.18.0",
"xlsx": "^0.18.5"
},
"devDependencies": {
"css-loader": "^7.1.4",
"esbuild": "^0.27.4",
"style-loader": "^4.0.0",
"tinymce": "^6.8.3"
}
}
+183
View File
@@ -0,0 +1,183 @@
(() => {
const originalFetch = window.fetch
window.fetch = (input, init = {}) => {
const opts = Object.assign({}, init)
if (!opts.credentials) opts.credentials = 'include'
return originalFetch(input, opts)
}
const overlayId = 'authOverlay'
const ensureOverlay = () => {
let ov = document.getElementById(overlayId)
if (ov) return ov
ov = document.createElement('div')
ov.id = overlayId
ov.style.position = 'fixed'
ov.style.left = '0'; ov.style.top = '0'; ov.style.right = '0'; ov.style.bottom = '0'
ov.style.display = 'none'
ov.style.alignItems = 'center'
ov.style.justifyContent = 'center'
ov.style.background = 'rgba(0,0,0,0.6)'
ov.style.zIndex = '9999'
const panel = document.createElement('div')
panel.style.background = '#fff'
panel.style.padding = '20px'
panel.style.borderRadius = '8px'
panel.style.boxShadow = '0 4px 12px rgba(0,0,0,0.2)'
const title = document.createElement('div')
title.textContent = '鉴权失败,请重新校验'
title.style.fontSize = '16px'
title.style.marginBottom = '12px'
title.style.color = '#333'
const debug = document.createElement('pre')
debug.id = 'authDebug'
debug.style.fontSize = '12px'
debug.style.lineHeight = '1.5'
debug.style.background = '#f7f7f8'
debug.style.border = '1px solid #e3e3e7'
debug.style.padding = '10px'
debug.style.margin = '0 0 12px 0'
debug.style.maxWidth = '520px'
debug.style.maxHeight = '240px'
debug.style.overflow = 'auto'
debug.textContent = '正在收集诊断信息...'
const btn = document.createElement('button')
btn.textContent = '重新校验'
btn.style.padding = '8px 16px'
btn.addEventListener('click', async () => {
await handshake()
})
panel.appendChild(title)
panel.appendChild(debug)
panel.appendChild(btn)
ov.appendChild(panel)
document.body.appendChild(ov)
return ov
}
const showOverlay = () => { ensureOverlay().style.display = 'flex' }
const hideOverlay = () => { const ov = ensureOverlay(); ov.style.display = 'none' }
let cfg = { enableCookieAuth: true, cookieName: 'rebalance_jwt' }
const loadConfig = async () => {
try {
const res = await fetch('/assets/auth_config.json', { cache: 'no-store' })
if (!res.ok) return
const data = await res.json()
cfg = Object.assign({}, cfg, data || {})
} catch (_) {}
}
const debugState = {
url: '',
config: {},
tokenInUrl: false,
tokenCall: { tried: false, ok: false, status: 0 },
handshake: { tried: false, ok: false, status: 0 },
server: {}
}
const removeTokenFromUrl = () => {
try {
const nu = new URL(window.location.href)
nu.searchParams.delete('token')
window.history.replaceState(null, document.title, nu.toString())
} catch (_) {}
}
const handleTokenInUrl = async () => {
try {
const u = new URL(window.location.href)
const token = u.searchParams.get('token')
debugState.url = u.toString()
debugState.config = { enableCookieAuth: !!cfg.enableCookieAuth, cookieName: String(cfg.cookieName || '') }
debugState.tokenInUrl = !!token
if (token) {
if (cfg.enableCookieAuth) {
const r = await fetch(`/auth/token?token=${encodeURIComponent(token)}`, { method: 'GET' })
debugState.tokenCall.tried = true
debugState.tokenCall.ok = r.ok
debugState.tokenCall.status = r.status || 0
removeTokenFromUrl()
return r.ok
} else {
removeTokenFromUrl()
return true
}
}
} catch (_) {}
return true
}
const handshake = async () => {
if (!cfg.enableCookieAuth) { hideOverlay(); return true }
try {
const r = await fetch('/auth/handshake', { cache: 'no-store' })
debugState.handshake.tried = true
debugState.handshake.ok = r.ok
debugState.handshake.status = r.status || 0
/*
try {
const dbgRes = await fetch('/auth/debug', { cache: 'no-store' })
try {
const body = await dbgRes.json()
debugState.server = body
} catch (_) {
debugState.server = { error: 'debug parse failed', status: dbgRes.status || 0 }
}
} catch (e) {
debugState.server = { error: 'debug request failed' }
}
*/
const box = document.getElementById('authDebug')
if (box) {
const lines = []
lines.push(`URL: ${debugState.url}`)
lines.push(`Config: enableCookieAuth=${debugState.config.enableCookieAuth} cookieName=${debugState.config.cookieName}`)
lines.push(`TokenInUrl: ${debugState.tokenInUrl}`)
lines.push(`TokenCall: tried=${debugState.tokenCall.tried} ok=${debugState.tokenCall.ok} status=${debugState.tokenCall.status}`)
lines.push(`Handshake: tried=${debugState.handshake.tried} ok=${debugState.handshake.ok} status=${debugState.handshake.status}`)
if (debugState.server && typeof debugState.server === 'object') {
lines.push(`Server.enableAuth: ${debugState.server.enableAuth}`)
lines.push(`Server.jwkLoaded: ${debugState.server.jwkLoaded}`)
lines.push(`Server.cookieName: ${debugState.server.cookieName}`)
lines.push(`Server.cookiePresent: ${debugState.server.cookiePresent}`)
lines.push(`Server.verified: ${debugState.server.verified}`)
lines.push(`Server.keysCount: ${debugState.server.keysCount}`)
try {
const ks = Array.isArray(debugState.server.keysSources) ? debugState.server.keysSources : []
lines.push(`Server.keysSources: ${JSON.stringify(ks)}`)
} catch (_) {}
try {
const th = debugState.server.tokenHeader || {}
const tp = debugState.server.tokenPayload || {}
lines.push(`Server.tokenHeader.alg: ${th.alg || ''}`)
lines.push(`Server.tokenPayload.iss: ${tp.iss || ''}`)
lines.push(`Server.tokenPayload.aud: ${tp.aud || ''}`)
lines.push(`Server.tokenPayload.exp: ${tp.exp || ''}`)
} catch (_) {}
if (debugState.server.error) {
lines.push(`Server.error: ${debugState.server.error}`)
}
const rq = debugState.server.request || {}
lines.push(`Server.request.host: ${rq.host || ''}`)
lines.push(`Server.request.path: ${rq.path || ''}`)
lines.push(`Server.request.origin: ${rq.origin || ''}`)
lines.push(`Server.request.secFetchMode: ${rq.secFetchMode || ''}`)
lines.push(`Server.request.forwardedProto: ${rq.forwardedProto || ''}`)
lines.push(`Server.request.secure: ${rq.secure}`)
lines.push(`Server.request.proto: ${rq.proto || ''}`)
} else {
lines.push(`Server: ${String(debugState.server)}`)
}
lines.push(`Expected URLs: /auth/token?token=... , /auth/handshake , /api/...`)
box.textContent = lines.join('\n')
}
if (r.ok) { hideOverlay(); return true }
showOverlay(); return false
} catch (_) { showOverlay(); return false }
}
const init = async () => {
await loadConfig()
await handleTokenInUrl()
await handshake()
}
if (document.readyState === 'complete' || document.readyState === 'interactive') {
init()
} else {
document.addEventListener('DOMContentLoaded', init)
}
})()
+7
View File
@@ -0,0 +1,7 @@
{
"_comment": "公共静态资源下,与 Rebalance 相关的 JWT 鉴权配置",
"cookieName_comment": "用于识别已登录用户的 JWT cookie 名称",
"cookieName": "rebalance_jwt",
"enableCookieAuth_comment": "true:启用基于 cookie 的鉴权;false:不校验登录状态",
"enableCookieAuth": true
}
+19
View File
@@ -0,0 +1,19 @@
* { box-sizing: border-box }
body { margin: 0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif }
.topbar { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; border-bottom: 1px solid #ddd; position: sticky; top: 0; background: #fff; z-index: 10 }
.tabs { display: flex; gap: 8px }
.tab { border: none; background: #f5f5f5; padding: 8px 12px; border-radius: 8px; cursor: pointer; text-decoration: none; color: inherit }
.tab.active { background: #222; color: #fff }
.settings { border: none; background: #fff; padding: 6px 10px; border: 1px solid #222; border-radius: 6px; cursor: pointer }
main { padding: 12px }
.modal { position: fixed; inset: 0; display: grid; place-items: center; background: rgba(0,0,0,0.35); z-index: 1000 }
.hidden { display: none }
.modal-body { background: #fff; width: 520px; max-width: 90vw; border-radius: 10px; padding: 16px; display: grid; gap: 8px }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px }
mark { background: #ffe58f }
.kw-0 { background: #ffe58f }
.kw-1 { background: #ffd6e7 }
.kw-2 { background: #d6f5ff }
.kw-3 { background: #d9f7be }
.kw-4 { background: #fff1b8 }
.kw-5 { background: #efdbff }
+61
View File
@@ -0,0 +1,61 @@
const el = id => document.getElementById(id)
const highlight = (text, terms) => {
if (!terms || terms.length === 0) return text
let s = text
terms.forEach((t, i) => {
const cls = `kw-${i % 6}`
const re = new RegExp(`(${t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi')
s = s.replace(re, `<mark class="${cls}">$1</mark>`)
})
return s
}
const fmtCNDateTime = (d) => {
const date = d instanceof Date ? d : new Date()
try {
const s = new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).format(date)
return s.replace(/\//g, '-').replace(/\u200E/g, '')
} catch {
const pad = n => String(n).padStart(2, '0')
const y = date.getFullYear(), m = pad(date.getMonth()+1), day = pad(date.getDate()), hh = pad(date.getHours()), mm = pad(date.getMinutes()), ss = pad(date.getSeconds())
return `${y}-${m}-${day} ${hh}:${mm}:${ss}`
}
}
const fmtCNSimpleTime = (d) => {
const date = d instanceof Date ? d : new Date()
try {
const s = new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', hour: '2-digit', minute: '2-digit', hour12: false }).format(date)
return s.replace(/\u200E/g, '')
} catch {
const pad = n => String(n).padStart(2, '0')
return `${pad(date.getHours())}:${pad(date.getMinutes())}`
}
}
const cnDateStr = (d) => {
const date = d instanceof Date ? d : new Date()
try {
const s = new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit' }).format(date)
return s.replace(/\//g, '-').replace(/\u200E/g, '')
} catch {
const pad = n => String(n).padStart(2, '0')
return `${date.getFullYear()}-${pad(date.getMonth()+1)}-${pad(date.getDate())}`
}
}
window.fmtCNDateTime = fmtCNDateTime
window.fmtCNSimpleTime = fmtCNSimpleTime
window.cnDateStr = cnDateStr
;(function handleSetToken() {
try {
const u = new URL(window.location.href)
const token = u.searchParams.get('set_token')
if (token) {
localStorage.setItem('toolbox_creds_token', token)
u.searchParams.delete('set_token')
window.history.replaceState(null, '', u.toString())
}
} catch {}
})()
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
<header class="topbar">
<nav class="tabs">
<a class="tab" href="/go?systemId=Tools-weibo" data-key="weibo">微博跟踪</a>
<a class="tab" href="/go?systemId=Tools-markets" data-key="markets">市场跟踪</a>
<a class="tab" href="/go?systemId=Tools-wall-" data-key="wall">告知墙</a>
<a class="tab" href="/go?systemId=Tools-funds" data-key="funds">本金变动池</a>
<a class="tab" href="/go?systemId=Tools-ccb_private_funds" data-key="ccb_private_funds">建行私募理财</a>
<a class="tab" href="/go?systemId=Tools-cloud" data-key="cloud">云产品管理</a>
<a class="tab" href="/go?systemId=Tools-weekly" data-key="weekly">工作周报</a>
<a class="tab" href="/go?systemId=TRAE-Rebalance&url=https%3A%2F%2Ftraesite.umersoft.com%3A8960%2FRebalance.html" data-key="rebalance">再平衡</a>
<a class="tab" href="/go?systemId=Wager&url=https%3A%2F%2Ftraesite.umersoft.com%3A8956" data-key="wager">投注</a>
<a class="tab" href="/go?systemId=TRAE-PSC&url=https%3A%2F%2Ftraesite.umersoft.com%3A8969%2F" data-key="disk">安全网盘</a>
<a class="tab" href="/go?systemId=FitnessDiary" data-key="fitness">运动日志</a>
<a class="tab" href="/go?systemId=CalendarReminder&url=https%3A%2F%2Ftraesite.umersoft.com%3A8972%2F" data-key="fitness">日历提醒</a>
</nav>
</header>
+26
View File
@@ -0,0 +1,26 @@
(async function(){
try {
const wrap = document.querySelector('#topbar')
if (!wrap) return
const res = await fetch('/common/nav.html')
const html = await res.text()
wrap.innerHTML = html
const path = location.pathname.toLowerCase()
let key = ''
if (path.includes('/tools/weibo/')) key = 'weibo'
else if (path.includes('/tools/markets/')) key = 'markets'
else if (path.includes('/tools/wall/')) key = 'wall'
else if (path.includes('/tools/funds/')) key = 'funds'
else if (path.includes('/tools/ccb_private_funds/')) key = 'ccb_private_funds'
else if (path.includes('/tools/cloud/')) key = 'cloud'
else if (path.includes('/tools/weekly/')) key = 'weekly'
else if (path.includes('/tools/ai-lib/')) key = 'ai-lib'
else if (path.includes('/tools/expense/')) key = 'expense'
if (key) {
wrap.querySelectorAll('a.tab').forEach(a => {
if (a.dataset.key === key) a.classList.add('active')
else a.classList.remove('active')
})
}
} catch {}
})()
+128
View File
@@ -0,0 +1,128 @@
[
{
"name": "地下偶像相关揭示板",
"url": "https://m.weibo.cn/u/7716940453",
"icon": "text_italic.png"
},{
"name": "世界树剧场",
"url": "https://m.weibo.cn/u/7925328421",
"icon": "user_go.png"
},
{
"name": "育音堂",
"url": "https://weibo.com/u/1802208671",
"icon": "weather_sun.png"
},
{
"name": "X下载利器",
"url": "https://ssstwitter.com/",
"icon": "twitter_tool.png"
},
{
"name": "上海地下偶像联盟",
"url": "https://m.weibo.cn/u/7912812433",
"icon": "weibo.png"
},
{
"name": "免费ICON",
"url": "https://igoutu.cn/icons",
"icon": ""
},
{
"name": "培训/导航/LOGO",
"url": "http://112.74.31.221:8888/default.html",
"icon": "HDA.png"
},
{
"name": "Git 服务器",
"url": "http://47.101.56.101:8998/Home/LogOn?ReturnUrl=%2F",
"icon": "HDA.png"
},
{
"name": "禅道 项目系统",
"url": "http://112.74.31.221:82/zentao/user-login-L3plbnRhby9teS5odG1s.html",
"icon": "HDA.png"
},
{
"name": "阿里云-合规报告",
"url": "https://security.aliyun.com/trust-center/compliance?spm=5176.32436255.J_JIpOXHuIiVOM6_FDQtQLN.2.377618c54gQlJa",
"icon": "aliyun.png"
},
{
"name": "硅谷-阿里合同",
"url": "https://traesite.umersoft.com:8975/download_files/%E9%98%BF%E9%87%8C%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%8D%8F%E8%AE%AE.pdf",
"icon": "aliyun.png"
},
{
"name": "在线MP3播放",
"url": "https://music.cpp-prog.com",
"icon": "music.png"
},
{
"name": "上海市医疗器械追溯报告系统",
"url": "https://zssb.yjj.sh.gov.cn",
"icon": "GOV.png"
},
{
"name": "虚拟显示器,USB-MMIDD 驱动",
"url": "https://traesite.umersoft.com:8975/download_files/usbmmidd_v2.zip",
"icon": "download.png"
},
{
"name": "CHROME纯净版X64",
"url": "https://traesite.umersoft.com:8975/download_files/ChromeStandaloneSetup64.exe",
"icon": "download.png"
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
},
{
"name": "测试长标题如果不指定图标",
"url": "#",
"icon": ""
}
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Some files were not shown because too many files have changed in this diff Show More