<commit_before>import { EncryptionState } from '../../plugin/AbstractPlugin'
import PluginAPI from '../../plugin/PluginAPI'
import { EncryptionPlugin } from '../../plugin/EncryptionPlugin'
import Contact from '../../Contact'
import Message from '../../Message'
import { DIRECTION } from '../../Message.interface'
import Session from './Session'
import DSA from 'otr/lib/dsa'
import Options from '../../Options'

import dsaWebworkerFile = require('otr/build/dsa-webworker.js?path')
import ChatWindow from '@ui/ChatWindow';
import { ContactType, IContact } from '@src/Contact.interface';
import Translation from '@util/Translation';
import VerificationDialog from '@ui/dialogs/verification';

const WHITESPACE_TAG = '\x20\x09\x20\x20\x09\x09\x09\x09\x20\x09\x20\x09\x20\x09\x20\x20';

interface IDSA {
   parsePrivate
   createInWebWorker
   packPrivate
}

Options.addDefaults({
   otr: {
      ERROR_START_AKE: false,
      debug: false,
      SEND_WHITESPACE_TAG: false,
      WHITESPACE_START_AKE: true
   }
});

const MIN_VERSION = '4.0.0';
const MAX_VERSION = '4.0.0';

export default class OTRPlugin extends EncryptionPlugin {
   private sessions = {};
   private key: IDSA;

   public static getName(): string {
      return 'otr';
   }

   constructor(pluginAPI: PluginAPI) {
      super(MIN_VERSION, MAX_VERSION, pluginAPI);

      pluginAPI.getStorage().registerHook('key', (key) => {
         if (this.key && this.key !== key) {
            this.pluginAPI.Log.warn('Something went wrong. We have two different DSA keys.');
         }

         this.key = key;
      });

      pluginAPI.addAfterReceiveMessageProcessor(this.afterReceiveMessageProcessor);
      pluginAPI.addPreSendMessageProcessor(this.preSendMessageProcessor);

      pluginAPI.registerChatWindowInitializedHook((chatWindow: ChatWindow) => {
         let contact = chatWindow.getContact();

         if (contact.getType() !== ContactType.CHAT) {
            return;
         }

         //@TODO enable/disable according to encryption state
         chatWindow.addMenuEntry('otr-verification', 'OTR ' + Translation.t('Verification'), () => this.openVerificationDialog(contact));
      });
   }

   public toggleTransfer(contact: Contact): Promise<void> {
      return this.getSession(contact).then((session: Session) => {
         if (session.isEnded()) {
            return session.end();
         } else if (session.isEncrypted()) {
            return session.goPlain();
         } else {
            return session.goEncrypted();
         }
      });
   }

   private afterReceiveMessageProcessor = (contact: Contact, message: Message, stanza: Element) => {
      let plaintextMessage = message.getPlaintextMessage();
      if (!plaintextMessage || (!/^\?OTR/.test(plaintextMessage) && plaintextMessage.indexOf(WHITESPACE_TAG) < 0)) {
         return Promise.resolve([contact, message, stanza]);
      }

      return this.getSession(contact).then((session: Session) => {
         return session.processMessage(message, 'decryptMessage');
      }).then((message) => {
         return [contact, message, stanza];
      });
   }

