An experimental type-safe/context-aware templating library for safe composition of typed strings.
Far too many tasks in web development still involve slapping strings into each other with zero modelling of what those strings mean, how they are encoded, what their source is, and so on. Several classes of security holes, including SQL injection and cross-site scripting, are the result of injecting text into a context where its characters carry new and unanticipated meaning. It is the job of web developers to safely encode/escape input strings for the context in which they are being used.
Or is it?
What if we actually modelled the types of the things strings represent. Things like HTML documents, URLs, query strings, CSS color values, SQL statements. What if our templating language understood these types and could safely and automatically encode everything for us based on context?
That's what Coping is. A framework for modelling types of strings and safely composing them using templating syntax.
Some simple examples to illustrate what I'm trying to do. Given a string containing arbitrary data, injecting into a 'raw' context should literally insert its characters, while injecting it where a query string value is expected will CGI-escape it.
text = 'Some &really?! =cool= <text>' raw = Coping::Raw.new('The text is: [%= text %]') raw.result(binding) # => "The text is: Some &really?! =cool= <text>" url = Coping::URL.new('http://example.com/search?q=[%= text %]') url.result(binding) # => "http://example.com/search?q=Some+%26really%3F%21+%3Dcool%3D+%3Ctext%3E"
These examples are not just changing the encoding used to inject text based on the type of the template. Coping parses your templates to understand their structure, which allows it to do contextual encoding.
For example, see you're rendering an HTML document. Text injected into text or attribute positions must be HTML-escaped, but text injected into URLs must be CGI-escaped. By checking where in the document you're trying to inject text, it can use the appropriate encoding.
html = Coping::HTML.new(<<-HTML) <a href="/visit?location=[%= world %]"> Visit [%= world %] </a> HTML world = '<Earth>' html.result(binding) # => <a href="/visit?location=%3CEarth%3E"> # Visit <Earth> # </a>
(The MIT License)
Copyright © 2012 James Coglan
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.