String OMLQuote::processHtml(shared_ptr<OMLItem> i, shared_ptr<OMLContext> context) const { mapDefaultParamTo(i, _S("title")); String title = encodeOML(context, i->getParam(_S("title"))); if(context->getMode() != omlRenderModeSearch) { if(i->hasParam(_S("id"))) { shared_ptr<const IPortalPage> page = context->getPortalPage(); if(page != nullptr) { String id = i->getParam(_S("id")); shared_ptr<EntitiesEntity> entity = page->getPortal()->getEntity(page->getDatabase(), id.to_ascii()); if(entity != nullptr) { shared_ptr<ObjectsIRevisionable> current = entity->getCurrent(); if(current != nullptr) { if(current->isVisible()) { shared_ptr<ObjectsUser> author = objects_user_cast(page->getObject(current->getAuthor())); String authorNick = encode(context, author->name); String itemDate = encode(context, context->getPage()->formatDate(current->submit_date, DateTime::dpUserFriendly)); String imageLinkUrl = context->getPage()->getSkin()->getResourceUrl(_S("images/oml/quote_link.gif")); imageLinkUrl = encode(context, imageLinkUrl); if(!title.empty()) title += _S(" "); String entryHref = encode(context, entity->getViewLink(page->getPortal())); title += String::format(_S("(%S @ %S)<a href=\"%S\"><img src=\"%S\"></a>").c_str(), authorNick.c_str(), itemDate.c_str(), entryHref.c_str(), imageLinkUrl.c_str()); } else { title += getText(context, _S("oml.quote.messages.hidden_id")); } } else { title += getText(context, _S("oml.quote.messages.skipped_id")); } } else { title += getText(context, _S("oml.quote.messages.unknown_id")); } } } } String body = i->getHtmlChilds(context); if(context->getMode() == omlRenderModeSearch) { return _S(" ") + title + _S(" ") + body + _S(" "); } else { return _S("<div class=\"") + OS_CSS_OML_QUOTETOP + _S("\">") + title + _S("</div><div class=\"") + OS_CSS_OML_QUOTEMAIN + _S("\">") + body + _S("</div>"); } }
String IOMLCode::encodeBody(shared_ptr<OMLContext> context, const String& text, bool postProcess, bool preserveStartLineSpaces, bool convertCR) { String value = text; if ( (postProcess) && (context->getMode() != omlRenderModeSearch) && (!context->getRow()) ) { // Detect degli url { String protocolsFindLinkOption = context->getPage()->getOption(Options::url_options::protocols_find_link); //String protocolsFindLinkOption = Options::instance()->getOption(Options::url_options::protocols_find_link); //String UrlMatch = _S("(")+getProtocolsFindLinkOption()+_S(")://(\\w*:\\w*@)?[-\\w.]+(:\\d+)?(/([\\w/_.]*(\\?\\S+)?)?)?"); //String UrlMatch = _S("((")+getProtocolsFindLinkOption()+_S(")(\\W+\\S+[^).,:;?\\]\\} \\r\\n$]+))"); //String UrlMatch = _S("(")+protocolsFindLinkOption+_S(")://(\\w*:\\w*@)?[-\\w.]+(:\\d+)?(/([\\w/_.]*(\\?\\S+)?)?)?"); // 0.11: //String UrlMatch = _S("(") + protocolsFindLinkOption + _S(")://\\S+"); // 1.0: String UrlMatch = _S("(") + protocolsFindLinkOption + _S("):[/\?]\\S+"); // La versione sotto sarebbe meglio, ma non funziona, ad esempio con il link seguente: // skype:?chat&blob=iCnRW4EXR0H_funqp8i2FpbcobXxBfFkllPp0s2NMRd_sbDEOEr5Je-RzNUi //String UrlMatch = _S("(")+protocolsFindLinkOption+_S("):\\S+"); String UrlReplace = _S("[url]$0[/url]"); //if(regex_match(value, RegexManager::instance()->getRegex(UrlMatch, true))) value = regex_replace(value, RegexManager::instance()->getRegex(UrlMatch, true), UrlReplace); //String MailMatch = _S("\\b((([A-Za-z0-9$_.+%=-])|%[A-Fa-f0-9]{2})+@(([A-Za-z0-9$_.+!*,;/?:%&=-])|%[A-Fa-f0-9]{2})+\\.[a-zA-Z0-9]{1,4})"); String MailMatch = _S("(\\w+\\.)*\\w+@(\\w+\\.)+[A-Za-z]+"); String MailReplace = _S("[email]$0[/email]"); //if(regex_match(value, RegexManager::instance()->getRegex(MailMatch, true))) value = regex_replace(value, RegexManager::instance()->getRegex(MailMatch, true), MailReplace); } if(value != text) { // Sono stati inseriti tag, ricomputo... return encodeOML(context, value); } } // Risolvo gli escaping value.replace_all(_S("\\["), _S("[")); //value.replace_all(_S("\\]"), _S("]")); // Encoding html value = encode(context, value); if(postProcess) { // Emoticons if( (context->getMode() != omlRenderModeSearch) && (context->getPage() != nullptr) ) { String valueLower = value; valueLower.to_lower(); //const StringMap &emoticons = IdeSystem::instance()->getEmoticons(); //for(StringMap::const_iterator i = emoticons.begin(); i != emoticons.end(); ++i) const OMLManager::Emoticons &emoticons = OMLManager::instance()->getEmoticons(); for(OMLManager::Emoticons::const_iterator i = emoticons.begin(); i != emoticons.end(); ++i) { //const String &code = i->first; shared_ptr<OMLEmoticon> emo = *i; const String &code = emo->getCode(); // Ottimizzazione, se non lo trovo con una 'find' secca sull'equivalente in lower-case, // inutile cercarlo via regex. if(valueLower.find(emo->getCode()) != String::npos) { //const String &name = i->second; const String &name = emo->getName(); String title = getText(context, _S("emoticons.") + name); String url = context->getPage()->getSkin()->getImageUrl(_S("emoticons/")+name+_S(".gif")); String out = String::format(_S(" <img src=\"%S\" alt=\"%S\" title=\"%S\"> ").c_str(), url.c_str(), code.c_str(), title.c_str()); // Se prima o dopo non c' niente, o c' un carattere : String codeRegexQuote = regex_quote(code); // RegEx presa da Invision // $txt = preg_replace( "!(?<=[^\w&;/])$code(?=.\W|\W.|\W$)!ei", "\$this->convert_emoticon('$code', '$image')", $txt ); //String re = _S("!(?<=[^\\w&;/])") + codeRegexQuote + _S("(?=.\\W|\\W.|\\W$)!ei"); //String re = _S("( ")+codeRegexQuote+_S(" |^")+codeRegexQuote+_S(" | ")+codeRegexQuote+_S("$|^")+codeRegexQuote+_S("$)"); // Non sono riuscito a far e il detect dei limiti della stringa, per cui aggiungo due spazi prima e trimmo dopo. value = _S(" ") + value + _S(" "); //String charsEmoBoundary = _S("\\s\\n\\r:),;"); //String re = String::format(_S("(?<=[%S])%S(?=[%S])").c_str(), charsEmoBoundary.c_str(), codeRegexQuote.c_str(), charsEmoBoundary.c_str()); String re = String::format(_S("(?<=[\\s])%S(?=[\\s])").c_str(), codeRegexQuote.c_str()); // URGENT: da ottimizzare con una // shared_ptr<boost::wregex> re = regex_create(regex, nocase); value = regex_replace(value, RegexManager::instance()->getRegex(re, true), out); // Tolgo i due spazi messi sopra value = value.substr(1,value.length()-2); } } } } // Encoding dei \n if ( (context->getMode() == omlRenderModeSearch) || (context->getRow()) ) { value.replace_all(_S("\n"), _S(" ")); } else { if(preserveStartLineSpaces) { for(;;) { String::size_type posCR = value.find(_S("\n")); if(posCR == String::npos) break; String::size_type posFirstNoSpace = value.find_first_not_of(_S(" "), posCR+1); if(posFirstNoSpace == String::npos) posFirstNoSpace = value.length(); String startLineText = value.substr(posCR+1, posFirstNoSpace - (posCR+1)); startLineText.replace_all(_S(" "),_S(" ")); value = value.substr(0,posCR) + _S("<br>") + startLineText + value.substr(posFirstNoSpace); } } else if(convertCR) { value.replace_all(_S("\n"), _S("<br />")); } } // Ulteriore encoding finale di sicurezza XSS, trasformo i '\' in '\'. value.replace_all(_S("\\"),_S("\")); return value; }