<html> <head> <title>Alter URL Demo</title> </head> <body> <p> Hey man, if you are looking for some good images, you should probably try out the search page on <a href="http://www.searchgalleries.com?source=bennadel.com" target="_blank">Search Galleries</a>. It's pretty darn comprehensive and seems to keep track of all the free galleries that you will ever need. If you want to mess with the URL, its easy; just add a "q" query string value to the search url. The general site search URL is <a href="http://www.searchgalleries.com/search/" target="_blank">http://www.searchgalleries.com/search/</a>. So, then, to add a query value to it, such as "mature", you would simply add the query string "q=mature" to the url: <a href="http://www.searchgalleries.com/search/?q=mature#links" target="_blank">http://www.searchgalleries.com/search/?q=mature</a>. You can even search for more than one value at a given time. So, for instance, if you want to search for mature brunette women, you would put go to the URL: <a href="http://www.searchgalleries.com/search/?q=mature+brunette#links" target="_blank">http://www.searchgalleries.com/search/?q=mature+brunette</a>. Notice that "mature" and "brunette" are separated by a "+" sign. This is the URL encoded form of a space. </p> </body> </html> <!--- Get the page context. ---> <cfset objPageContext = GetPageContext() /> <!--- Get the page buffer. ---> <cfset objBuffer = objPageContext.GetOut().GetBuffer() /> <!--- Get the content buffer string. This will give us everything that has NOT yet been flushed to the browser. This is just how I am doing it for this demo and is NOT the only way to perform this task. Since this page is small, (and is being tested), we can safely assume that the content has not yet been flushed to the client. ---> <cfset strContent = objBuffer.ToString() /> <!--- When examing the links, there a couple of case scenarios that we have to consider. Some URLs might have an existing query string. Other might not. Both might have a HASH value (page anchor) and URLs with an existing query string may already have the name-value pair that we are trying to insert. My original attempt used some fairly small regular expressions. I fear that to try and handle this entirely in regular expressions would become unreadable. Instead, I am going to go the Pattern / Matcher route. This way, we can examine each URL as it comes in. Let's create a pattern that matches any URL within an HREF. This pattern will require at least one none-quote character in its URL. It will also require quoated URLs. ---> <cfset objPattern = CreateObject( "java", "java.util.regex.Pattern" ).Compile( "(?<=href="")([^""]+)(?="")" ) /> <!--- Get a pattern matcher based on the content that we have pulled out of our page buffer. ---> <cfset objMatcher = objPattern.Matcher( strContent ) /> <!--- Create a string buffer into which we will store our update HTML content with updated URLs. ---> <cfset objBuffer = CreateObject( "java", "java.lang.StringBuffer" ).Init() /> <!--- Loop over all the matched links. ---> <cfloop condition="objMatcher.Find()"> <!--- Get the matched URL. ---> <cfset strURL = objMatcher.Group() /> <!--- First, we want to make sure that we are not duplicating our efforts. Check to see if the URL already contains our name/value pair. ---> <cfif NOT FindNoCase( "source=bennadel.com", strURL )> <!--- Split the URL on the hash sign. Even if there is no hash sign, this should result in an array with at least ONE index (the pre-hash value). ---> <cfset arrUrlParts = strUrl.Split( "##" ) /> <!--- Save the first part (possibly the only part) back into the URL value. Then we can deal with that on its own and add any hash value back in later. ---> <cfset strURL = arrUrlParts[ 1 ] /> <!--- Check to see if the URL contains an existing query string. ---> <cfif Find( "?", strURL )> <!--- Since there is already a query string, we can append ours to the query sting values. ---> <cfset strURL = (strURL & "&source=bennadel.com") /> <cfelse> <!--- Since there is no query string yet, we can create one with our name-value pair as its only value. ---> <cfset strURL = (strURL & "?source=bennadel.com") /> </cfif> <!--- Now that we have altered are base URL in the most appropriate way, let's see if we had a hash value to add back in. This will only be the case if we had a second parts index that has a value. ---> <cfif (ArrayLen( arrUrlParts ) GT 1)> <!--- Append the hash value to our new URL. When doing this, be sure to add the Hash sign back in. This was stripped out during our Split() method call. ---> <cfset strURL = ( strURL & "##" & arrUrlParts[ 2 ] ) /> </cfif> </cfif> <!--- ASSERT: At this point, we have updated the strURL value or we have left it alone. Either way, we are ready to add it back into the string buffer. When doing this, be sure to escape any group references and character escapes that might exist in the string. ---> <cfset objMatcher.AppendReplacement( objBuffer, strURL.ReplaceAll( "([\\\$]{1})", "\\$1" ) ) /> </cfloop> <!--- Now that we have matched all the URLs, add what ever content remains back into the results buffer. ---> <cfset objMatcher.AppendTail( objBuffer ) /> <!--- Clear the existing content buffer. ---> <cfset objPageContext.GetOut().ClearBuffer() /> <!--- Output the updated HTML. When doing this, we have to take our buffer and compile it down to a string. ---> <cfset WriteOutput( objBuffer.ToString() ) />