Spec-Zone.ru › Python 3.5

http.cookiejar — Обработка файлов cookie для HTTP-клиентов

Исходный код: Lib/http/cookiejar.py

Модуль http.cookiejar определяет классы для автоматической обработки HTTP-файлов cookie. Он полезен для доступа к веб-сайтам, которые требуют установки небольших фрагментов данных — файлов cookie — на клиентском компьютере с помощью HTTP-ответа веб-сервера, а затем возвращают их серверу в последующих HTTP-запросах.

Обрабатываются как стандартный протокол файлов cookie Netscape, так и протокол, определенный в RFC 2965. Обработка RFC 2965 по умолчанию отключена. Файлы cookie RFC 2109 анализируются как файлы cookie Netscape и затем обрабатываются как файлы cookie Netscape или RFC 2965 в соответствии с действующей «политикой». Обратите внимание, что подавляющее большинство файлов cookie в Интернете — это файлы cookie Netscape. http.cookiejar пытается следовать фактическому протоколу файлов cookie Netscape (который существенно отличается от протокола, описанного в оригинальной спецификации Netscape), включая учет max-age и port атрибутов файлов cookie, введенных в RFC 2965.

Примечание

Различные именованные параметры, встречающиеся в заголовках Set-Cookie и Set-Cookie2 (например, domain и expires) обычно называются атрибутами. Чтобы отличить их от атрибутов Python, в документации этого модуля используется термин атрибут файла cookie вместо этого.

Модуль определяет следующую исключительную ситуацию:

exception http.cookiejar.LoadError

Экземпляры FileCookieJar генерируют это исключение при неудачной загрузке файлов cookie из файла. LoadError является подклассом OSError.

Изменено в версии 3.3: LoadError был переведен в подкласс OSError вместо IOError.

Предоставлены следующие классы:

class http.cookiejar.CookieJar(policy=None)

policy — объект, реализующий интерфейс CookiePolicy.

Класс CookieJar хранит HTTP-файлы cookie. Он извлекает файлы cookie из HTTP-запросов и возвращает их в HTTP-ответах. Экземпляры CookieJar автоматически удаляют истекшие файлы cookie при необходимости. Подклассы также отвечают за хранение и извлечение файлов cookie из файла или базы данных.

class http.cookiejar.FileCookieJar(filename, delayload=None, policy=None)

policy — объект, реализующий интерфейс CookiePolicy. Для других аргументов см. документацию по соответствующим атрибутам.

Класс CookieJar, который может загружать файлы cookie из файла и, возможно, сохранять их в файл на диске. Файлы cookie НЕ загружаются из указанного файла до тех пор, пока не будет вызван метод load() или revert(). Подклассы этого класса описаны в разделе Подклассы FileCookieJar и взаимодействие с веб-браузерами.

class http.cookiejar.CookiePolicy

Этот класс отвечает за решение, нужно ли принимать каждый файл cookie от сервера или возвращать его на сервер.

class http.cookiejar.DefaultCookiePolicy(blocked_domains=None, allowed_domains=None, netscape=True, rfc2965=False, rfc2109_as_netscape=None, hide_cookie2=False, strict_domain=False, strict_rfc2965_unverifiable=True, strict_ns_unverifiable=False, strict_ns_domain=DefaultCookiePolicy.DomainLiberal, strict_ns_set_initial_dollar=False, strict_ns_set_path=False)

Аргументы конструктора должны передаваться только как ключевые аргументы. blocked_domains — последовательность имен доменов, для которых мы никогда не принимаем и не возвращаем файлы cookie. allowed_domains, если не None, — последовательность доменов, для которых мы принимаем и возвращаем файлы cookie. Для всех других аргументов см. документацию по объектам CookiePolicy и DefaultCookiePolicy.

DefaultCookiePolicy реализует стандартные правила приема/отклонения для файлов cookie Netscape и RFC 2965. По умолчанию файлы cookie RFC 2109 (то есть файлы cookie, полученные в заголовке Set-Cookie с атрибутом версии файла cookie равным 1) обрабатываются в соответствии с правилами RFC 2965. Однако, если обработка RFC 2965 отключена или rfc2109_as_netscape равно True, экземпляр CookieJar преобразует файлы cookie RFC 2109 в файлы cookie Netscape, установив атрибут version экземпляра Cookie в 0. DefaultCookiePolicy также предоставляет некоторые параметры для тонкой настройки политики.

