<commit_before>(function () {
'use strict';
var module = angular.module('fim.base');
module.factory('KeyService', function ($q, $timeout, $interval, $rootScope) {

  var unlockedKeys = {};

  var SERVICE = {
    wallet: null,
    lock: function () {
      unlockedKeys = {};
      this.wallet = null;
    },
    unlock: function (password) {
      return this.wallet = loadWallet(password);
    },
    get: function (id_rs) {
      if (this.wallet) {
        return this.wallet.get(id_rs);
      }
      if (unlockedKeys[id_rs]) {
        return unlockedKeys[id_rs];
      }
      return null;
    },
    create: function (password) {
      return this.wallet = new Wallet([], password);
    },
    walletExists: function () {
      return typeof window.localStorage.getItem("mofo.key.service") == 'string';
    },
    remember: function (id_rs, secretPhrase) {
      unlockedKeys[id_rs] = secretPhrase;
    },
    remove: function () {
      window.localStorage.removeItem("mofo.key.service");
      this.wallet = null;
      unlockedKeys = {};
    }
  };

  function Wallet(entries, password) {
    this.entries = entries;
    this.mapped = {};
    for (var i=0; i<this.entries.length; i++) {
      this.mapped[this.entries[i].id_rs] = this.entries[i].secretPhrase;
    }
    this.password = password;
  }
  Wallet.prototype = {
    save: function () {
      var encrypted = encryptJSONObject(this.entries, this.password);
      window.localStorage.setItem("mofo.key.service", encrypted);
    },

    add: function (id_rs, secretPhrase) {
      this.entries.push({id_rs:id_rs, secretPhrase:secretPhrase});
      this.mapped[id_rs] = secretPhrase;
      this.save();
    },

    remove: function (id_rs) {
      this.entries = this.entries.filter(function (e) { return e.id_rs != id_rs});
      delete this.mapped[id_rs];
      this.save();
    },

    get: function (id_rs) {
      return this.mapped[id_rs];
    }
  };

  /**
   * Reads the encrypted wallet list from localStorage and decrypts it.
   * Returns an array of objects.
   *
   * @param password
   * @return Array of Object
   */
  function loadWallet(password) {
    var text = window.localStorage.getItem("mofo.key.service");
    if (!text) {
      return null;
    }
    var list = decryptJSONObject(text, password);
    if (list == null) {
      return null;
    }
    return new Wallet(list, password);
  }

  /**
   * Encrypts a JSONObject, first turns it into a string then encrypts the string
   * with the provided password.
   *
   * @param Object (JSON object)
   * @returns String (encrypted)
   */
  function encryptJSONObject(object, password) {
    var text = JSON.stringify(object);
    return encrypt(password, text);
  }

  /**
   * Decrypts a piece of encrypted stringified JSONObject, parses the decerypted
   * string into a JSON object.
   *
   * @param cipherText String
   * @returns Object or null
   */
  function decryptJSONObject(cipherText, password) {
    try {
      var text = decrypt(password, cipherText);
      var object = JSON.parse(text);
      return typeof object == 'object' ? object : null;
    } catch (e) {
      console.log(e);
      console.log('password',password);
      console.log('text',text);
      console.log('cipherText', cipherText);
      return null;
    }
  } <commit_msg>Key service fixes<commit_after>(function () {
'use strict';
var module = angular.module('fim.base');
module.factory('KeyService', function ($q, $timeout, $interval, $rootScope) {

  var unlockedKeys = {};

  var SERVICE = {
    wallet: null,
    lock: function () {
      unlockedKeys = {};
      this.wallet = null;
    },
    unlock: function (password, cipher_text_override) {
      return this.wallet = loadWallet(password, cipher_text_override);
    },
    get: function (id_rs) {
      if (this.wallet) {
        return this.wallet.get(id_rs);
      }
      if (unlockedKeys[id_rs]) {
        return unlockedKeys[id_rs];
      }
      return null;
    },
    create: function (password) {
      return this.wallet = new Wallet([], password);
    },
    walletExists: function () {
      return typeof window.localStorage.getItem("mofo.key.service") == 'string';
    },
    remember: function (id_rs, secretPhrase) {
      unlockedKeys[id_rs] = secretPhrase;
    },
    remove: function () {
      window.localStorage.removeItem("mofo.key.service");
      this.wallet = null;
      unlockedKeys = {};
    },
    toString: function () {
      return encryptJSONObject(this.wallet.entries, this.wallet.password);
    }
  };

  function Wallet(entries, password) {
    this.password = password;
    this.mapped = {};
    this.entries = [];
    for (var i=0; i<entries.length;i++) {
      if (!this.mapped[entries[i].id_rs]) {
        this.entries.push(entries[i]);
        this.mapped[entries[i].id_rs] = entries[i].secretPhrase;
      }
    }
  }
  Wallet.prototype = {
    save: function () {
      var encrypted = encryptJSONObject(this.entries, this.password);
      window.localStorage.setItem("mofo.key.service", encrypted);
    },

    add: function (id_rs, secretPhrase) {
      if (this.mapped[id_rs]) return;
      this.entries.push({id_rs:id_rs, secretPhrase:secretPhrase});
      this.mapped[id_rs] = secretPhrase;
      this.save();
    },

    remove: function (id_rs) {
      this.entries = this.entries.filter(function (e) { return e.id_rs != id_rs});
      delete this.mapped[id_rs];
      this.save();
    },

    get: function (id_rs) {
      return this.mapped[id_rs];
    }
  };

  /**
   * Reads the encrypted wallet list from localStorage and decrypts it.
   * When @cipher_text_override is provided we use that instead of reading
   * from localstorage.
   * Returns an array of objects.
   *
   * @param password
   * @param cipher_text_override
   * @return Array of Object
   */
  function loadWallet(password, cipher_text_override) {
    var text = cipher_text_override || window.localStorage.getItem("mofo.key.service");
    if (!text) {
      return null;
    }
    var list = decryptJSONObject(text, password);
    if (list == null) {
      return null;
    }
    /* support legacy wallets that have a slightly different JSON schema */
    if (!Array.isArray(list)) {
      var temp = [];
      angular.forEach(list, function (value, name) {
        if (name !== 'padding') {
          temp.push({id_rs: value.id_rs, secretPhrase:value.secretPhrase});
        }
      });
      list = temp;
    }
    return new Wallet(list, password);
  }

  /**
   * Encrypts a JSONObject, first turns it into a string then encrypts the string
   * with the provided password.
   *
   * @param Object (JSON object)
   * @returns String (encrypted)
   */
  function encryptJSONObject(object, password) {
    var text = JSON.stringify(object);
    return encrypt(password, text);
  }

  /**
   * Decrypts a piece of encrypted stringified JSONObject, parses the decerypted
   * string into a JSON object.
   *
   * @param cipherText String
   * @returns Object or null
   */
  function decryptJSONObject(cipherText, password) {
    try {
      var text = decrypt(password, cipherText);
      var object = JSON.parse(text);
      return typeof object == 'object' ? object : null;
    } catch (e) {
      // console.log(e);
      // console.log('password',password);
      // console.log('text',text);
      // console.log('cipherText', cipherText);
      return null;
    }
  } 
{'fraction_non_alphanumeric': 0.13317092976045472, 'fraction_numerical': 0.0002706726214643389, 'mean_word_length': 2.689465801298053, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': '7468207', 'n_tokens_mistral': 2359, 'n_tokens_neox': 2321, 'n_words': 539}