LaTeX support in phpBB3

Looking for a MOD? Have a MOD request? Post here for help. (Note: This forum is community supported; phpBB does not have official MOD authors)
Anti-Spam Guide
Locked
sisteczko
Registered User
Posts: 8
Joined: Thu Dec 27, 2007 2:16 pm

LaTeX support in phpBB3

Post by sisteczko » Thu Dec 27, 2007 8:19 pm

I'm trying to get the LaTeX support through mathrenderer running in phpBB3. I found a little howto on this matter here, http://www.phpbb.com/community/viewtopic.php?p=2669402 (quote is below), and have some problems in implementing it. That original post was off-topic (the topic was about LaTeX support on phpBB2, not 3), so I decided to start a new topic here, in the right place.
stevem wrote:You'll be pleased to hear that LatexRender works fine with phpBB 3.0 Beta4. In fact in some ways it is even easier to install :)
Here are the small changes you need to make to the installation - of course things may change a little when phpBB 3.0 is finally released.
  1. In phpbb_hook_2.php:
    replace $uid by $bbcode_uid twice
    replace $text by $message six times
  2. In includes/bbcode.php there only needs to be one extra line
    Just before

    Code: Select all

    		// Remove the uid from tags that have not been transformed into HTML
    		$message = str_replace(':' . $this->bbcode_uid, '', $message);
    	}
    
    	/**
    	* Init bbcode cache
    	*
    	* requires: $this->bbcode_bitfield
    	* sets: $this->bbcode_cache with bbcode templates needed for bbcode_bitfield
    	*/
    	function bbcode_cache_init()
    Add (with appropriate path)

    Code: Select all

    include("/home/username/public_html/forum/latexrender/phpbb_hook_2.php");
  3. In the Administration Control Panel, Posting, Add a new BBCode
    1. In the top box put

      Code: Select all

      [tex]{TEXT}[/tex]
    2. Helpline text is whatever you want to tell your users
    3. Check Display on Posting
    4. Submit
You should now be able to use LatexRender as before. If you try it out (remember that phpBB3 should only be used for testing at the moment) let me know if there's a problem.
The problem is this: After instalation, I've got no errors, but no LaTeX support as well. Posts like «[tex]\frac{1}{2}[\tex]» display unchanged...

I'm running the Ubuntu 7.04 server (i.e. console only), with plain (and successful) instalation of most recent apache2, TeXLive, PHP5, MySQL, phpBB3 v.3.0.0. Besides,
  1. I've downloaded the latexrenderer 0.8 from http://www.mayer.dial.pipex.com/latexrender.zip.
  2. I've followed exactly the instructions above.
Here are my observations, which might give a clue:
  1. If I mess with the $_latex_path, $_dvips_path (and their other siblings) I've got no errors, so I conclude that no latex nor dvips nor convert is ever called
  2. Messing with the constructor of the LatexRender class produces errors if and only if there are [tag] and [/tag] tags in the document. So I conclude that the [tex] BBCode is handled differentely then other codes. So problem is somewhere else.
  3. Commenting out (almost) last 6 lines of class.latexrender.php doesn't leave me with any files in latexrenderer/tmp nor latexrenderer/pictures, which confirms observation nr 1.
...so why things don't work?
  • Maybe there are some significant differences between phpBB3 Beta 4, and the current version?
  • Maybe, after all, I've downloaded not the right verision of mathrenderer?
  • Contrary to my intuition, the quoted post on step 3 implicitely asked to leave HTML replacement blank. Maybe there is something obvious to put there? Other solutions of LaTeX support in phpBB do use HTML replacement. But then again, it is contrary to my observation nr. 2... I'm really stuck.
Help...! :(

stevem
Registered User
Posts: 398
Joined: Sun Aug 25, 2002 1:59 pm

Re: LaTeX support in phpBB3

Post by stevem » Fri Dec 28, 2007 8:39 pm

If you have commented out the last 6 lines then one of the files that should appear is a .tex file, before any command is run. If that is not happening then the tex tags are not being processed at all. I expect phpbb_hook_2.php is not being run. I would put some echo lines to find out what what is being processed. For example in phpbb_hook_2.php you could put something like:

Code: Select all

echo "Now in phpbb_hook_2.php processing $message<br>";
and ignore error messages about headers.
If nothing happens then maybe you need to put the include command somewhere else. If you get an output then make sure there is a tex tag there.

sisteczko
Registered User
Posts: 8
Joined: Thu Dec 27, 2007 2:16 pm

Re: LaTeX support in phpBB3

Post by sisteczko » Sat Dec 29, 2007 8:37 pm

Thank you steve for your reply.

I did what you've suggested, and I've got the following output:

Code: Select all

Now in phpbb_hook_2.php processing Test topic1: [tex:2616lo49]\frac{\pi}{2}[/tex:2616lo49]
Now in phpbb_hook_2.php processing Second test of a post: [tex:2hgm5yqy]\int x^2 dx[/tex:2hgm5yqy]
So the conclussion is that phpbb_hook_2.php is indeed called.

Anticipating your next question, here are contents of key source files (I didn't change with them anymore, then you've written on the original post): phpBB3.zip

I also confirm, that I can run LaTeX if I type "latex" command in the terminal. (well, the program which is actually ran claims to be pdftex to be exact, but I guess it doesn't make a difference here). And the paths to those programs are correct. (If they wouldn't I would expect some error. But, as I wrote, even If I alter them randomly, no error is produced).

And except for index.html there are absolutely no other files in both latexrenderer/tmp and latexrenderer/pictures folders.

I'm a complete PHP beginner, so please excuse my next question: How does one test manually the latex renderer? Is there a magic html, I expect something in the form like http://192.168.3.40/myforum/latexrender ... hook_2.php ?{\frac{3^2}{3}}?

Thank you again for your reply,
Adam

stevem
Registered User
Posts: 398
Joined: Sun Aug 25, 2002 1:59 pm

Re: LaTeX support in phpBB3

Post by stevem » Sat Dec 29, 2007 10:33 pm

That's good news as you can now concentrate on the latexrender files. I have to ask, but I assume that the /tmp and /pictures directories are chmod 777 so they are writeable to?

In phpbb_hook_2.php put the line

Code: Select all

echo "formula is $latex_formula<br>";
after the line

Code: Select all

$latex_formula = html_entity_decode($tex_matches[1][$i]);
which should show the latex formula.

More importantly, in class.latexrender.php we need to see if it gets to writing the tex file. In class.latexrender.php line 188 just after

Code: Select all

$string .= "\end{document}\n";
add
echo "tex file is $string<br>";
and on line 232 after

Code: Select all

chdir($this->_tmp_dir);
add

Code: Select all

echo "Saving the tex file ".$this->_tmp_dir."/".$this->_tmp_filename.".tex"." in ".$this->_tmp_dir."<br>";
which will tell you the name of the tex file and where it is saving it.
Either you won't get this message so something has gone wrong earlier or if you do get it but the tex file doesn't appear then the program can't write to the tex directory.
sisteczko wrote:I'm a complete PHP beginner, so please excuse my next question: How does one test manually the latex renderer?
Yes, in the download in otherPHP/latexrender use the example.php to test if latex is working, independently of phpBB. You can either upload example.php and latex.php to the same directory as phpbb_hook_2.php (changing the paths in latex.php) or upload example.php, latex.php, class.latexrender.php to somewhere totally different with its own /tmp and /pictures subdirectories.

sisteczko
Registered User
Posts: 8
Joined: Thu Dec 27, 2007 2:16 pm

Re: LaTeX support in phpBB3

Post by sisteczko » Sun Dec 30, 2007 6:12 pm

stevem wrote:That's good news as you can now concentrate on the latexrender files. I have to ask, but I assume that the /tmp and /pictures directories are chmod 777 so they are writeable to?
Of course they are. :)

