| 1 | <!----------------------------------------------------------------------- |
|---|
| 2 | ******************************************************************************** |
|---|
| 3 | Copyright 2005-2008 ColdBox Framework by Luis Majano and Ortus Solutions, Corp |
|---|
| 4 | www.coldboxframework.com | www.luismajano.com | www.ortussolutions.com |
|---|
| 5 | ******************************************************************************** |
|---|
| 6 | |
|---|
| 7 | Author : Luis Majano |
|---|
| 8 | Date : 9/28/2007 |
|---|
| 9 | Description : |
|---|
| 10 | This is an interceptor for ses support. This code is based almost totally on |
|---|
| 11 | Adam Fortuna's ColdCourse cfc, which is an AMAZING SES component |
|---|
| 12 | All credits go to him: http://coldcourse.riaforge.com |
|---|
| 13 | -----------------------------------------------------------------------> |
|---|
| 14 | <cfcomponent hint="This interceptor provides complete SES and URL mappings support to ColdBox Applications" |
|---|
| 15 | output="false" |
|---|
| 16 | extends="coldbox.system.Interceptor"> |
|---|
| 17 | |
|---|
| 18 | <!------------------------------------------- CONSTRUCTOR -------------------------------------------> |
|---|
| 19 | |
|---|
| 20 | <cfscript> |
|---|
| 21 | // Reserved Keys as needed for cleanups |
|---|
| 22 | instance.RESERVED_KEYS = "handler,action,view,viewNoLayout"; |
|---|
| 23 | instance.RESERVED_ROUTE_ARGUMENTS = "constraints,pattern,regexpattern,matchVariables,packageresolverexempt,patternParams,valuePairTranslation"; |
|---|
| 24 | </cfscript> |
|---|
| 25 | |
|---|
| 26 | <cffunction name="configure" access="public" returntype="void" hint="This is where the ses plugin configures itself." output="false" > |
|---|
| 27 | <cfscript> |
|---|
| 28 | // Setup the default interceptor properties |
|---|
| 29 | setRoutes( ArrayNew(1) ); |
|---|
| 30 | setLooseMatching(false); |
|---|
| 31 | setUniqueURLs(true); |
|---|
| 32 | setEnabled(true); |
|---|
| 33 | setDebugMode(false); |
|---|
| 34 | setAutoReload(false); |
|---|
| 35 | |
|---|
| 36 | //Import Config |
|---|
| 37 | importConfiguration(); |
|---|
| 38 | |
|---|
| 39 | // Save the base URL in the application settings |
|---|
| 40 | setSetting('sesBaseURL', getBaseURL() ); |
|---|
| 41 | setSetting('htmlBaseURL', replacenocase(getBaseURL(),"index.cfm","")); |
|---|
| 42 | </cfscript> |
|---|
| 43 | </cffunction> |
|---|
| 44 | |
|---|
| 45 | |
|---|
| 46 | <!------------------------------------------- INTERCEPTION POINTS -------------------------------------------> |
|---|
| 47 | |
|---|
| 48 | <!--- Pre execution process ---> |
|---|
| 49 | <cffunction name="preProcess" access="public" returntype="void" hint="This is the route dispatch" output="false" > |
|---|
| 50 | <!--- ************************************************************* ---> |
|---|
| 51 | <cfargument name="event" required="true" type="any" hint="The event object."> |
|---|
| 52 | <cfargument name="interceptData" required="true" type="struct" hint="interceptData of intercepted info."> |
|---|
| 53 | <!--- ************************************************************* ---> |
|---|
| 54 | <cfscript> |
|---|
| 55 | /* Find which route this URL matches */ |
|---|
| 56 | var aRoute = ""; |
|---|
| 57 | var key = ""; |
|---|
| 58 | var cleanedPaths = getCleanedPaths(); |
|---|
| 59 | var routedStruct = structnew(); |
|---|
| 60 | var rc = event.getCollection(); |
|---|
| 61 | |
|---|
| 62 | // Check if active or in proxy mode |
|---|
| 63 | if ( NOT getEnabled() OR arguments.event.isProxyRequest() ) |
|---|
| 64 | return; |
|---|
| 65 | |
|---|
| 66 | //Auto Reload? |
|---|
| 67 | if( getAutoReload() ){ configure(); } |
|---|
| 68 | |
|---|
| 69 | // Set that we are in ses mode |
|---|
| 70 | arguments.event.setIsSES(true); |
|---|
| 71 | |
|---|
| 72 | // Check for invalid URLs if in strict mode |
|---|
| 73 | if( getUniqueURLs() ){ |
|---|
| 74 | checkForInvalidURL( cleanedPaths["pathInfo"] , cleanedPaths["scriptName"], arguments.event ); |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | // Find a route to dispatch |
|---|
| 78 | aRoute = findRoute( cleanedPaths["pathInfo"], arguments.event ); |
|---|
| 79 | |
|---|
| 80 | // Now route should have all the key/pairs from the URL we need to pass to our event object |
|---|
| 81 | for( key in aRoute ){ |
|---|
| 82 | // Reserved Keys Check, only translate NON reserved keys |
|---|
| 83 | if( not listFindNoCase(instance.RESERVED_KEYS,key) ){ |
|---|
| 84 | rc[key] = aRoute[key]; |
|---|
| 85 | routedStruct[key] = aRoute[key]; |
|---|
| 86 | } |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | // Create Event To Dispatch if handler key exists |
|---|
| 90 | if( structKeyExists(aRoute,"handler") ){ |
|---|
| 91 | // If no action found, default to the convention of the framework, must likely 'index' |
|---|
| 92 | if( NOT structKeyExists(aRoute,"action") ){ |
|---|
| 93 | aRoute.action = getDefaultFrameworkAction(); |
|---|
| 94 | } |
|---|
| 95 | // else check if using HTTP method actions via struct |
|---|
| 96 | else if( isStruct(aRoute.action) ){ |
|---|
| 97 | // Verify HTTP method used is valid, else throw exception and 403 error |
|---|
| 98 | if( structKeyExists(aRoute.action,event.getHTTPMethod()) ){ |
|---|
| 99 | aRoute.action = aRoute.action[event.getHTTPMethod()]; |
|---|
| 100 | if( getDebugMode() ){ |
|---|
| 101 | getPlugin("Logger").debug("SES. Matched HTTP Method (#event.getHTTPMethod()#) to Action: #aRoute.action#"); |
|---|
| 102 | } |
|---|
| 103 | } |
|---|
| 104 | else{ |
|---|
| 105 | throwInvalidHTTP("The HTTP method used: #event.getHTTPMethod()# is not valid for the current executing event."); |
|---|
| 106 | } |
|---|
| 107 | } |
|---|
| 108 | // Create event |
|---|
| 109 | rc[getSetting('EventName')] = aRoute.handler & "." & aRoute.action; |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | // See if View is Dispatched |
|---|
| 113 | if( structKeyExists(aRoute,"view") ){ |
|---|
| 114 | // Dispatch the View |
|---|
| 115 | arguments.event.setView(name=aRoute.view,noLayout=aRoute.viewNoLayout); |
|---|
| 116 | arguments.event.noExecution(); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | // Save the Routed Variables so event caching can verify them |
|---|
| 120 | arguments.event.setRoutedStruct(routedStruct); |
|---|
| 121 | |
|---|
| 122 | // Execute Cache Test now that routing has been done. We override, because events are determined until now. |
|---|
| 123 | getController().getRequestService().EventCachingTest(context=arguments.event); |
|---|
| 124 | </cfscript> |
|---|
| 125 | </cffunction> |
|---|
| 126 | |
|---|
| 127 | <!------------------------------------------- PUBLIC -------------------------------------------> |
|---|
| 128 | |
|---|
| 129 | <!--- AddCourse ---> |
|---|
| 130 | <cffunction name="addCourse" returntype="void" access="public" hint="@Deprecated, please use addRoute as this method will be removed eventually." output="false"> |
|---|
| 131 | <cfargument name="pattern" type="string" required="true" hint="The pattern to match against the URL." /> |
|---|
| 132 | <cfargument name="handler" type="string" required="false" hint="The handler to execute if pattern matched."> |
|---|
| 133 | <cfargument name="action" type="string" required="false" hint="The action in a handler to execute if a pattern is matched."> |
|---|
| 134 | <cfargument name="packageResolverExempt" type="boolean" required="false" default="false" hint="If this is set to true, then the interceptor will not try to do handler package resolving. Else a package will always be resolved. Only works if :handler is in a pattern"> |
|---|
| 135 | <cfargument name="matchVariables" type="string" required="false" hint="A string of name-value pair variables to add to the request collection when this pattern matches. This is a comma delimmitted list. Ex: spaceFound=true,missingAction=onTest"> |
|---|
| 136 | <cfargument name="view" type="string" required="false" hint="The view to dispatch if pattern matches. No event will be fired, so handler,action will be ignored."> |
|---|
| 137 | <cfargument name="viewNoLayout" type="boolean" required="false" default="false" hint="If view is choosen, then you can choose to override and not display a layout with the view. Else the view renders in the assigned layout."> |
|---|
| 138 | <cfargument name="valuePairTranslation" type="boolean" required="false" default="true" hint="Activate convention name value pair translations or not. Turned on by default"> |
|---|
| 139 | <cfset addRoute(argumentCollection=arguments)> |
|---|
| 140 | </cffunction> |
|---|
| 141 | |
|---|
| 142 | <!--- Add a new Route ---> |
|---|
| 143 | <cffunction name="addRoute" access="public" returntype="void" hint="Adds a route to dispatch" output="false"> |
|---|
| 144 | <!--- ************************************************************* ---> |
|---|
| 145 | <cfargument name="pattern" type="string" required="true" hint="The pattern to match against the URL." /> |
|---|
| 146 | <cfargument name="handler" type="string" required="false" hint="The handler to execute if pattern matched."> |
|---|
| 147 | <cfargument name="action" type="string" required="false" hint="The action in a handler to execute if a pattern is matched. This can also be a json structure based on the HTTP method(GET,POST,PUT,DELETE). ex: {GET:'show', PUT:'update', DELETE:'delete', POST:'save'}"> |
|---|
| 148 | <cfargument name="packageResolverExempt" type="boolean" required="false" default="false" hint="If this is set to true, then the interceptor will not try to do handler package resolving. Else a package will always be resolved. Only works if :handler is in a pattern"> |
|---|
| 149 | <cfargument name="matchVariables" type="string" required="false" hint="A string of name-value pair variables to add to the request collection when this pattern matches. This is a comma delimmitted list. Ex: spaceFound=true,missingAction=onTest"> |
|---|
| 150 | <cfargument name="view" type="string" required="false" hint="The view to dispatch if pattern matches. No event will be fired, so handler,action will be ignored."> |
|---|
| 151 | <cfargument name="viewNoLayout" type="boolean" required="false" default="false" hint="If view is choosen, then you can choose to override and not display a layout with the view. Else the view renders in the assigned layout."> |
|---|
| 152 | <cfargument name="valuePairTranslation" type="boolean" required="false" default="true" hint="Activate convention name value pair translations or not. Turned on by default"> |
|---|
| 153 | <cfargument name="constraints" type="string" required="true" default="" hint="A json map of regex constraint overrides for variable placeholders. The key is the name of the variable, the value is the regex to try to match."/> |
|---|
| 154 | <!--- ************************************************************* ---> |
|---|
| 155 | <cfscript> |
|---|
| 156 | var thisRoute = structNew(); |
|---|
| 157 | var thisPattern = ""; |
|---|
| 158 | var thisPatternParam = ""; |
|---|
| 159 | var arg = 0; |
|---|
| 160 | var x =1; |
|---|
| 161 | var thisRegex = 0; |
|---|
| 162 | var oJSON = getPlugin("JSON"); |
|---|
| 163 | var jsonRegex = "^(\{|\[)(.)+(\}|\])$"; |
|---|
| 164 | var patternType = ""; |
|---|
| 165 | |
|---|
| 166 | // Process all incoming arguments |
|---|
| 167 | for(arg in arguments){ |
|---|
| 168 | if( structKeyExists(arguments,arg) ){ thisRoute[arg] = arguments[arg]; } |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | // Process json action? |
|---|
| 172 | if( structKeyExists(arguments,"action") AND reFindnocase(jsonRegex,arguments.action) ){ |
|---|
| 173 | try{ |
|---|
| 174 | // Inflate action to structure |
|---|
| 175 | thisRoute.action = oJSON.decode(arguments.action); |
|---|
| 176 | } |
|---|
| 177 | catch(Any e){ |
|---|
| 178 | $throw("Invalid JSON action","The action #arguments.action# is not valid JSON","SES.InvalidJSONAction"); |
|---|
| 179 | } |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | // Add trailing / to make it easier to parse |
|---|
| 183 | if( right(thisRoute.pattern,1) IS NOT "/" ){ |
|---|
| 184 | thisRoute.pattern = thisRoute.pattern & "/"; |
|---|
| 185 | } |
|---|
| 186 | // Cleanup initial / |
|---|
| 187 | if( left(thisRoute.pattern,1) IS "/" ){ |
|---|
| 188 | if( thisRoute.pattern eq "/" ){ |
|---|
| 189 | $throw(message="Pattern is empty, please verify the pattern is valid. Route: #thisRoute.toString()#",type="SES.InvalidRoute"); |
|---|
| 190 | } |
|---|
| 191 | thisRoute.pattern = right(thisRoute.pattern,len(thisRoute.pattern)-1); |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | // Check if we have optional args by looking for a ? |
|---|
| 195 | if( findnocase("?",thisRoute.pattern) ){ |
|---|
| 196 | processRouteOptionals(thisRoute); |
|---|
| 197 | return; |
|---|
| 198 | } |
|---|
| 199 | |
|---|
| 200 | // Process a json constraints? |
|---|
| 201 | thisRoute.constraints = structnew(); |
|---|
| 202 | if( reFindnocase(jsonRegex,arguments.constraints) ){ |
|---|
| 203 | try{ |
|---|
| 204 | // Inflate constratints to structure |
|---|
| 205 | thisRoute.constraints = oJSON.decode(arguments.constraints); |
|---|
| 206 | } |
|---|
| 207 | catch(Any e){ |
|---|
| 208 | $throw("Invalid JSON constraints","The constraints #arguments.constraints# is not valid JSON","SES.InvalidJSONConstraint"); |
|---|
| 209 | } |
|---|
| 210 | } |
|---|
| 211 | |
|---|
| 212 | |
|---|
| 213 | // Init the regexpattern |
|---|
| 214 | thisRoute.regexPattern = ""; |
|---|
| 215 | thisRoute.patternParams = arrayNew(1); |
|---|
| 216 | // Process the route as a regex pattern |
|---|
| 217 | for(x=1; x lte listLen(thisRoute.pattern,"/");x=x+1){ |
|---|
| 218 | |
|---|
| 219 | // Pattern and Pattern Param |
|---|
| 220 | thisPattern = listGetAt(thisRoute.pattern,x,"/"); |
|---|
| 221 | thisPatternParam = replace(listFirst(thisPattern,"-"),":",""); |
|---|
| 222 | |
|---|
| 223 | // Detect Optional Types |
|---|
| 224 | patternType = "alphanumeric"; |
|---|
| 225 | if( findnoCase("-numeric",thisPattern) ){ patternType = "numeric"; } |
|---|
| 226 | if( findnoCase("-alpha",thisPattern) ){ patternType = "alpha"; } |
|---|
| 227 | |
|---|
| 228 | switch(patternType){ |
|---|
| 229 | // ALPHANUMERICAL OPTIONAL |
|---|
| 230 | case "alphanumeric" : { |
|---|
| 231 | if( find(":",thisPattern) ){ |
|---|
| 232 | thisRegex = "(" & REReplace(thisPattern,":(.[^-]*)","[^/]"); |
|---|
| 233 | // Check Digits Repetions |
|---|
| 234 | if( find("{",thisPattern) ){ |
|---|
| 235 | thisRegex = listFirst(thisRegex,"{") & "{#listLast(thisPattern,"{")#)"; |
|---|
| 236 | arrayAppend(thisRoute.patternParams,replace(listFirst(thisPattern,"{"),":","")); |
|---|
| 237 | } |
|---|
| 238 | else{ |
|---|
| 239 | thisRegex = thisRegex & "+?)"; |
|---|
| 240 | arrayAppend(thisRoute.patternParams,thisPatternParam); |
|---|
| 241 | } |
|---|
| 242 | // Override Constraints with your own REGEX |
|---|
| 243 | if( structKeyExists(thisRoute.constraints,thisPatternParam) ){ |
|---|
| 244 | thisRegex = thisRoute.constraints[thisPatternParam]; |
|---|
| 245 | } |
|---|
| 246 | } |
|---|
| 247 | else{ |
|---|
| 248 | thisRegex = thisPattern; |
|---|
| 249 | } |
|---|
| 250 | break; |
|---|
| 251 | } |
|---|
| 252 | // NUMERICAL OPTIONAL |
|---|
| 253 | case "numeric" : { |
|---|
| 254 | // Convert to Regex Pattern |
|---|
| 255 | thisRegex = "(" & REReplace(thisPattern, ":.*?-numeric", "[0-9]"); |
|---|
| 256 | // Check Digits |
|---|
| 257 | if( find("{",thisPattern) ){ |
|---|
| 258 | thisRegex = listFirst(thisRegex,"{") & "{#listLast(thisPattern,"{")#)"; |
|---|
| 259 | } |
|---|
| 260 | else{ |
|---|
| 261 | thisRegex = thisRegex & "+?)"; |
|---|
| 262 | } |
|---|
| 263 | // Add Route Param |
|---|
| 264 | arrayAppend(thisRoute.patternParams,thisPatternParam); |
|---|
| 265 | break; |
|---|
| 266 | } |
|---|
| 267 | // ALPHA OPTIONAL |
|---|
| 268 | case "alpha" : { |
|---|
| 269 | // Convert to Regex Pattern |
|---|
| 270 | thisRegex = "(" & REReplace(thisPattern, ":.*?-alpha", "[a-zA-Z]"); |
|---|
| 271 | // Check Digits |
|---|
| 272 | if( find("{",thisPattern) ){ |
|---|
| 273 | thisRegex = listFirst(thisRegex,"{") & "{#listLast(thisPattern,"{")#)"; |
|---|
| 274 | } |
|---|
| 275 | else{ |
|---|
| 276 | thisRegex = thisRegex & "+?)"; |
|---|
| 277 | } |
|---|
| 278 | // Add Route Param |
|---|
| 279 | arrayAppend(thisRoute.patternParams,thisPatternParam); |
|---|
| 280 | break; |
|---|
| 281 | } |
|---|
| 282 | } //end pattern type detection switch |
|---|
| 283 | |
|---|
| 284 | // Add Regex Created To Pattern |
|---|
| 285 | thisRoute.regexPattern = thisRoute.regexPattern & thisRegex & "/"; |
|---|
| 286 | |
|---|
| 287 | } // end looping of pattern optionals |
|---|
| 288 | |
|---|
| 289 | // Finally add it to the routing table |
|---|
| 290 | ArrayAppend(getRoutes(), thisRoute); |
|---|
| 291 | </cfscript> |
|---|
| 292 | </cffunction> |
|---|
| 293 | |
|---|
| 294 | <cffunction name="getAutoReload" access="public" returntype="boolean" output="false" hint="Set to auto reload the rules in each request"> |
|---|
| 295 | <cfreturn instance.autoReload> |
|---|
| 296 | </cffunction> |
|---|
| 297 | <cffunction name="setAutoReload" access="public" returntype="void" output="false" hint="Get the auto reload flag."> |
|---|
| 298 | <cfargument name="autoReload" type="boolean" required="true"> |
|---|
| 299 | <cfset instance.autoReload = arguments.autoReload> |
|---|
| 300 | </cffunction> |
|---|
| 301 | |
|---|
| 302 | <!--- Getter/Setter for uniqueURLs ---> |
|---|
| 303 | <cffunction name="setUniqueURLs" access="public" output="false" returntype="void" hint="Set the uniqueURLs property"> |
|---|
| 304 | <cfargument name="uniqueURLs" type="boolean" required="true" /> |
|---|
| 305 | <cfset instance.uniqueURLs = arguments.uniqueURLs /> |
|---|
| 306 | </cffunction> |
|---|
| 307 | <cffunction name="getUniqueURLs" access="public" output="false" returntype="boolean" hint="Get uniqueURLs"> |
|---|
| 308 | <cfreturn instance.uniqueURLs/> |
|---|
| 309 | </cffunction> |
|---|
| 310 | |
|---|
| 311 | <!--- Interceptor DebugMode ---> |
|---|
| 312 | <cffunction name="getdebugMode" access="public" output="false" returntype="boolean" hint="Get the current debug mode for the interceptor"> |
|---|
| 313 | <cfreturn instance.debugMode/> |
|---|
| 314 | </cffunction> |
|---|
| 315 | <cffunction name="setdebugMode" access="public" output="false" returntype="void" hint="Set the interceptor into debug mode and log all translations"> |
|---|
| 316 | <cfargument name="debugMode" type="boolean" required="true"/> |
|---|
| 317 | <cfset instance.debugMode = arguments.debugMode/> |
|---|
| 318 | </cffunction> |
|---|
| 319 | |
|---|
| 320 | <!--- Setter/Getter for Base URL ---> |
|---|
| 321 | <cffunction name="setBaseURL" access="public" output="false" returntype="void" hint="Set the base URL for the application."> |
|---|
| 322 | <cfargument name="baseURL" type="string" required="true" /> |
|---|
| 323 | <cfset instance.baseURL = arguments.baseURL /> |
|---|
| 324 | </cffunction> |
|---|
| 325 | <cffunction name="getBaseURL" access="public" output="false" returntype="string" hint="Get BaseURL"> |
|---|
| 326 | <cfreturn instance.BaseURL/> |
|---|
| 327 | </cffunction> |
|---|
| 328 | |
|---|
| 329 | <!--- Get/set Loose Matching ---> |
|---|
| 330 | <cffunction name="getLooseMatching" access="public" returntype="boolean" output="false" hint="Get the current loose matching property"> |
|---|
| 331 | <cfreturn instance.looseMatching> |
|---|
| 332 | </cffunction> |
|---|
| 333 | <cffunction name="setLooseMatching" access="public" returntype="void" output="false" hint="Set the loose matching property of the interceptor"> |
|---|
| 334 | <cfargument name="looseMatching" type="boolean" required="true"> |
|---|
| 335 | <cfset instance.looseMatching = arguments.looseMatching> |
|---|
| 336 | </cffunction> |
|---|
| 337 | |
|---|
| 338 | <!--- Getter/Setter Enabled ---> |
|---|
| 339 | <cffunction name="setEnabled" access="public" output="false" returntype="void" hint="Set whether the interceptor is enabled or not."> |
|---|
| 340 | <cfargument name="enabled" type="boolean" required="true" /> |
|---|
| 341 | <cfset instance.enabled = arguments.enabled /> |
|---|
| 342 | </cffunction> |
|---|
| 343 | <cffunction name="getenabled" access="public" output="false" returntype="boolean" hint="Get enabled"> |
|---|
| 344 | <cfreturn instance.enabled/> |
|---|
| 345 | </cffunction> |
|---|
| 346 | |
|---|
| 347 | <!--- Getter routes ---> |
|---|
| 348 | <cffunction name="getRoutes" access="public" output="false" returntype="Array" hint="Get the array containing all the routes"> |
|---|
| 349 | <cfreturn instance.Routes/> |
|---|
| 350 | </cffunction> |
|---|
| 351 | |
|---|
| 352 | <!------------------------------------------- PRIVATE -------------------------------------------> |
|---|
| 353 | |
|---|
| 354 | <!--- throwInvalidHTTP ---> |
|---|
| 355 | <cffunction name="throwInvalidHTTP" output="false" access="private" returntype="void" hint="Throw an invalid HTTP exception"> |
|---|
| 356 | <cfargument name="description" type="string" required="true" hint="The throw description"/> |
|---|
| 357 | |
|---|
| 358 | <cfheader statuscode="403" statustext="403 Invalid HTTP Method Exception"> |
|---|
| 359 | <cfthrow type="SES.403" |
|---|
| 360 | errorcode="403" |
|---|
| 361 | message="403 Invalid HTTP Method Exception" |
|---|
| 362 | detail="#arguments.description#"> |
|---|
| 363 | |
|---|
| 364 | </cffunction> |
|---|
| 365 | |
|---|
| 366 | <!--- Set Routes ---> |
|---|
| 367 | <cffunction name="setRoutes" access="private" output="false" returntype="void" hint="Internal override of the routes array"> |
|---|
| 368 | <cfargument name="Routes" type="Array" required="true"/> |
|---|
| 369 | <cfset instance.Routes = arguments.Routes/> |
|---|
| 370 | </cffunction> |
|---|
| 371 | |
|---|
| 372 | <!--- Get Default Framework Action ---> |
|---|
| 373 | <cffunction name="getDefaultFrameworkAction" access="private" returntype="string" hint="Get the default framework action" output="false" > |
|---|
| 374 | <cfreturn getController().getSetting("eventAction",1)> |
|---|
| 375 | </cffunction> |
|---|
| 376 | |
|---|
| 377 | <!--- CGI Element Facade. ---> |
|---|
| 378 | <cffunction name="getCGIElement" access="private" returntype="string" hint="The cgi element facade method" output="false" > |
|---|
| 379 | <cfargument name="cgielement" required="true" type="string" hint="The cgi element to retrieve"> |
|---|
| 380 | <cfscript> |
|---|
| 381 | return cgi[arguments.cgielement]; |
|---|
| 382 | </cfscript> |
|---|
| 383 | </cffunction> |
|---|
| 384 | |
|---|
| 385 | <!--- Package Resolver ---> |
|---|
| 386 | <cffunction name="packageResolver" access="private" returntype="any" hint="Resolve handler packages" output="false" > |
|---|
| 387 | <!--- ************************************************************* ---> |
|---|
| 388 | <cfargument name="routingString" required="true" type="any" hint="The routing string"> |
|---|
| 389 | <cfargument name="routeParams" required="true" type="any" hint="The route params array"> |
|---|
| 390 | <!--- ************************************************************* ---> |
|---|
| 391 | <cfscript> |
|---|
| 392 | var root = getSetting("HandlersPath"); |
|---|
| 393 | var extRoot = getSetting("HandlersExternalLocationPath"); |
|---|
| 394 | var x = 1; |
|---|
| 395 | var newEvent = ""; |
|---|
| 396 | var thisFolder = ""; |
|---|
| 397 | var foundPaths = ""; |
|---|
| 398 | var rString = arguments.routingString; |
|---|
| 399 | var routeParamsLen = ArrayLen(routeParams); |
|---|
| 400 | var returnString = arguments.routingString; |
|---|
| 401 | |
|---|
| 402 | /* Verify if we have a handler on the route params */ |
|---|
| 403 | if( findnocase("handler", arrayToList(arguments.routeParams)) ){ |
|---|
| 404 | /* Cleanup routing string to position of :handler */ |
|---|
| 405 | for(x=1; x lte routeParamsLen; x=x+1){ |
|---|
| 406 | if( routeParams[x] neq "handler" ){ |
|---|
| 407 | rString = replace(rString,listFirst(rString,"/") & "/",""); |
|---|
| 408 | } |
|---|
| 409 | else{ |
|---|
| 410 | break; |
|---|
| 411 | } |
|---|
| 412 | } |
|---|
| 413 | /* Now Find Packaging in our stripped rString */ |
|---|
| 414 | for(x=1; x lte listLen(rString,"/"); x=x+1){ |
|---|
| 415 | /* Get Folder */ |
|---|
| 416 | thisFolder = listgetAt(rString,x,"/"); |
|---|
| 417 | /* Check if package exists in convention OR external location */ |
|---|
| 418 | if( directoryExists(root & "/" & foundPaths & thisFolder) |
|---|
| 419 | OR |
|---|
| 420 | ( len(extRoot) AND directoryExists(extRoot & "/" & foundPaths & thisFolder) ) |
|---|
| 421 | ){ |
|---|
| 422 | /* Save Found Paths */ |
|---|
| 423 | foundPaths = foundPaths & thisFolder & "/"; |
|---|
| 424 | /* Save new Event */ |
|---|
| 425 | if(len(newEvent) eq 0){ |
|---|
| 426 | newEvent = thisFolder & "."; |
|---|
| 427 | } |
|---|
| 428 | else{ |
|---|
| 429 | newEvent = newEvent & thisFolder & "."; |
|---|
| 430 | } |
|---|
| 431 | }//end if folder found |
|---|
| 432 | else{ |
|---|
| 433 | //newEvent = newEvent & "." & thisFolder; |
|---|
| 434 | break; |
|---|
| 435 | }//end not a folder. |
|---|
| 436 | }//end for loop |
|---|
| 437 | /* Replace Return String */ |
|---|
| 438 | if( len(newEvent) ){ |
|---|
| 439 | returnString = replacenocase(returnString,replace(newEvent,".","/","all"),newEvent); |
|---|
| 440 | } |
|---|
| 441 | }//end if handler found |
|---|
| 442 | |
|---|
| 443 | return returnString; |
|---|
| 444 | </cfscript> |
|---|
| 445 | </cffunction> |
|---|
| 446 | |
|---|
| 447 | <!--- Serialize a URL ---> |
|---|
| 448 | <cffunction name="serializeURL" access="private" output="false" returntype="string" hint="Serialize a URL"> |
|---|
| 449 | <!--- ************************************************************* ---> |
|---|
| 450 | <cfargument name="formVars" required="false" default="" type="string"> |
|---|
| 451 | <cfargument name="event" required="true" type="any" hint="The event object."> |
|---|
| 452 | <!--- ************************************************************* ---> |
|---|
| 453 | <cfscript> |
|---|
| 454 | var vars = arguments.formVars; |
|---|
| 455 | var key = 0; |
|---|
| 456 | var rc = arguments.event.getCollection(); |
|---|
| 457 | |
|---|
| 458 | for(key in rc){ |
|---|
| 459 | if( NOT ListFindNoCase("route,handler,action,#getSetting('eventName')#",key) ){ |
|---|
| 460 | vars = ListAppend(vars, "#lcase(key)#=#rc[key]#", "&"); |
|---|
| 461 | } |
|---|
| 462 | } |
|---|
| 463 | if( len(vars) eq 0 ){ |
|---|
| 464 | return ""; |
|---|
| 465 | } |
|---|
| 466 | else{ |
|---|
| 467 | return "?" & vars; |
|---|
| 468 | } |
|---|
| 469 | </cfscript> |
|---|
| 470 | </cffunction> |
|---|
| 471 | |
|---|
| 472 | <!--- Check for Invalid URL ---> |
|---|
| 473 | <cffunction name="checkForInvalidURL" access="private" output="false" returntype="void" hint="Check for invalid URL's"> |
|---|
| 474 | <!--- ************************************************************* ---> |
|---|
| 475 | <cfargument name="route" required="true" type="any" /> |
|---|
| 476 | <cfargument name="script_name" required="true" type="any" /> |
|---|
| 477 | <cfargument name="event" required="true" type="any" hint="The event object."> |
|---|
| 478 | <!--- ************************************************************* ---> |
|---|
| 479 | <cfset var handler = "" /> |
|---|
| 480 | <cfset var action = "" /> |
|---|
| 481 | <cfset var newpath = "" /> |
|---|
| 482 | <cfset var httpRequestData = ""> |
|---|
| 483 | <cfset var EventName = getSetting('EventName')> |
|---|
| 484 | <cfset var DefaultEvent = getSetting('DefaultEvent')> |
|---|
| 485 | <cfset var rc = event.getCollection()> |
|---|
| 486 | |
|---|
| 487 | <!--- Get the HTTP Data ---> |
|---|
| 488 | <cfset httpRequestData = GetHttpRequestData()/> |
|---|
| 489 | |
|---|
| 490 | <!--- |
|---|
| 491 | Verify we have uniqueURLs ON, the event var exists, route is empty or index.cfm |
|---|
| 492 | AND |
|---|
| 493 | if the incoming event is not the default OR it is the default via the URL. |
|---|
| 494 | ---> |
|---|
| 495 | <cfif StructKeyExists(rc, EventName) |
|---|
| 496 | AND (arguments.route EQ "/index.cfm" or arguments.route eq "") |
|---|
| 497 | AND ( |
|---|
| 498 | rc[EventName] NEQ DefaultEvent |
|---|
| 499 | OR |
|---|
| 500 | ( structKeyExists(url,EventName) AND rc[EventName] EQ DefaultEvent ) |
|---|
| 501 | )> |
|---|
| 502 | |
|---|
| 503 | <!--- New Pathing Calculations if not the default event. If default, relocate to the domain. ---> |
|---|
| 504 | <cfif rc[EventName] neq getSetting('DefaultEvent')> |
|---|
| 505 | <!--- Clean for handler & Action ---> |
|---|
| 506 | <cfif StructKeyExists(rc, EventName)> |
|---|
| 507 | <cfset handler = reReplace(rc[EventName],"\.[^.]*$","") /> |
|---|
| 508 | <cfset action = ListLast( rc[EventName], "." ) /> |
|---|
| 509 | </cfif> |
|---|
| 510 | <!--- route a handler ---> |
|---|
| 511 | <cfif len(handler)> |
|---|
| 512 | <cfset newpath = "/" & handler /> |
|---|
| 513 | </cfif> |
|---|
| 514 | <!--- route path with handler + action if not the default event action ---> |
|---|
| 515 | <cfif len(handler) |
|---|
| 516 | AND len(action) |
|---|
| 517 | AND action NEQ getDefaultFrameworkAction()> |
|---|
| 518 | <cfset newpath = newpath & "/" & action /> |
|---|
| 519 | </cfif> |
|---|
| 520 | </cfif> |
|---|
| 521 | <!--- Debug Mode? ---> |
|---|
| 522 | <cfif getDebugMode()> |
|---|
| 523 | <cfset getPlugin("Logger").debug("SES.Invalid URL detected. Route: #arguments.route#, script_name: #arguments.script_name#")> |
|---|
| 524 | </cfif> |
|---|
| 525 | |
|---|
| 526 | <!--- Relocation headers ---> |
|---|
| 527 | <cfif httpRequestData.method EQ "GET"> |
|---|
| 528 | <cfheader statuscode="301" statustext="Moved permanently" /> |
|---|
| 529 | <cfelse> |
|---|
| 530 | <cfheader statuscode="303" statustext="See Other" /> |
|---|
| 531 | </cfif> |
|---|
| 532 | <!--- Relocate ---> |
|---|
| 533 | <cfheader name="Location" value="#getBaseURL()##newpath##serializeURL(httpRequestData.content,event)#" /> |
|---|
| 534 | <cfabort /> |
|---|
| 535 | </cfif> |
|---|
| 536 | </cffunction> |
|---|
| 537 | |
|---|
| 538 | <!--- Fix Ending IIS funkyness ---> |
|---|
| 539 | <cffunction name="fixIISURLVars" access="private" returntype="string" hint="Clean up some IIS funkyness" output="false" > |
|---|
| 540 | <cfargument name="requestString" type="any" required="true" hint="The request string"> |
|---|
| 541 | <cfargument name="rc" type="any" required="true" hint="The request collection"> |
|---|
| 542 | <cfscript> |
|---|
| 543 | var varMatch = 0; |
|---|
| 544 | var qsValues = 0; |
|---|
| 545 | var qsVal = 0; |
|---|
| 546 | var x = 1; |
|---|
| 547 | |
|---|
| 548 | // Find a Matching position of IIS ? |
|---|
| 549 | varMatch = REFind("\?.*=",arguments.requestString,1,"TRUE"); |
|---|
| 550 | if( varMatch.pos[1] ){ |
|---|
| 551 | // Copy values to the RC |
|---|
| 552 | qsValues = REreplacenocase(arguments.requestString,"^.*\?","","all"); |
|---|
| 553 | // loop and create |
|---|
| 554 | for(x=1; x lte listLen(qsValues,"&"); x=x+1){ |
|---|
| 555 | qsVal = listGetAt(qsValues,x,"&"); |
|---|
| 556 | rc[listFirst(qsVal,"=")] = listLast(qsVal,"="); |
|---|
| 557 | } |
|---|
| 558 | // Clean the request string |
|---|
| 559 | arguments.requestString = Mid(arguments.requestString, 1, (varMatch.pos[1]-1)); |
|---|
| 560 | } |
|---|
| 561 | |
|---|
| 562 | return arguments.requestString; |
|---|
| 563 | </cfscript> |
|---|
| 564 | </cffunction> |
|---|
| 565 | |
|---|
| 566 | <!--- Find a route ---> |
|---|
| 567 | <cffunction name="findRoute" access="private" output="false" returntype="Struct" hint="Figures out which route matches this request"> |
|---|
| 568 | <!--- ************************************************************* ---> |
|---|
| 569 | <cfargument name="action" required="true" type="any" hint="The action evaluated by the path_info"> |
|---|
| 570 | <cfargument name="event" required="true" type="any" hint="The event object."> |
|---|
| 571 | <!--- ************************************************************* ---> |
|---|
| 572 | <cfset var requestString = arguments.action /> |
|---|
| 573 | <cfset var packagedRequestString = ""> |
|---|
| 574 | <cfset var match = structNew() /> |
|---|
| 575 | <cfset var foundRoute = structNew() /> |
|---|
| 576 | <cfset var params = structNew() /> |
|---|
| 577 | <cfset var key = "" /> |
|---|
| 578 | <cfset var i = 1 /> |
|---|
| 579 | <cfset var x = 1 > |
|---|
| 580 | <cfset var rc = event.getCollection()> |
|---|
| 581 | <cfset var _routes = getRoutes()> |
|---|
| 582 | <cfset var _routesLength = ArrayLen(_routes)> |
|---|
| 583 | |
|---|
| 584 | <cfscript> |
|---|
| 585 | // fix URL vars after ? |
|---|
| 586 | requestString = fixIISURLVars(requestString,rc); |
|---|
| 587 | //Remove the leading slash |
|---|
| 588 | if( len(requestString) GT 1 AND left(requestString,1) eq "/" ){ |
|---|
| 589 | requestString = right(requestString,len(requestString)-1); |
|---|
| 590 | } |
|---|
| 591 | // Add ending slash |
|---|
| 592 | if( right(requestString,1) IS NOT "/" ){ |
|---|
| 593 | requestString = requestString & "/"; |
|---|
| 594 | } |
|---|
| 595 | |
|---|
| 596 | // Let's Find a Route, Loop over all the routes array |
|---|
| 597 | for(i=1; i lte _routesLength; i=i+1){ |
|---|
| 598 | // Match The route to request String |
|---|
| 599 | match = reFindNoCase(_routes[i].regexPattern,requestString,1,true); |
|---|
| 600 | if( (match.len[1] IS NOT 0 AND getLooseMatching()) OR |
|---|
| 601 | (NOT getLooseMatching() AND match.len[1] IS NOT 0 AND match.pos[1] EQ 1) ){ |
|---|
| 602 | // Setup the found Route |
|---|
| 603 | foundRoute = _routes[i]; |
|---|
| 604 | // Debug mode? |
|---|
| 605 | if( getDebugMode() ){ |
|---|
| 606 | getPlugin("Logger").debug("SES.Route matched: #foundRoute.toString()#"); |
|---|
| 607 | } |
|---|
| 608 | break; |
|---|
| 609 | } |
|---|
| 610 | }//end finding routes |
|---|
| 611 | |
|---|
| 612 | // Check if we found a route, else just return empty params struct |
|---|
| 613 | if( structIsEmpty(foundRoute) ){ return params; } |
|---|
| 614 | |
|---|
| 615 | // Save Found Route |
|---|
| 616 | arguments.event.setValue("currentRoute",foundRoute.pattern); |
|---|
| 617 | |
|---|
| 618 | // Do we need to do package resolving |
|---|
| 619 | if( NOT foundRoute.packageResolverExempt ){ |
|---|
| 620 | // Resolve the packages |
|---|
| 621 | packagedRequestString = packageResolver(requestString,foundRoute.patternParams); |
|---|
| 622 | // reset pattern matching, if packages found. |
|---|
| 623 | if( compare(packagedRequestString,requestString) NEQ 0 ){ |
|---|
| 624 | if( getDebugMode() ){ |
|---|
| 625 | getPlugin("Logger").debug("SES.Package Resolved: #packagedRequestString#"); |
|---|
| 626 | } |
|---|
| 627 | return findRoute(packagedRequestString,arguments.event); |
|---|
| 628 | } |
|---|
| 629 | } |
|---|
| 630 | |
|---|
| 631 | // Populate the params, with variables found in the request string |
|---|
| 632 | for(x=1; x lte arrayLen(foundRoute.patternParams); x=x+1){ |
|---|
| 633 | params[foundRoute.patternParams[x]] = mid(requestString, match.pos[x+1], match.len[x+1]); |
|---|
| 634 | } |
|---|
| 635 | |
|---|
| 636 | // Process Convention Name-Value Pairs |
|---|
| 637 | if( foundRoute.valuePairTranslation ){ |
|---|
| 638 | findConventionNameValuePairs(requestString,match,params); |
|---|
| 639 | } |
|---|
| 640 | |
|---|
| 641 | // Now setup all found variables in the param struct, so we can return |
|---|
| 642 | for(key in foundRoute){ |
|---|
| 643 | if( NOT listFindNoCase(instance.RESERVED_ROUTE_ARGUMENTS,key) ){ |
|---|
| 644 | params[key] = foundRoute[key]; |
|---|
| 645 | } |
|---|
| 646 | else if (key eq "matchVariables"){ |
|---|
| 647 | for(i=1; i lte listLen(foundRoute.matchVariables); i = i+1){ |
|---|
| 648 | params[listFirst(listGetAt(foundRoute.matchVariables,i),"=")] = listLast(listGetAt(foundRoute.matchVariables,i),"="); |
|---|
| 649 | } |
|---|
| 650 | } |
|---|
| 651 | } |
|---|
| 652 | |
|---|
| 653 | return params; |
|---|
| 654 | </cfscript> |
|---|
| 655 | </cffunction> |
|---|
| 656 | |
|---|
| 657 | <cffunction name="findConventionNameValuePairs" access="private" returntype="void" hint="Find the convention name value pairs" output="false" > |
|---|
| 658 | <cfargument name="requestString" type="string" required="true" hint="The request string"> |
|---|
| 659 | <cfargument name="match" type="any" required="true" hint="The regex matcher"> |
|---|
| 660 | <cfargument name="params" type="struct" required="true" hint="The parameter structure"> |
|---|
| 661 | <cfscript> |
|---|
| 662 | //var leftOverLen = len(arguments.requestString)-(arguments.match.pos[arraylen(arguments.match.pos)]+arguments.match.len[arrayLen(arguments.match.len)]-1); |
|---|
| 663 | var leftOverLen = len(arguments.requestString) - arguments.match.len[1]; |
|---|
| 664 | var conventionString = 0; |
|---|
| 665 | var conventionStringLen = 0; |
|---|
| 666 | var tmpVar = 0; |
|---|
| 667 | var i = 1; |
|---|
| 668 | |
|---|
| 669 | if( leftOverLen gt 0 ){ |
|---|
| 670 | // Cleanup remaining string |
|---|
| 671 | conventionString = right(arguments.requestString,leftOverLen); |
|---|
| 672 | conventionStringLen = listLen(conventionString,"/"); |
|---|
| 673 | // If conventions found, continue parsing |
|---|
| 674 | if( conventionStringLen gt 1 ){ |
|---|
| 675 | for(i=1; i lte conventionStringLen; i=i+1){ |
|---|
| 676 | if( i mod 2 eq 0 ){ |
|---|
| 677 | // Even: Means Variable Value |
|---|
| 678 | arguments.params[tmpVar] = listGetAt(conventionString,i,'/'); |
|---|
| 679 | } |
|---|
| 680 | else{ |
|---|
| 681 | // ODD: Means variable name |
|---|
| 682 | tmpVar = trim(listGetAt(conventionString,i,'/')); |
|---|
| 683 | // Verify it is a valid variable Name |
|---|
| 684 | if ( NOT isValid("variableName",tmpVar) ){ |
|---|
| 685 | tmpVar = "_INVALID_VARIABLE_NAME_POS_#i#_"; |
|---|
| 686 | } |
|---|
| 687 | else{ |
|---|
| 688 | // Default Value of empty |
|---|
| 689 | arguments.params[tmpVar] = ""; |
|---|
| 690 | } |
|---|
| 691 | } |
|---|
| 692 | }//end loop over pairs |
|---|
| 693 | }//end if at least one pair found |
|---|
| 694 | }//end if convention name value pairs |
|---|
| 695 | </cfscript> |
|---|
| 696 | </cffunction> |
|---|
| 697 | |
|---|
| 698 | <cffunction name="getCleanedPaths" access="private" returntype="struct" hint="Get and Clean the path_info and script names" output="false" > |
|---|
| 699 | <cfscript> |
|---|
| 700 | var items = structnew(); |
|---|
| 701 | |
|---|
| 702 | // Get path_info |
|---|
| 703 | items["pathInfo"] = getCGIElement('path_info'); |
|---|
| 704 | items["scriptName"] = trim(reReplacenocase(getCGIElement('script_name'),"[/\\]index\.cfm","")); |
|---|
| 705 | |
|---|
| 706 | // Clean ContextRoots |
|---|
| 707 | if( len(getContextRoot()) ){ |
|---|
| 708 | items["pathInfo"] = replacenocase(items["pathInfo"],getContextRoot(),""); |
|---|
| 709 | items["scriptName"] = replacenocase(items["scriptName"],getContextRoot(),""); |
|---|
| 710 | } |
|---|
| 711 | // Clean up the path_info from index.cfm and nested pathing |
|---|
| 712 | items["pathInfo"] = trim(reReplacenocase(items["pathInfo"],"[/\\]index\.cfm","")); |
|---|
| 713 | // Clean up empty placeholders |
|---|
| 714 | items["pathInfo"] = replace(items["pathInfo"],"//","/","all"); |
|---|
| 715 | if( len(items["scriptName"]) ){ |
|---|
| 716 | items["pathInfo"] = replaceNocase(items["pathInfo"],items["scriptName"],''); |
|---|
| 717 | } |
|---|
| 718 | |
|---|
| 719 | return items; |
|---|
| 720 | </cfscript> |
|---|
| 721 | </cffunction> |
|---|
| 722 | |
|---|
| 723 | <cffunction name="processRouteOptionals" access="private" returntype="void" hint="Process route optionals" output="false" > |
|---|
| 724 | <cfargument name="thisRoute" type="struct" required="true" hint="The route struct"> |
|---|
| 725 | <cfscript> |
|---|
| 726 | var x=1; |
|---|
| 727 | var thisPattern = 0; |
|---|
| 728 | var base = ""; |
|---|
| 729 | var optionals = ""; |
|---|
| 730 | var routeList = ""; |
|---|
| 731 | |
|---|
| 732 | // Parse our base & optionals |
|---|
| 733 | for(x=1; x lte listLen(arguments.thisRoute.pattern,"/"); x=x+1){ |
|---|
| 734 | thisPattern = listgetAt(arguments.thisRoute.pattern,x,"/"); |
|---|
| 735 | // Check for ? |
|---|
| 736 | if( not findnocase("?",thisPattern) ){ |
|---|
| 737 | base = base & thisPattern & "/"; |
|---|
| 738 | } |
|---|
| 739 | else{ |
|---|
| 740 | optionals = optionals & replacenocase(thisPattern,"?","","all") & "/"; |
|---|
| 741 | } |
|---|
| 742 | } |
|---|
| 743 | // Register our routeList |
|---|
| 744 | routeList = base & optionals; |
|---|
| 745 | // Recurse and register in reverse order |
|---|
| 746 | for(x=1; x lte listLen(optionals,"/"); x=x+1){ |
|---|
| 747 | // Create new route |
|---|
| 748 | arguments.thisRoute.pattern = routeList; |
|---|
| 749 | // Register route |
|---|
| 750 | addRoute(argumentCollection=arguments.thisRoute); |
|---|
| 751 | // Remove last bit |
|---|
| 752 | routeList = listDeleteat(routeList,listlen(routeList,"/"),"/"); |
|---|
| 753 | } |
|---|
| 754 | // Setup the base route again |
|---|
| 755 | arguments.thisRoute.pattern = base; |
|---|
| 756 | // Register the final route |
|---|
| 757 | addRoute(argumentCollection=arguments.thisRoute); |
|---|
| 758 | </cfscript> |
|---|
| 759 | </cffunction> |
|---|
| 760 | |
|---|
| 761 | <!--- importConfiguration ---> |
|---|
| 762 | <cffunction name="importConfiguration" output="false" access="private" returntype="void" hint="Import the routing configuration file"> |
|---|
| 763 | <cfscript> |
|---|
| 764 | var appLocPrefix = "/"; |
|---|
| 765 | var configFilePath = ""; |
|---|
| 766 | var local = structnew(); |
|---|
| 767 | |
|---|
| 768 | // Verify the config file, else set it to our convention in the config/Routes.cfm |
|---|
| 769 | if( not propertyExists('configFile') ){ |
|---|
| 770 | setProperty('configFile','config/Routes.cfm'); |
|---|
| 771 | } |
|---|
| 772 | |
|---|
| 773 | //App location prefix |
|---|
| 774 | if( len(getSetting('AppMapping')) ){ |
|---|
| 775 | appLocPrefix = appLocPrefix & getSetting('AppMapping') & "/"; |
|---|
| 776 | } |
|---|
| 777 | |
|---|
| 778 | // Setup the config Path for relative location first. |
|---|
| 779 | configFilePath = appLocPrefix & reReplace(getProperty('ConfigFile'),"^/",""); |
|---|
| 780 | if( NOT fileExists(expandPath(configFilePath)) ){ |
|---|
| 781 | //Check absolute location as not found inside our app |
|---|
| 782 | configFilePath = getProperty('ConfigFile'); |
|---|
| 783 | if( NOT fileExists(expandPath(configFilePath)) ){ |
|---|
| 784 | $throw(message="Error locating routes file: #configFilePath#",type="SES.ConfigFileNotFound"); |
|---|
| 785 | } |
|---|
| 786 | } |
|---|
| 787 | |
|---|
| 788 | // We are ready to roll. Import config to setup the routes. |
|---|
| 789 | try{ |
|---|
| 790 | $include(configFilePath); |
|---|
| 791 | } |
|---|
| 792 | catch(Any e){ |
|---|
| 793 | $throw("Error including config file: #e.message# #e.detail#",e.tagContext.toString(),"SES.executingConfigException"); |
|---|
| 794 | } |
|---|
| 795 | |
|---|
| 796 | // Validate the base URL |
|---|
| 797 | if ( len(getBaseURL()) eq 0 ){ |
|---|
| 798 | $throw('The baseURL property has not been defined. Please define it using the setBaseURL() method.','','interceptors.SES.invalidPropertyException'); |
|---|
| 799 | } |
|---|
| 800 | </cfscript> |
|---|
| 801 | </cffunction> |
|---|
| 802 | |
|---|
| 803 | </cfcomponent> |
|---|