<commit_before>/*
 * Copyright (C) 2010 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var fs = require('fs'),
    url = require('url'),
    sys = require('sys'),
    crypto = require('crypto'),
    Buffer = require('buffer').Buffer,
    mime = require('./mime'),
    uuid = require('./uuid'),
    session = require('./session'),
    ghp = require('./ghp'),
    gh = require('./grasshopper'),
    i18n = require('./i18n'),
    base64 = require('./base64');

var viewsDir = '.',
    defaultViewExtn = 'html',
    staticsDir = '.',
    defaultEncoding = 'utf8',
    defaultCharset = 'UTF-8',
    flashEnabled = true,
    layout = undefined;

exports.handleError = function(err, req, res, params) {
    if(params === undefined) {
        params={};
    }

    new RequestContext(req, res, params).handleError(err);
};

exports.configure = function(config) {
    if(config.viewsDir)
        viewsDir = config.viewsDir;
    if(config.defaultViewExtn)
        defaultViewExtn = config.defaultViewExtn;
    if(config.staticsDir)
        staticsDir = config.staticsDir;
    if(config.defaultCharset)
        defaultCharset = config.defaultCharset;
    if(config.defaultEncoding)
        defaultEncoding = config.defaultEncoding;
    if(config.layout)
        layout = config.layout;
    if(config.flashEnabled !== undefined)
        flashEnabled = config.flashEnabled;
};

// Class: RequestContext
function RequestContext(request, response, params) {
    this.request = request;
    this.response = response;
    this.params = params;
    this.model = {};

    this.status = 200;
    this.extn = this.getExtn();
    this.encoding = defaultEncoding;
    this.headers = {
        'content-type': mime.mimes[this.extn] 
                        ? mime.mimes[this.extn] 
                        : 'application/octet-stream',
        'date': new Date().toUTCString(),
        'x-powered-by': 'Grasshopper/0.3.0'
    };

    var cookieLine = request.headers['cookie'];
    if(cookieLine) {
        this.requestCookies = {};
        var cookies = cookieLine.split('; ');
        for(var i = 0; i < cookies.length; i++) {
            var cookieParts = cookies[i].split('=');
            if(cookieParts[0] == 'GHSESSION') {
                this.sessionId = decodeURIComponent(cookieParts[1]);
            } else {
                this.requestCookies[cookieParts[0]] = decodeURIComponent(cookieParts[1]);
            }
        }
    }

    i18n.init(this);
    this.charset = defaultCharset;
}

RequestContext.prototype.getExtn = function() {
    var extn = defaultViewExtn;
    var path = url.parse(this.request.url).pathname;
    if(path.match(/\.[^\/]+$/)) {
        extn = path.substring(path.lastIndexOf('.') + 1);
        this.requestExtn = extn;
    }

    return extn;
};

RequestContext.prototype.challengeAuth = function(type, options) {
    var challengeHeader = type + ' ';
    Object.keys(options).forEach(function(key) {
        challengeHeader += key + '="' + options[key] + '",';
    });
    challengeHeader = challengeHeader.substring(0, challengeHeader.length - 1);
    this.headers['www-authenticate'] = challengeHeader;
    this.renderError(401);
};

RequestContext.prototype.getAuth = function() {
	var authHeader = this.request.headers['authorization'];
	if(authHeader && authHeader.substring(0, 6) == "Basic ") {
		var credentials = base64.decode(authHeader.substring(6), this.encoding);
		var userPass = credentials.split(":", 2);
		return {
			username: userPass[0],
			password: <PASSWORD>[1]
		};
	} else if(authHeader && authHeader.substring(0, 7) == "Digest ") {
		var credentials = authHeader.substring(7);
        var auth = {};
        credentials.split(',').forEach(function(part) {
            var subParts = part.trim().split('=');
            var value = subParts[1];
            if(value.charAt(0) == '"'
                   && value.charAt(0) == value.charAt(value.length - 1)) {
                value = value.substring(1, value.length - 1);
            }
            auth[subParts[0]] = value;
        });
        return auth;
    }
};

RequestContext.prototype.addCookie = function(cookie) {
    var cookieLine = cookie.name + '=' + encodeURIComponent(cookie.value);
    cookieLine += cookie.path ? '; path=' + cookie.path : '';
    cookieLine += cookie.expires ? '; expires=' + cookie.expires : '';
    cookieLine += cookie.domain ? '; domain=' + cookie.domain : '';
    cookieLine += cookie.secure ? '; secure' : '';
    cookieLine += cookie.httpOnly ? '; HttpOnly' : '';

    if(this.headers['set-cookie']) {
        this.headers['set-cookie'] += '\r\nset-cookie: ' + cookieLine;
    } else {
        this.headers['set-cookie'] = cookieLine;
    }
};

RequestContext.prototype.rotateFlash = function(cb) {
    var self = this;
    this.flash = {};
    if(flashEnabled) {
        this.getSessionValue('flash', function(err, flash) {
            if(flash) {
                self.flash = flash;
                self.unsetSessionValue('flash', function() {
                    cb();
                });
            } else {
                cb();
            }
        });
    } else {
		cb();
	}
};

RequestContext.prototype.render = function(view, useLayout) {
    if(view === undefined) {
        this.response.writeHead(this.status, this.headers);
        this.response.end();
    } else if(typeof view == 'function') {
        this.response.writeHead(this.status, this.headers);
        if(this.request.method != 'HEAD') {
            view();
        }
        this.response.end();
    } else {
        this.model['flash'] = this.flash;
        if(useLayout === undefined) {
            useLayout = true;
        }
        var viewFile = viewsDir + '/' + view + '.' + this.extn;
        if(layout && useLayout) {
            this.model.view = view;
            viewFile = layout + '.' + this.extn;
        }<commit_msg>Fixed callback based rendering for async callbacks.<commit_after>/*
 * Copyright (C) 2010 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var fs = require('fs'),
    url = require('url'),
    sys = require('sys'),
    crypto = require('crypto'),
    Buffer = require('buffer').Buffer,
    mime = require('./mime'),
    uuid = require('./uuid'),
    session = require('./session'),
    ghp = require('./ghp'),
    gh = require('./grasshopper'),
    i18n = require('./i18n'),
    base64 = require('./base64');

var viewsDir = '.',
    defaultViewExtn = 'html',
    staticsDir = '.',
    defaultEncoding = 'utf8',
    defaultCharset = 'UTF-8',
    flashEnabled = true,
    layout = undefined;

exports.handleError = function(err, req, res, params) {
    if(params === undefined) {
        params={};
    }

    new RequestContext(req, res, params).handleError(err);
};

exports.configure = function(config) {
    if(config.viewsDir)
        viewsDir = config.viewsDir;
    if(config.defaultViewExtn)
        defaultViewExtn = config.defaultViewExtn;
    if(config.staticsDir)
        staticsDir = config.staticsDir;
    if(config.defaultCharset)
        defaultCharset = config.defaultCharset;
    if(config.defaultEncoding)
        defaultEncoding = config.defaultEncoding;
    if(config.layout)
        layout = config.layout;
    if(config.flashEnabled !== undefined)
        flashEnabled = config.flashEnabled;
};

// Class: RequestContext
function RequestContext(request, response, params) {
    this.request = request;
    this.response = response;
    this.params = params;
    this.model = {};

    this.status = 200;
    this.extn = this.getExtn();
    this.encoding = defaultEncoding;
    this.headers = {
        'content-type': mime.mimes[this.extn] 
                        ? mime.mimes[this.extn] 
                        : 'application/octet-stream',
        'date': new Date().toUTCString(),
        'x-powered-by': 'Grasshopper/0.3.0'
    };

    var cookieLine = request.headers['cookie'];
    if(cookieLine) {
        this.requestCookies = {};
        var cookies = cookieLine.split('; ');
        for(var i = 0; i < cookies.length; i++) {
            var cookieParts = cookies[i].split('=');
            if(cookieParts[0] == 'GHSESSION') {
                this.sessionId = decodeURIComponent(cookieParts[1]);
            } else {
                this.requestCookies[cookieParts[0]] = decodeURIComponent(cookieParts[1]);
            }
        }
    }

    i18n.init(this);
    this.charset = defaultCharset;
}

RequestContext.prototype.getExtn = function() {
    var extn = defaultViewExtn;
    var path = url.parse(this.request.url).pathname;
    if(path.match(/\.[^\/]+$/)) {
        extn = path.substring(path.lastIndexOf('.') + 1);
        this.requestExtn = extn;
    }

    return extn;
};

RequestContext.prototype.challengeAuth = function(type, options) {
    var challengeHeader = type + ' ';
    Object.keys(options).forEach(function(key) {
        challengeHeader += key + '="' + options[key] + '",';
    });
    challengeHeader = challengeHeader.substring(0, challengeHeader.length - 1);
    this.headers['www-authenticate'] = challengeHeader;
    this.renderError(401);
};

RequestContext.prototype.getAuth = function() {
	var authHeader = this.request.headers['authorization'];
	if(authHeader && authHeader.substring(0, 6) == "Basic ") {
		var credentials = base64.decode(authHeader.substring(6), this.encoding);
		var userPass = credentials.split(":", 2);
		return {
			username: userPass[0],
			password: <PASSWORD>]
		};
	} else if(authHeader && authHeader.substring(0, 7) == "Digest ") {
		var credentials = authHeader.substring(7);
        var auth = {};
        credentials.split(',').forEach(function(part) {
            var subParts = part.trim().split('=');
            var value = subParts[1];
            if(value.charAt(0) == '"'
                   && value.charAt(0) == value.charAt(value.length - 1)) {
                value = value.substring(1, value.length - 1);
            }
            auth[subParts[0]] = value;
        });
        return auth;
    }
};

RequestContext.prototype.addCookie = function(cookie) {
    var cookieLine = cookie.name + '=' + encodeURIComponent(cookie.value);
    cookieLine += cookie.path ? '; path=' + cookie.path : '';
    cookieLine += cookie.expires ? '; expires=' + cookie.expires : '';
    cookieLine += cookie.domain ? '; domain=' + cookie.domain : '';
    cookieLine += cookie.secure ? '; secure' : '';
    cookieLine += cookie.httpOnly ? '; HttpOnly' : '';

    if(this.headers['set-cookie']) {
        this.headers['set-cookie'] += '\r\nset-cookie: ' + cookieLine;
    } else {
        this.headers['set-cookie'] = cookieLine;
    }
};

RequestContext.prototype.rotateFlash = function(cb) {
    var self = this;
    this.flash = {};
    if(flashEnabled) {
        this.getSessionValue('flash', function(err, flash) {
            if(flash) {
                self.flash = flash;
                self.unsetSessionValue('flash', function() {
                    cb();
                });
            } else {
                cb();
            }
        });
    } else {
		cb();
	}
};

RequestContext.prototype.render = function(view, useLayout) {
    if(view === undefined) {
        this.response.writeHead(this.status, this.headers);
        this.response.end();
    } else if(typeof view == 'function') {
        this.response.writeHead(this.status, this.headers);
        if(this.request.method != 'HEAD') {
            var self = this;
            view(function() {
                self.response.end();
            });
        }
    } else {
        this.model['flash'] = this.flash;
        if(useLayout === undefined) {
            useLayout = true;
        }
        var viewFile = viewsDir + '/' + view + '.' + this.extn;
        if(layout && useLayout) {
            this.model.view = view;
            viewFile = layout + '.' + this.extn;
        }
{'fraction_non_alphanumeric': 0.14999610197240196, 'fraction_numerical': 0.008497700163717158, 'mean_word_length': 2.439142091152815, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '786263', 'n_tokens_mistral': 3868, 'n_tokens_neox': 3747, 'n_words': 779}