PageRenderTime 67ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/chromeipass/chromeipass.js

https://github.com/ddingx/passifox
JavaScript | 1707 lines | 1378 code | 243 blank | 86 comment | 381 complexity | 392c82065287a7c4636df9ce0dee0ae2 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. // contains already called method names
  2. var _called = {};
  3. chrome.extension.onMessage.addListener(function(req, sender, callback) {
  4. if ('action' in req) {
  5. if(req.action == "fill_user_pass_with_specific_login") {
  6. if(cip.credentials[req.id]) {
  7. var combination = null;
  8. if (cip.u) {
  9. cip.u.val(cip.credentials[req.id].Login);
  10. combination = cipFields.getCombination("username", cip.u);
  11. cip.u.focus();
  12. }
  13. if (cip.p) {
  14. cip.p.val(cip.credentials[req.id].Password);
  15. combination = cipFields.getCombination("password", cip.p);
  16. }
  17. var list = {};
  18. if(cip.fillInStringFields(combination.fields, cip.credentials[req.id].StringFields, list)) {
  19. cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]});
  20. }
  21. }
  22. // wish I could clear out _logins and _u, but a subsequent
  23. // selection may be requested.
  24. }
  25. else if (req.action == "fill_user_pass") {
  26. cip.fillInFromActiveElement(false);
  27. }
  28. else if (req.action == "fill_pass_only") {
  29. cip.fillInFromActiveElementPassOnly(false);
  30. }
  31. else if (req.action == "activate_password_generator") {
  32. cip.initPasswordGenerator(cipFields.getAllFields());
  33. }
  34. else if(req.action == "remember_credentials") {
  35. cip.contextMenuRememberCredentials();
  36. }
  37. else if (req.action == "choose_credential_fields") {
  38. cipDefine.init();
  39. }
  40. else if (req.action == "clear_credentials") {
  41. cipEvents.clearCredentials();
  42. }
  43. else if (req.action == "activated_tab") {
  44. cipEvents.triggerActivatedTab();
  45. }
  46. else if (req.action == "redetect_fields") {
  47. chrome.extension.sendMessage({
  48. "action": "get_settings",
  49. }, function(response) {
  50. cip.settings = response.data;
  51. cip.initCredentialFields(true);
  52. });
  53. }
  54. }
  55. });
  56. // Hotkeys for every page
  57. // ctrl + shift + p = fill only password
  58. // ctrl + shift + u = fill username + password
  59. window.addEventListener("keydown", function(e) {
  60. if (e.ctrlKey && e.shiftKey) {
  61. if (e.keyCode == 80) { // P
  62. e.preventDefault();
  63. cip.fillInFromActiveElementPassOnly(false);
  64. } else if (e.keyCode == 85) { // U
  65. e.preventDefault();
  66. cip.fillInFromActiveElement(false);
  67. }
  68. }
  69. }, false);
  70. function _f(fieldId) {
  71. var field = (fieldId) ? cIPJQ("input[data-cip-id='"+fieldId+"']:first") : [];
  72. return (field.length > 0) ? field : null;
  73. }
  74. function _fs(fieldId) {
  75. var field = (fieldId) ? cIPJQ("input[data-cip-id='"+fieldId+"']:first,select[data-cip-id='"+fieldId+"']:first").first() : [];
  76. return (field.length > 0) ? field : null;
  77. }
  78. var cipAutocomplete = {};
  79. // objects of username + description for autocomplete
  80. cipAutocomplete.elements = [];
  81. cipAutocomplete.init = function(field) {
  82. if(field.hasClass("cip-ui-autocomplete-input")) {
  83. //_f(credentialInputs[i].username).autocomplete("source", autocompleteSource);
  84. field.autocomplete("destroy");
  85. }
  86. field
  87. .autocomplete({
  88. minLength: 0,
  89. source: cipAutocomplete.onSource,
  90. select: cipAutocomplete.onSelect,
  91. open: cipAutocomplete.onOpen
  92. });
  93. field
  94. .click(cipAutocomplete.onClick)
  95. .blur(cipAutocomplete.onBlur)
  96. .focus(cipAutocomplete.onFocus);
  97. }
  98. cipAutocomplete.onClick = function() {
  99. cIPJQ(this).autocomplete("search", cIPJQ(this).val());
  100. }
  101. cipAutocomplete.onOpen = function(event, ui) {
  102. // NOT BEAUTIFUL!
  103. // modifies ALL ui-autocomplete menus of class .cip-ui-menu
  104. cIPJQ("ul.cip-ui-autocomplete.cip-ui-menu").css("z-index", 2147483636);
  105. }
  106. cipAutocomplete.onSource = function (request, callback) {
  107. var matches = cIPJQ.map( cipAutocomplete.elements, function(tag) {
  108. if ( tag.label.toUpperCase().indexOf(request.term.toUpperCase()) === 0 ) {
  109. return tag;
  110. }
  111. });
  112. callback(matches);
  113. }
  114. cipAutocomplete.onSelect = function (e, ui) {
  115. e.preventDefault();
  116. cIPJQ(this).val(ui.item.value);
  117. var fieldId = cipFields.prepareId(cIPJQ(this).attr("data-cip-id"));
  118. var combination = cipFields.getCombination("username", fieldId);
  119. combination.loginId = ui.item.loginId;
  120. cip.fillInCredentials(combination, true, false);
  121. cIPJQ(this).data("fetched", true);
  122. }
  123. cipAutocomplete.onBlur = function() {
  124. if(cIPJQ(this).data("fetched") == true) {
  125. cIPJQ(this).data("fetched", false);
  126. }
  127. else {
  128. var fieldId = cipFields.prepareId(cIPJQ(this).attr("data-cip-id"));
  129. var fields = cipFields.getCombination("username", fieldId);
  130. if(_f(fields.password) && _f(fields.password).data("unchanged") != true && cIPJQ(this).val() != "") {
  131. cip.fillInCredentials(fields, true, true);
  132. }
  133. }
  134. }
  135. cipAutocomplete.onFocus = function() {
  136. cip.u = cIPJQ(this);
  137. if(cIPJQ(this).val() == "") {
  138. cIPJQ(this).autocomplete("search", "");
  139. }
  140. }
  141. var cipPassword = {};
  142. cipPassword.observedIcons = [];
  143. cipPassword.observingLock = false;
  144. cipPassword.init = function() {
  145. if("initPasswordGenerator" in _called) {
  146. return;
  147. }
  148. _called.initPasswordGenerator = true;
  149. window.setInterval(function() {
  150. cipPassword.checkObservedElements();
  151. }, 400);
  152. }
  153. cipPassword.initField = function(field, inputs, pos) {
  154. if(!field || field.length != 1) {
  155. return;
  156. }
  157. if(field.data("cip-password-generator")) {
  158. return;
  159. }
  160. field.data("cip-password-generator", true);
  161. cipPassword.createIcon(field);
  162. cipPassword.createDialog();
  163. var $found = false;
  164. if(inputs) {
  165. for(var i = pos + 1; i < inputs.length; i++) {
  166. if(inputs[i] && inputs[i].attr("type") && inputs[i].attr("type").toLowerCase() == "password") {
  167. field.data("cip-genpw-next-field-id", inputs[i].data("cip-id"));
  168. field.data("cip-genpw-next-is-password-field", (i == 0));
  169. $found = true;
  170. break;
  171. }
  172. }
  173. }
  174. field.data("cip-genpw-next-field-exists", $found);
  175. }
  176. cipPassword.createDialog = function() {
  177. if("passwordCreateDialog" in _called) {
  178. return;
  179. }
  180. _called.passwordCreateDialog = true;
  181. var $dialog = cIPJQ("<div>")
  182. .attr("id", "cip-genpw-dialog");
  183. var $divFloat = cIPJQ("<div>").addClass("cip-genpw-clearfix");
  184. var $btnGenerate = cIPJQ("<button>")
  185. .text("Generate")
  186. .attr("id", "cip-genpw-btn-generate")
  187. .addClass("b2c-btn")
  188. .addClass("b2c-btn-primary")
  189. .addClass("b2c-btn-small")
  190. .css("float", "left")
  191. .click(function(e) {
  192. e.preventDefault();
  193. chrome.extension.sendMessage({
  194. action: "generate_password"
  195. }, cipPassword.callbackGeneratedPassword);
  196. });
  197. $divFloat.append($btnGenerate);
  198. var $btnClipboard = cIPJQ("<button>")
  199. .text("Copy to clipboard")
  200. .attr("id", "cip-genpw-btn-clipboard")
  201. .addClass("b2c-btn")
  202. .addClass("b2c-btn-small")
  203. .css("float", "right")
  204. .click(function(e) {
  205. e.preventDefault();
  206. chrome.extension.sendMessage({
  207. action: "copy_password",
  208. args: [cIPJQ("input#cip-genpw-textfield-password").val()]
  209. }, cipPassword.callbackPasswordCopied);
  210. });
  211. $divFloat.append($btnClipboard);
  212. $dialog.append($divFloat);
  213. var $textfieldPassword = cIPJQ("<input>")
  214. .attr("id", "cip-genpw-textfield-password")
  215. .attr("type", "text")
  216. .addClass("cip-genpw-textfield")
  217. .on('change keypress paste textInput input', function() {
  218. cIPJQ("#cip-genpw-btn-clipboard:first").removeClass("b2c-btn-success");
  219. });
  220. var $quality = cIPJQ("<span>")
  221. .addClass("b2c-add-on")
  222. .attr("id", "cip-genpw-quality")
  223. .text("123 Bits");
  224. var $frameInputAppend = cIPJQ("<div>")
  225. .addClass("b2c-input-append")
  226. .addClass("cip-genpw-password-frame");
  227. $frameInputAppend.append($textfieldPassword).append($quality);
  228. $dialog.append($frameInputAppend);
  229. var $checkboxNextField = cIPJQ("<input>")
  230. .attr("id", "cip-genpw-checkbox-next-field")
  231. .attr("type", "checkbox")
  232. .addClass("cip-genpw-checkbox");
  233. var $labelNextField = cIPJQ("<label>")
  234. .append($checkboxNextField)
  235. .addClass("cip-genpw-label")
  236. .append(" also fill in the next password-field");
  237. $dialog.append($labelNextField);
  238. var $btnFillIn = cIPJQ("<button>")
  239. .text("Fill in & copy to clipboard")
  240. .attr("id", "cip-genpw-btn-fillin")
  241. .addClass("b2c-btn")
  242. .addClass("b2c-btn-small")
  243. .click(function(e) {
  244. e.preventDefault();
  245. var fieldId = cIPJQ("#cip-genpw-dialog:first").data("cip-genpw-field-id");
  246. var field = cIPJQ("input[data-cip-id='"+fieldId+"']:first");
  247. if(field.length == 1) {
  248. var $password = cIPJQ("input#cip-genpw-textfield-password:first").val();
  249. if(field.attr("maxlength")) {
  250. if($password.length > field.attr("maxlength")) {
  251. $password = $password.substring(0, field.attr("maxlength"));
  252. cIPJQ("input#cip-genpw-textfield-password:first").val($password);
  253. cIPJQ("#cip-genpw-btn-clipboard:first").removeClass("b2c-btn-success");
  254. alert("The generated password is longer than the allowed length!\nIt has been cut to fit the length.\n\nPlease remember the new password!");
  255. }
  256. }
  257. field.val($password);
  258. if(cIPJQ("input#cip-genpw-checkbox-next-field:checked").length == 1) {
  259. if(field.data("cip-genpw-next-field-exists")) {
  260. var nextFieldId = field.data("cip-genpw-next-field-id");
  261. var nextField = cIPJQ("input[data-cip-id='"+nextFieldId+"']:first");
  262. if(nextField.length == 1) {
  263. nextField.val($password);
  264. }
  265. }
  266. }
  267. // copy password to clipboard
  268. chrome.extension.sendMessage({
  269. action: "copy_password",
  270. args: [$password]
  271. }, cipPassword.callbackPasswordCopied);
  272. }
  273. });
  274. $dialog.append($btnFillIn);
  275. $dialog.hide();
  276. cIPJQ("body").append($dialog);
  277. $dialog.dialog({
  278. closeText: "×",
  279. autoOpen: false,
  280. modal: true,
  281. resizable: false,
  282. minWidth: 340,
  283. title: "Password Generator",
  284. open: function(event, ui) {
  285. cIPJQ(".cip-ui-widget-overlay").click(function() {
  286. cIPJQ("#cip-genpw-dialog:first").dialog("close");
  287. });
  288. if(cIPJQ("input#cip-genpw-textfield-password:first").val() == "") {
  289. cIPJQ("button#cip-genpw-btn-generate:first").click();
  290. }
  291. }
  292. });
  293. }
  294. cipPassword.createIcon = function(field) {
  295. var $className = (field.outerHeight() > 28) ? "cip-icon-key-big" : "cip-icon-key-small";
  296. var $size = (field.outerHeight() > 28) ? 24 : 16;
  297. var $offset = Math.floor((field.outerHeight() - $size) / 3);
  298. $offset = ($offset < 0) ? 0 : $offset;
  299. var $zIndex = 0;
  300. var $zIndexField = field;
  301. var z;
  302. var c = 0;
  303. while($zIndexField.length > 0) {
  304. z = $zIndexField.css("z-index");
  305. if(!isNaN(z) && parseInt(z) > $zIndex) {
  306. $zIndex = parseInt(z);
  307. }
  308. $zIndexField = $zIndexField.parent();
  309. if(c > 100) {
  310. break;
  311. }
  312. c++;
  313. }
  314. if(isNaN($zIndex) || $zIndex < 1) {
  315. $zIndex = 1;
  316. }
  317. $zIndex += 1;
  318. var $icon = cIPJQ("<div>").addClass("cip-genpw-icon")
  319. .addClass($className)
  320. .css("z-index", $zIndex)
  321. .data("size", $size)
  322. .data("offset", $offset)
  323. .data("cip-genpw-field-id", field.data("cip-id"));
  324. cipPassword.setIconPosition($icon, field);
  325. $icon.click(function(e) {
  326. e.preventDefault();
  327. if(!field.is(":visible")) {
  328. $icon.remove();
  329. field.removeData("cip-password-generator");
  330. return;
  331. }
  332. var $dialog = cIPJQ("#cip-genpw-dialog");
  333. if($dialog.dialog("isOpen")) {
  334. $dialog.dialog("close");
  335. }
  336. $dialog.dialog("option", "position", { my: "left-10px top", at: "center bottom", of: cIPJQ(this) });
  337. $dialog.data("cip-genpw-field-id", field.data("cip-id"));
  338. $dialog.data("cip-genpw-next-field-id", field.data("cip-genpw-next-field-id"));
  339. $dialog.data("cip-genpw-next-is-password-field", field.data("cip-genpw-next-is-password-field"));
  340. var $bool = Boolean(field.data("cip-genpw-next-field-exists"));
  341. cIPJQ("input#cip-genpw-checkbox-next-field:first")
  342. .attr("checked", $bool)
  343. .attr("disabled", !$bool);
  344. $dialog.dialog("open");
  345. });
  346. cipPassword.observedIcons.push($icon);
  347. cIPJQ("body").append($icon);
  348. }
  349. cipPassword.setIconPosition = function($icon, $field) {
  350. $icon.css("top", $field.offset().top + $icon.data("offset") + 1)
  351. .css("left", $field.offset().left + $field.outerWidth() - $icon.data("size") - $icon.data("offset"))
  352. }
  353. cipPassword.callbackPasswordCopied = function(bool) {
  354. if(bool) {
  355. cIPJQ("#cip-genpw-btn-clipboard").addClass("b2c-btn-success");
  356. }
  357. }
  358. cipPassword.callbackGeneratedPassword = function(entries) {
  359. if(entries && entries.length >= 1) {
  360. console.log(entries[0]);
  361. cIPJQ("#cip-genpw-btn-clipboard:first").removeClass("b2c-btn-success");
  362. cIPJQ("input#cip-genpw-textfield-password:first").val(entries[0].Password);
  363. if(isNaN(entries[0].Login)) {
  364. cIPJQ("#cip-genpw-quality:first").text("??? Bits");
  365. }
  366. else {
  367. cIPJQ("#cip-genpw-quality:first").text(entries[0].Login + " Bits");
  368. }
  369. }
  370. else {
  371. if(cIPJQ("div#cip-genpw-error:first").length == 0) {
  372. cIPJQ("button#cip-genpw-btn-generate:first").after("<div style='block' id='cip-genpw-error'>Cannot receive generated password.<br />Is your version of KeePassHttp up-to-date?<br /><br /><a href='https://github.com/pfn/keepasshttp/'>Please visit the KeePassHttp homepage</a></div>");
  373. cIPJQ("input#cip-genpw-textfield-password:first").parent().hide();
  374. cIPJQ("input#cip-genpw-checkbox-next-field:first").parent("label").hide();
  375. cIPJQ("button#cip-genpw-btn-generate").hide();
  376. cIPJQ("button#cip-genpw-btn-clipboard").hide();
  377. cIPJQ("button#cip-genpw-btn-fillin").hide();
  378. }
  379. }
  380. }
  381. cipPassword.onRequestPassword = function() {
  382. chrome.extension.sendMessage({
  383. 'action': 'generate_password'
  384. }, cipPassword.callbackGeneratedPassword);
  385. }
  386. cipPassword.checkObservedElements = function() {
  387. if(cipPassword.observingLock) {
  388. return;
  389. }
  390. cipPassword.observingLock = true;
  391. cIPJQ.each(cipPassword.observedIcons, function(index, iconField) {
  392. if(iconField && iconField.length == 1) {
  393. var fieldId = iconField.data("cip-genpw-field-id");
  394. var field = cIPJQ("input[data-cip-id='"+fieldId+"']:first");
  395. if(!field || field.length != 1) {
  396. iconField.remove();
  397. cipPassword.observedIcons.splice(index, 1);
  398. }
  399. else if(!field.is(":visible")) {
  400. iconField.hide();
  401. //field.removeData("cip-password-generator");
  402. }
  403. else if(field.is(":visible")) {
  404. iconField.show();
  405. cipPassword.setIconPosition(iconField, field);
  406. field.data("cip-password-generator", true);
  407. }
  408. }
  409. else {
  410. cipPassword.observedIcons.splice(index, 1);
  411. }
  412. });
  413. cipPassword.observingLock = false;
  414. }
  415. var cipForm = {};
  416. cipForm.init = function(form, credentialFields) {
  417. // TODO: could be called multiple times --> update credentialFields
  418. // not already initialized && password-field is not null
  419. if(!form.data("cipForm-initialized") && credentialFields.password) {
  420. form.data("cipForm-initialized", true);
  421. cipForm.setInputFields(form, credentialFields);
  422. form.submit(cipForm.onSubmit);
  423. }
  424. }
  425. cipForm.destroy = function(form, credentialFields) {
  426. if(form === false && credentialFields) {
  427. var field = _f(credentialFields.password) || _f(credentialFields.username);
  428. if(field) {
  429. form = field.closest("form");
  430. }
  431. }
  432. if(form && cIPJQ(form).length > 0) {
  433. cIPJQ(form).unbind('submit', cipForm.onSubmit);
  434. }
  435. }
  436. cipForm.setInputFields = function(form, credentialFields) {
  437. form.data("cipUsername", credentialFields.username);
  438. form.data("cipPassword", credentialFields.password);
  439. }
  440. cipForm.onSubmit = function() {
  441. var usernameId = cIPJQ(this).data("cipUsername");
  442. var passwordId = cIPJQ(this).data("cipPassword");
  443. var usernameValue = "";
  444. var passwordValue = "";
  445. var usernameField = _f(usernameId);
  446. var passwordField = _f(passwordId);
  447. if(usernameField) {
  448. usernameValue = usernameField.val();
  449. }
  450. if(passwordField) {
  451. passwordValue = passwordField.val();
  452. }
  453. cip.rememberCredentials(usernameValue, passwordValue);
  454. };
  455. var cipDefine = {};
  456. cipDefine.selection = {
  457. "username": null,
  458. "password": null,
  459. "fields": {}
  460. };
  461. cipDefine.eventFieldClick = null;
  462. cipDefine.init = function () {
  463. var $backdrop = cIPJQ("<div>").attr("id", "b2c-backdrop").addClass("b2c-modal-backdrop");
  464. cIPJQ("body").append($backdrop);
  465. var $chooser = cIPJQ("<div>").attr("id", "b2c-cipDefine-fields");
  466. cIPJQ("body").append($chooser);
  467. var $description = cIPJQ("<div>").attr("id", "b2c-cipDefine-description");
  468. $backdrop.append($description);
  469. cipFields.getAllFields();
  470. cipFields.prepareVisibleFieldsWithID("select");
  471. cipDefine.initDescription();
  472. cipDefine.resetSelection();
  473. cipDefine.prepareStep1();
  474. cipDefine.markAllUsernameFields($chooser);
  475. }
  476. cipDefine.initDescription = function() {
  477. var $description = cIPJQ("div#b2c-cipDefine-description");
  478. var $h1 = cIPJQ("<div>").addClass("b2c-chooser-headline");
  479. $description.append($h1);
  480. var $help = cIPJQ("<div>").addClass("b2c-chooser-help").attr("id", "b2c-help");
  481. $description.append($help);
  482. var $btnDismiss = cIPJQ("<button>").text("Dismiss").attr("id", "b2c-btn-dismiss")
  483. .addClass("b2c-btn").addClass("b2c-btn-danger")
  484. .click(function(e) {
  485. cIPJQ("div#b2c-backdrop").remove();
  486. cIPJQ("div#b2c-cipDefine-fields").remove();
  487. });
  488. var $btnSkip = cIPJQ("<button>").text("Skip").attr("id", "b2c-btn-skip")
  489. .addClass("b2c-btn").addClass("b2c-btn-info")
  490. .css("margin-right", "5px")
  491. .click(function() {
  492. if(cIPJQ(this).data("step") == 1) {
  493. cipDefine.selection.username = null;
  494. cipDefine.prepareStep2();
  495. cipDefine.markAllPasswordFields(cIPJQ("#b2c-cipDefine-fields"));
  496. }
  497. else if(cIPJQ(this).data("step") == 2) {
  498. cipDefine.selection.password = null;
  499. cipDefine.prepareStep3();
  500. cipDefine.markAllStringFields(cIPJQ("#b2c-cipDefine-fields"));
  501. }
  502. });
  503. var $btnAgain = cIPJQ("<button>").text("Again").attr("id", "b2c-btn-again")
  504. .addClass("b2c-btn").addClass("b2c-btn-warning")
  505. .css("margin-right", "5px")
  506. .click(function(e) {
  507. cipDefine.resetSelection();
  508. cipDefine.prepareStep1();
  509. cipDefine.markAllUsernameFields(cIPJQ("#b2c-cipDefine-fields"));
  510. })
  511. .hide();
  512. var $btnConfirm = cIPJQ("<button>").text("Confirm").attr("id", "b2c-btn-confirm")
  513. .addClass("b2c-btn").addClass("b2c-btn-primary")
  514. .css("margin-right", "15px")
  515. .click(function(e) {
  516. if(!cip.settings["defined-credential-fields"]) {
  517. cip.settings["defined-credential-fields"] = {};
  518. }
  519. if(cipDefine.selection.username) {
  520. cipDefine.selection.username = cipFields.prepareId(cipDefine.selection.username);
  521. }
  522. var passwordId = cIPJQ("div#b2c-cipDefine-fields").data("password");
  523. if(cipDefine.selection.password) {
  524. cipDefine.selection.password = cipFields.prepareId(cipDefine.selection.password);
  525. }
  526. var fieldIds = [];
  527. var fieldKeys = Object.keys(cipDefine.selection.fields);
  528. for(var i = 0; i < fieldKeys.length; i++) {
  529. fieldIds.push(cipFields.prepareId(fieldKeys[i]));
  530. }
  531. cip.settings["defined-credential-fields"][document.location.origin] = {
  532. "username": cipDefine.selection.username,
  533. "password": cipDefine.selection.password,
  534. "fields": fieldIds
  535. };
  536. chrome.extension.sendMessage({
  537. action: 'save_settings',
  538. args: [cip.settings]
  539. });
  540. cIPJQ("button#b2c-btn-dismiss").click();
  541. })
  542. .hide();
  543. $description.append($btnConfirm);
  544. $description.append($btnSkip);
  545. $description.append($btnAgain);
  546. $description.append($btnDismiss);
  547. if(cip.settings["defined-credential-fields"] && cip.settings["defined-credential-fields"][document.location.origin]) {
  548. var $p = cIPJQ("<p>").html("For this page credential fields are already selected and will be overwritten.<br />");
  549. var $btnDiscard = cIPJQ("<button>")
  550. .attr("id", "b2c-btn-discard")
  551. .text("Discard selection")
  552. .css("margin-top", "5px")
  553. .addClass("b2c-btn")
  554. .addClass("b2c-btn-small")
  555. .addClass("b2c-btn-danger")
  556. .click(function(e) {
  557. delete cip.settings["defined-credential-fields"][document.location.origin];
  558. chrome.extension.sendMessage({
  559. action: 'save_settings',
  560. args: [cip.settings]
  561. });
  562. chrome.extension.sendMessage({
  563. action: 'load_settings'
  564. });
  565. cIPJQ(this).parent("p").remove();
  566. });
  567. $p.append($btnDiscard);
  568. $description.append($p);
  569. }
  570. cIPJQ("div#b2c-cipDefine-description").draggable();
  571. }
  572. cipDefine.resetSelection = function() {
  573. cipDefine.selection = {
  574. username: null,
  575. password: null,
  576. fields: {}
  577. };
  578. }
  579. cipDefine.isFieldSelected = function($cipId) {
  580. return (
  581. $cipId == cipDefine.selection.username ||
  582. $cipId == cipDefine.selection.password ||
  583. $cipId in cipDefine.selection.fields
  584. );
  585. }
  586. cipDefine.markAllUsernameFields = function($chooser) {
  587. cipDefine.eventFieldClick = function(e) {
  588. cipDefine.selection.username = cIPJQ(this).data("cip-id");
  589. cIPJQ(this).addClass("b2c-fixed-username-field").text("Username").unbind("click");
  590. cipDefine.prepareStep2();
  591. cipDefine.markAllPasswordFields(cIPJQ("#b2c-cipDefine-fields"));
  592. };
  593. cipDefine.markFields($chooser, cipFields.inputQueryPattern);
  594. }
  595. cipDefine.markAllPasswordFields = function($chooser) {
  596. cipDefine.eventFieldClick = function(e) {
  597. cipDefine.selection.password = cIPJQ(this).data("cip-id");
  598. cIPJQ(this).addClass("b2c-fixed-password-field").text("Password").unbind("click");
  599. cipDefine.prepareStep3();
  600. cipDefine.markAllStringFields(cIPJQ("#b2c-cipDefine-fields"));
  601. };
  602. cipDefine.markFields($chooser, "input[type='password']");
  603. }
  604. cipDefine.markAllStringFields = function($chooser) {
  605. cipDefine.eventFieldClick = function(e) {
  606. cipDefine.selection.fields[cIPJQ(this).data("cip-id")] = true;
  607. var count = Object.keys(cipDefine.selection.fields).length;
  608. cIPJQ(this).addClass("b2c-fixed-string-field").text("String field #"+count.toString()).unbind("click");
  609. cIPJQ("button#b2c-btn-confirm:first").addClass("b2c-btn-primary").attr("disabled", false);
  610. };
  611. cipDefine.markFields($chooser, cipFields.inputQueryPattern + ", select");
  612. }
  613. cipDefine.markFields = function ($chooser, $pattern) {
  614. //var $found = false;
  615. cIPJQ($pattern).each(function() {
  616. if(cipDefine.isFieldSelected(cIPJQ(this).data("cip-id"))) {
  617. //continue
  618. return true;
  619. }
  620. if(cIPJQ(this).is(":visible") && cIPJQ(this).css("visibility") != "hidden" && cIPJQ(this).css("visibility") != "collapsed") {
  621. var $field = cIPJQ("<div>").addClass("b2c-fixed-field")
  622. .css("top", cIPJQ(this).offset().top)
  623. .css("left", cIPJQ(this).offset().left)
  624. .css("width", cIPJQ(this).outerWidth())
  625. .css("height", cIPJQ(this).outerHeight())
  626. .attr("data-cip-id", cIPJQ(this).attr("data-cip-id"))
  627. .click(cipDefine.eventFieldClick)
  628. .hover(function() {cIPJQ(this).addClass("b2c-fixed-hover-field");}, function() {cIPJQ(this).removeClass("b2c-fixed-hover-field");});
  629. $chooser.append($field);
  630. //$found = true;
  631. }
  632. });
  633. /* skip step if no entry was found
  634. if(!$found) {
  635. alert("No username field found.\nContinue with choosing a password field.");
  636. cIPJQ("button#b2c-btn-skip").click();
  637. }
  638. */
  639. }
  640. cipDefine.prepareStep1 = function() {
  641. cIPJQ("div#b2c-help").text("").css("margin-bottom", 0);
  642. cIPJQ("div#b2c-cipDefine-fields").removeData("username");
  643. cIPJQ("div#b2c-cipDefine-fields").removeData("password");
  644. cIPJQ("div.b2c-fixed-field", cIPJQ("div#b2c-cipDefine-fields")).remove();
  645. cIPJQ("div:first", cIPJQ("div#b2c-cipDefine-description")).text("1. Choose a username field");
  646. cIPJQ("button#b2c-btn-skip:first").data("step", "1").show();
  647. cIPJQ("button#b2c-btn-confirm:first").hide();
  648. cIPJQ("button#b2c-btn-again:first").hide();
  649. }
  650. cipDefine.prepareStep2 = function() {
  651. cIPJQ("div#b2c-help").text("").css("margin-bottom", 0);
  652. cIPJQ("div.b2c-fixed-field:not(.b2c-fixed-username-field)", cIPJQ("div#b2c-cipDefine-fields")).remove();
  653. cIPJQ("div:first", cIPJQ("div#b2c-cipDefine-description")).text("2. Now choose a password field");
  654. cIPJQ("button#b2c-btn-skip:first").data("step", "2");
  655. cIPJQ("button#b2c-btn-again:first").show();
  656. }
  657. cipDefine.prepareStep3 = function() {
  658. /* skip step if no entry was found
  659. if(!cIPJQ("div#b2c-cipDefine-fields").data("username") && !cIPJQ("div#b2c-cipDefine-fields").data("password")) {
  660. alert("Neither an username field nor a password field were selected.\nNothing will be changed and chooser will be closed now.");
  661. cIPJQ("button#b2c-btn-dismiss").click();
  662. return;
  663. }
  664. */
  665. if(!cipDefine.selection.username && !cipDefine.selection.password) {
  666. cIPJQ("button#b2c-btn-confirm:first").removeClass("b2c-btn-primary").attr("disabled", true);
  667. }
  668. cIPJQ("div#b2c-help").html("Please confirm your selection or choose more fields as <em>String fields</em>.").css("margin-bottom", "5px");
  669. cIPJQ("div.b2c-fixed-field:not(.b2c-fixed-password-field,.b2c-fixed-username-field)", cIPJQ("div#b2c-cipDefine-fields")).remove();
  670. cIPJQ("button#b2c-btn-confirm:first").show();
  671. cIPJQ("button#b2c-btn-skip:first").data("step", "3").hide();
  672. cIPJQ("div:first", cIPJQ("div#b2c-cipDefine-description")).text("3. Confirm selection");
  673. }
  674. cipFields = {}
  675. cipFields.inputQueryPattern = "input[type='text'], input[type='email'], input[type='password'], input:not([type])";
  676. // unique number as new IDs for input fields
  677. cipFields.uniqueNumber = 342845638;
  678. // objects with combination of username + password fields
  679. cipFields.combinations = [];
  680. cipFields.setUniqueId = function(field) {
  681. if(field && !field.attr("data-cip-id")) {
  682. // use ID of field if it is unique
  683. // yes, it should be, but there are many bad developers outside...
  684. var fieldId = field.attr("id");
  685. if(fieldId) {
  686. var foundIds = cIPJQ("input#" + cipFields.prepareId(fieldId));
  687. if(foundIds.length == 1) {
  688. field.attr("data-cip-id", fieldId);
  689. return;
  690. }
  691. }
  692. // create own ID if no ID is set for this field
  693. cipFields.uniqueNumber += 1;
  694. field.attr("data-cip-id", "cIPJQ"+String(cipFields.uniqueNumber));
  695. }
  696. }
  697. cipFields.prepareId = function(id) {
  698. id = id.replace(":", "\\:")
  699. .replace("#", "\\#")
  700. .replace(".", "\\.")
  701. .replace(",", "\\,")
  702. .replace("[", "\\[")
  703. .replace("]", "\\]")
  704. .replace("(", "\\(")
  705. .replace(")", "\\)")
  706. .replace("'", "\\'")
  707. .replace(" ", "\\ ")
  708. .replace("\"", "\\\"");
  709. return id;
  710. }
  711. cipFields.getAllFields = function() {
  712. var fields = [];
  713. // get all input fields which are text, email or password and visible
  714. cIPJQ(cipFields.inputQueryPattern).each(function() {
  715. if(cIPJQ(this).is(":visible") && cIPJQ(this).css("visibility") != "hidden" && cIPJQ(this).css("visibility") != "collapsed") {
  716. cipFields.setUniqueId(cIPJQ(this));
  717. fields.push(cIPJQ(this));
  718. }
  719. });
  720. return fields;
  721. }
  722. cipFields.prepareVisibleFieldsWithID = function($pattern) {
  723. cIPJQ($pattern).each(function() {
  724. if(cIPJQ(this).is(":visible") && cIPJQ(this).css("visibility") != "hidden" && cIPJQ(this).css("visibility") != "collapsed") {
  725. cipFields.setUniqueId(cIPJQ(this));
  726. }
  727. });
  728. }
  729. cipFields.getAllCombinations = function(inputs) {
  730. var fields = [];
  731. var uField = null;
  732. for(var i = 0; i < inputs.length; i++) {
  733. if(!inputs[i] || inputs[i].length < 1) {
  734. continue;
  735. }
  736. if(inputs[i].attr("type") && inputs[i].attr("type").toLowerCase() == "password") {
  737. var uId = (!uField || uField.length < 1) ? null : cipFields.prepareId(uField.attr("data-cip-id"));
  738. var combination = {
  739. "username": uId,
  740. "password": cipFields.prepareId(inputs[i].attr("data-cip-id"))
  741. };
  742. fields.push(combination);
  743. // reset selected username field
  744. uField = null;
  745. }
  746. else {
  747. // username field
  748. uField = inputs[i];
  749. }
  750. }
  751. return fields;
  752. }
  753. cipFields.getCombination = function(givenType, fieldId) {
  754. if(cipFields.combinations.length == 0) {
  755. if(cipFields.useDefinedCredentialFields()) {
  756. return cipFields.combinations[0];
  757. }
  758. }
  759. // use defined credential fields (already loaded into combinations)
  760. if(cip.settings["defined-credential-fields"] && cip.settings["defined-credential-fields"][document.location.origin]) {
  761. return cipFields.combinations[0];
  762. }
  763. for(var i = 0; i < cipFields.combinations.length; i++) {
  764. if(cipFields.combinations[i][givenType] == fieldId) {
  765. return cipFields.combinations[i];
  766. }
  767. }
  768. // find new combination
  769. var combination = {
  770. "username": null,
  771. "password": null
  772. };
  773. var newCombi = false;
  774. if(givenType == "username") {
  775. var passwordField = cipFields.getPasswordField(fieldId, true);
  776. var passwordId = null;
  777. if(passwordField && passwordField.length > 0) {
  778. passwordId = cipFields.prepareId(passwordField.attr("data-cip-id"));
  779. }
  780. combination = {
  781. "username": fieldId,
  782. "password": passwordId
  783. };
  784. newCombi = true;
  785. }
  786. else if(givenType == "password") {
  787. var usernameField = cipFields.getUsernameField(fieldId, true);
  788. var usernameId = null;
  789. if(usernameField && usernameField.length > 0) {
  790. usernameId = cipFields.prepareId(usernameField.attr("data-cip-id"));
  791. }
  792. combination = {
  793. "username": usernameId,
  794. "password": fieldId
  795. };
  796. newCombi = true;
  797. }
  798. if(combination.username || combination.password) {
  799. cipFields.combinations.push(combination);
  800. }
  801. if(combination.username) {
  802. if(cip.credentials.length > 0) {
  803. cip.preparePageForMultipleCredentials(cip.credentials);
  804. }
  805. }
  806. if(newCombi) {
  807. combination.isNew = true;
  808. }
  809. return combination;
  810. }
  811. /**
  812. * return the username field or null if it not exists
  813. */
  814. cipFields.getUsernameField = function(passwordId, checkDisabled) {
  815. var passwordField = _f(passwordId);
  816. if(!passwordField) {
  817. return null;
  818. }
  819. var form = passwordField.closest("form")[0];
  820. var usernameField = null;
  821. // search all inputs on this one form
  822. if(form) {
  823. cIPJQ(cipFields.inputQueryPattern, form).each(function() {
  824. cipFields.setUniqueId(cIPJQ(this));
  825. if(cIPJQ(this).attr("data-cip-id") == passwordId) {
  826. // break
  827. return false;
  828. }
  829. if(cIPJQ(this).attr("type") && cIPJQ(this).attr("type").toLowerCase() == "password") {
  830. // continue
  831. return true;
  832. }
  833. usernameField = cIPJQ(this);
  834. });
  835. }
  836. // search all inputs on page
  837. else {
  838. var inputs = cipFields.getAllFields();
  839. cip.initPasswordGenerator(inputs);
  840. for(var i = 0; i < inputs.length; i++) {
  841. if(inputs[i].attr("data-cip-id") == passwordId) {
  842. break;
  843. }
  844. if(inputs[i].attr("type") && inputs[i].attr("type").toLowerCase() == "password") {
  845. continue;
  846. }
  847. usernameField = inputs[i];
  848. }
  849. }
  850. if(usernameField && !checkDisabled) {
  851. var usernameId = usernameField.attr("data-cip-id");
  852. // check if usernameField is already used by another combination
  853. for(var i = 0; i < cipFields.combinations.length; i++) {
  854. if(cipFields.combinations[i].username == usernameId) {
  855. usernameField = null;
  856. break;
  857. }
  858. }
  859. }
  860. cipFields.setUniqueId(usernameField);
  861. return usernameField;
  862. }
  863. /**
  864. * return the password field or null if it not exists
  865. */
  866. cipFields.getPasswordField = function(usernameId, checkDisabled) {
  867. var usernameField = _f(usernameId);
  868. if(!usernameField) {
  869. return null;
  870. }
  871. var form = usernameField.closest("form")[0];
  872. var passwordField = null;
  873. // search all inputs on this one form
  874. if(form) {
  875. passwordField = cIPJQ("input[type='password']:first", form);
  876. if(passwordField.length < 1) {
  877. passwordField = null;
  878. }
  879. if(cip.settings.usePasswordGenerator) {
  880. cipPassword.init();
  881. cipPassword.initField(passwordField);
  882. }
  883. }
  884. // search all inputs on page
  885. else {
  886. var inputs = cipFields.getAllFields();
  887. cip.initPasswordGenerator(inputs);
  888. var active = false;
  889. for(var i = 0; i < inputs.length; i++) {
  890. if(inputs[i].attr("data-cip-id") == usernameId) {
  891. active = true;
  892. }
  893. if(active && cIPJQ(inputs[i]).attr("type") && cIPJQ(inputs[i]).attr("type").toLowerCase() == "password") {
  894. passwordField = inputs[i];
  895. break;
  896. }
  897. }
  898. }
  899. if(passwordField && !checkDisabled) {
  900. var passwordId = passwordField.attr("data-cip-id");
  901. // check if passwordField is already used by another combination
  902. for(var i = 0; i < cipFields.combinations.length; i++) {
  903. if(cipFields.combinations[i].password == passwordId) {
  904. passwordField = null;
  905. break;
  906. }
  907. }
  908. }
  909. cipFields.setUniqueId(passwordField);
  910. return passwordField;
  911. }
  912. cipFields.prepareCombinations = function(combinations) {
  913. for(var i = 0; i < combinations.length; i++) {
  914. // disable autocomplete for username field
  915. if(_f(combinations[i].username)) {
  916. _f(combinations[i].username).attr("autocomplete", "off");
  917. }
  918. var pwField = _f(combinations[i].password);
  919. // needed for auto-complete: don't overwrite manually filled-in password field
  920. if(pwField && !pwField.data("cipFields-onChange")) {
  921. pwField.data("cipFields-onChange", true);
  922. pwField.change(function() {
  923. cIPJQ(this).data("unchanged", false);
  924. });
  925. }
  926. // initialize form-submit for remembering credentials
  927. var fieldId = combinations[i].password || combinations[i].username;
  928. var field = _f(fieldId);
  929. if(field) {
  930. var form = field.closest("form");
  931. if(form && form.length > 0) {
  932. cipForm.init(form, combinations[i]);
  933. }
  934. }
  935. }
  936. }
  937. cipFields.useDefinedCredentialFields = function() {
  938. if(cip.settings["defined-credential-fields"] && cip.settings["defined-credential-fields"][document.location.origin]) {
  939. var creds = cip.settings["defined-credential-fields"][document.location.origin];
  940. var $found = _f(creds.username) || _f(creds.password);
  941. for(var i = 0; i < creds.fields.length; i++) {
  942. if(_fs(creds.fields[i])) {
  943. $found = true;
  944. break;
  945. }
  946. }
  947. if($found) {
  948. var fields = {
  949. "username": creds.username,
  950. "password": creds.password,
  951. "fields": creds.fields
  952. };
  953. cipFields.combinations = [];
  954. cipFields.combinations.push(fields);
  955. return true;
  956. }
  957. }
  958. return false;
  959. }
  960. var cip = {};
  961. // settings of chromeIPass
  962. cip.settings = {};
  963. // username field which will be set on focus
  964. cip.u = null;
  965. // password field which will be set on focus
  966. cip.p = null;
  967. // document.location
  968. cip.url = null;
  969. // request-url of the form in which the field is located
  970. cip.submitUrl = null;
  971. // received credentials from KeePassHTTP
  972. cip.credentials = [];
  973. cIPJQ(function() {
  974. cip.init();
  975. });
  976. cip.init = function() {
  977. chrome.extension.sendMessage({
  978. "action": "get_settings",
  979. }, function(response) {
  980. cip.settings = response.data;
  981. cip.initCredentialFields();
  982. });
  983. }
  984. cip.initCredentialFields = function(forceCall) {
  985. if(_called.initCredentialFields && !forceCall) {
  986. return;
  987. }
  988. _called.initCredentialFields = true;
  989. var inputs = cipFields.getAllFields();
  990. cipFields.prepareVisibleFieldsWithID("select");
  991. cip.initPasswordGenerator(inputs);
  992. if(!cipFields.useDefinedCredentialFields()) {
  993. // get all combinations of username + password fields
  994. cipFields.combinations = cipFields.getAllCombinations(inputs);
  995. }
  996. cipFields.prepareCombinations(cipFields.combinations);
  997. if(cipFields.combinations.length == 0) {
  998. chrome.extension.sendMessage({
  999. 'action': 'show_default_browseraction'
  1000. });
  1001. return;
  1002. }
  1003. cip.url = document.location.origin;
  1004. cip.submitUrl = cip.getFormActionUrl(cipFields.combinations[0]);
  1005. chrome.extension.sendMessage({
  1006. 'action': 'retrieve_credentials',
  1007. 'args': [ cip.url, cip.submitUrl ]
  1008. }, cip.retrieveCredentialsCallback);
  1009. } // end function init
  1010. cip.initPasswordGenerator = function(inputs) {
  1011. if(cip.settings.usePasswordGenerator) {
  1012. cipPassword.init();
  1013. for(var i = 0; i < inputs.length; i++) {
  1014. if(inputs[i] && inputs[i].attr("type") && inputs[i].attr("type").toLowerCase() == "password") {
  1015. cipPassword.initField(inputs[i], inputs, i);
  1016. }
  1017. }
  1018. }
  1019. }
  1020. cip.retrieveCredentialsCallback = function (credentials, dontAutoFillIn) {
  1021. if (cipFields.combinations.length > 0) {
  1022. cip.u = _f(cipFields.combinations[0].username);
  1023. cip.p = _f(cipFields.combinations[0].password);
  1024. }
  1025. if (credentials.length > 0) {
  1026. cip.credentials = credentials;
  1027. cip.prepareFieldsForCredentials(!Boolean(dontAutoFillIn));
  1028. }
  1029. }
  1030. cip.prepareFieldsForCredentials = function(autoFillInForSingle) {
  1031. // only one login for this site
  1032. if (autoFillInForSingle && cip.settings.autoFillSingleEntry && cip.credentials.length == 1) {
  1033. var combination = null;
  1034. if(!cip.p && !cip.u && cipFields.combinations.length > 0) {
  1035. cip.u = _f(cipFields.combinations[0].username);
  1036. cip.p = _f(cipFields.combinations[0].password);
  1037. combination = cipFields.combinations[0];
  1038. }
  1039. if (cip.u) {
  1040. cip.u.val(cip.credentials[0].Login);
  1041. combination = cipFields.getCombination("username", cip.u);
  1042. }
  1043. if (cip.p) {
  1044. cip.p.val(cip.credentials[0].Password);
  1045. combination = cipFields.getCombination("password", cip.p);
  1046. }
  1047. if(combination) {
  1048. var list = {};
  1049. if(cip.fillInStringFields(combination.fields, cip.credentials[0].StringFields, list)) {
  1050. cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]});
  1051. }
  1052. }
  1053. // generate popup-list of usernames + descriptions
  1054. chrome.extension.sendMessage({
  1055. 'action': 'popup_login',
  1056. 'args': [[cip.credentials[0].Login + " (" + cip.credentials[0].Name + ")"]]
  1057. });
  1058. }
  1059. //multiple logins for this site
  1060. else if (cip.credentials.length > 1 || (cip.credentials.length > 0 && (!cip.settings.autoFillSingleEntry || !autoFillInForSingle))) {
  1061. cip.preparePageForMultipleCredentials(cip.credentials);
  1062. }
  1063. }
  1064. cip.preparePageForMultipleCredentials = function(credentials) {
  1065. // add usernames + descriptions to autocomplete-list and popup-list
  1066. var usernames = [];
  1067. cipAutocomplete.elements = [];
  1068. var visibleLogin;
  1069. for(var i = 0; i < credentials.length; i++) {
  1070. visibleLogin = (credentials[i].Login.length > 0) ? credentials[i].Login : "- no username -";
  1071. usernames.push(visibleLogin + " (" + credentials[i].Name + ")");
  1072. var item = {
  1073. "label": visibleLogin + " (" + credentials[i].Name + ")",
  1074. "value": credentials[i].Login,
  1075. "loginId": i
  1076. };
  1077. cipAutocomplete.elements.push(item);
  1078. }
  1079. // generate popup-list of usernames + descriptions
  1080. chrome.extension.sendMessage({
  1081. 'action': 'popup_login',
  1082. 'args': [usernames]
  1083. });
  1084. // initialize autocomplete for username fields
  1085. if(cip.settings.autoCompleteUsernames) {
  1086. for(var i = 0; i < cipFields.combinations.length; i++) {
  1087. if(_f(cipFields.combinations[i].username)) {
  1088. cipAutocomplete.init(_f(cipFields.combinations[i].username));
  1089. }
  1090. }
  1091. }
  1092. }
  1093. cip.getFormActionUrl = function(combination) {
  1094. var field = _f(combination.password) || _f(combination.username);
  1095. if(field == null) {
  1096. return null;
  1097. }
  1098. var form = field.closest("form");
  1099. var action = null;
  1100. if(form && form.length > 0) {
  1101. action = form[0].action;
  1102. }
  1103. if(typeof(action) != "string" || action == "") {
  1104. action = document.location.origin + document.location.pathname;
  1105. }
  1106. return action;
  1107. }
  1108. cip.fillInCredentials = function(combination, onlyPassword, suppressWarnings) {
  1109. var action = cip.getFormActionUrl(combination);
  1110. var u = _f(combination.username);
  1111. var p = _f(combination.password);
  1112. if(combination.isNew) {
  1113. // initialize form-submit for remembering credentials
  1114. var fieldId = combination.password || combination.username;
  1115. var field = _f(fieldId);
  1116. if(field) {
  1117. var form2 = field.closest("form");
  1118. if(form2 && form2.length > 0) {
  1119. cipForm.init(form2, combination);
  1120. }
  1121. }
  1122. }
  1123. if(u) {
  1124. cip.u = u;
  1125. }
  1126. if(p) {
  1127. cip.p = p;
  1128. }
  1129. if(cip.url == document.location.origin && cip.submitUrl == action && cip.credentials.length > 0) {
  1130. cip.fillIn(combination, onlyPassword, suppressWarnings);
  1131. }
  1132. else {
  1133. cip.url = document.location.origin;
  1134. cip.submitUrl = action;
  1135. chrome.extension.sendMessage({
  1136. 'action': 'retrieve_credentials',
  1137. 'args': [ cip.url, cip.submitUrl, false, true ]
  1138. }, function(credentials) {
  1139. cip.retrieveCredentialsCallback(credentials, true);
  1140. cip.fillIn(combination, onlyPassword, suppressWarnings);
  1141. });
  1142. }
  1143. }
  1144. cip.fillInFromActiveElement = function(suppressWarnings) {
  1145. var el = document.activeElement;
  1146. if (el.tagName.toLowerCase() != "input") {
  1147. if(cipFields.combinations.length > 0) {
  1148. cip.fillInCredentials(cipFields.combinations[0], false, suppressWarnings);
  1149. }
  1150. return;
  1151. }
  1152. cipFields.setUniqueId(cIPJQ(el));
  1153. var fieldId = cipFields.prepareId(cIPJQ(el).attr("data-cip-id"));
  1154. var combination = null;
  1155. if(el.type && el.type.toLowerCase() == "password") {
  1156. combination = cipFields.getCombination("password", fieldId);
  1157. }
  1158. else {
  1159. combination = cipFields.getCombination("username", fieldId);
  1160. }
  1161. delete combination.loginId;
  1162. cip.fillInCredentials(combination, false, suppressWarnings);
  1163. }
  1164. cip.fillInFromActiveElementPassOnly = function(suppressWarnings) {
  1165. var el = document.activeElement;
  1166. if (el.tagName.toLowerCase() != "input") {
  1167. if(cipFields.combinations.length > 0) {
  1168. cip.fillInCredentials(cipFields.combinations[0], false, suppressWarnings);
  1169. }
  1170. return;
  1171. }
  1172. cipFields.setUniqueId(cIPJQ(el));
  1173. var fieldId = cipFields.prepareId(cIPJQ(el).attr("data-cip-id"));
  1174. var combination = null;
  1175. if(el.type && el.type.toLowerCase() == "password") {
  1176. combination = cipFields.getCombination("password", fieldId);
  1177. }
  1178. else {
  1179. combination = cipFields.getCombination("username", fieldId);
  1180. }
  1181. if(!_f(combination.password)) {
  1182. var message = "Unable to find a password field";
  1183. chrome.extension.sendMessage({
  1184. action: 'alert',
  1185. args: [message]
  1186. });
  1187. return;
  1188. }
  1189. delete combination.loginId;
  1190. cip.fillInCredentials(combination, true, suppressWarnings);
  1191. }
  1192. cip.setValue = function(field, value) {
  1193. if(field.is("select")) {
  1194. value = value.toLowerCase().trim();
  1195. cIPJQ("option", field).each(function() {
  1196. if(cIPJQ(this).text().toLowerCase().trim() == value) {
  1197. field.val(cIPJQ(this).val());
  1198. return false;
  1199. }
  1200. });
  1201. }
  1202. else {
  1203. field.val(value);
  1204. }
  1205. }
  1206. cip.fillInStringFields = function(fields, StringFields, filledInFields) {
  1207. var $filledIn = false;
  1208. filledInFields.list = [];
  1209. if(fields && StringFields && fields.length > 0 && StringFields.length > 0) {
  1210. for(var i = 0; i < fields.length; i++) {
  1211. var $sf = _fs(fields[i]);
  1212. if($sf && StringFields[i]) {
  1213. //$sf.val(StringFields[i].Value);
  1214. cip.setValue($sf, StringFields[i].Value);
  1215. filledInFields.list.push(fields[i]);
  1216. $filledIn = true;
  1217. }
  1218. }
  1219. }
  1220. return $filledIn;
  1221. }
  1222. cip.fillIn = function(combination, onlyPassword, suppressWarnings) {
  1223. // no credentials available
  1224. if (cip.credentials.length == 0 && !suppressWarnings) {
  1225. var message = "No logins found.";
  1226. chrome.extension.sendMessage({
  1227. action: 'alert',
  1228. args: [message]
  1229. });
  1230. return;
  1231. }
  1232. var uField = _f(combination.username);
  1233. var pField = _f(combination.password);
  1234. // exactly one pair of credentials available
  1235. if (cip.credentials.length == 1) {
  1236. var filledIn = false;
  1237. if(uField && !onlyPassword) {
  1238. uField.val(cip.credentials[0].Login);
  1239. filledIn = true;
  1240. }
  1241. if(pField) {
  1242. pField.attr("type", "password");
  1243. pField.val(cip.credentials[0].Password);
  1244. pField.data("unchanged", true);
  1245. filledIn = true;
  1246. }
  1247. var list = {};
  1248. if(cip.fillInStringFields(combination.fields, cip.credentials[0].StringFields, list)) {
  1249. cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]});
  1250. filledIn = true;
  1251. }
  1252. if(!filledIn) {
  1253. if(!suppressWarnings) {
  1254. var message = "Error #101\nCannot find fields to fill in.";
  1255. chrome.extension.sendMessage({
  1256. action: 'alert',
  1257. args: [message]
  1258. });
  1259. }
  1260. }
  1261. }
  1262. // specific login id given
  1263. else if(combination.loginId != undefined && cip.credentials[combination.loginId]) {
  1264. var filledIn = false;
  1265. if(uField) {
  1266. uField.val(cip.credentials[combination.loginId].Login);
  1267. filledIn = true;
  1268. }
  1269. if(pField) {
  1270. pField.val(cip.credentials[combination.loginId].Password);
  1271. pField.data("unchanged", true);
  1272. filledIn = true;
  1273. }
  1274. var list = {};
  1275. if(cip.fillInStringFields(combination.fields, cip.credentials[combination.loginId].StringFields, list)) {
  1276. cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]});
  1277. filledIn = true;
  1278. }
  1279. if(!filledIn) {
  1280. if(!suppressWarnings) {
  1281. var message = "Error #102\nCannot find fields to fill in.";
  1282. chrome.extension.sendMessage({
  1283. action: 'alert',
  1284. args: [message]
  1285. });
  1286. }
  1287. }
  1288. }
  1289. // multiple credentials available
  1290. else {
  1291. // check if only one password for given username exists
  1292. var countPasswords = 0;
  1293. if(uField) {
  1294. var valPassword = "";
  1295. var valUsername = "";
  1296. var valStringFields = [];
  1297. var valQueryUsername = uField.val().toLowerCase();
  1298. // find passwords to given username (even those with empty username)
  1299. for (var i = 0; i < cip.credentials.length; i++) {
  1300. if(cip.credentials[i].Login.toLowerCase() == valQueryUsername) {
  1301. countPasswords += 1;
  1302. valPassword = cip.credentials[i].Password;
  1303. valUsername = cip.credentials[i].Login;
  1304. valStringFields = cip.credentials[i].StringFields;
  1305. }
  1306. }
  1307. // for the correct alert message: 0 = no logins, X > 1 = too many logins
  1308. if(countPasswords == 0) {
  1309. countPasswords = cip.credentials.length;
  1310. }
  1311. // only one mapping username found
  1312. if(countPasswords == 1) {
  1313. if(!onlyPassword) {
  1314. uField.val(valUsername);
  1315. }
  1316. if(pField) {
  1317. pField.val(valPassword);
  1318. pField.data("unchanged", true);
  1319. }
  1320. var list = {};
  1321. if(cip.fillInStringFields(combination.fields, valStringFields, list)) {
  1322. cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]});
  1323. }
  1324. }
  1325. // user has to select correct credentials by himself
  1326. if(countPasswords > 1) {
  1327. if(!suppressWarnings) {
  1328. var message = "Error #105\nMore than one login was found in KeePass!\n" +
  1329. "Press the chromeIPass icon for more options.";
  1330. chrome.extension.sendMessage({
  1331. action: 'alert',
  1332. args: [message]
  1333. });
  1334. }
  1335. }
  1336. else if(countPasswords < 1) {
  1337. if(!suppressWarnings) {
  1338. var message = "Error #103\nNo credentials for given username found.";
  1339. chrome.extension.sendMessage({
  1340. action: 'alert',
  1341. args: [message]
  1342. });
  1343. }
  1344. }
  1345. }
  1346. else {
  1347. if(!suppressWarnings) {
  1348. var message = "Error #104\nMore than one login was found in KeePass!\n" +
  1349. "Press the chromeIPass icon for more options.";
  1350. chrome.extension.sendMessage({
  1351. action: 'alert',
  1352. args: [message]
  1353. });
  1354. }
  1355. }
  1356. }
  1357. }
  1358. cip.contextMenuRememberCredentials = function() {
  1359. var el = document.activeElement;
  1360. if (el.tagName.toLowerCase() != "input") {
  1361. return;
  1362. }
  1363. cipFields.setUniqueId(cIPJQ(el));
  1364. var fieldId = cipFields.prepareId(cIPJQ(el).attr("data-cip-id"));
  1365. var combination = null;
  1366. if(el.type && el.type.toLowerCase() == "password") {
  1367. combination = cipFields.getCombination("password", fieldId);
  1368. }
  1369. else {
  1370. combination = cipFields.getCombination("username", fieldId);
  1371. }
  1372. var usernameValue = "";
  1373. var passwordValue = "";
  1374. var usernameField = _f(combination.username);
  1375. var passwordField = _f(combination.password);
  1376. if(usernameField) {
  1377. usernameValue = usernameField.val();
  1378. }
  1379. if(passwordField) {
  1380. passwordValue = passwordField.val();
  1381. }
  1382. if(!cip.rememberCredentials(usernameValue, passwordValue)) {
  1383. alert("Could not detect changed credentials.");
  1384. }
  1385. };
  1386. cip.rememberCredentials = function(usernameValue, passwordValue) {
  1387. // no password given or field cleaned by a site-running script
  1388. // --> no password to save
  1389. if(passwordValue == "") {
  1390. return false;
  1391. }
  1392. var usernameExists = false;
  1393. var nothingChanged = false;
  1394. for(var i = 0; i < cip.credentials.length; i++) {
  1395. if(cip.credentials[i].Login == usernameValue && cip.credentials[i].Password == passwordValue) {
  1396. nothingChanged = true;
  1397. break;
  1398. }
  1399. if(cip.credentials[i].Login == usernameValue) {
  1400. usernameExists = true;
  1401. }
  1402. }
  1403. if(!nothingChanged) {
  1404. if(!usernameExists) {
  1405. for(var i = 0; i < cip.credentials.length; i++) {
  1406. if(cip.credentials[i].Login == usernameValue) {
  1407. usernameExists = true;
  1408. break;
  1409. }
  1410. }
  1411. }
  1412. var credentialsList = [];
  1413. for(var i = 0; i < cip.credentials.length; i++) {
  1414. credentialsList.push({
  1415. "Login": cip.credentials[i].Login,
  1416. "Name": cip.credentials[i].Name,
  1417. "Uuid": cip.credentials[i].Uuid
  1418. });
  1419. }
  1420. var url = cIPJQ(this)[0].action;
  1421. if(!url) {
  1422. url = document.location.href;
  1423. if(url.indexOf("?") > 0) {
  1424. url = url.substring(0, url.indexOf("?"));
  1425. if(url.length < document.location.origin.length) {
  1426. url = document.location.origin;
  1427. }
  1428. }
  1429. }
  1430. chrome.extension.sendMessage({
  1431. 'action': 'set_remember_credentials',
  1432. 'args': [usernameValue, passwordValue, url, usernameExists, credentialsList]
  1433. });
  1434. return true;
  1435. }
  1436. return false;
  1437. };
  1438. cipEvents = {};
  1439. cipEvents.clearCredentials = function() {
  1440. cip.credentials = [];
  1441. cipAutocomplete.elements = [];
  1442. if(cip.settings.autoCompleteUsernames) {
  1443. for(var i = 0; i < cipFields.combinations.length; i++) {
  1444. var uField = _f(cipFields.combinations[i].username);
  1445. if(uField) {
  1446. if(uField.hasClass("cip-ui-autocomplete-input")) {
  1447. uField.autocomplete("destroy");
  1448. }
  1449. }
  1450. }
  1451. }
  1452. }
  1453. cipEvents.triggerActivatedTab = function() {
  1454. // doesn't run a second time because of _called.initCredentialFields set to true
  1455. cip.init();
  1456. // initCredentialFields calls …

Large files files are truncated, but you can click here to view the full file