<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Brandon Sterne</title>
	<atom:link href="http://brandon.sternefamily.net/posts/feed/" rel="self" type="application/rss+xml" />
	<link>http://brandon.sternefamily.net/posts</link>
	<description>The Whole Brevity Thing</description>
	<lastBuildDate>Mon, 14 Mar 2011 22:52:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Moving to GitHub</title>
		<link>http://brandon.sternefamily.net/posts/2011/03/moving-to-github/</link>
		<comments>http://brandon.sternefamily.net/posts/2011/03/moving-to-github/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 21:24:35 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=483</guid>
		<description><![CDATA[GitHub is an amazing tool which holds a lot of promise for pushing open source software development forward. I say that because they make the process of forking someone else&#8217;s repository and then merging your changes (with their permission, of course) back into the master repo as simple as a few mouse clicks. I, for [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/">GitHub</a> is an amazing tool which holds a lot of promise for pushing open source software development forward.  I say that because they make the process of <a href="http://help.github.com/fork-a-repo/">forking</a> someone else&#8217;s repository and then <a href="http://help.github.com/pull-requests/">merging</a> your changes (with their permission, of course) back into the master repo as simple as a few mouse clicks.  I, for example, contributed a <a href="https://github.com/bsterne/jquery/commit/064060326c38b5f8593f97087c0ab65f098ace03">patch</a> that made jQuery <a href="https://developer.mozilla.org/en/Introducing_Content_Security_Policy">CSP</a>-compatible which was later pulled into the jQuery trunk.</p>
<p>Since GitHub has become the industry standard for sharing code, I&#8217;ve started the process of moving all of my open source tools to a <a href="https://github.com/bsterne/bsterne-tools">repository there</a>.  So far, I have only moved my <a href="http://brandon.sternefamily.net/posts/2007/12/python-cidr-block-converter/">Python CIDR block converter</a>, but the rest should follow soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2011/03/moving-to-github/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Update to CSP Bookmarklet</title>
		<link>http://brandon.sternefamily.net/posts/2011/01/update-to-csp-bookmarklet/</link>
		<comments>http://brandon.sternefamily.net/posts/2011/01/update-to-csp-bookmarklet/#comments</comments>
		<pubDate>Thu, 20 Jan 2011 16:43:10 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=434</guid>
		<description><![CDATA[It was pointed out to me that my CSP bookmarklet was using a feature added in ECMAScript 5, Object.keys, and thus did not work in older browsers. I added a bit of code to address this: Object.keys = Object.keys &#124;&#124; function(obj) { var keys = []; for (var key in obj) { if (obj.hasOwnProperty(key)) keys.push(key); [...]]]></description>
			<content:encoded><![CDATA[<p>It was pointed out to me that my <a href="/posts/2010/10/content-security-policy-recommendation-bookmarklet/">CSP bookmarklet</a> was using a feature added in ECMAScript 5, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys">Object.keys</a>, and thus did not work in older browsers.  I added a bit of code to address this:</p>
<pre class="brush: javascript; gutter: false">
Object.keys = Object.keys || function(obj) {
  var keys = [];
  for (var key in obj) {
    if (obj.hasOwnProperty(key))
      keys.push(key);
  }
  return keys;
}</pre>
<p>Browsers that don&#8217;t natively support <code>Object.keys</code> will now have that functionality added when the bookmarklet runs.  Go ahead, give it a try: <a href="javascript:function%20getElements%28tags%29%7Bvar%20arr%3D%5B%5D%3Btags%3Dtags.split%28%22%2C%22%29%3Bfor%28var%20i%3D0%3Bi%3Ctags.length%3Bi%2B%2B%29%7Bvar%20elems%3Ddocument.getElementsByTagName%28tags%5Bi%5D%29%3Bfor%28var%20j%3D0%3Bj%3Celems.length%3Bj%2B%2B%29arr.push%28elems%5Bj%5D%29%7D%0Areturn%20arr%3B%7D%0Afunction%20parseUri%28str%29%7Bvar%20o%3DparseUri.options%2Cm%3Do.parser%5Bo.strictMode%3F%22strict%22%3A%22loose%22%5D.exec%28str%29%2Curi%3D%7B%7D%2Ci%3D14%3Bwhile%28i--%29uri%5Bo.key%5Bi%5D%5D%3Dm%5Bi%5D%7C%7C%22%22%3Buri%5Bo.q.name%5D%3D%7B%7D%3Buri%5Bo.key%5B12%5D%5D.replace%28o.q.parser%2Cfunction%28%240%2C%241%2C%242%29%7Bif%28%241%29uri%5Bo.q.name%5D%5B%241%5D%3D%242%3B%7D%29%3Breturn%20uri%3B%7D%3BparseUri.options%3D%7BstrictMode%3Afalse%2Ckey%3A%5B%22source%22%2C%22protocol%22%2C%22authority%22%2C%22userInfo%22%2C%22user%22%2C%22password%22%2C%22host%22%2C%22port%22%2C%22relative%22%2C%22path%22%2C%22directory%22%2C%22file%22%2C%22query%22%2C%22anchor%22%5D%2Cq%3A%7Bname%3A%22queryKey%22%2Cparser%3A/%28%3F%3A%5E%7C%26%29%28%5B%5E%26%3D%5D%2A%29%3D%3F%28%5B%5E%26%5D%2A%29/g%7D%2Cparser%3A%7Bstrict%3A/%5E%28%3F%3A%28%5B%5E%3A%5C/%3F%23%5D%2B%29%3A%29%3F%28%3F%3A%5C/%5C/%28%28%3F%3A%28%28%5B%5E%3A%40%5D%2A%29%28%3F%3A%3A%28%5B%5E%3A%40%5D%2A%29%29%3F%29%3F%40%29%3F%28%5B%5E%3A%5C/%3F%23%5D%2A%29%28%3F%3A%3A%28%5Cd%2A%29%29%3F%29%29%3F%28%28%28%28%3F%3A%5B%5E%3F%23%5C/%5D%2A%5C/%29%2A%29%28%5B%5E%3F%23%5D%2A%29%29%28%3F%3A%5C%3F%28%5B%5E%23%5D%2A%29%29%3F%28%3F%3A%23%28.%2A%29%29%3F%29/%2Cloose%3A/%5E%28%3F%3A%28%3F%21%5B%5E%3A%40%5D%2B%3A%5B%5E%3A%40%5C/%5D%2A%40%29%28%5B%5E%3A%5C/%3F%23.%5D%2B%29%3A%29%3F%28%3F%3A%5C/%5C/%29%3F%28%28%3F%3A%28%28%5B%5E%3A%40%5D%2A%29%28%3F%3A%3A%28%5B%5E%3A%40%5D%2A%29%29%3F%29%3F%40%29%3F%28%5B%5E%3A%5C/%3F%23%5D%2A%29%28%3F%3A%3A%28%5Cd%2A%29%29%3F%29%28%28%28%5C/%28%3F%3A%5B%5E%3F%23%5D%28%3F%21%5B%5E%3F%23%5C/%5D%2A%5C.%5B%5E%3F%23%5C/.%5D%2B%28%3F%3A%5B%3F%23%5D%7C%24%29%29%29%2A%5C/%3F%29%3F%28%5B%5E%3F%23%5C/%5D%2A%29%29%28%3F%3A%5C%3F%28%5B%5E%23%5D%2A%29%29%3F%28%3F%3A%23%28.%2A%29%29%3F%29/%7D%7D%3Bvar%20sources%3D%7B%27images%27%3A%7B%7D%2C%27media%27%3A%7B%7D%2C%27script%27%3A%7B%7D%2C%27object%27%3A%7B%7D%2C%27frame%27%3A%7B%7D%2C%27font%27%3A%7B%7D%2C%27style%27%3A%7B%7D%7D%3Bvar%20directives%3D%7B%27images%27%3A%27img-src%27%2C%27media%27%3A%27media-src%27%2C%27script%27%3A%27script-src%27%2C%27object%27%3A%27object-src%27%2C%27frame%27%3A%27frame-src%27%2C%27font%27%3A%27font-src%27%2C%27style%27%3A%27style-src%27%7D%3Bvar%20violations%3D%5B%5D%3Bfunction%20capWord%28w%29%7Breturn%20w.charAt%280%29.toUpperCase%28%29%2Bw.slice%281%29%3B%7D%0Afunction%20objIsEmpty%28obj%29%7Bfor%28var%20prop%20in%20obj%29%7Bif%28obj.hasOwnProperty%28prop%29%29%0Areturn%20false%3B%7D%0Areturn%20true%3B%7D%0Afunction%20generatePolicyFromSources%28sourceList%2Cviolations%29%7Bvar%20policy%3D%22Recommended%20Policy%3A%5Cn%22%3Bpolicy%2B%3D%22allow%20%27self%27%3B%22%3Bfor%28type%20in%20sourceList%29%7Bif%28objIsEmpty%28sourceList%5Btype%5D%29%29%0Acontinue%3Bpolicy%2B%3D%22%20%22%2Bdirectives%5Btype%5D%2B%22%20%22%2B%0AObject.keys%28sourceList%5Btype%5D%29.join%28%22%20%22%29%2B%22%3B%22%3B%7D%0Aif%28violations.length%29%7Bpolicy%2B%3D%22%5Cn%5Cn%22%3Bpolicy%2B%3D%28violations.length%3D%3D1%29%3F%22Inline%20Script%20Violation%3A%22%3A%22Inline%20Script%20Violations%3A%22%3Bfor%28var%20v%3D0%3Bv%3Cviolations.length%3Bv%2B%2B%29%0Apolicy%2B%3D%22%5Cn%22%2B%28v%2B1%29%2B%22%3A%20%22%2Bviolations%5Bv%5D%3B%7D%0Areturn%20policy%3B%7D%0AObject.keys%3DObject.keys%7C%7Cfunction%28obj%29%7Bvar%20keys%3D%5B%5D%3Bfor%28var%20key%20in%20obj%29%7Bif%28obj.hasOwnProperty%28key%29%29%0Akeys.push%28key%29%3B%7D%0Areturn%20keys%3B%7D%0Afunction%20analyzeContent%28%29%7Bvar%20myHost%3DparseUri%28window.location.href%29.host%3Bvar%20images%3DgetElements%28%22img%22%29%3Bfor%28var%20i%3D0%3Bi%3Cimages.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28images%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.images%29%29%0Asources.images%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.images%29%29%0Asources.images%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20linkElems%3DgetElements%28%22link%22%29%3Bfor%28var%20i%3D0%3Bi%3ClinkElems.length%3Bi%2B%2B%29%7Bif%28linkElems%5Bi%5D.getAttribute%28%22rel%22%29%3D%3D%22shortcut%20icon%22%29%7Bvar%20uriParts%3DparseUri%28linkElems%5Bi%5D.href%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.images%29%29%0Asources.images%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.images%29%29%0Asources.images%5Bhost%5D%3Dnull%3B%7D%7D%7D%0Avar%20media%3DgetElements%28%22video%2Caudio%22%29%3Bfor%28var%20i%3D0%3Bi%3Cmedia.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28media%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.media%29%29%0Asources.media%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.media%29%29%0Asources.media%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20scripts%3DgetElements%28%22script%22%29%3Bfor%28var%20i%3D0%3Bi%3Cscripts.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28scripts%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.script%29%29%0Asources.script%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.script%29%29%0Asources.script%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20objAppl%3DgetElements%28%22object%2Capplet%22%29%3Bfor%28var%20i%3D0%3Bi%3CobjAppl.length%3Bi%2B%2B%29%7Bif%28objAppl%5Bi%5D.hasAttribute%28%22codebase%22%29%29%7Bvar%20uriParts%3DparseUri%28objAppl%5Bi%5D.getAttribute%28%22codebase%22%29%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%0Aif%28objAppl%5Bi%5D.hasAttribute%28%22classid%22%29%29%7Bvar%20uriParts%3DparseUri%28objAppl%5Bi%5D.getAttribute%28%22classid%22%29%29%3Bif%28%5B%22http%22%2C%22https%22%2C%22ftp%22%2Cnull%5D.indexOf%28uriParts%5B%22protocol%22%5D%29%21%3D-1%29%7Bvar%20host%3DuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%7D%0Aif%28objAppl%5Bi%5D.hasAttribute%28%22data%22%29%29%7Bvar%20uriParts%3DparseUri%28objAppl%5Bi%5D.getAttribute%28%22data%22%29%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%0Aif%28objAppl%5Bi%5D.hasAttribute%28%22archive%22%29%29%7Bvar%20uriParts%3DparseUri%28objAppl%5Bi%5D.getAttribute%28%22archive%22%29%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%7D%0Avar%20embeds%3DgetElements%28%22embed%22%29%3Bfor%28var%20i%3D0%3Bi%3Cembeds.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28embeds%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20frameElems%3DgetElements%28%22frame%2Ciframe%22%29%3Bfor%28var%20i%3D0%3Bi%3CframeElems.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28frameElems%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.frame%29%29%0Asources.frame%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.frame%29%29%0Asources.frame%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20stylesheets%3D%7B%7D%3Btry%7Bvar%20stylesheets%3Ddocument.styleSheets%3B%7D%0Acatch%28e%29%7B%7D%0Afor%28var%20i%3D0%3Bi%3Cstylesheets.length%3Bi%2B%2B%29%7Bvar%20rules%3D%7B%7D%3Btry%7Brules%3Dstylesheets%5Bi%5D.cssRules%3B%7D%0Acatch%28e%29%7Bcontinue%3B%7D%0Aif%28%21rules%29%7Bcontinue%3B%7D%0Afor%28var%20j%3D0%3Bj%3Crules.length%3Bj%2B%2B%29%7Bif%28rules%5Bj%5D.type%3D%3Drules%5Bj%5D.FONT_FACE_RULE%29%7Bvar%20src%3Drules%5Bj%5D.style.getPropertyValue%28%22src%22%29%3Bif%28src%29%7Bvar%20url%3Dsrc.replace%28/%5Eurl%5B%27%22%5D%2A/%2C%22%22%29.replace%28/%5B%27%22%5D%2A%5C%29%24/%2C%22%22%29%3Bvar%20uriParts%3DparseUri%28url%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.font%29%29%0Asources.font%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.font%29%29%0Asources.font%5Bhost%5D%3Dnull%3B%7D%7D%7D%7D%7D%0Avar%20linkElems%3DgetElements%28%22link%22%29%3Bfor%28var%20i%3D0%3Bi%3ClinkElems.length%3Bi%2B%2B%29%7Bif%28linkElems%5Bi%5D.getAttribute%28%22rel%22%29%3D%3D%22stylesheet%22%29%7Bvar%20uriParts%3DparseUri%28linkElems%5Bi%5D.href%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.style%29%29%0Asources.style%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.style%29%29%0Asources.style%5Bhost%5D%3Dnull%3B%7D%7D%7D%0Avar%20allElems%3DgetElements%28%22%2A%22%29%3Bfor%28var%20e%3D0%3Be%3CallElems.length%3Be%2B%2B%29%7Bvar%20elem%3DallElems%5Be%5D%3Bvar%20attrs%3D%5B%5D%3Bfor%28var%20key%20in%20elem.attributes%29%7Bif%28%21isNaN%28key%29%29%7Battrs.push%28elem.attributes%5Bkey%5D.name%29%3B%7D%7D%0Afor%28var%20i%3D0%3Bi%3Cattrs.length%3Bi%2B%2B%29%7Bif%28attrs%5Bi%5D.match%28/%5Eon/%29%29%7Bvar%20attr_pairs%3D%5B%5D%0Afor%28var%20j%3D0%3Bj%3Cattrs.length%3Bj%2B%2B%29%7Bvar%20attr_val%3Delem.attributes%5Battrs%5Bj%5D%5D.nodeValue.replace%28/%5Cs%2B/g%2C%22%20%22%29%3Battr_pairs.push%28attrs%5Bj%5D%2B%27%3D%22%27%2Battr_val%2B%27%22%27%29%3B%7D%0Avar%20error%3Dattrs%5Bi%5D%2B%22%20on%20element%20%3C%22%2Belem.nodeName%2B%22%20%22%2B%0Aattr_pairs.join%28%22%20%22%29%2B%22%3E%22%3Bviolations.push%28%22event%20handling%20attribute%3A%20%22%2Berror%29%3B%7D%7D%0Aif%28elem.nodeName%3D%3D%3D%22SCRIPT%22%26%26elem.text.length%29%7Bvar%20script%3D%28elem.text.length%3E100%29%3Felem.text.substr%280%2C100%29%2B%22%20...%20%22%3Aelem.text%3Bviolations.push%28%22internal%20script%20node%3A%20%22%2Bscript%29%3B%7D%7D%0Aalert%28generatePolicyFromSources%28sources%2Cviolations%29%29%3B%7D%0AanalyzeContent%28%29%3B" class="bookmarklet">Recommend CSP</a></p>
<p>As before, the <a href="https://github.com/bsterne/bsterne-tools/blob/master/csp-bookmarklet/csp-bookmarklet.js">full source</a> is posted for you to browse as well.</p>
<p><script type="text/javascript" src="/posts/syntax/src/shCore.js"></script><br />
<script type="text/javascript" src="/posts/syntax/scripts/shBrushJScript.js"></script></p>
<link rel="stylesheet" type="text/css" href="/posts/syntax/styles/shCore.css" />
<link type="text/css" rel="Stylesheet" href="/posts/syntax/styles/shThemeDefault.css"/>
<script type="text/javascript">SyntaxHighlighter.all()</script></p>
<style type="text/css">
a.bookmarklet {
  text-decoration: none;
  display: inline-block;
  border: 1px solid #bbb;
  padding: .25em .5em;
  margin: .5em;
  -moz-border-radius: .5em;
  -webkit-border-radius: .5em;
}
</style>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2011/01/update-to-csp-bookmarklet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Content Security Policy Recommendation Bookmarklet</title>
		<link>http://brandon.sternefamily.net/posts/2010/10/content-security-policy-recommendation-bookmarklet/</link>
		<comments>http://brandon.sternefamily.net/posts/2010/10/content-security-policy-recommendation-bookmarklet/#comments</comments>
		<pubDate>Thu, 14 Oct 2010 23:02:51 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=414</guid>
		<description><![CDATA[I wrote a bookmarklet that analyzes the content on the current page and recommends a Content Security Policy based on the types of content it finds on the page and the sources of that content. The implementation also takes into account resources that are dynamically added to the page by JavaScript. For instance, today I [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote a bookmarklet that analyzes the content on the current page and recommends a Content Security Policy based on the types of content it finds on the page and the sources of that content.  The implementation also takes into account resources that are dynamically added to the page by JavaScript.</p>
<p style="margin:1em">For instance, today I learned that ReCAPTCHA loads script both from api.recaptcha.net, but also from www.google.com.  <em>Note to self: figure out why Google needs to know about every ReCAPTCHA load.</em></p>
<p>You can test it out by clicking the following bookmarklet: <a href="javascript:function%20getElements%28tags%29%7Bvar%20arr%3D%5B%5D%3Btags%3Dtags.split%28%22%2C%22%29%3Bfor%28var%20i%3D0%3Bi%3Ctags.length%3Bi%2B%2B%29%7Bvar%20elems%3Ddocument.getElementsByTagName%28tags%5Bi%5D%29%3Bfor%28var%20j%3D0%3Bj%3Celems.length%3Bj%2B%2B%29arr.push%28elems%5Bj%5D%29%7D%0Areturn%20arr%3B%7D%0Afunction%20parseUri%28str%29%7Bvar%20o%3DparseUri.options%2Cm%3Do.parser%5Bo.strictMode%3F%22strict%22%3A%22loose%22%5D.exec%28str%29%2Curi%3D%7B%7D%2Ci%3D14%3Bwhile%28i--%29uri%5Bo.key%5Bi%5D%5D%3Dm%5Bi%5D%7C%7C%22%22%3Buri%5Bo.q.name%5D%3D%7B%7D%3Buri%5Bo.key%5B12%5D%5D.replace%28o.q.parser%2Cfunction%28%240%2C%241%2C%242%29%7Bif%28%241%29uri%5Bo.q.name%5D%5B%241%5D%3D%242%3B%7D%29%3Breturn%20uri%3B%7D%3BparseUri.options%3D%7BstrictMode%3Afalse%2Ckey%3A%5B%22source%22%2C%22protocol%22%2C%22authority%22%2C%22userInfo%22%2C%22user%22%2C%22password%22%2C%22host%22%2C%22port%22%2C%22relative%22%2C%22path%22%2C%22directory%22%2C%22file%22%2C%22query%22%2C%22anchor%22%5D%2Cq%3A%7Bname%3A%22queryKey%22%2Cparser%3A/%28%3F%3A%5E%7C%26%29%28%5B%5E%26%3D%5D%2A%29%3D%3F%28%5B%5E%26%5D%2A%29/g%7D%2Cparser%3A%7Bstrict%3A/%5E%28%3F%3A%28%5B%5E%3A%5C/%3F%23%5D%2B%29%3A%29%3F%28%3F%3A%5C/%5C/%28%28%3F%3A%28%28%5B%5E%3A%40%5D%2A%29%28%3F%3A%3A%28%5B%5E%3A%40%5D%2A%29%29%3F%29%3F%40%29%3F%28%5B%5E%3A%5C/%3F%23%5D%2A%29%28%3F%3A%3A%28%5Cd%2A%29%29%3F%29%29%3F%28%28%28%28%3F%3A%5B%5E%3F%23%5C/%5D%2A%5C/%29%2A%29%28%5B%5E%3F%23%5D%2A%29%29%28%3F%3A%5C%3F%28%5B%5E%23%5D%2A%29%29%3F%28%3F%3A%23%28.%2A%29%29%3F%29/%2Cloose%3A/%5E%28%3F%3A%28%3F%21%5B%5E%3A%40%5D%2B%3A%5B%5E%3A%40%5C/%5D%2A%40%29%28%5B%5E%3A%5C/%3F%23.%5D%2B%29%3A%29%3F%28%3F%3A%5C/%5C/%29%3F%28%28%3F%3A%28%28%5B%5E%3A%40%5D%2A%29%28%3F%3A%3A%28%5B%5E%3A%40%5D%2A%29%29%3F%29%3F%40%29%3F%28%5B%5E%3A%5C/%3F%23%5D%2A%29%28%3F%3A%3A%28%5Cd%2A%29%29%3F%29%28%28%28%5C/%28%3F%3A%5B%5E%3F%23%5D%28%3F%21%5B%5E%3F%23%5C/%5D%2A%5C.%5B%5E%3F%23%5C/.%5D%2B%28%3F%3A%5B%3F%23%5D%7C%24%29%29%29%2A%5C/%3F%29%3F%28%5B%5E%3F%23%5C/%5D%2A%29%29%28%3F%3A%5C%3F%28%5B%5E%23%5D%2A%29%29%3F%28%3F%3A%23%28.%2A%29%29%3F%29/%7D%7D%3Bvar%20sources%3D%7B%27images%27%3A%7B%7D%2C%27media%27%3A%7B%7D%2C%27script%27%3A%7B%7D%2C%27object%27%3A%7B%7D%2C%27frame%27%3A%7B%7D%2C%27font%27%3A%7B%7D%2C%27style%27%3A%7B%7D%7D%3Bvar%20directives%3D%7B%27images%27%3A%27img-src%27%2C%27media%27%3A%27media-src%27%2C%27script%27%3A%27script-src%27%2C%27object%27%3A%27object-src%27%2C%27frame%27%3A%27frame-src%27%2C%27font%27%3A%27font-src%27%2C%27style%27%3A%27style-src%27%7D%3Bfunction%20capWord%28w%29%7Breturn%20w.charAt%280%29.toUpperCase%28%29%2Bw.slice%281%29%3B%7D%0Afunction%20objIsEmpty%28obj%29%7Bfor%28var%20prop%20in%20obj%29%7Bif%28obj.hasOwnProperty%28prop%29%29%0Areturn%20false%3B%7D%0Areturn%20true%3B%7D%0Afunction%20generatePolicyFromSources%28sourceList%29%7Bvar%20policy%3D%22allow%20%27self%27%3B%22%3Bfor%28type%20in%20sourceList%29%7Bif%28objIsEmpty%28sourceList%5Btype%5D%29%29%0Acontinue%3Bpolicy%2B%3D%22%20%22%2Bdirectives%5Btype%5D%2B%22%20%22%2B%0AObject.keys%28sourceList%5Btype%5D%29.join%28%22%20%22%29%2B%22%3B%22%3B%7D%0Areturn%20policy%3B%7D%0AObject.keys%3DObject.keys%7C%7Cfunction%28obj%29%7Bvar%20keys%3D%5B%5D%3Bfor%28var%20key%20in%20obj%29%7Bif%28obj.hasOwnProperty%28key%29%29%0Akeys.push%28key%29%3B%7D%0Areturn%20keys%3B%7D%0Afunction%20analyzeContent%28%29%7Bvar%20myHost%3DparseUri%28location.href%29.host%3Bvar%20images%3DgetElements%28%22img%22%29%3Bfor%28var%20i%3D0%3Bi%3Cimages.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28images%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.images%29%29%0Asources.images%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.images%29%29%0Asources.images%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20linkElems%3DgetElements%28%22link%22%29%3Bfor%28var%20i%3D0%3Bi%3ClinkElems.length%3Bi%2B%2B%29%7Bif%28linkElems%5Bi%5D.getAttribute%28%22rel%22%29%3D%3D%22shortcut%20icon%22%29%7Bvar%20uriParts%3DparseUri%28linkElems%5Bi%5D.href%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.images%29%29%0Asources.images%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.images%29%29%0Asources.images%5Bhost%5D%3Dnull%3B%7D%7D%7D%0Avar%20media%3DgetElements%28%22video%2Caudio%22%29%3Bfor%28var%20i%3D0%3Bi%3Cmedia.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28media%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.media%29%29%0Asources.media%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.media%29%29%0Asources.media%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20scripts%3DgetElements%28%22script%22%29%3Bfor%28var%20i%3D0%3Bi%3Cscripts.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28scripts%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.script%29%29%0Asources.script%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.script%29%29%0Asources.script%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20objAppl%3DgetElements%28%22object%2Capplet%22%29%3Bfor%28var%20i%3D0%3Bi%3CobjAppl.length%3Bi%2B%2B%29%7Bif%28objAppl%5Bi%5D.hasAttribute%28%22codebase%22%29%29%7Bvar%20uriParts%3DparseUri%28objAppl%5Bi%5D.getAttribute%28%22codebase%22%29%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%0Aif%28objAppl%5Bi%5D.hasAttribute%28%22classid%22%29%29%7Bvar%20uriParts%3DparseUri%28objAppl%5Bi%5D.getAttribute%28%22classid%22%29%29%3Bif%28%5B%22http%22%2C%22https%22%2C%22ftp%22%2Cnull%5D.indexOf%28uriParts%5B%22protocol%22%5D%29%21%3D-1%29%7Bvar%20host%3DuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%7D%0Aif%28objAppl%5Bi%5D.hasAttribute%28%22data%22%29%29%7Bvar%20uriParts%3DparseUri%28objAppl%5Bi%5D.getAttribute%28%22data%22%29%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%0Aif%28objAppl%5Bi%5D.hasAttribute%28%22archive%22%29%29%7Bvar%20uriParts%3DparseUri%28objAppl%5Bi%5D.getAttribute%28%22archive%22%29%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%7D%0Avar%20embeds%3DgetElements%28%22embed%22%29%3Bfor%28var%20i%3D0%3Bi%3Cembeds.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28embeds%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.object%29%29%0Asources.object%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20frameElems%3DgetElements%28%22frame%2Ciframe%22%29%3Bfor%28var%20i%3D0%3Bi%3CframeElems.length%3Bi%2B%2B%29%7Bvar%20uriParts%3DparseUri%28frameElems%5Bi%5D.src%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.frame%29%29%0Asources.frame%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.frame%29%29%0Asources.frame%5Bhost%5D%3Dnull%3B%7D%7D%0Avar%20stylesheets%3D%7B%7D%3Btry%7Bvar%20stylesheets%3Ddocument.styleSheets%3B%7D%0Acatch%28e%29%7B%7D%0Afor%28var%20i%3D0%3Bi%3Cstylesheets.length%3Bi%2B%2B%29%7Bvar%20rules%3D%7B%7D%3Btry%7Brules%3Dstylesheets%5Bi%5D.cssRules%3B%7D%0Acatch%28e%29%7Bcontinue%3B%7D%0Aif%28%21rules%29%7Bcontinue%3B%7D%0Afor%28var%20j%3D0%3Bj%3Crules.length%3Bj%2B%2B%29%7Bif%28rules%5Bj%5D.type%3D%3Drules%5Bj%5D.FONT_FACE_RULE%29%7Bvar%20src%3Drules%5Bj%5D.style.getPropertyValue%28%22src%22%29%3Bif%28src%29%7Bvar%20url%3Dsrc.replace%28/%5Eurl%5B%27%22%5D%2A/%2C%22%22%29.replace%28/%5B%27%22%5D%2A%5C%29%24/%2C%22%22%29%3Bvar%20uriParts%3DparseUri%28url%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.font%29%29%0Asources.font%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.font%29%29%0Asources.font%5Bhost%5D%3Dnull%3B%7D%7D%7D%7D%7D%0Avar%20linkElems%3DgetElements%28%22link%22%29%3Bfor%28var%20i%3D0%3Bi%3ClinkElems.length%3Bi%2B%2B%29%7Bif%28linkElems%5Bi%5D.getAttribute%28%22rel%22%29%3D%3D%22stylesheet%22%29%7Bvar%20uriParts%3DparseUri%28linkElems%5Bi%5D.href%29%3Bvar%20host%3D%28uriParts%5B%22protocol%22%5D%3D%3D%22data%22%29%3F%22data%3A%22%3AuriParts%5B%22host%22%5D%3Bif%28host%3D%3Dnull%29%7Bif%28%21%28host%20in%20sources.style%29%29%0Asources.style%5B%22%27self%27%22%5D%3Dnull%3B%7D%0Aelse%7Bif%28host%3D%3DmyHost%29%0Ahost%3D%22%27self%27%22%3Bif%28%21%28host%20in%20sources.style%29%29%0Asources.style%5Bhost%5D%3Dnull%3B%7D%7D%7D%0Aalert%28generatePolicyFromSources%28sources%29%29%3B%7D%0AanalyzeContent%28%29%3B" class="bookmarklet">Recommend CSP</a></p>
<p>If you find it useful, drag it to your <a href="http://support.mozilla.com/en-us/kb/bookmarks#Where_to_find_bookmarks">bookmarks toolbar</a> and you can use it from any web page.  Feel free to check out the <a href="https://github.com/bsterne/bsterne-tools/blob/master/csp-bookmarklet/csp-bookmarklet.js">bookmarklet source</a> as well.</p>
<p>In the future, I would like to add notifications for potential <a href="https://developer.mozilla.org/en/Security/CSP/Default_CSP_restrictions#Restricted_scripts">inline script violations</a>.</p>
<style type="text/css">
a.bookmarklet {
  text-decoration: none;
  display: inline-block;
  border: 1px solid #bbb;
  padding: .25em .5em;
  margin: .5em;
  -moz-border-radius: .5em;
  -webkit-border-radius: .5em;
}
</style>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2010/10/content-security-policy-recommendation-bookmarklet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Productivity music for work</title>
		<link>http://brandon.sternefamily.net/posts/2010/09/productivity-music-for-work/</link>
		<comments>http://brandon.sternefamily.net/posts/2010/09/productivity-music-for-work/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 19:09:32 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=404</guid>
		<description><![CDATA[There are times at work when I like to put on my headphones and play some music (usually instrumental) or white noise to avoid distraction while I write code or do some other task that requires concentration. I never thought to do both at the same time&#8230; until now! Next time you want a nice [...]]]></description>
			<content:encoded><![CDATA[<p>There are times at work when I like to put on my headphones and play some <a href="http://www.pandora.com">music</a> (usually instrumental) or <a href="http://simplynoise.com/">white noise</a> to avoid distraction while I write code or do some other task that requires concentration.  I never thought to do both at the same time&#8230; until now!</p>
<p>Next time you want a nice anti-distraction music cocoon try opening in separate tabs:</p>
<ol>
<li>A nice <a href="http://www.pandora.com/stations/9f7394cb50f726dbdcd93d3cacefaa6e9d65bae90eaced8a">Jazz Piano</a> or <a href="http://www.pandora.com/stations/51c0d4684795ba6f71128bd1e22b7606ee56ad17f84d5fe3">Classical</a> station</li>
<li>A pleasant <a href="http://www.rainymood.com/">rainfall soundtrack</a></li>
</ol>
<p>If you are still distracted after that Google has <a href="https://health.google.com/health/ref/Attention+deficit+hyperactivity+disorder+(ADHD)">some information</a> that might help you.</p>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2010/09/productivity-music-for-work/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jetpack: Unread Messages in Gmail App Tab</title>
		<link>http://brandon.sternefamily.net/posts/2010/08/jetpack-unread-gmail-favicon/</link>
		<comments>http://brandon.sternefamily.net/posts/2010/08/jetpack-unread-gmail-favicon/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 18:20:05 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=395</guid>
		<description><![CDATA[One of the new features in Firefox 4 is the App Tab which lets users persist a tab that they use continuously. Firefox shrinks the tab down to just the favicon and places it in a special area for these tabs which generally aren&#8217;t closed by the user. The feature is great, but one of [...]]]></description>
			<content:encoded><![CDATA[<p>One of the new features in <a href="http://www.mozilla.com/en-US/firefox/beta/">Firefox 4</a> is the <a href="http://blog.mozilla.com/faaborg/2010/07/28/app-tabs-in-firefox-4-beta-2/">App Tab</a> which lets users persist a tab that they use continuously.  Firefox shrinks the tab down to just the favicon and places it in a special area for these tabs which generally aren&#8217;t closed by the user.  The feature is great, but one of the side effects is that Gmail App Tabs don&#8217;t show anymore the part of the <code>&lt;title></code> that indicates unread messages.</p>
<p>That&#8217;s where my new <a href="https://jetpack.mozillalabs.com/">Jetpack</a> (a cool new, lightweight (and secure!) way to write <a href="https://addons.mozilla.org/">Add-ons</a>) comes in.</p>
<p>Go install <a href="https://addons.mozilla.org/en-US/firefox/addon/216008/">Unread Gmail Favicon</a> from AMO and the favicon for that tab will indicate the number of unread messages when you have them like so:</p>
<p class="center"><a href="https://addons.mozilla.org/en-US/firefox/addon/216008/"><img src="http://brandon.sternefamily.net/posts/wp-content/uploads/2010/08/app-tab-closeup.png" alt="" title="Gmail Unread Favicon" width="185" height="139" class="aligncenter size-full wp-image-394" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2010/08/jetpack-unread-gmail-favicon/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Hacked my DEF CON 18 badge</title>
		<link>http://brandon.sternefamily.net/posts/2010/07/hacked-my-def-con-18-badge/</link>
		<comments>http://brandon.sternefamily.net/posts/2010/07/hacked-my-def-con-18-badge/#comments</comments>
		<pubDate>Sat, 31 Jul 2010 00:11:40 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=366</guid>
		<description><![CDATA[I was only able willing to stay for part of the first day of DEF CON this year, but I&#8217;m glad I did. One of the things they&#8217;ve done for the last five years or so is put microcontrollers in the badges, and put in little Easter eggs for people to search for. This year&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I was only <del datetime="2010-07-30T23:36:03+00:00">able</del> willing to stay for part of the first day of <a href="http://www.defcon.org/html/defcon-18/dc-18-index.html">DEF CON</a> this year, but I&#8217;m glad I did.  One of the things they&#8217;ve done for the last five years or so is put microcontrollers in the badges, and put in little Easter eggs for people to search for.  This year&#8217;s had a Ninja Party mode which was locked by default, but you could unlock it by placing a series of 15 tumblers in the correct position.</p>
<p>They published the source code for the badges on the CD they gave out at registration (so perhaps I&#8217;m stupid for loading the CD on my laptop rather than smart for reverse engineering the badge).  I opened up DC18_Badge.c and, searching for &#8220;Ninja&#8221; (the code was commented nicely), quickly found the following two C functions:</p>
<pre class="brush: cpp; gutter: false">
/**************************************************************/
/* NINJA ROUTINES
/**************************************************************/

int dc18_ninja_validate(uint32_t val)
{
    uint16_t a, b;

    a = (uint16_t)(val &#038; 0xfff);
    b = (uint16_t)(val >> 12);

    if((a ^ b) == 0x916)
    {
        return 1;
    }
    return 0;
}

// encode tumbler states into 24-bit value
uint32_t dc18_encode_tumblers(tumbler_state_type *tumblers)
{
    uint32_t x = 0, j = 1;
    uint16_t i;

    for(i = 0; i < TUMBLERS_PER_IMAGE; i++)
    {
        x += tumblers[i] * j;
        j *= 3;
    }

    return x;
}
</pre>
<p>So the trick was to find the number that made <code>(a ^ b) == 0x916</code> and then figure out the tumbler positions to represent that number.  I wrote two small Python functions to automate those tasks.  To find the number that would unlock Ninja Mode, I wrote this loop.  I added a print statement to show how far into the search we were, thinking it might take some time to find it, but it popped out 6423 in no time at all:
<pre class="brush: python; gutter: false">while 1:
	a = i &#038; 0xfff
	b = i >> 12
	if i % 10000 == 0:
		print "# a: %d, b: %d, i: %d" % (a, b, i)
	if a ^ b == 0x916:
		print "DONE: %d" % (i)
		break
	i += 1

DONE: 6423
</pre>
<p>Now all that was left was to figure out the tumbler positions to represent 6423.  Clearly, <code>dc18_encode_tumblers</code> tells us how to do that.  I whipped up this little function to convert the tumbler positions to a decimal number:</p>
<pre class="brush: python; gutter: false">def enc_tumblers(tum):
	x = 0; j = 1;
	for i in range(15):
		x += tum[i] * j
		j *= 3
	return x

>>> enc_tumblers([1,1,1,1,1,2,2,2,0,0,0,0,0,0,0])
6439
</pre>
<p>I was going to write another loop to increment the tumbler array I was passing to <code>enc_tumblers</code>, but my first guess was so close that I just manually entered the settings until I found the winning configuration:</p>
<pre class="brush: python; gutter: false">>>> enc_tumblers([0,2,2,0,1,2,2,2,0,0,0,0,0,0,0])
6423
</pre>
<p>Once I had the configuration, I put the tumblers in the appropriate positions: 0 - up, 1 - middle, 2 - down.  After that, well, I guess I'm a ninja now:</p>
<p><a href="http://brandon.sternefamily.net/posts/wp-content/uploads/2010/07/def-con.jpg"><img src="http://brandon.sternefamily.net/posts/wp-content/uploads/2010/07/def-con.jpg" alt="" title="Ninja Party Unlocked" width="80%" class="aligncenter size-full wp-image-380" /></a><br />
<script type="text/javascript" src="/posts/syntax/src/shCore.js"></script><br />
<script type="text/javascript" src="/posts/syntax/scripts/shBrushCpp.js"></script><br />
<script type="text/javascript" src="/posts/syntax/scripts/shBrushPython.js"></script></p>
<link rel="stylesheet" type="text/css" href="/posts/syntax/styles/shCore.css" />
<link type="text/css" rel="Stylesheet" href="/posts/syntax/styles/shThemeDefault.css"/>
<script type="text/javascript">SyntaxHighlighter.all()</script></p>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2010/07/hacked-my-def-con-18-badge/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress CSP Plugin</title>
		<link>http://brandon.sternefamily.net/posts/2010/05/wordpress-csp-plugin/</link>
		<comments>http://brandon.sternefamily.net/posts/2010/05/wordpress-csp-plugin/#comments</comments>
		<pubDate>Fri, 28 May 2010 18:41:30 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Web Security]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=350</guid>
		<description><![CDATA[My implementation of the Content Security Policy server logic for WordPress is now available as a WordPress Plugin. Fig.1 &#8211; CSP configuration page making a policy recommendation. Fig. 2 &#8211; New panel in media uploader allows direct creation of script files in the uploads directory.]]></description>
			<content:encoded><![CDATA[<p>My implementation of the Content Security Policy server logic for WordPress is now available as a <a href="http://wordpress.org/extend/plugins/content-security-policy/">WordPress Plugin</a>.</p>
<p class="center"><a href="http://brandon.sternefamily.net/posts/wp-content/uploads/2010/05/screenshot-1.png"><img src="http://brandon.sternefamily.net/posts/wp-content/uploads/2010/05/screenshot-1-300x234.png" alt="" title="CSP Policy Recommendation" width="300" height="234" class="aligncenter size-medium wp-image-352 noborder" /></a></p>
<p class="small center">Fig.1 &#8211; CSP configuration page making a policy recommendation.</p>
<p class="center"><a href="http://brandon.sternefamily.net/posts/wp-content/uploads/2010/05/screenshot-2.png"><img src="http://brandon.sternefamily.net/posts/wp-content/uploads/2010/05/screenshot-2-300x234.png" alt="" title="New Script File via Editor" width="300" height="234" class="aligncenter size-medium wp-image-353 noborder" /></a></p>
<p class="small center">Fig. 2 &#8211; New panel in media uploader allows direct creation of script files in the uploads directory.</p>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2010/05/wordpress-csp-plugin/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sharing Links</title>
		<link>http://brandon.sternefamily.net/posts/2010/05/sharing-links/</link>
		<comments>http://brandon.sternefamily.net/posts/2010/05/sharing-links/#comments</comments>
		<pubDate>Fri, 28 May 2010 16:23:50 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=320</guid>
		<description><![CDATA[Sometimes I make a tool that I use for a while and then wonder if it&#8217;s something others will find useful too. Here&#8217;s one of them&#8230; For a while I was sharing links on my home page by linking to the feed of stories I&#8217;ve upvoted on Reddit, but that has become less satisfying as [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
a.bookmarklet {
  text-decoration: none;
  border: 1px solid #bbb;
  margin: 1em;
  padding: .5em;
  -moz-border-radius: .5em;
  -webkit-border-radius: .5em;
}
</style>
<p style="margin:0 2em"><em>Sometimes I make a tool that I use for a while and then wonder if it&#8217;s something others will find useful too.  Here&#8217;s one of them&#8230;</em></p>
<p>For a while I was sharing links on my home page by linking to the feed of stories I&#8217;ve <a href="http://www.reddit.com/user/jackthecoiner/liked/">upvoted on Reddit</a>, but that has become less satisfying as Reddit dumbs itself down each day (the same thing that happened to Digg a few years earlier).  I decided to make my own link-sharing program that I could use by just clicking a <a href="http://en.wikipedia.org/wiki/Bookmarklet">bookmarklet</a> whenever I was on a page I wanted to share.</p>
<p>It is a very simple program that stores the links in a flat text file and uses <a href="http://www.w3.org/TR/cors/#access-control-allow-origin-response-hea">CORS</a> to allow the bookmarklet to POST data to it from across domains.  You can put the files in a directory on your server and use this simple bookmarklet to share links:</p>
<p style="margin:1em; font-size:80%">Drag this to your bookmarks toolbar: <a href='javascript:var shareUrl = "http://your.server/share/index.php"; var pw = "p@ssword";  function createXHR() {   if (window.XMLHttpRequest) {     return new XMLHttpRequest();   }   else if (window.ActiveXObject) {     return new ActiveXObject("Microsoft.XMLHTTP");   }   else {     return null;   } }  function handleResponse() {   if (http.readyState == 4 &#038;&#038; http.status == 200) {     var response = http.responseText;     if (response.length)       alert(response);   } }  var text = prompt("Enter Link Text", document.title);  if (text != "" &#038;&#038; text != null) {   var url = window.location.href;   var params = "text=" + escape(text) + "&#038;url=" + escape(url) + "&#038;pw=" + pw;    var http = createXHR();   http.open("POST", shareUrl, true);   http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");   http.onreadystatechange = handleResponse;   http.send(params); }' class="bookmarklet">Share This</a></p>
<div class="middleBlock">
<p>You can check out the <a href="/files/share/index.txt">server code</a> or the <a href="/files/share/bookmarklet.js">bookmarklet source</a>, or you can download the <a href="/files/share.zip">zip archive</a> and extract the files on your server.</p>
</div>
<p>When you fetch the server script with GET you get back a <a href="/share/index.php?format=json">JSON</a> or <a href="/share/index.php?format=rss">RSS</a> feed depending on the <code>format</code> parameter you pass.</p>
<p>Make sure the password in the bookmarklet stays synced with the password in the server file and change them to something secure.</p>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2010/05/sharing-links/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Removing file extensions with sed</title>
		<link>http://brandon.sternefamily.net/posts/2010/05/removing-file-extensions-with-sed/</link>
		<comments>http://brandon.sternefamily.net/posts/2010/05/removing-file-extensions-with-sed/#comments</comments>
		<pubDate>Wed, 12 May 2010 16:48:22 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=232</guid>
		<description><![CDATA[<p>I need the following sed one-liner periodically, and I thought it was useful enough to share here.  Other versions I've seen chopped off everything after the first dot, which doesn't work for files with a dot in the basename.  This one does:</p>
<pre class="brush: bash; gutter: false">sed s/\.[^\.]*$//</pre>
<p>Sample Usage:</p>
<pre class="brush: bash; gutter: false">bsterne@zodiac:~$ ls /video &#124; sed s/\.[^\.]*$// &#124; head -n5
2001: A Space Odyssey
40 Year Old Virgin, The
9
A Bronx Tale
A Clockwork Orange</pre>

<script type="text/javascript" src="/posts/syntax/src/shCore.js"></script>
<script type="text/javascript" src="/posts/syntax/scripts/shBrushBash.js"></script>
<link rel="stylesheet" type="text/css" href="/posts/syntax/styles/shCore.css" />
<link type="text/css" rel="Stylesheet" href="/posts/syntax/styles/shThemeDefault.css"/>
<script type="text/javascript">SyntaxHighlighter.all()</script>]]></description>
			<content:encoded><![CDATA[<p>I need the following sed one-liner periodically, and I thought it was useful enough to share here.  Other versions I&#8217;ve seen chopped off everything after the first dot, which doesn&#8217;t work for files with a dot in the basename.  This one does:</p>
<pre class="brush: bash; gutter: false">sed s/\.[^\.]*$//</pre>
<p>Sample Usage:</p>
<pre class="brush: bash; gutter: false">bsterne@zodiac:~$ ls /video | sed s/\.[^\.]*$// | head -n5
2001: A Space Odyssey
40 Year Old Virgin, The
9
A Bronx Tale
A Clockwork Orange</pre>
<p><script type="text/javascript" src="/posts/syntax/src/shCore.js"></script><br />
<script type="text/javascript" src="/posts/syntax/scripts/shBrushBash.js"></script></p>
<link rel="stylesheet" type="text/css" href="/posts/syntax/styles/shCore.css" />
<link type="text/css" rel="Stylesheet" href="/posts/syntax/styles/shThemeDefault.css"/>
<script type="text/javascript">SyntaxHighlighter.all()</script></p>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2010/05/removing-file-extensions-with-sed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wildflower Triathlon 2010</title>
		<link>http://brandon.sternefamily.net/posts/2010/05/wildflower-triathlon-2010/</link>
		<comments>http://brandon.sternefamily.net/posts/2010/05/wildflower-triathlon-2010/#comments</comments>
		<pubDate>Tue, 04 May 2010 15:32:35 +0000</pubDate>
		<dc:creator>bsterne</dc:creator>
				<category><![CDATA[Sports]]></category>

		<guid isPermaLink="false">http://brandon.sternefamily.net/posts/?p=227</guid>
		<description><![CDATA[I completed my first triathlon this weekend! I raced in Sunday&#8217;s Wildflower Olympic Distance Triathlon and placed 85th out of 224 in my age group. I was very happy with my performance and met or exceeded all my goals for the race. It was an awesome experience all the way around. The environment is fun [...]]]></description>
			<content:encoded><![CDATA[<p>I completed my first triathlon this weekend!  I raced in Sunday&#8217;s <a href="http://www.tricalifornia.com/index.cfm/WildFlower2010-course_descriptions_olympic_international.htm">Wildflower Olympic Distance Triathlon</a> and placed <a href="http://raceresults.eternaltiming.com/index.cfm/20100501_AVIA_Wildflower_Triathlons_and_Festival.htm?Fuseaction=Results&#038;Class=Olympic+Distance~M30-34">85<sup>th</sup> out of 224</a> in my age group.  I was very happy with my performance and met or exceeded all my goals for the race.</p>
<p>It was an awesome experience all the way around.  The environment is fun and festive with live music and food and race equipment vendors, all the athletes and volunteers are super supportive of each other, and the rush of finally getting to the finish line was indescribable.  I&#8217;m hooked, for sure.</p>
<p align="center"><a href="http://sternefamily.net/photos/main.php?g2_itemId=8965"><img alt="" src="http://sternefamily.net/photos/main.php?g2_view=core.DownloadItem&#038;g2_itemId=8966&#038;g2_serialNumber=2" title="Wildflower" class="aligncenter" style="width:40%;border:0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://brandon.sternefamily.net/posts/2010/05/wildflower-triathlon-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

