Files
payg/lib/track.cfm
T
2025-08-16 14:53:13 +03:00

104 lines
4.8 KiB
Plaintext

<cfsilent><!--- утилита для передачи стека вызовов через URL --->
<!---v1.01 14:00 03.04.2019 added output param thisURL--->
<!---v1.02 06:16 26.12.2019 symbols -._ are not encoded --->
<cfparam name="ATTRIBUTES.thisUrl" type="string" default=""><!--- текущий URL без трэка --->
<cfparam name="ATTRIBUTES.output" type="string" default="tr">
<cfparam name="ATTRIBUTES.input" type="string" default="track"><!--- имя параметра в URL или FORM, в которой лежит текущий трэк --->
<cfparam name="ATTRIBUTES.urlParamName" type="string" default="#ATTRIBUTES.input#">
<cfparam name="ATTRIBUTES.defaultBackUrl" type="string">
<!---<cffunction name="urlSafeWrap">
<cfargument name="s" type="string"/>
<cfreturn replace(URLEncodedFormat(s), "%", "!", "ALL")/>
</cffunction>--->
<!---<cffunction name="urlSafeWrap">
<cfargument name="s" type="string"/>
<cfreturn
replace(
replaceList(
URLEncodedFormat(s),
"#URLEncodedFormat('_')#,#URLEncodedFormat('.')#,#URLEncodedFormat('-')#,#URLEncodedFormat('~')#,#URLEncodedFormat('=')#",
"_,.,-,~,="
),
"%", "!", "ALL"
)/>
</cffunction>--->
<cffunction name="urlSafeWrap">
<cfargument name="s" type="string"/>
<cfreturn
replace(
replaceList(
URLEncodedFormat(s),
"#URLEncodedFormat('_')#,#URLEncodedFormat('.')#,#URLEncodedFormat('-')#",
"_,.,-"
),
"%", "!", "ALL"
)/><!---unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" https://www.ietf.org/rfc/rfc3986.txt--->
</cffunction>
<cffunction name="urlSafeUnWrap">
<cfargument name="s" type="string"/>
<cfreturn URLDecode(replace(s, "!", "%","ALL"))/>
</cffunction>
<cfif StructKeyExists(form, ATTRIBUTES.input)>
<cfset track=structFind(form, ATTRIBUTES.input)/>
<cfelseif StructKeyExists(url, ATTRIBUTES.input)>
<cfset track=structFind(url, ATTRIBUTES.input)/>
<cfelse>
<cfset track=""/>
</cfif>
<!--- для предохранения спецсимволов (особенно запятых) в урле используется заворачивание в URLEncodedFormat. ColdFusion (по крайней мере старые версии) не умеет возвращать множественные значения иначе, как списком через запятую. Чтобы избежать непрошенного разворачивания URLEncodedFormat при отправке GETом, мы заменяем % на !.
Реализовал вариант с заворачиванием в GZIP, работает неплохо, но вариант с URLEncodedFormat сохраняет хоть какую-то читабельность.
Можно было бы кодировать в base64. Или вообще хранить на сервере в сессии, а передавать хэш - но непонятно, когда можно забыть этот урл, а накапливать их зря в сессии не хочется.
Попробовал Base64 - очень плохо, все размножается при повторном кодировании и начинает виснуть.
--->
<cfset trackBack="">
<cfif listLen(track) GT 0>
<cfset trackBack=ListDeleteAt(track, listLen(track))>
</cfif>
<cfset trackForward=ListAppend(track, urlSafeWrap(ATTRIBUTES.thisUrl))/>
<cfset backUrlBase=urlSafeUnWrap(listLast(track))/>
<cfif len(backUrlBase) GT 0>
<cfif len(trackBack) GT 0>
<cfif find("?", backUrlBase) GT 0>
<!--- has query string --->
<cfset backUrl="#backUrlBase#&#ATTRIBUTES.urlParamName#=#trackBack#"/>
<cfelse>
<!--- no query string --->
<cfset backUrl="#backUrlBase#?#ATTRIBUTES.urlParamName#=#trackBack#"/>
</cfif>
<cfelse>
<cfset backUrl="#backUrlBase#"/>
</cfif>
<cfelse>
<cfset backUrl="#ATTRIBUTES.defaultBackUrl#"/>
</cfif>
<cfif NOT (find("?", ATTRIBUTES.thisUrl) GT 0)>
<cfset selfUrl="#ATTRIBUTES.thisUrl#?#ATTRIBUTES.urlParamName#=#track#"/>
<cfelse>
<cfset selfUrl="#ATTRIBUTES.thisUrl#&#ATTRIBUTES.urlParamName#=#track#"/>
</cfif>
<cfset setVariable("CALLER.#ATTRIBUTES.output#", structNew())/>
<cfset setVariable("CALLER.#ATTRIBUTES.output#.fw", trackForward)/><!--- значение стэка: &track=#tr.fw# --->
<cfset setVariable("CALLER.#ATTRIBUTES.output#.fwx", "#ATTRIBUTES.urlParamName#=#trackForward#")/><!--- готовый суффикс для URL: &#tr.fwx#--->
<cfset setVariable("CALLER.#ATTRIBUTES.output#.bk", trackBack)/>
<cfset setVariable("CALLER.#ATTRIBUTES.output#.backUrl", backUrl)/>
<cfset setVariable("CALLER.#ATTRIBUTES.output#.self", track)/>
<cfset setVariable("CALLER.#ATTRIBUTES.output#.selfUrl", selfUrl)/>
<cfset setVariable("CALLER.#ATTRIBUTES.output#.thisUrl", ATTRIBUTES.thisUrl)/>
<cfset setVariable("CALLER.#ATTRIBUTES.output#.len", listLen(track))/>
<cfexit method="exitTag"/>
</cfsilent>