class http.cookiejar.Cookie

Этот класс представляет файлы cookie Netscape, RFC 2109 и RFC 2965. Не ожидается, что пользователи http.cookiejar будут создавать собственные экземпляры Cookie. Вместо этого, при необходимости вызовите make_cookies() на экземпляре CookieJar.

См. также

Module urllib.request
Открытие URL-адресов с автоматической обработкой файлов cookie.
Module http.cookies
Классы HTTP-файлов cookie, в основном полезные для кода на стороне сервера. Модули http.cookiejar и http.cookies не зависят друг от друга.
https://curl.haxx.se/rfc/cookie_spec.html
Спецификация исходного протокола файлов cookie Netscape. Хотя это по-прежнему доминирующий протокол, протокол «файлов cookie Netscape», реализованный всеми основными браузерами (и http.cookiejar), лишь отдаленно напоминает протокол, набросанный в cookie_spec.html.
RFC 2109 - Механизм управления состоянием HTTP
Устарел RFC 2965. Использует Set-Cookie с версией=1.
RFC 2965 - Механизм управления состоянием HTTP
Протокол Netscape с исправленными ошибками. Использует Set-Cookie2 вместо Set-Cookie. Не широко используется.
http://kristol.org/cookie/errata.html
Незавершенные исправления RFC 2965.

RFC 2964 - Использование управления состоянием HTTP

1. Объекты CookieJar и FileCookieJar

CookieJar объекты поддерживают протокол итератор для итерирования по содержимым объектам Cookie.

CookieJar имеет следующие методы:

CookieJar.add_cookie_header(request)

Добавить правильный заголовок Cookie в запрос.

Если политика разрешает (т.е. атрибуты rfc2965 и hide_cookie2 экземпляра CookieJar’s CookiePolicy соответственно равны true и false), заголовок Cookie2 также добавляется при необходимости.

Объект запрос (обычно экземпляр urllib.request..Request ) должен поддерживать методы get_full_url(), get_host(), get_type(), unverifiable(), has_header(), get_header(), header_items(), add_unredirected_header() и атрибут origin_req_host, как описано в urllib.request.

Изменено в версии 3.3: Объект запрос требует атрибута origin_req_host. Зависимость от устаревшего метода get_origin_req_host() удалена.

CookieJar.extract_cookies(response, request)

Извлечь куки из HTTP-ответа и сохранить их в CookieJar, если это разрешено политикой.

CookieJar будет искать допустимые заголовки Set-Cookie и Set-Cookie2 в аргументе ответ и сохранять куки соответствующим образом (в соответствии с одобрением метода CookiePolicy.set_ok()).

Объект ответ (обычно результат вызова urllib.request.urlopen() или аналогичного) должен поддерживать метод info(), который возвращает экземпляр email.message.Message.

Объект запрос (обычно экземпляр urllib.request.Request) должен поддерживать методы get_full_url(), get_host(), unverifiable() и атрибут origin_req_host, как документировано в urllib.request. Запрос используется для установки значений по умолчанию для атрибутов куки, а также для проверки возможности установки куки.

Изменено в версии 3.3: Объект запрос требует атрибута origin_req_host. Зависимость от устаревшего метода get_origin_req_host() удалена.

CookieJar.set_policy(policy)

Установить используемый экземпляр CookiePolicy.

CookieJar.make_cookies(response, request)

Возвращает последовательность объектов Cookie, извлеченных из объекта ответ.

См. документацию для extract_cookies() для интерфейсов, необходимых для аргументов ответ и запрос.

CookieJar.set_cookie_if_ok(cookie, request)

Установить Cookie, если политика разрешает это сделать.

CookieJar.set_cookie(cookie)

Установить Cookie без проверки с политикой, чтобы определить, следует ли его устанавливать.

CookieJar.clear([domain[, path[, name]]])

Очистить некоторые куки.

Если вызвано без аргументов, очищаются все куки. Если задан один аргумент, удаляются только куки, принадлежащие этому домену. Если заданы два аргумента, удаляются куки, принадлежащие указанному домену и пути URL. Если заданы три аргумента, удаляется куки с указанным доменом, путем и именем.

