<commit_before>wesabe.download.Player.register({
  fid: 'us-003243',
  org: 'ING Direct',

  dispatchFrames: false,
  afterDownload: 'logoff',

  actions: {
    main: function() {
      wesabe.dom.browser.go(browser, 'https://secure.ingdirect.com/myaccount/');
    },

    customerNumber: function() {
      job.update('auth.user');
      page.fill(e.login.user.input, answers.customerNumber || answers.username);
      page.click(e.login.user.continueButton);
    },

    pin: function() {
      // prevent filling in the PIN more than once per job, since that is almost
      // always an error and could result in the user getting locked out
      if (tmp.haveGivenPinBefore) return job.fail(401, 'auth.pass.invalid');
      else tmp.haveGivenPinBefore = true;

      var pin = answers.pin || answers.password;
      var pinmap = {
        a: 2, b: 2, c: 2,
        d: 3, e: 3, f: 3,
        g: 4, h: 4, i: 4,
        j: 5, k: 5, l: 5,
        m: 6, n: 6, o: 6,
        p: 7, q: 7, r: 7, s: 7,
        t: 8, u: 8, v: 8,
        w: 9, x: 9, y: 9, z: 9
      };

      job.update('auth.pass');
      for (var i = 0; i < pin.length; i++) {
        // map letters to numbers using the above (telephone) mapping
        var n = pinmap[pin[i].toLowerCase()] || pin[i];
        page.click(wesabe.xpath.bind(e.pinNumericButton, {n: n}));
      }
      page.click(e.pinSubmitButton);
    },

    goDownloadPage: function() {
      job.update('account.download');
      page.click(e.downloadLink);
    },

    downloadActivity: function() {
      page.fill(e.downloadPeriod, '60');    // last 60 days
      page.fill(e.downloadAccount, 'ALL');  // there are cases where this is "null"
      page.fill(e.downloadType, 'OFX');     // Microsoft Money (OFX)

      // FIXME <<EMAIL>> 2009-01-22: Rip out this workaround for MainForm not having an id.
      // ING Direct released a new feature on 2009-01-22 around 8am PST where you can now specify
      // a specific date range to download rather than just the Last N Days approach (YAY!), but
      // their code relies on an IE bug [1] where document.getElementById finds things by name (BOO!).
      //
      // [1] http://blogs.msdn.com/ie/archive/2008/04/10/html-and-dom-standards-compliance-in-ie8-beta-1.aspx (item #3)
      //
      // <hack>
      var form = page.findStrict(e.downloadForm),
          formid = form.getAttribute('id');
      if (formid) {
        wesabe.warn("MainForm already has an id (", formid, ") -- doing nothing");
      } else {
        formid = form.getAttribute('name');
        wesabe.warn("Setting MainForm's id to ", formid);
        form.setAttribute('id', wesabe.untaint(formid));
      }
      // </hack>

      page.click(e.downloadButton);
    },

    logoff: function() {
      job.succeed();
      page.click(e.signOffLink);
    }
  },

  dispatch: function() {
    tmp.authenticated = page.visible(e.signOffLink);

    if (tmp.authenticated) {
      if (page.visible(e.errors.noTransactionsForPeriod)) {
        wesabe.warn('No transactions available, skipping account');
        job.succeed();
        action.logoff();
      } else if (page.visible(e.downloadPeriod)) {
        action.downloadActivity();
      } else {
        action.goDownloadPage();
      }
    } else {
      var pinIsPresent = page.present(wesabe.xpath.bind(e.pinNumericButton, {n: 1}));

      if (page.present(e.login.errors.badCreds)) {
        job.fail(401, 'auth.creds.invalid');
      } else if (page.present(e.login.errors.lockedOut)) {
        job.fail(403, 'auth.noaccess');
      } else if (pinIsPresent && page.visible(e.errors.general)) {
        job.fail(401, 'auth.creds.invalid');
      } else if (pinIsPresent) {
        action.pin();
      } else if (page.present(e.security.answers)) {
        action.answerSecurityQuestions();
      } else if (page.present(e.login.user.input)) {
        action.customerNumber();
      }
    }
  },

  elements: {<commit_msg>Fail with a more specific error message when ING asks us to change our PIN.<commit_after>wesabe.download.Player.register({
  fid: 'us-003243',
  org: 'ING Direct',

  dispatchFrames: false,
  afterDownload: 'logoff',

  actions: {
    main: function() {
      wesabe.dom.browser.go(browser, 'https://secure.ingdirect.com/myaccount/');
    },

    customerNumber: function() {
      job.update('auth.user');
      page.fill(e.login.user.input, answers.customerNumber || answers.username);
      page.click(e.login.user.continueButton);
    },

    pin: function() {
      // prevent filling in the PIN more than once per job, since that is almost
      // always an error and could result in the user getting locked out
      if (tmp.haveGivenPinBefore) return job.fail(401, 'auth.pass.invalid');
      else tmp.haveGivenPinBefore = true;

      var pin = answers.pin || answers.password;
      var pinmap = {
        a: 2, b: 2, c: 2,
        d: 3, e: 3, f: 3,
        g: 4, h: 4, i: 4,
        j: 5, k: 5, l: 5,
        m: 6, n: 6, o: 6,
        p: 7, q: 7, r: 7, s: 7,
        t: 8, u: 8, v: 8,
        w: 9, x: 9, y: 9, z: 9
      };

      job.update('auth.pass');
      for (var i = 0; i < pin.length; i++) {
        // map letters to numbers using the above (telephone) mapping
        var n = pinmap[pin[i].toLowerCase()] || pin[i];
        page.click(wesabe.xpath.bind(e.pinNumericButton, {n: n}));
      }
      page.click(e.pinSubmitButton);
    },

    goDownloadPage: function() {
      job.update('account.download');
      page.click(e.downloadLink);
    },

    downloadActivity: function() {
      page.fill(e.downloadPeriod, '60');    // last 60 days
      page.fill(e.downloadAccount, 'ALL');  // there are cases where this is "null"
      page.fill(e.downloadType, 'OFX');     // Microsoft Money (OFX)

      // FIXME <<EMAIL>> 2009-01-22: Rip out this workaround for MainForm not having an id.
      // ING Direct released a new feature on 2009-01-22 around 8am PST where you can now specify
      // a specific date range to download rather than just the Last N Days approach (YAY!), but
      // their code relies on an IE bug [1] where document.getElementById finds things by name (BOO!).
      //
      // [1] http://blogs.msdn.com/ie/archive/2008/04/10/html-and-dom-standards-compliance-in-ie8-beta-1.aspx (item #3)
      //
      // <hack>
      var form = page.findStrict(e.downloadForm),
          formid = form.getAttribute('id');
      if (formid) {
        wesabe.warn("MainForm already has an id (", formid, ") -- doing nothing");
      } else {
        formid = form.getAttribute('name');
        wesabe.warn("Setting MainForm's id to ", formid);
        form.setAttribute('id', wesabe.untaint(formid));
      }
      // </hack>

      page.click(e.downloadButton);
    },

    logoff: function() {
      job.succeed();
      page.click(e.signOffLink);
    }
  },

  dispatch: function() {
    tmp.authenticated = page.visible(e.signOffLink);

    var uri = wesabe.dom.browser.getURI(browser);
    if (uri && (uri.indexOf('pin_change_newpin') != -1)) {
      // user is being asked to change their PIN
      job.fail(403, 'auth.pass.expired');
      return;
    }

    if (tmp.authenticated) {
      if (page.visible(e.errors.noTransactionsForPeriod)) {
        wesabe.warn('No transactions available, skipping account');
        job.succeed();
        action.logoff();
      } else if (page.visible(e.downloadPeriod)) {
        action.downloadActivity();
      } else {
        action.goDownloadPage();
      }
    } else {
      var pinIsPresent = page.present(wesabe.xpath.bind(e.pinNumericButton, {n: 1}));

      if (page.present(e.login.errors.badCreds)) {
        job.fail(401, 'auth.creds.invalid');
      } else if (page.present(e.login.errors.lockedOut)) {
        job.fail(403, 'auth.noaccess');
      } else if (pinIsPresent && page.visible(e.errors.general)) {
        job.fail(401, 'auth.creds.invalid');
      } else if (pinIsPresent) {
        action.pin();
      } else if (page.present(e.security.answers)) {
        action.answerSecurityQuestions();
      } else if (page.present(e.login.user.input)) {
        action.customerNumber();
      }
    }
  },

  elements: {
{'fraction_non_alphanumeric': 0.1502635126853781, 'fraction_numerical': 0.020100502512562814, 'mean_word_length': 2.3456334563345633, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4889651', 'n_tokens_mistral': 2826, 'n_tokens_neox': 2642, 'n_words': 666}