Açıklama Yok

blocked-login-page.php 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. <?php
  2. use Automattic\Jetpack\Connection\Client;
  3. use Automattic\Jetpack\Redirect;
  4. /**
  5. * Class Jetpack_Protect_Blocked_Login_Page
  6. *
  7. * Instanciated on the wp-login page when Jetpack modules are loaded and $pagenow
  8. * is available, or during the login_head hook.
  9. *
  10. * Class will only be instanciated if Protect has detected a hard blocked IP address.
  11. *
  12. *
  13. */
  14. class Jetpack_Protect_Blocked_Login_Page {
  15. private static $__instance = null;
  16. public $can_send_recovery_emails;
  17. public $ip_address;
  18. public $valid_blocked_user_id;
  19. public $email_address;
  20. /**
  21. * URL to support page
  22. *
  23. * @deprecated 8.5.0 Use Jetpack_Protect_Blocked_Login_Page::get_help_url()
  24. * @see Jetpack_Protect_Blocked_Login_Page::get_help_url()
  25. *
  26. * @var string string $HELP_URL
  27. */
  28. const HELP_URL = 'https://jetpack.com/support/security-features/#unblock';
  29. const HTTP_STATUS_CODE_TOO_MANY_REQUESTS = 429;
  30. /**
  31. * Singleton implementation
  32. *
  33. * @return object
  34. */
  35. public static function instance( $ip_address ) {
  36. if ( ! is_a( self::$__instance, 'Jetpack_Protect_Blocked_Login_Page' ) ) {
  37. self::$__instance = new Jetpack_Protect_Blocked_Login_Page( $ip_address );
  38. }
  39. return self::$__instance;
  40. }
  41. function __construct( $ip_address ) {
  42. /**
  43. * Filter controls if an email recovery form is shown to blocked IPs.
  44. *
  45. * A recovery form allows folks to re-gain access to the login form
  46. * via an email link if their IP was mistakenly blocked.
  47. *
  48. * @module protect
  49. *
  50. * @since 5.6.0
  51. *
  52. * @param bool $can_send_recovery_emails Defaults to true.
  53. */
  54. $this->can_send_recovery_emails = apply_filters( 'jetpack_protect_can_send_recovery_emails', true );
  55. $this->ip_address = $ip_address;
  56. add_filter( 'wp_authenticate_user', array( $this, 'check_valid_blocked_user' ), 10, 1 );
  57. add_filter( 'site_url', array( $this, 'add_args_to_login_post_url' ), 10, 3 );
  58. add_filter( 'network_site_url', array( $this, 'add_args_to_login_post_url' ), 10, 3 );
  59. add_filter( 'lostpassword_url', array( $this, 'add_args_to_lostpassword_url' ), 10, 2 );
  60. add_filter( 'login_url', array( $this, 'add_args_to_login_url' ), 10, 3 );
  61. add_filter( 'lostpassword_redirect', array( $this, 'add_args_to_lostpassword_redirect_url' ), 10, 1 );
  62. }
  63. /**
  64. * Gets the URL that redirects to the support page on unblocking
  65. *
  66. * @since 8.5.0
  67. *
  68. * @return string
  69. */
  70. public static function get_help_url() {
  71. return Redirect::get_url( 'jetpack-support-security-features', array( 'anchor' => 'unblock' ) );
  72. }
  73. public function add_args_to_lostpassword_redirect_url( $url ) {
  74. if ( $this->valid_blocked_user_id ) {
  75. $url = empty( $url ) ? wp_login_url() : $url;
  76. $url = add_query_arg(
  77. array(
  78. 'validate_jetpack_protect_recovery' => $_GET['validate_jetpack_protect_recovery'],
  79. 'user_id' => $_GET['user_id'],
  80. 'checkemail' => 'confirm',
  81. ),
  82. $url
  83. );
  84. }
  85. return $url;
  86. }
  87. public function add_args_to_lostpassword_url( $url, $redirect ) {
  88. if ( $this->valid_blocked_user_id ) {
  89. $args = array(
  90. 'validate_jetpack_protect_recovery' => $_GET['validate_jetpack_protect_recovery'],
  91. 'user_id' => $_GET['user_id'],
  92. 'action' => 'lostpassword',
  93. );
  94. if ( ! empty( $redirect ) ) {
  95. $args['redirect_to'] = $redirect;
  96. }
  97. $url = add_query_arg( $args, $url );
  98. }
  99. return $url;
  100. }
  101. public function add_args_to_login_post_url( $url, $path, $scheme ) {
  102. if ( $this->valid_blocked_user_id && ( 'login_post' === $scheme || 'login' === $scheme ) ) {
  103. $url = add_query_arg(
  104. array(
  105. 'validate_jetpack_protect_recovery' => $_GET['validate_jetpack_protect_recovery'],
  106. 'user_id' => $_GET['user_id'],
  107. ),
  108. $url
  109. );
  110. }
  111. return $url;
  112. }
  113. public function add_args_to_login_url( $url, $redirect, $force_reauth ) {
  114. if ( $this->valid_blocked_user_id ) {
  115. $args = array(
  116. 'validate_jetpack_protect_recovery' => $_GET['validate_jetpack_protect_recovery'],
  117. 'user_id' => $_GET['user_id'],
  118. );
  119. if ( ! empty( $redirect ) ) {
  120. $args['redirect_to'] = $redirect;
  121. }
  122. if ( ! empty( $force_reauth ) ) {
  123. $args['reauth'] = '1';
  124. }
  125. $url = add_query_arg( $args, $url );
  126. }
  127. return $url;
  128. }
  129. public function check_valid_blocked_user( $user ) {
  130. if ( $this->valid_blocked_user_id && $this->valid_blocked_user_id != $user->ID ) {
  131. return new WP_Error( 'invalid_recovery_token', __( 'The recovery token is not valid for this user.', 'jetpack' ) );
  132. }
  133. return $user;
  134. }
  135. public function is_blocked_user_valid() {
  136. if ( ! $this->can_send_recovery_emails ) {
  137. return false;
  138. }
  139. if ( $this->valid_blocked_user_id ) {
  140. return true;
  141. }
  142. if ( ! isset( $_GET['validate_jetpack_protect_recovery'], $_GET['user_id'] ) ) {
  143. return false;
  144. }
  145. if ( ! $this->is_valid_protect_recovery_key( $_GET['validate_jetpack_protect_recovery'], $_GET['user_id'] ) ) {
  146. return false;
  147. }
  148. $this->valid_blocked_user_id = (int) $_GET['user_id'];
  149. return true;
  150. }
  151. public function is_valid_protect_recovery_key( $key, $user_id ) {
  152. $path = sprintf( '/sites/%d/protect/recovery/confirm', Jetpack::get_option( 'id' ) );
  153. $response = Client::wpcom_json_api_request_as_blog(
  154. $path,
  155. '1.1',
  156. array(
  157. 'method' => 'post'
  158. ),
  159. array(
  160. 'token' => $key,
  161. 'user_id' => $user_id,
  162. 'ip' => $this->ip_address,
  163. )
  164. );
  165. $result = json_decode( wp_remote_retrieve_body( $response ) );
  166. if ( is_wp_error( $result ) || empty( $result ) || isset( $result->error ) ) {
  167. return false;
  168. }
  169. return true;
  170. }
  171. public function render_and_die() {
  172. if ( ! $this->can_send_recovery_emails ) {
  173. $this->render_blocked_login_message();
  174. return;
  175. }
  176. if ( isset( $_GET['validate_jetpack_protect_recovery'] ) && $_GET['user_id'] ) {
  177. $error = new WP_Error( 'invalid_token', __( "Oops, we couldn't validate the recovery token.", 'jetpack' ) );
  178. $this->protect_die( $error );
  179. return;
  180. }
  181. if (
  182. isset( $_GET['jetpack-protect-recovery'] ) &&
  183. isset( $_POST['_wpnonce'] ) &&
  184. wp_verify_nonce( $_POST['_wpnonce'], 'bypass-protect' )
  185. ) {
  186. $this->process_recovery_email();
  187. return;
  188. }
  189. if ( isset( $_GET['loggedout'] ) && 'true' === $_GET['loggedout'] ) {
  190. $this->protect_die( __( 'You successfully logged out.', 'jetpack' ) );
  191. }
  192. $this->render_recovery_form();
  193. }
  194. public function render_blocked_login_message() {
  195. $this->protect_die( $this->get_html_blocked_login_message() );
  196. }
  197. function process_recovery_email() {
  198. $sent = $this->send_recovery_email();
  199. $show_recovery_form = true;
  200. if ( is_wp_error( $sent ) ) {
  201. if ( 'email_already_sent' === $sent->get_error_code() ) {
  202. $show_recovery_form = false;
  203. }
  204. $this->protect_die( $sent,null,true, $show_recovery_form );
  205. } else {
  206. $this->render_recovery_success();
  207. }
  208. }
  209. function send_recovery_email() {
  210. $email = isset( $_POST['email'] ) ? $_POST['email'] : '';
  211. if ( sanitize_email( $email ) !== $email || ! is_email( $email ) ) {
  212. return new WP_Error( 'invalid_email', __( "Oops, looks like that's not the right email address. Please try again!", 'jetpack' ) );
  213. }
  214. $user = get_user_by( 'email', trim( $email ) );
  215. if ( ! $user ) {
  216. return new WP_Error( 'invalid_user', __( "Oops, we couldn't find a user with that email. Please try again!", 'jetpack' ) );
  217. }
  218. $this->email_address = $email;
  219. $path = sprintf( '/sites/%d/protect/recovery/request', Jetpack::get_option( 'id' ) );
  220. $response = Client::wpcom_json_api_request_as_blog(
  221. $path,
  222. '1.1',
  223. array(
  224. 'method' => 'post'
  225. ),
  226. array(
  227. 'user_id' => $user->ID,
  228. 'ip' => $this->ip_address
  229. )
  230. );
  231. $code = wp_remote_retrieve_response_code( $response );
  232. $result = json_decode( wp_remote_retrieve_body( $response ) );
  233. if ( self::HTTP_STATUS_CODE_TOO_MANY_REQUESTS === $code ) {
  234. return new WP_Error( 'email_already_sent', sprintf( __( 'Recovery instructions were sent to %s. Check your inbox!', 'jetpack' ), $this->email_address ) );
  235. } else if ( is_wp_error( $result ) || empty( $result ) || isset( $result->error ) ) {
  236. return new WP_Error( 'email_send_error', __( 'Oops, we were unable to send a recovery email. Try again.', 'jetpack' ) );
  237. }
  238. return true;
  239. }
  240. function protect_die( $content, $title = null, $back_link = false, $recovery_form = false ) {
  241. if ( empty( $title ) ) {
  242. $title = __( 'Jetpack has locked your site\'s login page.', 'jetpack' );
  243. }
  244. if ( is_wp_error( $content ) ) {
  245. $svg = '<svg class="gridicon gridicons-notice" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm1 15h-2v-2h2v2zm0-4h-2l-.5-6h3l-.5 6z"/></g></svg>';
  246. $content = '<span class="error"> '. $svg . $content->get_error_message() . '</span>';
  247. }
  248. $content = '<p>'. $content .'</p>';
  249. // If for some reason the login pop up box show up in the wp-admin.
  250. if ( isset( $_GET['interim-login'] ) ) {
  251. $content = "<style>html{ background-color: #fff; } #error-message { margin:0 auto; padding: 1em; box-shadow: none; } </style>" . $content;
  252. }
  253. $this->display_page( $title, $content, $back_link, $recovery_form );
  254. }
  255. function render_recovery_form() {
  256. $content = $this->get_html_blocked_login_message();
  257. $this->protect_die( $content, null, null, true );
  258. }
  259. function render_recovery_success() {
  260. $this->protect_die( sprintf( __( 'Recovery instructions were sent to %s. Check your inbox!', 'jetpack' ), $this->email_address ) );
  261. }
  262. function get_html_blocked_login_message() {
  263. $icon = '<svg class="gridicon gridicons-spam" style="fill:#d94f4f" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M17 2H7L2 7v10l5 5h10l5-5V7l-5-5zm-4 15h-2v-2h2v2zm0-4h-2l-.5-6h3l-.5 6z"/></g></svg>';
  264. $ip = str_replace( 'http://', '', esc_url( 'http://' . $this->ip_address ) );
  265. return sprintf(
  266. __( '<p>Your IP address <code>%2$s</code> has been flagged for potential security violations. You can unlock your login by sending yourself a special link via email. <a href="%3$s">Learn More</a></p>', 'jetpack' ),
  267. $icon,
  268. $ip,
  269. esc_url( self::get_help_url() )
  270. );
  271. }
  272. function get_html_recovery_form() {
  273. ob_start(); ?>
  274. <div>
  275. <form method="post" action="?jetpack-protect-recovery=true">
  276. <?php echo wp_nonce_field( 'bypass-protect' ); ?>
  277. <p><label for="email"><?php esc_html_e( 'Your email', 'jetpack' ); ?><br/></label>
  278. <input type="email" name="email" class="text-input"/>
  279. <input type="submit" class="button"
  280. value="<?php esc_attr_e( 'Send email', 'jetpack' ); ?>"/>
  281. </p>
  282. </form>
  283. </div>
  284. <?php
  285. $contents = ob_get_contents();
  286. ob_end_clean();
  287. return $contents;
  288. }
  289. function display_page( $title, $message, $back_button = false, $recovery_form = false ) {
  290. if ( ! headers_sent() ) {
  291. nocache_headers();
  292. header( 'Content-Type: text/html; charset=utf-8' );
  293. }
  294. $text_direction = 'ltr';
  295. if ( is_rtl() ) {
  296. $text_direction = 'rtl';
  297. }
  298. ?>
  299. <!DOCTYPE html>
  300. <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) && function_exists( 'is_rtl' ) ) {
  301. language_attributes();
  302. } else {
  303. echo "dir='$text_direction'";
  304. } ?>>
  305. <head>
  306. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  307. <meta name="viewport" content="width=device-width">
  308. <?php
  309. if ( get_option( 'blog_public' ) ) {
  310. echo "<meta name='robots' content='noindex,follow' />\n";
  311. } else {
  312. echo "<meta name='robots' content='noindex,nofollow' />\n";
  313. }
  314. ?>
  315. <title><?php echo $title ?></title>
  316. <style type="text/css">
  317. html {
  318. background: #f6f6f6;
  319. }
  320. body {
  321. color: #2e4453;
  322. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  323. margin: 2em auto;
  324. padding: 1em 2em;
  325. max-width: 460px;
  326. text-align: left;
  327. }
  328. body.is-rtl {
  329. text-align: right;
  330. }
  331. h1 {
  332. clear: both;
  333. color: #3d596d;
  334. font-size: 24px;
  335. margin:0 0 24px 0;
  336. padding: 0;
  337. font-weight: 400;
  338. }
  339. #error-message {
  340. box-sizing: border-box;
  341. background: white;
  342. box-shadow: 0 0 0 1px rgba(200, 215, 225, 0.5), 0 1px 2px #e9eff3;
  343. padding: 24px;
  344. }
  345. #error-message img {
  346. margin: 0 auto;
  347. display: block;
  348. }
  349. #error-page {
  350. margin-top: 50px;
  351. }
  352. #error-page p {
  353. font-size: 14px;
  354. line-height: 1.5;
  355. margin: 24px 0 0;
  356. }
  357. #error-page code {
  358. font-family: Consolas, Monaco, monospace;
  359. }
  360. ul li {
  361. margin-bottom: 10px;
  362. font-size: 14px;
  363. }
  364. a {
  365. color: #00aadc;
  366. }
  367. label {
  368. font-weight: bold;
  369. font-size:16px;
  370. }
  371. a:hover,
  372. a:active {
  373. color: #0085be;
  374. }
  375. a:focus {
  376. color: #124964;
  377. -webkit-box-shadow: 0 0 0 1px #4f94d4,
  378. 0 0 2px 1px rgba(30, 140, 190, .8);
  379. box-shadow: 0 0 0 1px #4f94d4,
  380. 0 0 2px 1px rgba(30, 140, 190, .8);
  381. outline: none;
  382. }
  383. .button {
  384. background: #00aadc;
  385. color: white;
  386. border-color: #008ab3;
  387. border-style: solid;
  388. border-width: 1px 1px 2px;
  389. cursor: pointer;
  390. display: inline-block;
  391. margin: 0;
  392. margin-right: 0px;
  393. outline: 0;
  394. overflow: hidden;
  395. font-weight: 500;
  396. text-overflow: ellipsis;
  397. text-decoration: none;
  398. vertical-align: top;
  399. box-sizing: border-box;
  400. font-size: 14px;
  401. line-height: 21px;
  402. border-radius: 4px;
  403. padding: 7px 14px 9px;
  404. -webkit-appearance: none;
  405. -moz-appearance: none;
  406. appearance: none;
  407. font-size: 14px;
  408. width: 100%;
  409. }
  410. .button:hover,
  411. .button:focus {
  412. border-color: #005082;
  413. outline: none;
  414. }
  415. .button:focus {
  416. border-color: #005082;
  417. -webkit-box-shadow: 0 0 3px rgba(0, 115, 170, .8);
  418. box-shadow: 0 0 3px rgba(0, 115, 170, .8);
  419. outline: none;
  420. }
  421. .button::-moz-focus-inner {
  422. border: 0;
  423. }
  424. .button:active {
  425. border-width: 2px 1px 1px;
  426. }
  427. .gridicon {
  428. fill: currentColor;
  429. vertical-align: middle;
  430. }
  431. #error-footer {
  432. padding: 16px;
  433. }
  434. #error-footer a {
  435. text-decoration: none;
  436. line-height:20px;
  437. font-size: 14px;
  438. color: #4f748e;
  439. }
  440. #error-footer a:hover {
  441. color: #2e4453;
  442. }
  443. #error-footer .gridicon{
  444. width: 16px;
  445. }
  446. #error-footer .gridicons-help {
  447. width: 24px;
  448. margin-right:8px;
  449. }
  450. .is-rtl #error-footer .gridicons-help {
  451. margin-left:8px;
  452. }
  453. .error {
  454. background: #d94f4f;
  455. color:#FFF;
  456. display: block;
  457. border-radius: 3px;
  458. line-height: 1.5;
  459. padding: 16px;
  460. padding-left: 42px;
  461. }
  462. .is-rtl .error {
  463. padding-right: 42px;
  464. }
  465. .error .gridicon {
  466. float: left;
  467. margin-left: -32px;
  468. }
  469. .is-rtl .error .gridicon {
  470. float: right;
  471. margin-right: -32px;
  472. }
  473. .text-input {
  474. margin: 0;
  475. padding: 7px 14px;
  476. width: 100%;
  477. color: #2e4453;
  478. font-size: 16px;
  479. line-height: 1.5;
  480. border: 1px solid #c8d7e1;
  481. background-color: white;
  482. transition: all .15s ease-in-out;
  483. box-sizing: border-box;
  484. margin: 8px 0 16px;
  485. }
  486. #image {
  487. display: block;
  488. width: 200px;
  489. margin: 0 auto;
  490. }
  491. <?php
  492. $rtl_class = '';
  493. if ( 'rtl' == $text_direction ) {
  494. $rtl_class = 'class="is-rtl"';
  495. echo 'body { font-family: Tahoma, Arial; }';
  496. }
  497. ?>
  498. </style>
  499. </head>
  500. <body id="error-page" <?php echo $rtl_class; ?>>
  501. <h1 id="error-title"><?php echo esc_html( $title ); ?></h1>
  502. <div id="error-message">
  503. <svg id="image" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 250 134">
  504. <path fill="#E9EFF4" d="M205.2,129.8c3.7-0.7,7.4-0.9,11.1-1.1l5.5-0.1l5.5,0c3.7,0,7.4,0.1,11.1,0.2c3.7,0.1,7.4,0.3,11.1,0.8 c0.3,0,0.5,0.3,0.5,0.6c0,0.2-0.2,0.4-0.5,0.5c-3.7,0.5-7.4,0.6-11.1,0.8c-3.7,0.1-7.4,0.2-11.1,0.2l-5.5,0l-5.5-0.1 c-3.7-0.1-7.4-0.4-11.1-1.1c-0.1,0-0.2-0.2-0.2-0.3C205,129.9,205.1,129.8,205.2,129.8"/>
  505. <path fill="#E9EFF4" d="M0.2,130.9c3-0.7,5.9-0.9,8.9-1.1l4.4-0.1l4.4,0c3,0,5.9,0.1,8.9,0.2c3,0.1,5.9,0.3,8.9,0.8 c0.3,0,0.5,0.3,0.4,0.6c0,0.2-0.2,0.4-0.4,0.4c-3,0.5-5.9,0.6-8.9,0.8c-3,0.1-5.9,0.2-8.9,0.2l-4.4,0l-4.4-0.1 c-3-0.1-5.9-0.4-8.9-1.1c-0.1,0-0.2-0.2-0.2-0.3C0,131,0.1,130.9,0.2,130.9"/>
  506. <path fill="#C8D7E2" d="M101.6,130.1H70.1V52.5c0-8.5,6.9-15.3,15.3-15.3h16.1V130.1z"/>
  507. <path fill="#0DA9DD" d="M191.5,130.1h-73.8v-5.4c0-8.9,7.2-16.1,16.1-16.1h57.7V130.1z"/>
  508. <path fill="#C7E9F5" d="M55.2,25.6l-0.1,9.8L55,57l-0.1,21.6c0,0.2,0.2,0.4,0.4,0.4c0.2,0,0.4-0.2,0.4-0.4L56.6,57l0.8-21.6 c0.1-3.3,0.2-6.5,0.3-9.8H55.2z"/>
  509. <path fill="#C7E9F5" d="M203.1,25.6l0.1,18.1c0.2,28.8,0.4,57.6,1.2,86.3c0,0.4,0.4,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8 c0.8-28.8,1-57.6,1.2-86.3l0.1-18.1H203.1z"/>
  510. <path fill="#7FD3F2" d="M55.3,25.6v-8.2v-6.8c0-5.9,4-10.7,9-10.7h134c5,0,9,4.8,9,10.7v14.9H55.3z"/>
  511. <path fill="#005083" d="M210.7,25.6c-13.3,1.1-26.7,1-40,1l-40,0.2l-40-0.2c-13.3-0.1-26.7,0-40-1V25c13.3-1.1,26.7-1,40-1l40-0.2 l40,0.2c13.3,0.1,26.7,0,40,1V25.6z"/>
  512. <polygon fill="#C7E9F5" points="168.7,95.6 117.7,95.6 117.7,44.6 "/>
  513. <path fill="#C8D7E2" d="M191.5,56.5c0,11-8.9,19.9-19.9,19.9c-11,0-19.9-8.9-19.9-19.9c0-11,8.9-19.9,19.9-19.9 C182.6,36.6,191.5,45.5,191.5,56.5"/>
  514. <path fill="#FFFFFF" d="M213.2,95.5c-3.3-5.1-3.2-16.7-3.2-28.4h-32.3c0,0-5.2,25.5,4.6,33c7.5-0.1,29.9-0.6,29.9-0.6"/>
  515. <path fill="#C8D7E2" d="M213.5,95.3l-0.1-0.1l-0.3-0.5c-0.2-0.4-0.3-0.7-0.5-1.1c-0.3-0.8-0.5-1.6-0.7-2.4c-0.1-0.5-0.2-1.1-0.3-1.6 c-0.4,0-0.8,0-1.2,0c0.5,2.1,1.1,4.3,2.4,6.1l0.2,0.2c0.2,0,0.4-0.1,0.5-0.3C213.6,95.5,213.6,95.4,213.5,95.3L213.5,95.3z"/>
  516. <path fill="#C8D7E2" d="M212.5,98.6c-0.1,0-0.2,0-0.3,0l-0.1,0H212l-0.3,0l-0.6,0l-1.3,0l-2.5,0l-5,0l-19.5,0.2 c-1.9-1.7-3.1-4.1-3.8-6.5c-0.8-2.6-1.1-5.4-1.2-8.2c-0.2-5.2,0.3-10.4,1.1-15.6l5.7-0.1c0-0.9,0-1.8,0-2.6l-4.4,0l-2.5,0 c-0.4,0-0.8,0.2-1,0.5c-0.1,0.2-0.2,0.3-0.3,0.5l-0.1,0.3l-0.2,1.2c-0.3,1.7-0.5,3.3-0.7,5c-0.3,3.3-0.5,6.7-0.4,10.1 c0.1,3.4,0.5,6.7,1.5,10c0.5,1.6,1.2,3.2,2.2,4.7c0.5,0.7,1,1.4,1.7,2c0.3,0.3,0.6,0.6,1,0.9l0.1,0.1c0.1,0,0.2,0.1,0.3,0.2 c0.2,0.1,0.5,0.1,0.6,0.1l0.6,0l20-0.6l5-0.2l2.5-0.1l1.2,0l0.3,0l0.2,0c0,0,0.3,0,0.4-0.1c0.3-0.2,0.5-0.5,0.5-0.9 C213.1,99.1,212.9,98.7,212.5,98.6z"/>
  517. <path fill="#FFFFFF" d="M223.1,84.8c-3.3-5.1-4.8-16.7-4.8-28.4h-32.3c0,0-3.5,25.5,6.3,33c7.5-0.1,29.9-0.6,29.9-0.6"/>
  518. <path fill="#C8D7E2" d="M222.9,84.9c-1.3-2.1-2.2-4.4-2.8-6.7c-0.6-2.4-1.1-4.8-1.5-7.2c-0.7-4.8-1-9.1-1-13.9l0,0l-31,0.1l0,0 c-0.4,2.8-0.5,5.1-0.5,7.9c-0.1,2.9,0,5.7,0.3,8.6c0.3,2.8,0.8,5.7,1.7,8.3c0.9,2.6,2.3,5.2,4.5,6.9l-0.4-0.1l14.9-0.2 c5-0.1,10-0.1,14.9-0.1c0.1,0,0.3,0.1,0.3,0.3c0,0.1-0.1,0.3-0.2,0.3c-5,0.2-10,0.4-14.9,0.5l-14.9,0.4c-0.1,0-0.3,0-0.4-0.1l0,0 c-2.5-1.9-3.9-4.7-5-7.4c-1-2.8-1.5-5.7-1.9-8.6c-0.3-2.9-0.4-5.8-0.4-8.8c0.1-2.9,0.2-5.8,0.6-8.8c0-0.4,0.4-0.6,0.7-0.6h0 l32.3,0.1h0c0.3,0,0.6,0.3,0.6,0.6v0c0,4.8,0.2,9.6,0.7,14.4c0.3,2.4,0.6,4.8,1.2,7.1c0.5,2.3,1.2,4.7,2.4,6.8c0,0.1,0,0.1,0,0.2 C223.1,85,223,85,222.9,84.9"/>
  519. <path fill="#C8D7E2" d="M192.1,67.1c1.6-0.9,3.4-1.2,5.1-1.3c1.7-0.2,3.5-0.2,5.2-0.2c3.5,0.1,6.9,0.2,10.3,1c0.1,0,0.2,0.2,0.2,0.3 c0,0.1-0.1,0.2-0.2,0.2c-3.4,0.2-6.9,0-10.3,0c-1.7,0-3.4,0-5.1,0c-1.7,0-3.4,0.1-5.1,0.3l0,0c-0.1,0-0.1,0-0.1-0.1 C192,67.2,192.1,67.1,192.1,67.1"/>
  520. <path fill="#C8D7E2" d="M194.1,74c1.4,0,2.7,0,4.1,0c1.4,0,2.7,0,4.1,0c2.7,0,5.4-0.1,8.2-0.2c0.1,0,0.3,0.1,0.3,0.3 c0,0.1-0.1,0.2-0.2,0.3c-1.3,0.5-2.7,0.7-4.1,0.9c-1.4,0.2-2.8,0.2-4.2,0.3c-1.4,0-2.8,0-4.2-0.2c-1.4-0.2-2.8-0.4-4.1-1.1 c-0.1,0-0.1-0.1,0-0.2C193.9,74.1,194,74,194.1,74L194.1,74z"/>
  521. <path fill="#86A6BD" d="M40.2,88.6c-0.5,0-0.8-0.4-0.9-0.9l-0.1-8.2c0-0.7,0-1.4,0-2.1c0.1-0.7,0.2-1.5,0.4-2.2c0.4-1.4,1-2.8,1.9-4 c1.7-2.5,4.3-4.3,7.1-5.1c0.7-0.2,1.5-0.3,2.2-0.5c0.7-0.1,1.5-0.1,2.2-0.1c1.3,0,2.9,0,4.4,0.4c2.9,0.7,5.6,2.5,7.4,4.9 c0.9,1.2,1.6,2.6,2.1,4c0.5,1.4,0.6,3,0.6,4.4l0,16.4c0,0.7-0.6,1.3-1.3,1.3l-6.7,0c-0.7,0-1.3-0.6-1.3-1.3v0l0-10.8l0-5.4 c0-1.4-0.7-2.8-1.8-3.5c-0.6-0.4-1.3-0.6-2-0.7c-0.7,0-1.9,0-2.5,0c-1.4,0.1-2.7,1-3.3,2.3c-0.3,0.7-0.4,1.3-0.4,2.1l0,2.7 l-0.1,5.4l0,0c0,0.5-0.4,0.9-1,0.9"/>
  522. <path fill="#FFFFFF" d="M41.1,86.9l0.1-7.3c-0.1-2.6,0.7-5,2.1-7.1c1.4-2,3.6-3.5,5.9-4.1c0.6-0.2,1.2-0.3,1.8-0.3 c0.6,0,1.2-0.1,1.9,0c1.4,0,2.5,0,3.7,0.4c2.4,0.6,4.5,2,5.9,4c0.7,1,1.3,2.1,1.6,3.2c0.4,1.2,0.5,2.3,0.5,3.7l0,15.1l0,0l-4.2,0 l0-9.5l0-5.4c0-2.2-1.2-4.4-3-5.5c-0.9-0.6-2-0.9-3.1-1c-1.1,0-1.7,0-2.9,0c-2.2,0.2-4.2,1.7-5.1,3.6c-0.5,0.9-0.7,2.1-0.6,3.1 l0,2.7l0.1,4.4l0,0L41.1,86.9L41.1,86.9"/>
  523. <path fill="#86A6BD" d="M36.3,133c-1.9,0-3.8-1.1-4.8-2.8c-0.5-0.8-0.7-1.8-0.7-2.8l0-2.4l0-9.6l-0.1-9.6l0-4.8c0-0.7,0-1.8,0.3-2.8 c0.3-1,0.9-1.8,1.7-2.5c0.8-0.6,1.7-1.1,2.7-1.3c1.1-0.2,1.8-0.1,2.6-0.1l4.8,0l9.6-0.1l19.2,0c2.1,0,4.1,1.2,5.1,3 c0.5,0.9,0.8,2,0.8,3l0,2.4l0,9.6l-0.1,9.6l0,4.8c0,0.7,0,1.8-0.4,2.8c-0.3,0.9-1,1.8-1.7,2.4c-0.8,0.6-1.7,1.1-2.7,1.2 c-1.1,0.1-1.8,0-2.6,0.1l-4.8,0l-9.6-0.1L36.3,133z"/>
  524. <path fill="#FFFFFF" d="M74.8,112.3l-0.1-9.6l0-2.4c0-0.6-0.1-1.1-0.4-1.6c-0.6-1-1.7-1.6-2.8-1.6l-19.2,0L42.7,97l-4.8,0 c-0.8,0-1.7,0-2.2,0c-0.6,0.1-1.1,0.3-1.6,0.7c-0.5,0.4-0.8,0.9-1,1.4c-0.2,0.6-0.2,1.1-0.2,2l0,4.8l-0.1,9.6l0,9.6l0,2.4 c0,0.6,0.2,1.3,0.5,1.8c0.6,1.1,1.9,1.8,3.1,1.8l19.2-0.1l9.6-0.1l4.8,0c0.8,0,1.7,0,2.2-0.1c0.6-0.1,1.2-0.4,1.6-0.8 c0.5-0.4,0.8-0.9,1-1.5c0.2-0.6,0.2-1.1,0.2-2l0-4.8L74.8,112.3z"/>
  525. <path fill="#86A6BD" d="M48.1,121.4l2.9-6.2c0.3-0.6,0.2-1.3-0.3-1.8c-1-1-1.5-2.5-1.2-4c0.3-1.7,1.7-3.1,3.4-3.4 c2.9-0.6,5.4,1.6,5.4,4.4c0,1.2-0.5,2.3-1.3,3.1c-0.5,0.5-0.6,1.2-0.3,1.8l2.9,6.2c0.1,0.2-0.1,0.5-0.3,0.5H48.4 C48.1,121.9,48,121.6,48.1,121.4"/>
  526. </svg>
  527. <?php echo $message; ?>
  528. <?php if ( $recovery_form ) {
  529. echo $this->get_html_recovery_form();
  530. } ?>
  531. </div>
  532. <div id="error-footer">
  533. <?php
  534. if ( $back_button && ! $recovery_form ) {
  535. if ( 'rtl' === $text_direction ) {
  536. $back_button_icon = '<svg class="gridicon gridicons-arrow-right" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8z"/></g></svg>';
  537. } else {
  538. $back_button_icon = '<svg class="gridicon gridicons-arrow-left" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></g></svg>';
  539. }
  540. ?>
  541. <a href='javascript:history.back()'
  542. <?php
  543. printf(
  544. /* translators: %s is HTML markup, for a back icon. */
  545. __( '%s Back', 'jetpack' ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
  546. $back_button_icon // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
  547. );
  548. ?>
  549. </a>
  550. <?php
  551. } else {
  552. $help_icon = '<svg class="gridicon gridicons-help" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm1 16h-2v-2h2v2zm0-4.14V15h-2v-2c0-.552.448-1 1-1 1.103 0 2-.897 2-2s-.897-2-2-2-2 .897-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 1.862-1.278 3.413-3 3.86z"/></g></svg>';?>
  553. <a href="<?php echo esc_url( self::get_help_url() ); ?>" rel="noopener noreferrer" target="_blank">
  554. <?php
  555. printf(
  556. /* translators: %s is HTML markup, for a help icon. */
  557. __( '%s Get help unlocking your site', 'jetpack' ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
  558. $help_icon // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
  559. );
  560. ?>
  561. </a>
  562. <?php } ?>
  563. </div>
  564. </body>
  565. </html>
  566. <?php
  567. die();
  568. }
  569. }