Язык скриптования сайтов Parser 3

         

Mailsend


send. Отправка сообщения по электронной почте


^mail:send[сообщение]


Метод отправляет сообщение на заданный адрес электронной почты. Можно указать несколько адресов через запятую.

Пример:

^mail:send[

      $.from[Вася <vasya@hotmail.ru>]

      $.to[Петя <petya@hotmail.ru>]

      $.subject[как дела]

      $.text[Как у тебя дела? У меня - изумительно!]

]

В результате будет отправлено сообщение для petya@hotmail.ru с содержимым "Как у тебя дела? У меня - изумительно!".

сообщение - хеш, в котором могут быть заданы такие ключи:



·поле_заголовка  

·text  

·html  

·file  

·charset  

·options   [3.1.2]

 


Внимание: рекомендуется в поле заголовка errors-to задавать адрес, на который может придти сообщение об ошибке доставки письма. По-умолчанию «postmaster».

charset - если задан этот ключ, то заголовок и текстовые блоки сообщения будут перекодированы в указанную кодировку. По умолчанию сообщение отправляется в кодировке, заданной в $request:charset (т.е. не перекодируется).


Пример:

$.charset[koi8-r]


options - эти опции будут переданы в командную строку программе sendmail (только под UNIX).

Также можно задать все поля заголовка сообщения, передав их значение в таком виде (короткая форма):

$.поле_заголовка[строка]

или с параметрами (полная форма):

$.поле_заголовка[

    $.value[строка]

    $.параметр[строка]

]


Примеры:

$.from[Вася <vasya@hotmail.ru>]

$.to[Петя <petya@hotmail.ru>]

$.subject[Как у тебя дела? У меня - изумительно!]

$.x-mailer[Parser 3]


Кроме заголовка можно передать один или оба текстовых блока: text, html. А также любое количество блоков file и message (см.
ниже).

Если будет передано оба текстовых блока, будет сформирована секция MULTIPART/ALTERNATIVE, при прочтении полученного сообщения современные почтовые клиенты покажут HTML, а устаревшие - простой текст.

Короткая форма:

$.text[строка]

Полная форма…

$.text[

    $.value[строка]

    $.поле_заголовка[значение]

]

…где value - значение тестового блока, и можно задать все поля заголовка сообщения, передав их как и в хеше сообщение (см. выше).

Внимание: можно не передавать заголовок content-type, он будет сформирован автоматически. Этот заголовок не влияет на перекодирование, а влияет только на ту кодировку, в которой почтовый клиент будет отображать сообщение.

Отправка HTML. Короткая форма:

$.html{строка}

Полная форма:

$.html[

    $.value{строка}

    $.поле_заголовка[значение]

]

Фигурные скобки нужны для переключения вида преобразования по умолчанию на HTML.

Вложение файла. Короткая форма:

$.file[файл]

Полная форма:

$.file[

    $.value[файл]

    $.name[имя_файла]

]

Файл - объект класса file, который будет прикреплен к сообщению. MIME-тип данных (content-type заголовок части) определяется по таблице MIME-TYPES (см. Конфигурационный метод).

Имя_файла - имя, под которым файл будет передан.

Файл будет передан в uuencode форме.

Вложение сообщения:

$.message[сообщение]

Формат сообщения такой же, как у параметра всего метода.

Вложений может быть несколько, для чего после имени следует добавить целое число. Пример:

    $.file

    $.file2

    $.message

    $.message2



Пример с альтернативными блоками и вложениями:

^mail:send[

    $.from[Вася <vasya@hotmail.ru>]

    $.to[Петя <petya@hotmail.ru>]

    $.subject[как дела]

    $.text[Как у тебя дела? У меня изумительно!]



    $.html{Как у тебя дела? У меня <b>изумительно</b>!}

    $.file[^file::load[binary;perfect_life1.jpg]]

    $.file2[

        $.value[^file::load[binary;perfect_life2.jpg]]

        $.name[изумительная_жизнь2.jpg]

    ]

]

В результате будет отослано сообщение для petya@hotmail.ru с содержимым «Как у тебя дела? У меня - изумительно!» в простом тексте и HTML. К сообщению будут приложены две подтверждающие фотографии, на которых…

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 01.04.2004

Mainclass


Класс MAIN, обработка запроса


Parser обрабатывает запрошенный документ следующим образом:

1.

Считываются, компилируются и инициализируются Конфигурационный файл; затем все файлы с именем auto.p, поиск которых производится начиная от корня веб-пространства, и ниже по структуре каталогов, вплоть до каталога с запрошенным документом; наконец, сам запрошенный документ.

Все вместе они составляют определение класса MAIN.

Инициализация заключается в вызове метода auto каждого загруженного файла. Если определение этого метода содержит параметр, при вызове в нем будет передано имя загруженного файла.

Примечание: результат работы метода посетителю не выводится.

2.

Затем вызывается без параметров метод main класса MAIN.

Т.е. в любом из перечисленных файлов может быть определен метод main, и будет вызван тот, который был определен последним - скажем, определение этого метода в запрошенном документе перекрывает все остальные возможные определения, и будет вызван именно он.

Результат работы этого метода будет передан пользователю, если не был определен метод postprocess.

Если в файле не определен ни один метод, то все его тело считается определением метода main.

Примечание: задание $response:body[нестандартного ответа] переопределяет текст, получаемый пользователем.

3.

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

Таким образом вы получаете возможность «дополнительной полировки» результата работы вашего кода.

Простой пример

Добавление такого определения, скажем, в файл auto.p в корне вашего веб-пространства…

@postprocess[body]

^body.match[шило][g]{мыло}


…приведет к замене одних слов на другие в результатах обработки всех страниц.




Matdegreesetc


degrees, radians. Преобразования градусы-радианы


Методы выполняют преобразования из градусов в радианы и обратно.


^math:degrees(число радиан)

- возвращает число градусов, соответствующее заданному числу радиан

^math:radians(число градусов)

- возвращает число радиан, соответствующее заданному числу градусов



Пример

^math:degrees($math:PI/2)

- получаем 90 (градусов)

^math:radians(180)

- получаем p




Mathabssign


abs, sign. Операции со знаком


Выполняют операции со знаком числа.

^math:abs(число)

- возвращает абсолютную величину числа (модуль)

^math:sign(число)

- возвращает 1, если число положительное, -1, если число отрицательное и 0, если число равно 0

Пример

^math:abs(-15.506)

- получаем 15.506

^math:sign(-15.506)

- получаем -1





Mathclass


Класс math


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



Mathcrypt


crypt. Хеширование паролей


^math:crypt[password;salt]


Хеширует password с учетом salt.

Параметры:

·password - исходная строка;  

·salt - строка, определяющая алгоритм хеширования и вносящая элемент случайности в результат хеширования, состоит из начала и тела. Начало определяет алгоритм хеширования, тело вносит элемент случайности. Если тело не будет указано, Parser сформирует случайное.  


Неразумно хранить пароли пользователей, просто записывая их на диск или в базу данных - ведь если предположить, что злоумышленник украдет файл или таблицу с паролями, он легко сможет ими воспользоваться. Поэтому принято хранить не пароли, а их хеши - результат надежного однозначного необратимого преобразования строки пароля. Для проверки введенного пароля к нему применяют то же преобразование, передавая в качестве salt сохраненный хеш, а результат сверяют с сохраненным.

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

Внимание: обязательно задавайте случайное тело salt, или позвольте Parser сделать это за вас, попросту не указывая тело salt, указывая только начало salt.

Таблица доступных алгоритмов:

Алгоритм

Описание

Начало salt

Тело "salt"

MD5

встроен в Parser, доступен на всех платформах

$apr1$

до 8 случайных букв (в любом регистре) или цифр

MD5

если поддерживается операционной системой (UNIX)

$1$

до 8 случайных букв (в любом регистре) или цифр

DES

если поддерживается операционной системой (UNIX)

(нет)

2 случайных буквы (в любом регистре) или цифры

другие

какие поддерживаются операционной системой (UNIX)

читайте документацию на вашу операционную систему, функция crypt

читайте документацию на вашу операционную систему, функция crypt

<
br>

Внимание: в Parser для использования в тексте символа '$' его необходимо предварить символом '^'.

Примечание: Веб-сервер Apache допускает в файлах с паролями (.htpasswd) использовать хеши сформированные по любому из алгоритмов, представленных в таблице, включая алгоритм, встроенный в Parser.

Пример создания .htpasswd файла

@main[]

$users[^table::create{name   password

alice   xxxxxx

bob   yyyyyy

}]

$htpasswd[^table::create[nameless]{}]

^users.menu{

    ^htpasswd.append{$users.name:^math:crypt[$users.password;^$apr1^$]}

}

^htpasswd.save[nameless;.htpasswd-parser-test]



Пример проверки пароля

$right[123]

$from_user[123]

$crypted[^math:crypt[$right;^$apr1^$]]

#обратите внимание на то, что $crypted при каждом обращении разный

$crypted<br>

^if(^math:crypt[$from_user;$crypted] eq $crypted){

    Казнить нельзя, помиловать

}{

    Казнить, нельзя помиловать

}

Подробная информация о MD5 доступна здесь: http://www.ietf.org/rfc/rfc1321.txt

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 12.02.2004

Mathexplog


exp, log. Логарифмические функции


^math:exp(число)

- экспонента по основанию e

^math:log(число)

- натуральный логарифм

Методы вычисляют значения логарифмических функций от заданного числа

Примечание (если вы совсем забыли родную школу):

логарифм по произвольному основанию base вычисляется как log(число)/log(base).



в шестнадцатеричном виде без разделителей,


md5. MD5-отпечаток строки [3.0.8]



^math:md5[строка]



Из переданной строки получает «отпечаток» размером 16 байт.

Выдает его представление в виде строки - байты представлены в шестнадцатеричном виде без разделителей, в нижнем регистре.

Считается, что практически невозможно

·создать две строки, имеющие одинаковый «отпечаток»;  

·восстановить исходную строку по ее «отпечатку».  

Пример

В качестве имени cache-файла возьмем «отпечаток» строки $request:uri, это обеспечит взаимно-однозначное соответствие имени строке запроса, а также избавит нас от необходимости укорачивать строку запроса и очищать ее от спецсимволов.



^cache[$cache_directory/^math:md5[$request:uri]]($cache_time){

    …

}



Подробная информация о MD5 доступна здесь: http://www.ietf.org/rfc/rfc1321.txt


Mathpow


pow. Возведение числа в степень


^math:pow(число;степень)   


Возводит число в степень.

Пример

^math:pow(2;10) - получаем 1024 ( 210 =1024 )



Mathrandom


random. Случайное число


^math:random(верхняя_граница)   


Метод возвращает случайное число, попадающее в интервал от 0 до заданного числа, не включая заданное.

Примечание: на некоторых операционных системах выдает псевдослучайное число.

Пример

^math:random(1000)


Получим случайное число из диапазона от 0 до 999.



Mathroundetc


round, floor, ceiling. Округления


^math:round(число)

- округление до ближайшего целого

^math:floor(число)

- округление до целого в меньшую сторону

^math:ceiling(число)

- округление до целого в большую сторону



Методы возвращают округленное значение заданного числа класса double.

Пример

^math:round(45.50)

- получаем 46

^math:floor(45.60)

- получаем 45

^math:ceiling(45.20)

- получаем 46

^math:round(-4.5)

- получаем -4

^math:floor(-4.6)

- получаем -5

^math:ceiling(-4.20)

- получаем -4




Mathsinetc


sin, asin, cos, acos, tan, atan. Тригонометрические функции


^math:sin(радианы)

- арксинус

^math:asin(число)

- синус

^math:cos(радианы)

- косинус

^math:acos(число)

- аркосинус

^math:tan(радианы)

- тангенс

^math:atan(число)

- арктангенс



Методы вычисляют значения тригонометрических функций от заданного числа.

Пример

^math:cos(^math:radians(180)) - получаем -1 (cos p = -1).



Mathstats


Статические поля


Число Пи


$math:PI - число p



Mathtruncfrac


trunc, frac. Операции с целой/дробной частью числа


^math:trunc(число)

- возвращает целую часть числа

^math:frac(число)

- возвращает дробную часть числа



Пример

^math:trunc(85.506)

- получаем 85

^math:frac(85.506)

- получаем 0.506





uid64. 64-битный уникальный идентификатор [3.0.8]



^math:uid64[]



Выдает случайную строку вида…

    BA39BAB6340BE370

Примечание: на некоторых операционных системах выдает псевдослучайную строку.

См. ^math:uuid[].

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 12.02.2004

Mathuuid


uuid. Универсальный уникальный идентификатор [3.0.8]


^math:uuid[]


Выдает случайную строку вида…

    22C0983C-E26E-4169-BD07-77ECE9405BA5

Примечание: на некоторых операционных системах выдает псевдослучайную строку.

Удобно использовать, когда трудно обеспечить или вообще нецелесообразно использовать сквозную нумерацию объектов.

Например, при распределенных вычислениях.

UUID также известен как GUID.

Пример

В разных филиалах компании собираются заказы, которые периодически отправляются в центральный офис. Чтобы обеспечить уникальность идентификатора заказа используем UUID.


# в разных филиалах происходит наполнение таблицы orders и order_details

# создаем уникальный идентификатор

$order_uuid[^math:uuid[]]

# добавляем запись о заказе

^void:sql{

insert into orders

    (order_uuid, date_ordered, total)

values

    ('$order_uuid', '$date_ordered', $total)

}

#цикл по заказанным продуктам вокруг добавления записи о продукте

^void:sql{

insert into order_details

    (order_uuid, item_id, price)

values

    ('$order_uuid', $item_id, $price)

}

# с какой-то периодичностью выбирается часть таблицы orders (и order_details)

# отправляется (^mail:send[…]) в центральный офис, 

# где части таблиц попадают в общие таблицы orders и order_details

# БЕЗ проблем с повторяющимся order_id

Примечание: Parser создает UUID основываясь на случайных числах, а не времени. Параметры:

·variant = DCE;  

·version = DCE Security version, with embedded POSIX UIDs.  

В UUID не все биты случайны, и это так и должно быть:

xxxxxxxx-xxxx-4xxx-{8,9,A,B}xxx-xxxxxxxxxxxx

Подробная информация о UUID доступна здесь: http://www.opengroup.org/onlinepubs/9629399/apdxa.htm



Matsqrt


sqrt. Квадратный корень числа


^math:sqrt(число)   


Вычисляет квадратный корень числа.

Пример

^math:sqrt(16) - получаем 4

Примечание [если вы совсем забыли родную школу]:

корень n-ной степени вычисляется как возведение в степень 1/n.



Memoryclass


Класс memory [3.1]


Класс предназначен для работы с памятью Parser.

Его использование поможет вам экономить память в ваших скриптах.

Для любознательных: в Parser используется известный и хорошо зарекомендовавший себя консервативный сборщик мусора Boehm-Demers-Weiser, см. http://www.hpl.hp.com/personal/Hans_Boehm/gc/.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 16.02.2004



Memorycompact


compact. Сборка мусора [3.1]


^memory:compact[]


Собирает так называемый «мусор» в памяти, освобождая ее для повторного использования вашим кодом.

Мусором считается память, более не используемая вашим кодом, т.е. та, на которую в вашем коде нет ссылок.

Например,

$table[^table::sql{запрос}]

$table[]

# освободит память, занимаемую результатом выполнения SQL-запроса

