aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-06-21 11:04:36 +0200
committerWojtek Kosior <koszko@koszko.org>2022-06-21 11:06:02 +0200
commit43c126ecf8b4c7ce23a1d883993f2e62016a320f (patch)
treec88d629bdd017e447210806a89b16c73f3263d21
parenta0740ca80334d4668ee57139e14fb933e10a3bcc (diff)
downloadhacktcha-43c126ecf8b4c7ce23a1d883993f2e62016a320f.tar.gz
hacktcha-43c126ecf8b4c7ce23a1d883993f2e62016a320f.zip
final adjustments before the release
This commit: * adds handling of token expiration, * adds links to Google's Privacy Policy and Terms and * includes some other minor fixes adn adjustments.
-rw-r--r--captcha-child-bframe.js29
-rw-r--r--captcha-demo.js24
-rw-r--r--captcha-parent.js101
-rw-r--r--index.json10
4 files changed, 114 insertions, 50 deletions
diff --git a/captcha-child-bframe.js b/captcha-child-bframe.js
index 7f595c4..0a5b20d 100644
--- a/captcha-child-bframe.js
+++ b/captcha-child-bframe.js
@@ -58,6 +58,11 @@ const replacement_markup = `
background-color: white;
}
+ h4 {
+ margin-bottom: 10px;
+ margin-top: 10px;
+ }
+
#tiles_table, #tiles_body td {
border: 1px solid white;
padding: 0;
@@ -94,6 +99,12 @@ const replacement_markup = `
</style>
</head>
<body>
+ <div>
+ Google policies:
+ <a href="https://www.google.com/intl/en/policies/privacy/">privacy</a>
+ &amp;
+ <a href="https://www.google.com/intl/en/policies/terms/">terms</a>
+ </div>
<div id="main_loading">
<h4>
Loading Hacktcha - a libre client for reCAPTCHA.
@@ -103,7 +114,7 @@ const replacement_markup = `
<h4>
Challenge timed out.
</h4>
- <button id="resume_but">Resume</button>
+ <button class="retry_but">Reload Hacktcha</button>
</div>
<div id="main_challenge_blocked" class="hide">
<h4>
@@ -596,6 +607,8 @@ challenge_handlers.doscaptcha = function(api_helper, pmeta) {
challenge_handlers.default = challenge_handlers.doscaptcha;
+challenge_handlers.null = challenge_handlers.doscaptcha;
+
async function handle_challenge(api_helper, rresp) {
const pmeta = rresp[4];
const challenge_type = rresp[5];
@@ -674,8 +687,16 @@ async function get_final_token(site_key, rc_version, token) {
show_main_view("main_timed_out");
- const resume_but = document.getElementById("resume_but");
- await new Promise(cb => resume_but.onclick = cb);
+ /*
+ * Resuming after timeout does not work, so we allow the user to reload the
+ * iframe instead.
+ * TODO: fix resuming
+ */
+
+ /* const resume_but = document.getElementById("resume_but"); */
+ /* await new Promise(cb => resume_but.onclick = cb); */
+
+ return new Promise(() => {});
} else if (e.hacktcha_error === "challenge_blocked") {
show_main_view("main_challenge_blocked");
@@ -702,7 +723,7 @@ async function main() {
document.close();
for (const but of document.getElementsByClassName("retry_but"))
- but.onclick = () => window.postMessage("recreate_frame", origin);
+ but.onclick = () => window.parent.postMessage("recreate_frame", origin);
const final_token =
await get_final_token(site_key, rc_version, initial_token);
diff --git a/captcha-demo.js b/captcha-demo.js
index 28d331d..9c1ad55 100644
--- a/captcha-demo.js
+++ b/captcha-demo.js
@@ -22,19 +22,27 @@
if (document.getElementsByClassName("recaptcha-success").length > 0)
return;
- const demo_div = document.getElementById("recaptcha-demo");
+ const demo_submit = document.getElementById("recaptcha-demo-submit");
+ const demo_div = document.getElementById("recaptcha-demo");
+ const token_field = document.createElement("textarea");
const demo_site_key = demo_div.getAttribute("data-sitekey");
+ token_field.name = "g-recaptcha-response";
+ token_field.style.display = "none";
+
while (demo_div.nextElementSibling !== null)
demo_div.nextElementSibling.remove();
- const token = await HCHA.run(demo_div, demo_site_key);
-
- const token_field = document.createElement("textarea");
-
demo_div.after(token_field);
- token_field.name = "g-recaptcha-response";
- token_field.style.display = "none";
- token_field.value = token;
+ demo_submit.setAttribute("disabled", "");
+
+ for await (const token of HCHA.run(demo_div, demo_site_key)) {
+ if (token === null) {
+ demo_submit.setAttribute("disabled", "");
+ } else {
+ token_field.value = token;
+ demo_submit.removeAttribute("disabled");
+ }
+ }
})();
diff --git a/captcha-parent.js b/captcha-parent.js
index eaef67b..86ab909 100644
--- a/captcha-parent.js
+++ b/captcha-parent.js
@@ -73,6 +73,18 @@ HCHA._get_rc_version = async function() {
return match[1];
}
+HCHA._make_default_site_url = function() {
+ const url_obj = new URL(window.location.href);
+ let port = url_obj.port;
+
+ if (url_obj.protocol === "http:" && port === "80")
+ port = "";
+ else if (url_obj.protocol === "https:" && port === "")
+ port = "443";
+
+ return url_obj.origin + (port && `:${port}`);
+}
+
HCHA._make_anchor_frame_url = function(site_key, site_url, rc_version) {
const url = new URL("https://google.com/recaptcha/api2/anchor");
url.search = new URLSearchParams({
@@ -107,56 +119,79 @@ HCHA._spawn_frame = function(container, site_key, site_url, rc_version) {
HCHA._make_anchor_frame_url(site_key, site_url, rc_version);
}
-/* This library's external API consists of the run() function defined below. */
-HCHA.run = async function(container, site_key, site_url,
- start_immediately=false) {
- site_url ||= window.location.origin;
+HCHA._show_msg_and_wait = async function(container, button_text,
+ paragraph_text=null) {
+ container.innerHTML = "<div><p></p><button></button></div>";
- const rc_version = await HCHA._get_rc_version();
+ HCHA._style_contained_element(container.firstElementChild);
- if (!start_immediately) {
- container.innerHTML =
- "<div><button>Start solving reCAPTCHA</button></div>";
+ const paragraph = container.querySelector("p");
- HCHA._style_contained_element(container.firstElementChild);
+ if (paragraph_text === null)
+ paragraph.remove();
+ else
+ paragraph.textContent = paragraph_text;
- const button = container.querySelector("button");
- await new Promise(cb => button.onclick = e => {
- e.preventDefault();
- cb();
- });
- }
+ const button = container.querySelector("button");
+
+ button.textContent = button_text;
+
+ await new Promise(cb => button.onclick = e => {
+ e.preventDefault();
+ cb();
+ });
+}
- HCHA._spawn_frame(container, site_key, site_url, rc_version);
+HCHA._show_success_info = async function(container) {
+ const msg = "CAPTCHA completed successfully. The token shall be valid for 2 minutes.";
+ await HCHA._show_msg_and_wait(container, "OK", msg);
- let event, resolve;
+ container.innerHTML = "";
+}
+
+HCHA._main_loop = async function*(container, site_key, site_url) {
+ const rc_version = await HCHA._get_rc_version();
while (true) {
+ HCHA._spawn_frame(container, site_key, site_url, rc_version);
+
+ let event, resolve;
+
const prom = new Promise(cb => resolve = cb);
window.addEventListener("message", resolve, {once: true});
event = await prom;
- if (event.origin !== "https://google.com")
+ if (event.origin !== "https://google.com") {
console.warn("Received message from unexepected origin!", event);
- else if (event.data === "recreate_frame")
+ } else if (event.data === "recreate_frame") {
HCHA._spawn_frame(container, site_key, site_url, rc_version);
- else if (typeof event.data !== "string")
+ } else if (typeof event.data !== "string") {
console.error("Received token is not a string!", event);
- else
- break;
+ } else {
+ HCHA._show_success_info(container);
+
+ yield event.data;
+
+ await new Promise(cb => setTimeout(cb, 120000));
+
+ yield null;
+
+ await HCHA._show_msg_and_wait(container, "Solve reCAPTCHA again",
+ "Reached token timeout.");
+ }
}
+}
+
+/* This library's external API consists of the run() function defined below. */
+HCHA.run = async function*(container, site_key, site_url,
+ start_immediately=false) {
+ site_url = site_url || HCHA._make_default_site_url();
+
+ if (!start_immediately)
+ await HCHA._show_msg_and_wait(container, "Start solving reCAPTCHA");
- container.innerHTML = `
-<div style="width: 302px; border-style: none; padding: 10px">
- <p>
- CAPTCHA completed successfully. The token shall be valid for 2 minutes.
- </p>
- <button>OK</button>
-</div>
-`
- container.querySelector("button").onclick = () => container.innerHTML = "";
-
- return event.data;
+ for await (const value of HCHA._main_loop(container, site_key, site_url))
+ yield value;
}
diff --git a/index.json b/index.json
index fe8d343..99518a9 100644
--- a/index.json
+++ b/index.json
@@ -5,7 +5,7 @@
{
"$schema": "https://hydrilla.koszko.org/schemas/package_source-2.schema.json",
- "source_name": "hacktcha-2022.6.20",
+ "source_name": "hacktcha-2022.6.21",
"copyright": [
{"file": "report.spdx"},
{"file": "LICENSES/GPL-3.0-or-later.txt"},
@@ -17,7 +17,7 @@
"type": "mapping_and_resource",
"identifier": "hacktcha-anchor",
"long_name": "Hacktcha (anchor frame)",
- "version": [2022, 6, 20],
+ "version": [2022, 6, 21],
"revision": 1,
"description": "Make Google reCAPTCHA solvable without nonfree JavaScript.",
"dependencies": [],
@@ -32,7 +32,7 @@
"type": "mapping_and_resource",
"identifier": "hacktcha-bframe",
"long_name": "Hacktcha (bframe frame)",
- "version": [2022, 6, 20],
+ "version": [2022, 6, 21],
"revision": 1,
"description": "Make Google reCAPTCHA solvable without nonfree JavaScript.",
"dependencies": [],
@@ -48,7 +48,7 @@
"type": "resource",
"identifier": "hacktcha",
"long_name": "Hacktcha (main library)",
- "version": [2022, 6, 20],
+ "version": [2022, 6, 21],
"revision": 1,
"description": "Make Google reCAPTCHA solvable without nonfree JavaScript.",
"dependencies": [{"identifier": "cors-bypass"}],
@@ -58,7 +58,7 @@
"type": "mapping_and_resource",
"identifier": "hacktcha-demo",
"long_name": "Hacktcha demo",
- "version": [2022, 6, 20],
+ "version": [2022, 6, 21],
"revision": 1,
"description": "Solve Google reCAPTCHA online demo using Hacktcha.",
"dependencies": [{"identifier": "hacktcha"}],