Make PHPBB 3.0.14 and ABBC3 compatible with PHP 7.3 - php

I'm trying to make ABBC3 work with PHP 7.3 and PHPBB 3.0.14 since I can't move to PHPBB 3.3 due lots of issues with MODs not ported to extensions and theme (Absolution).
I have asked help in PHPBB forum without luck because 3.0.x and 3.1.x version are not supported anymore.
So after dozens of hours trying to understand bbcode functions I'm almost ready.
My code works when there's a single bbcode in message. But doesn't works when there's more bbcode or it's mixed with texts.
So I would like to get some help to solve this part to make everything work.
In line 98 in includes/bbcode.php this function:
$message = preg_replace($preg['search'], $preg['replace'], $message);
Is returning something like this:
$message = "some text $this->Text_effect_pass('glow', 'red', 'abc') another text. $this->moderator_pass('"fernando"', 'hello!') more text"
For this message:
some text [glow=red]abc[/glow] another text.
[mod="fernando"]hello![/mod] more text
The input for preg_replace above is like this just for context:
"some text [glow=red:mkpanc3g]abc[/glow:mkpanc3g] another text. [mod="fernando":mkpanc3g]hello![/mod:mkpanc3g]"
So basically I have to split this string in valid expressions to apply eval() then concatenate everything. Like this:
$message = "some text". eval($this->Text_effect_pass('glow', 'red', 'abc');) . "another text " . eval($this->moderator_pass('"fernando"', 'hello!');). "more text"
In this specific case there's also double quotes left in '"fernando"'.
I know is not safe apply eval() to user input so I would like to make some type of preg_match and/or preg_split to get values inside of () to pass as parameter to my functions.
The functions are basically:
Text_effect_pass()
moderator_pass()
anchor_pass()
simpleTabs_pass()
I'm thinking in something like this (Please ignore errors here):
if(preg_match("/$this->Text_effect_pass/", $message)
{
then split the string and get value inside of() and remove extra single or double quotes.
after:
$textEffect = Text_effect_pass($value[0], $value[1], $value[2]);
Finally concatenate everything:
$message = $string[0] .$textEffect. $string[1];
}
if(preg_match("/$this->moderator_pass/", $message)
{
.....
}
P.S.: ABBC3 is not compatible with PHP 7.3 due usage of e modifier. I have edited everything to remove the modifier.
Here you can see it working separately:
bbcode 1
bbcode 2
Can someone give me some help please?

After long time searching for a solution for this problem I found this site that helped me build the regex.
Now I have managed to solve the problem and I have my forum fully working with PHPBB 3.14, PHP 7.3 and ABBC3.
My solution is:
// Start Text_effect_pass
$regex = "/(\\$)(this->Text_effect_pass)(\().*?(\')(,)( )(\').*?(\')(,)( )(\').*?(\'\))/is";
if (preg_match_all($regex, $message, $matches)) {
foreach ($matches[0] as $key => $func) {
$bracket = preg_split("/(\\$)(this->Text_effect_pass)/", $func);
$param = explode("', '", $bracket[1]);
$param[0] = substr($param[0], 2);
$param[2] = substr($param[2], 0, strrpos($param[2], "')"));
$effect = $this->Text_effect_pass($param[0], $param[1], $param[2]);
if ($key == 0) {
$init = $message;
} else {
$init = $mess;
}
$mess = str_replace($matches[0][$key], $effect, $init);
}
$message = $mess;
} // End Text_effect_pass
// Start moderator_pass
$regex = "/(\\$)(this->moderator_pass)(\().*?(\')(,).*?(\').*?(\'\))/is";
if (preg_match_all($regex, $message, $matches)) {
foreach ($matches[0] as $key => $func) {
$bracket = "/(\\$)(this->moderator_pass)/";
$bracket = preg_split($bracket, $func);
$param = explode("', '", $bracket[1]);
$param[0] = substr($param[0], 2);
$param[1] = substr($param[1], 0, strrpos($param[1], "')"));
$effect = $this->moderator_pass($param[0], $param[1]);
if ($key == 0) {
$init = $message;
} else {
$init = $mess;
}
$mess = str_replace($matches[0][$key], $effect, $init);
}
$message = $mess;
} // End moderator_pass
If someone is interested can find patch files and instructions here.
Best regards.

Related

PHP - find and replace a string between two variables when the length can't be determined

I'm trying to create a simple PHP find and replace system by looking at all of the images in the HTML and add a simple bit of code at the start and end of the image source. The image source has something like this:
<img src="img/image-file.jpg">
and it should become into this:
<img src="{{media url="wysiwyg/image-file.jpg"}}"
The Find
="img/image-file1.jpg"
="img/file-2.png"
="img/image3.jpg"
Replace With
="{{media url="wysiwyg/image-file.jpg"}}"
="{{media url="wysiwyg/file-2.png"}}"
="{{media url="wysiwyg/image3.jpg"}}"
The solution is most likely simple yet from all of the research that I have done. It only works with one string not a variety of unpredictable strings.
Current Progress
$oldMessage = "img/";
$deletedFormat = '{{media url="wysiwyg/';
$str = file_get_contents('Content Slots/Compilied Code.html');
$str = str_replace("$oldMessage", "$deletedFormat",$str);
The bit I'm stuck at is find the " at the end of the source to add the end of the required code "}}"
I don't like to build regular expressions to parse HTML, but it seems that in this case, a regular expression will help you:
$reg = '/=["\']img\/([^"\']*)["\']/';
$src = ['="img/image-file1.jpg"', '="img/file-2.png"', '="img/image3.jpg"'];
foreach ($src as $s) {
$str = preg_replace($reg, '={{media url="wysiwyg/$1"}}', $s);
echo "$str\n";
}
Here you have an example on Ideone.
To make it works with your content:
$content = file_get_contents('Content Slots/Compilied Code.html');
$reg = '/=["\']img\/([^"\']*)["\']/';
$final = preg_replace($reg, '={{media url="wysiwyg/$1"}}', $content);
Here you have an example on Ideone.
In my opinion what you are doing is not the best way this can be done. I would use abstract template for this.
<?php
$content = file_get_contents('Content Slots/Compilied Code.html');
preg_match_all('/=\"img\/(.*?)\"/', $content, $matches);
$finds = $matches[1];
$abstract = '="{{media url="wysiwyg/{filename}"}}"';
$concretes = [];
foreach ($finds as $find) {
$concretes[] = str_replace("{filename}", $find, $abstract);
}
// $conretes[] will now have all matches formed properly...
Edit:
To return full html use this:
<?php
$content = file_get_contents('Content Slots/Compilied Code.html');
preg_match_all('/=\"img\/(.*)\"/', $content, $matches);
$finds = $matches[1];
$abstract = '="{{media url="wysiwyg/{filename}"}}"';
foreach ($finds as $find) {
$content = preg_replace('/=\"img\/(.*)\"/', str_replace("{filename}", $find, $abstract), $content, 1);
}
echo $content;

Php Regex - How to pick if equals something

class Something
{
public static function compile(&$subject, $replace, $with) {
$placeholders = array_combine($replace, $with);
$condition = '{[a-z0-9\_\- ]+:[a-z_]+}';
$inner = '((?:(?!{/?if).)*?)';
$pattern = '#{if\s?('.$condition.')}'.$inner.'{/if}#is';
while (preg_match($pattern, $subject, $match)) {
$placeholder = $match[1];
$content = $match[2];
// if empty value remove whole line
// else show line but remove pseudo-code
$subject = preg_replace($pattern,
empty($placeholders[$placeholder]) ? '' : addcslashes($content, '$'),
$subject,
1);
}
}
}
I have a html code area to play on. Dompdf handles the rest for converting my form to pdf. This class code was almost premade. It gives me freedom to use ;
{if {dil:value}} <div class="english">ENGLISH</div> {/if}
something like that in html area. But it was only checking if radio button is empty or not. But I want to learn which option is selected. So I want to use a code like ;
{if {dil:value}=='ENGLISH'} <div class="english">ENGLISH</div> {/if}
I converted empty check line with manual equality check to see if it works;
// if empty value remove whole line
// else show line but remove pseudo-code
$subject = preg_replace($pattern,
$placeholders[$placeholder]=='english' ? '' : addcslashes($content, '$'),
$subject,
1);
And it worked but without a freedom of course(only if radio equals to english). I'm so new to regex, so I couldn't figure it out. I tried to add $equality variable so I would use my code many times with different checks;
class Something
{
public static function compile(&$subject, $replace, $with) {
$placeholders = array_combine($replace, $with);
$condition = '{[a-z0-9\_\- ]+:[a-z_]+}';
$inner = '((?:(?!{/?if).)*?)';
$equality = '(?<=~)[^}]*(?=~)';
$pattern = '#{if\s?('.$condition.')'.$equality.'}'.$inner.'{/if}#is';
while (preg_match($pattern, $subject, $match)) {
$placeholder = $match[1];
$content = $match[2];
// if empty value remove whole line
// else show line but remove pseudo-code
$subject = preg_replace($pattern,
$placeholders[$placeholder]==$equality ? '' : addcslashes($content, '$'),
$subject,
1);
}
}
}
with this code on html area;
{if {dil:value}~'ENGLISH'~} <div class="english">ENGLISH</div> {/if}
I really believed that it would work, but it didn't :) Even pattern didn't get erase after converting to pdf so I can read my code under the pdf file.
I may be missing something about $match too. With equality variable included so $match might get third array I guess. So I also tried to add this but that didn't work too;
while (preg_match($pattern, $subject, $match)) {
$placeholder = $match[1];
$equality = $match[2];
$content = $match[3];
Well my goal is to put check icons on to specific box areas on premade designed form image. I handled all textboxes with absolute positions except getting which radio button is checked.
Thank you for all your help.
I solved it like this;
class Something
{
public static function compile(&$subject, $replace, $with) {
$placeholders = array_combine($replace, $with);
$condition = '{[a-z0-9\_\- ]+:[a-z_]+}';
$inner = '((?:(?!{\/?if).)*?)';
$equality = '(~[A-ZÇŞĞÜÖİçşğüöı]+~)';
$pattern = '#{if\s?('.$condition.')}'.$equality.''.$inner.'{\/if}#is';
while (preg_match($pattern, $subject, $match)) {
$placeholder = $match[1];
$equality = $match[2];
$content = $match[3];
$equality = substr($equality, 1, -1);
// if empty value remove whole line
// else show line but remove pseudo-code
$subject = preg_replace($pattern,
$placeholders[$placeholder] == $equality ? '' : addcslashes($content, '$'),
$subject,
1);
}
}
}
I changed my equality regex to support Utf-8 characters plus changed other regexes a bit. There were non excaped slashes. And finally I can use it at html like this;
{if {language:value}}~FRENCH~<div class="english">ENGLISH</div>{/if}
So first match gets radio button value, second match is my equality check, and third match is what will be written if equality is wrong. Yep I know it sounds a little bit reversed mode :) So it probably won't work with radio buttons which have more than 2 options. But in my situations my all radio buttons have 2 options.
So far so good, I kinda learnt regex today :)

PHP telegram bot reply_mark

I'm programming a bot on telegram and I didn't make the special keyboard via reply_mark up someone can help me?
My code is this:
file_get_contents($website."/sendmessage?chat_id=".$myID."&text=keyTest&reply_markup={"keyboard":[["test"]]}");
If I copy&paste your parameters to my bot and execute the command it works. But that's because I use the Text you provide as parts of my url.
api.telegram.org/bot[key]/sendMessage?chat_id=[id]&text=keyTest&reply_markup={"keyboard":[["test"]]}
What you are doing is writing a script that executes the command. As far as I can tell you're using the dot . to concatenate strings. Another thing you're doing is trying to write the JSON for the reply_markup directly into the url.
What your problem probably is, is one of the following: You're not escaping the " sign or not concatenating variables correctly.
So if keyboard and test are variables you need to concatenate them correctly using the dot:
file_get_contents($website."/sendmessage?chat_id=".$myID."&text=keyTest&reply_markup={".$keyboard.":[[".$test."]]}");
but if you just want to write your test keyboard into the string you need to escape the " so your string does not end:
file_get_contents($website."/sendmessage?chat_id=".$myID."&text=keyTest&reply_markup={\"keyboard\":[[\"test\"]]}");
Note: I have no idea if this is the correct way to escape " in php. This is just to explain your error. If you need to escape double quotes in php any other way, do it how it is supposed to be.
OK, I think that I have the solution for you!
So, this is the code:
$key = "{\"keyboard\":[ [\"OPTION1\"], [\"OPTION2\"], [\"OPTION3\"] ]}";
$url = $GLOBALS[API_URL]."/sendmessage?chat_id=$id&text=Choose%20your%20action&reply_markup=".urlencode($key);
file_get_contents($url);
Variable $GLOBALS[API_URL] = https://api.telegram.org/bot123456789:AAf6g4fr4rt5y67hadsffaerafasfasf
So replace my global var with your direct url or whatever :D
Other function that should be interesting for you is this:
function close_keyboard($id, $message)
{
//$text = "Keyboard_closed!";
$message = str_replace(" ", "%20", $message);
$key = "{\"hide_keyboard\":true}";
$url = $GLOBALS[API_URL]."/sendmessage?chat_id=$id&text=$messagge&reply_markup=".urlencode($key);
file_get_contents($url);
}
This function close your custom keyboard, and other my personal function is this:
function build_keyboard($elements, $message, $chat_id)
{
//Get length of array
$len = count($elements);
//Build custom keyboard
$keyboard = "{\"keyboard\":[ [\"";
for($i = 0; $i < $len; ++$i)
{
if($i < $len-1)
$keyboard .= $elements[$i]."\"],[\"";
else
$keyboard .= $elements[$i]."\"] ]}";
}
$url = $GLOBALS[API_URL]."/sendmessage?chat_id=$chat_id&text=".urlencode($message)."&reply_markup=".urlencode($keyboard);
file_get_contents($url);
}
Prototype of this function is build_keyboard(array(), String, String)
Example:
$messagge = "Wrong choise";
$keyboard = array("OPT1", "OPT2", "OPT3");
build_keyboard($keyboard, $message, $chat_id);
Remember that $message is always needed or reply_doesntt work!
Hope this will be usefull! You're welcome!

Apply inline CSS to PHP preg_replace or str_replace function

I have a PHP function that is calling the following:
function availability_filter_func($availability) {
$replacement = 'Out of Stock - Contact Us';
if(is_single(array(3186,3518)))
$availability['availability'] = str_ireplace('Out of stock', $replacement, $availability['availability']);
}
As you can see I am replacing the text string with custom text, however
I need the "Contact Us" text to be Contact Us - how would I go about doing this? Inputting raw html into the replacement string makes the html a part of the output.
Echo does not work and breaks the PHP function - same with trying to escape the PHP function, inserting html on on the entire string, and unescape the function.
Any advice would be appreciated, thank you.
Your code seems to be a complex way of doing this
function availability_filter_func($availability) {
$default = "Out of Stock";
$string = "<a href='mailto:contact#example.com'>Contact Us</a>";
if($availablity !== "") {
$return = $availability;
} else {
$return = $default;
}
return "$return - $string";
}
Try the Heredoc Syntax
$replacement = <<<LINK
Contact Us
LINK;

Replacing {{string}} within php file

I'm including a file in one of my class methods, and in that file has html + php code. I return a string in that code. I explicitly wrote {{newsletter}} and then in my method I did the following:
$contactStr = include 'templates/contact.php';
$contactStr = str_replace("{{newsletter}}",$newsletterStr,$contactStr);
However, it's not replacing the string. The only reason I'm doing this is because when I try to pass the variable to the included file it doesn't seem to recognize it.
$newsletterStr = 'some value';
$contactStr = include 'templates/contact.php';
So, how do I implement the string replacement method?
You can use PHP as template engine. No need for {{newsletter}} constructs.
Say you output a variable $newsletter in your template file.
// templates/contact.php
<?= htmlspecialchars($newsletter, ENT_QUOTES); ?>
To replace the variables do the following:
$newsletter = 'Your content to replace';
ob_start();
include('templates/contact.php');
$contactStr = ob_get_clean();
echo $contactStr;
// $newsletter should be replaces by `Your content to replace`
In this way you can build your own template engine.
class Template
{
protected $_file;
protected $_data = array();
public function __construct($file = null)
{
$this->_file = $file;
}
public function set($key, $value)
{
$this->_data[$key] = $value;
return $this;
}
public function render()
{
extract($this->_data);
ob_start();
include($this->_file);
return ob_get_clean();
}
}
// use it
$template = new Template('templates/contact.php');
$template->set('newsletter', 'Your content to replace');
echo $template->render();
The best thing about it: You can use conditional statements and loops (full PHP) in your template right away.
Use this for better readability: https://www.php.net/manual/en/control-structures.alternative-syntax.php
This is a code i'm using for templating, should do the trick
if (preg_match_all("/{{(.*?)}}/", $template, $m)) {
foreach ($m[1] as $i => $varname) {
$template = str_replace($m[0][$i], sprintf('%s', $varname), $template);
}
}
maybe a bit late, but I was looking something like this.
The problem is that include does not return the file content, and easier solution could be to use file_get_contents function.
$template = file_get_contents('test.html', FILE_USE_INCLUDE_PATH);
$page = str_replace("{{nombre}}","Alvaro",$template);
echo $page;
based on #da-hype
<?php
$template = "hello {{name}} world! {{abc}}\n";
$data = ['name' => 'php', 'abc' => 'asodhausdhasudh'];
if (preg_match_all("/{{(.*?)}}/", $template, $m)) {
foreach ($m[1] as $i => $varname) {
$template = str_replace($m[0][$i], sprintf('%s', $data[$varname]), $template);
}
}
echo $template;
?>
Use output_buffers together with PHP-variables. It's far more secure, compatible and reusable.
function template($file, $vars=array()) {
if(file_exists($file)){
// Make variables from the array easily accessible in the view
extract($vars);
// Start collecting output in a buffer
ob_start();
require($file);
// Get the contents of the buffer
$applied_template = ob_get_contents();
// Flush the buffer
ob_end_clean();
return $applied_template;
}
}
$final_newsletter = template('letter.php', array('newsletter'=>'The letter...'));
<?php
//First, define in the template/body the same field names coming from your data source:
$body = "{{greeting}}, {{name}}! Are You {{age}} years old?";
//So fetch the data at the source (here we will create some data to simulate a data source)
$data_source['name'] = 'Philip';
$data_source['age'] = 35;
$data_source['greeting'] = 'hello';
//Replace with field name
foreach ($data_source as $field => $value) {
//$body = str_replace("{{" . $field . "}}", $value, $body);
$body = str_replace("{{{$field}}}", $value, $body);
}
echo $body; //hello, Philip! Are You 35 years old?
Note - An alternative way to do the substitution is to use the commented syntax.
But why does using the three square brackets work?
By default the square brackets allow you to insert a variable inside a string.
As in:
$name = 'James';
echo "His name is {$name}";
So when you use three square brackets around your variable, the innermost square bracket is dedicated to the interpolation of the variables, to display their values:
This {{{$field}}} turns into this {{field}}
Finally the replacement with str_replace function works for two square brackets.
no, don't include for this. include is executing php code. and it's return value is the value the included file returns - or if there is no return: 1.
What you want is file_get_contents():
// Here it is safe to use eval(), but it IS NOT a good practice.
$contactStr = file_get_contents('templates/contact.php');
eval(str_replace("{{newsletter}}", $newsletterStr, $contactStr));

Categories