Вызывает KeyError, если соответствующий куки не существует.

CookieJar.clear_session_cookies()

Удалить все сессионные куки.

Удаляет все содержащиеся куки, у которых атрибут discard имеет значение true (обычно потому, что у них отсутствовал атрибут куки max-age или expires, или был явно задан атрибут куки discard). Для интерактивных браузеров окончание сессии обычно соответствует закрытию окна браузера.

Обратите внимание, что метод save() в любом случае не сохранит сессионные куки, если вы не попросите об этом, передав аргумент ignore_discard со значением true.

FileCookieJar реализует следующие дополнительные методы:

FileCookieJar.save(filename=None, ignore_discard=False, ignore_expires=False)

Сохранить куки в файл.

Этот базовый класс вызывает NotImplementedError. Подклассы могут оставить этот метод нереализованным.

filename — имя файла, в который нужно сохранить куки. Если filename не указан, используется self.filename (по умолчанию значение, переданное в конструктор, если таковое имеется); если self.filename равно None, генерируется ValueError.

ignore_discard: сохранять даже куки, установленные на удаление. ignore_expires: сохранять даже куки, срок действия которых истек.

Файл перезаписывается, если он уже существует, тем самым удаляя все содержащиеся в нем куки. Сохраненные куки можно восстановить позже, используя методы load() или revert().

FileCookieJar.load(filename=None, ignore_discard=False, ignore_expires=False)

Загрузить куки из файла.

Старые куки сохраняются, если они не перезаписываются вновь загруженными.

Аргументы аналогичны аргументам метода save().

Имя файла должно быть в формате, понятном для класса, в противном случае будет вызвано исключение LoadError. Также может быть вызвано исключение OSError, например, если файл не существует.

Изменено в версии 3.3: Исключение IOError было заменено на алиас исключения OSError.

FileCookieJar.revert(filename=None, ignore_discard=False, ignore_expires=False)

Очистить все куки и перезагрузить куки из сохраненного файла.

Метод revert() может вызвать те же исключения, что и метод load(). При ошибке состояние объекта не изменяется.

FileCookieJar экземпляры имеют следующие публичные атрибуты:

FileCookieJar.filename

Имя файла по умолчанию, в котором хранятся куки. Этот атрибут можно изменять.

FileCookieJar.delayload

Если true, куки загружаются лениво из файла. Этот атрибут не следует изменять. Это только подсказка, так как это влияет только на производительность, а не на поведение (если куки в файле изменяются). Объект CookieJar может игнорировать его. Ни один из классов FileCookieJar, включенных в стандартную библиотеку, не загружает куки лениво.

2. Подклассы FileCookieJar и взаимодействие с веб-браузерами

Для чтения и записи предоставляются следующие подклассы CookieJar.

class http.cookiejar.MozillaCookieJar(filename, delayload=None, policy=None)

A FileCookieJar that can load from and save cookies to disk in the Mozilla cookies.txt file format (which is also used by the Lynx and Netscape browsers).

Примечание

This loses information about RFC 2965 cookies, and also about newer or non-standard cookie-attributes such as port.

Предупреждение

Перед сохранением сделайте резервную копию файлов cookie, если потеря/повреждение файлов cookie будет неудобна (есть некоторые тонкости, которые могут привести к небольшим изменениям в файле при многократной загрузке/сохранении).

Также обратите внимание, что файлы cookie, сохраненные во время работы Mozilla, будут перезаписаны Mozilla.

class http.cookiejar.LWPCookieJar(filename, delayload=None, policy=None)

A FileCookieJar that can load from and save cookies to disk in format compatible with the libwww-perl library’s Set-Cookie3 file format. This is convenient if you want to store cookies in a human-readable file.

3. Объекты CookiePolicy

Объекты, реализующие интерфейс CookiePolicy, имеют следующие методы:

CookiePolicy.set_ok(cookie, request)

Возвращает булево значение, указывающее, следует ли принимать файл cookie от сервера.

cookie — экземпляр Cookie. request — объект, реализующий интерфейс, определённый в документации для CookieJar.extract_cookies().

CookiePolicy.return_ok(cookie, request)

Возвращает булево значение, указывающее, следует ли возвращать файл cookie на сервер.

cookie — экземпляр Cookie. request — объект, реализующий интерфейс, определённый в документации для CookieJar.add_cookie_header().

CookiePolicy.domain_return_ok(domain, request)

Возвращает значение false, если файлы cookie не должны возвращаться, учитывая домен файла cookie.

Этот метод является оптимизацией. Он избавляет от необходимости проверки каждого файла cookie с определённым доменом (что может потребовать чтения многих файлов). Возврат значения true из domain_return_ok() и path_return_ok() оставляет всю работу для return_ok().

Если domain_return_ok() возвращает true для домена файла cookie, вызывается path_return_ok() для пути файла cookie. В противном случае path_return_ok() и return_ok() никогда не вызываются для этого домена файла cookie. Если path_return_ok() возвращает true, вызывается return_ok() с самим объектом Cookie для полной проверки. В противном случае return_ok() никогда не вызывается для этого пути файла cookie.

Обратите внимание, что domain_return_ok() вызывается для каждого домена cookie, а не только для домена request. Например, функция может быть вызвана как с ".example.com", так и с "www.example.com", если домен запроса равен "www.example.com". То же самое относится к path_return_ok().

Аргумент request соответствует документации для return_ok().

CookiePolicy.path_return_ok(path, request)

Возвращает значение false, если файлы cookie не должны возвращаться, учитывая путь файла cookie.

См. документацию для domain_return_ok().

Помимо реализации методов выше, реализации интерфейса CookiePolicy также должны предоставлять следующие атрибуты, указывающие, какие протоколы должны использоваться и как. Все эти атрибуты могут быть присвоены.

CookiePolicy.netscape

Реализовать протокол Netscape.

CookiePolicy.rfc2965

Реализовать протокол RFC 2965.

CookiePolicy.hide_cookie2

Не добавлять заголовок Cookie2 в запросы (наличие этого заголовка указывает серверу, что мы понимаем файлы cookie RFC 2965).

Самый полезный способ определения класса CookiePolicy — это наследование от DefaultCookiePolicy и переопределение некоторых или всех методов выше. Сам CookiePolicy может использоваться в качестве «нулевой политики», чтобы разрешить установку и получение любых файлов cookie (вероятно, это не будет полезно).

4. Объекты DefaultCookiePolicy

Реализует стандартные правила для принятия и возвращения файлов cookie.

Обрабатываются как файлы cookie RFC 2965, так и Netscape. Обработка RFC 2965 по умолчанию выключена.

Самый простой способ предоставить собственную политику — переопределить этот класс и вызвать его методы в ваших переопределенных реализациях перед добавлением собственных дополнительных проверок:

import http.cookiejar
class MyCookiePolicy(http.cookiejar.DefaultCookiePolicy):
    def set_ok(self, cookie, request):
        if not http.cookiejar.DefaultCookiePolicy.set_ok(self, cookie, request):
            return False
        if i_dont_want_to_store_this_cookie(cookie):
            return False
        return True

В дополнение к функциям, необходимым для реализации интерфейса CookiePolicy, этот класс позволяет блокировать и разрешать домены для установки и получения файлов cookie. Также есть некоторые переключатели строгости, позволяющие немного ужесточить довольно свободные правила протокола Netscape (за счёт блокирования некоторых безобидных файлов cookie).

Предоставляется чёрный и белый списки доменов (оба по умолчанию отключены). Только домены, не указанные в чёрном списке и присутствующие в белом списке (если белый список активен), участвуют в установке и возврате файлов cookie. Используйте аргумент конструктора blocked_domains и методы blocked_domains() и set_blocked_domains() (а также соответствующие аргумент и методы для allowed_domains). Если вы установили белый список, вы можете его отключить, установив его значение в None.

Домены в чёрном или белом списках, которые не начинаются с точки, должны точно совпадать с доменом файла cookie для сопоставления. Например, "example.com" соответствует записи чёрного списка "example.com", но "www.example.com" не соответствует. Домены, начинающиеся с точки, также сопоставляются с более конкретными доменами. Например, и "www.example.com", и "www.coyote.example.com" сопоставляются с ".example.com", (но "example.com" сам не сопоставляется). IP-адреса являются исключением и должны точно совпадать. Например, если blocked_domains содержит "192.168.1.2" и ".168.1.2", 192.168.1.2 заблокирован, но 193.168.1.2 — нет.

