1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-24 20:19:10 +02:00

Compare commits

...

23 Commits

Author SHA1 Message Date
Laurent Cozic
169acace66 Tools: Improve git-changelog tag detection 2023-06-06 10:50:22 +01:00
Laurent Cozic
d2104a3ba1 Desktop release v2.10.20 2023-06-06 10:38:26 +01:00
Laurent Cozic
0b291915d5 Desktop, Mobile: Security: Disable SVG tag support in editor to prevent XSS 2023-06-06 10:38:10 +01:00
Laurent Cozic
b2285d4392 All: Security: Prevent XSS by sanitizing certain HTML attributes 2023-06-06 10:37:59 +01:00
Laurent Cozic
b8f1f8579e Desktop: Prevent double-initialisation of plugins 2023-06-06 10:36:50 +01:00
Laurent Cozic
609335aa5f Desktop: Fixes #7484: Window is white on startup 2023-06-06 10:36:44 +01:00
Laurent Cozic
1100ab0d6d Desktop release v2.10.19 2023-05-17 12:47:19 +01:00
Laurent Cozic
d4c43a8b67 Desktop, Server: Improved handling of items with duplicate IDs 2023-05-17 12:46:34 +01:00
Laurent Cozic
737ba82550 Desktop: Security: Fixed possible XSS injection 2023-05-17 12:46:28 +01:00
Laurent Cozic
09d7ddeb0f Desktop: Security: Prevent XSS and potential RCE when using a special HTML tag 2023-05-17 12:46:13 +01:00
Laurent Cozic
c67f5facd1 Desktop release v2.10.18 2023-05-09 13:45:35 +01:00
Laurent Cozic
8adfea6eca Desktop: Fixes #8149: Application cannot be installed on Windows 10 in some cases 2023-05-09 13:45:08 +01:00
Laurent Cozic
f2c13aa7e8 Desktop: Fixes #8149: Application cannot be installed on Windows 10 in some cases 2023-05-09 11:16:38 +01:00
Laurent Cozic
23d492f79e Desktop release v2.10.17 2023-05-08 17:12:29 +01:00
Laurent Cozic
346a9c6b17 Desktop: Fixes #8072: Enter Key No Longer Saves and Closes The Tag Dialog 2023-05-08 17:11:58 +01:00
Laurent Cozic
3b836fdd61 Desktop: Fixes #8143: Fixes crash when using multiple profiles along with certain plugins 2023-05-08 17:10:32 +01:00
Laurent Cozic
f0afffedc9 Desktop: Fixes #8143: Fixes crash when using multiple profiles along with certain plugins 2023-05-08 17:10:20 +01:00
Laurent Cozic
6d8374885c Desktop release v2.10.16 2023-04-27 09:28:27 +01:00
Laurent Cozic
2e2feaba3d Desktop: Revert to "normal" package compression 2023-04-27 09:28:11 +01:00
Laurent Cozic
b84fc1c8b0 Desktop release v2.10.15 2023-04-26 21:49:44 +01:00
Laurent Cozic
18fef2d9df Desktop: Resolves #8028: Remove custom PDF viewer to reduce application size 2023-04-26 21:49:17 +01:00
Laurent Cozic
dfd0c40982 Desktop release v2.10.14 2023-04-26 12:23:05 +01:00
Arun Kumar
b514ca7e7d Desktop: Resolves #8028: Compress installer to reduce size (#8068) 2023-04-26 12:19:34 +01:00
28 changed files with 461 additions and 219 deletions

View File

@@ -183,7 +183,12 @@ if [[ $GIT_TAG_NAME = v* ]]; then
# cd "$ROOT_DIR/packages/tools"
# node bundleDefaultPlugins.js
cd "$ROOT_DIR/packages/app-desktop"
USE_HARD_LINKS=false yarn run dist
if [ "$IS_MACOS" == "1" ]; then
PYTHON_PATH=$(which python) USE_HARD_LINKS=false yarn run dist
else
USE_HARD_LINKS=false yarn run dist
fi
elif [[ $IS_LINUX = 1 ]] && [[ $GIT_TAG_NAME = $SERVER_TAG_PREFIX-* ]]; then
echo "Step: Building Docker Image..."
cd "$ROOT_DIR"

View File

