Расширение представляет из себя организованный специальным образом скрипт на языке lua .
Для начала использования расширений в HandyCache необходимо чтобы в папке HandyCache находился файл библиотеки lua5.x.dll.
В начале расширения располагается заголовок. Заголовок имеет следующую структуру:
--[[ <HCEXTENSION> @field value @field value @field value ... @field value </HCEXTENSION> ]]
Имя (field) |
Значение (value) |
name | Наименование расширения |
author | Имя автора расширения |
version | Номер версии расширения |
description | Краткое описание расширения |
rule | Правило (регулярное выражение), которым будет проверяться URL запроса перед вызовом расширения. В заголовке может быть несколько полей rule. |
exception | Исключение (регулярное выражение), которым будет проверяться URL запроса перед вызовом расширения. В заголовке может быть несколько полей exception. |
event | Наименование события, для обработки которого будет вызываться расширение, и через косую черту имя функции, предназначенной для обработки этого события. В заголовке может быть несколько полей event. |
--[[ <HCEXTENSION> @name Save or block 403 and 404 @author DenZzz @version 0.01 @description Сохраняет или блокирует ответы 403 и 404 @exception _rtsi?_|rts_chart_ru|informer\.rts\.ru/|aton-line\.ru/.*index\.gif @exception ^http://[^/]*rambler\.ru/|^http://192\.168\.\d+\. @event AnswerHeaderReceived/answer </HCEXTENSION> ]]
За заголовком следуют функции-обработчики событий, а также функции вызываемые из этих обработчиков. Когда в HandyCache наступает событие, для которого зарегистрирован обработчик, вызывается соответсвующая функция.
Событие |
Условия возникновения |
Init | Возникает при загрузке расширений во время старта HandyCache и при нажатии кнопки Перечитать расширение на вкладке Настройки/Расширения. При загрузке расширения текст файла расширения сохраняется в памяти. Поэтому, если файл расширения изменился, нужно выделить расширение в списке и нажать кнопку Перечитать расширение . |
Options | Возникает при нажатии кнопки Настройки расширения на вкладке Настройки/Расширения . |
Timer1s | Возникает раз в секунду. |
Timer1m | Возникает раз в минуту. |
URLToFileNameConverting | Возникает, когда требуется выполнить преобразование URL в имя файла в кэше. |
RequestHeaderReceived | Возникает, когда получен заголовок запроса от клиента. |
BeforeRequestHeaderSend | Возникает, когда заголовок запроса готов к отправке на сервер. |
AnswerHeaderReceived | Возникает, когда получен заголовок ответа от сервера. |
BeforeAnswerHeaderSend | Возникает, когда заголовок ответа готов к отправке клиенту. Заголовок может быть получен от сервера или сформирован самим HandyCache. |
BeforeAnswerBodySend | Возникает, когда получена очередная порция данных для отправки клиенту. Данные могут быть получены от сервера или взяты из кэша. Если данные упакованы, то они перед передачей обработчику распаковываются. |
Destroy | Возникает при завершении работы расширения (при удалении расширения по кнопке Удалить расширение, при перезагрузке расширения по кнопке Перечитать расширение, при закрытии HandyCache) |
Перед вызовом функций расширения HandyCache создает в lua-машине две таблицы: hc и re. В первой собраны значения и функции, позволяющие получать информацию о значениях внутренних переменных HandyCache и изменять некоторые из них. Во второй собраны функции, позволяющие использовать в расширениях возможности библиотеки регулярных выражений PCRE .
Имя |
Допустимые действия | События |
Допустимые значения |
Описание |
script_name | чтение |
Init, Options, Timer1s, Timer1m, URLToFileNameConverting, |
"<строка>" | Имя текущего расширения. |
event | чтение |
Init, Options, Timer1s, Timer1m, URLToFileNameConverting, |
"<строка>" | Содержит наименование обрабатываемого события. |
ini_path | чтение |
Init, Options, Timer1s, Timer1m, URLToFileNameConverting, |
"<строка>" | Содержит путь к папке с файлами настройки. |
cache_path | чтение |
Init, Options, Timer1s, Timer1m,
URLToFileNameConverting, |
"<строка>" | Содержит путь к папке кэша. |
url | чтение | URLToFileNameConverting, RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | В соответствие с RFC 2616 п.3.2.2 | URL запроса |
method | чтение | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | В соответствие с RFC 2616 п.9 | Метод, использованный в запросе |
use_proxy | чтение, запись | RequestHeaderReceived, BeforeRequestHeaderSend | "<строка>" | Содержит параметры внешнего HTTP прокси-сервера, назначенного для текущего запроса. Пример: "192.186.55.2:8080" или "proxy.com:8081" |
use_proxy_login | чтение, запись | RequestHeaderReceived, BeforeRequestHeaderSend | "<строка>" | Содержит логин доступа внешнего HTTP прокси-сервера, назначенного для текущего запроса (basic-авторизация). Пример: "user:password" |
use_bound_ip | чтение, запись | RequestHeaderReceived, BeforeRequestHeaderSend | "<строка>" | Содержит IP-адрес сетевого устройства, через которое будет отправлен запрос. Пример: "192.186.0.2" |
request_header | чтение, запись | RequestHeaderReceived, BeforeRequestHeaderSend | В соответствие с RFC 2616 | Содержит заголовок запроса. Если расширение изменит значение этой переменной, измененный заголовок будет отправлен серверу. |
cache_file_name | чтение | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived | "<строка>" | Имя файла в кэше, соответсвующего текущему запросу. |
cache_file_size | чтение | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived | <число> | Размер файла в кэше (-1 если файла нет). |
cache_file_age | чтение | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived | <число> | Возраст файла в кэше в секундах. |
cache_file_content_type | чтение | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived | "<строка>" | Тип содержимого файла в кэше. |
user_name | чтение | URLToFileNameConverting, RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | "<строка>" | Имя пользователя, от которого поступил запрос. |
user_from_internet | чтение | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | <число> | Количество данных, полученных пользователем из интернета за текущие сутки. |
user_from_cache | чтение | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | <число> | Количество данных, полученных пользователем из кэша за текущие сутки. |
user_to_internet | чтение | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | <число> | Количество данных, отправленных пользователем за текущие сутки. |
answer_header | чтение, запись | RequestHeaderReceived, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | В соответствие с RFC 2616 | Заголовок ответа, полученный от сервера или сформированный расширением. Если этой переменной расширение присвоило новое значение, то клиенту будет передан измененный заголовок. |
answer_body | чтение, запись | RequestHeaderReceived, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | "<строка>", "file=<имя файла>", "file=URLToCache(<URL>)" |
При обработке событий RequestHeaderReceived, AnswerHeaderReceived,
BeforeAnswerHeaderSend содержит тело ответа, сформированное расширением. Если этой переменной присвоено значение, то клиенту будет передано содержимое этой переменной в качестве тела ответа. При обработке события BeforeAnswerBodySend через эту переменную расширение получает очередную порцию данных для обработки. В эту же переменную расширение записывает результат обработки. |
last_part | чтение | BeforeAnswerBodySend | true, false | Принимает значение true, когда расширение вызывается последний раз для обработки текущего запроса. |
action | чтение, запись | RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived | Для RequestHeaderReceived: "stop", "dont_update", "only_from_cache", Для AnswerHeaderReceived: "stop", "dont_update", "save", "dont_save" |
Действие, которое должен выполнить НС:
|
read_from_cache_on | чтение, запись | RequestHeaderReceived | true, false | Присвоение false запрещает чтение из кэша для текущего запроса. |
white_mask | чтение, запись | RequestHeaderReceived | "<строка>" | Маска Белого списка - в эту переменную можно добавить по одному символу для каждого из списков, если нужно, чтобы этот список не работал с данным запросом. Для обозначения списков можно использовать символы:
|
file_speed_limit | чтение, запись | RequestHeaderReceived, AnswerHeaderReceived | <число> | Если этой переменной присвоить значение больше 0, то это значение будет использоваться как лимит скорости (в байтах в секунду) для загрузки данного файла. |
user_speed_limit | чтение, запись | RequestHeaderReceived, AnswerHeaderReceived | <число> | Если этой переменной присвоить значение больше 0, то это значение будет использоваться как лимит скорости (в байтах в секунду) для данного пользователя до задания другого значения или перезапуска HandyCache. hc.user_speed_limit=0 снимает ограничения скорости для данного пользователя. |
dont_load_large_files_on | чтение |
Init, Options, Timer1s, Timer1m, |
true, false | Принимает текущее состояние опции Не загружать большие файлы. |
speed_limit_on | чтение |
Init, Options, Timer1s, Timer1m, |
true, false | Принимает текущее состояние опции Ограничить скорость загрузки. |
offline_on | чтение |
Init, Options, Timer1s, Timer1m, |
true, false | Принимает текущее состояние опции Автономный режим. |
monitor_string | чтение, запись | URLToFileNameConverting, RequestHeaderReceived, BeforeRequestHeaderSend, AnswerHeaderReceived, BeforeAnswerHeaderSend, BeforeAnswerBodySend | "<строка>" | Содержит значение, присвоенное предыдущими расширениями при обработке текущего события. Расширение может присвоить свое значение этой переменной. Значение этой переменной будет выведено в колонке Правила в Мониторе в строке текущего запроса. |
Имя |
Описание |
shell_execute |
Функция является оберткой Windows API функции ShellExecute (аргумент Operation="Open"). Подробнее смотрите здесь. Аргументы функции: Возвращаемое значение: Возвращает строку 'OK' при успешном вызове функции. В случае ошибки, возвращает сообщение об ошибке. Пример использования: hc.shell_execute('notepad.exe', 'stat.txt', nil, 'SW_SHOW') |
play_sound |
Функция является оберткой Windows API функции PlaySound. Подробнее смотрите здесь. Аргументы функции: Возвращаемое значение: нет. Примеры использования: |
execute_cmd |
Функция выполняет команду (те же команды, что и для утилиты HCCmd). Аргументы функции: Список команд.
Возвращаемое значение: нет. Примеры использования: |
put_msg |
Функция вызывает появление на экране информационного окошка с заданным сообщением. Аргументы функции: Возращаемое значение: нет. Пример использования: hc.put_msg('Очистка кэша запущена') |
put_to_log |
Функция помещает заданное сообщение в лог программы. Аргументы функции: Возращаемое значение: нет. Пример использования: hc.put_to_log('method='..hc.method) |
get_keyboard_state |
Функция получает список нажатых клавиш. Аргументы функции: нет. Возвращаемое значение: Строка со списком
нажатых клавиш. Пример использования: |
systime_to_str |
Функция преобразует системное время в строковое представление. Аргументы функции: Возвращаемое значение: Время в строковом представлении. Пример использования: s = hc.systime_to_str(os.time(), false) |
str_to_systime |
Функция преобразует строковое представление времени в числовое. Аргументы функции: Возращаемое значение: Время в числовом представлении (время в секундах, прошедшее после 0 часов 0 минут 1 января 1970 года). Пример использования: |
prepare_path |
Функция создает каталоги в соответсвии с путем, заданным аргументом. Аргументы функции: Возвращаемое значение: Нет. Пример использования: hc.prepare_path('c:\program files\handycache\cache\example') |
call_me_for |
Функция регистрирует функцию текущего расширения в качестве обработчика события для текущего запроса. Аргументы функции: Возвращаемое значение: Нет. Пример использования: hc.call_me_for('BeforeAnswerBodySend', 'body') |
server_disconnect |
Разрывает соединение с сервером. Аргументы функции: Нет. Возвращаемое значение: Нет. Пример использования: hc.server_disconnect() |
prepare_url |
Функция выполняет преобразование заданного URL в имя файла в кэше без вызова обработчика события URLToFileNameConverting. Аргументы
функции: Возвращаемое значение: Имя файла в кэше, полученное из заданного URL с помощью встроенного алгоритма преобразования; Пример использования: local s= hc.prepare_url(hc.url) |
preform_cache_file_name |
Функция задает имя файла в кэше, которое может быть сформировано расширением в обработчике события URLToFileNameConverting. HandyCache, если потребуется, может изменить заданное имя файла для его адаптации к текущему состоянию кэша. Путь к файлу может быть задан абсолютным (начинается с имени диска) или относительным. Во втором случае в начало имени добавляется путь к папке кэша. Замечание. По умолчанию HandyCache не использует файлы вне папки кэша. Чтобы разрешить использование файлов вне папки кэша, нужно в файл HandyCache.ini в секции MainForm добавить строку ReadOnlyFromCachePath=False Аргументы функции: Возвращаемое значение: Нет. Пример использования: hc.preform_cache_file_name('site1.ru\example.jpg') |
get_cache_file_name |
Функция получает имя файла в кэше и его наличие для заданного URL. Аргументы функции: Возвращаемое значение: Первым значением возвращается имя файла; вторым - наличие файла в кэше (true/false ); Пример использования: s,e=hc.get_cache_file_name('http://handycache.ru/') |
delete_cache_file |
Функция удаляет файл в кэше, соответствующий заданному URL. Аргументы функции: Возвращаемое значение: Нет. Пример использования: hc.delete_cache_file('http://site.ru/example.gif') |
update_url_info |
Функция удаляет информацию о заданном файле из RAM-кэша и очищает внутренние переменные HandyCache, хранящие информацию об этом файле. Если информация о файле понадобится, она будет добываться из дискового кэша заново. Аргументы
функции: Возвращаемое значение: Нет. Пример использования: hc.update_url_info('http://handycache.ru/') |
set_global |
Функция позволяет сохранить в памяти значение глобальной переменной. Сразу после завершения работы этой функции присвоенное значение будет доступно из других потоков. Аргументы функции: Возвращаемое значение: Нет. Пример использования: hc.set_global('MyVar', 'Value') |
get_global |
Функция позволяет получить значение глобальной переменной. Аргументы функции: Возвращаемое значение: Значение переменной name. Если переменной с заданным именем нет, то возвращается nil. Пример использования: |
window_pos |
Функция получает положение и размер главного окна HandyCache. Аргументы функции: Нет. Возвращаемое значение: Первым значением возвращается горизонтальная координата верхнего левого угла окна; вторым - вертикальная координата верхнего левого угла окна; третьим - ширина окна; четвертым - высота окна; Пример использования: x,y,w,h=hc.window_pos() |
enable_extension |
Функция позволяет разрешать или запрещать работу расширения с заданным именем. Аргументы
функции: Возвращаемое значение: Текущее состояние разрешения работы расширения (true/false). Пример использования: hc.enable_extension('Cache cleaner', true) |
reload_extension |
Функция заставляет HandyCache перечитать файл расширения с заданным именем с последущим вызовом обработчика события Init. Аргументы
функции: Возвращаемое значение: Нет. Пример использования: hc.reload_extension('Cache cleaner') |
Имя |
Описание |
set_regex |
Задает регулярное выражение. Аргументы функции: Возвращаемое значение: Нет. Пример использования: re.set_regex([[(.*\.).*]]) |
set_subj |
Задает строку, над которой буде исполняться регулярное выражение. Аргументы функции: Возвращаемое значение: Нет. Пример использования: re.set_subj(hc.answer_header) |
set_callout |
Задает имя callout-функции. Аргументы функции: Возвращаемое значение: Нет. Пример использования: re.set_callout('callout_func') |
match |
Вызывает исполнение регулярного выражения. Аргументы функции: Возвращаемое значение: Если в результате исполнения регулярного выражения найдена хотя бы одна подстрока, то первым значением функция возвращает таблицу; в этой таблице для каждой найденной подстроки находится по паре значений: begin_pos и end_pos; эти значения задают соответственно позиции в subj-строке для начала и конца каждой найденной подстроки; если в результате исполнения регулярного выражения не найдено ни одной подстроки, то первому возвращаемому значению присваивается nil, а в качестве второго значения возвращается строка с описанием ошибки. Пример использования: |
substr_count |
Получает количество подстрок, найденных в результате последнего исполнения регулярного выражения. Аргументы функции: Нет. Возвращаемое значение: Количество найденных подстрок. Пример использования: local num= re.substr_count() |
substr |
Получает подстроку с заданным номером, найденную в результате последнего исполнения регулярного выражения. Аргументы функции: Возвращаемое значение: Возвращается подстрока; если подстроки с заданным номером нет, то возвращается nil ; Пример использования: local s=re.substr(0) |
substr_length |
Получает длину подстроки с заданным номером, найденной в результате последнего исполнения регулярного выражения. Аргументы функции: Возвращаемое значение: Возвращается длина подстроки; если подстроки с заданным номером нет, то возвращается -1; Пример использования: local l=re.substr_length(0) |
substr_offset |
Получает смещение позиции начала подстроки с заданным номером в subj-строке, найденной в результате последнего исполнения регулярного выражения. Аргументы функции: Возвращаемое значение: Возвращается смещение подстроки; если подстроки с заданным номером нет, то возвращается -1 ; Пример использования: local offset=re.substr_offset(0) |
named_substr_index |
Получает индекс именованной подстроки, найденной в результате последнего исполнения регулярного выражения. Аргументы функции: Возвращаемое значение: Возвращается индекс подстроки с заданным именем; если подстроки с заданным именем нет, то возвращается -1 ; Пример использования: |
find |
Получает значение заданной подстроки. Аргументы функции: Возвращаемое значение: Если в результате исполнения регулярного выражения найдена подстрока с заданным номером, то первым значением функция возвращает эту подстроку; если не найдена заданная подстрока, то первому возвращаемому значению присваивается nil; если при исполнении регулярного выражения произошла ошибка, то в качестве второго значения возвращается строка с описанием ошибки. Пример использования: local s=re.find(hc.answer_header, [[^Content-Length: (.+)]], 1) |
replace |
Заменяет в строке найденные подстроки заданным значением. Аргументы функции: Возвращаемое значение: Если при исполнении регулярного выражения не было ошибок (даже если не найдено ни одной подстроки), то первым значением функция возвращает строку - результат обработки (в противном случае nil); вторым значением возвращается число произведенных замен; третьим значением функция возвращает позицию в исходной строке, с которой начинается неизмененная часть; если в результате исполнения регулярного выражения произошла ошибка, то четвертым значением возвращается строка с описанием ошибки. Пример использования: s=re.replace(hc.answer_header, [[(?-s)(Cache-Control:.*\r\n)]], nil) |
Для исполнения обработчиков событий в каждом потоке-обработчике запроса клиента создается своя lua-машина. Глобальные переменные, создаваемые обработчиками в lua -машине доступны для всех обработчиков, которые будут вызваны позднее в этом потоке.
При загрузке каждого расширения в HandyCache создается пустая таблица hc_static, привязанная к этому расширению. Следом для каждого расширения вызывается обработчик Init (если таковой зарегистрирован). Он может сохранить значения в таблице hc_static и они будут доступны во всех обработчиках этого расширения при обработке всех последующих запросов. Также обработчик Options (вызывается нажатием кнопки Настройки расширения на вкладке Расширения ) может изменить значения в этой таблице (или добавить новые) и они будут доступны при обработке всех последующих запросов.
Когда создается поток-обработчик запроса клиента, в нем создается копия таблицы hc_static для каждого расширения и внутри потока работа идет уже с этой копией. Обработчики событий могут добавлять/изменять переменные, но доступны эти значения будут только внутри этого потока.
Обработчики событий при необходимости могут сохранять значения в глобальных переменных. Значения, сохраненные в глобальных переменных, с момента присвоения и до завершения работы программы становятся доступны из всех обработчиков всех потоков. Для доступа к глобальным переменным используются функции hc.set_global и hc.get_global .
Расширения HandyCache как и другие программы на lua могут использовать графический интерфейс пользователя. Вот несколько примеров предназначенных для таких целей библиотек: wxlua, LuaInterface, VCLua. Мне наиболее подходящей для расширений HandyCache показалась библиотека VCLua (сравнительно просто использовать, малый размер dll). Пример использования этой библиотеки в обработчике события Options можно найти в расширении eCacheCleaner (для использования этой библиотеки в папке HandyCache должен находиться файл vcl.dll ).
В файле LuaTest.exe находится программа для тестирования работы расширений. Для тестирования расширения загрузите его в эту программу и нажмите кнопку Перечитать. В появившемся ниже списке обработчиков событий выберите интерисующий и нажмите кнопку Выполнить (F5) для вызова выделенной функции-обработчика. Чтобы выполнить функцию, отсутствующую в списке, впишите ее имя в поле ввода рядом с кнопкой Выполнить и нажмите эту кнопку.
Информацию о языке lua можно найти, например, здесь: