From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- browser/components/translation/test/yandex.sjs | 203 +++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 browser/components/translation/test/yandex.sjs (limited to 'browser/components/translation/test/yandex.sjs') diff --git a/browser/components/translation/test/yandex.sjs b/browser/components/translation/test/yandex.sjs new file mode 100644 index 0000000000..24dd0b6e7c --- /dev/null +++ b/browser/components/translation/test/yandex.sjs @@ -0,0 +1,203 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); +Cu.importGlobalProperties(["TextEncoder"]); + +function handleRequest(req, res) { + try { + reallyHandleRequest(req, res); + } catch (ex) { + res.setStatusLine("1.0", 200, "AlmostOK"); + let msg = "Error handling request: " + ex + "\n" + ex.stack; + log(msg); + res.write(msg); + } +} + +function log(msg) { + dump("YANDEX-SERVER-MOCK: " + msg + "\n"); +} + +const statusCodes = { + 400: "Bad Request", + 401: "Invalid API key", + 402: "This API key has been blocked", + 403: "Daily limit for requests reached", + 404: "Daily limit for chars reached", + 413: "The text size exceeds the maximum", + 422: "The text could not be translated", + 500: "Internal Server Error", + 501: "The specified translation direction is not supported", + 503: "Service Unavailable", +}; + +function HTTPError(code = 500, message) { + this.code = code; + this.name = statusCodes[code] || "HTTPError"; + this.message = message || this.name; +} +HTTPError.prototype = new Error(); +HTTPError.prototype.constructor = HTTPError; + +function sendError(res, err) { + if (!(err instanceof HTTPError)) { + err = new HTTPError( + typeof err == "number" ? err : 500, + err.message || typeof err == "string" ? err : "" + ); + } + res.setStatusLine("1.1", err.code, err.name); + res.write(err.message); +} + +// Based on the code borrowed from: +// http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript +function parseQuery(query) { + let match, + params = {}, + pl = /\+/g, + search = /([^&=]+)=?([^&]*)/g, + decode = function (s) { + return decodeURIComponent(s.replace(pl, " ")); + }; + + while ((match = search.exec(query))) { + let k = decode(match[1]), + v = decode(match[2]); + if (k in params) { + if (params[k] instanceof Array) { + params[k].push(v); + } else { + params[k] = [params[k], v]; + } + } else { + params[k] = v; + } + } + + return params; +} + +function sha1(str) { + // `data` is an array of bytes. + let data = new TextEncoder().encode(str); + let ch = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash); + ch.init(ch.SHA1); + ch.update(data, data.length); + let hash = ch.finish(false); + + // Return the two-digit hexadecimal code for a byte. + function toHexString(charCode) { + return ("0" + charCode.toString(16)).slice(-2); + } + + // Convert the binary hash data to a hex string. + return Array.from(hash, (c, i) => toHexString(hash.charCodeAt(i))).join(""); +} + +function getRequestBody(req) { + let avail; + let bytes = []; + let body = new BinaryInputStream(req.bodyInputStream); + + while ((avail = body.available()) > 0) { + Array.prototype.push.apply(bytes, body.readByteArray(avail)); + } + + return String.fromCharCode.apply(null, bytes); +} + +function getInputStream(path) { + let file = Services.dirsvc.get("CurWorkD", Ci.nsIFile); + for (let part of path.split("/")) { + file.append(part); + } + let fileStream = Cc[ + "@mozilla.org/network/file-input-stream;1" + ].createInstance(Ci.nsIFileInputStream); + fileStream.init(file, 1, 0, false); + return fileStream; +} + +/** + * Yandex Requests have to be signed with an API Key. This mock server + * supports the following keys: + * + * yandexValidKey Always passes the authentication, + * yandexInvalidKey Never passes authentication and fails with 401 code, + * yandexBlockedKey Never passes authentication and fails with 402 code, + * yandexOutOfRequestsKey Never passes authentication and fails with 403 code, + * yandexOutOfCharsKey Never passes authentication and fails with 404 code. + * + * If any other key is used the server reponds with 401 error code. + */ +function checkAuth(params) { + if (!("key" in params)) { + throw new HTTPError(400); + } + + let key = params.key; + if (key === "yandexValidKey") { + return true; + } + + let invalidKeys = { + yandexInvalidKey: 401, + yandexBlockedKey: 402, + yandexOutOfRequestsKey: 403, + yandexOutOfCharsKey: 404, + }; + + if (key in invalidKeys) { + throw new HTTPError(invalidKeys[key]); + } + + throw new HTTPError(401); +} + +function reallyHandleRequest(req, res) { + try { + // Preparing the query parameters. + let params = {}; + if (req.method == "POST") { + params = parseQuery(getRequestBody(req)); + } + + // Extracting the API key and attempting to authenticate the request. + log(JSON.stringify(params)); + + checkAuth(params); + methodHandlers.translate(res, params); + } catch (ex) { + sendError(res, ex, ex.code); + } +} + +const methodHandlers = { + translate(res, params) { + res.setStatusLine("1.1", 200, "OK"); + res.setHeader("Content-Type", "application/json"); + + let hash = sha1(JSON.stringify(params)).substr(0, 10); + log("SHA1 hash of content: " + hash); + + let fixture = + "browser/browser/components/translation/test/fixtures/result-yandex-" + + hash + + ".json"; + log("PATH: " + fixture); + + let inputStream = getInputStream(fixture); + res.bodyOutputStream.writeFrom(inputStream, inputStream.available()); + inputStream.close(); + }, +}; -- cgit v1.2.3