<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Brian Krausz</title>
	
	<link>http://briankrausz.com</link>
	<description />
	<lastBuildDate>Sat, 10 Mar 2012 06:52:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/nerdlife" /><feedburner:info uri="nerdlife" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Joining Facebook</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/UCJxUa9_kb4/</link>
		<comments>http://briankrausz.com/joining-facebook/#comments</comments>
		<pubDate>Sat, 10 Mar 2012 06:40:18 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://briankrausz.com/?p=398</guid>
		<description><![CDATA[For those who don&#8217;t follow my company blog: GazeHawk Team Joins Facebook I start at Facebook Monday.  As always I&#8217;m hoping I have the chance to blog more actively, though we&#8217;ll see how realistic that is. To go along with the new job, I&#8217;ve moved my blog over from nerdlife.net to briankrausz.com, and made it [...]]]></description>
			<content:encoded><![CDATA[<p>For those who don&#8217;t follow my company blog:</p>
<p><a href="http://www.gazehawk.com/blog/gazehawk-team-joins-facebook/">GazeHawk Team Joins Facebook</a></p>
<p>I start at Facebook Monday.  As always I&#8217;m hoping I have the chance to blog more actively, though we&#8217;ll see how realistic that is.</p>
<p>To go along with the new job, I&#8217;ve moved my blog over from nerdlife.net to briankrausz.com, and made it look a little more professional.  Nerdlife.net will be used to host my pet projects as they pop up.  Feedback/suggestions on the redesign are certainly welcome!</p>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/UCJxUa9_kb4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/joining-facebook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://briankrausz.com/joining-facebook/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=joining-facebook</feedburner:origLink></item>
		<item>
		<title>How to Catch a Cheater</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/sOiQnTK4oEA/</link>
		<comments>http://briankrausz.com/how-to-catch-a-cheater/#comments</comments>
		<pubDate>Mon, 22 Nov 2010 19:47:14 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=336</guid>
		<description><![CDATA[There's a story making its way around the web about professor catching 1/3 of his class cheating and the fallout from it (everyone retakes the midterm, people who admit to cheating have to take an ethics course).  It reminded me of something one of my professors at Carnegie Mellon did in one of my Freshman year CS classes. [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update:</strong> I wanted to explicitly mention that these homeworks were basically puzzles, which is why Googling was off-limits.</p>
<p><strong>Update 2:</strong> Thanks gzak for remembering the actual name of the problem. It&#8217;s &#8220;Finkleberg&#8217;s 101 Game&#8221; and a copy of the actual homework is <a href="http://russell.lums.edu.pk/~archive/DiscreteMath/cmu-greatideasintcs/Assignments/assignment03/assignment03.pdf">here</a>.</p>
<p>There&#8217;s a story making its way around the web about a <a href="http://tv.gawker.com/5693672/200-students-admit-cheating-after-professors-online-rant">professor catching 1/3 of his class cheating</a> and the fallout from it (everyone retakes the midterm, people who admit to cheating have to take an ethics course). It reminded me of something one of my professors at Carnegie Mellon did in one of my Freshman year CS classes. This is a from-memory recount of it, exact details are probably slightly off.</p>
<p>For context:</p>
<ul>
<li>The early homeworks in this class were basically puzzles, where if you&#8217;ve seen the style of problem before you more or less knew the answer. The goal was to expose us to these types of problems and teach us how to think them through properly.</li>
<li>We were explicitly told that searching online for answers to homeworks was forbidden.</li>
<li>One of our last homework&#8217;s problems began with something like &#8220;Commonly referred to as The Glorblar Problem, &#8230;&#8221; (I don&#8217;t remember the actual word he used, it seemed completely plausible)</li>
</ul>
<p>We get to class one day and wait for the professor to start speaking. Today he just starts running through slides silently:</p>
<ol>
<li>&#8220;As many of you know, one of my hobbies is catching cheaters&#8221;</li>
<li>A picture of the last homework with the phrase &#8220;The Glorblar Problem&#8221; circled</li>
<li>A screenshot of Google with &#8220;The Glorblar Problem&#8221; in the search box</li>
<li>A screenshot of the Google results, with the domain of the first result (which had the problem and correct solution) circled</li>
<li>The whois result for that domain, with the professor&#8217;s name circled (you can hear a collective gulp as half the room realized what was coming next)</li>
<li>The apache logs from the webserver, along with blurred-out reverse IP lookups for the entries</li>
</ol>
<p>Then he started speaking. He told us he had access to the login records from the school&#8217;s public machines as well. Anyone who Googled the result should confess and take a 0 for the homework, otherwise he would report them to the dean and they&#8217;d fail his mandatory class.</p>
<p>A ton of students confessed. A lot of them were sent the link from a friend and many claimed not to have used it, but nobody could deny that they were caught cheating by the letter of the law.</p>
<p>The moral of the story is don&#8217;t fuck with <a href="http://en.wikipedia.org/wiki/Luis_von_Ahn">Luis von Ahn</a>, he will wreck you (no, I wasn&#8217;t one of the students who cheated, but that was one of the more impressive hacks I&#8217;d seen during college).</p>
<p><strong>tl;dr &#8211; My professor made a honeypot for cheaters by planting a <a href="http://en.wikipedia.org/wiki/Google_bomb">Google bombed</a> phrase in his homework.</strong></p>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/sOiQnTK4oEA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/how-to-catch-a-cheater/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		<feedburner:origLink>http://briankrausz.com/how-to-catch-a-cheater/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-catch-a-cheater</feedburner:origLink></item>
		<item>
		<title>Force a Canvas Refresh</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/Uls5qL31614/</link>
		<comments>http://briankrausz.com/force-a-canvas-refresh/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 03:45:13 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=329</guid>
		<description><![CDATA[When playing around with some canvas stuff I found an interesting bug in Chrome. Basically when you have a putImageData call inside of a setInterval loop, canvas does not refresh properly. There&#8217;s a pretty simple hack to fix this: force the canvas to refresh every time you call putImageData. But how do you do this? [...]]]></description>
			<content:encoded><![CDATA[<p>When playing around with some canvas stuff I found an interesting <a href="http://code.google.com/p/chromium/issues/detail?id=55339">bug in Chrome</a>.  Basically when you have a <code>putImageData</code> call inside of a <code>setInterval</code> loop, canvas does not refresh properly.</p>
<p>There&#8217;s a pretty simple hack to fix this: force the canvas to refresh every time you call <code>putImageData</code>.  But how do you do this?  There is no redraw function, nor any obvious way to force a refresh.</p>
<p>The trick is making a change to some property of the canvas element.  Doing this in a way that forces a refresh every frame but won&#8217;t actually change anything for the user is not as obvious as you&#8217;d think.</p>
<p>Opacity isn&#8217;t actually visible with a sufficiently small delta, so it&#8217;s a good candidate.  We just switch back and forth between two different opacities.</p>
<pre>this.ctx.putImageData(img, x, y);
this.rebuild_chrome_hack = !this.rebuild_chrome_hack;
$('#canvas').css('background-color', this.rebuild_chrome_hack ? 1 : 0.999);</pre>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/Uls5qL31614" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/force-a-canvas-refresh/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://briankrausz.com/force-a-canvas-refresh/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=force-a-canvas-refresh</feedburner:origLink></item>
		<item>
		<title>GazeHawk Launches!</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/__tva_il3mA/</link>
		<comments>http://briankrausz.com/gazehawk-launches/#comments</comments>
		<pubDate>Thu, 29 Jul 2010 22:06:39 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=325</guid>
		<description><![CDATA[At least now I have a publicly known excuse for being busy! http://techcrunch.com/2010/07/29/y-combinator-backed-gazehawk-heatmaps-with-web-cams/ Keep an eye on our blog at http://gazehawk.com/blog/ for some interesting technology/startup posts. Time to go deal with my ever-growing inbox .]]></description>
			<content:encoded><![CDATA[<p>At least now I have a publicly known excuse for being busy!</p>
<p><a href="http://techcrunch.com/2010/07/29/y-combinator-backed-gazehawk-heatmaps-with-web-cams/">http://techcrunch.com/2010/07/29/y-combinator-backed-gazehawk-heatmaps-with-web-cams/</a></p>
<p>Keep an eye on our blog at <a href="http://gazehawk.com/blog/">http://gazehawk.com/blog/</a> for some interesting technology/startup posts.</p>
<p>Time to go deal with my ever-growing inbox <img src='http://briankrausz.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/__tva_il3mA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/gazehawk-launches/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://briankrausz.com/gazehawk-launches/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=gazehawk-launches</feedburner:origLink></item>
		<item>
		<title>The Worst Paragraph Ever Written</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/ScRNeKv1wPk/</link>
		<comments>http://briankrausz.com/the-worst-paragraph-ever-written/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 11:31:15 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=323</guid>
		<description><![CDATA[Context: There&#8217;s an organization that sponsors Shabbat dinners. It&#8217;s really awesome: they basically pay you to feed your friends. That being said, they need a copywriter. Here&#8217;s a paragraph in the email they sent confirming my sponsored dinner: As of Monday, July 19th, the new NEXT Shabbat program will begin providing new NEXT Shabbat&#8217;s with [...]]]></description>
			<content:encoded><![CDATA[<p>Context: There&#8217;s an organization that sponsors Shabbat dinners.  It&#8217;s really awesome: they basically pay you to feed your friends.  That being said, they need a copywriter.  Here&#8217;s a paragraph in the email they sent confirming my sponsored dinner:</p>
<blockquote><p>As of Monday, July 19th, the new NEXT Shabbat program will begin providing new NEXT Shabbat&#8217;s with up to $14 per guest (maximum of 16 guests) for the first three meals a host registers after that date. After those three meals, hosts will receive up to $10 dollars per guest. As a returning NEXT Shabbat host, your meal-payment will be based on the number of meals you’ve held already. However, since you have a meal scheduled to take place between July 19th and August 19th, you will still receive $18 per-guest for that meal. Following that meal, if you’ve already held at least three meals, any meal registered after July 19th will only be eligible for a payment of $10 per guest. By joining with us as we make these changes to the program you will give many more people the opportunity to host and will enable thousands to participate in home-based Shabbat meals for the first time. If you’ve held less than three meals, any meal registered after July 19th will be eligible for a payment of up to $14 through your third meal. You can also see how many meals you have already hosted.</p></blockquote>
<p>As always apologies for the lack of updates: I promise there&#8217;s a short (but major) update coming very soon, followed by more frequent posting (there&#8217;s a reason I&#8217;ve been so quiet lately).</p>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/ScRNeKv1wPk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/the-worst-paragraph-ever-written/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://briankrausz.com/the-worst-paragraph-ever-written/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=the-worst-paragraph-ever-written</feedburner:origLink></item>
		<item>
		<title>How to Dispose of a Hard Drive</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/ot3xRyObqhY/</link>
		<comments>http://briankrausz.com/how-to-dispose-of-a-hard-drive/#comments</comments>
		<pubDate>Thu, 03 Jun 2010 01:50:40 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=319</guid>
		<description><![CDATA[In 5 easy steps: Find hammer Give up on finding hammer&#8230;grab pliers Attack drive with pliers, destorying circuitry but leaving platters untouched Cut finger, swear and bleed profusely on drive Repeat steps 3 &#038; 4 until you realize that nobody cares enough about your data to read it directly from platters. Toss drive in trash, [...]]]></description>
			<content:encoded><![CDATA[<p>In 5 easy steps:</p>
<ol>
<li>Find hammer</li>
<li>Give up on finding hammer&#8230;grab pliers</li>
<li>Attack drive with pliers, destorying circuitry but leaving platters untouched</li>
<li>Cut finger, swear and bleed profusely on drive</li>
<li>Repeat steps 3 &#038; 4 until you realize that nobody cares enough about your data to read it directly from platters.  Toss drive in trash, go grab a band-aid</li>
</ol>
<p>Tada!</p>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/ot3xRyObqhY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/how-to-dispose-of-a-hard-drive/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://briankrausz.com/how-to-dispose-of-a-hard-drive/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-dispose-of-a-hard-drive</feedburner:origLink></item>
		<item>
		<title>Diaspora’s Upfront Costs</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/4TpAr-S_Wx4/</link>
		<comments>http://briankrausz.com/diasporas-upfront-costs/#comments</comments>
		<pubDate>Thu, 27 May 2010 03:08:55 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=307</guid>
		<description><![CDATA[This post on Hacker News got me thinking about the costs Dispora&#8216;s going to have receiving all of their money and fulfilling their promises, so I did a little digging. The numbers below are estimates, but they should be fairly close to actual costs for these services (assuming no huge burst in donations over the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://news.ycombinator.com/item?id=1380942">This post on Hacker News</a> got me thinking about the costs <a href="http://www.kickstarter.com/projects/196017994/diaspora-the-personally-controlled-do-it-all-distr">Dispora</a>&#8216;s going to have receiving all of their money and fulfilling their promises, so I did a little digging.  The numbers below are estimates, but they should be fairly close to actual costs for these services (assuming no huge burst in donations over the next 6 days):</p>
<pre>
$ 5510 = $190k * 2.9% Amazon fees[1]
  1800 = 6k donations * $0.30 Amazon fees
  9500 = $190k * 5% for Kickstarter
  4150 = 5000 cds with jewel cases * $0.83 (random googling, I assume the "note from our team" will be on the jewel case insert)
  1380 = 400 sheets of stickers * $3.45 (zazzle, 20 sheet of stickers, 2 stickers per person)
 10200 = 3000 shirts * $3.40 (customink, Gildan 50/50 1 color on white front only)
  9000 = 3000 postage &#038; packaging for shirts + stickers * $3
  2000 = 2000 postage &#038; packaging for just stickers * $1
  1200 = "Turnkey hosting" for 600 people[2]
  2800 = 4 new computers*$700
======
$47540</pre>
<p><small>[1] I&#8217;m not sure if Kickstarter gets a bulk discount here, or if it&#8217;s Dispora&#8217;s account history, so a volume discount may apply.  I also assume all transactions are billed at the $10+ rate (2.9%) rather than the < $10 rate (5%) for simplicity.<br />
[2] Turnkey hosting and phone support are hard to estimate...it may be more if they need to pay for phone support, but I think this is a reasonable number.  I'm also including project hosting costs.  I know they say plenty of hosting companies have offered their services, but you can't guarantee that will be there.</small></p>
<p>Keep in mind that this misses three big points:</p>
<ol>
<li>Declined credit cards &#038; canceled/fraudulent donations &#8211; I have no clue what the expected amount of these is</li>
<li>People who requested a gift for donating who never give their contact info</li>
<li>The huge overhead for packing/sending all of these items, though I imagine a day of pizza and soda for volunteers can get all of them packed (the con I used to help run had similar &#8220;mailing parties&#8221; that were fairly effective)</li>
</ol>
<p>With that in mind you&#8217;re looking at about 25% of the funding going toward transaction fees and fulfilling the rewards.  This leaves around $142,000 left for them, which is still plenty of money.  Though I don&#8217;t want to think about what an accountant would say about this money and how much he would charge to make it legitimate.</p>
<p>Don&#8217;t get me wrong: I think Diaspora is a great idea and I&#8217;d love to see it succeed, but I wonder if the founders considered the logistical overhead to this whole thing.  Granted, this would have been smaller had they only raised $10k, but it&#8217;s still a big task to undertake.  I hope they&#8217;re ready for it and they don&#8217;t let us down.</p>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/4TpAr-S_Wx4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/diasporas-upfront-costs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://briankrausz.com/diasporas-upfront-costs/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=diasporas-upfront-costs</feedburner:origLink></item>
		<item>
		<title>Boston WordPress Meetup Example Code</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/MIoKSPLgz14/</link>
		<comments>http://briankrausz.com/boston-wordpress-meetup-example-code/#comments</comments>
		<pubDate>Thu, 27 May 2010 02:01:50 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=289</guid>
		<description><![CDATA[As promised here&#8217;s the example code from the meetup I gave last Monday. It&#8217;s fairly small, so I only describe what it does briefly in the top comment. Feel free to use it how you wish (though if you make a lot of money off of it you owe me a t-shirt): Example 1: Erroring [...]]]></description>
			<content:encoded><![CDATA[<p>As promised here&#8217;s the example code from the meetup I gave last Monday.  It&#8217;s fairly small, so I only describe what it does briefly in the top comment.  Feel free to use it how you wish (though if you make a lot of money off of it you owe me a t-shirt):</p>
<p><span id="more-289"></span></p>
<h5>Example 1: Erroring out on install</h5>
<pre><code>register_activation_hook(__FILE__, 'bostonwp_install_error');

if('error_scrape' == $_GET['action'] &#038;&#038; basename($_SERVER['PHP_SELF']) == 'plugins.php') {
    echo '&lt;pre>' . get_option('bostonwp_activate_error') . '&lt;/pre>';
    delete_option('bostonwp_activate_error');
    deactivate_plugins($_GET['plugin']);
    die();
}

function bostonwp_install_error($error = false) {
    if(!$error) {
        $error = 'Generic Error Occurred';
    }
    add_option('bostonwp_activate_error', $error);
    //trigger a fatal error
    trigger_error('', E_USER_ERROR);
}</code></pre>
<p></p>
<h5>Example 2: Updating your DB structure</h5>
<pre><code>// http://codex.wordpress.org/Creating_Tables_with_Plugins

define('BOSTONWP_DB_VERSION', '1.0');

register_activation_hook(__FILE__, 'bostonwp_install');

$wpdb->bostonwp = $wpdb->prefix . 'bostonwp';

function bostonwp_install() {
    global $wpdb;

    $installed_ver = get_option( 'bostonwp_db_version' );

    $sql = 'CREATE TABLE ' . $wpdb->bostonwp . ' (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        time bigint(11) DEFAULT 0 NOT NULL,
        name tinytext NOT NULL,
        text text NOT NULL,
        url VARCHAR(55) NOT NULL,
        UNIQUE KEY id (id)
        );';

    if($wpdb->get_var('show tables like "' . $wpdb->bostonwp . '"') != $wpdb->bostonwp) {
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);

        $welcome_name = 'Mr. WordPress';
        $welcome_text = 'Congratulations, you just completed the installation!';

        $insert = 'INSERT INTO ' . $wpdb->bostonwp .
            ' (time, name, text) ' .
            'VALUES (' . time() . ',"' . $wpdb->escape($welcome_name) . '","' . $wpdb->escape($welcome_text) . '")"';

        $results = $wpdb->query( $insert );

        add_option("bostonwp_db_version", BOSTONWP_DB_VERSION);
    }
    elseif( $installed_ver != BOSTONWP_DB_VERSION ) {
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);

        update_option( "bostonwp_db_version", BOSTONWP_DB_VERSION );
    }
}</code></pre>
<p></p>
<h5>Example 3: Adding admin menus</h5>
<pre><code>// http://codex.wordpress.org/Adding_Administration_Menus

add_action('admin_menu', 'bostonwp_menu');
function bostonwp_menu() {
    add_posts_page('My Page', 'My Page', 'manage_categories', 'bostonwp_page', 'bostonwp_dostuff');
}

function bostonwp_dostuff() {
?>
    &lt;div class="wrap">
        &lt;?php if(function_exists('screen_icon')) screen_icon(); ?>
        &lt;h2>My Boston WP Page&lt;/h2>
    &lt;/div>
&lt;?php
}</code></pre>
<p></p>
<h5>Example 4: Adding meta boxes to posts</h5>
<pre><code>// http://www.deluxeblogtips.com/2010/04/how-to-create-meta-box-wordpress-post.html

add_action('add_meta_boxes_post', 'bostonwp_box');
add_action('save_post', 'bostonwp_save');
add_action('delete_post', 'bostonwp_delete');

function bostonwp_box($post) {
    // http://codex.wordpress.org/Function_Reference/add_meta_box
    add_meta_box('bostonwp', __('Boston WP'), 'bostonwp_meta_box', 'post', 'side');
}

function bostonwp_meta_box() {
    global $post;
    $val = get_post_meta($post->ID, 'bostonwp', true);

    // Use nonce for verification
    echo '&lt;input type="hidden" name="bostonwp_nonce" id="bostonwp_nonce" value="' . wp_create_nonce( plugin_basename(__FILE__) ) . '" />';

    // The actual fields for data entry
    echo '&lt;input type="checkbox" name="bostonwp" value="1" ' . ($val ? ' checked="checked" ' : '') . ' />';
    echo '&lt;label for="bostonwp">' . __('There Is Cake!') . '&lt;/label> ';
}

function bostonwp_save($id) {
    // verify nonce
    if ($_POST['action'] != 'inline-save' &#038;&#038; !wp_verify_nonce($_POST['bostonwp_nonce'], plugin_basename(__FILE__))) {
        return $id;
    }

    // check autosave
    if (defined('DOING_AUTOSAVE') &#038;&#038; DOING_AUTOSAVE) {
        return $id;
    }

    update_post_meta($id, 'bostonwp', $_POST['bostonwp']);
}

function bostonwp_delete($id) {
    delete_post_meta($id, 'bostonwp');
}</code></pre>
<p></p>
<h5>Example 5: Adding columns to post list</h5>
<pre><code>add_filter('manage_posts_columns', 'bostonwp_posts_column');
add_action('manage_posts_custom_column', 'bostonwp_manage_column', 10, 2);

function bostonwp_posts_column($cols) {
    $cols['bostonwp'] = __('Boston WP');
    return $cols;
}

function bostonwp_manage_column($name, $id) {
    if($name != 'bostonwp') {
        return;
    }
    $cake = get_post_meta($id, 'bostonwp', true);
    if($cake) {
        echo 'There is cake!';
        $cake = 1;
    }
    else {
        echo 'The cake is a lie!';
        $cake = 0;
    }
    echo '&lt;div id="inline_' . $id . '_bostonwp" class="hidden">' . $cake . '&lt;/div>';
}</code></pre>
<p></p>
<h5>Example 6: Expanding Quick Edit</h5>
<pre><code>add_action('quick_edit_custom_box', 'bostonwp_posts_custom_box', 10, 2);
add_action('admin_head-edit.php', 'bostonwp_add_script');

function bostonwp_posts_custom_box($col, $type) {
    if($col != 'bostonwp' || $type != 'post') {
        return;
    }
?>
&lt;fieldset class="inline-edit-col-right">&lt;div class="inline-edit-col">
    &lt;div class="inline-edit-group">
        &lt;label class="alignleft">
            &lt;input type="checkbox" value="1" name="bostonwp" id="bostonwp_check">
            &lt;span class="checkbox-title">This Post Has Cake&lt;/span>
        &lt;/label>
    &lt;/div>
&lt;/fieldset>
&lt;?php
}

function bostonwp_add_script() {
?>
&lt;script type="text/javascript">
jQuery(document).ready(function() {
    jQuery('a.editinline').live('click', function() {
        var id = inlineEditPost.getId(this);
        var val = parseInt(jQuery('#inline_' + id + '_bostonwp').text());
        jQuery('#bostonwp_check').attr('checked', !!val);
    });
});
&lt;/script>
&lt;?php
}
</code></pre>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/MIoKSPLgz14" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/boston-wordpress-meetup-example-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://briankrausz.com/boston-wordpress-meetup-example-code/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=boston-wordpress-meetup-example-code</feedburner:origLink></item>
		<item>
		<title>On To Bigger Things</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/6fVyddBjdII/</link>
		<comments>http://briankrausz.com/on-to-bigger-things/#comments</comments>
		<pubDate>Tue, 04 May 2010 01:20:56 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=282</guid>
		<description><![CDATA[Alternative title: OMGWTF I just quit my job! Alternative alternative title: A better way to resign from a company That&#8217;s right. I just gave notice that I&#8217;m leaving a great job with awesome coworkers and interesting problems. I&#8217;m trading all of that for the privilege of moving across the country, not taking a salary, and [...]]]></description>
			<content:encoded><![CDATA[<p>Alternative title: OMGWTF I just quit my job!<br />
Alternative alternative title: <a href="http://techcrunch.com/2010/04/24/how-not-to-handle-a-resignation-gracefully/">A better way to resign from a company</a></p>
<p>That&#8217;s right.  I just gave notice that I&#8217;m leaving a great job with awesome coworkers and interesting problems.  I&#8217;m trading all of that for the privilege of moving across the country, not taking a salary, and working 80 hours a week.  If I&#8217;m lucky, I&#8217;ll get to continue doing this for a long time, rather than finding another job that pays actual money.</p>
<p>Shorter explanation: I&#8217;m moving to Silicon Valley to start a business.</p>
<p>Not too much to say right now about the startup.  I got a funding offer I couldn&#8217;t turn down for an idea I really believe in.  Expect more posts in the future, since they valley always does inspire more blogging in me.  For now I don&#8217;t want to say too much about the idea itself, since we&#8217;re still fleshing a lot of things out, but I promise there will be some awesome posts about it in the future.</p>
<p>However, there is something to say about my current employer, TripAdvisor.  Shortly put, they&#8217;ve been amazing.  I got to work on awesome features (like mobile flight search, which just launched today&#8230;tripadvisor.com from a mobile phone).  And not just work on them but have a major say in their direction.  My coworkers were a lot of fun, and my boss was flexible and understanding.</p>
<p>I knew before I graduated that I would eventually leave my first employer to start a business (though I didn&#8217;t think it would be so soon).  TripAdvisor made that an incredibly hard thing to do, which I commend them for.  Hopefully I&#8217;ll be hiring soon, but until I open a Boston office, definitely <a href="http://www.tripadvisor.com/careers/jobs">apply for a position with them</a>.  If you&#8217;d like a contact within the company (not necessary, the engineering HR manager is a solid guy and will get your resume to the right place), <a href="http://nerdlife.net/about/">just ask</a>.</p>
<p>I&#8217;ll be out in Mountain View in early June.  See you on TechCrunch <img src='http://briankrausz.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/6fVyddBjdII" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/on-to-bigger-things/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://briankrausz.com/on-to-bigger-things/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=on-to-bigger-things</feedburner:origLink></item>
		<item>
		<title>Building a C++ XPCOM Component in Windows</title>
		<link>http://feedproxy.google.com/~r/nerdlife/~3/SLxBr-oJayQ/</link>
		<comments>http://briankrausz.com/building-a-c-xpcom-component-in-windows/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 20:47:58 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[XPCOM]]></category>

		<guid isPermaLink="false">http://nerdlife.net/?p=259</guid>
		<description><![CDATA[Jason was kind enough to translate this post to Belorussian. I&#8217;ve been teaching myself to write Firefox extensions for the last few weeks, and became interested in XPCOM components. Unfortunately, I couldn&#8217;t find a good (and recent) summary of them, and had to spend 3 or 4 days cobbling together various tutorials, so I figured [...]]]></description>
			<content:encoded><![CDATA[<p>Jason was kind enough to translate this post to <a href="http://www.movavi.com/opensource/building-a-c-xpcom-component-in-windows-be">Belorussian</a>.</p>
<p>I&#8217;ve been teaching myself to write Firefox extensions for the last few weeks, and became interested in XPCOM components.  Unfortunately, I couldn&#8217;t find a good (and recent) summary of them, and had to spend 3 or 4 days cobbling together various tutorials, so I figured it&#8217;s time to write one.</p>
<h4>What is XPCOM?</h4>
<p>XPCOM is a language-agnostic communication platform used in Mozilla products (and some other random pieces of software) to allow code (specifically extensions) to be written in a wide variety of languages.</p>
<h4>Why would I want to use XPCOM?</h4>
<p>There are two ways to &#8220;use&#8221; XPCOM.  First, you can call functions through XPCOM.  For example, the Firefox bookmarks service uses an XPCOM interface.  So in order to interact with this service from Javascript you would do something like:</p>
<pre>var bmarks = Components.classes["@mozilla.org/browser/bookmarks-service;1"].getService();
bmarks.QueryInterface(Components.interfaces.nsIBookmarksService);
bmarks.addBookmarkImmediately("http://www.mozilla.org","Mozilla",0,null);</pre>
<p>There are plenty of tutorials on doing this as it is the more common use for XPCOM, so I won&#8217;t go into any detail on it here.</p>
<p>The second way is to write an XPCOM service.  That is what this tutorial covers. Sometimes you need extra functionality, speed, or just want to tie into some library that requires a different language.  Most commonly this is C++, but there is also <a href="https://developer.mozilla.org/en/JavaXPCOM">JavaXPCOM</a> and <a href="https://developer.mozilla.org/en/PyXPCOM">PyXPCOM</a> (and probably a few others).  I&#8217;ll be talking about C++, since it&#8217;s what I needed for my project.</p>
<h4>Warnings</h4>
<ol>
<li>Before you trudge through this: <b>you most likely are in the wrong place</b>.  Firefox extensions are usually all Javascript.  If you can use JS to do what you want, <b>stop now</b>.  There is no need to go through the complexity of an XPCOM component when you can just use JS.  Go read <a href="https://developer.mozilla.org/en/Extensions">a tutorial about writing extensions</a> and get to work.</li>
<li>There is something called <a href="https://developer.mozilla.org/en/JavaScript_code_modules/ctypes.jsm">ctypes</a> coming to FF 3.7 that may make doing this a lot easier.  I haven&#8217;t touched this at all, but it may be worth considering if you can wait for the functionality and only need to tie into a particular DLL for some functionality.  Long story short, XPCOM may become the more difficult way to call C++ functions from FF extensions.</li>
</ol>
<h4>My Setup</h4>
<ul>
<li>Windows 7</li>
<li>Visual C++ Express 2008 (free from <a href="http://www.microsoft.com/express/Downloads/#2008-Visual-CPP">Microsoft&#8217;s website</a>)</li>
<li>Firefox 3.6 (Gecko 1.9.2)</li>
<li>A UUID or GUID generator.  This is a unique (read: random) ID that identifies your app to the world.  Windows and Linux have tools to generate this (guidgen &#038; uuidgen, respectively), or you can find various online generators (<a href="https://developer.mozilla.org/en/Generating_GUIDs">Mozilla links to several</a>).  I recommend <a href="http://mozilla.pettay.fi/cgi-bin/mozuuid.pl">this one</a> since it gives you the C++ encoded form too, which you will need.  You need two different UUIDs: one for your interface and one for your component.</li>
<li>Ability to read and understand C++</li>
</ul>
<h4>Sample Code</h4>
<p>If you don&#8217;t want to go through the tutorial and just want everything to work, then download <a href="http://nerdlife.net/wp-content/uploads/2010/02/mycomponent.zip">this sample code</a>.  Just follow step #1 of the tutorial, then make sure your Gecko SDK directory is set right in the build step, and you can breeze on by most of this article.</p>
<h4>The Tutorial</h4>
<p>This is mostly paraphrased from <a href="http://www.iosart.com/firefox/xpcom/">Alex Sirota&#8217;s great tutorial</a>, but it hasn&#8217;t been updated since 2005 and is a bit outdated.  This new one should work out of the box for FF 3.6.</p>
<p>This tutorial will create a component called <code>MyComponent</code> with one function: <code>Add</code>, which will take 2 numbers and, surprisingly, return the sum.</p>
<ol>
<li><a href="https://developer.mozilla.org/en/Gecko_SDK">Download the Gecko SDK</a> for your version of Firefox.  I used 1.9.2 for FF 3.6.</li>
<li>Create an idl file &#8211; <code>IMyComponent.idl</code>, with the following (replacing <code>***IUID***</code> with your interface UUID):
<pre>#include "nsISupports.idl"

[scriptable, uuid(***IUID***)]
interface IMyComponent : nsISupports
{
  long Add(in long a, in long b);
};
</pre>
<p>This file is a language-agnostic interface definition which you can read more about <a href="http://www.mozilla.org/scriptable/xpidl/idl-authors-guide/index.html">here</a>.</li>
<li>Generate the interface header and typelib files out of the interface definition file.  Assuming you extracted the Gecko SDK to <code>C:\xulrunner-sdk\</code>, run the following commands (from the directory you saved <code>IMyComponent.idl</code> to):
<pre>
C:\xulrunner-sdk\sdk\bin\xpidl.exe -m header -I C:\xulrunner-sdk\idl .\IMyComponent.idl
C:\xulrunner-sdk\sdk\bin\xpidl.exe -m typelib -I C:\xulrunner-sdk\idl .\IMyComponent.idl
</pre>
<p>These will create <code>IMyComponent.h</code> and <code>IMyComponent.xpt,</code> respectively.</li>
<li><code>IMyComponent.h</code> has two snippits of code that you can use for the next two files.  Everything between <code>/* Header file */</code> and <code>/* Implementation file */</code> can be used for <code>MyComponent.h</code>:
<ol>
<li>Start by inserting double inclusion protection code and the right include:
<pre>#ifndef _MY_COMPONENT_H_
#define _MY_COMPONENT_H_

#include "IMyComponent.h"</pre>
</li>
<li>Add the following lines, which define your component name, contract ID, and CUID (where ***CUID*** is the C++-style component UUID, of the form { 0&#215;12345678, 0x9abc, 0xdef0, { 0&#215;12, 0&#215;34, 0&#215;56, 0&#215;78, 0x9a, 0xbc, 0xde, 0xf0 } }):
<pre>#define MY_COMPONENT_CONTRACTID "@example.com/XPCOMSample/MyComponent;1"
#define MY_COMPONENT_CLASSNAME "A Simple XPCOM Sample"
#define MY_COMPONENT_CID ***CUID***</pre>
</li>
<li>Copy in the snippet from <code>IMyComponent.h</code>, replacing all the instances of <code>_MYCLASS_</code> with the name of your component (<code>MyComponent</code>).</li>
<li>Finish off the double inclusion protection code with <code>#endif //_MY_COMPONENT_H_</code></li>
</ol>
</li>
<li>Everything between <code>/* Implementation file */</code> and <code>/* End of implementation class template. */</code> can be used for <code>MyComponent.cpp</code>:
<ol>
<li>Start by inserting the right include:
<pre>#include "MyComponent.h"</pre>
</li>
<li>Copy in the snippet from <code>IMyComponent.h</code>, replacing all the instances of <code>_MYCLASS_</code> with the name of your component (<code>MyComponent</code>).</li>
<li>Add some implementation to the <code>Add</code> method.  I replaced <code>return NS_ERROR_NOT_IMPLEMENTED;</code> with
<pre>	*_retval = a + b;
return NS_OK;</pre>
</li>
</ol>
</li>
<li>Create your module definitions files:
<pre>#include "nsIGenericFactory.h"
#include "MyComponent.h"

NS_GENERIC_FACTORY_CONSTRUCTOR(MyComponent)

static nsModuleComponentInfo components[] =
{
    {
       MY_COMPONENT_CLASSNAME,
       MY_COMPONENT_CID,
       MY_COMPONENT_CONTRACTID,
       MyComponentConstructor,
    }
};

NS_IMPL_NSGETMODULE("MyComponentsModule", components) </pre>
</ol>
<p>You now have all of the files needed to build an XPCOM component:</p>
<pre>IMyComponent.h
IMyComponent.idl
IMyComponent.xpt
MyComponent.cpp
MyComponent.h
MyComponentModule.cpp</pre>
<p>Now comes the hard part: getting the damn thing to build.</p>
<h4>Building the code</h4>
<p>Ok, it&#8217;s actually not hard since I&#8217;ve done most of the legwork for you.  Assuming you&#8217;re using Visual C++ 2008 here are the settings you need (again assuming <code>C:\xulrunner-sdk</code> is where your Gecko SDK is).  In <code>Project->Properties</code>:</p>
<pre>Configuration Properties
  General
    Configuration Type: .dll
  C/C++
    General
      Additional Include Directories: C:\xulrunner-sdk\include
    Preprocessor
      Preprocessor Definitions: XP_WIN;XP_WIN32;XPCOM_GLUE_USE_NSPR
  Linker
    General
      Additional Library Directories: C:\xulrunner-sdk\lib
    Input
      Additional Dependencies: nspr4.lib xpcom.lib xpcomglue_s.lib</pre>
<p>If you put the idl file into your project, be sure to mark it &#8220;Excluded from Build&#8221; in its properties&#8230;we don&#8217;t want VS touching it.</p>
<p>Cross your fingers, pray to whatever deity you believe in, and hit the build button.  If it didn&#8217;t work let me know why in the comments and I&#8217;ll try to build a troubleshooting section.</p>
<h4>Installing/Testing the Code</h4>
<ol>
<li>Copy two files to <code>C:\Program Files\Mozilla Firefox\components</code>:
<ul>
<li>The DLL the build generated</li>
<li><code>IMyComponent.xpt</code></li>
</ul>
</li>
<li>Normally, if this was installed as part of an extension, it would automatically search this directory and find these files.  But now we have to force a refresh.  Delete <code>xpti.dat.</code> and <code>compreg.dat</code> from your <a href="http://support.mozilla.com/en-US/kb/Profiles#Where_is_my_profile_stored_">profile directory</a> (FF will regenerate them on next restart)</li>
<li>Close Firefox and open it with this test file (<code>MyComponentTest.html</code> in the sample code):
<pre>&lt;html>
&lt;script type="text/javascript">
function MyComponentTestGo() {
	try {
		// normally Firefox extensions implicitly have XPCOM privileges, but since this is a file we have to request it.
		netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
		const cid = "@example.com/XPCOMSample/MyComponent;1";
		obj = Components.classes[cid].createInstance();
		// bind the instance we just created to our interface
		obj = obj.QueryInterface(Components.interfaces.IMyComponent);
	} catch (err) {
		alert(err);
		return;
	}
	var res = obj.Add(3, 4);
	alert('Performing 3+4. Returned ' + res + '.');
}
&lt;/script>
&lt;body>
&lt;button onclick="MyComponentTestGo();">Go&lt;/button>
&lt;/body>
&lt;/html></pre>
<li>One last time: cross your fingers, pray to whatever deity you believe in, and hit the Go button.  If it didn&#8217;t work let me know why in the comments and I&#8217;ll try to build a troubleshooting section.</p>
</ol>
<p>Hopefully this clears up what looked like a lot of confusion to me.  I will keep this updated to the best of my abilities and hopefully it will continue to be useful for a long time.</p>
<img src="http://feeds.feedburner.com/~r/nerdlife/~4/SLxBr-oJayQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://briankrausz.com/building-a-c-xpcom-component-in-windows/feed/</wfw:commentRss>
		<slash:comments>55</slash:comments>
		<feedburner:origLink>http://briankrausz.com/building-a-c-xpcom-component-in-windows/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=building-a-c-xpcom-component-in-windows</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.620 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-04-05 03:36:45 -->

