[Patch] Fix form detection for password manager
Davide Baldini
baldiniebaldini at gmail.com
Thu Oct 5 15:19:53 BST 2023
I fixed the form detection script in src/lib/tools/scripts.cpp used to capture the login credentials for the password manager. I tested this on many websites, all work correctly.
This fixes two problems:
1) Some websites collect data from login forms without properly submit()ting them, thus the 'submit' event handler currently in use does not trigger;
2) the current script collects the DOM forms by reading 'document.forms', but this property often holds an empty set, and MutationObserver doesn't subsequently detect further forms. This patch circumvents this issue.
# This patch file was generated by NetBeans IDE
# It uses platform neutral UTF-8 encoding and \n newlines.
--- a/src/lib/tools/scripts.cpp
+++ b/src/lib/tools/scripts.cpp
@@ -74,31 +74,37 @@
QString Scripts::setupFormObserver()
{
QString source = QL1S("(function() {"
- "function findUsername(inputs) {"
- " var usernameNames = ['user', 'name', 'login'];"
- " for (var i = 0; i < usernameNames.length; ++i) {"
- " for (var j = 0; j < inputs.length; ++j)"
- " if (inputs[j].type == 'text' && inputs[j].value.length && inputs[j].name.indexOf(usernameNames[i]) != -1)"
- " return inputs[j].value;"
+ " let eFormsOld = [],"
+ " eFormsDone = [];"
+ ""
+ " function findUsername(inputs) {"
+ " let usernameNames = ['user', 'name', 'login'];"
+ ""
+ " for (let i = 0; i < usernameNames.length; ++i) {"
+ " for (let j = 0; j < inputs.length; ++j)"
+ " if (inputs[j].type == 'text' && inputs[j].value.length && inputs[j].name.indexOf(usernameNames[i]) != -1)"
+ " return inputs[j].value;"
+ " }"
+ ""
+ " for (let i = 0; i < inputs.length; ++i)"
+ " if (inputs[i].type == 'text' && inputs[i].value.length)"
+ " return inputs[i].value;"
+ ""
+ " for (let i = 0; i < inputs.length; ++i)"
+ " if (inputs[i].type == 'email' && inputs[i].value.length)"
+ " return inputs[i].value;"
+ ""
+ " return '';"
" }"
- " for (var i = 0; i < inputs.length; ++i)"
- " if (inputs[i].type == 'text' && inputs[i].value.length)"
- " return inputs[i].value;"
- " for (var i = 0; i < inputs.length; ++i)"
- " if (inputs[i].type == 'email' && inputs[i].value.length)"
- " return inputs[i].value;"
- " return '';"
- "}"
""
- "function registerForm(form) {"
- " form.addEventListener('submit', function() {"
- " var form = this;"
- " var data = '';"
- " var password = '';"
- " var inputs = form.getElementsByTagName('input');"
- " for (var i = 0; i < inputs.length; ++i) {"
- " var input = inputs[i];"
- " var type = input.type.toLowerCase();"
+ " function processForm(eForm) {"
+ " let data = '';"
+ " let password = '';"
+ " let inputs = eForm.getElementsByTagName('input');"
+ ""
+ " for (let i = 0; i < inputs.length; ++i) {"
+ " let input = inputs[i];"
+ " let type = input.type.toLowerCase();"
" if (type != 'text' && type != 'password' && type != 'email')"
" continue;"
" if (!password && type == 'password')"
@@ -108,30 +114,61 @@
" data += encodeURIComponent(input.value);"
" data += '&';"
" }"
+ ""
" if (!password)"
" return;"
+ ""
+ " if (eFormsDone.every(e => e != eForm)) {"
+ " eFormsDone.push(eForm);"
+ " } else {"
+ " return;"
+ " }"
+ ""
" data = data.substring(0, data.length - 1);"
- " var url = window.location.href;"
- " var username = findUsername(inputs);"
+ " let url = window.location.href;"
+ " let username = findUsername(inputs);"
" external.autoFill.formSubmitted(url, username, password, data);"
- " }, true);"
- "}"
+ " }"
""
- "if (!document.documentElement) return;"
+ " function undoForm(eForm) {"
+ " let i = eFormsDone.indexOf(eForm);"
""
- "for (var i = 0; i < document.forms.length; ++i)"
- " registerForm(document.forms[i]);"
+ " if (i >= 0) {"
+ " eFormsDone.splice(i, 1);"
+ " }"
+ " }"
""
- "var observer = new MutationObserver(function(mutations) {"
- " for (var mutation of mutations)"
- " for (var node of mutation.addedNodes)"
- " if (node.tagName && node.tagName.toLowerCase() == 'form')"
- " registerForm(node);"
- "});"
- "observer.observe(document.documentElement, { childList: true, subtree: true });"
+ " function registerForm(eForm) {"
+ " let eInputs = eForm.getElementsByTagName('input');"
""
+ " eForm.addEventListener('submit', () => processForm(eForm), true);"
+ ""
+ " for (let eInput of eInputs) {"
+ " let type = eInput.type.toLowerCase();"
+ " "
+ " if (type == 'password') {"
+ " eInput.addEventListener('blur', () => processForm(eForm), true);"
+ " eInput.addEventListener('input', () => undoForm(eForm), true);"
+ " eInput.addEventListener('keydown', () => event.keyCode === 13 && processForm(eForm), true);"
+ " }"
+ " }"
+ " }"
+ ""
+ " setInterval(() => {"
+ " try {"
+ " let eFormsNew = Array.from(document.forms);"
+ ""
+ " for (let eFormNew of eFormsNew) {"
+ " if (eFormsOld.every(e => e != eFormNew)) {"
+ " eFormsOld.push(eFormNew);"
+ " registerForm(eFormNew);"
+ " }"
+ " }"
+ ""
+ " } catch (e) {}"
+ " }, 100);"
"})()");
-
+
return source;
}
More information about the Falkon
mailing list