@@ -35,7 +35,7 @@ describe('MdToHtml', () => {
const mdFilePath = `${basePath}/${mdFilename}`;
const htmlPath = `${basePath}/${filename(mdFilePath)}.html`;
// if (mdFilename !== 'sanitize_9.md') continue;
if (mdFilename !== 'sanitize_15.md') continue;
const mdToHtmlOptions: any = {
bodyOnly: true,

View File

@@ -0,0 +1 @@
<div class="jop-noMdConv"><svg class="jop-noMdConv"><style class="jop-noMdConv">&lt;/svg>&lt;iframe srcdoc="&lt;script>top.require('child_process').execSync('calc')&lt;/script>">&lt;/iframe>&lt;/div>

View File

@@ -0,0 +1 @@
<div><svg><style></svg><iframe srcdoc="<script>top.require('child_process').execSync('calc')</script>"></iframe></div>

View File

@@ -0,0 +1 @@
<a href="#" class="jop-noMdConv">XSS</a>

View File

@@ -0,0 +1 @@
<a data-from-md="" href="javascript:top.require('child_process').execSync('open -a Calculator')">XSS</a>

View File

@@ -0,0 +1 @@
<use href="data:image/svg+xml,&lt;svg id=&apos;x&apos; xmlns=&apos;http://www.w3.org/2000/svg&apos;&gt;&lt;image href=&apos;asdf&apos; onerror=&apos;top.require(`child_process`).execSync(`calc.exe`)&apos; /&gt;&lt;/svg&gt;#x" class="jop-noMdConv">

View File

@@ -0,0 +1 @@
<svg><use href="data:image/svg+xml,&lt;svg id='x' xmlns='http://www.w3.org/2000/svg'&gt;&lt;image href='asdf' onerror='top.require(`child_process`).execSync(`calc.exe`)' /&gt;&lt;/svg&gt;#x" />

After

Width:  |  Height:  |  Size: 193 B

View File

@@ -0,0 +1 @@
<map name="test" class="jop-noMdConv"><area coords="0,0,1000,1000" href="#" class="jop-noMdConv"/></map><img usemap="#test" src="https://github.com/Ry0taK.png" class="jop-noMdConv"/>

View File

@@ -0,0 +1 @@
<map name="test"><area coords="0,0,1000,1000" href="javascript:top.require(`child_process`).execSync(`calc.exe`)"></map><img usemap="#test" src="https://github.com/Ry0taK.png">

View File

@@ -80,6 +80,7 @@ const appDefaultState = createAppDefaultState(
class Application extends BaseApplication {
private checkAllPluginStartedIID_: any = null;
private initPluginServiceDone_: boolean = false;
public constructor() {
super();
@@ -258,6 +259,9 @@ class Application extends BaseApplication {
}
private async initPluginService() {
if (this.initPluginServiceDone_) return;
this.initPluginServiceDone_ = true;
const service = PluginService.instance();
const pluginRunner = new PluginRunner();
@@ -553,7 +557,15 @@ class Application extends BaseApplication {
bridge().addEventListener('nativeThemeUpdated', this.bridge_nativeThemeUpdated);
await this.initPluginService();
// We need to delay plugin initialisation until the main screen is
// ready. Otherwise plugins might try to modify the application layout,
// which will cause an error related to an empty layout item. This in
// turns will cause the screen to go white on startup.
//
// https://discourse.joplinapp.org/t/upgrade-produces-blank-window/31138/8
eventManager.on('mainScreenReady', () => {
void this.initPluginService();
});
this.setupContextMenu();

View File

@@ -46,6 +46,7 @@ import PromptDialog from '../PromptDialog';
import NotePropertiesDialog from '../NotePropertiesDialog';
const PluginManager = require('@joplin/lib/services/PluginManager');
const ipcRenderer = require('electron').ipcRenderer;
import eventManager from '@joplin/lib/eventManager';
interface LayerModalState {
visible: boolean;
@@ -391,6 +392,7 @@ class MainScreenComponent extends React.Component<Props, State> {
componentDidMount() {
window.addEventListener('keydown', this.layoutModeListenerKeyDown);
eventManager.emit('mainScreenReady');
}
componentWillUnmount() {

View File

@@ -631,7 +631,7 @@ const mapStateToProps = (state: AppState) => {
], whenClauseContext)[0],
contentMaxWidth: state.settings['style.editor.contentMaxWidth'],
isSafeMode: state.settings.isSafeMode,
useCustomPdfViewer: state.settings.useCustomPdfViewer,
useCustomPdfViewer: false, // state.settings.useCustomPdfViewer,
};
};

View File

@@ -26,11 +26,15 @@ export default class PromptDialog extends React.Component<Props, any> {
private focusInput_: boolean;
private styles_: any;
private styleKey_: string;
private menuIsOpened_: boolean = false;
constructor(props: Props) {
super(props);
this.answerInput_ = React.createRef();
this.select_menuOpen = this.select_menuOpen.bind(this);
this.select_menuClose = this.select_menuClose.bind(this);
}
UNSAFE_componentWillMount() {
@@ -39,6 +43,7 @@ export default class PromptDialog extends React.Component<Props, any> {
answer: this.props.defaultValue ? this.props.defaultValue : '',
});
this.focusInput_ = true;
this.menuIsOpened_ = false;
}
UNSAFE_componentWillReceiveProps(newProps: Props) {
@@ -52,7 +57,15 @@ export default class PromptDialog extends React.Component<Props, any> {
}
}
componentDidUpdate() {
private select_menuOpen() {
this.menuIsOpened_ = true;
}
private select_menuClose() {
this.menuIsOpened_ = false;
}
public componentDidUpdate() {
if (this.focusInput_ && this.answerInput_.current) this.answerInput_.current.focus();
this.focusInput_ = false;
}
@@ -224,16 +237,14 @@ export default class PromptDialog extends React.Component<Props, any> {
const onKeyDown = (event: any) => {
if (event.key === 'Enter') {
if (this.props.inputType === 'tags' || this.props.inputType === 'dropdown') {
// If the dropdown is open, we don't close the dialog - instead
// the currently item will be selcted. If it is closed however
// we confirm the dialog.
if ((this.props.inputType === 'tags' || this.props.inputType === 'dropdown') && this.menuIsOpened_) {
// Do nothing
} else {
onClose(true);
}
// } else if (this.answerInput_.current && !this.answerInput_.current.state.menuIsOpen) {
// // The menu will be open if the user is selecting a new item
// onClose(true);
// }
} else if (event.key === 'Escape') {
onClose(false);
}
@@ -246,9 +257,9 @@ export default class PromptDialog extends React.Component<Props, any> {
if (this.props.inputType === 'datetime') {
inputComp = <Datetime className="datetime-picker" value={this.state.answer} inputProps={{ style: styles.input }} dateFormat={time.dateFormat()} timeFormat={time.timeFormat()} onChange={(momentObject: any) => onDateTimeChange(momentObject)} />;
} else if (this.props.inputType === 'tags') {
inputComp = <CreatableSelect className="tag-selector" styles={styles.select} theme={styles.selectTheme} ref={this.answerInput_} value={this.state.answer} placeholder="" components={makeAnimated()} isMulti={true} isClearable={false} backspaceRemovesValue={true} options={this.props.autocomplete} onChange={onSelectChange} onKeyDown={(event: any) => onKeyDown(event)} />;
inputComp = <CreatableSelect className="tag-selector" onMenuOpen={this.select_menuOpen} onMenuClose={this.select_menuClose} styles={styles.select} theme={styles.selectTheme} ref={this.answerInput_} value={this.state.answer} placeholder="" components={makeAnimated()} isMulti={true} isClearable={false} backspaceRemovesValue={true} options={this.props.autocomplete} onChange={onSelectChange} onKeyDown={(event: any) => onKeyDown(event)} />;
} else if (this.props.inputType === 'dropdown') {
inputComp = <Select className="item-selector" styles={styles.select} theme={styles.selectTheme} ref={this.answerInput_} components={makeAnimated()} value={this.props.answer} defaultValue={this.props.defaultValue} isClearable={false} options={this.props.autocomplete} onChange={onSelectChange} onKeyDown={(event: any) => onKeyDown(event)} />;
inputComp = <Select className="item-selector" onMenuOpen={this.select_menuOpen} onMenuClose={this.select_menuClose} styles={styles.select} theme={styles.selectTheme} ref={this.answerInput_} components={makeAnimated()} value={this.props.answer} defaultValue={this.props.defaultValue} isClearable={false} options={this.props.autocomplete} onChange={onSelectChange} onKeyDown={(event: any) => onKeyDown(event)} />;
} else {
inputComp = <input style={styles.input} ref={this.answerInput_} value={this.state.answer} type="text" onChange={event => onChange(event)} onKeyDown={event => onKeyDown(event)} />;
}

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "2.10.13",
"version": "2.10.20",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,
@@ -27,6 +27,7 @@
},
"build": {
"appId": "net.cozic.joplin-desktop",
"compression": "normal",
"productName": "Joplin",
"npmRebuild": false,
"afterSign": "./tools/notarizeMacApp.js",
@@ -115,7 +116,7 @@
"@types/react-redux": "7.1.25",
"@types/styled-components": "5.1.26",
"electron": "19.1.4",
"electron-builder": "23.6.0",
"electron-builder": "22.11.7",
"electron-notarize": "1.2.2",
"electron-rebuild": "3.2.9",
"glob": "8.1.0",
@@ -137,7 +138,6 @@
"@fortawesome/fontawesome-free": "5.15.4",
"@joeattardi/emoji-button": "4.6.4",
"@joplin/lib": "~2.10",
"@joplin/pdf-viewer": "~2.10",
"@joplin/renderer": "~2.10",
"async-mutex": "0.4.0",
"codemirror": "5.65.9",

View File

@@ -72,10 +72,10 @@ async function main() {
src: langSourceDir,
dest: `${buildLibDir}/tinymce/langs`,
},
{
src: resolve(__dirname, '../../pdf-viewer/dist'),
dest: `${buildLibDir}/@joplin/pdf-viewer`,
},
// {
// src: resolve(__dirname, '../../pdf-viewer/dist'),
// dest: `${buildLibDir}/@joplin/pdf-viewer`,
// },
];
const files = [
@@ -93,10 +93,10 @@ async function main() {
src: resolve(__dirname, '../../lib/services/plugins/sandboxProxy.js'),
dest: `${buildLibDir}/@joplin/lib/services/plugins/sandboxProxy.js`,
},
{
src: resolve(__dirname, '../../pdf-viewer/index.html'),
dest: `${buildLibDir}/@joplin/pdf-viewer/index.html`,
},
// {
// src: resolve(__dirname, '../../pdf-viewer/index.html'),
// dest: `${buildLibDir}/@joplin/pdf-viewer/index.html`,
// },
];
// First we delete all the destination directories, then we copy the files.

View File

@@ -45,12 +45,13 @@ export default class JoplinServerApi {
private options_: Options;
private session_: Session;
private debugRequests_: boolean = false;
private debugRequestsShowPasswords_: boolean = false;
public constructor(options: Options) {
this.options_ = options;
if (options.env === Env.Dev) {
// this.debugRequests_ = true;
if (options.env !== Env.Dev) {
this.debugRequestsShowPasswords_ = false;
}
}
@@ -97,15 +98,15 @@ export default class JoplinServerApi {
try {
const output = JSON.parse(o);
if (!output) return o;
if (output.password) output.password = '******';
if (output.password && !this.debugRequestsShowPasswords_) output.password = '******';
return JSON.stringify(output);
} catch (error) {
return o;
}
} else {
const output = { ...o };
if (output.password) output.password = '******';
if (output['X-API-AUTH']) output['X-API-AUTH'] = '******';
if (output.password && !this.debugRequestsShowPasswords_) output.password = '******';
if (output['X-API-AUTH'] && !this.debugRequestsShowPasswords_) output['X-API-AUTH'] = '******';
return output;
}
}

View File

@@ -175,6 +175,10 @@ export default class FileApiDriverJoplinServer {
// they can have names such as ".resources/xxxxxxxxxx'
}
private isRejectedBySyncTargetError(error: any) {
return error.code === 413 || error.code === 409 || error.httpCode === 413 || error.httpCode === 409;
}
public async put(path: string, content: any, options: any = null) {
try {
const output = await this.api().exec('PUT', `${this.apiFilePath_(path)}/content`, options && options.shareId ? { share_id: options.shareId } : null, content, {
@@ -182,7 +186,7 @@ export default class FileApiDriverJoplinServer {
}, options);
return output;
} catch (error) {
if (error.code === 413) {
if (this.isRejectedBySyncTargetError(error)) {
throw new JoplinError(error.message, 'rejectedByTarget');
}
throw error;
@@ -190,7 +194,15 @@ export default class FileApiDriverJoplinServer {
}
public async multiPut(items: MultiPutItem[], options: any = null) {
return this.api().exec('PUT', 'api/batch_items', null, { items: items }, null, options);
const output = await this.api().exec('PUT', 'api/batch_items', null, { items: items }, null, options);
for (const [, response] of Object.entries<any>(output.items)) {
if (response.error && this.isRejectedBySyncTargetError(response.error)) {
response.error.code = 'rejectedByTarget';
}
}
return output;
}
public async delete(path: string) {

View File

@@ -1,4 +1,4 @@
import Setting, { SettingSectionSource, SettingStorage } from '../models/Setting';
import Setting, { SettingItemType, SettingSectionSource, SettingStorage } from '../models/Setting';
import { setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow, msleep } from '../testing/test-utils';
import { readFile, stat, mkdirp, writeFile, pathExists, readdir } from 'fs-extra';
import Logger from '../Logger';
@@ -297,12 +297,21 @@ describe('models/Setting', () => {
expect(Setting.isSet('spellChecker.languages')).toBe(false);
}));
it('should load sub-profile settings - 1', async () => {
it('should load sub-profile settings', async () => {
await Setting.reset();
await Setting.registerSetting('non_builtin', {
public: true,
storage: SettingStorage.File,
isGlobal: true,
type: SettingItemType.Bool,
value: false,
});
Setting.setValue('locale', 'fr_FR'); // Global setting
Setting.setValue('theme', Setting.THEME_DARK); // Global setting
Setting.setValue('sync.target', 9); // Local setting
Setting.setValue('non_builtin', true); // Local setting
await Setting.saveAll();
await switchToSubProfileSettings();
@@ -311,6 +320,9 @@ describe('models/Setting', () => {
expect(Setting.value('theme')).toBe(Setting.THEME_DARK); // Should come from the root profile
expect(Setting.value('sync.target')).toBe(0); // Should come from the local profile
// Non-built-in variables are not copied
expect(() => Setting.value('non_builtin')).toThrow();
// Also check that the special loadOne() function works as expected
expect((await Setting.loadOne('locale')).value).toBe('fr_FR');
@@ -318,7 +330,7 @@ describe('models/Setting', () => {
expect((await Setting.loadOne('sync.target')).value).toBe(undefined);
});
it('should save sub-profile settings - 2', async () => {
it('should save sub-profile settings', async () => {
await Setting.reset();
Setting.setValue('locale', 'fr_FR'); // Global setting
Setting.setValue('theme', Setting.THEME_DARK); // Global setting

View File

@@ -9,6 +9,7 @@ import FileHandler, { SettingValues } from './settings/FileHandler';
import Logger from '../Logger';
import mergeGlobalAndLocalSettings from '../services/profileConfig/mergeGlobalAndLocalSettings';
import splitGlobalAndLocalSettings from '../services/profileConfig/splitGlobalAndLocalSettings';
import JoplinError from '../JoplinError';
const { sprintf } = require('sprintf-js');
const ObjectUtils = require('../ObjectUtils');
const { toTitleCase } = require('../string-utils.js');
@@ -312,6 +313,7 @@ class Setting extends BaseModel {
private static fileHandler_: FileHandler = null;
private static rootFileHandler_: FileHandler = null;
private static settingFilename_: string = 'settings.json';
private static buildInMetadata_: SettingItems = null;
static tableName() {
return 'settings';
@@ -406,7 +408,7 @@ class Setting extends BaseModel {
return output;
};
this.metadata_ = {
this.buildInMetadata_ = {
'clientId': {
value: '',
type: SettingItemType.String,
@@ -1384,7 +1386,7 @@ class Setting extends BaseModel {
useCustomPdfViewer: {
value: false,
type: SettingItemType.Bool,
public: true,
public: false,
advanced: true,
appTypes: [AppType.Desktop],
label: () => 'Use custom PDF viewer (Beta)',
@@ -1685,6 +1687,8 @@ class Setting extends BaseModel {
};
this.metadata_ = { ...this.buildInMetadata_ };
this.metadata_ = Object.assign(this.metadata_, this.customMetadata_);
if (this.constants_.env === Env.Dev) this.validateMetadata(this.metadata_);
@@ -1698,6 +1702,10 @@ class Setting extends BaseModel {
}
}
public static isBuiltinKey(key: string): boolean {
return key in this.buildInMetadata_;
}
public static customCssFilePath(filename: string): string {
return `${this.value('rootProfileDir')}/${filename}`;
}
@@ -1799,7 +1807,7 @@ class Setting extends BaseModel {
static settingMetadata(key: string): SettingItem {
const metadata = this.metadata();
if (!(key in metadata)) throw new Error(`Unknown key: ${key}`);
if (!(key in metadata)) throw new JoplinError(`Unknown key: ${key}`, 'unknown_key');
const output = Object.assign({}, metadata[key]);
output.key = key;
return output;
@@ -2244,7 +2252,7 @@ class Setting extends BaseModel {
static enumOptions(key: string) {
const metadata = this.metadata();
if (!metadata[key]) throw new Error(`Unknown key: ${key}`);
if (!metadata[key]) throw new JoplinError(`Unknown key: ${key}`, 'unknown_key');
if (!metadata[key].options) throw new Error(`No options for: ${key}`);
return metadata[key].options();
}

View File

@@ -1,20 +1,52 @@
import Logger from '../../Logger';
import Setting from '../../models/Setting';
const logger = Logger.create('mergeGlobalAndLocalSettings');
export default (rootSettings: Record<string, any>, subProfileSettings: Record<string, any>) => {
const output: Record<string, any> = { ...subProfileSettings };
for (const k of Object.keys(output)) {
const md = Setting.settingMetadata(k);
if (md.isGlobal) {
delete output[k];
if (k in rootSettings) output[k] = rootSettings[k];
try {
const md = Setting.settingMetadata(k);
if (md.isGlobal) {
delete output[k];
if (k in rootSettings) output[k] = rootSettings[k];
}
} catch (error) {
if (error.code === 'unknown_key') {
// The root settings may contain plugin parameters, but the
// sub-profile won't necessarily have these plugins. In that
// case, the app will throw an error, but we can ignore it since
// we don't need this particular setting.
// https://github.com/laurent22/joplin/issues/8143
logger.info(`Ignoring unknown key in root settings: ${k}`);
}
}
}
for (const k of Object.keys(rootSettings)) {
const md = Setting.settingMetadata(k);
if (md.isGlobal) {
output[k] = rootSettings[k];
// We only copy built-in key and not, for example, plugin keys, because
// those are plugin-specific
if (!Setting.isBuiltinKey(k)) {
logger.info(`Skipping non-built-in key: ${k}`);
continue;
}
try {
const md = Setting.settingMetadata(k);
if (md.isGlobal) {
output[k] = rootSettings[k];
}
} catch (error) {
if (error.code === 'unknown_key') {
// The root settings may contain plugin parameters, but the
// sub-profile won't necessarily have these plugins. In that
// case, the app will throw an error, but we can ignore it since
// we don't need this particular setting.
// https://github.com/laurent22/joplin/issues/8143
logger.info(`Ignoring unknown key in root settings: ${k}`);
}
}
}

View File

@@ -1,5 +1,6 @@
import { ModelType } from '../../BaseModel';
import { FileApi, MultiPutItem } from '../../file-api';
import JoplinError from '../../JoplinError';
import Logger from '../../Logger';
import BaseItem from '../../models/BaseItem';
import { BaseItemEntity } from '../database/types';
@@ -45,7 +46,8 @@ export default class ItemUploader {
// the regular upload.
logger.warn(`Pre-uploaded item updated_time has changed. It is going to be re-uploaded again: ${path} (From ${this.preUploadedItemUpdatedTimes_[path]} to ${local.updated_time})`);
} else {
if (preUploadItem.error) throw new Error(preUploadItem.error.message ? preUploadItem.error.message : 'Unknown pre-upload error');
const error = preUploadItem.error;
if (error) throw new JoplinError(error.message ? error.message : 'Unknown pre-upload error', error.code);
return;
}
}

View File

@@ -9,12 +9,12 @@
"access": "restricted"
},
"scripts": {
"tsc": "tsc --project tsconfig.json",
"watch": "webpack --watch --config webpack.config.js --mode=development",
"build": "webpack --config webpack.config.js --mode=production",
"test": "jest",
"test-ci": "yarn test",
"postinstall": "yarn build"
"tsc_DISABLED": "tsc --project tsconfig.json",
"watch_DISABLED": "webpack --watch --config webpack.config.js --mode=development",
"build_DISABLED": "webpack --config webpack.config.js --mode=production",
"test_DISABLED": "jest",
"test-ci_DISABLED": "yarn test",
"postinstall_DISABLED": "yarn build"
},
"author": "Joplin",
"license": "AGPL-3.0-or-later",

View File

@@ -144,6 +144,11 @@ class HtmlUtils {
.replace(/</g, '&lt;');
}
private isAcceptedUrl(url: string): boolean {
url = url.toLowerCase();
return url.startsWith('https://') || url.startsWith('http://') || url.startsWith('mailto://');
}
public sanitizeHtml(html: string, options: any = null) {
options = Object.assign({}, {
// If true, adds a "jop-noMdConv" class to all the tags.
@@ -167,23 +172,31 @@ class HtmlUtils {
// The BASE tag allows changing the base URL from which files are
// loaded, and that can break several plugins, such as Katex (which
// needs to load CSS files using a relative URL). For that reason
// it is disabled. More info:
// https://github.com/laurent22/joplin/issues/3021
// needs to load CSS files using a relative URL). For that reason it is
// disabled. More info: https://github.com/laurent22/joplin/issues/3021
//
// "link" can be used to escape the parser and inject JavaScript.
// Adding "meta" too for the same reason as it shouldn't be used in
// notes anyway.
// "link" can be used to escape the parser and inject JavaScript. Adding
// "meta" too for the same reason as it shouldn't be used in notes
// anyway.
//
// There are too many issues with SVG tags and to handle them properly
// we should parse them separately. Currently we are not so it is better
// to disable them. SVG graphics are still supported via the IMG tag.
const disallowedTags = [
'script', 'iframe', 'frameset', 'frame', 'object', 'base',
'embed', 'link', 'meta', 'noscript', 'button', 'form',
'input', 'select', 'textarea', 'option', 'optgroup',
'svg',
];
const parser = new htmlparser2.Parser({
onopentag: (name: string, attrs: any) => {
tagStack.push(name.toLowerCase());
onopentag: (name: string, attrs: Record<string, string>) => {
// Note: "name" and attribute names are always lowercase even
// when the input is not. So there is no need to call
// "toLowerCase" on them.
tagStack.push(name);
if (disallowedTags.includes(currentTag())) {
disallowedTagDepth++;
@@ -202,11 +215,25 @@ class HtmlUtils {
// regular harmless attribute that starts with "on" will also
// be removed.
// 0: https://developer.mozilla.org/en-US/docs/Web/Events
for (const name in attrs) {
if (!attrs.hasOwnProperty(name)) continue;
if (name.length <= 2) continue;
if (name.toLowerCase().substr(0, 2) !== 'on') continue;
delete attrs[name];
for (const attrName in attrs) {
if (!attrs.hasOwnProperty(attrName)) continue;
if (attrName.length <= 2) continue;
if (attrName.substr(0, 2) !== 'on') continue;
delete attrs[attrName];
}
// Make sure that only non-acceptable URLs are filtered out. In
// particular we want to exclude `javascript:` URLs. This
// applies to A tags, and also AREA ones but to be safe we don't
// filter on the tag name and process all HREF attributes.
if ('href' in attrs && !this.isAcceptedUrl(attrs['href'])) {
attrs['href'] = '#';
}
// We need to clear any such attribute, otherwise it will
// make any arbitrary link open within the application.
if ('data-from-md' in attrs) {
delete attrs['data-from-md'];
}
if (options.addNoMdConvClass) {
@@ -222,7 +249,7 @@ class HtmlUtils {
// attribute. It doesn't always happen and it seems to depend on
// what else is in the note but in any case adding the "href"
// fixes it. https://github.com/laurent22/joplin/issues/5687
if (name.toLowerCase() === 'a' && !attrs['href']) {
if (name === 'a' && !attrs['href']) {
attrs['href'] = '#';
}
@@ -235,11 +262,18 @@ class HtmlUtils {
ontext: (decodedText: string) => {
if (disallowedTagDepth) return;
if (currentTag() === 'style') {
// For CSS, we have to put the style as-is inside the tag because if we html-entities encode
// it, it's not going to work. But it's ok because JavaScript won't run within the style tag.
// Ideally CSS should be loaded from an external file.
output.push(decodedText);
// For CSS, we have to put the style as-is inside the tag
// because if we html-entities encode it, it's not going to
// work. But it's ok because JavaScript won't run within the
// style tag. Ideally CSS should be loaded from an external
// file.
// We however have to encode at least the `<` characters to
// prevent certain XSS injections that would rely on the
// content not being encoded (see sanitize_13.md)
output.push(decodedText.replace(/</g, '&lt;'));
} else {
output.push(htmlentities(decodedText));
}

View File

@@ -3,12 +3,12 @@ import { ItemType, databaseSchema, Uuid, Item, ShareType, Share, ChangeType, Use
import { defaultPagination, paginateDbQuery, PaginatedResults, Pagination } from './utils/pagination';
import { isJoplinItemName, isJoplinResourceBlobPath, linkedResourceIds, serializeJoplinItem, unserializeJoplinItem } from '../utils/joplinUtils';
import { ModelType } from '@joplin/lib/BaseModel';
import { ApiError, ErrorCode, ErrorForbidden, ErrorPayloadTooLarge, ErrorUnprocessableEntity } from '../utils/errors';
import { ApiError, ErrorCode, ErrorConflict, ErrorForbidden, ErrorPayloadTooLarge, ErrorUnprocessableEntity } from '../utils/errors';
import { Knex } from 'knex';
import { ChangePreviousItem } from './ChangeModel';
import { unique } from '../utils/array';
import StorageDriverBase, { Context } from './items/storage/StorageDriverBase';
import { DbConnection, returningSupported } from '../db';
import { DbConnection, isUniqueConstraintError, returningSupported } from '../db';
import { Config, StorageDriverConfig, StorageDriverMode } from '../utils/types';
import { NewModelFactoryHandler } from './factory';
import loadStorageDriver from './items/storage/loadStorageDriver';
@@ -21,6 +21,8 @@ const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
// Converts "root:/myfile.txt:" to "myfile.txt"
const extractNameRegex = /^root:\/(.*):$/;
const modelLogger = Logger.create('ItemModel');
export interface DeleteOptions extends BaseDeleteOptions {
deleteChanges?: boolean;
}
@@ -928,7 +930,16 @@ export default class ItemModel extends BaseModel<Item> {
}
return this.withTransaction(async () => {
item = await super.save(item, options);
try {
item = await super.save(item, options);
} catch (error) {
if (isUniqueConstraintError(error)) {
modelLogger.error(`Unique constraint error on item: ${JSON.stringify({ id: item.id, name: item.name, jop_id: item.jop_id, owner_id: item.owner_id })}`, error);
throw new ErrorConflict(`This item is already present and cannot be added again: ${item.jop_id}`);
} else {
throw error;
}
}
if (isNew) await this.models().userItem().add(userId, item.id);

View File

@@ -3,6 +3,7 @@
// (Desktop|Mobile|Android|iOS[CLI): (New|Improved|Fixed): Some message..... (#ISSUE)
import { execCommand, githubUsername } from './tool-utils';
import * as compareVersions from 'compare-versions';
interface LogEntry {
message: string;
@@ -91,6 +92,11 @@ function platformFromTag(tagName: string): Platform {
throw new Error(`Could not determine platform from tag: "${tagName}"`);
}
const versionFromTag = (tag: string) => {
const s = tag.split('-');
return s[s.length - 1];
};
function filterLogs(logs: LogEntry[], platform: Platform) {
const output: LogEntry[] = [];
const revertedLogs = [];
@@ -311,10 +317,13 @@ function capitalizeFirstLetter(string: string) {
async function findFirstRelevantTag(baseTag: string, platform: Platform, allTags: string[]) {
let baseTagIndex = allTags.indexOf(baseTag);
if (baseTagIndex < 0) baseTagIndex = allTags.length;
const baseVersion = versionFromTag(baseTag);
for (let i = baseTagIndex - 1; i >= 0; i--) {
const tag = allTags[i];
if (platformFromTag(tag) !== platform) continue;
const currentVersion = versionFromTag(tag);
if (compareVersions(baseVersion, currentVersion) <= 0) continue;
try {
const logs = await gitLog(tag);

View File

@@ -24,6 +24,7 @@
"@joplin/renderer": "^2.10.2",
"@types/node-fetch": "2.6.2",
"@types/yargs": "17.0.20",
"compare-versions": "3.6.0",
"dayjs": "1.11.7",
"execa": "4.1.0",
"fs-extra": "11.1.0",

374
yarn.lock
View File

@@ -3825,18 +3825,16 @@ __metadata:
languageName: node
linkType: hard
"@electron/universal@npm:1.2.1":
version: 1.2.1
resolution: "@electron/universal@npm:1.2.1"
"@electron/universal@npm:1.0.5":
version: 1.0.5
resolution: "@electron/universal@npm:1.0.5"
dependencies:
"@malept/cross-spawn-promise": ^1.1.0
asar: ^3.1.0
asar: ^3.0.3
debug: ^4.3.1
dir-compare: ^2.4.0
fs-extra: ^9.0.1
minimatch: ^3.0.4
plist: ^3.0.4
checksum: 9a7d98cf2b8414ff0274384fef1b72b5a545a0feb7ce03163d2e2ee1b13e4f7064dfe7147cdd652708a1314d1b5e68acdd907847a1747866ec8d2d3e757ec1f7
checksum: 64eae3bbbfa422f28dbc1e92d12d954059cec7dac9ecc3ecad2c7895bb6cd10d30e8b3848092bfba8815bc71b60393a42f792751e50b9b5f643d6f1d03826b86
languageName: node
linkType: hard
@@ -4644,7 +4642,6 @@ __metadata:
"@fortawesome/fontawesome-free": 5.15.4
"@joeattardi/emoji-button": 4.6.4
"@joplin/lib": ~2.10
"@joplin/pdf-viewer": ~2.10
"@joplin/renderer": ~2.10
"@joplin/tools": ~2.10
"@testing-library/react-hooks": 8.0.1
@@ -4660,7 +4657,7 @@ __metadata:
countable: 3.0.1
debounce: 1.2.1
electron: 19.1.4
electron-builder: 23.6.0
electron-builder: 22.11.7
electron-notarize: 1.2.2
electron-rebuild: 3.2.9
electron-window-state: 5.0.3
@@ -4948,7 +4945,7 @@ __metadata:
languageName: unknown
linkType: soft
"@joplin/pdf-viewer@workspace:packages/pdf-viewer, @joplin/pdf-viewer@~2.10":
"@joplin/pdf-viewer@workspace:packages/pdf-viewer":
version: 0.0.0-use.local
resolution: "@joplin/pdf-viewer@workspace:packages/pdf-viewer"
dependencies:
@@ -5145,6 +5142,7 @@ __metadata:
"@types/node": 18.11.18
"@types/node-fetch": 2.6.2
"@types/yargs": 17.0.20
compare-versions: 3.6.0
dayjs: 1.11.7
execa: 4.1.0
fs-extra: 11.1.0
@@ -7244,7 +7242,7 @@ __metadata:
languageName: node
linkType: hard
"@types/debug@npm:^4.1.6":
"@types/debug@npm:^4.1.5":
version: 4.1.7
resolution: "@types/debug@npm:4.1.7"
dependencies:
@@ -7985,12 +7983,12 @@ __metadata:
languageName: node
linkType: hard
"@types/yargs@npm:^17.0.1":
version: 17.0.7
resolution: "@types/yargs@npm:17.0.7"
"@types/yargs@npm:^16.0.2":
version: 16.0.5
resolution: "@types/yargs@npm:16.0.5"
dependencies:
"@types/yargs-parser": "*"
checksum: 520e803720b2a626338c0e2b61825dd1b956910fec4d855018c17e62cf9fb41eb67bcf122ba5c6fb569b1bfac73520d5d73e8be502b87f9a551619df441b1875
checksum: 22697f7cc8aa32dcc10981a87f035e183303a58351c537c81fb450270d5c494b1d918186210e445b0eb2e4a8b34a8bda2a595f346bdb1c9ed2b63d193cb00430
languageName: node
linkType: hard
@@ -8709,7 +8707,7 @@ __metadata:
languageName: node
linkType: hard
"ansi-align@npm:^3.0.1":
"ansi-align@npm:^3.0.0, ansi-align@npm:^3.0.1":
version: 3.0.1
resolution: "ansi-align@npm:3.0.1"
dependencies:
@@ -8910,44 +8908,41 @@ __metadata:
languageName: node
linkType: hard
"app-builder-bin@npm:4.0.0":
version: 4.0.0
resolution: "app-builder-bin@npm:4.0.0"
checksum: c3c8fd85c371b7a396c1bb1160ab2e3231ba4309abea5b36a5b366e42511e347c65a33ff50d56f4960b337833d539c263137b0ba131e2fa268c32edeb6c9f683
"app-builder-bin@npm:3.5.13":
version: 3.5.13
resolution: "app-builder-bin@npm:3.5.13"
checksum: 2947c693642c877e518ced1b13d975e23184dbd6ea8e258d9406034de0416f820b65bc465c47d9367063382e154a298ee614b19189eac46e27bbfe8c3064e9f4
languageName: node
linkType: hard
"app-builder-lib@npm:23.6.0":
version: 23.6.0
resolution: "app-builder-lib@npm:23.6.0"
"app-builder-lib@npm:22.11.7":
version: 22.11.7
resolution: "app-builder-lib@npm:22.11.7"
dependencies:
7zip-bin: ~5.1.1
"@develar/schema-utils": ~2.6.5
"@electron/universal": 1.2.1
"@electron/universal": 1.0.5
"@malept/flatpak-bundler": ^0.4.0
async-exit-hook: ^2.0.1
bluebird-lst: ^1.0.9
builder-util: 23.6.0
builder-util-runtime: 9.1.1
builder-util: 22.11.7
builder-util-runtime: 8.7.7
chromium-pickle-js: ^0.2.0
debug: ^4.3.4
ejs: ^3.1.7
electron-osx-sign: ^0.6.0
electron-publish: 23.6.0
form-data: ^4.0.0
fs-extra: ^10.1.0
hosted-git-info: ^4.1.0
debug: ^4.3.2
ejs: ^3.1.6
electron-publish: 22.11.7
fs-extra: ^10.0.0
hosted-git-info: ^4.0.2
is-ci: ^3.0.0
isbinaryfile: ^4.0.10
isbinaryfile: ^4.0.8
js-yaml: ^4.1.0
lazy-val: ^1.0.5
minimatch: ^3.1.2
minimatch: ^3.0.4
read-config-file: 6.2.0
sanitize-filename: ^1.6.3
semver: ^7.3.7
tar: ^6.1.11
semver: ^7.3.5
temp-file: ^3.4.0
checksum: da3cc9f24e127add651197076c5fa2f68bc7979bcd6a441df7f69629e96bf3aca3118d61c63a85d382a824748f8056a7639464f07b1ded09db53ff1c4b3101be
checksum: e7691fd09d0663693fa650b53c0b92c8027202d07da85b65dcb24a9cbe85fbeb6c8f6b5a4b93282638675a64e1a650bec0962ef945561788937ccad8723b1607
languageName: node
linkType: hard
@@ -9317,9 +9312,9 @@ __metadata:
languageName: node
linkType: hard
"asar@npm:^3.1.0":
version: 3.1.0
resolution: "asar@npm:3.1.0"
"asar@npm:^3.0.3":
version: 3.2.0
resolution: "asar@npm:3.2.0"
dependencies:
"@types/glob": ^7.1.1
chromium-pickle-js: ^0.2.0
@@ -9331,7 +9326,7 @@ __metadata:
optional: true
bin:
asar: bin/asar.js
checksum: facc80845639fa4f9e1d1aa40b96adbd1e8b6fee0725d287e8c8e30a69b235cd5b7131b7b09ff700da06c919dd0595b373e372c55722808f983fdb71ef0d5399
checksum: f7d30b45970b053252ac124230bf319459d0728d7f6dedbe2f765cd2a83792d5a716d2c3f2861ceda69372b401f335e1f46460335169eadd0e91a0904a4f5a15
languageName: node
linkType: hard
@@ -9980,7 +9975,7 @@ __metadata:
languageName: node
linkType: hard
"bluebird@npm:^3.5.0, bluebird@npm:^3.5.1, bluebird@npm:^3.5.3, bluebird@npm:^3.5.5":
"bluebird@npm:^3.5.1, bluebird@npm:^3.5.3, bluebird@npm:^3.5.5":
version: 3.7.2
resolution: "bluebird@npm:3.7.2"
checksum: 869417503c722e7dc54ca46715f70e15f4d9c602a423a02c825570862d12935be59ed9c7ba34a9b31f186c017c23cac6b54e35446f8353059c101da73eac22ef
@@ -10015,6 +10010,22 @@ __metadata:
languageName: node
linkType: hard
"boxen@npm:^5.0.0":
version: 5.1.2
resolution: "boxen@npm:5.1.2"
dependencies:
ansi-align: ^3.0.0
camelcase: ^6.2.0
chalk: ^4.1.0
cli-boxes: ^2.2.1
string-width: ^4.2.2
type-fest: ^0.20.2
widest-line: ^3.1.0
wrap-ansi: ^7.0.0
checksum: 82d03e42a72576ff235123f17b7c505372fe05c83f75f61e7d4fa4bcb393897ec95ce766fecb8f26b915f0f7a7227d66e5ec7cef43f5b2bd9d3aeed47ec55877
languageName: node
linkType: hard
"boxen@npm:^7.0.0":
version: 7.0.0
resolution: "boxen@npm:7.0.0"
@@ -10329,23 +10340,6 @@ __metadata:
languageName: node
linkType: hard
"buffer-alloc-unsafe@npm:^1.1.0":
version: 1.1.0
resolution: "buffer-alloc-unsafe@npm:1.1.0"
checksum: c5e18bf51f67754ec843c9af3d4c005051aac5008a3992938dda1344e5cfec77c4b02b4ca303644d1e9a6e281765155ce6356d85c6f5ccc5cd21afc868def396
languageName: node
linkType: hard
"buffer-alloc@npm:^1.2.0":
version: 1.2.0
resolution: "buffer-alloc@npm:1.2.0"
dependencies:
buffer-alloc-unsafe: ^1.1.0
buffer-fill: ^1.0.0
checksum: 560cd27f3cbe73c614867da373407d4506309c62fe18de45a1ce191f3785ec6ca2488d802ff82065798542422980ca25f903db078c57822218182c37c3576df5
languageName: node
linkType: hard
"buffer-crc32@npm:~0.2.3":
version: 0.2.13
resolution: "buffer-crc32@npm:0.2.13"
@@ -10360,13 +10354,6 @@ __metadata:
languageName: node
linkType: hard
"buffer-fill@npm:^1.0.0":
version: 1.0.0
resolution: "buffer-fill@npm:1.0.0"
checksum: c29b4723ddeab01e74b5d3b982a0c6828f2ded49cef049ddca3dac661c874ecdbcecb5dd8380cf0f4adbeb8cff90a7de724126750a1f1e5ebd4eb6c59a1315b1
languageName: node
linkType: hard
"buffer-from@npm:^1.0.0":
version: 1.1.2
resolution: "buffer-from@npm:1.1.2"
@@ -10419,38 +10406,45 @@ __metadata:
languageName: node
linkType: hard
"builder-util-runtime@npm:9.1.1":
version: 9.1.1
resolution: "builder-util-runtime@npm:9.1.1"
"builder-util-runtime@npm:8.7.6":
version: 8.7.6
resolution: "builder-util-runtime@npm:8.7.6"
dependencies:
debug: ^4.3.4
debug: ^4.3.2
sax: ^1.2.4
checksum: 3458f9c8accad6e934c841cffa93f5d4b342c22b10b9c1a2eb3fd44ca96ea2c662b1048f9a075da9b8a4fada17206887b7e92ebdca331b1071520916e013e245
checksum: 0d02e6a5069f3d1b105d34bab6ca4aaafd70fbc182986ccf6803afa1705b6139aa99666c08087def21a722b209a81fda9d7ce19671ba041a0953bfb56fe7f4a9
languageName: node
linkType: hard
"builder-util@npm:23.6.0":
version: 23.6.0
resolution: "builder-util@npm:23.6.0"
"builder-util-runtime@npm:8.7.7":
version: 8.7.7
resolution: "builder-util-runtime@npm:8.7.7"
dependencies:
debug: ^4.3.2
sax: ^1.2.4
checksum: cf09c5538d4758a5408a5989ca4c0441fea6416b98f9047508dbe2e8fdfe0fa4b11c7a9952c5bacda0f6711573b05c12ee29bfe93fc456cc3e41b7b2996b54aa
languageName: node
linkType: hard
"builder-util@npm:22.11.7":
version: 22.11.7
resolution: "builder-util@npm:22.11.7"
dependencies:
7zip-bin: ~5.1.1
"@types/debug": ^4.1.6
"@types/debug": ^4.1.5
"@types/fs-extra": ^9.0.11
app-builder-bin: 4.0.0
app-builder-bin: 3.5.13
bluebird-lst: ^1.0.9
builder-util-runtime: 9.1.1
builder-util-runtime: 8.7.7
chalk: ^4.1.1
cross-spawn: ^7.0.3
debug: ^4.3.4
debug: ^4.3.2
fs-extra: ^10.0.0
http-proxy-agent: ^5.0.0
https-proxy-agent: ^5.0.0
is-ci: ^3.0.0
js-yaml: ^4.1.0
source-map-support: ^0.5.19
stat-mode: ^1.0.0
temp-file: ^3.4.0
checksum: 138fb9abed01ea2e5ac895e6a6ed75310ca6c89e0050483c81801b052f61b42ae5a042f457088b6e205ec8b4403b1ff3a325955f110255afb4da2310e3cf14ad
checksum: 53791d1feefc1c839ddb711ef84f74c3efdb37b0fc523c9c3ea7261bd755a4126c2f15d826ca8486aed9a3a0a5a942208b86c4ec15be94ee7552e1459ec9e588
languageName: node
linkType: hard
@@ -11202,7 +11196,7 @@ __metadata:
languageName: node
linkType: hard
"cli-boxes@npm:^2.2.0":
"cli-boxes@npm:^2.2.0, cli-boxes@npm:^2.2.1":
version: 2.2.1
resolution: "cli-boxes@npm:2.2.1"
checksum: be79f8ec23a558b49e01311b39a1ea01243ecee30539c880cf14bf518a12e223ef40c57ead0cb44f509bffdffc5c129c746cd50d863ab879385370112af4f585
@@ -11733,7 +11727,7 @@ __metadata:
languageName: node
linkType: hard
"compare-version@npm:0.1.2, compare-version@npm:^0.1.2":
"compare-version@npm:0.1.2":
version: 0.1.2
resolution: "compare-version@npm:0.1.2"
checksum: 0ceaf50b5f912c8eb8eeca19375e617209d200abebd771e9306510166462e6f91ad764f33f210a3058ee27c83f2f001a7a4ca32f509da2d207d0143a3438a020
@@ -13303,7 +13297,7 @@ __metadata:
languageName: node
linkType: hard
"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.3.3, debug@npm:^2.6.8, debug@npm:^2.6.9":
"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.3.3, debug@npm:^2.6.9":
version: 2.6.9
resolution: "debug@npm:2.6.9"
dependencies:
@@ -14055,25 +14049,25 @@ __metadata:
languageName: node
linkType: hard
"dmg-builder@npm:23.6.0":
version: 23.6.0
resolution: "dmg-builder@npm:23.6.0"
"dmg-builder@npm:22.11.7":
version: 22.11.7
resolution: "dmg-builder@npm:22.11.7"
dependencies:
app-builder-lib: 23.6.0
builder-util: 23.6.0
builder-util-runtime: 9.1.1
dmg-license: ^1.0.11
app-builder-lib: 22.11.7
builder-util: 22.11.7
builder-util-runtime: 8.7.6
dmg-license: ^1.0.9
fs-extra: ^10.0.0
iconv-lite: ^0.6.2
js-yaml: ^4.1.0
dependenciesMeta:
dmg-license:
optional: true
checksum: 3e37a4b191cf40c9c7b97d07408c2bf58e7632d78de0dc49a142fb7c68670fd2a7123f31ee8803b3cd100f38feea7b785c28698dfaace508254659d81ecc0b80
checksum: a46b7a0eaf304eef8ed1ebe859743d8415a1206c29ffadbf2781e67c849bfbec22c641985f08eb421ccbe47bc629ea954f4818ff22f55c6023542d50639f5852
languageName: node
linkType: hard
"dmg-license@npm:^1.0.11":
"dmg-license@npm:^1.0.9":
version: 1.0.11
resolution: "dmg-license@npm:1.0.11"
dependencies:
@@ -14389,37 +14383,37 @@ __metadata:
languageName: node
linkType: hard
"ejs@npm:^3.1.7":
version: 3.1.7
resolution: "ejs@npm:3.1.7"
"ejs@npm:^3.1.6":
version: 3.1.9
resolution: "ejs@npm:3.1.9"
dependencies:
jake: ^10.8.5
bin:
ejs: bin/cli.js
checksum: fe40764af39955ce8f8b116716fc8b911959946698edb49ecab85df597746c07aa65d5b74ead28a1e2ffa75b0f92d9bedd752f1c29437da6137b3518271e988c
checksum: af6f10eb815885ff8a8cfacc42c6b6cf87daf97a4884f87a30e0c3271fedd85d76a3a297d9c33a70e735b97ee632887f85e32854b9cdd3a2d97edf931519a35f
languageName: node
linkType: hard
"electron-builder@npm:23.6.0":
version: 23.6.0
resolution: "electron-builder@npm:23.6.0"
"electron-builder@npm:22.11.7":
version: 22.11.7
resolution: "electron-builder@npm:22.11.7"
dependencies:
"@types/yargs": ^17.0.1
app-builder-lib: 23.6.0
builder-util: 23.6.0
builder-util-runtime: 9.1.1
"@types/yargs": ^16.0.2
app-builder-lib: 22.11.7
builder-util: 22.11.7
builder-util-runtime: 8.7.7
chalk: ^4.1.1
dmg-builder: 23.6.0
dmg-builder: 22.11.7
fs-extra: ^10.0.0
is-ci: ^3.0.0
lazy-val: ^1.0.5
read-config-file: 6.2.0
simple-update-notifier: ^1.0.7
yargs: ^17.5.1
update-notifier: ^5.1.0
yargs: ^17.0.1
bin:
electron-builder: cli.js
install-app-deps: install-app-deps.js
checksum: 227f8fb9c9bb11a11d999f2ade6a5cd1afb720d6ff5053c88b4be62d1265b6268c8f6b4b3b8ad6d0a7261d57ea5acd6619ef301b843865f260b616c474cf8cbd
checksum: 8f21d2d1d4acb88c51b077d8d7da851d6ac4d32577296c586640618c9569be33826ce55e255d5a849060748fae1c218f38baef4792da247163962065e543a103
languageName: node
linkType: hard
@@ -14433,35 +14427,18 @@ __metadata:
languageName: node
linkType: hard
"electron-osx-sign@npm:^0.6.0":
version: 0.6.0
resolution: "electron-osx-sign@npm:0.6.0"
dependencies:
bluebird: ^3.5.0
compare-version: ^0.1.2
debug: ^2.6.8
isbinaryfile: ^3.0.2
minimist: ^1.2.0
plist: ^3.0.1
bin:
electron-osx-flat: bin/electron-osx-flat.js
electron-osx-sign: bin/electron-osx-sign.js
checksum: b688f9efb013670b4226cff7c38101e7b1384ea44e1ab203259995f1eefc019c63aa18e936217a76d33b5a5a452b987ab3d86a56a961294582ce42acbb950de6
languageName: node
linkType: hard
"electron-publish@npm:23.6.0":
version: 23.6.0
resolution: "electron-publish@npm:23.6.0"
"electron-publish@npm:22.11.7":
version: 22.11.7
resolution: "electron-publish@npm:22.11.7"
dependencies:
"@types/fs-extra": ^9.0.11
builder-util: 23.6.0
builder-util-runtime: 9.1.1
builder-util: 22.11.7
builder-util-runtime: 8.7.7
chalk: ^4.1.1
fs-extra: ^10.0.0
lazy-val: ^1.0.5
mime: ^2.5.2
checksum: 70473d800f0607b5ffc32473e87004079fe3e5f133242bb498dcff0be89bfaa4ce967860809e12b97ce216b1e907649a8a916b7483daf7a00ea28db3d665878e
checksum: 99eb8f50d92210904212125e59936e45bae1cd3f2b363f728846d6ff23fa1358395945c19f582b977dcc8e3f45c1bbcfb8100e0cf5718429be2c135a8359e6e4
languageName: node
linkType: hard
@@ -14954,6 +14931,13 @@ __metadata:
languageName: node
linkType: hard
"escape-goat@npm:^2.0.0":
version: 2.1.1
resolution: "escape-goat@npm:2.1.1"
checksum: ce05c70c20dd7007b60d2d644b625da5412325fdb57acf671ba06cb2ab3cd6789e2087026921a05b665b0a03fadee2955e7fc0b9a67da15a6551a980b260eba7
languageName: node
linkType: hard
"escape-html@npm:^1.0.3, escape-html@npm:~1.0.3":
version: 1.0.3
resolution: "escape-html@npm:1.0.3"
@@ -17701,6 +17685,13 @@ __metadata:
languageName: node
linkType: hard
"has-yarn@npm:^2.1.0":
version: 2.1.0
resolution: "has-yarn@npm:2.1.0"
checksum: 5eb1d0bb8518103d7da24532bdbc7124ffc6d367b5d3c10840b508116f2f1bcbcf10fd3ba843ff6e2e991bdf9969fd862d42b2ed58aade88343326c950b7e7f7
languageName: node
linkType: hard
"has@npm:^1.0.0, has@npm:^1.0.3, has@npm:~1.0.3":
version: 1.0.3
resolution: "has@npm:1.0.3"
@@ -17858,7 +17849,7 @@ __metadata:
languageName: node
linkType: hard
"hosted-git-info@npm:^4.1.0":
"hosted-git-info@npm:^4.0.2":
version: 4.1.0
resolution: "hosted-git-info@npm:4.1.0"
dependencies:
@@ -18355,6 +18346,13 @@ __metadata:
languageName: node
linkType: hard
"import-lazy@npm:^2.1.0":
version: 2.1.0
resolution: "import-lazy@npm:2.1.0"
checksum: 05294f3b9dd4971d3a996f0d2f176410fb6745d491d6e73376429189f5c1c3d290548116b2960a7cf3e89c20cdf11431739d1d2d8c54b84061980795010e803a
languageName: node
linkType: hard
"import-local@npm:^2.0.0":
version: 2.0.0
resolution: "import-local@npm:2.0.0"
@@ -19126,6 +19124,13 @@ __metadata:
languageName: node
linkType: hard
"is-npm@npm:^5.0.0":
version: 5.0.0
resolution: "is-npm@npm:5.0.0"
checksum: 9baff02b0c69a3d3c79b162cb2f9e67fb40ef6d172c16601b2e2471c21e9a4fa1fc9885a308d7bc6f3a3cd2a324c27fa0bf284c133c3349bb22571ab70d041cc
languageName: node
linkType: hard
"is-number-object@npm:^1.0.4":
version: 1.0.6
resolution: "is-number-object@npm:1.0.6"
@@ -19441,6 +19446,13 @@ __metadata:
languageName: node
linkType: hard
"is-yarn-global@npm:^0.3.0":
version: 0.3.0
resolution: "is-yarn-global@npm:0.3.0"
checksum: bca013d65fee2862024c9fbb3ba13720ffca2fe750095174c1c80922fdda16402b5c233f5ac9e265bc12ecb5446e7b7f519a32d9541788f01d4d44e24d2bf481
languageName: node
linkType: hard
"is2@npm:^2.0.6":
version: 2.0.7
resolution: "is2@npm:2.0.7"
@@ -19459,16 +19471,7 @@ __metadata:
languageName: node
linkType: hard
"isbinaryfile@npm:^3.0.2":
version: 3.0.3
resolution: "isbinaryfile@npm:3.0.3"
dependencies:
buffer-alloc: ^1.2.0
checksum: 9a555786857c66fe36024d15a54e0ca371c02275622b007356d6afca2b3bca179cb0bd97e1adf5d3922b3325c0fe22813645c7f7eafb4c4bdab1da9d635133c2
languageName: node
linkType: hard
"isbinaryfile@npm:^4.0.10":
"isbinaryfile@npm:^4.0.8":
version: 4.0.10
resolution: "isbinaryfile@npm:4.0.10"
checksum: a6b28db7e23ac7a77d3707567cac81356ea18bd602a4f21f424f862a31d0e7ab4f250759c98a559ece35ffe4d99f0d339f1ab884ffa9795172f632ab8f88e686
@@ -21043,6 +21046,15 @@ __metadata:
languageName: node
linkType: hard
"latest-version@npm:^5.1.0":
version: 5.1.0
resolution: "latest-version@npm:5.1.0"
dependencies:
package-json: ^6.3.0
checksum: fbc72b071eb66c40f652441fd783a9cca62f08bf42433651937f078cd9ef94bf728ec7743992777826e4e89305aef24f234b515e6030503a2cbee7fc9bdc2c0f
languageName: node
linkType: hard
"lazy-val@npm:^1.0.4, lazy-val@npm:^1.0.5":
version: 1.0.5
resolution: "lazy-val@npm:1.0.5"
@@ -24737,6 +24749,18 @@ __metadata:
languageName: node
linkType: hard
"package-json@npm:^6.3.0":
version: 6.5.0
resolution: "package-json@npm:6.5.0"
dependencies:
got: ^9.6.0
registry-auth-token: ^4.0.0
registry-url: ^5.0.0
semver: ^6.2.0
checksum: cc9f890d3667d7610e6184decf543278b87f657d1ace0deb4a9c9155feca738ef88f660c82200763d3348010f4e42e9c7adc91e96ab0f86a770955995b5351e2
languageName: node
linkType: hard
"packet-reader@npm:1.0.0":
version: 1.0.0
resolution: "packet-reader@npm:1.0.0"
@@ -25380,7 +25404,7 @@ __metadata:
languageName: node
linkType: hard
"plist@npm:^3.0.1, plist@npm:^3.0.4":
"plist@npm:^3.0.4":
version: 3.0.4
resolution: "plist@npm:3.0.4"
dependencies:
@@ -26044,6 +26068,15 @@ __metadata:
languageName: node
linkType: hard
"pupa@npm:^2.1.1":
version: 2.1.1
resolution: "pupa@npm:2.1.1"
dependencies:
escape-goat: ^2.0.0
checksum: 49529e50372ffdb0cccf0efa0f3b3cb0a2c77805d0d9cc2725bd2a0f6bb414631e61c93a38561b26be1259550b7bb6c2cb92315aa09c8bf93f3bdcb49f2b2fb7
languageName: node
linkType: hard
"q@npm:^1.5.1":
version: 1.5.1
resolution: "q@npm:1.5.1"
@@ -26226,7 +26259,7 @@ __metadata:
languageName: node
linkType: hard
"rc@npm:^1.2.7":
"rc@npm:1.2.8, rc@npm:^1.2.7, rc@npm:^1.2.8":
version: 1.2.8
resolution: "rc@npm:1.2.8"
dependencies:
@@ -27301,6 +27334,24 @@ __metadata:
languageName: node
linkType: hard
"registry-auth-token@npm:^4.0.0":
version: 4.2.2
resolution: "registry-auth-token@npm:4.2.2"
dependencies:
rc: 1.2.8
checksum: c5030198546ecfdcbcb0722cbc3e260c4f5f174d8d07bdfedd4620e79bfdf17a2db735aa230d600bd388fce6edd26c0a9ed2eb7e9b4641ec15213a28a806688b
languageName: node
linkType: hard
"registry-url@npm:^5.0.0":
version: 5.1.0
resolution: "registry-url@npm:5.1.0"
dependencies:
rc: ^1.2.8
checksum: bcea86c84a0dbb66467b53187fadebfea79017cddfb4a45cf27530d7275e49082fe9f44301976eb0164c438e395684bcf3dae4819b36ff9d1640d8cc60c73df9
languageName: node
linkType: hard
"regjsgen@npm:^0.7.1":
version: 0.7.1
resolution: "regjsgen@npm:0.7.1"
@@ -28203,6 +28254,15 @@ __metadata:
languageName: node
linkType: hard
"semver-diff@npm:^3.1.1":
version: 3.1.1
resolution: "semver-diff@npm:3.1.1"
dependencies:
semver: ^6.3.0
checksum: 8bbe5a5d7add2d5e51b72314a9215cd294d71f41cdc2bf6bd59ee76411f3610b576172896f1d191d0d7294cb9f2f847438d2ee158adacc0c224dca79052812fe
languageName: node
linkType: hard
"semver-greatest-satisfied-range@npm:^1.1.0":
version: 1.1.0
resolution: "semver-greatest-satisfied-range@npm:1.1.0"
@@ -31743,6 +31803,28 @@ __metadata:
languageName: node
linkType: hard
"update-notifier@npm:^5.1.0":
version: 5.1.0
resolution: "update-notifier@npm:5.1.0"
dependencies:
boxen: ^5.0.0
chalk: ^4.1.0
configstore: ^5.0.1
has-yarn: ^2.1.0
import-lazy: ^2.1.0
is-ci: ^2.0.0
is-installed-globally: ^0.4.0
is-npm: ^5.0.0
is-yarn-global: ^0.3.0
latest-version: ^5.1.0
pupa: ^2.1.1
semver: ^7.3.4
semver-diff: ^3.1.1
xdg-basedir: ^4.0.0
checksum: 461e5e5b002419296d3868ee2abe0f9ab3e1846d9db642936d0c46f838872ec56069eddfe662c45ce1af0a8d6d5026353728de2e0a95ab2e3546a22ea077caf1
languageName: node
linkType: hard
"upper-case-first@npm:^2.0.2":
version: 2.0.2
resolution: "upper-case-first@npm:2.0.2"