Skip to content

Commit

Permalink
Use hex view for true binary files by default.
Browse files Browse the repository at this point in the history
  • Loading branch information
unconed committed Jun 13, 2011
1 parent 3bca9c8 commit 96152ec
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 17 deletions.
36 changes: 29 additions & 7 deletions Node/shell/meta.js
Expand Up @@ -432,18 +432,40 @@ exports.headers.prototype = {
* Mime type detection.
*/
exports.sniff = function (file, data) {
var parts = file.split('.'),
extension = parts.pop();
var type = mime.lookup(file),
utf8 = true,
binary = false;

// Detect valid UTF-8.
// Ignore trailing error due to possible truncation.
var attempt = data.toString('utf-8').replace(/�$/, ''), error = attempt.indexOf('�');
if (error != -1) {
utf8 = false;
}

if ((type = mime.lookup(file)) && (type != 'application/octet-stream')){
return type;
// Detect binary data.
if (/[\u0000]/(attempt)) {
binary = true;
}

if (/[^\u0001-\uFFFF]/('' + data)) {
return 'application/octet-stream';
// Plain text.
if (utf8 || !binary) {
return [ type, { charset: 'utf-8' } ];
}

return 'text/plain';
// Specific binary type.
if (type != 'application/octet-stream') {
return type;
}

// If data contains random binary data, then a significant part will be invalid / non-printable.
// Use hex-view.
if (attempt.replace(/[^\n\r\t\u0020-\uFFFC]/g, '').length < .8 * data.length) {
return [ type, { schema: 'termkit.hex' } ];
}

// Fallback, escaped binary text output.
return type;
};

/**
Expand Down
55 changes: 49 additions & 6 deletions Node/shell/reader.js
Expand Up @@ -8,6 +8,16 @@ var fs = require('fs'),
composePath = require('misc').composePath,
expandPath = require('misc').expandPath;

// Is x an object?
function isObject(x) {
return typeof x == 'object';
}

// Is x an array?
function isArray(x) {
return isObject(x) && x.constructor == [].constructor;
}

/**
* Data reader for termkit-style dataIn.
*
Expand Down Expand Up @@ -379,6 +389,32 @@ exports.filesReader.prototype = {
return types[0];
}

// Merge multiple types.
var merged = {}, hasParams = false;
for (var i in types) {
// Process params.
if (isArray(types[i])) {
var params = types[i][1];

// Only merge identical params.
for (var j in params) {
if (merged[j] === null) continue;
if (merged[j] != params[j]) {
merged[j] = null;
}
merged[j] = params[j];
}

// Strip params for merge.
types[i] = types[i][0];
}
}
// Check if there are params.
for (var j in merged) {
hasParams = true;
break;
}

function commonPrefix(types) {
// Sort types, inspect first/last strings.
types.sort();
Expand All @@ -399,6 +435,8 @@ exports.filesReader.prototype = {
return match;
}

var type = 'application/octed-stream';

prefix = commonPrefix(types);
if (!(/^[^\/]+\/[^\/]+$/(prefix))) {
// If we only matched a type category (e.g. text/),
Expand All @@ -410,22 +448,27 @@ exports.filesReader.prototype = {

if (!(/^[^\/]+\/[^\/]+$/(prefix))) {
// Replace with generic type.
return meta.default(prefix) || 'application/octet-stream';
type = meta.default(prefix) || 'application/octet-stream';
}
else {
type = prefix;
}

return prefix;
}
else {
// Only return a unified type for content types which can be composed safely.
var composable = meta.composable();
if (composable[prefix]) {
if (typeof composable[prefix] == 'string') {
return composable[prefix];
type = composable[prefix];
}
else {
type = prefix;
}
return prefix;
}
return 'application/octet-stream';
}

// Return with or without merged params.
return hasParams ? [ type, merged ] : type;
},

/**
Expand Down
4 changes: 2 additions & 2 deletions Node/test.js
Expand Up @@ -43,7 +43,7 @@ function mockClient(flow, callback) {
var messages = [], success = true, i;

client.send = function (message) {
messages.push(JSON.parse(message));
messages.push(message);
};

client.disconnect = function (message) {
Expand All @@ -53,7 +53,7 @@ function mockClient(flow, callback) {
var r = new router.router(client);
for (i in flow) (function (message) {
setTimeout(function () {
client.emit('message', JSON.stringify(message));
client.emit('message', message);
}, i * 100);
})(flow[i]);

Expand Down
5 changes: 3 additions & 2 deletions todo.txt
Expand Up @@ -3,8 +3,9 @@ Tasks:
[X] redefine ansi colors
[X] make fileReader with same pattern as reader.js
[X] cat multiple files -> octet-stream w/ type coercion
[ ] hex widget
[ ] hex utility
[X] hex widget
[X] hex utility
[ ] hex detection
[ ] backgrounding / new command trigger
[ ] move escapeUnixText into front-end, unixLegacy widget
[ ] command aliases
Expand Down

0 comments on commit 96152ec

Please sign in to comment.