mirror of
https://github.com/putyy/res-downloader.git
synced 2026-01-12 06:04:55 +08:00
init
This commit is contained in:
1
.env.development
Executable file
1
.env.development
Executable file
@@ -0,0 +1 @@
|
||||
VITE_APP_API=""
|
||||
1
.env.production
Executable file
1
.env.production
Executable file
@@ -0,0 +1 @@
|
||||
VITE_APP_API=""
|
||||
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
dist-electron
|
||||
release
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/.debug.env
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
.env
|
||||
|
||||
# lockfile
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
yarn.lock
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 草鞋没号
|
||||
|
||||
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.
|
||||
34
README.md
Normal file
34
README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# res-downloader
|
||||
|
||||
🎯 基于 [electron-vite-vue]( https://github.com/electron-vite/electron-vite-vue.git)
|
||||
📦 操作简单、可获取不同类型的资源
|
||||
💪 支持获取视频、音频、图片、m3u8
|
||||
🖥 支持获取视频号、抖音、快手、小红书、酷狗音乐、qq音乐等网络资源
|
||||
|
||||
## 扩展开发
|
||||
```sh
|
||||
git clone https://github.com/putyy/res-downloader
|
||||
|
||||
cd res-downloader
|
||||
|
||||
yarn install
|
||||
|
||||
yarn run dev
|
||||
|
||||
# 打包mac
|
||||
yarn run build --mac
|
||||
|
||||
# 打包win
|
||||
yarn run build --win
|
||||
```
|
||||
|
||||
## 软件截图
|
||||

|
||||
|
||||
## 实现原理
|
||||
> 通过代理网络抓包拦截响应,筛选出有用的资源,同fiddler、charles等抓包软件、浏览器F12打开控制也能达到目的,只不过这些软件需要手动进行筛选,对于小白用户上手还是有点难度,所以就有了本项目这样的软件。
|
||||
|
||||
|
||||
## 参考项目
|
||||
|
||||
- [WeChatVideoDownloader](https://github.com/lecepin/WeChatVideoDownloader) 原项目是react写的,且有段时间未更新,本项目参考原项目用vue3重写了一下,核心逻辑没什么变化,主要是增加了一些新的功能,再次感谢!
|
||||
9
auto-imports.d.ts
vendored
Executable file
9
auto-imports.d.ts
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
|
||||
}
|
||||
32
components.d.ts
vendored
Executable file
32
components.d.ts
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
export {}
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||
ElFooter: typeof import('element-plus/es')['ElFooter']
|
||||
ElForm: typeof import('element-plus/es')['ElForm']
|
||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||
ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElMain: typeof import('element-plus/es')['ElMain']
|
||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||
ElOption: typeof import('element-plus/es')['ElOption']
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
ElTable: typeof import('element-plus/es')['ElTable']
|
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||
Footer: typeof import('./src/components/layout/Footer.vue')['default']
|
||||
Index: typeof import('./src/components/layout/Index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Sidebar: typeof import('./src/components/layout/Sidebar.vue')['default']
|
||||
}
|
||||
}
|
||||
45
electron-builder.json5
Normal file
45
electron-builder.json5
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @see https://www.electron.build/configuration/configuration
|
||||
*/
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/electron-userland/electron-builder/master/packages/app-builder-lib/scheme.json",
|
||||
"appId": "com.putyy.ResDownloader",
|
||||
"asar": true,
|
||||
"directories": {
|
||||
"output": "release/${version}"
|
||||
},
|
||||
"files": [
|
||||
"dist-electron",
|
||||
"dist",
|
||||
"electron/res/**/*"
|
||||
],
|
||||
"mac": {
|
||||
"icon": "electron/res/icon/icons/mac/icon.icns",
|
||||
"artifactName": "${productName}_${version}.${ext}",
|
||||
"target": [
|
||||
"dmg"
|
||||
]
|
||||
},
|
||||
"win": {
|
||||
"icon": "electron/res/icon/icons/win/icon.ico",
|
||||
"target": [
|
||||
{
|
||||
"target": "nsis",
|
||||
"arch": [
|
||||
"x64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"artifactName": "${productName}_${version}.${ext}"
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"perMachine": false,
|
||||
"allowElevation": true,
|
||||
"allowToChangeInstallationDirectory": true,
|
||||
"deleteAppDataOnUninstall": false
|
||||
},
|
||||
"extraResources": [
|
||||
"electron/res"
|
||||
]
|
||||
}
|
||||
11
electron/electron-env.d.ts
vendored
Normal file
11
electron/electron-env.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/// <reference types="vite-plugin-electron/electron-env" />
|
||||
|
||||
declare namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
VSCODE_DEBUG?: 'true'
|
||||
DIST_ELECTRON: string
|
||||
DIST: string
|
||||
/** /dist/ or /public/ */
|
||||
VITE_PUBLIC: string
|
||||
}
|
||||
}
|
||||
47
electron/main/cert.ts
Executable file
47
electron/main/cert.ts
Executable file
@@ -0,0 +1,47 @@
|
||||
import CONFIG from './const'
|
||||
import {mkdirp} from 'mkdirp'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import {clipboard, dialog} from 'electron'
|
||||
import spawn from 'cross-spawn'
|
||||
|
||||
export function checkCertInstalled() {
|
||||
return fs.existsSync(CONFIG.INSTALL_CERT_FLAG)
|
||||
}
|
||||
|
||||
export async function installCert(checkInstalled = true) {
|
||||
if (checkInstalled && checkCertInstalled()) {
|
||||
return;
|
||||
}
|
||||
mkdirp.sync(path.dirname(CONFIG.INSTALL_CERT_FLAG))
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
return new Promise((resolve, reject) => {
|
||||
clipboard.writeText(
|
||||
`echo "输入本地登录密码" && sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "${CONFIG.CERT_PUBLIC_PATH}" && touch ${CONFIG.INSTALL_CERT_FLAG} && echo "安装完成"`,
|
||||
)
|
||||
dialog.showMessageBoxSync({
|
||||
type: 'info',
|
||||
message: `命令已复制到剪贴板,粘贴命令到终端并运行以安装并信任证书`,
|
||||
});
|
||||
|
||||
reject()
|
||||
});
|
||||
} else {
|
||||
return new Promise((resolve: any, reject) => {
|
||||
const result = spawn.sync(CONFIG.WIN_CERT_INSTALL_HELPER, [
|
||||
'-c',
|
||||
'-add',
|
||||
CONFIG.CERT_PUBLIC_PATH,
|
||||
'-s',
|
||||
'root',
|
||||
]);
|
||||
if (result.stdout.toString().indexOf('Succeeded') > -1) {
|
||||
fs.writeFileSync(CONFIG.INSTALL_CERT_FLAG, '')
|
||||
resolve()
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
30
electron/main/const.ts
Executable file
30
electron/main/const.ts
Executable file
@@ -0,0 +1,30 @@
|
||||
import path from 'path'
|
||||
import isDev from 'electron-is-dev'
|
||||
import os from 'os'
|
||||
import {app} from 'electron'
|
||||
|
||||
const APP_PATH = app.getAppPath();
|
||||
// 对于一些 shell 去执行的文件,asar 目录下无法使用。配合 extraResources
|
||||
const EXECUTABLE_PATH = path.join(
|
||||
APP_PATH.indexOf('app.asar') > -1
|
||||
? APP_PATH.substring(0, APP_PATH.indexOf('app.asar'))
|
||||
: APP_PATH,
|
||||
'electron/res',
|
||||
)
|
||||
|
||||
const HOME_PATH = path.join(os.homedir(), '.res-downloader@putyy')
|
||||
|
||||
export default {
|
||||
IS_DEV: isDev,
|
||||
EXECUTABLE_PATH,
|
||||
HOME_PATH,
|
||||
CERT_PRIVATE_PATH: path.join(EXECUTABLE_PATH, './keys/private.pem'),
|
||||
CERT_PUBLIC_PATH: path.join(EXECUTABLE_PATH, './keys/public.pem'),
|
||||
INSTALL_CERT_FLAG: path.join(HOME_PATH, './installed.lock'),
|
||||
WIN_CERT_INSTALL_HELPER: path.join(EXECUTABLE_PATH, './w_c.exe'),
|
||||
APP_CN_NAME: '资源下载器',
|
||||
APP_EN_NAME: 'ResDownloader',
|
||||
REGEDIT_VBS_PATH: path.join(EXECUTABLE_PATH, './regedit-vbs'),
|
||||
OPEN_SSL_BIN_PATH: path.join(EXECUTABLE_PATH, './openssl/openssl.exe'),
|
||||
OPEN_SSL_CNF_PATH: path.join(EXECUTABLE_PATH, './openssl/openssl.cnf'),
|
||||
};
|
||||
182
electron/main/index.ts
Normal file
182
electron/main/index.ts
Normal file
@@ -0,0 +1,182 @@
|
||||
import {app, BrowserWindow, shell, ipcMain, Menu} from 'electron'
|
||||
import {release} from 'node:os'
|
||||
import {join} from 'node:path'
|
||||
import CONFIG from './const'
|
||||
import initIPC, {setWin} from './ipc'
|
||||
|
||||
// The built directory structure
|
||||
//
|
||||
// ├─┬ dist-electron
|
||||
// │ ├─┬ main
|
||||
// │ │ └── index.js > Electron-Main
|
||||
// │ └─┬ preload
|
||||
// │ └── index.js > Preload-Scripts
|
||||
// ├─┬ dist
|
||||
// │ └── index.html > Electron-Renderer
|
||||
//
|
||||
process.env.DIST_ELECTRON = join(__dirname, '..')
|
||||
process.env.DIST = join(process.env.DIST_ELECTRON, '../dist')
|
||||
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
|
||||
? join(process.env.DIST_ELECTRON, '../public')
|
||||
: process.env.DIST
|
||||
|
||||
// Disable GPU Acceleration for Windows 7
|
||||
if (release().startsWith('6.1')) app.disableHardwareAcceleration()
|
||||
|
||||
// Set application name for Windows 10+ notifications
|
||||
if (process.platform === 'win32') app.setAppUserModelId(app.getName())
|
||||
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
app.quit()
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
// Remove electron security warnings
|
||||
// This warning only shows in development mode
|
||||
// Read more on https://www.electronjs.org/docs/latest/tutorial/security
|
||||
// process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
|
||||
|
||||
app.commandLine.appendSwitch('--no-proxy-server')
|
||||
process.on('uncaughtException', () => {
|
||||
});
|
||||
process.on('unhandledRejection', () => {
|
||||
});
|
||||
|
||||
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
let previewWin: BrowserWindow | null = null
|
||||
|
||||
// Here, you can also use other preload
|
||||
const preload = join(__dirname, '../preload/index.js')
|
||||
const url = process.env.VITE_DEV_SERVER_URL
|
||||
const indexHtml = join(process.env.DIST, 'index.html')
|
||||
|
||||
// app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
mainWindow = null
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
app.on('second-instance', () => {
|
||||
if (mainWindow) {
|
||||
// Focus on the main window if the user tried to open another
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
const allWindows = BrowserWindow.getAllWindows()
|
||||
if (allWindows.length) {
|
||||
allWindows[0].focus()
|
||||
} else {
|
||||
createWindow()
|
||||
createPreviewWindow(mainWindow)
|
||||
setWin(mainWindow, previewWin)
|
||||
}
|
||||
})
|
||||
|
||||
// New window example arg: new windows url
|
||||
ipcMain.handle('open-win', (_, arg) => {
|
||||
const childWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload,
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
})
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
childWindow.loadURL(`${url}#${arg}`)
|
||||
} else {
|
||||
childWindow.loadFile(indexHtml, {hash: arg})
|
||||
}
|
||||
})
|
||||
|
||||
function createWindow() {
|
||||
Menu.setApplicationMenu(null);
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
title: 'Main window',
|
||||
icon: join(process.env.VITE_PUBLIC, 'favicon.ico'),
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload,
|
||||
// Warning: Enable nodeIntegration and disable contextIsolation is not secure in production
|
||||
// Consider using contextBridge.exposeInMainWorld
|
||||
// Read more on https://www.electronjs.org/docs/latest/tutorial/context-isolation
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
webSecurity: false,
|
||||
},
|
||||
})
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) { // electron-vite-vue#298
|
||||
mainWindow.loadURL(url).then(r => {
|
||||
})
|
||||
// Open devTool if the app is not packaged
|
||||
// mainWindow.webContents.openDevTools()
|
||||
} else {
|
||||
mainWindow.loadFile(indexHtml).then(r => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
CONFIG.IS_DEV && mainWindow.webContents.openDevTools()
|
||||
|
||||
// Test actively push message to the Electron-Renderer
|
||||
mainWindow.webContents.on('did-finish-load', () => {
|
||||
mainWindow?.webContents.send('main-process-message', new Date().toLocaleString())
|
||||
})
|
||||
|
||||
// Make all links open with the browser, not with the application
|
||||
mainWindow.webContents.setWindowOpenHandler(({url}) => {
|
||||
if (url.startsWith('https:')) shell.openExternal(url)
|
||||
return {action: 'deny'}
|
||||
})
|
||||
// win.webContents.on('will-navigate', (event, url) => { }) #344
|
||||
}
|
||||
|
||||
function createPreviewWindow(parent: BrowserWindow) {
|
||||
previewWin = new BrowserWindow({
|
||||
parent: parent,
|
||||
width: 600,
|
||||
height: 400,
|
||||
show: false,
|
||||
// paintWhenInitiallyHidden: false,
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
})
|
||||
|
||||
// previewWin.hide()
|
||||
previewWin.setTitle("预览")
|
||||
|
||||
previewWin.webContents.session.on('will-download', (event, item, webContents) => {
|
||||
// console.log("取消下载")
|
||||
item.cancel()
|
||||
})
|
||||
|
||||
previewWin.on("page-title-updated", (event) => {
|
||||
// 阻止该事件
|
||||
event.preventDefault()
|
||||
})
|
||||
|
||||
previewWin.on("close", (event) => {
|
||||
// 不关闭窗口
|
||||
event.preventDefault()
|
||||
// 影藏窗口
|
||||
previewWin.hide()
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
initIPC()
|
||||
createWindow()
|
||||
createPreviewWindow(mainWindow)
|
||||
setWin(mainWindow, previewWin)
|
||||
})
|
||||
268
electron/main/ipc.ts
Executable file
268
electron/main/ipc.ts
Executable file
@@ -0,0 +1,268 @@
|
||||
import {ipcMain, dialog, BrowserWindow, app, shell} from 'electron'
|
||||
import {startServer} from './proxyServer'
|
||||
import {installCert, checkCertInstalled} from './cert'
|
||||
import {downloadFile} from './utils'
|
||||
// @ts-ignore
|
||||
import {hexMD5} from '../../src/common/md5'
|
||||
import fs from "fs"
|
||||
import * as urlTool from "url"
|
||||
import CryptoJS from 'crypto-js'
|
||||
import {closeProxy, setProxy} from "./setProxy"
|
||||
import log from "electron-log"
|
||||
|
||||
let getMac = require("getmac").default
|
||||
let win: BrowserWindow
|
||||
let previewWin: BrowserWindow
|
||||
let isStartProxy = false
|
||||
let isOpenProxy = false
|
||||
let videoList = {}
|
||||
let aesKey = "as5d45as4d6qe6wqfar6gt4749q6y7w6h34v64tv7t37ty5qwtv6t6qv"
|
||||
let qqReg = RegExp("finder.video.qq.com")
|
||||
|
||||
const toSize = (size: number) => {
|
||||
if (size > 1048576) {
|
||||
return (size / 1048576).toFixed(2) + "MB"
|
||||
}
|
||||
if (size > 1024) {
|
||||
return (size / 1024).toFixed(2) + "KB"
|
||||
}
|
||||
return size + 'b'
|
||||
}
|
||||
|
||||
const suffix = (type: string) => {
|
||||
switch (type) {
|
||||
case "video/mp4":
|
||||
return ".mp4";
|
||||
case "image/png":
|
||||
return ".png";
|
||||
case "image/webp":
|
||||
return ".webp";
|
||||
case "image/svg+xml":
|
||||
return ".svg";
|
||||
case "image/gif":
|
||||
return ".gif";
|
||||
case "audio/mpeg":
|
||||
return ".mp3";
|
||||
case "application/vnd.apple.mpegurl":
|
||||
return ".m3u8";
|
||||
}
|
||||
}
|
||||
|
||||
export default function initIPC() {
|
||||
|
||||
ipcMain.handle('invoke_app_is_init', async (event, arg) => {
|
||||
// 初始化应用 安装证书相关
|
||||
return checkCertInstalled()
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_init_app', (event, arg) => {
|
||||
// 开始 初始化应用 安装证书相关
|
||||
// console.log('invoke_init_app')
|
||||
return installCert(false)
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_start_proxy', async (event, arg) => {
|
||||
// 启动代理服务
|
||||
if (isStartProxy) {
|
||||
if (isOpenProxy === false) {
|
||||
isOpenProxy = true
|
||||
setProxy('127.0.0.1', 8899)
|
||||
.then(() => {
|
||||
})
|
||||
.catch((err) => {
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
isStartProxy = true
|
||||
isOpenProxy = true
|
||||
return startServer({
|
||||
// @ts-ignore
|
||||
interceptCallback: phase => async (req, res) => {
|
||||
// 拦截响应
|
||||
if (phase === 'response') {
|
||||
let ctype = res?._data?.headers?.['content-type']
|
||||
let url_sign: string = hexMD5(req.fullUrl())
|
||||
let res_url = req.fullUrl()
|
||||
let urlInfo = urlTool.parse(res_url, true)
|
||||
switch (ctype) {
|
||||
case "video/mp4":
|
||||
if (videoList.hasOwnProperty(url_sign) === false) {
|
||||
videoList[url_sign] = req.fullUrl()
|
||||
let high_url = ''
|
||||
let down_url = res_url
|
||||
if (qqReg.test(down_url)) {
|
||||
down_url = down_url.replace("finder.video.qq.com/251/20302", "finder.video.qq.com/251/20304")
|
||||
urlInfo = urlTool.parse(down_url, true)
|
||||
high_url = urlInfo.protocol + "//" + urlInfo.hostname + urlInfo.pathname
|
||||
+ '?encfilekey=' + urlInfo.query?.encfilekey
|
||||
+ '&token=' + urlInfo.query?.token
|
||||
}
|
||||
|
||||
win?.webContents?.send?.('on_get_queue', {
|
||||
url_sign: url_sign,
|
||||
url: down_url,
|
||||
down_url: down_url,
|
||||
high_url: high_url,
|
||||
platform: urlInfo.hostname,
|
||||
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
||||
type: ctype,
|
||||
type_str: 'video',
|
||||
progress_bar: '',
|
||||
save_path: '',
|
||||
downing: false
|
||||
})
|
||||
}
|
||||
break;
|
||||
case "image/png":
|
||||
case "image/webp":
|
||||
case "image/svg+xml":
|
||||
case "image/gif":
|
||||
win?.webContents?.send?.('on_get_queue', {
|
||||
url_sign: url_sign,
|
||||
url: res_url,
|
||||
down_url: res_url,
|
||||
high_url: '',
|
||||
platform: urlInfo.hostname,
|
||||
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
||||
type: ctype,
|
||||
type_str: 'image',
|
||||
progress_bar: '',
|
||||
save_path: '',
|
||||
downing: false
|
||||
})
|
||||
break;
|
||||
case "audio/mpeg":
|
||||
win?.webContents?.send?.('on_get_queue', {
|
||||
url_sign: url_sign,
|
||||
url: res_url,
|
||||
down_url: res_url,
|
||||
high_url: '',
|
||||
platform: urlInfo.hostname,
|
||||
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
||||
type: ctype,
|
||||
type_str: 'audio',
|
||||
progress_bar: '',
|
||||
save_path: '',
|
||||
downing: false
|
||||
})
|
||||
break;
|
||||
case "application/vnd.apple.mpegurl":
|
||||
win?.webContents?.send?.('on_get_queue', {
|
||||
url_sign: url_sign,
|
||||
url: res_url,
|
||||
down_url: res_url,
|
||||
high_url: '',
|
||||
platform: urlInfo.hostname,
|
||||
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
||||
type: ctype,
|
||||
type_str: 'm3u8',
|
||||
progress_bar: '',
|
||||
save_path: '',
|
||||
downing: false
|
||||
})
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
setProxyErrorCallback: err => {
|
||||
isStartProxy = false
|
||||
isOpenProxy = false
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_close_proxy', (event, arg) => {
|
||||
// 关闭代理
|
||||
try {
|
||||
isOpenProxy = false
|
||||
return closeProxy()
|
||||
} catch (error) {
|
||||
log.log("--------------closeProxy error--------------", error)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_select_down_dir', async (event, arg) => {
|
||||
// 选择下载位置
|
||||
const result = dialog.showOpenDialogSync({title: '保存', properties: ['openDirectory']})
|
||||
if (!result?.[0]) {
|
||||
return false
|
||||
}
|
||||
|
||||
return result?.[0]
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_file_exists', async (event, {save_path, url}) => {
|
||||
let url_sign = hexMD5(url)
|
||||
let res = fs.existsSync(`${save_path}/${url_sign}.mp4`)
|
||||
return {is_file: res, fileName: `${save_path}/${url_sign}.mp4`}
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_down_file', async (event, {index, data, save_path, high}) => {
|
||||
let down_url = data.down_url
|
||||
if (high && data.high_url) {
|
||||
down_url = data.high_url
|
||||
}
|
||||
|
||||
if (!down_url) {
|
||||
return false
|
||||
}
|
||||
|
||||
let url_sign = hexMD5(down_url)
|
||||
let save_path_file = `${save_path}/${url_sign}` + suffix(data.type)
|
||||
if (fs.existsSync(save_path_file)) {
|
||||
return {fullFileName: save_path_file, totalLen: ""}
|
||||
}
|
||||
// 开始下载
|
||||
return downloadFile(
|
||||
down_url,
|
||||
save_path_file,
|
||||
(res) => {
|
||||
return save_path_file
|
||||
}
|
||||
).catch(err => {
|
||||
// console.log('invoke_down_file:err', err)
|
||||
return false
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_get_mac', async (event) => {
|
||||
let mac = getMac()
|
||||
if (mac === "") {
|
||||
return ""
|
||||
}
|
||||
return CryptoJS.AES.encrypt(mac, CryptoJS.enc.Hex.parse(aesKey), {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}).ciphertext.toString()
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_resources_preview', async (event, {url}) => {
|
||||
if (!url) {
|
||||
return
|
||||
}
|
||||
|
||||
previewWin.loadURL(url).then(r => {
|
||||
return
|
||||
}).catch(res => {
|
||||
})
|
||||
previewWin.show()
|
||||
return
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_open_default_browser', (event, {url}) => {
|
||||
shell.openExternal(url).then(r => {})
|
||||
})
|
||||
|
||||
ipcMain.handle('invoke_open_dir', (event, {dir}) => {
|
||||
shell.openPath(dir).then(r => {})
|
||||
})
|
||||
}
|
||||
|
||||
export function setWin(w, p) {
|
||||
win = w
|
||||
previewWin = p
|
||||
}
|
||||
70
electron/main/proxyServer.ts
Executable file
70
electron/main/proxyServer.ts
Executable file
@@ -0,0 +1,70 @@
|
||||
import fs from 'fs'
|
||||
import log from 'electron-log'
|
||||
import CONFIG from './const'
|
||||
import {closeProxy, setProxy} from './setProxy'
|
||||
import {app} from "electron"
|
||||
|
||||
const hoXy = require('hoxy')
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
process.env.OPENSSL_BIN = CONFIG.OPEN_SSL_BIN_PATH
|
||||
process.env.OPENSSL_CONF = CONFIG.OPEN_SSL_CNF_PATH
|
||||
}
|
||||
|
||||
export async function startServer({
|
||||
interceptCallback = f => f => f,
|
||||
setProxyErrorCallback = f => f,
|
||||
}) {
|
||||
// const port = await getPort()
|
||||
const port = 8899
|
||||
|
||||
return new Promise(async (resolve: any, reject) => {
|
||||
const proxy = hoXy
|
||||
.createServer({
|
||||
certAuthority: {
|
||||
key: fs.readFileSync(CONFIG.CERT_PRIVATE_PATH),
|
||||
cert: fs.readFileSync(CONFIG.CERT_PUBLIC_PATH),
|
||||
},
|
||||
})
|
||||
.listen(port, () => {
|
||||
setProxy('127.0.0.1', port)
|
||||
.then(() => {
|
||||
log.log("--------------setProxy success--------------")
|
||||
resolve()
|
||||
})
|
||||
.catch((err) => {
|
||||
log.log("--------------setProxy error--------------")
|
||||
// setProxyErrorCallback(data);
|
||||
setProxyErrorCallback({});
|
||||
reject('设置代理失败');
|
||||
});
|
||||
})
|
||||
.on('error', err => {
|
||||
log.log("--------------proxy err--------------", err)
|
||||
});
|
||||
|
||||
proxy.intercept(
|
||||
{
|
||||
phase: 'request',
|
||||
},
|
||||
interceptCallback('request'),
|
||||
);
|
||||
|
||||
proxy.intercept(
|
||||
{
|
||||
phase: 'response',
|
||||
},
|
||||
interceptCallback('response'),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
app.on('before-quit', async e => {
|
||||
e.preventDefault()
|
||||
try {
|
||||
await closeProxy()
|
||||
log.log("--------------closeProxy success--------------")
|
||||
} catch (error) {
|
||||
}
|
||||
app.exit()
|
||||
})
|
||||
116
electron/main/setProxy.ts
Executable file
116
electron/main/setProxy.ts
Executable file
@@ -0,0 +1,116 @@
|
||||
import {exec} from 'child_process'
|
||||
// @ts-ignore
|
||||
import regedit from 'regedit'
|
||||
import CONFIG from './const'
|
||||
|
||||
regedit.setExternalVBSLocation(CONFIG.REGEDIT_VBS_PATH)
|
||||
|
||||
export async function setProxy(host, port) {
|
||||
if (process.platform === 'darwin') {
|
||||
const networks = await getMacAvailableNetworks()
|
||||
|
||||
// @ts-ignore
|
||||
if (networks.length === 0) {
|
||||
throw 'no network'
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
// @ts-ignore
|
||||
networks.map(network => {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(`networksetup -setsecurewebproxy "${network}" ${host} ${port}`, error => {
|
||||
if (error) {
|
||||
reject(null)
|
||||
} else {
|
||||
resolve(network)
|
||||
}
|
||||
});
|
||||
});
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
const valuesToPut = {
|
||||
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings': {
|
||||
ProxyServer: {
|
||||
value: `${host}:${port}`,
|
||||
type: 'REG_SZ',
|
||||
},
|
||||
ProxyEnable: {
|
||||
value: 1,
|
||||
type: 'REG_DWORD',
|
||||
},
|
||||
},
|
||||
};
|
||||
// @ts-ignore
|
||||
return regedit.promisified.putValue(valuesToPut)
|
||||
}
|
||||
}
|
||||
|
||||
export async function closeProxy() {
|
||||
if (process.platform === 'darwin') {
|
||||
const networks = await getMacAvailableNetworks()
|
||||
|
||||
// @ts-ignore
|
||||
if (networks.length === 0) {
|
||||
throw 'no network'
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
// @ts-ignore
|
||||
networks.map(network => {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(`networksetup -setsecurewebproxystate "${network}" off`, error => {
|
||||
if (error) {
|
||||
reject(null)
|
||||
} else {
|
||||
resolve(network)
|
||||
}
|
||||
});
|
||||
});
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
const valuesToPut = {
|
||||
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings': {
|
||||
ProxyEnable: {
|
||||
value: 0,
|
||||
type: 'REG_DWORD',
|
||||
},
|
||||
},
|
||||
};
|
||||
// @ts-ignore
|
||||
return regedit.promisified.putValue(valuesToPut)
|
||||
}
|
||||
}
|
||||
|
||||
function getMacAvailableNetworks() {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec('networksetup -listallnetworkservices', (error, stdout) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
Promise.all(
|
||||
stdout
|
||||
.toString()
|
||||
.split('\n')
|
||||
.map(network => {
|
||||
return new Promise(resolve => {
|
||||
exec(
|
||||
`networksetup getinfo "${network}" | grep "^IP address:\\s\\d"`,
|
||||
(error, stdout) => {
|
||||
if (error) {
|
||||
resolve(null)
|
||||
} else {
|
||||
resolve(stdout ? network : null)
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
}),
|
||||
).then(networks => {
|
||||
resolve(networks.filter(Boolean))
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
65
electron/main/utils.ts
Executable file
65
electron/main/utils.ts
Executable file
@@ -0,0 +1,65 @@
|
||||
import {app, dialog, shell} from 'electron'
|
||||
import semver from 'semver'
|
||||
import fs from 'fs'
|
||||
|
||||
const axios = require('axios')
|
||||
|
||||
// packageUrl 需要包含 { "version": "1.0.0" } 结构
|
||||
function checkUpdate(
|
||||
// 可以使用加速地址 https://cdn.jsdelivr.net/gh/lecepin/electron-react-tpl/package.json
|
||||
packageUrl = 'https://raw.githubusercontent.com/lecepin/electron-react-tpl/master/package.json',
|
||||
downloadUrl = 'https://github.com/lecepin/electron-react-tpl/releases',
|
||||
) {
|
||||
axios.get(packageUrl)
|
||||
.then(({data}) => {
|
||||
if (semver.gt(data?.version, app.getVersion())) {
|
||||
const result = dialog.showMessageBoxSync({
|
||||
message: '发现新版本,是否更新?',
|
||||
type: 'question',
|
||||
cancelId: 1,
|
||||
defaultId: 0,
|
||||
buttons: ['进入新版本下载页面', '取消'],
|
||||
});
|
||||
|
||||
if (result === 0 && downloadUrl) {
|
||||
shell.openExternal(downloadUrl).then(r => {
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
})
|
||||
}
|
||||
|
||||
function downloadFile(url, fullFileName, progressCallback) {
|
||||
return axios.get(url, {
|
||||
responseType: 'stream',
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
|
||||
},
|
||||
}).then(({data, headers}) => {
|
||||
let currentLen = 0
|
||||
const totalLen = headers['content-length']
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
data.on('data', ({length}) => {
|
||||
currentLen += length
|
||||
// @ts-ignore
|
||||
progressCallback?.(currentLen / totalLen)
|
||||
});
|
||||
|
||||
data.on('error', err => reject(err))
|
||||
|
||||
data.pipe(
|
||||
fs.createWriteStream(fullFileName).on('finish', () => {
|
||||
resolve({
|
||||
fullFileName,
|
||||
totalLen,
|
||||
});
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export {checkUpdate, downloadFile}
|
||||
92
electron/preload/index.ts
Normal file
92
electron/preload/index.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
function domReady(condition: DocumentReadyState[] = ['complete', 'interactive']) {
|
||||
return new Promise((resolve) => {
|
||||
if (condition.includes(document.readyState)) {
|
||||
resolve(true)
|
||||
} else {
|
||||
document.addEventListener('readystatechange', () => {
|
||||
if (condition.includes(document.readyState)) {
|
||||
resolve(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const safeDOM = {
|
||||
append(parent: HTMLElement, child: HTMLElement) {
|
||||
if (!Array.from(parent.children).find(e => e === child)) {
|
||||
return parent.appendChild(child)
|
||||
}
|
||||
},
|
||||
remove(parent: HTMLElement, child: HTMLElement) {
|
||||
if (Array.from(parent.children).find(e => e === child)) {
|
||||
return parent.removeChild(child)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* https://tobiasahlin.com/spinkit
|
||||
* https://connoratherton.com/loaders
|
||||
* https://projects.lukehaas.me/css-loaders
|
||||
* https://matejkustec.github.io/SpinThatShit
|
||||
*/
|
||||
function useLoading() {
|
||||
const className = `loaders-css__square-spin`
|
||||
const styleContent = `
|
||||
@keyframes square-spin {
|
||||
25% { transform: perspective(100px) rotateX(180deg) rotateY(0); }
|
||||
50% { transform: perspective(100px) rotateX(180deg) rotateY(180deg); }
|
||||
75% { transform: perspective(100px) rotateX(0) rotateY(180deg); }
|
||||
100% { transform: perspective(100px) rotateX(0) rotateY(0); }
|
||||
}
|
||||
.${className} > div {
|
||||
animation-fill-mode: both;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: #fff;
|
||||
animation: square-spin 3s 0s cubic-bezier(0.09, 0.57, 0.49, 0.9) infinite;
|
||||
}
|
||||
.app-loading-wrap {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #282c34;
|
||||
z-index: 9;
|
||||
}
|
||||
`
|
||||
const oStyle = document.createElement('style')
|
||||
const oDiv = document.createElement('div')
|
||||
|
||||
oStyle.id = 'app-loading-style'
|
||||
oStyle.innerHTML = styleContent
|
||||
oDiv.className = 'app-loading-wrap'
|
||||
oDiv.innerHTML = `<div class="${className}"><div></div></div>`
|
||||
|
||||
return {
|
||||
appendLoading() {
|
||||
safeDOM.append(document.head, oStyle)
|
||||
safeDOM.append(document.body, oDiv)
|
||||
},
|
||||
removeLoading() {
|
||||
safeDOM.remove(document.head, oStyle)
|
||||
safeDOM.remove(document.body, oDiv)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const { appendLoading, removeLoading } = useLoading()
|
||||
domReady().then(appendLoading)
|
||||
|
||||
window.onmessage = (ev) => {
|
||||
ev.data.payload === 'removeLoading' && removeLoading()
|
||||
}
|
||||
|
||||
setTimeout(removeLoading, 4999)
|
||||
BIN
electron/res/icon/icon.png
Executable file
BIN
electron/res/icon/icon.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
BIN
electron/res/icon/icons/mac/icon.icns
Executable file
BIN
electron/res/icon/icons/mac/icon.icns
Executable file
Binary file not shown.
BIN
electron/res/icon/icons/win/icon.ico
Executable file
BIN
electron/res/icon/icons/win/icon.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 199 KiB |
12
electron/res/index.html
Executable file
12
electron/res/index.html
Executable file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>资源下载器</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
27
electron/res/keys/private.key
Executable file
27
electron/res/keys/private.key
Executable file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAsmAqn3hYd/YZcrfgqM1Q6xgHI50EBckbOkfCqTWS1yVFZjLF
|
||||
bMehWb9xGFZJD21A5sxl4xelIWblhety+YTVa/mn2CEJh3je069oeULfXdzhhHyf
|
||||
/ci0IloJhvX+2RJ+176uTKKcWhuOtNVs5VeFoHDoUcISnTqkaVyWeeLfafgrOW7w
|
||||
N8ip128nuBx19ylIygb/DELmjKRRCSpx2vOw2JErTM8L5r0f4eWdqiwBOwu0NHWy
|
||||
Svh9YG8B31UPga4I8FbFhybOP9cQNQPafOSfjwuZoi5CAtyJbwT7KyII9iMD74bZ
|
||||
1mTx2xokmQ2TeiCSKSF8Mx9/8Gq+95mzvvIbRwIDAQABAoIBAHNt++caj9WBclJk
|
||||
X4Oc6eJYuDX5o+LCk1YRngy12IJVYiWScWPFg8p6MouXOsw63Sb92mksofWNirYw
|
||||
+UQzC5FGC7G3H12FgFzoQ+lEtxscluuPYlFukfMw5L1rbzG14FNo145MJHXDI4Qu
|
||||
ILwA+T4sEorl1fndOwvbmJzjjcQaeRNz7/R9e6QTOlZ2+IEMKnHSBXXGJbDj6mPN
|
||||
+f1/ec6nVENdxazgRCi0xfinyft4Ipst93Eb+wGcpk+J43aF+0leWQCdl6Y9U1Lz
|
||||
zpv5H5XOQdwpX+dpuioRp73zwPwIialq+hTUN28Bn9U1jW2tjxUl/vgIpjy1s94a
|
||||
UipRwSECgYEA57vYB+wGnxQxY9IPpr9H/y3HciIwCnuOEsWBzjYe8sIqBif2tEpO
|
||||
OgDZZMQY7+JJrDQbDRs442TuRjKhJ5hiW+MyoiFWaYkBBoNVM8RBTkIjHfrh+uB2
|
||||
XT15FbEyyxo3n9QY610ZJFRnW4Uf5V0osjOqqUgQRrVXvamk6NQH6FkCgYEAxQ3v
|
||||
jFYPL3EkZe1br6X0RM42ykGv5Di5Q6NnjpSPcyn9a2obA1cZuCd5S1lhrkuZGsdI
|
||||
iFapeL+7vpts9gu9/ii9y+CgEKplOMmm0ZrChBKAcXMZvdDKV3y5SmTMZPas4X5i
|
||||
hqNqatx9/J93sMYWc0CuoosDEJYKtSz8GE+1rJ8CgYAmp5rdl21zU7b5Y6zgr7+e
|
||||
vVArpbBFz15fmzqP309CR0kjRb9NS6fI3SNmP5+5RBHt+7MXeJcAt3FXnFJtfGnL
|
||||
0hY8HTuA1y2onHe17uLF3xpkgdj4NEEKRJrSF4DViEYHDyYo/JqZCMtE5OvxIp0L
|
||||
PLsXCcJNSSqdpJKxk8zN4QKBgEuoxSAh7uStUWddUkXHt1kvwDO6MtmyuddxhxJk
|
||||
kguKxMWYUNTgfXyKk3TN1caBOkDg4UWP2LQHEgPmU1jJO2K5q9362hpsAj9ilY2H
|
||||
GUZygCSPKAQMhZQ/zDj3KM9fMxPFXfkKB5MOI8V6SQ9zjy0jWaoJK90TbvsPUZ/Y
|
||||
Aw5LAoGADifZwCHPiXhTfJjOom2uBgXmL03yTXcCw4EDIX3ZR0sP6ACPQq4T4jxZ
|
||||
UJLXLjOb2pzCq0c5+k0cG6ahYINq4tGOo+vQ9fDvhKg0nlf1FrzxSd7S12o+un2q
|
||||
+U+dBllYIDlRMgMhXu9CxFDjUsCwPRmsBvmVZiH4XSs6QVnfn90=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
electron/res/keys/private.pem
Executable file
27
electron/res/keys/private.pem
Executable file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAsmAqn3hYd/YZcrfgqM1Q6xgHI50EBckbOkfCqTWS1yVFZjLF
|
||||
bMehWb9xGFZJD21A5sxl4xelIWblhety+YTVa/mn2CEJh3je069oeULfXdzhhHyf
|
||||
/ci0IloJhvX+2RJ+176uTKKcWhuOtNVs5VeFoHDoUcISnTqkaVyWeeLfafgrOW7w
|
||||
N8ip128nuBx19ylIygb/DELmjKRRCSpx2vOw2JErTM8L5r0f4eWdqiwBOwu0NHWy
|
||||
Svh9YG8B31UPga4I8FbFhybOP9cQNQPafOSfjwuZoi5CAtyJbwT7KyII9iMD74bZ
|
||||
1mTx2xokmQ2TeiCSKSF8Mx9/8Gq+95mzvvIbRwIDAQABAoIBAHNt++caj9WBclJk
|
||||
X4Oc6eJYuDX5o+LCk1YRngy12IJVYiWScWPFg8p6MouXOsw63Sb92mksofWNirYw
|
||||
+UQzC5FGC7G3H12FgFzoQ+lEtxscluuPYlFukfMw5L1rbzG14FNo145MJHXDI4Qu
|
||||
ILwA+T4sEorl1fndOwvbmJzjjcQaeRNz7/R9e6QTOlZ2+IEMKnHSBXXGJbDj6mPN
|
||||
+f1/ec6nVENdxazgRCi0xfinyft4Ipst93Eb+wGcpk+J43aF+0leWQCdl6Y9U1Lz
|
||||
zpv5H5XOQdwpX+dpuioRp73zwPwIialq+hTUN28Bn9U1jW2tjxUl/vgIpjy1s94a
|
||||
UipRwSECgYEA57vYB+wGnxQxY9IPpr9H/y3HciIwCnuOEsWBzjYe8sIqBif2tEpO
|
||||
OgDZZMQY7+JJrDQbDRs442TuRjKhJ5hiW+MyoiFWaYkBBoNVM8RBTkIjHfrh+uB2
|
||||
XT15FbEyyxo3n9QY610ZJFRnW4Uf5V0osjOqqUgQRrVXvamk6NQH6FkCgYEAxQ3v
|
||||
jFYPL3EkZe1br6X0RM42ykGv5Di5Q6NnjpSPcyn9a2obA1cZuCd5S1lhrkuZGsdI
|
||||
iFapeL+7vpts9gu9/ii9y+CgEKplOMmm0ZrChBKAcXMZvdDKV3y5SmTMZPas4X5i
|
||||
hqNqatx9/J93sMYWc0CuoosDEJYKtSz8GE+1rJ8CgYAmp5rdl21zU7b5Y6zgr7+e
|
||||
vVArpbBFz15fmzqP309CR0kjRb9NS6fI3SNmP5+5RBHt+7MXeJcAt3FXnFJtfGnL
|
||||
0hY8HTuA1y2onHe17uLF3xpkgdj4NEEKRJrSF4DViEYHDyYo/JqZCMtE5OvxIp0L
|
||||
PLsXCcJNSSqdpJKxk8zN4QKBgEuoxSAh7uStUWddUkXHt1kvwDO6MtmyuddxhxJk
|
||||
kguKxMWYUNTgfXyKk3TN1caBOkDg4UWP2LQHEgPmU1jJO2K5q9362hpsAj9ilY2H
|
||||
GUZygCSPKAQMhZQ/zDj3KM9fMxPFXfkKB5MOI8V6SQ9zjy0jWaoJK90TbvsPUZ/Y
|
||||
Aw5LAoGADifZwCHPiXhTfJjOom2uBgXmL03yTXcCw4EDIX3ZR0sP6ACPQq4T4jxZ
|
||||
UJLXLjOb2pzCq0c5+k0cG6ahYINq4tGOo+vQ9fDvhKg0nlf1FrzxSd7S12o+un2q
|
||||
+U+dBllYIDlRMgMhXu9CxFDjUsCwPRmsBvmVZiH4XSs6QVnfn90=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
17
electron/res/keys/public.crt
Executable file
17
electron/res/keys/public.crt
Executable file
@@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICuDCCAaACCQC7PQmrxgWOlTANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDDBJs
|
||||
ZWNlcGluLTIwMjItMDUtMTkwIBcNMjIwNTE5MTI1NjA0WhgPMzAyMTA5MTkxMjU2
|
||||
MDRaMB0xGzAZBgNVBAMMEmxlY2VwaW4tMjAyMi0wNS0xOTCCASIwDQYJKoZIhvcN
|
||||
AQEBBQADggEPADCCAQoCggEBALJgKp94WHf2GXK34KjNUOsYByOdBAXJGzpHwqk1
|
||||
ktclRWYyxWzHoVm/cRhWSQ9tQObMZeMXpSFm5YXrcvmE1Wv5p9ghCYd43tOvaHlC
|
||||
313c4YR8n/3ItCJaCYb1/tkSfte+rkyinFobjrTVbOVXhaBw6FHCEp06pGlclnni
|
||||
32n4Kzlu8DfIqddvJ7gcdfcpSMoG/wxC5oykUQkqcdrzsNiRK0zPC+a9H+Hlnaos
|
||||
ATsLtDR1skr4fWBvAd9VD4GuCPBWxYcmzj/XEDUD2nzkn48LmaIuQgLciW8E+ysi
|
||||
CPYjA++G2dZk8dsaJJkNk3ogkikhfDMff/BqvveZs77yG0cCAwEAATANBgkqhkiG
|
||||
9w0BAQsFAAOCAQEADymHk+wLJAdv3p+4hHo57VLaBtwVYXc5oRUbUzgMYTTtPWIs
|
||||
xuILEqXftMspt6PzdEt0V1WeCWNyypsAbur/CKpAOoVjBDPIo09TiYnYIn9xt5wQ
|
||||
AmR5kVEZheuazcvzW3C9NAY1T6QDmxNvFCiCXRbtklOg2HqFDZX+pkj8CylQ9TDk
|
||||
rroUg17b/FD1ds1uyPXzucEWfxqkOaujvsCnzrbFs9luB5VfM+QzLU+l9QRN9Tmj
|
||||
z7CpGuP6vKvhXJLUjXkZ0q5JyL5wEAe6Ttbu+c/8HhPFKQsW6q/lQSDo0v0LGDrd
|
||||
ikjWXhSrVjd8+qTTVgia/UNqv/wi+bkWnVdRzQ==
|
||||
-----END CERTIFICATE-----
|
||||
17
electron/res/keys/public.pem
Executable file
17
electron/res/keys/public.pem
Executable file
@@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICuDCCAaACCQC7PQmrxgWOlTANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDDBJs
|
||||
ZWNlcGluLTIwMjItMDUtMTkwIBcNMjIwNTE5MTI1NjA0WhgPMzAyMTA5MTkxMjU2
|
||||
MDRaMB0xGzAZBgNVBAMMEmxlY2VwaW4tMjAyMi0wNS0xOTCCASIwDQYJKoZIhvcN
|
||||
AQEBBQADggEPADCCAQoCggEBALJgKp94WHf2GXK34KjNUOsYByOdBAXJGzpHwqk1
|
||||
ktclRWYyxWzHoVm/cRhWSQ9tQObMZeMXpSFm5YXrcvmE1Wv5p9ghCYd43tOvaHlC
|
||||
313c4YR8n/3ItCJaCYb1/tkSfte+rkyinFobjrTVbOVXhaBw6FHCEp06pGlclnni
|
||||
32n4Kzlu8DfIqddvJ7gcdfcpSMoG/wxC5oykUQkqcdrzsNiRK0zPC+a9H+Hlnaos
|
||||
ATsLtDR1skr4fWBvAd9VD4GuCPBWxYcmzj/XEDUD2nzkn48LmaIuQgLciW8E+ysi
|
||||
CPYjA++G2dZk8dsaJJkNk3ogkikhfDMff/BqvveZs77yG0cCAwEAATANBgkqhkiG
|
||||
9w0BAQsFAAOCAQEADymHk+wLJAdv3p+4hHo57VLaBtwVYXc5oRUbUzgMYTTtPWIs
|
||||
xuILEqXftMspt6PzdEt0V1WeCWNyypsAbur/CKpAOoVjBDPIo09TiYnYIn9xt5wQ
|
||||
AmR5kVEZheuazcvzW3C9NAY1T6QDmxNvFCiCXRbtklOg2HqFDZX+pkj8CylQ9TDk
|
||||
rroUg17b/FD1ds1uyPXzucEWfxqkOaujvsCnzrbFs9luB5VfM+QzLU+l9QRN9Tmj
|
||||
z7CpGuP6vKvhXJLUjXkZ0q5JyL5wEAe6Ttbu+c/8HhPFKQsW6q/lQSDo0v0LGDrd
|
||||
ikjWXhSrVjd8+qTTVgia/UNqv/wi+bkWnVdRzQ==
|
||||
-----END CERTIFICATE-----
|
||||
BIN
electron/res/openssl/HashInfo.txt
Executable file
BIN
electron/res/openssl/HashInfo.txt
Executable file
Binary file not shown.
126
electron/res/openssl/OpenSSL License.txt
Executable file
126
electron/res/openssl/OpenSSL License.txt
Executable file
@@ -0,0 +1,126 @@
|
||||
|
||||
LICENSE ISSUES
|
||||
==============
|
||||
|
||||
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
|
||||
the OpenSSL License and the original SSLeay license apply to the toolkit.
|
||||
See below for the actual license texts. Actually both licenses are BSD-style
|
||||
Open Source licenses. In case of any license issues related to OpenSSL
|
||||
please contact openssl-core@openssl.org.
|
||||
|
||||
OpenSSL License
|
||||
---------------
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED 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 OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
Original SSLeay License
|
||||
-----------------------
|
||||
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* 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 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
59
electron/res/openssl/ReadMe.txt
Executable file
59
electron/res/openssl/ReadMe.txt
Executable file
@@ -0,0 +1,59 @@
|
||||
=============================================================================
|
||||
OpenSSL v1.0.2q Precompiled Binaries for Win32
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
*** Release Information ***
|
||||
|
||||
Release Date: Nov 22, 2018
|
||||
|
||||
Author: Frederik A. Winkelsdorf (opendec.wordpress.com)
|
||||
for the Indy Project (www.indyproject.org)
|
||||
|
||||
Requirements: Indy 10.5.5+ (SVN Version or Delphi 2009 and newer)
|
||||
|
||||
Dependencies: The libraries have no noteworthy dependencies
|
||||
|
||||
Installation: Copy both DLL files into your application directory
|
||||
|
||||
Supported OS: Windows 2000 up to Windows 10
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
*** Legal Disclaimer ***
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ITS AUTHOR AND THE INDY PROJECT "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 REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
OpenSSL license terms are provided in the file "OpenSSL License.txt".
|
||||
|
||||
PLEASE CHECK IF YOU NEED TO COMPLY WITH EXPORT RESTRICTIONS FOR CRYPTOGRAPHIC
|
||||
SOFTWARE AND/OR PATENTS.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
*** Build Information Win32 ***
|
||||
|
||||
Built with: Microsoft Visual C++ 2008 Express Edition
|
||||
The Netwide Assembler (NASM) v2.11.08 Win32
|
||||
Strawberry Perl v5.22.0.1 Win32 Portable
|
||||
Windows PowerShell
|
||||
FinalBuilder 7
|
||||
|
||||
Commands: perl configure VC-WIN32
|
||||
ms\do_nasm
|
||||
adjusted ms\ntdll.mak (replaced "/MD" with "/MT")
|
||||
adjusted ms\version32.rc (Indy Information inserted)
|
||||
nmake -f ms\ntdll.mak
|
||||
nmake -f ms\ntdll.mak test
|
||||
editbin.exe /rebase:base=0x11000000 libeay32.dll
|
||||
editbin.exe /rebase:base=0x12000000 ssleay32.dll
|
||||
|
||||
=============================================================================
|
||||
BIN
electron/res/openssl/libeay32.dll
Executable file
BIN
electron/res/openssl/libeay32.dll
Executable file
Binary file not shown.
350
electron/res/openssl/openssl.cnf
Executable file
350
electron/res/openssl/openssl.cnf
Executable file
@@ -0,0 +1,350 @@
|
||||
#
|
||||
# OpenSSL example configuration file.
|
||||
# This is mostly being used for generation of certificate requests.
|
||||
#
|
||||
|
||||
# Note that you can include other files from the main configuration
|
||||
# file using the .include directive.
|
||||
#.include filename
|
||||
|
||||
# This definition stops the following lines choking if HOME isn't
|
||||
# defined.
|
||||
HOME = .
|
||||
|
||||
# Extra OBJECT IDENTIFIER info:
|
||||
#oid_file = $ENV::HOME/.oid
|
||||
oid_section = new_oids
|
||||
|
||||
# To use this configuration file with the "-extfile" option of the
|
||||
# "openssl x509" utility, name here the section containing the
|
||||
# X.509v3 extensions to use:
|
||||
# extensions =
|
||||
# (Alternatively, use a configuration file that has only
|
||||
# X.509v3 extensions in its main [= default] section.)
|
||||
|
||||
[ new_oids ]
|
||||
|
||||
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
|
||||
# Add a simple OID like this:
|
||||
# testoid1=1.2.3.4
|
||||
# Or use config file substitution like this:
|
||||
# testoid2=${testoid1}.5.6
|
||||
|
||||
# Policies used by the TSA examples.
|
||||
tsa_policy1 = 1.2.3.4.1
|
||||
tsa_policy2 = 1.2.3.4.5.6
|
||||
tsa_policy3 = 1.2.3.4.5.7
|
||||
|
||||
####################################################################
|
||||
[ ca ]
|
||||
default_ca = CA_default # The default ca section
|
||||
|
||||
####################################################################
|
||||
[ CA_default ]
|
||||
|
||||
dir = ./demoCA # Where everything is kept
|
||||
certs = $dir/certs # Where the issued certs are kept
|
||||
crl_dir = $dir/crl # Where the issued crl are kept
|
||||
database = $dir/index.txt # database index file.
|
||||
#unique_subject = no # Set to 'no' to allow creation of
|
||||
# several certs with same subject.
|
||||
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||
|
||||
certificate = $dir/cacert.pem # The CA certificate
|
||||
serial = $dir/serial # The current serial number
|
||||
crlnumber = $dir/crlnumber # the current crl number
|
||||
# must be commented out to leave a V1 CRL
|
||||
crl = $dir/crl.pem # The current CRL
|
||||
private_key = $dir/private/cakey.pem# The private key
|
||||
|
||||
x509_extensions = usr_cert # The extensions to add to the cert
|
||||
|
||||
# Comment out the following two lines for the "traditional"
|
||||
# (and highly broken) format.
|
||||
name_opt = ca_default # Subject Name options
|
||||
cert_opt = ca_default # Certificate field options
|
||||
|
||||
# Extension copying option: use with caution.
|
||||
# copy_extensions = copy
|
||||
|
||||
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||
# so this is commented out by default to leave a V1 CRL.
|
||||
# crlnumber must also be commented out to leave a V1 CRL.
|
||||
# crl_extensions = crl_ext
|
||||
|
||||
default_days = 365 # how long to certify for
|
||||
default_crl_days= 30 # how long before next CRL
|
||||
default_md = default # use public key default MD
|
||||
preserve = no # keep passed DN ordering
|
||||
|
||||
# A few difference way of specifying how similar the request should look
|
||||
# For type CA, the listed attributes must be the same, and the optional
|
||||
# and supplied fields are just that :-)
|
||||
policy = policy_match
|
||||
|
||||
# For the CA policy
|
||||
[ policy_match ]
|
||||
countryName = match
|
||||
stateOrProvinceName = match
|
||||
organizationName = match
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
# For the 'anything' policy
|
||||
# At this point in time, you must list all acceptable 'object'
|
||||
# types.
|
||||
[ policy_anything ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
####################################################################
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_keyfile = privkey.pem
|
||||
distinguished_name = req_distinguished_name
|
||||
attributes = req_attributes
|
||||
x509_extensions = v3_ca # The extensions to add to the self signed cert
|
||||
|
||||
# Passwords for private keys if not present they will be prompted for
|
||||
# input_password = secret
|
||||
# output_password = secret
|
||||
|
||||
# This sets a mask for permitted string types. There are several options.
|
||||
# default: PrintableString, T61String, BMPString.
|
||||
# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
|
||||
# utf8only: only UTF8Strings (PKIX recommendation after 2004).
|
||||
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||
# MASK:XXXX a literal mask value.
|
||||
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
|
||||
string_mask = utf8only
|
||||
|
||||
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||
|
||||
[ req_distinguished_name ]
|
||||
countryName = Country Name (2 letter code)
|
||||
countryName_default = AU
|
||||
countryName_min = 2
|
||||
countryName_max = 2
|
||||
|
||||
stateOrProvinceName = State or Province Name (full name)
|
||||
stateOrProvinceName_default = Some-State
|
||||
|
||||
localityName = Locality Name (eg, city)
|
||||
|
||||
0.organizationName = Organization Name (eg, company)
|
||||
0.organizationName_default = Internet Widgits Pty Ltd
|
||||
|
||||
# we can do this but it is not needed normally :-)
|
||||
#1.organizationName = Second Organization Name (eg, company)
|
||||
#1.organizationName_default = World Wide Web Pty Ltd
|
||||
|
||||
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||
#organizationalUnitName_default =
|
||||
|
||||
commonName = Common Name (e.g. server FQDN or YOUR name)
|
||||
commonName_max = 64
|
||||
|
||||
emailAddress = Email Address
|
||||
emailAddress_max = 64
|
||||
|
||||
# SET-ex3 = SET extension number 3
|
||||
|
||||
[ req_attributes ]
|
||||
challengePassword = A challenge password
|
||||
challengePassword_min = 4
|
||||
challengePassword_max = 20
|
||||
|
||||
unstructuredName = An optional company name
|
||||
|
||||
[ usr_cert ]
|
||||
|
||||
# These extensions are added when 'ca' signs a request.
|
||||
|
||||
# This goes against PKIX guidelines but some CAs do it and some software
|
||||
# requires this to avoid interpreting an end user certificate as a CA.
|
||||
|
||||
basicConstraints=CA:FALSE
|
||||
|
||||
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||
# the certificate can be used for anything *except* object signing.
|
||||
|
||||
# This is OK for an SSL server.
|
||||
# nsCertType = server
|
||||
|
||||
# For an object signing certificate this would be used.
|
||||
# nsCertType = objsign
|
||||
|
||||
# For normal client use this is typical
|
||||
# nsCertType = client, email
|
||||
|
||||
# and for everything including object signing:
|
||||
# nsCertType = client, email, objsign
|
||||
|
||||
# This is typical in keyUsage for a client certificate.
|
||||
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
# This will be displayed in Netscape's comment listbox.
|
||||
nsComment = "OpenSSL Generated Certificate"
|
||||
|
||||
# PKIX recommendations harmless if included in all certificates.
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
|
||||
# This stuff is for subjectAltName and issuerAltname.
|
||||
# Import the email address.
|
||||
# subjectAltName=email:copy
|
||||
# An alternative to produce certificates that aren't
|
||||
# deprecated according to PKIX.
|
||||
# subjectAltName=email:move
|
||||
|
||||
# Copy subject details
|
||||
# issuerAltName=issuer:copy
|
||||
|
||||
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||
#nsBaseUrl
|
||||
#nsRevocationUrl
|
||||
#nsRenewalUrl
|
||||
#nsCaPolicyUrl
|
||||
#nsSslServerName
|
||||
|
||||
# This is required for TSA certificates.
|
||||
# extendedKeyUsage = critical,timeStamping
|
||||
|
||||
[ v3_req ]
|
||||
|
||||
# Extensions to add to a certificate request
|
||||
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
[ v3_ca ]
|
||||
|
||||
|
||||
# Extensions for a typical CA
|
||||
|
||||
|
||||
# PKIX recommendation.
|
||||
|
||||
subjectKeyIdentifier=hash
|
||||
|
||||
authorityKeyIdentifier=keyid:always,issuer
|
||||
|
||||
basicConstraints = critical,CA:true
|
||||
|
||||
# Key usage: this is typical for a CA certificate. However since it will
|
||||
# prevent it being used as an test self-signed certificate it is best
|
||||
# left out by default.
|
||||
# keyUsage = cRLSign, keyCertSign
|
||||
|
||||
# Some might want this also
|
||||
# nsCertType = sslCA, emailCA
|
||||
|
||||
# Include email address in subject alt name: another PKIX recommendation
|
||||
# subjectAltName=email:copy
|
||||
# Copy issuer details
|
||||
# issuerAltName=issuer:copy
|
||||
|
||||
# DER hex encoding of an extension: beware experts only!
|
||||
# obj=DER:02:03
|
||||
# Where 'obj' is a standard or added object
|
||||
# You can even override a supported extension:
|
||||
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||
|
||||
[ crl_ext ]
|
||||
|
||||
# CRL extensions.
|
||||
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||
|
||||
# issuerAltName=issuer:copy
|
||||
authorityKeyIdentifier=keyid:always
|
||||
|
||||
[ proxy_cert_ext ]
|
||||
# These extensions should be added when creating a proxy certificate
|
||||
|
||||
# This goes against PKIX guidelines but some CAs do it and some software
|
||||
# requires this to avoid interpreting an end user certificate as a CA.
|
||||
|
||||
basicConstraints=CA:FALSE
|
||||
|
||||
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||
# the certificate can be used for anything *except* object signing.
|
||||
|
||||
# This is OK for an SSL server.
|
||||
# nsCertType = server
|
||||
|
||||
# For an object signing certificate this would be used.
|
||||
# nsCertType = objsign
|
||||
|
||||
# For normal client use this is typical
|
||||
# nsCertType = client, email
|
||||
|
||||
# and for everything including object signing:
|
||||
# nsCertType = client, email, objsign
|
||||
|
||||
# This is typical in keyUsage for a client certificate.
|
||||
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
# This will be displayed in Netscape's comment listbox.
|
||||
nsComment = "OpenSSL Generated Certificate"
|
||||
|
||||
# PKIX recommendations harmless if included in all certificates.
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
|
||||
# This stuff is for subjectAltName and issuerAltname.
|
||||
# Import the email address.
|
||||
# subjectAltName=email:copy
|
||||
# An alternative to produce certificates that aren't
|
||||
# deprecated according to PKIX.
|
||||
# subjectAltName=email:move
|
||||
|
||||
# Copy subject details
|
||||
# issuerAltName=issuer:copy
|
||||
|
||||
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||
#nsBaseUrl
|
||||
#nsRevocationUrl
|
||||
#nsRenewalUrl
|
||||
#nsCaPolicyUrl
|
||||
#nsSslServerName
|
||||
|
||||
# This really needs to be in place for it to be a proxy certificate.
|
||||
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
||||
|
||||
####################################################################
|
||||
[ tsa ]
|
||||
|
||||
default_tsa = tsa_config1 # the default TSA section
|
||||
|
||||
[ tsa_config1 ]
|
||||
|
||||
# These are used by the TSA reply generation only.
|
||||
dir = ./demoCA # TSA root directory
|
||||
serial = $dir/tsaserial # The current serial number (mandatory)
|
||||
crypto_device = builtin # OpenSSL engine to use for signing
|
||||
signer_cert = $dir/tsacert.pem # The TSA signing certificate
|
||||
# (optional)
|
||||
certs = $dir/cacert.pem # Certificate chain to include in reply
|
||||
# (optional)
|
||||
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
|
||||
signer_digest = sha256 # Signing digest to use. (Optional)
|
||||
default_policy = tsa_policy1 # Policy if request did not specify it
|
||||
# (optional)
|
||||
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
|
||||
digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory)
|
||||
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
|
||||
clock_precision_digits = 0 # number of digits after dot. (optional)
|
||||
ordering = yes # Is ordering defined for timestamps?
|
||||
# (optional, default: no)
|
||||
tsa_name = yes # Must the TSA name be included in the reply?
|
||||
# (optional, default: no)
|
||||
ess_cert_id_chain = no # Must the ESS cert id chain be included?
|
||||
# (optional, default: no)
|
||||
ess_cert_id_alg = sha1 # algorithm to compute certificate
|
||||
# identifier (optional, default: sha1)
|
||||
BIN
electron/res/openssl/openssl.exe
Executable file
BIN
electron/res/openssl/openssl.exe
Executable file
Binary file not shown.
BIN
electron/res/openssl/ssleay32.dll
Executable file
BIN
electron/res/openssl/ssleay32.dll
Executable file
Binary file not shown.
26
electron/res/regedit-vbs/1.wsf
Executable file
26
electron/res/regedit-vbs/1.wsf
Executable file
@@ -0,0 +1,26 @@
|
||||
<job id="test">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
CheckZeroArgs("type A as first arg!!")
|
||||
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
'On Error Resume Next
|
||||
|
||||
Dim key: key = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
|
||||
Dim value: value = "AppData"
|
||||
|
||||
ParseHiveAndSubKey key, constHive, strSubKey
|
||||
|
||||
GetExpandedStringValue constHive, strSubKey, value, exResult
|
||||
WriteLine "GetExpandedStringValue: " & exResult
|
||||
|
||||
GetStringValue constHive, strSubKey, value, nResult
|
||||
WriteLine "GetStringValue: " & nResult
|
||||
|
||||
set ws = createobject("Wscript.shell")
|
||||
WriteLine "regread: " & ws.regread(key & "\AppData")
|
||||
</script>
|
||||
</job>
|
||||
75
electron/res/regedit-vbs/ArchitectureAgnosticRegistry.vbs
Executable file
75
electron/res/regedit-vbs/ArchitectureAgnosticRegistry.vbs
Executable file
@@ -0,0 +1,75 @@
|
||||
' Notes: wanted to implement this using a class but:
|
||||
' 1. No matter what I did I could not assign the result of GetObject to a private member
|
||||
' 2. It looks as if all methods were treated as subs from the outside world which is not good since
|
||||
' some of these need to return a value
|
||||
'
|
||||
|
||||
Set private_oReg = GetObject("winmgmts:\root\default:StdRegProv")
|
||||
|
||||
Function SetStringValue(constHive, strSubKey, strValueName, strValue)
|
||||
SetStringValue = private_oReg.SetStringValue(constHive, strSubKey, strValueName, strValue)
|
||||
End Function
|
||||
|
||||
Sub GetStringValue(constHive, strKey, strValueName, strValue)
|
||||
private_oReg.GetStringValue constHive, strKey, strValueName, strValue
|
||||
End Sub
|
||||
|
||||
Function SetExpandedStringValue(constHive, strSubKey, strValueName, strValue)
|
||||
SetExpandedStringValue = private_oReg.SetExpandedStringValue(constHive, strSubKey, strValueName, strValue)
|
||||
End Function
|
||||
|
||||
Sub GetExpandedStringValue(constHive, strKey, strValueName, strValue)
|
||||
private_oReg.GetExpandedStringValue constHive, strKey, strValueName, strValue
|
||||
End Sub
|
||||
|
||||
Function SetMultiStringValue(constHive, strSubKey, strValueName, arrValue)
|
||||
SetMultiStringValue = private_oReg.SetMultiStringValue(constHive, strSubKey, strValueName, arrValue)
|
||||
End Function
|
||||
|
||||
Sub GetMultiStringValue(constHive, strKey, strValueName, arrStrValue)
|
||||
private_oReg.GetMultiStringValue constHive, strKey, strValueName, arrStrValue
|
||||
End Sub
|
||||
|
||||
Function SetDWORDValue(constHive, strSubKey, strValueName, arrValue)
|
||||
SetDWORDValue = private_oReg.SetDWORDValue(constHive, strSubKey, strValueName, arrValue)
|
||||
End Function
|
||||
|
||||
Sub GetDWORDValue(constHive, strKey, strValueName, intDWordValue)
|
||||
private_oReg.GetDWORDValue constHive, strKey, strValueName, intDWordValue
|
||||
End Sub
|
||||
|
||||
Function SetQWORDValue(constHive, strSubKey, strValueName, strQWordValue)
|
||||
SetQWORDValue = private_oReg.SetQWORDValue(constHive, strSubKey, strValueName, strQWordValue)
|
||||
End Function
|
||||
|
||||
Sub GetQWORDValue(constHive, strKey, strValueName, intQWordValue)
|
||||
private_oReg.GetQWORDValue constHive, strKey, strValueName, intQWordValue
|
||||
End Sub
|
||||
|
||||
Function SetBinaryValue(constHive, strSubKey, strValueName, arrValue)
|
||||
SetBinaryValue = private_oReg.SetBinaryValue(constHive, strSubKey, strValueName, arrValue)
|
||||
End Function
|
||||
|
||||
Sub GetBinaryValue(constHive, strKey, strValueName, arrBinaryValue)
|
||||
private_oReg.GetBinaryValue constHive, strKey, strValueName, arrBinaryValue
|
||||
End Sub
|
||||
|
||||
Function EnumKey(constHive, strSubKey, arrKeyNames)
|
||||
EnumKey = private_oReg.EnumKey(constHive, strSubKey, arrKeyNames)
|
||||
End Function
|
||||
|
||||
Function EnumValues(constHive, strSubKey, arrValueNames, arrValueTypes)
|
||||
EnumValues = private_oReg.EnumValues(constHive, strSubKey, arrValueNames, arrValueTypes)
|
||||
End Function
|
||||
|
||||
Function CreateKey(constHive, strSubKey)
|
||||
CreateKey = private_oReg.CreateKey(constHive, strSubKey)
|
||||
End Function
|
||||
|
||||
Function DeleteKey(constHive, strSubKey)
|
||||
DeleteKey = private_oReg.DeleteKey(constHive, strSubKey)
|
||||
End Function
|
||||
|
||||
Function DeleteValue(constHive, strSubKey, strValue)
|
||||
DeleteValue = private_oReg.DeleteValue(constHive, strSubKey, strValue)
|
||||
End Function
|
||||
358
electron/res/regedit-vbs/ArchitectureSpecificRegistry.vbs
Executable file
358
electron/res/regedit-vbs/ArchitectureSpecificRegistry.vbs
Executable file
@@ -0,0 +1,358 @@
|
||||
' Notes: wanted to implement this using a class but:
|
||||
' 1. No matter what I did I could not assign the result of GetObject to a private member
|
||||
' 2. It looks as if all methods were treated as subs from the outside world which is not good since
|
||||
' some of these need to return a value
|
||||
|
||||
' should be removed when migration is complete
|
||||
Set private_oReg = GetObject("winmgmts:\root\default:StdRegProv")
|
||||
|
||||
Set private_oCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
|
||||
private_oCtx.Add "__ProviderArchitecture", CInt(OSArchitecture)
|
||||
|
||||
Set private_oLocator = CreateObject("Wbemscripting.SWbemLocator")
|
||||
Set private_oServices = private_oLocator.ConnectServer(".", "root\default","","",,,,private_oCtx)
|
||||
Set private_oRegSpecific = private_oServices.Get("StdRegProv")
|
||||
|
||||
Function CheckAccess(hDefKey,sSubKeyName,uRequired, bGranted )
|
||||
Set Inparams = private_oRegSpecific.Methods_("CheckAccess").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.uRequired = uRequired
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("CheckAccess", Inparams,,private_oCtx)
|
||||
|
||||
bGranted = Outparams.bGranted
|
||||
|
||||
|
||||
CheckAccess = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function CreateKey(hDefKey,sSubKeyName)
|
||||
Set Inparams = private_oRegSpecific.Methods_("CreateKey").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("CreateKey", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
CreateKey = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function DeleteKey(hDefKey,sSubKeyName)
|
||||
Set Inparams = private_oRegSpecific.Methods_("DeleteKey").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("DeleteKey", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
DeleteKey = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function DeleteValue(hDefKey,sSubKeyName,sValueName)
|
||||
Set Inparams = private_oRegSpecific.Methods_("DeleteValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("DeleteValue", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
DeleteValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function EnumKey(hDefKey,sSubKeyName, sNames )
|
||||
Set Inparams = private_oRegSpecific.Methods_("EnumKey").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("EnumKey", Inparams,,private_oCtx)
|
||||
|
||||
sNames = Outparams.sNames
|
||||
|
||||
|
||||
EnumKey = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function EnumValues(hDefKey,sSubKeyName, sNames,Types )
|
||||
Set Inparams = private_oRegSpecific.Methods_("EnumValues").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("EnumValues", Inparams,,private_oCtx)
|
||||
|
||||
sNames = Outparams.sNames
|
||||
|
||||
Types = Outparams.Types
|
||||
|
||||
|
||||
EnumValues = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function GetBinaryValue(hDefKey,sSubKeyName,sValueName, uValue )
|
||||
Set Inparams = private_oRegSpecific.Methods_("GetBinaryValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("GetBinaryValue", Inparams,,private_oCtx)
|
||||
|
||||
uValue = Outparams.uValue
|
||||
|
||||
|
||||
GetBinaryValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function GetDWORDValue(hDefKey,sSubKeyName,sValueName, uValue )
|
||||
Set Inparams = private_oRegSpecific.Methods_("GetDWORDValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("GetDWORDValue", Inparams,,private_oCtx)
|
||||
|
||||
uValue = Outparams.uValue
|
||||
|
||||
|
||||
GetDWORDValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function GetExpandedStringValue(hDefKey,sSubKeyName,sValueName, sValue )
|
||||
Set Inparams = private_oRegSpecific.Methods_("GetExpandedStringValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("GetExpandedStringValue", Inparams,,private_oCtx)
|
||||
|
||||
sValue = Outparams.sValue
|
||||
|
||||
|
||||
GetExpandedStringValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function GetMultiStringValue(hDefKey,sSubKeyName,sValueName, sValue )
|
||||
Set Inparams = private_oRegSpecific.Methods_("GetMultiStringValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("GetMultiStringValue", Inparams,,private_oCtx)
|
||||
|
||||
sValue = Outparams.sValue
|
||||
|
||||
|
||||
GetMultiStringValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function GetQWORDValue(hDefKey,sSubKeyName,sValueName, uValue )
|
||||
Set Inparams = private_oRegSpecific.Methods_("GetQWORDValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("GetQWORDValue", Inparams,,private_oCtx)
|
||||
|
||||
uValue = Outparams.uValue
|
||||
|
||||
|
||||
GetQWORDValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function GetSecurityDescriptor(hDefKey,sSubKeyName, Descriptor )
|
||||
Set Inparams = private_oRegSpecific.Methods_("GetSecurityDescriptor").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("GetSecurityDescriptor", Inparams,,private_oCtx)
|
||||
|
||||
Descriptor = Outparams.Descriptor
|
||||
|
||||
|
||||
GetSecurityDescriptor = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function GetStringValue(hDefKey,sSubKeyName,sValueName, sValue )
|
||||
Set Inparams = private_oRegSpecific.Methods_("GetStringValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("GetStringValue", Inparams,,private_oCtx)
|
||||
|
||||
sValue = Outparams.sValue
|
||||
|
||||
|
||||
GetStringValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function SetBinaryValue(hDefKey,sSubKeyName,sValueName,uValue)
|
||||
Set Inparams = private_oRegSpecific.Methods_("SetBinaryValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
Inparams.uValue = uValue
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("SetBinaryValue", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
SetBinaryValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function SetDWORDValue(hDefKey,sSubKeyName,sValueName,uValue)
|
||||
Set Inparams = private_oRegSpecific.Methods_("SetDWORDValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
Inparams.uValue = uValue
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("SetDWORDValue", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
SetDWORDValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function SetExpandedStringValue(hDefKey,sSubKeyName,sValueName,sValue)
|
||||
Set Inparams = private_oRegSpecific.Methods_("SetExpandedStringValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
Inparams.sValue = sValue
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("SetExpandedStringValue", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
SetExpandedStringValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function SetMultiStringValue(hDefKey,sSubKeyName,sValueName,sValue)
|
||||
Set Inparams = private_oRegSpecific.Methods_("SetMultiStringValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
Inparams.sValue = sValue
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("SetMultiStringValue", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
SetMultiStringValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function SetQWORDValue(hDefKey,sSubKeyName,sValueName,uValue)
|
||||
Set Inparams = private_oRegSpecific.Methods_("SetQWORDValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
Inparams.uValue = uValue
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("SetQWORDValue", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
SetQWORDValue = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function SetSecurityDescriptor(hDefKey,sSubKeyName,Descriptor)
|
||||
Set Inparams = private_oRegSpecific.Methods_("SetSecurityDescriptor").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.Descriptor = Descriptor
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("SetSecurityDescriptor", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
SetSecurityDescriptor = 0
|
||||
|
||||
End Function
|
||||
|
||||
Function SetStringValue(hDefKey,sSubKeyName,sValueName,sValue)
|
||||
Set Inparams = private_oRegSpecific.Methods_("SetStringValue").Inparameters
|
||||
|
||||
Inparams.hDefKey = hDefKey
|
||||
|
||||
Inparams.sSubKeyName = sSubKeyName
|
||||
|
||||
Inparams.sValueName = sValueName
|
||||
|
||||
Inparams.sValue = sValue
|
||||
|
||||
set Outparams = private_oRegSpecific.ExecMethod_("SetStringValue", Inparams,,private_oCtx)
|
||||
|
||||
|
||||
SetStringValue = 0
|
||||
|
||||
End Function
|
||||
7
electron/res/regedit-vbs/JsonSafeTest.wsf
Executable file
7
electron/res/regedit-vbs/JsonSafeTest.wsf
Executable file
@@ -0,0 +1,7 @@
|
||||
<job id="JsonSafeStreamTest">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript">
|
||||
str = """" & vbcrlf & "测试\"
|
||||
Write("{ ""a"": """ & JsonSafe(str) & """}" & vbcrlf)
|
||||
</script>
|
||||
</job>
|
||||
32
electron/res/regedit-vbs/regCreateKey.wsf
Executable file
32
electron/res/regedit-vbs/regCreateKey.wsf
Executable file
@@ -0,0 +1,32 @@
|
||||
<job id="createKeyStream">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
|
||||
CheckZeroArgs("usage: cscript regCreateKey.wsf architecture")
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
Do While Not stdin.AtEndOfLine
|
||||
strLine = stdin.ReadLine()
|
||||
strLine = unescape(trim(strLine))
|
||||
|
||||
If IsNull(strLine) or strLine = "" Then
|
||||
WScript.Quit 25127
|
||||
End If
|
||||
|
||||
ParseHiveAndSubKey strLine, constHive, strSubKey
|
||||
|
||||
if IsNull(constHive) Then
|
||||
WriteLineErr "unsupported hive " & strLine
|
||||
WScript.Quit 25122
|
||||
End If
|
||||
|
||||
Result = CreateKey(constHive, strSubKey)
|
||||
|
||||
If Not Result = 0 Then
|
||||
WScript.Quit Result
|
||||
End If
|
||||
Loop
|
||||
</script>
|
||||
</job>
|
||||
29
electron/res/regedit-vbs/regDeleteKey.wsf
Executable file
29
electron/res/regedit-vbs/regDeleteKey.wsf
Executable file
@@ -0,0 +1,29 @@
|
||||
<job id="deleteKey">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
|
||||
CheckZeroArgs("usage: cscript regDeleteKey.wsf architecture")
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
Do While Not stdin.AtEndOfLine
|
||||
|
||||
strLine = stdin.ReadLine()
|
||||
strLine = unescape(trim(strLine))
|
||||
|
||||
ParseHiveAndSubKey strLine, constHive, strSubKey
|
||||
|
||||
if IsNull(constHive) Then
|
||||
WriteLineErr "unsupported hive " & strLine
|
||||
WScript.Quit 25122
|
||||
End If
|
||||
|
||||
Result = DeleteKey(constHive, strSubKey)
|
||||
|
||||
If Not Result = 0 Then
|
||||
WScript.Quit Result
|
||||
End If
|
||||
Loop
|
||||
</script>
|
||||
</job>
|
||||
29
electron/res/regedit-vbs/regDeleteValue.wsf
Executable file
29
electron/res/regedit-vbs/regDeleteValue.wsf
Executable file
@@ -0,0 +1,29 @@
|
||||
<job id="deleteValue">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
|
||||
CheckZeroArgs("usage: cscript regDeleteValue.wsf architecture")
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
Do While Not stdin.AtEndOfLine
|
||||
|
||||
strLine = stdin.ReadLine()
|
||||
strLine = unescape(trim(strLine))
|
||||
|
||||
ParseHiveAndSubKeyAndValue strLine, constHive, strSubKey, strValue
|
||||
|
||||
if IsNull(constHive) Then
|
||||
WriteLineErr "unsupported hive " & strLine
|
||||
WScript.Quit 25122
|
||||
End If
|
||||
|
||||
Result = DeleteValue(constHive, strSubKey, strValue)
|
||||
|
||||
If Not Result = 0 Then
|
||||
WScript.Quit Result
|
||||
End If
|
||||
Loop
|
||||
</script>
|
||||
</job>
|
||||
49
electron/res/regedit-vbs/regList.wsf
Executable file
49
electron/res/regedit-vbs/regList.wsf
Executable file
@@ -0,0 +1,49 @@
|
||||
'
|
||||
' Lists the sub keys and values of a given registry key
|
||||
'
|
||||
' cscript regList.wsg HKLM\Software
|
||||
'
|
||||
' Will Yield:
|
||||
'
|
||||
' {
|
||||
' "hklm\software": {
|
||||
' "keys": [ .. array of sub keys .. ],
|
||||
' "values": {
|
||||
' "moo": {
|
||||
' "type": "REG_SZ",
|
||||
' "value": "bar"
|
||||
' }
|
||||
' }
|
||||
' }
|
||||
' }
|
||||
<job id="list">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
CheckZeroArgs("usage: cscript regList.wsf architecture regpath1 [regpath2] ... [regpathN]")
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
Write "{"
|
||||
On Error Resume Next
|
||||
For v = 1 To args.Count - 1
|
||||
If (v > 1) Then
|
||||
Write ","
|
||||
End If
|
||||
|
||||
Dim key: key = trim(args(v))
|
||||
|
||||
Write """" & JsonSafe(key) & """: "
|
||||
|
||||
ParseHiveAndSubKey key, constHive, strSubKey
|
||||
|
||||
If IsNull(constHive) Then
|
||||
WriteLineErr "unsupported hive " & args(v)
|
||||
WScript.Quit 25122
|
||||
End If
|
||||
|
||||
ListChildrenAsJson constHive, strSubKey
|
||||
Next
|
||||
Write "}"
|
||||
</script>
|
||||
</job>
|
||||
46
electron/res/regedit-vbs/regListStream.wsf
Executable file
46
electron/res/regedit-vbs/regListStream.wsf
Executable file
@@ -0,0 +1,46 @@
|
||||
'
|
||||
' Lists the sub keys and values of a given registry key, this script is slightly different
|
||||
' than regList because it reads stdin for the keys to list
|
||||
'
|
||||
' echo HKLM\Software | cscript regListStream.wsf A
|
||||
'
|
||||
' Will Yield:
|
||||
'
|
||||
' {
|
||||
' "hklm\software": {
|
||||
' "keys": [ .. array of sub keys .. ],
|
||||
' "values": {
|
||||
' "moo": {
|
||||
' "type": "REG_SZ",
|
||||
' "value": "bar"
|
||||
' }
|
||||
' }
|
||||
' }
|
||||
' }
|
||||
<job id="listStream">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
CheckZeroArgs("usage: echo KEY | cscript regListStream.wsf architecture")
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
Do While Not stdin.AtEndOfLine
|
||||
|
||||
strLine = stdin.ReadLine()
|
||||
strLine = unescape(trim(strLine))
|
||||
|
||||
ParseHiveAndSubKey strLine, constHive, strSubKey
|
||||
|
||||
if IsNull(constHive) Then
|
||||
WriteLineErr "unsupported hive " & strLine
|
||||
WScript.Quit 25122
|
||||
End If
|
||||
|
||||
Write "{ ""key"" : """ & JsonSafe(strLine) & """, ""data"": "
|
||||
ListChildrenAsJson constHive, strSubKey
|
||||
Write "}" & vbcrlf
|
||||
Loop
|
||||
|
||||
</script>
|
||||
</job>
|
||||
56
electron/res/regedit-vbs/regPutValue.wsf
Executable file
56
electron/res/regedit-vbs/regPutValue.wsf
Executable file
@@ -0,0 +1,56 @@
|
||||
<job id="putValue">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
usage = "usage: cscript regPutValue.wsf architecture" & vbNewLine _
|
||||
& "types: REG_SZ, REG_EXPAND_SZ, REG_BINARY, REG_DWORD, REG_MULTI_SZ, REG_QWORD"
|
||||
|
||||
CheckZeroArgs(usage)
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
ReadCount = 0
|
||||
Dim lineArgs(3)
|
||||
|
||||
Do While Not stdin.AtEndOfLine
|
||||
strLine = stdin.ReadLine()
|
||||
strLine = unescape(trim(strLine))
|
||||
|
||||
If IsNull(strLine) or strLine = "" Then
|
||||
WScript.Quit 25127
|
||||
End If
|
||||
|
||||
lineArgs(ReadCount) = strLine
|
||||
|
||||
ReadCount = ReadCount + 1
|
||||
|
||||
If ReadCount = 4 Then
|
||||
|
||||
ParseHiveAndSubKey lineArgs(0), constHive, strSubKey
|
||||
|
||||
if IsNull(constHive) Then
|
||||
WriteLineErr "unsupported hive " & lineArgs(0)
|
||||
WScript.Quit 25122
|
||||
End If
|
||||
|
||||
strValueName = lineArgs(1)
|
||||
strValue = lineArgs(2)
|
||||
strType = lineArgs(3)
|
||||
|
||||
Result = PutValue(constHive, strSubKey, strValueName, strValue, strType)
|
||||
|
||||
If Not Result = 0 Then
|
||||
WriteLineErr "error while putting value: " & result
|
||||
WScript.Quit Result
|
||||
End If
|
||||
|
||||
ReadCount = 0
|
||||
Erase lineArgs
|
||||
End If
|
||||
Loop
|
||||
|
||||
If ReadCount <> 0 Then
|
||||
WScript.Quit 25123
|
||||
End If
|
||||
</script>
|
||||
</job>
|
||||
358
electron/res/regedit-vbs/regUtil.vbs
Executable file
358
electron/res/regedit-vbs/regUtil.vbs
Executable file
@@ -0,0 +1,358 @@
|
||||
' TODO: consider incorporating a json writer of some sort instead of adhoc solution like the following
|
||||
' e.g: http://demon.tw/my-work/vbs-json.html
|
||||
|
||||
const HKEY_CLASSES_ROOT = &H80000000
|
||||
const HKEY_CURRENT_USER = &H80000001
|
||||
const HKEY_LOCAL_MACHINE = &H80000002
|
||||
const HKEY_USERS = &H80000003
|
||||
const HKEY_CURRENT_CONFIG = &H80000005
|
||||
|
||||
Sub LoadRegistryImplementationByOSArchitecture()
|
||||
If IsNull(OSArchitecture) Then
|
||||
WriteLineErr "missing OSArchitecture global. did not call util.DetermineOSArchitecture? or Forgot to load util.vbs?"
|
||||
WScript.Quit 25125
|
||||
End If
|
||||
|
||||
If OSArchitecture = "A" Then
|
||||
Include "ArchitectureAgnosticRegistry.vbs"
|
||||
Else
|
||||
Include "ArchitectureSpecificRegistry.vbs"
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Function PutValue(constHive, strSubKey, strValueName, strValue, strType)
|
||||
Select Case UCase(strType)
|
||||
|
||||
Case "REG_SZ"
|
||||
PutValue = SetStringValue(constHive, strSubKey, strValueName, strValue)
|
||||
|
||||
Case "REG_EXPAND_SZ"
|
||||
PutValue = SetExpandedStringValue(constHive, strSubKey, strValueName, strValue)
|
||||
|
||||
Case "REG_BINARY"
|
||||
PutValue = SetBinaryValue(constHive, strSubKey, strValueName, ToBinaryValue(strValue))
|
||||
|
||||
Case "REG_NONE"
|
||||
PutValue = SetBinaryValue(constHive, strSubKey, strValueName, ToBinaryValue(strValue))
|
||||
|
||||
' TODO: need to check that indeed int is the right type here
|
||||
Case "REG_DWORD"
|
||||
PutValue = SetDWORDValue(constHive, strSubKey, strValueName, CDbl(strValue))
|
||||
|
||||
Case "REG_MULTI_SZ"
|
||||
PutValue = SetMultiStringValue(constHive, strSubKey, strValueName, Split(strValue, ","))
|
||||
|
||||
Case "REG_QWORD"
|
||||
PutValue = SetQWORDValue(constHive, strSubKey, strValueName, strValue)
|
||||
|
||||
Case "REG_DEFAULT"
|
||||
PutValue = SetStringValue(constHive, strSubKey, "", strValue)
|
||||
|
||||
Case Else
|
||||
PutValue = SetStringValue(constHive, strSubKey, strValueName, strValue)
|
||||
|
||||
End Select
|
||||
End Function
|
||||
|
||||
' render the child of a sub path strSubKey in hive constHive
|
||||
' as json.
|
||||
Sub ListChildrenAsJson(constHive, strSubKey)
|
||||
' start outputting json to stdout
|
||||
Write "{"
|
||||
|
||||
Dim e1: e1 = EnumKey (constHive, strSubKey, arrKeyNames)
|
||||
If e1 <> 0 Then
|
||||
Write """exists"": false,"
|
||||
Dim arrValueNames: arrValueNames = null
|
||||
Else
|
||||
Write """exists"": true,"
|
||||
|
||||
Dim e2: e2 = EnumValues (constHive, strSubKey, arrValueNames, arrValueTypes)
|
||||
If e2 <> 0 Then
|
||||
WScript.Quit e2
|
||||
End If
|
||||
End If
|
||||
|
||||
Write """keys"": ["
|
||||
If Not IsNull(arrKeyNames) Then
|
||||
For x = 0 To UBound(arrKeyNames)
|
||||
If (x > 0) Then
|
||||
Write ","
|
||||
End If
|
||||
|
||||
Write """" & JsonSafe(arrKeyNames(x)) & """"
|
||||
Next
|
||||
End If
|
||||
Write "],"
|
||||
' TODO: some duplicity of code between the two paths of this condition, this needs to be address at some point
|
||||
Write """values"":{"
|
||||
If Not IsNull(arrValueNames) Then
|
||||
For y = 0 To UBound(arrValueNames)
|
||||
If y > 0 Then
|
||||
Write ","
|
||||
End If
|
||||
|
||||
strValueName = arrValueNames(y)
|
||||
intValueType = arrValueTypes(y)
|
||||
|
||||
' assign the value to varValue
|
||||
GetValueByType constHive, strSubKey, strValueName, intValueType, varValue
|
||||
|
||||
WriteValue strValueName, intValueType, varValue
|
||||
Next
|
||||
Else
|
||||
' fix for keys with only default values in them
|
||||
' see http://stackoverflow.com/questions/8840343/how-to-read-the-default-value-from-registry-in-vbscript
|
||||
GetStringValue constHive, strSubKey, "", strDefaultValue
|
||||
|
||||
If IsNull(strDefaultValue) = false and strDefaultValue <> "" Then
|
||||
' write the default value with REG_SZ
|
||||
WriteValue "", 1, strDefaultValue
|
||||
End If
|
||||
End If
|
||||
Write "}}"
|
||||
End Sub
|
||||
|
||||
Sub WriteValue (strValueName, intValueType, varValue)
|
||||
Write """"
|
||||
Write JsonSafe(strValueName)
|
||||
Write """:{"
|
||||
Write """type"": """
|
||||
Write RenderType(intValueType)
|
||||
Write ""","
|
||||
Write """value"":"
|
||||
Write RenderValueByType(intValueType, varValue)
|
||||
Write "}"
|
||||
End Sub
|
||||
|
||||
' give a raw HKLM\something\somewhere
|
||||
' output the hive constant and the subkey, in this case:
|
||||
' HKEY_LOCAL_MACHINE will be assigned to outConstHive
|
||||
' and something\somewhere will be assigned to outStrSubKey
|
||||
Sub ParseHiveAndSubKey(strRawKey, outConstHive, outStrSubKey)
|
||||
' split into two parts to deduce the hive and the sub key
|
||||
arrSplitted = Split(strRawKey, "\", 2, 1)
|
||||
|
||||
If UBound(arrSplitted) > 0 Then
|
||||
strHive = arrSplitted(0)
|
||||
outStrSubKey = arrSplitted(1)
|
||||
Else
|
||||
strHive = strRawKey
|
||||
outStrSubKey = ""
|
||||
End If
|
||||
|
||||
outConstHive = StringToHiveConst(UCase(strHive))
|
||||
End Sub
|
||||
|
||||
Function ArrayRemoveAt(arr, pos)
|
||||
Dim i
|
||||
If IsArray(arr) Then
|
||||
If pos >= 0 And pos <= UBound(arr) Then
|
||||
For i = pos To UBound(arr) - 1
|
||||
arr(i) = arr(i + 1)
|
||||
Next
|
||||
ReDim Preserve arr(UBound(arr) - 1)
|
||||
End If
|
||||
End If
|
||||
End Function
|
||||
|
||||
Sub ParseHiveAndSubKeyAndValue(strRawKey, outConstHive, outStrSubKey, outStrValue)
|
||||
' split into two parts to deduce the hive and the sub key
|
||||
arrSplitted = Split(strRawKey, "\", -1, 1)
|
||||
|
||||
If UBound(arrSplitted) > 0 Then
|
||||
strHive = arrSplitted(0)
|
||||
outStrValue = arrSplitted(UBound(arrSplitted))
|
||||
test = ArrayRemoveAt(arrSplitted, UBound(arrSplitted))
|
||||
test = ArrayRemoveAt(arrSplitted, 0)
|
||||
outStrSubKey = Join(arrSplitted, "\")
|
||||
Else
|
||||
strHive = strRawKey
|
||||
outStrSubKey = ""
|
||||
End If
|
||||
|
||||
outConstHive = StringToHiveConst(UCase(strHive))
|
||||
End Sub
|
||||
|
||||
Function StringToHiveConst(strHive)
|
||||
|
||||
Select Case strHive
|
||||
Case "HKCR"
|
||||
StringToHiveConst = HKEY_CLASSES_ROOT
|
||||
Case "HKCU"
|
||||
StringToHiveConst = HKEY_CURRENT_USER
|
||||
Case "HKLM"
|
||||
StringToHiveConst = HKEY_LOCAL_MACHINE
|
||||
Case "HKU"
|
||||
StringToHiveConst = HKEY_USERS
|
||||
Case "HKCC"
|
||||
StringToHiveConst = HKEY_CURRENT_CONFIG
|
||||
Case Else
|
||||
StringToHiveConst = Null
|
||||
End Select
|
||||
|
||||
End Function
|
||||
|
||||
' TODO: this entire "by type" should be transformed into OOP style
|
||||
' where each type will have a class with render(), getValue() etc...
|
||||
|
||||
' convert a value type number into a string label
|
||||
Function RenderType(intType)
|
||||
RenderType = "REG_UNKNOWN"
|
||||
|
||||
Select Case intType
|
||||
Case 0
|
||||
RenderType = "REG_NONE"
|
||||
Case 1
|
||||
RenderType = "REG_SZ"
|
||||
Case 2
|
||||
RenderType = "REG_EXPAND_SZ"
|
||||
Case 3
|
||||
RenderType = "REG_BINARY"
|
||||
Case 4
|
||||
RenderType = "REG_DWORD"
|
||||
Case 7
|
||||
RenderType = "REG_MULTI_SZ"
|
||||
Case 11
|
||||
RenderType = "REG_QWORD"
|
||||
Case Else
|
||||
' TODO: should report / throw an error here
|
||||
WriteErr("invalid Registry Value Type " & intType)
|
||||
|
||||
End Select
|
||||
|
||||
End Function
|
||||
|
||||
' render by value type:
|
||||
' string will return as a string with double quotes, e.g "value"
|
||||
' multi string values which return as an array ot strings "["1", "2"]" (double quotes included ofc)
|
||||
' numeric values like DWORD and QWORD just return as the number e.g. 1
|
||||
' byte arrays such as reg_binary return as an array of ints, e.g [1,2,3]
|
||||
Function RenderValueByType(intType, varValue)
|
||||
|
||||
Select Case intType
|
||||
' REG_NONE
|
||||
Case 0
|
||||
RenderValueByType = "0"
|
||||
|
||||
' REG_SZ
|
||||
Case 1
|
||||
RenderValueByType = """" & JsonSafe(varValue) & """"
|
||||
|
||||
' REG_EXPAND_SZ
|
||||
Case 2
|
||||
RenderValueByType = """" & JsonSafe(varValue) & """"
|
||||
|
||||
' REG_BINARY
|
||||
Case 3
|
||||
RenderValueByType = RenderByteArray(varValue)
|
||||
|
||||
' REG_DWORD
|
||||
Case 4
|
||||
RenderValueByType= varValue
|
||||
|
||||
' REG_MULYI_SZ'
|
||||
Case 7
|
||||
|
||||
RenderValueByType = RenderStringArray(varValue)
|
||||
' REG_QWORD
|
||||
Case 11
|
||||
RenderValueByType = varValue
|
||||
Case Else
|
||||
' TODO: should report / throw an error here
|
||||
WriteErr("invalid Registry Value Type " & intType)
|
||||
End Select
|
||||
|
||||
End Function
|
||||
|
||||
' get the value of a registry based on its value type and assign it to out parameter outVarValue
|
||||
Sub GetValueByType(constHive, strKey, strValueName, intType, outVarValue)
|
||||
|
||||
Select Case intType
|
||||
' REG_NONE
|
||||
Case 0
|
||||
GetStringValue constHive, strKey, strValueName, "0"
|
||||
Exit Sub
|
||||
|
||||
' REG_SZ
|
||||
Case 1
|
||||
GetStringValue constHive, strKey, strValueName, outVarValue
|
||||
Exit Sub
|
||||
|
||||
' REG_EXPAND_SZ
|
||||
Case 2
|
||||
GetExpandedStringValue constHive, strKey, strValueName, outVarValue
|
||||
Exit Sub
|
||||
|
||||
' REG_BINARY
|
||||
Case 3
|
||||
GetBinaryValue constHive, strKey, strValueName, outVarValue
|
||||
Exit Sub
|
||||
|
||||
' REG_DWORD
|
||||
Case 4
|
||||
GetDWORDValue constHive, strKey, strValueName, outVarValue
|
||||
|
||||
' #21 - VBS does not support UInt32. This is the workaround
|
||||
If outVarValue < 0 Then outVarValue = 4294967296 + outVarValue
|
||||
|
||||
Exit Sub
|
||||
|
||||
' REG_MULYI_SZ'
|
||||
Case 7
|
||||
GetMultiStringValue constHive, strKey, strValueName, outVarValue
|
||||
Exit Sub
|
||||
|
||||
' REG_QWORD
|
||||
Case 11
|
||||
GetQWORDValue constHive, strKey, strValueName, outVarValue
|
||||
Exit Sub
|
||||
|
||||
Case Else
|
||||
' TODO: should report / throw an error here
|
||||
WriteErr("invalid Registry Value Type " & intType)
|
||||
End Select
|
||||
|
||||
End Sub
|
||||
|
||||
' render a byte array as a json array of numbers
|
||||
Function RenderByteArray(arr)
|
||||
RenderByteArray = "[]"
|
||||
|
||||
If Not IsNull(arr) Then
|
||||
RenderByteArray = "[" & Join(arr, ",") & "]"
|
||||
End If
|
||||
End Function
|
||||
|
||||
' render a string array as json string array
|
||||
Function RenderStringArray(arr)
|
||||
Result = "["
|
||||
If Not IsNull(arr) Then
|
||||
For t = 0 To UBound(arr)
|
||||
If (t > 0) Then
|
||||
Result = Result & ","
|
||||
End If
|
||||
|
||||
Result = Result & """" & JsonSafe(arr(t)) & """"
|
||||
Next
|
||||
End If
|
||||
Result = Result & "]"
|
||||
|
||||
RenderStringArray = Result
|
||||
End Function
|
||||
|
||||
Function ToBinaryValue(strValue)
|
||||
|
||||
arrValue = Split(strValue, ",")
|
||||
|
||||
If IsNull(arrValue) Then
|
||||
ToBinaryValue = Array()
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
For i = 0 To UBound(arrValue)
|
||||
arrValue(i) = CInt(arrValue(i))
|
||||
Next
|
||||
|
||||
ToBinaryValue = arrValue
|
||||
End Function
|
||||
162
electron/res/regedit-vbs/util.vbs
Executable file
162
electron/res/regedit-vbs/util.vbs
Executable file
@@ -0,0 +1,162 @@
|
||||
Set stdout = WScript.StdOut
|
||||
Set stderr = WScript.StdErr
|
||||
Set stdin = WScript.StdIn
|
||||
Set args = WScript.Arguments
|
||||
Set fs = CreateObject("scripting.filesystemobject")
|
||||
Dim OSArchitecture
|
||||
|
||||
Sub WriteErr(message)
|
||||
stderr.Write message
|
||||
End Sub
|
||||
|
||||
Sub WriteLineErr(message)
|
||||
stderr.WriteLine message
|
||||
End Sub
|
||||
|
||||
Sub Write(message)
|
||||
stdout.Write message
|
||||
End Sub
|
||||
|
||||
Sub WriteLine(message)
|
||||
stdout.WriteLine message
|
||||
End Sub
|
||||
|
||||
Function IndexOf(varNeedle, arrHaystack)
|
||||
IndexOf = -1
|
||||
|
||||
If Not IsArray(arrHaystack) Then
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
For xyz = 0 To UBound(arrHaystack)
|
||||
If arrHaystack(xyz) = varNeedle Then
|
||||
IndexOf = xyz
|
||||
Exit Function
|
||||
End If
|
||||
Next
|
||||
End Function
|
||||
|
||||
Sub CheckZeroArgs(message)
|
||||
' bail if args are missing
|
||||
If args.Count = 0 Then
|
||||
WriteLineErr message
|
||||
WScript.Quit 25121
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Dim ALLOWED_OS_ARCHITECTURE_VALUES: ALLOWED_OS_ARCHITECTURE_VALUES = Array("S", "A", "32", "64")
|
||||
|
||||
'
|
||||
' determine the architecture of the operating system, that will be used. there are 4 possibilities:
|
||||
' A - means agnostic
|
||||
' S - means that we want to use a specific architecture, but auto detect Item
|
||||
' 32 - explicitly use 32 bit architecture
|
||||
' 64 - explicitly use 64 bit architecture
|
||||
'
|
||||
Sub DetermineOSArchitecture()
|
||||
strArchitecture = args(0)
|
||||
|
||||
If IsNull(strArchitecture) Then
|
||||
WriteLineErr "missing architecture argument"
|
||||
WScript.Quit 25124
|
||||
End If
|
||||
|
||||
strArchitecture = UCase(strArchitecture)
|
||||
|
||||
If IndexOf(strArchitecture, ALLOWED_OS_ARCHITECTURE_VALUES) = -1 Then
|
||||
WriteLineErr "invalid architecture argument"
|
||||
WScript.Quit 25124
|
||||
End If
|
||||
|
||||
If (strArchitecture = "S") Then
|
||||
OSArchitecture = GetOSArchitecture()
|
||||
If OSArchitecture = -1 Then
|
||||
WriteLineErr "invalid os architecture detected " & OSArchitecture
|
||||
WScript.Quit 25126
|
||||
End If
|
||||
Else
|
||||
OSArchitecture = strArchitecture
|
||||
End If
|
||||
|
||||
End Sub
|
||||
|
||||
Sub Include(sPath)
|
||||
' TODO this is fragile, but should work for "modules" nested relatively to script root
|
||||
include_ScriptPath = Left(WScript.ScriptFullName, InStr(WScript.ScriptFullName, WScript.ScriptName) - 2)
|
||||
sPath = include_ScriptPath & "\" & sPath
|
||||
|
||||
include_code = fs.OpenTextFile(sPath).ReadAll
|
||||
ExecuteGlobal include_code
|
||||
End Sub
|
||||
|
||||
Function GetOSArchitecture()
|
||||
|
||||
Dim ObjWMI, ColSettings, ObjProcessor
|
||||
Dim StrComputer, ObjNetwork
|
||||
|
||||
Set ObjWMI = GetObject("winmgmts:\Root\CIMV2")
|
||||
Set ColSettings = ObjWMI.ExecQuery ("SELECT DataWidth, AddressWidth, Architecture FROM Win32_Processor")
|
||||
|
||||
' TODO: I make two assumptions here:
|
||||
' 1. Eveyone will have CPU0 device
|
||||
' 2. There is only one cpu defined in the wmi database (and if not, then they are all of the same architecture)
|
||||
Set ObjProcessor = ColSettings.Item("Win32_Processor.DeviceID=""CPU0""")
|
||||
|
||||
If ObjProcessor.Architecture = 0 AND ObjProcessor.AddressWidth = 32 Then
|
||||
GetOSArchitecture = 32
|
||||
ElseIf (ObjProcessor.Architecture = 6 OR ObjProcessor.Architecture = 9) AND ObjProcessor.DataWidth = 64 AND ObjProcessor.AddressWidth = 32 Then
|
||||
GetOSArchitecture = 32
|
||||
ElseIf (ObjProcessor.Architecture = 6 OR ObjProcessor.Architecture = 9) AND ObjProcessor.DataWidth = 64 AND ObjProcessor.AddressWidth = 64 Then
|
||||
GetOSArchitecture = 64
|
||||
Else
|
||||
GetOSArchitecture = -1
|
||||
End If
|
||||
|
||||
End Function
|
||||
|
||||
Function JsonSafe(inStrText)
|
||||
If inStrText = "" Then
|
||||
JsonSafe = ""
|
||||
Exit Function
|
||||
End If
|
||||
Dim outStrText: outStrText = inStrText
|
||||
outStrText = Replace(outStrText, "\", "\\")
|
||||
outStrText = Replace(outStrText, vbcrlf, "\\r\\n")
|
||||
outStrText = Replace(outStrText, vblf, "\\n")
|
||||
outStrText = Replace(outStrText, vbcr, "\\r")
|
||||
outStrText = Replace(outStrText, """", "\""")
|
||||
outStrText = JsonU(outStrText)
|
||||
JsonSafe = outStrText
|
||||
End Function
|
||||
|
||||
'TODO: need to change this function's name to something more appropriate
|
||||
Function JsonU(astr)
|
||||
|
||||
If isNull(astr) Then
|
||||
JsonU = ""
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
Dim c
|
||||
Dim utftext: utftext = ""
|
||||
|
||||
For n = 1 To Len(astr)
|
||||
c = CLng(AscW(Mid(astr, n, 1)))
|
||||
|
||||
If c < 0 Then
|
||||
c = &H10000 + c
|
||||
End If
|
||||
|
||||
If c < &H80 Then
|
||||
utftext = utftext & Mid(astr, n, 1)
|
||||
ElseIf c < &H100 Then
|
||||
utftext = utftext & "\u00" & Hex(c)
|
||||
ElseIf c < &H1000 Then
|
||||
utftext = utftext & "\u0" & Hex(c)
|
||||
Else
|
||||
utftext = utftext & "\u" & Hex(c)
|
||||
End If
|
||||
Next
|
||||
|
||||
JsonU = utftext
|
||||
End Function
|
||||
52
electron/res/regedit-vbs/wsRegReadList.wsf
Executable file
52
electron/res/regedit-vbs/wsRegReadList.wsf
Executable file
@@ -0,0 +1,52 @@
|
||||
'
|
||||
' Lists the values of a given registry path, this script takes its input from stdin
|
||||
'
|
||||
' cscript regListStream.wsf A "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\AppData"
|
||||
'
|
||||
' Will Yield:
|
||||
'
|
||||
' {
|
||||
' "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\AppData": "value here"
|
||||
' }
|
||||
<job id="regRead">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
CheckZeroArgs("usage: cscript wsRegRead.wsf architecture path1...pathN")
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
set ws = createobject("Wscript.shell")
|
||||
|
||||
Write "["
|
||||
On Error Resume Next
|
||||
For v = 1 To args.Count - 1
|
||||
If (v > 1) Then
|
||||
Write ","
|
||||
End If
|
||||
|
||||
Dim key: key = trim(args(v))
|
||||
|
||||
' not really needed except for validation
|
||||
ParseHiveAndSubKeyAndValue key, constHive, strSubKey, strValue
|
||||
|
||||
if IsNull(constHive) Then
|
||||
WriteLineErr "unsupported hive " & args(v)
|
||||
WScript.Quit 25122
|
||||
End If
|
||||
|
||||
Write "{ ""path"" : """ & JsonSafe(key) & """, "
|
||||
|
||||
Dim result: result = ws.RegRead(args(v))
|
||||
Dim exists: exists = "true"
|
||||
|
||||
If Err.Number <> 0 Then
|
||||
exists = "false"
|
||||
End if
|
||||
|
||||
Write """exists"": " & exists & ", "
|
||||
Write """value"": """ & JsonSafe(result) & """}" & vbcrlf
|
||||
Next
|
||||
Write "]"
|
||||
</script>
|
||||
</job>
|
||||
47
electron/res/regedit-vbs/wsRegReadListStream.wsf
Executable file
47
electron/res/regedit-vbs/wsRegReadListStream.wsf
Executable file
@@ -0,0 +1,47 @@
|
||||
'
|
||||
' Lists the values of a given registry path, this script takes its input from stdin
|
||||
'
|
||||
' echo HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\AppData | cscript regListStream.wsf A
|
||||
'
|
||||
' Will Yield:
|
||||
'
|
||||
' {
|
||||
' "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\AppData": "value here"
|
||||
' }
|
||||
<job id="regRead">
|
||||
<script language="VBScript" src="util.vbs" />
|
||||
<script language="VBScript" src="regUtil.vbs" />
|
||||
<script language="VBScript">
|
||||
CheckZeroArgs("usage: echo KEY | cscript wsRegRead.wsf architecture")
|
||||
DetermineOSArchitecture()
|
||||
LoadRegistryImplementationByOSArchitecture()
|
||||
|
||||
set ws = createobject("Wscript.shell")
|
||||
|
||||
Do While Not stdin.AtEndOfLine
|
||||
|
||||
strLine = stdin.ReadLine()
|
||||
strLine = unescape(trim(strLine))
|
||||
|
||||
' not really needed except for validation
|
||||
ParseHiveAndSubKeyAndValue strLine, constHive, strSubKey, strValue
|
||||
|
||||
if IsNull(constHive) Then
|
||||
WriteLineErr "unsupported hive " & strLine
|
||||
WScript.Quit 25122
|
||||
End If
|
||||
|
||||
Write "{ ""path"" : """ & JsonSafe(strLine) & """, "
|
||||
|
||||
Dim result: result = ws.RegRead(strLine)
|
||||
Dim exists: exists = "true"
|
||||
|
||||
If Err.Number <> 0 Then
|
||||
exists = "false"
|
||||
End if
|
||||
|
||||
Write """exists"": " & exists & ", "
|
||||
Write """value"": """ & JsonSafe(result) & """}" & vbcrlf
|
||||
Loop
|
||||
</script>
|
||||
</job>
|
||||
BIN
electron/res/w_c.exe
Executable file
BIN
electron/res/w_c.exe
Executable file
Binary file not shown.
14
index.html
Normal file
14
index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
<title>资源下载器</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
61
package.json
Normal file
61
package.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "res-downloader",
|
||||
"version": "1.0.1",
|
||||
"main": "dist-electron/main/index.js",
|
||||
"description": "Really simple Electron + Vue + Vite boilerplate.",
|
||||
"author": "putyy@qq.com",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"keywords": [
|
||||
"electron",
|
||||
"rollup",
|
||||
"vite",
|
||||
"vue3",
|
||||
"vue"
|
||||
],
|
||||
"debug": {
|
||||
"env": {
|
||||
"VITE_DEV_SERVER_URL": "http://127.0.0.1:3344/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build && electron-builder",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@element-plus/icons-vue": "^2.1.0",
|
||||
"@vitejs/plugin-vue": "^4.3.3",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"crypto-js": "^4.1.1",
|
||||
"electron": "^26.0.0",
|
||||
"electron-builder": "^24.6.3",
|
||||
"electron-is-dev": "^2.0.0",
|
||||
"electron-log": "^4.4.8",
|
||||
"element-plus": "^2.3.12",
|
||||
"get-port": "^7.0.0",
|
||||
"less": "^4.2.0",
|
||||
"less-loader": "^11.1.3",
|
||||
"lodash": "^4.17.21",
|
||||
"mkdirp": "^3.0.1",
|
||||
"pug": "^3.0.2",
|
||||
"pug-plain-loader": "^1.1.0",
|
||||
"regedit": "^5.1.2",
|
||||
"semver": "^7.5.4",
|
||||
"typescript": "^5.1.6",
|
||||
"unplugin-auto-import": "^0.16.6",
|
||||
"unplugin-vue-components": "^0.25.2",
|
||||
"vite": "^4.4.9",
|
||||
"vite-plugin-electron": "^0.13.0-beta.3",
|
||||
"vite-plugin-electron-renderer": "^0.14.5",
|
||||
"vue": "^3.3.4",
|
||||
"vue-router": "^4.2.4",
|
||||
"vue-tsc": "^1.8.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.5.0",
|
||||
"electron-store": "^8.1.0",
|
||||
"getmac": "^5.20.0",
|
||||
"hoxy": "^3.3.1"
|
||||
}
|
||||
}
|
||||
BIN
public/favicon.ico
Executable file
BIN
public/favicon.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
BIN
public/show.png
Normal file
BIN
public/show.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
9
src/App.vue
Normal file
9
src/App.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
BIN
src/assets/logo.png
Executable file
BIN
src/assets/logo.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
5
src/common/api.ts
Executable file
5
src/common/api.ts
Executable file
@@ -0,0 +1,5 @@
|
||||
import request from './request'
|
||||
|
||||
export function getPackageJson() {
|
||||
return request.get("https://github.com/putyy/res-downloader/raw/main/package.json")
|
||||
}
|
||||
61
src/common/localStorage.ts
Executable file
61
src/common/localStorage.ts
Executable file
@@ -0,0 +1,61 @@
|
||||
const localStorageCache = {
|
||||
set: function set(key: string, value: any, time?: number) {
|
||||
if (!localStorage) {
|
||||
return false
|
||||
}
|
||||
if (!time || isNaN(time)) {
|
||||
time = 1200
|
||||
}
|
||||
try {
|
||||
let expireDate = -1
|
||||
if (time !== -1) {
|
||||
// @ts-ignore
|
||||
expireDate = (new Date() - 1) + time * 1000
|
||||
}
|
||||
localStorage.setItem(key, JSON.stringify({val: value, exp: expireDate}))
|
||||
} catch (e) {
|
||||
}
|
||||
return true
|
||||
},
|
||||
get: function get(key: string) {
|
||||
try {
|
||||
if (!localStorage) {
|
||||
return null
|
||||
}
|
||||
let value = localStorage.getItem(key)
|
||||
// @ts-ignore
|
||||
let result = JSON.parse(value)
|
||||
// @ts-ignore
|
||||
let now = new Date() - 1
|
||||
if (!result) {
|
||||
return null
|
||||
}// 缓存不存在
|
||||
if (result.exp !== -1 && now > result.exp) {
|
||||
// 缓存过期
|
||||
this.del(key)
|
||||
return null
|
||||
}
|
||||
return result.val
|
||||
} catch (e) {
|
||||
this.del(key)
|
||||
return null
|
||||
}
|
||||
},
|
||||
del: function del(key: string) {
|
||||
if (!localStorage) {
|
||||
return false
|
||||
}
|
||||
localStorage.removeItem(key)
|
||||
return true
|
||||
},
|
||||
// 清空所有缓存
|
||||
delAll: function delAll() {
|
||||
if (!localStorage) {
|
||||
return false
|
||||
}
|
||||
localStorage.clear()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
export default localStorageCache
|
||||
144
src/common/md5.ts
Executable file
144
src/common/md5.ts
Executable file
@@ -0,0 +1,144 @@
|
||||
function safeAdd(x:any, y:any) {
|
||||
let lsw = (x & 0xFFFF) + (y & 0xFFFF)
|
||||
let msw = (x >> 16) + (y >> 16) + (lsw >> 16)
|
||||
return (msw << 16) | (lsw & 0xFFFF)
|
||||
}
|
||||
|
||||
function rol(num:any, cnt:any) {
|
||||
return (num << cnt) | (num >>> (32 - cnt))
|
||||
}
|
||||
|
||||
function cmn(q:any, a:any, b:any, x:any, s:any, t:any) {
|
||||
return safeAdd(rol(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b)
|
||||
}
|
||||
|
||||
function ff(a:any, b:any, c:any, d:any, x:any, s:any, t:any) {
|
||||
return cmn((b & c) | ((~b) & d), a, b, x, s, t)
|
||||
}
|
||||
|
||||
function gg(a:any, b:any, c:any, d:any, x:any, s:any, t:any) {
|
||||
return cmn((b & d) | (c & (~d)), a, b, x, s, t)
|
||||
}
|
||||
|
||||
function hh(a:any, b:any, c:any, d:any, x:any, s:any, t:any) {
|
||||
return cmn(b ^ c ^ d, a, b, x, s, t)
|
||||
}
|
||||
|
||||
function ii(a:any, b:any, c:any, d:any, x:any, s:any, t:any) {
|
||||
return cmn(c ^ (b | (~d)), a, b, x, s, t)
|
||||
}
|
||||
|
||||
function coreMD5(x:any) {
|
||||
let a = 1732584193
|
||||
let b = -271733879
|
||||
let c = -1732584194
|
||||
let d = 271733878
|
||||
|
||||
for (let i = 0; i < x.length; i += 16) {
|
||||
let olda = a
|
||||
let oldb = b
|
||||
let oldc = c
|
||||
let oldd = d
|
||||
|
||||
a = ff(a, b, c, d, x[i], 7, -680876936)
|
||||
d = ff(d, a, b, c, x[i + 1], 12, -389564586)
|
||||
c = ff(c, d, a, b, x[i + 2], 17, 606105819)
|
||||
b = ff(b, c, d, a, x[i + 3], 22, -1044525330)
|
||||
a = ff(a, b, c, d, x[i + 4], 7, -176418897)
|
||||
d = ff(d, a, b, c, x[i + 5], 12, 1200080426)
|
||||
c = ff(c, d, a, b, x[i + 6], 17, -1473231341)
|
||||
b = ff(b, c, d, a, x[i + 7], 22, -45705983)
|
||||
a = ff(a, b, c, d, x[i + 8], 7, 1770035416)
|
||||
d = ff(d, a, b, c, x[i + 9], 12, -1958414417)
|
||||
c = ff(c, d, a, b, x[i + 10], 17, -42063)
|
||||
b = ff(b, c, d, a, x[i + 11], 22, -1990404162)
|
||||
a = ff(a, b, c, d, x[i + 12], 7, 1804603682)
|
||||
d = ff(d, a, b, c, x[i + 13], 12, -40341101)
|
||||
c = ff(c, d, a, b, x[i + 14], 17, -1502002290)
|
||||
b = ff(b, c, d, a, x[i + 15], 22, 1236535329)
|
||||
|
||||
a = gg(a, b, c, d, x[i + 1], 5, -165796510)
|
||||
d = gg(d, a, b, c, x[i + 6], 9, -1069501632)
|
||||
c = gg(c, d, a, b, x[i + 11], 14, 643717713)
|
||||
b = gg(b, c, d, a, x[i], 20, -373897302)
|
||||
a = gg(a, b, c, d, x[i + 5], 5, -701558691)
|
||||
d = gg(d, a, b, c, x[i + 10], 9, 38016083)
|
||||
c = gg(c, d, a, b, x[i + 15], 14, -660478335)
|
||||
b = gg(b, c, d, a, x[i + 4], 20, -405537848)
|
||||
a = gg(a, b, c, d, x[i + 9], 5, 568446438)
|
||||
d = gg(d, a, b, c, x[i + 14], 9, -1019803690)
|
||||
c = gg(c, d, a, b, x[i + 3], 14, -187363961)
|
||||
b = gg(b, c, d, a, x[i + 8], 20, 1163531501)
|
||||
a = gg(a, b, c, d, x[i + 13], 5, -1444681467)
|
||||
d = gg(d, a, b, c, x[i + 2], 9, -51403784)
|
||||
c = gg(c, d, a, b, x[i + 7], 14, 1735328473)
|
||||
b = gg(b, c, d, a, x[i + 12], 20, -1926607734)
|
||||
|
||||
a = hh(a, b, c, d, x[i + 5], 4, -378558)
|
||||
d = hh(d, a, b, c, x[i + 8], 11, -2022574463)
|
||||
c = hh(c, d, a, b, x[i + 11], 16, 1839030562)
|
||||
b = hh(b, c, d, a, x[i + 14], 23, -35309556)
|
||||
a = hh(a, b, c, d, x[i + 1], 4, -1530992060)
|
||||
d = hh(d, a, b, c, x[i + 4], 11, 1272893353)
|
||||
c = hh(c, d, a, b, x[i + 7], 16, -155497632)
|
||||
b = hh(b, c, d, a, x[i + 10], 23, -1094730640)
|
||||
a = hh(a, b, c, d, x[i + 13], 4, 681279174)
|
||||
d = hh(d, a, b, c, x[i], 11, -358537222)
|
||||
c = hh(c, d, a, b, x[i + 3], 16, -722521979)
|
||||
b = hh(b, c, d, a, x[i + 6], 23, 76029189)
|
||||
a = hh(a, b, c, d, x[i + 9], 4, -640364487)
|
||||
d = hh(d, a, b, c, x[i + 12], 11, -421815835)
|
||||
c = hh(c, d, a, b, x[i + 15], 16, 530742520)
|
||||
b = hh(b, c, d, a, x[i + 2], 23, -995338651)
|
||||
|
||||
a = ii(a, b, c, d, x[i], 6, -198630844)
|
||||
d = ii(d, a, b, c, x[i + 7], 10, 1126891415)
|
||||
c = ii(c, d, a, b, x[i + 14], 15, -1416354905)
|
||||
b = ii(b, c, d, a, x[i + 5], 21, -57434055)
|
||||
a = ii(a, b, c, d, x[i + 12], 6, 1700485571)
|
||||
d = ii(d, a, b, c, x[i + 3], 10, -1894986606)
|
||||
c = ii(c, d, a, b, x[i + 10], 15, -1051523)
|
||||
b = ii(b, c, d, a, x[i + 1], 21, -2054922799)
|
||||
a = ii(a, b, c, d, x[i + 8], 6, 1873313359)
|
||||
d = ii(d, a, b, c, x[i + 15], 10, -30611744)
|
||||
c = ii(c, d, a, b, x[i + 6], 15, -1560198380)
|
||||
b = ii(b, c, d, a, x[i + 13], 21, 1309151649)
|
||||
a = ii(a, b, c, d, x[i + 4], 6, -145523070)
|
||||
d = ii(d, a, b, c, x[i + 11], 10, -1120210379)
|
||||
c = ii(c, d, a, b, x[i + 2], 15, 718787259)
|
||||
b = ii(b, c, d, a, x[i + 9], 21, -343485551)
|
||||
|
||||
a = safeAdd(a, olda)
|
||||
b = safeAdd(b, oldb)
|
||||
c = safeAdd(c, oldc)
|
||||
d = safeAdd(d, oldd)
|
||||
}
|
||||
return [a, b, c, d]
|
||||
}
|
||||
|
||||
function binl2hex(binarray:any) {
|
||||
let hexTab = '0123456789abcdef'
|
||||
let str = ''
|
||||
for (let i = 0; i < binarray.length * 4; i++) {
|
||||
str += hexTab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) +
|
||||
hexTab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
function str2binl(str:any) {
|
||||
let nblk = ((str.length + 8) >> 6) + 1 // number of 16-word blocks
|
||||
let blks = new Array(nblk * 16)
|
||||
for (let i = 0; i < nblk * 16; i++) blks[i] = 0
|
||||
var i = 0
|
||||
for (i; i < str.length; i++) {
|
||||
blks[i >> 2] |= (str.charCodeAt(i) & 0xFF) << ((i % 4) * 8)
|
||||
}
|
||||
blks[i >> 2] |= 0x80 << ((i % 4) * 8)
|
||||
blks[nblk * 16 - 2] = str.length * 8
|
||||
return blks
|
||||
}
|
||||
|
||||
export function hexMD5(str:any) {
|
||||
return binl2hex(coreMD5(str2binl(str)))
|
||||
}
|
||||
71
src/common/request.ts
Executable file
71
src/common/request.ts
Executable file
@@ -0,0 +1,71 @@
|
||||
import axios from 'axios'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {hexMD5} from "./md5"
|
||||
import localStorageCache from "./localStorage"
|
||||
import _ from "lodash"
|
||||
|
||||
class RequestService {
|
||||
private axios: any;
|
||||
private requestList: any;
|
||||
constructor() {
|
||||
let that = this
|
||||
that.requestList = []
|
||||
that.axios = axios.create({
|
||||
timeout: 60000, // 请求超时时间毫秒
|
||||
})
|
||||
|
||||
// 请求拦截
|
||||
that.axios.interceptors.request.use(
|
||||
function (config: any) {
|
||||
if (config.url.slice(0, 8) !== "https://") {
|
||||
config.url = import.meta.env.VITE_APP_API + "/" + config.url
|
||||
}
|
||||
return config
|
||||
},
|
||||
function (error: any) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// 响应拦截
|
||||
that.axios.interceptors.response.use(
|
||||
function (response: any) {
|
||||
return response
|
||||
},
|
||||
function (error: any) {
|
||||
// console.log(error)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
get(url: string, data?: any) {
|
||||
return this.axios.get(url, {params: data}).catch((err:any)=>{
|
||||
console.log('get-err', err)
|
||||
})
|
||||
}
|
||||
|
||||
post(url: string, data: any, isHandle?: any) {
|
||||
isHandle = isHandle || true
|
||||
if (isHandle){
|
||||
data = Object.keys(data).map(item => {
|
||||
let value = data[item];
|
||||
if (_.isArray(value) || _.isObject(value)) {
|
||||
value = JSON.stringify(value)
|
||||
}
|
||||
return encodeURIComponent(item) + '=' + encodeURIComponent(value)
|
||||
}).join('&');
|
||||
}
|
||||
return this.axios.post(url, data).catch((err:any)=>{
|
||||
console.log('post-err', err)
|
||||
})
|
||||
}
|
||||
|
||||
axiosObj() {
|
||||
return this.axios
|
||||
}
|
||||
}
|
||||
|
||||
const request = new RequestService()
|
||||
export default request
|
||||
49
src/components/layout/Footer.vue
Executable file
49
src/components/layout/Footer.vue
Executable file
@@ -0,0 +1,49 @@
|
||||
<script setup lang="ts">
|
||||
import {ipcRenderer} from 'electron'
|
||||
import pkg from '../../../package.json'
|
||||
const v = pkg.version
|
||||
const jump = (scene: number)=>{
|
||||
switch (scene) {
|
||||
case 1:
|
||||
ipcRenderer.invoke('invoke_open_default_browser', {
|
||||
url: "https://github.com/putyy/res-downloader"
|
||||
})
|
||||
break;
|
||||
case 2:
|
||||
ipcRenderer.invoke('invoke_open_default_browser', {
|
||||
url: "https://s.gowas.cn"
|
||||
})
|
||||
break;
|
||||
case 3:
|
||||
ipcRenderer.invoke('invoke_open_default_browser', {
|
||||
url: "https://i.gowas.cn"
|
||||
})
|
||||
break;
|
||||
case 4:
|
||||
ipcRenderer.invoke('invoke_open_default_browser', {
|
||||
url: "https://github.com/putyy/res-downloader/issues"
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template lang="pug">
|
||||
div.line
|
||||
a.item 版本号: {{v}} 站长邮箱: putyy@qq.com
|
||||
a.item(@click="jump(1)") 软件源码
|
||||
a.item(@click="jump(2)") 云盘资源
|
||||
a.item(@click="jump(3)") chatgpt
|
||||
a.item(@click="jump(4)") 问题反馈
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.line{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
.item{
|
||||
padding: 0 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
27
src/components/layout/Index.vue
Executable file
27
src/components/layout/Index.vue
Executable file
@@ -0,0 +1,27 @@
|
||||
<script setup lang="ts">
|
||||
import {ref, provide} from 'vue'
|
||||
import Sidebar from './Sidebar.vue'
|
||||
import Footer from './Footer.vue'
|
||||
|
||||
const sidebarCollapse = ref(false)
|
||||
provide('sidebarCollapse', sidebarCollapse)
|
||||
|
||||
</script>
|
||||
<template lang="pug">
|
||||
el-container
|
||||
Sidebar
|
||||
el-container
|
||||
el-main
|
||||
router-view
|
||||
el-footer
|
||||
Footer
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.el-header {
|
||||
padding: 0;
|
||||
}
|
||||
.el-main {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
70
src/components/layout/Sidebar.vue
Executable file
70
src/components/layout/Sidebar.vue
Executable file
@@ -0,0 +1,70 @@
|
||||
<script setup lang="ts">
|
||||
import {inject, onMounted, ref, watch} from 'vue'
|
||||
import localStorageCache from "../../common/localStorage";
|
||||
|
||||
const appName = "资源下载器"
|
||||
const sidebarCollapse = ref(inject('sidebarCollapse'))
|
||||
const defaultActive = ref("/index")
|
||||
|
||||
onMounted(() => {
|
||||
let lastRoute = localStorageCache.get('last-route')
|
||||
defaultActive.value = lastRoute ? lastRoute : "/index"
|
||||
})
|
||||
</script>
|
||||
<template lang="pug">
|
||||
div.sidebar
|
||||
el-menu(class="menu" :collapse="sidebarCollapse" :default-active="defaultActive" router)
|
||||
div.logo
|
||||
img(src="../../assets/logo.png" width="32" height="32")
|
||||
span(v-show="!sidebarCollapse") {{appName}}
|
||||
el-menu-item(key="1" index="/index")
|
||||
el-icon
|
||||
VideoCamera
|
||||
span 拦截下载
|
||||
el-menu-item(key="7" index="/vip-parse")
|
||||
el-icon
|
||||
VideoCamera
|
||||
span 影视解析
|
||||
el-menu-item(key="2" index="/about")
|
||||
el-icon
|
||||
Share
|
||||
span 帮助
|
||||
el-menu-item(key="99" index="/setting")
|
||||
el-icon
|
||||
Setting
|
||||
span 设置
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.menu-icon {
|
||||
max-width: 1rem;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
height: 100vh;
|
||||
box-shadow: .2rem 0 .6rem 0 rgba(0, 0, 0, 0.1);
|
||||
.menu {
|
||||
border-right: unset;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
.logo {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
overflow: hidden;
|
||||
img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
span {
|
||||
color: #eab728;
|
||||
}
|
||||
}
|
||||
}
|
||||
.menu:not(.el-menu--collapse) {
|
||||
width: 10rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
8
src/env.d.ts
vendored
Executable file
8
src/env.d.ts
vendored
Executable file
@@ -0,0 +1,8 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
19
src/main.ts
Normal file
19
src/main.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import {Component, createApp} from 'vue'
|
||||
import "./style.css"
|
||||
import VueApp from './App.vue'
|
||||
import './samples/node-api'
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import 'element-plus/dist/index.css'
|
||||
import router from './route'
|
||||
|
||||
const app = createApp(VueApp)
|
||||
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, <Component>component)
|
||||
}
|
||||
|
||||
app.use(router)
|
||||
.mount('#app')
|
||||
.$nextTick(() => {
|
||||
postMessage({ payload: 'removeLoading' }, '*')
|
||||
})
|
||||
46
src/route.ts
Executable file
46
src/route.ts
Executable file
@@ -0,0 +1,46 @@
|
||||
import {createMemoryHistory, createRouter} from 'vue-router'
|
||||
// @ts-ignore
|
||||
import localStorageCache from "./common/localStorage"
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('./components/layout/Index.vue'),
|
||||
// 重定向
|
||||
redirect: {name: 'Index'},
|
||||
// 子路由
|
||||
children: [
|
||||
{
|
||||
path: '/index',
|
||||
name: 'Index',
|
||||
component: () => import('./views/Index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'about',
|
||||
component: () => import('./views/About.vue'),
|
||||
},
|
||||
{
|
||||
path: '/setting',
|
||||
name: 'Setting',
|
||||
component: () => import('./views/Setting.vue'),
|
||||
},
|
||||
{
|
||||
path: '/vip-parse',
|
||||
name: 'VipParse',
|
||||
component: () => import('./views/VipParse.vue'),
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes: routes,
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
export default router
|
||||
13
src/samples/node-api.ts
Normal file
13
src/samples/node-api.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { lstat } from 'node:fs/promises'
|
||||
import { cwd } from 'node:process'
|
||||
import { ipcRenderer } from 'electron'
|
||||
|
||||
ipcRenderer.on('main-process-message', (_event, ...args) => {
|
||||
console.log('[Receive Main-process message]:', ...args)
|
||||
})
|
||||
|
||||
lstat(cwd()).then(stats => {
|
||||
console.log('[fs.lstat]', stats)
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
})
|
||||
90
src/style.css
Normal file
90
src/style.css
Normal file
@@ -0,0 +1,90 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #ffffff;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #1a1a1a;
|
||||
padding: 2px 4px;
|
||||
margin: 0 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
/*margin: 0 auto;*/
|
||||
/*padding: 2rem;*/
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
code {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
54
src/views/About.vue
Normal file
54
src/views/About.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<script lang="ts" setup>
|
||||
import {ipcRenderer} from 'electron'
|
||||
const jump = (scene: number)=>{
|
||||
switch (scene) {
|
||||
case 1:
|
||||
ipcRenderer.invoke('invoke_open_default_browser', {
|
||||
url: "https://m3u8-down.gowas.cn/"
|
||||
})
|
||||
break;
|
||||
case 2:
|
||||
ipcRenderer.invoke('invoke_open_default_browser', {
|
||||
url: "https://www.baidu.com/s?wd=m3u8%E5%9C%A8%E7%BA%BF"
|
||||
})
|
||||
break;
|
||||
case 3:
|
||||
ipcRenderer.invoke('invoke_open_default_browser', {
|
||||
url: "https://github.com/putyy/res-downloader"
|
||||
})
|
||||
break;
|
||||
case 4:
|
||||
ipcRenderer.invoke('invoke_open_default_browser', {
|
||||
url: "https://github.com/putyy/res-downloader/issues"
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template lang="pug">
|
||||
div.about
|
||||
div 1. 本软件免费、源代码已经开源,不会以任何形式收取费用。
|
||||
el-button(@click="jump(3)") 查看源码
|
||||
div 2. m3u8复制的链接如何使用?
|
||||
el-button(@click="jump(1)") 在线下载
|
||||
el-button(@click="jump(2)") 在线播放
|
||||
div 3. 软件如何获取更新?
|
||||
el-button(@click="jump(3)") 获取更新
|
||||
div 4. 问题反馈
|
||||
el-button(@click="jump(4)") 点击前往
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.about{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
color: #ec8d13;
|
||||
.problem{
|
||||
padding: .3rem;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
295
src/views/Index.vue
Executable file
295
src/views/Index.vue
Executable file
@@ -0,0 +1,295 @@
|
||||
<script setup lang="ts">
|
||||
import {ref, onMounted} from "vue"
|
||||
import {ipcRenderer} from 'electron'
|
||||
import {onUnmounted} from "@vue/runtime-core"
|
||||
import {ElMessage} from "element-plus"
|
||||
import localStorageCache from "../common/localStorage"
|
||||
import {ElLoading} from 'element-plus'
|
||||
|
||||
const tableData = ref<{
|
||||
url_sign: string,
|
||||
url: string,
|
||||
size: any,
|
||||
platform: string,
|
||||
progress_bar: any,
|
||||
save_path: string,
|
||||
downing: boolean
|
||||
}[]>([])
|
||||
|
||||
const resType = ref({
|
||||
video: true,
|
||||
audio: true,
|
||||
image: false,
|
||||
m3u8: false
|
||||
})
|
||||
|
||||
|
||||
const isInitApp = ref(false)
|
||||
|
||||
const toSize = (size: number) => {
|
||||
if (size > 1048576) {
|
||||
return (size / 1048576).toFixed(2) + "MB"
|
||||
}
|
||||
if (size > 1024) {
|
||||
return (size / 1024).toFixed(2) + "KB"
|
||||
}
|
||||
return size + 'b'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
let resTypeCache = localStorageCache.get("res-type")
|
||||
if (resTypeCache) {
|
||||
resType.value = resTypeCache
|
||||
}
|
||||
|
||||
let tableDataCache = localStorageCache.get("res-table-data")
|
||||
if (tableDataCache) {
|
||||
tableData.value = tableDataCache
|
||||
}
|
||||
|
||||
ipcRenderer.invoke('invoke_app_is_init').then((isInit: boolean) => {
|
||||
if (!isInit) {
|
||||
isInitApp.value = true
|
||||
ipcRenderer.invoke('invoke_init_app')
|
||||
}
|
||||
})
|
||||
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: 'Loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
})
|
||||
|
||||
ipcRenderer.invoke('invoke_start_proxy').then(() => {
|
||||
loading.close()
|
||||
ipcRenderer.on('on_get_queue', (res, data) => {
|
||||
// @ts-ignore
|
||||
if (resType.value.hasOwnProperty(data.type_str) && resType.value[data.type_str]) {
|
||||
tableData.value.push(data)
|
||||
localStorageCache.set("res-table-data", tableData.value, -1)
|
||||
}
|
||||
return
|
||||
})
|
||||
}).catch((err) => {
|
||||
// console.log('invoke_start_proxy err', err)
|
||||
ElMessage({
|
||||
message: err,
|
||||
type: 'warning',
|
||||
})
|
||||
loading.close()
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
ipcRenderer.removeListener('on_get_queue', (res) => {
|
||||
// console.log(res)
|
||||
})
|
||||
|
||||
ipcRenderer.invoke('invoke_close_proxy').then((res) => {
|
||||
})
|
||||
localStorageCache.set("res-table-data", tableData.value, -1)
|
||||
localStorageCache.set("res-type", resType.value, -1)
|
||||
})
|
||||
|
||||
|
||||
const handleDown = async (index: number, row: any, high: boolean) => {
|
||||
|
||||
let save_dir = localStorageCache.get("save_dir")
|
||||
|
||||
if (!save_dir) {
|
||||
ElMessage({
|
||||
message: '请设置保存目录',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
let loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: 'Loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
})
|
||||
|
||||
let result = await ipcRenderer.invoke('invoke_file_exists', {
|
||||
save_path: save_dir,
|
||||
url: (high && row.high_url) ? row.high_url : row.url,
|
||||
})
|
||||
|
||||
if (result.is_file) {
|
||||
tableData.value[index].progress_bar = "100%"
|
||||
tableData.value[index].save_path = result.fileName
|
||||
ElMessage({
|
||||
message: "文件已存在(" + result.fileName + ")",
|
||||
type: 'warning',
|
||||
})
|
||||
loading.close()
|
||||
return
|
||||
}
|
||||
|
||||
ipcRenderer.invoke('invoke_down_file', {
|
||||
index: index,
|
||||
data: Object.assign({}, tableData.value[index]),
|
||||
save_path: save_dir,
|
||||
high: high
|
||||
}).then((res) => {
|
||||
if (res !== false) {
|
||||
tableData.value[index].progress_bar = "100%"
|
||||
tableData.value[index].save_path = res.fullFileName
|
||||
}else{
|
||||
ElMessage({
|
||||
message: "下载失败",
|
||||
type: 'warning',
|
||||
})
|
||||
}
|
||||
loading.close()
|
||||
}).catch((err) => {
|
||||
// console.log('invoke_down_file err', err)
|
||||
ElMessage({
|
||||
message: "下载失败",
|
||||
type: 'warning',
|
||||
})
|
||||
loading.close()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const handlePreview = (index: number, row: any) => {
|
||||
// console.log('row.down_url',row)
|
||||
ipcRenderer.invoke('invoke_resources_preview', {url: row.down_url}).catch(() => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleClear = () => {
|
||||
tableData.value = []
|
||||
localStorageCache.del("res-table-data")
|
||||
}
|
||||
|
||||
const handleCopy = (text: string) => {
|
||||
let el = document.createElement('input')
|
||||
el.setAttribute('value', text)
|
||||
document.body.appendChild(el)
|
||||
el.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(el)
|
||||
ElMessage({
|
||||
message: "复制成功",
|
||||
type: 'success',
|
||||
})
|
||||
}
|
||||
|
||||
const handleDel = (index: number)=>{
|
||||
let arr = tableData.value
|
||||
arr.splice(index, 1);
|
||||
tableData.value = arr
|
||||
}
|
||||
|
||||
const openDir = ()=>{
|
||||
let save_dir = localStorageCache.get("save_dir")
|
||||
|
||||
if (!save_dir) {
|
||||
ElMessage({
|
||||
message: '目录不存在',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ipcRenderer.invoke('invoke_open_dir', {
|
||||
dir: save_dir
|
||||
})
|
||||
}
|
||||
|
||||
const handleInitApp = () => {
|
||||
ipcRenderer.invoke('invoke_app_is_init').then((isInit: boolean) => {
|
||||
if (isInit) {
|
||||
isInitApp.value = false
|
||||
} else {
|
||||
ipcRenderer.invoke('invoke_init_app')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template lang="pug">
|
||||
el-container.container
|
||||
el-header
|
||||
el-row
|
||||
div
|
||||
el-button(v-if="isInitApp" @click="handleInitApp")
|
||||
el-icon
|
||||
Promotion
|
||||
p 安装检测(如果看到此按钮说明软件安装未完成则需要手动点击此按钮)
|
||||
el-button(@click="handleClear")
|
||||
el-icon
|
||||
Delete
|
||||
p 清空
|
||||
el-button(@click="resType.video=!resType.video" :type="resType.video ? 'primary' : 'info'" ) 视频
|
||||
el-button(@click="resType.audio=!resType.audio" :type="resType.audio ? 'primary' : 'info'" ) 音频
|
||||
el-button(@click="resType.image=!resType.image" :type="resType.image ? 'primary' : 'info'" ) 图片
|
||||
el-button(@click="resType.m3u8=!resType.m3u8" :type="resType.m3u8 ? 'primary' : 'info'" ) m3u8
|
||||
a(style="color: red") 点击左边选项,选择需要拦截的资源类型
|
||||
el-main
|
||||
el-table(:data="tableData" max-height="100%" stripe style="max-content")
|
||||
el-table-column(label="预览" show-overflow-tooltip width="350px" )
|
||||
template(#default="scope" )
|
||||
div.show_res
|
||||
video(v-if="scope.row.type_str === 'video'" :src="scope.row.down_url" controls preload="none" style="width: 100%;height: auto;") 您的浏览器不支持 video 标签。
|
||||
img.img(v-if="scope.row.type_str === 'image'" :src="scope.row.down_url")
|
||||
audio(v-if="scope.row.type_str === 'audio'" controls preload="none")
|
||||
source(:src="scope.row.down_url" :type="scope.row.type")
|
||||
el-table-column(prop="type_str" label="类型" show-overflow-tooltip)
|
||||
el-table-column(prop="platform" label="主机地址")
|
||||
el-table-column(prop="size" label="资源大小")
|
||||
el-table-column(prop="save_path" label="保存目录")
|
||||
el-table-column(label="操作")
|
||||
template(#default="scope")
|
||||
template(v-if="scope.row.type_str !== 'm3u8'" )
|
||||
el-button(v-if="!scope.row.save_path" link type="primary" @click="handleDown(scope.$index, scope.row, false)") 下载
|
||||
el-button(v-if="!scope.row.save_path && scope.row.high_url !='' " link type="primary" @click="handleDown(scope.$index, scope.row, true)") 高清下载
|
||||
el-button(link type="primary" @click="handlePreview(scope.$index, scope.row)") 窗口预览
|
||||
el-button(link type="primary" @click="handleCopy(scope.row.down_url)") 复制链接
|
||||
el-button(link type="primary" @click="handleDel(scope.$index)") 删 除
|
||||
el-button(link type="primary" @click="openDir()") 打开目录
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
.container {
|
||||
padding: 0.5rem;
|
||||
|
||||
.el-button {
|
||||
margin: 0.1rem;
|
||||
}
|
||||
|
||||
.el-button p {
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.el-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
header {
|
||||
height: unset !important;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.select-dir {
|
||||
background: #fff5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.show_res{
|
||||
.img{
|
||||
width: 100px;
|
||||
height: auto;
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
36
src/views/Setting.vue
Executable file
36
src/views/Setting.vue
Executable file
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import {ipcRenderer} from "electron";
|
||||
import localStorageCache from "../common/localStorage";
|
||||
import {ElMessage} from "element-plus";
|
||||
|
||||
onMounted(() => {
|
||||
saveDir.value = localStorageCache.get("save_dir")
|
||||
saveDir.value = !saveDir.value ? "" : saveDir.value
|
||||
})
|
||||
|
||||
const saveDir = ref("")
|
||||
const selectSaveDir = () => {
|
||||
ipcRenderer.invoke('invoke_select_down_dir').then(save_path => {
|
||||
if (save_path !== false) {
|
||||
saveDir.value = save_path
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const onSetting = () => {
|
||||
localStorageCache.set("save_dir", saveDir.value, -1)
|
||||
ElMessage({
|
||||
message: "操作成功",
|
||||
type: 'success',
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<template lang="pug">
|
||||
el-form
|
||||
el-form-item(label="保存位置")
|
||||
el-button.select-dir(@click="selectSaveDir") {{saveDir ? saveDir : '选择'}}
|
||||
el-form-item
|
||||
el-button(type="primary" @click="onSetting") 保存
|
||||
</template>
|
||||
99
src/views/VipParse.vue
Executable file
99
src/views/VipParse.vue
Executable file
@@ -0,0 +1,99 @@
|
||||
<script lang="ts" setup>
|
||||
import {onMounted, ref} from "vue"
|
||||
import {ElMessage} from "element-plus"
|
||||
import {ipcRenderer} from 'electron'
|
||||
import {onUnmounted} from "@vue/runtime-core"
|
||||
import localStorageCache from "../common/localStorage"
|
||||
|
||||
const parseUrls = ref([
|
||||
"https://www.8090g.cn/jiexi/?url=",
|
||||
"https://jx.m3u8.tv/jiexi/?url=",
|
||||
"https://www.playm3u8.cn/jiexi.php?url=",
|
||||
"https://www.8090.la/8090/?url=",
|
||||
"https://jx.xmflv.com/?url=",
|
||||
"https://www.8090g.cn/?url=",
|
||||
"https://dm.xmflv.com:4433/?url=",
|
||||
])
|
||||
|
||||
const useParseUrl = ref("")
|
||||
const playUrl = ref("")
|
||||
const iframeSrc = ref("")
|
||||
const descText = ref(
|
||||
"支持各大视频付费、VIP电影电视剧解析免费观看: 爱奇艺、优酷、腾讯、乐视、土豆、芒果等\r\n若视频播放异常或时长不对,请尝试【更换线路】或【退出软件重新打开】即可解决!\r\n如有线路不行,请把页面拉倒最下方,发邮件给站长!"
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
useParseUrl.value = parseUrls.value[0]
|
||||
let dataCache = localStorageCache.get("res-vip-parse-data")
|
||||
if (dataCache) {
|
||||
useParseUrl.value = dataCache.useParseUrl
|
||||
playUrl.value = dataCache.playUrl
|
||||
// iframeSrc.value = useParseUrl.value + encodeURI(playUrl.value)
|
||||
}
|
||||
})
|
||||
|
||||
const parsePlay = () => {
|
||||
if (!playUrl) {
|
||||
ElMessage({
|
||||
message: "请填写播放地址",
|
||||
type: 'warning',
|
||||
})
|
||||
return
|
||||
}
|
||||
iframeSrc.value = useParseUrl.value + encodeURI(playUrl.value)
|
||||
}
|
||||
|
||||
const parseFullPlay = () => {
|
||||
if (!playUrl) {
|
||||
ElMessage({
|
||||
message: "请填写播放地址",
|
||||
type: 'warning',
|
||||
})
|
||||
return
|
||||
}
|
||||
ipcRenderer.invoke('invoke_resources_preview', {url: useParseUrl.value + encodeURI(playUrl.value)}).catch(() => {
|
||||
})
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
localStorageCache.set("res-vip-parse-data", {useParseUrl: useParseUrl.value, playUrl: playUrl.value}, -1)
|
||||
})
|
||||
|
||||
</script>
|
||||
<template lang="pug">
|
||||
el-main.play-box
|
||||
iframe.iframe(:src="iframeSrc")
|
||||
el-form
|
||||
el-form-item(label="线路选择:")
|
||||
el-select(v-model="useParseUrl")
|
||||
el-option(v-for="(v, k) in parseUrls" :value="v" :label="'线路'+(k+1)")
|
||||
el-form-item(label="播放地址:")
|
||||
el-input(v-model="playUrl" type="textarea" placeholder="爱奇艺、优酷、腾讯、芒果、乐视、土豆")
|
||||
el-form-item
|
||||
el-button(type="primary" @click="parsePlay()") 立即播放
|
||||
el-button(type="primary" @click="parseFullPlay()") 全屏播放
|
||||
el-row.desc {{descText}}
|
||||
</template>
|
||||
<style scoped lang="less">
|
||||
.play-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.iframe {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border: 0;
|
||||
background-color: #211f1f;
|
||||
width: 100%;
|
||||
height: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: red;
|
||||
font-size: 20px;
|
||||
white-space: pre-wrap;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
7
src/vite-env.d.ts
vendored
Normal file
7
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
10
tsconfig.node.json
Normal file
10
tsconfig.node.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts", "package.json", "electron"]
|
||||
}
|
||||
81
vite.config.ts
Normal file
81
vite.config.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { rmSync } from 'node:fs'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import electron from 'vite-plugin-electron'
|
||||
import renderer from 'vite-plugin-electron-renderer'
|
||||
import pkg from './package.json'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import {ElementPlusResolver} from 'unplugin-vue-components/resolvers'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ command }) => {
|
||||
rmSync('dist-electron', { recursive: true, force: true })
|
||||
|
||||
const isServe = command === 'serve'
|
||||
const isBuild = command === 'build'
|
||||
const sourcemap = isServe || !!process.env.VSCODE_DEBUG
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
vue(),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
electron([
|
||||
{
|
||||
// Main-Process entry file of the Electron App.
|
||||
entry: 'electron/main/index.ts',
|
||||
onstart(options) {
|
||||
if (process.env.VSCODE_DEBUG) {
|
||||
console.log(/* For `.vscode/.debug.script.mjs` */'[startup] Electron App')
|
||||
} else {
|
||||
options.startup()
|
||||
}
|
||||
},
|
||||
vite: {
|
||||
build: {
|
||||
sourcemap,
|
||||
minify: isBuild,
|
||||
outDir: 'dist-electron/main',
|
||||
rollupOptions: {
|
||||
external: Object.keys('dependencies' in pkg ? pkg.dependencies : {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
entry: 'electron/preload/index.ts',
|
||||
onstart(options) {
|
||||
// Notify the Renderer-Process to reload the page when the Preload-Scripts build is complete,
|
||||
// instead of restarting the entire Electron App.
|
||||
options.reload()
|
||||
},
|
||||
vite: {
|
||||
build: {
|
||||
sourcemap: sourcemap ? 'inline' : undefined, // #332
|
||||
minify: isBuild,
|
||||
outDir: 'dist-electron/preload',
|
||||
rollupOptions: {
|
||||
external: Object.keys('dependencies' in pkg ? pkg.dependencies : {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
]),
|
||||
// Use Node.js API in the Renderer-process
|
||||
renderer(),
|
||||
],
|
||||
server: process.env.VSCODE_DEBUG && (() => {
|
||||
const url = new URL(pkg.debug.env.VITE_DEV_SERVER_URL)
|
||||
return {
|
||||
host: url.hostname,
|
||||
port: +url.port,
|
||||
}
|
||||
})(),
|
||||
clearScreen: false,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user