зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1579049 - P1: Map Http error response codes to gecko error codes r=mayhemer,valentin
Differential Revision: https://phabricator.services.mozilla.com/D49903 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
c8984db985
Коммит
60f6486027
|
@ -4000,7 +4000,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
|||
break;
|
||||
case NS_ERROR_PROXY_CONNECTION_REFUSED:
|
||||
case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
|
||||
case NS_ERROR_TOO_MANY_REQUESTS:
|
||||
case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
|
||||
// Proxy connection was refused.
|
||||
error = "proxyConnectFailure";
|
||||
break;
|
||||
|
@ -6563,7 +6563,7 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
|||
aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
|
||||
aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
|
||||
aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
|
||||
aStatus == NS_ERROR_TOO_MANY_REQUESTS ||
|
||||
aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
|
||||
aStatus == NS_ERROR_BLOCKED_BY_POLICY) &&
|
||||
(isTopFrame || UseErrorPages())) {
|
||||
DisplayLoadError(aStatus, url, nullptr, aChannel);
|
||||
|
|
|
@ -148,7 +148,7 @@ XPC_MSG_DEF(NS_ERROR_PROXY_CONNECTION_REFUSED , "The connection to the pro
|
|||
XPC_MSG_DEF(NS_ERROR_PROXY_AUTHENTICATION_FAILED , "The proxy requires authentication")
|
||||
XPC_MSG_DEF(NS_ERROR_PROXY_BAD_GATEWAY , "The request failed on the proxy")
|
||||
XPC_MSG_DEF(NS_ERROR_PROXY_GATEWAY_TIMEOUT , "The request timed out on the proxy")
|
||||
XPC_MSG_DEF(NS_ERROR_TOO_MANY_REQUESTS , "Sending too many requests to a proxy")
|
||||
XPC_MSG_DEF(NS_ERROR_PROXY_TOO_MANY_REQUESTS , "Sending too many requests to a proxy")
|
||||
XPC_MSG_DEF(NS_ERROR_NET_TIMEOUT , "The connection has timed out")
|
||||
XPC_MSG_DEF(NS_ERROR_OFFLINE , "The requested action could not be completed in the offline state")
|
||||
XPC_MSG_DEF(NS_ERROR_PORT_ACCESS_NOT_ALLOWED , "Establishing a connection to an unsafe or otherwise banned port was prohibited")
|
||||
|
|
|
@ -1168,24 +1168,11 @@ void SpdyConnectTransaction::MapStreamToHttpConnection(
|
|||
mTunnelStreamOut = new OutputStreamShim(this, mIsWebsocket);
|
||||
mTunneledConn = new nsHttpConnection();
|
||||
|
||||
switch (httpResponseCode) {
|
||||
case 404:
|
||||
CreateShimError(NS_ERROR_UNKNOWN_HOST);
|
||||
break;
|
||||
case 407:
|
||||
CreateShimError(NS_ERROR_PROXY_AUTHENTICATION_FAILED);
|
||||
break;
|
||||
case 429:
|
||||
CreateShimError(NS_ERROR_TOO_MANY_REQUESTS);
|
||||
break;
|
||||
case 502:
|
||||
CreateShimError(NS_ERROR_PROXY_BAD_GATEWAY);
|
||||
break;
|
||||
case 504:
|
||||
CreateShimError(NS_ERROR_PROXY_GATEWAY_TIMEOUT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (httpResponseCode != 200) {
|
||||
nsresult err = HttpProxyResponseToErrorCode(httpResponseCode);
|
||||
if (NS_FAILED(err)) {
|
||||
CreateShimError(err);
|
||||
}
|
||||
}
|
||||
|
||||
// this new http connection has a specific hashkey (i.e. to a particular
|
||||
|
|
|
@ -841,5 +841,141 @@ void LogHeaders(const char* lineStart) {
|
|||
}
|
||||
}
|
||||
|
||||
nsresult HttpProxyResponseToErrorCode(uint32_t aStatusCode) {
|
||||
MOZ_ASSERT(aStatusCode >= 300,
|
||||
"Call HttpProxyResponseToErrorCode with successful status code!");
|
||||
|
||||
nsresult rv;
|
||||
switch (aStatusCode) {
|
||||
case 300:
|
||||
case 301:
|
||||
case 302:
|
||||
case 303:
|
||||
case 307:
|
||||
case 308:
|
||||
// Bad redirect: not top-level, or it's a POST, bad/missing Location,
|
||||
// or ProcessRedirect() failed for some other reason. Legal
|
||||
// redirects that fail because site not available, etc., are handled
|
||||
// elsewhere, in the regular codepath.
|
||||
rv = NS_ERROR_CONNECTION_REFUSED;
|
||||
break;
|
||||
// Squid sends 404 if DNS fails (regular 404 from target is tunneled)
|
||||
case 404: // HTTP/1.1: "Not Found"
|
||||
// RFC 2616: "some deployed proxies are known to return 400 or
|
||||
// 500 when DNS lookups time out." (Squid uses 500 if it runs
|
||||
// out of sockets: so we have a conflict here).
|
||||
case 400: // HTTP/1.1 "Bad Request"
|
||||
case 500: // HTTP/1.1: "Internal Server Error"
|
||||
rv = NS_ERROR_UNKNOWN_HOST;
|
||||
break;
|
||||
case 401:
|
||||
rv = NS_ERROR_PROXY_UNAUTHORIZED;
|
||||
break;
|
||||
case 402:
|
||||
rv = NS_ERROR_PROXY_PAYMENT_REQUIRED;
|
||||
break;
|
||||
case 403:
|
||||
rv = NS_ERROR_PROXY_FORBIDDEN;
|
||||
break;
|
||||
case 405:
|
||||
rv = NS_ERROR_PROXY_METHOD_NOT_ALLOWED;
|
||||
break;
|
||||
case 406:
|
||||
rv = NS_ERROR_PROXY_NOT_ACCEPTABLE;
|
||||
break;
|
||||
case 407: // ProcessAuthentication() failed (e.g. no header)
|
||||
rv = NS_ERROR_PROXY_AUTHENTICATION_FAILED;
|
||||
break;
|
||||
case 408:
|
||||
rv = NS_ERROR_PROXY_REQUEST_TIMEOUT;
|
||||
break;
|
||||
case 409:
|
||||
rv = NS_ERROR_PROXY_CONFLICT;
|
||||
break;
|
||||
case 410:
|
||||
rv = NS_ERROR_PROXY_GONE;
|
||||
break;
|
||||
case 411:
|
||||
rv = NS_ERROR_PROXY_LENGTH_REQUIRED;
|
||||
break;
|
||||
case 412:
|
||||
rv = NS_ERROR_PROXY_PRECONDITION_FAILED;
|
||||
break;
|
||||
case 413:
|
||||
rv = NS_ERROR_PROXY_REQUEST_ENTITY_TOO_LARGE;
|
||||
break;
|
||||
case 414:
|
||||
rv = NS_ERROR_PROXY_REQUEST_URI_TOO_LONG;
|
||||
break;
|
||||
case 415:
|
||||
rv = NS_ERROR_PROXY_UNSUPPORTED_MEDIA_TYPE;
|
||||
break;
|
||||
case 416:
|
||||
rv = NS_ERROR_PROXY_REQUESTED_RANGE_NOT_SATISFIABLE;
|
||||
break;
|
||||
case 417:
|
||||
rv = NS_ERROR_PROXY_EXPECTATION_FAILED;
|
||||
break;
|
||||
case 421:
|
||||
rv = NS_ERROR_PROXY_MISDIRECTED_REQUEST;
|
||||
break;
|
||||
case 425:
|
||||
rv = NS_ERROR_PROXY_TOO_EARLY;
|
||||
break;
|
||||
case 426:
|
||||
rv = NS_ERROR_PROXY_UPGRADE_REQUIRED;
|
||||
break;
|
||||
case 428:
|
||||
rv = NS_ERROR_PROXY_PRECONDITION_REQUIRED;
|
||||
break;
|
||||
case 429:
|
||||
rv = NS_ERROR_PROXY_TOO_MANY_REQUESTS;
|
||||
break;
|
||||
case 431:
|
||||
rv = NS_ERROR_PROXY_REQUEST_HEADER_FIELDS_TOO_LARGE;
|
||||
break;
|
||||
case 451:
|
||||
rv = NS_ERROR_PROXY_UNAVAILABLE_FOR_LEGAL_REASONS;
|
||||
break;
|
||||
case 501:
|
||||
rv = NS_ERROR_PROXY_NOT_IMPLEMENTED;
|
||||
break;
|
||||
case 502:
|
||||
rv = NS_ERROR_PROXY_BAD_GATEWAY;
|
||||
break;
|
||||
case 503:
|
||||
// Squid returns 503 if target request fails for anything but DNS.
|
||||
/* User sees: "Failed to Connect:
|
||||
* Firefox can't establish a connection to the server at
|
||||
* www.foo.com. Though the site seems valid, the browser
|
||||
* was unable to establish a connection."
|
||||
*/
|
||||
rv = NS_ERROR_CONNECTION_REFUSED;
|
||||
break;
|
||||
// RFC 2616 uses 504 for both DNS and target timeout, so not clear what to
|
||||
// do here: picking target timeout, as DNS covered by 400/404/500
|
||||
case 504:
|
||||
rv = NS_ERROR_PROXY_GATEWAY_TIMEOUT;
|
||||
break;
|
||||
case 505:
|
||||
rv = NS_ERROR_PROXY_VERSION_NOT_SUPPORTED;
|
||||
break;
|
||||
case 506:
|
||||
rv = NS_ERROR_PROXY_VARIANT_ALSO_NEGOTIATES;
|
||||
break;
|
||||
case 510:
|
||||
rv = NS_ERROR_PROXY_NOT_EXTENDED;
|
||||
break;
|
||||
case 511:
|
||||
rv = NS_ERROR_PROXY_NETWORK_AUTHENTICATION_REQUIRED;
|
||||
break;
|
||||
default:
|
||||
rv = NS_ERROR_PROXY_CONNECTION_REFUSED;
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -336,6 +336,11 @@ class ParsedHeaderValueListList {
|
|||
|
||||
void LogHeaders(const char* lineStart);
|
||||
|
||||
// Convert HTTP response codes returned by a proxy to nsresult.
|
||||
// This function should be only used when we get a failed response to the
|
||||
// CONNECT method.
|
||||
nsresult HttpProxyResponseToErrorCode(uint32_t aStatusCode);
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -1938,67 +1938,7 @@ nsresult nsHttpChannel::ProcessFailedProxyConnect(uint32_t httpStatus) {
|
|||
|
||||
MOZ_ASSERT(mConnectionInfo->UsingConnect(),
|
||||
"proxy connect failed but not using CONNECT?");
|
||||
nsresult rv;
|
||||
switch (httpStatus) {
|
||||
case 300:
|
||||
case 301:
|
||||
case 302:
|
||||
case 303:
|
||||
case 307:
|
||||
case 308:
|
||||
// Bad redirect: not top-level, or it's a POST, bad/missing Location,
|
||||
// or ProcessRedirect() failed for some other reason. Legal
|
||||
// redirects that fail because site not available, etc., are handled
|
||||
// elsewhere, in the regular codepath.
|
||||
rv = NS_ERROR_CONNECTION_REFUSED;
|
||||
break;
|
||||
case 403: // HTTP/1.1: "Forbidden"
|
||||
case 501: // HTTP/1.1: "Not Implemented"
|
||||
// user sees boilerplate Mozilla "Proxy Refused Connection" page.
|
||||
rv = NS_ERROR_PROXY_CONNECTION_REFUSED;
|
||||
break;
|
||||
case 407: // ProcessAuthentication() failed (e.g. no header)
|
||||
rv = NS_ERROR_PROXY_AUTHENTICATION_FAILED;
|
||||
break;
|
||||
case 429:
|
||||
rv = NS_ERROR_TOO_MANY_REQUESTS;
|
||||
break;
|
||||
// Squid sends 404 if DNS fails (regular 404 from target is tunneled)
|
||||
case 404: // HTTP/1.1: "Not Found"
|
||||
// RFC 2616: "some deployed proxies are known to return 400 or
|
||||
// 500 when DNS lookups time out." (Squid uses 500 if it runs
|
||||
// out of sockets: so we have a conflict here).
|
||||
case 400: // HTTP/1.1 "Bad Request"
|
||||
case 500: // HTTP/1.1: "Internal Server Error"
|
||||
/* User sees: "Address Not Found: Firefox can't find the server at
|
||||
* www.foo.com."
|
||||
*/
|
||||
rv = NS_ERROR_UNKNOWN_HOST;
|
||||
break;
|
||||
case 502: // HTTP/1.1: "Bad Gateway" (invalid resp from target server)
|
||||
rv = NS_ERROR_PROXY_BAD_GATEWAY;
|
||||
break;
|
||||
case 503: // HTTP/1.1: "Service Unavailable"
|
||||
// Squid returns 503 if target request fails for anything but DNS.
|
||||
/* User sees: "Failed to Connect:
|
||||
* Firefox can't establish a connection to the server at
|
||||
* www.foo.com. Though the site seems valid, the browser
|
||||
* was unable to establish a connection."
|
||||
*/
|
||||
rv = NS_ERROR_CONNECTION_REFUSED;
|
||||
break;
|
||||
// RFC 2616 uses 504 for both DNS and target timeout, so not clear what to
|
||||
// do here: picking target timeout, as DNS covered by 400/404/500
|
||||
case 504: // HTTP/1.1: "Gateway Timeout"
|
||||
// user sees: "Network Timeout: The server at www.foo.com
|
||||
// is taking too long to respond."
|
||||
rv = NS_ERROR_PROXY_GATEWAY_TIMEOUT;
|
||||
break;
|
||||
// Confused proxy server or malicious response
|
||||
default:
|
||||
rv = NS_ERROR_PROXY_CONNECTION_REFUSED;
|
||||
break;
|
||||
}
|
||||
nsresult rv = HttpProxyResponseToErrorCode(httpStatus);
|
||||
LOG(("Cancelling failed proxy CONNECT [this=%p httpStatus=%u]\n", this,
|
||||
httpStatus));
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ add_task(async function proxy_too_many_requests_failure() {
|
|||
CL_EXPECT_FAILURE
|
||||
);
|
||||
|
||||
Assert.equal(status, Cr.NS_ERROR_TOO_MANY_REQUESTS);
|
||||
Assert.equal(status, Cr.NS_ERROR_PROXY_TOO_MANY_REQUESTS);
|
||||
Assert.equal(http_code, undefined);
|
||||
});
|
||||
|
||||
|
|
|
@ -446,7 +446,7 @@ add_task(async function proxy_too_many_requests_failure() {
|
|||
CL_EXPECT_FAILURE
|
||||
);
|
||||
|
||||
Assert.equal(status, Cr.NS_ERROR_TOO_MANY_REQUESTS);
|
||||
Assert.equal(status, Cr.NS_ERROR_PROXY_TOO_MANY_REQUESTS);
|
||||
Assert.equal(http_code, undefined);
|
||||
Assert.equal(
|
||||
await proxy_session_counter(),
|
||||
|
|
|
@ -330,14 +330,6 @@ with modules["NETWORK"]:
|
|||
errors["NS_ERROR_NET_INTERRUPT"] = FAILURE(71)
|
||||
# The connection attempt to a proxy failed.
|
||||
errors["NS_ERROR_PROXY_CONNECTION_REFUSED"] = FAILURE(72)
|
||||
# The proxy requires authentication; used when we can't easily propagate 407s.
|
||||
errors["NS_ERROR_PROXY_AUTHENTICATION_FAILED"] = FAILURE(407)
|
||||
# Indicates that we have sent too many requests in a given amount of time.
|
||||
errors["NS_ERROR_TOO_MANY_REQUESTS"] = FAILURE(429)
|
||||
# The proxy failed to connect the remote server.
|
||||
errors["NS_ERROR_PROXY_BAD_GATEWAY"] = FAILURE(502)
|
||||
# The proxy did get any response from the remote server in time.
|
||||
errors["NS_ERROR_PROXY_GATEWAY_TIMEOUT"] = FAILURE(504)
|
||||
# A transfer was only partially done when it completed.
|
||||
errors["NS_ERROR_NET_PARTIAL_TRANSFER"] = FAILURE(76)
|
||||
# HTTP/2 detected invalid TLS configuration
|
||||
|
@ -460,6 +452,61 @@ with modules["NETWORK"]:
|
|||
# Generic error for non-specific failures during service worker interception
|
||||
errors["NS_ERROR_INTERCEPTION_FAILED"] = FAILURE(100)
|
||||
|
||||
# All Http proxy CONNECT response codes
|
||||
errors["NS_ERROR_PROXY_CODE_BASE"] = FAILURE(1000)
|
||||
# Redirection 3xx
|
||||
errors["NS_ERROR_PROXY_MULTIPLE_CHOICES"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 300
|
||||
errors["NS_ERROR_PROXY_MOVED_PERMANENTLY"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 301
|
||||
errors["NS_ERROR_PROXY_FOUND"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 302
|
||||
errors["NS_ERROR_PROXY_SEE_OTHER"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 303
|
||||
errors["NS_ERROR_PROXY_NOT_MODIFIED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 304
|
||||
errors["NS_ERROR_PROXY_TEMPORARY_REDIRECT"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 307
|
||||
errors["NS_ERROR_PROXY_PERMANENT_REDIRECT"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 308
|
||||
|
||||
# Client error 4xx
|
||||
errors["NS_ERROR_PROXY_BAD_REQUEST"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 400
|
||||
errors["NS_ERROR_PROXY_UNAUTHORIZED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 401
|
||||
errors["NS_ERROR_PROXY_PAYMENT_REQUIRED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 402
|
||||
errors["NS_ERROR_PROXY_FORBIDDEN"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 403
|
||||
errors["NS_ERROR_PROXY_NOT_FOUND"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 404
|
||||
errors["NS_ERROR_PROXY_METHOD_NOT_ALLOWED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 405
|
||||
errors["NS_ERROR_PROXY_NOT_ACCEPTABLE"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 406
|
||||
# The proxy requires authentication; used when we can't easily propagate 407s.
|
||||
errors["NS_ERROR_PROXY_AUTHENTICATION_FAILED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 407
|
||||
errors["NS_ERROR_PROXY_REQUEST_TIMEOUT"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 408
|
||||
errors["NS_ERROR_PROXY_CONFLICT"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 409
|
||||
errors["NS_ERROR_PROXY_GONE"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 410
|
||||
errors["NS_ERROR_PROXY_LENGTH_REQUIRED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 411
|
||||
errors["NS_ERROR_PROXY_PRECONDITION_FAILED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 412
|
||||
errors["NS_ERROR_PROXY_REQUEST_ENTITY_TOO_LARGE"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 413
|
||||
errors["NS_ERROR_PROXY_REQUEST_URI_TOO_LONG"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 414
|
||||
errors["NS_ERROR_PROXY_UNSUPPORTED_MEDIA_TYPE"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 415
|
||||
errors["NS_ERROR_PROXY_REQUESTED_RANGE_NOT_SATISFIABLE"] = \
|
||||
errors["NS_ERROR_PROXY_CODE_BASE"] + 416
|
||||
errors["NS_ERROR_PROXY_EXPECTATION_FAILED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 417
|
||||
errors["NS_ERROR_PROXY_MISDIRECTED_REQUEST"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 421
|
||||
errors["NS_ERROR_PROXY_TOO_EARLY"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 425
|
||||
errors["NS_ERROR_PROXY_UPGRADE_REQUIRED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 426
|
||||
errors["NS_ERROR_PROXY_PRECONDITION_REQUIRED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 428
|
||||
# Indicates that we have sent too many requests in a given amount of time.
|
||||
errors["NS_ERROR_PROXY_TOO_MANY_REQUESTS"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 429
|
||||
errors["NS_ERROR_PROXY_REQUEST_HEADER_FIELDS_TOO_LARGE"] = \
|
||||
errors["NS_ERROR_PROXY_CODE_BASE"] + 431
|
||||
errors["NS_ERROR_PROXY_UNAVAILABLE_FOR_LEGAL_REASONS"] = \
|
||||
errors["NS_ERROR_PROXY_CODE_BASE"] + 451
|
||||
|
||||
# Server error 5xx
|
||||
errors["NS_ERROR_PROXY_INTERNAL_SERVER_ERROR"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 500
|
||||
errors["NS_ERROR_PROXY_NOT_IMPLEMENTED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 501
|
||||
errors["NS_ERROR_PROXY_BAD_GATEWAY"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 502
|
||||
errors["NS_ERROR_PROXY_SERVICE_UNAVAILABLE"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 503
|
||||
# The proxy did get any response from the remote server in time.
|
||||
errors["NS_ERROR_PROXY_GATEWAY_TIMEOUT"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 504
|
||||
errors["NS_ERROR_PROXY_VERSION_NOT_SUPPORTED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 505
|
||||
errors["NS_ERROR_PROXY_VARIANT_ALSO_NEGOTIATES"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 506
|
||||
errors["NS_ERROR_PROXY_NOT_EXTENDED"] = errors["NS_ERROR_PROXY_CODE_BASE"] + 510
|
||||
errors["NS_ERROR_PROXY_NETWORK_AUTHENTICATION_REQUIRED"] = \
|
||||
errors["NS_ERROR_PROXY_CODE_BASE"] + 511
|
||||
|
||||
# =======================================================================
|
||||
# 7: NS_ERROR_MODULE_PLUGINS
|
||||
|
|
Загрузка…
Ссылка в новой задаче