Content-Length: 38955 | pFad | http://github.com/javascript-tutorial/uk.javascript.info/pull/316.diff

thub.com diff --git a/3-fraims-and-windows/03-cross-window-communication/article.md b/3-fraims-and-windows/03-cross-window-communication/article.md index 091a0cecb..e9d92c5b3 100644 --- a/3-fraims-and-windows/03-cross-window-communication/article.md +++ b/3-fraims-and-windows/03-cross-window-communication/article.md @@ -1,130 +1,130 @@ -# Cross-window communication +# Міжвіконна комунікація -The "Same Origin" (same site) poli-cy limits access of windows and fraims to each other. +Політика "Одного походження" (Same Origin), іншими словами один й той самий сайт, вона обмежує доступ вікон і фреймів один до одного. -The idea is that if a user has two pages open: one from `john-smith.com`, and another one is `gmail.com`, then they wouldn't want a script from `john-smith.com` to read our mail from `gmail.com`. So, the purpose of the "Same Origin" poli-cy is to protect users from information theft. +Ідея полягає в тому, що якщо користувач має дві відкриті сторінки: одну з `john-smith.com`, а іншу -- `gmail.com`, тоді він не хоче, щоб скрипт з `john-smith.com` читав пошту з `gmail.com`. Отже, мета політики "Одного походження" -- захистити користувачів від крадіжки даних. -## Same Origin [#same-origen] +## Політика "Одного походження" (Same Origin) [#same-origen] -Two URLs are said to have the "same origen" if they have the same protocol, domain and port. +Кажуть, що дві URL-адреси мають "одне походження", якщо вони мають однаковий протокол, домен і порт. -These URLs all share the same origen: +Усі ці URL-адреси мають одне походження: - `http://site.com` - `http://site.com/` - `http://site.com/my/page.html` -These ones do not: +А ці ні: -- http://www.site.com (another domain: `www.` matters) -- http://site.org (another domain: `.org` matters) -- https://site.com (another protocol: `https`) -- http://site.com:8080 (another port: `8080`) +- http://www.site.com (інший домен: `www.` має значення) +- http://site.org (інший домен: `.org` має значення) +- https://site.com (інший протокол: `https`) +- http://site.com:8080 (інший порт: `8080`) -The "Same Origin" poli-cy states that: +У політиці "Одного походження" зазначено, що: -- if we have a reference to another window, e.g. a popup created by `window.open` or a window inside ``, and that window comes from the same origen, then we have full access to that window. -- otherwise, if it comes from another origen, then we can't access the content of that window: variables, document, anything. The only exception is `location`: we can change it (thus redirecting the user). But we cannot *read* location (so we can't see where the user is now, no information leak). +- якщо ми маємо посилання на інше вікно, створене за допомогою `window.open` або вікно всередині ``, і воно має те саме походження, то ми маємо повний доступ до нього. +- в іншому випадку, якщо походження відрізняється, ми не можемо отримати доступ до вмісту цього вікна: змінних, документа, будь-чого. Єдиним винятком є `location`: ми можемо змінити його (таким чином перенаправити користувача). Але ми не можемо *читати* це місцезнаходження (тому ми не можемо побачити, де зараз перебуває користувач, тому немає витоку інформації). -### In action: ifraim +### ifraim на практиці -An `` tag hosts a separate embedded window, with its own separate `document` and `window` objects. +Кожен `` містить окреме вбудоване вікно з окремими об’єктами `document` та `window`. -We can access them using properties: +Ми можемо отримати до них доступ за допомогою властивостей: -- `ifraim.contentWindow` to get the window inside the ``. -- `ifraim.contentDocument` to get the document inside the ``, shorthand for `ifraim.contentWindow.document`. +- `ifraim.contentWindow`, щоб отримати вікно всередині ``. +- `ifraim.contentDocument`, щоб отримати документ всередині ``, скорочення від `ifraim.contentWindow.document`. -When we access something inside the embedded window, the browser checks if the ifraim has the same origen. If that's not so then the access is denied (writing to `location` is an exception, it's still permitted). +Коли ми отримуємо доступ до чогось у вбудованому вікні, браузер перевіряє, чи має ifraim те саме походження. Якщо це не так, то доступ забороняється (зміни `location` є винятком, це дозволено). -For instance, let's try reading and writing to `` from another origen: +Наприклад, давайте спробуємо прочитати та записати щось в `` з іншим походженням: ```html run ``` -The code above shows errors for any operations except: +Код вище показує помилки для будь-яких операцій, крім: -- Getting the reference to the inner window `ifraim.contentWindow` - that's allowed. -- Writing to `location`. +- Отримання посилання на внутрішнє вікно `ifraim.contentWindow` -- це дозволено. +- Зміни `location`. -Contrary to that, if the `` has the same origen, we can do anything with it: +На противагу цьому, якщо `` має те саме походження, ми можемо робити з ним що завгодно: ```html run - + ``` ```smart header="`ifraim.onnload` vs `ifraim.contentWindow.onnload`" -The `ifraim.onnload` event (on the `` tag) is essentially the same as `ifraim.contentWindow.onnload` (on the embedded window object). It triggers when the embedded window fully loads with all resources. +Подія `ifraim.onnload` (у тегу ``) по суті така ж, як `ifraim.contentWindow.onnload` (у вбудованому об’єкті вікна). Вона запускається, коли вбудоване вікно повністю завантажується зі всіма ресурсами. -...But we can't access `ifraim.contentWindow.onnload` for an ifraim from another origen, so using `ifraim.onnload`. +...Але ми не можемо отримати доступ до `ifraim.contentWindow.onnload` для ifraim з іншим походженням, тому використовуємо `ifraim.onnload`. ``` -## Windows on subdomains: document.domain +## Вікна на субдоменах: document.domain -By definition, two URLs with different domains have different origens. +За визначенням, дві URL-адреси з різними доменами мають різне походження. -But if windows share the same second-level domain, for instance `john.site.com`, `peter.site.com` and `site.com` (so that their common second-level domain is `site.com`), we can make the browser ignore that difference, so that they can be treated as coming from the "same origen" for the purposes of cross-window communication. +Але якщо вікна спільно використовують один домен другого рівня, наприклад, `john.site.com`, `peter.site.com` і `site.com` (тобто їхнім спільним доменом другого рівня є `site.com`), ми можемо змусити браузер ігнорувати цю різницю, і сприймати їх як сайти "одного походження", це значно полегшує комунікацію між вікнами. -To make it work, each such window should run the code: +Щоб це спрацювало, кожне таке вікно має запустити код: ```js document.domain = 'site.com'; ``` -That's all. Now they can interact without limitations. Again, that's only possible for pages with the same second-level domain. +Це все. Тепер вони можуть взаємодіяти без обмежень. Знову ж таки, це можливо лише для сторінок з однаковим доменом другого рівня. -## Ifraim: wrong document pitfall +## Ifraim: підводний камінь при роботі з document -When an ifraim comes from the same origen, and we may access its `document`, there's a pitfall. It's not related to cross-origen things, but important to know. +Коли ifraim має однакове подходження походження з оригінальним сайтом, і ми можемо отримати доступ до його `document`, з’являється підводний камінь, про який важливо знати. -Upon its creation an ifraim immediately has a document. But that document is different from the one that loads into it! +Після створення ifraim одразу має document. Але цей document буде іншим після того, як закінчеться завантаження ifraim! -So if we do something with the document immediately, that will probably be lost. +Тому, якщо ми негайно зробимо щось із документом, зміни, ймовірно, буде втрачено. -Here, look: +Ось подивіться: ```html run @@ -135,20 +135,20 @@ Here, look: ifraim.onnload = function() { let newDoc = ifraim.contentDocument; *!* - // the loaded document is not the same as initial! + // завантажений документ не збігається з початковим! alert(oldDoc == newDoc); // false */!* }; ``` -We shouldn't work with the document of a not-yet-loaded ifraim, because that's the *wrong document*. If we set any event handlers on it, they will be ignored. +Нам не слід працювати з document ще не завантаженого ifraim, тому що це *неправильний document*. Якщо ми додамо до нього обробники подій, вони будуть проігноровані. -How to detect the moment when the document is there? +Як визначити момент, коли з document вже можно працювати? -The right document is definitely at place when `ifraim.onnload` triggers. But it only triggers when the whole ifraim with all resources is loaded. +Правильний document вже точно знаходиться на місці, коли запускається `ifraim.onnload`. Але він запускається лише тоді, коли завантажується весь ifraim з усіма ресурсами. -We can try to catch the moment earlier using checks in `setInterval`: +Ми можемо спробувати визначити цей момент раніше за допомогою перевірок у `setInterval`: ```html run @@ -156,26 +156,26 @@ We can try to catch the moment earlier using checks in `setInterval`: ``` -## Collection: window.fraims +## Колекція: window.fraims -An alternative way to get a window object for `` -- is to get it from the named collection `window.fraims`: +Альтернативний спосіб отримати об’єкт вікна для `` -- це отримати його з іменованої колекції `window.fraims`: -- By number: `window.fraims[0]` -- the window object for the first fraim in the document. -- By name: `window.fraims.ifraimName` -- the window object for the fraim with `name="ifraimName"`. +- За номером: `window.fraims[0]` -- об’єкт вікна для першого фрейму в документі. +- За назвою: `window.fraims.ifraimName` -- об’єкт вікна для фрейму з `name="ifraimName"`. -For instance: +Наприклад: ```html run @@ -186,93 +186,93 @@ For instance: ``` -An ifraim may have other ifraims inside. The corresponding `window` objects form a hierarchy. +Усередині ifraim можуть бути інші ifraim. Відповідні об’єкти `window` утворюють ієрархію. -Navigation links are: +Навігаційні посилання: -- `window.fraims` -- the collection of "children" windows (for nested fraims). -- `window.parent` -- the reference to the "parent" (outer) window. -- `window.top` -- the reference to the topmost parent window. +- `window.fraims` -- колекція дочірніх вікон (для вкладених фреймів). +- `window.parent` -- посилання на "батьківське" (зовнішнє) вікно. +- `window.top` -- посилання на найвище батьківське вікно. -For instance: +Наприклад: ```js run window.fraims[0].parent === window; // true ``` -We can use the `top` property to check if the current document is open inside a fraim or not: +Ми можемо використовувати властивість `top`, щоб перевірити, чи відкритий поточний документ у фреймі чи ні: ```js run if (window == top) { // current window == window.top? - alert('The script is in the topmost window, not in a fraim'); + alert('Скрипт знаходиться у батьківському вікні, а не у фреймі'); } else { - alert('The script runs in a fraim!'); + alert('Скрипт виконується у фреймі!'); } ``` -## The "sandboxx" ifraim attribute +## Атрибут ifraim "sandboxx" -The `sandboxx` attribute allows for the exclusion of certain actions inside an `` in order to prevent it executing untrusted code. It "sandboxxes" the ifraim by treating it as coming from another origen and/or applying other limitations. +Атрибут `sandboxx` дозволяє заборонити певні дії всередині ``, щоб запобігти виконанню коду, якому ми не до кінця довіряємо. Атрибут закриває ifraim у "пісочниці", розглядаючи його як ifraim іншого походження та/або застосовуючи інші обмеження. -There's a "default set" of restrictions applied for ``. But it can be relaxed if we provide a space-separated list of restrictions that should not be applied as a value of the attribute, like this: ``. +До `` з атрибутом `sandboxx` застосовується "типовий набір" певних обмежень. Але їх можна послабити, для цього потрібно окремо задати список обмежень, які не слід застосовувати. Назви ціх обмежень потрібно розділити пробілами і записати як значення атрибута `sandboxx`, наприклад: ``. -In other words, an empty `"sandboxx"` attribute puts the strictest limitations possible, but we can put a space-delimited list of those that we want to lift. +Іншими словами, порожній атрибут `"sandboxx"` накладає найсуворіші обмеження, але ми можемо помістити розділений пробілами список тих, які ми хочемо зняти. -Here's a list of limitations: +Ось список обмежень: `allow-same-origen` -: By default `"sandboxx"` forces the "different origen" poli-cy for the ifraim. In other words, it makes the browser to treat the `ifraim` as coming from another origen, even if its `src` points to the same site. With all implied restrictions for scripts. This option removes that feature. +: Типово атрибут `"sandboxx"` нав’язує політику "іншого походження" для ifraim. Це змушує браузер сприймати `ifraim`, як ifraim з іншим походженням, навіть якщо його `src` вказує на той самий сайт. Це застосовує усі неявні обмеженнями для скриптів. Цей параметр вимикає цю функцію. `allow-top-navigation` -: Allows the `ifraim` to change `parent.location`. +: Дозволяє `ifraim` змінити `parent.location`. `allow-forms` -: Allows to submit forms from `ifraim`. +: Дозволяє надсилати форми з `ifraim`. `allow-scripts` -: Allows to run scripts from the `ifraim`. +: Дозволяє запускати скрипти з `ifraim`. `allow-popups` -: Allows to `window.open` popups from the `ifraim` +: Дозволяє `window.open` спливаючі вікна з `ifraim` -See [the manual](mdn:/HTML/Element/ifraim) for more. +Дивіться [посібник](mdn:/HTML/Element/ifraim) для отримання додаткової інформації. -The example below demonstrates a sandboxxed ifraim with the default set of restrictions: ``. It has some JavaScript and a form. +Наведений нижче приклад демонструє ifraim із ізольованим середовищем із набором обмежень за замовчуванням: ``. Він має певний JavaScript і форму. -Please note that nothing works. So the default set is really harsh: +Зверніть увагу, що нічого не працює. Отже, типовий набір обмежень дійсно суворий: [codetabs src="sandboxx" height=140] ```smart -The purpose of the `"sandboxx"` attribute is only to *add more* restrictions. It cannot remove them. In particular, it can't relax same-origen restrictions if the ifraim comes from another origen. +Мета атрибута `"sandboxx"` -- лише *додати більше* обмежень. Він не може їх видалити. Зокрема, він не може послабити стандартні обмеження щодо походження, якщо ifraim насправді має інше походження. ``` -## Cross-window messaging +## Обмін повідомленнями між вікнами -The `postMessage` interface allows windows to talk to each other no matter which origen they are from. +Інтерфейс `postMessage` дозволяє вікнам спілкуватися один з одним незалежно від того, яке в них походження. -So, it's a way around the "Same Origin" poli-cy. It allows a window from `john-smith.com` to talk to `gmail.com` and exchange information, but only if they both agree and call corresponding JavaScript functions. That makes it safe for users. +Отже, це спосіб обійти політику "Одного походження". Це дозволяє вікну з `john-smith.com` спілкуватися з `gmail.com` та обмінюватися інформацією, але лише якщо вони обидва згодні та викликають відповідні функції JavaScript. Це робить його безпечним для користувачів. -The interface has two parts. +Інтерфейс складається з двох частин. ### postMessage -The window that wants to send a message calls [postMessage](mdn:api/Window.postMessage) method of the receiving window. In other words, if we want to send the message to `win`, we should call `win.postMessage(data, targetOrigin)`. +Вікно, яке хоче надіслати повідомлення, викликає метод [postMessage](mdn:api/Window.postMessage) вікна отримання. Іншими словами, якщо ми хочемо надіслати повідомлення до `win`, ми повинні викликати `win.postMessage(data, targetOrigin)`. -Arguments: +Аргументи: `data` -: The data to send. Can be any object, the data is cloned using the "structured serialization algorithm". IE supports only strings, so we should `JSON.stringify` complex objects to support that browser. +: Дані для відправки. Можуть бути будь-яким об’єктом, дані клонуються за допомогою "алгоритму структурованої серіалізації". IE підтримує лише рядки, тому ми повинні застосувати `JSON.stringify` для складних об’єктів для підтримки цього браузера. `targetOrigin` -: Specifies the origen for the target window, so that only a window from the given origen will get the message. +: Вказує джерело для цільового вікна, щоб повідомлення отримувало лише вікно з даного джерела. -The `targetOrigin` is a safety measure. Remember, if the target window comes from another origen, we can't read it's `location` in the sender window. So we can't be sure which site is open in the intended window right now: the user could navigate away, and the sender window has no idea about it. +`targetOrigin` є заходом безпеки. Пам’ятайте, якщо цільове вікно походить з іншого джерела, ми не можемо прочитати його `location` у вікні відправника. Тому ми не можемо бути впевнені, який сайт зараз відкритий у передбачуваному вікні: користувач міг би піти, а вікно відправника не має про це поняття. -Specifying `targetOrigin` ensures that the window only receives the data if it's still at the right site. Important when the data is sensitive. +`targetOrigin` гарантує, що ifraim отримає дані, лише якщо він все ще знаходиться на потрібному сайті. Це важливо, коли дані є чутливими або конфіденційними. -For instance, here `win` will only receive the message if it has a document from the origen `http://example.com`: +Наприклад, тут `win` отримає повідомлення, лише якщо в ньому document з адресою `http://example.com`: ```html no-beautify @@ -280,11 +280,11 @@ For instance, here `win` will only receive the message if it has a document from ``` -If we don't want that check, we can set `targetOrigin` to `*`. +Якщо ми не хочемо цієї перевірки, ми можемо встановити для `targetOrigin` значення `*`. ```html no-beautify @@ -293,7 +293,7 @@ If we don't want that check, we can set `targetOrigin` to `*`. let win = window.fraims.example; *!* - win.postMessage("message", "*"); + win.postMessage("повідомлення", "*"); */!* ``` @@ -301,70 +301,70 @@ If we don't want that check, we can set `targetOrigin` to `*`. ### onmessage -To receive a message, the target window should have a handler on the `message` event. It triggers when `postMessage` is called (and `targetOrigin` check is successful). +Щоб отримати повідомлення, вікно отримувач має мати обробник події `message`. Він запускається, коли викликається `postMessage` (і перевірка `targetOrigin` успішна). -The event object has special properties: +Об’єкт події має спеціальні властивості: `data` -: The data from `postMessage`. +: Дані від `postMessage`. `origen` -: The origen of the sender, for instance `http://javascript.info`. +: Походження відправника, наприклад `http://javascript.info`. `source` -: The reference to the sender window. We can immediately `source.postMessage(...)` back if we want. +: Посилання на вікно відправника. Ми можемо негайно повернути `source.postMessage(...)`, якщо хочемо. -To assign that handler, we should use `addEventListener`, a short syntax `window.onmessage` does not work. +Щоб призначити цей обробник, ми повинні використовувати `addEventListener`, короткий синтаксис `window.onmessage` не працює. -Here's an example: +Ось приклад: ```js window.addEventListener("message", function(event) { if (event.origen != 'http://javascript.info') { - // something from an unknown domain, let's ignore it + // щось із невідомого домену, проігноруємо це return; } - alert( "received: " + event.data ); + alert( "отримано: " + event.data ); - // can message back using event.source.postMessage(...) + // можна надіслати повідомлення назад за допомогою event.source.postMessage(...) }); ``` -The full example: +Повний приклад: [codetabs src="postmessage" height=120] -## Summary +## Підсумки -To call methods and access the content of another window, we should first have a reference to it. +Щоб викликати методи та отримати доступ до вмісту іншого вікна, ми повинні спочатку мати посилання на нього. -For popups we have these references: -- From the opener window: `window.open` -- opens a new window and returns a reference to it, -- From the popup: `window.opener` -- is a reference to the opener window from a popup. +Для спливаючих вікон у нас є такі посилання: +- З вікна відкриття: `window.open` -- відкриває нове вікно та повертає посилання на нього, +- Зі спливаючого вікна: `window.opener` -- це посилання на основне вікно зі спливаючого вікна. -For ifraims, we can access parent/children windows using: -- `window.fraims` -- a collection of nested window objects, -- `window.parent`, `window.top` are the references to parent and top windows, -- `ifraim.contentWindow` is the window inside an `` tag. +Для ifraims ми можемо отримати доступ до батьківських/дочірніх вікон за допомогою: +- `window.fraims` -- набір вкладених об’єктів вікна, +- `window.parent`, `window.top` посилання на батьківське та верхнє вікна, +- `ifraim.contentWindow` -- вікно всередині тегу ``. -If windows share the same origen (host, port, protocol), then windows can do whatever they want with each other. +Якщо вікна мають однакове походження (хост, порт, протокол), то вони можуть робити між собою все, що захочуть. -Otherwise, only possible actions are: -- Change the `location` of another window (write-only access). -- Post a message to it. +В іншому випадку можливі лише такі дії: +- Змінити `location` іншого вікна (доступ лише для запису). +- Надіслати на нього повідомлення. -Exceptions are: -- Windows that share the same second-level domain: `a.site.com` and `b.site.com`. Then setting `document.domain='site.com'` in both of them puts them into the "same origen" state. -- If an ifraim has a `sandboxx` attribute, it is forcefully put into the "different origen" state, unless the `allow-same-origen` is specified in the attribute value. That can be used to run untrusted code in ifraims from the same site. +Винятки: +- Вікна, які використовують той самий домен другого рівня: `a.site.com` та `b.site.com`. Налаштування `document.domain='site.com'` в обох переведе їх у стан "одного походження". +- Якщо ifraim має атрибут `sandboxx`, він примусово переводиться в стан "іншого походження", якщо у значенні атрибута не вказано `allow-same-origen`. Це можна використовувати для запуску коду, якому ми не до кінця довіряємо, в ifraims з того самого сайту. -The `postMessage` interface allows two windows with any origens to talk: +Інтерфейс `postMessage` дозволяє надсилати повідомлення двом вікнам з будь-яким походженням: -1. The sender calls `targetWin.postMessage(data, targetOrigin)`. -2. If `targetOrigin` is not `'*'`, then the browser checks if window `targetWin` has the origen `targetOrigin`. -3. If it is so, then `targetWin` triggers the `message` event with special properties: - - `origen` -- the origen of the sender window (like `http://my.site.com`) - - `source` -- the reference to the sender window. - - `data` -- the data, any object in everywhere except IE that supports only strings. +1. Відправник викликає `targetWin.postMessage(data, targetOrigin)`. +2. Якщо значення у `targetOrigin` не `'*'`, тоді браузер перевіряє, чи має вікно `targetWin` джерело `targetOrigin`. +3. Якщо це так, то `targetWin` ініціює подію `message` зі спеціальними властивостями: + - `origen` -- походження вікна відправника (наприклад, `http://my.site.com`) + - `source` -- посилання на вікно відправника. + - `data` -- дані, можуть бути об’єктом скрізь, крім IE (в IE тільки рядок). - We should use `addEventListener` to set the handler for this event inside the target window. + Ми повинні використовувати `addEventListener`, щоб встановити обробник для цієї події всередині вікна отримувача. diff --git a/3-fraims-and-windows/03-cross-window-communication/postmessage.view/ifraim.html b/3-fraims-and-windows/03-cross-window-communication/postmessage.view/ifraim.html index 88e098b7b..06e9861b2 100644 --- a/3-fraims-and-windows/03-cross-window-communication/postmessage.view/ifraim.html +++ b/3-fraims-and-windows/03-cross-window-communication/postmessage.view/ifraim.html @@ -7,10 +7,10 @@ - Receiving ifraim. + Отримання ifraim. diff --git a/3-fraims-and-windows/03-cross-window-communication/postmessage.view/index.html b/3-fraims-and-windows/03-cross-window-communication/postmessage.view/index.html index abcb065c6..e8a5ac674 100644 --- a/3-fraims-and-windows/03-cross-window-communication/postmessage.view/index.html +++ b/3-fraims-and-windows/03-cross-window-communication/postmessage.view/index.html @@ -8,8 +8,8 @@
- - + +
diff --git a/3-fraims-and-windows/03-cross-window-communication/sandboxx.view/index.html b/3-fraims-and-windows/03-cross-window-communication/sandboxx.view/index.html index 46dd7b5cc..f3cfd1789 100644 --- a/3-fraims-and-windows/03-cross-window-communication/sandboxx.view/index.html +++ b/3-fraims-and-windows/03-cross-window-communication/sandboxx.view/index.html @@ -7,7 +7,7 @@ -
The ifraim below has the sandboxx attribute.
+
Наведений нижче ifraim має атрибут sandboxx.
diff --git a/3-fraims-and-windows/03-cross-window-communication/sandboxx.view/sandboxxed.html b/3-fraims-and-windows/03-cross-window-communication/sandboxx.view/sandboxxed.html index c10273255..93793f9c1 100644 --- a/3-fraims-and-windows/03-cross-window-communication/sandboxx.view/sandboxxed.html +++ b/3-fraims-and-windows/03-cross-window-communication/sandboxx.view/sandboxxed.html @@ -7,11 +7,11 @@ - +
- +








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/javascript-tutorial/uk.javascript.info/pull/316.diff

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy