﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>RichB commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Path.Combine("~/Content/css", file)

This combines with a backslash delimiter, when the other segments contain forward slashes. Better to use VirtualPathUtility.Combine():

http://msdn.microsoft.com/en-us/library/system.web.virtualpathutility.combine.aspx

Also if you put a rooted path into the files parameter, you will get a YSOD  eg:
http://localhost/css?files=c:\boot.ini</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment32</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment32</guid><pubDate>Mon, 04 Jul 2011 09:07:27 GMT</pubDate></item><item><title>dario-g commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Check out: http://mscd.codeplex.com</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment31</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment31</guid><pubDate>Thu, 09 Jun 2011 22:07:38 GMT</pubDate></item><item><title>Dmitry commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Many proxies do not cache URLs with ?querystring in them. It is better to make files a part of the actual URL like proposed above. The only negative is there is a shorter length limitation.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment30</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment30</guid><pubDate>Thu, 09 Jun 2011 14:03:58 GMT</pubDate></item><item><title>Jonathan Mahoney commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>I have the same concerns as Alistair - if you're using MVC you could create a route that took something like this:

/CSS/{files}.{version}.css

Make 'files' an underscore delimited list of the files, which you split and use in your controller code above. 'Version' doesn't even need to be used server side - it could just be a number to do cache busting.

However one thing I might like as an addition is a variable that allows you to serve the full (for development) or minified version.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment29</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment29</guid><pubDate>Thu, 09 Jun 2011 06:04:47 GMT</pubDate></item><item><title>Harry Steinhilber commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Nevermind, the 404 will occur for outside of the correct path. So I suppose that could be an issue.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment28</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment28</guid><pubDate>Wed, 08 Jun 2011 18:56:01 GMT</pubDate></item><item><title>Harry Steinhilber commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>@tobi,

The code is exiting with an `HttpNotFound` on the first file that doesn't exist on disk. So in your scenario, it would exit with a 404 once it hit the `0.css` file. It won't even attempt to process the other 9,999,999 files. So I don't believe this could overload it.

I have to agree that not handling the duplicate file bit could be an issue, though.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment27</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment27</guid><pubDate>Wed, 08 Jun 2011 18:53:27 GMT</pubDate></item><item><title>tobi commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>And I forgot that you have to normalize casing and filenames may not contain ".." etc. because that would also allow multiple URLs for the same content. Disallow duplicates.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment26</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment26</guid><pubDate>Wed, 08 Jun 2011 17:42:25 GMT</pubDate></item><item><title>Bertrand Le Roy commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>@Ayende: right, that's why I said it was probably a minor issue ;) This being said, unless I'm missing something, what goes into the cache is the combination of files (so yes it would take a lot of these to flood the cache) but my point was that it's keyed by the Files querystring parameter, and it's not handling multiple inclusions of the same file. So if you wanted to mitigate that maybe just taking distinct paths and/or rejecting requests with duplicates would help. If you consider the threat to be serious. Which we would in a framework but you probably would justifiably dismiss in this specific context.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment25</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment25</guid><pubDate>Wed, 08 Jun 2011 17:42:12 GMT</pubDate></item><item><title>tobi commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Overload it like this:

from i in Enumerable.Range(0, 10000000)
let files = new [] { "normal.css", i + ".css" }
select "/css?files=" + files.Concat(",");

And request all of those URLs. Solution: Return 404 if any file does not exist and, if files is not sorted, redirect to the canonical URL.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment24</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment24</guid><pubDate>Wed, 08 Jun 2011 12:52:28 GMT</pubDate></item><item><title>Dave Roberts commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Path validation is hard. The best approach I've seen is CAS (http://msdn.microsoft.com/en-us/library/930b76w0(v=VS.90).aspx):

var perm = new FileIOPermission(FileIOPermissionAccess.Read, rootPhysicalPath);
perm.PermitOnly();

