handle autofill for pages with no forms, but still has fields

This commit is contained in:
Kyle Spearrin 2016-09-17 09:35:58 -04:00
parent 5daeb0ee95
commit 4751cc04fc
1 changed files with 65 additions and 53 deletions

View File

@ -16,82 +16,94 @@ namespace Bit.iOS.Extension.Models
DocumentUUID = pageDetails.DocumentUUID; DocumentUUID = pageDetails.DocumentUUID;
var passwordFields = pageDetails.Fields.Where(f => f.Type == "password"); var passwordFields = pageDetails.Fields.Where(f => f.Type == "password").ToArray();
var passwordForms = pageDetails.Forms.Where(form => passwordFields.Any(f => f.Form == form.Key)); var passwordForms = pageDetails.Forms.Where(form => passwordFields.Any(f => f.Form == form.Key)).ToArray();
if(!passwordForms.Any())
{
return;
}
PageDetails.Form loginForm = null; PageDetails.Form loginForm = null;
if(passwordForms.Count() > 1) PageDetails.Field username = null, password = null;
if(passwordForms.Any())
{ {
// More than one form with a password field is on the page. if(passwordForms.Count() > 1)
// This usually occurs when a website has a login and signup form on the same page.
// Let's try to guess which one is the login form.
// First let's try to guess the correct login form by examining the form attribute strings
// for common login form attribute.
foreach(var form in passwordForms)
{ {
var formDescriptor = string.Format("{0}~{1}~{2}", // More than one form with a password field is on the page.
form.Value?.HtmlName, form.Value?.HtmlId, form.Value?.HtmlAction) // This usually occurs when a website has a login and signup form on the same page.
?.ToLowerInvariant()?.Replace('_', '-'); // Let's try to guess which one is the login form.
if(formDescriptor.Contains("login") || formDescriptor.Contains("log-in") // First let's try to guess the correct login form by examining the form attribute strings
|| formDescriptor.Contains("signin") || formDescriptor.Contains("sign-in") // for common login form attribute.
|| formDescriptor.Contains("logon") || formDescriptor.Contains("log-on")) foreach(var form in passwordForms)
{ {
loginForm = form.Value; var formDescriptor = string.Format("{0}~{1}~{2}",
break; form.Value?.HtmlName, form.Value?.HtmlId, form.Value?.HtmlAction)
?.ToLowerInvariant()?.Replace('_', '-');
if(formDescriptor.Contains("login") || formDescriptor.Contains("log-in")
|| formDescriptor.Contains("signin") || formDescriptor.Contains("sign-in")
|| formDescriptor.Contains("logon") || formDescriptor.Contains("log-on"))
{
loginForm = form.Value;
break;
}
}
if(loginForm == null)
{
// Next we can try to find the login form that only has one password field. Typically
// a registration form may have two password fields for password confirmation.
var fieldGroups = passwordFields.GroupBy(f => f.Form);
var singleFields = fieldGroups.FirstOrDefault(f => f.Count() == 1);
if(singleFields.Any())
{
var singlePasswordForms = passwordForms.Where(f => f.Key == singleFields.Key);
if(singlePasswordForms.Any())
{
loginForm = singlePasswordForms.First().Value;
}
}
} }
} }
if(loginForm == null) if(loginForm == null)
{ {
// Next we can try to find the login form that only has one password field. Typically loginForm = passwordForms.FirstOrDefault().Value;
// a registration form may have two password fields for password confirmation. }
var fieldGroups = passwordFields.GroupBy(f => f.Form);
var singleFields = fieldGroups.FirstOrDefault(f => f.Count() == 1); password = pageDetails.Fields.FirstOrDefault(f =>
if(singleFields.Any()) f.Form == loginForm.OpId
{ && f.Type == "password");
var singlePasswordForms = passwordForms.Where(f => f.Key == singleFields.Key);
if(singlePasswordForms.Any()) username = pageDetails.Fields.LastOrDefault(f =>
{ f.Form == loginForm.OpId
loginForm = singlePasswordForms.First().Value; && (f.Type == "text" || f.Type == "email")
} && f.ElementNumber < password.ElementNumber);
}
if(loginForm.HtmlAction != null)
{
AutoSubmit = new Submit { FocusOpId = password.OpId };
}
}
else if(passwordFields.Count() == 1)
{
password = passwordFields.First();
if(password.ElementNumber > 0)
{
username = pageDetails.Fields[password.ElementNumber - 1];
} }
} }
if(loginForm == null)
{
loginForm = passwordForms.FirstOrDefault().Value;
}
Script = new List<List<string>>(); Script = new List<List<string>>();
var password = pageDetails.Fields.FirstOrDefault(f =>
f.Form == loginForm.OpId
&& f.Type == "password");
var username = pageDetails.Fields.LastOrDefault(f =>
f.Form == loginForm.OpId
&& (f.Type == "text" || f.Type == "email")
&& f.ElementNumber < password.ElementNumber);
if(username != null) if(username != null)
{ {
Script.Add(new List<string> { "click_on_opid", username.OpId }); Script.Add(new List<string> { "click_on_opid", username.OpId });
Script.Add(new List<string> { "fill_by_opid", username.OpId, fillUsername }); Script.Add(new List<string> { "fill_by_opid", username.OpId, fillUsername });
} }
Script.Add(new List<string> { "click_on_opid", password.OpId }); if(password != null)
Script.Add(new List<string> { "fill_by_opid", password.OpId, fillPassword });
if(loginForm.HtmlAction != null)
{ {
AutoSubmit = new Submit { FocusOpId = password.OpId }; Script.Add(new List<string> { "click_on_opid", password.OpId });
Script.Add(new List<string> { "fill_by_opid", password.OpId, fillPassword });
} }
} }