diff --git a/app/sql.js b/app/sql.js index 8c395d5da..086100c5b 100644 --- a/app/sql.js +++ b/app/sql.js @@ -106,7 +106,6 @@ module.exports = { updateConversation, removeConversation, getAllConversations, - getAllRssFeedConversations, getAllPublicConversations, getPublicConversationsByServer, getPubkeysInPublicConversation, @@ -810,6 +809,7 @@ const LOKI_SCHEMA_VERSIONS = [ updateToLokiSchemaVersion3, updateToLokiSchemaVersion4, updateToLokiSchemaVersion5, + updateToLokiSchemaVersion6, ]; async function updateToLokiSchemaVersion1(currentVersion, instance) { @@ -999,6 +999,34 @@ async function updateToLokiSchemaVersion5(currentVersion, instance) { console.log('updateToLokiSchemaVersion5: success!'); } +async function updateToLokiSchemaVersion6(currentVersion, instance) { + if (currentVersion >= 6) { + return; + } + + console.log('updateToLokiSchemaVersion6: starting...'); + + await instance.run('BEGIN TRANSACTION;'); + + // Remove RSS Feed conversations + await instance.run( + `DELETE FROM conversations WHERE + type = 'group' AND + id LIKE 'rss://%';` + ); + + await instance.run( + `INSERT INTO loki_schema ( + version + ) values ( + 6 + );` + ); + + await instance.run('COMMIT TRANSACTION;'); + console.log('updateToLokiSchemaVersion6: success!'); +} + async function updateLokiSchema(instance) { const result = await instance.get( "SELECT name FROM sqlite_master WHERE type = 'table' AND name='loki_schema';" @@ -1905,17 +1933,6 @@ async function getAllPrivateConversations() { return map(rows, row => jsonToObject(row.json)); } -async function getAllRssFeedConversations() { - const rows = await db.all( - `SELECT json FROM conversations WHERE - type = 'group' AND - id LIKE 'rss://%' - ORDER BY id ASC;` - ); - - return map(rows, row => jsonToObject(row.json)); -} - async function getAllPublicConversations() { const rows = await db.all( `SELECT json FROM conversations WHERE diff --git a/background.html b/background.html index ad3063e11..db453bb99 100644 --- a/background.html +++ b/background.html @@ -456,7 +456,6 @@ - diff --git a/background_test.html b/background_test.html index cbb09488c..c6a198b6e 100644 --- a/background_test.html +++ b/background_test.html @@ -456,7 +456,6 @@ - diff --git a/js/background.js b/js/background.js index f14212183..2bcb012b3 100644 --- a/js/background.js +++ b/js/background.js @@ -216,14 +216,6 @@ if (specialConvInited) { return; } - const rssFeedConversations = await window.Signal.Data.getAllRssFeedConversations( - { - ConversationCollection: Whisper.ConversationCollection, - } - ); - rssFeedConversations.forEach(conversation => { - window.feeds.push(new window.LokiRssAPI(conversation.getRssSettings())); - }); const publicConversations = await window.Signal.Data.getAllPublicConversations( { ConversationCollection: Whisper.ConversationCollection, @@ -1480,6 +1472,10 @@ return; } + if (firstRun) { + window.readyForUpdates(); + } + if (!Whisper.Registration.everDone()) { return; } diff --git a/js/models/blockedNumbers.js b/js/models/blockedNumbers.js deleted file mode 100644 index cb24c6466..000000000 --- a/js/models/blockedNumbers.js +++ /dev/null @@ -1,83 +0,0 @@ -/* global storage, _ */ -/* global _: false */ -/* global Backbone: false */ - -/* global BlockedNumberController: false */ -/* global storage: false */ -/* global Whisper: false */ - -/* eslint-disable more/no-then */ - -// eslint-disable-next-line func-names -(function() { - 'use strict'; - - window.Whisper = window.Whisper || {}; - - const BLOCKED_NUMBERS_ID = 'blocked'; - const BLOCKED_GROUPS_ID = 'blocked-groups'; - - storage.isBlocked = number => { - const numbers = storage.get(BLOCKED_NUMBERS_ID, []); - - return _.include(numbers, number); - }; - storage.getBlockedNumbers = () => storage.get(BLOCKED_NUMBERS_ID, []); - storage.addBlockedNumber = number => { - const numbers = storage.get(BLOCKED_NUMBERS_ID, []); - if (_.include(numbers, number)) { - return; - } - - window.log.info('adding', number, 'to blocked list'); - storage.put(BLOCKED_NUMBERS_ID, numbers.concat(number)); - }; - storage.removeBlockedNumber = number => { - const numbers = storage.get(BLOCKED_NUMBERS_ID, []); - if (!_.include(numbers, number)) { - return; - } - - window.log.info('removing', number, 'from blocked list'); - storage.put(BLOCKED_NUMBERS_ID, _.without(numbers, number)); - }; - - storage.isGroupBlocked = groupId => { - const groupIds = storage.get(BLOCKED_GROUPS_ID, []); - - return _.include(groupIds, groupId); - }; - storage.removeBlockedGroup = groupId => { - const groupIds = storage.get(BLOCKED_GROUPS_ID, []); - if (!_.include(groupIds, groupId)) { - return; - } - - window.log.info(`removing group(${groupId} from blocked list`); - storage.put(BLOCKED_GROUPS_ID, _.without(groupIds, groupId)); - }; - - Whisper.BlockedNumber = Backbone.Model.extend({ - defaults() { - return { - number: '', - }; - }, - block() { - return BlockedNumberController.block(this.number); - }, - unblock() { - return BlockedNumberController.unblock(this.number); - }, - }); - - Whisper.BlockedNumberCollection = Backbone.Collection.extend({ - model: Whisper.BlockedNumber, - comparator(m) { - return m.get('number'); - }, - getModel(number) { - return this.models.find(m => m.get('number') === number); - }, - }); -})(); diff --git a/js/modules/data.js b/js/modules/data.js index 1f27ff1d6..e532978e1 100644 --- a/js/modules/data.js +++ b/js/modules/data.js @@ -124,7 +124,6 @@ module.exports = { getAllConversations, getAllConversationIds, getAllPrivateConversations, - getAllRssFeedConversations, getAllPublicConversations, getPublicConversationsByServer, getPubkeysInPublicConversation, @@ -811,14 +810,6 @@ async function getAllConversationIds() { return ids; } -async function getAllRssFeedConversations({ ConversationCollection }) { - const conversations = await channels.getAllRssFeedConversations(); - - const collection = new ConversationCollection(); - collection.add(conversations); - return collection; -} - async function getAllPublicConversations({ ConversationCollection }) { const conversations = await channels.getAllPublicConversations(); diff --git a/js/modules/loki_app_dot_net_api.js b/js/modules/loki_app_dot_net_api.js index da97bfdb8..cc05254cc 100644 --- a/js/modules/loki_app_dot_net_api.js +++ b/js/modules/loki_app_dot_net_api.js @@ -1533,6 +1533,10 @@ class LokiPublicChannelAPI { }); if (res.err || !res.response || !res.response.data) { + if (res.statusCode === 403) { + // token is now invalid + this.serverAPI.getOrRefreshServerToken(true); + } return; } @@ -1656,6 +1660,10 @@ class LokiPublicChannelAPI { !res.response.data || !res.response.meta ) { + if (res.statusCode === 403) { + // token is now invalid + this.serverAPI.getOrRefreshServerToken(true); + } if (res.err) { log.error(`pollOnceForDeletions Error ${res.err}`); } else { @@ -1852,6 +1860,10 @@ class LokiPublicChannelAPI { }); if (res.err || !res.response) { + if (res.statusCode === 403) { + // token is now invalid + this.serverAPI.getOrRefreshServerToken(true); + } log.error( `app_dot_net:::pollOnceForMessages - Could not get messages from`, this.serverAPI.baseServerUrl, diff --git a/js/modules/loki_rss_api.js b/js/modules/loki_rss_api.js deleted file mode 100644 index ff857ff78..000000000 --- a/js/modules/loki_rss_api.js +++ /dev/null @@ -1,162 +0,0 @@ -/* eslint-disable no-await-in-loop */ -/* eslint-disable no-loop-func */ -/* global log, window, textsecure */ - -const EventEmitter = require('events'); - -const PER_MIN = 60 * 1000; -const PER_HR = 60 * PER_MIN; -const RSS_POLL_EVERY = 1 * PER_HR; // once an hour - -function xml2json(xml) { - try { - let obj = {}; - if (xml.children.length > 0) { - for (let i = 0; i < xml.children.length; i += 1) { - const item = xml.children.item(i); - const { nodeName } = item; - - if (typeof obj[nodeName] === 'undefined') { - obj[nodeName] = xml2json(item); - } else { - if (typeof obj[nodeName].push === 'undefined') { - const old = obj[nodeName]; - - obj[nodeName] = []; - obj[nodeName].push(old); - } - obj[nodeName].push(xml2json(item)); - } - } - } else { - obj = xml.textContent; - } - return obj; - } catch (e) { - log.error(e.message); - } - return {}; -} - -class LokiRssAPI extends EventEmitter { - constructor(settings) { - super(); - // properties - this.feedUrl = settings.RSS_FEED; - this.groupId = settings.CONVO_ID; - this.feedTitle = settings.title; - this.closeable = settings.closeable; - // non configureable options - this.feedTimer = null; - // initial set up - this.getFeed(); - } - - async getFeed() { - // deal with file server proxy hardcoding - const map = { - 'https://loki.network/category/messenger-updates/feed/': - 'loki/v1/rss/messenger', - 'https://loki.network/feed/': 'loki/v1/rss/loki', - }; - if (map[this.feedUrl] === undefined) { - log.warn('LokiRssAPI unsupported rss feed', this.feedUrl); - return; - } - const result = await window.tokenlessFileServerAdnAPI.serverRequest( - map[this.feedUrl] - ); - if (!result) { - log.error('LokiRssAPI empty rss proxy response'); - return; - } - if (!result.response) { - log.error('LokiRssAPI rss proxy error, no response', result); - return; - } - if (!result.response.data) { - log.error( - 'LokiRssAPI rss proxy error, no data, response', - typeof result.response, - result.response - ); - return; - } - const responseXML = result.response.data; - let feedDOM = {}; - try { - feedDOM = await new window.DOMParser().parseFromString( - responseXML, - 'text/xml' - ); - } catch (e) { - log.error('LokiRssAPI xml parsing error', e, responseXML); - return; - } - const feedObj = xml2json(feedDOM); - let receivedAt = new Date().getTime(); - - if (!feedObj || !feedObj.rss || !feedObj.rss.channel) { - log.error( - 'LokiRssAPI rss structure error', - feedObj, - feedDOM, - responseXML - ); - return; - } - if (!feedObj.rss.channel.item) { - // no records, not an error - return; - } - if (feedObj.rss.channel.item.constructor !== Array) { - // Treat single record as array for consistency - feedObj.rss.channel.item = [feedObj.rss.channel.item]; - } - feedObj.rss.channel.item.reverse().forEach(item => { - // log.debug('item', item) - - const pubDate = new Date(item.pubDate); - - // if we use group style, we can put the title in the source - const messageData = { - isSessionRequest: false, - source: this.groupId, - sourceDevice: 1, - timestamp: pubDate.getTime(), - serverTimestamp: pubDate.getTime(), - receivedAt, - isRss: true, - message: { - body: `

${item.title}

${item.description}`, - attachments: [], - group: { - id: this.groupId, - type: textsecure.protobuf.GroupContext.Type.DELIVER, - }, - flags: 0, - expireTimer: 0, - profileKey: null, - timestamp: pubDate.getTime(), - received_at: receivedAt, - sent_at: pubDate.getTime(), - quote: null, - contact: [], - preview: [], - profile: null, - }, - }; - receivedAt += 1; // Ensure different arrival times - this.emit('rssMessage', { - message: messageData, - }); - }); - const ref = this; - function callTimer() { - ref.getFeed(); - } - this.feedTimer = setTimeout(callTimer, RSS_POLL_EVERY); - } -} - -module.exports = LokiRssAPI; diff --git a/package.json b/package.json index 41b04d124..15fc7b89e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "1.0.9", + "version": "1.1.2", "license": "GPL-3.0", "author": { "name": "Loki Project", @@ -312,7 +312,7 @@ "!**/node_modules/*/build/**", "!**/*.{o,hprof,orig,pyc,pyo,rbc}", "!**/._*", - "!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore,.gitattributes,.editorconfig,.flowconfig,.yarn-metadata.json,.idea,appveyor.yml,.travis.yml,circle.yml,npm-debug.log,.nyc_output,yarn.lock,.yarn-integrity}", + "!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore,.gitattributes,.editorconfig,.flowconfig,.yarn-metadata.json,.idea,appveyor.yml,.travis.yml,circle.yml,npm-debug.log,.nyc_output,yarn.lock,.yarn-integrity,.map}", "node_modules/spellchecker/build/Release/*.node", "node_modules/websocket/build/Release/*.node", "node_modules/socks/build/*.js", diff --git a/password_preload.js b/password_preload.js index e0cc712ef..d499b1609 100644 --- a/password_preload.js +++ b/password_preload.js @@ -21,19 +21,18 @@ window.getEnvironment = () => config.environment; window.getVersion = () => config.version; window.getAppInstance = () => config.appInstance; -// So far we're only using this for Signal.Types -const Signal = require('./js/modules/signal'); const electron = require('electron'); const ipc = electron.ipcRenderer; - -window.Signal = Signal.setup({ - Attachments: null, - userDataPath: null, - getRegionCode: () => null, -}); - -window.Signal.Logs = require('./js/modules/logs'); +const { + SessionPasswordPrompt, +} = require('./ts/components/session/SessionPasswordPrompt'); + +window.Signal = { + Components: { + SessionPasswordPrompt, + }, +} window.CONSTANTS = { MAX_LOGIN_TRIES: 3, diff --git a/preload.js b/preload.js index 2761195cf..4956a29cf 100644 --- a/preload.js +++ b/preload.js @@ -358,8 +358,6 @@ window.LokiPublicChatAPI = require('./js/modules/loki_public_chat_api'); window.LokiFileServerAPI = require('./js/modules/loki_file_server_api'); -window.LokiRssAPI = require('./js/modules/loki_rss_api'); - window.mnemonic = require('./libloki/modules/mnemonic'); const WorkerInterface = require('./js/modules/util_worker_interface'); diff --git a/test/index.html b/test/index.html index c98043693..7e9022a49 100644 --- a/test/index.html +++ b/test/index.html @@ -503,7 +503,6 @@ - diff --git a/ts/receiver/dataMessage.ts b/ts/receiver/dataMessage.ts index c371e6778..24de0c604 100644 --- a/ts/receiver/dataMessage.ts +++ b/ts/receiver/dataMessage.ts @@ -236,7 +236,7 @@ export async function processDecrypted(envelope: EnvelopePlus, decrypted: any) { /* tslint:disable:no-bitwise */ } -function isMessageEmpty(message: SignalService.DataMessage) { +export function isMessageEmpty(message: SignalService.DataMessage) { const { flags, body, @@ -251,7 +251,8 @@ function isMessageEmpty(message: SignalService.DataMessage) { return ( !flags && - _.isEmpty(body) && + // FIXME remove this hack to drop auto friend requests messages in a few weeks 15/07/2020 + isBodyEmpty(body) && _.isEmpty(attachments) && _.isEmpty(group) && _.isEmpty(quote) && @@ -262,6 +263,16 @@ function isMessageEmpty(message: SignalService.DataMessage) { ); } +function isBodyEmpty(body: string) { + return _.isEmpty(body) || isBodyAutoFRContent(body); +} + +function isBodyAutoFRContent(body: string) { + return ( + body === 'Please accept to enable messages to be synced across devices' + ); +} + export async function handleDataMessage( envelope: EnvelopePlus, dataMessage: SignalService.IDataMessage diff --git a/ts/receiver/multidevice.ts b/ts/receiver/multidevice.ts index 9633c3247..6dd9142b6 100644 --- a/ts/receiver/multidevice.ts +++ b/ts/receiver/multidevice.ts @@ -338,22 +338,29 @@ async function onContactReceived(details: any) { activeAt = activeAt || Date.now(); conversation.set('active_at', activeAt); } - const ourPrimaryKey = window.storage.get('primaryDevicePubKey'); - if (ourPrimaryKey) { - const secondaryDevices = await MultiDeviceProtocol.getSecondaryDevices( - ourPrimaryKey - ); - if (secondaryDevices.some(device => device.key === id)) { - await conversation.setSecondaryStatus(true, ourPrimaryKey); - } - } - const devices = await MultiDeviceProtocol.getAllDevices(id); - const deviceConversations = await Promise.all( - devices.map(d => - ConversationController.getOrCreateAndWait(d.key, 'private') - ) + const primaryDevice = await MultiDeviceProtocol.getPrimaryDevice(id); + const secondaryDevices = await MultiDeviceProtocol.getSecondaryDevices(id); + const primaryConversation = await ConversationController.getOrCreateAndWait( + primaryDevice.key, + 'private' + ); + const secondaryConversations = await Promise.all( + secondaryDevices.map(async d => { + const secondaryConv = await ConversationController.getOrCreateAndWait( + d.key, + 'private' + ); + await secondaryConv.setSecondaryStatus(true, primaryDevice.key); + return conversation; + }) ); + + const deviceConversations = [ + primaryConversation, + ...secondaryConversations, + ]; + // triger session request with every devices of that user // when we do not have a session with it already deviceConversations.forEach(device => { @@ -366,23 +373,17 @@ async function onContactReceived(details: any) { conversation.setProfileKey(profileKey); } - if (details.blocked !== 'undefined') { - if (details.blocked) { - storage.addBlockedNumber(id); - } else { - storage.removeBlockedNumber(id); - } - } - // Do not set name to allow working with lokiProfile and nicknames conversation.set({ // name: details.name, color: details.color, }); - await conversation.setLokiProfile({ displayName: details.name }); + if (details.name && details.name.length) { + await conversation.setLokiProfile({ displayName: details.name }); + } - if (details.nickname) { + if (details.nickname && details.nickname.length) { await conversation.setNickname(details.nickname); } diff --git a/ts/receiver/syncMessages.ts b/ts/receiver/syncMessages.ts index d4d574bc7..94b56e432 100644 --- a/ts/receiver/syncMessages.ts +++ b/ts/receiver/syncMessages.ts @@ -7,11 +7,16 @@ import ByteBuffer from 'bytebuffer'; import { handleEndSession } from './sessionHandling'; import { handleMediumGroupUpdate } from './mediumGroups'; -import { handleMessageEvent, processDecrypted } from './dataMessage'; +import { + handleMessageEvent, + isMessageEmpty, + processDecrypted, +} from './dataMessage'; import { updateProfile } from './receiver'; import { handleContacts } from './multidevice'; import { onGroupReceived } from './groups'; import { MultiDeviceProtocol } from '../session/protocols'; +import { DataMessage } from '../session/messages/outgoing'; export async function handleSyncMessage( envelope: EnvelopePlus, @@ -88,6 +93,12 @@ async function handleSentMessage( return; } + if (isMessageEmpty(msg as SignalService.DataMessage)) { + window.console.log('dropping empty message synced'); + await removeFromCache(envelope); + return; + } + const { ConversationController } = window; // tslint:disable-next-line no-bitwise diff --git a/ts/window.d.ts b/ts/window.d.ts index 10b903a2b..659146ca0 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -25,7 +25,6 @@ declare global { LokiAppDotNetServerAPI: any; LokiFileServerAPI: any; LokiPublicChatAPI: any; - LokiRssAPI: any; LokiSnodeAPI: any; MessageController: any; Session: any;