/wheels/dispatch/request.cfm

http://raihan.googlecode.com/ · ColdFusion · 412 lines · 397 code · 15 blank · 0 comment · 48 complexity · 2deb6fbb32a2773f6f3f5bf22cfae214 MD5 · raw file

  1. <cffunction name="$init" returntype="any" access="public" output="false">
  2. <cfreturn this>
  3. </cffunction>
  4. <cffunction name="$createParams" returntype="struct" access="public" output="false">
  5. <cfargument name="path" type="string" required="true">
  6. <cfargument name="route" type="struct" required="true">
  7. <cfargument name="formScope" type="struct" required="true">
  8. <cfargument name="urlScope" type="struct" required="true">
  9. <cfscript>
  10. var loc = {};
  11. loc.params = {};
  12. loc.params = $mergeURLAndFormScopes(loc.params, arguments.urlScope, arguments.formScope);
  13. loc.params = $mergeRoutePattern(loc.params, arguments.route, arguments.path);
  14. loc.params = $decryptParams(loc.params);
  15. loc.params = $translateBlankCheckBoxSubmissions(loc.params);
  16. loc.params = $translateDatePartSubmissions(loc.params);
  17. loc.params = $createNestedParamStruct(loc.params);
  18. /***********************************************
  19. * We now do the routing and controller
  20. * params after we have built all other params
  21. * so that we don't have more logic around
  22. * params in arrays
  23. ***********************************************/
  24. loc.params = $ensureControllerAndAction(loc.params, arguments.route);
  25. loc.params = $addRouteFormat(loc.params, arguments.route);
  26. loc.params = $addRouteName(loc.params, arguments.route);
  27. </cfscript>
  28. <cfreturn loc.params>
  29. </cffunction>
  30. <cffunction name="$createNestedParamStruct" returntype="struct" access="public" output="false">
  31. <cfargument name="params" type="struct" required="true" />
  32. <cfscript>
  33. var loc = {};
  34. for (loc.key in arguments.params)
  35. {
  36. if (Find("[", loc.key) && Right(loc.key, 1) == "]")
  37. {
  38. // object form field
  39. loc.name = SpanExcluding(loc.key, "[");
  40. // we split the key into an array so the developer can have unlimited levels of params passed in
  41. loc.nested = ListToArray(ReplaceList(loc.key, loc.name & "[,]", ""), "[", true);
  42. if (!StructKeyExists(arguments.params, loc.name))
  43. arguments.params[loc.name] = {};
  44. loc.struct = arguments.params[loc.name]; // we need a reference to the struct so we can nest other structs if needed
  45. loc.iEnd = ArrayLen(loc.nested);
  46. for (loc.i = 1; loc.i lte loc.iEnd; loc.i++) // looping over the array allows for infinite nesting
  47. {
  48. loc.item = loc.nested[loc.i];
  49. if (!StructKeyExists(loc.struct, loc.item))
  50. loc.struct[loc.item] = {};
  51. if (loc.i != loc.iEnd)
  52. loc.struct = loc.struct[loc.item]; // pass the new reference (structs pass a reference instead of a copy) to the next iteration
  53. else
  54. loc.struct[loc.item] = arguments.params[loc.key];
  55. }
  56. // delete the original key so it doesn't show up in the params
  57. StructDelete(arguments.params, loc.key, false);
  58. }
  59. }
  60. </cfscript>
  61. <cfreturn arguments.params />
  62. </cffunction>
  63. <cffunction name="$findMatchingRoute" returntype="struct" access="public" output="false">
  64. <cfargument name="path" type="string" required="true">
  65. <cfscript>
  66. var loc = {};
  67. loc.iEnd = ArrayLen(application.wheels.routes);
  68. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  69. {
  70. loc.format = "";
  71. if (StructKeyExists(application.wheels.routes[loc.i], "format"))
  72. loc.format = application.wheels.routes[loc.i].format;
  73. loc.currentRoute = application.wheels.routes[loc.i].pattern;
  74. if (loc.currentRoute == "*") {
  75. loc.returnValue = application.wheels.routes[loc.i];
  76. break;
  77. }
  78. else if (arguments.path == "" && loc.currentRoute == "")
  79. {
  80. loc.returnValue = application.wheels.routes[loc.i];
  81. break;
  82. }
  83. else if (ListLen(arguments.path, "/") gte ListLen(loc.currentRoute, "/") && loc.currentRoute != "")
  84. {
  85. loc.match = true;
  86. loc.jEnd = ListLen(loc.currentRoute, "/");
  87. for (loc.j=1; loc.j <= loc.jEnd; loc.j++)
  88. {
  89. loc.item = ListGetAt(loc.currentRoute, loc.j, "/");
  90. loc.thisRoute = ReplaceList(loc.item, "[,]", "");
  91. loc.thisURL = ListGetAt(arguments.path, loc.j, "/");
  92. if (Left(loc.item, 1) != "[" && loc.thisRoute != loc.thisURL)
  93. loc.match = false;
  94. }
  95. if (loc.match)
  96. {
  97. loc.returnValue = application.wheels.routes[loc.i];
  98. if (len(loc.format))
  99. {
  100. loc.returnValue[ReplaceList(loc.format, "[,]", "")] = $getFormatFromRequest(pathInfo=arguments.path);
  101. }
  102. break;
  103. }
  104. }
  105. }
  106. if (!StructKeyExists(loc, "returnValue"))
  107. $throw(type="Wheels.RouteNotFound", message="Wheels couldn't find a route that matched this request.", extendedInfo="Make sure there is a route setup in your `config/routes.cfm` file that matches the `#arguments.path#` request.");
  108. </cfscript>
  109. <cfreturn loc.returnValue>
  110. </cffunction>
  111. <cffunction name="$getPathFromRequest" returntype="string" access="public" output="false">
  112. <cfargument name="pathInfo" type="string" required="true">
  113. <cfargument name="scriptName" type="string" required="true">
  114. <cfscript>
  115. var returnValue = "";
  116. // we want the path without the leading "/" so this is why we do some checking here
  117. if (arguments.pathInfo == arguments.scriptName || arguments.pathInfo == "/" || arguments.pathInfo == "")
  118. returnValue = "";
  119. else
  120. returnValue = Right(arguments.pathInfo, Len(arguments.pathInfo)-1);
  121. </cfscript>
  122. <cfreturn returnValue>
  123. </cffunction>
  124. <cffunction name="$getFormatFromRequest" returntype="string" access="public" output="false">
  125. <cfargument name="pathInfo" type="string" required="true">
  126. <cfscript>
  127. var returnValue = "";
  128. if (Find(".", arguments.pathInfo))
  129. returnValue = ListLast(arguments.pathInfo, ".");
  130. </cfscript>
  131. <cfreturn returnValue>
  132. </cffunction>
  133. <cffunction name="$request" returntype="string" access="public" output="false">
  134. <cfargument name="pathInfo" type="string" required="false" default="#request.cgi.path_info#">
  135. <cfargument name="scriptName" type="string" required="false" default="#request.cgi.script_name#">
  136. <cfargument name="formScope" type="struct" required="false" default="#form#">
  137. <cfargument name="urlScope" type="struct" required="false" default="#url#">
  138. <cfscript>
  139. var loc = {};
  140. if (application.wheels.showDebugInformation)
  141. $debugPoint("setup");
  142. loc.params = $paramParser(argumentCollection=arguments);
  143. // set params in the request scope as well so we can display it in the debug info outside of the dispatch / controller context
  144. request.wheels.params = loc.params;
  145. if (application.wheels.showDebugInformation)
  146. $debugPoint("setup");
  147. // create the requested controller
  148. loc.controller = controller(name=loc.params.controller, params=loc.params);
  149. // if the controller fails to process, instantiate a new controller and try again
  150. if (!loc.controller.$processAction())
  151. {
  152. loc.controller = controller(name=loc.params.controller, params=loc.params);
  153. loc.controller.$processAction();
  154. }
  155. // if there is a delayed redirect pending we execute it here thus halting the rest of the request
  156. if (loc.controller.$performedRedirect())
  157. $location(argumentCollection=loc.controller.$getRedirect());
  158. // clear out the flash (note that this is not done for redirects since the processing does not get here)
  159. loc.controller.$flashClear();
  160. </cfscript>
  161. <cfreturn loc.controller.response()>
  162. </cffunction>
  163. <cffunction name="$paramParser" returntype="struct" access="public" output="false">
  164. <cfargument name="pathInfo" type="string" required="false" default="#request.cgi.path_info#">
  165. <cfargument name="scriptName" type="string" required="false" default="#request.cgi.script_name#">
  166. <cfargument name="formScope" type="struct" required="false" default="#form#">
  167. <cfargument name="urlScope" type="struct" required="false" default="#url#">
  168. <cfscript>
  169. var loc = {};
  170. loc.path = $getPathFromRequest(pathInfo=arguments.pathInfo, scriptName=arguments.scriptName);
  171. loc.route = $findMatchingRoute(path=loc.path);
  172. return $createParams(path=loc.path, route=loc.route, formScope=arguments.formScope, urlScope=arguments.urlScope);
  173. </cfscript>
  174. </cffunction>
  175. <cffunction name="$mergeURLAndFormScopes" returntype="struct" access="public" output="false"
  176. hint="merges the url and form scope into a single structure. url scope has presidence">
  177. <cfargument name="params" type="struct" required="true">
  178. <cfargument name="urlScope" type="struct" required="true">
  179. <cfargument name="formScope" type="struct" required="true">
  180. <cfscript>
  181. structAppend(arguments.params, arguments.formScope, true);
  182. structAppend(arguments.params, arguments.urlScope, true);
  183. // get rid of the fieldnames
  184. StructDelete(arguments.params, "fieldnames", false);
  185. </cfscript>
  186. <cfreturn arguments.params>
  187. </cffunction>
  188. <cffunction name="$mergeRoutePattern" returntype="struct" access="public" output="false"
  189. hint="parses the route pattern. identifies the variable markers within the pattern and assigns the value from the url variables with the path">
  190. <cfargument name="params" type="struct" required="true">
  191. <cfargument name="route" type="struct" required="true">
  192. <cfargument name="path" type="string" required="true">
  193. <cfscript>
  194. var loc = {};
  195. loc.iEnd = ListLen(arguments.route.pattern, "/");
  196. if (StructKeyExists(arguments.route, "format") AND len(arguments.route.format))
  197. {
  198. arguments.path = Reverse(ListRest(Reverse(arguments.path), "."));
  199. }
  200. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  201. {
  202. loc.item = ListGetAt(arguments.route.pattern, loc.i, "/");
  203. if (Left(loc.item, 1) == "[")
  204. {
  205. arguments.params[ReplaceList(loc.item, "[,]", "")] = ListGetAt(arguments.path, loc.i, "/");
  206. }
  207. }
  208. </cfscript>
  209. <cfreturn arguments.params>
  210. </cffunction>
  211. <cffunction name="$decryptParams" returntype="struct" access="public" output="false"
  212. hint="loops through the params struct passed in and attempts to deobfuscate them. ignores the controller and action params values.">
  213. <cfargument name="params" type="struct" required="true">
  214. <cfscript>
  215. var loc = {};
  216. if (application.wheels.obfuscateUrls)
  217. {
  218. for (loc.key in arguments.params)
  219. {
  220. if (loc.key != "controller" && loc.key != "action")
  221. {
  222. try
  223. {
  224. arguments.params[loc.key] = deobfuscateParam(arguments.params[loc.key]);
  225. }
  226. catch(Any e)
  227. {}
  228. }
  229. }
  230. }
  231. </cfscript>
  232. <cfreturn arguments.params>
  233. </cffunction>
  234. <cffunction name="$translateBlankCheckBoxSubmissions" returntype="struct" access="public" output="false"
  235. hint="loops through the params struct and handle the cases where checkboxes are unchecked">
  236. <cfargument name="params" type="struct" required="true">
  237. <cfscript>
  238. var loc = {};
  239. for (loc.key in arguments.params)
  240. {
  241. if (FindNoCase("($checkbox)", loc.key))
  242. {
  243. // if no other form parameter exists with this name it means that the checkbox was left
  244. // blank and therefore we force the value to the unchecked values for the checkbox
  245. // (to get around the problem that unchecked checkboxes don't post at all)
  246. loc.formParamName = ReplaceNoCase(loc.key, "($checkbox)", "");
  247. if (!StructKeyExists(arguments.params, loc.formParamName))
  248. {
  249. arguments.params[loc.formParamName] = arguments.params[loc.key];
  250. }
  251. StructDelete(arguments.params, loc.key, false);
  252. }
  253. }
  254. </cfscript>
  255. <cfreturn arguments.params>
  256. </cffunction>
  257. <cffunction name="$translateDatePartSubmissions" returntype="struct" access="public" output="false"
  258. hint="combines date parts into a single value">
  259. <cfargument name="params" type="struct" required="true">
  260. <cfscript>
  261. var loc = {};
  262. loc.dates = {};
  263. for (loc.key in arguments.params)
  264. {
  265. if (REFindNoCase(".*\((\$year|\$month|\$day|\$hour|\$minute|\$second|\$ampm)\)$", loc.key))
  266. {
  267. loc.temp = ListToArray(loc.key, "(");
  268. loc.firstKey = loc.temp[1];
  269. loc.secondKey = SpanExcluding(loc.temp[2], ")");
  270. if (!StructKeyExists(loc.dates, loc.firstKey))
  271. {
  272. loc.dates[loc.firstKey] = {};
  273. }
  274. loc.dates[loc.firstKey][ReplaceNoCase(loc.secondKey, "$", "")] = arguments.params[loc.key];
  275. }
  276. }
  277. for (loc.key in loc.dates)
  278. {
  279. if (!StructKeyExists(loc.dates[loc.key], "year"))
  280. {
  281. loc.dates[loc.key].year = 1899;
  282. }
  283. if (!StructKeyExists(loc.dates[loc.key], "month"))
  284. {
  285. loc.dates[loc.key].month = 1;
  286. }
  287. if (!StructKeyExists(loc.dates[loc.key], "day"))
  288. {
  289. loc.dates[loc.key].day = 1;
  290. }
  291. if (!StructKeyExists(loc.dates[loc.key], "hour"))
  292. {
  293. loc.dates[loc.key].hour = 0;
  294. }
  295. if (!StructKeyExists(loc.dates[loc.key], "minute"))
  296. {
  297. loc.dates[loc.key].minute = 0;
  298. }
  299. if (!StructKeyExists(loc.dates[loc.key], "second"))
  300. {
  301. loc.dates[loc.key].second = 0;
  302. }
  303. if (StructKeyExists(loc.dates[loc.key], "ampm"))
  304. {
  305. if (loc.dates[loc.key].ampm IS "AM" && loc.dates[loc.key].hour EQ 12)
  306. {
  307. loc.dates[loc.key].hour = 0;
  308. }
  309. else if (loc.dates[loc.key].ampm IS "PM")
  310. {
  311. loc.dates[loc.key].hour += 12;
  312. }
  313. }
  314. if (!StructKeyExists(arguments.params, loc.key) || !IsArray(arguments.params[loc.key]))
  315. {
  316. arguments.params[loc.key] = [];
  317. }
  318. try
  319. {
  320. arguments.params[loc.key] = CreateDateTime(loc.dates[loc.key].year, loc.dates[loc.key].month, loc.dates[loc.key].day, loc.dates[loc.key].hour, loc.dates[loc.key].minute, loc.dates[loc.key].second);
  321. }
  322. catch(Any e)
  323. {
  324. arguments.params[loc.key] = "";
  325. }
  326. StructDelete(arguments.params, "#loc.key#($year)", false);
  327. StructDelete(arguments.params, "#loc.key#($month)", false);
  328. StructDelete(arguments.params, "#loc.key#($day)", false);
  329. StructDelete(arguments.params, "#loc.key#($hour)", false);
  330. StructDelete(arguments.params, "#loc.key#($minute)", false);
  331. StructDelete(arguments.params, "#loc.key#($second)", false);
  332. }
  333. </cfscript>
  334. <cfreturn arguments.params>
  335. </cffunction>
  336. <cffunction name="$ensureControllerAndAction" returntype="struct" access="public" output="false"
  337. hint="ensure that the controller and action params exists and camelized">
  338. <cfargument name="params" type="struct" required="true">
  339. <cfargument name="route" type="struct" required="true">
  340. <cfscript>
  341. if (!StructKeyExists(arguments.params, "controller"))
  342. {
  343. arguments.params.controller = arguments.route.controller;
  344. }
  345. if (!StructKeyExists(arguments.params, "action"))
  346. {
  347. arguments.params.action = arguments.route.action;
  348. }
  349. // convert controller to upperCamelCase and action to normal camelCase
  350. arguments.params.controller = REReplace(arguments.params.controller, "(^|-)([a-z])", "\u\2", "all");
  351. arguments.params.action = REReplace(arguments.params.action, "-([a-z])", "\u\1", "all");
  352. </cfscript>
  353. <cfreturn arguments.params>
  354. </cffunction>
  355. <cffunction name="$addRouteFormat" returntype="struct" access="public" output="false"
  356. hint="adds in the format variable from the route if it exists">
  357. <cfargument name="params" type="struct" required="true">
  358. <cfargument name="route" type="struct" required="true">
  359. <cfscript>
  360. if (StructKeyExists(arguments.route, "formatVariable") && StructKeyExists(arguments.route, "format"))
  361. {
  362. arguments.params[arguments.route.formatVariable] = arguments.route.format;
  363. }
  364. </cfscript>
  365. <cfreturn arguments.params>
  366. </cffunction>
  367. <cffunction name="$addRouteName" returntype="struct" access="public" output="false"
  368. hint="adds in the name variable from the route if it exists">
  369. <cfargument name="params" type="struct" required="true">
  370. <cfargument name="route" type="struct" required="true">
  371. <cfscript>
  372. if (StructKeyExists(arguments.route, "name") && Len(arguments.route.name) && !StructKeyExists(arguments.params, "route"))
  373. {
  374. arguments.params.route = arguments.route.name;
  375. }
  376. </cfscript>
  377. <cfreturn arguments.params>
  378. </cffunction>