Skip to content
Browse files

added deployment script + loggly error handing

  • Loading branch information...
1 parent 01833ae commit 13824070f33e4626ee2e4563ccd2978d58b9a2ac @kevbook committed Apr 10, 2012
Showing with 585 additions and 18 deletions.
  1. +3 −3 app/config.js
  2. +1 −1 app/errorhandler.js
  3. +6 −0 deploy.sh
  4. +5 −7 lib/logger.js
  5. +2 −2 lib/mailer.js
  6. +13 −3 package.json
  7. +1 −1 public/js/script.min.js
  8. +553 −0 s3up
  9. +1 −1 views/home.jade
View
6 app/config.js
@@ -6,7 +6,7 @@ module.exports = function(){
devConfig = {
mongodb: {
- url: process.env.MONGO_DB || 'mongodb://hackd:hackd@staff.mongohq.com:10045/hackd'
+ url: process.env.MONGO_DB || 'mongodb://hackd:hackd>@flame.mongohq.com:27048/hackd_signups_test'
},
loggly: {
subdomain:'kevbook'
@@ -16,15 +16,15 @@ module.exports = function(){
},
viewOptions: {
pretty: true,
- assetVersion: '?v2',
+ assetVersion: '?v3',
assetUrl: '',
layout: false
},
};
prodConfig = {
mongodb: {
- url: process.env.MONGO_DB || 'mongodb://hackd:hackd@staff.mongohq.com:10045/hackd'
+ url: process.env.MONGO_DB || 'mongodb://hackd:hackd@staff.mongohq.com:10045/hackd_signups'
},
loggly: {
subdomain:'kevbook'
View
2 app/errorhandler.js
@@ -6,7 +6,7 @@ module.exports = function(app){
// 404 not found
notFound: function(req, res){
// log error:
- logger.log('notFound', '404 error: ' + req.url);
+ logger.log('not_found', '404 error: ' + req.url);
res.render('errors/404', {
status: 404,
View
6 deploy.sh
@@ -0,0 +1,6 @@
+## Static Files to S3
+php s3up -u AKIAIQK5HEJJVK6HGTAA -p XzEjLGtlMbgFybkEPcVH8rOOrqtNJxqj7lFQFPNm -xzow hackd/assets/css/ /sites/hackd.it/public/css/
+
+php s3up -u AKIAIQK5HEJJVK6HGTAA -p XzEjLGtlMbgFybkEPcVH8rOOrqtNJxqj7lFQFPNm -xzow hackd/assets/js/ /sites/hackd.it/public/js/
+
+php s3up -u AKIAIQK5HEJJVK6HGTAA -p XzEjLGtlMbgFybkEPcVH8rOOrqtNJxqj7lFQFPNm -xzow hackd/assets/img/ /sites/hackd.it/public/img/
View
12 lib/logger.js
@@ -34,12 +34,10 @@ exports.log = function(input, msg, printAlso){
*/
function errCodes(){
return {
- auth_fail: 'bb73aef8-80f1-4265-aa4b-8db88ba48488',
- db_conn_error: '54b98e8c-627a-4212-95f1-1333e148a0fe',
- email_send_error: 'fc1c8105-ebf4-40ff-94e6-a2116fb51413',
- not_found: '49715906-22a9-4039-a605-ebe29e2131d4',
- server_error: '2c6337a8-f15b-4ae6-b41f-9d957f7af05e',
- server_start: '2637cf4c-642a-48ff-bad5-02741a5c22c1',
- oauth_error: 'cb6238e8-1af9-4bcc-b396-30345bf203f9'
+ db_conn_error: '70cb98bd-f24d-4977-a6c9-af25015da38a',
+ email_send_error: 'f352aab8-31cc-4d61-85b3-80278738a0b2',
+ not_found: '16d836cb-84ab-44e3-a0cc-954d75646fcf',
+ server_error: '0decb618-f72b-4183-a20e-8a880ef3746b',
+ server_start: '2e4a1908-87f5-4334-b710-a03e061f2a54'
};
}
View
4 lib/mailer.js
@@ -48,13 +48,13 @@
if(res.statusCode != 200){
res.setEncoding('utf8');
res.on('data', function (chunk) {
- logger.log('emailError', res.statusCode + '- BODY: ' + chunk);
+ logger.log('email_send_error', res.statusCode + '- BODY: ' + chunk);
});
}
});
req.on('error', function(err) {
- logger.log('emailError', 'Error with request: ' + err.message);
+ logger.log('email_send_error', 'Error with request: ' + err.message);
callback(err);
});
View
16 package.json
@@ -1,9 +1,11 @@
{
"name": "hackd",
- "version": "0.0.1",
+ "version": "0.0.1-2",
"description": "hackathons in jax",
"author": "Kevin Sakhuja <kevin.sakhuja@gmail.com>",
- "engine": "node >= 0.6.13",
+ "engines": {
+ "node": ">= 0.6.0 < 0.7.0"
+ },
"repository": {
"type": "git",
"url": "git@github.com:kevbook/hackd.it.git"
@@ -16,7 +18,15 @@
"gravatar": "latest"
},
"devDependencies": {
- "node-inspector": "latest",
+ "node-inspector": "latest",
"nodetime": "latest"
+ },
+ "domains": [
+ "hackd.it",
+ "www.hackd.it"
+ ],
+ "subdomain": "hackd",
+ "scripts": {
+ "start": "app.js"
}
}
View
2 public/js/script.min.js
@@ -1 +1 @@
-head.ready(function(){function escape(){var a=this;if(this.isShown&&this.options.keyboard){$(document).on("keyup.dismiss.modal",function(b){b.which==27&&a.hide()})}else if(!this.isShown){$(document).off("keyup.dismiss.modal")}}function removeBackdrop(){this.$backdrop.remove();this.$backdrop=null}function backdrop(a){var b=this,c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=$.support.transition&&c;this.$backdrop=$('<div class="modal-backdrop '+c+'" />').appendTo(document.body);if(this.options.backdrop!="static"){this.$backdrop.click($.proxy(this.hide,this))}if(d)this.$backdrop[0].offsetWidth;this.$backdrop.addClass("in");d?this.$backdrop.one($.support.transition.end,a):a()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");$.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one($.support.transition.end,$.proxy(removeBackdrop,this)):removeBackdrop.call(this)}else if(a){a()}}function hideModal(a){this.$element.hide().trigger("hidden");backdrop.call(this)}function hideWithTransition(){var a=this,b=setTimeout(function(){a.$element.off($.support.transition.end);hideModal.call(a)},500);this.$element.one($.support.transition.end,function(){clearTimeout(b);hideModal.call(a)})}function set_msg(a){$("#msg").show().html(a);setTimeout(function(){$("#msg").hide()},3e3)}$("#why").live("click",function(){$("#myModal").modal("show")});var emailReg=/^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;$("#submit").live("click",function(){var name=$("#name").val();if(name.length<1){$("#name").addClass("animated shake");setTimeout(function(){$("#name").removeClass("animated shake")},900);return false}var email=$("#email").val();if(email==""||!emailReg.test(email)){$("#email").addClass("animated shake");setTimeout(function(){$("#email").removeClass("animated shake")},900);return false}var data={name:name,email:email};$.ajax({type:"POST",url:"home",data:data,dataType:"json",success:function(a){if(a.status){set_msg(a.msg);$(".wrapper").prepend('<div class="attendee"><a href="'+a.link+'" target="_blank"><img src="'+a.pic+'">'+a.name+"</a></div>");$(".form").slideUp("slow")}else{set_msg(a.msg)}},error:function(XMLHttpRequest){var data=eval("("+XMLHttpRequest.responseText+")");set_msg(data.msg)}});return false});var Modal=function(a,b){this.options=$.extend({},$.fn.modal.defaults,b);this.$element=$(a).delegate('[data-dismiss="modal"]',"click.dismiss.modal",$.proxy(this.hide,this))};Modal.prototype={constructor:Modal,toggle:function(){return this[!this.isShown?"show":"hide"]()},show:function(){var a=this;if(this.isShown)return;$("body").addClass("modal-open");this.isShown=true;this.$element.trigger("show");escape.call(this);backdrop.call(this,function(){var b=$.support.transition&&a.$element.hasClass("fade");!a.$element.parent().length&&a.$element.appendTo(document.body);a.$element.show();if(b){a.$element[0].offsetWidth}a.$element.addClass("in");b?a.$element.one($.support.transition.end,function(){a.$element.trigger("shown")}):a.$element.trigger("shown")})},hide:function(a){a&&a.preventDefault();if(!this.isShown)return;var b=this;this.isShown=false;$("body").removeClass("modal-open");escape.call(this);this.$element.trigger("hide").removeClass("in");$.support.transition&&this.$element.hasClass("fade")?hideWithTransition.call(this):hideModal.call(this)}};$.fn.modal=function(a){return this.each(function(){var b=$(this),c=b.data("modal"),d=typeof a=="object"&&a;if(!c)b.data("modal",c=new Modal(this,d));if(typeof a=="string")c[a]();else c.show()})};$.fn.modal.defaults={backdrop:true,keyboard:true};$.fn.modal.Constructor=Modal;$(function(){$("body").on("click.modal.data-api",'[data-toggle="modal"]',function(a){var b=$(this),c,d=$(b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),e=d.data("modal")?"toggle":$.extend({},d.data(),b.data());a.preventDefault();d.modal(e)})})})
+$(window).load(function(){function set_msg(msg){$('#msg').show().html(msg);setTimeout(function(){$('#msg').hide()},3000)}var emailReg=/^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;$("#submit").live("click",function(){var name=$('#name').val();if(name.length<1){$('#name').addClass('animated shake');setTimeout(function(){$('#name').removeClass('animated shake')},900);return false}var email=$('#email').val();if(email==''||!emailReg.test(email)){$('#email').addClass('animated shake');setTimeout(function(){$('#email').removeClass('animated shake')},900);return false}$.ajax({type:"POST",url:"rsvp",data:{name:name,email:email},dataType:"json",cache:false,success:function(data){if(data.status){set_msg(data.msg);$(".wrapper ul").prepend('<li class="attendee clear"><img src="'+data.pic+'"><p>'+data.name+'</p></li>');$(".form").slideUp("slow")}else{set_msg(data.msg)}},error:function(xhr,textStatus,err){data=xhr.responseText;set_msg(data.msg)}});return false})});
View
553 s3up
@@ -0,0 +1,553 @@
+<?PHP
+ date_default_timezone_set('America/Los_Angeles');
+
+ $shortops = 'ctzosu:p:v:rwf:';
+ $longopts = array('key:', 'secret:', 'log:', 'help');
+ $options = getopt($shortops, $longopts);
+
+ if(array_key_exists('help', $options) || $GLOBALS['argc'] == 1)
+ {
+ echo "Usage: " . $GLOBALS['argv'][0] . " [OPTION]... bucket-name/path file-or-folder-to-upload\n";
+ echo "\n";
+ echo "-c Use MD5 checksum to avoid duplicate PUTs, useful for resuming uploads\n";
+ echo "-t Append timestamp to uploaded filename for versioning\n";
+ echo "-z Upload a gzipped version in addition to the main file\n";
+ echo "-o If used with -z option, send only a gzipped file with same name\n";
+ echo "-v Appends a string of your choosing to each filename\n";
+ echo "-s Compress images using Smush.it before uploading\n";
+ echo "-r Recurse into directories\n";
+ echo "-w Only upload static web files\n";
+ echo "-f Folder in S3\n";
+ echo "\n";
+ echo "-u, --key Amazon S3 key\n";
+ echo "-p, --secret Amazon S3 private key\n";
+ echo "--log Log to specific file\n";
+ echo "\n";
+ echo " If --key and --secret are not specified,\n";
+ echo " s3up will read values from the AMZ_KEY\n";
+ echo " and AMZ_SECRET environment variables.\n";
+ echo "\n";
+ exit;
+ }
+
+ $AMZ_KEY = null;
+ $AMZ_SECRET = null;
+ if(isset($_SERVER['AMZ_KEY'])) $AMZ_KEY = $_SERVER['AMZ_KEY'];
+ if(isset($_SERVER['AMZ_SECRET'])) $AMZ_SECRET = $_SERVER['AMZ_SECRET'];
+ if(array_key_exists('u', $options)) $AMZ_KEY = $options['u'];
+ if(array_key_exists('p', $options)) $AMZ_SECRET = $options['p'];
+ if(array_key_exists('key', $options)) $AMZ_KEY = $options['key'];
+ if(array_key_exists('secret', $options)) $AMZ_SECRET = $options['secret'];
+ if(is_null($AMZ_KEY) || is_null($AMZ_SECRET))
+ die("Error: Amazon key and secret must be defined!\n");
+
+ $filename = $GLOBALS['argv'][$GLOBALS['argc'] - 1];
+
+ if(!file_exists($filename))
+ die("Error: '$filename' does not exist\n");
+
+ logMessage("\n\n\nStarting s3up...");
+ logMessage("Filename: $filename");
+
+ if(is_dir($filename))
+ {
+ $recursive = array_key_exists('r', $options) ? true : false;
+ $base_dir = $filename;
+ logMessage('Will upload ' . ($recursive ? 'recursively ' : '') . "from $base_dir");
+ dir_walk('upload', $filename, $recursive);
+ }
+ else {
+ logMessage("Uploading single file: $filename");
+ upload($filename);
+ }
+ logMessage('Finished!');
+
+ function logMessage($message)
+ {
+ static $logFile = null;
+ if ($logFile === null) {
+ global $options;
+ if (empty($options['log'])) {
+ $logFile = false;
+ } else {
+ $logFile = $options['log'];
+ if (file_exists($logFile)) {
+ unlink($logFile);
+ }
+ }
+ }
+
+ if (!$logFile) {
+ return;
+ }
+
+ file_put_contents($logFile, print_r($message, true) . PHP_EOL, FILE_APPEND);
+ }
+
+
+ function dir_walk($callback, $dir, $recursive = false)
+ {
+ if(is_null($dir)) return;
+
+ $dir = rtrim($dir, '/') . '/';
+ logMessage("Uploading directory $dir");
+ if($dh = opendir($dir))
+ {
+ while(($file = readdir($dh)) !== false)
+ {
+ if($file == '.' || $file == '..')
+ continue;
+
+ if(is_file($dir . $file))
+ $callback($dir . $file);
+ elseif($recursive && is_dir($dir . $file))
+ dir_walk($callback, $dir . $file, $recursive);
+ }
+ closedir($dh);
+ }
+ logMessage("Upload of $dir done.");
+ }
+
+ function upload($filename)
+ {
+ global $options;
+
+ if(!is_readable($filename))
+ echo "Error: Cannot read '$filename'\n";
+
+ if(strpos($filename, '.DS_Store') !== false) return;
+
+ logMessage("Starting upload of $filename...");
+
+ $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
+ $allowed = array('jpg', 'jpeg', 'png', 'gif', 'js', 'fla', 'flv', 'ico', 'css');
+ if(array_key_exists('w', $options) && !in_array($ext, $allowed)) return;
+
+ if(array_key_exists('s', $options))
+ {
+ if($ext == 'jpg' || $ext == 'jpeg' || $ext == 'png' || $ext == 'gif')
+ {
+ $img = new SmushIt($filename);
+ if(isset($img->compressedUrl) && strlen($img->compressedUrl) > 0)
+ {
+ $the_real_file = tempnam('/tmp', 's3up');
+ $fh = fopen($the_real_file, 'w');
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL,$img->compressedUrl);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_FILE, $fh);
+ curl_exec($ch);
+ logMessage("This file is a image and was smushed.");
+ upload_static_file($filename, $the_real_file);
+ return;
+ }
+ }
+ }
+
+ upload_static_file($filename);
+ }
+
+ function upload_static_file($filename, $the_real_file = null)
+ {
+ global $AMZ_KEY, $AMZ_SECRET, $options, $base_dir;
+
+ $bucket_and_path = rtrim($GLOBALS['argv'][$GLOBALS['argc'] - 2], '/') . '/';
+ $bucket_list = explode('/', $bucket_and_path);
+ $bucket = array_shift($bucket_list);
+ if(strpos($bucket_and_path, '/') !== false)
+ $path = substr($bucket_and_path, strpos($bucket_and_path, '/'));
+ else
+ $path = '';
+
+ $headers = array();
+ $headers['Expires'] = date('D, j M Y H:i:s', time() + (86400 * 360)) . ' GMT'; // 1 year
+
+ $info = pathinfo($filename);
+ $dir = $info['dirname'] . '/';
+
+ if (substr($dir, 0, 2) === './') $dir = substr($dir, 2);
+
+ if (!empty($options['f'])) {
+ $dir = $options['f'] . '/' . $dir;
+ }
+
+ // Version the file?
+ if(array_key_exists('t', $options))
+ $remote_name = $path . $info['filename'] . '.' . date('YmdHis');
+ else
+ $remote_name = $path . $info['filename'];
+
+ if(!empty($info['extension']))
+ $remote_name .= '.' . $info['extension'];
+
+ if(array_key_exists('v', $options))
+ $remote_name .= $options['v'];
+
+ // $remote_name = preg_replace("!^$base_dir!", '', $remote_name);
+ $remote_name = ltrim($remote_name, '/');
+
+ // Begin the upload proccess
+ $s3 = new S3($AMZ_KEY, $AMZ_SECRET);
+
+ // Should we check to see if the file has already been uploaded?
+ $ok_to_upload = true;
+ if(array_key_exists('c', $options))
+ {
+ $info = $s3->getObjectInfo($bucket, $remote_name);
+ if(substr($info['ETag'], 1, -2) == md5_file($filename))
+ {
+ $ok_to_upload = false;
+ echo "Skipping (MD5 match): http://$bucket.s3.amazonaws.com/$remote_name\n";
+ logMessage("Skipping (MD5 match): http://$bucket.s3.amazonaws.com/$remote_name");
+ }
+ }
+
+ // Actually upload the file...
+ $isJsOrCss = !empty($info['extension']) && in_array(strtolower($info['extension']), array('css', 'js'));
+ if($ok_to_upload && (!$isJsOrCss || !array_key_exists('o', $options)))
+ {
+ if(!is_null($the_real_file)) $filename = $the_real_file;
+ logMessage("Uploading...");
+ if($s3->uploadFile($bucket, $remote_name, $filename, true, $headers)) {
+ echo "http://$bucket.s3.amazonaws.com/$remote_name\n";
+ logMessage("File '$filename' uploaded to 'http://$bucket.s3.amazonaws.com/$remote_name'");
+ } else {
+ echo "Error: Unable to upload '$filename'\n";
+ logMessage("Upload of '$filename' failed.");
+ }
+ }
+
+ // Upload the gzipped version...
+ if(array_key_exists('z', $options))
+ {
+ $info = pathinfo($remote_name);
+ if($isJsOrCss)
+ {
+ if (!array_key_exists('o', $options)) {
+ $remote_name = $info['dirname'] . '/' . $info['filename'] . '.gz';
+ if(strlen($info['extension']) > 0)
+ $remote_name .= '.' . $info['extension'];
+ }
+
+ $gzname = tempnam('/tmp', 's3up');
+ if(!is_null($the_real_file)) $filename = $the_real_file;
+ shell_exec(sprintf('gzip -c %s > %s', escapeshellarg($filename), escapeshellarg($gzname)));
+ logMessage("The '$filename' has gziped to '$gzname'");
+
+ $headers['Content-Encoding'] = 'gzip';
+
+ // Should we check to see if the file has already been uploaded?
+ $ok_to_upload = true;
+ if(array_key_exists('c', $options))
+ {
+ $info = $s3->getObjectInfo($bucket, $remote_name);
+ if(substr($info['ETag'], 1, -2) == md5_file($local_name))
+ {
+ $ok_to_upload = false;
+ echo "Skipping (MD5 match): http://$bucket.s3.amazonaws.com/$remote_name\n";
+ logMessage("Skipping (MD5 match): http://$bucket.s3.amazonaws.com/$remote_name");
+ }
+ }
+
+ // Actually upload the file...
+ if($ok_to_upload)
+ {
+ logMessage("Uploading...");
+ if($s3->uploadFile($bucket, $remote_name, $gzname, true, $headers)) {
+ echo "http://$bucket.s3.amazonaws.com/$remote_name\n";
+ logMessage("File '$filename' ($gzname) uploaded to 'http://$bucket.s3.amazonaws.com/$remote_name'");
+ } else {
+ echo "Error: Unable to upload '$filename' (gzip version)\n";
+ logMessage("Error: Unable to upload '$filename' (gzip version)");
+ }
+ }
+ }
+ }
+ }
+
+ // ################################################################
+ // ################################################################
+ // ################################################################
+
+ class S3
+ {
+ private $key;
+ private $privateKey;
+ private $host;
+ private $date;
+ private $curlInfo;
+
+ public function __construct($key, $private_key, $host = 's3.amazonaws.com')
+ {
+ $this->key = $key;
+ $this->privateKey = $private_key;
+ $this->host = $host;
+ $this->date = gmdate('D, d M Y H:i:s T');
+ return true;
+ }
+
+ public function uploadFile($bucket_name, $s3_path, $fs_path, $web_accessible = false, $headers = null)
+ {
+ $s3_path = str_replace(' ', '%20', $s3_path);
+
+ $request = array('verb' => 'PUT',
+ 'resource' => "/$bucket_name/$s3_path",
+ 'content-md5' => $this->base64(md5_file($fs_path)));
+
+ $fh = fopen($fs_path, 'r');
+ $curl_opts = array('CURLOPT_PUT' => true,
+ 'CURLOPT_INFILE' => $fh,
+ 'CURLOPT_INFILESIZE' => filesize($fs_path),
+ 'CURLOPT_CUSTOMREQUEST' => 'PUT');
+
+ if(is_null($headers))
+ $headers = array();
+
+ $headers['Content-MD5'] = $request['content-md5'];
+
+ if($web_accessible === true && !isset($headers['x-amz-acl']))
+ $headers['x-amz-acl'] = 'public-read';
+
+ if(!isset($headers['Content-Type']))
+ {
+ $ext = pathinfo($s3_path, PATHINFO_EXTENSION);
+ $headers['Content-Type'] = isset($this->mimeTypes[strtolower($ext)]) ? $this->mimeTypes[strtolower($ext)] : 'application/octet-stream';
+ // print_r($headers);
+ }
+ $request['content-type'] = $headers['Content-Type'];
+
+ $result = $this->sendRequest($request, $headers, $curl_opts);
+ fclose($fh);
+ return $this->curlInfo['http_code'] == '200';
+ }
+
+ public function getObjectInfo($bucket_name, $s3_path)
+ {
+ $request = array('verb' => 'HEAD', 'resource' => "/$bucket_name/$s3_path");
+ $curl_opts = array('CURLOPT_HEADER' => true, 'CURLOPT_NOBODY' => true);
+ $result = $this->sendRequest($request, null, $curl_opts);
+ $xml = @simplexml_load_string($result);
+
+ if($xml !== false)
+ return false;
+
+ preg_match_all('/^(\S*?): (.*?)$/ms', $result, $matches);
+ $info = array();
+ for($i = 0; $i < count($matches[1]); $i++)
+ $info[$matches[1][$i]] = $matches[2][$i];
+
+ if(!isset($info['Last-Modified']))
+ return false;
+
+ return $info;
+ }
+
+ private function sendRequest($request, $headers = null, $curl_opts = null)
+ {
+ if(is_null($headers))
+ $headers = array();
+
+ $headers['Date'] = $this->date;
+ $headers['Authorization'] = 'AWS ' . $this->key . ':' . $this->signature($request, $headers);
+ foreach($headers as $k => $v)
+ $headers[$k] = "$k: $v";
+
+ $uri = 'http://' . $this->host . $request['resource'];
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $uri);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request['verb']);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ // curl_setopt($ch, CURLOPT_VERBOSE, true);
+
+ if(is_array($curl_opts))
+ {
+ foreach($curl_opts as $k => $v)
+ curl_setopt($ch, constant($k), $v);
+ }
+
+ // Try request a few times because amazon is crazy sometimes
+ $result = false;
+ $retries = 0;
+ while( ($result === false || $this->curlInfo['http_code'] != '200') && $retries < 3 )
+ {
+ if($retries++ > 0) sleep($retries);
+ $result = curl_exec($ch);
+ $this->curlInfo = curl_getinfo($ch);
+ }
+ if($retries == 3)
+ {
+ fwrite(STDERR, 'Curl error: ' . curl_error($ch) . "\n");
+ // print_r($this->curlInfo);
+ fwrite(STDERR,"AWS Response:\n$result");
+ }
+ curl_close($ch);
+ return $result;
+ }
+
+ private function signature($request, $headers = null)
+ {
+ if(is_null($headers))
+ $headers = array();
+
+ $CanonicalizedAmzHeadersArr = array();
+ $CanonicalizedAmzHeadersStr = '';
+ foreach($headers as $k => $v)
+ {
+ $k = strtolower($k);
+
+ if(substr($k, 0, 5) != 'x-amz') continue;
+
+ if(isset($CanonicalizedAmzHeadersArr[$k]))
+ $CanonicalizedAmzHeadersArr[$k] .= ',' . trim($v);
+ else
+ $CanonicalizedAmzHeadersArr[$k] = trim($v);
+ }
+ ksort($CanonicalizedAmzHeadersArr);
+
+ foreach($CanonicalizedAmzHeadersArr as $k => $v)
+ $CanonicalizedAmzHeadersStr .= "$k:$v\n";
+
+ $str = $request['verb'] . "\n";
+ $str .= isset($request['content-md5']) ? $request['content-md5'] . "\n" : "\n";
+ $str .= isset($request['content-type']) ? $request['content-type'] . "\n" : "\n";
+ $str .= isset($request['date']) ? $request['date'] . "\n" : $this->date . "\n";
+ $str .= $CanonicalizedAmzHeadersStr . preg_replace('/\?.*/', '', $request['resource']);
+
+ $sha1 = $this->hasher($str);
+ return $this->base64($sha1);
+ }
+
+ // Algorithm adapted (stolen) from http://pear.php.net/package/Crypt_HMAC/)
+ private function hasher($data)
+ {
+ $key = $this->privateKey;
+ if(strlen($key) > 64)
+ $key = pack('H40', sha1($key));
+ if(strlen($key) < 64)
+ $key = str_pad($key, 64, chr(0));
+ $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64));
+ $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64));
+ return sha1($opad . pack('H40', sha1($ipad . $data)));
+ }
+
+ private function base64($str)
+ {
+ $ret = '';
+ for($i = 0; $i < strlen($str); $i += 2)
+ $ret .= chr(hexdec(substr($str, $i, 2)));
+ return base64_encode($ret);
+ }
+
+ private function match($regex, $str, $i = 0)
+ {
+ if(preg_match($regex, $str, $match) == 1)
+ return $match[$i];
+ else
+ return false;
+ }
+
+ private $mimeTypes = array("323" => "text/h323", "acx" => "application/internet-property-stream", "ai" => "application/postscript", "aif" => "audio/x-aiff", "aifc" => "audio/x-aiff", "aiff" => "audio/x-aiff",
+ "asf" => "video/x-ms-asf", "asr" => "video/x-ms-asf", "asx" => "video/x-ms-asf", "au" => "audio/basic", "avi" => "video/quicktime", "axs" => "application/olescript", "bas" => "text/plain", "bcpio" => "application/x-bcpio", "bin" => "application/octet-stream", "bmp" => "image/bmp",
+ "c" => "text/plain", "cat" => "application/vnd.ms-pkiseccat", "cdf" => "application/x-cdf", "cer" => "application/x-x509-ca-cert", "class" => "application/octet-stream", "clp" => "application/x-msclip", "cmx" => "image/x-cmx", "cod" => "image/cis-cod", "cpio" => "application/x-cpio", "crd" => "application/x-mscardfile",
+ "crl" => "application/pkix-crl", "crt" => "application/x-x509-ca-cert", "csh" => "application/x-csh", "css" => "text/css", "dcr" => "application/x-director", "der" => "application/x-x509-ca-cert", "dir" => "application/x-director", "dll" => "application/x-msdownload", "dms" => "application/octet-stream", "doc" => "application/msword",
+ "dot" => "application/msword", "dvi" => "application/x-dvi", "dxr" => "application/x-director", "eps" => "application/postscript", "etx" => "text/x-setext", "evy" => "application/envoy", "exe" => "application/octet-stream", "fif" => "application/fractals", "flr" => "x-world/x-vrml", "gif" => "image/gif",
+ "gtar" => "application/x-gtar", "gz" => "application/x-gzip", "h" => "text/plain", "hdf" => "application/x-hdf", "hlp" => "application/winhlp", "hqx" => "application/mac-binhex40", "hta" => "application/hta", "htc" => "text/x-component", "htm" => "text/html", "html" => "text/html",
+ "htt" => "text/webviewhtml", "ico" => "image/x-icon", "ief" => "image/ief", "iii" => "application/x-iphone", "ins" => "application/x-internet-signup", "isp" => "application/x-internet-signup", "jfif" => "image/pipeg", "jpe" => "image/jpeg", "jpeg" => "image/jpeg", "jpg" => "image/jpeg",
+ "js" => "application/x-javascript", "latex" => "application/x-latex", "lha" => "application/octet-stream", "lsf" => "video/x-la-asf", "lsx" => "video/x-la-asf", "lzh" => "application/octet-stream", "m13" => "application/x-msmediaview", "m14" => "application/x-msmediaview", "m3u" => "audio/x-mpegurl", "man" => "application/x-troff-man",
+ "mdb" => "application/x-msaccess", "me" => "application/x-troff-me", "mht" => "message/rfc822", "mhtml" => "message/rfc822", "mid" => "audio/mid", "mny" => "application/x-msmoney", "mov" => "video/quicktime", "movie" => "video/x-sgi-movie", "mp2" => "video/mpeg", "mp3" => "audio/mpeg",
+ "mpa" => "video/mpeg", "mpe" => "video/mpeg", "mpeg" => "video/mpeg", "mpg" => "video/mpeg", "mpp" => "application/vnd.ms-project", "mpv2" => "video/mpeg", "ms" => "application/x-troff-ms", "mvb" => "application/x-msmediaview", "nws" => "message/rfc822", "oda" => "application/oda",
+ "p10" => "application/pkcs10", "p12" => "application/x-pkcs12", "p7b" => "application/x-pkcs7-certificates", "p7c" => "application/x-pkcs7-mime", "p7m" => "application/x-pkcs7-mime", "p7r" => "application/x-pkcs7-certreqresp", "p7s" => "application/x-pkcs7-signature", "pbm" => "image/x-portable-bitmap", "pdf" => "application/pdf", "pfx" => "application/x-pkcs12",
+ "pgm" => "image/x-portable-graymap", "pko" => "application/ynd.ms-pkipko", "pma" => "application/x-perfmon", "pmc" => "application/x-perfmon", "pml" => "application/x-perfmon", "pmr" => "application/x-perfmon", "pmw" => "application/x-perfmon", "png" => "image/png", "pnm" => "image/x-portable-anymap", "pot" => "application/vnd.ms-powerpoint", "ppm" => "image/x-portable-pixmap",
+ "pps" => "application/vnd.ms-powerpoint", "ppt" => "application/vnd.ms-powerpoint", "prf" => "application/pics-rules", "ps" => "application/postscript", "pub" => "application/x-mspublisher", "qt" => "video/quicktime", "ra" => "audio/x-pn-realaudio", "ram" => "audio/x-pn-realaudio", "ras" => "image/x-cmu-raster", "rgb" => "image/x-rgb",
+ "rmi" => "audio/mid", "roff" => "application/x-troff", "rtf" => "application/rtf", "rtx" => "text/richtext", "scd" => "application/x-msschedule", "sct" => "text/scriptlet", "setpay" => "application/set-payment-initiation", "setreg" => "application/set-registration-initiation", "sh" => "application/x-sh", "shar" => "application/x-shar",
+ "sit" => "application/x-stuffit", "snd" => "audio/basic", "spc" => "application/x-pkcs7-certificates", "spl" => "application/futuresplash", "src" => "application/x-wais-source", "sst" => "application/vnd.ms-pkicertstore", "stl" => "application/vnd.ms-pkistl", "stm" => "text/html", "svg" => "image/svg+xml", "sv4cpio" => "application/x-sv4cpio",
+ "sv4crc" => "application/x-sv4crc", "t" => "application/x-troff", "tar" => "application/x-tar", "tcl" => "application/x-tcl", "tex" => "application/x-tex", "texi" => "application/x-texinfo", "texinfo" => "application/x-texinfo", "tgz" => "application/x-compressed", "tif" => "image/tiff", "tiff" => "image/tiff",
+ "tr" => "application/x-troff", "trm" => "application/x-msterminal", "tsv" => "text/tab-separated-values", "txt" => "text/plain", "uls" => "text/iuls", "ustar" => "application/x-ustar", "vcf" => "text/x-vcard", "vrml" => "x-world/x-vrml", "wav" => "audio/x-wav", "wcm" => "application/vnd.ms-works",
+ "wdb" => "application/vnd.ms-works", "wks" => "application/vnd.ms-works", "wmf" => "application/x-msmetafile", "wps" => "application/vnd.ms-works", "wri" => "application/x-mswrite", "wrl" => "x-world/x-vrml", "wrz" => "x-world/x-vrml", "xaf" => "x-world/x-vrml", "xbm" => "image/x-xbitmap", "xla" => "application/vnd.ms-excel",
+ "xlc" => "application/vnd.ms-excel", "xlm" => "application/vnd.ms-excel", "xls" => "application/vnd.ms-excel", "xlt" => "application/vnd.ms-excel", "xlw" => "application/vnd.ms-excel", "xof" => "x-world/x-vrml", "xpm" => "image/x-xpixmap", "xwd" => "image/x-xwindowdump", "z" => "application/x-compress", "zip" => "application/zip");
+ }
+
+ class SmushIt
+ {
+ const SMUSH_URL = 'http://www.smushit.com/ysmush.it/ws.php?';
+
+ public $filename;
+ public $url;
+ public $compressedUrl;
+ public $size;
+ public $compressedSize;
+ public $savings;
+ public $error;
+
+ public function __construct($data = null)
+ {
+ if(!is_null($data))
+ {
+ if(preg_match('/https?:\/\//', $data) == 1)
+ $this->smushURL($data);
+ else
+ $this->smushFile($data);
+ }
+ }
+
+ public function smushURL($url)
+ {
+ $this->url = $url;
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, self::SMUSH_URL . 'img=' . $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
+ $json_str = curl_exec($ch);
+ curl_close($ch);
+
+ return $this->parseResponse($json_str);
+ }
+
+ public function smushFile($filename)
+ {
+ $this->filename = $filename;
+
+ if(!is_readable($filename))
+ {
+ $this->error = 'Could not read file';
+ return false;
+ }
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, self::SMUSH_URL);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, array('files' => '@' . $filename));
+ $json_str = curl_exec($ch);
+ curl_close($ch);
+
+ return $this->parseResponse($json_str);
+ }
+
+ private function parseResponse($json_str)
+ {
+ $this->error = null;
+ $json = json_decode($json_str);
+
+ if(is_null($json))
+ {
+ $this->error = 'Bad response from Smush.it web service';
+ return false;
+ }
+
+ if(isset($json->error))
+ {
+ $this->error = $json->error;
+ return false;
+ }
+
+ $this->size = $json->src_size;
+ $this->compressedUrl = $json->dest;
+ $this->compressedSize = $json->dest_size;
+ $this->savings = $json->percent;
+ return true;
+ }
+ }
View
2 views/home.jade
@@ -78,7 +78,7 @@ html(lang='en')
img(src=assetUrl + 'img/github.png' + assetVersion)
script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js')
- script(src=assetUrl + 'js/script.js' + assetVersion)
+ script(src=assetUrl + 'js/script.min.js' + assetVersion)
script
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");

0 comments on commit 1382407

Please sign in to comment.
Something went wrong with that request. Please try again.