20000) {
$input = substr($input, 0, 20000);
}
/* ===============================
SAFE OUTPUT ESCAPER
=============================== */
function bb_e(string $value): string
{
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
/* ===============================
BUILD PATTERNS ENTERPRISE STYLE
=============================== */
$pattern = [];
$replace = [];
/* -------- BASIC TAGS (bounded, no catastrophic backtracking) -------- */
$pattern[] = "/\[b\]([^[]{0,5000})\[\/b\]/i";
$replace[] = "$1";
$pattern[] = "/\[i\]([^[]{0,5000})\[\/i\]/i";
$replace[] = "$1";
$pattern[] = "/\[u\]([^[]{0,5000})\[\/u\]/i";
$replace[] = "$1";
/* -------- UNIT TAGS (tid1–tid50) -------- */
for ($i = 1; $i <= 50; $i++) {
$pattern[] = "/\[tid{$i}\]/i";
$const = "U{$i}";
$title = defined($const) ? bb_e(constant($const)) : '';
$replace[] = "
";
}
/* -------- HERO -------- */
$pattern[] = "/\[hero\]/i";
$replace[] = "
";
/* -------- RESOURCES -------- */
$resources = [
'lumber' => ['class' => 'r1', 'title' => LUMBER],
'clay' => ['class' => 'r2', 'title' => CLAY],
'iron' => ['class' => 'r3', 'title' => IRON],
'crop' => ['class' => 'r4', 'title' => CROP],
];
foreach ($resources as $tag => $data) {
$title = bb_e($data['title']);
$pattern[] = "/\[{$tag}\]/i";
$replace[] = "
";
}
/* -------- SMILEYS -------- */
$smileys = [
"*aha*" => "aha","*angry*" => "angry","*cool*" => "cool","*cry*" => "cry",
"*cute*" => "cute","*depressed*" => "depressed","*eek*" => "eek",
"*ehem*" => "ehem","*emotional*" => "emotional","*hit*" => "hit",
"*hmm*" => "hmm","*hmpf*" => "hmpf","*hrhr*" => "hrhr","*huh*" => "huh",
"*lazy*" => "lazy","*love*" => "love","*nocomment*" => "nocomment",
"*noemotion*" => "noemotion","*notamused*" => "notamused","*pout*" => "pout",
"*redface*" => "redface","*rolleyes*" => "rolleyes","*shy*" => "shy",
"*smile*" => "smile","*tongue*" => "tongue",
"*veryangry*" => "veryangry","*veryhappy*" => "veryhappy",
];
foreach ($smileys as $code => $class) {
$pattern[] = "/" . preg_quote($code, '/') . "/";
$replace[] = "
";
}
/* basic emoticons */
$basic = [":D"=>"grin",":)"=>"happy",":("=>"sad",";)"=>"wink"];
foreach ($basic as $code => $class) {
$pattern[] = "/" . preg_quote($code, '/') . "/";
$replace[] = "
";
}
/* ===============================
SECURE PLACEHOLDER CALLBACKS
=============================== */
/* -------- ALLIANCE -------- */
$input = preg_replace_callback(
"/\[alliance(\d{1,20})\]([0-9]{1,20})\[\/alliance\d{1,20}\]/i",
static function ($m) {
global $database;
$aid = (int)$m[2];
$aname = $database->getAllianceName($aid);
return $aname
? "".bb_e($aname).""
: "Alliance not found!";
},
$input
);
/* -------- PLAYER -------- */
$input = preg_replace_callback(
"/\[player(\d{1,20})\]([0-9]{1,20})\[\/player\d{1,20}\]/i",
static function ($m) {
global $database;
$uid = (int)$m[2];
$uname = $database->getUserField($uid, "username", 0);
return ($uname && $uname !== "[?]")
? "".bb_e($uname).""
: "Player not found!";
},
$input
);
/* -------- REPORT -------- */
$input = preg_replace_callback(
"/\[report(\d{1,20})\]([0-9]{0,20})\[\/report\d{1,20}\]/i",
static function ($m) {
global $database;
$rid = (int)($m[1] ?: $m[2]);
$report = $database->getNotice2($rid, null, false);
return $report
? "".bb_e($report['topic']).""
: "Report not found!";
},
$input
);
/* -------- COORDINATES -------- */
$input = preg_replace_callback(
"/\[coor(\d{1,20})\](-?\d{1,4}\|-?\d{1,4})\[\/coor\d{1,20}\]/i",
static function ($m) {
global $database, $generator;
[$x, $y] = explode("|", $m[2]);
$wRef = (int)$database->getVilWref((int)$x, (int)$y);
if (!$wRef) return "Village not found!";
$cwref = (int)$generator->getMapCheck($wRef);
$state = $database->getVillageType($wRef);
if ($state > 0) {
$name = $database->getVillageState($wRef)
? $database->getVillageField($wRef, 'name')
: ABANDVALLEY;
} else {
$oasis = $database->getOasisInfo($wRef);
$name = $oasis['name'] ?? '';
}
return $name
? "".bb_e($name)." ({$x}|{$y})"
: "Village not found!";
},
$input
);
/* -------- REMOVE MESSAGE TAGS -------- */
$input = preg_replace('/\[\/?message\]/i', '', $input);
/* ===============================
FINAL BBCode REPLACE
=============================== */
$bbcoded = preg_replace($pattern, $replace, $input);