DefaultCookiePolicy реализует следующие дополнительные методы:

DefaultCookiePolicy.blocked_domains()

Возвращает последовательность заблокированных доменов (в виде кортежа).

DefaultCookiePolicy.set_blocked_domains(blocked_domains)

Устанавливает последовательность заблокированных доменов.

DefaultCookiePolicy.is_blocked(domain)

Возвращает значение true, если domain находится в чёрном списке для установки или получения файлов cookie.

DefaultCookiePolicy.allowed_domains()

Возвращает None или последовательность разрешённых доменов (в виде кортежа).

DefaultCookiePolicy.set_allowed_domains(allowed_domains)

Устанавливает последовательность разрешённых доменов или None.

DefaultCookiePolicy.is_not_allowed(domain)

Возвращает значение true, если domain не находится в белом списке для установки или получения файлов cookie.

DefaultCookiePolicy экземпляры имеют следующие атрибуты, которые инициализируются из аргументов конструктора с одинаковыми именами и к которым можно обращаться.

DefaultCookiePolicy.rfc2109_as_netscape

Если значение равно true, запрашивается понижение версии RFC 2109 куки (т.е. куки, полученные в заголовке Set-Cookie с атрибутом версии куки 1) до куки Netscape путём установки атрибута версии экземпляра Cookie в 0. Значение по умолчанию — None, в этом случае RFC 2109 куки понижаются в версии только если обработка RFC 2965 выключена. Таким образом, RFC 2109 куки понижаются по умолчанию.

Общие переключатели строгости:

DefaultCookiePolicy.strict_domain

Не разрешает сайтам устанавливать домены из двух компонентов с кодами стран в доменных именах верхнего уровня, таких как .co.uk, .gov.uk, .co.nz. и т.д. Это далеко не идеальный способ и не гарантирует работоспособность!

Переключатели строгости протокола RFC 2965:

DefaultCookiePolicy.strict_rfc2965_unverifiable

Следует правилам RFC 2965 для непроверяемых транзакций (обычно, непроверяемой является транзакция, полученная в результате перенаправления или запроса изображения, размещённого на другом сайте). Если значение ложь, куки никогда не блокируются на основе проверяемости.

Переключатели строгости протокола Netscape:

DefaultCookiePolicy.strict_ns_unverifiable

Применяет правила RFC 2965 для непроверяемых транзакций даже для куки Netscape.

DefaultCookiePolicy.strict_ns_domain

Флаги, определяющие, насколько строго следует соблюдать правила сопоставления доменов для куки Netscape. Допустимые значения приведены ниже.

DefaultCookiePolicy.strict_ns_set_initial_dollar

Игнорирует куки в заголовках Set-Cookie, имена которых начинаются с '$'.

DefaultCookiePolicy.strict_ns_set_path

Не разрешает установку куки, путь которых не соответствует запросу URI.

strict_ns_domain представляет собой набор флагов. Его значение строится путём объединения побитового ИЛИ (например, DomainStrictNoDots|DomainStrictNonDomain означает, что оба флага установлены).

DefaultCookiePolicy.DomainStrictNoDots

При установке куки, префикс хоста не должен содержать точку (например, www.foo.bar.com не может установить куки для .bar.com, так как www.foo содержит точку).

DefaultCookiePolicy.DomainStrictNonDomain

Куки, которые не указали явно атрибут куки domain, могут быть возвращены только в домен, равный домену, установившему куки (например, spam.example.com не получит куки из example.com, у которых отсутствовал атрибут куки domain).

DefaultCookiePolicy.DomainRFC2965Match

Требует полного соответствия домена по RFC 2965 при установке куки.

Следующие атрибуты предоставлены для удобства и представляют собой наиболее полезные комбинации вышеперечисленных флагов:

DefaultCookiePolicy.DomainLiberal

Эквивалентно 0 (т.е. все вышеперечисленные флаги строгости доменов Netscape отключены).

