Fully end to end encrypted anonymous chat program. Server only stores public key lookup for users and the encrypted messages. No credentials are transfered to the server, but kept in local browser storage. This allows 100% safe chatting. https://safechat.ch
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
3.7 KiB

/*!
* Stylus - plugin - url
* Copyright (c) Automattic <developer.wordpress.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var utils = require('../utils')
, nodes = require('../nodes')
, fs = require('fs')
, path = require('path')
, sax = require('sax');
/**
* Initialize a new `Image` with the given `ctx` and `path.
*
* @param {Evaluator} ctx
* @param {String} path
* @api private
*/
var Image = module.exports = function Image(ctx, path) {
this.ctx = ctx;
this.path = utils.lookup(path, ctx.paths);
if (!this.path) throw new Error('failed to locate file ' + path);
};
/**
* Open the image for reading.
*
* @api private
*/
Image.prototype.open = function(){
this.fd = fs.openSync(this.path, 'r');
this.length = fs.fstatSync(this.fd).size;
this.extname = path.extname(this.path).slice(1);
};
/**
* Close the file.
*
* @api private
*/
Image.prototype.close = function(){
if (this.fd) fs.closeSync(this.fd);
};
/**
* Return the type of image, supports:
*
* - gif
* - png
* - jpeg
* - svg
*
* @return {String}
* @api private
*/
Image.prototype.type = function(){
var type
, buf = new Buffer(4);
fs.readSync(this.fd, buf, 0, 4, 0);
// GIF
if (0x47 == buf[0] && 0x49 == buf[1] && 0x46 == buf[2]) type = 'gif';
// PNG
else if (0x50 == buf[1] && 0x4E == buf[2] && 0x47 == buf[3]) type = 'png';
// JPEG
else if (0xff == buf[0] && 0xd8 == buf[1]) type = 'jpeg';
// SVG
else if ('svg' == this.extname) type = this.extname;
return type;
};
/**
* Return image dimensions `[width, height]`.
*
* @return {Array}
* @api private
*/
Image.prototype.size = function(){
var type = this.type()
, width
, height
, buf
, offset
, blockSize
, parser;
function uint16(b) { return b[1] << 8 | b[0]; }
function uint32(b) { return b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; }
// Determine dimensions
switch (type) {
case 'jpeg':
buf = new Buffer(this.length);
fs.readSync(this.fd, buf, 0, this.length, 0);
offset = 4;
blockSize = buf[offset] << 8 | buf[offset + 1];
while (offset < this.length) {
offset += blockSize;
if (offset >= this.length || 0xff != buf[offset]) break;
// SOF0 or SOF2 (progressive)
if (0xc0 == buf[offset + 1] || 0xc2 == buf[offset + 1]) {
height = buf[offset + 5] << 8 | buf[offset + 6];
width = buf[offset + 7] << 8 | buf[offset + 8];
} else {
offset += 2;
blockSize = buf[offset] << 8 | buf[offset + 1];
}
}
break;
case 'png':
buf = new Buffer(8);
// IHDR chunk width / height uint32_t big-endian
fs.readSync(this.fd, buf, 0, 8, 16);
width = uint32(buf);
height = uint32(buf.slice(4, 8));
break;
case 'gif':
buf = new Buffer(4);
// width / height uint16_t little-endian
fs.readSync(this.fd, buf, 0, 4, 6);
width = uint16(buf);
height = uint16(buf.slice(2, 4));
break;
case 'svg':
offset = Math.min(this.length, 1024);
buf = new Buffer(offset);
fs.readSync(this.fd, buf, 0, offset, 0);
buf = buf.toString('utf8');
parser = sax.parser(true);
parser.onopentag = function(node) {
if ('svg' == node.name && node.attributes.width && node.attributes.height) {
width = parseInt(node.attributes.width, 10);
height = parseInt(node.attributes.height, 10);
}
};
parser.write(buf).close();
break;
}
if ('number' != typeof width) throw new Error('failed to find width of "' + this.path + '"');
if ('number' != typeof height) throw new Error('failed to find height of "' + this.path + '"');
return [width, height];
};