I've put the suggested lines in phpbb_hook_2.php and class.latexrender.php, and removed the previous echo line from the previous post. (In case you want to inspect them yourself, here they are: latexrenderer.zip) And now I see no debug info at all. No even errors.
BTW, I call the latexrender BBCode by using the [tex] BBCode, just as I declared it on the Administration Control Panel->Posting->BBCode usage: "[tex]{TEXT}[/tex]". As I wrote, I put no text in the field below, in the HTML Replacement field. I left it blank. I hope this was correct.

I also did test the LaTeX latexrenderer installation using the otherPHP/latexrender code. The test was partially successful. In short, I've got a bunch of warnings/errors and TeX output upon executing the example.php, but in the tmp directory I found successful render of the first LaTeX output, the [tex]\sqrt{2}[/tex]. I'll put the details on another post, because my intuition tells me, that it is another problem. In our case, it seems that the class.latexrender.php is hardly called at all.

To double check it, I've copied the example text verbatim into the post in my phpBB3 forum, and the result didn't change; I've got neighter warnings nor errors nor any other echos I've put to the both php files.

stevem
Registered User
Posts: 398
Joined: Sun Aug 25, 2002 1:59 pm

Re: LaTeX support in phpBB3

Post by stevem » Sun Dec 30, 2007 6:35 pm

I think I have the answer! Looking at the files you posted phpbb_hook_2.php is not finding the tex tags because you forgot to change $uid to $bbcode_uid
In phpbb_hook_2.php:
replace $uid by $bbcode_uid twice
phpbb3 uses a different variable to the one in phpbb2 so this needs changing in two places in the line

Code: Select all

preg_match_all("#\[tex:$uid\](.*?)\[/tex:$uid\]#si",$text,$tex_matches);

sisteczko
Registered User
Posts: 8
Joined: Thu Dec 27, 2007 2:16 pm

Latexrender: Testing the renderer from otherPHP/latexrender

Post by sisteczko » Sun Dec 30, 2007 6:44 pm

I've copied the latex.php and example.php from otherPHP.latexrender into the latexrenderer folder, where I've installed the latexrender in the phpBB3.

I've called in my webrowser http://192.168.3.44/fora/phpBB3/latexre ... xample.php (where 192.168.3.44 is the address of the server) and in the web page I've pressed the "Render" button to render the following sample:

Code: Select all

Example Text:
This is just text but [tex]\sqrt{2}[/tex] should be shown as an image and so should [tex]\frac {1}{2}[/tex].
			
Another formula is [tex]\frac {43}{12} \sqrt {43}[/tex]
...and I've got the following echos: (The echos are displayed due to the debug modifications found in in the http://www.phpbb.com/community/viewtopi ... 5#p3657175)

Code: Select all

tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $\sqrt{2}$ \end{document} 
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/8a6249bcfc851c39d676cca0122fec1d.tex in /var/www/fora/phpBB3/latexrenderer/tmp

Warning: copy(8a6249bcfc851c39d676cca0122fec1d.gif) [function.copy]: failed to open stream: No such file or directory in /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270
tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $\frac {1}{2}$ \end{document} 
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/8a6249bcfc851c39d676cca0122fec1d.tex in /var/www/fora/phpBB3/latexrenderer/tmp

Warning: copy(8a6249bcfc851c39d676cca0122fec1d.gif) [function.copy]: failed to open stream: No such file or directory in /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270
tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $\frac {43}{12} \sqrt {43}$ \end{document} 
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/8a6249bcfc851c39d676cca0122fec1d.tex in /var/www/fora/phpBB3/latexrenderer/tmp

Warning: copy(8a6249bcfc851c39d676cca0122fec1d.gif) [function.copy]: failed to open stream: No such file or directory in /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270
Example Text:
This is just text but [Unparseable or potentially dangerous latex formula. Error 6 ] should be shown as an image and so should [Unparseable or potentially dangerous latex formula. Error 6 ].

Another formula is [Unparseable or potentially dangerous latex formula. Error 6 ]
After that, in the tmp directory I've got only the following files:

Code: Select all

8a6249bcfc851c39d676cca0122fec1d.aux
8a6249bcfc851c39d676cca0122fec1d.dvi
8a6249bcfc851c39d676cca0122fec1d.log
8a6249bcfc851c39d676cca0122fec1d.ps
8a6249bcfc851c39d676cca0122fec1d.tex
In the tex file we find that only the first formula has been rendered: color=#0000FF]8a6249bcfc851c39d676cca0122fec1d.tex[/color]:

Code: Select all

\documentclass[10pt]{article}
\usepackage[latin1]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\pagestyle{empty}
\begin{document}
$\sqrt{2}$
\end{document}
\documentclass[10pt]{article}
\usepackage[latin1]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\pagestyle{empty}
\begin{document}
$\frac {1}{2}$
\end{document}
\documentclass[10pt]{article}
\usepackage[latin1]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\pagestyle{empty}
\begin{document}
$\frac {43}{12} \sqrt {43}$
\end{document}
...and not even to the end - the gif file itself is missing.
(All files can be seen in the following address: tmp.zip). What can be wrong? All dependencies has been installed (I'm using Ubuntu server, and I've installed them from the official ubuntu repositories).

sisteczko
Registered User
Posts: 8
Joined: Thu Dec 27, 2007 2:16 pm

Re: LaTeX support in phpBB3

Post by sisteczko » Sun Dec 30, 2007 6:58 pm

stevem wrote:I think I have the answer! Looking at the files you posted phpbb_hook_2.php is not finding the tex tags because you forgot to change $uid to $bbcode_uid
In phpbb_hook_2.php:
replace $uid by $bbcode_uid twice
phpbb3 uses a different variable to the one in phpbb2 so this needs changing in two places in the line

Code: Select all