Lots of the discussions around CAS are for sandboxing plugins, but I've found it very useful in cases like this.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment23</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment23</guid><pubDate>Wed, 08 Jun 2011 11:29:22 GMT</pubDate></item><item><title>Ayende Rahien commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Tobi,
How could you do that?</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment22</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment22</guid><pubDate>Wed, 08 Jun 2011 09:06:57 GMT</pubDate></item><item><title>Ayende Rahien commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Bertrand,
That is just another way to say DDoS, and there are other ways to mitigate against that. You couldn't really flood the cache, since the only things that goes into the cache are the actual files on disk.
And even if you flood the cache, nothing bad would happen, things would just not be cached.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment21</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment21</guid><pubDate>Wed, 08 Jun 2011 09:06:23 GMT</pubDate></item><item><title>Luke commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Interested in why you use == false instead of !. 
I assume that is to increase readability. Is that something you do throughout your code?


</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment20</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment20</guid><pubDate>Tue, 07 Jun 2011 23:48:57 GMT</pubDate></item><item><title>Alistair commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Yeah there are some ugly caching implications of this code. Specifically it violates:

http://code.google.com/speed/page-speed/docs/caching.html#LeverageProxyCaching

So some proxies won't cache this resource as there is a querystring in the url.

Additionally, how do you handle refreshing peoples cache? Presumably with something like &amp;version=1?</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment19</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment19</guid><pubDate>Tue, 07 Jun 2011 23:30:04 GMT</pubDate></item><item><title>tobi commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>You could even overload the server by causing it to process the css over and over.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment18</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment18</guid><pubDate>Tue, 07 Jun 2011 20:34:24 GMT</pubDate></item><item><title>Bertrand Le Roy commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>If I'm not mistaken, there is a minor issue that you may flood the cache by querying many different combinations of existing files (and maybe also requiring the same file more than once). While the file dependency call might mitigate this somehow, adding a crypto validation hash of sorts might help if that becomes a problem (unlikely but eh). Never a fan of crypto stuff on the querystring but I thought I would mention it.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment17</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment17</guid><pubDate>Tue, 07 Jun 2011 19:24:46 GMT</pubDate></item><item><title>Ryan Heath commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>@Jesse 
I don't like the fact that the client can determine which files are going to be merged.
It's only a security bug waiting to be exploited. Of course Ayende has checked the path, but another dev could easily remove the check (unintended) and all seems to be ok and working, but then the server is left wide open ...

I would not perse (hard)code it into the controller. Via a route or some other mapping (hashing,lookup) would be fine too, but certainly not on the client.

// Ryan      </description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment16</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment16</guid><pubDate>Tue, 07 Jun 2011 17:40:34 GMT</pubDate></item><item><title>tobi commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>I saw the call to MapPath but was unsure about its contract. And that is what bothers me: I do not feel sure about this.

PS: I would appreciate if the Name/Email input was remembered by the comment form.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment15</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment15</guid><pubDate>Tue, 07 Jun 2011 15:59:21 GMT</pubDate></item><item><title>Kiliman commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>@Patrick, I'm not sure why it would be safer. The code disallows anything that is not exactly ~/Content/css. So using incorrect case would simply return 404. It's a pretty restrictive whitelist, which is all that is needed.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment14</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment14</guid><pubDate>Tue, 07 Jun 2011 14:01:56 GMT</pubDate></item><item><title>JC commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>You can take this line from inside the loop.

