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.
324 lines
7.8 KiB
324 lines
7.8 KiB
9 years ago
|
|
||
|
/*!
|
||
|
* Express - request
|
||
|
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||
|
* MIT Licensed
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Module dependencies.
|
||
|
*/
|
||
|
|
||
|
var http = require('http')
|
||
|
, req = http.IncomingMessage.prototype
|
||
|
, utils = require('./utils')
|
||
|
, parse = require('url').parse
|
||
|
, mime = require('mime');
|
||
|
|
||
|
/**
|
||
|
* Default flash formatters.
|
||
|
*
|
||
|
* @type Object
|
||
|
*/
|
||
|
|
||
|
var flashFormatters = exports.flashFormatters = {
|
||
|
s: function(val){
|
||
|
return String(val);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Return request header or optional default.
|
||
|
*
|
||
|
* The `Referrer` header field is special-cased,
|
||
|
* both `Referrer` and `Referer` will yield are
|
||
|
* interchangeable.
|
||
|
*
|
||
|
* Examples:
|
||
|
*
|
||
|
* req.header('Content-Type');
|
||
|
* // => "text/plain"
|
||
|
*
|
||
|
* req.header('content-type');
|
||
|
* // => "text/plain"
|
||
|
*
|
||
|
* req.header('Accept');
|
||
|
* // => undefined
|
||
|
*
|
||
|
* req.header('Accept', 'text/html');
|
||
|
* // => "text/html"
|
||
|
*
|
||
|
* @param {String} name
|
||
|
* @param {String} defaultValue
|
||
|
* @return {String}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
req.header = function(name, defaultValue){
|
||
|
switch (name = name.toLowerCase()) {
|
||
|
case 'referer':
|
||
|
case 'referrer':
|
||
|
return this.headers.referrer
|
||
|
|| this.headers.referer
|
||
|
|| defaultValue;
|
||
|
default:
|
||
|
return this.headers[name] || defaultValue;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Get `field`'s `param` value, defaulting to ''.
|
||
|
*
|
||
|
* Examples:
|
||
|
*
|
||
|
* req.get('content-disposition', 'filename');
|
||
|
* // => "something.png"
|
||
|
*
|
||
|
* @param {String} field
|
||
|
* @param {String} param
|
||
|
* @return {String}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
req.get = function(field, param){
|
||
|
var val = this.header(field);
|
||
|
if (!val) return '';
|
||
|
var regexp = new RegExp(param + ' *= *(?:"([^"]+)"|([^;]+))', 'i');
|
||
|
if (!regexp.exec(val)) return '';
|
||
|
return RegExp.$1 || RegExp.$2;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Short-hand for `require('url').parse(req.url).pathname`.
|
||
|
*
|
||
|
* @return {String}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
req.__defineGetter__('path', function(){
|
||
|
return parse(this.url).pathname;
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* Check if the _Accept_ header is present, and includes the given `type`.
|
||
|
*
|
||
|
* When the _Accept_ header is not present `true` is returned. Otherwise
|
||
|
* the given `type` is matched by an exact match, and then subtypes. You
|
||
|
* may pass the subtype such as "html" which is then converted internally
|
||
|
* to "text/html" using the mime lookup table.
|
||
|
*
|
||
|
* Examples:
|
||
|
*
|
||
|
* // Accept: text/html
|
||
|
* req.accepts('html');
|
||
|
* // => true
|
||
|
*
|
||
|
* // Accept: text/*; application/json
|
||
|
* req.accepts('html');
|
||
|
* req.accepts('text/html');
|
||
|
* req.accepts('text/plain');
|
||
|
* req.accepts('application/json');
|
||
|
* // => true
|
||
|
*
|
||
|
* req.accepts('image/png');
|
||
|
* req.accepts('png');
|
||
|
* // => false
|
||
|
*
|
||
|
* @param {String} type
|
||
|
* @return {Boolean}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
req.accepts = function(type){
|
||
|
var accept = this.header('Accept');
|
||
|
|
||
|
// normalize extensions ".json" -> "json"
|
||
|
if (type && '.' == type[0]) type = type.substr(1);
|
||
|
|
||
|
// when Accept does not exist, or is '*/*' return true
|
||
|
if (!accept || '*/*' == accept) {
|
||
|
return true;
|
||
|
} else if (type) {
|
||
|
// allow "html" vs "text/html" etc
|
||
|
if (!~type.indexOf('/')) type = mime.lookup(type);
|
||
|
|
||
|
// check if we have a direct match
|
||
|
if (~accept.indexOf(type)) return true;
|
||
|
|
||
|
// check if we have type/*
|
||
|
type = type.split('/')[0] + '/*';
|
||
|
return !!~accept.indexOf(type);
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Return the value of param `name` when present or `defaultValue`.
|
||
|
*
|
||
|
* - Checks route placeholders, ex: _/user/:id_
|
||
|
* - Checks query string params, ex: ?id=12
|
||
|
* - Checks urlencoded body params, ex: id=12
|
||
|
*
|
||
|
* To utilize urlencoded request bodies, `req.body`
|
||
|
* should be an object. This can be done by using
|
||
|
* the `connect.bodyParser` middleware.
|
||
|
*
|
||
|
* @param {String} name
|
||
|
* @param {Mixed} defaultValue
|
||
|
* @return {String}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
req.param = function(name, defaultValue){
|
||
|
// route params like /user/:id
|
||
|
if (this.params && this.params.hasOwnProperty(name) && undefined !== this.params[name]) {
|
||
|
return this.params[name];
|
||
|
}
|
||
|
// query string params
|
||
|
if (undefined !== this.query[name]) {
|
||
|
return this.query[name];
|
||
|
}
|
||
|
// request body params via connect.bodyParser
|
||
|
if (this.body && undefined !== this.body[name]) {
|
||
|
return this.body[name];
|
||
|
}
|
||
|
return defaultValue;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Queue flash `msg` of the given `type`.
|
||
|
*
|
||
|
* Examples:
|
||
|
*
|
||
|
* req.flash('info', 'email sent');
|
||
|
* req.flash('error', 'email delivery failed');
|
||
|
* req.flash('info', 'email re-sent');
|
||
|
* // => 2
|
||
|
*
|
||
|
* req.flash('info');
|
||
|
* // => ['email sent', 'email re-sent']
|
||
|
*
|
||
|
* req.flash('info');
|
||
|
* // => []
|
||
|
*
|
||
|
* req.flash();
|
||
|
* // => { error: ['email delivery failed'], info: [] }
|
||
|
*
|
||
|
* Formatting:
|
||
|
*
|
||
|
* Flash notifications also support arbitrary formatting support.
|
||
|
* For example you may pass variable arguments to `req.flash()`
|
||
|
* and use the %s specifier to be replaced by the associated argument:
|
||
|
*
|
||
|
* req.flash('info', 'email has been sent to %s.', userName);
|
||
|
*
|
||
|
* To add custom formatters use the `exports.flashFormatters` object.
|
||
|
*
|
||
|
* @param {String} type
|
||
|
* @param {String} msg
|
||
|
* @return {Array|Object|Number}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
req.flash = function(type, msg){
|
||
|
if (this.session === undefined) throw Error('req.flash() requires sessions');
|
||
|
var msgs = this.session.flash = this.session.flash || {};
|
||
|
if (type && msg) {
|
||
|
var i = 2
|
||
|
, args = arguments
|
||
|
, formatters = this.app.flashFormatters || {};
|
||
|
formatters.__proto__ = flashFormatters;
|
||
|
msg = utils.miniMarkdown(msg);
|
||
|
msg = msg.replace(/%([a-zA-Z])/g, function(_, format){
|
||
|
var formatter = formatters[format];
|
||
|
if (formatter) return formatter(utils.escape(args[i++]));
|
||
|
});
|
||
|
return (msgs[type] = msgs[type] || []).push(msg);
|
||
|
} else if (type) {
|
||
|
var arr = msgs[type];
|
||
|
delete msgs[type];
|
||
|
return arr || [];
|
||
|
} else {
|
||
|
this.session.flash = {};
|
||
|
return msgs;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Check if the incoming request contains the "Content-Type"
|
||
|
* header field, and it contains the give mime `type`.
|
||
|
*
|
||
|
* Examples:
|
||
|
*
|
||
|
* // With Content-Type: text/html; charset=utf-8
|
||
|
* req.is('html');
|
||
|
* req.is('text/html');
|
||
|
* // => true
|
||
|
*
|
||
|
* // When Content-Type is application/json
|
||
|
* req.is('json');
|
||
|
* req.is('application/json');
|
||
|
* // => true
|
||
|
*
|
||
|
* req.is('html');
|
||
|
* // => false
|
||
|
*
|
||
|
* Ad-hoc callbacks can also be registered with Express, to perform
|
||
|
* assertions again the request, for example if we need an expressive
|
||
|
* way to check if our incoming request is an image, we can register "an image"
|
||
|
* callback:
|
||
|
*
|
||
|
* app.is('an image', function(req){
|
||
|
* return 0 == req.headers['content-type'].indexOf('image');
|
||
|
* });
|
||
|
*
|
||
|
* Now within our route callbacks, we can use to to assert content types
|
||
|
* such as "image/jpeg", "image/png", etc.
|
||
|
*
|
||
|
* app.post('/image/upload', function(req, res, next){
|
||
|
* if (req.is('an image')) {
|
||
|
* // do something
|
||
|
* } else {
|
||
|
* next();
|
||
|
* }
|
||
|
* });
|
||
|
*
|
||
|
* @param {String} type
|
||
|
* @return {Boolean}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
req.is = function(type){
|
||
|
var fn = this.app.is(type);
|
||
|
if (fn) return fn(this);
|
||
|
var ct = this.headers['content-type'];
|
||
|
if (!ct) return false;
|
||
|
ct = ct.split(';')[0];
|
||
|
if (!~type.indexOf('/')) type = mime.lookup(type);
|
||
|
if (~type.indexOf('*')) {
|
||
|
type = type.split('/');
|
||
|
ct = ct.split('/');
|
||
|
if ('*' == type[0] && type[1] == ct[1]) return true;
|
||
|
if ('*' == type[1] && type[0] == ct[0]) return true;
|
||
|
return false;
|
||
|
}
|
||
|
return !! ~ct.indexOf(type);
|
||
|
};
|
||
|
|
||
|
// Callback for isXMLHttpRequest / xhr
|
||
|
|
||
|
function isxhr() {
|
||
|
return this.header('X-Requested-With', '').toLowerCase() === 'xmlhttprequest';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if the request was an _XMLHttpRequest_.
|
||
|
*
|
||
|
* @return {Boolean}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
req.__defineGetter__('isXMLHttpRequest', isxhr);
|
||
|
req.__defineGetter__('xhr', isxhr);
|