preg_match_all("#\[tex:$uid\](.*?)\[/tex:$uid\]#si",$text,$tex_matches);
YES! Somehow I also failed to replace the other, $text into $message... Strange, because I could swear that I have done that... No I am a step further, and I've got the same problems as in the example.php posted before. Here are the echos and errors:
forumla is \frac{\pi}{2}
tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $\frac{\pi}{2}$ \end{document}
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/b857820418a6154c1e6d397f974d51cb.tex in /var/www/fora/phpBB3/latexrenderer/tmp
[phpBB Debug] PHP Notice: in file /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270: copy(b857820418a6154c1e6d397f974d51cb.gif) [function.copy]: failed to open stream: No such file or directory
forumla is \int x^2 dx
tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $\int x^2 dx$ \end{document}
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/4911ed945e1b356cbaac37af553088e3.tex in /var/www/fora/phpBB3/latexrenderer/tmp
[phpBB Debug] PHP Notice: in file /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270: copy(4911ed945e1b356cbaac37af553088e3.gif) [function.copy]: failed to open stream: No such file or directory
forumla is \int x^2 dx
tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $\int x^2 dx$ \end{document}
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/1948e6bd3744a8a097306a9774799635.tex in /var/www/fora/phpBB3/latexrenderer/tmp
[phpBB Debug] PHP Notice: in file /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270: copy(1948e6bd3744a8a097306a9774799635.gif) [function.copy]: failed to open stream: No such file or directory
forumla is x^2
tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $x^2$ \end{document}
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/1948e6bd3744a8a097306a9774799635.tex in /var/www/fora/phpBB3/latexrenderer/tmp
[phpBB Debug] PHP Notice: in file /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270: copy(1948e6bd3744a8a097306a9774799635.gif) [function.copy]: failed to open stream: No such file or directory
forumla is \int x^2 dx
tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $\int x^2 dx$ \end{document}
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/14d018b58c618a92569b39328dd43947.tex in /var/www/fora/phpBB3/latexrenderer/tmp
[phpBB Debug] PHP Notice: in file /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270: copy(14d018b58c618a92569b39328dd43947.gif) [function.copy]: failed to open stream: No such file or directory
forumla is x^2
tex file is \documentclass[10pt]{article} \usepackage[latin1]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \pagestyle{empty} \begin{document} $x^2$ \end{document}
Saving the tex file /var/www/fora/phpBB3/latexrenderer/tmp/14d018b58c618a92569b39328dd43947.tex in /var/www/fora/phpBB3/latexrenderer/tmp
[phpBB Debug] PHP Notice: in file /var/www/fora/phpBB3/latexrenderer/class.latexrender.php on line 270: copy(14d018b58c618a92569b39328dd43947.gif) [function.copy]: failed to open stream: No such file or directory
[phpBB Debug] PHP Notice: in file /includes/functions.php on line 3391: Cannot modify header information - headers already sent by (output started at /latexrenderer/phpbb_hook_2.php:41)
[phpBB Debug] PHP Notice: in file /includes/functions.php on line 3393: Cannot modify header information - headers already sent by (output started at /latexrenderer/phpbb_hook_2.php:41)
[phpBB Debug] PHP Notice: in file /includes/functions.php on line 3394: Cannot modify header information - headers already sent by (output started at /latexrenderer/phpbb_hook_2.php:41)
[phpBB Debug] PHP Notice: in file /includes/functions.php on line 3395: Cannot modify header information - headers already sent by (output started at /latexrenderer/phpbb_hook_2.php:41)

stevem
Registered User
Posts: 398
Joined: Sun Aug 25, 2002 1:59 pm

Re: LaTeX support in phpBB3

Post by stevem » Sun Dec 30, 2007 7:04 pm

Since only the gif file is missing it is a problem with ImageMagick and Ghostscript. I am assuming that the ImageMagick files convert and identify are in /usr/bin (as stated at the beginning of class.latexrender.php). If not then change those lines.The problem is that sometimes gs is not in /usr/bin so cannot be found by ImageMagick.

The workaround is to add to the path environmental variable so ImageMagick can find GhostScript. In class.latexrender.php before the line

Code: Select all

// imagemagick convert ps to image and trim picture
add

Code: Select all

// begin of workaround
// extending the PATH environmental variable
$oldpath = getenv(”PATH”);
$where_gs_is = “/usr/sfw/bin”;
if ($oldpath) { $where_gs_is .= “:$oldpath”;}
putenv(”PATH=$where_gs_is”);
// end of workaround
Try this using the strange /usr/sfw/bin path first but if that doesn't work replace it by where the path the binary file gs is in.

sisteczko
Registered User
Posts: 8
Joined: Thu Dec 27, 2007 2:16 pm

Re: LaTeX support in phpBB3

Post by sisteczko » Sun Dec 30, 2007 7:26 pm

It works!!! Thank you for your help very much. In an hour I'll try to post a detailed howto for dummies like me ;-)

sisteczko
Registered User
Posts: 8
Joined: Thu Dec 27, 2007 2:16 pm

HowTo: LaTeX in phpBB3 on Ubuntu server (for dummies)

Post by sisteczko » Mon Dec 31, 2007 12:41 am

Assumed that phpBB3 is installed on /var/www/phpBB3 and running on Ubuntu server 7.04 (it should also apply to Debian Linux as well)
1. In terminal type: sudo apt-get install texlive gs imagemagick
2. Download, and unpack latexrender.zip into /var/www/phpBB3/latexrender
3. Add appropriate permissions. In console write:

Code: Select all

sudo chmod -R u=rw /var/www/phpBB3/latexrender
sudo chmod -R g=r /var/www/phpBB3/latexrender
sudo chmod -R o=r /var/www/phpBB3/latexrender
sudo chmod u=rwx /var/www/phpBB3/latexrender/tmp
sudo chmod g=rwx /var/www/phpBB3/latexrender/tmp
sudo chmod o=rwx /var/www/phpBB3/latexrender/tmp
sudo chmod u=rwx /var/www/phpBB3/latexrender/pictures
sudo chmod g=rwx /var/www/phpBB3/latexrender/pictures
sudo chmod o=rwx /var/www/phpBB3/latexrender/pictures
4. Open the file /var/www/phpBB3/latexrender/phpbb_hook_2.php.
5. Replace all two occurances of $uid into $bbcode_uid. Because of file permissions you should be root to do that.
6. Replace all six occurances of $text into $message.
7. Open the file /var/www/phpBB3/includes/bbcode.php and on the 118 line (just before "// Remove the uid from tags that have not been transformed into HTML") add the following:

Code: Select all

include("/var/www/phpBB3/latexrender/phpbb_hook_2.php");
8. Open the Administrative Control Panel of phpBB3 using the web interface, and under posting->BBCode usage put the

Code: Select all