^memory:compact[]


Parser не собирает мусор автоматически, полагаясь в данном вопросе на кодера: поставьте вызов compact в той точке (точках), где ожидаете наибольшей выгоды, например, перед XSL преобразованием.

$status:memory поможет вам в отладке и поиске мест, наиболее выгодных для сборки мусора.

Важно: необходимо как можно более интенсивно использовать локальные переменные, и обнулить глобальные, которые вам не будут нужны для дальнейшей работы кода. Это поможет compact освободить больше.

Важно: не гарантируется, что будет освобождена абсолютно вся неиспользуемая память.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 03.07.2003



Numlit


Числовые литералы


Запись числовых литералов допускается в следующем виде:

1

-8

(целое)

1.23

-4.56

(дробное)


0xA8 равно 168

(форма шестнадцатиричной записи)

Примечание: регистр букв не важен.



Obj


Объект класса


Создание объекта

^класс::конструктор[параметры]


Конструктор создает объект класса, наделяя его полями и методами класса. Параметры конструкторов подробно описаны в соответствующем разделе.

Примечание: результат работы конструктора - созданный объект, обычный результат работы метода игнорируется (никуда не попадает).

Вызов метода

^объект.метод[параметры]


Вызов метода класса, к которому принадлежит объект. Параметры конструкторов подробно описаны в соответствующем разделе.

Если не указан объект, то конструкция является вызовом метода текущего класса (если у класса нет метода с таким именем, будет вызван метод базового класса) или оператора. При совпадении имен вызывается оператор.

Методы бывают статические и динамические.

Динамический метод - код выполняется в контексте объекта (экземпляра класса).

Статический метод - код выполняется в контексте самого класса, то есть метод работает не с конкретным объектом класса, а со всем классом (например, классы MAIN, math, mail)

Значение поля объекта

$объект.поле


Получение значения поля объекта.

Системное поле объекта: CLASS

$объект.CLASS - хранит ссылку на класс объекта.

