数値の HTML エンティティをプレーンテキスト文字に相当するものに変換する方法が必要です。たとえば、エンティティを次のように変更したいと思います。
é
キャラクターに:
é
グーグルで調べてみると、 HtmlUnEditFormatという関数が見つかりましたが、この関数は名前付きエンティティのみを変換します。ColdFusion で数値エンティティをデコードする方法はありますか?
数値の HTML エンティティをプレーンテキスト文字に相当するものに変換する方法が必要です。たとえば、エンティティを次のように変更したいと思います。
é
キャラクターに:
é
グーグルで調べてみると、 HtmlUnEditFormatという関数が見つかりましたが、この関数は名前付きエンティティのみを変換します。ColdFusion で数値エンティティをデコードする方法はありますか?
CF(およびRailo)にパッケージ化されているApache Commons StringEscapeUtilsライブラリを使用して、これを行うための非常に簡単な方法を指摘してくれたTodd Sharpに感謝します。
<cfset Entity = "&##0233;" />
<cfset StrEscUtils = createObject("java", "org.apache.commons.lang.StringEscapeUtils") />
<cfset Character = StrEscUtils.unescapeHTML(Entity) />
そのリンクされた関数は厄介です-明示的に名前を付ける必要はありません。また、あなたが言うように、数値を実行しません。
XmlParse
関数を使用して、CFに作業を任せる方がはるかに簡単です。
<cffunction name="decodeHtmlEntity" returntype="String" output="false">
<cfargument name="Entity" type="String" hint="&##<number>; or &<name>;" />
<cfreturn XmlParse('<xml>#Arguments.Entity#</xml>').XmlRoot.XmlText />
</cffunction>
これは Railo で動作しますが、CF がその構文をサポートしているかどうかはまだ思い出せないので、次のように変更する必要があるかもしれません。
<cffunction name="decodeHtmlEntity" returntype="String" output="false">
<cfargument name="Entity" type="String" hint="&##<number>; or &<name>;" />
<cfset var XmlDoc = XmlParse('<xml>#Arguments.Entity#</xml>') />
<cfreturn XmlDoc.XmlRoot.XmlText />
</cffunction>
文字列内のすべての数値 html 文字エンティティをデコードする別の関数を次に示します。xml 解析に依存しないため、不均衡な xml タグを含む文字列で機能します。文字列に多数のエンティティがある場合は効率的ではありませんが、エンティティがない場合や少ない場合はかなり有効です。これは AdobeCF ではなく、Railo でのみテストしました。
<cffunction name="decodeHtmlEntities" returntype="String" output="false">
<cfargument name="s" type="String"/>
<cfset var LOCAL = {f = ReFind("&##([0-9]+);", ARGUMENTS.s, 1, true), map={}}>
<cfloop condition="LOCAL.f.pos[1] GT 0">
<cfset LOCAL.map[mid(ARGUMENTS.s, LOCAL.f.pos[1], LOCAL.f.len[1])] = chr(mid(ARGUMENTS.s, LOCAL.f.pos[2], LOCAL.f.len[2]))>
<cfset LOCAL.f = ReFind("&##([0-9]+);", ARGUMENTS.s, LOCAL.f.pos[1]+LOCAL.f.len[1], true)>
</cfloop>
<cfloop collection=#LOCAL.map# item="LOCAL.key">
<cfset ARGUMENTS.s = Replace(ARGUMENTS.s, LOCAL.key, LOCAL.map[LOCAL.key], "all")>
</cfloop>
<cfreturn ARGUMENTS.s />
</cffunction>
自分でコーディングするのは非常に簡単なはずです。見つけた HtmlUNEditFormat() 関数を編集して、lEntities と lEntitiesChars の最後に含めます。
ブラックボックスの原則により、着信文字列が HTML エンティティでエンコードされているか、そうでないかを信頼できないメソッドを使用しているときに、この質問を見つけました。
HTML エンティティでまだ処理されていない文字列で安全に使用できるように、Peter Boughton の関数を適合させました。(これが問題になるのは、アンパサンドがゆるい場合 ("Cats & Dogs" など) だけです。) この変更されたバージョンは、予期しない XML 解析エラーが発生した場合にも、ある程度適切に失敗します。
<cffunction name="decodeHtmlEntity" returntype="string" output="false">
<cfargument name="str" type="string" hint="&##<number>; or &<name>;" />
<cfset var XML = '<xml>#arguments.str#</xml>' />
<cfset var XMLDoc = '' />
<!--- ampersands that aren't pre-encoded as entities cause errors --->
<cfset XML = REReplace(XML, '&(?!(\##\d{1,3}|\w+);)', '&', 'all') />
<cftry>
<cfset XMLDoc = XmlParse(XML) />
<cfreturn XMLDoc.XMLRoot.XMLText />
<cfcatch>
<cfreturn arguments.str />
</cfcatch>
</cftry>
</cffunction>
これにより、次のユースケースが安全にサポートされます。
<cffunction name="notifySomeoneWhoCares" access="private" returntype="void">
<cfargument name="str" type="string" required="true"
hint="String of unknown preprocessing" />
<cfmail from="process@domain.com" to="someoneWhoCares@domain.com"
subject="Comments from Web User" format="html">
Some Web User Spoke Thus:<br />
<cfoutput>#HTMLEditFormat(decodeHTMLEntity(arguments.str))#</cfoutput>
</cfmail>
</cffunction>
この関数は、Web で送信されたコンテンツが、電子メールで送信されるか、データベース テーブルに送信される前に、エンティティ セーフ (XSS を考えてください) であることを確認するのに非常に役立ちます。
お役に立てれば。