2##############################################
3# Bitrix Site Manager Forum #
4# Copyright (c) 2002-2007 Bitrix #
6# mailto:admin@bitrixsoft.com #
7##############################################
12 require_once(
$_SERVER[
"DOCUMENT_ROOT"].
"/bitrix/modules/forum/lang/".LANGUAGE_ID.
"/errors.php");
34 parent::__construct();
35 $this->arFiles =
array();
36 $this->arFilesParsed =
array();
38 $this->arUserfields =
array();
39 $this->ajaxPage =
$GLOBALS[
"APPLICATION"]->GetCurPageParam(
"",
array(
"bxajaxid",
"logout"));
41 $this->userNameTemplate = str_replace(
array(
"#NOBR#",
"#/NOBR#"),
"", CSite::GetDefaultNameFormat());
42 $this->smilesGallery = \COption::GetOptionInt(
"forum",
"smile_gallery_id", 0);
46 AddEventHandler(
"main",
"TextParserAfterTags", Array(&$this,
"ParserFile"));
53 "HTML",
"ANCHOR",
"BIU",
"IMG",
54 "VIDEO",
"LIST",
"QUOTE",
"CODE",
55 "FONT",
"UPLOAD",
"NL2BR",
"SMILES",
58 if (is_array($arForum))
62 $result[$feature] = ((isset($arForum[
'ALLOW_'.$feature]) && $arForum[
'ALLOW_'.$feature] ==
'Y') ?
'Y' :
'N');
71 $arEditorFeatures =
array(
72 "ALLOW_QUOTE" =>
array(
'Quote'),
73 'ALLOW_ANCHOR' =>
array(
'CreateLink'),
74 "ALLOW_VIDEO" =>
array(
'InputVideo'),
75 "ALLOW_UPLOAD" =>
array(
'UploadFile'),
76 "ALLOW_MENTION" =>
array(
'MentionUser')
80 $res = array_intersect_key(
$arParams[
'forum'], $arEditorFeatures);
81 foreach (
$res as $featureName =>
$val)
92 static $arEditorFeatures =
array(
93 "ALLOW_BIU" =>
array(
'Bold',
'Italic',
'Underline',
'Strike',
'Spoiler'),
94 "ALLOW_FONT" =>
array(
'ForeColor',
'FontList',
'FontSizeList'),
95 "ALLOW_QUOTE" =>
array(
'Quote'),
96 "ALLOW_CODE" =>
array(
'Code'),
97 'ALLOW_ANCHOR' =>
array(
'CreateLink',
'DeleteLink'),
98 "ALLOW_IMG" =>
array(
'Image'),
99 "ALLOW_VIDEO" =>
array(
'InputVideo'),
100 "ALLOW_TABLE" =>
array(
'Table'),
101 "ALLOW_ALIGN" =>
array(
'Justify'),
102 "ALLOW_LIST" =>
array(
'InsertOrderedList',
'InsertUnorderedList'),
103 "ALLOW_SMILES" =>
array(
'SmileList'),
111 foreach ($arEditorFeatures as $featureName => $toolbarIcons)
118 foreach ($arEditorFeatures as $featureName => $toolbarIcons)
120 if (isset(
$arParams[
'forum'][$featureName]) && (
$arParams[
'forum'][$featureName] ==
'Y'))
125 $result = array_merge(
$result,
array(
'MentionUser',
'UploadFile',
'RemoveFormat',
'Source'));
126 if (LANGUAGE_ID ==
'ru')
136 $this->imageWidth = (isset($this->image_params[
"width"]) && $this->image_params[
"width"] > 0 ? $this->image_params[
"width"] : ($this->imageWidth > 0 ? $this->imageWidth : 300));
137 $this->imageHeight = (isset($this->image_params[
"height"]) && $this->image_params[
"height"] > 0 ? $this->image_params[
"height"] : ($this->imageHeight > 0 ? $this->imageHeight : 300));
139 $this->userPath = str_replace(
array(
"#UID#",
"#uid#"),
"#user_id#", (empty($this->userPath) && !empty($this->pathToUser) ? $this->pathToUser : $this->userPath));
144 if (!empty($this->arUserfields))
145 $allow[
"USERFIELDS"] = $this->arUserfields;
149 if (!isset(
$allow[
'TABLE']))
152 $this->allow = array_merge((is_array($this->allow) ? $this->allow :
array()),
$allow);
154 $this->parser_nofollow = COption::GetOptionString(
"forum",
"parser_nofollow",
"Y");
155 $this->link_target = COption::GetOptionString(
"forum",
"parser_link_target",
"_blank");
159 $this->arFilesIDParsed =
array();
167 $this->arFiles = (is_array($files) ? $files : ($files ?
array($files) :
array()));
168 $this->arFilesIDParsed =
array();
173 "RECIPIENT_ID" => intval(
$params[
"RECIPIENT_ID"]),
187 )),
array(
"SMILES" =>
"N"));
189 $this->RECIPIENT_ID = $mail[
"RECIPIENT_ID"];
190 $this->SITE_ID = $mail[
"SITE_ID"];
192 if (is_array($this->arUserfields))
194 foreach ($this->arUserfields as &
$f)
204 if (!empty($this->arFiles))
206 if (preg_match(
"/\\[cut(([^\\]])*)\\]/isu",
$text,
$matches))
208 $text = preg_replace(
209 array(
"/\\[cut(([^\\]])*)\\]/isu",
210 "/\\[\\/cut\\]/isu"),
214 while (preg_match(
"/(\001([^\002]*)\002([^\001\002\003]+)\003)/isu",
$text, $arMatches))
215 $text = preg_replace(
216 "/(\001([^\002]*)\002([^\001\002\003]+)\003)/isu",
217 "\n>================== CUT ===================\n\\3\n>==========================================\n",
219 $text = preg_replace(
220 array(
"/\001([^\002]+)\002/",
234 if (method_exists($obj,
"convert_attachment"))
236 $tmpType = $obj->type;
238 $text = preg_replace_callback(
"/\[file([^\]]*)id\s*=\s*([0-9]+)([^\]]*)\]/isu",
array($this,
"convert_attachment"),
$text);
239 $obj->type = $tmpType;
245 $marker = (mb_strtolower($marker) ==
"code" ?
"code" :
"quote");
247 $this->{$marker.
"_open"}++;
248 if ($this->type ==
"rss")
249 return "\n====".$marker.
"====\n";
250 else if ($this->type ==
"mail")
251 return ($marker ==
"code" ?
"<code>" :
"<blockquote>");
252 else if ($this->bMobile)
253 return "<div class='blog-post-".$marker.
"' title=\"".($marker ==
"quote" ?
GetMessage(
"FRM_QUOTE") :
GetMessage(
"FRM_CODE")).
"\"><table class='blog".$marker.
"'><tr><td>";
255 return '<div class="entry-'.$marker.
'"><table class="forum-'.$marker.
'"><thead><tr><th>'.($marker ==
"quote" ?
GetMessage(
"FRM_QUOTE") :
GetMessage(
"FRM_CODE")).
'</th></tr></thead><tbody><tr><td>';
260 $marker = (mb_strtolower($marker) ==
"code" ?
"code" :
"quote");
262 if ($this->{$marker.
"_open"} == 0)
264 $this->{$marker.
"_error"}++;
267 $this->{$marker.
"_closed"}++;
269 if ($this->type ==
"rss")
270 return "\n=============\n";
271 else if ($this->type ==
"mail")
272 return ($marker ==
"code" ?
"</code>" :
"</blockquote>");
273 else if ($this->bMobile)
274 return "</td></tr></table></div>";
276 return "</td></tr></tbody></table></div>";
283 if (empty(
$url))
return "";
284 $type = (mb_strtolower($this->type) ==
"rss" ?
"rss" :
"html");
286 $bErrorIMG = !preg_match(
"/^(http|https|ftp|\/)/iu",
$url);
292 return "[img]".$url.
"[/img]";
295 return '<img src="'.$url.
'" alt="'.
GetMessage(
"FRM_IMAGE_ALT").
'" border="0" />';
298 if (preg_match_all(
"/width\=(?P<width>\d+)|height\=(?P<height>\d+)/isu",
$params,
$matches)):
303 "bitrix:forum.interface",
304 $this->imageTemplate,
307 "SIZE" =>
array(
"width" =>
$width,
"height" => $height),
308 "MAX_SIZE" =>
array(
"width" => $this->imageWidth,
"height" => $this->imageHeight),
309 "HTML_SIZE"=>
array(
"width" => $this->imageHtmlWidth,
"height" => $this->imageHtmlHeight),
315 array(
"HIDE_ICONS" =>
"Y"));
321 if (is_array($fileID))
325 $fileID = $fileID[2];
328 $fileID = intval($fileID);
332 $this->arFiles = (is_array($this->arFiles) ? $this->arFiles :
array($this->arFiles));
333 if ($fileID <= 0 || (!array_key_exists($fileID, $this->arFiles) && !in_array($fileID, $this->arFiles)))
336 if (!array_key_exists($fileID, $this->arFiles) && in_array($fileID, $this->arFiles)):
337 unset($this->arFiles[array_search($fileID, $this->arFiles)]);
338 $this->arFiles[$fileID] = $fileID;
341 if (!is_array($this->arFiles[$fileID]))
342 $this->arFiles[$fileID] = CFile::GetFileArray($fileID);
344 if (!is_array($this->arFiles[$fileID])):
345 unset($this->arFiles[$fileID]);
349 if (!array_key_exists($fileID, $this->arFilesParsed) || empty($this->arFilesParsed[$fileID][
$type]))
351 $arFile = $this->arFiles[$fileID];
355 if (preg_match_all(
"/width\=(?P<width>\d+)|height\=(?P<height>\d+)/isu",
$p,
$matches)):
360 "bitrix:forum.interface",
364 "SHOW_MODE" => (
$type ==
"html" ?
"THUMB" :
"RSS"),
365 "SIZE" =>
array(
"width" =>
$width,
"height" => $height),
366 "MAX_SIZE" =>
array(
"width" => $this->imageWidth,
"height" => $this->imageHeight),
367 "HTML_SIZE"=>
array(
"width" => $this->imageHtmlWidth,
"height" => $this->imageHtmlHeight),
369 "NAME_TEMPLATE" => $this->userNameTemplate,
374 array(
"HIDE_ICONS" =>
"Y"));
378 $path =
'/bitrix/components/bitrix/forum.interface/show_file.php?fid='.$arFile[
"ID"];
379 $bIsImage = (CFile::CheckImageFile(CFile::MakeFileArray($fileID)) ===
null);
385 $arFile[
"bbcode"] = ($bIsImage ?
'[IMG]'.$path.
'[/IMG]' :
'[URL='.$path.
']'.$arFile[
"ORIGINAL_NAME"].
'[/URL]');
388 $arFile[
"mail"] = $arFile[
"ORIGINAL_NAME"].($bIsImage ?
" (IMAGE: ".$path.
")" :
" (URL: ".$path.
")");
392 $this->arFilesParsed[$fileID] = $arFile;
394 $this->arFilesIDParsed[] = $fileID;
395 return $this->arFilesParsed[$fileID][
$type];
417 $text = preg_replace(
419 "#^(.+?)<cut[\s]*(/>|>).*?$#isu",
420 "#^(.+?)\[cut[\s]*(/\]|\]).*?$#isu"),
423 return $this->
convert(
$text, $arAllow,
"rss", $arImages);
428 $classAdditional = (!empty(
$fields[
'CLASS_ADDITIONAL']) ?
$fields[
'CLASS_ADDITIONAL'] :
'');
435 return "<span class=\"blog-p-user-name\">{$userName}</span>";
438 $anchorId = RandString(8);
440 return '<a class="blog-p-user-name'.$classAdditional.
'" id="bp_'.$anchorId.
'" href="'.CComponentEngine::MakePathFromTemplate(
$pathToUser,
array(
"user_id" =>
$userId)).
'" bx-tooltip-user-id="'.(!$this->bMobile ?
$userId :
'').
'">'.
$userName.
'</a>';
450 return parent::clearAllTags(
$text);
457 private $parse_search_needle =
'/([^\[]*)(?:\[(.*)\])*/iu';
458 private $parse_tag =
"/<(?<closing>\/?)(?<tag>[a-z]+)(?<params>.*?)(?<selfclosing>\/?)>/ismu";
459 private $parse_params =
'/([a-z\-]+)\s*=\s*(?:([^\s]*)|(?:[\'"]([^\'"])[\'"]))/imu';
460 private $lastError =
'';
461 private $preg =
array(
463 "pattern" =>
array(),
469 $this->data = $this->prepare($data);
475 private function prepare(
string $text): string
477 $text = preg_replace_callback(
478 "/<pre>(.+?)<\\/pre>/isu",
479 [$this,
"defendTags"],
482 $text = str_replace([
"\r\n",
"\n",
"\t"],
"",
$text);
483 $text = str_replace($this->preg[
"pattern"], $this->preg[
"replace"],
$text);
484 $this->preg[
"pattern"] =
array();
485 $this->preg[
"replace"] =
array();
495 $text =
"<\017#".(++$this->preg[
"counter"]).
">";
496 $this->preg[
"pattern"][] =
$text;
497 $this->preg[
"replace"][] =
$matches[0];
506 if (preg_match($this->parse_search_needle, $needle,
$matches ) == 0)
514 $arAttr = explode(
';',
$matches[2]);
515 foreach($arAttr as $attr)
517 list($attr_name, $attr_value) = explode(
'=', $attr);
518 $search[mb_strtoupper(trim($attr_name))] = trim($attr_value);
533 if (mb_strlen(
$matches[
'closing']) <= 0 && $tag_name == $search[
'TAG'])
537 if (preg_match_all($this->parse_params,
$params,
$arParams, PREG_SET_ORDER ) > 0)
540 $arTagParams =
array();
542 $arTagParams[mb_strtoupper(trim($arParam[1]))] = trim(trim($arParam[2]),
'"\'');
545 foreach($search as
$key => $value)
547 if (
$key ==
'TAG')
continue;
548 if (!( isset($arTagParams[
$key]) && $arTagParams[
$key] == $value))
561 $offset += $localOffset;
562 $tmp = mb_substr(
$tmp, $localOffset);
576 static $tags_open =
array(
'<!--',
'<script');
577 static $tags_close =
array(
'-->',
'</script>');
581 if (!is_array($tags_quoted))
582 for (
$i=0;
$i<$n_tags;
$i++)
583 $tags_quoted[
$i] =
array(
'open' => preg_quote($tags_open[
$i]),
'close' => preg_quote($tags_close[
$i]));
585 for (
$i=0;
$i<$n_tags;
$i++)
587 if (preg_match(
'#^\s*'.$tags_quoted[
$i][
'open'].
'#iu',
$tmp) < 1)
continue;
588 if (preg_match(
'#('.$tags_quoted[
$i][
'close'].
'[^<]*)#imu',
$tmp,
$matches) > 0)
591 $offset = $endpos + mb_strlen(
$matches[1]);
600 $this->lastError = $msg;
606 if ($startIndex ===
false || (intval($startIndex) == 0 && $startIndex !== 0))
607 return $this->
setError(
'E_PARSE_INVALID_INDEX');
608 $tmp = mb_substr($this->data, $startIndex);
610 $this->lastError =
'';
619 $tag_name = mb_strtoupper(
$matches[
'tag']);
624 if (end($arStack) == $tag_name)
631 for (
$i=2;
$i<=$closeMistmatch+1;
$i++)
633 if (
sizeof($arStack) >
$i && $arStack[
sizeof($arStack)-
$i] == $tag_name)
635 $arStack = array_slice($arStack, 0, -
$i);
641 return $this->
setError(
'E_PARSE_INVALID_DOM_2');
645 else if (
$matches[
'selfclosing'] ==
'/')
649 else if ($tag_name ==
'LI' && end($arStack) ==
'LI')
655 $arStack[] = $tag_name;
657 if (
sizeof($arStack) > 300)
659 return $this->
setError(
'E_PARSE_TOO_BIG_DOM_3');
661 else if (
sizeof($arStack) == 0)
663 return $offset + $localOffset;
667 $offset += $localOffset;
668 $tmp = mb_substr(
$tmp, $localOffset);
677 return $this->
setError(
'E_PARSE_INVALID_DOM_4');
684 if ($messageStart ===
false)
return '';
685 $messageEnd = $this->
findTagEnd($messageStart);
686 if ($messageEnd !==
false)
687 $messagePost = mb_substr($this->data, $messageStart, $messageEnd);
688 return trim($messagePost);
693 $startPos = mb_strpos($this->data, $startLabel);
694 if ($startPos ===
false)
return '';
695 $startPos += mb_strlen($startLabel);
696 $endPos = mb_strpos($this->data, $endLabel, $startPos);
697 if ($endPos ===
false)
return '';
698 return trim(mb_substr($this->data, $startPos, $endPos - $startPos));
706 if(defined(
"BX_COMP_MANAGED_CACHE"))
723 AddEventHandler(
"main",
"OnCancelRatingVote", Array(&$this,
"OnRate"));
730 is_array($arDictCollection) &&
731 (
sizeof($arDictCollection) > 9)
734 reset($arDictCollection);
735 $arFirst = current($arDictCollection);
736 $arKeys = array_keys($arFirst);
739 foreach($arDictCollection as &$arDictionary)
744 foreach($arKeys as
$k)
746 if (isset($arDictionary[
$k]) && ($arDictionary[
$k] === $arFirst[
$k]))
747 unset($arDictionary[
$k]);
751 return $arDictCollection;
754 public static function Expand($arDictCollection)
757 is_array($arDictCollection) &&
758 (
sizeof($arDictCollection) > 9) &&
759 is_array($arDictCollection[0])
763 $arFirst =& $arDictCollection[0];
764 $arKeys = array_keys($arFirst);
767 foreach($arDictCollection as &$arDictionary)
772 foreach($arKeys as
$k)
774 if (!isset($arDictionary[
$k]))
776 $arDictionary[
$k] = $arFirst[
$k];
781 return $arDictCollection;
787 if (! defined(
"BX_COMP_MANAGED_CACHE"))
792 foreach ($tags as $tag)
806 static $forum =
"forum_";
807 static $topic =
"forum_topic_";
825 if (!isset($arData[
'ENTITY_TYPE_ID']) ||
826 !isset($arData[
'ENTITY_ID']) ||
827 ($arData[
'ENTITY_TYPE_ID'] !==
'FORUM_POST' && $arData[
'ENTITY_TYPE_ID'] !==
'FORUM_TOPIC'))
830 if ($arData[
'ENTITY_TYPE_ID'] ===
'FORUM_POST')
834 $this->
ClearTag(
"T", $arMessage[
'TOPIC_ID']);
836 else if ($arData[
'ENTITY_TYPE_ID'] ===
'FORUM_TOPIC')
840 $this->
ClearTag(
"F", $arTopic[
'FORUM_ID']);
841 $this->
ClearTag(
"T", $arData[
'ENTITY_ID']);
854 $arMessage = (is_array($arMessage) ? $arMessage :
array());
855 if ($topic_id =
$arFields[
"FORUM_TOPIC_ID"] ??
$arFields[
"TOPIC_ID"] ?? $arMessage[
"TOPIC_ID"] ?? 0)
859 if ($forum_id =
$arFields[
"FORUM_ID"] ?? $arMessage[
"FORUM_ID"] ?? 0)
861 $this->
ClearTag(
"forum_msg_count" . $forum_id);
867 self::ClearTag(
"T", isset($arMessage[
"FORUM_TOPIC_ID"]) ? $arMessage[
"FORUM_TOPIC_ID"] : $arMessage[
"TOPIC_ID"]);
908 private static $instance;
919 if (!
$GLOBALS[
'USER']->IsAuthorized())
921 if (COption::GetOptionString(
"forum",
"USE_AUTOSAVE",
"Y") ===
"N")
924 if (!isset(self::$instance))
927 self::$instance =
new $c;
930 return self::$instance;
941 $id = $this->as->GetID();
945 window.autosave_<?=$id?>_func =
function() { ForumFormAutosave(<?=
$jsParams?>); window.autosave_<?=$id?>.Prepare(); };
946 if (!!window[
"ForumFormAutosave"])
947 window.autosave_<?=$id?>_func();
950 BX.addCustomEvent(window,
'onScriptForumAutosaveLoaded', window.autosave_<?=$id?>_func);
951 BX.loadScript(
"<?=CUtil::GetAdditionalFileURL("/bitrix/js/forum/autosave.js
")?>");
960 return $this->as->Init(
false);
965 return $this->as->Reset();
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
static GetByID($ID, $arAddParams=array())
static GetByID($ID, $arAddParams=array())
static ClearTag($type, $ID=0)
static SetTag($path, $tags)
OnTopicUpdate($ID, $arFields)
OnMessageAdd($ID, $arFields)
OnForumUpdate($ID, $arFields)
OnTopicDelete(&$ID, $arTopic)
OnTopicAdd($ID, $arFields)
OnMessageUpdate($ID, $arFields, $arMessage=array())
static Compress($arDictCollection)
static Expand($arDictCollection)
OnMessageDelete($ID, $arMessage)
getInnerHTML($startLabel, $endLabel, $multiple=false)
static URN2URI($urn, $server_name='')
static Init($arExt=array(), $bReturn=false)
defended_tags($text, $tag='replace')
convertText($text, $attributes=[])
convert_attachment($fileID="", $p="", $type="", $text="")
static GetFeatures($arForum)
ParserFile(&$text, &$obj, $type="html")
convert4mail($text, $files=false, $allow=array(), $params=array())
convert_image_tag($url="", $params="")
static GetEditorButtons($arParams)
convert_close_tag($marker="quote")
static GetEditorToolbar($arParams)
convert_to_rss( $text, $arImages=Array(), $arAllow=Array())
convert_open_tag($marker="quote")
__construct($lang=false, $pathToSmiles='', $type=false, $mode='full')
convert($text, $allow=array(), $type="html", $arFiles=false, $attributes=[])
if(!is_array($prop["VALUES"])) $tmp
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
$_SERVER["DOCUMENT_ROOT"]
if(!defined('SITE_ID')) $lang
AddEventHandler($FROM_MODULE_ID, $MESSAGE_ID, $CALLBACK, $SORT=100, $FULL_PATH=false)
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
GetMessage($name, $aReplace=null)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
$GLOBALS['_____370096793']