Bugfixes for v1.29
* If focus was set to document.body during archive, focus left pane * Shortcut Guide: Add space between text and shortcut highlight * Ensure that draft attachment can be closed with click on X button * Move to keyDown event for user idle checking * Additional resiliency around avatars; check for them on on-disk * Increase timeouts to preserve websocket connection * On startup, be resilient to malformed JSON in log files * Don't crash if shell.openExternal returns an error * Whenever we request a contact/group sync, also request block list * Avatar popup: Ensure styling is mouse- and keyboard-appropriate * MainHeader: Create popperRoot on demand, not on mount * CompositionInput: Disable default Ctrl-/ shortcut * Update libphonenumber
This commit is contained in:
parent
ee9e86ab7a
commit
e9f08c3da9
19 changed files with 300 additions and 128 deletions
|
@ -105,6 +105,30 @@ exports.createReader = root => {
|
|||
};
|
||||
};
|
||||
|
||||
exports.createDoesExist = root => {
|
||||
if (!isString(root)) {
|
||||
throw new TypeError("'root' must be a path");
|
||||
}
|
||||
|
||||
return async relativePath => {
|
||||
if (!isString(relativePath)) {
|
||||
throw new TypeError("'relativePath' must be a string");
|
||||
}
|
||||
|
||||
const absolutePath = path.join(root, relativePath);
|
||||
const normalized = path.normalize(absolutePath);
|
||||
if (!normalized.startsWith(root)) {
|
||||
throw new Error('Invalid relative path');
|
||||
}
|
||||
try {
|
||||
await fse.access(normalized, fse.constants.F_OK);
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.copyIntoAttachmentsDirectory = root => {
|
||||
if (!isString(root)) {
|
||||
throw new TypeError("'root' must be a path");
|
||||
|
|
123
app/logging.js
123
app/logging.js
|
@ -31,7 +31,7 @@ module.exports = {
|
|||
fetch,
|
||||
};
|
||||
|
||||
function initialize() {
|
||||
async function initialize() {
|
||||
if (logger) {
|
||||
throw new Error('Already called initialize!');
|
||||
}
|
||||
|
@ -40,66 +40,81 @@ function initialize() {
|
|||
const logPath = path.join(basePath, 'logs');
|
||||
mkdirp.sync(logPath);
|
||||
|
||||
return cleanupLogs(logPath).then(() => {
|
||||
const logFile = path.join(logPath, 'log.log');
|
||||
const loggerOptions = {
|
||||
name: 'log',
|
||||
streams: [
|
||||
try {
|
||||
await cleanupLogs(logPath);
|
||||
} catch (error) {
|
||||
const errorString = `Failed to clean logs; deleting all. Error: ${
|
||||
error.stack
|
||||
}`;
|
||||
console.error(errorString);
|
||||
await deleteAllLogs(logPath);
|
||||
mkdirp.sync(logPath);
|
||||
|
||||
// If we want this log entry to persist on disk, we need to wait until we've
|
||||
// set up our logging infrastructure.
|
||||
setTimeout(() => {
|
||||
console.error(errorString);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
const logFile = path.join(logPath, 'log.log');
|
||||
const loggerOptions = {
|
||||
name: 'log',
|
||||
streams: [
|
||||
{
|
||||
type: 'rotating-file',
|
||||
path: logFile,
|
||||
period: '1d',
|
||||
count: 3,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (isRunningFromConsole) {
|
||||
loggerOptions.streams.push({
|
||||
level: 'debug',
|
||||
stream: process.stdout,
|
||||
});
|
||||
}
|
||||
|
||||
logger = bunyan.createLogger(loggerOptions);
|
||||
|
||||
LEVELS.forEach(level => {
|
||||
ipc.on(`log-${level}`, (first, ...rest) => {
|
||||
logger[level](...rest);
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on('batch-log', (first, batch) => {
|
||||
batch.forEach(item => {
|
||||
logger[item.level](
|
||||
{
|
||||
type: 'rotating-file',
|
||||
path: logFile,
|
||||
period: '1d',
|
||||
count: 3,
|
||||
time: new Date(item.timestamp),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (isRunningFromConsole) {
|
||||
loggerOptions.streams.push({
|
||||
level: 'debug',
|
||||
stream: process.stdout,
|
||||
});
|
||||
}
|
||||
|
||||
logger = bunyan.createLogger(loggerOptions);
|
||||
|
||||
LEVELS.forEach(level => {
|
||||
ipc.on(`log-${level}`, (first, ...rest) => {
|
||||
logger[level](...rest);
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on('batch-log', (first, batch) => {
|
||||
batch.forEach(item => {
|
||||
logger[item.level](
|
||||
{
|
||||
time: new Date(item.timestamp),
|
||||
},
|
||||
item.logText
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on('fetch-log', event => {
|
||||
fetch(logPath).then(
|
||||
data => {
|
||||
event.sender.send('fetched-log', data);
|
||||
},
|
||||
error => {
|
||||
logger.error(`Problem loading log from disk: ${error.stack}`);
|
||||
}
|
||||
item.logText
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on('delete-all-logs', async event => {
|
||||
try {
|
||||
await deleteAllLogs(logPath);
|
||||
} catch (error) {
|
||||
logger.error(`Problem deleting all logs: ${error.stack}`);
|
||||
ipc.on('fetch-log', event => {
|
||||
fetch(logPath).then(
|
||||
data => {
|
||||
event.sender.send('fetched-log', data);
|
||||
},
|
||||
error => {
|
||||
logger.error(`Problem loading log from disk: ${error.stack}`);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
event.sender.send('delete-all-logs-complete');
|
||||
});
|
||||
ipc.on('delete-all-logs', async event => {
|
||||
try {
|
||||
await deleteAllLogs(logPath);
|
||||
} catch (error) {
|
||||
logger.error(`Problem deleting all logs: ${error.stack}`);
|
||||
}
|
||||
|
||||
event.sender.send('delete-all-logs-complete');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
const ACTIVE_TIMEOUT = 15 * 1000;
|
||||
const ACTIVE_EVENTS = [
|
||||
'click',
|
||||
'keypress',
|
||||
'keydown',
|
||||
'mousedown',
|
||||
'mousemove',
|
||||
// 'scroll', // this is triggered by Timeline re-renders, can't use
|
||||
|
@ -193,6 +193,7 @@
|
|||
upgradeMessageSchema,
|
||||
writeNewAttachmentData,
|
||||
deleteAttachmentData,
|
||||
doesAttachmentExist,
|
||||
} = window.Signal.Migrations;
|
||||
const { Views } = window.Signal;
|
||||
|
||||
|
@ -1049,6 +1050,23 @@
|
|||
document.body
|
||||
);
|
||||
|
||||
// It's very likely that the act of archiving a conversation will set focus to
|
||||
// 'none,' or the top-level body element. This resets it to the left pane,
|
||||
// whether in the normal conversation list or search results.
|
||||
if (document.activeElement === document.body) {
|
||||
const leftPaneEl = document.querySelector('.module-left-pane__list');
|
||||
if (leftPaneEl) {
|
||||
leftPaneEl.focus();
|
||||
}
|
||||
|
||||
const searchResultsEl = document.querySelector(
|
||||
'.module-search-results'
|
||||
);
|
||||
if (searchResultsEl) {
|
||||
searchResultsEl.focus();
|
||||
}
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
|
@ -1852,12 +1870,14 @@
|
|||
{
|
||||
writeNewAttachmentData,
|
||||
deleteAttachmentData,
|
||||
doesAttachmentExist,
|
||||
}
|
||||
);
|
||||
conversation.set(newAttributes);
|
||||
}
|
||||
|
||||
window.Signal.Data.updateConversation(id, conversation.attributes);
|
||||
|
||||
const { expireTimer } = details;
|
||||
const isValidExpireTimer = typeof expireTimer === 'number';
|
||||
if (isValidExpireTimer) {
|
||||
|
@ -1934,6 +1954,7 @@
|
|||
{
|
||||
writeNewAttachmentData,
|
||||
deleteAttachmentData,
|
||||
doesAttachmentExist,
|
||||
}
|
||||
);
|
||||
conversation.set(newAttributes);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
const { Conversation, Contact, Message, PhoneNumber } = window.Signal.Types;
|
||||
const {
|
||||
deleteAttachmentData,
|
||||
doesAttachmentExist,
|
||||
getAbsoluteAttachmentPath,
|
||||
loadAttachmentData,
|
||||
readStickerData,
|
||||
|
@ -1746,7 +1747,6 @@
|
|||
error && error.stack ? error.stack : error
|
||||
);
|
||||
await c.dropProfileKey();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -1814,6 +1814,7 @@
|
|||
{
|
||||
writeNewAttachmentData,
|
||||
deleteAttachmentData,
|
||||
doesAttachmentExist,
|
||||
}
|
||||
);
|
||||
this.set(newAttributes);
|
||||
|
|
|
@ -114,6 +114,7 @@ function initializeMigrations({
|
|||
createReader,
|
||||
createWriterForExisting,
|
||||
createWriterForNew,
|
||||
createDoesExist,
|
||||
getDraftPath,
|
||||
getPath,
|
||||
getStickersPath,
|
||||
|
@ -139,6 +140,7 @@ function initializeMigrations({
|
|||
const copyIntoAttachmentsDirectory = Attachments.copyIntoAttachmentsDirectory(
|
||||
attachmentsPath
|
||||
);
|
||||
const doesAttachmentExist = createDoesExist(attachmentsPath);
|
||||
|
||||
const stickersPath = getStickersPath(userDataPath);
|
||||
const writeNewStickerData = createWriterForNew(stickersPath);
|
||||
|
@ -173,6 +175,7 @@ function initializeMigrations({
|
|||
}),
|
||||
deleteSticker,
|
||||
deleteTempFile,
|
||||
doesAttachmentExist,
|
||||
getAbsoluteAttachmentPath,
|
||||
getAbsoluteDraftPath,
|
||||
getAbsoluteStickerPath,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global crypto */
|
||||
/* global crypto, window */
|
||||
|
||||
const { isFunction, isNumber } = require('lodash');
|
||||
const { createLastMessageUpdate } = require('../../../ts/types/Conversation');
|
||||
|
@ -16,17 +16,26 @@ function buildAvatarUpdater({ field }) {
|
|||
}
|
||||
|
||||
const avatar = conversation[field];
|
||||
const { writeNewAttachmentData, deleteAttachmentData } = options;
|
||||
if (!isFunction(writeNewAttachmentData)) {
|
||||
throw new Error(
|
||||
'Conversation.buildAvatarUpdater: writeNewAttachmentData must be a function'
|
||||
);
|
||||
}
|
||||
const {
|
||||
deleteAttachmentData,
|
||||
doesAttachmentExist,
|
||||
writeNewAttachmentData,
|
||||
} = options;
|
||||
if (!isFunction(deleteAttachmentData)) {
|
||||
throw new Error(
|
||||
'Conversation.buildAvatarUpdater: deleteAttachmentData must be a function'
|
||||
);
|
||||
}
|
||||
if (!isFunction(doesAttachmentExist)) {
|
||||
throw new Error(
|
||||
'Conversation.buildAvatarUpdater: deleteAttachmentData must be a function'
|
||||
);
|
||||
}
|
||||
if (!isFunction(writeNewAttachmentData)) {
|
||||
throw new Error(
|
||||
'Conversation.buildAvatarUpdater: writeNewAttachmentData must be a function'
|
||||
);
|
||||
}
|
||||
|
||||
const newHash = await computeHash(data);
|
||||
|
||||
|
@ -41,8 +50,14 @@ function buildAvatarUpdater({ field }) {
|
|||
}
|
||||
|
||||
const { hash, path } = avatar;
|
||||
const exists = await doesAttachmentExist(path);
|
||||
if (!exists) {
|
||||
window.log.warn(
|
||||
`Conversation.buildAvatarUpdater: attachment ${path} did not exist`
|
||||
);
|
||||
}
|
||||
|
||||
if (hash === newHash) {
|
||||
if (exists && hash === newHash) {
|
||||
return conversation;
|
||||
}
|
||||
|
||||
|
|
|
@ -556,6 +556,30 @@ MessageSender.prototype = {
|
|||
return this.server.getStickerPackManifest(packId);
|
||||
},
|
||||
|
||||
sendRequestBlockSyncMessage(options) {
|
||||
const myNumber = textsecure.storage.user.getNumber();
|
||||
const myDevice = textsecure.storage.user.getDeviceId();
|
||||
if (myDevice !== 1 && myDevice !== '1') {
|
||||
const request = new textsecure.protobuf.SyncMessage.Request();
|
||||
request.type = textsecure.protobuf.SyncMessage.Request.Type.BLOCKED;
|
||||
const syncMessage = this.createSyncMessage();
|
||||
syncMessage.request = request;
|
||||
const contentMessage = new textsecure.protobuf.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const silent = true;
|
||||
return this.sendIndividualProto(
|
||||
myNumber,
|
||||
contentMessage,
|
||||
Date.now(),
|
||||
silent,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
sendRequestConfigurationSyncMessage(options) {
|
||||
const myNumber = textsecure.storage.user.getNumber();
|
||||
const myDevice = textsecure.storage.user.getDeviceId();
|
||||
|
@ -1236,6 +1260,10 @@ textsecure.MessageSender = function MessageSenderWrapper(username, password) {
|
|||
this.sendRequestConfigurationSyncMessage = sender.sendRequestConfigurationSyncMessage.bind(
|
||||
sender
|
||||
);
|
||||
this.sendRequestBlockSyncMessage = sender.sendRequestBlockSyncMessage.bind(
|
||||
sender
|
||||
);
|
||||
|
||||
this.sendMessageToNumber = sender.sendMessageToNumber.bind(sender);
|
||||
this.sendMessage = sender.sendMessage.bind(sender);
|
||||
this.resetSession = sender.resetSession.bind(sender);
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
window.log.info('SyncRequest created. Sending config sync request...');
|
||||
wrap(sender.sendRequestConfigurationSyncMessage(sendOptions));
|
||||
|
||||
window.log.info('SyncRequest now sending block sync request...');
|
||||
wrap(sender.sendRequestBlockSyncMessage(sendOptions));
|
||||
|
||||
window.log.info('SyncRequest now sending contact sync message...');
|
||||
wrap(sender.sendRequestContactSyncMessage(sendOptions))
|
||||
.then(() => {
|
||||
|
|
|
@ -191,7 +191,7 @@
|
|||
ev.code = code;
|
||||
ev.reason = reason;
|
||||
this.dispatchEvent(ev);
|
||||
}, 1000);
|
||||
}, 5000);
|
||||
};
|
||||
};
|
||||
window.WebSocketResource.prototype = new textsecure.EventTarget();
|
||||
|
@ -227,7 +227,7 @@
|
|||
this.disconnectTimer = setTimeout(() => {
|
||||
clearTimeout(this.keepAliveTimer);
|
||||
this.wsr.close(3001, 'No response to keepalive request');
|
||||
}, 1000);
|
||||
}, 10000);
|
||||
} else {
|
||||
this.reset();
|
||||
}
|
||||
|
|
8
main.js
8
main.js
|
@ -166,11 +166,15 @@ function prepareURL(pathSegments, moreKeys) {
|
|||
});
|
||||
}
|
||||
|
||||
function handleUrl(event, target) {
|
||||
async function handleUrl(event, target) {
|
||||
event.preventDefault();
|
||||
const { protocol } = url.parse(target);
|
||||
if (protocol === 'http:' || protocol === 'https:') {
|
||||
shell.openExternal(target);
|
||||
try {
|
||||
await shell.openExternal(target);
|
||||
} catch (error) {
|
||||
console.log(`Failed to open url: ${error.stack}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
"fs-extra": "5.0.0",
|
||||
"fuse.js": "3.4.4",
|
||||
"glob": "7.1.2",
|
||||
"google-libphonenumber": "3.2.2",
|
||||
"google-libphonenumber": "3.2.6",
|
||||
"got": "8.2.0",
|
||||
"he": "1.2.0",
|
||||
"intl-tel-input": "12.1.15",
|
||||
|
|
|
@ -6831,13 +6831,27 @@ button.module-image__border-overlay:focus {
|
|||
padding: 6px;
|
||||
|
||||
@include light-theme {
|
||||
&:hover,
|
||||
&:hover {
|
||||
background-color: $color-gray-05;
|
||||
}
|
||||
}
|
||||
@include keyboard-mode {
|
||||
&:hover {
|
||||
background-color: inherit;
|
||||
}
|
||||
&:focus {
|
||||
background-color: $color-gray-05;
|
||||
}
|
||||
}
|
||||
@include dark-theme {
|
||||
&:hover,
|
||||
&:hover {
|
||||
background-color: $color-gray-60;
|
||||
}
|
||||
}
|
||||
@include dark-keyboard-mode {
|
||||
&:hover {
|
||||
background-color: inherit;
|
||||
}
|
||||
&:focus {
|
||||
background-color: $color-gray-60;
|
||||
}
|
||||
|
@ -7009,6 +7023,7 @@ button.module-image__border-overlay:focus {
|
|||
align-items: center;
|
||||
break-inside: avoid;
|
||||
|
||||
padding-left: 4px;
|
||||
min-height: 40px;
|
||||
outline: none;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ export interface Props {
|
|||
|
||||
interface State {
|
||||
imageBroken: boolean;
|
||||
lastAvatarPath?: string;
|
||||
}
|
||||
|
||||
export class Avatar extends React.Component<Props, State> {
|
||||
|
@ -35,10 +36,23 @@ export class Avatar extends React.Component<Props, State> {
|
|||
this.handleImageErrorBound = this.handleImageError.bind(this);
|
||||
|
||||
this.state = {
|
||||
lastAvatarPath: props.avatarPath,
|
||||
imageBroken: false,
|
||||
};
|
||||
}
|
||||
|
||||
public static getDerivedStateFromProps(props: Props, state: State): State {
|
||||
if (props.avatarPath !== state.lastAvatarPath) {
|
||||
return {
|
||||
...state,
|
||||
lastAvatarPath: props.avatarPath,
|
||||
imageBroken: false,
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public handleImageError() {
|
||||
// tslint:disable-next-line no-console
|
||||
console.log('Avatar: Image failed to load; failing over to placeholder');
|
||||
|
|
|
@ -700,6 +700,13 @@ export const CompositionInput = ({
|
|||
return null;
|
||||
}
|
||||
|
||||
// Get rid of Ctrl-/, which on GNOME is bound to 'select all'
|
||||
if (e.key === '/' && !e.shiftKey && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return getDefaultKeyBinding(e);
|
||||
},
|
||||
[emojiResults, large]
|
||||
|
|
|
@ -70,15 +70,6 @@ export class MainHeader extends React.Component<PropsType, StateType> {
|
|||
};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
const popperRoot = document.createElement('div');
|
||||
document.body.appendChild(popperRoot);
|
||||
|
||||
this.setState({
|
||||
popperRoot,
|
||||
});
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps: PropsType) {
|
||||
const { searchConversationId, startSearchCounter } = this.props;
|
||||
|
||||
|
@ -114,28 +105,41 @@ export class MainHeader extends React.Component<PropsType, StateType> {
|
|||
};
|
||||
|
||||
public showAvatarPopup = () => {
|
||||
const popperRoot = document.createElement('div');
|
||||
document.body.appendChild(popperRoot);
|
||||
|
||||
this.setState({
|
||||
showingAvatarPopup: true,
|
||||
popperRoot,
|
||||
});
|
||||
document.addEventListener('click', this.handleOutsideClick);
|
||||
document.addEventListener('keydown', this.handleOutsideKeyDown);
|
||||
};
|
||||
|
||||
public hideAvatarPopup = () => {
|
||||
const { popperRoot } = this.state;
|
||||
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
document.removeEventListener('keydown', this.handleOutsideKeyDown);
|
||||
|
||||
this.setState({
|
||||
showingAvatarPopup: false,
|
||||
popperRoot: null,
|
||||
});
|
||||
|
||||
if (popperRoot) {
|
||||
document.body.removeChild(popperRoot);
|
||||
}
|
||||
};
|
||||
|
||||
public componentWillUnmount() {
|
||||
const { popperRoot } = this.state;
|
||||
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
document.removeEventListener('keydown', this.handleOutsideKeyDown);
|
||||
|
||||
if (popperRoot) {
|
||||
document.body.removeChild(popperRoot);
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
document.removeEventListener('keydown', this.handleOutsideKeyDown);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -162,20 +162,6 @@ export class Image extends React.Component<Props> {
|
|||
alt={i18n('imageCaptionIconAlt')}
|
||||
/>
|
||||
) : null}
|
||||
{closeButton ? (
|
||||
<button
|
||||
onClick={(e: React.MouseEvent<{}>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (onClickClose) {
|
||||
onClickClose(attachment);
|
||||
}
|
||||
}}
|
||||
className="module-image__close-button"
|
||||
title={i18n('remove-attachment')}
|
||||
/>
|
||||
) : null}
|
||||
{bottomOverlay ? (
|
||||
<div
|
||||
className={classNames(
|
||||
|
@ -199,6 +185,20 @@ export class Image extends React.Component<Props> {
|
|||
</div>
|
||||
) : null}
|
||||
{overlay}
|
||||
{closeButton ? (
|
||||
<button
|
||||
onClick={(e: React.MouseEvent<{}>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (onClickClose) {
|
||||
onClickClose(attachment);
|
||||
}
|
||||
}}
|
||||
className="module-image__close-button"
|
||||
title={i18n('remove-attachment')}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ export const actions = {
|
|||
};
|
||||
|
||||
function userChanged(attributes: {
|
||||
interactionMode?: 'mouse' | 'keyboard';
|
||||
ourNumber: string;
|
||||
regionCode: string;
|
||||
}): UserChangedActionType {
|
||||
|
|
|
@ -1292,18 +1292,26 @@
|
|||
{
|
||||
"rule": "jQuery-wrap(",
|
||||
"path": "libtextsecure/sync_request.js",
|
||||
"line": " wrap(sender.sendRequestContactSyncMessage(sendOptions))",
|
||||
"line": " wrap(sender.sendRequestBlockSyncMessage(sendOptions));",
|
||||
"lineNumber": 36,
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2018-10-05T23:12:28.961Z"
|
||||
"updated": "2019-12-03T00:28:08.683Z"
|
||||
},
|
||||
{
|
||||
"rule": "jQuery-wrap(",
|
||||
"path": "libtextsecure/sync_request.js",
|
||||
"line": " wrap(sender.sendRequestContactSyncMessage(sendOptions))",
|
||||
"lineNumber": 39,
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2019-12-03T00:28:08.683Z"
|
||||
},
|
||||
{
|
||||
"rule": "jQuery-wrap(",
|
||||
"path": "libtextsecure/sync_request.js",
|
||||
"line": " return wrap(sender.sendRequestGroupSyncMessage(sendOptions));",
|
||||
"lineNumber": 39,
|
||||
"lineNumber": 42,
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2018-10-05T23:12:28.961Z"
|
||||
"updated": "2019-12-03T00:28:08.683Z"
|
||||
},
|
||||
{
|
||||
"rule": "jQuery-wrap(",
|
||||
|
@ -3673,7 +3681,7 @@
|
|||
"rule": "eval",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " var a = !eval('\"use strict\";let x = 1; function f() { return typeof x; };f() == \"number\";');",
|
||||
"lineNumber": 232,
|
||||
"lineNumber": 233,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2018-11-27T01:31:13.384Z",
|
||||
"reasonDetail": "Hard-coded string used for testing capabilities."
|
||||
|
@ -3682,25 +3690,16 @@
|
|||
"rule": "eval",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " eval(a);",
|
||||
"lineNumber": 267,
|
||||
"lineNumber": 268,
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2018-11-27T01:31:13.384Z",
|
||||
"reasonDetail": "Used to load dependencies; parent function loadModuleFromSource_ is used in one place only."
|
||||
},
|
||||
{
|
||||
"rule": "eval",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " eval(g + \"\\n//# sourceURL=\" + f);",
|
||||
"lineNumber": 298,
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2019-04-12T00:50:12.124Z",
|
||||
"reasonDetail": "Used for google closure compiler transpilation scenarios"
|
||||
},
|
||||
{
|
||||
"rule": "eval",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " goog.global.eval(\"var _evalTest_ = 1;\");",
|
||||
"lineNumber": 444,
|
||||
"lineNumber": 445,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2019-04-12T00:50:12.124Z",
|
||||
"reasonDetail": "Hard-coded string used for testing capabilities"
|
||||
|
@ -3709,7 +3708,7 @@
|
|||
"rule": "eval",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " goog.global.eval(a);",
|
||||
"lineNumber": 458,
|
||||
"lineNumber": 459,
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2018-11-27T01:31:13.384Z",
|
||||
"reasonDetail": "More transpilation logic"
|
||||
|
@ -3717,16 +3716,16 @@
|
|||
{
|
||||
"rule": "jQuery-$(",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " b && (a = a.replace(/\\{\\$([^}]+)}/g, function(a, d) {",
|
||||
"lineNumber": 498,
|
||||
"line": " b && (a = a.replace(/\\{\\$([^}]+)}/g, function(a, c) {",
|
||||
"lineNumber": 500,
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2018-11-27T01:31:13.384Z"
|
||||
"updated": "2019-12-03T19:24:21.611Z"
|
||||
},
|
||||
{
|
||||
"rule": "eval",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " return !!eval(a);",
|
||||
"lineNumber": 640,
|
||||
"lineNumber": 642,
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2018-11-27T01:31:13.384Z",
|
||||
"reasonDetail": "More transpilation logic"
|
||||
|
@ -3735,7 +3734,7 @@
|
|||
"rule": "jQuery-load(",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " d.load(f);",
|
||||
"lineNumber": 796,
|
||||
"lineNumber": 794,
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2019-04-12T00:50:12.124Z",
|
||||
"reasonDetail": "Part of their google closure 'debug loader'"
|
||||
|
@ -3752,11 +3751,29 @@
|
|||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " e || (d.innerHTML = a + \" \", e = d.firstChild.nodeValue.slice(0, -1));",
|
||||
"lineNumber": 2045,
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2018-11-27T01:31:13.384Z",
|
||||
"reasonDetail": "An odd technique of unescaping content by putting it into the dom"
|
||||
"line": " a.innerHTML = goog.html.SafeHtml.unwrapTrustedHTML(goog.html.SafeHtml.EMPTY);",
|
||||
"lineNumber": 3448,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2019-12-03T19:24:21.611Z",
|
||||
"reasonDetail": "HTML is escaped"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " a.innerHTML = goog.html.SafeHtml.unwrapTrustedHTML(b);",
|
||||
"lineNumber": 3457,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2019-12-03T19:24:21.611Z",
|
||||
"reasonDetail": "HTML is escaped"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-outerHTML",
|
||||
"path": "node_modules/google-libphonenumber/dist/libphonenumber.js",
|
||||
"line": " a.outerHTML = goog.html.SafeHtml.unwrapTrustedHTML(b);",
|
||||
"lineNumber": 3469,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2019-12-03T19:24:21.611Z",
|
||||
"reasonDetail": "HTML is escaped"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
|
@ -7560,7 +7577,7 @@
|
|||
"rule": "React-createRef",
|
||||
"path": "ts/components/MainHeader.js",
|
||||
"line": " this.inputRef = react_1.default.createRef();",
|
||||
"lineNumber": 134,
|
||||
"lineNumber": 142,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2019-08-09T21:17:57.798Z",
|
||||
"reasonDetail": "Used only to set focus"
|
||||
|
|
|
@ -4242,10 +4242,10 @@ glogg@^1.0.1:
|
|||
dependencies:
|
||||
sparkles "^1.0.0"
|
||||
|
||||
google-libphonenumber@3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.2.tgz#3d9d7ba727e99a50812f21b0ed313723b76c5c54"
|
||||
integrity sha512-ubjGeosYPeusjYbUHy76lCniGTTI0k1rIFc+uKBX+jHQLDmWOSUtlFUxaeoLJ+Y+PAMM6dWp+C1HjHx5BI8kEw==
|
||||
google-libphonenumber@3.2.6:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.6.tgz#3d725b48ff44706b80246e77f95f2c2fdc6fd729"
|
||||
integrity sha512-6QCQAaKJlSd/1dUqvdQf7zzfb3uiZHsG8yhCfOdCVRfMuPZ/VDIEB47y5SYwjPQJPs7ebfW5jj6PeobB9JJ4JA==
|
||||
|
||||
got@8.2.0:
|
||||
version "8.2.0"
|
||||
|
|
Loading…
Add table
Reference in a new issue