[tex]{TEXT}[/tex]
and check the Display on Posting, and click Submit.
9. Optionally one might want to make his own custom LaTeX commands available for forum users. In order to do that we need to add lines to the /var/www/phpBB3/latexrender/class.latexrender.php, between lines 184 and 185:

Code: Select all

    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";
<PUT NEW \usepackage OR \newcommand OR \DeclareMathOperator OR whatever here>
        $string .= "\pagestyle{empty}\n";
        $string .= "\begin{document}\n";
        $string .= "$".$latex_formula."$\n";
        $string .= "\end{document}\n";

        return $string;
    }
Each LaTeX command need to wrapped in quotation marks. We also need to replace backslash with double backlash (\ -> \\), quotation marks with backslash quatation mark (" -> \"). Each line must end with \n.
Example:

Code: Select all

$string .= "\\newcommand{\\dbar}{d\\mkern-6mu\\mathchar'26}\n";
$string .= "\\newcommand{\\suchas}[1]{\\Bigr\\rvert_{#1}}\n";
Remarks:
  • Yes, if we don't want to add custom LaTeX commands, no editing of class.latexrender.php is required on Ubuntu Server.
  • I have totaly no idea why in the original string literal in function wrap_formula (/var/www/phpBB3/latexrender/class.latexrender.php, lines 188) single backlashes are not replaced with double backslashes... But if we want to add custom LaTeX command to be ran, we need to use the guidelines from point 9.
Last edited by sisteczko on Mon Dec 31, 2007 11:31 am, edited 1 time in total.

stevem
Registered User
Posts: 398
Joined: Sun Aug 25, 2002 1:59 pm

Re: HowTo: LaTeX in phpBB3 on Ubuntu server (for dummies)

Post by stevem » Mon Dec 31, 2007 10:47 am

sisteczko wrote:I have totaly no idea why in the original string literal in function wrap_formula (/var/www/phpBB3/latexrender/class.latexrender.php, lines 188) single backlashes are not replaced with double backslashes... But if we want to add custom LaTeX command to be ran, we need to use the guidelines from point 9.[/list]
The double backslashes are only needed where the letter could be misinterpreted. \newcommand would be interpreted as \n followed by ewcommand and similarly for anything beginning with \r. On the other hand \e has no meaning so \end{document} is fine.

Evgeni Sergeev
Registered User
Posts: 2
Joined: Sun Feb 10, 2008 6:55 am

Re: LaTeX support in phpBB3

Post by Evgeni Sergeev » Sun Feb 10, 2008 7:58 am

Hi,

I have set up LatexRender on phpBB3 without problems, thanks for your good work.

If anyone is getting lost, then the post by sisteczko on Mon Dec 31, 2007 above is all that is necessary. Just make sure you edit bbcode.php in the right place, that is, near the end of the function bbcode_second_pass(..).

Now I wanted the $..$ and the other nice tags. The post in the big thread shows how it's done on http://mathlinks.ro. Thanks for those guys for showing us that it's possible. However, I wasn't comfortable with making deep incisions into phpBB. All I really wanted was a shortcut, such that $..$ would be changed to [tex]..[/tex]. That is a clean solution.

The following code is for this. To install:
  1. Save the file below as phpbb/latexrender/phpbb_hook_dollars.php
  2. In the file phpbb/include/message_parser.php, find "// Parse BBCode" - for me this is line 1121, and before it insert the line

    Code: Select all

    include("/path/to/phpbb/latexrender/phpbb_hook_dollars.php");
  3. In the Administration Control Panel, go to Posting, BBCode and add the following two codes:
    1. [indentedblock]{TEXT}[/indentedblock] with replacement

      Code: Select all

      <div style="padding-left:4em;">{TEXT}</div>
    2. [dollar][/dollar] with replacement $
  4. Done.
phpbb_hook_dollars.php

Code: Select all

<?php
/**
 * LaTeX Rendering Class - PHPBB Hook for dollar signs (superficial type)
 * Copyright (C) 2008 Evgeni Sergeev
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * --------------------------------------------------------------------
 * @author Evgeni Sergeev
 * @vetsion 0.1
 * @package latexrender
 *
 */

/**
 * This is for phpBB version 3.
 * The idea is to use a pair of dollar signs to contain LaTeX mathematics in forum
 * posts, as a shorthand, in the same way we are used to in proper LaTeX documents.
 *
 * This superficial approach doesn't try to make dollar signs into first-class
 * phpBB3 tags -- as soon as the program gets its hands on the message, it replaces
 * the dollar signs with [tex][/tex] tags, etc. It just makes the [tex][/tex]
 * tags much nicer to use. The downside is that once the message is in the system,
 * it is slightly more difficult to cut and paste into a LaTeX document, but I
 * find that I hardly ever need to.
 *
 * The superficial approach is very light, which probably makes it more reusable
 * between versions, with less modifications. Just a few lines of code in one
 * place.
 *
 * An issue is how to deal with real dollar signs. We define [dollar][/dollar]
 * tags, and allow the user to type \$ as a shorthand.
 *
 *
 * HOW TO INSTALL
 *
 * SAVE the file you are reading as phpbb/latexrender/phpbb_hook_dollars.php
 *
 * OPEN phpbb/include/message_parser.php
 *      In the function parse(), before it parses the BBCode, 
 *      which is roughly at line 1121, and has "// Parse BBCode" near it, insert
 *      the following line (changing the path):
 *
 *      include("path/to/phpBB3/latexrender/phpbb_hook_dollars.php");
 *
 * GO TO Administration Control Panel, Posting, BBCodes
 *      Add a new BBCode as follows:
 *          BBCode usage is         [indentedblock]{TEXT}[/indentedblock]
 *          HTML replacement is     <div style="padding-left:4em;">{TEXT}</div>
 *          Helpline and "Display on posting page" are probably unnecessary.
 *
 *      Add another BBCode:
 *          BBCode usage is         [dollar][/dollar]
 *          HTML replacement is     $
 *          Helpline                Insert a literal $ sign
 *          Display on posting page Yes
 *
 * DONE
 *
 */
    
    //First replace \$ signs.
    $this->message = preg_replace("#\\\\\\\$#" , "[dollar][/dollar]", $this->message);

    //Replace $$..$$.
    $this->message = preg_replace("#\\\$\\\$(.*?)\\\$\\\$#si", 
        "[indentedblock][tex]\\displaystyle{\\1}[/tex][/indentedblock]", $this->message);

    //Replace $..$.
    $this->message = preg_replace("#\\\$(.*?)\\\$#si",
        "[tex]\\1[/tex]", $this->message);

    //Replace \[..\].
    $this->message = preg_replace("#\\\\\\[(.*?)\\\\\\]#si",
        "[indentedblock][tex]\\displaystyle{\\1}[/tex][/indentedblock]", $this->message);
?>
You can see what I've done. This works for any message, even if it doesn't contain any BBCode, just dollars. For [indentedblock][/indentedblock], I could probably have used a <p></p> element instead. All this does is puts the contents on its own line, with a 4 space indent from the left. The [dollar][/dollar] tag is used for a literal dollar. Writing \$ is a shorthand. First it is replaced. Then the only dollar signs left are the demarcation ones. We take the double dollar signs first, as doing single dollar signs would incorrectly parse these, if done first. The replacements contain only BBCode tags, no dollars. Then we process $..$ and \[..\]. By the end of the hook, there are no dollar signs left in the message, unless there were mismatched dollar signs. Then, phpbb replaces [dollar][/dollar] with a dollar sign. And after it has processed all of the system tags, including [indentedblock] now, LatexRender processes the [tex][/tex] tags.

How would we change this to ignore the dollar signs within

Code: Select all

 tags? I would probably store character ranges of these [code] structures, including beginning and end tag, in an array, using preg_match_all with PREG_OFFSET_CAPTURE flag. Then I would split the string along the boundaries of these ranges, and run the sequence of substitutions as in phpbb_hook_dollar.php for all char spans outside of the ranges. And then I would concat them all back. I don't have time for it now.

texasmath
Registered User
Posts: 12
Joined: Tue Feb 19, 2008 2:59 am

Re: LaTeX support in phpBB3

Post by texasmath » Tue Feb 19, 2008 3:12 am

I had no problem getting LatexRender to work when my board was running 2.0.21. Now I can't get it to work with phpBB3.

I've done all the steps listed in sisteczko's post but I can't even get an echo statement in phpbb_hook_2.php to run.

phpbb_hook_2.php

Code: Select all

<?php
/**
 * LaTeX Rendering Class - PHPBB Hook
 * Copyright (C) 2003  Benjamin Zeiss <zeiss@math.uni-goettingen.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * --------------------------------------------------------------------
 * @author Benjamin Zeiss <zeiss@math.uni-goettingen.de>
 * @version v0.8
 * @package latexrender
 *
 */
    // --------------------------------------------------------------------------------------------------
    // adjust this to match your system configuration
    $latexrender_path = "/var/www/texasmath.org/forum/latexrender/";
    $latexrender_path_http = "/forum/phpbb/latexrender";

    // --------------------------------------------------------------------------------------------------
    include_once($latexrender_path."/class.latexrender.php");

    preg_match_all("#\[tex:$bbcode_uid\](.*?)\[/tex:$bbcode_uid\]#si",$message,$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($message, $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","&#13;",$alt_latex_formula);
                $alt_latex_formula = str_replace("\n","&#10;",$alt_latex_formula);

        if ($url != false) {
            $message = substr_replace($message, "<img src='".$url."' title='".$alt_latex_formula."' alt='".$alt_latex_formula."' align='absmiddle'>",$pos,strlen($tex_matches[0][$i]));
        } else {
            $message = substr_replace($message, "[unparseable or potentially dangerous latex formula]",$pos,strlen($tex_matches[0][$i]));
        }
    }

?>
class.latexrender.php

Code: Select all

<?php
/**
 * LaTeX Rendering Class
 * Copyright (C) 2003  Benjamin Zeiss <zeiss@math.uni-goettingen.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * --------------------------------------------------------------------
 * @author Benjamin Zeiss <zeiss@math.uni-goettingen.de>
 * @version v0.8
 * @package latexrender
 *
 */

class LatexRender {

    // ====================================================================================
    // Variable Definitions
    // ====================================================================================
    var $_picture_path = "";
    var $_picture_path_httpd = "";
    var $_tmp_dir = "";
    // i was too lazy to write mutator functions for every single program used
    // just access it outside the class or change it here if nescessary
    var $_latex_path = "/usr/bin/latex";
    var $_dvips_path = "/usr/bin/dvips";
    var $_convert_path = "/usr/bin/bin/convert";
    var $_identify_path="/usr/bin/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"; //install extarticle class if you wish to have smaller font sizes
    var $_tmp_filename;
        var $_image_format = "gif"; //change to png if you prefer
    // this most certainly needs to be extended. in the long term it is planned to use
    // a positive list for more security. this is hopefully enough for now. i'd be glad
    // to receive more bad tags !
    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 = "";


    // ====================================================================================
    // constructor
    // ====================================================================================

    /**
     * Initializes the class
     *
     * @param string path where the rendered pictures should be stored
     * @param string same path, but from the httpd chroot
     */
    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());
    }

    // ====================================================================================
    // public functions
    // ====================================================================================

    /**
     * Picture path Mutator function
     *
     * @param string sets the current picture path to a new location
     */
    function setPicturePath($name) {
        $this->_picture_path = $name;
    }

    /**
     * Picture path Mutator function
     *
     * @returns the current picture path
     */
    function getPicturePath() {
        return $this->_picture_path;
    }

    /**
     * Picture path HTTPD Mutator function
     *
     * @param string sets the current httpd picture path to a new location
     */
    function setPicturePathHTTPD($name) {
        $this->_picture_path_httpd = $name;
    }

    /**
     * Picture path HTTPD Mutator function
     *
     * @returns the current picture path
     */
    function getPicturePathHTTPD() {
        return $this->_picture_path_httpd;
    }

    /**
     * Tries to match the LaTeX Formula given as argument against the
     * formula cache. If the picture has not been rendered before, it'll
     * try to render the formula and drop it in the picture cache directory.
     *
     * @param string formula in LaTeX format
     * @returns the webserver based URL to a picture which contains the
     * requested LaTeX formula. If anything fails, the resultvalue is false.
     */
    function getFormulaURL($latex_formula) {
        // circumvent certain security functions of web-software which
        // is pretty pointless right here
        $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 {
            // security filter: reject too long formulas
            if (strlen($latex_formula) > $this->_string_length_limit) {
                $this->_errorcode = 1;
                return false;
            }

            // security filter: try to match against LaTeX-Tags Blacklist
            for ($i=0;$i<sizeof($this->_latex_tags_blacklist);$i++) {
                if (stristr($latex_formula,$this->_latex_tags_blacklist[$i])) {
                        $this->_errorcode = 2;
                    return false;
                }
            }

            // security checks assume correct formula, let's render it
            if ($this->renderLatex($latex_formula)) {
                return $this->getPicturePathHTTPD()."/".$filename;
            } else {
                // uncomment if required
                // $this->_errorcode = 3;
                return false;
            }
        }
    }

    // ====================================================================================
    // private functions
    // ====================================================================================

    /**
     * wraps a minimalistic LaTeX document around the formula and returns a string
     * containing the whole document as string. Customize if you want other fonts for
     * example.
     *
     * @param string formula in LaTeX format
     * @returns minimalistic LaTeX document containing the given formula
     */
    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;
    }

    /**
     * returns the dimensions of a picture file using 'identify' of the
     * imagemagick tools. The resulting array can be adressed with either
     * $dim[0] / $dim[1] or $dim["x"] / $dim["y"]
     *
     * @param string path to a picture
     * @returns array containing the picture dimensions
     */
    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;
    }

    /**
     * Renders a LaTeX formula by the using the following method:
     *  - write the formula into a wrapped tex-file in a temporary directory
     *    and change to it
     *  - Create a DVI file using latex (tetex)
     *  - Convert DVI file to Postscript (PS) using dvips (tetex)
     *  - convert, trim and add transparancy by using 'convert' from the
     *    imagemagick package.
     *  - Save the resulting image to the picture cache directory using an
     *    md5 hash as filename. Already rendered formulas can be found directly
     *    this way.
     *
     * @param string LaTeX formula
     * @returns true if the picture has been successfully saved to the picture
     *          cache directory
     */
    function renderLatex($latex_formula) {
        $latex_document = $this->wrap_formula($latex_formula);

        $current_dir = getcwd();

        chdir($this->_tmp_dir);

        // create temporary latex file
        $fp = fopen($this->_tmp_dir."/".$this->_tmp_filename.".tex","a+");
        fputs($fp,$latex_document);
        fclose($fp);

        // create temporary dvi file
        $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; }

        // convert dvi file to postscript using dvips
        $command = $this->_dvips_path." -E ".$this->_tmp_filename.".dvi"." -o ".$this->_tmp_filename.".ps";
        $status_code = exec($command);

        // imagemagick convert ps to image and trim picture
        $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);

        // test picture for correct dimensions
        $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;
        }

        // copy temporary formula file to cahed formula directory
        $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;
    }

    /**
     * Cleans the temporary directory
     */
    function cleanTemporaryDirectory() {
        $current_dir = getcwd();
        chdir($this->_tmp_dir);

        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);
    }

}