Это необходимо при задании контекста компиляции кода (см. «process. Компиляция и исполнение строки».



Opcache


cache. Сохранение результатов работы кода


^cache[файл](число секунд){код}

^cache[файл](число секунд){код}{обработчик проблем}   [3.1.2]

^cache[файл][дата устаревания]{код}

^cache[файл][дата устаревания]{код}{обработчик проблем}   [3.1.2]


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

Крайне рекомендуется подключать модули (^use[…]) изнутри кода оператора cache, а не делать это статически (@USE).

По-возможности, работайте с базой данных (^connect[…]) также внутри кода оператора cache - вы существенно снизите нагрузку на ваш SQL-сервер и повысите производительность ваших сайтов.

Файл - имя файла-кеша. Если такой файл существует и не устарел, то его содержимое выдается клиенту, если не существует - выполняется код, и результат сохраняется в файл с указанным именем.

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

Дата устаревания - время, до которого хранится результата работы кода. Если она в прошлом, то результат не сохраняется, а файл с предыдущим сохраненным результатом уничтожается.

Код - код, результат которого будет сохранен.

Обработчик проблем - здесь можно обработать проблему, если она возникнет в коде. В этом отношении оператор похож на try, см. раздел «Обработка ошибок». В отличие от try, можно задать $exception.handled[cache] - это дает указание Parser обработать ошибку особенным образом: достать из файла ранее сохраненный результат работы кода, проигнорировав тот факт, что этот результат устарел.


Внутри кода допустимы команды, изменяющие время хранения результата работы кода:


^cache(число секунд)

^cache[дата устаревания]


Берется минимальное время хранения кода.

Пример

^cache[/data/cache/test1](5){

   Нажимайте reload, меняется каждые 5 секунд: ^math:random(100)

}


Изменение времени хранения

^cache[/data/cache/test2](5){

   по ходу работы вы выяснили, 

   что страницу сохранять не нужно: ^cache(0)

}

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 01.04.2004



Opconnect


connect. Подключение к базе данных


^connect[строка подключения]{код}


Оператор connect осуществляет подключение к серверу баз. Код оператора обрабатывается Parser, работая с базой данных в рамках установленного подключения.

Parser (в виде модуля к Apache или IIS) кеширует соединения с SQL-серверами, и повторный запрос на соединение с той же строкой подключения не производится, а соединение берется из кеша, если оно еще действительно.

Вариант CGI также кеширует соединение, но только на один запрос, поэтому явно допустимы конструкции вида:

^connect[строка подключения]{…}

^connect[строка подключения]{…}


При этом не будет двух соединений, и это полезно, когда, скажем, изредка соединение нужно, и заранее неизвестно нужно или нет - заранее его можно не делать, а делать визуально многократно, зная, что оно фактически не разрывается.

Передать SQL-запрос БД может один из следующих методов или конструкторов языка Parser:

table::sql

string:sql

void:sql

hash::sql

int:sql

double:sql


Замечание: для работы оператора connect необходимо наличие настроенного драйвера баз данных (см. раздел Настройка).   

Форматы строки соединения для поддерживаемых серверов баз данных описаны в приложении.

Пример

^connect[mysql://admin:pwd@localhost/p3test]{

   $news[^table::sql{select * from news}]

}



Opdef


def. Проверка определенности объекта


Оператор возвращает булевое значение (истина/ложь) и отвечает на вопрос «определен ли объект?» Проверяемым объектом может любой объект Parser: таблица, строка, файл, объект пользовательского класса и т.д.

def объект   

не определенными (не def) считаются пустая строка, пустая таблица, пустой хеш и код.

Пример

$str[Это определенная строка]

^if(def $str){

    Строка определена

}{

    Строка не определена

}

Важно: для проверки «содержит ли переменная код» и «определен ли метод» используйте оператор is, а не def. Таким образом. ^if(def $hash.delete){-}{в hash нет элемента «delete»}.




Opeval


eval. Вычисление математических выражений


^eval(математическое выражение)  

^eval(математическое выражение)[форматная строка]   


Оператор eval вычисляет математическое выражение и позволяет вывести результат в нужном виде, задаваемом форматной строкой (см. Форматные строки).

Пример

^eval(100/6)[%.2f]

вернет: 16.67.

Внимание: настоятельно советуем задавать комментарии к частям сложного математического выражения (см. «Комментарии к частям выражения»).



Opevalcomment


Комментарии к частям выражения


Допустимо использование комментариев к частям математического выражения, которые начинаются со знака #, и продолжаются до конца строки исходного файла или до конца выражения.

Пример

^if(

    $age>=$MINIMUM_AGE  # не слишком молод

    && $age<=$MAXIMUM_AGE  # и не слишком стар

){

    Годен

}


Внимание: настоятельно советуем задавать комментарии к частям сложного математического выражения. Бывает, что даже вам самим через какое-то время бывает трудно в них разобраться.



Opfor


for. Цикл с заданным числом повторов


^for[счетчик](от;до){тело}

^for[счетчик](от;до){тело}[разделитель]  

^for[счетчик](от;до){тело}{разделитель}


Оператор for повторяет тело цикла, перебирая значения счетчика от начального значения до конечного. С каждым выполнением тела значение счетчика автоматически увеличивается на 1.

Счетчик - имя переменной, которая является счетчиком цикла

От и до - начальное и конечное значения счетчика, математические выражения, задающие соответственно начало и конец диапазона значений, принимаемых счетчиком. Если конечное значение счетчика меньше начального, тело цикла не выполнится ни разу

Разделитель - код, который выполняется перед каждым непустым не первым телом

Замечание: поскольку имена счетчиков могут повторяться, полезно объявлять их локальными переменными метода, где используется цикл for.   

Пример

^for[week](1;4){

   <a href="/news/archive.html?week=$week">Новости за неделю №$week</a>

}[<br>]


Пример выводит ссылки на недели с первой по четвертую, после очередной строки ставится тег перевода строки.



Opif


if. Выбор одного варианта из двух


^if(логическое выражение){код, если значение логического выражения «истина»}

^if(логическое выражение){

   код, если значение логического выражения «истина»

}{

   код, если значение логического выражения «ложь»

}

Оператор вычисляет значение логического выражения. Затем, в зависимости от полученного результата, либо выполняется или не выполняется код (первый вариант использования оператора if), либо для исполнения выбирается код, соответствующий полученному значению логического выражения (второй вариант). На код не накладывается никаких ограничений, в том числе внутри него может содержаться еще один или несколько операторов if.

Внимание: настоятельно советуем задавать комментарии к частям сложного логического выражения (см. «Комментарии к частям выражения»).



Opin


in. Проверка, находится ли документ в каталоге


in "/каталог/"    


Возвращает результат "истина/ложь" в зависимости от того, находится ли текщий документ в указанном каталоге.

Пример

^if(in "/news/"){

   Мы в разделе новостей

}{

   <a href="/news/">Новости</a>

}



Opis


is. Проверка типа


объект is тип   


Возвращает результат "истина/ложь" в зависимости от того, относится ли левый операнд к заданному типу.

Полезно использовать этот оператор в случае, если переменная может содержать единственное значение или набор значений (хеш), а также для проверки определенности методов.

Тип - имя типа, им может быть системное имя (hash, junction, …), или имя пользовательского класса.

Простая проверка типа

@main[]

$date[1999-10-10]

#$date[^date::now[]]

^if($date is string){

    ^parse[$date]

}{

    ^print_date[$date.year;$date.month;$date.day]

}

@parse[date_string][date_parts]

$date_parts[^date_string.match[(\d{4})-(\d{2})-(\d{2})][]]

^print_date[$date_parts.1;$date_parts.2;$date_parts.3]

@print_date[year;month;day]

Работаем с датой:<br>

День:  $day<br>

Месяц: $month<br>

Год:   $year<br>


В этом примере в зависимости от типа переменной $date либо выполняется синтаксический анализ строки, либо методу print_date передаются поля объекта класса date:

Проверка наличия в переменной кода

Т.к. оператор def не считает переменные, содержащие код, определенными, для проверки наличия в переменной кода необходимо использовать is:

$something{^do[]}

^if($something is junction){

#   выполнение кода

    $something

}

Проверка определенности метода

Значение $имя_метода, это тоже junction, поэтому проверять существование метода необходимо также оператором is, а не def:

@body[]

тело


@main[]

Старт

^if($body is junction){

   ^body[]

}{

   Метод «body» не определен!

}

Финиш



Opprocess


process. Компиляция и исполнение строки


^process{строка}

^process[контекст]{строка}

^process[контекст]{строка}[опции]   [3.1.2]


Строка будет скомпилирована и выполнена как код на Parser, в указанном контексте, или в текущем контексте.

В качестве контекста можно указать объект или класс.

Удобно использовать, если какие-то части кода или собственные методы необходимо хранить не в файлах .html, которые обрабатываются Parser, а в каких-то других, или базе данных.

Также можно указать ряд опций (хеш):

·$.main[новое имя для метода main, описанного в коде строки}

 

·$.file[имя файла, из которого взята данная строка}

 

·$.lineno(номер строки в файле, откуда взята данная строка. может быть отрицательным)

 


Простые примеры

^process{@extra[]

   Здоровья прежде всего…

}

Метод extra будет добавлен к текущему классу, и его можно будет вызывать в дальнейшем.

^process[$engine:CLASS]{@start[]

   Мотор…

}

Метод start будет добавлен к пользовательскому классу engine.

$running_man[^man::create[Вася]]

^process[$running_man]{

    Имя: $name<br>

}

Код будет выполнен в контексте объекта $running_man, соответственно, может воспользоваться полем name этого объекта, выдаст «Вася».

Оператор include

@include[filename][file]

$file[^file::load[text;$filename]]

^process[$caller.self]{^taint[as-is][$file.text]}[

   $.file[$filename]

]

Код загружает указанный файл и выполняет его в контексте вызова include. Опция file позволяет указать имя файла, откуда был загружен код. Если возникнет ошибка, вы увидите это «имя файла».

Сложный пример

Часто удобно поместить компилируемый код в некоторый метод с именем, вычисляющимся по ходу работы:

# это исходный код, обратите внимание, на ^^

$source_code[2*2=^^eval(2*2)]

# по ходу работы выясняется, что необходимо создать метод с именем method1

$method_name[method1]

# компилируем исходный код, помещяем его в новый метод

^process{$source_code}[

   $.main[$method_name]

]


# далее по коду можно вызывать метод method1

^method1[]

Данный пример будет продолжать работать, даже если в $source_code будет определен ряд методов, поскольку опция main задает новое имя методу main.


Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 01.04.2004



Oprem


rem. Вставка комментария


^rem{комментарий}


Весь код, содержащийся внутри оператора, не будет выполнен. Используется для комментирования блоков кода.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 11.04.2002



Opsfd


-f и -d. Проверка существования файла и каталога


-f имя_файла - проверка существования файла на диске.

-d имя_каталога - проверка существования каталога на диске.   

Возвращает результат "истина/ложь" в зависимости от того, существует ли указанный файл или каталог по заданному пути.

Пример

^if(-f "/index.html"){

   Главная страница существует

}{

   Главная страница не существует

}



Opswitch


switch. Выбор одного варианта из нескольких


^switch[строка для сравнения]{

   ^case[вариант1]{действие для 1}

   ^case[вариант2]{действие для 2}

   ^case[вариант3;вариант 4]{действие для 3 или 4}

         …         

   ^case[DEFAULT]{вариант по умолчанию}

}

^switch(математическое выражение){

   ^case(вариант1){действие для 1}

      ^case(вариант2){действие для 2}

      ^case(вариант3;вариант 4){действие для 3 или 4}

         …         

   ^case[DEFAULT]{вариант по умолчанию}

}


Оператор switch сравнивает строку или результат математического выражения со значениями, перечисленными в case. В случае совпадения выполняется код, соответствующий совпавшему значению. Если совпадений нет, выполняется код, соответствующий значению DEFAULT (пишется только заглавными буквами).

Если код для DEFAULT не определен и нет совпадений со значениями, перечисленными в case, ни один из вариантов кода, присутствующих в операторе switch, выполнен не будет.

Пример

^switch[$color]{

   ^case[red]{Необходимо остановиться и подумать о вечном…}

   ^case[yellow]{Настало время собраться и приготовиться!}

   ^case[green]{Покажи им, кто король дороги!}

   ^case[DEFAULT]{Вы дальтоник, или это вовсе не светофор.}

}



Opthrow


throw. Сообщение об ошибке


^throw[type;source]

^throw[type;source;comment]

Оператор throw сообщает об ошибке типа type, произошедшей по вине source, с комментарием comment.

Эта ошибка может быть перехвачена и обработана при помощи оператора try.

Не перехватывайте ошибки только для их красивого вывода, пусть этим централизованно займется метод unhandled_exception, вызываемый Parser если ни одного обработчика ошибки так и не будет найдено. Кроме прочего, произойдет запись в журнал ошибок веб-сервера, который можно регулярно просматривать на предмет имевших место проблем.

Пример

@method[command]

^switch[$command]{

   ^case[add]{

      добавляем…

   }

   ^case[delete]{

      удаляем…

   }

   ^case[DEFAULT]{

      ^throw[bad.command;$command;Wrong command $command, good are add&delete]

   }

}

@main[]

$action[format c:]

^try{

   ^method[$action]

}{

   ^if($exception.type eq bad.command){

      $exception.handled(1)

      Неправильная команда '$exception.source', задана

      в файле $exception.file, в $exception.lineno строке.

   }

}

Результатом работы примера будет

Неправильная команда 'format c:', задана 

в файле c:/parser3tests/www/htdocs/throw.html, в 15 строке.

Обращаем ваше внимание на то, что пользователи вашего сайта не должны увидеть технические подробности в сообщениях об ошибках, тем более содержащие пути к файлам, это некрасиво и ненадежно.

Вывод $exception.file дан в качестве примера и настоятельно не рекомендуется к использованию на промышленных серверах - только для отладки.



Optry


try. Перехват и обработка ошибок


^try{код, ошибки которого попадают…}{…в этот обработчик в виде $exception}


Если по ходу работы кода возникла ошибка, создается переменная $exception, и управление передается обработчику.

$exception, это такой hash:


$exception.type

строка, тип ошибки.

Определен ряд системных типов, также тип ошибки может быть задан в операторе throw.

$exception.source

строка, источник ошибки (ошибочное имя файла, метода, …)

$exception.file

$exception.lineno

$exception.colno

файл, содержащий source,

номера строки и колонки в нем

$exception.comment

комментарий к ошибке, по английски

$exception.handled

истина или ложь, флаг «обработана ли ошибка»

необходимо зажечь этот флаг в обработчике, если вы обработали переданную вам ошибку

Обработчик обязан сообщить Parser, что данную ошибку он обработал, для чего только для нужных типов ошибок он должен зажечь флаг:

$exception.handled(1)


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

Если ошибка так и не будет обработана, если есть, вызывается метод unhandled_exception и ему передается информация об ошибке, стек вызовов, приведших к ошибке, и выдаются результаты его работы. А также производится запись в журнал ошибок веб-сервера.


Пример

^try{

   $srcDoc[^xdoc::create{$untrustedXML}]

}{

   ^if($exception.type eq xml){

      $exception.handled(1)

      Ошибочный XML,

      <pre>$exception.comment</pre>

   }

}



Opuntainttaint


untaint, taint. Преобразование данных


^untaint{код}

^untaint[вид преобразования]{код}

^taint[текст]

^taint[вид преобразования][текст]

Оператор taint помечает весь переданный ему текст, как нуждающийся в преобразовании заданного вида. Оператор untaint выполняет переданный ему код и помечает, как нуждающиеся в преобразовании, те части результата выполнения кода, которые не являлись частью кода на Parser, а поступили извне, например, из полей формы.

Если вид преобразования не указан, оператор untaint делает преобразование вида as-is, а оператор taint помечает текст как tainted (неопределенно «грязный», без указания вида преобразования).

Само преобразование Parser выполняет позже, при выдаче результата обработки документа пользователю, перед выполнением SQL-запроса или отправкой письма.

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

as-is

file-spec

http-header

mail-header

uri

sql

js

xml

html

optimized-as-is

optimized-xml

optimized-html


Выполняемые замены для каждого вида преобразования сведены в таблице ниже.

Важное замечание: «чистый» код также подвергается автоматическому преобразованию. Parser выполняет оптимизацию по «white spaces» (символы пробела, табуляция, перевода строки). Идущие подряд перечисленные символы заменяются только одним, который встречается в коде первым. В общем виде можно представить весь набираемый код следующим образом:

^untaint[optimized-html]{здесь находится код, набранный скриптовальщиком}


Необходимо учитывать это при создании кода! Схема автоматического преобразования Parser - optimized-html.   

Пример:

Пример на ^^untaint.<br>

<form>

<input name=field>

<input type=submit>

</form>

$tainted[$form:field]

"Грязные" данные - $tainted<br>

"Чистые" данные - ^untaint{$tainted}





В результате выполнения этого кода поступившие через поля формы данные не будут преобразовываться Parser и выдадутся в том виде, в каком они поступили. В квадратных скобках оператора untaint задается вид выполняемого преобразования. Здесь мы опускаем квадратные скобки в методе untaint и используем параметр по умолчанию [as-is].

Как уже было сказано выше, большую часть работы по преобразованию данных Parser выполняет автоматически. Внешние данные, которые используются в «чистом» коде преобразуются к optimized-html.

Оператор taint также помечает преобразование данных в соответствии с указанной таблицей, но, в отличие от untaint, используется для «чистых» данных, т.е. созданных кодером, либо поступивших извне и уже обработанных untaint. Еще раз обращаем внимание, что преобразование происходит только в момент выдачи данных во внешнюю среду (пользователю, в файл или базу данных). Если не задан вид преобразования, данные останутся "грязными", но никаких замен сделано не будет.

Пример

Пример ^^taint.<br>

$town[Москва]

<a href="town.html?^taint[uri][$town]">$town</a>



В результате данные, хранящиеся в переменной town, будут преобразованы к типу URI. Русские буквы будут заменены на шестнадцатеричные коды символов и представлены в виде %ХХ.

Таблицы преобразований



as-is



изменений в тексте не делается



file-spec



символы * ? ' " < > |

преобразуются в "_XX",

где XX - код символа в шестнадцатеричной форме



uri



символы за исключением цифр, строчных и прописных латинских букв, а также следующих символов: _ - . "

преобразуется в %XX где XX - код символа в шестнадцатеричной форме



http-header



то же, что и URI



mail-header



если известен charset (если неизвестен, не будут работать up/low case), то фрагмент, начиная с первой буквы с восьмым битом и до конца строки, будет представлен в подобном виде:

Subject: Re: parser3: =?koi8-r?Q?=D3=C5=CD=C9=CE=C1=D2?=



sql



в зависимости от SQL-сервера

для Oracle/ODBC меняется ' на ''

для PgSQL меняется ' на '' и \ на \\

для MySQL делается средствами самого MySQL



js



" преобразуется в \"

' преобразуется в \' 

\ преобразуется в \\

символ конца строки преобразуется в \n

символ с кодом 0xFF предваряется \



xml



& преобразуется в &amp;

> преобразуется в &gt;

< преобразуется в &lt;

" преобразуется в &quot;

' преобразуется в &apos;



html



& преобразуется в &amp;

> преобразуется в &gt;

< преобразуется в &lt;

" преобразуется в &quot;



optimized-as-is

optimized-xml

optimized-html



дополнительно к заменам выполняется оптимизация по "white spaces" (символы пробела, табуляция, перевода строки).

Идущие подряд перечисленные символы заменяются только одним, который встречается в коде первым

<


br>

Ряд taint преобразований Parser делает автоматически, так, имена и пути файлов всегда автоматически file-spec преобразуются, и когда вы пишите…



^file::load[filename]



…Parser выполняет…



^file::load[^taint[file-spec][filename]]



Аналогично, при задании HTTP-заголовков и заголовков писем, происходят http-header и mail-header преобразования соответственно. А при DOM-операциях текстовые параметры всех методов автоматически xml преобразуются.

Также Parser выполняет ряд автоматических untaint преобразований:

вид

что преобразуется

sql

тело SQL-запроса

xml

XML код при создании объекта класса xdoc



Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 28.05.2004

Opuse


use. Подключение модулей


^use[файл]

Оператор позволяет использовать модуль из указанного файла. Если путь к файлу начинается с "/", то считается, что это путь от корня веб-пространства. В любом другом случае Parser будет искать модуль по путям, определенным в переменной $CLASS_PATH в Конфигурационном методе.

Для подключения модулей также можно воспользоваться конструкцией:

@USE

имя файла 1

имя файла 2



Разница между этими конструкциями в том, что использование @USE подключает файлы с модулями до начала выполнения кода, в то время как оператор use может быть вызван непосредственно из тела программы, например:

^if(условие){

   ^use[модуль1]

}{

   ^use[модуль2]

}


Замечание: попытки подключить уже подключенные ранее модули не приводят к повторным считываниям файлов с диска. Однако нужно иметь ввиду, что для этого полное имя файла подключаемого модуля должно с точностью до символа совпадать с именем файла уже подключенного ранее модуля. В случае написания ^use[module.p] и ^use[sub/../module.p] будет считаться, что идет попытка подключить разные модули.

Крайне рекомендуем использовать возможность сохранения результатов работы кода, используя оператор use для подключения необходимых модулей в коде оператора cache.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 25.02.2004



Opuserdefined


Операторы, определяемые пользователем


Иногда вам будет казаться, что каких-то операторов в языке не хватает. Parser позволяет вам определить собственные операторы, которые затем можно будет использовать наравне с системными.

Операторами в Parser считаются методы класса MAIN, добавляя новые методы в этот класс вы расширяете базовый набор операторов.

Внимание: при описании оператора можно использовать и не локальные переменные, при этом вы будете читать и записывать в поля класса MAIN.

Пользовательские операторы могут определяться и в отдельных текстовых файлах без заголовка @CLASS, которые подключаются к нужным разделам сайта. Если в таком файле определить оператор (написав, скажем, @include[]), то при обращении ^include[…] всегда будет вызываться пользовательский оператор.

Будьте внимательны! Если определить оператор, одноименный с системным, то всегда будет вызываться пользовательский. При этом системный оператор вызвать нельзя никак. Стоит делать как можно меньше пользовательских операторов, используя вместо них статические методы пользовательских классов.

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

^news:help[]

^forum:help[]

^search:help[]


Примеры

Поместите этот код…

@default[a;b]

^if(def $a){$a}{$b}


… в файл operators.p, в корень вашего веб-сайта.

Там, где вам необходимы дополнительные операторы, подключите этот модуль. Например, в корневом auto.p, напишите…

@USE

/operators.p


…теперь не только в любой странице, но, что главное, в любом вашем классе можно будет воспользоваться конструкцией

^default[$form:name;Аноним]

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



Opwhile


while. Цикл с условием


^while(условие){тело}   


Оператор while повторяет тело цикла, пока условие истинно. Если условие заведомо ложно, тело цикла не выполнится ни разу.


Пример

$little_negros(10)

^while($little_negros > 0){

   <br>

   $little_negros негритят пошли купаться в море.

   Один из них ^little_negros.dec[] утоп,

   ему срубили гроб, и вот вам результат -

   $little_negros негритят.

}



Params


Передача параметров


Параметры могут передаваться в разных скобках и, соответственно, будут по-разному обрабатываться:

(выражение)

- вычисление параметра происходит при каждом обращении к нему внутри вызова метода

[код]

- вычисление параметра происходит один раз перед вызовом метода

{код}

- вычисление происходит при каждом обращении к параметру внутри вызова метода

Пример на различие скобок, в которых передаются параметры:

@main[]

$a(20)

$b(10)

^sum[^eval($a+$b)]

<hr>

^sum{^eval($a+$b)}

@sum[c]

^for[b](100;110){

   $c

}[<br>]


Здесь хорошо видно, что в первом случае код был вычислен один раз перед вызовом метода sum, и методу передался результат кода - число 30. Во втором случае вычисление кода происходило при каждом обращении к параметру, поэтому результат менялся в зависимости от значения счетчика.

Параметров может быть сколь угодно много или не быть совсем. Если в однотипных скобках несколько параметров, то они могут отделяться друг от друга точкой с запятой. Допустимы любые комбинации различных типов параметров.

Например…

    ^if(условие){когда да;когда нет}

…эквивалентно…

    ^if(условие){когда да}{когда нет}

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 03.12.2002



Parserconfig


Конфигурационный файл


Пример файла включен в поставку (см. auto.p.dist).

Этот файл - основной, с которого начинается сборка класса MAIN. Может содержать Конфигурационный метод, который выполняется первым, до метода auto, и задает важные системные параметры.

После выполнения конфигурационного метода можно задать кодировку ответа и кодировку, в которой набран код (по умолчанию в обоих случаях используется кодировка UTF-8):

Рекомендуемый код:

@auto[]

#source/client charsets

$request:charset[windows-1251]

$response:charset[windows-1251]

$response:content-type[

   $.value[text/html]

   $.charset[$response:charset]

]


Примечание: для корректной работы методов upper и lower класса string с национальными языками (в том числе русским) необходимо корректное задание $request:charset.

Также здесь рекомендуется определить путь к классам вашего сайта:

$CLASS_PATH[/../classes]


И строку соединения с SQL-сервером, используемым на вашем сайте (пример для ODBC):

$SQL.connect-string[odbc://DSN=www_mydomain_ru^;UID=user^;PWD=password]

Примечание: вашем коде вы будете использовать ее так:

^connect[$SQL.connect-string]{…} 


Советуем поместить сюда же определение метода unhandled_exception, который будет выводить сообщение о возможных проблемах на вашем сайте.

Внимание: конечно, Конфигурационный файл можно не использовать, а Конфигурационный метод поместить в файл auto.p в корне веб-пространства, однако в разных местах размещения сервера (например: отладочная версия и основной сервер) конфигурации скорее всего будут различными, и очень удобно, когда эти различия находятся в отдельном файле и вне веб-пространства.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 20.02.2004



Parserconfmethod


Конфигурационный метод


Если в файле определен метод conf,он выполняется первым, до auto, и задает важные системные параметры:

·файлы, описывающие кодировки символов,  

·ограничение на размер HTTP POST-запроса,  

·сервер/программу отправки почты,  

·SQL-драйвера и их параметры,  

·таблицу соответствия расширения имени файла и его mime-типа.  

Рекомендуется поместить этот метод в Конфигурационный файл.

Определение метода:

@conf[filespec]

filespec - полное имя файла, содержащего метод.


Всегда доступна и не нуждается в загрузке файла кодировка UTF-8, являющаяся для Parser кодировкой по умолчанию.

Чтобы сделать доступными для использования Parser другие кодировки, необходимо указать файлы их описывающие, делается это так:

$CHARSETS[

   $.windows-1251[/полный/путь/к/windows-1251.cfg]

   …

]

См. Описание формата файла, описывающего кодировку.

Максимальный размер POST данных:

$LIMITS[

   $.post_max_size(10*0x400*0x400)

]


Параметр отправки писем (см. ^mail:send[…])…

…под Windows и UNIX (под UNIX [3.1.2]) адрес SMTP-сервера

$MAIL[

   $.SMTP[mail.office.design.ru]

]


…под UNIX в safe-mode версиях, настроить программу отправки можно только при сборке Parser из исходных кодов, в бинарных версиях, распространяемых с сайта parser.ru, задана команда

   /usr/sbin/sendmail -i -t -f postmaster

Только в unsafe-mode версиях можно задать программу отправки почты самому:

$MAIL[

   $.sendmail[/custom/mail/sending/program params]

]

и, по умолчанию, используется эта…

   /usr/sbin/sendmail -t -i -f postmaster

…или эта…

   /usr/lib/sendmail -t -i -f postmaster

…команда, в зависимости от вашей системы.

При отправке письма вместо «postmaster» будет подставлен адрес отправителя из письма из обязательного поля заголовка «from».

Также можно задать таблицу SQL-драйверов:



$SQL[

$.drivers[^table::create{protocol driver client

mysql   /full/disk/path/parser3mysql.dll   /full/disk/path/libmySQL.dll

odbc /full/disk/path/parser3odbc.dll

pgsql /full/disk/path/parser3pgsql.dll /full/disk/path/libpq.dll

oracle /path/to/parser3oracle.dll   C:\Oracle\Ora81\BIN\oci.dll?PATH+=^;C:\Oracle\Ora81\bin

}]

]

В колонке client таблицы drivers допустимы параметры клиентской библиотеке, отделяемые знаком ? от имени файла библиотеки, в таком виде:

имя1=значение1&имя2=значение2&…

а также имя+=значение.

Эти переменные будут занесены(=) или добавлены к имеющемуся значению(+=) в программное окружение (environment) перед инициализацией библиотеки. В частности, удобно добавить путь к Oracle библиотекам здесь, если этого не было сделано в системном программном окружении (system environment).

Таблица типов файлов:

#файл, создаваемый ^file::load[…],

#при выдаче в $response:body задаст этот $response:content-type

$MIME-TYPES[^table::create{ext mime-type

zip application/zip

doc application/msword

xls application/vnd.ms-excel

pdf application/pdf

ppt application/powerpoint

rtf application/rtf

gif image/gif

jpg image/jpeg

jpeg image/jpeg

png image/png

tif image/tiff

html text/html

htm text/html

txt text/plain

mts application/metastream

mid audio/midi

midi audio/midi

mp3 audio/mpeg

ram audio/x-pn-realaudio

rpm audio/x-pn-realaudio-plugin

ra audio/x-realaudio

wav audio/x-wav

au audio/basic

mpg video/mpeg

avi video/x-msvideo

mov video/quicktime

swf application/x-shockwave-flash

}]

Расширения имен файлов в таблице должны быть написаны в нижнем регистре. Поиск по таблице нечувствителен к регистру, т.е. файл FACE.GIF получит mime-тип image/gif.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 29.03.2004

Parserexceptions


Системные ошибки


type

Пример возникновения

Описание

parser.compile

^test[}

Ошибка компиляции кода. Непарная скобка, и т.п.

parser.runtime

^if(0).

Методу передано неправильное количество параметров или не тех типов, и т.п.

parser.interrupted

Загрузка страницы прервалась (пользователь остановил загрузку страницы или истекло время ожидания)

number.zerodivision

^eval(1/0), ^eval(1\0) или ^eval(1%0)

Деление или остаток от деления на ноль

number.format

^eval(abc*5)

Преобразование к числу нечисловых данных

file.missing

^file:delete[skdfjs.delme]

файл отсутствует

file.access

^table::load[.]

Нет доступа к файлу

image.format

^image::measure[index.html]

Файл изображения имеет неправильный формат (возможно, расширение имени не соответствует содержимому, или файл пуст?)

sql.connect

^connect[mysql://baduser:pass@host/db]{}

Сервер баз данных не может быть найден или временно недоступен

sql.execute

^void:sql{bad select}

Ошибка исполнения SQL запроса

xml

^xdoc::create{<forgot?>}

Ошибочный XML код или операция

smtp.connect

SMTP сервер не может быть найден или временно недоступен

smtp.execute

Ошибка отправки письма по SMTP протоколу

email.format 

Ошибка в email адресе: адрес пустой или содержит неправильные символы

email.send

Ошибка запуска почтовой программы

http.host

^file::load[http://notfound/there]

Сервер не найден

http.connect

^file::load[http://not_accepting/there]

Сервер найден, но не принимает соединение

http.response

^file::load[http://ok/there]

Сервер найден, соединение принял, но выдал некорректный ответ (нет статуса, заголовка)

http.status

^file::load[http://ok/there]

Cервер выдал ответ со статусом не равным 200 (не успешное выполнение запроса)

http.timeout

Загрузка документа с HTTP-сервера не завершилась в отведенное для нее время




Parserscript


Использование Parser в качестве интерпретатора скриптов


/путь/к/parser3 файл_со_скриптом

x:\путь\к\parser3 файл_со_скриптом

Выполнять скрипты можно и без веб-сервера, достаточно запустить интерпретатор Parser, передав ему в командной строке параметр - имя скрипта. При этом корнем веб-пространства считается текущий каталог.

При этом ошибки попадут в стандартный поток ошибок, который можно перенаправить в желаемый файл так:

команда 2>>error_log

Внимание: не забывайте его время от времени очищать.

На UNIX можно также использовать стандартный подход с заданием команды запуска интерпретатора в первой строке скрипта:

#!/путь/к/parser3

#ваш код

Проверка: ^eval(2*2)

Не забудьте зажечь биты атрибута, разрешающие исполнение владельцу и группе. Команда:

chmod ug+x файл

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 24.02.2004



Requestbody


body. Получение текста запроса


$request:body


Получение текста HTTP POST-запроса.

Вариант использования: можно написать свой XML-RPC сервер (см. http://xmlrpc.org).

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 16.10.2002



Requestcharset


charset. Задание кодировки документов на сервере


$request:charset[кодировка]


Задает кодировку документов, обрабатываемых на сервере.

При обработке запроса считается, что в этой кодировке находятся все файлы на сервере.

По умолчанию используется кодировка UTF-8.

Список допустимых кодировок определяется Конфигурационным методом.

Рекомендуется определять кодировку документов в Конфигурационном файле.

См. также «Задание кодировки ответа».



Requestclass


Класс request


Класс содержит статические поля, которые позволяют получать информацию, передаваемую браузером веб-серверу (по HTTP протоколу).

Для работы с полями форм (<FORM>) и строкой после второго ? (/?a=b?thisText) используйте класс form.

Часть информации о запросе доступна через переменные окружения, см. «Получение значения поля запроса».



Requestdocroot


document-root. Корень веб-пространства   [3.1.2]


$request:document-root[/дисковый/путь/к/корню/вашего/веб-пространства]


По-умолчанию, $request:document-root равен значению, которое задается в веб-сервере.

Однако иногда его удобно заменить.

См. также «Пути к файлам и каталогам».

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 01.04.2004



Requestquery


query. Получение строки запроса


$request:query   


Возвращает строку после ? в URI (значение переменной окружения QUERY_STRING).

Для работы с полями форм (<FORM>) и строкой после второго ? (/?a=b?thisText) используйте класс form.

Пример

Предположим, пользователь запросил такую страницу: http://www.mysite.ru/news/articles.html?year=2000&month=05&day=27

Тогда:

$request:query


вернет:

year=2000&month=05&day=27



Requesturi


uri. Получение URI страницы


$request:uri   


Возвращает URI документа.

Пример

Предположим, пользователь запросил такую страницу: http://www.mysite.ru/news/articles.html?year=2000&month=05&day=27

Тогда:

$request:uri


вернет:

/news/articles.html?year=2000&month=05&day=27



Responsebody


body. Задание нового тела ответа


$response:body[DATA]   

Замещает все тело ответа значением DATA.

DATA - строка (string) или файл (file). Если передан файл с известным content-type (см. поля объекта класса file), этот заголовок передается в пользователю.

См. также $response:download.

Пример замены всего тела на результат работы скрипта

$response:body[^file::cgi[script.cgi]]


Заменит весь ответ результатом работы программы script.cgi.


Пример выдачи создаваемой картинки

$square[^image::create(100;100;0x000000)]

^square.circle(50;50;10;0xFFFFFF)

$response:body[^square.gif[]]


В браузере будет выведен черный квадрат с белой окружностью. Кроме того, автоматически будет установлен нужный тип файла (content-type) по таблице MIME-TYPES.



Responsecharset


charset. Задание кодировки ответа


$response:charset[кодировка]


Задает кодировку ответа.

После обработки запроса результат перекодируется в эту кодировку.

По умолчанию используется кодировка UTF-8.

Список допустимых кодировок определяется Конфигурационным методом.

Рекомендуется определять кодировку документов в Конфигурационном файле.

См. также «Задание кодировки документов на сервере».



Responseclass


Класс response


Класс позволяет дополнять стандартные HTTP-ответы сервера. Класс не имеет конструкторов для создания объектов.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 02.12.2002



Responseclear


clear. Отмена задания новых заголовков HTTP-ответа


^response:clear[]   

Метод отменяет все действия по переопределению полей ответа.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 16.10.2002



Responsedownload


download. Задание нового тела ответа


$response:download[DATA]   

Идентичен $response:body, но выставляет флаг, который браузер воспринимает как «Предложить пользователю сохранить файл на диске».

Браузеры умеют отображать файлы некоторых типов прямо внутри своего окна (например: .doc, .pdf файлы).

Однако бывает необходимо дать возможность посетителю скачать файл по простому нажатию на ссылку.

Пример: выдача PDF файла

Посетитель заходит на страницу с таким HTML…

<a href="/download/documentation.html">Скачать документацию</a>


download_documentation.html:

$response:download[^file::load[binary;documentation.pdf]]


…и нажимает на ссылку, браузер предлагает ему Скачать/Запустить.



Responsefields


Заголовки HTTP-ответа


$response:поле[значение]

$response:поле

Поле соответствует заголовку HTTP-ответа, выдаваемого Parser. Его можно как задавать, так и считывать. Значением может быть дата, строка или хеш с обязательным ключом value. Дата может использоваться и в качестве значения поля и в качестве значения атрибута поля, при этом она будет стандартно отформатирована.

Примечание: имя поля, при задании значения, преобразуется к нижнему регистру, а при считывании ищется в нижнем регистре.

Пример перенаправления браузера пользователя на стартовую страницу

$response:location[/]

$response:refresh[

   $.value[0]

   $.url[/]

]


Пример задания заголовка expires в значение «завтра»

$response:expires[^date::now(+1)]



Sokr


Принятые обозначения


ABCDEFGH - Код Parser в примерах для визуального отличия от HTML (Courier New, 10). Для удобства работы с электронной документацией дополнительно выделен цветом.

ABCDEFGH - Файлы и каталоги, рассматриваемые в рамках урока.

ABCDEFGH - Дополнительная и справочная информация.

[3.1] - Номер версии Parser, начиная с которой доступна данная функция или опция.

В справочнике символ "|" равнозначен союзу ИЛИ.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 04.03.2004



Stats


Статические поля и методы


Вызов статического метода

^класс:метод[параметры]   

Вызов статического метода класса.

Примечание: точно так же вызываются динамические методы родительского класса (см. Создание пользовательского класса).

Значение статического поля

$класс:поле   


Получение значения статического поля класса.

Задание статического поля

$класс:поле[значение]           

Задание значения статического поля класса.



Statusclass


Класс status


Класс предназначен для анализа текущего состояния скрипта на Parser.

Его использование поможет вам найти узкие места в ваших скриптах.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 12.05.2003



Statusmemory


memory. Информация о памяти под контролем сборщика мусора [3.1]


Это поле - хеш с информацией о памяти, находящейся под контролем сборщика мусора.

Поле

Значение (в килобайтах)

Детали

used

Занято

В это число не включен размер cлужебных данных самого сборщика мусора.

free

Свободно

Свободная память скорее всего фрагментирована.

ever_allocated_since_compact

Было выделено с момента последней сборки мусора. См. memory:compact.

Между сборками мусора это число только растет.

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

ever_allocated_since_start

Было выделено за все время обработки запроса

Это число только растет.

Ни факты сборки мусора, ни освобождения памяти между сборками мусора на него не влияют.

Рекомендуемый способ анализа

Временно добавьте вызовы…

^musage[before XXX]

^musage[after XXX]


…вокруг интересующего вас блока вот этого метода…

@musage[comment][v;now;prefix;message;line]

$v[$status:memory]

$now[^date::now[]]

$prefix[[^now.sql-string[]] $env:REMOTE_ADDR: $comment]

$message[$v.used $v.free $v.ever_allocated_since_compact $v.ever_allocated_since_start $request:uri]

$line[$prefix $message ^#0A]

^line.save[append;/musage.log]

$result[]


…и проанализируйте журнал.

Важно: в ходе работы Parser захватывает у операционной системы дополнительные блоки памяти по мере необходимости. Поэтому есть моменты, когда и used и free, увеличиваются. Это нормально.

Примечание: для записи журнала не рекомендуется использовать веб-пространство.



Statuspid


pid. Идентификатор процесса


Идентификатор процесса (process) операционной системы, в котором работает Parser.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 23.03.2004



Statusrusage


rusage. Информация о затраченных ресурсах


Это поле - хеш с информацией о ресурсах сервера, затраченных на данный момент системой на обработку вашего Parser-скрипта.

Не все операционные системы умеют возвращать эти значения (WinNT/Win2000/WinXP умеет все, Win98 умеет только tv_sec и tv_usec [3.0.8]).

Ключ

Единица

Описание значения

Как уменьшить?

utime

секунда

Чистое время, затраченное текущим процессом

(не включает время, когда работали другие задачи)

Упростить манипуляции с данными внутри Parser (улучшить алгоритм, переложить часть действий на SQL-сервер)

stime

секунда

Время, сколько система читала ваши файлы, каталоги, библиотеки

Уменьшить количество и размер необходимых для работы файлов, не подключать ненужные для обработки данного документа модули

maxrss

блок

Память, занимаемая процессом

Уменьшить количество загружаемых ненужных данных.

Найти и исправить все «select * …», задав список действительно необходимых полей. Не загружать из SQL-сервера ненужные записи, отфильтровать как можно больше средствами самого SQL-сервера.

Точное системное время. Позволяет оценить траты времени на ожидание ответа от SQL-, HTTP-, SMTP-серверов.

Сколько прошло с Epoch…

Упростить SQL запросы, для MySQL воспользуйтесь EXPLAIN, см. http://www.mysql.com/doc/en/EXPLAIN.html; для Oracle: EXPLAIN PLAN, см. документацию по серверу; для других SQL-серверов: см. их документацию.

tv_sec

секунда

…целых секунд;

tv_usec

микросекунда

(10E-6)

…еще прошло микросекунд

(миллионных долей секунды)

Рекомендуемый способ анализа

Временно добавьте в конец вашего скрипта вызов…

^rusage[total]


…вот этого метода…

@rusage[comment][v;now;prefix;message;line;usec]

$v[$status:rusage]

$now[^date::now[]]

$usec(^v.tv_usec.double[])

$prefix[[^now.sql-string[].^usec.format[%06.0f]] $env:REMOTE_ADDR: $comment]

$message[$v.utime $v.stime $request:uri]

$line[$prefix $message ^#0A]

^line.save[append;/rusage.log]



$result[]



…и проанализируйте журнал.

Для более точного анализа, добавьте вызовы…

^rusage[before XXX]

^rusage[after XXX]



…вокруг интересующего вас блока.



Примечание: для записи журнала не рекомендуется использовать веб-пространство.

WinNT/2K/XP

Под этими OS доступен ряд дополнительных значений:



Ключ



Единица



Описание значения



Как уменьшить?



ReadOperationCount

ReadTransferCount



штук

байт



Количество операций чтения с диска и суммарное количество считанных байт



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

Больше использовать SQL-сервер, меньше файлы.



WriteOperationCount

WriteTransferCount



штука

байт



Количество операций записи на диск и суммарное количество записанных байт





OtherOperationCount

OtherTransferCount



штука

байт



Количество других операций с диском (не чтения/записи) и суммарное количество переданных байт





PeakPagefileUsage

QuotaPeakNonPagedPoolUsage

QuotaPeakPagedPoolUsage





байт



Максимальное количество памяти в файле подкачки (swap-файле)



см. комментарий к maxrss выше.


Statustid


tid. Идентификатор потока


Идентификатор потока (thread) операционной системы, в котором работает Parser.

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 23.03.2004



Stringclass


Класс string


Класс для работы со строками. В выражении строка считается определенной (def), если она не пуста. Если в строке содержится число, то при попытке использовать его в математических выражениях содержимое строки будет автоматически преобразовано к double. Если строка пуста, ее числовое "значение" в математических выражениях считается нулем.

Создание объекта класса string:

$str[Строка, которая содержится в объекте]

Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 12.02.2004