From 0858131ede641beeb5df2d1731dd82bd5fde7d35 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Sat, 26 Mar 2022 03:55:57 +0200 Subject: [PATCH] remove some polyfills --- src/components/appSearchSuper..ts | 3 +- src/components/appSelectPeers.ts | 3 +- src/components/audio.ts | 5 +- src/components/call/description.ts | 3 +- src/components/chat/bubbleGroups.ts | 3 +- src/components/chat/bubbles.ts | 3 +- src/components/chat/input.ts | 3 +- src/components/lazyLoadQueue.ts | 3 +- src/components/peerProfileAvatars.ts | 3 +- src/components/poll.ts | 3 +- .../sidebarLeft/tabs/activeSessions.ts | 3 +- src/components/wrappers.ts | 9 +-- src/helpers/array/findAndSplice.ts | 4 ++ src/helpers/array/randomize.ts | 9 +++ src/helpers/bytes/addPadding.ts | 3 +- src/helpers/eventListenerBase.ts | 3 +- src/helpers/string/toHHMMSS.ts | 11 ++++ src/lib/appManagers/appChatsManager.ts | 3 +- src/lib/appManagers/appMessagesManager.ts | 2 +- src/lib/appManagers/appReactionsManager.ts | 5 +- src/lib/appManagers/appStickersManager.ts | 3 +- src/lib/appManagers/appUsersManager.ts | 3 +- src/lib/crypto/generateDh.ts | 3 +- src/lib/crypto/srp.ts | 3 +- src/lib/mediaPlayer.ts | 9 +-- src/lib/mtproto/apiFileManager.ts | 5 +- src/lib/mtproto/authorizer.ts | 11 ++-- src/lib/mtproto/networker.ts | 7 +- src/lib/mtproto/passwordManager.ts | 3 +- src/lib/mtproto/tl_utils.ts | 2 +- src/lib/mtproto/transports/obfuscation.ts | 5 +- src/lib/mtproto/transports/padded.ts | 3 +- src/lib/mtproto/transports/tcpObfuscated.ts | 3 +- src/lib/polyfill.ts | 65 ------------------- 34 files changed, 98 insertions(+), 111 deletions(-) create mode 100644 src/helpers/array/findAndSplice.ts create mode 100644 src/helpers/array/randomize.ts create mode 100644 src/helpers/string/toHHMMSS.ts diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index c8d698a7..ca4adfdf 100644 --- a/src/components/appSearchSuper..ts +++ b/src/components/appSearchSuper..ts @@ -54,6 +54,7 @@ import getObjectKeysAndSort from "../helpers/object/getObjectKeysAndSort"; import safeAssign from "../helpers/object/safeAssign"; import escapeRegExp from "../helpers/string/escapeRegExp"; import limitSymbols from "../helpers/string/limitSymbols"; +import findAndSplice from "../helpers/array/findAndSplice"; //const testScroll = false; @@ -1476,7 +1477,7 @@ export default class AppSearchSuper { }); if(peerId.isUser()) { - toLoad.findAndSplice(mediaTab => mediaTab.type === 'members'); + findAndSplice(toLoad, mediaTab => mediaTab.type === 'members'); } if(!toLoad.length) { diff --git a/src/components/appSelectPeers.ts b/src/components/appSelectPeers.ts index 36b1ec4b..b861ab81 100644 --- a/src/components/appSelectPeers.ts +++ b/src/components/appSelectPeers.ts @@ -27,6 +27,7 @@ import { attachClickEvent } from "../helpers/dom/clickEvent"; import filterUnique from "../helpers/array/filterUnique"; import indexOfAndSplice from "../helpers/array/indexOfAndSplice"; import safeAssign from "../helpers/object/safeAssign"; +import findAndSplice from "../helpers/array/findAndSplice"; type SelectSearchPeerType = 'contacts' | 'dialogs' | 'channelParticipants'; @@ -312,7 +313,7 @@ export default class AppSelectPeers { const newOffsetIndex = dialogs[dialogs.length - 1].index || 0; dialogs = dialogs.slice(); - dialogs.findAndSplice(d => d.peerId === rootScope.myId); // no my account + findAndSplice(dialogs, d => d.peerId === rootScope.myId); // no my account if(this.chatRightsAction) { dialogs = dialogs.filter(d => this.filterByRights(d.peerId)); diff --git a/src/components/audio.ts b/src/components/audio.ts index 6536ba76..e760b6bf 100644 --- a/src/components/audio.ts +++ b/src/components/audio.ts @@ -31,6 +31,7 @@ import { NULL_PEER_ID } from "../lib/mtproto/mtproto_config"; import formatBytes from "../helpers/formatBytes"; import { animateSingle } from "../helpers/animation"; import clamp from "../helpers/number/clamp"; +import toHHMMSS from "../helpers/string/toHHMMSS"; rootScope.addEventListener('messages_media_read', ({mids, peerId}) => { mids.forEach(mid => { @@ -423,7 +424,7 @@ export default class AudioElement extends HTMLElement { const isOutgoing = this.message.pFlags.is_outgoing; const uploading = isOutgoing && this.preloader; - const durationStr = String(doc.duration | 0).toHHMMSS(); + const durationStr = toHHMMSS(doc.duration | 0); this.innerHTML = `
@@ -466,7 +467,7 @@ export default class AudioElement extends HTMLElement { this.onTypeDisconnect = onTypeLoad(); - const getTimeStr = () => String(audio.currentTime | 0).toHHMMSS() + (isVoice ? (' / ' + durationStr) : ''); + const getTimeStr = () => toHHMMSS(audio.currentTime | 0) + (isVoice ? (' / ' + durationStr) : ''); const onPlay = () => { audioTimeDiv.innerText = getTimeStr(); diff --git a/src/components/call/description.ts b/src/components/call/description.ts index d503d07e..a9838807 100644 --- a/src/components/call/description.ts +++ b/src/components/call/description.ts @@ -5,6 +5,7 @@ */ import replaceContent from "../../helpers/dom/replaceContent"; +import toHHMMSS from "../../helpers/string/toHHMMSS"; import CALL_STATE from "../../lib/calls/callState"; import { i18n, LangPackKey } from "../../lib/langPack"; @@ -43,7 +44,7 @@ export default class CallDescriptionElement { element.classList.add('call-description-duration'); const setTime = () => { - element.innerText = ('' + instance.duration).toHHMMSS(true); + element.innerText = toHHMMSS(instance.duration, true); }; this.interval = window.setInterval(setTime, 1000); diff --git a/src/components/chat/bubbleGroups.ts b/src/components/chat/bubbleGroups.ts index 7f6738bb..c2121fdd 100644 --- a/src/components/chat/bubbleGroups.ts +++ b/src/components/chat/bubbleGroups.ts @@ -9,6 +9,7 @@ import rootScope from "../../lib/rootScope"; import { MyMessage } from "../../lib/appManagers/appMessagesManager"; import type Chat from "./chat"; import indexOfAndSplice from "../../helpers/array/indexOfAndSplice"; +import findAndSplice from "../../helpers/array/findAndSplice"; type Group = {bubble: HTMLElement, mid: number, timestamp: number}[]; type BubbleGroup = {timestamp: number, fromId: PeerId, mid: number, group: Group}; @@ -27,7 +28,7 @@ export default class BubbleGroups { const details = this.detailsMap.get(bubble); if(details) { if(details.group.length) { - details.group.findAndSplice(d => d.bubble === bubble); + findAndSplice(details.group, d => d.bubble === bubble); if(!details.group.length) { indexOfAndSplice(this.groups, details.group); } else { diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 6a4a006b..4a2fae69 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -94,6 +94,7 @@ import ScrollSaver from "../../helpers/scrollSaver"; import getObjectKeysAndSort from "../../helpers/object/getObjectKeysAndSort"; import forEachReverse from "../../helpers/array/forEachReverse"; import formatNumber from "../../helpers/number/formatNumber"; +import findAndSplice from "../../helpers/array/findAndSplice"; const USE_MEDIA_TAILS = false; const IGNORE_ACTIONS: Set = new Set([ @@ -4148,7 +4149,7 @@ export default class ChatBubbles { const subtitle = i18n('NoMessagesGreetingsDescription'); subtitle.classList.add('center', BASE_CLASS + '-subtitle'); - this.messagesQueue.findAndSplice(q => q.bubble === bubble); + findAndSplice(this.messagesQueue, q => q.bubble === bubble); const stickerDiv = document.createElement('div'); stickerDiv.classList.add(BASE_CLASS + '-sticker'); diff --git a/src/components/chat/input.ts b/src/components/chat/input.ts index 00dac6b1..e69147fc 100644 --- a/src/components/chat/input.ts +++ b/src/components/chat/input.ts @@ -92,6 +92,7 @@ import callbackify from '../../helpers/callbackify'; import ChatBotCommands from './botCommands'; import copy from '../../helpers/object/copy'; import indexOfAndSplice from '../../helpers/array/indexOfAndSplice'; +import toHHMMSS from '../../helpers/string/toHHMMSS'; const RECORD_MIN_TIME = 500; const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.'; @@ -2262,7 +2263,7 @@ export default class ChatInput { let diff = Date.now() - this.recordStartTime; let ms = diff % 1000; - let formatted = ('' + (diff / 1000)).toHHMMSS() + ',' + ('00' + Math.round(ms / 10)).slice(-2); + let formatted = toHHMMSS(diff / 1000) + ',' + ('00' + Math.round(ms / 10)).slice(-2); this.recordTimeEl.innerText = formatted; diff --git a/src/components/lazyLoadQueue.ts b/src/components/lazyLoadQueue.ts index a3b124f6..0a9e9249 100644 --- a/src/components/lazyLoadQueue.ts +++ b/src/components/lazyLoadQueue.ts @@ -9,6 +9,7 @@ import VisibilityIntersector, { OnVisibilityChange } from "./visibilityIntersect import throttle from "../helpers/schedulers/throttle"; import findAndSpliceAll from "../helpers/array/findAndSpliceAll"; import indexOfAndSplice from "../helpers/array/indexOfAndSplice"; +import findAndSplice from "../helpers/array/findAndSplice"; type LazyLoadElementBase = { load: () => Promise @@ -252,7 +253,7 @@ export default class LazyLoadQueue extends LazyLoadQueueIntersector { }; protected getItem() { - return this.queue.findAndSplice(item => item.wasSeen); + return findAndSplice(this.queue, item => item.wasSeen); } public async processItem(item: LazyLoadElement) { diff --git a/src/components/peerProfileAvatars.ts b/src/components/peerProfileAvatars.ts index 4c2aaa94..8543d797 100644 --- a/src/components/peerProfileAvatars.ts +++ b/src/components/peerProfileAvatars.ts @@ -6,6 +6,7 @@ import IS_PARALLAX_SUPPORTED from "../environment/parallaxSupport"; import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport"; +import findAndSplice from "../helpers/array/findAndSplice"; import { cancelEvent } from "../helpers/dom/cancelEvent"; import { attachClickEvent } from "../helpers/dom/clickEvent"; import filterChatPhotosMessages from "../helpers/filterChatPhotosMessages"; @@ -286,7 +287,7 @@ export default class PeerProfileAvatars { if(!listLoader.current) { const chatFull = result[0]; - const message = value.history.findAndSplice(m => { + const message = findAndSplice(value.history, m => { return ((m as Message.messageService).action as MessageAction.messageActionChannelEditPhoto).photo.id === chatFull.chat_photo.id; }) as Message.messageService; diff --git a/src/components/poll.ts b/src/components/poll.ts index a7b99c46..1b0d2bfc 100644 --- a/src/components/poll.ts +++ b/src/components/poll.ts @@ -23,6 +23,7 @@ import { attachClickEvent, detachClickEvent } from "../helpers/dom/clickEvent"; import replaceContent from "../helpers/dom/replaceContent"; import windowSize from "../helpers/windowSize"; import { Poll, PollResults } from "../layer"; +import toHHMMSS from "../helpers/string/toHHMMSS"; let lineTotalLength = 0; const tailLength = 9; @@ -342,7 +343,7 @@ export default class PollElement extends HTMLElement { const time = Date.now(); const percents = (closeTime - time) / period; const timeLeft = (closeTime - time) / 1000 + 1 | 0; - timeLeftDiv.innerHTML = String(timeLeft).toHHMMSS(); + timeLeftDiv.innerHTML = toHHMMSS(timeLeft); if (timeLeft <= 5) { timeLeftDiv.style.color = '#ee545c'; diff --git a/src/components/sidebarLeft/tabs/activeSessions.ts b/src/components/sidebarLeft/tabs/activeSessions.ts index 95088a82..0739a2a1 100644 --- a/src/components/sidebarLeft/tabs/activeSessions.ts +++ b/src/components/sidebarLeft/tabs/activeSessions.ts @@ -21,6 +21,7 @@ import findUpClassName from "../../../helpers/dom/findUpClassName"; import { attachClickEvent } from "../../../helpers/dom/clickEvent"; import toggleDisability from "../../../helpers/dom/toggleDisability"; import { SliderSuperTabEventable } from "../../sliderTab"; +import findAndSplice from "../../../helpers/array/findAndSplice"; export default class AppActiveSessionsTab extends SliderSuperTabEventable { public authorizations: Authorization.authorization[]; @@ -58,7 +59,7 @@ export default class AppActiveSessionsTab extends SliderSuperTabEventable { caption: 'ClearOtherSessionsHelp' }); - const auth = authorizations.findAndSplice(auth => auth.pFlags.current); + const auth = findAndSplice(authorizations, auth => auth.pFlags.current); const session = Session(auth); section.content.append(session.container); diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts index 986b4b88..cebdc57b 100644 --- a/src/components/wrappers.ts +++ b/src/components/wrappers.ts @@ -57,6 +57,7 @@ import IS_VIBRATE_SUPPORTED from '../environment/vibrateSupport'; import Row from './row'; import { ChatAutoDownloadSettings } from '../helpers/autoDownload'; import formatBytes from '../helpers/formatBytes'; +import toHHMMSS from '../helpers/string/toHHMMSS'; const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB @@ -123,7 +124,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai let needPlayButton = false; if(doc.type !== 'gif') { - spanTime.innerText = (doc.duration + '').toHHMMSS(false); + spanTime.innerText = toHHMMSS(doc.duration, false); if(!noPlayButton && doc.type !== 'round') { if(canAutoplay && !noAutoDownload) { @@ -266,7 +267,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai onFrame(); } - spanTime.innerText = (globalVideo.duration - globalVideo.currentTime + '').toHHMMSS(false); + spanTime.innerText = toHHMMSS(globalVideo.duration - globalVideo.currentTime, false); }; const throttledTimeUpdate = throttleWithRaf(onTimeUpdate); @@ -295,7 +296,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai divRound.classList.add('is-paused'); video.currentTime = 0; - spanTime.innerText = ('' + globalVideo.duration).toHHMMSS(false); + spanTime.innerText = toHHMMSS(globalVideo.duration, false); if(globalVideo.currentTime) { globalVideo.currentTime = 0; @@ -451,7 +452,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai if(doc.type === 'video') { video.addEventListener('timeupdate', () => { - spanTime.innerText = (video.duration - video.currentTime + '').toHHMMSS(false); + spanTime.innerText = toHHMMSS(video.duration - video.currentTime, false); }); if(spanPlay) { diff --git a/src/helpers/array/findAndSplice.ts b/src/helpers/array/findAndSplice.ts new file mode 100644 index 00000000..6940a469 --- /dev/null +++ b/src/helpers/array/findAndSplice.ts @@ -0,0 +1,4 @@ +export default function findAndSplice(array: Array, verify: (value: T, index?: number, array?: Array) => boolean) { + const index = array.findIndex(verify); + return index !== -1 ? array.splice(index, 1)[0] : undefined; +}; diff --git a/src/helpers/array/randomize.ts b/src/helpers/array/randomize.ts new file mode 100644 index 00000000..2f5e1246 --- /dev/null +++ b/src/helpers/array/randomize.ts @@ -0,0 +1,9 @@ +export default function randomize(arr: T) { + if(crypto && 'getRandomValues' in crypto) { + crypto.getRandomValues(arr); + } else { + throw new Error('NO_SECURE_RANDOM'); + } + + return arr; +} diff --git a/src/helpers/bytes/addPadding.ts b/src/helpers/bytes/addPadding.ts index db2b322e..1aa984d5 100644 --- a/src/helpers/bytes/addPadding.ts +++ b/src/helpers/bytes/addPadding.ts @@ -1,3 +1,4 @@ +import randomize from "../array/randomize"; import bufferConcats from "./bufferConcats"; export default function addPadding( @@ -17,7 +18,7 @@ export default function addPadding>> = new WeakMap(); @@ -105,7 +106,7 @@ export default class EventListenerBase public removeEventListener(name: T, callback: Listeners[T], options?: boolean | AddEventListenerOptions) { if(this.listeners[name]) { - this.listeners[name].findAndSplice(l => l.callback === callback); + findAndSplice(this.listeners[name], l => l.callback === callback); } //e.remove(this, name, callback); } diff --git a/src/helpers/string/toHHMMSS.ts b/src/helpers/string/toHHMMSS.ts new file mode 100644 index 00000000..3d5d7f48 --- /dev/null +++ b/src/helpers/string/toHHMMSS.ts @@ -0,0 +1,11 @@ +export default function toHHMMSS(str: string | number, leadZero = false) { + const sec_num = parseInt(str + '', 10); + const hours = Math.floor(sec_num / 3600); + let minutes: any = Math.floor((sec_num - (hours * 3600)) / 60); + let seconds: any = sec_num - (hours * 3600) - (minutes * 60); + + if(hours) leadZero = true; + if(minutes < 10) minutes = leadZero ? "0" + minutes : minutes; + if(seconds < 10) seconds = "0" + seconds; + return (hours ? /* ('0' + hours).slice(-2) */hours + ':' : '') + minutes + ':' + seconds; +} diff --git a/src/lib/appManagers/appChatsManager.ts b/src/lib/appManagers/appChatsManager.ts index 332ce029..3b599852 100644 --- a/src/lib/appManagers/appChatsManager.ts +++ b/src/lib/appManagers/appChatsManager.ts @@ -24,6 +24,7 @@ import appPeersManager from "./appPeersManager"; import appStateManager from "./appStateManager"; import appUsersManager from "./appUsersManager"; import { isRestricted } from "../../helpers/restrictions"; +import findAndSplice from "../../helpers/array/findAndSplice"; export type Channel = Chat.channel; export type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags'] | 'change_type' | 'change_permissions' | 'delete_chat' | 'view_participants'; @@ -104,7 +105,7 @@ export class AppChatsManager { delete this.usernames[cleanUsername(chat.username)]; } */ - chats.findAndSplice((chat) => chat.id === chatId); + findAndSplice(chats, (chat) => chat.id === chatId); this.storage.delete(chatId); delete this.chats[chatId]; } diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index 2da4265d..d3f5df75 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -5576,7 +5576,7 @@ export class AppMessagesManager { if(options.userReaction) { const langPackKey: LangPackKey = /* isAnyChat ? 'Notification.Group.Reacted' : */'Notification.Contact.Reacted'; const args: FormatterArguments = [ - options.userReaction.reaction, + RichTextProcessor.fixEmoji(options.userReaction.reaction), // can be plain heart notificationMessage ]; diff --git a/src/lib/appManagers/appReactionsManager.ts b/src/lib/appManagers/appReactionsManager.ts index 1f6cca43..ecfc616a 100644 --- a/src/lib/appManagers/appReactionsManager.ts +++ b/src/lib/appManagers/appReactionsManager.ts @@ -5,6 +5,7 @@ */ import { MOUNT_CLASS_TO } from "../../config/debug"; +import findAndSplice from "../../helpers/array/findAndSplice"; import assumeType from "../../helpers/assumeType"; import callbackify from "../../helpers/callbackify"; import callbackifyAll from "../../helpers/callbackifyAll"; @@ -113,7 +114,7 @@ export class AppReactionsManager { } private unshiftQuickReactionInner(availableReactions: AvailableReaction.availableReaction[], quickReaction: AvailableReaction.availableReaction) { - const availableReaction = availableReactions.findAndSplice(availableReaction => availableReaction.reaction === quickReaction.reaction); + const availableReaction = findAndSplice(availableReactions, availableReaction => availableReaction.reaction === quickReaction.reaction); if(availableReaction) { availableReactions.unshift(availableReaction); } @@ -245,7 +246,7 @@ export class AppReactionsManager { } */ if(reactions.recent_reactions) { - reactions.recent_reactions.findAndSplice((recentReaction) => appPeersManager.getPeerId(recentReaction.peer_id) === myPeerId); + findAndSplice(reactions.recent_reactions, (recentReaction) => appPeersManager.getPeerId(recentReaction.peer_id) === myPeerId); } if(!reactions.results.length) { diff --git a/src/lib/appManagers/appStickersManager.ts b/src/lib/appManagers/appStickersManager.ts index 2637b374..4d309353 100644 --- a/src/lib/appManagers/appStickersManager.ts +++ b/src/lib/appManagers/appStickersManager.ts @@ -20,6 +20,7 @@ import assumeType from '../../helpers/assumeType'; import fixBase64String from '../../helpers/fixBase64String'; import IS_WEBM_SUPPORTED from '../../environment/webmSupport'; import forEachReverse from '../../helpers/array/forEachReverse'; +import findAndSplice from '../../helpers/array/findAndSplice'; const CACHE_TIME = 3600e3; @@ -568,7 +569,7 @@ export class AppStickersManager { for(const emoticon in this.getStickersByEmoticonsPromises) { const promise = this.getStickersByEmoticonsPromises[emoticon]; promise.then(stickers => { - const _doc = stickers.findAndSplice(_doc => _doc.id === doc.id); + const _doc = findAndSplice(stickers, _doc => _doc.id === doc.id); if(_doc) { stickers.unshift(_doc); } else if(emoticon.includes(docEmoticon)) { diff --git a/src/lib/appManagers/appUsersManager.ts b/src/lib/appManagers/appUsersManager.ts index 583041af..84d8eb3f 100644 --- a/src/lib/appManagers/appUsersManager.ts +++ b/src/lib/appManagers/appUsersManager.ts @@ -11,6 +11,7 @@ import { MOUNT_CLASS_TO } from "../../config/debug"; import filterUnique from "../../helpers/array/filterUnique"; +import findAndSplice from "../../helpers/array/findAndSplice"; import indexOfAndSplice from "../../helpers/array/indexOfAndSplice"; import { CancellablePromise, deferredPromise } from "../../helpers/cancellablePromise"; import cleanSearchText from "../../helpers/cleanSearchText"; @@ -190,7 +191,7 @@ export class AppUsersManager { delete this.usernames[cleanUsername(user.username)]; } - users.findAndSplice((user) => user.id === userId); + findAndSplice(users, (user) => user.id === userId); this.storage.delete(userId); delete this.users[userId]; } diff --git a/src/lib/crypto/generateDh.ts b/src/lib/crypto/generateDh.ts index f8a817c5..fcb6294a 100644 --- a/src/lib/crypto/generateDh.ts +++ b/src/lib/crypto/generateDh.ts @@ -5,6 +5,7 @@ */ import bigInt from "big-integer"; +import randomize from "../../helpers/array/randomize"; import { bigIntFromBytes } from "../../helpers/bigInt/bigIntConversion"; import addPadding from "../../helpers/bytes/addPadding"; import bytesFromHex from "../../helpers/bytes/bytesFromHex"; @@ -17,7 +18,7 @@ export default async function generateDh(dhConfig: MessagesDhConfig.messagesDhCo const generateA = (p: Uint8Array) => { for(;;) { - const a = new Uint8Array(p.length).randomize(); + const a = randomize(new Uint8Array(p.length)); // const a = new Uint8Array(4).randomize(); const aBigInt = bigIntFromBytes(a); // str2bigInt(bytesToHex(a), 16); diff --git a/src/lib/crypto/srp.ts b/src/lib/crypto/srp.ts index 383ae151..f849c4b3 100644 --- a/src/lib/crypto/srp.ts +++ b/src/lib/crypto/srp.ts @@ -118,7 +118,8 @@ export default async function computeSRP(password: string, state: AccountPasswor const a_for_hash = bigIntToBytes(A); const s = await cryptoWorker.invokeCrypto('sha256', bufferConcats(a_for_hash, b_for_hash)); - const u = bigInt(s.hex, 16); + // const u = bigInt(s.hex, 16); + const u = bigIntFromBytes(s); if(!u.isZero() && !u.isNegative()) return {a, a_for_hash, u}; } diff --git a/src/lib/mediaPlayer.ts b/src/lib/mediaPlayer.ts index 5b89916d..beaa9d39 100644 --- a/src/lib/mediaPlayer.ts +++ b/src/lib/mediaPlayer.ts @@ -18,6 +18,7 @@ import { GrabEvent } from "../helpers/dom/attachGrabListeners"; import { attachClickEvent } from "../helpers/dom/clickEvent"; import ControlsHover from "../helpers/dom/controlsHover"; import { addFullScreenListener, cancelFullScreen, isFullScreen, requestFullScreen } from "../helpers/dom/fullScreen"; +import toHHMMSS from "../helpers/string/toHHMMSS"; export class MediaProgressLine extends RangeSelector { protected filledLoad: HTMLDivElement; @@ -351,7 +352,7 @@ export default class VideoPlayer extends ControlsHover { const fullScreenButton = wrapper.querySelector('.fullscreen') as HTMLElement; const timeElapsed = wrapper.querySelector('#time-elapsed'); timeDuration = wrapper.querySelector('#time-duration') as HTMLElement; - timeDuration.innerHTML = String(video.duration | 0).toHHMMSS(); + timeDuration.innerHTML = toHHMMSS(video.duration | 0); const volumeSelector = new VolumeSelector(listenerSetter); @@ -430,7 +431,7 @@ export default class VideoPlayer extends ControlsHover { addFullScreenListener(wrapper, this.onFullScreen.bind(this, fullScreenButton), listenerSetter); listenerSetter.add(video)('timeupdate', () => { - timeElapsed.innerHTML = String(video.currentTime | 0).toHHMMSS(); + timeElapsed.innerHTML = toHHMMSS(video.currentTime | 0); }); listenerSetter.add(video)('play', () => { @@ -461,10 +462,10 @@ export default class VideoPlayer extends ControlsHover { }); if(video.duration || initDuration) { - timeDuration.innerHTML = String(Math.round(video.duration || initDuration)).toHHMMSS(); + timeDuration.innerHTML = toHHMMSS(Math.round(video.duration || initDuration)); } else { onMediaLoad(video).then(() => { - timeDuration.innerHTML = String(Math.round(video.duration)).toHHMMSS(); + timeDuration.innerHTML = toHHMMSS(Math.round(video.duration)); }); } } diff --git a/src/lib/mtproto/apiFileManager.ts b/src/lib/mtproto/apiFileManager.ts index af805035..e25af9fb 100644 --- a/src/lib/mtproto/apiFileManager.ts +++ b/src/lib/mtproto/apiFileManager.ts @@ -29,6 +29,7 @@ import ctx from "../../environment/ctx"; import noop from "../../helpers/noop"; import readBlobAsArrayBuffer from "../../helpers/blob/readBlobAsArrayBuffer"; import bytesToHex from "../../helpers/bytes/bytesToHex"; +import findAndSplice from "../../helpers/array/findAndSplice"; type Delayed = { offset: number, @@ -145,7 +146,7 @@ export class ApiFileManager { } //const data = downloadPull.shift(); - const data = downloadPull.findAndSplice(d => d.queueId === 0) || downloadPull.findAndSplice(d => d.queueId === this.queueId) || downloadPull.shift(); + const data = findAndSplice(downloadPull, d => d.queueId === 0) || findAndSplice(downloadPull, d => d.queueId === this.queueId) || downloadPull.shift(); const activeDelta = data.activeDelta || 1; this.downloadActives[dcId] += activeDelta; @@ -521,7 +522,7 @@ export class ApiFileManager { this.cachedDownloadPromises[fileName] = deferred; - deferred.safeFinally(() => { + deferred.catch(noop).finally(() => { delete this.cachedDownloadPromises[fileName]; }); diff --git a/src/lib/mtproto/authorizer.ts b/src/lib/mtproto/authorizer.ts index 2a9adf25..4053470a 100644 --- a/src/lib/mtproto/authorizer.ts +++ b/src/lib/mtproto/authorizer.ts @@ -31,6 +31,7 @@ import bytesToHex from "../../helpers/bytes/bytesToHex"; import bytesXor from "../../helpers/bytes/bytesXor"; import { bigIntFromBytes } from "../../helpers/bigInt/bigIntConversion"; import bigInt from "big-integer"; +import randomize from "../../helpers/array/randomize"; /* let fNewNonce: any = bytesFromHex('8761970c24cb2329b5b2459752c502f3057cb7e8dbab200e526e8767fdc73b3c').reverse(); let fNonce: any = bytesFromHex('b597720d11faa5914ef485c529cde414').reverse(); @@ -200,7 +201,7 @@ export class Authorizer { request.storeMethod('req_pq_multi', {nonce: auth.nonce}); if(DEBUG) { - this.log('Send req_pq', auth.nonce.hex); + this.log('Send req_pq', bytesToHex(auth.nonce)); } let deserializer: Awaited>; @@ -262,7 +263,7 @@ export class Authorizer { } private async sendReqDhParams(auth: AuthOptions): Promise { - auth.newNonce = new Uint8Array(32).randomize(); + auth.newNonce = randomize(new Uint8Array(32)); const p_q_inner_data_dc: P_Q_inner_data = { _: 'p_q_inner_data_dc', @@ -288,7 +289,7 @@ export class Authorizer { const getKeyAesEncrypted = async() => { for(;;) { - const tempKey = new Uint8Array(32).randomize(); + const tempKey = randomize(new Uint8Array(32)); const dataWithHash = dataPadReversed.concat(await CryptoWorker.invokeCrypto('sha256', tempKey.concat(dataWithPadding))); if(dataWithHash.length !== 224) { throw 'DH_params: dataWithHash !== 224 bytes!'; @@ -475,7 +476,7 @@ export class Authorizer { private async sendSetClientDhParams(auth: AuthOptions): Promise { const gBytes = bytesFromHex(auth.g.toString(16)); - auth.b = new Uint8Array(256).randomize(); + auth.b = randomize(new Uint8Array(256)); //MTProto.secureRandom.nextBytes(auth.b); // let gB: Awaited>; @@ -611,7 +612,7 @@ export class Authorizer { try { const auth: AuthOptions = { dcId, - nonce: new Uint8Array(16).randomize() + nonce: randomize(new Uint8Array(16)) }; const promise = this.sendReqPQ(auth); diff --git a/src/lib/mtproto/networker.ts b/src/lib/mtproto/networker.ts index 475658b7..6091caa1 100644 --- a/src/lib/mtproto/networker.ts +++ b/src/lib/mtproto/networker.ts @@ -40,6 +40,7 @@ import convertToUint8Array from '../../helpers/bytes/convertToUint8Array'; import isObject from '../../helpers/object/isObject'; import forEachReverse from '../../helpers/array/forEachReverse'; import sortLongsArray from '../../helpers/long/sortLongsArray'; +import randomize from '../../helpers/array/randomize'; //console.error('networker included!', new Error().stack); @@ -193,7 +194,7 @@ export default class MTPNetworker { private updateSession() { this.seqNo = 0; this.prevSessionId = this.sessionId; - this.sessionId = new Uint8Array(8).randomize(); + this.sessionId = randomize(new Uint8Array(8)); } /* private clearContainers() { @@ -1149,7 +1150,7 @@ export default class MTPNetworker { } */ const paddingLength = (16 - (data.getOffset() % 16)) + 16 * (1 + nextRandomUint(8) % 5); - const padding = /* (message as any).padding || */new Uint8Array(paddingLength).randomize()/* .fill(0) */; + const padding = /* (message as any).padding || */randomize(new Uint8Array(paddingLength))/* .fill(0) */; /* const padding = [167, 148, 207, 226, 86, 192, 193, 57, 124, 153, 174, 145, 159, 1, 5, 70, 127, 157, 51, 241, 46, 85, 141, 212, 139, 234, 213, 164, 197, 116, 245, 70, 184, 40, 40, 201, 233, 211, 150, 94, 57, 84, 1, 135, 108, 253, 34, 139, 222, 208, 71, 214, 90, 67, 36, 28, 167, 148, 207, 226, 86, 192, 193, 57, 124, 153, 174, 145, 159, 1, 5, 70, 127, 157, @@ -1249,7 +1250,7 @@ export default class MTPNetworker { const authKeyId = deserializer.fetchIntBytes(64, true, 'auth_key_id'); if(!bytesCmp(authKeyId, this.authKeyId)) { - throw new Error('[MT] Invalid server auth_key_id: ' + authKeyId.hex); + throw new Error('[MT] Invalid server auth_key_id: ' + bytesToHex(authKeyId)); } const msgKey = deserializer.fetchIntBytes(128, true, 'msg_key'); diff --git a/src/lib/mtproto/passwordManager.ts b/src/lib/mtproto/passwordManager.ts index 011bd7b8..a03a3498 100644 --- a/src/lib/mtproto/passwordManager.ts +++ b/src/lib/mtproto/passwordManager.ts @@ -12,6 +12,7 @@ import type { AccountPassword, AccountUpdatePasswordSettings, InputCheckPasswordSRP, PasswordKdfAlgo } from '../../layer'; import { MOUNT_CLASS_TO } from '../../config/debug'; import apiManager from './mtprotoworker'; +import randomize from '../../helpers/array/randomize'; export class PasswordManager { public getState(): Promise { @@ -52,7 +53,7 @@ export class PasswordManager { // * https://core.telegram.org/api/srp#setting-a-new-2fa-password, but still there is a mistake, TDesktop passes 'new_algo' everytime const newAlgo = state.new_algo as PasswordKdfAlgo.passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; const salt1 = new Uint8Array(newAlgo.salt1.length + 32); - salt1.randomize(); + randomize(salt1); salt1.set(newAlgo.salt1, 0); newAlgo.salt1 = salt1; diff --git a/src/lib/mtproto/tl_utils.ts b/src/lib/mtproto/tl_utils.ts index f55f4fba..36e34709 100644 --- a/src/lib/mtproto/tl_utils.ts +++ b/src/lib/mtproto/tl_utils.ts @@ -484,7 +484,7 @@ class TLDeserialization { this.debug/* || field.includes('[dialog][read_outbox_max_id]') */ && console.log('<<<', i.toString(16), i, field, this.byteView.slice(this.offset - 16, this.offset + 16), - this.byteView.slice(this.offset - 16, this.offset + 16).hex); + bytesToHex(this.byteView.slice(this.offset - 16, this.offset + 16))); this.offset += 4; diff --git a/src/lib/mtproto/transports/obfuscation.ts b/src/lib/mtproto/transports/obfuscation.ts index 577078d2..83c88f66 100644 --- a/src/lib/mtproto/transports/obfuscation.ts +++ b/src/lib/mtproto/transports/obfuscation.ts @@ -6,6 +6,7 @@ //import aesjs from 'aes-js'; import AES from "@cryptography/aes"; +import randomize from "../../../helpers/array/randomize"; import bytesFromWordss from "../../../helpers/bytes/bytesFromWordss"; import { Codec } from "./codec"; @@ -72,7 +73,7 @@ export default class Obfuscation { public /* async */ init(codec: Codec) { const initPayload = new Uint8Array(64); - initPayload.randomize(); + randomize(initPayload); while(true) { const val = (initPayload[3] << 24) | (initPayload[2] << 16) | (initPayload[1] << 8) | initPayload[0]; @@ -88,7 +89,7 @@ export default class Obfuscation { //initPayload[56] = initPayload[57] = initPayload[58] = initPayload[59] = transport; break; } - initPayload.randomize(); + randomize(initPayload); } ////////////////////////initPayload.subarray(60, 62).hex = dcId; diff --git a/src/lib/mtproto/transports/padded.ts b/src/lib/mtproto/transports/padded.ts index a9b6d023..03c0f65b 100644 --- a/src/lib/mtproto/transports/padded.ts +++ b/src/lib/mtproto/transports/padded.ts @@ -4,6 +4,7 @@ * https://github.com/morethanwords/tweb/blob/master/LICENSE */ +import randomize from "../../../helpers/array/randomize"; import { nextRandomUint } from "../../../helpers/random"; import { IntermediatePacketCodec } from "./intermediate"; /* Data packets are aligned to 4bytes. This codec adds random bytes of size @@ -13,7 +14,7 @@ class PaddedIntermediatePacketCodec extends IntermediatePacketCodec { public obfuscateTag = new Uint8Array([this.tag, this.tag, this.tag, this.tag]); public encodePacket(data: Uint8Array) { - let padding = new Uint8Array(nextRandomUint(8) % 3).randomize(); + let padding = randomize(new Uint8Array(nextRandomUint(8) % 3)); let len = data.byteLength + padding.byteLength; let header = new Uint8Array(new Uint32Array([len]).buffer); diff --git a/src/lib/mtproto/transports/tcpObfuscated.ts b/src/lib/mtproto/transports/tcpObfuscated.ts index b316e901..8df09b28 100644 --- a/src/lib/mtproto/transports/tcpObfuscated.ts +++ b/src/lib/mtproto/transports/tcpObfuscated.ts @@ -14,6 +14,7 @@ import { ConnectionStatus } from "../connectionStatus"; /// #if MTPROTO_AUTO import transportController from "./controller"; +import bytesToHex from "../../../helpers/bytes/bytesToHex"; /// #endif export default class TcpObfuscated implements MTTransport { @@ -112,7 +113,7 @@ export default class TcpObfuscated implements MTTransport { //console.log('got hex:', data.hex); const pending = this.pending.shift(); if(!pending) { - this.debug && this.log.debug('no pending for res:', data.hex); + this.debug && this.log.debug('no pending for res:', bytesToHex(data)); return; } diff --git a/src/lib/polyfill.ts b/src/lib/polyfill.ts index 67557d43..53004f4e 100644 --- a/src/lib/polyfill.ts +++ b/src/lib/polyfill.ts @@ -5,30 +5,6 @@ */ import bufferConcats from "../helpers/bytes/bufferConcats"; -import bytesFromHex from "../helpers/bytes/bytesFromHex"; -import bytesToHex from "../helpers/bytes/bytesToHex"; - -Object.defineProperty(Uint8Array.prototype, 'hex', { - get: function(): string { - return bytesToHex(this); - }, - - set: function(str: string) { - this.set(bytesFromHex(str)); - }, - enumerable: true, - configurable: true -}); - -Uint8Array.prototype.randomize = function() { - if(crypto && 'getRandomValues' in crypto) { - crypto.getRandomValues(this); - } else { - throw new Error('NO_SECURE_RANDOM'); - } - - return this; -}; Uint8Array.prototype.concat = function(...args: Array) { return bufferConcats(this, ...args); @@ -43,32 +19,6 @@ Uint8Array.prototype.toJSON = function() { //return {type: 'bytes', value: [...this]}; }; -Array.prototype.findAndSplice = function(verify: (value: T, index?: number, array?: Array) => boolean) { - let index = this.findIndex(verify); - return index !== -1 ? this.splice(index, 1)[0] : undefined; -}; - -String.prototype.toHHMMSS = function(leadZero = false) { - const sec_num = parseInt(this + '', 10); - const hours = Math.floor(sec_num / 3600); - let minutes: any = Math.floor((sec_num - (hours * 3600)) / 60); - let seconds: any = sec_num - (hours * 3600) - (minutes * 60); - - if(hours) leadZero = true; - if(minutes < 10) minutes = leadZero ? "0" + minutes : minutes; - if(seconds < 10) seconds = "0" + seconds; - return (hours ? /* ('0' + hours).slice(-2) */hours + ':' : '') + minutes + ':' + seconds; -}; - -/* Promise.prototype.finally = Promise.prototype.finally || { - finally(fn: () => any) { - const onFinally = (callback: typeof fn) => Promise.resolve(fn()).then(callback); - return this.then( - result => onFinally(() => result), - reason => onFinally(() => Promise.reject(reason)) - ); - } -}.finally; */ Promise.prototype.finally = Promise.prototype.finally || function(this: Promise, fn: () => any) { const onFinally = (callback: typeof fn) => Promise.resolve(fn()).then(callback); return this.then( @@ -77,30 +27,15 @@ Promise.prototype.finally = Promise.prototype.finally || function(this: Promi ); }; -Promise.prototype.safeFinally = function(this: Promise, fn: () => any) { - return this.catch(() => {}).finally(fn); -}; - declare global { interface Uint8Array { - hex: string; - randomize: () => Uint8Array, concat: (...args: Array) => Uint8Array, //toString: () => string, toJSON: () => number[], //toJSON: () => {type: 'bytes', value: number[]}, } - interface Array { - findAndSplice(verify: (value: T, index?: number, array?: Array) => boolean): T; - } - - interface String { - toHHMMSS(leadZero?: boolean): string; - } - interface Promise { finally: (onfinally?: () => void) => Promise; - safeFinally: (onfinally?: () => void) => Promise; } }