?>
bbcode.php

Code: Select all

<?php
/**
*
* @package phpBB3
* @version $Id: bbcode.php,v 1.114 2007/10/07 10:34:45 naderman Exp $
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/

/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
	exit;
}

/**
* BBCode class
* @package phpBB3
*/
class bbcode
{
	var $bbcode_uid = '';
	var $bbcode_bitfield = '';
	var $bbcode_cache = array();
	var $bbcode_template = array();

	var $bbcodes = array();

	var $template_bitfield;
	var $template_filename = '';

	/**
	* Constructor
	* Init bbcode cache entries if bitfield is specified
	*/
	function bbcode($bitfield = '')
	{
		if ($bitfield)
		{
			$this->bbcode_bitfield = $bitfield;
			$this->bbcode_cache_init();
		}
	}

	/**
	* Second pass bbcodes
	*/
	function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false)
	{
		if ($bbcode_uid)
		{
			$this->bbcode_uid = $bbcode_uid;
		}

		if ($bbcode_bitfield !== false)
		{
			$this->bbcode_bitfield = $bbcode_bitfield;

			// Init those added with a new bbcode_bitfield (already stored codes will not get parsed again)
			$this->bbcode_cache_init();
		}

		if (!$this->bbcode_bitfield)
		{
			include("/var/www/texasmath.org/forum/latexrender/phpbb_hook_2.php"); 
			// Remove the uid from tags that have not been transformed into HTML
			if ($this->bbcode_uid)
			{
				$message = str_replace(':' . $this->bbcode_uid, '', $message);
			}

			return;
		}

		$str = array('search' => array(), 'replace' => array());
		$preg = array('search' => array(), 'replace' => array());

		$bitfield = new bitfield($this->bbcode_bitfield);
		$bbcodes_set = $bitfield->get_all_set();

		$undid_bbcode_specialchars = false;
		foreach ($bbcodes_set as $bbcode_id)
		{
			if (!empty($this->bbcode_cache[$bbcode_id]))
			{
				foreach ($this->bbcode_cache[$bbcode_id] as $type => $array)
				{
					foreach ($array as $search => $replace)
					{
						${$type}['search'][] = str_replace('$uid', $this->bbcode_uid, $search);
						${$type}['replace'][] = $replace;
					}

					if (sizeof($str['search']))
					{
						$message = str_replace($str['search'], $str['replace'], $message);
						$str = array('search' => array(), 'replace' => array());
					}

					if (sizeof($preg['search']))
					{
						// we need to turn the entities back into their original form to allow the
						// search patterns to work properly
						if (!$undid_bbcode_specialchars)
						{
							$message = str_replace(array('&#58;', '&#46;'), array(':', '.'), $message);
							$undid_bbcode_specialchars = true;
						}

						$message = preg_replace($preg['search'], $preg['replace'], $message);
						$preg = array('search' => array(), 'replace' => array());
					}
				}
			}
		}

		// Remove the uid from tags that have not been transformed into HTML
		$message = str_replace(':' . $this->bbcode_uid, '', $message);
	}

	/**
	* Init bbcode cache
	*
	* requires: $this->bbcode_bitfield
	* sets: $this->bbcode_cache with bbcode templates needed for bbcode_bitfield
	*/
	function bbcode_cache_init()
	{
		include("/var/www/texasmath.org/forum/latexrender/phpbb_hook_2.php");
		global $user, $phpbb_root_path;

		if (empty($this->template_filename))
		{
			$this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']);
			$this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/bbcode.html';

			if (!@file_exists($this->template_filename))
			{
				trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR);
			}
		}

		$bbcode_ids = $rowset = $sql = array();

		$bitfield = new bitfield($this->bbcode_bitfield);
		$bbcodes_set = $bitfield->get_all_set();

		foreach ($bbcodes_set as $bbcode_id)
		{
			if (isset($this->bbcode_cache[$bbcode_id]))
			{
				// do not try to re-cache it if it's already in
				continue;
			}
			$bbcode_ids[] = $bbcode_id;

			if ($bbcode_id > NUM_CORE_BBCODES)
			{
				$sql[] = $bbcode_id;
			}
		}

		if (sizeof($sql))
		{
			global $db;

			$sql = 'SELECT *
				FROM ' . BBCODES_TABLE . '
				WHERE ' . $db->sql_in_set('bbcode_id', $sql);
			$result = $db->sql_query($sql, 3600);

			while ($row = $db->sql_fetchrow($result))
			{
				// To circumvent replacing newlines with <br /> for the generated html,
				// we use carriage returns here. They are later changed back to newlines
				$row['bbcode_tpl'] = str_replace("\n", "\r", $row['bbcode_tpl']);
				$row['second_pass_replace'] = str_replace("\n", "\r", $row['second_pass_replace']);

				$rowset[$row['bbcode_id']] = $row;
			}
			$db->sql_freeresult($result);
		}

		foreach ($bbcode_ids as $bbcode_id)
		{
			switch ($bbcode_id)
			{
				case 0:
					$this->bbcode_cache[$bbcode_id] = array(
						'str' => array(
							'[/quote:$uid]'	=> $this->bbcode_tpl('quote_close', $bbcode_id)
						),
						'preg' => array(
							'#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#ise'	=> "\$this->bbcode_second_pass_quote('\$1', '\$2')"
						)
					);
				break;

				case 1:
					$this->bbcode_cache[$bbcode_id] = array(
						'str' => array(
							'[b:$uid]'	=> $this->bbcode_tpl('b_open', $bbcode_id),
							'[/b:$uid]'	=> $this->bbcode_tpl('b_close', $bbcode_id),
						)
					);
				break;

				case 2:
					$this->bbcode_cache[$bbcode_id] = array(
						'str' => array(
							'[i:$uid]'	=> $this->bbcode_tpl('i_open', $bbcode_id),
							'[/i:$uid]'	=> $this->bbcode_tpl('i_close', $bbcode_id),
						)
					);
				break;

				case 3:
					$this->bbcode_cache[$bbcode_id] = array(
						'preg' => array(
							'#\[url:$uid\]((.*?))\[/url:$uid\]#s'			=> $this->bbcode_tpl('url', $bbcode_id),
							'#\[url=([^\[]+?):$uid\](.*?)\[/url:$uid\]#s'	=> $this->bbcode_tpl('url', $bbcode_id),
						)
					);
				break;

				case 4:
					if ($user->optionget('viewimg'))
					{
						$this->bbcode_cache[$bbcode_id] = array(
							'preg' => array(
								'#\[img:$uid\](.*?)\[/img:$uid\]#s'		=> $this->bbcode_tpl('img', $bbcode_id),
							)
						);
					}
					else
					{
						$this->bbcode_cache[$bbcode_id] = array(
							'preg' => array(
								'#\[img:$uid\](.*?)\[/img:$uid\]#s'		=> str_replace('$2', '[ img ]', $this->bbcode_tpl('url', $bbcode_id, true)),
							)
						);
					}
				break;

				case 5:
					$this->bbcode_cache[$bbcode_id] = array(
						'preg' => array(
							'#\[size=([\-\+]?\d+):$uid\](.*?)\[/size:$uid\]#s'	=> $this->bbcode_tpl('size', $bbcode_id),
						)
					);
				break;

				case 6:
					$this->bbcode_cache[$bbcode_id] = array(
						'preg' => array(
							'!\[color=(#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is'	=> $this->bbcode_tpl('color', $bbcode_id),
						)
					);
				break;

				case 7:
					$this->bbcode_cache[$bbcode_id] = array(
						'str' => array(
							'[u:$uid]'	=> $this->bbcode_tpl('u_open', $bbcode_id),
							'[/u:$uid]'	=> $this->bbcode_tpl('u_close', $bbcode_id),
						)
					);
				break;

				case 8:
					$this->bbcode_cache[$bbcode_id] = array(
						'preg' => array(
							'#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise'	=> "\$this->bbcode_second_pass_code('\$1', '\$2')",
						)
					);
				break;

				case 9:
					$this->bbcode_cache[$bbcode_id] = array(
						'preg' => array(
							'#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#'	=> "\$1",
							'#(\[list=([^\[]+):$uid\])[\n]{1}#'			=> "\$1",
							'#\[list=([^\[]+):$uid\]#e'					=> "\$this->bbcode_list('\$1')",
						),
						'str' => array(
							'[list:$uid]'		=> $this->bbcode_tpl('ulist_open_default', $bbcode_id),
							'[/list:u:$uid]'	=> $this->bbcode_tpl('ulist_close', $bbcode_id),
							'[/list:o:$uid]'	=> $this->bbcode_tpl('olist_close', $bbcode_id),
							'[*:$uid]'			=> $this->bbcode_tpl('listitem', $bbcode_id),
							'[/*:$uid]'			=> $this->bbcode_tpl('listitem_close', $bbcode_id),
							'[/*:m:$uid]'		=> $this->bbcode_tpl('listitem_close', $bbcode_id)
						),
					);
				break;

				case 10:
					$this->bbcode_cache[$bbcode_id] = array(
						'preg' => array(
							'#\[email:$uid\]((.*?))\[/email:$uid\]#is'			=> $this->bbcode_tpl('email', $bbcode_id),
							'#\[email=([^\[]+):$uid\](.*?)\[/email:$uid\]#is'	=> $this->bbcode_tpl('email', $bbcode_id)
						)
					);
				break;

				case 11:
					if ($user->optionget('viewflash'))
					{
						$this->bbcode_cache[$bbcode_id] = array(
							'preg' => array(
								'#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#'	=> $this->bbcode_tpl('flash', $bbcode_id),
							)
						);
					}
					else
					{
						$this->bbcode_cache[$bbcode_id] = array(
							'preg' => array(
								'#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#'	=> str_replace('$1', '$3', str_replace('$2', '[ flash ]', $this->bbcode_tpl('url', $bbcode_id, true)))
							)
						);
					}
				break;

				case 12:
					$this->bbcode_cache[$bbcode_id] = array(
						'str'	=> array(
							'[/attachment:$uid]'	=> $this->bbcode_tpl('inline_attachment_close', $bbcode_id)
						),
						'preg'	=> array(
							'#\[attachment=([0-9]+):$uid\]#'	=> $this->bbcode_tpl('inline_attachment_open', $bbcode_id)
						)
					);
				break;

				default:
					if (isset($rowset[$bbcode_id]))
					{
						if ($this->template_bitfield->get($bbcode_id))
						{
							// The bbcode requires a custom template to be loaded
							if (!$bbcode_tpl = $this->bbcode_tpl($rowset[$bbcode_id]['bbcode_tag'], $bbcode_id))
							{
								// For some reason, the required template seems not to be available, use the default template
								$bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
							}
							else
							{
								// In order to use templates with custom bbcodes we need
								// to replace all {VARS} to corresponding backreferences
								// Note that backreferences are numbered from bbcode_match
								if (preg_match_all('/\{(URL|LOCAL_URL|EMAIL|TEXT|SIMPLETEXT|IDENTIFIER|COLOR|NUMBER)[0-9]*\}/', $rowset[$bbcode_id]['bbcode_match'], $m))
								{
									foreach ($m[0] as $i => $tok)
									{
										$bbcode_tpl = str_replace($tok, '$' . ($i + 1), $bbcode_tpl);
									}
								}
							}
						}
						else
						{
							// Default template
							$bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
						}

						// Replace {L_*} lang strings
						$bbcode_tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl);

						if (!empty($rowset[$bbcode_id]['second_pass_replace']))
						{
							// The custom BBCode requires second-pass pattern replacements
							$this->bbcode_cache[$bbcode_id] = array(
								'preg' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
							);
						}
						else
						{
							$this->bbcode_cache[$bbcode_id] = array(
								'str' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
							);
						}
					}
					else
					{
						$this->bbcode_cache[$bbcode_id] = false;
					}
				break;
			}
		}
	}

	/**
	* Return bbcode template
	*/
	function bbcode_tpl($tpl_name, $bbcode_id = -1, $skip_bitfield_check = false)
	{
		static $bbcode_hardtpl = array();
		if (empty($bbcode_hardtpl))
		{
			global $user;
			
			$bbcode_hardtpl = array(
				'b_open'	=> '<span style="font-weight: bold">',
				'b_close'	=> '</span>',
				'i_open'	=> '<span style="font-style: italic">',
				'i_close'	=> '</span>',
				'u_open'	=> '<span style="text-decoration: underline">',
				'u_close'	=> '</span>',
				'img'		=> '<img src="$1" alt="' . $user->lang['IMAGE'] . '" />',
				'size'		=> '<span style="font-size: $1%; line-height: normal">$2</span>',
				'color'		=> '<span style="color: $1">$2</span>',
				'email'		=> '<a href="mailto:$1">$2</a>'
			);
		}

		if ($bbcode_id != -1 && !$skip_bitfield_check && !$this->template_bitfield->get($bbcode_id))
		{
			return (isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false;
		}

		if (empty($this->bbcode_template))
		{
			if (($tpl = file_get_contents($this->template_filename)) === false)
			{
				trigger_error('Could not load bbcode template', E_USER_ERROR);
			}

			// replace \ with \\ and then ' with \'.
			$tpl = str_replace('\\', '\\\\', $tpl);
			$tpl = str_replace("'", "\'", $tpl);

			// strip newlines and indent
			$tpl = preg_replace("/\n[\n\r\s\t]*/", '', $tpl);

			// Turn template blocks into PHP assignment statements for the values of $bbcode_tpl..
			$this->bbcode_template = array();

			$matches = preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END (?:.*?) -->#', $tpl, $match);

			for ($i = 0; $i < $matches; $i++)
			{
				if (empty($match[1][$i]))
				{
					continue;
				}

				$this->bbcode_template[$match[1][$i]] = $this->bbcode_tpl_replace($match[1][$i], $match[2][$i]);
			}
		}

		return (isset($this->bbcode_template[$tpl_name])) ? $this->bbcode_template[$tpl_name] : ((isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false);
	}

	/**
	* Return bbcode template replacement
	*/
	function bbcode_tpl_replace($tpl_name, $tpl)
	{
		global $user;

		static $replacements = array(
			'quote_username_open'	=> array('{USERNAME}'	=> '$1'),
			'color'					=> array('{COLOR}'		=> '$1', '{TEXT}'			=> '$2'),
			'size'					=> array('{SIZE}'		=> '$1', '{TEXT}'			=> '$2'),
			'img'					=> array('{URL}'		=> '$1'),
			'flash'					=> array('{WIDTH}'		=> '$1', '{HEIGHT}'			=> '$2', '{URL}'	=> '$3'),
			'url'					=> array('{URL}'		=> '$1', '{DESCRIPTION}'	=> '$2'),
			'email'					=> array('{EMAIL}'		=> '$1', '{DESCRIPTION}'	=> '$2')
		);

		$tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl);

		if (!empty($replacements[$tpl_name]))
		{
			$tpl = strtr($tpl, $replacements[$tpl_name]);
		}

		return trim($tpl);
	}

	/**
	* Second parse list bbcode
	*/
	function bbcode_list($type)
	{
		if ($type == '')
		{
			$tpl = 'ulist_open_default';
			$type = 'default';
		}
		else if ($type == 'i')
		{
			$tpl = 'olist_open';
			$type = 'lower-roman';
		}
		else if ($type == 'I')
		{
			$tpl = 'olist_open';
			$type = 'upper-roman';
		}
		else if (preg_match('#^(disc|circle|square)$#i', $type))
		{
			$tpl = 'ulist_open';
			$type = strtolower($type);
		}
		else if (preg_match('#^[a-z]$#', $type))
		{
			$tpl = 'olist_open';
			$type = 'lower-alpha';
		}
		else if (preg_match('#[A-Z]#', $type))
		{
			$tpl = 'olist_open';
			$type = 'upper-alpha';
		}
		else if (is_numeric($type))
		{
			$tpl = 'olist_open';
			$type = 'arabic-numbers';
		}
		else
		{
			$tpl = 'olist_open';
			$type = 'arabic-numbers';
		}

		return str_replace('{LIST_TYPE}', $type, $this->bbcode_tpl($tpl));
	}

	/**
	* Second parse quote tag
	*/
	function bbcode_second_pass_quote($username, $quote)
	{
		// when using the /e modifier, preg_replace slashes double-quotes but does not
		// seem to slash anything else
		$quote = str_replace('\"', '"', $quote);
		$username = str_replace('\"', '"', $username);

		// remove newline at the beginning
		if ($quote == "\n")
		{
			$quote = '';
		}

		$quote = (($username) ? str_replace('$1', $username, $this->bbcode_tpl('quote_username_open')) : $this->bbcode_tpl('quote_open')) . $quote;

		return $quote;
	}

	/**
	* Second parse code tag
	*/
	function bbcode_second_pass_code($type, $code)
	{
		// when using the /e modifier, preg_replace slashes double-quotes but does not
		// seem to slash anything else
		$code = str_replace('\"', '"', $code);

		switch ($type)
		{
			case 'php':
				// Not the english way, but valid because of hardcoded syntax highlighting
				if (strpos($code, '<span class="syntaxdefault"><br /></span>') === 0)
				{
					$code = substr($code, 41);
				}

			// no break;

			default:
				$code = str_replace("\t", '&nbsp; &nbsp;', $code);
				$code = str_replace('  ', '&nbsp; ', $code);
				$code = str_replace('  ', ' &nbsp;', $code);

				// remove newline at the beginning
				if (!empty($code) && $code[0] == "\n")
				{
					$code = substr($code, 1);
				}
			break;
		}

		$code = $this->bbcode_tpl('code_open') . $code . $this->bbcode_tpl('code_close');

		return $code;
	}
}

?>
Any ideas where I can go from here?

Thanks,
Tony David Potter

stevem
Registered User
Posts: 398
Joined: Sun Aug 25, 2002 1:59 pm

Re: LaTeX support in phpBB3

Post by stevem » Tue Feb 19, 2008 10:26 am

It looks as if you have put the include path to phpbb_hook_2.php in the wrong place in bbcode.php. It goes just before the code that sisteczko gives whereas you've put it just after.

Locked

Return to “[3.0.x] MOD Requests”