Skip to content

Instantly share code, notes, and snippets.

@paulklinkenberg
Created February 24, 2016 20:53
Show Gist options
  • Save paulklinkenberg/b308f277e73c67811e98 to your computer and use it in GitHub Desktop.
Save paulklinkenberg/b308f277e73c67811e98 to your computer and use it in GitHub Desktop.
CFML script to find broken links in cfml and html files, case-sensitive! Very useful when switching from Windows to Linux.
<cfset maxErrors = 500 />
<cfset root = expandPath('/') />
<cfset files = directoryList(root, true, "path", "*.cfm|*.cfc|*.html|*.htm") />
<cfset currErrors = 0 />
<cfoutput>
<p>#arraylen(files)# cfm/cfc/html/htm files found</p>
</cfoutput>
<table border="1">
<thead>
<tr>
<th>Found in file</th>
<th>Non-existent link</th>
</tr>
</thead>
<tbody>
<cfsetting enablecfoutputonly="true" />
<cfset reg = '(src|href) ?= ?[''"](.*?)[''"]' />
<cfloop array="#files#" index="filePath">
<!--- skip railo/lucee directories --->
<cfif find('/WEB-INF/', filePath)>
<cfcontinue />
</cfif>
<cfset contents = fileRead(filePath) />
<!--- remove breaks and cfml comments from page where possible (nested cfml comments won't be completely removed) --->
<cfif refindNoCase(reg, contents)>
<cfset contents = replace(replace(contents, chr(10), chr(9), 'all'), chr(13), chr(9), 'all') />
<cfset contents = rereplace(contents, '<\!\-\-\-.*?\-\-\->', '', 'all') />
</cfif>
<cfset curr = 1 />
<cfloop condition="refindNoCase(reg, contents, curr)">
<cfset found = refindNoCase(reg, contents, curr, true) />
<cfset curr = found.pos[3] />
<cfset link = mid(contents, found.pos[3], found.len[3]) />
<!--- remove query string --->
<cfif find('?', link)>
<cfset link = listToArray(link, '?')[1] />
</cfif>
<!--- js links / dynamic links / abs links / cf code inside: skip --->
<cfif findNoCase('javascript:', link) or find('##', link) or find('http://', link) eq 1
or findNoCase('<cf', link) or link eq 'about:blank'
or find('https://', link) eq 1 or find('ftp://', link) eq 1 or find('mailto:', link) eq 1>
<cfcontinue />
</cfif>
<cfif left(link, 1) neq "/">
<cfset abslink = expandPath(replace(getDirectoryFromPath(filePath), root, "/") & link) />
<cfelse>
<cfset abslink = expandPath(link) />
</cfif>
<cfif not fileExists(abslink)>
<!--- link can be a directory! --->
<cfif directoryExists(abslink)>
<cfcontinue />
</cfif>
<cfoutput>
<tr>
<td>#htmleditformat(filePath)#</td>
<td>#mid(contents, found.pos[1], found.len[1])#<!---<br/>#htmleditformat(abslink)#---></td>
</tr>
</cfoutput>
<cfflush />
<cfif ++currErrors eq maxErrors>
<cfbreak />
</cfif>
<!--- file exists, okay. But did expandPath change case of the file? --->
<cfelseif compare(listLast(link, '/\'), listLast(absLink, '/\')) neq 0>
<cfoutput>
<tr>
<td>#htmleditformat(filePath)#</td>
<td>#mid(contents, found.pos[1], found.len[1])#
&nbsp; <b>Case sensitive mismatch</b>
</td>
</tr>
</cfoutput>
<cfflush />
<cfif ++currErrors eq maxErrors>
<cfbreak />
</cfif>
</cfif>
</cfloop>
<cfif currErrors eq maxErrors>
<cfoutput>
<tr>
<td colspan="2">
<h3 style="color:red">The max number of reported errors, #maxErrors#, has been reached</h3>
</td>
</tr>
</cfoutput>
<cfbreak />
</cfif>
</cfloop>
<cfsetting enablecfoutputonly="false" />
</tbody>
</table>
<h1>Done</h1>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment