Reveal Passwords Bookmarklet (change all password fields into regular text fields)

Discussion in 'JavaScript' started by brian394, Jun 12, 2006.

  1. #1
    The other day I was doing some research into bookmarklets and I decided to do a search on this forum to see if anyone had posted any interesting ones. Although I didn't find any I did come across an interesting question...

    http://forums.digitalpoint.com/showthread.php?t=24550

    Someone posted this about a year ago and was basically asking if there was such a bookmarklet can convert all password text fields on a page into normal text fields (without the aterisks). It wasn't so much that the person wanted to "reveal" his passwords, he basically just wanted to see what he was typing. Well, I think he explains it better...

    I searched long and hard for this but I couldn't find anything so I decided to write my own. I knew that it was possible and at first I just thought, "well, that's easy, all you have to do is go through all textboxes on the page and find all the ones which have a type of "password" and change their type to "text". Well, turns out, that doesn't work. Buried deep within Microsoft's site I finally found out why.

    So once a password field has been rendered to the page you can't change it's type. So I thought "ok, what's another way of doing this?". Then I figured another thing I could do is create a new textbox and position it on the page exactly over the password textbox and then mimic every key that was typed in to the new textbox into the password textbox. This would give the "illusion" that the password text field had been replaced. I spent a couple days debugging it and I think I finally have come up with a working solution. Here is a demo page I set up that shows it in action...

    Demo: http://home.earthlink.net/~duhomax/reveal_pw_bookmarklet.html

    There are three bookmarklets on the page.

    1.) Show All Textbox values
    This will simply go through all forms and iframes on the page and collect the value of all the textboxes on the page and then display them to you in a message box.

    2.) Reveal Passwords
    This is the real workhorse. This bookmarklet will go through all forms and iframes on the page and then create a replacement textbox for every password textbox it finds. It will then copy all attributes of the password textbox (length, borders, background color, etc.) and try to position itself exactly over the password text field. Then, when you type a key into this text field it will mimic (echo) it back to the original password text field.

    3.) Reveal Passwords for IE
    This is the same as #2 but it's made for IE only. In IE 6, bookmarklets are limited to a maximum of 508 characters. Since my code is longer than that I have to put it into an external script to get it to run properly.

    And finally here is the actual code that "reveals" the aterisks (well, it doesn't actually "reveal" anything, it just creates a new textbox on top of the old textbox, but the end result is the same)...

    
    if (typeof frst_time == 'undefined') {
     var tb_cnt=0, new_tf=new Array(), old_tf=new Array(), frst_time=true;
    }
    
    function rvl() {
     if (frst_time == true) {
      var D=document, F=D.forms;
      if (F.length > 0) {
       rvl2(F,D);
      }
      var R=D.frames;
      if (R.length > 0) {
       var r, m=0;
       for(m=0; m<R.length; m++) {
        D = R[m].document;
        r = D.forms;
        rvl2(r,D);
       }
      }
      frst_time = false;
     }
    }
    
    function rvl2(F,D) {
     var a, att, f, n, i=0, j=0, k=0;
     for(j=0; j<F.length; j++) {
      f=F[j];
      for(i=0; i<f.length; i++) {
       if (f[i].type.toLowerCase() == 'password') {
        if (D.getElementById) {
         old_tf[tb_cnt] = f[i];
         new_tf[tb_cnt] = D.createElement('input');
         new_tf[tb_cnt].type = 'text';
         new_tf[tb_cnt].value = old_tf[tb_cnt].value;
         a = old_tf[tb_cnt].attributes;
         for(k=0; k<a.length; k++) {
          n = old_tf[tb_cnt].attributes.item(k).nodeName.toLowerCase();
          if((old_tf[tb_cnt].attributes.item(k).specified) && (n != 'type')){
           att = D.createAttribute(n);
           att.value = old_tf[tb_cnt].attributes.item(k).nodeValue;
           new_tf[tb_cnt].attributes.setNamedItem(att);
          }
         }
         new_tf[tb_cnt].name = '';
         new_tf[tb_cnt].id = old_tf[tb_cnt].id + '_1';
         old_tf[tb_cnt].style.position = 'absolute';
         old_tf[tb_cnt].style.overflow = 'hidden';
         old_tf[tb_cnt].style.top = '-9999px';
         old_tf[tb_cnt].style.left = '-9999px';
         old_tf[tb_cnt].insertAdjacentElement('afterEnd',new_tf[tb_cnt]);
         new_tf[tb_cnt].onkeyup = function() {this.previousSibling.value = this.value;};
         tb_cnt++;
        }
       }
      }
     }
    }
    
    Code (markup):
    A few notes regarding the code:

    1.) I tried to use unique variable names so as not to conflict with any other JavaScript already on the page.
    2.) If a person clicks on the bookmarklet more than once on the same page it shouldn't do anything, that is why I use the boolean value frst_time.
    3.) I assign the name attribute of the new textbox to '' (empty string) so that it doesn't get passed to the form's processing page.
    4.) At first I set the 'display' property of the password textbox to 'none' to hide it but then I thought some browsers may not pass the value of a form element which isn't displayed, so instead I move it off the screen using absolute positioning.
    5.) The 'id' of the new (replacement) textbox is the 'id' of the password text box plus '_1', because we don't want two textboxes on the same page to have the same id.

    Any questions/comments/suggestions?
     
    brian394, Jun 12, 2006 IP