Пример исполнения программного кода

From SunFlurry wiki
Jump to: navigation, search

Данная онлайн демонстрация возможностей функции контролируемой среды исполнения ExecEx использует консольный http сервер и позволяет исполнять произвольный код программы непосредственно из текущей веб-страницы. Консольный сервер не использует подключение к базе данных, поэтому код обращения к базе данных не сможет работать (для демонстрации работы с базой данных, скачайте демонстрационную версию клиента программы). Если сервер (работающий на машине с Apache http сервером) в данный момент недоступен, демонстрация не сможет функционировать правильно и будет выдавать сообщение об ошибке. Для уменьшения количества векторов атаки на консольный сервер, функция ExecEx вызывается со следующими ограничениями (см. описание функции):

  • второй аргумент при вызове имеет значение: 0b1111111111111111111 (запрещены все опасные и визуальные функции, однако, работа с картинками разрешена).
  • исполнение имеет ограничение по времени, фрагмент не может исполняться дольше 5 секунд.

Ограничений по количеству запросов к демонстрации нет, однако, встроенная защита от DOS выведет Captcha и запросит ее решение после нескольких запросов, если Captcha решена неверно несколько раз подряд, будет включена защита, которая не позволит выполнять запросы с текущего IP-адреса в течение двух часов. Описание Captcha и дополнительную информацию по тестовому http серверу ищите в статье Онлайн демонстрации. Для данного примера использован объект XMLHttpRequest, работающий по технологии AJAX. Во время исполнения кода браузер ожидает получения информации от консольного сервера, по мере поступления, она будет выводиться в лог в нижней части страницы. Следующие функции и события выводят информацию в лог страницы:

  • Message и Writeln -- стандартные функции для вывода информации в лог.
  • Переменная Result позволяет возвратить текстовое значение, которое будет выведено на странице последним, выделено размером шрифта, и отделено от остального вывода полосой.
    • Особое значение переменной Result может быть с типом картинка, в этом случае, это значение будет перекодировано в строку, а затем в base64 и отослано с меткой о том, что это картинка-результат. Картинка будет выведена на странице после полосы, отделяющей результат от обычного текста. Таким образом демонстрируется возможность передачи в одном пакете данных разного типа (см. ниже примеры).
  • При ошибках компиляции и необработанных исключениях, информация также будет выведена в лог.
  • При превышении времени исполнения, программа прерывается и информация об ошибке будет выведена в лог.

Путь прохождения запроса и ответа на запрос выглядит следующим образом:

  1. Java-скрипт в браузере создает URL запроса в виде sfsys.ru/sfsl/?ExecuteReq=1 и отправляет его на сервер с помощью объекта XMLHttpRequest, в теле запроса выгружается программный код, размещенный на этой странице.
  2. Apache http сервер получает POST запрос и передает его на адрес локального консольного SFSL сервера (прокси-запрос)
  3. Локальный консольный клиент создает событие типа OnTCPConnection и передает программе TCP объект соединения с Apache http сервером
  4. Программа создает новый поток, и запускает обработку, которая будет заниматься обслуживанием соединения
    1. Обработка получает http заголовок с помощью HTTPReceiveHeader и находит POST запрос с помощью HTTPGetOperation, после чего также получает тело запроса (HTTPReceiveBody) с кодированном в UTF-8 кодом данной страницы.
    2. Обработка создает обратный пакет, не заполняя поле Content-Length (так как информация будет передаваться по мере поступления и ее размер заранее неизвестен) и отправляет его с помощью HTTPSend, не разрывая текущего соединения.
    3. Обработка выполняет функцию ExecEx с заданной процедурой вывода информации.
      1. Процедура вывода информации, при получении новой строки, переводит ее в формат html и отсылает по активному соединению добавляя метку конца отрезка текста в размере 32-х символов с кодами 0, такое количество добавочных символов может быть необходимо при работе по стандарту https, так как передача информации производится блоками, не равными одному байту.
      2. Apache http сервер получает информацию и отправляет ее, в свою очередь, в ожидающий браузер.
      3. Браузер получает очередной блок информации, разделяет ее на отрезки с помощью меток их концов, и выводит ее в лог отдельными параграфами.
    4. По окончании исполнения функции, обработка разрывает связь, работа окончена.

Примеры кода

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

//Простейший пример, показывающий работу с переменной результата Result и выводом информации

//Изменяем переменную результата
Result:="Hello, World!";

//Выводим произвольную информацию. Заметьте, эта информация будет выведена в лог до текста результата!
Message("Вывод информации с помощью функции Message");
//Данный пример показывает, как при превышении времени исполнения, исполнение будет прервано и в лог страницы будет введено сообщение об ошибке
//Пример также демонстрирует разнообразную окраску лога с помощью функции Message

//Выводим сообщения с разными стилями
Message("Простой текст");
Message("Голубой (нейтральный) текст",".");
Message("Зеленый (положительный) текст","i");
Message("Текст об ошибке","!");
Message("Текст о серьезной ошибке","!!");
Message("Текст о критической ошибке","!!!");

//Ниже дается цикл, который будет исполняться не менее 10 секунд, однако, время исполнения ограничено пятью
//  данный цикл никогда не будет завершен.
For i:=1 To 100 Do
  Message("Цикл, значение i:="+i);
  Sleep(100);
EndDo;
//Данное сообщение не будет выедено
Message("Цикл окончил работу!");


//Данный пример взят со страницы описания функции DecToBase
//Будет выведено "11101110001010001111010101"
Message(DecToBase(62432213,2));

//Будет выведено "186A0"
Message(DecToBase(100000,16));

//Будет выведено "FFFFFFFFFFFFFFFF" (отрицательное основание используется для представления беззнаковых чисел, в числе -1 все 64 бита установлены)
Message(DecToBase(-1,-16));

//Будет выведено "-BCPNB"
Message(DecToBase(-77777,16,"ABCDEFGHIJKLMNOP"));


//Данный пример взят со страницы описания функции Picture.Rectangle
//Он позволяет создать и присвоить переменной-результату картинку, которая будет выведена на эту страницу
aPic:=Picture.Create(400,400);
aPic.Rectangle(1,1,200,200,,_CLR_RED);
aPic.Rectangle(201,1,400,200,,_CLR_BLUE);
aPic.Rectangle(1,201,200,400,,_CLR_GREEN);
aPic.Rectangle(201,201,400,400,,_CLR_YELLOW);
aPic.Text(6,6,"1","Tahoma|40|B|"+DecToBase(_CLR_YELLOW,16),,,,3);
aPic.Text(206,6,"2","Tahoma|40|B|"+DecToBase(_CLR_GREEN,16),,,,3);
aPic.Text(6,206,"3","Tahoma|40|B|"+DecToBase(_CLR_BLUE,16),,,,3);
aPic.Text(206,206,"4","Tahoma|40|B|"+DecToBase(_CLR_RED,16),,,,3);
aPic.Rectangle(5,5,aPic.Width-5,aPic.Height-5,_CLR_RED);
Result:=aPic;


Программа для исполнения: