# HG changeset patch # User Adam Chlipala # Date 1241367879 14400 # Node ID 412ccd97ab710dc82c66adfcb250dad0fa4d80ce # Parent 74a090ff296ea9aa7de2a60aaf51062cd2325af5 url demo diff -r 74a090ff296e -r 412ccd97ab71 demo/prose --- a/demo/prose Sun May 03 12:01:55 2009 -0400 +++ b/demo/prose Sun May 03 12:24:39 2009 -0400 @@ -64,6 +64,12 @@

After setting the cookie, try browsing back to this demo from the main index. The data you entered should still be there.

+url.urp + +

Up to this point, we haven't included a single URL in our source code. This may be very surprising to programmers used to working with traditional web frameworks! In Ur/Web, we avoid writing URLs explicitly wherever possible. To link to an external web page, we rely on an abstract type url. Strings can't be treated implicitly as URLs; rather, they must be "blessed" explicitly. This helps avoid some classes of code injection attacks.

+ +

Further, each Ur/Web application enforces a global condition on which strings are allowed as URLs. The .urp file for this demo shows an example that specifies particular rules about which URLs are allowed. You can try entering a variety of URLs on the form on the front page. Only those satisfying the allow url/deny url conditions should be permitted.

+ listShop.urp

This example shows off algebraic datatypes, parametric polymorphism, and functors.

diff -r 74a090ff296e -r 412ccd97ab71 demo/url.ur --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/url.ur Sun May 03 12:24:39 2009 -0400 @@ -0,0 +1,13 @@ +fun yourChoice r = return + {case checkUrl r.Url of + None => You aren't allowed to link to there. + | Some url => Enjoy!} + + +fun main () = return + Learn something
+
+
+ URL of your choice: + +
diff -r 74a090ff296e -r 412ccd97ab71 demo/url.urp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/url.urp Sun May 03 12:24:39 2009 -0400 @@ -0,0 +1,4 @@ +deny url http://en.wikipedia.org/wiki/PHP +allow url http://en.wikipedia.org/wiki/* + +url diff -r 74a090ff296e -r 412ccd97ab71 demo/url.urs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/url.urs Sun May 03 12:24:39 2009 -0400 @@ -0,0 +1,1 @@ +val main : unit -> transaction page diff -r 74a090ff296e -r 412ccd97ab71 src/demo.sml --- a/src/demo.sml Sun May 03 12:01:55 2009 -0400 +++ b/src/demo.sml Sun May 03 12:24:39 2009 -0400 @@ -104,7 +104,7 @@ clientOnly = [], serverOnly = [], jsFuncs = [], - rewrites = [], + rewrites = #rewrites combined @ #rewrites urp, filterUrl = #filterUrl combined @ #filterUrl urp, filterMime = #filterMime combined @ #filterMime urp } @@ -372,6 +372,35 @@ TextIO.output (outf, "prefix "); TextIO.output (outf, prefix); TextIO.output (outf, "\n"); + app (fn rule => + (TextIO.output (outf, "rewrite "); + TextIO.output (outf, case #pkind rule of + Settings.Any => "any" + | Settings.Url => "url" + | Settings.Table => "table" + | Settings.Sequence => "sequence" + | Settings.View => "view" + | Settings.Relation => "relation" + | Settings.Cookie => "cookie" + | Settings.Style => "style"); + TextIO.output (outf, " "); + TextIO.output (outf, #from rule); + case #kind rule of + Settings.Exact => () + | Settings.Prefix => TextIO.output (outf, "*"); + TextIO.output (outf, " "); + TextIO.output (outf, #to rule); + TextIO.output (outf, "\n"))) (#rewrites combined); + app (fn rule => + (TextIO.output (outf, case #action rule of + Settings.Allow => "allow" + | Settings.Deny => "deny"); + TextIO.output (outf, " url "); + TextIO.output (outf, #pattern rule); + case #kind rule of + Settings.Exact => () + | Settings.Prefix => TextIO.output (outf, "*"); + TextIO.output (outf, "\n"))) (#filterUrl combined); TextIO.output (outf, "\n"); app (fn s =>