Initial commit
This commit is contained in:
390
css/style.css
Normal file
390
css/style.css
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
:root {
|
||||||
|
/* Adastra-inspired Theme: Deep Navy & Clean White/Cyan */
|
||||||
|
--bg-body: #020b1c;
|
||||||
|
/* Very dark navy */
|
||||||
|
--bg-sidebar: #051635;
|
||||||
|
/* Lighter navy */
|
||||||
|
--bg-card: #0a1f49;
|
||||||
|
/* Card background blue */
|
||||||
|
--bg-hover: #122b5f;
|
||||||
|
/* Hover state */
|
||||||
|
|
||||||
|
--accent-primary: #00b4d8;
|
||||||
|
/* Bright Cyan/Blue */
|
||||||
|
--accent-secondary: #0077b6;
|
||||||
|
/* Ocean Blue */
|
||||||
|
--accent-glow: rgba(0, 180, 216, 0.4);
|
||||||
|
|
||||||
|
--text-main: #f0f9ff;
|
||||||
|
--text-muted: #94a3b8;
|
||||||
|
--border-color: #1e3a6e;
|
||||||
|
|
||||||
|
--success: #00e676;
|
||||||
|
--warning: #ffb74d;
|
||||||
|
--danger: #ef5350;
|
||||||
|
|
||||||
|
--font-main: 'Plus Jakarta Sans', sans-serif;
|
||||||
|
|
||||||
|
--sidebar-width: 260px;
|
||||||
|
--header-height: 70px;
|
||||||
|
--card-radius: 8px;
|
||||||
|
/* Slightly squarer for corporate look */
|
||||||
|
--transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--font-main);
|
||||||
|
background-color: var(--bg-body);
|
||||||
|
color: var(--text-main);
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-container {
|
||||||
|
display: flex;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar */
|
||||||
|
.sidebar {
|
||||||
|
width: var(--sidebar-width);
|
||||||
|
background-color: var(--bg-sidebar);
|
||||||
|
border-right: 1px solid var(--border-color);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 1.5rem;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-area {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-icon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
|
||||||
|
border-radius: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-area h1 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-area .highlight {
|
||||||
|
color: var(--accent-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-nav {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 0.85rem 1rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: var(--transition);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item i {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item:hover {
|
||||||
|
background-color: var(--bg-hover);
|
||||||
|
color: var(--text-main);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item.active {
|
||||||
|
background-color: rgba(0, 180, 216, 0.1);
|
||||||
|
color: var(--accent-primary);
|
||||||
|
box-shadow: 0 0 12px var(--accent-glow);
|
||||||
|
border: 1px solid rgba(0, 180, 216, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: var(--bg-card);
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-top: auto;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar img {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info .name {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info .role {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main Content */
|
||||||
|
.main-content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar {
|
||||||
|
height: var(--header-height);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 2rem;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
background-color: rgba(15, 17, 26, 0.8);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumbs .current-page {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 1.25rem;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: var(--transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn:hover {
|
||||||
|
background-color: var(--bg-card);
|
||||||
|
color: var(--text-main);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-area {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Common UI Elements */
|
||||||
|
.card {
|
||||||
|
background-color: var(--bg-card);
|
||||||
|
border-radius: var(--card-radius);
|
||||||
|
padding: 1.5rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 0.6rem 1.2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
transition: var(--transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: var(--accent-primary);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #5558e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dashboard Grid */
|
||||||
|
.dashboard-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-trend {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trend-up {
|
||||||
|
color: var(--success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trend-down {
|
||||||
|
color: var(--danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Jobs Table */
|
||||||
|
.table-container {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
padding: 1rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-weight: 500;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 1rem;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
color: var(--text-main);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:last-child td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge {
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: 100px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-success {
|
||||||
|
background-color: rgba(16, 185, 129, 0.1);
|
||||||
|
color: var(--success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-error {
|
||||||
|
background-color: rgba(239, 68, 68, 0.1);
|
||||||
|
color: var(--danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-running {
|
||||||
|
background-color: rgba(99, 102, 241, 0.1);
|
||||||
|
color: var(--accent-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fadeIn 0.4s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
color: var(--text-muted);
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 3px solid rgba(99, 102, 241, 0.3);
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top-color: var(--accent-primary);
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
85
index.html
Normal file
85
index.html
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Adastra BackSTOR</title>
|
||||||
|
<link rel="stylesheet" href="css/style.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap"
|
||||||
|
rel="stylesheet">
|
||||||
|
<!-- Using Phosphor Icons for modern look -->
|
||||||
|
<script src="https://unpkg.com/@phosphor-icons/web"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- Sidebar -->
|
||||||
|
<aside class="sidebar">
|
||||||
|
<div class="logo-area">
|
||||||
|
<div class="logo-icon"><i class="ph ph-hard-drives"></i></div>
|
||||||
|
<h1>Adastra BackSTOR<span class="highlight">UI</span></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="main-nav">
|
||||||
|
<a href="#dashboard" class="nav-item active" data-page="dashboard">
|
||||||
|
<i class="ph ph-squares-four"></i>
|
||||||
|
<span>Dashboard</span>
|
||||||
|
</a>
|
||||||
|
<a href="#jobs" class="nav-item" data-page="jobs">
|
||||||
|
<i class="ph ph-list-dashes"></i>
|
||||||
|
<span>Jobs</span>
|
||||||
|
</a>
|
||||||
|
<a href="#clients" class="nav-item" data-page="clients">
|
||||||
|
<i class="ph ph-desktop"></i>
|
||||||
|
<span>Clients</span>
|
||||||
|
</a>
|
||||||
|
<a href="#storage" class="nav-item" data-page="storage">
|
||||||
|
<i class="ph ph-database"></i>
|
||||||
|
<span>Storage</span>
|
||||||
|
</a>
|
||||||
|
<a href="#settings" class="nav-item" data-page="settings">
|
||||||
|
<i class="ph ph-gear"></i>
|
||||||
|
<span>Settings</span>
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="user-profile">
|
||||||
|
<div class="avatar">
|
||||||
|
<img src="https://ui-avatars.com/api/?name=Admin+User&background=00b4d8&color=fff" alt="Admin">
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<span class="name">Admin User</span>
|
||||||
|
<span class="role">Super Admin</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<main class="main-content">
|
||||||
|
<header class="top-bar">
|
||||||
|
<div class="breadcrumbs">
|
||||||
|
<span class="current-page">Dashboard</span>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="icon-btn"><i class="ph ph-bell"></i></button>
|
||||||
|
<button class="icon-btn"><i class="ph ph-magnifying-glass"></i></button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div id="content-area" class="content-area">
|
||||||
|
<!-- Dynamic Content Will Be Loaded Here -->
|
||||||
|
<div class="loading-state">
|
||||||
|
<div class="spinner"></div>
|
||||||
|
<p>Loading Backup Environment...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="module" src="js/app.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
478
js/app.js
Normal file
478
js/app.js
Normal file
@@ -0,0 +1,478 @@
|
|||||||
|
import { MockApi } from './mock_api.js';
|
||||||
|
import { RealApi } from './real_api.js';
|
||||||
|
|
||||||
|
// Toggle this to switch modes
|
||||||
|
const USE_REAL_API = true;
|
||||||
|
|
||||||
|
const Api = USE_REAL_API ? RealApi : MockApi;
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
const formatBytes = (bytes, decimals = 2) => {
|
||||||
|
if (!+bytes) return '0 Bytes';
|
||||||
|
const k = 1024;
|
||||||
|
const dm = decimals < 0 ? 0 : decimals;
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDate = (dateString) => {
|
||||||
|
if (!dateString) return 'Never';
|
||||||
|
const options = {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit'
|
||||||
|
};
|
||||||
|
return new Date(dateString).toLocaleDateString(undefined, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Component Rendering Functions
|
||||||
|
const renderDashboard = async () => {
|
||||||
|
const stats = await Api.getDashboardStats();
|
||||||
|
const jobs = await Api.getRecentJobs();
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="animate-fade-in">
|
||||||
|
<h2 style="margin-bottom: 1.5rem;">System Overview</h2>
|
||||||
|
|
||||||
|
<div class="dashboard-grid">
|
||||||
|
<div class="card stat-card">
|
||||||
|
<div class="stat-header">
|
||||||
|
<div class="stat-icon" style="background: rgba(99, 102, 241, 0.1); color: var(--accent-primary);">
|
||||||
|
<i class="ph ph-briefcase"></i>
|
||||||
|
</div>
|
||||||
|
<div class="stat-trend trend-up">
|
||||||
|
<i class="ph ph-trend-up"></i> +12%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value">${stats.totalJobs}</div>
|
||||||
|
<div class="stat-label">Total Jobs Run</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card stat-card">
|
||||||
|
<div class="stat-header">
|
||||||
|
<div class="stat-icon" style="background: rgba(16, 185, 129, 0.1); color: var(--success);">
|
||||||
|
<i class="ph ph-check-circle"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value">${stats.successRate}%</div>
|
||||||
|
<div class="stat-label">Success Rate</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card stat-card">
|
||||||
|
<div class="stat-header">
|
||||||
|
<div class="stat-icon" style="background: rgba(236, 72, 153, 0.1); color: var(--accent-secondary);">
|
||||||
|
<i class="ph ph-hard-drives"></i>
|
||||||
|
</div>
|
||||||
|
<div class="stat-trend trend-up">
|
||||||
|
<i class="ph ph-warning"></i> ${stats.storageUsage}% used
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value">${formatBytes(stats.totalBytes)}</div>
|
||||||
|
<div class="stat-label">Total Backup Size</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card stat-card">
|
||||||
|
<div class="stat-header">
|
||||||
|
<div class="stat-icon" style="background: rgba(245, 158, 11, 0.1); color: var(--warning);">
|
||||||
|
<i class="ph ph-desktop"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value">${stats.activeClients}</div>
|
||||||
|
<div class="stat-label">Active Clients</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
|
||||||
|
<h3>Recent Jobs</h3>
|
||||||
|
<button class="btn btn-primary" onclick="window.location.hash='#jobs'">View All</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-container">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Job Name</th>
|
||||||
|
<th>Client</th>
|
||||||
|
<th>Level</th>
|
||||||
|
<th>Files</th>
|
||||||
|
<th>Size</th>
|
||||||
|
<th>Duration</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${jobs.map(job => `
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span class="status-badge status-${job.status.toLowerCase()}">
|
||||||
|
${job.status}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td style="font-weight: 500;">${job.name}</td>
|
||||||
|
<td style="color: var(--text-muted);">${job.client}</td>
|
||||||
|
<td>${job.level}</td>
|
||||||
|
<td>${job.files.toLocaleString()}</td>
|
||||||
|
<td>${formatBytes(job.bytes)}</td>
|
||||||
|
<td>${job.duration}</td>
|
||||||
|
</tr>
|
||||||
|
`).join('')}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// State for Jobs View
|
||||||
|
const jobsState = {
|
||||||
|
filter: 'All',
|
||||||
|
search: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
// Global handlers for filter updates
|
||||||
|
window.updateJobFilter = (value) => {
|
||||||
|
jobsState.filter = value;
|
||||||
|
// Trigger re-render of current page
|
||||||
|
window.dispatchEvent(new Event('hashchange'));
|
||||||
|
};
|
||||||
|
|
||||||
|
window.updateJobSearch = (value) => {
|
||||||
|
jobsState.search = value.toLowerCase();
|
||||||
|
// Debounce re-render could be better, but simple re-render works for now
|
||||||
|
// We'll just re-render the table body via DOM manipulation ideally,
|
||||||
|
// but for simplicity with this router, we can re-trigger route or just rely on input keeping focus if we are careful.
|
||||||
|
// Re-rendering whole page loses focus.
|
||||||
|
// Better strategy: Store the value, but let the user press enter or wait.
|
||||||
|
// For now, let's just make the search work on 'onchange' or 'onkeyup' with a small re-render hack
|
||||||
|
|
||||||
|
// Actually, to avoid losing focus on every keystroke, let's just use the router re-render
|
||||||
|
// but we need to manage focus.
|
||||||
|
// Simplified approach: Just update state. The user has to trigger search?
|
||||||
|
// Or simpler: Just re-render. To keep input focus, we can select it after render.
|
||||||
|
|
||||||
|
const contentArea = document.getElementById('content-area');
|
||||||
|
// For this prototype, a full re-render is jarring.
|
||||||
|
// But let's stick to the request pattern.
|
||||||
|
window.dispatchEvent(new Event('hashchange'));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to keep focus helper (hacky but works for simple vanilla js SPA)
|
||||||
|
const restoreFocus = () => {
|
||||||
|
const searchInput = document.querySelector('#job-search-input');
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.focus();
|
||||||
|
// Move cursor to end
|
||||||
|
const val = searchInput.value;
|
||||||
|
searchInput.value = '';
|
||||||
|
searchInput.value = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderJobs = async () => {
|
||||||
|
const jobs = await Api.getRecentJobs();
|
||||||
|
const allJobs = [...jobs, ...jobs, ...jobs]; // Demo duplication
|
||||||
|
|
||||||
|
// Apply Filters
|
||||||
|
const filteredJobs = allJobs.filter(job => {
|
||||||
|
const matchesStatus = jobsState.filter === 'All' || job.status === jobsState.filter;
|
||||||
|
const matchesSearch = jobsState.search === '' ||
|
||||||
|
job.name.toLowerCase().includes(jobsState.search) ||
|
||||||
|
job.client.toLowerCase().includes(jobsState.search);
|
||||||
|
return matchesStatus && matchesSearch;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Schedule focus restore after render
|
||||||
|
setTimeout(restoreFocus, 0);
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="animate-fade-in">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
|
||||||
|
<h2>Backup Jobs</h2>
|
||||||
|
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
||||||
|
<div style="position: relative;">
|
||||||
|
<i class="ph ph-magnifying-glass" style="position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--text-muted);"></i>
|
||||||
|
<input type="text"
|
||||||
|
id="job-search-input"
|
||||||
|
placeholder="Search jobs..."
|
||||||
|
value="${jobsState.search}"
|
||||||
|
oninput="updateJobSearch(this.value)"
|
||||||
|
style="padding-left: 36px; background: var(--bg-card); border: 1px solid var(--border-color); color: white; border-radius: 6px; height: 40px; width: 250px; outline: none;">
|
||||||
|
</div>
|
||||||
|
<select onchange="updateJobFilter(this.value)" style="background: var(--bg-card); border: 1px solid var(--border-color); color: white; border-radius: 6px; height: 40px; padding: 0 12px; outline: none; cursor: pointer;">
|
||||||
|
<option value="All" ${jobsState.filter === 'All' ? 'selected' : ''}>All Status</option>
|
||||||
|
<option value="Success" ${jobsState.filter === 'Success' ? 'selected' : ''}>Success</option>
|
||||||
|
<option value="Running" ${jobsState.filter === 'Running' ? 'selected' : ''}>Running</option>
|
||||||
|
<option value="Error" ${jobsState.filter === 'Error' ? 'selected' : ''}>Error</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-primary" style="height: 40px;"><i class="ph ph-play"></i> Run Job</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="table-container">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Job Name</th>
|
||||||
|
<th>Client</th>
|
||||||
|
<th>Level</th>
|
||||||
|
<th>Start Time</th>
|
||||||
|
<th>Files</th>
|
||||||
|
<th>Size</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${filteredJobs.length > 0 ? filteredJobs.map(job => `
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span class="status-badge status-${job.status.toLowerCase()}">
|
||||||
|
${job.status}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td style="font-weight: 500;">${job.name}</td>
|
||||||
|
<td style="color: var(--text-muted);">${job.client}</td>
|
||||||
|
<td>${job.level}</td>
|
||||||
|
<td>${formatDate(job.startTime)}</td>
|
||||||
|
<td>${job.files.toLocaleString()}</td>
|
||||||
|
<td>${formatBytes(job.bytes)}</td>
|
||||||
|
</tr>
|
||||||
|
`).join('') : `
|
||||||
|
<tr>
|
||||||
|
<td colspan="7" style="text-align: center; padding: 2rem; color: var(--text-muted);">
|
||||||
|
No jobs found matching your filters.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderClients = async () => {
|
||||||
|
const clients = await Api.getClients();
|
||||||
|
return `
|
||||||
|
<div class="animate-fade-in">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
|
||||||
|
<h2>Clients</h2>
|
||||||
|
<button class="btn btn-primary" onclick="openAddClientModal()"><i class="ph ph-plus"></i> Add Client</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dashboard-grid">
|
||||||
|
${clients.map(client => `
|
||||||
|
<div class="card">
|
||||||
|
<div style="display: flex; justify-content: space-between; margin-bottom: 1rem;">
|
||||||
|
<div style="width: 48px; height: 48px; background: var(--bg-hover); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 1.5rem;">
|
||||||
|
<i class="ph ph-desktop"></i>
|
||||||
|
</div>
|
||||||
|
<span class="status-badge status-${client.status === 'Online' ? 'success' : 'error'}">
|
||||||
|
${client.status}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<h3 style="margin-bottom: 0.5rem;">${client.name}</h3>
|
||||||
|
<p style="color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1rem;">${client.os}</p>
|
||||||
|
|
||||||
|
<div style="padding-top: 1rem; border-top: 1px solid var(--border-color); display: flex; justify-content: space-between; font-size: 0.85rem;">
|
||||||
|
<span style="color: var(--text-muted);">Last Backup</span>
|
||||||
|
<span>${formatDate(client.lastBackup)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Router
|
||||||
|
const router = async () => {
|
||||||
|
const contentArea = document.getElementById('content-area');
|
||||||
|
const hash = window.location.hash || '#dashboard';
|
||||||
|
const page = hash.substring(1);
|
||||||
|
|
||||||
|
// Update Sidebar Active State
|
||||||
|
document.querySelectorAll('.nav-item').forEach(el => {
|
||||||
|
el.classList.toggle('active', el.dataset.page === page);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update Breadcrumbs
|
||||||
|
document.querySelector('.current-page').textContent = page.charAt(0).toUpperCase() + page.slice(1);
|
||||||
|
|
||||||
|
contentArea.innerHTML = `
|
||||||
|
<div class="loading-state">
|
||||||
|
<div class="spinner"></div>
|
||||||
|
<p>Loading...</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let content = '';
|
||||||
|
switch (page) {
|
||||||
|
case 'dashboard':
|
||||||
|
content = await renderDashboard();
|
||||||
|
break;
|
||||||
|
case 'jobs':
|
||||||
|
content = await renderJobs();
|
||||||
|
break;
|
||||||
|
case 'clients':
|
||||||
|
content = await renderClients();
|
||||||
|
break;
|
||||||
|
case 'storage':
|
||||||
|
const storageDevices = await Api.getStorage();
|
||||||
|
|
||||||
|
content = `
|
||||||
|
<div class="animate-fade-in">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
|
||||||
|
<h2>Storage Daemons</h2>
|
||||||
|
<button class="btn btn-primary"><i class="ph ph-plus"></i> Add Storage</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="table-container">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Capacity</th>
|
||||||
|
<th>Usage</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${storageDevices.length > 0 ? storageDevices.map(dev => `
|
||||||
|
<tr>
|
||||||
|
<td style="font-weight: 500;">${dev.name}</td>
|
||||||
|
<td>${dev.type}</td>
|
||||||
|
<td>
|
||||||
|
<span class="status-badge status-${dev.status === 'Active' ? 'success' : 'running'}">
|
||||||
|
${dev.status}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>${dev.capacity}</td>
|
||||||
|
<td>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 0.25rem;">
|
||||||
|
<span>${dev.used}</span>
|
||||||
|
${dev.percent > 0 ? `
|
||||||
|
<div style="width: 100px; height: 4px; background: #2d3748; border-radius: 2px;">
|
||||||
|
<div style="width: ${dev.percent}%; height: 100%; background: ${dev.percent > 75 ? 'var(--warning)' : 'var(--accent-primary)'}; border-radius: 2px;"></div>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="icon-btn"><i class="ph ph-dots-three-vertical"></i></button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`).join('') : `
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" style="text-align: center; padding: 2rem; color: var(--text-muted);">
|
||||||
|
No storage devices found.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
break;
|
||||||
|
case 'settings':
|
||||||
|
content = '<div class="animate-fade-in"><h2>Settings</h2><p>Coming soon...</p></div>';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
content = '<div class="animate-fade-in"><h2>404 Not Found</h2></div>';
|
||||||
|
}
|
||||||
|
contentArea.innerHTML = content;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
contentArea.innerHTML = '<div class="animate-fade-in"><h2>Error loading content</h2></div>';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Init
|
||||||
|
window.addEventListener('hashchange', router);
|
||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
router();
|
||||||
|
|
||||||
|
// Append Modal to Body if not exists
|
||||||
|
if (!document.getElementById('client-modal')) {
|
||||||
|
const modal = document.createElement('div');
|
||||||
|
modal.id = 'client-modal';
|
||||||
|
modal.innerHTML = `
|
||||||
|
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: none; align-items: center; justify-content: center; z-index: 1000;" id="client-modal-overlay">
|
||||||
|
<div class="card" style="width: 400px; max-width: 90%;">
|
||||||
|
<h3 style="margin-bottom: 1.5rem;">Add New Client</h3>
|
||||||
|
<form onsubmit="handleClientSubmit(event)">
|
||||||
|
<div style="margin-bottom: 1rem;">
|
||||||
|
<label style="display: block; margin-bottom: 0.5rem; color: var(--text-muted);">Client Name</label>
|
||||||
|
<input type="text" name="name" required style="width: 100%; padding: 0.5rem; background: var(--bg-hover); border: 1px solid var(--border-color); color: white; border-radius: 6px;">
|
||||||
|
</div>
|
||||||
|
<div style="margin-bottom: 1rem;">
|
||||||
|
<label style="display: block; margin-bottom: 0.5rem; color: var(--text-muted);">Address (IP/Host)</label>
|
||||||
|
<input type="text" name="address" required style="width: 100%; padding: 0.5rem; background: var(--bg-hover); border: 1px solid var(--border-color); color: white; border-radius: 6px;">
|
||||||
|
</div>
|
||||||
|
<div style="margin-bottom: 1.5rem;">
|
||||||
|
<label style="display: block; margin-bottom: 0.5rem; color: var(--text-muted);">Password</label>
|
||||||
|
<input type="password" name="password" required style="width: 100%; padding: 0.5rem; background: var(--bg-hover); border: 1px solid var(--border-color); color: white; border-radius: 6px;">
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; justify-content: flex-end; gap: 1rem;">
|
||||||
|
<button type="button" class="btn" onclick="closeClientModal()" style="background: transparent; border: 1px solid var(--border-color); color: white;">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Save Client</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.openAddClientModal = () => {
|
||||||
|
document.getElementById('client-modal-overlay').style.display = 'flex';
|
||||||
|
};
|
||||||
|
|
||||||
|
window.closeClientModal = () => {
|
||||||
|
document.getElementById('client-modal-overlay').style.display = 'none';
|
||||||
|
};
|
||||||
|
|
||||||
|
window.handleClientSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const formData = new FormData(e.target);
|
||||||
|
const data = Object.fromEntries(formData.entries());
|
||||||
|
|
||||||
|
try {
|
||||||
|
const btn = e.target.querySelector('button[type="submit"]');
|
||||||
|
const origText = btn.textContent;
|
||||||
|
btn.textContent = 'Saving...';
|
||||||
|
btn.disabled = true;
|
||||||
|
|
||||||
|
const res = await fetch(`${Api.getBaseUrl()}/clients`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) throw new Error((await res.json()).error);
|
||||||
|
|
||||||
|
alert('Client added successfully!');
|
||||||
|
closeClientModal();
|
||||||
|
e.target.reset();
|
||||||
|
window.dispatchEvent(new Event('hashchange')); // Reload view
|
||||||
|
} catch (err) {
|
||||||
|
alert('Error adding client: ' + err.message);
|
||||||
|
} finally {
|
||||||
|
const btn = e.target.querySelector('button[type="submit"]');
|
||||||
|
btn.textContent = 'Save Client';
|
||||||
|
btn.disabled = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
44
js/mock_api.js
Normal file
44
js/mock_api.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Mock Data Service for Bacula Interface
|
||||||
|
* Simulates API calls to the Bacula Backend
|
||||||
|
*/
|
||||||
|
|
||||||
|
const MOCK_JOBS = [
|
||||||
|
{ id: 10423, name: 'Weekly-Server-Full', client: 'db-prod-01', level: 'Full', files: 45201, bytes: 48500000000, status: 'Success', startTime: '2025-10-24 02:00:00', duration: '1h 12m' },
|
||||||
|
{ id: 10424, name: 'Daily-Web-Inc', client: 'web-front-01', level: 'Incremental', files: 1205, bytes: 540000000, status: 'Success', startTime: '2025-10-24 03:30:00', duration: '15m' },
|
||||||
|
{ id: 10425, name: 'Daily-Web-Inc', client: 'web-front-02', level: 'Incremental', files: 1150, bytes: 520000000, status: 'Warning', startTime: '2025-10-24 03:45:00', duration: '14m' },
|
||||||
|
{ id: 10426, name: 'Log-Archive', client: 'log-svr-01', level: 'Differential', files: 8500, bytes: 12000000000, status: 'Running', startTime: '2025-10-24 04:00:00', duration: 'Running' },
|
||||||
|
{ id: 10427, name: 'User-Home-Backup', client: 'file-svr-01', level: 'Full', files: 0, bytes: 0, status: 'Error', startTime: '2025-10-24 01:00:00', duration: '2m' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const MOCK_STATS = {
|
||||||
|
totalJobs: 1250,
|
||||||
|
successRate: 98.5,
|
||||||
|
totalBytes: 85400000000000, // 85.4 TB
|
||||||
|
activeClients: 42,
|
||||||
|
storageUsage: 76 // Percent
|
||||||
|
};
|
||||||
|
|
||||||
|
export class MockApi {
|
||||||
|
static async getDashboardStats() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => resolve(MOCK_STATS), 600); // Simulate network latency
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getRecentJobs() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => resolve(MOCK_JOBS), 800);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getClients() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => resolve([
|
||||||
|
{ name: 'db-prod-01', os: 'Linux (Debian 12)', lastBackup: '2025-10-24 02:00:00', status: 'Online' },
|
||||||
|
{ name: 'web-front-01', os: 'Linux (Ubuntu 24.04)', lastBackup: '2025-10-24 03:30:00', status: 'Online' },
|
||||||
|
{ name: 'win-office-01', os: 'Windows Server 2022', lastBackup: '2025-10-23 20:00:00', status: 'Offline' }
|
||||||
|
]), 500);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
45
js/real_api.js
Normal file
45
js/real_api.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
export class RealApi {
|
||||||
|
static getBaseUrl() {
|
||||||
|
// Adjust if serving from a different machine
|
||||||
|
return window.location.hostname === 'localhost'
|
||||||
|
? 'http://localhost:3001/api'
|
||||||
|
: `http://${window.location.hostname}:3001/api`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async fetchData(endpoint) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${this.getBaseUrl()}${endpoint}`);
|
||||||
|
if (!response.ok) throw new Error(`API Error: ${response.status}`);
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return null; // Handle gracefully in UI
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getDashboardStats() {
|
||||||
|
const data = await this.fetchData('/dashboard');
|
||||||
|
return data || {
|
||||||
|
totalJobs: 0,
|
||||||
|
successRate: 0,
|
||||||
|
totalBytes: 0,
|
||||||
|
activeClients: 0,
|
||||||
|
storageUsage: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getRecentJobs() {
|
||||||
|
const data = await this.fetchData('/jobs');
|
||||||
|
return data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getClients() {
|
||||||
|
const data = await this.fetchData('/clients');
|
||||||
|
return data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getStorage() {
|
||||||
|
const data = await this.fetchData('/storage');
|
||||||
|
return data || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
18
server/.env
Normal file
18
server/.env
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Database Configuration
|
||||||
|
# Bacula Database Credentials
|
||||||
|
DB_HOST=10.10.14.82
|
||||||
|
DB_USER=bass
|
||||||
|
DB_PASSWORD=Pnd77net
|
||||||
|
DB_NAME=bacula
|
||||||
|
|
||||||
|
# Server Config
|
||||||
|
PORT=5432
|
||||||
|
|
||||||
|
# Remote Admin (SSH)
|
||||||
|
SSH_HOST=10.10.14.82
|
||||||
|
SSH_USER=root
|
||||||
|
# Isi SALAH SATU aja (Password atau Key Path)
|
||||||
|
SSH_PASSWORD=
|
||||||
|
SSH_KEY_PATH=/home/othman/.ssh/id_rsa.pub
|
||||||
|
# Folder tempat config Client disimpan
|
||||||
|
BACULA_CONF_DIR=/etc/bacula/conf.d/clients
|
||||||
19
server/.env.example
Normal file
19
server/.env.example
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Database Configuration
|
||||||
|
# Bacula Database Credentials (PostgreSQL)
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_USER=bacula
|
||||||
|
DB_PASSWORD=your_secure_password
|
||||||
|
DB_NAME=bacula
|
||||||
|
DB_PORT=5432
|
||||||
|
|
||||||
|
# Remote Admin (SSH)
|
||||||
|
SSH_HOST=10.10.14.82
|
||||||
|
SSH_USER=root
|
||||||
|
# Use either Password OR Key
|
||||||
|
SSH_PASSWORD=your_ssh_password
|
||||||
|
SSH_KEY_PATH=/path/to/private/key
|
||||||
|
# Directory where Client configs are stored
|
||||||
|
BACULA_CONF_DIR=/etc/bacula/conf.d/clients
|
||||||
|
|
||||||
|
# Server Config
|
||||||
|
PORT=3000
|
||||||
57
server/bacula_config.js
Normal file
57
server/bacula_config.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// Utility to parse and stringify Bacula Config Resources
|
||||||
|
// Format:
|
||||||
|
// ResourceType {
|
||||||
|
// Key = Value
|
||||||
|
// Key = "Value With Spaces"
|
||||||
|
// }
|
||||||
|
|
||||||
|
const parseConfig = (content) => {
|
||||||
|
const lines = content.split('\n');
|
||||||
|
const resources = [];
|
||||||
|
let currentResource = null;
|
||||||
|
|
||||||
|
lines.forEach(line => {
|
||||||
|
const trimmed = line.trim();
|
||||||
|
if (!trimmed || trimmed.startsWith('#')) return;
|
||||||
|
|
||||||
|
// Start of Resource
|
||||||
|
if (trimmed.match(/^[a-zA-Z0-9]+\s*{/)) {
|
||||||
|
const type = trimmed.split(/\s+/)[0];
|
||||||
|
currentResource = { _type: type };
|
||||||
|
}
|
||||||
|
// End of Resource
|
||||||
|
else if (trimmed === '}') {
|
||||||
|
if (currentResource) {
|
||||||
|
resources.push(currentResource);
|
||||||
|
currentResource = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Key-Value Pair
|
||||||
|
else if (currentResource && trimmed.includes('=')) {
|
||||||
|
const [key, ...values] = trimmed.split('=');
|
||||||
|
let value = values.join('=').trim();
|
||||||
|
|
||||||
|
// Remove wrapping quotes and trailing semicolons
|
||||||
|
value = value.replace(/^"|"$/g, '').replace(/;$/, '');
|
||||||
|
|
||||||
|
currentResource[key.trim()] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateClientConfig = (data) => {
|
||||||
|
return `Client {
|
||||||
|
Name = "${data.Name}"
|
||||||
|
Address = "${data.Address}"
|
||||||
|
FDPort = ${data.FDPort || 9102}
|
||||||
|
Catalog = "${data.Catalog || 'MyCatalog'}"
|
||||||
|
Password = "${data.Password}"
|
||||||
|
File Retention = ${data.FileRetention || '30 days'}
|
||||||
|
Job Retention = ${data.JobRetention || '6 months'}
|
||||||
|
AutoPrune = ${data.AutoPrune || 'yes'}
|
||||||
|
}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { parseConfig, generateClientConfig };
|
||||||
34
server/check_columns.js
Normal file
34
server/check_columns.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const { Client } = require('pg');
|
||||||
|
|
||||||
|
const client = new Client({
|
||||||
|
host: process.env.DB_HOST,
|
||||||
|
user: process.env.DB_USER,
|
||||||
|
password: process.env.DB_PASSWORD,
|
||||||
|
database: process.env.DB_NAME,
|
||||||
|
port: process.env.DB_PORT,
|
||||||
|
});
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
const tables = ['job', 'client'];
|
||||||
|
|
||||||
|
for (const table of tables) {
|
||||||
|
console.log(`\n--- Columns in table '${table}' ---`);
|
||||||
|
const res = await client.query(`
|
||||||
|
SELECT column_name, data_type
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_name = '${table}'
|
||||||
|
ORDER BY ordinal_position;
|
||||||
|
`);
|
||||||
|
res.rows.forEach(r => console.log(`${r.column_name} (${r.data_type})`));
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.end();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
})();
|
||||||
28
server/check_tables.js
Normal file
28
server/check_tables.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const { Client } = require('pg');
|
||||||
|
|
||||||
|
const client = new Client({
|
||||||
|
host: process.env.DB_HOST,
|
||||||
|
user: process.env.DB_USER,
|
||||||
|
password: process.env.DB_PASSWORD,
|
||||||
|
database: process.env.DB_NAME,
|
||||||
|
port: process.env.DB_PORT,
|
||||||
|
});
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
await client.connect();
|
||||||
|
console.log('Listing tables in database...');
|
||||||
|
const res = await client.query(`
|
||||||
|
SELECT table_name
|
||||||
|
FROM information_schema.tables
|
||||||
|
WHERE table_schema = 'public'
|
||||||
|
ORDER BY table_name;
|
||||||
|
`);
|
||||||
|
console.log(res.rows.map(r => r.table_name));
|
||||||
|
await client.end();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
})();
|
||||||
22
server/find_service.js
Normal file
22
server/find_service.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
const { execCommand } = require('./ssh_service');
|
||||||
|
require('dotenv').config();
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
console.log('--- Diagnosing Service Name ---');
|
||||||
|
console.log('Checking systemctl unit files...');
|
||||||
|
try {
|
||||||
|
const list = await execCommand('systemctl list-units --type=service --all | grep bacula');
|
||||||
|
console.log(list);
|
||||||
|
} catch (e) { console.log('systemctl check failed or no grep match'); }
|
||||||
|
|
||||||
|
console.log('\nChecking /etc/init.d...');
|
||||||
|
try {
|
||||||
|
const list2 = await execCommand('ls /etc/init.d | grep bacula');
|
||||||
|
console.log(list2);
|
||||||
|
} catch (e) { console.log('init.d check failed'); }
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Diagnostic error:', err);
|
||||||
|
}
|
||||||
|
})();
|
||||||
203
server/index.js
Normal file
203
server/index.js
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const express = require('express');
|
||||||
|
const cors = require('cors');
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
const { exec } = require('child_process');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const PORT = process.env.PORT || 3000;
|
||||||
|
|
||||||
|
app.use(cors());
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
// Database Connection Pool (PostgreSQL)
|
||||||
|
const pool = new Pool({
|
||||||
|
host: process.env.DB_HOST || 'localhost',
|
||||||
|
user: process.env.DB_USER || 'bacula',
|
||||||
|
password: process.env.DB_PASSWORD || '',
|
||||||
|
database: process.env.DB_NAME || 'bacula',
|
||||||
|
port: process.env.DB_PORT || 5432,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Helper: Run bconsole commands
|
||||||
|
const runBconsole = (command) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
exec(`echo "${command}" | bconsole`, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(`exec error: ${error}`);
|
||||||
|
resolve("Note: bconsole command failed (server might not have bconsole configured). Mocking success.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(stdout);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Routes ---
|
||||||
|
|
||||||
|
// Dashboard Stats
|
||||||
|
app.get('/api/dashboard', async (req, res) => {
|
||||||
|
try {
|
||||||
|
console.log('GET /api/dashboard request received');
|
||||||
|
// Postgres query returns { rows: [] }
|
||||||
|
// Using lowercase unquoted table/column names
|
||||||
|
const jobStats = await pool.query(`
|
||||||
|
SELECT
|
||||||
|
COUNT(*) as total,
|
||||||
|
SUM(CASE WHEN jobstatus = 'T' THEN 1 ELSE 0 END) as success,
|
||||||
|
SUM(jobbytes) as totalbytes
|
||||||
|
FROM job
|
||||||
|
`);
|
||||||
|
|
||||||
|
const clients = await pool.query('SELECT COUNT(*) as count FROM client');
|
||||||
|
|
||||||
|
const statsRow = jobStats.rows[0];
|
||||||
|
const clientCount = clients.rows[0].count;
|
||||||
|
|
||||||
|
const total = parseInt(statsRow.total || 0);
|
||||||
|
const success = parseInt(statsRow.success || 0);
|
||||||
|
const successRate = total > 0 ? Math.round((success / total) * 100) : 0;
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
totalJobs: total,
|
||||||
|
successRate: successRate,
|
||||||
|
totalBytes: Number(statsRow.totalbytes || 0),
|
||||||
|
activeClients: parseInt(clientCount),
|
||||||
|
storageUsage: 75
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error in /api/dashboard:', err);
|
||||||
|
res.status(500).json({ error: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { generateClientConfig } = require('./bacula_config');
|
||||||
|
const { writeFile, execCommand } = require('./ssh_service');
|
||||||
|
|
||||||
|
// Recent Jobs
|
||||||
|
app.get('/api/jobs', async (req, res) => {
|
||||||
|
try {
|
||||||
|
console.log('GET /api/jobs request received');
|
||||||
|
const result = await pool.query(`
|
||||||
|
SELECT
|
||||||
|
j.jobid as id,
|
||||||
|
j.name as name,
|
||||||
|
c.name as client,
|
||||||
|
CASE j.level
|
||||||
|
WHEN 'F' THEN 'Full'
|
||||||
|
WHEN 'I' THEN 'Incremental'
|
||||||
|
WHEN 'D' THEN 'Differential'
|
||||||
|
ELSE j.level
|
||||||
|
END as level,
|
||||||
|
j.jobfiles as files,
|
||||||
|
j.jobbytes as bytes,
|
||||||
|
CASE j.jobstatus
|
||||||
|
WHEN 'T' THEN 'Success'
|
||||||
|
WHEN 'E' THEN 'Error'
|
||||||
|
WHEN 'R' THEN 'Running'
|
||||||
|
ELSE 'Other'
|
||||||
|
END as status,
|
||||||
|
j.starttime as "startTime",
|
||||||
|
(j.endtime - j.starttime) as duration
|
||||||
|
FROM job j
|
||||||
|
JOIN client c ON j.clientid = c.clientid
|
||||||
|
ORDER BY j.starttime DESC
|
||||||
|
LIMIT 20
|
||||||
|
`);
|
||||||
|
// Note: Postgres lowercases column aliases by default, so 'startTime' might be 'starttime'
|
||||||
|
// Adjusted query accordingly.
|
||||||
|
res.json(result.rows);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error in /api/jobs:', err);
|
||||||
|
res.status(500).json({ error: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clients
|
||||||
|
app.get('/api/clients', async (req, res) => {
|
||||||
|
try {
|
||||||
|
console.log('GET /api/clients request received');
|
||||||
|
// Subquery might need specific Postgres tuning if large, but fine for basic
|
||||||
|
const result = await pool.query(`
|
||||||
|
SELECT
|
||||||
|
c.name as name,
|
||||||
|
c.uname as os,
|
||||||
|
(SELECT starttime FROM job WHERE clientid = c.clientid ORDER BY starttime DESC LIMIT 1) as "lastBackup"
|
||||||
|
FROM client c
|
||||||
|
`);
|
||||||
|
|
||||||
|
const clients = result.rows.map(c => ({
|
||||||
|
...c,
|
||||||
|
status: 'Online'
|
||||||
|
}));
|
||||||
|
|
||||||
|
res.json(clients);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error in /api/clients:', err);
|
||||||
|
res.status(500).json({ error: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/clients', async (req, res) => {
|
||||||
|
try {
|
||||||
|
console.log('POST /api/clients request received', req.body);
|
||||||
|
const { name, address, password } = req.body;
|
||||||
|
|
||||||
|
if (!name || !address || !password) {
|
||||||
|
return res.status(400).json({ error: 'Name, Address, and Password are required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const configContent = generateClientConfig({
|
||||||
|
Name: name,
|
||||||
|
Address: address,
|
||||||
|
Password: password,
|
||||||
|
// Defaults
|
||||||
|
FileRetention: '30 days',
|
||||||
|
JobRetention: '6 months',
|
||||||
|
AutoPrune: 'yes'
|
||||||
|
});
|
||||||
|
|
||||||
|
const clientDir = process.env.BACULA_CONF_DIR || '/etc/bacula/conf.d/clients';
|
||||||
|
const filePath = `${clientDir}/${name}.conf`;
|
||||||
|
|
||||||
|
console.log(`Writing config to remote: ${filePath}`);
|
||||||
|
await writeFile(filePath, configContent);
|
||||||
|
|
||||||
|
console.log('Reloading Bacula Director...');
|
||||||
|
try {
|
||||||
|
await execCommand('systemctl reload bacula-director');
|
||||||
|
} catch (e) {
|
||||||
|
await execCommand('service bacula-director reload');
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({ success: true, message: 'Client created and Director reloaded' });
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error in POST /api/clients:', err);
|
||||||
|
res.status(500).json({ error: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Storage
|
||||||
|
app.get('/api/storage', async (req, res) => {
|
||||||
|
try {
|
||||||
|
console.log('GET /api/storage request received');
|
||||||
|
const result = await pool.query('SELECT name, autochanger FROM storage');
|
||||||
|
const storage = result.rows.map(s => ({
|
||||||
|
name: s.name, // Postgres behavior: likely lowercase
|
||||||
|
type: s.autochanger ? 'Autochanger' : 'Disk',
|
||||||
|
status: 'Active',
|
||||||
|
capacity: 'N/A',
|
||||||
|
used: 'N/A',
|
||||||
|
percent: 0
|
||||||
|
}));
|
||||||
|
res.json(storage);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error in /api/storage:', err);
|
||||||
|
res.status(500).json({ error: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
console.log(`Bacula API Server (PostgreSQL) running on port ${PORT}`);
|
||||||
|
});
|
||||||
1
server/node_modules/.bin/mime
generated
vendored
Symbolic link
1
server/node_modules/.bin/mime
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../mime/cli.js
|
||||||
1064
server/node_modules/.package-lock.json
generated
vendored
Normal file
1064
server/node_modules/.package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
243
server/node_modules/accepts/HISTORY.md
generated
vendored
Normal file
243
server/node_modules/accepts/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
1.3.8 / 2022-02-02
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.34
|
||||||
|
- deps: mime-db@~1.51.0
|
||||||
|
* deps: negotiator@0.6.3
|
||||||
|
|
||||||
|
1.3.7 / 2019-04-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.6.2
|
||||||
|
- Fix sorting charset, encoding, and language with extra parameters
|
||||||
|
|
||||||
|
1.3.6 / 2019-04-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.24
|
||||||
|
- deps: mime-db@~1.40.0
|
||||||
|
|
||||||
|
1.3.5 / 2018-02-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.18
|
||||||
|
- deps: mime-db@~1.33.0
|
||||||
|
|
||||||
|
1.3.4 / 2017-08-22
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.16
|
||||||
|
- deps: mime-db@~1.29.0
|
||||||
|
|
||||||
|
1.3.3 / 2016-05-02
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.11
|
||||||
|
- deps: mime-db@~1.23.0
|
||||||
|
* deps: negotiator@0.6.1
|
||||||
|
- perf: improve `Accept` parsing speed
|
||||||
|
- perf: improve `Accept-Charset` parsing speed
|
||||||
|
- perf: improve `Accept-Encoding` parsing speed
|
||||||
|
- perf: improve `Accept-Language` parsing speed
|
||||||
|
|
||||||
|
1.3.2 / 2016-03-08
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.10
|
||||||
|
- Fix extension of `application/dash+xml`
|
||||||
|
- Update primary extension for `audio/mp4`
|
||||||
|
- deps: mime-db@~1.22.0
|
||||||
|
|
||||||
|
1.3.1 / 2016-01-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.9
|
||||||
|
- deps: mime-db@~1.21.0
|
||||||
|
|
||||||
|
1.3.0 / 2015-09-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.7
|
||||||
|
- deps: mime-db@~1.19.0
|
||||||
|
* deps: negotiator@0.6.0
|
||||||
|
- Fix including type extensions in parameters in `Accept` parsing
|
||||||
|
- Fix parsing `Accept` parameters with quoted equals
|
||||||
|
- Fix parsing `Accept` parameters with quoted semicolons
|
||||||
|
- Lazy-load modules from main entry point
|
||||||
|
- perf: delay type concatenation until needed
|
||||||
|
- perf: enable strict mode
|
||||||
|
- perf: hoist regular expressions
|
||||||
|
- perf: remove closures getting spec properties
|
||||||
|
- perf: remove a closure from media type parsing
|
||||||
|
- perf: remove property delete from media type parsing
|
||||||
|
|
||||||
|
1.2.13 / 2015-09-06
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.6
|
||||||
|
- deps: mime-db@~1.18.0
|
||||||
|
|
||||||
|
1.2.12 / 2015-07-30
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.4
|
||||||
|
- deps: mime-db@~1.16.0
|
||||||
|
|
||||||
|
1.2.11 / 2015-07-16
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.3
|
||||||
|
- deps: mime-db@~1.15.0
|
||||||
|
|
||||||
|
1.2.10 / 2015-07-01
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.2
|
||||||
|
- deps: mime-db@~1.14.0
|
||||||
|
|
||||||
|
1.2.9 / 2015-06-08
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.1
|
||||||
|
- perf: fix deopt during mapping
|
||||||
|
|
||||||
|
1.2.8 / 2015-06-07
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.0
|
||||||
|
- deps: mime-db@~1.13.0
|
||||||
|
* perf: avoid argument reassignment & argument slice
|
||||||
|
* perf: avoid negotiator recursive construction
|
||||||
|
* perf: enable strict mode
|
||||||
|
* perf: remove unnecessary bitwise operator
|
||||||
|
|
||||||
|
1.2.7 / 2015-05-10
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.5.3
|
||||||
|
- Fix media type parameter matching to be case-insensitive
|
||||||
|
|
||||||
|
1.2.6 / 2015-05-07
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.11
|
||||||
|
- deps: mime-db@~1.9.1
|
||||||
|
* deps: negotiator@0.5.2
|
||||||
|
- Fix comparing media types with quoted values
|
||||||
|
- Fix splitting media types with quoted commas
|
||||||
|
|
||||||
|
1.2.5 / 2015-03-13
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.10
|
||||||
|
- deps: mime-db@~1.8.0
|
||||||
|
|
||||||
|
1.2.4 / 2015-02-14
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Support Node.js 0.6
|
||||||
|
* deps: mime-types@~2.0.9
|
||||||
|
- deps: mime-db@~1.7.0
|
||||||
|
* deps: negotiator@0.5.1
|
||||||
|
- Fix preference sorting to be stable for long acceptable lists
|
||||||
|
|
||||||
|
1.2.3 / 2015-01-31
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.8
|
||||||
|
- deps: mime-db@~1.6.0
|
||||||
|
|
||||||
|
1.2.2 / 2014-12-30
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.7
|
||||||
|
- deps: mime-db@~1.5.0
|
||||||
|
|
||||||
|
1.2.1 / 2014-12-30
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.5
|
||||||
|
- deps: mime-db@~1.3.1
|
||||||
|
|
||||||
|
1.2.0 / 2014-12-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.5.0
|
||||||
|
- Fix list return order when large accepted list
|
||||||
|
- Fix missing identity encoding when q=0 exists
|
||||||
|
- Remove dynamic building of Negotiator class
|
||||||
|
|
||||||
|
1.1.4 / 2014-12-10
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.4
|
||||||
|
- deps: mime-db@~1.3.0
|
||||||
|
|
||||||
|
1.1.3 / 2014-11-09
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.3
|
||||||
|
- deps: mime-db@~1.2.0
|
||||||
|
|
||||||
|
1.1.2 / 2014-10-14
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.4.9
|
||||||
|
- Fix error when media type has invalid parameter
|
||||||
|
|
||||||
|
1.1.1 / 2014-09-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.2
|
||||||
|
- deps: mime-db@~1.1.0
|
||||||
|
* deps: negotiator@0.4.8
|
||||||
|
- Fix all negotiations to be case-insensitive
|
||||||
|
- Stable sort preferences of same quality according to client order
|
||||||
|
|
||||||
|
1.1.0 / 2014-09-02
|
||||||
|
==================
|
||||||
|
|
||||||
|
* update `mime-types`
|
||||||
|
|
||||||
|
1.0.7 / 2014-07-04
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix wrong type returned from `type` when match after unknown extension
|
||||||
|
|
||||||
|
1.0.6 / 2014-06-24
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.4.7
|
||||||
|
|
||||||
|
1.0.5 / 2014-06-20
|
||||||
|
==================
|
||||||
|
|
||||||
|
* fix crash when unknown extension given
|
||||||
|
|
||||||
|
1.0.4 / 2014-06-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* use `mime-types`
|
||||||
|
|
||||||
|
1.0.3 / 2014-06-11
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.4.6
|
||||||
|
- Order by specificity when quality is the same
|
||||||
|
|
||||||
|
1.0.2 / 2014-05-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix interpretation when header not in request
|
||||||
|
* deps: pin negotiator@0.4.5
|
||||||
|
|
||||||
|
1.0.1 / 2014-01-18
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Identity encoding isn't always acceptable
|
||||||
|
* deps: negotiator@~0.4.0
|
||||||
|
|
||||||
|
1.0.0 / 2013-12-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Genesis
|
||||||
23
server/node_modules/accepts/LICENSE
generated
vendored
Normal file
23
server/node_modules/accepts/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
|
||||||
|
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
140
server/node_modules/accepts/README.md
generated
vendored
Normal file
140
server/node_modules/accepts/README.md
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# accepts
|
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url]
|
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||||
|
[![Node.js Version][node-version-image]][node-version-url]
|
||||||
|
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator).
|
||||||
|
Extracted from [koa](https://www.npmjs.com/package/koa) for general use.
|
||||||
|
|
||||||
|
In addition to negotiator, it allows:
|
||||||
|
|
||||||
|
- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])`
|
||||||
|
as well as `('text/html', 'application/json')`.
|
||||||
|
- Allows type shorthands such as `json`.
|
||||||
|
- Returns `false` when no types match
|
||||||
|
- Treats non-existent headers as `*`
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install accepts
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```js
|
||||||
|
var accepts = require('accepts')
|
||||||
|
```
|
||||||
|
|
||||||
|
### accepts(req)
|
||||||
|
|
||||||
|
Create a new `Accepts` object for the given `req`.
|
||||||
|
|
||||||
|
#### .charset(charsets)
|
||||||
|
|
||||||
|
Return the first accepted charset. If nothing in `charsets` is accepted,
|
||||||
|
then `false` is returned.
|
||||||
|
|
||||||
|
#### .charsets()
|
||||||
|
|
||||||
|
Return the charsets that the request accepts, in the order of the client's
|
||||||
|
preference (most preferred first).
|
||||||
|
|
||||||
|
#### .encoding(encodings)
|
||||||
|
|
||||||
|
Return the first accepted encoding. If nothing in `encodings` is accepted,
|
||||||
|
then `false` is returned.
|
||||||
|
|
||||||
|
#### .encodings()
|
||||||
|
|
||||||
|
Return the encodings that the request accepts, in the order of the client's
|
||||||
|
preference (most preferred first).
|
||||||
|
|
||||||
|
#### .language(languages)
|
||||||
|
|
||||||
|
Return the first accepted language. If nothing in `languages` is accepted,
|
||||||
|
then `false` is returned.
|
||||||
|
|
||||||
|
#### .languages()
|
||||||
|
|
||||||
|
Return the languages that the request accepts, in the order of the client's
|
||||||
|
preference (most preferred first).
|
||||||
|
|
||||||
|
#### .type(types)
|
||||||
|
|
||||||
|
Return the first accepted type (and it is returned as the same text as what
|
||||||
|
appears in the `types` array). If nothing in `types` is accepted, then `false`
|
||||||
|
is returned.
|
||||||
|
|
||||||
|
The `types` array can contain full MIME types or file extensions. Any value
|
||||||
|
that is not a full MIME types is passed to `require('mime-types').lookup`.
|
||||||
|
|
||||||
|
#### .types()
|
||||||
|
|
||||||
|
Return the types that the request accepts, in the order of the client's
|
||||||
|
preference (most preferred first).
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Simple type negotiation
|
||||||
|
|
||||||
|
This simple example shows how to use `accepts` to return a different typed
|
||||||
|
respond body based on what the client wants to accept. The server lists it's
|
||||||
|
preferences in order and will get back the best match between the client and
|
||||||
|
server.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var accepts = require('accepts')
|
||||||
|
var http = require('http')
|
||||||
|
|
||||||
|
function app (req, res) {
|
||||||
|
var accept = accepts(req)
|
||||||
|
|
||||||
|
// the order of this list is significant; should be server preferred order
|
||||||
|
switch (accept.type(['json', 'html'])) {
|
||||||
|
case 'json':
|
||||||
|
res.setHeader('Content-Type', 'application/json')
|
||||||
|
res.write('{"hello":"world!"}')
|
||||||
|
break
|
||||||
|
case 'html':
|
||||||
|
res.setHeader('Content-Type', 'text/html')
|
||||||
|
res.write('<b>hello, world!</b>')
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
// the fallback is text/plain, so no need to specify it above
|
||||||
|
res.setHeader('Content-Type', 'text/plain')
|
||||||
|
res.write('hello, world!')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
http.createServer(app).listen(3000)
|
||||||
|
```
|
||||||
|
|
||||||
|
You can test this out with the cURL program:
|
||||||
|
```sh
|
||||||
|
curl -I -H'Accept: text/html' http://localhost:3000/
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master
|
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master
|
||||||
|
[github-actions-ci-image]: https://badgen.net/github/checks/jshttp/accepts/master?label=ci
|
||||||
|
[github-actions-ci-url]: https://github.com/jshttp/accepts/actions/workflows/ci.yml
|
||||||
|
[node-version-image]: https://badgen.net/npm/node/accepts
|
||||||
|
[node-version-url]: https://nodejs.org/en/download
|
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/accepts
|
||||||
|
[npm-url]: https://npmjs.org/package/accepts
|
||||||
|
[npm-version-image]: https://badgen.net/npm/v/accepts
|
||||||
238
server/node_modules/accepts/index.js
generated
vendored
Normal file
238
server/node_modules/accepts/index.js
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
/*!
|
||||||
|
* accepts
|
||||||
|
* Copyright(c) 2014 Jonathan Ong
|
||||||
|
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Negotiator = require('negotiator')
|
||||||
|
var mime = require('mime-types')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = Accepts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Accepts object for the given req.
|
||||||
|
*
|
||||||
|
* @param {object} req
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Accepts (req) {
|
||||||
|
if (!(this instanceof Accepts)) {
|
||||||
|
return new Accepts(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.headers = req.headers
|
||||||
|
this.negotiator = new Negotiator(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given `type(s)` is acceptable, returning
|
||||||
|
* the best match when true, otherwise `undefined`, in which
|
||||||
|
* case you should respond with 406 "Not Acceptable".
|
||||||
|
*
|
||||||
|
* The `type` value may be a single mime type string
|
||||||
|
* such as "application/json", the extension name
|
||||||
|
* such as "json" or an array `["json", "html", "text/plain"]`. When a list
|
||||||
|
* or array is given the _best_ match, if any is returned.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* // Accept: text/html
|
||||||
|
* this.types('html');
|
||||||
|
* // => "html"
|
||||||
|
*
|
||||||
|
* // Accept: text/*, application/json
|
||||||
|
* this.types('html');
|
||||||
|
* // => "html"
|
||||||
|
* this.types('text/html');
|
||||||
|
* // => "text/html"
|
||||||
|
* this.types('json', 'text');
|
||||||
|
* // => "json"
|
||||||
|
* this.types('application/json');
|
||||||
|
* // => "application/json"
|
||||||
|
*
|
||||||
|
* // Accept: text/*, application/json
|
||||||
|
* this.types('image/png');
|
||||||
|
* this.types('png');
|
||||||
|
* // => undefined
|
||||||
|
*
|
||||||
|
* // Accept: text/*;q=.5, application/json
|
||||||
|
* this.types(['html', 'json']);
|
||||||
|
* this.types('html', 'json');
|
||||||
|
* // => "json"
|
||||||
|
*
|
||||||
|
* @param {String|Array} types...
|
||||||
|
* @return {String|Array|Boolean}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Accepts.prototype.type =
|
||||||
|
Accepts.prototype.types = function (types_) {
|
||||||
|
var types = types_
|
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (types && !Array.isArray(types)) {
|
||||||
|
types = new Array(arguments.length)
|
||||||
|
for (var i = 0; i < types.length; i++) {
|
||||||
|
types[i] = arguments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no types, return all requested types
|
||||||
|
if (!types || types.length === 0) {
|
||||||
|
return this.negotiator.mediaTypes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// no accept header, return first given type
|
||||||
|
if (!this.headers.accept) {
|
||||||
|
return types[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
var mimes = types.map(extToMime)
|
||||||
|
var accepts = this.negotiator.mediaTypes(mimes.filter(validMime))
|
||||||
|
var first = accepts[0]
|
||||||
|
|
||||||
|
return first
|
||||||
|
? types[mimes.indexOf(first)]
|
||||||
|
: false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return accepted encodings or best fit based on `encodings`.
|
||||||
|
*
|
||||||
|
* Given `Accept-Encoding: gzip, deflate`
|
||||||
|
* an array sorted by quality is returned:
|
||||||
|
*
|
||||||
|
* ['gzip', 'deflate']
|
||||||
|
*
|
||||||
|
* @param {String|Array} encodings...
|
||||||
|
* @return {String|Array}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Accepts.prototype.encoding =
|
||||||
|
Accepts.prototype.encodings = function (encodings_) {
|
||||||
|
var encodings = encodings_
|
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (encodings && !Array.isArray(encodings)) {
|
||||||
|
encodings = new Array(arguments.length)
|
||||||
|
for (var i = 0; i < encodings.length; i++) {
|
||||||
|
encodings[i] = arguments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no encodings, return all requested encodings
|
||||||
|
if (!encodings || encodings.length === 0) {
|
||||||
|
return this.negotiator.encodings()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.negotiator.encodings(encodings)[0] || false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return accepted charsets or best fit based on `charsets`.
|
||||||
|
*
|
||||||
|
* Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
|
||||||
|
* an array sorted by quality is returned:
|
||||||
|
*
|
||||||
|
* ['utf-8', 'utf-7', 'iso-8859-1']
|
||||||
|
*
|
||||||
|
* @param {String|Array} charsets...
|
||||||
|
* @return {String|Array}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Accepts.prototype.charset =
|
||||||
|
Accepts.prototype.charsets = function (charsets_) {
|
||||||
|
var charsets = charsets_
|
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (charsets && !Array.isArray(charsets)) {
|
||||||
|
charsets = new Array(arguments.length)
|
||||||
|
for (var i = 0; i < charsets.length; i++) {
|
||||||
|
charsets[i] = arguments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no charsets, return all requested charsets
|
||||||
|
if (!charsets || charsets.length === 0) {
|
||||||
|
return this.negotiator.charsets()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.negotiator.charsets(charsets)[0] || false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return accepted languages or best fit based on `langs`.
|
||||||
|
*
|
||||||
|
* Given `Accept-Language: en;q=0.8, es, pt`
|
||||||
|
* an array sorted by quality is returned:
|
||||||
|
*
|
||||||
|
* ['es', 'pt', 'en']
|
||||||
|
*
|
||||||
|
* @param {String|Array} langs...
|
||||||
|
* @return {Array|String}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Accepts.prototype.lang =
|
||||||
|
Accepts.prototype.langs =
|
||||||
|
Accepts.prototype.language =
|
||||||
|
Accepts.prototype.languages = function (languages_) {
|
||||||
|
var languages = languages_
|
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (languages && !Array.isArray(languages)) {
|
||||||
|
languages = new Array(arguments.length)
|
||||||
|
for (var i = 0; i < languages.length; i++) {
|
||||||
|
languages[i] = arguments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no languages, return all requested languages
|
||||||
|
if (!languages || languages.length === 0) {
|
||||||
|
return this.negotiator.languages()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.negotiator.languages(languages)[0] || false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert extnames to mime.
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
* @return {String}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function extToMime (type) {
|
||||||
|
return type.indexOf('/') === -1
|
||||||
|
? mime.lookup(type)
|
||||||
|
: type
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if mime is valid.
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
* @return {String}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function validMime (type) {
|
||||||
|
return typeof type === 'string'
|
||||||
|
}
|
||||||
47
server/node_modules/accepts/package.json
generated
vendored
Normal file
47
server/node_modules/accepts/package.json
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "accepts",
|
||||||
|
"description": "Higher-level content negotiation",
|
||||||
|
"version": "1.3.8",
|
||||||
|
"contributors": [
|
||||||
|
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||||
|
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "jshttp/accepts",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-types": "~2.1.34",
|
||||||
|
"negotiator": "0.6.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"deep-equal": "1.0.1",
|
||||||
|
"eslint": "7.32.0",
|
||||||
|
"eslint-config-standard": "14.1.1",
|
||||||
|
"eslint-plugin-import": "2.25.4",
|
||||||
|
"eslint-plugin-markdown": "2.2.1",
|
||||||
|
"eslint-plugin-node": "11.1.0",
|
||||||
|
"eslint-plugin-promise": "4.3.1",
|
||||||
|
"eslint-plugin-standard": "4.1.0",
|
||||||
|
"mocha": "9.2.0",
|
||||||
|
"nyc": "15.1.0"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"LICENSE",
|
||||||
|
"HISTORY.md",
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"test": "mocha --reporter spec --check-leaks --bail test/",
|
||||||
|
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"content",
|
||||||
|
"negotiation",
|
||||||
|
"accept",
|
||||||
|
"accepts"
|
||||||
|
]
|
||||||
|
}
|
||||||
21
server/node_modules/array-flatten/LICENSE
generated
vendored
Normal file
21
server/node_modules/array-flatten/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
43
server/node_modules/array-flatten/README.md
generated
vendored
Normal file
43
server/node_modules/array-flatten/README.md
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Array Flatten
|
||||||
|
|
||||||
|
[![NPM version][npm-image]][npm-url]
|
||||||
|
[![NPM downloads][downloads-image]][downloads-url]
|
||||||
|
[![Build status][travis-image]][travis-url]
|
||||||
|
[![Test coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
> Flatten an array of nested arrays into a single flat array. Accepts an optional depth.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install array-flatten --save
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var flatten = require('array-flatten')
|
||||||
|
|
||||||
|
flatten([1, [2, [3, [4, [5], 6], 7], 8], 9])
|
||||||
|
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
|
||||||
|
flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2)
|
||||||
|
//=> [1, 2, 3, [4, [5], 6], 7, 8, 9]
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
flatten(arguments) //=> [1, 2, 3]
|
||||||
|
})(1, [2, 3])
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
||||||
|
[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat
|
||||||
|
[npm-url]: https://npmjs.org/package/array-flatten
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat
|
||||||
|
[downloads-url]: https://npmjs.org/package/array-flatten
|
||||||
|
[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat
|
||||||
|
[travis-url]: https://travis-ci.org/blakeembrey/array-flatten
|
||||||
|
[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat
|
||||||
|
[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master
|
||||||
64
server/node_modules/array-flatten/array-flatten.js
generated
vendored
Normal file
64
server/node_modules/array-flatten/array-flatten.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose `arrayFlatten`.
|
||||||
|
*/
|
||||||
|
module.exports = arrayFlatten
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursive flatten function with depth.
|
||||||
|
*
|
||||||
|
* @param {Array} array
|
||||||
|
* @param {Array} result
|
||||||
|
* @param {Number} depth
|
||||||
|
* @return {Array}
|
||||||
|
*/
|
||||||
|
function flattenWithDepth (array, result, depth) {
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
var value = array[i]
|
||||||
|
|
||||||
|
if (depth > 0 && Array.isArray(value)) {
|
||||||
|
flattenWithDepth(value, result, depth - 1)
|
||||||
|
} else {
|
||||||
|
result.push(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursive flatten function. Omitting depth is slightly faster.
|
||||||
|
*
|
||||||
|
* @param {Array} array
|
||||||
|
* @param {Array} result
|
||||||
|
* @return {Array}
|
||||||
|
*/
|
||||||
|
function flattenForever (array, result) {
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
var value = array[i]
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
flattenForever(value, result)
|
||||||
|
} else {
|
||||||
|
result.push(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flatten an array, with the ability to define a depth.
|
||||||
|
*
|
||||||
|
* @param {Array} array
|
||||||
|
* @param {Number} depth
|
||||||
|
* @return {Array}
|
||||||
|
*/
|
||||||
|
function arrayFlatten (array, depth) {
|
||||||
|
if (depth == null) {
|
||||||
|
return flattenForever(array, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
return flattenWithDepth(array, [], depth)
|
||||||
|
}
|
||||||
39
server/node_modules/array-flatten/package.json
generated
vendored
Normal file
39
server/node_modules/array-flatten/package.json
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "array-flatten",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"description": "Flatten an array of nested arrays into a single flat array",
|
||||||
|
"main": "array-flatten.js",
|
||||||
|
"files": [
|
||||||
|
"array-flatten.js",
|
||||||
|
"LICENSE"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "istanbul cover _mocha -- -R spec"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/blakeembrey/array-flatten.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"array",
|
||||||
|
"flatten",
|
||||||
|
"arguments",
|
||||||
|
"depth"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Blake Embrey",
|
||||||
|
"email": "hello@blakeembrey.com",
|
||||||
|
"url": "http://blakeembrey.me"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/blakeembrey/array-flatten/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/blakeembrey/array-flatten",
|
||||||
|
"devDependencies": {
|
||||||
|
"istanbul": "^0.3.13",
|
||||||
|
"mocha": "^2.2.4",
|
||||||
|
"pre-commit": "^1.0.7",
|
||||||
|
"standard": "^3.7.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
65
server/node_modules/asn1/Jenkinsfile
generated
vendored
Normal file
65
server/node_modules/asn1/Jenkinsfile
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
@Library('jenkins-joylib@v1.0.8') _
|
||||||
|
|
||||||
|
pipeline {
|
||||||
|
|
||||||
|
agent none
|
||||||
|
|
||||||
|
options {
|
||||||
|
buildDiscarder(logRotator(numToKeepStr: '45'))
|
||||||
|
timestamps()
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('top') {
|
||||||
|
parallel {
|
||||||
|
stage('v4-zone') {
|
||||||
|
agent {
|
||||||
|
label joyCommonLabels(image_ver: '15.4.1')
|
||||||
|
}
|
||||||
|
tools {
|
||||||
|
nodejs 'sdcnode-v4-zone'
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage('check') {
|
||||||
|
steps{
|
||||||
|
sh('make check')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('test') {
|
||||||
|
steps{
|
||||||
|
sh('make test')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('v6-zone64') {
|
||||||
|
agent {
|
||||||
|
label joyCommonLabels(image_ver: '18.4.0')
|
||||||
|
}
|
||||||
|
tools {
|
||||||
|
nodejs 'sdcnode-v6-zone64'
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage('check') {
|
||||||
|
steps{
|
||||||
|
sh('make check')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('test') {
|
||||||
|
steps{
|
||||||
|
sh('make test')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
joySlackNotifications()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
server/node_modules/asn1/LICENSE
generated
vendored
Normal file
19
server/node_modules/asn1/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2011 Mark Cavage, All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE
|
||||||
50
server/node_modules/asn1/README.md
generated
vendored
Normal file
50
server/node_modules/asn1/README.md
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
node-asn1 is a library for encoding and decoding ASN.1 datatypes in pure JS.
|
||||||
|
Currently BER encoding is supported; at some point I'll likely have to do DER.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Mostly, if you're *actually* needing to read and write ASN.1, you probably don't
|
||||||
|
need this readme to explain what and why. If you have no idea what ASN.1 is,
|
||||||
|
see this: ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
|
||||||
|
|
||||||
|
The source is pretty much self-explanatory, and has read/write methods for the
|
||||||
|
common types out there.
|
||||||
|
|
||||||
|
### Decoding
|
||||||
|
|
||||||
|
The following reads an ASN.1 sequence with a boolean.
|
||||||
|
|
||||||
|
var Ber = require('asn1').Ber;
|
||||||
|
|
||||||
|
var reader = new Ber.Reader(Buffer.from([0x30, 0x03, 0x01, 0x01, 0xff]));
|
||||||
|
|
||||||
|
reader.readSequence();
|
||||||
|
console.log('Sequence len: ' + reader.length);
|
||||||
|
if (reader.peek() === Ber.Boolean)
|
||||||
|
console.log(reader.readBoolean());
|
||||||
|
|
||||||
|
### Encoding
|
||||||
|
|
||||||
|
The following generates the same payload as above.
|
||||||
|
|
||||||
|
var Ber = require('asn1').Ber;
|
||||||
|
|
||||||
|
var writer = new Ber.Writer();
|
||||||
|
|
||||||
|
writer.startSequence();
|
||||||
|
writer.writeBoolean(true);
|
||||||
|
writer.endSequence();
|
||||||
|
|
||||||
|
console.log(writer.buffer);
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
npm install asn1
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT.
|
||||||
|
|
||||||
|
## Bugs
|
||||||
|
|
||||||
|
See <https://github.com/joyent/node-asn1/issues>.
|
||||||
13
server/node_modules/asn1/lib/ber/errors.js
generated
vendored
Normal file
13
server/node_modules/asn1/lib/ber/errors.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
newInvalidAsn1Error: function (msg) {
|
||||||
|
var e = new Error();
|
||||||
|
e.name = 'InvalidAsn1Error';
|
||||||
|
e.message = msg || '';
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
27
server/node_modules/asn1/lib/ber/index.js
generated
vendored
Normal file
27
server/node_modules/asn1/lib/ber/index.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||||
|
|
||||||
|
var errors = require('./errors');
|
||||||
|
var types = require('./types');
|
||||||
|
|
||||||
|
var Reader = require('./reader');
|
||||||
|
var Writer = require('./writer');
|
||||||
|
|
||||||
|
|
||||||
|
// --- Exports
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
Reader: Reader,
|
||||||
|
|
||||||
|
Writer: Writer
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var t in types) {
|
||||||
|
if (types.hasOwnProperty(t))
|
||||||
|
module.exports[t] = types[t];
|
||||||
|
}
|
||||||
|
for (var e in errors) {
|
||||||
|
if (errors.hasOwnProperty(e))
|
||||||
|
module.exports[e] = errors[e];
|
||||||
|
}
|
||||||
262
server/node_modules/asn1/lib/ber/reader.js
generated
vendored
Normal file
262
server/node_modules/asn1/lib/ber/reader.js
generated
vendored
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
|
var Buffer = require('safer-buffer').Buffer;
|
||||||
|
|
||||||
|
var ASN1 = require('./types');
|
||||||
|
var errors = require('./errors');
|
||||||
|
|
||||||
|
|
||||||
|
// --- Globals
|
||||||
|
|
||||||
|
var newInvalidAsn1Error = errors.newInvalidAsn1Error;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- API
|
||||||
|
|
||||||
|
function Reader(data) {
|
||||||
|
if (!data || !Buffer.isBuffer(data))
|
||||||
|
throw new TypeError('data must be a node Buffer');
|
||||||
|
|
||||||
|
this._buf = data;
|
||||||
|
this._size = data.length;
|
||||||
|
|
||||||
|
// These hold the "current" state
|
||||||
|
this._len = 0;
|
||||||
|
this._offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(Reader.prototype, 'length', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () { return (this._len); }
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Reader.prototype, 'offset', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () { return (this._offset); }
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Reader.prototype, 'remain', {
|
||||||
|
get: function () { return (this._size - this._offset); }
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Reader.prototype, 'buffer', {
|
||||||
|
get: function () { return (this._buf.slice(this._offset)); }
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a single byte and advances offset; you can pass in `true` to make this
|
||||||
|
* a "peek" operation (i.e., get the byte, but don't advance the offset).
|
||||||
|
*
|
||||||
|
* @param {Boolean} peek true means don't move offset.
|
||||||
|
* @return {Number} the next byte, null if not enough data.
|
||||||
|
*/
|
||||||
|
Reader.prototype.readByte = function (peek) {
|
||||||
|
if (this._size - this._offset < 1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var b = this._buf[this._offset] & 0xff;
|
||||||
|
|
||||||
|
if (!peek)
|
||||||
|
this._offset += 1;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reader.prototype.peek = function () {
|
||||||
|
return this.readByte(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a (potentially) variable length off the BER buffer. This call is
|
||||||
|
* not really meant to be called directly, as callers have to manipulate
|
||||||
|
* the internal buffer afterwards.
|
||||||
|
*
|
||||||
|
* As a result of this call, you can call `Reader.length`, until the
|
||||||
|
* next thing called that does a readLength.
|
||||||
|
*
|
||||||
|
* @return {Number} the amount of offset to advance the buffer.
|
||||||
|
* @throws {InvalidAsn1Error} on bad ASN.1
|
||||||
|
*/
|
||||||
|
Reader.prototype.readLength = function (offset) {
|
||||||
|
if (offset === undefined)
|
||||||
|
offset = this._offset;
|
||||||
|
|
||||||
|
if (offset >= this._size)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var lenB = this._buf[offset++] & 0xff;
|
||||||
|
if (lenB === null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if ((lenB & 0x80) === 0x80) {
|
||||||
|
lenB &= 0x7f;
|
||||||
|
|
||||||
|
if (lenB === 0)
|
||||||
|
throw newInvalidAsn1Error('Indefinite length not supported');
|
||||||
|
|
||||||
|
if (lenB > 4)
|
||||||
|
throw newInvalidAsn1Error('encoding too long');
|
||||||
|
|
||||||
|
if (this._size - offset < lenB)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
this._len = 0;
|
||||||
|
for (var i = 0; i < lenB; i++)
|
||||||
|
this._len = (this._len << 8) + (this._buf[offset++] & 0xff);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Wasn't a variable length
|
||||||
|
this._len = lenB;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the next sequence in this BER buffer.
|
||||||
|
*
|
||||||
|
* To get the length of the sequence, call `Reader.length`.
|
||||||
|
*
|
||||||
|
* @return {Number} the sequence's tag.
|
||||||
|
*/
|
||||||
|
Reader.prototype.readSequence = function (tag) {
|
||||||
|
var seq = this.peek();
|
||||||
|
if (seq === null)
|
||||||
|
return null;
|
||||||
|
if (tag !== undefined && tag !== seq)
|
||||||
|
throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
|
||||||
|
': got 0x' + seq.toString(16));
|
||||||
|
|
||||||
|
var o = this.readLength(this._offset + 1); // stored in `length`
|
||||||
|
if (o === null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
this._offset = o;
|
||||||
|
return seq;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reader.prototype.readInt = function () {
|
||||||
|
return this._readTag(ASN1.Integer);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reader.prototype.readBoolean = function () {
|
||||||
|
return (this._readTag(ASN1.Boolean) === 0 ? false : true);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reader.prototype.readEnumeration = function () {
|
||||||
|
return this._readTag(ASN1.Enumeration);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reader.prototype.readString = function (tag, retbuf) {
|
||||||
|
if (!tag)
|
||||||
|
tag = ASN1.OctetString;
|
||||||
|
|
||||||
|
var b = this.peek();
|
||||||
|
if (b === null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (b !== tag)
|
||||||
|
throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
|
||||||
|
': got 0x' + b.toString(16));
|
||||||
|
|
||||||
|
var o = this.readLength(this._offset + 1); // stored in `length`
|
||||||
|
|
||||||
|
if (o === null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (this.length > this._size - o)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
this._offset = o;
|
||||||
|
|
||||||
|
if (this.length === 0)
|
||||||
|
return retbuf ? Buffer.alloc(0) : '';
|
||||||
|
|
||||||
|
var str = this._buf.slice(this._offset, this._offset + this.length);
|
||||||
|
this._offset += this.length;
|
||||||
|
|
||||||
|
return retbuf ? str : str.toString('utf8');
|
||||||
|
};
|
||||||
|
|
||||||
|
Reader.prototype.readOID = function (tag) {
|
||||||
|
if (!tag)
|
||||||
|
tag = ASN1.OID;
|
||||||
|
|
||||||
|
var b = this.readString(tag, true);
|
||||||
|
if (b === null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var values = [];
|
||||||
|
var value = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < b.length; i++) {
|
||||||
|
var byte = b[i] & 0xff;
|
||||||
|
|
||||||
|
value <<= 7;
|
||||||
|
value += byte & 0x7f;
|
||||||
|
if ((byte & 0x80) === 0) {
|
||||||
|
values.push(value);
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = values.shift();
|
||||||
|
values.unshift(value % 40);
|
||||||
|
values.unshift((value / 40) >> 0);
|
||||||
|
|
||||||
|
return values.join('.');
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reader.prototype._readTag = function (tag) {
|
||||||
|
assert.ok(tag !== undefined);
|
||||||
|
|
||||||
|
var b = this.peek();
|
||||||
|
|
||||||
|
if (b === null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (b !== tag)
|
||||||
|
throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
|
||||||
|
': got 0x' + b.toString(16));
|
||||||
|
|
||||||
|
var o = this.readLength(this._offset + 1); // stored in `length`
|
||||||
|
if (o === null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (this.length > 4)
|
||||||
|
throw newInvalidAsn1Error('Integer too long: ' + this.length);
|
||||||
|
|
||||||
|
if (this.length > this._size - o)
|
||||||
|
return null;
|
||||||
|
this._offset = o;
|
||||||
|
|
||||||
|
var fb = this._buf[this._offset];
|
||||||
|
var value = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < this.length; i++) {
|
||||||
|
value <<= 8;
|
||||||
|
value |= (this._buf[this._offset++] & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fb & 0x80) === 0x80 && i !== 4)
|
||||||
|
value -= (1 << (i * 8));
|
||||||
|
|
||||||
|
return value >> 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- Exported API
|
||||||
|
|
||||||
|
module.exports = Reader;
|
||||||
36
server/node_modules/asn1/lib/ber/types.js
generated
vendored
Normal file
36
server/node_modules/asn1/lib/ber/types.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
EOC: 0,
|
||||||
|
Boolean: 1,
|
||||||
|
Integer: 2,
|
||||||
|
BitString: 3,
|
||||||
|
OctetString: 4,
|
||||||
|
Null: 5,
|
||||||
|
OID: 6,
|
||||||
|
ObjectDescriptor: 7,
|
||||||
|
External: 8,
|
||||||
|
Real: 9, // float
|
||||||
|
Enumeration: 10,
|
||||||
|
PDV: 11,
|
||||||
|
Utf8String: 12,
|
||||||
|
RelativeOID: 13,
|
||||||
|
Sequence: 16,
|
||||||
|
Set: 17,
|
||||||
|
NumericString: 18,
|
||||||
|
PrintableString: 19,
|
||||||
|
T61String: 20,
|
||||||
|
VideotexString: 21,
|
||||||
|
IA5String: 22,
|
||||||
|
UTCTime: 23,
|
||||||
|
GeneralizedTime: 24,
|
||||||
|
GraphicString: 25,
|
||||||
|
VisibleString: 26,
|
||||||
|
GeneralString: 28,
|
||||||
|
UniversalString: 29,
|
||||||
|
CharacterString: 30,
|
||||||
|
BMPString: 31,
|
||||||
|
Constructor: 32,
|
||||||
|
Context: 128
|
||||||
|
};
|
||||||
317
server/node_modules/asn1/lib/ber/writer.js
generated
vendored
Normal file
317
server/node_modules/asn1/lib/ber/writer.js
generated
vendored
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
|
var Buffer = require('safer-buffer').Buffer;
|
||||||
|
var ASN1 = require('./types');
|
||||||
|
var errors = require('./errors');
|
||||||
|
|
||||||
|
|
||||||
|
// --- Globals
|
||||||
|
|
||||||
|
var newInvalidAsn1Error = errors.newInvalidAsn1Error;
|
||||||
|
|
||||||
|
var DEFAULT_OPTS = {
|
||||||
|
size: 1024,
|
||||||
|
growthFactor: 8
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// --- Helpers
|
||||||
|
|
||||||
|
function merge(from, to) {
|
||||||
|
assert.ok(from);
|
||||||
|
assert.equal(typeof (from), 'object');
|
||||||
|
assert.ok(to);
|
||||||
|
assert.equal(typeof (to), 'object');
|
||||||
|
|
||||||
|
var keys = Object.getOwnPropertyNames(from);
|
||||||
|
keys.forEach(function (key) {
|
||||||
|
if (to[key])
|
||||||
|
return;
|
||||||
|
|
||||||
|
var value = Object.getOwnPropertyDescriptor(from, key);
|
||||||
|
Object.defineProperty(to, key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- API
|
||||||
|
|
||||||
|
function Writer(options) {
|
||||||
|
options = merge(DEFAULT_OPTS, options || {});
|
||||||
|
|
||||||
|
this._buf = Buffer.alloc(options.size || 1024);
|
||||||
|
this._size = this._buf.length;
|
||||||
|
this._offset = 0;
|
||||||
|
this._options = options;
|
||||||
|
|
||||||
|
// A list of offsets in the buffer where we need to insert
|
||||||
|
// sequence tag/len pairs.
|
||||||
|
this._seq = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(Writer.prototype, 'buffer', {
|
||||||
|
get: function () {
|
||||||
|
if (this._seq.length)
|
||||||
|
throw newInvalidAsn1Error(this._seq.length + ' unended sequence(s)');
|
||||||
|
|
||||||
|
return (this._buf.slice(0, this._offset));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Writer.prototype.writeByte = function (b) {
|
||||||
|
if (typeof (b) !== 'number')
|
||||||
|
throw new TypeError('argument must be a Number');
|
||||||
|
|
||||||
|
this._ensure(1);
|
||||||
|
this._buf[this._offset++] = b;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.writeInt = function (i, tag) {
|
||||||
|
if (typeof (i) !== 'number')
|
||||||
|
throw new TypeError('argument must be a Number');
|
||||||
|
if (typeof (tag) !== 'number')
|
||||||
|
tag = ASN1.Integer;
|
||||||
|
|
||||||
|
var sz = 4;
|
||||||
|
|
||||||
|
while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000 >> 0)) &&
|
||||||
|
(sz > 1)) {
|
||||||
|
sz--;
|
||||||
|
i <<= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sz > 4)
|
||||||
|
throw newInvalidAsn1Error('BER ints cannot be > 0xffffffff');
|
||||||
|
|
||||||
|
this._ensure(2 + sz);
|
||||||
|
this._buf[this._offset++] = tag;
|
||||||
|
this._buf[this._offset++] = sz;
|
||||||
|
|
||||||
|
while (sz-- > 0) {
|
||||||
|
this._buf[this._offset++] = ((i & 0xff000000) >>> 24);
|
||||||
|
i <<= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.writeNull = function () {
|
||||||
|
this.writeByte(ASN1.Null);
|
||||||
|
this.writeByte(0x00);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.writeEnumeration = function (i, tag) {
|
||||||
|
if (typeof (i) !== 'number')
|
||||||
|
throw new TypeError('argument must be a Number');
|
||||||
|
if (typeof (tag) !== 'number')
|
||||||
|
tag = ASN1.Enumeration;
|
||||||
|
|
||||||
|
return this.writeInt(i, tag);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.writeBoolean = function (b, tag) {
|
||||||
|
if (typeof (b) !== 'boolean')
|
||||||
|
throw new TypeError('argument must be a Boolean');
|
||||||
|
if (typeof (tag) !== 'number')
|
||||||
|
tag = ASN1.Boolean;
|
||||||
|
|
||||||
|
this._ensure(3);
|
||||||
|
this._buf[this._offset++] = tag;
|
||||||
|
this._buf[this._offset++] = 0x01;
|
||||||
|
this._buf[this._offset++] = b ? 0xff : 0x00;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.writeString = function (s, tag) {
|
||||||
|
if (typeof (s) !== 'string')
|
||||||
|
throw new TypeError('argument must be a string (was: ' + typeof (s) + ')');
|
||||||
|
if (typeof (tag) !== 'number')
|
||||||
|
tag = ASN1.OctetString;
|
||||||
|
|
||||||
|
var len = Buffer.byteLength(s);
|
||||||
|
this.writeByte(tag);
|
||||||
|
this.writeLength(len);
|
||||||
|
if (len) {
|
||||||
|
this._ensure(len);
|
||||||
|
this._buf.write(s, this._offset);
|
||||||
|
this._offset += len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.writeBuffer = function (buf, tag) {
|
||||||
|
if (typeof (tag) !== 'number')
|
||||||
|
throw new TypeError('tag must be a number');
|
||||||
|
if (!Buffer.isBuffer(buf))
|
||||||
|
throw new TypeError('argument must be a buffer');
|
||||||
|
|
||||||
|
this.writeByte(tag);
|
||||||
|
this.writeLength(buf.length);
|
||||||
|
this._ensure(buf.length);
|
||||||
|
buf.copy(this._buf, this._offset, 0, buf.length);
|
||||||
|
this._offset += buf.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.writeStringArray = function (strings) {
|
||||||
|
if ((!strings instanceof Array))
|
||||||
|
throw new TypeError('argument must be an Array[String]');
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
strings.forEach(function (s) {
|
||||||
|
self.writeString(s);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is really to solve DER cases, but whatever for now
|
||||||
|
Writer.prototype.writeOID = function (s, tag) {
|
||||||
|
if (typeof (s) !== 'string')
|
||||||
|
throw new TypeError('argument must be a string');
|
||||||
|
if (typeof (tag) !== 'number')
|
||||||
|
tag = ASN1.OID;
|
||||||
|
|
||||||
|
if (!/^([0-9]+\.){3,}[0-9]+$/.test(s))
|
||||||
|
throw new Error('argument is not a valid OID string');
|
||||||
|
|
||||||
|
function encodeOctet(bytes, octet) {
|
||||||
|
if (octet < 128) {
|
||||||
|
bytes.push(octet);
|
||||||
|
} else if (octet < 16384) {
|
||||||
|
bytes.push((octet >>> 7) | 0x80);
|
||||||
|
bytes.push(octet & 0x7F);
|
||||||
|
} else if (octet < 2097152) {
|
||||||
|
bytes.push((octet >>> 14) | 0x80);
|
||||||
|
bytes.push(((octet >>> 7) | 0x80) & 0xFF);
|
||||||
|
bytes.push(octet & 0x7F);
|
||||||
|
} else if (octet < 268435456) {
|
||||||
|
bytes.push((octet >>> 21) | 0x80);
|
||||||
|
bytes.push(((octet >>> 14) | 0x80) & 0xFF);
|
||||||
|
bytes.push(((octet >>> 7) | 0x80) & 0xFF);
|
||||||
|
bytes.push(octet & 0x7F);
|
||||||
|
} else {
|
||||||
|
bytes.push(((octet >>> 28) | 0x80) & 0xFF);
|
||||||
|
bytes.push(((octet >>> 21) | 0x80) & 0xFF);
|
||||||
|
bytes.push(((octet >>> 14) | 0x80) & 0xFF);
|
||||||
|
bytes.push(((octet >>> 7) | 0x80) & 0xFF);
|
||||||
|
bytes.push(octet & 0x7F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmp = s.split('.');
|
||||||
|
var bytes = [];
|
||||||
|
bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10));
|
||||||
|
tmp.slice(2).forEach(function (b) {
|
||||||
|
encodeOctet(bytes, parseInt(b, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this._ensure(2 + bytes.length);
|
||||||
|
this.writeByte(tag);
|
||||||
|
this.writeLength(bytes.length);
|
||||||
|
bytes.forEach(function (b) {
|
||||||
|
self.writeByte(b);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.writeLength = function (len) {
|
||||||
|
if (typeof (len) !== 'number')
|
||||||
|
throw new TypeError('argument must be a Number');
|
||||||
|
|
||||||
|
this._ensure(4);
|
||||||
|
|
||||||
|
if (len <= 0x7f) {
|
||||||
|
this._buf[this._offset++] = len;
|
||||||
|
} else if (len <= 0xff) {
|
||||||
|
this._buf[this._offset++] = 0x81;
|
||||||
|
this._buf[this._offset++] = len;
|
||||||
|
} else if (len <= 0xffff) {
|
||||||
|
this._buf[this._offset++] = 0x82;
|
||||||
|
this._buf[this._offset++] = len >> 8;
|
||||||
|
this._buf[this._offset++] = len;
|
||||||
|
} else if (len <= 0xffffff) {
|
||||||
|
this._buf[this._offset++] = 0x83;
|
||||||
|
this._buf[this._offset++] = len >> 16;
|
||||||
|
this._buf[this._offset++] = len >> 8;
|
||||||
|
this._buf[this._offset++] = len;
|
||||||
|
} else {
|
||||||
|
throw newInvalidAsn1Error('Length too long (> 4 bytes)');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Writer.prototype.startSequence = function (tag) {
|
||||||
|
if (typeof (tag) !== 'number')
|
||||||
|
tag = ASN1.Sequence | ASN1.Constructor;
|
||||||
|
|
||||||
|
this.writeByte(tag);
|
||||||
|
this._seq.push(this._offset);
|
||||||
|
this._ensure(3);
|
||||||
|
this._offset += 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype.endSequence = function () {
|
||||||
|
var seq = this._seq.pop();
|
||||||
|
var start = seq + 3;
|
||||||
|
var len = this._offset - start;
|
||||||
|
|
||||||
|
if (len <= 0x7f) {
|
||||||
|
this._shift(start, len, -2);
|
||||||
|
this._buf[seq] = len;
|
||||||
|
} else if (len <= 0xff) {
|
||||||
|
this._shift(start, len, -1);
|
||||||
|
this._buf[seq] = 0x81;
|
||||||
|
this._buf[seq + 1] = len;
|
||||||
|
} else if (len <= 0xffff) {
|
||||||
|
this._buf[seq] = 0x82;
|
||||||
|
this._buf[seq + 1] = len >> 8;
|
||||||
|
this._buf[seq + 2] = len;
|
||||||
|
} else if (len <= 0xffffff) {
|
||||||
|
this._shift(start, len, 1);
|
||||||
|
this._buf[seq] = 0x83;
|
||||||
|
this._buf[seq + 1] = len >> 16;
|
||||||
|
this._buf[seq + 2] = len >> 8;
|
||||||
|
this._buf[seq + 3] = len;
|
||||||
|
} else {
|
||||||
|
throw newInvalidAsn1Error('Sequence too long');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Writer.prototype._shift = function (start, len, shift) {
|
||||||
|
assert.ok(start !== undefined);
|
||||||
|
assert.ok(len !== undefined);
|
||||||
|
assert.ok(shift);
|
||||||
|
|
||||||
|
this._buf.copy(this._buf, start + shift, start, start + len);
|
||||||
|
this._offset += shift;
|
||||||
|
};
|
||||||
|
|
||||||
|
Writer.prototype._ensure = function (len) {
|
||||||
|
assert.ok(len);
|
||||||
|
|
||||||
|
if (this._size - this._offset < len) {
|
||||||
|
var sz = this._size * this._options.growthFactor;
|
||||||
|
if (sz - this._offset < len)
|
||||||
|
sz += len;
|
||||||
|
|
||||||
|
var buf = Buffer.alloc(sz);
|
||||||
|
|
||||||
|
this._buf.copy(buf, 0, 0, this._offset);
|
||||||
|
this._buf = buf;
|
||||||
|
this._size = sz;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- Exported API
|
||||||
|
|
||||||
|
module.exports = Writer;
|
||||||
20
server/node_modules/asn1/lib/index.js
generated
vendored
Normal file
20
server/node_modules/asn1/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||||
|
|
||||||
|
// If you have no idea what ASN.1 or BER is, see this:
|
||||||
|
// ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
|
||||||
|
|
||||||
|
var Ber = require('./ber/index');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- Exported API
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
Ber: Ber,
|
||||||
|
|
||||||
|
BerReader: Ber.Reader,
|
||||||
|
|
||||||
|
BerWriter: Ber.Writer
|
||||||
|
|
||||||
|
};
|
||||||
31
server/node_modules/asn1/package.json
generated
vendored
Normal file
31
server/node_modules/asn1/package.json
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"author": "Joyent (joyent.com)",
|
||||||
|
"contributors": [
|
||||||
|
"Mark Cavage <mcavage@gmail.com>",
|
||||||
|
"David Gwynne <loki@animata.net>",
|
||||||
|
"Yunong Xiao <yunong@joyent.com>",
|
||||||
|
"Alex Wilson <alex.wilson@joyent.com>"
|
||||||
|
],
|
||||||
|
"name": "asn1",
|
||||||
|
"description": "Contains parsers and serializers for ASN.1 (currently BER only)",
|
||||||
|
"version": "0.2.6",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/joyent/node-asn1.git"
|
||||||
|
},
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": "~2.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"istanbul": "^0.3.6",
|
||||||
|
"faucet": "0.0.1",
|
||||||
|
"tape": "^3.5.0",
|
||||||
|
"eslint": "2.13.1",
|
||||||
|
"eslint-plugin-joyent": "~1.3.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "./node_modules/.bin/tape ./test/ber/*.test.js"
|
||||||
|
},
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
13
server/node_modules/bcrypt-pbkdf/CONTRIBUTING.md
generated
vendored
Normal file
13
server/node_modules/bcrypt-pbkdf/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
This repository uses [cr.joyent.us](https://cr.joyent.us) (Gerrit) for new
|
||||||
|
changes. Anyone can submit changes. To get started, see the [cr.joyent.us user
|
||||||
|
guide](https://github.com/joyent/joyent-gerrit/blob/master/docs/user/README.md).
|
||||||
|
This repo does not use GitHub pull requests.
|
||||||
|
|
||||||
|
See the [Joyent Engineering
|
||||||
|
Guidelines](https://github.com/joyent/eng/blob/master/docs/index.md) for general
|
||||||
|
best practices expected in this repository.
|
||||||
|
|
||||||
|
If you're changing something non-trivial or user-facing, you may want to submit
|
||||||
|
an issue first.
|
||||||
66
server/node_modules/bcrypt-pbkdf/LICENSE
generated
vendored
Normal file
66
server/node_modules/bcrypt-pbkdf/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
The Blowfish portions are under the following license:
|
||||||
|
|
||||||
|
Blowfish block cipher for OpenBSD
|
||||||
|
Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Implementation advice by David Mazieres <dm@lcs.mit.edu>.
|
||||||
|
|
||||||
|
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.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The bcrypt_pbkdf portions are under the following license:
|
||||||
|
|
||||||
|
Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Performance improvements (Javascript-specific):
|
||||||
|
|
||||||
|
Copyright 2016, Joyent Inc
|
||||||
|
Author: Alex Wilson <alex.wilson@joyent.com>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
45
server/node_modules/bcrypt-pbkdf/README.md
generated
vendored
Normal file
45
server/node_modules/bcrypt-pbkdf/README.md
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
Port of the OpenBSD `bcrypt_pbkdf` function to pure Javascript. `npm`-ified
|
||||||
|
version of [Devi Mandiri's port](https://github.com/devi/tmp/blob/master/js/bcrypt_pbkdf.js),
|
||||||
|
with some minor performance improvements. The code is copied verbatim (and
|
||||||
|
un-styled) from Devi's work.
|
||||||
|
|
||||||
|
This product includes software developed by Niels Provos.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### `bcrypt_pbkdf.pbkdf(pass, passlen, salt, saltlen, key, keylen, rounds)`
|
||||||
|
|
||||||
|
Derive a cryptographic key of arbitrary length from a given password and salt,
|
||||||
|
using the OpenBSD `bcrypt_pbkdf` function. This is a combination of Blowfish and
|
||||||
|
SHA-512.
|
||||||
|
|
||||||
|
See [this article](http://www.tedunangst.com/flak/post/bcrypt-pbkdf) for
|
||||||
|
further information.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
* `pass`, a Uint8Array of length `passlen`
|
||||||
|
* `passlen`, an integer Number
|
||||||
|
* `salt`, a Uint8Array of length `saltlen`
|
||||||
|
* `saltlen`, an integer Number
|
||||||
|
* `key`, a Uint8Array of length `keylen`, will be filled with output
|
||||||
|
* `keylen`, an integer Number
|
||||||
|
* `rounds`, an integer Number, number of rounds of the PBKDF to run
|
||||||
|
|
||||||
|
### `bcrypt_pbkdf.hash(sha2pass, sha2salt, out)`
|
||||||
|
|
||||||
|
Calculate a Blowfish hash, given SHA2-512 output of a password and salt. Used as
|
||||||
|
part of the inner round function in the PBKDF.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
* `sha2pass`, a Uint8Array of length 64
|
||||||
|
* `sha2salt`, a Uint8Array of length 64
|
||||||
|
* `out`, a Uint8Array of length 32, will be filled with output
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This source form is a 1:1 port from the OpenBSD `blowfish.c` and `bcrypt_pbkdf.c`.
|
||||||
|
As a result, it retains the original copyright and license. The two files are
|
||||||
|
under slightly different (but compatible) licenses, and are here combined in
|
||||||
|
one file. For each of the full license texts see `LICENSE`.
|
||||||
556
server/node_modules/bcrypt-pbkdf/index.js
generated
vendored
Normal file
556
server/node_modules/bcrypt-pbkdf/index.js
generated
vendored
Normal file
@@ -0,0 +1,556 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var crypto_hash_sha512 = require('tweetnacl').lowlevel.crypto_hash;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is a 1:1 port from the OpenBSD blowfish.c and bcrypt_pbkdf.c. As a
|
||||||
|
* result, it retains the original copyright and license. The two files are
|
||||||
|
* under slightly different (but compatible) licenses, and are here combined in
|
||||||
|
* one file.
|
||||||
|
*
|
||||||
|
* Credit for the actual porting work goes to:
|
||||||
|
* Devi Mandiri <me@devi.web.id>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Blowfish portions are under the following license:
|
||||||
|
*
|
||||||
|
* Blowfish block cipher for OpenBSD
|
||||||
|
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Implementation advice by David Mazieres <dm@lcs.mit.edu>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The bcrypt_pbkdf portions are under the following license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Performance improvements (Javascript-specific):
|
||||||
|
*
|
||||||
|
* Copyright 2016, Joyent Inc
|
||||||
|
* Author: Alex Wilson <alex.wilson@joyent.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Ported from OpenBSD bcrypt_pbkdf.c v1.9
|
||||||
|
|
||||||
|
var BLF_J = 0;
|
||||||
|
|
||||||
|
var Blowfish = function() {
|
||||||
|
this.S = [
|
||||||
|
new Uint32Array([
|
||||||
|
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
||||||
|
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
||||||
|
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||||
|
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
||||||
|
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
|
||||||
|
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||||
|
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
|
||||||
|
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
||||||
|
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||||
|
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
||||||
|
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
|
||||||
|
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||||
|
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
|
||||||
|
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
||||||
|
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||||
|
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
||||||
|
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
|
||||||
|
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||||
|
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
|
||||||
|
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
||||||
|
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||||
|
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
||||||
|
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
|
||||||
|
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||||
|
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
|
||||||
|
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
||||||
|
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||||
|
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
||||||
|
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
|
||||||
|
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||||
|
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
|
||||||
|
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
||||||
|
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||||
|
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
||||||
|
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
|
||||||
|
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||||
|
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
|
||||||
|
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
||||||
|
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||||
|
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
||||||
|
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
|
||||||
|
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||||
|
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
|
||||||
|
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
||||||
|
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||||
|
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
||||||
|
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
|
||||||
|
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||||
|
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
|
||||||
|
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
||||||
|
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||||
|
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
||||||
|
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
|
||||||
|
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||||
|
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
|
||||||
|
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
||||||
|
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||||
|
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
||||||
|
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
|
||||||
|
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||||
|
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
||||||
|
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
||||||
|
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||||
|
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a]),
|
||||||
|
new Uint32Array([
|
||||||
|
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
||||||
|
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
||||||
|
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||||
|
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
||||||
|
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
||||||
|
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||||
|
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
|
||||||
|
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
||||||
|
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||||
|
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
||||||
|
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
||||||
|
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||||
|
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
|
||||||
|
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
||||||
|
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||||
|
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
||||||
|
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
||||||
|
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||||
|
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
|
||||||
|
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
||||||
|
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||||
|
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
||||||
|
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
||||||
|
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||||
|
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
|
||||||
|
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
||||||
|
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||||
|
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
||||||
|
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
||||||
|
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||||
|
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
|
||||||
|
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
||||||
|
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||||
|
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
||||||
|
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
||||||
|
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||||
|
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
|
||||||
|
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
||||||
|
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||||
|
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
||||||
|
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
||||||
|
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||||
|
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
|
||||||
|
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
||||||
|
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||||
|
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
||||||
|
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
||||||
|
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||||
|
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
|
||||||
|
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
||||||
|
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||||
|
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
||||||
|
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
||||||
|
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||||
|
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
|
||||||
|
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
||||||
|
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||||
|
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
||||||
|
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
||||||
|
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||||
|
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
||||||
|
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
||||||
|
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||||
|
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7]),
|
||||||
|
new Uint32Array([
|
||||||
|
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
||||||
|
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
||||||
|
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||||
|
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
||||||
|
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
|
||||||
|
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||||
|
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
||||||
|
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
||||||
|
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||||
|
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
||||||
|
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
|
||||||
|
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||||
|
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
||||||
|
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
||||||
|
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||||
|
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
||||||
|
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
|
||||||
|
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||||
|
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
||||||
|
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
||||||
|
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||||
|
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
||||||
|
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
|
||||||
|
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||||
|
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
||||||
|
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
||||||
|
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||||
|
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
||||||
|
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
|
||||||
|
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||||
|
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
||||||
|
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
||||||
|
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||||
|
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
||||||
|
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
|
||||||
|
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||||
|
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
||||||
|
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
||||||
|
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||||
|
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
||||||
|
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
|
||||||
|
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||||
|
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
||||||
|
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
||||||
|
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||||
|
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
||||||
|
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
|
||||||
|
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||||
|
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
||||||
|
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
||||||
|
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||||
|
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
||||||
|
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
|
||||||
|
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||||
|
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
||||||
|
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
||||||
|
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||||
|
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
||||||
|
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
|
||||||
|
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||||
|
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
||||||
|
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
||||||
|
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||||
|
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0]),
|
||||||
|
new Uint32Array([
|
||||||
|
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
||||||
|
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
||||||
|
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||||
|
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
||||||
|
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
|
||||||
|
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||||
|
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
|
||||||
|
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
||||||
|
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||||
|
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
||||||
|
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
|
||||||
|
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||||
|
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
|
||||||
|
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
||||||
|
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||||
|
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
||||||
|
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
|
||||||
|
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||||
|
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
|
||||||
|
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
||||||
|
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||||
|
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
||||||
|
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
|
||||||
|
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||||
|
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
|
||||||
|
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
||||||
|
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||||
|
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
||||||
|
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
|
||||||
|
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||||
|
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
|
||||||
|
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
||||||
|
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||||
|
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
||||||
|
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
|
||||||
|
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||||
|
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
|
||||||
|
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
||||||
|
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||||
|
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
||||||
|
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
|
||||||
|
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||||
|
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
|
||||||
|
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
||||||
|
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||||
|
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
||||||
|
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
|
||||||
|
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||||
|
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
|
||||||
|
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
||||||
|
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||||
|
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
||||||
|
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
|
||||||
|
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||||
|
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
|
||||||
|
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
||||||
|
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||||
|
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
||||||
|
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
|
||||||
|
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||||
|
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
||||||
|
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
||||||
|
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||||
|
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6])
|
||||||
|
];
|
||||||
|
this.P = new Uint32Array([
|
||||||
|
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
||||||
|
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
||||||
|
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||||
|
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
||||||
|
0x9216d5d9, 0x8979fb1b]);
|
||||||
|
};
|
||||||
|
|
||||||
|
function F(S, x8, i) {
|
||||||
|
return (((S[0][x8[i+3]] +
|
||||||
|
S[1][x8[i+2]]) ^
|
||||||
|
S[2][x8[i+1]]) +
|
||||||
|
S[3][x8[i]]);
|
||||||
|
};
|
||||||
|
|
||||||
|
Blowfish.prototype.encipher = function(x, x8) {
|
||||||
|
if (x8 === undefined) {
|
||||||
|
x8 = new Uint8Array(x.buffer);
|
||||||
|
if (x.byteOffset !== 0)
|
||||||
|
x8 = x8.subarray(x.byteOffset);
|
||||||
|
}
|
||||||
|
x[0] ^= this.P[0];
|
||||||
|
for (var i = 1; i < 16; i += 2) {
|
||||||
|
x[1] ^= F(this.S, x8, 0) ^ this.P[i];
|
||||||
|
x[0] ^= F(this.S, x8, 4) ^ this.P[i+1];
|
||||||
|
}
|
||||||
|
var t = x[0];
|
||||||
|
x[0] = x[1] ^ this.P[17];
|
||||||
|
x[1] = t;
|
||||||
|
};
|
||||||
|
|
||||||
|
Blowfish.prototype.decipher = function(x) {
|
||||||
|
var x8 = new Uint8Array(x.buffer);
|
||||||
|
if (x.byteOffset !== 0)
|
||||||
|
x8 = x8.subarray(x.byteOffset);
|
||||||
|
x[0] ^= this.P[17];
|
||||||
|
for (var i = 16; i > 0; i -= 2) {
|
||||||
|
x[1] ^= F(this.S, x8, 0) ^ this.P[i];
|
||||||
|
x[0] ^= F(this.S, x8, 4) ^ this.P[i-1];
|
||||||
|
}
|
||||||
|
var t = x[0];
|
||||||
|
x[0] = x[1] ^ this.P[0];
|
||||||
|
x[1] = t;
|
||||||
|
};
|
||||||
|
|
||||||
|
function stream2word(data, databytes){
|
||||||
|
var i, temp = 0;
|
||||||
|
for (i = 0; i < 4; i++, BLF_J++) {
|
||||||
|
if (BLF_J >= databytes) BLF_J = 0;
|
||||||
|
temp = (temp << 8) | data[BLF_J];
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
};
|
||||||
|
|
||||||
|
Blowfish.prototype.expand0state = function(key, keybytes) {
|
||||||
|
var d = new Uint32Array(2), i, k;
|
||||||
|
var d8 = new Uint8Array(d.buffer);
|
||||||
|
|
||||||
|
for (i = 0, BLF_J = 0; i < 18; i++) {
|
||||||
|
this.P[i] ^= stream2word(key, keybytes);
|
||||||
|
}
|
||||||
|
BLF_J = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 18; i += 2) {
|
||||||
|
this.encipher(d, d8);
|
||||||
|
this.P[i] = d[0];
|
||||||
|
this.P[i+1] = d[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
for (k = 0; k < 256; k += 2) {
|
||||||
|
this.encipher(d, d8);
|
||||||
|
this.S[i][k] = d[0];
|
||||||
|
this.S[i][k+1] = d[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Blowfish.prototype.expandstate = function(data, databytes, key, keybytes) {
|
||||||
|
var d = new Uint32Array(2), i, k;
|
||||||
|
|
||||||
|
for (i = 0, BLF_J = 0; i < 18; i++) {
|
||||||
|
this.P[i] ^= stream2word(key, keybytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, BLF_J = 0; i < 18; i += 2) {
|
||||||
|
d[0] ^= stream2word(data, databytes);
|
||||||
|
d[1] ^= stream2word(data, databytes);
|
||||||
|
this.encipher(d);
|
||||||
|
this.P[i] = d[0];
|
||||||
|
this.P[i+1] = d[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
for (k = 0; k < 256; k += 2) {
|
||||||
|
d[0] ^= stream2word(data, databytes);
|
||||||
|
d[1] ^= stream2word(data, databytes);
|
||||||
|
this.encipher(d);
|
||||||
|
this.S[i][k] = d[0];
|
||||||
|
this.S[i][k+1] = d[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BLF_J = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Blowfish.prototype.enc = function(data, blocks) {
|
||||||
|
for (var i = 0; i < blocks; i++) {
|
||||||
|
this.encipher(data.subarray(i*2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Blowfish.prototype.dec = function(data, blocks) {
|
||||||
|
for (var i = 0; i < blocks; i++) {
|
||||||
|
this.decipher(data.subarray(i*2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var BCRYPT_BLOCKS = 8,
|
||||||
|
BCRYPT_HASHSIZE = 32;
|
||||||
|
|
||||||
|
function bcrypt_hash(sha2pass, sha2salt, out) {
|
||||||
|
var state = new Blowfish(),
|
||||||
|
cdata = new Uint32Array(BCRYPT_BLOCKS), i,
|
||||||
|
ciphertext = new Uint8Array([79,120,121,99,104,114,111,109,97,116,105,
|
||||||
|
99,66,108,111,119,102,105,115,104,83,119,97,116,68,121,110,97,109,
|
||||||
|
105,116,101]); //"OxychromaticBlowfishSwatDynamite"
|
||||||
|
|
||||||
|
state.expandstate(sha2salt, 64, sha2pass, 64);
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
state.expand0state(sha2salt, 64);
|
||||||
|
state.expand0state(sha2pass, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < BCRYPT_BLOCKS; i++)
|
||||||
|
cdata[i] = stream2word(ciphertext, ciphertext.byteLength);
|
||||||
|
for (i = 0; i < 64; i++)
|
||||||
|
state.enc(cdata, cdata.byteLength / 8);
|
||||||
|
|
||||||
|
for (i = 0; i < BCRYPT_BLOCKS; i++) {
|
||||||
|
out[4*i+3] = cdata[i] >>> 24;
|
||||||
|
out[4*i+2] = cdata[i] >>> 16;
|
||||||
|
out[4*i+1] = cdata[i] >>> 8;
|
||||||
|
out[4*i+0] = cdata[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function bcrypt_pbkdf(pass, passlen, salt, saltlen, key, keylen, rounds) {
|
||||||
|
var sha2pass = new Uint8Array(64),
|
||||||
|
sha2salt = new Uint8Array(64),
|
||||||
|
out = new Uint8Array(BCRYPT_HASHSIZE),
|
||||||
|
tmpout = new Uint8Array(BCRYPT_HASHSIZE),
|
||||||
|
countsalt = new Uint8Array(saltlen+4),
|
||||||
|
i, j, amt, stride, dest, count,
|
||||||
|
origkeylen = keylen;
|
||||||
|
|
||||||
|
if (rounds < 1)
|
||||||
|
return -1;
|
||||||
|
if (passlen === 0 || saltlen === 0 || keylen === 0 ||
|
||||||
|
keylen > (out.byteLength * out.byteLength) || saltlen > (1<<20))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
stride = Math.floor((keylen + out.byteLength - 1) / out.byteLength);
|
||||||
|
amt = Math.floor((keylen + stride - 1) / stride);
|
||||||
|
|
||||||
|
for (i = 0; i < saltlen; i++)
|
||||||
|
countsalt[i] = salt[i];
|
||||||
|
|
||||||
|
crypto_hash_sha512(sha2pass, pass, passlen);
|
||||||
|
|
||||||
|
for (count = 1; keylen > 0; count++) {
|
||||||
|
countsalt[saltlen+0] = count >>> 24;
|
||||||
|
countsalt[saltlen+1] = count >>> 16;
|
||||||
|
countsalt[saltlen+2] = count >>> 8;
|
||||||
|
countsalt[saltlen+3] = count;
|
||||||
|
|
||||||
|
crypto_hash_sha512(sha2salt, countsalt, saltlen + 4);
|
||||||
|
bcrypt_hash(sha2pass, sha2salt, tmpout);
|
||||||
|
for (i = out.byteLength; i--;)
|
||||||
|
out[i] = tmpout[i];
|
||||||
|
|
||||||
|
for (i = 1; i < rounds; i++) {
|
||||||
|
crypto_hash_sha512(sha2salt, tmpout, tmpout.byteLength);
|
||||||
|
bcrypt_hash(sha2pass, sha2salt, tmpout);
|
||||||
|
for (j = 0; j < out.byteLength; j++)
|
||||||
|
out[j] ^= tmpout[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
amt = Math.min(amt, keylen);
|
||||||
|
for (i = 0; i < amt; i++) {
|
||||||
|
dest = i * stride + (count - 1);
|
||||||
|
if (dest >= origkeylen)
|
||||||
|
break;
|
||||||
|
key[dest] = out[i];
|
||||||
|
}
|
||||||
|
keylen -= i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
BLOCKS: BCRYPT_BLOCKS,
|
||||||
|
HASHSIZE: BCRYPT_HASHSIZE,
|
||||||
|
hash: bcrypt_hash,
|
||||||
|
pbkdf: bcrypt_pbkdf
|
||||||
|
};
|
||||||
15
server/node_modules/bcrypt-pbkdf/package.json
generated
vendored
Normal file
15
server/node_modules/bcrypt-pbkdf/package.json
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "bcrypt-pbkdf",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"description": "Port of the OpenBSD bcrypt_pbkdf function to pure JS",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/joyent/node-bcrypt-pbkdf.git"
|
||||||
|
},
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"tweetnacl": "^0.14.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {},
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
}
|
||||||
680
server/node_modules/body-parser/HISTORY.md
generated
vendored
Normal file
680
server/node_modules/body-parser/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,680 @@
|
|||||||
|
1.20.4 / 2025-12-01
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: qs@~6.14.0
|
||||||
|
* deps: use tilde notation for dependencies
|
||||||
|
* deps: http-errors@~2.0.1
|
||||||
|
* deps: raw-body@~2.5.3
|
||||||
|
|
||||||
|
1.20.3 / 2024-09-10
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: qs@6.13.0
|
||||||
|
* add `depth` option to customize the depth level in the parser
|
||||||
|
* IMPORTANT: The default `depth` level for parsing URL-encoded data is now `32` (previously was `Infinity`)
|
||||||
|
|
||||||
|
1.20.2 / 2023-02-21
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Fix strict json error message on Node.js 19+
|
||||||
|
* deps: content-type@~1.0.5
|
||||||
|
- perf: skip value escaping when unnecessary
|
||||||
|
* deps: raw-body@2.5.2
|
||||||
|
|
||||||
|
1.20.1 / 2022-10-06
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: qs@6.11.0
|
||||||
|
* perf: remove unnecessary object clone
|
||||||
|
|
||||||
|
1.20.0 / 2022-04-02
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Fix error message for json parse whitespace in `strict`
|
||||||
|
* Fix internal error when inflated body exceeds limit
|
||||||
|
* Prevent loss of async hooks context
|
||||||
|
* Prevent hanging when request already read
|
||||||
|
* deps: depd@2.0.0
|
||||||
|
- Replace internal `eval` usage with `Function` constructor
|
||||||
|
- Use instance methods on `process` to check for listeners
|
||||||
|
* deps: http-errors@2.0.0
|
||||||
|
- deps: depd@2.0.0
|
||||||
|
- deps: statuses@2.0.1
|
||||||
|
* deps: on-finished@2.4.1
|
||||||
|
* deps: qs@6.10.3
|
||||||
|
* deps: raw-body@2.5.1
|
||||||
|
- deps: http-errors@2.0.0
|
||||||
|
|
||||||
|
1.19.2 / 2022-02-15
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: bytes@3.1.2
|
||||||
|
* deps: qs@6.9.7
|
||||||
|
* Fix handling of `__proto__` keys
|
||||||
|
* deps: raw-body@2.4.3
|
||||||
|
- deps: bytes@3.1.2
|
||||||
|
|
||||||
|
1.19.1 / 2021-12-10
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: bytes@3.1.1
|
||||||
|
* deps: http-errors@1.8.1
|
||||||
|
- deps: inherits@2.0.4
|
||||||
|
- deps: toidentifier@1.0.1
|
||||||
|
- deps: setprototypeof@1.2.0
|
||||||
|
* deps: qs@6.9.6
|
||||||
|
* deps: raw-body@2.4.2
|
||||||
|
- deps: bytes@3.1.1
|
||||||
|
- deps: http-errors@1.8.1
|
||||||
|
* deps: safe-buffer@5.2.1
|
||||||
|
* deps: type-is@~1.6.18
|
||||||
|
|
||||||
|
1.19.0 / 2019-04-25
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: bytes@3.1.0
|
||||||
|
- Add petabyte (`pb`) support
|
||||||
|
* deps: http-errors@1.7.2
|
||||||
|
- Set constructor name when possible
|
||||||
|
- deps: setprototypeof@1.1.1
|
||||||
|
- deps: statuses@'>= 1.5.0 < 2'
|
||||||
|
* deps: iconv-lite@0.4.24
|
||||||
|
- Added encoding MIK
|
||||||
|
* deps: qs@6.7.0
|
||||||
|
- Fix parsing array brackets after index
|
||||||
|
* deps: raw-body@2.4.0
|
||||||
|
- deps: bytes@3.1.0
|
||||||
|
- deps: http-errors@1.7.2
|
||||||
|
- deps: iconv-lite@0.4.24
|
||||||
|
* deps: type-is@~1.6.17
|
||||||
|
- deps: mime-types@~2.1.24
|
||||||
|
- perf: prevent internal `throw` on invalid type
|
||||||
|
|
||||||
|
1.18.3 / 2018-05-14
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Fix stack trace for strict json parse error
|
||||||
|
* deps: depd@~1.1.2
|
||||||
|
- perf: remove argument reassignment
|
||||||
|
* deps: http-errors@~1.6.3
|
||||||
|
- deps: depd@~1.1.2
|
||||||
|
- deps: setprototypeof@1.1.0
|
||||||
|
- deps: statuses@'>= 1.3.1 < 2'
|
||||||
|
* deps: iconv-lite@0.4.23
|
||||||
|
- Fix loading encoding with year appended
|
||||||
|
- Fix deprecation warnings on Node.js 10+
|
||||||
|
* deps: qs@6.5.2
|
||||||
|
* deps: raw-body@2.3.3
|
||||||
|
- deps: http-errors@1.6.3
|
||||||
|
- deps: iconv-lite@0.4.23
|
||||||
|
* deps: type-is@~1.6.16
|
||||||
|
- deps: mime-types@~2.1.18
|
||||||
|
|
||||||
|
1.18.2 / 2017-09-22
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: debug@2.6.9
|
||||||
|
* perf: remove argument reassignment
|
||||||
|
|
||||||
|
1.18.1 / 2017-09-12
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: content-type@~1.0.4
|
||||||
|
- perf: remove argument reassignment
|
||||||
|
- perf: skip parameter parsing when no parameters
|
||||||
|
* deps: iconv-lite@0.4.19
|
||||||
|
- Fix ISO-8859-1 regression
|
||||||
|
- Update Windows-1255
|
||||||
|
* deps: qs@6.5.1
|
||||||
|
- Fix parsing & compacting very deep objects
|
||||||
|
* deps: raw-body@2.3.2
|
||||||
|
- deps: iconv-lite@0.4.19
|
||||||
|
|
||||||
|
1.18.0 / 2017-09-08
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Fix JSON strict violation error to match native parse error
|
||||||
|
* Include the `body` property on verify errors
|
||||||
|
* Include the `type` property on all generated errors
|
||||||
|
* Use `http-errors` to set status code on errors
|
||||||
|
* deps: bytes@3.0.0
|
||||||
|
* deps: debug@2.6.8
|
||||||
|
* deps: depd@~1.1.1
|
||||||
|
- Remove unnecessary `Buffer` loading
|
||||||
|
* deps: http-errors@~1.6.2
|
||||||
|
- deps: depd@1.1.1
|
||||||
|
* deps: iconv-lite@0.4.18
|
||||||
|
- Add support for React Native
|
||||||
|
- Add a warning if not loaded as utf-8
|
||||||
|
- Fix CESU-8 decoding in Node.js 8
|
||||||
|
- Improve speed of ISO-8859-1 encoding
|
||||||
|
* deps: qs@6.5.0
|
||||||
|
* deps: raw-body@2.3.1
|
||||||
|
- Use `http-errors` for standard emitted errors
|
||||||
|
- deps: bytes@3.0.0
|
||||||
|
- deps: iconv-lite@0.4.18
|
||||||
|
- perf: skip buffer decoding on overage chunk
|
||||||
|
* perf: prevent internal `throw` when missing charset
|
||||||
|
|
||||||
|
1.17.2 / 2017-05-17
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: debug@2.6.7
|
||||||
|
- Fix `DEBUG_MAX_ARRAY_LENGTH`
|
||||||
|
- deps: ms@2.0.0
|
||||||
|
* deps: type-is@~1.6.15
|
||||||
|
- deps: mime-types@~2.1.15
|
||||||
|
|
||||||
|
1.17.1 / 2017-03-06
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: qs@6.4.0
|
||||||
|
- Fix regression parsing keys starting with `[`
|
||||||
|
|
||||||
|
1.17.0 / 2017-03-01
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: http-errors@~1.6.1
|
||||||
|
- Make `message` property enumerable for `HttpError`s
|
||||||
|
- deps: setprototypeof@1.0.3
|
||||||
|
* deps: qs@6.3.1
|
||||||
|
- Fix compacting nested arrays
|
||||||
|
|
||||||
|
1.16.1 / 2017-02-10
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: debug@2.6.1
|
||||||
|
- Fix deprecation messages in WebStorm and other editors
|
||||||
|
- Undeprecate `DEBUG_FD` set to `1` or `2`
|
||||||
|
|
||||||
|
1.16.0 / 2017-01-17
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: debug@2.6.0
|
||||||
|
- Allow colors in workers
|
||||||
|
- Deprecated `DEBUG_FD` environment variable
|
||||||
|
- Fix error when running under React Native
|
||||||
|
- Use same color for same namespace
|
||||||
|
- deps: ms@0.7.2
|
||||||
|
* deps: http-errors@~1.5.1
|
||||||
|
- deps: inherits@2.0.3
|
||||||
|
- deps: setprototypeof@1.0.2
|
||||||
|
- deps: statuses@'>= 1.3.1 < 2'
|
||||||
|
* deps: iconv-lite@0.4.15
|
||||||
|
- Added encoding MS-31J
|
||||||
|
- Added encoding MS-932
|
||||||
|
- Added encoding MS-936
|
||||||
|
- Added encoding MS-949
|
||||||
|
- Added encoding MS-950
|
||||||
|
- Fix GBK/GB18030 handling of Euro character
|
||||||
|
* deps: qs@6.2.1
|
||||||
|
- Fix array parsing from skipping empty values
|
||||||
|
* deps: raw-body@~2.2.0
|
||||||
|
- deps: iconv-lite@0.4.15
|
||||||
|
* deps: type-is@~1.6.14
|
||||||
|
- deps: mime-types@~2.1.13
|
||||||
|
|
||||||
|
1.15.2 / 2016-06-19
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: bytes@2.4.0
|
||||||
|
* deps: content-type@~1.0.2
|
||||||
|
- perf: enable strict mode
|
||||||
|
* deps: http-errors@~1.5.0
|
||||||
|
- Use `setprototypeof` module to replace `__proto__` setting
|
||||||
|
- deps: statuses@'>= 1.3.0 < 2'
|
||||||
|
- perf: enable strict mode
|
||||||
|
* deps: qs@6.2.0
|
||||||
|
* deps: raw-body@~2.1.7
|
||||||
|
- deps: bytes@2.4.0
|
||||||
|
- perf: remove double-cleanup on happy path
|
||||||
|
* deps: type-is@~1.6.13
|
||||||
|
- deps: mime-types@~2.1.11
|
||||||
|
|
||||||
|
1.15.1 / 2016-05-05
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: bytes@2.3.0
|
||||||
|
- Drop partial bytes on all parsed units
|
||||||
|
- Fix parsing byte string that looks like hex
|
||||||
|
* deps: raw-body@~2.1.6
|
||||||
|
- deps: bytes@2.3.0
|
||||||
|
* deps: type-is@~1.6.12
|
||||||
|
- deps: mime-types@~2.1.10
|
||||||
|
|
||||||
|
1.15.0 / 2016-02-10
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: http-errors@~1.4.0
|
||||||
|
- Add `HttpError` export, for `err instanceof createError.HttpError`
|
||||||
|
- deps: inherits@2.0.1
|
||||||
|
- deps: statuses@'>= 1.2.1 < 2'
|
||||||
|
* deps: qs@6.1.0
|
||||||
|
* deps: type-is@~1.6.11
|
||||||
|
- deps: mime-types@~2.1.9
|
||||||
|
|
||||||
|
1.14.2 / 2015-12-16
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: bytes@2.2.0
|
||||||
|
* deps: iconv-lite@0.4.13
|
||||||
|
* deps: qs@5.2.0
|
||||||
|
* deps: raw-body@~2.1.5
|
||||||
|
- deps: bytes@2.2.0
|
||||||
|
- deps: iconv-lite@0.4.13
|
||||||
|
* deps: type-is@~1.6.10
|
||||||
|
- deps: mime-types@~2.1.8
|
||||||
|
|
||||||
|
1.14.1 / 2015-09-27
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Fix issue where invalid charset results in 400 when `verify` used
|
||||||
|
* deps: iconv-lite@0.4.12
|
||||||
|
- Fix CESU-8 decoding in Node.js 4.x
|
||||||
|
* deps: raw-body@~2.1.4
|
||||||
|
- Fix masking critical errors from `iconv-lite`
|
||||||
|
- deps: iconv-lite@0.4.12
|
||||||
|
* deps: type-is@~1.6.9
|
||||||
|
- deps: mime-types@~2.1.7
|
||||||
|
|
||||||
|
1.14.0 / 2015-09-16
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Fix JSON strict parse error to match syntax errors
|
||||||
|
* Provide static `require` analysis in `urlencoded` parser
|
||||||
|
* deps: depd@~1.1.0
|
||||||
|
- Support web browser loading
|
||||||
|
* deps: qs@5.1.0
|
||||||
|
* deps: raw-body@~2.1.3
|
||||||
|
- Fix sync callback when attaching data listener causes sync read
|
||||||
|
* deps: type-is@~1.6.8
|
||||||
|
- Fix type error when given invalid type to match against
|
||||||
|
- deps: mime-types@~2.1.6
|
||||||
|
|
||||||
|
1.13.3 / 2015-07-31
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: type-is@~1.6.6
|
||||||
|
- deps: mime-types@~2.1.4
|
||||||
|
|
||||||
|
1.13.2 / 2015-07-05
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: iconv-lite@0.4.11
|
||||||
|
* deps: qs@4.0.0
|
||||||
|
- Fix dropping parameters like `hasOwnProperty`
|
||||||
|
- Fix user-visible incompatibilities from 3.1.0
|
||||||
|
- Fix various parsing edge cases
|
||||||
|
* deps: raw-body@~2.1.2
|
||||||
|
- Fix error stack traces to skip `makeError`
|
||||||
|
- deps: iconv-lite@0.4.11
|
||||||
|
* deps: type-is@~1.6.4
|
||||||
|
- deps: mime-types@~2.1.2
|
||||||
|
- perf: enable strict mode
|
||||||
|
- perf: remove argument reassignment
|
||||||
|
|
||||||
|
1.13.1 / 2015-06-16
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: qs@2.4.2
|
||||||
|
- Downgraded from 3.1.0 because of user-visible incompatibilities
|
||||||
|
|
||||||
|
1.13.0 / 2015-06-14
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Add `statusCode` property on `Error`s, in addition to `status`
|
||||||
|
* Change `type` default to `application/json` for JSON parser
|
||||||
|
* Change `type` default to `application/x-www-form-urlencoded` for urlencoded parser
|
||||||
|
* Provide static `require` analysis
|
||||||
|
* Use the `http-errors` module to generate errors
|
||||||
|
* deps: bytes@2.1.0
|
||||||
|
- Slight optimizations
|
||||||
|
* deps: iconv-lite@0.4.10
|
||||||
|
- The encoding UTF-16 without BOM now defaults to UTF-16LE when detection fails
|
||||||
|
- Leading BOM is now removed when decoding
|
||||||
|
* deps: on-finished@~2.3.0
|
||||||
|
- Add defined behavior for HTTP `CONNECT` requests
|
||||||
|
- Add defined behavior for HTTP `Upgrade` requests
|
||||||
|
- deps: ee-first@1.1.1
|
||||||
|
* deps: qs@3.1.0
|
||||||
|
- Fix dropping parameters like `hasOwnProperty`
|
||||||
|
- Fix various parsing edge cases
|
||||||
|
- Parsed object now has `null` prototype
|
||||||
|
* deps: raw-body@~2.1.1
|
||||||
|
- Use `unpipe` module for unpiping requests
|
||||||
|
- deps: iconv-lite@0.4.10
|
||||||
|
* deps: type-is@~1.6.3
|
||||||
|
- deps: mime-types@~2.1.1
|
||||||
|
- perf: reduce try block size
|
||||||
|
- perf: remove bitwise operations
|
||||||
|
* perf: enable strict mode
|
||||||
|
* perf: remove argument reassignment
|
||||||
|
* perf: remove delete call
|
||||||
|
|
||||||
|
1.12.4 / 2015-05-10
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: debug@~2.2.0
|
||||||
|
* deps: qs@2.4.2
|
||||||
|
- Fix allowing parameters like `constructor`
|
||||||
|
* deps: on-finished@~2.2.1
|
||||||
|
* deps: raw-body@~2.0.1
|
||||||
|
- Fix a false-positive when unpiping in Node.js 0.8
|
||||||
|
- deps: bytes@2.0.1
|
||||||
|
* deps: type-is@~1.6.2
|
||||||
|
- deps: mime-types@~2.0.11
|
||||||
|
|
||||||
|
1.12.3 / 2015-04-15
|
||||||
|
===================
|
||||||
|
|
||||||
|
* Slight efficiency improvement when not debugging
|
||||||
|
* deps: depd@~1.0.1
|
||||||
|
* deps: iconv-lite@0.4.8
|
||||||
|
- Add encoding alias UNICODE-1-1-UTF-7
|
||||||
|
* deps: raw-body@1.3.4
|
||||||
|
- Fix hanging callback if request aborts during read
|
||||||
|
- deps: iconv-lite@0.4.8
|
||||||
|
|
||||||
|
1.12.2 / 2015-03-16
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: qs@2.4.1
|
||||||
|
- Fix error when parameter `hasOwnProperty` is present
|
||||||
|
|
||||||
|
1.12.1 / 2015-03-15
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: debug@~2.1.3
|
||||||
|
- Fix high intensity foreground color for bold
|
||||||
|
- deps: ms@0.7.0
|
||||||
|
* deps: type-is@~1.6.1
|
||||||
|
- deps: mime-types@~2.0.10
|
||||||
|
|
||||||
|
1.12.0 / 2015-02-13
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add `debug` messages
|
||||||
|
* accept a function for the `type` option
|
||||||
|
* use `content-type` to parse `Content-Type` headers
|
||||||
|
* deps: iconv-lite@0.4.7
|
||||||
|
- Gracefully support enumerables on `Object.prototype`
|
||||||
|
* deps: raw-body@1.3.3
|
||||||
|
- deps: iconv-lite@0.4.7
|
||||||
|
* deps: type-is@~1.6.0
|
||||||
|
- fix argument reassignment
|
||||||
|
- fix false-positives in `hasBody` `Transfer-Encoding` check
|
||||||
|
- support wildcard for both type and subtype (`*/*`)
|
||||||
|
- deps: mime-types@~2.0.9
|
||||||
|
|
||||||
|
1.11.0 / 2015-01-30
|
||||||
|
===================
|
||||||
|
|
||||||
|
* make internal `extended: true` depth limit infinity
|
||||||
|
* deps: type-is@~1.5.6
|
||||||
|
- deps: mime-types@~2.0.8
|
||||||
|
|
||||||
|
1.10.2 / 2015-01-20
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: iconv-lite@0.4.6
|
||||||
|
- Fix rare aliases of single-byte encodings
|
||||||
|
* deps: raw-body@1.3.2
|
||||||
|
- deps: iconv-lite@0.4.6
|
||||||
|
|
||||||
|
1.10.1 / 2015-01-01
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: on-finished@~2.2.0
|
||||||
|
* deps: type-is@~1.5.5
|
||||||
|
- deps: mime-types@~2.0.7
|
||||||
|
|
||||||
|
1.10.0 / 2014-12-02
|
||||||
|
===================
|
||||||
|
|
||||||
|
* make internal `extended: true` array limit dynamic
|
||||||
|
|
||||||
|
1.9.3 / 2014-11-21
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: iconv-lite@0.4.5
|
||||||
|
- Fix Windows-31J and X-SJIS encoding support
|
||||||
|
* deps: qs@2.3.3
|
||||||
|
- Fix `arrayLimit` behavior
|
||||||
|
* deps: raw-body@1.3.1
|
||||||
|
- deps: iconv-lite@0.4.5
|
||||||
|
* deps: type-is@~1.5.3
|
||||||
|
- deps: mime-types@~2.0.3
|
||||||
|
|
||||||
|
1.9.2 / 2014-10-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@2.3.2
|
||||||
|
- Fix parsing of mixed objects and values
|
||||||
|
|
||||||
|
1.9.1 / 2014-10-22
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: on-finished@~2.1.1
|
||||||
|
- Fix handling of pipelined requests
|
||||||
|
* deps: qs@2.3.0
|
||||||
|
- Fix parsing of mixed implicit and explicit arrays
|
||||||
|
* deps: type-is@~1.5.2
|
||||||
|
- deps: mime-types@~2.0.2
|
||||||
|
|
||||||
|
1.9.0 / 2014-09-24
|
||||||
|
==================
|
||||||
|
|
||||||
|
* include the charset in "unsupported charset" error message
|
||||||
|
* include the encoding in "unsupported content encoding" error message
|
||||||
|
* deps: depd@~1.0.0
|
||||||
|
|
||||||
|
1.8.4 / 2014-09-23
|
||||||
|
==================
|
||||||
|
|
||||||
|
* fix content encoding to be case-insensitive
|
||||||
|
|
||||||
|
1.8.3 / 2014-09-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@2.2.4
|
||||||
|
- Fix issue with object keys starting with numbers truncated
|
||||||
|
|
||||||
|
1.8.2 / 2014-09-15
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: depd@0.4.5
|
||||||
|
|
||||||
|
1.8.1 / 2014-09-07
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: media-typer@0.3.0
|
||||||
|
* deps: type-is@~1.5.1
|
||||||
|
|
||||||
|
1.8.0 / 2014-09-05
|
||||||
|
==================
|
||||||
|
|
||||||
|
* make empty-body-handling consistent between chunked requests
|
||||||
|
- empty `json` produces `{}`
|
||||||
|
- empty `raw` produces `new Buffer(0)`
|
||||||
|
- empty `text` produces `''`
|
||||||
|
- empty `urlencoded` produces `{}`
|
||||||
|
* deps: qs@2.2.3
|
||||||
|
- Fix issue where first empty value in array is discarded
|
||||||
|
* deps: type-is@~1.5.0
|
||||||
|
- fix `hasbody` to be true for `content-length: 0`
|
||||||
|
|
||||||
|
1.7.0 / 2014-09-01
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add `parameterLimit` option to `urlencoded` parser
|
||||||
|
* change `urlencoded` extended array limit to 100
|
||||||
|
* respond with 413 when over `parameterLimit` in `urlencoded`
|
||||||
|
|
||||||
|
1.6.7 / 2014-08-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@2.2.2
|
||||||
|
- Remove unnecessary cloning
|
||||||
|
|
||||||
|
1.6.6 / 2014-08-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@2.2.0
|
||||||
|
- Array parsing fix
|
||||||
|
- Performance improvements
|
||||||
|
|
||||||
|
1.6.5 / 2014-08-16
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: on-finished@2.1.0
|
||||||
|
|
||||||
|
1.6.4 / 2014-08-14
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@1.2.2
|
||||||
|
|
||||||
|
1.6.3 / 2014-08-10
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@1.2.1
|
||||||
|
|
||||||
|
1.6.2 / 2014-08-07
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@1.2.0
|
||||||
|
- Fix parsing array of objects
|
||||||
|
|
||||||
|
1.6.1 / 2014-08-06
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@1.1.0
|
||||||
|
- Accept urlencoded square brackets
|
||||||
|
- Accept empty values in implicit array notation
|
||||||
|
|
||||||
|
1.6.0 / 2014-08-05
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: qs@1.0.2
|
||||||
|
- Complete rewrite
|
||||||
|
- Limits array length to 20
|
||||||
|
- Limits object depth to 5
|
||||||
|
- Limits parameters to 1,000
|
||||||
|
|
||||||
|
1.5.2 / 2014-07-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: depd@0.4.4
|
||||||
|
- Work-around v8 generating empty stack traces
|
||||||
|
|
||||||
|
1.5.1 / 2014-07-26
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: depd@0.4.3
|
||||||
|
- Fix exception when global `Error.stackTraceLimit` is too low
|
||||||
|
|
||||||
|
1.5.0 / 2014-07-20
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: depd@0.4.2
|
||||||
|
- Add `TRACE_DEPRECATION` environment variable
|
||||||
|
- Remove non-standard grey color from color output
|
||||||
|
- Support `--no-deprecation` argument
|
||||||
|
- Support `--trace-deprecation` argument
|
||||||
|
* deps: iconv-lite@0.4.4
|
||||||
|
- Added encoding UTF-7
|
||||||
|
* deps: raw-body@1.3.0
|
||||||
|
- deps: iconv-lite@0.4.4
|
||||||
|
- Added encoding UTF-7
|
||||||
|
- Fix `Cannot switch to old mode now` error on Node.js 0.10+
|
||||||
|
* deps: type-is@~1.3.2
|
||||||
|
|
||||||
|
1.4.3 / 2014-06-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: type-is@1.3.1
|
||||||
|
- fix global variable leak
|
||||||
|
|
||||||
|
1.4.2 / 2014-06-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: type-is@1.3.0
|
||||||
|
- improve type parsing
|
||||||
|
|
||||||
|
1.4.1 / 2014-06-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* fix urlencoded extended deprecation message
|
||||||
|
|
||||||
|
1.4.0 / 2014-06-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add `text` parser
|
||||||
|
* add `raw` parser
|
||||||
|
* check accepted charset in content-type (accepts utf-8)
|
||||||
|
* check accepted encoding in content-encoding (accepts identity)
|
||||||
|
* deprecate `bodyParser()` middleware; use `.json()` and `.urlencoded()` as needed
|
||||||
|
* deprecate `urlencoded()` without provided `extended` option
|
||||||
|
* lazy-load urlencoded parsers
|
||||||
|
* parsers split into files for reduced mem usage
|
||||||
|
* support gzip and deflate bodies
|
||||||
|
- set `inflate: false` to turn off
|
||||||
|
* deps: raw-body@1.2.2
|
||||||
|
- Support all encodings from `iconv-lite`
|
||||||
|
|
||||||
|
1.3.1 / 2014-06-11
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: type-is@1.2.1
|
||||||
|
- Switch dependency from mime to mime-types@1.0.0
|
||||||
|
|
||||||
|
1.3.0 / 2014-05-31
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add `extended` option to urlencoded parser
|
||||||
|
|
||||||
|
1.2.2 / 2014-05-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: raw-body@1.1.6
|
||||||
|
- assert stream encoding on node.js 0.8
|
||||||
|
- assert stream encoding on node.js < 0.10.6
|
||||||
|
- deps: bytes@1
|
||||||
|
|
||||||
|
1.2.1 / 2014-05-26
|
||||||
|
==================
|
||||||
|
|
||||||
|
* invoke `next(err)` after request fully read
|
||||||
|
- prevents hung responses and socket hang ups
|
||||||
|
|
||||||
|
1.2.0 / 2014-05-11
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add `verify` option
|
||||||
|
* deps: type-is@1.2.0
|
||||||
|
- support suffix matching
|
||||||
|
|
||||||
|
1.1.2 / 2014-05-11
|
||||||
|
==================
|
||||||
|
|
||||||
|
* improve json parser speed
|
||||||
|
|
||||||
|
1.1.1 / 2014-05-11
|
||||||
|
==================
|
||||||
|
|
||||||
|
* fix repeated limit parsing with every request
|
||||||
|
|
||||||
|
1.1.0 / 2014-05-10
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add `type` option
|
||||||
|
* deps: pin for safety and consistency
|
||||||
|
|
||||||
|
1.0.2 / 2014-04-14
|
||||||
|
==================
|
||||||
|
|
||||||
|
* use `type-is` module
|
||||||
|
|
||||||
|
1.0.1 / 2014-03-20
|
||||||
|
==================
|
||||||
|
|
||||||
|
* lower default limits to 100kb
|
||||||
23
server/node_modules/body-parser/LICENSE
generated
vendored
Normal file
23
server/node_modules/body-parser/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
|
||||||
|
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
476
server/node_modules/body-parser/README.md
generated
vendored
Normal file
476
server/node_modules/body-parser/README.md
generated
vendored
Normal file
@@ -0,0 +1,476 @@
|
|||||||
|
# body-parser
|
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url]
|
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||||
|
[![Build Status][ci-image]][ci-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer]
|
||||||
|
|
||||||
|
Node.js body parsing middleware.
|
||||||
|
|
||||||
|
Parse incoming request bodies in a middleware before your handlers, available
|
||||||
|
under the `req.body` property.
|
||||||
|
|
||||||
|
**Note** As `req.body`'s shape is based on user-controlled input, all
|
||||||
|
properties and values in this object are untrusted and should be validated
|
||||||
|
before trusting. For example, `req.body.foo.toString()` may fail in multiple
|
||||||
|
ways, for example the `foo` property may not be there or may not be a string,
|
||||||
|
and `toString` may not be a function and instead a string or other user input.
|
||||||
|
|
||||||
|
[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/).
|
||||||
|
|
||||||
|
_This does not handle multipart bodies_, due to their complex and typically
|
||||||
|
large nature. For multipart bodies, you may be interested in the following
|
||||||
|
modules:
|
||||||
|
|
||||||
|
* [busboy](https://www.npmjs.org/package/busboy#readme) and
|
||||||
|
[connect-busboy](https://www.npmjs.org/package/connect-busboy#readme)
|
||||||
|
* [multiparty](https://www.npmjs.org/package/multiparty#readme) and
|
||||||
|
[connect-multiparty](https://www.npmjs.org/package/connect-multiparty#readme)
|
||||||
|
* [formidable](https://www.npmjs.org/package/formidable#readme)
|
||||||
|
* [multer](https://www.npmjs.org/package/multer#readme)
|
||||||
|
|
||||||
|
This module provides the following parsers:
|
||||||
|
|
||||||
|
* [JSON body parser](#bodyparserjsonoptions)
|
||||||
|
* [Raw body parser](#bodyparserrawoptions)
|
||||||
|
* [Text body parser](#bodyparsertextoptions)
|
||||||
|
* [URL-encoded form body parser](#bodyparserurlencodedoptions)
|
||||||
|
|
||||||
|
Other body parsers you might be interested in:
|
||||||
|
|
||||||
|
- [body](https://www.npmjs.org/package/body#readme)
|
||||||
|
- [co-body](https://www.npmjs.org/package/co-body#readme)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install body-parser
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```js
|
||||||
|
var bodyParser = require('body-parser')
|
||||||
|
```
|
||||||
|
|
||||||
|
The `bodyParser` object exposes various factories to create middlewares. All
|
||||||
|
middlewares will populate the `req.body` property with the parsed body when
|
||||||
|
the `Content-Type` request header matches the `type` option, or an empty
|
||||||
|
object (`{}`) if there was no body to parse, the `Content-Type` was not matched,
|
||||||
|
or an error occurred.
|
||||||
|
|
||||||
|
The various errors returned by this module are described in the
|
||||||
|
[errors section](#errors).
|
||||||
|
|
||||||
|
### bodyParser.json([options])
|
||||||
|
|
||||||
|
Returns middleware that only parses `json` and only looks at requests where
|
||||||
|
the `Content-Type` header matches the `type` option. This parser accepts any
|
||||||
|
Unicode encoding of the body and supports automatic inflation of `gzip` and
|
||||||
|
`deflate` encodings.
|
||||||
|
|
||||||
|
A new `body` object containing the parsed data is populated on the `request`
|
||||||
|
object after the middleware (i.e. `req.body`).
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
The `json` function takes an optional `options` object that may contain any of
|
||||||
|
the following keys:
|
||||||
|
|
||||||
|
##### inflate
|
||||||
|
|
||||||
|
When set to `true`, then deflated (compressed) bodies will be inflated; when
|
||||||
|
`false`, deflated bodies are rejected. Defaults to `true`.
|
||||||
|
|
||||||
|
##### limit
|
||||||
|
|
||||||
|
Controls the maximum request body size. If this is a number, then the value
|
||||||
|
specifies the number of bytes; if it is a string, the value is passed to the
|
||||||
|
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
|
||||||
|
to `'100kb'`.
|
||||||
|
|
||||||
|
##### reviver
|
||||||
|
|
||||||
|
The `reviver` option is passed directly to `JSON.parse` as the second
|
||||||
|
argument. You can find more information on this argument
|
||||||
|
[in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter).
|
||||||
|
|
||||||
|
##### strict
|
||||||
|
|
||||||
|
When set to `true`, will only accept arrays and objects; when `false` will
|
||||||
|
accept anything `JSON.parse` accepts. Defaults to `true`.
|
||||||
|
|
||||||
|
##### type
|
||||||
|
|
||||||
|
The `type` option is used to determine what media type the middleware will
|
||||||
|
parse. This option can be a string, array of strings, or a function. If not a
|
||||||
|
function, `type` option is passed directly to the
|
||||||
|
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
|
||||||
|
be an extension name (like `json`), a mime type (like `application/json`), or
|
||||||
|
a mime type with a wildcard (like `*/*` or `*/json`). If a function, the `type`
|
||||||
|
option is called as `fn(req)` and the request is parsed if it returns a truthy
|
||||||
|
value. Defaults to `application/json`.
|
||||||
|
|
||||||
|
##### verify
|
||||||
|
|
||||||
|
The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`,
|
||||||
|
where `buf` is a `Buffer` of the raw request body and `encoding` is the
|
||||||
|
encoding of the request. The parsing can be aborted by throwing an error.
|
||||||
|
|
||||||
|
### bodyParser.raw([options])
|
||||||
|
|
||||||
|
Returns middleware that parses all bodies as a `Buffer` and only looks at
|
||||||
|
requests where the `Content-Type` header matches the `type` option. This
|
||||||
|
parser supports automatic inflation of `gzip` and `deflate` encodings.
|
||||||
|
|
||||||
|
A new `body` object containing the parsed data is populated on the `request`
|
||||||
|
object after the middleware (i.e. `req.body`). This will be a `Buffer` object
|
||||||
|
of the body.
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
The `raw` function takes an optional `options` object that may contain any of
|
||||||
|
the following keys:
|
||||||
|
|
||||||
|
##### inflate
|
||||||
|
|
||||||
|
When set to `true`, then deflated (compressed) bodies will be inflated; when
|
||||||
|
`false`, deflated bodies are rejected. Defaults to `true`.
|
||||||
|
|
||||||
|
##### limit
|
||||||
|
|
||||||
|
Controls the maximum request body size. If this is a number, then the value
|
||||||
|
specifies the number of bytes; if it is a string, the value is passed to the
|
||||||
|
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
|
||||||
|
to `'100kb'`.
|
||||||
|
|
||||||
|
##### type
|
||||||
|
|
||||||
|
The `type` option is used to determine what media type the middleware will
|
||||||
|
parse. This option can be a string, array of strings, or a function.
|
||||||
|
If not a function, `type` option is passed directly to the
|
||||||
|
[type-is](https://www.npmjs.org/package/type-is#readme) library and this
|
||||||
|
can be an extension name (like `bin`), a mime type (like
|
||||||
|
`application/octet-stream`), or a mime type with a wildcard (like `*/*` or
|
||||||
|
`application/*`). If a function, the `type` option is called as `fn(req)`
|
||||||
|
and the request is parsed if it returns a truthy value. Defaults to
|
||||||
|
`application/octet-stream`.
|
||||||
|
|
||||||
|
##### verify
|
||||||
|
|
||||||
|
The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`,
|
||||||
|
where `buf` is a `Buffer` of the raw request body and `encoding` is the
|
||||||
|
encoding of the request. The parsing can be aborted by throwing an error.
|
||||||
|
|
||||||
|
### bodyParser.text([options])
|
||||||
|
|
||||||
|
Returns middleware that parses all bodies as a string and only looks at
|
||||||
|
requests where the `Content-Type` header matches the `type` option. This
|
||||||
|
parser supports automatic inflation of `gzip` and `deflate` encodings.
|
||||||
|
|
||||||
|
A new `body` string containing the parsed data is populated on the `request`
|
||||||
|
object after the middleware (i.e. `req.body`). This will be a string of the
|
||||||
|
body.
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
The `text` function takes an optional `options` object that may contain any of
|
||||||
|
the following keys:
|
||||||
|
|
||||||
|
##### defaultCharset
|
||||||
|
|
||||||
|
Specify the default character set for the text content if the charset is not
|
||||||
|
specified in the `Content-Type` header of the request. Defaults to `utf-8`.
|
||||||
|
|
||||||
|
##### inflate
|
||||||
|
|
||||||
|
When set to `true`, then deflated (compressed) bodies will be inflated; when
|
||||||
|
`false`, deflated bodies are rejected. Defaults to `true`.
|
||||||
|
|
||||||
|
##### limit
|
||||||
|
|
||||||
|
Controls the maximum request body size. If this is a number, then the value
|
||||||
|
specifies the number of bytes; if it is a string, the value is passed to the
|
||||||
|
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
|
||||||
|
to `'100kb'`.
|
||||||
|
|
||||||
|
##### type
|
||||||
|
|
||||||
|
The `type` option is used to determine what media type the middleware will
|
||||||
|
parse. This option can be a string, array of strings, or a function. If not
|
||||||
|
a function, `type` option is passed directly to the
|
||||||
|
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
|
||||||
|
be an extension name (like `txt`), a mime type (like `text/plain`), or a mime
|
||||||
|
type with a wildcard (like `*/*` or `text/*`). If a function, the `type`
|
||||||
|
option is called as `fn(req)` and the request is parsed if it returns a
|
||||||
|
truthy value. Defaults to `text/plain`.
|
||||||
|
|
||||||
|
##### verify
|
||||||
|
|
||||||
|
The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`,
|
||||||
|
where `buf` is a `Buffer` of the raw request body and `encoding` is the
|
||||||
|
encoding of the request. The parsing can be aborted by throwing an error.
|
||||||
|
|
||||||
|
### bodyParser.urlencoded([options])
|
||||||
|
|
||||||
|
Returns middleware that only parses `urlencoded` bodies and only looks at
|
||||||
|
requests where the `Content-Type` header matches the `type` option. This
|
||||||
|
parser accepts only UTF-8 encoding of the body and supports automatic
|
||||||
|
inflation of `gzip` and `deflate` encodings.
|
||||||
|
|
||||||
|
A new `body` object containing the parsed data is populated on the `request`
|
||||||
|
object after the middleware (i.e. `req.body`). This object will contain
|
||||||
|
key-value pairs, where the value can be a string or array (when `extended` is
|
||||||
|
`false`), or any type (when `extended` is `true`).
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
The `urlencoded` function takes an optional `options` object that may contain
|
||||||
|
any of the following keys:
|
||||||
|
|
||||||
|
##### extended
|
||||||
|
|
||||||
|
The `extended` option allows to choose between parsing the URL-encoded data
|
||||||
|
with the `querystring` library (when `false`) or the `qs` library (when
|
||||||
|
`true`). The "extended" syntax allows for rich objects and arrays to be
|
||||||
|
encoded into the URL-encoded format, allowing for a JSON-like experience
|
||||||
|
with URL-encoded. For more information, please
|
||||||
|
[see the qs library](https://www.npmjs.org/package/qs#readme).
|
||||||
|
|
||||||
|
Defaults to `true`, but using the default has been deprecated. Please
|
||||||
|
research into the difference between `qs` and `querystring` and choose the
|
||||||
|
appropriate setting.
|
||||||
|
|
||||||
|
##### inflate
|
||||||
|
|
||||||
|
When set to `true`, then deflated (compressed) bodies will be inflated; when
|
||||||
|
`false`, deflated bodies are rejected. Defaults to `true`.
|
||||||
|
|
||||||
|
##### limit
|
||||||
|
|
||||||
|
Controls the maximum request body size. If this is a number, then the value
|
||||||
|
specifies the number of bytes; if it is a string, the value is passed to the
|
||||||
|
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
|
||||||
|
to `'100kb'`.
|
||||||
|
|
||||||
|
##### parameterLimit
|
||||||
|
|
||||||
|
The `parameterLimit` option controls the maximum number of parameters that
|
||||||
|
are allowed in the URL-encoded data. If a request contains more parameters
|
||||||
|
than this value, a 413 will be returned to the client. Defaults to `1000`.
|
||||||
|
|
||||||
|
##### type
|
||||||
|
|
||||||
|
The `type` option is used to determine what media type the middleware will
|
||||||
|
parse. This option can be a string, array of strings, or a function. If not
|
||||||
|
a function, `type` option is passed directly to the
|
||||||
|
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
|
||||||
|
be an extension name (like `urlencoded`), a mime type (like
|
||||||
|
`application/x-www-form-urlencoded`), or a mime type with a wildcard (like
|
||||||
|
`*/x-www-form-urlencoded`). If a function, the `type` option is called as
|
||||||
|
`fn(req)` and the request is parsed if it returns a truthy value. Defaults
|
||||||
|
to `application/x-www-form-urlencoded`.
|
||||||
|
|
||||||
|
##### verify
|
||||||
|
|
||||||
|
The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`,
|
||||||
|
where `buf` is a `Buffer` of the raw request body and `encoding` is the
|
||||||
|
encoding of the request. The parsing can be aborted by throwing an error.
|
||||||
|
|
||||||
|
#### depth
|
||||||
|
|
||||||
|
The `depth` option is used to configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. Defaults to `32`. It is recommended to keep this value as low as possible.
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
The middlewares provided by this module create errors using the
|
||||||
|
[`http-errors` module](https://www.npmjs.com/package/http-errors). The errors
|
||||||
|
will typically have a `status`/`statusCode` property that contains the suggested
|
||||||
|
HTTP response code, an `expose` property to determine if the `message` property
|
||||||
|
should be displayed to the client, a `type` property to determine the type of
|
||||||
|
error without matching against the `message`, and a `body` property containing
|
||||||
|
the read body, if available.
|
||||||
|
|
||||||
|
The following are the common errors created, though any error can come through
|
||||||
|
for various reasons.
|
||||||
|
|
||||||
|
### content encoding unsupported
|
||||||
|
|
||||||
|
This error will occur when the request had a `Content-Encoding` header that
|
||||||
|
contained an encoding but the "inflation" option was set to `false`. The
|
||||||
|
`status` property is set to `415`, the `type` property is set to
|
||||||
|
`'encoding.unsupported'`, and the `charset` property will be set to the
|
||||||
|
encoding that is unsupported.
|
||||||
|
|
||||||
|
### entity parse failed
|
||||||
|
|
||||||
|
This error will occur when the request contained an entity that could not be
|
||||||
|
parsed by the middleware. The `status` property is set to `400`, the `type`
|
||||||
|
property is set to `'entity.parse.failed'`, and the `body` property is set to
|
||||||
|
the entity value that failed parsing.
|
||||||
|
|
||||||
|
### entity verify failed
|
||||||
|
|
||||||
|
This error will occur when the request contained an entity that could not be
|
||||||
|
failed verification by the defined `verify` option. The `status` property is
|
||||||
|
set to `403`, the `type` property is set to `'entity.verify.failed'`, and the
|
||||||
|
`body` property is set to the entity value that failed verification.
|
||||||
|
|
||||||
|
### request aborted
|
||||||
|
|
||||||
|
This error will occur when the request is aborted by the client before reading
|
||||||
|
the body has finished. The `received` property will be set to the number of
|
||||||
|
bytes received before the request was aborted and the `expected` property is
|
||||||
|
set to the number of expected bytes. The `status` property is set to `400`
|
||||||
|
and `type` property is set to `'request.aborted'`.
|
||||||
|
|
||||||
|
### request entity too large
|
||||||
|
|
||||||
|
This error will occur when the request body's size is larger than the "limit"
|
||||||
|
option. The `limit` property will be set to the byte limit and the `length`
|
||||||
|
property will be set to the request body's length. The `status` property is
|
||||||
|
set to `413` and the `type` property is set to `'entity.too.large'`.
|
||||||
|
|
||||||
|
### request size did not match content length
|
||||||
|
|
||||||
|
This error will occur when the request's length did not match the length from
|
||||||
|
the `Content-Length` header. This typically occurs when the request is malformed,
|
||||||
|
typically when the `Content-Length` header was calculated based on characters
|
||||||
|
instead of bytes. The `status` property is set to `400` and the `type` property
|
||||||
|
is set to `'request.size.invalid'`.
|
||||||
|
|
||||||
|
### stream encoding should not be set
|
||||||
|
|
||||||
|
This error will occur when something called the `req.setEncoding` method prior
|
||||||
|
to this middleware. This module operates directly on bytes only and you cannot
|
||||||
|
call `req.setEncoding` when using this module. The `status` property is set to
|
||||||
|
`500` and the `type` property is set to `'stream.encoding.set'`.
|
||||||
|
|
||||||
|
### stream is not readable
|
||||||
|
|
||||||
|
This error will occur when the request is no longer readable when this middleware
|
||||||
|
attempts to read it. This typically means something other than a middleware from
|
||||||
|
this module read the request body already and the middleware was also configured to
|
||||||
|
read the same request. The `status` property is set to `500` and the `type`
|
||||||
|
property is set to `'stream.not.readable'`.
|
||||||
|
|
||||||
|
### too many parameters
|
||||||
|
|
||||||
|
This error will occur when the content of the request exceeds the configured
|
||||||
|
`parameterLimit` for the `urlencoded` parser. The `status` property is set to
|
||||||
|
`413` and the `type` property is set to `'parameters.too.many'`.
|
||||||
|
|
||||||
|
### unsupported charset "BOGUS"
|
||||||
|
|
||||||
|
This error will occur when the request had a charset parameter in the
|
||||||
|
`Content-Type` header, but the `iconv-lite` module does not support it OR the
|
||||||
|
parser does not support it. The charset is contained in the message as well
|
||||||
|
as in the `charset` property. The `status` property is set to `415`, the
|
||||||
|
`type` property is set to `'charset.unsupported'`, and the `charset` property
|
||||||
|
is set to the charset that is unsupported.
|
||||||
|
|
||||||
|
### unsupported content encoding "bogus"
|
||||||
|
|
||||||
|
This error will occur when the request had a `Content-Encoding` header that
|
||||||
|
contained an unsupported encoding. The encoding is contained in the message
|
||||||
|
as well as in the `encoding` property. The `status` property is set to `415`,
|
||||||
|
the `type` property is set to `'encoding.unsupported'`, and the `encoding`
|
||||||
|
property is set to the encoding that is unsupported.
|
||||||
|
|
||||||
|
### The input exceeded the depth
|
||||||
|
|
||||||
|
This error occurs when using `bodyParser.urlencoded` with the `extended` property set to `true` and the input exceeds the configured `depth` option. The `status` property is set to `400`. It is recommended to review the `depth` option and evaluate if it requires a higher value. When the `depth` option is set to `32` (default value), the error will not be thrown.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Express/Connect top-level generic
|
||||||
|
|
||||||
|
This example demonstrates adding a generic JSON and URL-encoded parser as a
|
||||||
|
top-level middleware, which will parse the bodies of all incoming requests.
|
||||||
|
This is the simplest setup.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var express = require('express')
|
||||||
|
var bodyParser = require('body-parser')
|
||||||
|
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
// parse application/x-www-form-urlencoded
|
||||||
|
app.use(bodyParser.urlencoded({ extended: false }))
|
||||||
|
|
||||||
|
// parse application/json
|
||||||
|
app.use(bodyParser.json())
|
||||||
|
|
||||||
|
app.use(function (req, res) {
|
||||||
|
res.setHeader('Content-Type', 'text/plain')
|
||||||
|
res.write('you posted:\n')
|
||||||
|
res.end(JSON.stringify(req.body, null, 2))
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Express route-specific
|
||||||
|
|
||||||
|
This example demonstrates adding body parsers specifically to the routes that
|
||||||
|
need them. In general, this is the most recommended way to use body-parser with
|
||||||
|
Express.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var express = require('express')
|
||||||
|
var bodyParser = require('body-parser')
|
||||||
|
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
// create application/json parser
|
||||||
|
var jsonParser = bodyParser.json()
|
||||||
|
|
||||||
|
// create application/x-www-form-urlencoded parser
|
||||||
|
var urlencodedParser = bodyParser.urlencoded({ extended: false })
|
||||||
|
|
||||||
|
// POST /login gets urlencoded bodies
|
||||||
|
app.post('/login', urlencodedParser, function (req, res) {
|
||||||
|
res.send('welcome, ' + req.body.username)
|
||||||
|
})
|
||||||
|
|
||||||
|
// POST /api/users gets JSON bodies
|
||||||
|
app.post('/api/users', jsonParser, function (req, res) {
|
||||||
|
// create user in req.body
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Change accepted type for parsers
|
||||||
|
|
||||||
|
All the parsers accept a `type` option which allows you to change the
|
||||||
|
`Content-Type` that the middleware will parse.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var express = require('express')
|
||||||
|
var bodyParser = require('body-parser')
|
||||||
|
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
// parse various different custom JSON types as JSON
|
||||||
|
app.use(bodyParser.json({ type: 'application/*+json' }))
|
||||||
|
|
||||||
|
// parse some custom thing into a Buffer
|
||||||
|
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
|
||||||
|
|
||||||
|
// parse an HTML body into a string
|
||||||
|
app.use(bodyParser.text({ type: 'text/html' }))
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
[ci-image]: https://badgen.net/github/checks/expressjs/body-parser/master?label=ci
|
||||||
|
[ci-url]: https://github.com/expressjs/body-parser/actions/workflows/ci.yml
|
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/body-parser/master
|
||||||
|
[coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master
|
||||||
|
[node-version-image]: https://badgen.net/npm/node/body-parser
|
||||||
|
[node-version-url]: https://nodejs.org/en/download
|
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/body-parser
|
||||||
|
[npm-url]: https://npmjs.org/package/body-parser
|
||||||
|
[npm-version-image]: https://badgen.net/npm/v/body-parser
|
||||||
|
[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/body-parser/badge
|
||||||
|
[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/body-parser
|
||||||
156
server/node_modules/body-parser/index.js
generated
vendored
Normal file
156
server/node_modules/body-parser/index.js
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var deprecate = require('depd')('body-parser')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache of loaded parsers.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var parsers = Object.create(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Parsers
|
||||||
|
* @type {function}
|
||||||
|
* @property {function} json
|
||||||
|
* @property {function} raw
|
||||||
|
* @property {function} text
|
||||||
|
* @property {function} urlencoded
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @type {Parsers}
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports = module.exports = deprecate.function(bodyParser,
|
||||||
|
'bodyParser: use individual json/urlencoded middlewares')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON parser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Object.defineProperty(exports, 'json', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: createParserGetter('json')
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw parser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Object.defineProperty(exports, 'raw', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: createParserGetter('raw')
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text parser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Object.defineProperty(exports, 'text', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: createParserGetter('text')
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL-encoded parser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Object.defineProperty(exports, 'urlencoded', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: createParserGetter('urlencoded')
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse json and urlencoded bodies.
|
||||||
|
*
|
||||||
|
* @param {object} [options]
|
||||||
|
* @return {function}
|
||||||
|
* @deprecated
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function bodyParser (options) {
|
||||||
|
// use default type for parsers
|
||||||
|
var opts = Object.create(options || null, {
|
||||||
|
type: {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
value: undefined,
|
||||||
|
writable: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var _urlencoded = exports.urlencoded(opts)
|
||||||
|
var _json = exports.json(opts)
|
||||||
|
|
||||||
|
return function bodyParser (req, res, next) {
|
||||||
|
_json(req, res, function (err) {
|
||||||
|
if (err) return next(err)
|
||||||
|
_urlencoded(req, res, next)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a getter for loading a parser.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function createParserGetter (name) {
|
||||||
|
return function get () {
|
||||||
|
return loadParser(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a parser module.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function loadParser (parserName) {
|
||||||
|
var parser = parsers[parserName]
|
||||||
|
|
||||||
|
if (parser !== undefined) {
|
||||||
|
return parser
|
||||||
|
}
|
||||||
|
|
||||||
|
// this uses a switch for static require analysis
|
||||||
|
switch (parserName) {
|
||||||
|
case 'json':
|
||||||
|
parser = require('./lib/types/json')
|
||||||
|
break
|
||||||
|
case 'raw':
|
||||||
|
parser = require('./lib/types/raw')
|
||||||
|
break
|
||||||
|
case 'text':
|
||||||
|
parser = require('./lib/types/text')
|
||||||
|
break
|
||||||
|
case 'urlencoded':
|
||||||
|
parser = require('./lib/types/urlencoded')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// store to prevent invoking require()
|
||||||
|
return (parsers[parserName] = parser)
|
||||||
|
}
|
||||||
205
server/node_modules/body-parser/lib/read.js
generated
vendored
Normal file
205
server/node_modules/body-parser/lib/read.js
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var createError = require('http-errors')
|
||||||
|
var destroy = require('destroy')
|
||||||
|
var getBody = require('raw-body')
|
||||||
|
var iconv = require('iconv-lite')
|
||||||
|
var onFinished = require('on-finished')
|
||||||
|
var unpipe = require('unpipe')
|
||||||
|
var zlib = require('zlib')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = read
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a request into a buffer and parse.
|
||||||
|
*
|
||||||
|
* @param {object} req
|
||||||
|
* @param {object} res
|
||||||
|
* @param {function} next
|
||||||
|
* @param {function} parse
|
||||||
|
* @param {function} debug
|
||||||
|
* @param {object} options
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function read (req, res, next, parse, debug, options) {
|
||||||
|
var length
|
||||||
|
var opts = options
|
||||||
|
var stream
|
||||||
|
|
||||||
|
// flag as parsed
|
||||||
|
req._body = true
|
||||||
|
|
||||||
|
// read options
|
||||||
|
var encoding = opts.encoding !== null
|
||||||
|
? opts.encoding
|
||||||
|
: null
|
||||||
|
var verify = opts.verify
|
||||||
|
|
||||||
|
try {
|
||||||
|
// get the content stream
|
||||||
|
stream = contentstream(req, debug, opts.inflate)
|
||||||
|
length = stream.length
|
||||||
|
stream.length = undefined
|
||||||
|
} catch (err) {
|
||||||
|
return next(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set raw-body options
|
||||||
|
opts.length = length
|
||||||
|
opts.encoding = verify
|
||||||
|
? null
|
||||||
|
: encoding
|
||||||
|
|
||||||
|
// assert charset is supported
|
||||||
|
if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) {
|
||||||
|
return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
|
||||||
|
charset: encoding.toLowerCase(),
|
||||||
|
type: 'charset.unsupported'
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// read body
|
||||||
|
debug('read body')
|
||||||
|
getBody(stream, opts, function (error, body) {
|
||||||
|
if (error) {
|
||||||
|
var _error
|
||||||
|
|
||||||
|
if (error.type === 'encoding.unsupported') {
|
||||||
|
// echo back charset
|
||||||
|
_error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
|
||||||
|
charset: encoding.toLowerCase(),
|
||||||
|
type: 'charset.unsupported'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// set status code on error
|
||||||
|
_error = createError(400, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unpipe from stream and destroy
|
||||||
|
if (stream !== req) {
|
||||||
|
unpipe(req)
|
||||||
|
destroy(stream, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read off entire request
|
||||||
|
dump(req, function onfinished () {
|
||||||
|
next(createError(400, _error))
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify
|
||||||
|
if (verify) {
|
||||||
|
try {
|
||||||
|
debug('verify body')
|
||||||
|
verify(req, res, body, encoding)
|
||||||
|
} catch (err) {
|
||||||
|
next(createError(403, err, {
|
||||||
|
body: body,
|
||||||
|
type: err.type || 'entity.verify.failed'
|
||||||
|
}))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse
|
||||||
|
var str = body
|
||||||
|
try {
|
||||||
|
debug('parse body')
|
||||||
|
str = typeof body !== 'string' && encoding !== null
|
||||||
|
? iconv.decode(body, encoding)
|
||||||
|
: body
|
||||||
|
req.body = parse(str)
|
||||||
|
} catch (err) {
|
||||||
|
next(createError(400, err, {
|
||||||
|
body: str,
|
||||||
|
type: err.type || 'entity.parse.failed'
|
||||||
|
}))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the content stream of the request.
|
||||||
|
*
|
||||||
|
* @param {object} req
|
||||||
|
* @param {function} debug
|
||||||
|
* @param {boolean} [inflate=true]
|
||||||
|
* @return {object}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function contentstream (req, debug, inflate) {
|
||||||
|
var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()
|
||||||
|
var length = req.headers['content-length']
|
||||||
|
var stream
|
||||||
|
|
||||||
|
debug('content-encoding "%s"', encoding)
|
||||||
|
|
||||||
|
if (inflate === false && encoding !== 'identity') {
|
||||||
|
throw createError(415, 'content encoding unsupported', {
|
||||||
|
encoding: encoding,
|
||||||
|
type: 'encoding.unsupported'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (encoding) {
|
||||||
|
case 'deflate':
|
||||||
|
stream = zlib.createInflate()
|
||||||
|
debug('inflate body')
|
||||||
|
req.pipe(stream)
|
||||||
|
break
|
||||||
|
case 'gzip':
|
||||||
|
stream = zlib.createGunzip()
|
||||||
|
debug('gunzip body')
|
||||||
|
req.pipe(stream)
|
||||||
|
break
|
||||||
|
case 'identity':
|
||||||
|
stream = req
|
||||||
|
stream.length = length
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw createError(415, 'unsupported content encoding "' + encoding + '"', {
|
||||||
|
encoding: encoding,
|
||||||
|
type: 'encoding.unsupported'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump the contents of a request.
|
||||||
|
*
|
||||||
|
* @param {object} req
|
||||||
|
* @param {function} callback
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function dump (req, callback) {
|
||||||
|
if (onFinished.isFinished(req)) {
|
||||||
|
callback(null)
|
||||||
|
} else {
|
||||||
|
onFinished(req, callback)
|
||||||
|
req.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
247
server/node_modules/body-parser/lib/types/json.js
generated
vendored
Normal file
247
server/node_modules/body-parser/lib/types/json.js
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014 Jonathan Ong
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bytes = require('bytes')
|
||||||
|
var contentType = require('content-type')
|
||||||
|
var createError = require('http-errors')
|
||||||
|
var debug = require('debug')('body-parser:json')
|
||||||
|
var read = require('../read')
|
||||||
|
var typeis = require('type-is')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = json
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match the first non-space in a string.
|
||||||
|
*
|
||||||
|
* Allowed whitespace is defined in RFC 7159:
|
||||||
|
*
|
||||||
|
* ws = *(
|
||||||
|
* %x20 / ; Space
|
||||||
|
* %x09 / ; Horizontal tab
|
||||||
|
* %x0A / ; Line feed or New line
|
||||||
|
* %x0D ) ; Carriage return
|
||||||
|
*/
|
||||||
|
|
||||||
|
var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/ // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
var JSON_SYNTAX_CHAR = '#'
|
||||||
|
var JSON_SYNTAX_REGEXP = /#+/g
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse JSON bodies.
|
||||||
|
*
|
||||||
|
* @param {object} [options]
|
||||||
|
* @return {function}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function json (options) {
|
||||||
|
var opts = options || {}
|
||||||
|
|
||||||
|
var limit = typeof opts.limit !== 'number'
|
||||||
|
? bytes.parse(opts.limit || '100kb')
|
||||||
|
: opts.limit
|
||||||
|
var inflate = opts.inflate !== false
|
||||||
|
var reviver = opts.reviver
|
||||||
|
var strict = opts.strict !== false
|
||||||
|
var type = opts.type || 'application/json'
|
||||||
|
var verify = opts.verify || false
|
||||||
|
|
||||||
|
if (verify !== false && typeof verify !== 'function') {
|
||||||
|
throw new TypeError('option verify must be function')
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the appropriate type checking function
|
||||||
|
var shouldParse = typeof type !== 'function'
|
||||||
|
? typeChecker(type)
|
||||||
|
: type
|
||||||
|
|
||||||
|
function parse (body) {
|
||||||
|
if (body.length === 0) {
|
||||||
|
// special-case empty json body, as it's a common client-side mistake
|
||||||
|
// TODO: maybe make this configurable or part of "strict" option
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strict) {
|
||||||
|
var first = firstchar(body)
|
||||||
|
|
||||||
|
if (first !== '{' && first !== '[') {
|
||||||
|
debug('strict violation')
|
||||||
|
throw createStrictSyntaxError(body, first)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
debug('parse json')
|
||||||
|
return JSON.parse(body, reviver)
|
||||||
|
} catch (e) {
|
||||||
|
throw normalizeJsonSyntaxError(e, {
|
||||||
|
message: e.message,
|
||||||
|
stack: e.stack
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return function jsonParser (req, res, next) {
|
||||||
|
if (req._body) {
|
||||||
|
debug('body already parsed')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.body = req.body || {}
|
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!typeis.hasBody(req)) {
|
||||||
|
debug('skip empty body')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type'])
|
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!shouldParse(req)) {
|
||||||
|
debug('skip parsing')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert charset per RFC 7159 sec 8.1
|
||||||
|
var charset = getCharset(req) || 'utf-8'
|
||||||
|
if (charset.slice(0, 4) !== 'utf-') {
|
||||||
|
debug('invalid charset')
|
||||||
|
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
|
||||||
|
charset: charset,
|
||||||
|
type: 'charset.unsupported'
|
||||||
|
}))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// read
|
||||||
|
read(req, res, next, parse, debug, {
|
||||||
|
encoding: charset,
|
||||||
|
inflate: inflate,
|
||||||
|
limit: limit,
|
||||||
|
verify: verify
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create strict violation syntax error matching native error.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @param {string} char
|
||||||
|
* @return {Error}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function createStrictSyntaxError (str, char) {
|
||||||
|
var index = str.indexOf(char)
|
||||||
|
var partial = ''
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
partial = str.substring(0, index) + JSON_SYNTAX_CHAR
|
||||||
|
|
||||||
|
for (var i = index + 1; i < str.length; i++) {
|
||||||
|
partial += JSON_SYNTAX_CHAR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation')
|
||||||
|
} catch (e) {
|
||||||
|
return normalizeJsonSyntaxError(e, {
|
||||||
|
message: e.message.replace(JSON_SYNTAX_REGEXP, function (placeholder) {
|
||||||
|
return str.substring(index, index + placeholder.length)
|
||||||
|
}),
|
||||||
|
stack: e.stack
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the first non-whitespace character in a string.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @return {function}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function firstchar (str) {
|
||||||
|
var match = FIRST_CHAR_REGEXP.exec(str)
|
||||||
|
|
||||||
|
return match
|
||||||
|
? match[1]
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the charset of a request.
|
||||||
|
*
|
||||||
|
* @param {object} req
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getCharset (req) {
|
||||||
|
try {
|
||||||
|
return (contentType.parse(req).parameters.charset || '').toLowerCase()
|
||||||
|
} catch (e) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a SyntaxError for JSON.parse.
|
||||||
|
*
|
||||||
|
* @param {SyntaxError} error
|
||||||
|
* @param {object} obj
|
||||||
|
* @return {SyntaxError}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function normalizeJsonSyntaxError (error, obj) {
|
||||||
|
var keys = Object.getOwnPropertyNames(error)
|
||||||
|
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
var key = keys[i]
|
||||||
|
if (key !== 'stack' && key !== 'message') {
|
||||||
|
delete error[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace stack before message for Node.js 0.10 and below
|
||||||
|
error.stack = obj.stack.replace(error.message, obj.message)
|
||||||
|
error.message = obj.message
|
||||||
|
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the simple type checker.
|
||||||
|
*
|
||||||
|
* @param {string} type
|
||||||
|
* @return {function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function typeChecker (type) {
|
||||||
|
return function checkType (req) {
|
||||||
|
return Boolean(typeis(req, type))
|
||||||
|
}
|
||||||
|
}
|
||||||
101
server/node_modules/body-parser/lib/types/raw.js
generated
vendored
Normal file
101
server/node_modules/body-parser/lib/types/raw.js
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bytes = require('bytes')
|
||||||
|
var debug = require('debug')('body-parser:raw')
|
||||||
|
var read = require('../read')
|
||||||
|
var typeis = require('type-is')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = raw
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse raw bodies.
|
||||||
|
*
|
||||||
|
* @param {object} [options]
|
||||||
|
* @return {function}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function raw (options) {
|
||||||
|
var opts = options || {}
|
||||||
|
|
||||||
|
var inflate = opts.inflate !== false
|
||||||
|
var limit = typeof opts.limit !== 'number'
|
||||||
|
? bytes.parse(opts.limit || '100kb')
|
||||||
|
: opts.limit
|
||||||
|
var type = opts.type || 'application/octet-stream'
|
||||||
|
var verify = opts.verify || false
|
||||||
|
|
||||||
|
if (verify !== false && typeof verify !== 'function') {
|
||||||
|
throw new TypeError('option verify must be function')
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the appropriate type checking function
|
||||||
|
var shouldParse = typeof type !== 'function'
|
||||||
|
? typeChecker(type)
|
||||||
|
: type
|
||||||
|
|
||||||
|
function parse (buf) {
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
return function rawParser (req, res, next) {
|
||||||
|
if (req._body) {
|
||||||
|
debug('body already parsed')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.body = req.body || {}
|
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!typeis.hasBody(req)) {
|
||||||
|
debug('skip empty body')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type'])
|
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!shouldParse(req)) {
|
||||||
|
debug('skip parsing')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// read
|
||||||
|
read(req, res, next, parse, debug, {
|
||||||
|
encoding: null,
|
||||||
|
inflate: inflate,
|
||||||
|
limit: limit,
|
||||||
|
verify: verify
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the simple type checker.
|
||||||
|
*
|
||||||
|
* @param {string} type
|
||||||
|
* @return {function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function typeChecker (type) {
|
||||||
|
return function checkType (req) {
|
||||||
|
return Boolean(typeis(req, type))
|
||||||
|
}
|
||||||
|
}
|
||||||
121
server/node_modules/body-parser/lib/types/text.js
generated
vendored
Normal file
121
server/node_modules/body-parser/lib/types/text.js
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bytes = require('bytes')
|
||||||
|
var contentType = require('content-type')
|
||||||
|
var debug = require('debug')('body-parser:text')
|
||||||
|
var read = require('../read')
|
||||||
|
var typeis = require('type-is')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = text
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse text bodies.
|
||||||
|
*
|
||||||
|
* @param {object} [options]
|
||||||
|
* @return {function}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function text (options) {
|
||||||
|
var opts = options || {}
|
||||||
|
|
||||||
|
var defaultCharset = opts.defaultCharset || 'utf-8'
|
||||||
|
var inflate = opts.inflate !== false
|
||||||
|
var limit = typeof opts.limit !== 'number'
|
||||||
|
? bytes.parse(opts.limit || '100kb')
|
||||||
|
: opts.limit
|
||||||
|
var type = opts.type || 'text/plain'
|
||||||
|
var verify = opts.verify || false
|
||||||
|
|
||||||
|
if (verify !== false && typeof verify !== 'function') {
|
||||||
|
throw new TypeError('option verify must be function')
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the appropriate type checking function
|
||||||
|
var shouldParse = typeof type !== 'function'
|
||||||
|
? typeChecker(type)
|
||||||
|
: type
|
||||||
|
|
||||||
|
function parse (buf) {
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
return function textParser (req, res, next) {
|
||||||
|
if (req._body) {
|
||||||
|
debug('body already parsed')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.body = req.body || {}
|
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!typeis.hasBody(req)) {
|
||||||
|
debug('skip empty body')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type'])
|
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!shouldParse(req)) {
|
||||||
|
debug('skip parsing')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// get charset
|
||||||
|
var charset = getCharset(req) || defaultCharset
|
||||||
|
|
||||||
|
// read
|
||||||
|
read(req, res, next, parse, debug, {
|
||||||
|
encoding: charset,
|
||||||
|
inflate: inflate,
|
||||||
|
limit: limit,
|
||||||
|
verify: verify
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the charset of a request.
|
||||||
|
*
|
||||||
|
* @param {object} req
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getCharset (req) {
|
||||||
|
try {
|
||||||
|
return (contentType.parse(req).parameters.charset || '').toLowerCase()
|
||||||
|
} catch (e) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the simple type checker.
|
||||||
|
*
|
||||||
|
* @param {string} type
|
||||||
|
* @return {function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function typeChecker (type) {
|
||||||
|
return function checkType (req) {
|
||||||
|
return Boolean(typeis(req, type))
|
||||||
|
}
|
||||||
|
}
|
||||||
300
server/node_modules/body-parser/lib/types/urlencoded.js
generated
vendored
Normal file
300
server/node_modules/body-parser/lib/types/urlencoded.js
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014 Jonathan Ong
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bytes = require('bytes')
|
||||||
|
var contentType = require('content-type')
|
||||||
|
var createError = require('http-errors')
|
||||||
|
var debug = require('debug')('body-parser:urlencoded')
|
||||||
|
var deprecate = require('depd')('body-parser')
|
||||||
|
var read = require('../read')
|
||||||
|
var typeis = require('type-is')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = urlencoded
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache of parser modules.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var parsers = Object.create(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse urlencoded bodies.
|
||||||
|
*
|
||||||
|
* @param {object} [options]
|
||||||
|
* @return {function}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function urlencoded (options) {
|
||||||
|
var opts = options || {}
|
||||||
|
|
||||||
|
// notice because option default will flip in next major
|
||||||
|
if (opts.extended === undefined) {
|
||||||
|
deprecate('undefined extended: provide extended option')
|
||||||
|
}
|
||||||
|
|
||||||
|
var extended = opts.extended !== false
|
||||||
|
var inflate = opts.inflate !== false
|
||||||
|
var limit = typeof opts.limit !== 'number'
|
||||||
|
? bytes.parse(opts.limit || '100kb')
|
||||||
|
: opts.limit
|
||||||
|
var type = opts.type || 'application/x-www-form-urlencoded'
|
||||||
|
var verify = opts.verify || false
|
||||||
|
|
||||||
|
if (verify !== false && typeof verify !== 'function') {
|
||||||
|
throw new TypeError('option verify must be function')
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the appropriate query parser
|
||||||
|
var queryparse = extended
|
||||||
|
? extendedparser(opts)
|
||||||
|
: simpleparser(opts)
|
||||||
|
|
||||||
|
// create the appropriate type checking function
|
||||||
|
var shouldParse = typeof type !== 'function'
|
||||||
|
? typeChecker(type)
|
||||||
|
: type
|
||||||
|
|
||||||
|
function parse (body) {
|
||||||
|
return body.length
|
||||||
|
? queryparse(body)
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return function urlencodedParser (req, res, next) {
|
||||||
|
if (req._body) {
|
||||||
|
debug('body already parsed')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.body = req.body || {}
|
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!typeis.hasBody(req)) {
|
||||||
|
debug('skip empty body')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type'])
|
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!shouldParse(req)) {
|
||||||
|
debug('skip parsing')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert charset
|
||||||
|
var charset = getCharset(req) || 'utf-8'
|
||||||
|
if (charset !== 'utf-8') {
|
||||||
|
debug('invalid charset')
|
||||||
|
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
|
||||||
|
charset: charset,
|
||||||
|
type: 'charset.unsupported'
|
||||||
|
}))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// read
|
||||||
|
read(req, res, next, parse, debug, {
|
||||||
|
debug: debug,
|
||||||
|
encoding: charset,
|
||||||
|
inflate: inflate,
|
||||||
|
limit: limit,
|
||||||
|
verify: verify
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the extended query parser.
|
||||||
|
*
|
||||||
|
* @param {object} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
function extendedparser (options) {
|
||||||
|
var parameterLimit = options.parameterLimit !== undefined
|
||||||
|
? options.parameterLimit
|
||||||
|
: 1000
|
||||||
|
var depth = options.depth !== undefined ? options.depth : 32
|
||||||
|
var parse = parser('qs')
|
||||||
|
|
||||||
|
if (isNaN(parameterLimit) || parameterLimit < 1) {
|
||||||
|
throw new TypeError('option parameterLimit must be a positive number')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(depth) || depth < 0) {
|
||||||
|
throw new TypeError('option depth must be a zero or a positive number')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFinite(parameterLimit)) {
|
||||||
|
parameterLimit = parameterLimit | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return function queryparse (body) {
|
||||||
|
var paramCount = parameterCount(body, parameterLimit)
|
||||||
|
|
||||||
|
if (paramCount === undefined) {
|
||||||
|
debug('too many parameters')
|
||||||
|
throw createError(413, 'too many parameters', {
|
||||||
|
type: 'parameters.too.many'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrayLimit = Math.max(100, paramCount)
|
||||||
|
|
||||||
|
debug('parse extended urlencoding')
|
||||||
|
try {
|
||||||
|
return parse(body, {
|
||||||
|
allowPrototypes: true,
|
||||||
|
arrayLimit: arrayLimit,
|
||||||
|
depth: depth,
|
||||||
|
strictDepth: true,
|
||||||
|
parameterLimit: parameterLimit
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof RangeError) {
|
||||||
|
throw createError(400, 'The input exceeded the depth', {
|
||||||
|
type: 'querystring.parse.rangeError'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the charset of a request.
|
||||||
|
*
|
||||||
|
* @param {object} req
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getCharset (req) {
|
||||||
|
try {
|
||||||
|
return (contentType.parse(req).parameters.charset || '').toLowerCase()
|
||||||
|
} catch (e) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of parameters, stopping once limit reached
|
||||||
|
*
|
||||||
|
* @param {string} body
|
||||||
|
* @param {number} limit
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function parameterCount (body, limit) {
|
||||||
|
var count = 0
|
||||||
|
var index = 0
|
||||||
|
|
||||||
|
while ((index = body.indexOf('&', index)) !== -1) {
|
||||||
|
count++
|
||||||
|
index++
|
||||||
|
|
||||||
|
if (count === limit) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get parser for module name dynamically.
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @return {function}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function parser (name) {
|
||||||
|
var mod = parsers[name]
|
||||||
|
|
||||||
|
if (mod !== undefined) {
|
||||||
|
return mod.parse
|
||||||
|
}
|
||||||
|
|
||||||
|
// this uses a switch for static require analysis
|
||||||
|
switch (name) {
|
||||||
|
case 'qs':
|
||||||
|
mod = require('qs')
|
||||||
|
break
|
||||||
|
case 'querystring':
|
||||||
|
mod = require('querystring')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// store to prevent invoking require()
|
||||||
|
parsers[name] = mod
|
||||||
|
|
||||||
|
return mod.parse
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the simple query parser.
|
||||||
|
*
|
||||||
|
* @param {object} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
function simpleparser (options) {
|
||||||
|
var parameterLimit = options.parameterLimit !== undefined
|
||||||
|
? options.parameterLimit
|
||||||
|
: 1000
|
||||||
|
var parse = parser('querystring')
|
||||||
|
|
||||||
|
if (isNaN(parameterLimit) || parameterLimit < 1) {
|
||||||
|
throw new TypeError('option parameterLimit must be a positive number')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFinite(parameterLimit)) {
|
||||||
|
parameterLimit = parameterLimit | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return function queryparse (body) {
|
||||||
|
var paramCount = parameterCount(body, parameterLimit)
|
||||||
|
|
||||||
|
if (paramCount === undefined) {
|
||||||
|
debug('too many parameters')
|
||||||
|
throw createError(413, 'too many parameters', {
|
||||||
|
type: 'parameters.too.many'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
debug('parse urlencoding')
|
||||||
|
return parse(body, undefined, undefined, { maxKeys: parameterLimit })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the simple type checker.
|
||||||
|
*
|
||||||
|
* @param {string} type
|
||||||
|
* @return {function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function typeChecker (type) {
|
||||||
|
return function checkType (req) {
|
||||||
|
return Boolean(typeis(req, type))
|
||||||
|
}
|
||||||
|
}
|
||||||
55
server/node_modules/body-parser/package.json
generated
vendored
Normal file
55
server/node_modules/body-parser/package.json
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"name": "body-parser",
|
||||||
|
"description": "Node.js body parsing middleware",
|
||||||
|
"version": "1.20.4",
|
||||||
|
"contributors": [
|
||||||
|
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||||
|
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "expressjs/body-parser",
|
||||||
|
"dependencies": {
|
||||||
|
"bytes": "~3.1.2",
|
||||||
|
"content-type": "~1.0.5",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"destroy": "~1.2.0",
|
||||||
|
"http-errors": "~2.0.1",
|
||||||
|
"iconv-lite": "~0.4.24",
|
||||||
|
"on-finished": "~2.4.1",
|
||||||
|
"qs": "~6.14.0",
|
||||||
|
"raw-body": "~2.5.3",
|
||||||
|
"type-is": "~1.6.18",
|
||||||
|
"unpipe": "~1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "8.34.0",
|
||||||
|
"eslint-config-standard": "14.1.1",
|
||||||
|
"eslint-plugin-import": "2.27.5",
|
||||||
|
"eslint-plugin-markdown": "3.0.0",
|
||||||
|
"eslint-plugin-node": "11.1.0",
|
||||||
|
"eslint-plugin-promise": "6.1.1",
|
||||||
|
"eslint-plugin-standard": "4.1.0",
|
||||||
|
"methods": "1.1.2",
|
||||||
|
"mocha": "10.2.0",
|
||||||
|
"nyc": "15.1.0",
|
||||||
|
"safe-buffer": "5.2.1",
|
||||||
|
"supertest": "6.3.3"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib/",
|
||||||
|
"LICENSE",
|
||||||
|
"HISTORY.md",
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8",
|
||||||
|
"npm": "1.2.8000 || >= 1.4.16"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/",
|
||||||
|
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
||||||
|
}
|
||||||
|
}
|
||||||
5
server/node_modules/buildcheck/.eslintrc.js
generated
vendored
Normal file
5
server/node_modules/buildcheck/.eslintrc.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
extends: '@mscdex/eslint-config',
|
||||||
|
};
|
||||||
88
server/node_modules/buildcheck/.github/workflows/ci.yml
generated
vendored
Normal file
88
server/node_modules/buildcheck/.github/workflows/ci.yml
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests-linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x, 22.x, 24.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- name: Check Node.js version
|
||||||
|
run: node -pe process.versions
|
||||||
|
- name: Install module
|
||||||
|
run: npm install
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
|
tests-macos-intel:
|
||||||
|
runs-on: macos-15-intel
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x, 22.x, 24.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- name: Check Node.js version
|
||||||
|
run: node -pe process.versions
|
||||||
|
- name: Install module
|
||||||
|
run: npm install
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
|
tests-macos-arm:
|
||||||
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node-version: [16.x, 18.x, 20.x, 22.x, 24.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- name: Check Node.js version
|
||||||
|
run: node -pe process.versions
|
||||||
|
- name: Install module
|
||||||
|
run: npm install
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
|
tests-windows-2022:
|
||||||
|
runs-on: windows-2022
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node-version: [24.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- name: Check Node.js version
|
||||||
|
run: node -pe process.versions
|
||||||
|
- name: Install module
|
||||||
|
run: npm install
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
27
server/node_modules/buildcheck/.github/workflows/lint.yml
generated
vendored
Normal file
27
server/node_modules/buildcheck/.github/workflows/lint.yml
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 22.x
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-js:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Use Node.js ${{ env.NODE_VERSION }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
- name: Check Node.js version
|
||||||
|
run: node -pe process.versions
|
||||||
|
- name: Install ESLint + ESLint configs/plugins
|
||||||
|
run: npm install --only=dev
|
||||||
|
- name: Lint files
|
||||||
|
run: npm run lint
|
||||||
3
server/node_modules/buildcheck/.npmignore
generated
vendored
Normal file
3
server/node_modules/buildcheck/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.eslintcache
|
||||||
|
**/node_modules/**
|
||||||
|
/package-lock.json
|
||||||
19
server/node_modules/buildcheck/LICENSE
generated
vendored
Normal file
19
server/node_modules/buildcheck/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright Brian White. All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to
|
||||||
|
deal in the Software without restriction, including without limitation the
|
||||||
|
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
IN THE SOFTWARE.
|
||||||
106
server/node_modules/buildcheck/README.md
generated
vendored
Normal file
106
server/node_modules/buildcheck/README.md
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# Description
|
||||||
|
|
||||||
|
Build environment checking for [node.js](http://nodejs.org/).
|
||||||
|
|
||||||
|
This allows for autoconf-like functionality for node addons/build scripts.
|
||||||
|
|
||||||
|
**Note:** Obsolete and/or exotic build environments or platforms not supported
|
||||||
|
by node.js are not supported.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* [node.js](http://nodejs.org/) -- v10.0.0 or newer
|
||||||
|
* Supported compilers:
|
||||||
|
* gcc
|
||||||
|
* clang
|
||||||
|
* MSVC 2013+ and Windows SDK 8.1+
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
npm install buildcheck
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Check if a C function exists
|
||||||
|
|
||||||
|
```js
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const BuildEnvironment = require('buildcheck');
|
||||||
|
|
||||||
|
const buildEnv = new BuildEnvironment();
|
||||||
|
|
||||||
|
console.log(buildEnv.checkFunction('c', 'preadv2'));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check if a C header is usable
|
||||||
|
|
||||||
|
```js
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const BuildEnvironment = require('buildcheck');
|
||||||
|
|
||||||
|
const buildEnv = new BuildEnvironment();
|
||||||
|
|
||||||
|
console.log(buildEnv.checkHeader('c', 'linux/io_uring.h'));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Try to compile some C code
|
||||||
|
|
||||||
|
```js
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const BuildEnvironment = require('buildcheck');
|
||||||
|
|
||||||
|
const buildEnv = new BuildEnvironment();
|
||||||
|
|
||||||
|
// Should be a successful compile
|
||||||
|
console.log(buildEnv.tryCompile('c', 'int main() { return 0; }'));
|
||||||
|
|
||||||
|
// Should be a failed compile
|
||||||
|
console.log(buildEnv.tryCompile('c', 'int main() { return z; }'));
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Exports
|
||||||
|
|
||||||
|
The exported value is `BuildEnvironment`, the main class for dealing with a build environment.
|
||||||
|
|
||||||
|
### BuildEnvironment
|
||||||
|
|
||||||
|
#### Methods
|
||||||
|
|
||||||
|
* **(constructor)**([< _object_ >config]) - Creates and returns a new BuildEnvironment instance. `config` may contain:
|
||||||
|
|
||||||
|
* **compilerC** - _string_ - C compiler command to use. *Note: this is ignored on Windows.* **Default:** `process.env.CC` or `'cc'`
|
||||||
|
|
||||||
|
* **compilerCXX** - _string_ - C++ compiler command to use. *Note: this is ignored on Windows.* **Default:** `process.env.CXX` or `'c++'`
|
||||||
|
|
||||||
|
* **msvs_version** - _mixed_ - A string or number containing the year of the Visual Studio compiler to use. *Note: this is for Windows only.* **Default:** newest version installed
|
||||||
|
|
||||||
|
* **checkDeclared**(< _string_ >lang, < _string_ >symbolName[, < _object_ >options]) - _boolean_ - Checks if a symbol `symbolName` is declared where `lang` is either `'c'` or `'c++'`. Returns `true` if symbol exists, `false` otherwise. `options` may contain:
|
||||||
|
|
||||||
|
* **headers** - _array_ - A list of headers to try when checking if the symbol is declared. `checkFunction()` will always first try without a library. If not supplied, a default list of common (platform-specific) headers will be used.
|
||||||
|
|
||||||
|
* **searchLibs** - _array_ - A list of library names (without the `'-l'` prefix) to try when checking if the symbol is declared. `checkDeclared()` will always first try without a library.
|
||||||
|
|
||||||
|
* **checkFunction**(< _string_ >lang, < _string_ >functionName[, < _object_ >options]) - _boolean_ - Checks if a function `functionName` exists and is linkable where `lang` is either `'c'` or `'c++'`. Returns `true` if function exists, `false` otherwise. `options` may contain:
|
||||||
|
|
||||||
|
* **searchLibs** - _array_ - A list of library names (without the `'-l'` prefix) to try when checking for this function. `checkFunction()` will always first try without a library.
|
||||||
|
|
||||||
|
* **checkFeature**(< _string_ >featureName) - _mixed_ - Executes a special test for a "feature" and returns the result. Supported values for `featureName`:
|
||||||
|
|
||||||
|
* `'strerror_r'` - Returns an object containing:
|
||||||
|
|
||||||
|
* `declared` - _boolean_ - Whether `strerror_r()` is declared
|
||||||
|
|
||||||
|
* `returnsCharPtr` - _boolean_ - If `strerror_r()` is declared, whether it returns `char*` (a GNU extension) or not.
|
||||||
|
|
||||||
|
* **checkHeader**(< _string_ >lang, < _string_ >headerName) - _boolean_ - Checks if the header `headerName` exists and is usable where `lang` is either `'c'` or `'c++'`. Returns `true` if the header exists and is usable, `false` otherwise.
|
||||||
|
|
||||||
|
* **defines**([< _string_ >lang[, < _boolean_ >rendered]]) - _array_ - Returns a list of features, functions, headers, and symbols known to be defined by this build environment instance. `lang` is either `'c'` or `'c++'` If `lang` is not set, defines for both `'c'` and `'c++'` will be returned. If `rendered` is `true` (defaults to `false`), autoconf-style defines (e.g. "HAVE_FOO=1") will be returned instead. Defines coming from features utilize base strings/names from autoconf for better compatibility.
|
||||||
|
|
||||||
|
* **libs**([< _string_ >lang]) - _array_ - Returns a list of (`'-l'`-prefixed) libraries known to be required for features and functions defined by this build environment instance. `lang` is either `'c'` or `'c++'` If `lang` is not set, defines for both `'c'` and `'c++'` will be returned.
|
||||||
|
|
||||||
|
* **tryCompile**(< _string_ >lang, < _string_ >code[, < _array_ >compilerParams]) - _mixed_ - Attempts to compile `code` where `lang` is either `'c'` or `'c++'`. `compilerParams` is an optional array of compiler/linker flags to include. Returns `true` on successful compilation, or an _Error_ instance with an `output` property containing the compiler error output.
|
||||||
250
server/node_modules/buildcheck/deps/Find-VisualStudio.cs
generated
vendored
Normal file
250
server/node_modules/buildcheck/deps/Find-VisualStudio.cs
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
// Copyright 2017 - Refael Ackermann
|
||||||
|
// Distributed under MIT style license
|
||||||
|
// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf
|
||||||
|
|
||||||
|
// Usage:
|
||||||
|
// powershell -ExecutionPolicy Unrestricted -Command "Add-Type -Path Find-VisualStudio.cs; [VisualStudioConfiguration.Main]::PrintJson()"
|
||||||
|
// This script needs to be compatible with PowerShell v2 to run on Windows 2008R2 and Windows 7.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace VisualStudioConfiguration
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum InstanceState : uint
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Local = 1,
|
||||||
|
Registered = 2,
|
||||||
|
NoRebootRequired = 4,
|
||||||
|
NoErrors = 8,
|
||||||
|
Complete = 4294967295,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[ComImport]
|
||||||
|
public interface IEnumSetupInstances
|
||||||
|
{
|
||||||
|
|
||||||
|
void Next([MarshalAs(UnmanagedType.U4), In] int celt,
|
||||||
|
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt,
|
||||||
|
[MarshalAs(UnmanagedType.U4)] out int pceltFetched);
|
||||||
|
|
||||||
|
void Skip([MarshalAs(UnmanagedType.U4), In] int celt);
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.Interface)]
|
||||||
|
IEnumSetupInstances Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[ComImport]
|
||||||
|
public interface ISetupConfiguration
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[ComImport]
|
||||||
|
public interface ISetupConfiguration2 : ISetupConfiguration
|
||||||
|
{
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.Interface)]
|
||||||
|
IEnumSetupInstances EnumInstances();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.Interface)]
|
||||||
|
ISetupInstance GetInstanceForCurrentProcess();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.Interface)]
|
||||||
|
ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path);
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.Interface)]
|
||||||
|
IEnumSetupInstances EnumAllInstances();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[ComImport]
|
||||||
|
public interface ISetupInstance
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[ComImport]
|
||||||
|
public interface ISetupInstance2 : ISetupInstance
|
||||||
|
{
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetInstanceId();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.Struct)]
|
||||||
|
System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetInstallationName();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetInstallationPath();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetInstallationVersion();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid);
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid);
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath);
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.U4)]
|
||||||
|
InstanceState GetState();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
|
||||||
|
ISetupPackageReference[] GetPackages();
|
||||||
|
|
||||||
|
ISetupPackageReference GetProduct();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetProductPath();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.VariantBool)]
|
||||||
|
bool IsLaunchable();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.VariantBool)]
|
||||||
|
bool IsComplete();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
|
||||||
|
ISetupPropertyStore GetProperties();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetEnginePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[ComImport]
|
||||||
|
public interface ISetupPackageReference
|
||||||
|
{
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetId();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetVersion();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetChip();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetLanguage();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetBranch();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetType();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.BStr)]
|
||||||
|
string GetUniqueId();
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.VariantBool)]
|
||||||
|
bool GetIsExtension();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[ComImport]
|
||||||
|
public interface ISetupPropertyStore
|
||||||
|
{
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
|
||||||
|
string[] GetNames();
|
||||||
|
|
||||||
|
object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
|
||||||
|
[CoClass(typeof(SetupConfigurationClass))]
|
||||||
|
[ComImport]
|
||||||
|
public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
|
||||||
|
[ClassInterface(ClassInterfaceType.None)]
|
||||||
|
[ComImport]
|
||||||
|
public class SetupConfigurationClass
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Main
|
||||||
|
{
|
||||||
|
public static void PrintJson()
|
||||||
|
{
|
||||||
|
ISetupConfiguration query = new SetupConfiguration();
|
||||||
|
ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
|
||||||
|
IEnumSetupInstances e = query2.EnumAllInstances();
|
||||||
|
|
||||||
|
int pceltFetched;
|
||||||
|
ISetupInstance2[] rgelt = new ISetupInstance2[1];
|
||||||
|
List<string> instances = new List<string>();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
e.Next(1, rgelt, out pceltFetched);
|
||||||
|
if (pceltFetched <= 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine(String.Format("[{0}]", string.Join(",", instances.ToArray())));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
instances.Add(InstanceJson(rgelt[0]));
|
||||||
|
}
|
||||||
|
catch (COMException)
|
||||||
|
{
|
||||||
|
// Ignore instances that can't be queried.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string JsonString(string s)
|
||||||
|
{
|
||||||
|
return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string InstanceJson(ISetupInstance2 setupInstance2)
|
||||||
|
{
|
||||||
|
// Visual Studio component directory:
|
||||||
|
// https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids
|
||||||
|
|
||||||
|
StringBuilder json = new StringBuilder();
|
||||||
|
json.Append("{");
|
||||||
|
|
||||||
|
string path = JsonString(setupInstance2.GetInstallationPath());
|
||||||
|
json.Append(String.Format("\"path\":{0},", path));
|
||||||
|
|
||||||
|
string version = JsonString(setupInstance2.GetInstallationVersion());
|
||||||
|
json.Append(String.Format("\"version\":{0},", version));
|
||||||
|
|
||||||
|
List<string> packages = new List<string>();
|
||||||
|
foreach (ISetupPackageReference package in setupInstance2.GetPackages())
|
||||||
|
{
|
||||||
|
string id = JsonString(package.GetId());
|
||||||
|
packages.Add(id);
|
||||||
|
}
|
||||||
|
json.Append(String.Format("\"packages\":[{0}]", string.Join(",", packages.ToArray())));
|
||||||
|
|
||||||
|
json.Append("}");
|
||||||
|
return json.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
361
server/node_modules/buildcheck/lib/findvs.js
generated
vendored
Normal file
361
server/node_modules/buildcheck/lib/findvs.js
generated
vendored
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { execFileSync } = require('child_process');
|
||||||
|
const { readFileSync, statSync } = require('fs');
|
||||||
|
const { win32: path } = require('path');
|
||||||
|
|
||||||
|
const modernMSBuildPath = (() => {
|
||||||
|
let arch;
|
||||||
|
switch (process.arch) {
|
||||||
|
case 'x64':
|
||||||
|
arch = 'amd64';
|
||||||
|
break;
|
||||||
|
case 'arm64':
|
||||||
|
arch = process.arch;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
arch = '';
|
||||||
|
}
|
||||||
|
return path.join('MSBuild', 'Current', 'Bin', arch, 'MSBuild.exe');
|
||||||
|
})();
|
||||||
|
const VS_VERSIONS_MODERN = new Map([
|
||||||
|
[15, {
|
||||||
|
year: 2017,
|
||||||
|
msbuild: path.join('MSBuild', '15.0', 'Bin', 'MSBuild.exe'),
|
||||||
|
toolset: 'v141',
|
||||||
|
}],
|
||||||
|
[16, {
|
||||||
|
year: 2019,
|
||||||
|
msbuild: path.join('MSBuild', 'Current', 'Bin', 'MSBuild.exe'),
|
||||||
|
toolset: 'v142',
|
||||||
|
}],
|
||||||
|
[17, {
|
||||||
|
year: 2022,
|
||||||
|
msbuild: modernMSBuildPath,
|
||||||
|
toolset: 'v143',
|
||||||
|
}],
|
||||||
|
[18, {
|
||||||
|
year: 2026,
|
||||||
|
msbuild: modernMSBuildPath,
|
||||||
|
toolset: 'v145',
|
||||||
|
}],
|
||||||
|
]);
|
||||||
|
const PACKAGES = {
|
||||||
|
msbuild: /^Microsoft[.]VisualStudio[.]VC[.]MSBuild[.](?:v\d+[.])?Base$/i,
|
||||||
|
vctools: /^Microsoft[.]VisualStudio[.]Component[.]VC[.]Tools[.](x86[.]x64|ARM64)$/i,
|
||||||
|
express: /^Microsoft[.]VisualStudio[.]WDExpress$/i,
|
||||||
|
winsdk:
|
||||||
|
/^Microsoft[.]VisualStudio[.]Component[.]Windows(81|10|11)SDK(?:[.](\d+)(?:[.]Desktop.*)?)?$/,
|
||||||
|
};
|
||||||
|
const SDK_REG = 'HKLM\\Software\\Microsoft\\Microsoft SDKs\\Windows';
|
||||||
|
const SDK32_REG =
|
||||||
|
'HKLM\\Software\\Wow6432Node\\Microsoft\\Microsoft SDKs\\Windows';
|
||||||
|
|
||||||
|
function checkRequiredPackages(packages) {
|
||||||
|
if (!Array.isArray(packages))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let foundMSBuild = false;
|
||||||
|
let foundVCTools = false;
|
||||||
|
let foundExpress = false;
|
||||||
|
for (const pkg of packages) {
|
||||||
|
if (!foundMSBuild && PACKAGES.msbuild.test(pkg))
|
||||||
|
foundMSBuild = true;
|
||||||
|
else if (!foundVCTools && PACKAGES.vctools.test(pkg))
|
||||||
|
foundVCTools = true;
|
||||||
|
else if (!foundExpress && PACKAGES.express.test(pkg))
|
||||||
|
foundExpress = true;
|
||||||
|
|
||||||
|
if (foundMSBuild && (foundVCTools || foundExpress))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sorts newest to oldest
|
||||||
|
function versionStringCompare(a, b) {
|
||||||
|
const splitA = a.split('.');
|
||||||
|
const splitB = b.split('.');
|
||||||
|
const len = Math.min(splitA.length, splitB.length);
|
||||||
|
for (let i = 0; i < len; ++i) {
|
||||||
|
const nA = parseInt(splitA[i], 10);
|
||||||
|
const nB = parseInt(splitB[i], 10);
|
||||||
|
if (nA > nB)
|
||||||
|
return -1;
|
||||||
|
if (nA < nB)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (splitA.length > splitB.length)
|
||||||
|
return -1;
|
||||||
|
else if (splitA.length < splitB.length)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sdkVersionCompare(a, b) {
|
||||||
|
return versionStringCompare(a.fullVersion, b.fullVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSDKPaths(fullVer) {
|
||||||
|
if (typeof fullVer !== 'string' || !fullVer)
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
const arch = (process.arch === 'ia32' ? 'x86' : process.arch);
|
||||||
|
const shortVer = `v${/^\d+[.]\d+/.exec(fullVer)[0]}`;
|
||||||
|
let verPath = getRegValue(`${SDK_REG}\\${shortVer}`, 'InstallationFolder');
|
||||||
|
if (!verPath)
|
||||||
|
verPath = getRegValue(`${SDK32_REG}\\${shortVer}`, 'InstallationFolder');
|
||||||
|
if (!verPath)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Includes
|
||||||
|
const includePaths = [];
|
||||||
|
for (const type of ['shared', 'um', 'ucrt']) {
|
||||||
|
const testPath = path.resolve(verPath, 'Include', fullVer, type);
|
||||||
|
statSync(testPath);
|
||||||
|
includePaths.push(testPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
const libPaths = [];
|
||||||
|
for (const type of ['um', 'ucrt']) {
|
||||||
|
const testPath = path.resolve(verPath, 'Lib', fullVer, type, arch);
|
||||||
|
statSync(testPath);
|
||||||
|
libPaths.push(testPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { includePaths, libPaths };
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const execOpts = {
|
||||||
|
encoding: 'utf8',
|
||||||
|
stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
|
windowsHide: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
function findModernVS() {
|
||||||
|
const versions = [];
|
||||||
|
const ps = path.join(
|
||||||
|
process.env.SystemRoot,
|
||||||
|
'System32',
|
||||||
|
'WindowsPowerShell',
|
||||||
|
'v1.0',
|
||||||
|
'powershell.exe'
|
||||||
|
);
|
||||||
|
const cs = path.resolve(__dirname, '..', 'deps', 'Find-VisualStudio.cs');
|
||||||
|
const args = [
|
||||||
|
'-ExecutionPolicy',
|
||||||
|
'Unrestricted',
|
||||||
|
'-NoProfile',
|
||||||
|
'-Command',
|
||||||
|
`&{Add-Type -Path '${cs}';[VisualStudioConfiguration.Main]::PrintJson()}`
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
const out = execFileSync(ps, args, execOpts);
|
||||||
|
const info = JSON.parse(out);
|
||||||
|
if (Array.isArray(info)) {
|
||||||
|
for (const vs of info) {
|
||||||
|
const vsPath = path.resolve(vs.path);
|
||||||
|
let vsVer = /^(?<major>\d+)[.](?<minor>\d+)[.]/.exec(vs.version);
|
||||||
|
if (!vsVer)
|
||||||
|
continue;
|
||||||
|
vsVer = {
|
||||||
|
full: vs.version,
|
||||||
|
major: +vsVer.groups.major,
|
||||||
|
minor: +vsVer.groups.minor,
|
||||||
|
};
|
||||||
|
const verInfo = VS_VERSIONS_MODERN.get(vsVer.major);
|
||||||
|
if (verInfo === undefined)
|
||||||
|
continue;
|
||||||
|
if (!checkRequiredPackages(vs.packages))
|
||||||
|
continue;
|
||||||
|
const vsSDKs = [];
|
||||||
|
for (const pkg of vs.packages) {
|
||||||
|
let fullVersion;
|
||||||
|
let version;
|
||||||
|
const m = PACKAGES.winsdk.exec(pkg);
|
||||||
|
if (!m)
|
||||||
|
continue;
|
||||||
|
const sdk = m[1];
|
||||||
|
switch (sdk) {
|
||||||
|
case '81':
|
||||||
|
fullVersion = version = '8.1';
|
||||||
|
break;
|
||||||
|
case '10':
|
||||||
|
case '11': {
|
||||||
|
if (m[2] === undefined)
|
||||||
|
continue;
|
||||||
|
const sdkVer = parseInt(m[2], 10);
|
||||||
|
if (!isFinite(sdkVer) || sdkVer < 0)
|
||||||
|
continue;
|
||||||
|
fullVersion = `10.0.${sdkVer}.0`;
|
||||||
|
version = '10.0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const paths = getSDKPaths(fullVersion);
|
||||||
|
if (!paths)
|
||||||
|
continue;
|
||||||
|
vsSDKs.push({
|
||||||
|
version,
|
||||||
|
fullVersion,
|
||||||
|
...paths,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (vsSDKs.length === 0)
|
||||||
|
continue;
|
||||||
|
let clPath;
|
||||||
|
const includePaths = [];
|
||||||
|
const libPaths = [];
|
||||||
|
try {
|
||||||
|
let vcVerFile;
|
||||||
|
let clVer;
|
||||||
|
try {
|
||||||
|
vcVerFile = path.join(
|
||||||
|
vsPath,
|
||||||
|
'VC',
|
||||||
|
'Auxiliary',
|
||||||
|
'Build',
|
||||||
|
`Microsoft.VCToolsVersion.${verInfo.toolset}.default.txt`
|
||||||
|
);
|
||||||
|
clVer = readFileSync(vcVerFile, { encoding: 'utf8' }).trim();
|
||||||
|
} catch {}
|
||||||
|
if (!clVer) {
|
||||||
|
vcVerFile = path.join(
|
||||||
|
vsPath,
|
||||||
|
'VC',
|
||||||
|
'Auxiliary',
|
||||||
|
'Build',
|
||||||
|
'Microsoft.VCToolsVersion.default.txt'
|
||||||
|
);
|
||||||
|
clVer = readFileSync(vcVerFile, { encoding: 'utf8' }).trim();
|
||||||
|
}
|
||||||
|
const arch = (process.arch === 'ia32' ? 'x86' : process.arch);
|
||||||
|
let testPath = path.join(
|
||||||
|
vsPath,
|
||||||
|
'VC',
|
||||||
|
'Tools',
|
||||||
|
'MSVC',
|
||||||
|
clVer,
|
||||||
|
'bin',
|
||||||
|
`Host${arch}`,
|
||||||
|
arch,
|
||||||
|
'cl.exe'
|
||||||
|
);
|
||||||
|
statSync(testPath);
|
||||||
|
clPath = testPath;
|
||||||
|
|
||||||
|
testPath = path.join(
|
||||||
|
vsPath,
|
||||||
|
'VC',
|
||||||
|
'Tools',
|
||||||
|
'MSVC',
|
||||||
|
clVer,
|
||||||
|
'include'
|
||||||
|
);
|
||||||
|
statSync(testPath);
|
||||||
|
includePaths.push(testPath);
|
||||||
|
|
||||||
|
testPath = path.join(
|
||||||
|
vsPath,
|
||||||
|
'VC',
|
||||||
|
'Tools',
|
||||||
|
'MSVC',
|
||||||
|
clVer,
|
||||||
|
'lib',
|
||||||
|
arch
|
||||||
|
);
|
||||||
|
statSync(testPath);
|
||||||
|
libPaths.push(testPath);
|
||||||
|
} catch {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vsSDKs.sort(sdkVersionCompare);
|
||||||
|
versions.push({
|
||||||
|
path: vsPath,
|
||||||
|
version: vsVer,
|
||||||
|
sdks: vsSDKs,
|
||||||
|
...verInfo,
|
||||||
|
msbuild: path.join(vsPath, verInfo.msbuild),
|
||||||
|
cl: clPath,
|
||||||
|
includePaths,
|
||||||
|
libPaths,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
return versions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VS_VERSIONS_OLDER = [
|
||||||
|
{
|
||||||
|
version: { full: '12.0', major: 12, minor: 0 },
|
||||||
|
year: 2013,
|
||||||
|
toolset: 'v120',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: { full: '14.0', major: 14, minor: 0 },
|
||||||
|
year: 2015,
|
||||||
|
toolset: 'v140',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const VC_REG = 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7';
|
||||||
|
const VC32_REG =
|
||||||
|
'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7';
|
||||||
|
const MSBUILD_REG = 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions';
|
||||||
|
|
||||||
|
function getRegValue(key, value, use32) {
|
||||||
|
const extraArgs = (use32 ? [ '/reg:32' ] : []);
|
||||||
|
const regexp = new RegExp(`^\\s+${value}\\s+REG_\\w+\\s+(\\S.*)$`, 'im');
|
||||||
|
const reg = path.join(process.env.SystemRoot, 'System32', 'reg.exe');
|
||||||
|
const args = [ 'query', key, '/v', value, ...extraArgs ];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const out = execFileSync(reg, args, execOpts);
|
||||||
|
const m = regexp.exec(out);
|
||||||
|
if (m)
|
||||||
|
return m[1];
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findOlderVS() {
|
||||||
|
const versions = [];
|
||||||
|
try {
|
||||||
|
for (const vs of VS_VERSIONS_OLDER) {
|
||||||
|
let vsPath = getRegValue(VC_REG, vs.version.full);
|
||||||
|
if (!vsPath)
|
||||||
|
vsPath = getRegValue(VC32_REG, vs.version.full);
|
||||||
|
if (!vsPath)
|
||||||
|
continue;
|
||||||
|
vsPath = path.resolve(vsPath, '..');
|
||||||
|
|
||||||
|
const msbuildPath = getRegValue(
|
||||||
|
`${MSBUILD_REG}\\${vs.version.full}`,
|
||||||
|
'MSBuildToolsPath',
|
||||||
|
(process.arch === 'ia32')
|
||||||
|
);
|
||||||
|
if (!msbuildPath)
|
||||||
|
continue;
|
||||||
|
versions.push({
|
||||||
|
path: vsPath,
|
||||||
|
...vs,
|
||||||
|
msbuild: path.join(msbuildPath, 'MSBuild.exe'),
|
||||||
|
cl: path.join(vsPath, 'VC', 'bin', 'cl.exe'),
|
||||||
|
includePaths: [path.join(vsPath, 'VC', 'include')],
|
||||||
|
libPaths: [path.join(vsPath, 'VC', 'lib')],
|
||||||
|
sdks: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
return versions;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = () => {
|
||||||
|
const versions = findModernVS().concat(findOlderVS());
|
||||||
|
// Sorts newest to oldest
|
||||||
|
versions.sort((a, b) => {
|
||||||
|
return versionStringCompare(a.version.full, b.version.full);
|
||||||
|
});
|
||||||
|
return versions;
|
||||||
|
};
|
||||||
738
server/node_modules/buildcheck/lib/index.js
generated
vendored
Normal file
738
server/node_modules/buildcheck/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,738 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// TODO: take `compilerParams`, headers into account in cache for all cached
|
||||||
|
// results
|
||||||
|
// TODO: debug output
|
||||||
|
|
||||||
|
const { spawnSync } = require('child_process');
|
||||||
|
const { unlinkSync, writeFileSync } = require('fs');
|
||||||
|
const { tmpdir } = require('os');
|
||||||
|
const { win32: path } = require('path');
|
||||||
|
const { inspect } = require('util');
|
||||||
|
|
||||||
|
const isWindows = (process.platform === 'win32');
|
||||||
|
const findVS = require('./findvs.js');
|
||||||
|
|
||||||
|
const RE_HEADER_DECORATED = /^(?:"(.+)")|(?:<(.+)>)$/;
|
||||||
|
|
||||||
|
const genWinTmpFilenames = (() => {
|
||||||
|
let instance = 1;
|
||||||
|
return () => {
|
||||||
|
const base =
|
||||||
|
path.resolve(tmpdir(), `_buildcheck-${process.pid}-${instance++}`);
|
||||||
|
return {
|
||||||
|
input: `${base}.in.tmp`,
|
||||||
|
object: `${base}.out.obj`,
|
||||||
|
output: `${base}.out.tmp`,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
function getKind(prop) {
|
||||||
|
const spawnOpts = {
|
||||||
|
encoding: 'utf8',
|
||||||
|
stdio: 'pipe',
|
||||||
|
windowsHide: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const lang = (prop === '_cc' ? 'c' : 'c++');
|
||||||
|
|
||||||
|
if (isWindows) {
|
||||||
|
spawnOpts.stdio = [ 'ignore', 'pipe', 'pipe' ];
|
||||||
|
writeFileSync(this._tmpInFile, [
|
||||||
|
'_MSC_VER',
|
||||||
|
].join(' '));
|
||||||
|
const result = spawnSync(
|
||||||
|
this[prop],
|
||||||
|
[ '-EP', `-T${lang === 'c' ? 'c' : 'p'}`, this._tmpInFile],
|
||||||
|
spawnOpts
|
||||||
|
);
|
||||||
|
unlinkSync(this._tmpInFile);
|
||||||
|
|
||||||
|
if (result.status === 0) {
|
||||||
|
const values = result.stdout.trim().split(' ');
|
||||||
|
if (values.length === 1 && /^\d+$/.test(values[0])) {
|
||||||
|
this[`${prop}Kind`] = 'msvc';
|
||||||
|
this[`${prop}Version`] = values[0];
|
||||||
|
this[`${prop}SpawnOpts`] = spawnOpts;
|
||||||
|
this._debug(
|
||||||
|
`>>> Detected MSVC ${values[0]} for ${lang.toUpperCase()} language`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const result = spawnSync(
|
||||||
|
this[prop],
|
||||||
|
[ '-E', '-P', '-x', lang, '-' ],
|
||||||
|
{
|
||||||
|
...spawnOpts,
|
||||||
|
input: [
|
||||||
|
'__clang__',
|
||||||
|
'__GNUC__',
|
||||||
|
'__GNUC_MINOR__',
|
||||||
|
'__GNUC_PATCHLEVEL__',
|
||||||
|
'__clang_major__',
|
||||||
|
'__clang_minor__',
|
||||||
|
'__clang_patchlevel__',
|
||||||
|
].join(' '),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.status === 0) {
|
||||||
|
const values = result.stdout.trim().split(' ');
|
||||||
|
if (values.length === 7) {
|
||||||
|
let kind;
|
||||||
|
let version;
|
||||||
|
if (values[0] === '1') {
|
||||||
|
kind = 'clang';
|
||||||
|
version = values.slice(4).map((v) => +v);
|
||||||
|
} else {
|
||||||
|
kind = 'gnu';
|
||||||
|
version = values.slice(1, 4).map((v) => +v);
|
||||||
|
}
|
||||||
|
let good = true;
|
||||||
|
for (const part of version) {
|
||||||
|
if (!isFinite(part) || part < 0) {
|
||||||
|
good = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (good) {
|
||||||
|
this[`${prop}Kind`] = kind;
|
||||||
|
this[`${prop}Version`] = version;
|
||||||
|
this[`${prop}SpawnOpts`] = spawnOpts;
|
||||||
|
const verStr = version.join('.');
|
||||||
|
this._debug(
|
||||||
|
`>>> Detected ${kind} ${verStr} for ${lang.toUpperCase()} language`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Unable to detect compiler type');
|
||||||
|
}
|
||||||
|
|
||||||
|
class BuildEnvironment {
|
||||||
|
constructor(cfg) {
|
||||||
|
if (typeof cfg !== 'object' || cfg === null)
|
||||||
|
cfg = {};
|
||||||
|
|
||||||
|
this._debug = (typeof cfg.debug === 'function' ? cfg.debug : () => {});
|
||||||
|
|
||||||
|
let cc;
|
||||||
|
let cxx;
|
||||||
|
if (isWindows) {
|
||||||
|
const versions = findVS();
|
||||||
|
this._debug(
|
||||||
|
`>>> Detected MSVS installations: ${inspect(versions, false, 10)}`
|
||||||
|
);
|
||||||
|
if (versions.length === 0)
|
||||||
|
throw new Error('Unable to detect compiler type');
|
||||||
|
let selected_msvs;
|
||||||
|
if (cfg.msvs_version
|
||||||
|
&& (typeof cfg.msvs_version === 'string'
|
||||||
|
|| typeof cfg.msvs_version === 'number')) {
|
||||||
|
this._debug(`>>> Explicit MSVS requested: ${cfg.msvs_version}`);
|
||||||
|
// Try to select compiler by year
|
||||||
|
const msvs_version = cfg.msvs_version.toString();
|
||||||
|
for (const vs of versions) {
|
||||||
|
if (vs.year.toString() === msvs_version) {
|
||||||
|
selected_msvs = vs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selected_msvs === undefined)
|
||||||
|
throw new Error(`Unable to find MSVS with year '${msvs_version}'`);
|
||||||
|
} else {
|
||||||
|
selected_msvs = versions[0]; // Use newest
|
||||||
|
}
|
||||||
|
this._debug(`>>> Using MSVS: ${selected_msvs.year}`);
|
||||||
|
cc = selected_msvs.cl;
|
||||||
|
cxx = cc;
|
||||||
|
this._includePaths = selected_msvs.includePaths;
|
||||||
|
this._libPaths = selected_msvs.libPaths;
|
||||||
|
// Add (newest) SDK paths if we have them
|
||||||
|
for (const sdk of selected_msvs.sdks) {
|
||||||
|
this._debug(`>>> Using Windows SDK: ${sdk.fullVersion}`);
|
||||||
|
this._includePaths = this._includePaths.concat(sdk.includePaths);
|
||||||
|
this._libPaths = this._libPaths.concat(sdk.libPaths);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { input, object, output } = genWinTmpFilenames();
|
||||||
|
this._tmpInFile = input;
|
||||||
|
this._tmpObjFile = object;
|
||||||
|
this._tmpOutFile = output;
|
||||||
|
} else {
|
||||||
|
cc = ((typeof cfg.compilerC === 'string' && cfg.compilerC)
|
||||||
|
|| process.env.CC
|
||||||
|
|| 'cc');
|
||||||
|
cxx = ((typeof cfg.compilerCXX === 'string' && cfg.compilerCXX)
|
||||||
|
|| process.env.CXX
|
||||||
|
|| 'c++');
|
||||||
|
this._debug(`>>> Using C compiler: ${cc}`);
|
||||||
|
this._debug(`>>> Using C++ compiler: ${cxx}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._cc = cc;
|
||||||
|
this._ccKind = undefined;
|
||||||
|
this._ccVersion = undefined;
|
||||||
|
this._ccSpawnOpts = undefined;
|
||||||
|
|
||||||
|
this._cxx = cxx;
|
||||||
|
this._cxxKind = undefined;
|
||||||
|
this._cxxVersion = undefined;
|
||||||
|
this._cxxSpawnOpts = undefined;
|
||||||
|
|
||||||
|
if (cfg.cache !== false) {
|
||||||
|
this._cache = new Map(Object.entries({
|
||||||
|
c: new Map(),
|
||||||
|
cxx: new Map(),
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
this._cache = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkDeclared(type, symbolName, opts) {
|
||||||
|
validateType(type);
|
||||||
|
if (typeof symbolName !== 'string' || !symbolName)
|
||||||
|
throw new Error(`Invalid symbol name: ${inspect(symbolName)}`);
|
||||||
|
|
||||||
|
const cached = getCachedValue(type, this._cache, 'declared', symbolName);
|
||||||
|
if (cached !== undefined) {
|
||||||
|
this._debug(
|
||||||
|
`>>> Checking if '${symbolName}' is declared... ${cached} (cached)`
|
||||||
|
);
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof opts !== 'object' || opts === null)
|
||||||
|
opts = {};
|
||||||
|
|
||||||
|
const { headers, searchLibs } = opts;
|
||||||
|
const headersList = renderHeaders(Array.isArray(headers)
|
||||||
|
? headers
|
||||||
|
: getDefaultHeaders(this, type));
|
||||||
|
|
||||||
|
const declName = symbolName.replace(/ *\(.*/, '');
|
||||||
|
const declUse = symbolName.replace(/\(/, '((')
|
||||||
|
.replace(/\)/, ') 0)')
|
||||||
|
.replace(/,/g, ') 0, (');
|
||||||
|
|
||||||
|
const libs = [
|
||||||
|
'',
|
||||||
|
...(Array.isArray(searchLibs) ? searchLibs : [])
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let lib of libs) {
|
||||||
|
if (typeof lib !== 'string')
|
||||||
|
continue;
|
||||||
|
lib = lib.trim();
|
||||||
|
|
||||||
|
const code = `
|
||||||
|
${headersList}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
#ifndef ${declName}
|
||||||
|
#ifdef __cplusplus
|
||||||
|
(void) ${declUse};
|
||||||
|
#else
|
||||||
|
(void) ${declName};
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}`;
|
||||||
|
const compilerParams = (lib ? [`-l${lib}`] : []);
|
||||||
|
const result = this.tryCompile(type, code, compilerParams);
|
||||||
|
|
||||||
|
this._debug(
|
||||||
|
`>>> Checking if '${symbolName}' is declared `
|
||||||
|
+ `(using ${lib ? `'${lib}'` : 'no'} library)... ${result === true}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result !== true) {
|
||||||
|
this._debug('... check failed with compiler output:');
|
||||||
|
this._debug(result.output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result === true) {
|
||||||
|
setCachedValue(
|
||||||
|
type,
|
||||||
|
this._cache,
|
||||||
|
'declared',
|
||||||
|
symbolName,
|
||||||
|
(result === true)
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkFeature(name) {
|
||||||
|
const cached = getCachedValue('features', this._cache, null, name);
|
||||||
|
if (cached !== undefined) {
|
||||||
|
if (typeof cached === 'object'
|
||||||
|
&& cached !== null
|
||||||
|
&& typeof cached.val !== undefined) {
|
||||||
|
return cached.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
const feature = features.get(name);
|
||||||
|
if (feature === undefined)
|
||||||
|
throw new Error(`Invalid feature: ${name}`);
|
||||||
|
|
||||||
|
let result = feature(this);
|
||||||
|
if (result === undefined)
|
||||||
|
result = null;
|
||||||
|
|
||||||
|
setCachedValue('features', this._cache, null, name, result);
|
||||||
|
|
||||||
|
if (typeof result === 'object'
|
||||||
|
&& result !== null
|
||||||
|
&& typeof result.val !== undefined) {
|
||||||
|
return result.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkFunction(type, funcName, opts) {
|
||||||
|
validateType(type);
|
||||||
|
if (typeof funcName !== 'string' || !funcName)
|
||||||
|
throw new Error(`Invalid function name: ${inspect(funcName)}`);
|
||||||
|
|
||||||
|
const cached = getCachedValue(type, this._cache, 'functions', funcName);
|
||||||
|
if (cached !== undefined) {
|
||||||
|
this._debug(
|
||||||
|
`>>> Checking if function '${funcName}' exists... true (cached)`
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof opts !== 'object' || opts === null)
|
||||||
|
opts = {};
|
||||||
|
|
||||||
|
const { searchLibs } = opts;
|
||||||
|
const libs = [
|
||||||
|
'',
|
||||||
|
...(Array.isArray(searchLibs) ? searchLibs : [])
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let lib of libs) {
|
||||||
|
if (typeof lib !== 'string')
|
||||||
|
continue;
|
||||||
|
lib = lib.trim();
|
||||||
|
|
||||||
|
const code = `
|
||||||
|
/* Define ${funcName} to an innocuous variant, in case <limits.h> declares
|
||||||
|
${funcName}.
|
||||||
|
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
||||||
|
#define ${funcName} innocuous_${funcName}
|
||||||
|
/* System header to define __stub macros and hopefully few prototypes,
|
||||||
|
which can conflict with char ${funcName} (); below. */
|
||||||
|
#include <limits.h>
|
||||||
|
#undef ${funcName}
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char ${funcName} ();
|
||||||
|
/* The GNU C library defines this for functions which it implements
|
||||||
|
to always fail with ENOSYS. Some functions are actually named
|
||||||
|
something starting with __ and the normal name is an alias. */
|
||||||
|
#if defined __stub_${funcName} || defined __stub___${funcName}
|
||||||
|
choke me
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return ${funcName} ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const compilerParams = (lib ? [`-l${lib}`] : []);
|
||||||
|
const result = this.tryCompile(type, code, compilerParams);
|
||||||
|
|
||||||
|
this._debug(
|
||||||
|
`>>> Checking if function '${funcName}' exists `
|
||||||
|
+ `(using ${lib ? `'${lib}'` : 'no'} library)... ${result === true}`
|
||||||
|
);
|
||||||
|
if (result !== true) {
|
||||||
|
this._debug('... check failed with compiler output:');
|
||||||
|
this._debug(result.output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result === true) {
|
||||||
|
setCachedValue(
|
||||||
|
type,
|
||||||
|
this._cache,
|
||||||
|
'functions',
|
||||||
|
funcName,
|
||||||
|
compilerParams
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkHeader(type, header) {
|
||||||
|
validateType(type);
|
||||||
|
const cached = getCachedValue(
|
||||||
|
type,
|
||||||
|
this._cache,
|
||||||
|
'headers',
|
||||||
|
normalizeHeader(header)
|
||||||
|
);
|
||||||
|
if (cached !== undefined) {
|
||||||
|
this._debug(
|
||||||
|
`>>> Checking if header '${header}' exists... ${cached} (cached)`
|
||||||
|
);
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headersList = renderHeaders([header]);
|
||||||
|
|
||||||
|
const code = `
|
||||||
|
${headersList}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const result = this.tryCompile(type, code);
|
||||||
|
setCachedValue(
|
||||||
|
type,
|
||||||
|
this._cache,
|
||||||
|
'headers',
|
||||||
|
normalizeHeader(header),
|
||||||
|
(result === true)
|
||||||
|
);
|
||||||
|
this._debug(
|
||||||
|
`>>> Checking if header '${header}' exists... ${result === true}`
|
||||||
|
);
|
||||||
|
if (result !== true) {
|
||||||
|
this._debug('... check failed with compiler output:');
|
||||||
|
this._debug(result.output);
|
||||||
|
}
|
||||||
|
return (result === true);
|
||||||
|
}
|
||||||
|
|
||||||
|
defines(type, rendered) {
|
||||||
|
if (this._cache === null)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
const defines = new Map();
|
||||||
|
|
||||||
|
let types;
|
||||||
|
if (!['c', 'c++'].includes(type))
|
||||||
|
types = ['c', 'c++'];
|
||||||
|
else
|
||||||
|
types = [type];
|
||||||
|
|
||||||
|
for (const t of types) {
|
||||||
|
const typeCache = this._cache.get(t);
|
||||||
|
if (!typeCache)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const [subtype, entries] of typeCache) {
|
||||||
|
for (let name of entries.keys()) {
|
||||||
|
if (subtype === 'headers')
|
||||||
|
name = name.replace(RE_HEADER_DECORATED, '$1$2');
|
||||||
|
defines.set(makeDefine(name, rendered), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const featuresCache = this._cache.get('features');
|
||||||
|
if (featuresCache) {
|
||||||
|
for (const result of featuresCache.values()) {
|
||||||
|
if (typeof result === 'object'
|
||||||
|
&& result !== null
|
||||||
|
&& Array.isArray(result.defines)) {
|
||||||
|
for (const define of result.defines)
|
||||||
|
defines.set(makeDefine(define, rendered), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(defines.keys());
|
||||||
|
}
|
||||||
|
|
||||||
|
libs(type) {
|
||||||
|
if (this._cache === null)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
const libs = new Map();
|
||||||
|
|
||||||
|
let types;
|
||||||
|
if (!['c', 'c++'].includes(type))
|
||||||
|
types = ['c', 'c++'];
|
||||||
|
else
|
||||||
|
types = [type];
|
||||||
|
|
||||||
|
for (const t of types) {
|
||||||
|
const typeCache = this._cache.get(t);
|
||||||
|
if (!typeCache)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const functionsCache = typeCache.get('functions');
|
||||||
|
if (!functionsCache)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const compilerParams of functionsCache.values()) {
|
||||||
|
for (const param of compilerParams)
|
||||||
|
libs.set(param, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const featuresCache = this._cache.get('features');
|
||||||
|
if (featuresCache) {
|
||||||
|
for (const result of featuresCache.values()) {
|
||||||
|
if (typeof result === 'object'
|
||||||
|
&& result !== null
|
||||||
|
&& Array.isArray(result.libs)) {
|
||||||
|
for (const lib of result.libs)
|
||||||
|
libs.set(lib, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(libs.keys());
|
||||||
|
}
|
||||||
|
|
||||||
|
tryCompile(type, code, compilerParams) {
|
||||||
|
validateType(type);
|
||||||
|
if (typeof code !== 'string')
|
||||||
|
throw new TypeError('Invalid code argument');
|
||||||
|
|
||||||
|
type = (type === 'c' ? 'c' : 'c++');
|
||||||
|
const prop = (type === 'c' ? '_cc' : '_cxx');
|
||||||
|
|
||||||
|
if (this[`${prop}Kind`] === undefined)
|
||||||
|
getKind.call(this, prop);
|
||||||
|
|
||||||
|
if (!Array.isArray(compilerParams))
|
||||||
|
compilerParams = [];
|
||||||
|
|
||||||
|
let result;
|
||||||
|
if (this[`${prop}Kind`] === 'msvc') {
|
||||||
|
const cmpOpts = [`-Fo${this._tmpObjFile}`];
|
||||||
|
for (const includePath of this._includePaths)
|
||||||
|
cmpOpts.push('-I', includePath);
|
||||||
|
const lnkOpts = [];
|
||||||
|
for (const libPath of this._libPaths)
|
||||||
|
lnkOpts.push(`-LIBPATH:${libPath}`);
|
||||||
|
for (const opt of compilerParams) {
|
||||||
|
let m;
|
||||||
|
if (m = /^[-/]l(.+)$/.exec(opt))
|
||||||
|
lnkOpts.push(m[1]);
|
||||||
|
else
|
||||||
|
cmpOpts.push(opt);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writeFileSync(this._tmpInFile, code);
|
||||||
|
const args = [
|
||||||
|
...cmpOpts,
|
||||||
|
`-T${prop === '_cc' ? 'c' : 'p'}`,
|
||||||
|
this._tmpInFile,
|
||||||
|
'-link',
|
||||||
|
`-out:${this._tmpOutFile}`,
|
||||||
|
...lnkOpts,
|
||||||
|
];
|
||||||
|
result = spawnSync(
|
||||||
|
this[prop],
|
||||||
|
args,
|
||||||
|
this[`${prop}SpawnOpts`]
|
||||||
|
);
|
||||||
|
unlinkSync(this._tmpInFile);
|
||||||
|
// Overwrite stderr with stdout because MSVC seems to print
|
||||||
|
// errors to stdout instead for some reason
|
||||||
|
result.stderr = result.stdout;
|
||||||
|
} catch (ex) {
|
||||||
|
// We had trouble writing or deleting a temp file, fake
|
||||||
|
// the result
|
||||||
|
result = { status: Infinity, stderr: ex.stack };
|
||||||
|
}
|
||||||
|
try { unlinkSync(this._tmpObjFile); } catch {}
|
||||||
|
try { unlinkSync(this._tmpOutFile); } catch {}
|
||||||
|
} else {
|
||||||
|
result = spawnSync(
|
||||||
|
this[prop],
|
||||||
|
[
|
||||||
|
'-x', type,
|
||||||
|
'-o', '/dev/null',
|
||||||
|
'-',
|
||||||
|
...compilerParams,
|
||||||
|
],
|
||||||
|
{
|
||||||
|
...this[`${prop}SpawnOpts`],
|
||||||
|
input: code,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.status === 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const err = new Error('Compilation failed');
|
||||||
|
err.output = result.stderr;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateType(type) {
|
||||||
|
if (!['c', 'c++'].includes(type))
|
||||||
|
throw new Error('Invalid type argument');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCachedValue(type, cache, subtype, key) {
|
||||||
|
if (cache === null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const typeCache = cache.get(type);
|
||||||
|
if (!typeCache)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const subtypeCache = (typeof subtype !== 'string'
|
||||||
|
? typeCache
|
||||||
|
: typeCache.get(subtype));
|
||||||
|
if (!subtypeCache)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return subtypeCache.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCachedValue(type, cache, subtype, key, value) {
|
||||||
|
if (cache === null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let typeCache = cache.get(type);
|
||||||
|
if (!typeCache)
|
||||||
|
cache.set(type, typeCache = new Map());
|
||||||
|
|
||||||
|
let subtypeCache = (typeof subtype !== 'string'
|
||||||
|
? typeCache
|
||||||
|
: typeCache.get(subtype));
|
||||||
|
if (!subtypeCache)
|
||||||
|
typeCache.set(subtype, subtypeCache = new Map());
|
||||||
|
|
||||||
|
subtypeCache.set(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderHeaders(headers) {
|
||||||
|
let ret = '';
|
||||||
|
|
||||||
|
if (Array.isArray(headers)) {
|
||||||
|
for (const header of headers) {
|
||||||
|
if (typeof header !== 'string' || !header)
|
||||||
|
throw new Error(`Invalid header: ${inspect(header)}`);
|
||||||
|
ret += `#include ${normalizeHeader(header)}\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeHeader(header) {
|
||||||
|
if (!RE_HEADER_DECORATED.test(header))
|
||||||
|
header = `<${header}>`;
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_HEADERS_POSIX = [
|
||||||
|
'stdio.h',
|
||||||
|
'sys/types.h',
|
||||||
|
'sys/stat.h',
|
||||||
|
'stdlib.h',
|
||||||
|
'stddef.h',
|
||||||
|
'memory.h',
|
||||||
|
'string.h',
|
||||||
|
'strings.h',
|
||||||
|
'inttypes.h',
|
||||||
|
'stdint.h',
|
||||||
|
'unistd.h'
|
||||||
|
];
|
||||||
|
const DEFAULT_HEADERS_MSVC = [
|
||||||
|
'windows.h',
|
||||||
|
];
|
||||||
|
function getDefaultHeaders(be, type) {
|
||||||
|
const prop = (type === 'c' ? '_cc' : '_cxx');
|
||||||
|
if (be[`${prop}Kind`] === undefined)
|
||||||
|
getKind.call(be, prop);
|
||||||
|
|
||||||
|
let headers;
|
||||||
|
if (be[`${prop}Kind`] === 'msvc')
|
||||||
|
headers = DEFAULT_HEADERS_MSVC;
|
||||||
|
else
|
||||||
|
headers = DEFAULT_HEADERS_POSIX;
|
||||||
|
|
||||||
|
return headers.filter((hdr) => be.checkHeader(type, hdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
const features = new Map(Object.entries({
|
||||||
|
'strerror_r': (be) => {
|
||||||
|
const defines = [];
|
||||||
|
let returnsCharPtr = false;
|
||||||
|
|
||||||
|
const declared = be.checkDeclared('c', 'strerror_r');
|
||||||
|
if (declared) {
|
||||||
|
const code = `
|
||||||
|
${renderHeaders(getDefaultHeaders(be, 'c'))}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
char buf[100];
|
||||||
|
char x = *strerror_r (0, buf, sizeof buf);
|
||||||
|
char *p = strerror_r (0, buf, sizeof buf);
|
||||||
|
return !p || x;
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}`;
|
||||||
|
returnsCharPtr = (be.tryCompile('c', code) === true);
|
||||||
|
if (returnsCharPtr)
|
||||||
|
defines.push('STRERROR_R_CHAR_P');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
defines,
|
||||||
|
val: { declared, returnsCharPtr }
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
function makeDefine(name, rendered) {
|
||||||
|
name = name.replace(/[*]/g, 'P')
|
||||||
|
.replace(/[^_A-Za-z0-9]/g, '_')
|
||||||
|
.toUpperCase();
|
||||||
|
return (rendered ? `HAVE_${name}=1` : name);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BuildEnvironment;
|
||||||
36
server/node_modules/buildcheck/package.json
generated
vendored
Normal file
36
server/node_modules/buildcheck/package.json
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "buildcheck",
|
||||||
|
"version": "0.0.7",
|
||||||
|
"author": "Brian White <mscdex@mscdex.net>",
|
||||||
|
"description": "Build environment checking (a la autoconf) for node.js",
|
||||||
|
"main": "./lib/index.js",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@mscdex/eslint-config": "^1.1.0",
|
||||||
|
"eslint": "^7.0.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "node test/test.js",
|
||||||
|
"lint": "eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib",
|
||||||
|
"lint:fix": "npm run lint -- --fix"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"build",
|
||||||
|
"autoconf",
|
||||||
|
"addons",
|
||||||
|
"compiler",
|
||||||
|
"environment"
|
||||||
|
],
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "http://github.com/mscdex/buildcheck/raw/master/LICENSE"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "http://github.com/mscdex/buildcheck.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
server/node_modules/buildcheck/test/test.js
generated
vendored
Normal file
8
server/node_modules/buildcheck/test/test.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const BE = require('..');
|
||||||
|
|
||||||
|
{
|
||||||
|
// Test compiler detection
|
||||||
|
new BE({ debug: console.log });
|
||||||
|
}
|
||||||
97
server/node_modules/bytes/History.md
generated
vendored
Normal file
97
server/node_modules/bytes/History.md
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
3.1.2 / 2022-01-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix return value for un-parsable strings
|
||||||
|
|
||||||
|
3.1.1 / 2021-11-15
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix "thousandsSeparator" incorrecting formatting fractional part
|
||||||
|
|
||||||
|
3.1.0 / 2019-01-22
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add petabyte (`pb`) support
|
||||||
|
|
||||||
|
3.0.0 / 2017-08-31
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Change "kB" to "KB" in format output
|
||||||
|
* Remove support for Node.js 0.6
|
||||||
|
* Remove support for ComponentJS
|
||||||
|
|
||||||
|
2.5.0 / 2017-03-24
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add option "unit"
|
||||||
|
|
||||||
|
2.4.0 / 2016-06-01
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add option "unitSeparator"
|
||||||
|
|
||||||
|
2.3.0 / 2016-02-15
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Drop partial bytes on all parsed units
|
||||||
|
* Fix non-finite numbers to `.format` to return `null`
|
||||||
|
* Fix parsing byte string that looks like hex
|
||||||
|
* perf: hoist regular expressions
|
||||||
|
|
||||||
|
2.2.0 / 2015-11-13
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add option "decimalPlaces"
|
||||||
|
* add option "fixedDecimals"
|
||||||
|
|
||||||
|
2.1.0 / 2015-05-21
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add `.format` export
|
||||||
|
* add `.parse` export
|
||||||
|
|
||||||
|
2.0.2 / 2015-05-20
|
||||||
|
==================
|
||||||
|
|
||||||
|
* remove map recreation
|
||||||
|
* remove unnecessary object construction
|
||||||
|
|
||||||
|
2.0.1 / 2015-05-07
|
||||||
|
==================
|
||||||
|
|
||||||
|
* fix browserify require
|
||||||
|
* remove node.extend dependency
|
||||||
|
|
||||||
|
2.0.0 / 2015-04-12
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add option "case"
|
||||||
|
* add option "thousandsSeparator"
|
||||||
|
* return "null" on invalid parse input
|
||||||
|
* support proper round-trip: bytes(bytes(num)) === num
|
||||||
|
* units no longer case sensitive when parsing
|
||||||
|
|
||||||
|
1.0.0 / 2014-05-05
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add negative support. fixes #6
|
||||||
|
|
||||||
|
0.3.0 / 2014-03-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* added terabyte support
|
||||||
|
|
||||||
|
0.2.1 / 2013-04-01
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add .component
|
||||||
|
|
||||||
|
0.2.0 / 2012-10-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* bytes(200).should.eql('200b')
|
||||||
|
|
||||||
|
0.1.0 / 2012-07-04
|
||||||
|
==================
|
||||||
|
|
||||||
|
* add bytes to string conversion [yields]
|
||||||
23
server/node_modules/bytes/LICENSE
generated
vendored
Normal file
23
server/node_modules/bytes/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2012-2014 TJ Holowaychuk <tj@vision-media.ca>
|
||||||
|
Copyright (c) 2015 Jed Watson <jed.watson@me.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
152
server/node_modules/bytes/Readme.md
generated
vendored
Normal file
152
server/node_modules/bytes/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# Bytes utility
|
||||||
|
|
||||||
|
[![NPM Version][npm-image]][npm-url]
|
||||||
|
[![NPM Downloads][downloads-image]][downloads-url]
|
||||||
|
[![Build Status][ci-image]][ci-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
Utility to parse a string bytes (ex: `1TB`) to bytes (`1099511627776`) and vice-versa.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
var bytes = require('bytes');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### bytes(number|string value, [options]): number|string|null
|
||||||
|
|
||||||
|
Default export function. Delegates to either `bytes.format` or `bytes.parse` based on the type of `value`.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
|---------|----------|--------------------|
|
||||||
|
| value | `number`|`string` | Number value to format or string value to parse |
|
||||||
|
| options | `Object` | Conversion options for `format` |
|
||||||
|
|
||||||
|
**Returns**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
|---------|------------------|-------------------------------------------------|
|
||||||
|
| results | `string`|`number`|`null` | Return null upon error. Numeric value in bytes, or string value otherwise. |
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
```js
|
||||||
|
bytes(1024);
|
||||||
|
// output: '1KB'
|
||||||
|
|
||||||
|
bytes('1KB');
|
||||||
|
// output: 1024
|
||||||
|
```
|
||||||
|
|
||||||
|
#### bytes.format(number value, [options]): string|null
|
||||||
|
|
||||||
|
Format the given value in bytes into a string. If the value is negative, it is kept as such. If it is a float, it is
|
||||||
|
rounded.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
|---------|----------|--------------------|
|
||||||
|
| value | `number` | Value in bytes |
|
||||||
|
| options | `Object` | Conversion options |
|
||||||
|
|
||||||
|
**Options**
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
|-------------------|--------|-----------------------------------------------------------------------------------------|
|
||||||
|
| decimalPlaces | `number`|`null` | Maximum number of decimal places to include in output. Default value to `2`. |
|
||||||
|
| fixedDecimals | `boolean`|`null` | Whether to always display the maximum number of decimal places. Default value to `false` |
|
||||||
|
| thousandsSeparator | `string`|`null` | Example of values: `' '`, `','` and `'.'`... Default value to `''`. |
|
||||||
|
| unit | `string`|`null` | The unit in which the result will be returned (B/KB/MB/GB/TB). Default value to `''` (which means auto detect). |
|
||||||
|
| unitSeparator | `string`|`null` | Separator to use between number and unit. Default value to `''`. |
|
||||||
|
|
||||||
|
**Returns**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
|---------|------------------|-------------------------------------------------|
|
||||||
|
| results | `string`|`null` | Return null upon error. String value otherwise. |
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
```js
|
||||||
|
bytes.format(1024);
|
||||||
|
// output: '1KB'
|
||||||
|
|
||||||
|
bytes.format(1000);
|
||||||
|
// output: '1000B'
|
||||||
|
|
||||||
|
bytes.format(1000, {thousandsSeparator: ' '});
|
||||||
|
// output: '1 000B'
|
||||||
|
|
||||||
|
bytes.format(1024 * 1.7, {decimalPlaces: 0});
|
||||||
|
// output: '2KB'
|
||||||
|
|
||||||
|
bytes.format(1024, {unitSeparator: ' '});
|
||||||
|
// output: '1 KB'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### bytes.parse(string|number value): number|null
|
||||||
|
|
||||||
|
Parse the string value into an integer in bytes. If no unit is given, or `value`
|
||||||
|
is a number, it is assumed the value is in bytes.
|
||||||
|
|
||||||
|
Supported units and abbreviations are as follows and are case-insensitive:
|
||||||
|
|
||||||
|
* `b` for bytes
|
||||||
|
* `kb` for kilobytes
|
||||||
|
* `mb` for megabytes
|
||||||
|
* `gb` for gigabytes
|
||||||
|
* `tb` for terabytes
|
||||||
|
* `pb` for petabytes
|
||||||
|
|
||||||
|
The units are in powers of two, not ten. This means 1kb = 1024b according to this parser.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
|---------------|--------|--------------------|
|
||||||
|
| value | `string`|`number` | String to parse, or number in bytes. |
|
||||||
|
|
||||||
|
**Returns**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
|---------|-------------|-------------------------|
|
||||||
|
| results | `number`|`null` | Return null upon error. Value in bytes otherwise. |
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
```js
|
||||||
|
bytes.parse('1KB');
|
||||||
|
// output: 1024
|
||||||
|
|
||||||
|
bytes.parse('1024');
|
||||||
|
// output: 1024
|
||||||
|
|
||||||
|
bytes.parse(1024);
|
||||||
|
// output: 1024
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
[ci-image]: https://badgen.net/github/checks/visionmedia/bytes.js/master?label=ci
|
||||||
|
[ci-url]: https://github.com/visionmedia/bytes.js/actions?query=workflow%3Aci
|
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/visionmedia/bytes.js/master
|
||||||
|
[coveralls-url]: https://coveralls.io/r/visionmedia/bytes.js?branch=master
|
||||||
|
[downloads-image]: https://badgen.net/npm/dm/bytes
|
||||||
|
[downloads-url]: https://npmjs.org/package/bytes
|
||||||
|
[npm-image]: https://badgen.net/npm/v/bytes
|
||||||
|
[npm-url]: https://npmjs.org/package/bytes
|
||||||
170
server/node_modules/bytes/index.js
generated
vendored
Normal file
170
server/node_modules/bytes/index.js
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/*!
|
||||||
|
* bytes
|
||||||
|
* Copyright(c) 2012-2014 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2015 Jed Watson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = bytes;
|
||||||
|
module.exports.format = format;
|
||||||
|
module.exports.parse = parse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module variables.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
|
||||||
|
|
||||||
|
var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
|
||||||
|
|
||||||
|
var map = {
|
||||||
|
b: 1,
|
||||||
|
kb: 1 << 10,
|
||||||
|
mb: 1 << 20,
|
||||||
|
gb: 1 << 30,
|
||||||
|
tb: Math.pow(1024, 4),
|
||||||
|
pb: Math.pow(1024, 5),
|
||||||
|
};
|
||||||
|
|
||||||
|
var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value in bytes into a string or parse to string to an integer in bytes.
|
||||||
|
*
|
||||||
|
* @param {string|number} value
|
||||||
|
* @param {{
|
||||||
|
* case: [string],
|
||||||
|
* decimalPlaces: [number]
|
||||||
|
* fixedDecimals: [boolean]
|
||||||
|
* thousandsSeparator: [string]
|
||||||
|
* unitSeparator: [string]
|
||||||
|
* }} [options] bytes options.
|
||||||
|
*
|
||||||
|
* @returns {string|number|null}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function bytes(value, options) {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return parse(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return format(value, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the given value in bytes into a string.
|
||||||
|
*
|
||||||
|
* If the value is negative, it is kept as such. If it is a float,
|
||||||
|
* it is rounded.
|
||||||
|
*
|
||||||
|
* @param {number} value
|
||||||
|
* @param {object} [options]
|
||||||
|
* @param {number} [options.decimalPlaces=2]
|
||||||
|
* @param {number} [options.fixedDecimals=false]
|
||||||
|
* @param {string} [options.thousandsSeparator=]
|
||||||
|
* @param {string} [options.unit=]
|
||||||
|
* @param {string} [options.unitSeparator=]
|
||||||
|
*
|
||||||
|
* @returns {string|null}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function format(value, options) {
|
||||||
|
if (!Number.isFinite(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mag = Math.abs(value);
|
||||||
|
var thousandsSeparator = (options && options.thousandsSeparator) || '';
|
||||||
|
var unitSeparator = (options && options.unitSeparator) || '';
|
||||||
|
var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2;
|
||||||
|
var fixedDecimals = Boolean(options && options.fixedDecimals);
|
||||||
|
var unit = (options && options.unit) || '';
|
||||||
|
|
||||||
|
if (!unit || !map[unit.toLowerCase()]) {
|
||||||
|
if (mag >= map.pb) {
|
||||||
|
unit = 'PB';
|
||||||
|
} else if (mag >= map.tb) {
|
||||||
|
unit = 'TB';
|
||||||
|
} else if (mag >= map.gb) {
|
||||||
|
unit = 'GB';
|
||||||
|
} else if (mag >= map.mb) {
|
||||||
|
unit = 'MB';
|
||||||
|
} else if (mag >= map.kb) {
|
||||||
|
unit = 'KB';
|
||||||
|
} else {
|
||||||
|
unit = 'B';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var val = value / map[unit.toLowerCase()];
|
||||||
|
var str = val.toFixed(decimalPlaces);
|
||||||
|
|
||||||
|
if (!fixedDecimals) {
|
||||||
|
str = str.replace(formatDecimalsRegExp, '$1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thousandsSeparator) {
|
||||||
|
str = str.split('.').map(function (s, i) {
|
||||||
|
return i === 0
|
||||||
|
? s.replace(formatThousandsRegExp, thousandsSeparator)
|
||||||
|
: s
|
||||||
|
}).join('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return str + unitSeparator + unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the string value into an integer in bytes.
|
||||||
|
*
|
||||||
|
* If no unit is given, it is assumed the value is in bytes.
|
||||||
|
*
|
||||||
|
* @param {number|string} val
|
||||||
|
*
|
||||||
|
* @returns {number|null}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function parse(val) {
|
||||||
|
if (typeof val === 'number' && !isNaN(val)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof val !== 'string') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if the string passed is valid
|
||||||
|
var results = parseRegExp.exec(val);
|
||||||
|
var floatValue;
|
||||||
|
var unit = 'b';
|
||||||
|
|
||||||
|
if (!results) {
|
||||||
|
// Nothing could be extracted from the given string
|
||||||
|
floatValue = parseInt(val, 10);
|
||||||
|
unit = 'b'
|
||||||
|
} else {
|
||||||
|
// Retrieve the value and the unit
|
||||||
|
floatValue = parseFloat(results[1]);
|
||||||
|
unit = results[4].toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(floatValue)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.floor(map[unit] * floatValue);
|
||||||
|
}
|
||||||
42
server/node_modules/bytes/package.json
generated
vendored
Normal file
42
server/node_modules/bytes/package.json
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "bytes",
|
||||||
|
"description": "Utility to parse a string bytes to bytes and vice-versa",
|
||||||
|
"version": "3.1.2",
|
||||||
|
"author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
|
||||||
|
"contributors": [
|
||||||
|
"Jed Watson <jed.watson@me.com>",
|
||||||
|
"Théo FIDRY <theo.fidry@gmail.com>"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"byte",
|
||||||
|
"bytes",
|
||||||
|
"utility",
|
||||||
|
"parse",
|
||||||
|
"parser",
|
||||||
|
"convert",
|
||||||
|
"converter"
|
||||||
|
],
|
||||||
|
"repository": "visionmedia/bytes.js",
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "7.32.0",
|
||||||
|
"eslint-plugin-markdown": "2.2.1",
|
||||||
|
"mocha": "9.2.0",
|
||||||
|
"nyc": "15.1.0"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"History.md",
|
||||||
|
"LICENSE",
|
||||||
|
"Readme.md",
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"test": "mocha --check-leaks --reporter spec",
|
||||||
|
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
server/node_modules/call-bind-apply-helpers/.eslintrc
generated
vendored
Normal file
17
server/node_modules/call-bind-apply-helpers/.eslintrc
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
|
||||||
|
"extends": "@ljharb",
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
"func-name-matching": 0,
|
||||||
|
"id-length": 0,
|
||||||
|
"new-cap": [2, {
|
||||||
|
"capIsNewExceptions": [
|
||||||
|
"GetIntrinsic",
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
"no-extra-parens": 0,
|
||||||
|
"no-magic-numbers": 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
12
server/node_modules/call-bind-apply-helpers/.github/FUNDING.yml
generated
vendored
Normal file
12
server/node_modules/call-bind-apply-helpers/.github/FUNDING.yml
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [ljharb]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: npm/call-bind-apply-helpers
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
9
server/node_modules/call-bind-apply-helpers/.nycrc
generated
vendored
Normal file
9
server/node_modules/call-bind-apply-helpers/.nycrc
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"all": true,
|
||||||
|
"check-coverage": false,
|
||||||
|
"reporter": ["text-summary", "text", "html", "json"],
|
||||||
|
"exclude": [
|
||||||
|
"coverage",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
}
|
||||||
30
server/node_modules/call-bind-apply-helpers/CHANGELOG.md
generated
vendored
Normal file
30
server/node_modules/call-bind-apply-helpers/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [v1.0.2](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.1...v1.0.2) - 2025-02-12
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [types] improve inferred types [`e6f9586`](https://github.com/ljharb/call-bind-apply-helpers/commit/e6f95860a3c72879cb861a858cdfb8138fbedec1)
|
||||||
|
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`e43d540`](https://github.com/ljharb/call-bind-apply-helpers/commit/e43d5409f97543bfbb11f345d47d8ce4e066d8c1)
|
||||||
|
|
||||||
|
## [v1.0.1](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.0...v1.0.1) - 2024-12-08
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [types] `reflectApply`: fix types [`4efc396`](https://github.com/ljharb/call-bind-apply-helpers/commit/4efc3965351a4f02cc55e836fa391d3d11ef2ef8)
|
||||||
|
- [Fix] `reflectApply`: oops, Reflect is not a function [`83cc739`](https://github.com/ljharb/call-bind-apply-helpers/commit/83cc7395de6b79b7730bdf092f1436f0b1263c75)
|
||||||
|
- [Dev Deps] update `@arethetypeswrong/cli` [`80bd5d3`](https://github.com/ljharb/call-bind-apply-helpers/commit/80bd5d3ae58b4f6b6995ce439dd5a1bcb178a940)
|
||||||
|
|
||||||
|
## v1.0.0 - 2024-12-05
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- Initial implementation, tests, readme [`7879629`](https://github.com/ljharb/call-bind-apply-helpers/commit/78796290f9b7430c9934d6f33d94ae9bc89fce04)
|
||||||
|
- Initial commit [`3f1dc16`](https://github.com/ljharb/call-bind-apply-helpers/commit/3f1dc164afc43285631b114a5f9dd9137b2b952f)
|
||||||
|
- npm init [`081df04`](https://github.com/ljharb/call-bind-apply-helpers/commit/081df048c312fcee400922026f6e97281200a603)
|
||||||
|
- Only apps should have lockfiles [`5b9ca0f`](https://github.com/ljharb/call-bind-apply-helpers/commit/5b9ca0fe8101ebfaf309c549caac4e0a017ed930)
|
||||||
21
server/node_modules/call-bind-apply-helpers/LICENSE
generated
vendored
Normal file
21
server/node_modules/call-bind-apply-helpers/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Jordan Harband
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
62
server/node_modules/call-bind-apply-helpers/README.md
generated
vendored
Normal file
62
server/node_modules/call-bind-apply-helpers/README.md
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# call-bind-apply-helpers <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
|
||||||
|
|
||||||
|
[![github actions][actions-image]][actions-url]
|
||||||
|
[![coverage][codecov-image]][codecov-url]
|
||||||
|
[![dependency status][deps-svg]][deps-url]
|
||||||
|
[![dev dependency status][dev-deps-svg]][dev-deps-url]
|
||||||
|
[![License][license-image]][license-url]
|
||||||
|
[![Downloads][downloads-image]][downloads-url]
|
||||||
|
|
||||||
|
[![npm badge][npm-badge-png]][package-url]
|
||||||
|
|
||||||
|
Helper functions around Function call/apply/bind, for use in `call-bind`.
|
||||||
|
|
||||||
|
The only packages that should likely ever use this package directly are `call-bind` and `get-intrinsic`.
|
||||||
|
Please use `call-bind` unless you have a very good reason not to.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save call-bind-apply-helpers
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage/Examples
|
||||||
|
|
||||||
|
```js
|
||||||
|
const assert = require('assert');
|
||||||
|
const callBindBasic = require('call-bind-apply-helpers');
|
||||||
|
|
||||||
|
function f(a, b) {
|
||||||
|
assert.equal(this, 1);
|
||||||
|
assert.equal(a, 2);
|
||||||
|
assert.equal(b, 3);
|
||||||
|
assert.equal(arguments.length, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fBound = callBindBasic([f, 1]);
|
||||||
|
|
||||||
|
delete Function.prototype.call;
|
||||||
|
delete Function.prototype.bind;
|
||||||
|
|
||||||
|
fBound(2, 3);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Clone the repo, `npm install`, and run `npm test`
|
||||||
|
|
||||||
|
[package-url]: https://npmjs.org/package/call-bind-apply-helpers
|
||||||
|
[npm-version-svg]: https://versionbadg.es/ljharb/call-bind-apply-helpers.svg
|
||||||
|
[deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers.svg
|
||||||
|
[deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers
|
||||||
|
[dev-deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers/dev-status.svg
|
||||||
|
[dev-deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers#info=devDependencies
|
||||||
|
[npm-badge-png]: https://nodei.co/npm/call-bind-apply-helpers.png?downloads=true&stars=true
|
||||||
|
[license-image]: https://img.shields.io/npm/l/call-bind-apply-helpers.svg
|
||||||
|
[license-url]: LICENSE
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/call-bind-apply-helpers.svg
|
||||||
|
[downloads-url]: https://npm-stat.com/charts.html?package=call-bind-apply-helpers
|
||||||
|
[codecov-image]: https://codecov.io/gh/ljharb/call-bind-apply-helpers/branch/main/graphs/badge.svg
|
||||||
|
[codecov-url]: https://app.codecov.io/gh/ljharb/call-bind-apply-helpers/
|
||||||
|
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bind-apply-helpers
|
||||||
|
[actions-url]: https://github.com/ljharb/call-bind-apply-helpers/actions
|
||||||
1
server/node_modules/call-bind-apply-helpers/actualApply.d.ts
generated
vendored
Normal file
1
server/node_modules/call-bind-apply-helpers/actualApply.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export = Reflect.apply;
|
||||||
10
server/node_modules/call-bind-apply-helpers/actualApply.js
generated
vendored
Normal file
10
server/node_modules/call-bind-apply-helpers/actualApply.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bind = require('function-bind');
|
||||||
|
|
||||||
|
var $apply = require('./functionApply');
|
||||||
|
var $call = require('./functionCall');
|
||||||
|
var $reflectApply = require('./reflectApply');
|
||||||
|
|
||||||
|
/** @type {import('./actualApply')} */
|
||||||
|
module.exports = $reflectApply || bind.call($call, $apply);
|
||||||
19
server/node_modules/call-bind-apply-helpers/applyBind.d.ts
generated
vendored
Normal file
19
server/node_modules/call-bind-apply-helpers/applyBind.d.ts
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import actualApply from './actualApply';
|
||||||
|
|
||||||
|
type TupleSplitHead<T extends any[], N extends number> = T['length'] extends N
|
||||||
|
? T
|
||||||
|
: T extends [...infer R, any]
|
||||||
|
? TupleSplitHead<R, N>
|
||||||
|
: never
|
||||||
|
|
||||||
|
type TupleSplitTail<T, N extends number, O extends any[] = []> = O['length'] extends N
|
||||||
|
? T
|
||||||
|
: T extends [infer F, ...infer R]
|
||||||
|
? TupleSplitTail<[...R], N, [...O, F]>
|
||||||
|
: never
|
||||||
|
|
||||||
|
type TupleSplit<T extends any[], N extends number> = [TupleSplitHead<T, N>, TupleSplitTail<T, N>]
|
||||||
|
|
||||||
|
declare function applyBind(...args: TupleSplit<Parameters<typeof actualApply>, 2>[1]): ReturnType<typeof actualApply>;
|
||||||
|
|
||||||
|
export = applyBind;
|
||||||
10
server/node_modules/call-bind-apply-helpers/applyBind.js
generated
vendored
Normal file
10
server/node_modules/call-bind-apply-helpers/applyBind.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bind = require('function-bind');
|
||||||
|
var $apply = require('./functionApply');
|
||||||
|
var actualApply = require('./actualApply');
|
||||||
|
|
||||||
|
/** @type {import('./applyBind')} */
|
||||||
|
module.exports = function applyBind() {
|
||||||
|
return actualApply(bind, $apply, arguments);
|
||||||
|
};
|
||||||
1
server/node_modules/call-bind-apply-helpers/functionApply.d.ts
generated
vendored
Normal file
1
server/node_modules/call-bind-apply-helpers/functionApply.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export = Function.prototype.apply;
|
||||||
4
server/node_modules/call-bind-apply-helpers/functionApply.js
generated
vendored
Normal file
4
server/node_modules/call-bind-apply-helpers/functionApply.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** @type {import('./functionApply')} */
|
||||||
|
module.exports = Function.prototype.apply;
|
||||||
1
server/node_modules/call-bind-apply-helpers/functionCall.d.ts
generated
vendored
Normal file
1
server/node_modules/call-bind-apply-helpers/functionCall.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export = Function.prototype.call;
|
||||||
4
server/node_modules/call-bind-apply-helpers/functionCall.js
generated
vendored
Normal file
4
server/node_modules/call-bind-apply-helpers/functionCall.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** @type {import('./functionCall')} */
|
||||||
|
module.exports = Function.prototype.call;
|
||||||
64
server/node_modules/call-bind-apply-helpers/index.d.ts
generated
vendored
Normal file
64
server/node_modules/call-bind-apply-helpers/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
type RemoveFromTuple<
|
||||||
|
Tuple extends readonly unknown[],
|
||||||
|
RemoveCount extends number,
|
||||||
|
Index extends 1[] = []
|
||||||
|
> = Index["length"] extends RemoveCount
|
||||||
|
? Tuple
|
||||||
|
: Tuple extends [infer First, ...infer Rest]
|
||||||
|
? RemoveFromTuple<Rest, RemoveCount, [...Index, 1]>
|
||||||
|
: Tuple;
|
||||||
|
|
||||||
|
type ConcatTuples<
|
||||||
|
Prefix extends readonly unknown[],
|
||||||
|
Suffix extends readonly unknown[]
|
||||||
|
> = [...Prefix, ...Suffix];
|
||||||
|
|
||||||
|
type ExtractFunctionParams<T> = T extends (this: infer TThis, ...args: infer P extends readonly unknown[]) => infer R
|
||||||
|
? { thisArg: TThis; params: P; returnType: R }
|
||||||
|
: never;
|
||||||
|
|
||||||
|
type BindFunction<
|
||||||
|
T extends (this: any, ...args: any[]) => any,
|
||||||
|
TThis,
|
||||||
|
TBoundArgs extends readonly unknown[],
|
||||||
|
ReceiverBound extends boolean
|
||||||
|
> = ExtractFunctionParams<T> extends {
|
||||||
|
thisArg: infer OrigThis;
|
||||||
|
params: infer P extends readonly unknown[];
|
||||||
|
returnType: infer R;
|
||||||
|
}
|
||||||
|
? ReceiverBound extends true
|
||||||
|
? (...args: RemoveFromTuple<P, Extract<TBoundArgs["length"], number>>) => R extends [OrigThis, ...infer Rest]
|
||||||
|
? [TThis, ...Rest] // Replace `this` with `thisArg`
|
||||||
|
: R
|
||||||
|
: <U, RemainingArgs extends RemoveFromTuple<P, Extract<TBoundArgs["length"], number>>>(
|
||||||
|
thisArg: U,
|
||||||
|
...args: RemainingArgs
|
||||||
|
) => R extends [OrigThis, ...infer Rest]
|
||||||
|
? [U, ...ConcatTuples<TBoundArgs, Rest>] // Preserve bound args in return type
|
||||||
|
: R
|
||||||
|
: never;
|
||||||
|
|
||||||
|
declare function callBind<
|
||||||
|
const T extends (this: any, ...args: any[]) => any,
|
||||||
|
Extracted extends ExtractFunctionParams<T>,
|
||||||
|
const TBoundArgs extends Partial<Extracted["params"]> & readonly unknown[],
|
||||||
|
const TThis extends Extracted["thisArg"]
|
||||||
|
>(
|
||||||
|
args: [fn: T, thisArg: TThis, ...boundArgs: TBoundArgs]
|
||||||
|
): BindFunction<T, TThis, TBoundArgs, true>;
|
||||||
|
|
||||||
|
declare function callBind<
|
||||||
|
const T extends (this: any, ...args: any[]) => any,
|
||||||
|
Extracted extends ExtractFunctionParams<T>,
|
||||||
|
const TBoundArgs extends Partial<Extracted["params"]> & readonly unknown[]
|
||||||
|
>(
|
||||||
|
args: [fn: T, ...boundArgs: TBoundArgs]
|
||||||
|
): BindFunction<T, Extracted["thisArg"], TBoundArgs, false>;
|
||||||
|
|
||||||
|
declare function callBind<const TArgs extends readonly unknown[]>(
|
||||||
|
args: [fn: Exclude<TArgs[0], Function>, ...rest: TArgs]
|
||||||
|
): never;
|
||||||
|
|
||||||
|
// export as namespace callBind;
|
||||||
|
export = callBind;
|
||||||
15
server/node_modules/call-bind-apply-helpers/index.js
generated
vendored
Normal file
15
server/node_modules/call-bind-apply-helpers/index.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bind = require('function-bind');
|
||||||
|
var $TypeError = require('es-errors/type');
|
||||||
|
|
||||||
|
var $call = require('./functionCall');
|
||||||
|
var $actualApply = require('./actualApply');
|
||||||
|
|
||||||
|
/** @type {(args: [Function, thisArg?: unknown, ...args: unknown[]]) => Function} TODO FIXME, find a way to use import('.') */
|
||||||
|
module.exports = function callBindBasic(args) {
|
||||||
|
if (args.length < 1 || typeof args[0] !== 'function') {
|
||||||
|
throw new $TypeError('a function is required');
|
||||||
|
}
|
||||||
|
return $actualApply(bind, $call, args);
|
||||||
|
};
|
||||||
85
server/node_modules/call-bind-apply-helpers/package.json
generated
vendored
Normal file
85
server/node_modules/call-bind-apply-helpers/package.json
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"name": "call-bind-apply-helpers",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"description": "Helper functions around Function call/apply/bind, for use in `call-bind`",
|
||||||
|
"main": "index.js",
|
||||||
|
"exports": {
|
||||||
|
".": "./index.js",
|
||||||
|
"./actualApply": "./actualApply.js",
|
||||||
|
"./applyBind": "./applyBind.js",
|
||||||
|
"./functionApply": "./functionApply.js",
|
||||||
|
"./functionCall": "./functionCall.js",
|
||||||
|
"./reflectApply": "./reflectApply.js",
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"prepack": "npmignore --auto --commentLines=auto",
|
||||||
|
"prepublish": "not-in-publish || npm run prepublishOnly",
|
||||||
|
"prepublishOnly": "safe-publish-latest",
|
||||||
|
"prelint": "evalmd README.md",
|
||||||
|
"lint": "eslint --ext=.js,.mjs .",
|
||||||
|
"postlint": "tsc -p . && attw -P",
|
||||||
|
"pretest": "npm run lint",
|
||||||
|
"tests-only": "nyc tape 'test/**/*.js'",
|
||||||
|
"test": "npm run tests-only",
|
||||||
|
"posttest": "npx npm@'>=10.2' audit --production",
|
||||||
|
"version": "auto-changelog && git add CHANGELOG.md",
|
||||||
|
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/ljharb/call-bind-apply-helpers.git"
|
||||||
|
},
|
||||||
|
"author": "Jordan Harband <ljharb@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/ljharb/call-bind-apply-helpers/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/ljharb/call-bind-apply-helpers#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@arethetypeswrong/cli": "^0.17.3",
|
||||||
|
"@ljharb/eslint-config": "^21.1.1",
|
||||||
|
"@ljharb/tsconfig": "^0.2.3",
|
||||||
|
"@types/for-each": "^0.3.3",
|
||||||
|
"@types/function-bind": "^1.1.10",
|
||||||
|
"@types/object-inspect": "^1.13.0",
|
||||||
|
"@types/tape": "^5.8.1",
|
||||||
|
"auto-changelog": "^2.5.0",
|
||||||
|
"encoding": "^0.1.13",
|
||||||
|
"es-value-fixtures": "^1.7.1",
|
||||||
|
"eslint": "=8.8.0",
|
||||||
|
"evalmd": "^0.0.19",
|
||||||
|
"for-each": "^0.3.5",
|
||||||
|
"has-strict-mode": "^1.1.0",
|
||||||
|
"in-publish": "^2.0.1",
|
||||||
|
"npmignore": "^0.3.1",
|
||||||
|
"nyc": "^10.3.2",
|
||||||
|
"object-inspect": "^1.13.4",
|
||||||
|
"safe-publish-latest": "^2.0.0",
|
||||||
|
"tape": "^5.9.0",
|
||||||
|
"typescript": "next"
|
||||||
|
},
|
||||||
|
"testling": {
|
||||||
|
"files": "test/index.js"
|
||||||
|
},
|
||||||
|
"auto-changelog": {
|
||||||
|
"output": "CHANGELOG.md",
|
||||||
|
"template": "keepachangelog",
|
||||||
|
"unreleased": false,
|
||||||
|
"commitLimit": false,
|
||||||
|
"backfillLimit": false,
|
||||||
|
"hideCredit": true
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"ignore": [
|
||||||
|
".github/workflows"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
server/node_modules/call-bind-apply-helpers/reflectApply.d.ts
generated
vendored
Normal file
3
server/node_modules/call-bind-apply-helpers/reflectApply.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
declare const reflectApply: false | typeof Reflect.apply;
|
||||||
|
|
||||||
|
export = reflectApply;
|
||||||
4
server/node_modules/call-bind-apply-helpers/reflectApply.js
generated
vendored
Normal file
4
server/node_modules/call-bind-apply-helpers/reflectApply.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** @type {import('./reflectApply')} */
|
||||||
|
module.exports = typeof Reflect !== 'undefined' && Reflect && Reflect.apply;
|
||||||
63
server/node_modules/call-bind-apply-helpers/test/index.js
generated
vendored
Normal file
63
server/node_modules/call-bind-apply-helpers/test/index.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var callBind = require('../');
|
||||||
|
var hasStrictMode = require('has-strict-mode')();
|
||||||
|
var forEach = require('for-each');
|
||||||
|
var inspect = require('object-inspect');
|
||||||
|
var v = require('es-value-fixtures');
|
||||||
|
|
||||||
|
var test = require('tape');
|
||||||
|
|
||||||
|
test('callBindBasic', function (t) {
|
||||||
|
forEach(v.nonFunctions, function (nonFunction) {
|
||||||
|
t['throws'](
|
||||||
|
// @ts-expect-error
|
||||||
|
function () { callBind([nonFunction]); },
|
||||||
|
TypeError,
|
||||||
|
inspect(nonFunction) + ' is not a function'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
var sentinel = { sentinel: true };
|
||||||
|
/** @type {<T, A extends number, B extends number>(this: T, a: A, b: B) => [T | undefined, A, B]} */
|
||||||
|
var func = function (a, b) {
|
||||||
|
// eslint-disable-next-line no-invalid-this
|
||||||
|
return [!hasStrictMode && this === global ? undefined : this, a, b];
|
||||||
|
};
|
||||||
|
t.equal(func.length, 2, 'original function length is 2');
|
||||||
|
|
||||||
|
/** type {(thisArg: unknown, a: number, b: number) => [unknown, number, number]} */
|
||||||
|
var bound = callBind([func]);
|
||||||
|
/** type {((a: number, b: number) => [typeof sentinel, typeof a, typeof b])} */
|
||||||
|
var boundR = callBind([func, sentinel]);
|
||||||
|
/** type {((b: number) => [typeof sentinel, number, typeof b])} */
|
||||||
|
var boundArg = callBind([func, sentinel, /** @type {const} */ (1)]);
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with no args');
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(bound(1, 2), [hasStrictMode ? 1 : Object(1), 2, undefined], 'bound func too few args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args');
|
||||||
|
|
||||||
|
t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args');
|
||||||
|
t.deepEqual(bound(1, 2, 3), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with right args');
|
||||||
|
t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args');
|
||||||
|
t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg');
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(bound(1, 2, 3, 4), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with too many args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args');
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
9
server/node_modules/call-bind-apply-helpers/tsconfig.json
generated
vendored
Normal file
9
server/node_modules/call-bind-apply-helpers/tsconfig.json
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "@ljharb/tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2021",
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"coverage",
|
||||||
|
],
|
||||||
|
}
|
||||||
13
server/node_modules/call-bound/.eslintrc
generated
vendored
Normal file
13
server/node_modules/call-bound/.eslintrc
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
|
||||||
|
"extends": "@ljharb",
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
"new-cap": [2, {
|
||||||
|
"capIsNewExceptions": [
|
||||||
|
"GetIntrinsic",
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
}
|
||||||
12
server/node_modules/call-bound/.github/FUNDING.yml
generated
vendored
Normal file
12
server/node_modules/call-bound/.github/FUNDING.yml
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [ljharb]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: npm/call-bound
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
9
server/node_modules/call-bound/.nycrc
generated
vendored
Normal file
9
server/node_modules/call-bound/.nycrc
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"all": true,
|
||||||
|
"check-coverage": false,
|
||||||
|
"reporter": ["text-summary", "text", "html", "json"],
|
||||||
|
"exclude": [
|
||||||
|
"coverage",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
}
|
||||||
42
server/node_modules/call-bound/CHANGELOG.md
generated
vendored
Normal file
42
server/node_modules/call-bound/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [v1.0.4](https://github.com/ljharb/call-bound/compare/v1.0.3...v1.0.4) - 2025-03-03
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [types] improve types [`e648922`](https://github.com/ljharb/call-bound/commit/e6489222a9e54f350fbf952ceabe51fd8b6027ff)
|
||||||
|
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`a42a5eb`](https://github.com/ljharb/call-bound/commit/a42a5ebe6c1b54fcdc7997c7dc64fdca9e936719)
|
||||||
|
- [Deps] update `call-bind-apply-helpers`, `get-intrinsic` [`f529eac`](https://github.com/ljharb/call-bound/commit/f529eac132404c17156bbc23ab2297a25d0f20b8)
|
||||||
|
|
||||||
|
## [v1.0.3](https://github.com/ljharb/call-bound/compare/v1.0.2...v1.0.3) - 2024-12-15
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [Refactor] use `call-bind-apply-helpers` instead of `call-bind` [`5e0b134`](https://github.com/ljharb/call-bound/commit/5e0b13496df14fb7d05dae9412f088da8d3f75be)
|
||||||
|
- [Deps] update `get-intrinsic` [`41fc967`](https://github.com/ljharb/call-bound/commit/41fc96732a22c7b7e8f381f93ccc54bb6293be2e)
|
||||||
|
- [readme] fix example [`79a0137`](https://github.com/ljharb/call-bound/commit/79a0137723f7c6d09c9c05452bbf8d5efb5d6e49)
|
||||||
|
- [meta] add `sideEffects` flag [`08b07be`](https://github.com/ljharb/call-bound/commit/08b07be7f1c03f67dc6f3cdaf0906259771859f7)
|
||||||
|
|
||||||
|
## [v1.0.2](https://github.com/ljharb/call-bound/compare/v1.0.1...v1.0.2) - 2024-12-10
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `gopd` [`e6a5ffe`](https://github.com/ljharb/call-bound/commit/e6a5ffe849368fe4f74dfd6cdeca1b9baa39e8d5)
|
||||||
|
- [Deps] update `call-bind`, `get-intrinsic` [`2aeb5b5`](https://github.com/ljharb/call-bound/commit/2aeb5b521dc2b2683d1345c753ea1161de2d1c14)
|
||||||
|
- [types] improve return type [`1a0c9fe`](https://github.com/ljharb/call-bound/commit/1a0c9fe3114471e7ca1f57d104e2efe713bb4871)
|
||||||
|
|
||||||
|
## v1.0.1 - 2024-12-05
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- Initial implementation, tests, readme, types [`6d94121`](https://github.com/ljharb/call-bound/commit/6d94121a9243602e506334069f7a03189fe3363d)
|
||||||
|
- Initial commit [`0eae867`](https://github.com/ljharb/call-bound/commit/0eae867334ea025c33e6e91cdecfc9df96680cf9)
|
||||||
|
- npm init [`71b2479`](https://github.com/ljharb/call-bound/commit/71b2479c6723e0b7d91a6b663613067e98b7b275)
|
||||||
|
- Only apps should have lockfiles [`c3754a9`](https://github.com/ljharb/call-bound/commit/c3754a949b7f9132b47e2d18c1729889736741eb)
|
||||||
|
- [actions] skip `npm ls` in node < 10 [`74275a5`](https://github.com/ljharb/call-bound/commit/74275a5186b8caf6309b6b97472bdcb0df4683a8)
|
||||||
|
- [Dev Deps] add missing peer dep [`1354de8`](https://github.com/ljharb/call-bound/commit/1354de8679413e4ae9c523d85f76fa7a5e032d97)
|
||||||
21
server/node_modules/call-bound/LICENSE
generated
vendored
Normal file
21
server/node_modules/call-bound/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Jordan Harband
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
53
server/node_modules/call-bound/README.md
generated
vendored
Normal file
53
server/node_modules/call-bound/README.md
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# call-bound <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
|
||||||
|
|
||||||
|
[![github actions][actions-image]][actions-url]
|
||||||
|
[![coverage][codecov-image]][codecov-url]
|
||||||
|
[![dependency status][deps-svg]][deps-url]
|
||||||
|
[![dev dependency status][dev-deps-svg]][dev-deps-url]
|
||||||
|
[![License][license-image]][license-url]
|
||||||
|
[![Downloads][downloads-image]][downloads-url]
|
||||||
|
|
||||||
|
[![npm badge][npm-badge-png]][package-url]
|
||||||
|
|
||||||
|
Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save call-bound
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage/Examples
|
||||||
|
|
||||||
|
```js
|
||||||
|
const assert = require('assert');
|
||||||
|
const callBound = require('call-bound');
|
||||||
|
|
||||||
|
const slice = callBound('Array.prototype.slice');
|
||||||
|
|
||||||
|
delete Function.prototype.call;
|
||||||
|
delete Function.prototype.bind;
|
||||||
|
delete Array.prototype.slice;
|
||||||
|
|
||||||
|
assert.deepEqual(slice([1, 2, 3, 4], 1, -1), [2, 3]);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Clone the repo, `npm install`, and run `npm test`
|
||||||
|
|
||||||
|
[package-url]: https://npmjs.org/package/call-bound
|
||||||
|
[npm-version-svg]: https://versionbadg.es/ljharb/call-bound.svg
|
||||||
|
[deps-svg]: https://david-dm.org/ljharb/call-bound.svg
|
||||||
|
[deps-url]: https://david-dm.org/ljharb/call-bound
|
||||||
|
[dev-deps-svg]: https://david-dm.org/ljharb/call-bound/dev-status.svg
|
||||||
|
[dev-deps-url]: https://david-dm.org/ljharb/call-bound#info=devDependencies
|
||||||
|
[npm-badge-png]: https://nodei.co/npm/call-bound.png?downloads=true&stars=true
|
||||||
|
[license-image]: https://img.shields.io/npm/l/call-bound.svg
|
||||||
|
[license-url]: LICENSE
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/call-bound.svg
|
||||||
|
[downloads-url]: https://npm-stat.com/charts.html?package=call-bound
|
||||||
|
[codecov-image]: https://codecov.io/gh/ljharb/call-bound/branch/main/graphs/badge.svg
|
||||||
|
[codecov-url]: https://app.codecov.io/gh/ljharb/call-bound/
|
||||||
|
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bound
|
||||||
|
[actions-url]: https://github.com/ljharb/call-bound/actions
|
||||||
94
server/node_modules/call-bound/index.d.ts
generated
vendored
Normal file
94
server/node_modules/call-bound/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
type Intrinsic = typeof globalThis;
|
||||||
|
|
||||||
|
type IntrinsicName = keyof Intrinsic | `%${keyof Intrinsic}%`;
|
||||||
|
|
||||||
|
type IntrinsicPath = IntrinsicName | `${StripPercents<IntrinsicName>}.${string}` | `%${StripPercents<IntrinsicName>}.${string}%`;
|
||||||
|
|
||||||
|
type AllowMissing = boolean;
|
||||||
|
|
||||||
|
type StripPercents<T extends string> = T extends `%${infer U}%` ? U : T;
|
||||||
|
|
||||||
|
type BindMethodPrecise<F> =
|
||||||
|
F extends (this: infer This, ...args: infer Args) => infer R
|
||||||
|
? (obj: This, ...args: Args) => R
|
||||||
|
: F extends {
|
||||||
|
(this: infer This1, ...args: infer Args1): infer R1;
|
||||||
|
(this: infer This2, ...args: infer Args2): infer R2
|
||||||
|
}
|
||||||
|
? {
|
||||||
|
(obj: This1, ...args: Args1): R1;
|
||||||
|
(obj: This2, ...args: Args2): R2
|
||||||
|
}
|
||||||
|
: never
|
||||||
|
|
||||||
|
// Extract method type from a prototype
|
||||||
|
type GetPrototypeMethod<T extends keyof typeof globalThis, M extends string> =
|
||||||
|
(typeof globalThis)[T] extends { prototype: any }
|
||||||
|
? M extends keyof (typeof globalThis)[T]['prototype']
|
||||||
|
? (typeof globalThis)[T]['prototype'][M]
|
||||||
|
: never
|
||||||
|
: never
|
||||||
|
|
||||||
|
// Get static property/method
|
||||||
|
type GetStaticMember<T extends keyof typeof globalThis, P extends string> =
|
||||||
|
P extends keyof (typeof globalThis)[T] ? (typeof globalThis)[T][P] : never
|
||||||
|
|
||||||
|
// Type that maps string path to actual bound function or value with better precision
|
||||||
|
type BoundIntrinsic<S extends string> =
|
||||||
|
S extends `${infer Obj}.prototype.${infer Method}`
|
||||||
|
? Obj extends keyof typeof globalThis
|
||||||
|
? BindMethodPrecise<GetPrototypeMethod<Obj, Method & string>>
|
||||||
|
: unknown
|
||||||
|
: S extends `${infer Obj}.${infer Prop}`
|
||||||
|
? Obj extends keyof typeof globalThis
|
||||||
|
? GetStaticMember<Obj, Prop & string>
|
||||||
|
: unknown
|
||||||
|
: unknown
|
||||||
|
|
||||||
|
declare function arraySlice<T>(array: readonly T[], start?: number, end?: number): T[];
|
||||||
|
declare function arraySlice<T>(array: ArrayLike<T>, start?: number, end?: number): T[];
|
||||||
|
declare function arraySlice<T>(array: IArguments, start?: number, end?: number): T[];
|
||||||
|
|
||||||
|
// Special cases for methods that need explicit typing
|
||||||
|
interface SpecialCases {
|
||||||
|
'%Object.prototype.isPrototypeOf%': (thisArg: {}, obj: unknown) => boolean;
|
||||||
|
'%String.prototype.replace%': {
|
||||||
|
(str: string, searchValue: string | RegExp, replaceValue: string): string;
|
||||||
|
(str: string, searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string
|
||||||
|
};
|
||||||
|
'%Object.prototype.toString%': (obj: {}) => string;
|
||||||
|
'%Object.prototype.hasOwnProperty%': (obj: {}, v: PropertyKey) => boolean;
|
||||||
|
'%Array.prototype.slice%': typeof arraySlice;
|
||||||
|
'%Array.prototype.map%': <T, U>(array: readonly T[], callbackfn: (value: T, index: number, array: readonly T[]) => U, thisArg?: any) => U[];
|
||||||
|
'%Array.prototype.filter%': <T>(array: readonly T[], predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any) => T[];
|
||||||
|
'%Array.prototype.indexOf%': <T>(array: readonly T[], searchElement: T, fromIndex?: number) => number;
|
||||||
|
'%Function.prototype.apply%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, args: A) => R;
|
||||||
|
'%Function.prototype.call%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, ...args: A) => R;
|
||||||
|
'%Function.prototype.bind%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, ...args: A) => (...remainingArgs: A) => R;
|
||||||
|
'%Promise.prototype.then%': {
|
||||||
|
<T, R>(promise: Promise<T>, onfulfilled: (value: T) => R | PromiseLike<R>): Promise<R>;
|
||||||
|
<T, R>(promise: Promise<T>, onfulfilled: ((value: T) => R | PromiseLike<R>) | undefined | null, onrejected: (reason: any) => R | PromiseLike<R>): Promise<R>;
|
||||||
|
};
|
||||||
|
'%RegExp.prototype.test%': (regexp: RegExp, str: string) => boolean;
|
||||||
|
'%RegExp.prototype.exec%': (regexp: RegExp, str: string) => RegExpExecArray | null;
|
||||||
|
'%Error.prototype.toString%': (error: Error) => string;
|
||||||
|
'%TypeError.prototype.toString%': (error: TypeError) => string;
|
||||||
|
'%String.prototype.split%': (
|
||||||
|
obj: unknown,
|
||||||
|
splitter: string | RegExp | {
|
||||||
|
[Symbol.split](string: string, limit?: number): string[];
|
||||||
|
},
|
||||||
|
limit?: number | undefined
|
||||||
|
) => string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a bound function for a prototype method, or a value for a static property.
|
||||||
|
*
|
||||||
|
* @param name - The name of the intrinsic (e.g. 'Array.prototype.slice')
|
||||||
|
* @param {AllowMissing} [allowMissing] - Whether to allow missing intrinsics (default: false)
|
||||||
|
*/
|
||||||
|
declare function callBound<K extends keyof SpecialCases | StripPercents<keyof SpecialCases>, S extends IntrinsicPath>(name: K, allowMissing?: AllowMissing): SpecialCases[`%${StripPercents<K>}%`];
|
||||||
|
declare function callBound<K extends keyof SpecialCases | StripPercents<keyof SpecialCases>, S extends IntrinsicPath>(name: S, allowMissing?: AllowMissing): BoundIntrinsic<S>;
|
||||||
|
|
||||||
|
export = callBound;
|
||||||
19
server/node_modules/call-bound/index.js
generated
vendored
Normal file
19
server/node_modules/call-bound/index.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var GetIntrinsic = require('get-intrinsic');
|
||||||
|
|
||||||
|
var callBindBasic = require('call-bind-apply-helpers');
|
||||||
|
|
||||||
|
/** @type {(thisArg: string, searchString: string, position?: number) => number} */
|
||||||
|
var $indexOf = callBindBasic([GetIntrinsic('%String.prototype.indexOf%')]);
|
||||||
|
|
||||||
|
/** @type {import('.')} */
|
||||||
|
module.exports = function callBoundIntrinsic(name, allowMissing) {
|
||||||
|
/* eslint no-extra-parens: 0 */
|
||||||
|
|
||||||
|
var intrinsic = /** @type {(this: unknown, ...args: unknown[]) => unknown} */ (GetIntrinsic(name, !!allowMissing));
|
||||||
|
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
|
||||||
|
return callBindBasic(/** @type {const} */ ([intrinsic]));
|
||||||
|
}
|
||||||
|
return intrinsic;
|
||||||
|
};
|
||||||
99
server/node_modules/call-bound/package.json
generated
vendored
Normal file
99
server/node_modules/call-bound/package.json
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
{
|
||||||
|
"name": "call-bound",
|
||||||
|
"version": "1.0.4",
|
||||||
|
"description": "Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`.",
|
||||||
|
"main": "index.js",
|
||||||
|
"exports": {
|
||||||
|
".": "./index.js",
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"sideEffects": false,
|
||||||
|
"scripts": {
|
||||||
|
"prepack": "npmignore --auto --commentLines=auto",
|
||||||
|
"prepublish": "not-in-publish || npm run prepublishOnly",
|
||||||
|
"prepublishOnly": "safe-publish-latest",
|
||||||
|
"prelint": "evalmd README.md",
|
||||||
|
"lint": "eslint --ext=.js,.mjs .",
|
||||||
|
"postlint": "tsc -p . && attw -P",
|
||||||
|
"pretest": "npm run lint",
|
||||||
|
"tests-only": "nyc tape 'test/**/*.js'",
|
||||||
|
"test": "npm run tests-only",
|
||||||
|
"posttest": "npx npm@'>=10.2' audit --production",
|
||||||
|
"version": "auto-changelog && git add CHANGELOG.md",
|
||||||
|
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/ljharb/call-bound.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"javascript",
|
||||||
|
"ecmascript",
|
||||||
|
"es",
|
||||||
|
"js",
|
||||||
|
"callbind",
|
||||||
|
"callbound",
|
||||||
|
"call",
|
||||||
|
"bind",
|
||||||
|
"bound",
|
||||||
|
"call-bind",
|
||||||
|
"call-bound",
|
||||||
|
"function",
|
||||||
|
"es-abstract"
|
||||||
|
],
|
||||||
|
"author": "Jordan Harband <ljharb@gmail.com>",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/ljharb/call-bound/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/ljharb/call-bound#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"get-intrinsic": "^1.3.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@arethetypeswrong/cli": "^0.17.4",
|
||||||
|
"@ljharb/eslint-config": "^21.1.1",
|
||||||
|
"@ljharb/tsconfig": "^0.3.0",
|
||||||
|
"@types/call-bind": "^1.0.5",
|
||||||
|
"@types/get-intrinsic": "^1.2.3",
|
||||||
|
"@types/tape": "^5.8.1",
|
||||||
|
"auto-changelog": "^2.5.0",
|
||||||
|
"encoding": "^0.1.13",
|
||||||
|
"es-value-fixtures": "^1.7.1",
|
||||||
|
"eslint": "=8.8.0",
|
||||||
|
"evalmd": "^0.0.19",
|
||||||
|
"for-each": "^0.3.5",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-strict-mode": "^1.1.0",
|
||||||
|
"in-publish": "^2.0.1",
|
||||||
|
"npmignore": "^0.3.1",
|
||||||
|
"nyc": "^10.3.2",
|
||||||
|
"object-inspect": "^1.13.4",
|
||||||
|
"safe-publish-latest": "^2.0.0",
|
||||||
|
"tape": "^5.9.0",
|
||||||
|
"typescript": "next"
|
||||||
|
},
|
||||||
|
"testling": {
|
||||||
|
"files": "test/index.js"
|
||||||
|
},
|
||||||
|
"auto-changelog": {
|
||||||
|
"output": "CHANGELOG.md",
|
||||||
|
"template": "keepachangelog",
|
||||||
|
"unreleased": false,
|
||||||
|
"commitLimit": false,
|
||||||
|
"backfillLimit": false,
|
||||||
|
"hideCredit": true
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"ignore": [
|
||||||
|
".github/workflows"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
61
server/node_modules/call-bound/test/index.js
generated
vendored
Normal file
61
server/node_modules/call-bound/test/index.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var test = require('tape');
|
||||||
|
|
||||||
|
var callBound = require('../');
|
||||||
|
|
||||||
|
/** @template {true} T @template U @typedef {T extends U ? T : never} AssertType */
|
||||||
|
|
||||||
|
test('callBound', function (t) {
|
||||||
|
// static primitive
|
||||||
|
t.equal(callBound('Array.length'), Array.length, 'Array.length yields itself');
|
||||||
|
t.equal(callBound('%Array.length%'), Array.length, '%Array.length% yields itself');
|
||||||
|
|
||||||
|
// static non-function object
|
||||||
|
t.equal(callBound('Array.prototype'), Array.prototype, 'Array.prototype yields itself');
|
||||||
|
t.equal(callBound('%Array.prototype%'), Array.prototype, '%Array.prototype% yields itself');
|
||||||
|
t.equal(callBound('Array.constructor'), Array.constructor, 'Array.constructor yields itself');
|
||||||
|
t.equal(callBound('%Array.constructor%'), Array.constructor, '%Array.constructor% yields itself');
|
||||||
|
|
||||||
|
// static function
|
||||||
|
t.equal(callBound('Date.parse'), Date.parse, 'Date.parse yields itself');
|
||||||
|
t.equal(callBound('%Date.parse%'), Date.parse, '%Date.parse% yields itself');
|
||||||
|
|
||||||
|
// prototype primitive
|
||||||
|
t.equal(callBound('Error.prototype.message'), Error.prototype.message, 'Error.prototype.message yields itself');
|
||||||
|
t.equal(callBound('%Error.prototype.message%'), Error.prototype.message, '%Error.prototype.message% yields itself');
|
||||||
|
|
||||||
|
var x = callBound('Object.prototype.toString');
|
||||||
|
var y = callBound('%Object.prototype.toString%');
|
||||||
|
|
||||||
|
// prototype function
|
||||||
|
t.notEqual(x, Object.prototype.toString, 'Object.prototype.toString does not yield itself');
|
||||||
|
t.notEqual(y, Object.prototype.toString, '%Object.prototype.toString% does not yield itself');
|
||||||
|
t.equal(x(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original');
|
||||||
|
t.equal(y(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original');
|
||||||
|
|
||||||
|
t['throws'](
|
||||||
|
// @ts-expect-error
|
||||||
|
function () { callBound('does not exist'); },
|
||||||
|
SyntaxError,
|
||||||
|
'nonexistent intrinsic throws'
|
||||||
|
);
|
||||||
|
t['throws'](
|
||||||
|
// @ts-expect-error
|
||||||
|
function () { callBound('does not exist', true); },
|
||||||
|
SyntaxError,
|
||||||
|
'allowMissing arg still throws for unknown intrinsic'
|
||||||
|
);
|
||||||
|
|
||||||
|
t.test('real but absent intrinsic', { skip: typeof WeakRef !== 'undefined' }, function (st) {
|
||||||
|
st['throws'](
|
||||||
|
function () { callBound('WeakRef'); },
|
||||||
|
TypeError,
|
||||||
|
'real but absent intrinsic throws'
|
||||||
|
);
|
||||||
|
st.equal(callBound('WeakRef', true), undefined, 'allowMissing arg avoids exception');
|
||||||
|
st.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
10
server/node_modules/call-bound/tsconfig.json
generated
vendored
Normal file
10
server/node_modules/call-bound/tsconfig.json
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "@ljharb/tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"lib": ["es2024"],
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"coverage",
|
||||||
|
],
|
||||||
|
}
|
||||||
60
server/node_modules/content-disposition/HISTORY.md
generated
vendored
Normal file
60
server/node_modules/content-disposition/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
0.5.4 / 2021-12-10
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: safe-buffer@5.2.1
|
||||||
|
|
||||||
|
0.5.3 / 2018-12-17
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Use `safe-buffer` for improved Buffer API
|
||||||
|
|
||||||
|
0.5.2 / 2016-12-08
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix `parse` to accept any linear whitespace character
|
||||||
|
|
||||||
|
0.5.1 / 2016-01-17
|
||||||
|
==================
|
||||||
|
|
||||||
|
* perf: enable strict mode
|
||||||
|
|
||||||
|
0.5.0 / 2014-10-11
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add `parse` function
|
||||||
|
|
||||||
|
0.4.0 / 2014-09-21
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Expand non-Unicode `filename` to the full ISO-8859-1 charset
|
||||||
|
|
||||||
|
0.3.0 / 2014-09-20
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add `fallback` option
|
||||||
|
* Add `type` option
|
||||||
|
|
||||||
|
0.2.0 / 2014-09-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Reduce ambiguity of file names with hex escape in buggy browsers
|
||||||
|
|
||||||
|
0.1.2 / 2014-09-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix periodic invalid Unicode filename header
|
||||||
|
|
||||||
|
0.1.1 / 2014-09-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix invalid characters appearing in `filename*` parameter
|
||||||
|
|
||||||
|
0.1.0 / 2014-09-18
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Make the `filename` argument optional
|
||||||
|
|
||||||
|
0.0.0 / 2014-09-18
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Initial release
|
||||||
22
server/node_modules/content-disposition/LICENSE
generated
vendored
Normal file
22
server/node_modules/content-disposition/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014-2017 Douglas Christopher Wilson
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
142
server/node_modules/content-disposition/README.md
generated
vendored
Normal file
142
server/node_modules/content-disposition/README.md
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
# content-disposition
|
||||||
|
|
||||||
|
[![NPM Version][npm-image]][npm-url]
|
||||||
|
[![NPM Downloads][downloads-image]][downloads-url]
|
||||||
|
[![Node.js Version][node-version-image]][node-version-url]
|
||||||
|
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
Create and parse HTTP `Content-Disposition` header
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install content-disposition
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```js
|
||||||
|
var contentDisposition = require('content-disposition')
|
||||||
|
```
|
||||||
|
|
||||||
|
### contentDisposition(filename, options)
|
||||||
|
|
||||||
|
Create an attachment `Content-Disposition` header value using the given file name,
|
||||||
|
if supplied. The `filename` is optional and if no file name is desired, but you
|
||||||
|
want to specify `options`, set `filename` to `undefined`.
|
||||||
|
|
||||||
|
```js
|
||||||
|
res.setHeader('Content-Disposition', contentDisposition('∫ maths.pdf'))
|
||||||
|
```
|
||||||
|
|
||||||
|
**note** HTTP headers are of the ISO-8859-1 character set. If you are writing this
|
||||||
|
header through a means different from `setHeader` in Node.js, you'll want to specify
|
||||||
|
the `'binary'` encoding in Node.js.
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
`contentDisposition` accepts these properties in the options object.
|
||||||
|
|
||||||
|
##### fallback
|
||||||
|
|
||||||
|
If the `filename` option is outside ISO-8859-1, then the file name is actually
|
||||||
|
stored in a supplemental field for clients that support Unicode file names and
|
||||||
|
a ISO-8859-1 version of the file name is automatically generated.
|
||||||
|
|
||||||
|
This specifies the ISO-8859-1 file name to override the automatic generation or
|
||||||
|
disables the generation all together, defaults to `true`.
|
||||||
|
|
||||||
|
- A string will specify the ISO-8859-1 file name to use in place of automatic
|
||||||
|
generation.
|
||||||
|
- `false` will disable including a ISO-8859-1 file name and only include the
|
||||||
|
Unicode version (unless the file name is already ISO-8859-1).
|
||||||
|
- `true` will enable automatic generation if the file name is outside ISO-8859-1.
|
||||||
|
|
||||||
|
If the `filename` option is ISO-8859-1 and this option is specified and has a
|
||||||
|
different value, then the `filename` option is encoded in the extended field
|
||||||
|
and this set as the fallback field, even though they are both ISO-8859-1.
|
||||||
|
|
||||||
|
##### type
|
||||||
|
|
||||||
|
Specifies the disposition type, defaults to `"attachment"`. This can also be
|
||||||
|
`"inline"`, or any other value (all values except inline are treated like
|
||||||
|
`attachment`, but can convey additional information if both parties agree to
|
||||||
|
it). The type is normalized to lower-case.
|
||||||
|
|
||||||
|
### contentDisposition.parse(string)
|
||||||
|
|
||||||
|
```js
|
||||||
|
var disposition = contentDisposition.parse('attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt')
|
||||||
|
```
|
||||||
|
|
||||||
|
Parse a `Content-Disposition` header string. This automatically handles extended
|
||||||
|
("Unicode") parameters by decoding them and providing them under the standard
|
||||||
|
parameter name. This will return an object with the following properties (examples
|
||||||
|
are shown for the string `'attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt'`):
|
||||||
|
|
||||||
|
- `type`: The disposition type (always lower case). Example: `'attachment'`
|
||||||
|
|
||||||
|
- `parameters`: An object of the parameters in the disposition (name of parameter
|
||||||
|
always lower case and extended versions replace non-extended versions). Example:
|
||||||
|
`{filename: "€ rates.txt"}`
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Send a file for download
|
||||||
|
|
||||||
|
```js
|
||||||
|
var contentDisposition = require('content-disposition')
|
||||||
|
var destroy = require('destroy')
|
||||||
|
var fs = require('fs')
|
||||||
|
var http = require('http')
|
||||||
|
var onFinished = require('on-finished')
|
||||||
|
|
||||||
|
var filePath = '/path/to/public/plans.pdf'
|
||||||
|
|
||||||
|
http.createServer(function onRequest (req, res) {
|
||||||
|
// set headers
|
||||||
|
res.setHeader('Content-Type', 'application/pdf')
|
||||||
|
res.setHeader('Content-Disposition', contentDisposition(filePath))
|
||||||
|
|
||||||
|
// send file
|
||||||
|
var stream = fs.createReadStream(filePath)
|
||||||
|
stream.pipe(res)
|
||||||
|
onFinished(res, function () {
|
||||||
|
destroy(stream)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1][rfc-2616]
|
||||||
|
- [RFC 5987: Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters][rfc-5987]
|
||||||
|
- [RFC 6266: Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)][rfc-6266]
|
||||||
|
- [Test Cases for HTTP Content-Disposition header field (RFC 6266) and the Encodings defined in RFCs 2047, 2231 and 5987][tc-2231]
|
||||||
|
|
||||||
|
[rfc-2616]: https://tools.ietf.org/html/rfc2616
|
||||||
|
[rfc-5987]: https://tools.ietf.org/html/rfc5987
|
||||||
|
[rfc-6266]: https://tools.ietf.org/html/rfc6266
|
||||||
|
[tc-2231]: http://greenbytes.de/tech/tc2231/
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
[npm-image]: https://img.shields.io/npm/v/content-disposition.svg
|
||||||
|
[npm-url]: https://npmjs.org/package/content-disposition
|
||||||
|
[node-version-image]: https://img.shields.io/node/v/content-disposition.svg
|
||||||
|
[node-version-url]: https://nodejs.org/en/download
|
||||||
|
[coveralls-image]: https://img.shields.io/coveralls/jshttp/content-disposition.svg
|
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/content-disposition?branch=master
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/content-disposition.svg
|
||||||
|
[downloads-url]: https://npmjs.org/package/content-disposition
|
||||||
|
[github-actions-ci-image]: https://img.shields.io/github/workflow/status/jshttp/content-disposition/ci/master?label=ci
|
||||||
|
[github-actions-ci-url]: https://github.com/jshttp/content-disposition?query=workflow%3Aci
|
||||||
458
server/node_modules/content-disposition/index.js
generated
vendored
Normal file
458
server/node_modules/content-disposition/index.js
generated
vendored
Normal file
@@ -0,0 +1,458 @@
|
|||||||
|
/*!
|
||||||
|
* content-disposition
|
||||||
|
* Copyright(c) 2014-2017 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = contentDisposition
|
||||||
|
module.exports.parse = parse
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var basename = require('path').basename
|
||||||
|
var Buffer = require('safe-buffer').Buffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match non attr-char, *after* encodeURIComponent (i.e. not including "%")
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match percent encoding escape.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/
|
||||||
|
var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match non-latin1 characters.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var NON_LATIN1_REGEXP = /[^\x20-\x7e\xa0-\xff]/g
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match quoted-pair in RFC 2616
|
||||||
|
*
|
||||||
|
* quoted-pair = "\" CHAR
|
||||||
|
* CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var QESC_REGEXP = /\\([\u0000-\u007f])/g // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match chars that must be quoted-pair in RFC 2616
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var QUOTE_REGEXP = /([\\"])/g
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp for various RFC 2616 grammar
|
||||||
|
*
|
||||||
|
* parameter = token "=" ( token | quoted-string )
|
||||||
|
* token = 1*<any CHAR except CTLs or separators>
|
||||||
|
* separators = "(" | ")" | "<" | ">" | "@"
|
||||||
|
* | "," | ";" | ":" | "\" | <">
|
||||||
|
* | "/" | "[" | "]" | "?" | "="
|
||||||
|
* | "{" | "}" | SP | HT
|
||||||
|
* quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
|
||||||
|
* qdtext = <any TEXT except <">>
|
||||||
|
* quoted-pair = "\" CHAR
|
||||||
|
* CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||||
|
* TEXT = <any OCTET except CTLs, but including LWS>
|
||||||
|
* LWS = [CRLF] 1*( SP | HT )
|
||||||
|
* CRLF = CR LF
|
||||||
|
* CR = <US-ASCII CR, carriage return (13)>
|
||||||
|
* LF = <US-ASCII LF, linefeed (10)>
|
||||||
|
* SP = <US-ASCII SP, space (32)>
|
||||||
|
* HT = <US-ASCII HT, horizontal-tab (9)>
|
||||||
|
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
|
||||||
|
* OCTET = <any 8-bit sequence of data>
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var PARAM_REGEXP = /;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g // eslint-disable-line no-control-regex
|
||||||
|
var TEXT_REGEXP = /^[\x20-\x7e\x80-\xff]+$/
|
||||||
|
var TOKEN_REGEXP = /^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp for various RFC 5987 grammar
|
||||||
|
*
|
||||||
|
* ext-value = charset "'" [ language ] "'" value-chars
|
||||||
|
* charset = "UTF-8" / "ISO-8859-1" / mime-charset
|
||||||
|
* mime-charset = 1*mime-charsetc
|
||||||
|
* mime-charsetc = ALPHA / DIGIT
|
||||||
|
* / "!" / "#" / "$" / "%" / "&"
|
||||||
|
* / "+" / "-" / "^" / "_" / "`"
|
||||||
|
* / "{" / "}" / "~"
|
||||||
|
* language = ( 2*3ALPHA [ extlang ] )
|
||||||
|
* / 4ALPHA
|
||||||
|
* / 5*8ALPHA
|
||||||
|
* extlang = *3( "-" 3ALPHA )
|
||||||
|
* value-chars = *( pct-encoded / attr-char )
|
||||||
|
* pct-encoded = "%" HEXDIG HEXDIG
|
||||||
|
* attr-char = ALPHA / DIGIT
|
||||||
|
* / "!" / "#" / "$" / "&" / "+" / "-" / "."
|
||||||
|
* / "^" / "_" / "`" / "|" / "~"
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var EXT_VALUE_REGEXP = /^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp for various RFC 6266 grammar
|
||||||
|
*
|
||||||
|
* disposition-type = "inline" | "attachment" | disp-ext-type
|
||||||
|
* disp-ext-type = token
|
||||||
|
* disposition-parm = filename-parm | disp-ext-parm
|
||||||
|
* filename-parm = "filename" "=" value
|
||||||
|
* | "filename*" "=" ext-value
|
||||||
|
* disp-ext-parm = token "=" value
|
||||||
|
* | ext-token "=" ext-value
|
||||||
|
* ext-token = <the characters in token, followed by "*">
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var DISPOSITION_TYPE_REGEXP = /^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/ // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an attachment Content-Disposition header.
|
||||||
|
*
|
||||||
|
* @param {string} [filename]
|
||||||
|
* @param {object} [options]
|
||||||
|
* @param {string} [options.type=attachment]
|
||||||
|
* @param {string|boolean} [options.fallback=true]
|
||||||
|
* @return {string}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function contentDisposition (filename, options) {
|
||||||
|
var opts = options || {}
|
||||||
|
|
||||||
|
// get type
|
||||||
|
var type = opts.type || 'attachment'
|
||||||
|
|
||||||
|
// get parameters
|
||||||
|
var params = createparams(filename, opts.fallback)
|
||||||
|
|
||||||
|
// format into string
|
||||||
|
return format(new ContentDisposition(type, params))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create parameters object from filename and fallback.
|
||||||
|
*
|
||||||
|
* @param {string} [filename]
|
||||||
|
* @param {string|boolean} [fallback=true]
|
||||||
|
* @return {object}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function createparams (filename, fallback) {
|
||||||
|
if (filename === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var params = {}
|
||||||
|
|
||||||
|
if (typeof filename !== 'string') {
|
||||||
|
throw new TypeError('filename must be a string')
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback defaults to true
|
||||||
|
if (fallback === undefined) {
|
||||||
|
fallback = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof fallback !== 'string' && typeof fallback !== 'boolean') {
|
||||||
|
throw new TypeError('fallback must be a string or boolean')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof fallback === 'string' && NON_LATIN1_REGEXP.test(fallback)) {
|
||||||
|
throw new TypeError('fallback must be ISO-8859-1 string')
|
||||||
|
}
|
||||||
|
|
||||||
|
// restrict to file base name
|
||||||
|
var name = basename(filename)
|
||||||
|
|
||||||
|
// determine if name is suitable for quoted string
|
||||||
|
var isQuotedString = TEXT_REGEXP.test(name)
|
||||||
|
|
||||||
|
// generate fallback name
|
||||||
|
var fallbackName = typeof fallback !== 'string'
|
||||||
|
? fallback && getlatin1(name)
|
||||||
|
: basename(fallback)
|
||||||
|
var hasFallback = typeof fallbackName === 'string' && fallbackName !== name
|
||||||
|
|
||||||
|
// set extended filename parameter
|
||||||
|
if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) {
|
||||||
|
params['filename*'] = name
|
||||||
|
}
|
||||||
|
|
||||||
|
// set filename parameter
|
||||||
|
if (isQuotedString || hasFallback) {
|
||||||
|
params.filename = hasFallback
|
||||||
|
? fallbackName
|
||||||
|
: name
|
||||||
|
}
|
||||||
|
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format object to Content-Disposition header.
|
||||||
|
*
|
||||||
|
* @param {object} obj
|
||||||
|
* @param {string} obj.type
|
||||||
|
* @param {object} [obj.parameters]
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function format (obj) {
|
||||||
|
var parameters = obj.parameters
|
||||||
|
var type = obj.type
|
||||||
|
|
||||||
|
if (!type || typeof type !== 'string' || !TOKEN_REGEXP.test(type)) {
|
||||||
|
throw new TypeError('invalid type')
|
||||||
|
}
|
||||||
|
|
||||||
|
// start with normalized type
|
||||||
|
var string = String(type).toLowerCase()
|
||||||
|
|
||||||
|
// append parameters
|
||||||
|
if (parameters && typeof parameters === 'object') {
|
||||||
|
var param
|
||||||
|
var params = Object.keys(parameters).sort()
|
||||||
|
|
||||||
|
for (var i = 0; i < params.length; i++) {
|
||||||
|
param = params[i]
|
||||||
|
|
||||||
|
var val = param.substr(-1) === '*'
|
||||||
|
? ustring(parameters[param])
|
||||||
|
: qstring(parameters[param])
|
||||||
|
|
||||||
|
string += '; ' + param + '=' + val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a RFC 5987 field value (gracefully).
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function decodefield (str) {
|
||||||
|
var match = EXT_VALUE_REGEXP.exec(str)
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
throw new TypeError('invalid extended field value')
|
||||||
|
}
|
||||||
|
|
||||||
|
var charset = match[1].toLowerCase()
|
||||||
|
var encoded = match[2]
|
||||||
|
var value
|
||||||
|
|
||||||
|
// to binary string
|
||||||
|
var binary = encoded.replace(HEX_ESCAPE_REPLACE_REGEXP, pdecode)
|
||||||
|
|
||||||
|
switch (charset) {
|
||||||
|
case 'iso-8859-1':
|
||||||
|
value = getlatin1(binary)
|
||||||
|
break
|
||||||
|
case 'utf-8':
|
||||||
|
value = Buffer.from(binary, 'binary').toString('utf8')
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw new TypeError('unsupported charset in extended field')
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get ISO-8859-1 version of string.
|
||||||
|
*
|
||||||
|
* @param {string} val
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getlatin1 (val) {
|
||||||
|
// simple Unicode -> ISO-8859-1 transformation
|
||||||
|
return String(val).replace(NON_LATIN1_REGEXP, '?')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse Content-Disposition header string.
|
||||||
|
*
|
||||||
|
* @param {string} string
|
||||||
|
* @return {object}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function parse (string) {
|
||||||
|
if (!string || typeof string !== 'string') {
|
||||||
|
throw new TypeError('argument string is required')
|
||||||
|
}
|
||||||
|
|
||||||
|
var match = DISPOSITION_TYPE_REGEXP.exec(string)
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
throw new TypeError('invalid type format')
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize type
|
||||||
|
var index = match[0].length
|
||||||
|
var type = match[1].toLowerCase()
|
||||||
|
|
||||||
|
var key
|
||||||
|
var names = []
|
||||||
|
var params = {}
|
||||||
|
var value
|
||||||
|
|
||||||
|
// calculate index to start at
|
||||||
|
index = PARAM_REGEXP.lastIndex = match[0].substr(-1) === ';'
|
||||||
|
? index - 1
|
||||||
|
: index
|
||||||
|
|
||||||
|
// match parameters
|
||||||
|
while ((match = PARAM_REGEXP.exec(string))) {
|
||||||
|
if (match.index !== index) {
|
||||||
|
throw new TypeError('invalid parameter format')
|
||||||
|
}
|
||||||
|
|
||||||
|
index += match[0].length
|
||||||
|
key = match[1].toLowerCase()
|
||||||
|
value = match[2]
|
||||||
|
|
||||||
|
if (names.indexOf(key) !== -1) {
|
||||||
|
throw new TypeError('invalid duplicate parameter')
|
||||||
|
}
|
||||||
|
|
||||||
|
names.push(key)
|
||||||
|
|
||||||
|
if (key.indexOf('*') + 1 === key.length) {
|
||||||
|
// decode extended value
|
||||||
|
key = key.slice(0, -1)
|
||||||
|
value = decodefield(value)
|
||||||
|
|
||||||
|
// overwrite existing value
|
||||||
|
params[key] = value
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof params[key] === 'string') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value[0] === '"') {
|
||||||
|
// remove quotes and escapes
|
||||||
|
value = value
|
||||||
|
.substr(1, value.length - 2)
|
||||||
|
.replace(QESC_REGEXP, '$1')
|
||||||
|
}
|
||||||
|
|
||||||
|
params[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index !== -1 && index !== string.length) {
|
||||||
|
throw new TypeError('invalid parameter format')
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ContentDisposition(type, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Percent decode a single character.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @param {string} hex
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function pdecode (str, hex) {
|
||||||
|
return String.fromCharCode(parseInt(hex, 16))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Percent encode a single character.
|
||||||
|
*
|
||||||
|
* @param {string} char
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function pencode (char) {
|
||||||
|
return '%' + String(char)
|
||||||
|
.charCodeAt(0)
|
||||||
|
.toString(16)
|
||||||
|
.toUpperCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quote a string for HTTP.
|
||||||
|
*
|
||||||
|
* @param {string} val
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function qstring (val) {
|
||||||
|
var str = String(val)
|
||||||
|
|
||||||
|
return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a Unicode string for HTTP (RFC 5987).
|
||||||
|
*
|
||||||
|
* @param {string} val
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function ustring (val) {
|
||||||
|
var str = String(val)
|
||||||
|
|
||||||
|
// percent encode as UTF-8
|
||||||
|
var encoded = encodeURIComponent(str)
|
||||||
|
.replace(ENCODE_URL_ATTR_CHAR_REGEXP, pencode)
|
||||||
|
|
||||||
|
return 'UTF-8\'\'' + encoded
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for parsed Content-Disposition header for v8 optimization
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @param {string} type
|
||||||
|
* @param {object} parameters
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
function ContentDisposition (type, parameters) {
|
||||||
|
this.type = type
|
||||||
|
this.parameters = parameters
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user