async messageParseCallback()

in mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js [944:1243]


  async messageParseCallback(
    msgText,
    msgDate,
    contentEncoding,
    charset,
    interactive,
    importOnly,
    messageUrl,
    signature,
    retry,
    head,
    tail,
    msgUriSpec,
    isAuto,
    pbMessageIndex
  ) {
    if (!msgText) {
      return;
    }

    EnigmailCore.init();

    var plainText;
    var exitCode;
    var newSignature = "";
    var statusFlags = 0;
    var extStatusFlags = 0;

    var errorMsgObj = {
      value: "",
    };
    var keyIdObj = {};
    var userIdObj = {};
    var sigDetailsObj = {};
    var extraDetailsObj = {};

    var blockSeparationObj = {
      value: "",
    };

    if (importOnly) {
      // Import public key
      await this.importKeyFromMsgBody(msgText);
      return;
    }
    // See https://www.rfc-editor.org/rfc/rfc4880#section-6
    // An implementation MAY implement this key and any
    //   translations it cares to; an implementation MAY ignore it and
    //   assume all text is UTF-8.
    const armorHeaders = EnigmailArmor.getArmorHeaders(msgText);
    if ("charset" in armorHeaders) {
      charset = armorHeaders.charset;
    }

    var exitCodeObj = {};
    var statusFlagsObj = {};
    var signatureObj = {};
    signatureObj.value = signature;

    var uiFlags = interactive
      ? EnigmailConstants.UI_INTERACTIVE |
        // EnigmailConstants.UI_ALLOW_KEY_IMPORT |
        EnigmailConstants.UI_UNVERIFIED_ENC_OK
      : 0;

    plainText = await EnigmailDecryption.decryptMessage(
      window,
      uiFlags,
      msgText,
      msgDate,
      signatureObj,
      exitCodeObj,
      statusFlagsObj,
      keyIdObj,
      userIdObj,
      sigDetailsObj,
      errorMsgObj,
      blockSeparationObj,
      extraDetailsObj
    );
    exitCode = exitCodeObj.value;
    newSignature = signatureObj.value;

    if (plainText === "" && exitCode === 0) {
      plainText = " ";
    }

    statusFlags = statusFlagsObj.value;
    extStatusFlags = statusFlagsObj.ext;

    var errorMsg = errorMsgObj.value;

    if (importOnly) {
      if (interactive && errorMsg) {
        Services.prompt.alert(window, null, errorMsg);
      }
      return;
    }

    var displayedUriSpec = Enigmail.msg.getCurrentMsgUriSpec();
    if (!msgUriSpec || displayedUriSpec == msgUriSpec) {
      if (exitCode && !statusFlags) {
        // Failure, but we don't know why it failed.
        // Peek inside msgText, and check what kind of content it is,
        // so we can show a minimal error.

        const msgType = Enigmail.msg.getFirstPGPMessageType(msgText);
        if (msgType == "encrypted") {
          statusFlags = EnigmailConstants.DECRYPTION_FAILED;
        } else if (msgType == "signed") {
          statusFlags = EnigmailConstants.BAD_SIGNATURE;
        }
      }

      Enigmail.hdrView.updatePgpStatus(
        exitCode,
        statusFlags,
        extStatusFlags,
        keyIdObj.value,
        userIdObj.value,
        sigDetailsObj.value,
        errorMsg,
        null, // blockSeparation
        extraDetailsObj.value
      );
    }

    var noSecondTry =
      EnigmailConstants.GOOD_SIGNATURE |
      EnigmailConstants.EXPIRED_SIGNATURE |
      EnigmailConstants.EXPIRED_KEY_SIGNATURE |
      EnigmailConstants.EXPIRED_KEY |
      EnigmailConstants.REVOKED_KEY |
      EnigmailConstants.NO_PUBKEY |
      EnigmailConstants.NO_SECKEY |
      EnigmailConstants.IMPORTED_KEY |
      EnigmailConstants.MISSING_PASSPHRASE |
      EnigmailConstants.BAD_PASSPHRASE |
      EnigmailConstants.UNKNOWN_ALGO |
      EnigmailConstants.DECRYPTION_OKAY |
      EnigmailConstants.OVERFLOWED;

    if (exitCode !== 0 && !(statusFlags & noSecondTry)) {
      // Bad signature/armor
      if (retry == 1) {
        msgText = MailStringUtils.stringToByteString(msgText);
        console.warn(`Retrying decrypt; retry=${retry}, msgText=${msgText}`);
        await Enigmail.msg.messageParseCallback(
          msgText,
          msgDate,
          contentEncoding,
          charset,
          interactive,
          importOnly,
          messageUrl,
          signature,
          retry + 1,
          head,
          tail,
          msgUriSpec,
          isAuto,
          pbMessageIndex
        );
        return;
      } else if (retry == 2) {
        console.warn(`Retrying decrypt; retry=${retry} - direct decrypt`);
        // Try to verify signature by accessing raw message text directly
        // (avoid recursion by setting retry parameter to false on callback)
        newSignature = "";
        await Enigmail.msg.msgDirectDecrypt(
          interactive,
          importOnly,
          contentEncoding,
          charset,
          newSignature,
          0,
          head,
          tail,
          msgUriSpec,
          msgDate,
          Enigmail.msg.messageParseCallback,
          isAuto
        );
        return;
      } else if (retry == 3) {
        msgText = MailStringUtils.stringToByteString(msgText);
        console.warn(`Retrying decrypt; retry=${retry}, msgText=${msgText}`);
        await Enigmail.msg.messageParseCallback(
          msgText,
          msgDate,
          contentEncoding,
          charset,
          interactive,
          importOnly,
          messageUrl,
          null,
          retry + 1,
          head,
          tail,
          msgUriSpec,
          isAuto,
          pbMessageIndex
        );
        return;
      }
    }

    if (!plainText) {
      // Show the subset that we cannot process, together with status.
      plainText = msgText;
    }

    if (retry >= 2) {
      plainText = EnigmailData.convertFromUnicode(
        MailStringUtils.byteStringToString(plainText),
        charset
      );
    }

    // TODO: what is blockSeparation ? How to emulate with RNP?
    /*
    if (blockSeparationObj.value.includes(" ")) {
      var blocks = blockSeparationObj.value.split(/ /);
      var blockInfo = blocks[0].split(/:/);
      plainText =
          "*Parts of the message have NOT been signed nor encrypted*",
        "\n\n" +
        plainText.substr(0, blockInfo[1]) +
        "\n\n" +
        "*Multiple message blocks found -- decryption/verification aborted*";
    }
    */

    // Save decrypted message status, headers, and content
    var headerList = {
      subject: "",
      from: "",
      date: "",
      to: "",
      cc: "",
    };

    if (!gViewAllHeaders) {
      for (let index = 0; index < headerList.length; index++) {
        headerList[index] = "";
      }
    } else {
      for (let index = 0; index < gExpandedHeaderList.length; index++) {
        headerList[gExpandedHeaderList[index].name] = "";
      }

      for (const headerName in currentHeaderData) {
        headerList[headerName] = "";
      }
    }

    for (const headerName in headerList) {
      if (currentHeaderData[headerName]) {
        headerList[headerName] = currentHeaderData[headerName].headerValue;
      }
    }

    // WORKAROUND
    if (headerList.cc == headerList.to) {
      headerList.cc = "";
    }

    var hasAttachments = currentAttachments && currentAttachments.length;
    var attachmentsEncrypted = true;

    for (const attachment of currentAttachments) {
      if (!Enigmail.msg.checkEncryptedAttach(attachment)) {
        if (
          !EnigmailMsgRead.checkSignedAttachment(attachment, currentAttachments)
        ) {
          attachmentsEncrypted = false;
        }
      }
    }

    // don't display decrypted message if message selection has changed
    displayedUriSpec = Enigmail.msg.getCurrentMsgUriSpec();
    if (msgUriSpec && displayedUriSpec && displayedUriSpec != msgUriSpec) {
      return;
    }
    let msgContent = "";
    if (hasAttachments && !attachmentsEncrypted) {
      msgContent =
        "\r\n" +
        EnigmailData.convertFromUnicode(
          l10n.formatValueSync("enig-content-note"),
          charset
        ) +
        "\r\n\r\n";
    }
    msgContent += plainText;

    msgContent = MailStringUtils.byteStringToString(msgContent, charset);
    this.setDisplayToText(msgContent);
  },