449 lines
31 KiB
HTML
449 lines
31 KiB
HTML
<!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN>
|
||
<html>
|
||
<head>
|
||
<title>Safe Tcl</title>
|
||
</head>
|
||
|
||
<body>
|
||
<h1>Safe Tcl</h1>
|
||
|
||
<p>Механизм создания и управления безопасными
|
||
интерпретаторами.</p>
|
||
|
||
<h2><a name=СИНТАКСИС></a>СИНТАКСИС</h2>
|
||
|
||
<pre>
|
||
<a href=#safe::interpCreate>::safe::interpCreate</a> ?<em>slave</em>? ?<em>options</em>...?
|
||
<a href=#safe::interpInit>::safe::interpInit</a> <em>slave</em> ?<em>options</em>...?
|
||
<a href=#safe::interpConfigure>::safe::interpConfigure</a> <em>slave</em> ?<em>options</em>...?
|
||
<a href=#safe::interpDelete>::safe::interpDelete</a> <em>slave</em>
|
||
<a href=#safe::interpAddToAccessPath>::safe::interpAddToAccessPath</a> <em>slave</em> <em>directory</em>
|
||
<a href=#safe::interpFindInAccessPath>::safe::interpFindInAccessPath</a> <em>slave</em> <em>directory</em>
|
||
<a href=#safe::setLogCmd>::safe::setLogCmd</a> ?<em>cmd</em> <em>arg</em>...?
|
||
</pre>
|
||
|
||
<h2><a name=ОПИСАНИЕ></a>ОПИСАНИЕ</h2>
|
||
|
||
<p><strong>Safe Tcl</strong> - это механизм безопасного исполнения
|
||
ненадежных Tcl скриптов и предоставления этим скриптам
|
||
опосредованного доступа к потенциально опасным функциям.</p>
|
||
|
||
<p><strong>Safe Tcl</strong> служит для того, чтобы ненадежные скрипты не
|
||
смогли нарушить работу вызывающего их приложения: он
|
||
предотвращает покушения на несанкционированный доступ к
|
||
информации и нарушение целостности вызывающего этот скрипт
|
||
процесса.</p>
|
||
|
||
<p><strong>Safe Tcl</strong> позволяет интерпретатору-предку
|
||
создавать безопасные интерпретаторы с ограниченными
|
||
возможностями, в которых содержится набор предопределенных
|
||
синонимов для команд <a
|
||
href=source.html><strong>source</strong></a>, <a
|
||
href=load.html><strong>load</strong></a>, <a
|
||
href=file.html><strong>file</strong></a> и <a
|
||
href=exit.html><strong>exit</strong></a> и сохраняются
|
||
возможности автозагрузки команд и пакетов.</p>
|
||
|
||
<p>Безопасный интерпретатор не позволяет получить какую-либо
|
||
информацию о структуре файловой системы, поскольку для доступа к
|
||
файлам в безопасном интерпретаторе используются специальные
|
||
метки. Когда безопасный интерпретатор запрашивает доступ к
|
||
файлу, он использует метку как часть виртуального имени файла.
|
||
Родительский интерпретатор заменяет метку на реальное имя
|
||
каталога и выполняет требуемую операцию с файлом. С помощью
|
||
опций команд, описанных ниже, можно выбрать требуемый уровень
|
||
безопасности интерпретатора.</p>
|
||
|
||
<p>Все команды для работы с безопасными интерпретаторами
|
||
содержатся в пространстве имен safe. Команда <a href=
|
||
#safe::interpCreate><strong>::safe::interpCreate</strong></a>
|
||
создает безопасный интерпретатор. Возможные опции команды
|
||
описаны ниже, см. "<a href=#ОПЦИИ>Опции</a>".</p>
|
||
|
||
<p>Команда возвращает имя созданного интерпретатора. Команда <a
|
||
href=#safe::interpInit><strong>::safe::interpInit</strong></a>
|
||
аналогична, но ее первым аргументом должно быть имя
|
||
интерпретатора, созданного с помощью команды <a href=
|
||
interp.html><strong>interp</strong></a>. Команда <a href=
|
||
#safe::interpDelete><strong>::safe::interpDelete</strong></a>
|
||
удаляет интерпретатор, имя которого использовано в качестве
|
||
аргумента. Команда <a href=#safe::interpConfigure
|
||
><strong>::safe::interpConfigure</strong></a> позволяет задать
|
||
опции для безопасного интерпретатора или получить информацию
|
||
об заданных ранее опциях. Подробно опции описаны ниже
|
||
(см. "<a href=#ОПЦИИ>Опции</a>").</p>
|
||
|
||
<p>Для каждого безопасного интерпретатора, созданного с помощью
|
||
команды <a
|
||
href=#safe::interpCreate><strong>::safe::interpCreate</strong></a>
|
||
или инициированного с помощью команды <a
|
||
href=#safe::interpInit><strong>::safe::interpInit</strong></a>
|
||
в родительском интерпретаторе создается список доступных
|
||
каталогов - виртуальный путь. Каждый каталог в пути связывается
|
||
с реальным каталогом локальной файловой системы и с меткой,
|
||
доступной в безопасном интерпретаторе. В результате надежный
|
||
интерпретатор обходится без сведений о реальной файловой системе
|
||
на машине, на которой исполняется интерпретатор. Когда в
|
||
надежном интерпретаторе используется метка для доступа к
|
||
конкретному файлу (например, для выполнения команды <a
|
||
href=source.html><strong>source</strong></a> или <a
|
||
href=load.html><strong>load</strong></a>), метка заменяется в
|
||
родительском интерпретаторе на настоящее имя каталога и
|
||
необходимый файл ищется в файловой системе. Надежный
|
||
интерпретатор не получает сведений о реальном имени файла в
|
||
файловой системе. Для работы с виртуальными именами файлов
|
||
предусмотрены специальные команды. Команда <a href=
|
||
#safe::interpConfigure><strong>::safe::interpConfigure</strong></a>
|
||
позволяет задавать новый виртуальный путь для интерпретатора.
|
||
Команда <a href=#safe::interpAddToAccessPath
|
||
><strong>::safe::interpAddToAccessPath</strong></a> позволяет
|
||
добавлять каталоги к виртуальному пути указанного безопасного
|
||
интерпретатора. Команда <a href=#safe::interpFindInAccessPath
|
||
><strong>::safe::interpFindInAccessPath</strong></a> позволяет
|
||
найти каталог в виртуальном пути для безопасного интерпретатора
|
||
и получить его метку. Если каталог не найден, выдается сообщение
|
||
об ошибке.</p>
|
||
|
||
<p>Команда <a href=#safe::setLogCmd
|
||
><strong>::safe::setLogCommand</strong></a> позволяет задать
|
||
скрипт, который выполняется при каждом событии в безопасном
|
||
интерпретаторе. Этот скрипт вызывается с одним аргументом -
|
||
строкой, содержащей описание события.</p>
|
||
|
||
<h2><a name=СИНОНИМЫ></a>СИНОНИМЫ</h2>
|
||
|
||
<p>При создании безопасного интерпретатора в нем определяются
|
||
следующие команды - синонимы:</p>
|
||
|
||
<dl>
|
||
<dt><strong>source</strong> <em>fileName</em></dt>
|
||
|
||
<dd>Аналогична команде <a
|
||
href=source.html><strong>source</strong></a>, однако
|
||
позволяет работать только с файлами в виртуальном пути
|
||
безопасного интерпретатора. Имя файла <em>fileName</em> должно
|
||
содержать одну из меток, определенных для каталогов в
|
||
виртуальном пути. Допустимые имена файлов более подробно
|
||
описаны ниже (см. "<a
|
||
href=#БЕЗОПАСНОСТЬ>Безопасность</a>").
|
||
</dd>
|
||
|
||
<dt><strong>load</strong> <em>fileName</em></dt>
|
||
|
||
<dd>Требуемый файл (обычно, объектный файл из разделяемой
|
||
библиотеки) загружается в безопасный интерпретатор, если его
|
||
удается найти. Имя файла должно содержать одну из меток для
|
||
каталогов виртуального пути. Кроме того, разделяемый объектный
|
||
файл должен содержать безопасную точку входа. Подробности
|
||
приведены в описании команды
|
||
<a href=load.html><strong>load</strong></a>.
|
||
</dd>
|
||
|
||
<dt><strong>file</strong> ?<em>options</em>?</dt>
|
||
|
||
<dd>Синоним команды <a href=file.html><strong>file</strong></a> содержит
|
||
только безопасные подкоманды обычной команды <a href=
|
||
file.html><strong>file</strong></a>, а именно: <a
|
||
href=file.html#dirname><strong>dirname</strong></a>,
|
||
<a href=file.html#join><strong>join</strong></a>,
|
||
<a href=file.html#extension><strong>extension</strong></a>,
|
||
<a href=file.html#rootname><strong>root</strong></a>,
|
||
<a href=file.html#tail><strong>tail</strong></a>,
|
||
<a href=file.html#pathname><strong>pathname</strong></a> и
|
||
<a href=file.html#split><strong>split</strong></a>.
|
||
Назначение подкоманд приведено в
|
||
описании команды <a href=file.html><strong>file</strong></a>.
|
||
</dd>
|
||
|
||
<dt><strong>exit</strong></dt>
|
||
|
||
<dd>При выполнении команды безопасный
|
||
интерпретатор удаляется, вычисления в нем прерываются, но
|
||
родительский интерпретатор продолжает существовать.
|
||
</dd>
|
||
</dl>
|
||
|
||
<h2><a name=КОМАНДЫ></a>КОМАНДЫ</h2>
|
||
|
||
<p>В родительском интерпретаторе для работы с безопасными
|
||
интерпретаторами предусмотрены следующие команды:</p>
|
||
|
||
<dl>
|
||
<dt><a name=safe::interpCreate></a><strong>::safe::interpCreate</strong>
|
||
?<em>slave</em>? ?<em>options</em>...?</dt>
|
||
|
||
<dd>Создает безопасный интерпретатор, инициализирует в нем
|
||
команды - синонимы, описанные выше, и механизмы автозагрузки
|
||
команд и пакетов в соответствии с заданными опциями
|
||
(см. "<a href=#ОПЦИИ>Опции</a>"). Если аргумент
|
||
slave отсутствует, имя интерпретатора формируется
|
||
автоматически. Команда всегда возвращает имя созданного
|
||
интерпретатора.
|
||
</dd>
|
||
|
||
<dt><a name=safe::interpInit></a><strong>::safe::interpInit</strong>
|
||
<em>slave</em> ?<em>options</em>...?</dt>
|
||
|
||
<dd>Команда аналогична предыдущей, однако интерпретатор должен
|
||
быть уже создан каким-либо иным способом, например с помощью
|
||
команды <strong>::interp create-safe</strong>.
|
||
</dd>
|
||
|
||
<dt><a
|
||
name=safe::interpConfigure></a><strong>::safe::interpConfigure</strong>
|
||
<em>slave</em> ?<em>options</em>...?</dt>
|
||
|
||
<dd>Если опции не заданы, возвращает значения всех опций для
|
||
указанного безопасного интерпретатора. В противном случае
|
||
устанавливает указанные значения опций (подробнее см. "<a
|
||
href=#ОПЦИИ>Опции</a>").
|
||
</dd>
|
||
|
||
<dt><a name=safe::interpDelete>
|
||
</a><strong>::safe::interpDelete</strong> <em>slave</em></dt>
|
||
|
||
<dd>Удаляет безопасный интерпретатор и
|
||
вычищает в родительском интерпретаторе информацию о нем. Перед
|
||
удалением выполняется скрипт, заданный с помощью опции <strong>
|
||
-deletehook</strong>, если он был задан. К скрипту добавляется
|
||
дополнительный аргумент - имя удаляемого интерпретатора.
|
||
</dd>
|
||
|
||
<dt><a name=safe::interpFindInAccessPath>
|
||
</a><strong>::safe::interpFindInAccessPath</strong> <em>slave</em>
|
||
<em>directory</em></dt>
|
||
|
||
<dd> Команда возвращает метку, которую можно использовать в
|
||
безопасном интерпретаторе для каталога <em>directory</em>. Если
|
||
в виртуальном пути нет такого каталога, возвращается сообщение
|
||
об ошибке. Пример использования команды:
|
||
<pre>
|
||
###Создание безопасного интерпретатора
|
||
::safe::interpCreate qqq
|
||
###Присваивание переменной tk_library метки соответствующего каталога
|
||
qqq eval [list set tk_library [::safe::interpFindInAccessPath qqq ]]
|
||
###Выполнение команды source в безопасном интерпретаторе
|
||
qqq eval source $tk_library/msgbox.tcl
|
||
</pre>
|
||
</dd>
|
||
|
||
<dt><a name=safe::interpAddToAccessPath>
|
||
</a><strong>::safe::interpAddToAccessPath</strong> <em>slave</em>
|
||
<em>directory</em></dt>
|
||
|
||
<dd> Команда позволяет добавить к виртуальному пути указанного
|
||
безопасного интерпретатора каталог <em>directory</em>. Команда
|
||
возвращает значение метки для каталога <em> directory</em>. Если
|
||
каталог уже содержался в виртуальном пути, команда только
|
||
возвращает его метку и не добавляет его в виртуальный
|
||
путь. Пример использования команды (см. пример к предыдущей
|
||
команде):
|
||
<pre>
|
||
::safe::interpAddToAccessPath qqq
|
||
qqq eval source $my_lib/$my_file
|
||
</pre>
|
||
</dd>
|
||
|
||
<dt><a name=safe::setLogCmd>
|
||
</a><strong>::safe::setLogCmd</strong> ?<em>cmd</em> <em>arg</em>...?</dt>
|
||
|
||
<dd><p>Эта команда позволяет задать скрипт, который будет
|
||
выполняться при различных событиях, связанных с безопасными
|
||
интерпретаторами. Если команда вызвана без аргументов, то
|
||
она возвращает установленный ранее скрипт. Вызванная с одним
|
||
аргументом - пустой строкой - команда удаляет установленный
|
||
ранее скрипт и отменяет процесс журнализации. Установленный
|
||
скрипт выполняется с одним дополнительным аргументом -
|
||
строкой, описывающей событие. Основное назначение команды -
|
||
использование при отладке скриптов, выполняемых в безопасных
|
||
интерпретаторах. Используя ее, вы сможете получить полную
|
||
информацию об ошибке, в то время как безопасный
|
||
интерпретатор возвращает только обобщенное сообщение об
|
||
ошибке (это позволяет избежать разглашения в сообщении об
|
||
ошибке конфиденциальной информации, например, о реальных
|
||
именах файлов). Пример использования:</p>
|
||
<pre>
|
||
::safe::setLogCmd puts stderr
|
||
</pre>
|
||
<p>Ниже приведен журнал сессии, в которой безопасный
|
||
интерпретатор пытается прочитать файл, который не найден в
|
||
виртуальном пути. Обратите внимание, что сам безопасный
|
||
интерпретатор получает при этом только сообщение о том, что
|
||
файл не найден:</p>
|
||
<pre>
|
||
NOTICE for slave interp10 : Created
|
||
NOTICE for slave interp10 : Setting accessPath=(/foo/bar)
|
||
staticsok=1 nestedok=0 deletehook=()
|
||
NOTICE for slave interp10 : auto_path in interp10 has been
|
||
set to {(:0:)}
|
||
ERROR for slave interp10 : /foo/bar/init.tcl: no such file
|
||
or directory
|
||
</pre>
|
||
</dd>
|
||
</dl>
|
||
|
||
<h2><a name=ОПЦИИ></a>ОПЦИИ</h2>
|
||
|
||
<p>Для команд <strong>::safe::interpCreate</strong>,
|
||
<strong>::safe::interpInit</strong>, и <strong>:safe::interpConfigure</strong>
|
||
определены перечисленные ниже опции. Имена опций могут быть
|
||
сокращены до минимальных однозначных имен. Имена опций не
|
||
чувствительны к регистру, в котором они набраны.</p>
|
||
|
||
<dl>
|
||
<dt><strong>-accessPath</strong> ?<em>directoryList</em>?</dt>
|
||
|
||
<dd>Опция задает список каталогов, к которым может иметь доступ
|
||
безопасный интерпретатор, и возвращает метки соответствующих
|
||
каталогов. Если список не задан или если он пуст, безопасный
|
||
интерпретатор получает доступ к каталогам, используемым для
|
||
автозагрузки в родительском интерпретаторе. Подробнее
|
||
см. "<a href=#БЕЗОПАСНОСТЬ>Безопасность</a>".</dd>
|
||
|
||
<dt><strong>-noStatics</strong></dt>
|
||
|
||
<dd>Если эта опция задана, то не допускается загрузка статически
|
||
связанных пакетов (как <strong>load {} Tk</strong>). По умолчанию
|
||
загрузка таких пакетов разрешена.
|
||
</dd>
|
||
|
||
<dt><strong>-nestedLoadOk</strong></dt>
|
||
|
||
<dd>Если эта опция задана, безопасный интерпретатор может
|
||
загружать пакеты в собственные подинтерпретаторы. По умолчанию
|
||
загрузка пакетов в подинтерпретаторы запрещена.
|
||
</dd>
|
||
|
||
<dt><strong>-deleteHook</strong> ?<em>script</em>?</dt>
|
||
|
||
<dd>Если скрипт задан, он выполняется в родительском
|
||
интерпретаторе (с дополнительным аргументом - именем
|
||
безопасного интерпретатора) перед удалением безопасного
|
||
интерпретатора. Если скрипт не задан, то удаляется заданный
|
||
ранее скрипт (если такой был) и никаких дополнительных
|
||
действий перед удалением безопасного интерпретатора не
|
||
производится. По умолчанию скрипт не задан.</dd>
|
||
</dl>
|
||
|
||
<h2><a name=БЕЗОПАСНОСТЬ></a>БЕЗОПАСНОСТЬ</h2>
|
||
|
||
<p>Save Tcl не дает полной гарантии безопасности. В частности, он
|
||
не защищает от атак на сервер, когда поглощаются все ресурсы
|
||
процессора и пользователь не может использовать компьютер для
|
||
полезной работы. Однако такие атаки считаются, как правило,
|
||
менее опасными, чем несанкционированный доступ к информации и
|
||
нарушение целостности, от которых безопасный интерпретатор
|
||
защищает. В безопасном интерпретаторе, помимо безопасного набора
|
||
команд, который описан в описании команды <a href=
|
||
interp.html><strong>interp</strong></a>, имеются синонимы для команд <a
|
||
href=source.html><strong>source</strong></a>, <a
|
||
href=load.html><strong>load</strong></a>, <a
|
||
href=exit.html><strong>exit</strong></a> и безопасное подмножество
|
||
подкоманд команды <a href=file.html><strong>file</strong></a>. В
|
||
безопасном интерпретаторе возможна автозагрузка библиотек и
|
||
пакетов. Поскольку эти команды имеют дело с локальной файловой
|
||
системой, существует потенциальная опасность использования их
|
||
для доступа к конфиденциальной информации. Чтобы предотвратить
|
||
эту возможность, в безопасном интерпретаторе используются не
|
||
настоящие имена каталогов, а специальные метки. Эти метки
|
||
транслируются в реальные имена файлов только в родительском
|
||
интерпретаторе.</p>
|
||
|
||
<p>Чтобы исключить доступ к файлам, которые оказались в силу тех
|
||
или иных причин в разрешенных для чтения в безопасном
|
||
интерпретаторе каталогах, синоним команды <a
|
||
href=source.html><strong>source</strong></a> обеспечивает
|
||
доступ только к файлам с расширением tcl, в именах которых
|
||
содержится ровно одна точка, а общая длина имени не превышает
|
||
четырнадцати символов.</p>
|
||
|
||
<p>По умолчанию в Tcl переменной <em>auto_path</em> содержатся метки
|
||
для каталогов, содержащихся в аналогичной переменной в
|
||
родительском интерпретаторе и их непосредственных подкаталогов.
|
||
Первая метка в списке присваивается также Tcl переменной
|
||
<em>tcl_library</em> безопасного интерпретатора. Вы можете
|
||
сократить этот список, в явном виде задав доступные каталоги для
|
||
безопасного интерпретатора с помощью опции
|
||
<strong>-accessPath.</strong></p>
|
||
|
||
<p><strong>Safe Tcl</strong> - это механизм безопасного исполнения
|
||
ненадежных Tcl скриптов и предоставления этим скриптам
|
||
опосредованного доступа к потенциально опасным функциям.</p>
|
||
|
||
<p><strong>Safe Tcl</strong> служит для того, чтобы ненадежные скрипты не
|
||
смогли нарушить работу вызывающего их приложения: он
|
||
предотвращает покушения на несанкционированный доступ к
|
||
информации и нарушение целостности вызывающего этот скрипт
|
||
процесса.</p>
|
||
|
||
<p><strong>Safe Tcl</strong> позволяет интерпретатору-предку создавать
|
||
безопасные интерпретаторы с ограниченными возможностями, в
|
||
которых содержится набор предопределенных синонимов для команд
|
||
<a href=source.html><strong>source</strong></a>, <a
|
||
href=load.html><strong>load</strong></a>, <a
|
||
href=file.html><strong>file</strong></a> и <a
|
||
href=exit.html><strong>exit</strong></a> и сохраняются возможности
|
||
автозагрузки команд и пакетов.</p>
|
||
|
||
<p>Безопасный интерпретатор не позволяет получить какую-либо
|
||
информацию о структуре файловой системы, поскольку для доступа к
|
||
файлам в безопасном интерпретаторе используются специальные
|
||
метки. Когда безопасный интерпретатор запрашивает доступ к
|
||
файлу, он использует метку как часть виртуального имени файла.
|
||
Родительский интерпретатор заменяет метку на реальное имя
|
||
каталога и выполняет требуемую операцию с файлом. С помощью
|
||
опций команд, описанных ниже, можно выбрать требуемый уровень
|
||
безопасности интерпретатора.</p>
|
||
|
||
<p>Все команды для работы с безопасными интерпретаторами
|
||
содержатся в пространстве имен safe. Команда
|
||
<strong>::safe::interpCreate</strong> создает безопасный интерпретатор.
|
||
Возможные опции команды описаны ниже, см. <a
|
||
href=#ОПЦИИ>"Опции"</a>.</p>
|
||
|
||
<p>Команда возвращает имя созданного интерпретатора. Команда
|
||
<strong>::safe::interpInit</strong> аналогична, но ее первым аргументом
|
||
должно быть имя интерпретатора, созданного с помощью команды
|
||
<strong><a href=interp.html>interp</a></strong>.</p>
|
||
|
||
<p>Команда <strong>::safe::interpDelete</strong> удаляет интерпретатор, имя
|
||
которого использовано в качестве аргумента. Команда
|
||
<strong>::safe::interpConfigure</strong> позволяет задать опции для
|
||
безопасного интерпретатора или получить информацию об заданных
|
||
ранее опциях. Подробно опции описаны ниже (см. <a
|
||
href=#ОПЦИИ>Опции</a>).</p>
|
||
|
||
<p>Для каждого безопасного интерпретатора, созданного с помощью
|
||
команды <strong>::safe::interpCreate</strong> или инициированного с
|
||
помощью команды <strong>::safe::interpInit</strong> в родительском
|
||
интерпретаторе создается список доступных каталогов -
|
||
виртуальный путь. Каждый каталог в пути связывается с реальным
|
||
каталогом локальной файловой системы и с меткой, доступной в
|
||
безопасном интерпретаторе. В результате надежный интерпретатор
|
||
обходится без сведений о реальной файловой системе на машине, на
|
||
которой исполняется интерпретатор. Когда в надежном
|
||
интерпретаторе используется метка для доступа к конкретному
|
||
файлу (например, для выполнения команды <a
|
||
href=source.html><strong>source</strong></a> или <a
|
||
href=load.html><strong>load</strong></a>), метка заменяется в родительском
|
||
интерпретаторе на настоящее имя каталога и необходимый файл
|
||
ищется в файловой системе. Надежный интерпретатор не получает
|
||
сведений о реальном имени файла в файловой системе. Для работы с
|
||
виртуальными именами файлов предусмотрены специальные
|
||
команды. Команда <strong>::safe::interpConfigure</strong> позволяет
|
||
задавать новый виртуальный путь для интерпретатора. Команда
|
||
<strong>::safe::interpAddToAccessPath</strong> позволяет добавлять
|
||
каталоги к виртуальному пути указанного безопасного
|
||
интерпретатора. Команда <strong>::safe::interpFindInAccessPath</strong>
|
||
позволяет найти каталог в виртуальном пути для безопасного
|
||
интерпретатора и получить его метку. Если каталог не найден,
|
||
выдается сообщение об ошибке.</p>
|
||
|
||
<p>Команда <strong>::safe::setLogCommand</strong> позволяет задать скрипт,
|
||
который выполняется при каждом событии в безопасном
|
||
интерпретаторе. Этот скрипт вызывается с одним аргументом -
|
||
строкой, содержащей описание события.</p>
|
||
</body>
|
||
</html>
|
||
|