Реализация поставленной задачи
Сначала опишем сам процесс, направленный на получение отображения необходимой формулы: участник форума во время написания сообщения может использовать тег [TeX] (обязателен закрывающий тег [/TeX]), внутри которого необходимо написать требуемую формулу, используя язык разметки TeX. Далее первый хук перехватывает весь текст сообщения и изменяет теги [TeX] и [/TeX] на теги вида [TeX:$uid] и [/TeX:$uid] для возможной дальнейшей более тесной интеграции с форумом. Второй хук выполняет непосредственные преобразования всех формул, заключенных в теги [TeX] и [/TeX] в картинки необходимого формата (gif или png) с последующим вставлением картинок в отправляемый текст сообщения. При наведении курсора на картинку всплывает исходный текст формулы. Преобразование формул в картинки происходит следующим образом: 1. весь текст между тегами формул заносится в массив для удобной обработки; 2. далее идет обработка каждой формулы: проверка на корректность; 3. во временной директории создается файл с расширением tex, который содержит стандартное оформление документа с отдельной формулой, и случайным именем; 4. создается dvi файл, используя latex; 5. этот dvi файл конвертируется в Postscript (ps), используя dvips (tetex); 6. конвертирование, обрезка и добавление прозрачности, используя convert из пакета ImageMagick, в результате получается требуемая картинка; 7. далее имя конечной картинки рассчитывается через применение функции необратимого шифрования md5 (), которая является стандартной в языке PHP, параметром этой функции является текст формулы; полученное имя является уникальным для данной формулы; 8. очистка временной директории от использовавшихся файлов; 9. в текст сообщения передается ссылка на получившуюся картинку;
10. в случае ошибки при данном процессе выводится соответствующее предупреждение («[unparseable or potentially dangerous latex formula]»). Практическая часть. Часть php-скрипта («posting.php») форума, в которую были внесены необходимые изменения(хуки) для перехвата текста сообщения: if ($ submit || $ preview || $ refresh) // Отправка, предварительный просмотр написанного сообщения { $post_data ['topic_cur_post_id'] = request_var ('topic_cur_post_id', 0); $post_data ['post_subject'] = utf8_normalize_nfc (request_var ('subject', «, true)); $text = utf8_normalize_nfc (request_var ('message', «, true)); // Перехват сообщения include_once ('latexrender/phpbb_hook_1.php'); // Первый хук include_once ('latexrender/phpbb_hook_2.php'); // Второй хук $ message _ parser -> message = $ text; // Дальнейшая обработка сообщения средствами форума $post_data['username'] = utf8_normalize_nfc (request_var ('username', $post_data['username'], true)); … Первый хук: <? php $text = preg_replace(«#\[tex\] (.*?)\[/tex\]#si», «[tex:$uid]\\1 [/tex:$uid]», $text); ?> Второй хук: <? php $latexrender_path = «latexrender»; $latexrender_path_http = «latexrender»; include_once ($latexrender_path. "/class.latexrender.php»); preg_match_all(«#\[tex:$uid\] (.*?)\[/tex:$uid\]#si»,$text,$tex_matches); $latex = new LatexRender ($latexrender_path. "/pictures», $latexrender_path_http. "/pictures», $latexrender_path. "/tmp»); for ($i=0; $i < count ($tex_matches[0]); $i++) { $pos = strpos ($text, $tex_matches[0] [$i]); $latex_formula = html_entity_decode ($tex_matches[1] [$i]); $url = $latex->getFormulaURL ($latex_formula); $alt_latex_formula = htmlentities ($latex_formula, ENT_QUOTES); $alt_latex_formula = str_replace («\r», « »,$alt_latex_formula); $alt_latex_formula = str_replace («\n», « »,$alt_latex_formula); if ($url!= false) { $text = substr_replace ($text, «<img src='».$url. «' title='»..$alt_latex_formula. «' alt='».$alt_latex_formula. «' align='absmiddle'>», $pos, strlen ($tex_matches[0] [$i])); } else { $text = substr_replace ($text, «[unparseable or potentially dangerous latex formula]»,$pos, strlen ($tex_matches[0] [$i])); } } ?> Скрипт, используемый для обработки формул в массиве, включающий в себя класс: <? php class LatexRender { var $_picture_path =».»; var $_picture_path_httpd =».»; var $_tmp_dir =».»; var $_latex_path = «/usr/bin/latex»; var $_dvips_path = «/usr/bin/dvips»; var $_convert_path = «/usr/bin/convert»; var $_identify_path=»/usr/bin/identify»; var $_formula_density = 120; var $_xsize_limit = 500; var $_ysize_limit = 500; var $_string_length_limit = 500; var $_font_size = 10; var $_latexclass = «article»; var $_tmp_filename; var $_image_format = «gif»; // или «png»
var $_latex_tags_blacklist = array ( «include», «def», «command», «loop», «repeat», «open», «toks», «output», «input», «catcode», «name», «^^», «\\every», «\\errhelp», «\\errorstopmode», «\\scrollmode», «\\nonstopmode», «\\batchmode», «\\read», «\\write», «csname», «\\newhelp», «\\uppercase», «\\lowercase», «\\relax», «\\aftergroup», «\\afterassignment», «\\expandafter», «\\noexpand», «\\special» ); var $_errorcode = 0; var $_errorextra = «»; function LatexRender ($picture_path,$picture_path_httpd,$tmp_dir) { $this->_picture_path = $picture_path; $this->_picture_path_httpd = $picture_path_httpd; $this->_tmp_dir = $tmp_dir; $this->_tmp_filename = md5 (rand()); } function setPicturePath($name) { $this->_picture_path = $name; } function getPicturePath() { return $this->_picture_path; } function setPicturePathHTTPD($name) { $this->_picture_path_httpd = $name; } function getPicturePathHTTPD() { return $this->_picture_path_httpd; } function getFormulaURL ($latex_formula) { $latex_formula = preg_replace («/>/i», «>», $latex_formula); $latex_formula = preg_replace («/</i», «<», $latex_formula); $formula_hash = md5 ($latex_formula); $filename = $formula_hash.».».$this->_image_format; $full_path_filename = $this->getPicturePath(). "/».$filename; if (is_file ($full_path_filename)) { return $this->getPicturePathHTTPD(). "/».$filename; } else { if (strlen ($latex_formula) > $this->_string_length_limit) { this->_errorcode = 1; return false; } for ($i=0;$i<sizeof ($this->_latex_tags_blacklist);$i++) { if (stristr ($latex_formula,$this->_latex_tags_blacklist[$i])) { $this->_errorcode = 2; return false; } } if ($this->renderLatex ($latex_formula)) { return $this->getPicturePathHTTPD(). "/».$filename; } else { return false; } } } function wrap_formula ($latex_formula) { $string = «\documentclass [».$this->_font_size. «pt] {».$this->_latexclass.»}\n»; $string.= «\usepackage[latin1] {inputenc}\n»; $string.= «\usepackage{amsmath}\n»; $string.= «\usepackage{amsfonts}\n»; $string.= «\usepackage{amssymb}\n»; $string.= «\pagestyle{empty}\n»; $string.= «\begin{document}\n»; $string.= «$».$latex_formula. «$\n»; $string.= «\end{document}\n»; return $string; } function getDimensions($filename) { $output=exec ($this->_identify_path. "».$filename); $result=explode(«»,$output); $dim=explode («x»,$result[2]); $dim [«x»] = $dim[0]; $dim [«y»] = $dim[1]; return $dim; } function renderLatex ($latex_formula) { $latex_document = $this->wrap_formula ($latex_formula); $current_dir = getcwd(); chdir ($this->_tmp_dir); $fp = fopen ($this->_tmp_filename.».tex», «a+»); fputs ($fp,$latex_document); fclose($fp); $command = $this->_latex_path.» – interaction=nonstopmode».$this-> _tmp_filename.».tex»; $status_code = exec($command); if (!$status_code) {$this->cleanTemporaryDirectory(); chdir ($current_dir); $this->_errorcode = 4; return false;} $command = $this->_dvips_path.» – E».$this->_tmp_filename.».dvi».» – o».$this->_tmp_filename.».ps»; $status_code = exec($command); $command = $this->_convert_path.» – density».$this->_formula_density..» – trim – transparent \ «#FFFFFF\»».$this->_tmp_filename.».ps». $this->_tmp_filename.».».$this->_image_format; $status_code = exec($command); $dim = $this->getDimensions ($this->_tmp_filename.».».$this-> _image_format); if (($dim [«x»] > $this->_xsize_limit) or ($dim [«y»] > $this->_ysize_limit)) { $this->cleanTemporaryDirectory(); chdir ($current_dir); $this->_errorcode = 5;
$this->_errorextra =»: «. $dim [«x»]. «x». number_format ($dim[«y»], 0, «», «»); return false; } $latex_hash = md5 ($latex_formula); $filename = $this->getPicturePath(). "/».$latex_hash.».».$this->_image_format; $status_code = copy ($this->_tmp_filename.».».$this->_image_format,»../../». $filename); $this->cleanTemporaryDirectory(); if (!$status_code) {chdir ($current_dir); $this->_errorcode = 6; return false;} chdir ($current_dir); return true; } function cleanTemporaryDirectory() { $current_dir = getcwd(); chdir(»../../»); unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».tex»); unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».aux»); unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».log»); unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».dvi»); unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».ps»); unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».».$this->_image_format); chdir ($current_dir); } } ?> Заключение В данной работе были достигнуты следующие результаты: · Собран и изучен материал, связанный с использованием формул в Интернете; · Изучен форумный движок phpBB3; · Созданы PHP скрипты для взаимодействия с форумом.
Список литературы 1. Афонин С.М. Программирование на языке PHP / Афонин С.М. – М.: НТ Пресс, 2007. – 256 с.: ил. 2. Колисниченко Д.Н. Самоучитель PHP 5. – СПб: Наука и техника, 2004. 576 с.: ил. 3. Мазуркевич А. PHP: настольная книга программиста / Александр Мазуркевич, Дмитрий Еловой. – Мн.: Новое знание, 2003. – 480 с.: ил. 4. Томсон Лаура. Разработка Web-приложений на РНР и MySQL: Пер. с англ. / Лаура Томсон, Люк Веллинг. – 2-е изд., испр. – СПб: ООО «ДиаСофтЮП», 2003. – 672 с. 5. Ульман Л. Основы программирования на РНР: Пер. с англ. – М.: ДМК Пресс, 2001. – 288 с.: ил. (Самоучитель). 6. Харрис Э. PHP/MySQL для начинающих / Пер. с англ. – М.: КУДИЦ-ОБРАЗ, 2005. – 384 с. 7. http://ru.wikipedia.org 8. http://lib.mexmat.ru 9. http://avi.ru 10. http://teacode.com
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|