var pathAllowed = Server.MapPath(Url.Content("~/Content/css" </description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment13</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment13</guid><pubDate>Tue, 07 Jun 2011 14:01:49 GMT</pubDate></item><item><title>Patrick Smacchia commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>It would look safer to me with...

normalizeFile.ToLower().StartsWith(pathAllowed.ToLower())

... since path are case insensitive.
I hate treating path as string!

http://codebetter.com/patricksmacchia/2008/12/28/what-is-microsoft-waiting-for-providing-a-descent-path-api/</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment11</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment11</guid><pubDate>Tue, 07 Jun 2011 13:51:37 GMT</pubDate></item><item><title>Ayende Rahien commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Tobi,
Did you see the call to MapPath, as part of its work, it will normalize the path properly.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment10</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment10</guid><pubDate>Tue, 07 Jun 2011 13:32:13 GMT</pubDate></item><item><title>Jesse Williamson commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>I like this very much, and I would disagree with Ryan about hardcoding your file names in your controller. I saw an interesting alternative from Mads Kristensen from a talk he gave at Mix (http://channel9.msdn.com/events/MIX/MIX11/FRM04). What I liked about his solution was the hashing of the files to create a unique filename. So the view calls a static function that creates the file name, and if the CSS or JS ever changes, the file name reflects that and the new version is sent to the browser as needed.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment9</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment9</guid><pubDate>Tue, 07 Jun 2011 13:00:23 GMT</pubDate></item><item><title>Dan Plaskon commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Another bump for Combres; it does this and a WHOLE lot more.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment8</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment8</guid><pubDate>Tue, 07 Jun 2011 12:25:17 GMT</pubDate></item><item><title>Ryan Heath commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>I don't like the files parameter. I would hardcode the css files you need in code. And even make another action method if you need to include different css files.

public ActionResult CssOne()
{
  return Merge("base.css", "one.css");
}
public ActionResult CssTwo()
{
  return Merge("base.css", "two.css");
}

private ActionResult Merge(param string[] files)
{
// your implementation
}
</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment7</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment7</guid><pubDate>Tue, 07 Jun 2011 12:08:32 GMT</pubDate></item><item><title>Erik Juhlin commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>@tobi,
I think that validation is pretty much best practice. It doesn't stop you from writing "files=../css/resetcss.css", but it doesn't matter since you will still be in the correct directory.
And it can be nice to be able to write "files=layout/foo.css".</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment6</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment6</guid><pubDate>Tue, 07 Jun 2011 11:59:47 GMT</pubDate></item><item><title>Erik Juhlin commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>Yes, this code is nice. Didn't know about the cache/file dependencies. I've always done that coding myself.
I've looked at dotless, but thought it lacked a good caching strategy.

The only problem I can see with this code is that files that are imported with the @import directive will not be added as dependencies. It would be nice if dotless could include this in the HttpHandler. I prefer using @import instead of putting the filenames in the querystring.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment5</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment5</guid><pubDate>Tue, 07 Jun 2011 11:53:33 GMT</pubDate></item><item><title>tobi commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>"If you aren’t in the CSS directory, you won’t be returned." Are you sure "\..\" is stripped from the path? I don't like that path validation at all. I would restrict the input file names to letters, numbers and "-._". That way you white list and are safe.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment4</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment4</guid><pubDate>Tue, 07 Jun 2011 10:32:18 GMT</pubDate></item><item><title>Felix commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>I'm using very similar code and noticed that browsers occasionally will still re-ask for the files and IIS wouldn't serve them from the cache. So adding checks for If-ModifiedXXX headers will allow you to return 304 instead of sending the entire file stream.</description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment3</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment3</guid><pubDate>Tue, 07 Jun 2011 10:22:16 GMT</pubDate></item><item><title>Matt commented on Elegant Code, Raccoon Blog&amp;rsquo;s CSS Controller</title><description>You really should look into Combres too - it does all this work for you, except that it's completely configurable and functions differently in Debug vs. Release - in Debug mode you get all the separate files loaded separately; in Release mode they get minified, combined, and sent as one.

It does JavaScript too, and the minifier etc. is all configurable.  </description><link>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment2</link><guid>http://ayende.com/13314/elegant-code-raccoon-blog-s-css-controller#comment2</guid><pubDate>Tue, 07 Jun 2011 10:06:06 GMT</pubDate></item></channel></rss>