   private preSendMessageProcessor = (contact: Contact, message: Message) => {
      if (contact.getEncryptionState() === EncryptionState.Plaintext || contact.getEncryptionPluginName() !== OTRPlugin.getName()) {
         return Promise.resolve([contact, message]);
      }

      return this.getSession(contact).then((session: Session) => {
         if (session.isEnded()) {
            //@TODO block this message
            message.setDirection(DIRECTION.SYS);
            message.setPlaintextMessage('This message was not send');

            return message;
         } else if (session.isEncrypted()) {
            return session.processMessage(message, 'encryptMessage');
         } else {
            return message;<commit_msg>fix: block messages if otr session is ended<commit_after>import { EncryptionState } from '../../plugin/AbstractPlugin'
import PluginAPI from '../../plugin/PluginAPI'
import { EncryptionPlugin } from '../../plugin/EncryptionPlugin'
import Contact from '../../Contact'
import Message from '../../Message'
import Session from './Session'
import DSA from 'otr/lib/dsa'
import Options from '../../Options'

import dsaWebworkerFile = require('otr/build/dsa-webworker.js?path')
import ChatWindow from '@ui/ChatWindow';
import { ContactType, IContact } from '@src/Contact.interface';
import Translation from '@util/Translation';
import VerificationDialog from '@ui/dialogs/verification';

const WHITESPACE_TAG = '\x20\x09\x20\x20\x09\x09\x09\x09\x20\x09\x20\x09\x20\x09\x20\x20';

interface IDSA {
   parsePrivate
   createInWebWorker
   packPrivate
}

Options.addDefaults({
   otr: {
      ERROR_START_AKE: false,
      debug: false,
      SEND_WHITESPACE_TAG: false,
      WHITESPACE_START_AKE: true
   }
});

const MIN_VERSION = '4.0.0';
const MAX_VERSION = '4.0.0';

export default class OTRPlugin extends EncryptionPlugin {
   private sessions = {};
   private key: IDSA;

   public static getName(): string {
      return 'otr';
   }

   constructor(pluginAPI: PluginAPI) {
      super(MIN_VERSION, MAX_VERSION, pluginAPI);

      pluginAPI.getStorage().registerHook('key', (key) => {
         if (this.key && this.key !== key) {
            this.pluginAPI.Log.warn('Something went wrong. We have two different DSA keys.');
         }

         this.key = key;
      });

      pluginAPI.addAfterReceiveMessageProcessor(this.afterReceiveMessageProcessor);
      pluginAPI.addPreSendMessageProcessor(this.preSendMessageProcessor);

      pluginAPI.registerChatWindowInitializedHook((chatWindow: ChatWindow) => {
         let contact = chatWindow.getContact();

         if (contact.getType() !== ContactType.CHAT) {
            return;
         }

         //@TODO enable/disable according to encryption state
         chatWindow.addMenuEntry('otr-verification', 'OTR ' + Translation.t('Verification'), () => this.openVerificationDialog(contact));
      });
   }

   public toggleTransfer(contact: Contact): Promise<void> {
      return this.getSession(contact).then((session: Session) => {
         if (session.isEnded()) {
            return session.end();
         } else if (session.isEncrypted()) {
            return session.goPlain();
         } else {
            return session.goEncrypted();
         }
      });
   }

   private afterReceiveMessageProcessor = (contact: Contact, message: Message, stanza: Element) => {
      let plaintextMessage = message.getPlaintextMessage();
      if (!plaintextMessage || (!/^\?OTR/.test(plaintextMessage) && plaintextMessage.indexOf(WHITESPACE_TAG) < 0)) {
         return Promise.resolve([contact, message, stanza]);
      }

      return this.getSession(contact).then((session: Session) => {
         return session.processMessage(message, 'decryptMessage');
      }).then((message) => {
         return [contact, message, stanza];
      });
   }

   private preSendMessageProcessor = (contact: Contact, message: Message) => {
      if (contact.getEncryptionState() === EncryptionState.Plaintext || contact.getEncryptionPluginName() !== OTRPlugin.getName()) {
         return Promise.resolve([contact, message]);
      }

      return this.getSession(contact).then((session: Session) => {
         if (session.isEnded()) {
            contact.addSystemMessage(Translation.t('your_message_wasnt_send_please_end_your_private_conversation'));

            throw new Error('OTR session is ended');
         } else if (session.isEncrypted()) {
            return session.processMessage(message, 'encryptMessage');
         } else {
            return message;
{'fraction_non_alphanumeric': 0.13304552590266877, 'fraction_numerical': 0.01020408163265306, 'mean_word_length': 3.055702917771883, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3363870', 'n_tokens_mistral': 2219, 'n_tokens_neox': 2149, 'n_words': 457}