Finding and auto-filling HTML login forms in a UIWebView using JavaScript

at0m87 picture at0m87 · Mar 15, 2012 · Viewed 14k times · Source

i have a UIWebView which acts like an internet browser and loads the HTML of the webpages that it is at.

in the webViewController, the method webViewDidFinishLoad, would have loaded the HTML from the webpage when the webpage finish loading on the UIWebView.

From the HTML i would like to sieve out textfields to facilitate the auto population of that textfield with values stored in my database.

Any methods to do that? The method should be able to work on all websites.

Set text for a textfield in UIWebView has almost what might help me, but i have tried it and the text field never got filled.

In a login page there will be two text fields so i tried using

document.getElementsByTagName('INPUT')[0].value
document.getElementsByTagName('INPUT')[1].value 

to input in the values but no magic.

Edit: i have tried other position in the array. the username and password for Facebook is [3] and[4] whereas for amazon it is [11] and [14]. so the position of where the fields are using the above method is kinda random. Any other suggestion that will work for all website?

Edit2: i could try

document.getElementsById('id_name').value

but the ID method is not going to work for me as i need a universal method that will identify textfields on any websites(all websites uses different ID names)

Also it seems to me that some of the websites have consistently set this tabindex="1" for username and tabindex="2" for password.

for instance in the webpage like Facebook:

<input type="text" class="inputtext" name="email" id="email" value="" tabindex="1" />
<input type="password" class="inputtext" name="pass" id="pass" tabindex="2" /> 

amazon:

<input id="ap_email" name="email" value="" type="email" size="30" maxlength="128" tabindex="1" autocorrect="off" autocapitalize="off" />
<input id="ap_password" name="password" type="password" maxlength="1024" size="20"  tabindex="2" onkeypress="displayCapsWarning(event,'ap_caps_warning', this);" class="password"/> 

dbs bank:

<input type="text" tabindex="1" maxlength="20" size="32" name="UID" id="UID">
<input type="password" onkeyup="keyUp(event)" onkeydown="return onlyNumerics(event)" tabindex="2" maxlength="9" size="32" name="PIN" id="PIN" autocomplete="off">

but i didn't see this tabindex in google:

<input type="text" spellcheck="false" name="Email" id="Email" value="">
<input type="password" name="Passwd" id="Passwd">

any suggestion?

The Ultimate goal is to be able to sieve out Username and Password Text field for all/any websites. =)

Answer

Johannes Fahrenkrug picture Johannes Fahrenkrug · Mar 15, 2012

OK, so there's no one-size-fits-all for this. You can get pretty close, but it will never work on every website, since a website could possibly have multiple login forms, or multiple fields that make up the username (some banks have that).

But this will get you in the right direction. To get all the password fields (mostly just one), use this:

document.querySelectorAll("input[type='password']")

To get all the text input fields, use this:

document.querySelectorAll("input[type='text']")

For the text input fields, you'll most likely get multiple results (maybe search fields and stuff). So you'll have to iterate over them and look for common IDs or names, like "username", "user", "user_name", "UID" and so on.

This is how you could use it in Objective-C:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSString *savedUsername = @"peter";
    NSString *savedPassword = @"Pan123";

    if (savedUsername.length != 0 && savedPassword.length != 0) { 
        //create js strings
        NSString *loadUsernameJS = [NSString stringWithFormat:@"var inputFields = document.querySelectorAll(\"input[type='text']\"); \
        for (var i = inputFields.length >>> 0; i--;) { inputFields[i].value = '%@';}", savedUsername];
        NSString *loadPasswordJS = [NSString stringWithFormat:@"document.querySelectorAll(\"input[type='password']\").value ='%@'", savedPassword];

        //autofill the form
        [self.webView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
        [self.webView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
    }
}

Please note: It fills every textfield with the username and only the first password field with the password.

Enjoy.