<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;DkQNQXw5fyp7ImA9WhNXFUU.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443</id><updated>2012-12-04T01:26:30.227Z</updated><category term="grails" /><category term="Facebook Graph API" /><category term="Mobile" /><category term="hibernate" /><category term="Microsoft" /><category term="rails" /><category term="AdobeAIR" /><category term="Facebook Connect" /><category term="Tools" /><category term="Flex" /><category term="github" /><category term="RockMelt" /><category term="Security" /><category term="Search" /><category term="TinyMCE alfresco" /><category term="ASP.NET" /><title>Thoughts.</title><subtitle type="html">In descending chronological order.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/adamcreeger/thoughts" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="adamcreeger/thoughts" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;D0QFQng9cCp7ImA9WhVTGUQ.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-7746939143890041265</id><published>2012-03-06T00:12:00.016Z</published><updated>2012-03-06T00:55:13.668Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-06T00:55:13.668Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="github" /><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>What Grails developers can learn from the Github/Rails Mass Assignment Vulnerability</title><content type="html">&lt;div style="padding:5px; background-color: rgba(165, 175, 200, .2);"&gt;&lt;strong&gt;In short:&lt;/strong&gt; Github's security was breached due to a "vulnerability" in Rails. Grails also suffers from the same vulnerability, but there are ways to protect your app. Check your code for instances of:&lt;pre name="code" class="java"&gt;new DomainModel(params)&lt;/pre&gt; and replace them with &lt;a target="_blank" href="http://grails.org/doc/2.0.x/ref/Controllers/bindData.html"&gt;bindData&lt;/a&gt; or command objects. When using bindData, use the "includes" option - it is safer than "excludes". The following regular expression might help you find some offending code:&lt;pre name="code" class="java"&gt;new .*?\(params\)&lt;/pre&gt;&lt;br /&gt;In addition, make sure that all your domain objects have comprehensive constraints to protect from malicious users. For more info, read on.&lt;/div&gt;&lt;hr style="margin: 20px auto; border:1px solid silver; width:75%" /&gt;Over the weekend, Github suffered a &lt;a href="https://github.com/blog/1068-public-key-security-vulnerability-and-mitigation" target="_blank"&gt;security breach&lt;/a&gt; that allowed an unauthorized user to make a &lt;a href="https://github.com/rails/rails/commit/b83965785db1eec019edf1fc272b1aa393e6dc57" target="_blank"&gt;commit&lt;/a&gt; to the main &lt;a href="https://github.com/rails/rails" target="_blank"&gt;rails/rails&lt;/a&gt; repo. Fortunately, the user had no malicious intent, and only made the commit to bring awareness to the issue. Whether this was the best approach to achieve this is another discussion, and not the subject of this post.&lt;br /&gt;&lt;br /&gt;Github quickly resolved the issue, but thousands of other Rails sites out there are vulnerable to the same attack. Unfortunately, many Grails apps are also liable to have the same issues. Before I go into why this is, and how you can mitigate it, here's a bit of background.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Weapons of Mass Assignment&lt;/h4&gt;Rails, just like many modern web frameworks, allows you to quickly create an object using the request's parameters. In Rails, this code looks a little like this:&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;@user.update_attributes(params[:user])&lt;br /&gt;&lt;/pre&gt;- or - &lt;br /&gt;&lt;pre name="code" class="ruby"&gt;@user = User.new(params[:user])&lt;/pre&gt;&lt;br /&gt;Basically, what is happening here is that any of the &lt;span class="code"&gt;user&lt;/span&gt; instance's properties that have a corresponding request parameter get the value of that parameter. In this case, imagine the User object class had at least two properties: &lt;ul&gt;&lt;li&gt;name&lt;/li&gt;&lt;li&gt;isAdmin&lt;/li&gt;&lt;/ul&gt; Now imagine that the request to create a user had one parameter, name. Under normal operating circumstances, this would work - but it is inherently insecure. An attacker only has to guess that a property exists on the User object with the name 'isAdmin', then add isAdmin=true to the HTTP request. When they do this, the user will be created with isAdmin set to true. Bad news.&lt;br /&gt;&lt;br /&gt;This is known as the "mass-assignment vulnerability" and is, along with mitigation strategies, described in many places - including the &lt;a href="http://guides.rubyonrails.org/security.html#mass-assignment" target="_blank"&gt;Ruby on Rails Security Guide&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;What happened at Github?&lt;/h4&gt;According to the &lt;a href="https://github.com/blog/1068-public-key-security-vulnerability-and-mitigation" target="_blank"&gt;github blog&lt;/a&gt;, the "malicious" user used the mass-assignment vulnerability to compromise the form that allows you to set authorized SSH public keys for your repo, and added his public key to the rails repo, effectively giving him permission to directly commit there.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;What about Grails?&lt;/h4&gt;Grails also has the concept of mass assignment, but tends to refer to it as "data binding" or "batch updating". It is &lt;a href="http://grails.org/doc/latest/guide/theWebLayer.html#dataBinding" target="_blank"&gt;covered in detail&lt;/a&gt; in the Grails Reference, but i'll summarize it here.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;//Create a user object, initializing it with values taken directly from the request.&lt;br /&gt;def user = new User(params)&lt;br /&gt;&lt;/pre&gt;- or -&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;def user = new User()&lt;br /&gt;//Update the user object, with values taken directly from the request.&lt;br /&gt;user.properties = params&lt;br /&gt;&lt;/pre&gt;This is exactly equivalent to the ruby code I posted above. It also suffers from the same vulnerability. Any property on the User object that grants that user elevated privileges will be open to attack via HTTP.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;If it's insecure, why would anyone use it?&lt;/h4&gt;Well, two reasons:&lt;ol&gt;&lt;li&gt;Many people don't know it's insecure&lt;/li&gt;&lt;li&gt;They RTFM. But only briefly.&lt;/li&gt;&lt;/ol&gt; To address my first point, most Grails developers, like those using any other language/frameworks, are mid-level devs under pressure to get features out. In this situation, it's also unlikely that their code will get peer-reviewed, and unlikely that they'll benefit from an experienced developer pointing out the error of their ways. This is what has happened in the Rails world, and I'm sure it's happened with Grails too.&lt;br /&gt;&lt;br /&gt;So, what about the documentation? Grails docs are awesome. They've improved leaps and bounds in the last couple of years. They're clear, concise and accurate. However, in this case, the security risks and mitigation strategies are buried deep down in the topic of &lt;a href="http://grails.org/doc/latest/guide/theWebLayer.html#dataBinding" target="_blank"&gt;data binding&lt;/a&gt;. "Data Binding and Security concerns" appears as the 7th and final section, after the section entitled "Data binding and type conversion errors". Up until this point, every example shows the use of the &lt;span style="font-family:Courier"&gt;new User(params)&lt;/span&gt; method of object creation.&lt;br /&gt;&lt;br /&gt;So this in combination with inexperienced developers pushed for time, eager to please the powers that be, gives us a perfect storm. Very fews devs will know about the risks of batch updating and fewer will know how to avoid them. It also doesn't help that Grails scaffolding also uses the &lt;span style="font-family:Courier"&gt;new User(params)&lt;/span&gt; method of object creation. It doesn't really have a choice right now, since the scaffolding scripts can't make a good guess which properties to include in the batch-update, and which to exclude. They could perhaps just use bindData (see below), including all of the object's properties. But that doesn't seem to illustrate much of a point.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;So, what should I do?&lt;/h4&gt;As a developer who is using Grails, you should use this as a wake up call. Never write code that uses this style of batch updating, and review your controller code, removing any examples of it you can find. Take a look at the docs and understand the mitigation strategies for this issue. In short, they are:&lt;h5&gt;Using bindData&lt;/h5&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;//Update the Person object, with values taken directly from the request - including only properties known to be safe&lt;br /&gt;def p = new Person()&lt;br /&gt;bindData(p, params, [include: ['firstName', 'lastName]])&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For more, see the &lt;a href="http://grails.org/doc/2.0.x/ref/Controllers/bindData.html" target="_blank"&gt;bindData docs&lt;/a&gt;. You'll notice that there are ways to blacklist/&lt;strong&gt;exclude&lt;/strong&gt; certain properties - this is ok, but it is more prudent to always white-list/&lt;strong&gt;include&lt;/strong&gt; allowed properties instead.&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Using the subscript operator&lt;/h5&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;//Retrieve a Person object, and update it with values taken directly from the request - including only properties known to be safe&lt;br /&gt;def p = Person.get(1)&lt;br /&gt;p.properties['firstName','lastName'] = params&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is a "white-list" approach, that achieves the same as the bindData method above, but only works on Domain Objects. It is also not as flexible as bindData.&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Using Command Objects or Action Arguments&lt;/h5&gt;&lt;a href="http://grails.org/doc/latest/guide/theWebLayer.html#commandObjects" target="_blank"&gt;Command Objects&lt;/a&gt; are explained in the docs too, but in a different section. They enable the developer to create a class that has very similar characteristics to domain objects. By including the command object in the parameter list of a an action, Grails will automatically initialize the command object with the values taken from the request. This is not dangerous, because this object will not be directly saved to the DB, but instead probably passed down to a service layer where its properties will be accessed directly. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class UserController {&lt;br /&gt;    def authService&lt;br /&gt;&lt;br /&gt;    def create = { CreateUserCommand cmd -&gt;&lt;br /&gt;        if (cmd.hasErrors()) {&lt;br /&gt;            redirect(action: 'createForm')&lt;br /&gt;            return&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        authService.createUser(cmd)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class CreateUserCommand {&lt;br /&gt;    String username&lt;br /&gt;    String password&lt;br /&gt;&lt;br /&gt;    static constraints = {&lt;br /&gt;        username(blank: false, minSize: 6)&lt;br /&gt;        password(blank: false, minSize: 6)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you have one or two properties you need to update, you could use action arguments (new in Grails 2.0). They allow you to do something similar:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;def create = { String firstName,  String lastName-&gt;&lt;br /&gt;    def user = new User(firstName: firstName, lastName: lastName)&lt;br /&gt;    // save the user, checking for validation errors&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Important:&lt;/strong&gt; None of these mechanisms guarantee safety. You can never trust any input that comes from a user, even if using one of the above strategies. Use the Grails validation mechanism to its fullest. Sanitize your input before saving it down to the DB. Basically, assume your user is out to get you.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;What about the Grails Framework?&lt;/h4&gt;Thankfully, the Grails core team is wanting to address this, and are asking for feedback from the community. Here's mine...&lt;br /&gt;&lt;h5&gt;Update the docs for all Grails versions&lt;/h5&gt;Remove examples of the insecure method of creating objects, and replace it with bindData. Move the "security" paragraphs to the top of the section on data-binding. This will make it clear that security is of primary importance, not an after-thought. As I mentioned earlier, the docs are great - this minor tweak will make them even better.&lt;br /&gt;&lt;h5&gt;Introduce a dataBindable static property&lt;/h5&gt;Grails doesn't have an equivalent of Rails's &lt;a href="http://apidock.com/rails/ActiveModel/MassAssignmentSecurity/ClassMethods/attr_accessible" target="_blank"&gt;attr_accessible&lt;/a&gt; or &lt;a href="http://apidock.com/rails/ActiveModel/MassAssignmentSecurity/ClassMethods/attr_protected" target="_blank"&gt;attr_protected&lt;/a&gt; attributes. But it should. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class User {&lt;br /&gt;    //Fields listed here would not be processed bindData, or new User(params)&lt;br /&gt;    static dataBindable = ["username", "firstName", "lastName"]&lt;br /&gt;    &lt;br /&gt;    String username&lt;br /&gt;    String firstName&lt;br /&gt;    String lastName&lt;br /&gt; &lt;br /&gt;    boolean isActive = false&lt;br /&gt;    int failedPasswordAttemptCount = 0&lt;br /&gt; &lt;br /&gt;    Date dateCreated&lt;br /&gt;    Date lastUpdated&lt;br /&gt;&lt;br /&gt;    static constraints = {&lt;br /&gt;        //strict constraints go here&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Crucially, a class with an empty or missing dataBindable property would not be processed at all by bindData or other batch updating mechanisms. This is a harsh breaking change, but makes it clear that the developer must think about security. Since it is a breaking change, there should be a configurable "legacy mode" that could be configured to "true" to enable old behavior for all objects, or it could also be configured to a list of classes or namespaces to enable gradual migration. "dateCreated" and "lastUpdated" should never be updated via bindData or similar.&lt;br /&gt;&lt;h5&gt;Update the scaffolding scripts&lt;/h5&gt;With the introduction of the dataBindable property, the scaffolding scripts can be smart enough to inspect each domain class and understand which properties should be included in a generated "bindData" statement in the controller code. As a consequence of this, the scaffolding UI would do one of:&lt;ul&gt;&lt;li&gt;Not display properties that are not in the "dataBindable" property&lt;/li&gt;&lt;li&gt;Update these properties using explicit setters in the controller code, with comments explaining why this is so.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;In Conclusion&lt;/h4&gt;Grails isn't immune from this kind of vulnerability - in fact it is likely that many Grails apps suffer from it. Use what happened to Github as inspiration for auditing your code, and make sure that you use sensible methods of handling data from HTTP requests. I hope both the Grails framework and its community are able to benefit from this weekend's events.</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/7746939143890041265/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2012/03/grails-rails-github-and-mass-assignment.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/7746939143890041265?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/7746939143890041265?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2012/03/grails-rails-github-and-mass-assignment.html" title="What Grails developers can learn from the Github/Rails Mass Assignment Vulnerability" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>6</thr:total></entry><entry gd:etag="W/&quot;AkcNRHcyfSp7ImA9Wx9VF0s.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-3800276399397679361</id><published>2011-02-03T19:13:00.026Z</published><updated>2011-02-03T21:21:35.995Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-03T21:21:35.995Z</app:edited><title>It is all about Tweet Shortening, not just URL shortening</title><content type="html">&lt;strong&gt;In short:&lt;/strong&gt; Break the habit of using cryptic short urls and then adding some context to them manually. Instead, use a shortened version of your [brand] name as your domain, then write each "URL alias" in the style of a short facebook status update. For example: &lt;blockquote&gt;&lt;a target="_blank" href="http://acree.gr/likes_the_VW_ad"&gt;http://acree.gr/likes_the_VW_ad&lt;/a&gt;&lt;/blockquote&gt;If you're tweeting, you can then use the rest of the 140 characters much more efficiently - or not at all.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The Background&lt;/h4&gt;A few months ago, I decided to buy a domain name in Greece. Now, I love Greece, but that isn't why I did it. I dit it because I wanted my own, private, URL shortening service: acree.gr. It was primarily an excuse to geek out, but also served as a way to separate myself from millions of other tweeters - my tweets with link would always contain personalized short URLs.&lt;br /&gt;&lt;br /&gt;A few days ago, I got around to building it. Sure, I could have bought it, but I wanted the challenge of maintaining it and hosting it too. To make a short story shorter, it is now live. I used it for real this morning, in &lt;a href="http://twitter.com/#!/Creeger/status/33196888882810880" target="_blank"&gt;this tweet&lt;/a&gt;. To save you a click, here it is:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://2.bp.blogspot.com/_tnnKzrpsmdQ/TUsBq8M1zxI/AAAAAAAAL14/VZ-_TAdrZqk/s400/Screen%2Bshot%2B2011-02-03%2Bat%2B11.23.26%2BAM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5569547201399869202" /&gt;&lt;br /&gt;&lt;br /&gt;After I had written it, I realized that I had saved myself a few characters by using a facebook style status update as the URL. Sure, that is handy, but there is another benefit too. Whenever anyone shares that link, your opinion/fact will be shared immediately, without requiring any additional context or anyone to click on anything. You are helping to ensure your voice does not morph as it is shared. If you are a brand or celebrity, that is pretty powerful. I'm sure someone has done this before, but I haven't seen it. In effect, acree.gr isn't a URL shortening service, &lt;strong&gt;it has become my personal Tweet Shortening Service.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Tweet Shortening in Action&lt;/h4&gt;The link to this page is &lt;a href="http://acree.gr/invented-tweet-shortening"&gt;http://acree.gr/invented-tweet-shortening&lt;/a&gt;. It might be a bit longer than the average bit.ly link, but that URL is working much harder than most. It is not just a reference that goes alongside some context, it IS the context. That can be the tweet on its own. For example, I could tweet about this blog post as follows:&lt;br /&gt;&lt;blockquote&gt;I wrote a blog post about being smarter with URLs: &lt;a href="http://bit.ly/fxvEXf"&gt;http://bit.ly/fxvEXf&lt;/a&gt;&lt;/blockquote&gt;But instead, I think I'll just tweet:&lt;br /&gt;&lt;blockquote&gt;http://acree.gr/invented-tweet-shortening - kind of.&lt;/blockquote&gt;Pompous? Definitely. Inaccurate? Maybe. Concise? Yes. Intriguing? I hope so. Effective? We'll see. (For the record, I don't really believe I've invented anything)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;How to start get your own Tweet Shortening Service&lt;/h4&gt;In the off chance you want to join in, you can follow these steps:&lt;ol&gt;&lt;li&gt;First of all, you should buy the domain you want to use to identify yourself. You might want to check out &lt;a href="http://iwantmyname.com/" target="_blank"&gt;iwantmyname.com&lt;/a&gt; as a start.&lt;/li&gt;&lt;li&gt;Now, you want to get a white-labeled URL shortener. I rolled my own, but I wouldn't recommend it for most people. It looks like &lt;a href="http://shortswitch.com/" target="_blank"&gt;ShortSwitch&lt;/a&gt; is a good option. For the majority of individuals, their $4 a month plan should suffice.&lt;/li&gt;&lt;li&gt;Start writing short tweets! I suggest your first should be something like: "&lt;em&gt;http://yourna.me/loves-short-tweets&lt;/em&gt;" linking to this blog post of course :-)&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h4&gt;The problems with Tweet Shortening&lt;/h4&gt;There is one main reason why Tweet Shortening might not work: people will habitually (even automatically) shorten a URL and then manually add context to the cryptic link they've just produced. It is what they have been doing for months/years. Some apps even do it for you (TweetDeck, for example). In the process of this habitual/automatic shortening, the context rich URL will be lost. For example, if you enter the context-rich link to this post (&lt;a href="http://acree.gr/invented-tweet-shortening"&gt;http://acree.gr/invented-tweet-shortening&lt;/a&gt;) in TweetDeck, it auto-converts it to &lt;a href="http://bit.ly/fxvEXf"&gt;http://bit.ly/fxvEXf&lt;/a&gt;. Damage done. Thankfully, you can disable this otherwise useful feature. Those smart folks at TweetDeck were also kind enough to make it easy to toggle on and off on a per-link basis.&lt;br /&gt;&lt;br /&gt;That's it! I'm enjoying messing around with short tweets, I hope you do too.</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/3800276399397679361/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2011/02/it-is-all-about-tweet-shortening-not.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/3800276399397679361?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/3800276399397679361?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2011/02/it-is-all-about-tweet-shortening-not.html" title="It is all about Tweet Shortening, not just URL shortening" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_tnnKzrpsmdQ/TUsBq8M1zxI/AAAAAAAAL14/VZ-_TAdrZqk/s72-c/Screen%2Bshot%2B2011-02-03%2Bat%2B11.23.26%2BAM.png" height="72" width="72" /><thr:total>5</thr:total></entry><entry gd:etag="W/&quot;CUMHQH4ycCp7ImA9Wx9TEEs.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-2240162465268882366</id><published>2010-11-10T19:11:00.027Z</published><updated>2010-11-18T06:57:11.098Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-18T06:57:11.098Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="RockMelt" /><title>3 Days In: Some RockMelt Tips and Tricks</title><content type="html">&lt;strong&gt;UPDATE: &lt;span style="text-decoration:line-through"&gt;I have 50 Rockmelt invites, on a first come, first served basis. Click here for your invite!&lt;/span&gt; Sorry, all the invites were used in only 45 minutes...&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;It's been almost 3 whole days since I got hold of &lt;a href="http://www.rockmelt.com/" target="_blank" onClick="recordOutboundLink(this, 'Outbound Links', 'rockmelt.com');"&gt;RockMelt&lt;/a&gt;, a new social media web browser. It has been fun playing with the new features, and I've learnt a few tricks that have made it more fun. I thought I'd share them here. This isn't a complete list, please let me know if you want to contribute your own tip.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Learn the lingo, get an edge&lt;/h4&gt;An "edge" is a simply a toolbar that appears at the edge of the screen. RockMelt has two edges out of the box, the friend edge (on the left) and the app edge (on the right).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The friend edge&lt;/strong&gt; will show you either your friends that are online, or your favorites (more on that later). &lt;strong&gt;The app edge&lt;/strong&gt; integrates with Facebook and other apps to shows you feeds (perhaps it should be called the feed edge?). Common feeds to have here are your Facebook feed, your Facebook notifications and your Twitter stream. You can also consume other feeds such as blogs or news. Read on for a easy way to choose your feeds.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Side note: Graph geeks amongst you may well have though an edge was a relationship between two friends - but no, in RockMelt, it's just a toolbar.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Share a link with a friend, in a couple of clicks&lt;/h4&gt;Like a page you're looking at? Want to share it with someone in particular? That's pretty easy.&lt;br /&gt;&lt;br /&gt;Drag and drop the URL from the address bar (using the globe &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh6.googleusercontent.com/Q-27PGQnm0mo5wkeDcZi2oe0ITagUIGqthMQwyk_Sfsx2pxMYAC2g5faBeR2qTALVpCFs_YBWz3jg27bK4zAtBtHlaETU8EescthvvHFjoeXB2LW" /&gt; or the padlock &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh6.googleusercontent.com/1lmUC-7AfWupojfxFCiFHPNmmdBcpk1RiaGx9AfuAkeRN_Uh9YyTs5zE-Wg3MA1PJcl67hbarKzTPgntK64EGqDbw2aDdfeQGKKlQYCimaIyLpM3" /&gt;) onto your friend in the friend edge on the left. Then choose one of the options:&lt;br /&gt;&lt;br /&gt;&lt;img style="border:none" src="https://lh6.googleusercontent.com/BeWyo0zgpM5vfQPU26iCxp_RbrBhA-Wc0kOuncH93FNz3Zpuy-V427zg0hgjK591MCjuAyPg0N0yfZ1a0cjv8w7P2FZfRlZd3LolDmVGUnmHY0L0" /&gt;&lt;br /&gt;&lt;br /&gt;Type your own message, and your done!&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Open search results in way that suits you&lt;/h4&gt;Take a close look at the search results pane, and you'll see two features you may find useful:&lt;br /&gt;&lt;img style="border:none" src="https://lh5.googleusercontent.com/JDoONjoBEswWv52Yqd2R84IvvJ8h8ogHDP0X5iQlpPdKPF_yGDlcq2_-lGU64xrldbGKLA4XaKpvv4ASObBeQAiNBrQsFuTlTVaMoHCTOY8I0bra" /&gt;&lt;ul&gt;&lt;li&gt;If you would rather open each search result in a new background tab, click on the small plus icon &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh3.googleusercontent.com/VGihMDUxTcMRvc54X4Z-YTlG-Kcs2ZzyKPAjWljrh-sucOcXOoUP9ZSUP8gJyeNkaooM_budPW0qeqtRVrAXWrzx-pb0HnNYeBDFFyXeiXx_3RTn" /&gt; that appears when you move your mouse over each result.&lt;/li&gt;&lt;li&gt;If you decide you want to see your search results in one tab, just like a search in most other browsers, then click the &amp;quot;View in tab&amp;quot; link at the top.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;I also use the arrow keys to quickly preview each result, then the enter key to go there.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Let RockMelt feed you&lt;/h4&gt;After a little while, RockMelt can start suggesting new feeds for you to consume. Use the browser for a few days, then use the the "Add Feeds" button &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh6.googleusercontent.com/GK4gDP_l1bnirdmsfZ1m4z6VFIn9dq63ypDY4YsOAIcRzXGMv6eAoJjaSoyXHzvT3zhP_u3QoSoUBKm2CZu6j6hOEdZvpeOkcz8clk9l1PoGZs9m" /&gt; on the app edge (on the right) to have RockMelt automatically suggest feeds for sites you've been using. Click the star next to a feed to add it to the app edge.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Get friendly with the address bar&lt;/h4&gt;You can get to your friend's Facebook profile pages easily in RockMelt. Just type their name into the address bar, click on the suggestion, then click on your friend's profile image that appears.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Pick favorites&lt;/h4&gt;Chances are you've got a lot of friends. Cut down the noise and choose some &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh5.googleusercontent.com/bTugaSg1YUSOkBznur5g7zpg1oIkhBUTwmtwVhpkYJ6TW3_r7shpVp4PApwOxUENnWpDYaYer6rAheWy9r16qBN-PS9xRX4zS8UtAqgbshFcnNwr" /&gt; favorites. The easiest way is to add favorites is to:&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Click on the star in the online/favorite toggle button &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh5.googleusercontent.com/RYuHPi06GQ3eMvwNvVXn218s3vbFai0CXxY9JUrLgn1Bp4Bwfv-aCOJDP9_BFqlIdV2EVhOU3T67qE2U6jlWwweBM0NyOOgSDBKe1PfF2LMun0I4" /&gt; at the top of the friend edge.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click the &amp;quot;Show Friends&amp;quot; button &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh6.googleusercontent.com/2ol_WqYpTVgr6igLLUCfBxkOkqwPvSX7TQqLeY0VztW5roIKc2OWeJW4xsklggSQ8SgeEOj5EiaTr42L-lEXGew1lWGCG1Hgl9o2rbhOq5CEdJtl" /&gt; towards the bottom of the friend edge.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use the search box to find the friends you really want to know about, then make them a favorite by clicking the star &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh6.googleusercontent.com/tvQFEXGweFZvUH1I2Q8j5_jTaOs76I7QW-NwrbXzeexTbJpydC5X7L-Kg3Mi_HABwUFwv443xkk6DV_6CIdfrhOhGfK41ZuAwXh9YJRZVwZXw1tX" /&gt; next to their name.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;(Optional) Unfriend everyone else. :-)&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;h4&gt;Business up front, party in the back&lt;/h4&gt;Being so connected to your friends is great, but what if you need to focus on your work and not get distracted? Use the &lt;span style="font-family:courier"&gt;Ctrl-Shift-Space&lt;/span&gt; key combo to take the edges off your RockMelt. Think of it as a modern-day &lt;a target="_blank" onClick="recordOutboundLink(this, 'Outbound Links', 'en.wikipedia.org/wiki/Boss_key');" href="http://en.wikipedia.org/wiki/Boss_key"&gt;Boss Key&lt;/a&gt;. If you want to hide just one of the edges you can use the &lt;span style="font-family:courier"&gt;Ctrl-Shift-LeftArrow&lt;/span&gt; and &lt;span style="font-family:courier"&gt;Ctrl-Shift-RightArrow&lt;/span&gt; to control your &amp;quot;friend edge&amp;quot; and your &amp;quot;app edge&amp;quot; respectively. The same key combo will bring them back.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Use your invites, wisely&lt;/h4&gt;RockMelt seems to give out an invite or two every couple of days (so far!) It also very cleverly suggests friends that have requested an invite, so hook a friend up, send them an invite - you're sure to get more. Use the "Open Invites" button &lt;img style="border:none;vertical-align:bottom;padding:0" src="https://lh4.googleusercontent.com/YUkwW4FZQc_Jr0xMaflx-sc7wGE_IBE8R9lTb-XQCsBA1GxL4SBMBpqV1L9jj6zTwOYxO0y61F70UAPUry0-gBYocC7qc_RqM3JWmvFmc4zy_Hu3" /&gt; to send invites to the friends who you know really want one.</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/2240162465268882366/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2010/11/3-days-in-some-rockmelt-tips.html#comment-form" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2240162465268882366?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2240162465268882366?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2010/11/3-days-in-some-rockmelt-tips.html" title="3 Days In: Some RockMelt Tips and Tricks" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>10</thr:total></entry><entry gd:etag="W/&quot;CkIMQHo8fyp7ImA9Wx5bEE8.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-3139246900858242840</id><published>2010-10-25T15:43:00.006+01:00</published><updated>2010-10-25T16:29:41.477+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-25T16:29:41.477+01:00</app:edited><title>virtuwell launches</title><content type="html">&lt;span style="font-style:italic;"&gt;Note: The opinions expressed in this post (and all others) are my own and are not necessarily representative of those of AKQA, HealthPartners or any party involved in virtuwell. Please read &lt;a target="_blank" title="Press, then release." href="http://www.businesswire.com/news/home/20101025006435/en/HealthPartners-launches-247-online-clinic-virtuwell.com"&gt;this press release&lt;/a&gt; for more information.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Today is a good day. This morning, at around 7am PST, &lt;a target="_blank" title="The smartest, friendliest insurance company on the planet" href="http://www.healthpartners.com"&gt;HealthPartners &lt;/a&gt;launched an application called &lt;a target="_blank" title="Say hi to the bouncing ball, he's called Fred" href="http://www.virtuwell.com"&gt;virtuwell&lt;/a&gt;. It was created in partnership with &lt;a target="_blank" href="http://www.akqa.com" title="Shameless plug."&gt;AKQA&lt;/a&gt; (the company I work for) over the last 15 months or so.&lt;br /&gt;&lt;br /&gt;The premise of the application is simple. If you or your kids are feeling sick and you are short of time, or perhaps if you don't have insurance, then virtuwell may be for you. It offers online diagnosis and treatment (including prescriptions) at a very affordable cost - it may even be covered by your health plan.&lt;br /&gt;&lt;br /&gt;As Technical Architect, virtuwell was definitely the most challenging project of my career. We were responsible for developing the entire application, and had to meet the strict security and quality requirements that come hand in hand with a healthcare app without sacrificing a clean, friendly user interface. On top of that, I've had to master an entirely new technology stack. We have all learned a lot.&lt;br /&gt;&lt;br /&gt;As a recent arrival in the USA, I have barely began to understand the challenges facing the health system here, but I am proud to have been part of a passionate and dedicated team that has made strides towards making healthcare more accessible to all.&lt;br /&gt;&lt;br /&gt;It is also my mother's birthday.&lt;br /&gt;&lt;br /&gt;As I said earlier, today is a good day.</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/3139246900858242840/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2010/10/virtuwell-launches.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/3139246900858242840?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/3139246900858242840?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2010/10/virtuwell-launches.html" title="virtuwell launches" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEEESHs8cCp7ImA9WxFVGE8.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-8910215947043557578</id><published>2010-06-18T02:48:00.005+01:00</published><updated>2010-06-18T03:03:29.578+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-18T03:03:29.578+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="TinyMCE alfresco" /><title>Alfresco 3.1.1 and paragraph tags</title><content type="html">Right now I am getting to grips with the finer details of an Alfresco v3.1.1 installation. It has been fun*.&lt;br /&gt;&lt;br /&gt;Today's quest was all about stopping the TinyMCE plugin that Alfresco uses from wrapping absolutely everything in a &amp;lt;p&amp;gt; tag. Usually I love &amp;lt;p&amp;gt; tags. Way more than I love &amp;lt;br&amp;gt;tags. But not all content entered through a CMS should be wrapped in them.&lt;br /&gt;&lt;br /&gt;I found &lt;a target="_blank" href="https://issues.alfresco.com/jira/browse/ETHREEOH-2789?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel"&gt;this bug report&lt;/a&gt;, which mentioned a rather drastic way of fixing it, but also gave some clues as to another, less invasive, way. The hunt was on. A few hours later (it would have been a few minutes if I had thought to clear my browser cache), I came up with the following:&lt;br /&gt;&lt;br /&gt;(DISCLAIMER: The following changes will be lost if you upgrade/replace your Alfresco installation. But since this issue doesn't occur in any other version of Alfresco, that should be ok.)&lt;br /&gt;&lt;br /&gt;Step 1: Open up &amp;lt;tomcat&amp;gt;/webapps/alfresco/scripts/ajax/xforms.js&lt;br /&gt;&lt;br /&gt;Step 2: Find the definition of alfresco.constants.TINY_MCE_DEFAULT_SETTINGS (it is near the end) and change it to be:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;alfresco.constants.TINY_MCE_DEFAULT_SETTINGS =&lt;br /&gt;{&lt;br /&gt;theme: "advanced",&lt;br /&gt;mode: "exact",&lt;br /&gt;plugins: alfresco.constants.TINY_MCE_DEFAULT_PLUGINS,&lt;br /&gt;width: -1,&lt;br /&gt;height: -1,&lt;br /&gt;auto_resize: false,&lt;br /&gt;force_p_newlines: false,&lt;br /&gt;encoding: "UTF-8",&lt;br /&gt;entity_encoding: "raw",&lt;br /&gt;add_unload_trigger: false,&lt;br /&gt;add_form_submit_trigger: false,&lt;br /&gt;theme_advanced_toolbar_location: "top",&lt;br /&gt;theme_advanced_toolbar_align: "left",&lt;br /&gt;theme_advanced_buttons1: "",&lt;br /&gt;theme_advanced_buttons2: "",&lt;br /&gt;theme_advanced_buttons3: "",&lt;br /&gt;urlconverter_callback: "alfresco_TinyMCE_urlconverter_callback",&lt;br /&gt;file_browser_callback: "alfresco_TinyMCE_file_browser_callback",&lt;br /&gt;forced_root_block: false,&lt;br /&gt;force_br_newlines: true&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note the two last lines.&lt;br /&gt;&lt;br /&gt;When you are done, all you need to do is clear your browser's cache, and go edit some web content in Alfresco. Anything you create from now on will no longer be wrapped in the usually wonderful &amp;lt;p&amp;gt; tags.&lt;br /&gt;&lt;br /&gt;*This depends on your definition of fun.&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/8910215947043557578/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2010/06/alfresco-311-and-paragraph-tags.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/8910215947043557578?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/8910215947043557578?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2010/06/alfresco-311-and-paragraph-tags.html" title="Alfresco 3.1.1 and paragraph tags" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0AARHkyeSp7ImA9WxFVF08.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-7989959072840212973</id><published>2010-06-16T21:18:00.014+01:00</published><updated>2010-06-16T21:55:45.791+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-16T21:55:45.791+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Facebook Graph API" /><category scheme="http://www.blogger.com/atom/ns#" term="Facebook Connect" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><title>New version of FBConnectAuth released: 1.0</title><content type="html">One year on, I've just released a minor enhancement to the tiny open source project I created called &lt;a target="_blank" href="http://fbconnectauth.codeplex.com/"&gt;FBConnectAuth - Facebook Connect Authentication for ASP.NET&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This release contains two enhancements:&lt;br /&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;It supports Facebook's new &lt;a target="_blank" href="http://developers.facebook.com/docs/reference/javascript/"&gt;Graph API Javscript SDK&lt;/a&gt; (but remains backwards compatible)&lt;/li&gt;&lt;li&gt;It works in partially trusted environments&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;It is specifically targeted at .NET 2.0 (as was the previous release) for the benefit of those who don't have control over their production environment.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Interestingly, I noticed that the new Graph API requires the use of the Facebook Application's "Application ID", rather than "API Key". This means that an example of using FBConnectAuth looks with the Graph API like this:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp"&gt;&lt;br /&gt;//Note this is the "app id", not "api Key"&lt;br /&gt;FBConnectAuthentication auth = new FBConnectAuthentication(appId,appSecret);&lt;br /&gt;if (auth.Validate() != ValidationState.Valid)&lt;br /&gt;{&lt;br /&gt;    // The request does not contain the details&lt;br /&gt;    // of a valid Facebook connect session.&lt;br /&gt;    // You'll probably want to throw an error here.&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;    FBConnectSession fbSession = auth.GetSession();&lt;br /&gt;&lt;br /&gt;    string userId = fbSession.UserID;&lt;br /&gt;    string sessionKey = fbSession.SessionKey;&lt;br /&gt;&lt;br /&gt;    //This is the Graph API access token&lt;br /&gt;    //(available only when using the Graph API)&lt;br /&gt;    string accessToken = fbSession.AccessToken;&lt;br /&gt;&lt;br /&gt;    // The above values can now be used to communicate&lt;br /&gt;    // with Facebook on behalf of your user,&lt;br /&gt;    // perhaps using the Facebook Developer Toolkit&lt;br /&gt;&lt;br /&gt;    // The expiry time and session secret is also available.&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you are interested, go &lt;a target="_blank" href="http://fbconnectauth.codeplex.com/releases/view/45294"&gt;take a look&lt;/a&gt;.</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/7989959072840212973/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2010/06/new-version-of-fbconnectauth-released.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/7989959072840212973?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/7989959072840212973?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2010/06/new-version-of-fbconnectauth-released.html" title="New version of FBConnectAuth released: 1.0" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CE8ASXc6fSp7ImA9Wx5RF0s.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-6988402028350100259</id><published>2010-05-11T17:20:00.008+01:00</published><updated>2010-08-25T20:00:48.915+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-25T20:00:48.915+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="hibernate" /><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>Random Grails tip: Using a DB reserved word as a domain class name in Grails</title><content type="html">We recently came across a situation where we couldn't our Grails app was failing because it was trying to create a table with the name of 'Condition', which turns out to be a reserved word in MySQL... We worked around it by changing the name of the table to 'conditions' by using the &lt;a target="_blank" href="http://www.grails.org/GORM+-+Mapping+DSL"&gt;Grails ORM DSL&lt;/a&gt;, but it turns out there is another way.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Backtick to the rescue...&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Hibernate allows you to use backticks (`) to indicate that a name should be escaped - you can simply use this in your grails mapping. For example, we could have used:&lt;/div&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;class Condition {&lt;br /&gt; String property1&lt;br /&gt; String property2&lt;br /&gt; ...&lt;br /&gt;&lt;br /&gt; static mapping = {&lt;br /&gt;  table '`condition`'&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To be honest, I'm not sure why Grails and/or hibernate don't escape all table and column names by default (I'm sure there is a good reason) - there is an &lt;a href="http://jira.codehaus.org/browse/GRAILS-1675" target="_blank"&gt;open JIRA issue&lt;/a&gt; in Grails around this very problem...</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/6988402028350100259/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2010/05/random-grails-tip-using-db-reserved.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/6988402028350100259?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/6988402028350100259?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2010/05/random-grails-tip-using-db-reserved.html" title="Random Grails tip: Using a DB reserved word as a domain class name in Grails" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;A0IGRnY-eCp7ImA9WxFQF00.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-9053766497061193437</id><published>2010-04-30T22:56:00.009+01:00</published><updated>2010-05-13T01:12:07.850+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-13T01:12:07.850+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>The location of the User Profile for Network Service on Windows Server 2008 &amp; 7</title><content type="html">This kind of thing should be easy to find, but I couldn't hunt it down on google. So to save someone else some pain, here it is - the location of the %USERPROFILE% / home directory for the NT AUTHORITY\NetworkService user:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(drum roll...)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;%systemroot%\ServiceProfiles\NetworkService&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;which usually translates as:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;c:\Windows\ServiceProfiles\NetworkService&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The user profiles for other "well known" service accounts (such as LocalService) are siblings of this directory.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope that saves someone some time...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/9053766497061193437/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2010/04/where-is-user-profile-for-network.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/9053766497061193437?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/9053766497061193437?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2010/04/where-is-user-profile-for-network.html" title="The location of the User Profile for Network Service on Windows Server 2008 &amp; 7" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;CU4MQ34_eSp7ImA9WxBSFk8.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-8967196593787308078</id><published>2009-12-23T05:54:00.006Z</published><updated>2009-12-24T03:06:22.041Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-24T03:06:22.041Z</app:edited><title>2009 - A good year...</title><content type="html">2009 draws to a close, and it just struck me what a phenomenal year it has been.&lt;br /&gt;&lt;br /&gt;This year I:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Traveled through Morocco&lt;/li&gt;&lt;li&gt;Visited Paris&lt;/li&gt;&lt;li&gt;Got engaged!&lt;/li&gt;&lt;li&gt;Drove across the USA, from New York to California, via Nashville, New Orleans, Austin and Roswell&lt;/li&gt;&lt;li&gt;Moved to San Francisco&lt;/li&gt;&lt;li&gt;Helped AKQA and Fiat win &lt;a href="http://www.google.com/search?q=eco:Drive+awards"&gt;loads of awards&lt;/a&gt; for eco:Drive&lt;/li&gt;&lt;li&gt;&lt;a href="http://picasaweb.google.com/adamcreeger/BeautyAndTheGeek?authkey=Gv1sRgCK36n_mElYPZnQE#5314466300580263762"&gt;Hung out with a supermodel&lt;/a&gt;, and got paid for it.&lt;/li&gt;&lt;li&gt;Got &lt;a href="http://is.gd/1sFLM"&gt;interviewed by Wired Magazine&lt;/a&gt;, along with a cool photo shoot.&lt;/li&gt;&lt;li&gt;Joined a great team at AKQA SF, and helped make it even greater&lt;/li&gt;&lt;li&gt;Released &lt;a href="http://fbconnectauth.codeplex.com/"&gt;FBConnectAuth&lt;/a&gt;, a tiny open source component for ASP.NET that helps with Facebook Connect authentication.&lt;/li&gt;&lt;li&gt;Met someone who was actually using FBConnectAuth. &lt;/li&gt;&lt;li&gt;Got to live in a great house in SF, in an awesome neighborhood.&lt;/li&gt;&lt;li&gt;Learnt to speak American.&lt;/li&gt;&lt;li&gt;Got to learn Groovy and Grails&lt;/li&gt;&lt;li&gt;Worked (and still working) on a massive (and still super-secret) grails project&lt;/li&gt;&lt;li&gt;Earned a new nickname ("Piping Hot" - for my terrible Halo skills)&lt;/li&gt;&lt;li&gt;Made new friends with funny accents.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I have a lot to be thankful for.&lt;br /&gt;&lt;br /&gt;I hope you all (that's you mum) have a wonderful 2010! &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Happy Holidays (see, check out my American skills)&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/8967196593787308078/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2009/12/2009-good-year.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/8967196593787308078?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/8967196593787308078?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2009/12/2009-good-year.html" title="2009 - A good year..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0YBRHkyfyp7ImA9WxJWGU8.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-8226815844263083959</id><published>2009-06-25T10:41:00.003+01:00</published><updated>2009-06-25T11:19:15.797+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-25T11:19:15.797+01:00</app:edited><title>On winning...</title><content type="html">18 months ago a few of us started work on something rather special. 12 hours ago, we won &lt;a href="http://www.campaignlive.co.uk/news/915698/AKQA-triumphs-Grand-Prix-award-Cyber-Lions/"&gt;the advertising industry's biggest award&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It is sometimes the ones who shout the loudest that get the praise, so I want to take a moment to thank those that worked incredibly hard on an amazing product. To the small core of us that sat in that cosy, sunny room, developing a language of our own: Mark, Harald, Stuart (who pretty much became my wife), James, Richard S, Tristan, Martin, Zahid, Kevin - you rock! We can now, officially, get a woop woop.&lt;br /&gt;&lt;br /&gt;To the guys who worked so closely with us the whole time, crafting words, designing t-shirts and making everything look wonderful: Chris, Richard B, Andy - you guys were the best creative team a bunch of geeks could have ever asked for.&lt;br /&gt;&lt;br /&gt;Alison, you made the complicated simple. James and Nick, the branding was amazing - the video was a masterpiece.&lt;br /&gt;&lt;br /&gt;Thanks to Bonnie, Eli and Livia for kicking things off and keeping them going. Deep gratitude to Neville and Miriam for all your advice.&lt;br /&gt;&lt;br /&gt;And not forgetting our client - Luis. Without such a visionary and passionate figure sitting on the other side of the table, none of this would have happened.&lt;br /&gt;&lt;br /&gt;That is enough gushing for now - I'm off to bed. Ciao!</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/8226815844263083959/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2009/06/on-winning.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/8226815844263083959?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/8226815844263083959?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2009/06/on-winning.html" title="On winning..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CE8FQXc9fip7ImA9WxRbGE8.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-2597895617502246878</id><published>2008-12-09T10:07:00.025Z</published><updated>2008-12-09T11:40:10.966Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T11:40:10.966Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="AdobeAIR" /><title>Signing Adobe AIR files with Authenticode Certificates</title><content type="html">There are some things that always seem a little trickier than they should be. Renting an apartment in London that has working heating and hot water is one of them, converting an Authenticode certificate from SPC and PVK files to a format that you can sign Adobe AIR files with is another.&lt;br /&gt;&lt;br /&gt;Since I still haven't figured out the former, I'm going to write about the latter.&lt;br /&gt;&lt;br /&gt;First things first, if you're going to get a certificate &lt;span style="font-weight: bold;"&gt;solely&lt;/span&gt; for signing AIR files, then buy one from &lt;a target="_blank" href="https://securitycenter.verisign.com/celp/enroll/upsell?application_locale=VRSN_US&amp;amp;originator=VeriSign:CELP&amp;amp;bundle_id=NOSCS002"&gt;Verisign&lt;/a&gt; or &lt;a target="_blank" href="https://www.thawte.com/process/retail/new_devel"&gt;Thawte&lt;/a&gt; specifically for AIR. It's just easier.&lt;br /&gt;&lt;br /&gt;If, however, you want to use your certificate to sign .NET applications as well, then get a Microsoft Authenticode certificate. You can use that certificate to sign AIR apps and well as .NET apps. We got our Authenticode certificate from Verisign, but there are other vendors. If this is what works for you, then the following might be helpful. If you have haven't already done so, go away and buy the certificate now - I'll see you again when you have downloaded a PVK file and an SPC file.&lt;br /&gt;&lt;br /&gt;So, let's skip forward a few days. You've got your PVK file (the private key), and the SPC file. You're probably wondering how to turn those files in to a PFX file that you can use with ADT to sign files. Hopefully, these steps should help. Oh, I'm assuming that you're using a PC here...&lt;br /&gt;&lt;br /&gt;Firstly, you need to ask yourself two questions:&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Do you feel lucky?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Can you find a tool called pvk2pfx on your machine. This is a pain to get hold of, but lives in bin directory of most Microsoft SDKs.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;If you're lucky AND you can find pvk2pfx, then &lt;a href="#IAmFeelingLucky"&gt;skip forward a little&lt;/a&gt;. If you can't find it, then read on.&lt;br /&gt;&lt;a name="IAmNotFeelingLucky"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;I don't have pvk2pfx, I need something else&lt;/h3&gt;&lt;br /&gt;Worry not, this is still completely possible...&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Get a tool called pvkimprt. You can &lt;a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=F9992C94-B129-46BC-B240-414BDFF679A7&amp;amp;displaylang=EN"&gt;download it from Microsoft&lt;/a&gt;. Run the self extracting whatsit, then run the installer, and make a note of its final resting place.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Open up a commmand prompt (Start, Run, "cmd").&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Change to the directory where pvkimprt ended up.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Run:&lt;br /&gt;&lt;span style="font-family:Courier;"&gt;pvkimprt -PFX &amp;lt;path\to\cert.spc&gt; &amp;lt;path\to\key.pvk&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Choose the following options:&lt;br /&gt;&lt;br /&gt;&lt;a title="Choose to export the private key..." onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_tnnKzrpsmdQ/ST5Rck1rQGI/AAAAAAAADTU/1z6asY30L-A/s1600-h/1.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 246px;" src="http://2.bp.blogspot.com/_tnnKzrpsmdQ/ST5Rck1rQGI/AAAAAAAADTU/1z6asY30L-A/s320/1.JPG" alt="Choose to export the private key..." id="BLOGGER_PHOTO_ID_5277745364691796066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title="Choose the PFX format, choosing to include certificate chain and use strong protection." onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_tnnKzrpsmdQ/ST5SLTN231I/AAAAAAAADTc/JPb-AdCNCJw/s1600-h/2.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 246px;" src="http://4.bp.blogspot.com/_tnnKzrpsmdQ/ST5SLTN231I/AAAAAAAADTc/JPb-AdCNCJw/s320/2.JPG" border="0" alt="Choose the PFX format, choosing to include certificate chain and use strong protection." id="BLOGGER_PHOTO_ID_5277746167415234386" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title="Choose a password..." onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_tnnKzrpsmdQ/ST5SLUYLoaI/AAAAAAAADTk/gl66it8GBTQ/s1600-h/3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 246px;" src="http://1.bp.blogspot.com/_tnnKzrpsmdQ/ST5SLUYLoaI/AAAAAAAADTk/gl66it8GBTQ/s320/3.jpg" border="0" alt="Choose a password..." id="BLOGGER_PHOTO_ID_5277746167726973346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title="Select a location to save the pfx file..." onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_tnnKzrpsmdQ/ST5SLjJbuJI/AAAAAAAADTs/UDlwkftHR0g/s1600-h/4.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 246px;" src="http://2.bp.blogspot.com/_tnnKzrpsmdQ/ST5SLjJbuJI/AAAAAAAADTs/UDlwkftHR0g/s320/4.jpg" border="0" alt="Select a location to save the pfx file" id="BLOGGER_PHOTO_ID_5277746171691645074" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title="This is what success looks like..." onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_tnnKzrpsmdQ/ST5SLlXr-CI/AAAAAAAADT0/YdlfxNizjTc/s1600-h/5.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 183px; height: 100px;" src="http://2.bp.blogspot.com/_tnnKzrpsmdQ/ST5SLlXr-CI/AAAAAAAADT0/YdlfxNizjTc/s320/5.jpg" border="0" alt="This is what success looks like..." id="BLOGGER_PHOTO_ID_5277746172288301090" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can use the resulting pfx file to &lt;a target="_blank" href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7fd6.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7f72"&gt;sign an Adobe AIR file with adt&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;You're done! You might want to ignore the rest of this post, it will make you wish you were luckier. Any questions/mistakes/omissions, feel free to ask...&lt;br /&gt;&lt;br /&gt;&lt;a name="IAmFeelingLucky"&gt;&lt;/a&gt;&lt;h3&gt;I'm lucky, I have pvk2pfx&lt;/h3&gt;This is much easier. Simply:&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Open up a commmand prompt (Start, Run, "cmd")&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Change to directory where you found pvk2pfx.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Run:&lt;br /&gt;&lt;span style="font-family:Courier;"&gt;pvk2pfx -pvk &amp;lt;path\to\key.pvk&gt; -pi &amp;lt;pvk password&gt; -spc &amp;lt;path\to\cert.spc&gt; -pfx &amp;lt;path\to\output.pfx&gt; -po &amp;lt;new password for pfx file&gt;&lt;/span&gt; (all on one line)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can use the resulting pfx file to &lt;a target="_blank" href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7fd6.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7f72"&gt;sign an Adobe AIR file with adt&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;I hope that was helpful!</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/2597895617502246878/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/12/signing-adobe-air-files-with.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2597895617502246878?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2597895617502246878?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/12/signing-adobe-air-files-with.html" title="Signing Adobe AIR files with Authenticode Certificates" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_tnnKzrpsmdQ/ST5Rck1rQGI/AAAAAAAADTU/1z6asY30L-A/s72-c/1.JPG" height="72" width="72" /><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;DUEARXY7fSp7ImA9WxRbFEw.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-2110099965199703993</id><published>2008-12-04T12:35:00.006Z</published><updated>2008-12-04T19:07:24.805Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-04T19:07:24.805Z</app:edited><title>The Anatomy of a Seriously Sophisticated AIR Application</title><content type="html">As promised, I've uploaded the slides that &lt;a href="http://www.pixelpod.co.uk/blog" target="_blank" title="Mr. Pixel Pod"&gt;Rick Williams&lt;/a&gt; and I presented at Adobe MAX Milan on December 2nd 2008. Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;embed src="http://data.sliderocket.com/SlideRocketPlayer.swf" flashvars="id=e756537e-239c-4c8d-b3da-c22f91ce9469" width="500" height="375" allowFullScreen="true" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/2110099965199703993/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/12/anatomy-of-seriously-sophisticated-air.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2110099965199703993?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2110099965199703993?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/12/anatomy-of-seriously-sophisticated-air.html" title="The Anatomy of a Seriously Sophisticated AIR Application" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>4</thr:total></entry><entry gd:etag="W/&quot;C0MDQH08eip7ImA9WxRbE0Q.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-7987076706821254229</id><published>2008-12-02T15:37:00.003Z</published><updated>2008-12-04T11:51:11.372Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-04T11:51:11.372Z</app:edited><title>Thanks to all those who came to see us talk...</title><content type="html">Just a quick note to say thanks to all the folks that came to see &lt;a href="http://www.pixelpod.co.uk/blog" target="_blank" title="Mr. Rick Williams"&gt;Rick&lt;/a&gt; and I present "The Anatomy of a Sophisticated Air Application" at Adobe MAX in Milan. It was also great to speak to so many people who loved Fiat eco:Drive.&lt;br /&gt;&lt;br /&gt;We will the get the slides up ASAP. Over the next few weeks, I'll blog about some of the topics we covered in a bit more detail - leave a comment if there is something specific you would like to know about.&lt;br /&gt;&lt;br /&gt;Thanks!</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/7987076706821254229/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/12/thanks-to-all-those-who-came-to-see-us.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/7987076706821254229?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/7987076706821254229?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/12/thanks-to-all-those-who-came-to-see-us.html" title="Thanks to all those who came to see us talk..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEMCR3c_eyp7ImA9WxRVFks.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-2824089234742755821</id><published>2008-11-14T12:39:00.001Z</published><updated>2008-11-14T12:41:06.943Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-14T12:41:06.943Z</app:edited><title>The kind of waterfall development I like...</title><content type="html">The process cynic in me says you don't often hear the words "waterfall" and "innovation" in the same sentence... This, however, is an exception.&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/0HeUixe_Lpg&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/0HeUixe_Lpg&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/2824089234742755821/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/11/kind-of-waterfall-development-i-like.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2824089234742755821?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2824089234742755821?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/11/kind-of-waterfall-development-i-like.html" title="The kind of waterfall development I like..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;CUYHQ3Y9eSp7ImA9WxRVE0s.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-1450865641340662636</id><published>2008-11-11T00:14:00.002Z</published><updated>2008-11-11T00:25:32.861Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-11T00:25:32.861Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><title>Web Sequence Diagrams: It doesn't get any more exciting than this...</title><content type="html">Ok, a slight exaggeration. You might even accuse me of lying, but I find this pretty damn cool.&lt;br /&gt;&lt;br /&gt;Last year I stumbled upon an ingenious tool - &lt;a target="_blank" title="Get to know Alice, Bob and co..." href="http://www.websequencediagrams.com/"&gt;Web Sequence Diagrams&lt;/a&gt;. By using a markup language, you can draw sequence diagrams without the fuss of Visio, or even Gliffy.&lt;p&gt;&lt;img src="http://www.websequencediagrams.com/cgi-bin/cdraw?lz=cGFydGljaXBhbnQgSG9tZW93bmVyIGFzIEgKAA8MIkJ1aWxkZXIgMSIgYXMgQjEACBYyABgGMgAvDUtldHRsZSBhcyBLCgpILT4gQjE6IEZpeCBib2RnZWQgRElZCkIxIC0-IEs6IEJvaWwgd2F0ZXIKYWN0aXZhdGUgSwAYB0IyOiBGaW5kIG1vc3RcbmV4cGVuc2l2ZVxubXVnCkIyABwIQnJlYWsgAA8FACsNXG5hbm90aGVyACQNMTogRm91ABgGdGlxdQBIB0sAgSIHV2F0ZXJcbmhhc1xuYm9pbGVkCmRlAIEGFVBvdXIgdGVhAE4LVGVhIAA0BmVlbiBwb3VyZWQAgUUIMTogRHJpbmsALQYAgXsFSDogV2UgbmVlZCAAgSEJZGF5IG1hdGUsXG5zb3JyeS4&amp;s=napkin" alt="A day in the life of a builder, sequence diagram style..." /&gt;&lt;/p&gt;&lt;br /&gt;In just a couple of hours, you can be in diagram heaven. You could flood your desktop with exported versions of the diagrams. You could fill your office with print outs (but consider the environment kids). But there was something missing. There just wasn't an easy way to store them in their raw text format, and view the results... The tool was SCREAMING out for a wiki plugin.&lt;br /&gt;&lt;br /&gt;So, I set about writing one. And got no further. Life, well actually work, intervened, as usual.&lt;br /&gt;&lt;br /&gt;But fear not (for I know you are trembling with fear and anticipation), others have come to the rescue with a &lt;a title="Oh the excitment..." target="_blank" href="http://labs.atlassian.com/wiki/display/CUML/Confluence+UML+Sequence+Plugin"&gt;plugin &lt;/a&gt;for &lt;a target="_blank" title="The uber-wiki" href="http://www.atlassian.com/software/confluence/"&gt;Confluence&lt;/a&gt; and a &lt;a href="http://www.websequencediagrams.com/sequencediagram.zip" target="_blank" title="What sheer bliss..."&gt;plugin&lt;/a&gt; for the &lt;a target="_blank" title="Ok, it has some flaws, but not many..." href="http://trac.edgewall.org/"&gt;rather wonderful Trac&lt;/a&gt;. On top of all this, you can also find a &lt;a target="_blank" title="With these scripts, you are truly spoiling us" href="http://www.websequencediagrams.com/embedding.html"&gt;whole set of example scripts for Python, Java, and Ruby&lt;/a&gt;. Apparently, you can even render inline markup by using a bit of JavaScript magic, but I haven't quite got that working yet...&lt;br /&gt;&lt;br /&gt;Genius.</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/1450865641340662636/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/11/web-sequence-diagrams-it-doesnt-get-any.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/1450865641340662636?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/1450865641340662636?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/11/web-sequence-diagrams-it-doesnt-get-any.html" title="Web Sequence Diagrams: It doesn't get any more exciting than this..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0UGQ3o5fSp7ImA9WxRVE0g.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-2011707898986241390</id><published>2008-11-07T16:38:00.007Z</published><updated>2008-11-10T22:13:42.425Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-10T22:13:42.425Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Mobile" /><title>A prediction about projection...</title><content type="html">&lt;p&gt;This morning, &lt;a title="David Pogue, talking about a small projector" target="_blank" href="http://www.nytimes.com/2008/11/05/technology/personaltech/05pogue.html"&gt;news about a tiny projector&lt;/a&gt; dropped into my inbox.&lt;/p&gt;&lt;p&gt;To summarise, this is a battery powered projector, perfect for showing movies from your ipod. Great. The author of that article got it right, this is game changing stuff. Very cool.&lt;br /&gt;&lt;br /&gt;But I think it is bigger than that.&lt;br /&gt;&lt;br /&gt;You see, when the MP3 format first came on the scene, the people rejoiced. "Woo", said Bob, "I can burn a CD with 200 songs". "Amazing", said Esmeralda, "I can FTP this song in just 1 hour!". "Holy crap!", said &lt;a title="Now making music production software..." target="_blank" href="http://en.wikipedia.org/wiki/Justin_Frankel"&gt;Justin&lt;/a&gt;, "I can make a fortune out of writing a media player". No one (that I knew) said: "Wow, in just a few years we'll have changed the way we listen to music. Oh, it'll be much prettier too." Very few really saw the true potential of this breakthrough. And I think the same is true here.&lt;br /&gt;&lt;br /&gt;Right now, we're using desktops and laptops as much as ever. Sure we're using mobiles to access the web, but we're not using them as a replacement. We use them where we wouldn't use a regular computer. With a few improvements, we'll start to see these small projectors converge with mobile devices. Add to the mix the inevitable rise in processing power, and a new breed of device will start to replace the desktop computer, and indeed the laptop. We'll be able to forget about the small screen, and use a projected larger one. Add a &lt;a title="Not quite like this, but nearly..." target="_blank" href="http://www.thinkgeek.com/computing/input/8193/"&gt;futuristic input mechanism&lt;/a&gt;, and you'll have a pocket powerhouse.&lt;br /&gt;&lt;br /&gt;I'm guessing this is why Google never bothered trying to make a desktop operating system - mobile will be the new desktop.</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/2011707898986241390/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/11/prediction-about-projection.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2011707898986241390?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2011707898986241390?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/11/prediction-about-projection.html" title="A prediction about projection..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0MDSX0zcSp7ImA9WxRWEko.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-3568671058262730965</id><published>2008-10-28T20:13:00.006Z</published><updated>2008-10-29T09:11:18.389Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-29T09:11:18.389Z</app:edited><title>A belated first post...</title><content type="html">&lt;p&gt;There seem to be a few questions to answer before actually starting a blog. What will the content be? How often will I post? How will I start it? When will I stop procrastinating and actually do it?&lt;/p&gt;&lt;p&gt;This sentence answers all those questions in one - (see below; whenever something substantial falls out of my brain; with a random post; a few posts ago)&lt;/p&gt;&lt;p&gt;With the realisation that a blog that has a shaky start is better than no blog at all, it's time to get this thing off the ground. First let me introduce myself. My name is Adam Creeger. I work as a "Technical Architect" for &lt;a id="neq1" title="Check out the recruitment section..." href="http://www.akqa.com/" target="_blank"&gt;AKQA&lt;/a&gt; London, a leading light in the murky world of Digital Advertising. They used to call themselves an interactive marketing shop, but I guess the advertising industry shifted itself our way, and swallowed us up in the process.&lt;/p&gt;&lt;p&gt;What is a Technical Architect at an ad agency? Good question. I get to spend most of my time designing (think UML - not crayons), mentoring, experimenting, talking to the people that pay the bills and occasionally coding. Somewhere amongst this I get to observe - and even influence - the running of some pretty intense projects. Pushing boundaries under tight timeline pressures with challenging resourcing issues makes for an interesting day.&lt;/p&gt;&lt;p&gt;Traditionally (7 years professionally), I've been devoted to the art of .NET and all things Microsoft, especially C#/ASP.NET. These days though, I've broadened my horizons to include RIAs (Flex, AIR, WPF, and of course the AJAX/DHTML combo), functional languages and the fall and rise of the &lt;a id="t4p5" title="the obligatory wikipedia link" href="http://en.wikipedia.org/wiki/Dynamic_language" target="_blank"&gt;dynamic language&lt;/a&gt; (including Powershell). At the end of last year, I stepped back in time and did some &lt;a title="Fancy fancy..." href="http://news.zdnet.co.uk/internet/0,1000000097,39492234,00.htm" target="_blank"&gt;award winning&lt;/a&gt;, brain-taxing &lt;a href="http://www.fiat.co.uk/Showroom/#showroom/new_500/configurator" title="Fiat 500? Paint it black..." target="_blank"&gt;work&lt;/a&gt; (&lt;a id="hm6p" title="enjoy" href="http://www.cs.hut.fi/%7Eenu/tc.html" target="_blank"&gt;transitive closures&lt;/a&gt;, anyone?) in Actionscript 2. Learning a new language is always fun, but having to do without all the goodness of C# (au revoir Typed Arrays, Generics, Run time type checking to name a few) makes it well, let's just say, intriguing. Right now I'm recovering from giving birth to &lt;a title="Say Ciao! to Franco, Merv and Claudia..." target="_blank" href="http://www.fiat.co.uk/ecoDrive" id="pv6t"&gt;Fiat eco:Drive&lt;/a&gt; - one heck of an AIR project. Most importantly though, I get to work with some inspirational people who astound me with their passion for this game.&lt;/p&gt;&lt;p&gt;I'm going to write about all these things. There's plenty of room for discussion on all fronts, but I imagine I'll spend a fair amount of time on the art of software development itself. What makes for a successful project? Why do smart programmers fail to produce applications that work? Why are project management techniques so hit and miss? How do you ensure teams in different time zones get along just fine? These questions have been answered before, but perhaps not from the inside of an advertising agency where the projects are many and the risks, rewards and pressures are high. There'll be a few tech-heavy posts too, stuff I discover along the way etc etc. Whatever happens, I'm sure this will evolve into something beyond what I imagined in this paragraph.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Thank you, and good night.&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/3568671058262730965/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/10/belated-first-post.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/3568671058262730965?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/3568671058262730965?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/10/belated-first-post.html" title="A belated first post..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;CkQDRXg_eCp7ImA9WxRREk0.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-4486155233613511714</id><published>2008-08-28T21:01:00.007+01:00</published><updated>2008-09-23T21:06:14.640+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-23T21:06:14.640+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Flex" /><category scheme="http://www.blogger.com/atom/ns#" term="AdobeAIR" /><title>Logging in Flex/Air: Filters behaving badly...</title><content type="html">I'm a firm believer in diagnostics - in .NET land I just can't live without log4net. The mx.logging.* namespace in Flex 3 appears to give us &lt;span style="font-style: italic;"&gt;some &lt;/span&gt;similar functionality (I'm talking about restricting loggers to certain "categories" here) but without the &lt;a target="_blank" href="http://logging.apache.org/log4net/release/manual/configuration.html"&gt;lovely configuration framework&lt;/a&gt; of log4net.&lt;br /&gt;&lt;br /&gt;In an app we're writing at the moment, I was seeing some wierd behaviour. Basically, the logging targets were just not obeying their filters, meaning every message was getting written everywhere. Not good. At all.&lt;br /&gt;&lt;br /&gt;So I did some digging and found two things that surprised me:&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;1. Setting a level on a target will call Log.addTarget() - probably prematurely&lt;/h4&gt;&lt;br /&gt;When stepping through the source code of the Flex logging framework, I found this bit of code in AbstractTarget:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;public function set level(value:int):void&lt;br /&gt;{&lt;br /&gt; // A change of level may impact&lt;br /&gt; // the target level for Log.&lt;br /&gt; Log.removeTarget(this);&lt;br /&gt; _level = value;&lt;br /&gt; &lt;strong style="color: rgb(204, 0, 0);"&gt;Log.addTarget(this);&lt;/strong&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This highlighted line is the culprit. The contents of the addTarget method set up logging restrictions based on the value of the filters array. This has two consequences. Firstly, if you follow &lt;a target="_blank" href="http://livedocs.adobe.com/flex/3/html/help.html?content=logging_09.html"&gt;Adobe's guidelines&lt;/a&gt; you'll end up running through the addTarget code twice, once when you set the level, and once when you actually call Log.addTarget yourself - not&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;span style="font-style: italic;"&gt;awful, &lt;/span&gt;but not great either - lots of loops, which gets bad when you've got a lot of Loggers.&lt;br /&gt;&lt;br /&gt;The other consequence was the cause of my pain...&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;2. You have to set your filters before you set your level&lt;/h4&gt;&lt;br /&gt;Yep. That's right, the following code is bad:&lt;br /&gt;&lt;pre class="code"&gt;//BAD CODE, DON'T USE&lt;br /&gt;var target : TraceTarget = new TraceTarget();&lt;br /&gt;target.level = level; //This should not come first.&lt;br /&gt;target.filters = filters; //This is pretty much ignored&lt;/pre&gt;&lt;br /&gt;Here's why:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The default value of target.filters is ["*"], which will means the target listens to log messages from every logger.&lt;/li&gt;&lt;li&gt;When you set target.level, Log.addTarget is called, and all the filter magic happens. Except that you haven't set the filters yet. So it uses the default value ["*"], and your filter listens to everything. This was what was happening in our code.&lt;/li&gt;&lt;/ol&gt;So, the correct code should be: &lt;pre class="code"&gt;var target : TraceTarget = new TraceTarget();&lt;br /&gt;target.filters = [com.mydomain.myproject.MyClass,mx.rpc.*]; //Set first&lt;br /&gt;target.level = level; // set second.&lt;/pre&gt;&lt;br /&gt;In this example, a TraceTarget is created which will only listen to Loggers that have a category that is equal to "com.mydomain.myproject.MyClass" or begins with "mx.rpc". It is not at all obvious, but you the above code will also start Logging, as setting target.level also calls Log.addTarget().&lt;br /&gt;&lt;br /&gt;The observant among you may have noticed that if Adobe improve the behaviour of setting target.level in the future, you may find that your logging stops because addTarget never gets called. If you're worried about that, you can do the following: &lt;pre class="code"&gt;var target : TraceTarget = new TraceTarget();&lt;br /&gt;target.filters = [com.mydomain.myproject.MyClass,mx.rpc.*];&lt;br /&gt;Log.addTarget(target); //honours the filters&lt;br /&gt;// setting target.level will&lt;br /&gt;// remove the target, then add it again.&lt;br /&gt;target.level = level;&lt;br /&gt;&lt;/pre&gt;Still inefficient, but at least it is future proof. I hope that helps somebody, somewhere...</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/4486155233613511714/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/08/logging-in-flexair-two-strange-things.html#comment-form" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/4486155233613511714?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/4486155233613511714?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/08/logging-in-flexair-two-strange-things.html" title="Logging in Flex/Air: Filters behaving badly..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>10</thr:total></entry><entry gd:etag="W/&quot;D0YDRHk-fyp7ImA9WxRWEk8.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-2149873725929147554</id><published>2008-07-25T11:17:00.008+01:00</published><updated>2008-10-28T20:19:35.757Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-28T20:19:35.757Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Search" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>Ballmer gets that search thing wrong...</title><content type="html">Microsoft are rather obviously obsessed with getting their search revenues up. That's no surprise - pretty much everyone knows about their [twice] failed Yahoo bid. Then there is their &lt;a target="_blank" href="http://search.live.com/cashback"&gt;cashback &lt;/a&gt;offer, and now the announcement of a plan to &lt;a target="_blank" href="http://www.nytimes.com/2008/07/25/business/media/25adco.html?ref=media"&gt;provide search facilities&lt;/a&gt; (and therefore advertising revenue) on Facebook. It makes sense. Search is big business.&lt;br /&gt;&lt;br /&gt;It seems, however, that Steve Ballmer has forgotten why people actually use search engines. Apparently he thinks that:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"advertisers don’t want to sell on Live Search unless there’s more people  using the site, and people don’t want to search on the site unless there are  more relevant ads."&lt;br /&gt;Source: &lt;a target="_blank" href="http://techland.blogs.fortune.cnn.com/2008/07/24/microsofts-circular-conundrum/"&gt;CNN&lt;/a&gt;&lt;br /&gt;&lt;/blockquote&gt;Oh dear.&lt;br /&gt;&lt;br /&gt;Surely Ballmer cannot believe that Google's near domination of the global search market was down to relevant ads? Can he? That would make him &lt;a target="_blank" href="http://www.youtube.com/watch?v=wvsboPUjrGc"&gt;slightly crazy&lt;/a&gt;...</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/2149873725929147554/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/07/ballmer-gets-that-search-thing-wrong.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2149873725929147554?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2149873725929147554?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/07/ballmer-gets-that-search-thing-wrong.html" title="Ballmer gets that search thing wrong..." /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkAFQHw7fyp7ImA9WxdaGUg.&quot;"><id>tag:blogger.com,1999:blog-2408001626957860443.post-2603250884992493278</id><published>2008-07-15T13:00:00.009+01:00</published><updated>2008-08-28T21:18:31.207+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-28T21:18:31.207+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="AdobeAIR" /><title>OutOfMemoryError while using mxmlc and ant</title><content type="html">My first blog post. Very practical too...&lt;br /&gt;&lt;br /&gt;Basically, I'm working on a fancy Adobe AIR app right now. As part of that, we are implementing an automated build process using CruiseControl and such. I'm using &lt;a href="http://ant.apache.org/"&gt;ant&lt;/a&gt;, and the &lt;a href="http://labs.adobe.com/wiki/index.php/Flex_Ant_Tasks"&gt;flexTasks&lt;/a&gt; provided by Adobe. All was going pretty well, until this happened:&lt;br /&gt;&lt;pre class="code"&gt;[mxmlc] Loading configuration file C:\Program Files\Adobe\Flex3SDK\frameworks\air-config.xml&lt;br /&gt;[mxmlc] Error: null&lt;br /&gt;[mxmlc]&lt;br /&gt;[mxmlc] java.lang.OutOfMemoryError&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;After a bit of googling, there was no &lt;span style="font-style: italic;"&gt;obvious&lt;/span&gt; solution. I did see mentions of setting the ANT_OPTS environment variable. So this is what I did (I'm running Windows Server 2003 btw...):&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Hit Windows-Break to open the "System Properties" dialog.&lt;/li&gt;&lt;li&gt;Go to the advanced tab.&lt;/li&gt;&lt;li&gt;Click "environment variables"&lt;/li&gt;&lt;li&gt;In the System variables section, click New.&lt;/li&gt;&lt;li&gt;Enter the variable name as &lt;span style="font-family:courier new;"&gt;ANT_OPTS&lt;/span&gt;, and the value as &lt;span style="font-family:courier new;"&gt;-Xmx512m&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Click "OK".&lt;/li&gt;&lt;/ol&gt;If you were using a command prompt, you'll need to close it down and re-open it to use the new settings. Try running your ant script again, and your error should be gone.&lt;br /&gt;&lt;br /&gt;You can find a much nicer visualisation of that process &lt;a href="http://wiki.liferay.com/index.php/Ant_opts"&gt;here&lt;/a&gt;. If you are on a UNIX box, then you'll need to:&lt;br /&gt;&lt;pre class="code"&gt;set ANT_OPTS=-Xmx512M; export ANT_OPTS&lt;/pre&gt;from the shell.&lt;br /&gt;&lt;br /&gt;If you want to know more, you should read about the &lt;a href="http://www.devx.com/tips/Tip/5578"&gt;Java virtual machine's memory tuning options&lt;/a&gt;. I couldn't find any documentation about the &lt;span style="font-family: courier new;"&gt;ANT_OPTS&lt;/span&gt; environment variable.</content><link rel="replies" type="application/atom+xml" href="http://blog.adamcreeger.com/feeds/2603250884992493278/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.adamcreeger.com/2008/07/outofmemoryerror-while-using-mxmlc-and.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2603250884992493278?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2408001626957860443/posts/default/2603250884992493278?v=2" /><link rel="alternate" type="text/html" href="http://blog.adamcreeger.com/2008/07/outofmemoryerror-while-using-mxmlc-and.html" title="OutOfMemoryError while using mxmlc and ant" /><author><name>Adam Creeger</name><uri>https://plus.google.com/114130515915720124432</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-XEUtayxm4yk/AAAAAAAAAAI/AAAAAAAAUHo/xyRhXS_hcG4/s512-c/photo.jpg" /></author><thr:total>3</thr:total></entry></feed>
