A lot of folks have been raving about HTML5 lately and I’ve been a little behind on writing about it, especially being that I’m a Flash developer and it is being touted as a “Flash killer”. I’ll keep this short and not ranty, but there’s a few things I want to discuss.
HTML5′s feature set, even when you consider new abilities that are still experimental, is not even remotely close to what modern Actionscript programming has to offer. The days when Flash was just good for banner ads and website intros has long since passed. If you’re not already familiar, take a look here, or here to see what I’m talking about. Talking about it as a Flash killer is really quite silly. If anything, HTML5 will encroach on Flash at simple interactive experiences, basic video, and “Web 2.0″ ui. Flash, meanwhile, will be moving deeper into developing full applications and insane experiences. This is all good. Everyone should be happy. YAY!
HTML5 has a lot of claims about what it can do, but the dirty little secret is that like previous versions of HTML, the major browsers have decided to implement the standard differently. Things that should be consistent are not. The best example of this is the HTM5 video object, which is supported badly, with lots of bugs (that vary from browser to browser), and supporting different video types in each browser. These issues are extensive still because HTML5 is still evolving. It’s not a fast process at all, and will be years before we can safely use the features that are currently defined, let alone the new concepts on the horizon.
Here are two very important links for HTML5. These are instrumental references for developers, and really good info for the rest of the world:
html5please.us – This shows the major new features in HTML5 and CSS3, along with a description of whether they are currently safe to implement alone, with some extra JS code, with caveats or fallbacks, or not at all.
caniuse.com – This site goes into more depth. Feature by feature it shows which browsers and versions are supported fully or partially.
OSX has an option in the Desktop Background section that allows you to select an entire folder to serve as your background image. You can configure the images to change whenever you’d like: every five minutes, every hour, even every five seconds. I had a silly idea, and I’m happy to say it worked.
I created a folder with about 700 copies of the same background image and set it to change every five seconds. If I test it like that, the background never seems to change at all. Now for the kicker… I toss a single image of a crazy monkey in the mix, tell my background change to use “random order” and voila! Occasionally throughout the day, my background becomes a crazy monkey for 5 seconds!
Creating a pure AS3 (no Flex) project using Ant and command line tools has not been the easiest thing to learn. I wanted to summarize what I’d pulled together here so I have a reference for later projects and for any of you who might be starting down this path.
First, let me give you an overview of the file structure I’m using.
My main folders are “ant”, “build”, “html-template”, and “src”. The “ant” folder contains properties and configuration specific to the ant tasks. Everything in my build folder will be generated by the ant script. It’s completely empty right now. The “src” folder contains all of my Flash AS3 code, whether as AS files or SWCs.
In this example, I’m working with an extremely basic Flash document. Since we’re compiling with Ant and not Flash or Flex, we don’t need an FLA or an MXML, we just need an AS file. Here’s mine:
package org.tomasino.projects.antexample
{
import flash.display.Sprite;
import flash.events.Event;
[SWF(width="800", height="600", frameRate="30", backgroundColor="#FFFFFF")]
public class Example extends Sprite
{
public function Example ():void
{
if (this.stage) init();
else addEventListener (Event.ADDED_TO_STAGE, init);
}
private function init (e:Event = null):void
{
removeEventListener (Event.ADDED_TO_STAGE, init);
}
}
}
The “html-template” folder will have its contents and structure copied into “build” when we run the Ant script later on. I started using this habit with Eclipse and I’ve come to like it. I can keep my nice, clean, template code in a place all by itself. If necessary, I can do some processing on it with the Ant script later on, only including certain files in certain situations. For now, I’m just copying what I need, including the index file. Here it is:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Ant Flash Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" media="screen" href="css/styles.css.php" />
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript">
var swfVersionStr = "11.0.0";
var xiSwfUrlStr = "playerProductInstall.swf";
var flashvars = {};
var params = {};
var attributes = {};
var flashObject;
// When Flash is loaded, store reference to FlashObject for easy ExternalInterface calls
function flashReady (status)
{
if (status.success)
{
flashObject = status.ref;
}
}
params.quality = "high";
params.allowscriptaccess = "sameDomain";
params.allowfullscreen = "true";
params.wmode = "transparent";
swfobject.embedSWF( "example.swf", "flash", "800", "600", swfVersionStr, xiSwfUrlStr, flashvars, params, attributes, flashReady);
</script>
</head>
<body>
<div id="flash">
<h1>Adobe Flash Player Needed</h1>
<p><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>
</div>
</body>
</html>
You might notice that I’m using the CSS optimizer from an earlier post. I’ve also included a callback method in my swfobject.embedSWF line, called “flashReady”. When SWFObject loads my SWF, this method will be called immediately where it will store a reference to the Flash object. If you’ve used ExternalInterface callbacks before, you know it can be difficult to figure out how to reference the Flash object in every browser. SWFObject makes it easy with this little trick.
Finally: the important stuff. The Ant script (build.xml in my folder) is the heart of the project. To run it, drop to terminal, change directory to the folder and type “ant”. It will run the “compile” target by default. Let’s take a look:
<project name="antExample" default="compile" basedir="." >
<description>
Ant Example
</description>
<property file="ant/local.properties" description="local build configuration."/>
<property file="ant/build.properties" description="build configuration."/>
<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
<!-- Create the build folder for project -->
<target name="make_build">
<mkdir dir="${build.dir}"/>
</target>
<!-- Copy template folder to build -->
<target name="make_template" depends="make_build" unless="nochanges_template">
<copy todir="${build.dir}">
<fileset dir="${template.dir}">
<include name="**/css/**"/>
<include name="**/images/**"/>
<include name="**/js/**"/>
<include name="*.html"/>
</fileset>
</copy>
</target>
<!-- Compile SWF to build -->
<target name="make_swf" depends="make_template" unless="nochanges_flash">
<mxmlc
file="${src.dir}/org/tomasino/projects/antexample/Example.as"
output="${build.dir}/example.swf"
actionscript-file-encoding="UTF-8"
keep-generated-actionscript="false"
optimize="true"
>
<!-- Get default compiler options. Hand modified to remove extraneous Flex trash -->
<load-config filename="ant/config.xml"/>
<!-- List of path elements that form the roots of ActionScript class hierarchies. -->
<source-path path-element="${FLEX_HOME}/frameworks" />
<source-path path-element="${src.dir}" />
<source-path path-element="${tomasinolibs.dir}" />
<!-- List of SWC files or directories that contain SWC files. -->
<compiler.library-path dir="${libs.dir}" append="true">
<!-- <include name="example.swc" /> -->
</compiler.library-path>
<!-- Flags -->
<compiler.debug>false</compiler.debug>
</mxmlc>
</target>
<!-- Test for dependencies and changes -->
<target name="init">
<uptodate property="nochanges_flash" targetfile="${build.dir}/example.swf">
<srcfiles dir="${src.dir}" includes="**/**"/>
</uptodate>
<uptodate property="nochanges_template" targetfile="${build.dir}/index.html">
<srcfiles dir="${template.dir}" includes="**/**"/>
</uptodate>
<condition property="build.exists">
<available file="${build.dir}" type="dir"/>
</condition>
</target>
<!-- Cleanup -->
<target name="clean" depends="init" if="build.exists">
<delete dir="${build.dir}"/>
</target>
<!-- Compile SWF -->
<target name="compile" depends="init, make_swf" />
</project>
build.properties file defines the common properties in the project.
FLEX_HOME = OVERRIDE IN LOCAL PROPERTIES
src.dir = src
libs.dir = src/libs
build.dir = build
template.dir = html-template
local.properties file defines the local properties that override defaults. These are used to dictate the developer-specific paths.
The targets are listed in order of dependency for ease of use. The “compile” target depends on “make_swf” which depends on “make_template” which depends on “make_build”. I built those names and structure myself, so don’t think of it as a required way of doing things. It just helps me keep things straight.
The “make_swf” target performs the actual SWF compilation using the mxmlc task provided by flexTasks.jar. You’ll notice up near the top I am including this jar file. Without it, ant has no idea what a SWF is or what to do with it. I should also note that I’m including a property reference to the Flex SDK in the local.properties file. You can see we’re using that inside the mxmlc block. The mxmlc block gets its configuration settings from config.xml, included in the ant folder. I edited the Flex configuration file to remove all the non-Pure AS3 references. All of this is free stuff, of course.
Just to illustrate how to do it, I’m including my own “tomasino” source in this project. It’s not being used by my example, but it could be. The <source-path> element dictates where all these things are found. The <compiler.library-path> element would contain any SWCs you need to include. If it’s not easily relative to the project, you can go ahead and give it an absolute path (in the local.properties file).
The “make_template” target is copying the files from the “html-template” folder into the “build” folder. The “make_build” target creates the “build” folder (if it doesn’t exist already). The “clean” target deletes the “build” folder and its contents to make sure we always start fresh.
Just a few final notes about ant. Properties are your variables, of a sort, though they are generally not assigned multiple different values in a script. Ant is not a programming language, and you’ll continuously run into walls if you forget that. There are no loops, for instance (if you want them, check out ant-contrib). I’ve named my properties with “.dir” suffixes to let me know if it’s a directory versus a folder name, for example. It’s all style, though. FLEX_HOME seems to require that it be named with all-caps for some reason. It may just be a bug in the code when I was testing changing it, but I left it anyway.
That’s it. I hope it wasn’t overwhelming. I didn’t cover how to install ant, so if you’re on a Windows box, you might want to google that. Please, grab the project and play around with it. Let me know if you have any suggestions or questions.
I’m putting together a really tight little todo list manager right now, and in the process I’ve been exploring some simple things on my … todo list. Hrm, that came out weird.
Anyway, I wanted to manually handle minifying and organizing my CSS files. I wanted three important things:
The CSS files, no matter how many, should be served up from a single HTTP request
The CSS contents should be stripped down to take out unnecessary whitespace and comments
<?php
//##################################################################
//######################### COMPRESS CSS #########################
//##################################################################
ob_start ("ob_gzhandler");
header ("content-type: text/css; charset: UTF-8");
header ("cache-control: must-revalidate");
header ("expires: " . gmdate ("D, d M Y H:i:s", time() + 3600) . " GMT");
//##################################################################
//######################### CSS FILE LIST ########################
//##################################################################
$css = array (
'reset.css',
'master.css',
);
//##################################################################
//######################### PROCESS CSS #########################
//##################################################################
$_inHack = true;
function minify($css) // From Google Minify
{
$css = str_replace("\r\n", "\n", $css);
// preserve empty comment after '>'
// http://www.webdevout.net/css-hacks#in_css-selectors
$css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
// preserve empty comment between property and value
// http://css-discuss.incutio.com/?page=BoxModelHack
$css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
$css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
// apply callback to all valid comments (and strip out surrounding ws
$css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@', '_commentCB', $css);
// remove ws around { } and last semicolon in declaration block
$css = preg_replace('/\\s*{\\s*/', '{', $css);
$css = preg_replace('/;?\\s*}\\s*/', '}', $css);
// remove ws surrounding semicolons
$css = preg_replace('/\\s*;\\s*/', ';', $css);
// remove ws around urls
$css = preg_replace('/
url\\( # url(
\\s*
([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
\\s*
\\) # )
/x', 'url($1)', $css);
// remove ws between rules and colons
$css = preg_replace('/
\\s*
([{;]) # 1 = beginning of block or rule separator
\\s*
([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
\\s*
:
\\s*
(\\b|[#\'"-]) # 3 = first character of a value
/x', '$1$2:$3', $css);
// remove ws in selectors
$css = preg_replace_callback('/
(?: # non-capture
\\s*
[^~>+,\\s]+ # selector part
\\s*
[,>+~] # combinators
)+
\\s*
[^~>+,\\s]+ # selector part
{ # open declaration block
/x', '_selectorsCB', $css);
// minimize hex colors
$css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'
, '$1#$2$3$4$5', $css);
$css = preg_replace('/@import\\s+url/', '@import url', $css);
// replace any ws involving newlines with a single newline
$css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
// separate common descendent selectors w/ newlines (to limit line lengths)
$css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css);
// Use newline after 1st numeric value (to limit line lengths).
$css = preg_replace('/
((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
\\s+
/x'
,"$1\n", $css);
// prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
$css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
return trim($css);
}
function _selectorsCB($m)
{
// remove ws around the combinators
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
}
function _commentCB($m)
{
global $_inHack;
$hasSurroundingWs = (trim($m[0]) !== $m[1]);
$m = $m[1];
// $m is the comment content w/o the surrounding tokens,
// but the return value will replace the entire comment.
if ($m === 'keep') {
return '/**/';
}
if ($m === '" "') {
// component of http://tantek.com/CSS/Examples/midpass.html
return '/*" "*/';
}
if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
// component of http://tantek.com/CSS/Examples/midpass.html
return '/*";}}/* */';
}
if ($_inHack) {
// inversion: feeding only to one browser
if (preg_match('@
^/ # comment started like /*/
\\s*
(\\S[\\s\\S]+?) # has at least some non-ws content
\\s*
/\\* # ends like /*/ or /**/
@x', $m, $n)) {
// end hack mode after this comment, but preserve the hack and comment content
$_inHack = false;
return "/*/{$n[1]}/**/";
}
}
if (substr($m, -1) === '\\') { // comment ends like \*/
// begin hack mode and preserve hack
$_inHack = true;
return '/*\\*/';
}
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
// begin hack mode and preserve hack
$_inHack = true;
return '/*/*/';
}
if ($_inHack) {
// a regular comment ends hack mode but should be preserved
$_inHack = false;
return '/**/';
}
// Issue 107: if there's any surrounding whitespace, it may be important, so
// replace the comment with a single space
return $hasSurroundingWs // remove all other comments
? ' '
: '';
}
$buffer = '';
for ($i = 0; $i < count($css); $i++ )
{
$filename = $css[$i];
if (is_file($filename))
{
$buffer .= "\n" . file_get_contents ($filename);
}
}
$buffer = minify($buffer);
echo $buffer;
?>
I set my compression up with ob_gzhandler, and do a little magic with the headers. Cache expires in a day, which I think is plenty often enough, but feel free to tweak to your own needs.
Next I set up an array of CSS files. Notice they’re all real CSS files, not PHP files in disguise. I kept things simple. They’ll be read into PHP and cleaned up in the bottom section. Simple, right?
Oh, right… you can use it in your HTML just like you would a normal CSS file:
In an ongoing effort to make my javascript code not look like trash, I’ve compiled the following template for all of my class files. It allows for static, private, privileged, and public methods and properties. It’s a bit of an overkill because I wanted to account for everything.
Due to the nature of the private and privileged methods and variables, these will take up memory for every instance of the class (they are not part of the prototype) and they will not allow for inheritance. I find the tradeoff for encapsulation more important than inheritance which is much more rare in JavaScript. Of course, if the class is going to end up with a bajillion instances, you’d better rely primarily on the Publics.
It’s important to take a moment to explain the scope of each of these method types since JavaScript is infamous for its issues on that front. First, public methods can only access other publics and privileged methods and properties. Privileged methods can access public, privileged and private methods and properties. Private methods can also access any of the types. The limitation from the publics is related to their definition in the prototype. Finally, the line “var that = this;” allows for private and privileged methods to access the “this” scope of the class. Due to a weird issue with scope inside closures, normally accessing “this” inside one of those methods would fail.
I don’t like how I’m forced to write my getters and setters currently. There’s the “__definegetter__” option, but from what I’ve read it isn’t standardized and might not work everywhere. Does anyone have experience with this?
The semicolon at the beginning takes care of any improperly terminated statements that might preface this class and cause it to poop out. Thanks to Dave Hamp for that idea!
Finally, everything is wrapped in a function to preserve scope.
;(function(window) {
function TestClass ()
{
// ----------------------------------------------
// Static Properties
// ----------------------------------------------
TestClass.STATIC_VALUE = 'static value';
// ----------------------------------------------
// Privileged Properties
// ----------------------------------------------
this.privilegedVar = 'Privileged Variable';
// ----------------------------------------------
// Private Properties
// ----------------------------------------------
// Used for scope in inner functions
var self = this;
var _privateVar = 'Private Variable';
// ----------------------------------------------
// Privileged Methods
// ----------------------------------------------
this.privilegedMethod = function ()
{
};
// ----------------------------------------------
// Private Methods
// ----------------------------------------------
function privateMethod ()
{
}
// ----------------------------------------------
// Getters / Setters
// ----------------------------------------------
// Getters / Setters via Privileged Methods
self.getPrivateVar = function ()
{
return _privateVar;
};
self.setPrivateVar = function (val)
{
_privateVar = val;
};
// ----------------------------------------------
// Constructor
// ----------------------------------------------
function __construct()
{
} __construct();
}
var p = TestClass.prototype;
// ----------------------------------------------
// Public Properties
// ----------------------------------------------
p.publicVar = 'Public Variable';
// ----------------------------------------------
// Public Methods
// ----------------------------------------------
p.publicMethod = function ()
{
}
window.TestClass = TestClass;
}(window));
There is a bug in GoogleAnalytics that causes links with target=_blank to open a new window as well as navigating the current window to the new link. This happens primarily in CMSs where you have the option to “Track Outbound Links”. Below is my solution to this problem.
First of all, my solution requires jQuery (because if you’re using JavaScript, why would you use anything else).
Second, turn off “Track Outbound Links” if you have that option. We’ll do it manually.
Third, I’ve named my methods in such a way that they really shouldn’t collide with anything of yours.
Finally, I’m using namespaces on my click events so that I won’t destroy any other click events you might have on your links. My convention is to make the namespace of the click equal the name of the method it calls. It lends some semblance of organization to JS, I find.
jQuery(document).ready( google_analytics_documentready );
function google_analytics_documentready ($)
{
// unbind first in case we're doing weird stuff with ajax loading or whatevers.
$('a[target=_blank]').unbind('click.google_analytics_trackoutbound');
$('a[target=_blank]').bind('click.google_analytics_trackoutbound', google_analytics_trackoutbound );
}
function google_analytics_trackoutbound (e)
{
try
{
_gaq.push(["_trackEvent", "Outbound links", "Click", e.target.href]);
}
catch(err)
{
}
return true;
}
In an effort to never, ever get a single bit of spam, I instituted a bit of a ridiculous solution. Here’s what I did:
I never use my real e-mail address publicly. This includes my friends and family. Nobody has it. Period.
If someone somehow discovers my private account, I can move to a new one by simply updating all the forwards.
I create a unique alias for every website/account I use. For instance, yahoo@jamesrocks.com, wachovia@jamesrocks.com, etc.
If any of these accounts sell my address to a spammer, or send me annoying things without offering an unsubscribe, I can simply delete the alias and my problems are gone.
For aliases I want to send mail “from”, I create a full pop3 email account.
I can then use the smtp server to send mail as that account without getting the annoying “on behalf of…” message in certain email clients.
I run a cron job to automatically clear out the contents of the mail account nightly. Since the mail is all being forwarded anyway, I don’t actually need to pull anything from the account. This cleans things up nicely and avoids using up space unnecessarily.
Since my actual email account is at GMail, I have to handle separately the spam I receive directly at that account. Luckily it seems that most spammers that brute-force mail every letter combination at GMail do not include dots (.) in the addresses. I can use this to my advantage by filtering the “deliverto:” property and auto-deleting these messages.
In the GMail filters, under “Has the words” include “deliveredto:realaddresswithoutdots@gmail.com” (no quotes).
That will capture things delivered to your address whether or not you are included in the TO: field or BCC: or whatever. It’s awesome, right?
I like to include my source code in my WordPress posts, but it was getting annoying to keep up-to-date. Every time I’d make a change to my code and commit it to GitHub, I’d have to dig through WordPress to find the old post, duplicate my changes there, and republish. That’s entirely too manual for me. I needed a better solution.
A little digging around on GitHub itself paid off. I ran across a project called GitHub Code Viewer written by Steve Francia. (He’s the creator of spf13-vim, the totally amazing vim profile.)
GitHub Code Viewer is a WordPress plugin that allows you to grab your source code directly from GitHub and display it in a post. It was perfect! The code, unfortunately, didn’t work right with the latest WordPress release. I was sad. (sadface)
I had some free time that day, thankfully, and took it upon myself to fix the code up myself. It was my very first time forking a git repository, or doing a pull request, or any of those fun group-git things. It was very exciting. The end result is a working WordPress plugin that lets me pull in code from my repository.
I already use a wonderful syntax highlighter called SyntaxHighlighter Evolved. Together with GitHub Code Viewer I can include all of my source directly in my posts, have it look pretty, and be automatically updated.
Now, in an experiment of hilarious recursion, you will find below the code to GitHub Code Viewer displayed in my blog via GitHub Code Viewer. But before that, I’ll ALSO show you the code to use GitHub Code Viewer to display GitHub Code Viewer. (Takes a bow).
I do web development. I love Chrome. What I don’t love is that Chrome has no simple way to disable the browser cache. It makes using Chrome for my development tasks so frustrating that I usually end up cracking open Firefox (and crying). It’s especially bad for Flash development because even where a SHIFT-Refresh would serve to pull new HTML updates from the server, Flash content remains cached as always.
Yes, I know I can run my Chrome in Incognito Mode to avoid caching things, but my Flash Builder and other apps don’t automatically launch in Incognito mode. It’s all a big hassle. I don’t like big hassles. Well, I don’t mind them once, but I don’t like regular big hassles.
So I set out to fix it. I knew there must be some way around the problem, and I had just enough patience to deal with that hassle once.
Look what I came up with! See that, folks? No cache. Pretty awesome, right? Well, it’s a little annoying to set up, but I think it’ll be worth the trouble.
Disclaimer: This method only works on Unix / OSX systems. It requires /dev/null.
Lets get started:
Step 1: Making Chrome Cachless
Chrome has a handful of handy command-line parameters that can help you customize where your cache is stored or how much space to allot. At first, I thought I might be able to use one of these (–disk-cache-size=0) to set the cache size to zero. That seems like the simplest, but apparently the minimum value you can use is (1). That’s not good enough.
A little more looking revealed another parameter, seemingly less useful at first.(–disk-cache-dir) allows you to change the folder used to hold your cache. It took me a while to realize just how awesome that is on a Unix architecture, though. In Unix-like systems, we have a special file(ish) location called /dev/null that acts as a kind of black hole to data. Anything you send its way gets discarded cleanly. It’s a quick read over on Wikipedia. I’ll wait.
That means that you can run Chrome without it being able to store or retrieve cache information like so: chrome –disk-cache-dir=”/dev/null/”
Of course, you can’t just run an app like that on a Mac, which leads us to part two!
Step 2: Running Chrome from Command Line
You can’t run an .app file with switches. That’s because .apps are really directories launched via launchd (if I recall), and subject to their own unique manner of wonkery (yes, that’s a word now). If you want to launch an .app from the command line, you have to look inside the directory. From Finder you can do this by right-clicking and choosing “Show Package Contents”. In terminal, just “cd” into the directory. Here’s what it looks like inside Chrome:
Well, almost. You’ll notice your MacOS folder has only the “Google Chrome” file, not the little darling “chrome”. That’s because I wrote “chrome” myself. I’ll show you that in a minute. The important thing is that “Google Chrome” is the actual executable file you can run with switches to launch your app. Cool, right? Give it a try. You can launch a cacheless chrome from here.
Step 3: Making the App Cachless
Obviously you don’t want to have to run this from the command line every time you want to launch Chrome. Some people would start blathering to you about AppleScripts and Automators and all manner of annoying things. Those may make it easier to launch a cachless Chrome by hand, but what I really wanted was to make the app itself, by default, launch without cache. It turns out it was pretty simple with a bit of shell scripting.
Remember I told you that “Google Chrome” was the file that was actually run by the .app? We can use that to our advantage. Rename “Google Chrome” to “chrome” (see, I told you I’d show you). Now, create a new file called “Google Chrome” in its place. Open it up in your favorite text editor. Inside, we’ll write a little shell script that will launch our app for us using the “exec” command and our parameter. Here it is. Just tweak your paths to work for you.
Save and exit your editor. Last, but certainly not least, remember to “chmod” your new “Google Chrome” app to 755 so it’ll be executable. You’re done!
Launch Chrome and witness the awesome. You may also want to delete all your old cache files to clean things up a bit. You can use the Chrome interface, and also pop into these two folders and wipe out their cache contents to be thorough: ~/Library/Caches/Google/Chrome and ~/Library/Application Support/Google/Chrome.
Congratulations! I hope you enjoy your new cacheless browser. Everything will probably get wiped out and reset when you upgrade, so beware.
A while back I had mentioned that I was working on a bigger cipher project. This is it!
For me, the VIC Cipher represents the ultimate challenge in hand-created cryptography. It is the epitome of thousands of years of code development and one of (if not the) last functional hand-created cipher before the advent of computers. In a way, the VIC is a collection of other ciphers: lagged fibonacci generators, sequential substitution, digit-based (non-carrying) addition & subtraction, straddling checkerboards, and various types of transpositions.
If you want to know all about this amazing feat of code-making, here’s the full story from the CIA: link.
Before I continue, I need to put a special thanks out to “raincomplex” over at everything2.com whose extremely detailed post really enabled me to build this. If you’d like to try encoding or decoding a message with VIC cipher by hand, I recommend you follow his instructions.
1) How to encode a message
To encode a message you will need to memorize three bits of information. Luckily, they’re all quite simple mnemonics!
A song lyric that has at least (20) characters in it, not counting spaces or punctuation.
A date. It will be formatted as dd/mm/yyyy with no leading 0′s.
A personal ID number. It needs to be between 0 and 16. (The math just works out that way)
Finally, each message will have a 5 digit random number added in. You don’t need to remember this after sending the message, and the recipient doesn’t need to know it in advance. So, if you can remember those three things above, and pick 5 digits, you can send a message! Let’s try it. You can type anything you want, but only letters, numbers, and the period (full stop) characters will be saved. (That’s flash below, not an image. You can try it right here!)
In the latest versions of Flash, Adobe has removed the Date Chooser component. As a result, and due to my laziness, I’m using one I found here. It does a decent job and remains fairly light-weight. Still, it’s a bit limiting when changing years. I should really look around for something more feature rich.
Update: Thanks to Carl Leiner the VIC Coders now have an awesome Date Chooser that can quickly update the year based on your typed input, or by the more familiar expanded calendar. Thanks Carl! Awesome work.
If you look carefully at your generated code, you’ll notice that (5) digit random message ID you added can be found in plain text near the end of the code. Its position is determined by the last digit of the date. Cool, right? Ok… lets look at decoding.
The requirements to decode are the same as those to encode. As long as your keys match up, you should have no problems. Your message may have some extra characters at the end. This jibberish is called “null characters” in code-speak. It’s just there so our numeric code is always in pretty units of 5 digits. If you don’t see any jibberish, it’s because your message already fit into groups of five perfectly.
And that’s it, folks. A VIC Cipher encoder / decoder written in AS3. Why, you might ask–I have no idea. It just seemed like a lot of fun. Now, get encoding. Leave me some coded comments on this post.
All the source for this lab project can be found here. All the libraries for the encoding can be found at my GIT repository here.