DefaultCookiePolicy.DomainStrict

Эквивалентно DomainStrictNoDots|DomainStrictNonDomain.

5. Объекты куки

Cookie экземпляры имеют атрибуты Python, примерно соответствующие стандартным атрибутам куки, указанным в различных стандартах куки. Соответствие не является однозначным, так как существуют сложные правила назначения значений по умолчанию, так как атрибуты куки max-age и expires содержат эквивалентную информацию, и потому что куки RFC 2109 могут быть «снижены» модулем http.cookiejar с версии 1 до версии 0 (куки Netscape).

Присвоение этих атрибутов не требуется, кроме редких случаев в методе CookiePolicy. Класс не проверяет внутреннюю согласованность, поэтому вы должны понимать, что делаете, если это делаете.

Cookie.version

Целое число или None. Куки Netscape имеют версию version 0. Куки RFC 2965 и RFC 2109 имеют атрибут куки version равный 1. Однако обратите внимание, что http.cookiejar может «понизить» куки RFC 2109 до куки Netscape, в этом случае version будет 0.

Cookie.name

Имя куки (строка).

Cookie.value

Значение куки (строка) или None.

Cookie.port

Строка, представляющая порт или набор портов (например, «80» или «80,8080»), или None.

Cookie.path

Путь куки (строка, например, '/acme/rocket_launchers').

Cookie.secure

True если куки должна возвращаться только по защищенному соединению.

Cookie.expires

Дата истечения срока действия в секундах с эпохи, или None. См. также метод is_expired().

Cookie.discard

True если это куки сессии.

Cookie.comment

Строковый комментарий от сервера, объясняющий назначение этой куки, или None.

Cookie.comment_url

URL, который ссылается на комментарий сервера, объясняющий назначение этой куки, или None.

Cookie.rfc2109

True если эта куки была получена как куки RFC 2109 (т.е. куки была получена в заголовке Set-Cookie, и значение атрибута версии куки в этом заголовке было 1). Этот атрибут предоставлен, поскольку модуль http.cookiejar может «понизить» куки RFC 2109 до куки Netscape, в этом случае version равен 0.

Cookie.port_specified

True если порт или набор портов были явно указаны сервером (в заголовке Set-Cookie / Set-Cookie2).

Cookie.domain_specified

True если домен был явно указан сервером.

Cookie.domain_initial_dot

True если домен, явно указанный сервером, начинался с точки ('.').

Куки могут иметь дополнительные нестандартные атрибуты куки. К ним можно получить доступ с помощью следующих методов:

Cookie.has_nonstandard_attr(name)

Возвращает true, если куки имеет указанный атрибут куки.

Cookie.get_nonstandard_attr(name, default=None)

Если у куки есть указанный атрибут куки, возвращает его значение. В противном случае возвращает default.

Cookie.set_nonstandard_attr(name, value)

Устанавливает значение указанного атрибута куки.

Класс Cookie также определяет следующий метод:

Cookie.is_expired(now=None)

True если куки прошла время, в которое сервер запросил ее истечения. Если now задан (в секундах с эпохи), возвращает, истекла ли куки в указанное время.

6. Примеры

Первый пример демонстрирует наиболее распространённое использование модуля http.cookiejar:

import http.cookiejar, urllib.request
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

Этот пример демонстрирует, как открыть URL-адрес, используя ваши cookie Netscape, Mozilla или Lynx (предполагается соглашение Unix/Netscape для местоположения файла cookie):

import os, http.cookiejar, urllib.request
cj = http.cookiejar.MozillaCookieJar()
cj.load(os.path.join(os.path.expanduser("~"), ".netscape", "cookies.txt"))
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

Следующий пример демонстрирует использование DefaultCookiePolicy. Включите cookie RFC 2965, будьте более строгими относительно доменов при установке и возврате cookie Netscape и заблокируйте некоторые домены от установки cookie или их возврата:

import urllib.request
from http.cookiejar import CookieJar, DefaultCookiePolicy
policy = DefaultCookiePolicy(
    rfc2965=True, strict_ns_domain=Policy.DomainStrict,
    blocked_domains=["ads.net", ".ads.net"])
cj = CookieJar(policy)
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.5/library/http.cookiejar.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API