<commit_before>var url   = require('url'),
    http  = require('http'),
    https = require('https'),
    fs    = require('fs'),
    qs    = require('qs'),
    mime  = require('mime');
var exceptions = require('./exceptions'),
    InvalidRoboHydraRequestException =
        exceptions.InvalidRoboHydraRequestException,
    InvalidRoboHydraResponseException =
        exceptions.InvalidRoboHydraResponseException,
    InvalidRoboHydraResponseEventException =
        exceptions.InvalidRoboHydraResponseEventException;

(function () {
    "use strict";

    function serveStaticFile(filePath, res, opts) {
        opts = opts || {};
        var fsObject   = opts.fs      || fs;
        var mimeObject = opts.mime    || mime;
        var headers    = opts.headers || {};
        var indexFiles = opts.indexFiles || ['index.html', 'index.htm',
                                             'home.html',  'home.htm'];
        var path = filePath.split('?')[0];

        fsObject.stat(path, function(err, stats) {
            if (!err) {
                if (stats.isFile()) {
                    var mtime = stats.mtime,
                        modifiedSince = headers['if-modified-since'];

                    // Check modification date, if available
                    if (!modifiedSince || new Date(modifiedSince) < mtime) {
                        fsObject.readFile(path, function(err, data) {
                            res.headers["content-type"]  = mimeObject.lookup(path);
                            res.headers["last-modified"] = mtime.toUTCString();
                            res.send(data);
                        });

                        // 304 - Not Modified
                    } else {
                        res.statusCode = 304;
                        res.end();
                    }
                    // If it's a directory, try to serve one of the index files
                } else if (stats.isDirectory()) {
                    for (var i = 0, len = indexFiles.length; i < len; i++) {
                        var indexFilePath = path + "/" + indexFiles[i];
                        try {
                            // This will throw an exception if the file is
                            // not there
                            fsObject.statSync(indexFilePath);
                            serveStaticFile(indexFilePath, res, opts);
                            return;
                        } catch (e) {
                            // Ignore if the file is not there; otherwise...
                            if (e.code !== 'ENOENT') {
                                throw e;
                            }
                        }
                    }

                    res.statusCode = 403;
                    res.send("Directory listing forbidden");
                }

                // 404 - Not Found
            } else {
                res.statusCode = 404;
                res.send("Not Found");
            }
        });
    }

    function proxyRequest(req, res, proxyTo, opts) {
        opts = opts || {};
        var httpRequestFunction  = opts.httpRequestFunction  || http.request;
        var httpsRequestFunction = opts.httpsRequestFunction || https.request;
        var setHostHeader = opts.setHostHeader;

        var proxyUrl = proxyTo;
        if (typeof(proxyTo) === 'string') {
            proxyUrl = url.parse(proxyTo);
        }
        var proxyToHost = proxyUrl.hostname;
        var proxyToPort = proxyUrl.port ||
                (proxyUrl.protocol === 'https:' ? 443 : 80);
        var proxyToPath = proxyUrl.pathname;
        var requestFunction = (proxyUrl.protocol === 'https:') ?
                httpsRequestFunction : httpRequestFunction;
        var headers = {};
        for (var h in req.headers) { headers[h] = req.headers[h]; }
        if (setHostHeader) {
            headers.host = proxyToHost +
                (proxyUrl.port ? ":" + proxyUrl.port : "");
        }

        var proxyReq = requestFunction(
            {host: proxyToHost,
             port: proxyToPort,
             method: req.method,
             path: proxyToPath,
             headers: headers},
            function (proxyRes) {
                // Copy over headers and status code from proxied request
                res.statusCode = proxyRes.statusCode;
                res.headers    = proxyRes.headers;

                proxyRes.on("data", function (chunk) {
                    res.write(chunk);
                });

                proxyRes.on("end", function () {
                    res.end();
                });
            });

        proxyReq.on('error', function (err) {
            res.statusCode = 502;
            res.send('Bad Gateway! Could not proxy request. Invalid host or proxy destination down? Reported error was: ' + err);
        });

        if (req.rawBody) {
            proxyReq.write(req.rawBody);
        }
        proxyReq.end();
    }

    function stringForLog(req, res) {
        var remoteAddr = req.socket && req.socket.remoteAddress || "-";
        var date = new Date().toUTCString();
        var method = req.method;
        var url = req.url;
        var httpVersion = req.httpVersionMajor + '.' + req.httpVersionMinor;
        var status = res.statusCode;
        var resContentLength = res.headers['content-length'] || "-";
        var referrer = req.headers.referer || req.headers.referrer || "-";
        var userAgent = req.headers['user-agent'] || "-";

        return remoteAddr + " - - [" + date + "] \"" + method + " " +
            url + " HTTP/" + httpVersion + "\" " + status + " " +
            resContentLength + " \"" + referrer + "\" \"" + userAgent + "\"";
    }

    /*
     *  This function extends the given object with any number of
     *  other objects (parameters two, three, etc.), and returns it.
     */
    function extendObject(obj) {
        for (var i = 1, len = arguments.length; i < len; i++) {
            for (var p in arguments[i]) {
                if (arguments[i].hasOwnProperty(p)) {
                    obj[p] = arguments[i][p];
                }
            }
        }

        return obj;
    }

    function deprecationWarning(msg) {
        var prefix       = "*** WARNING: ",
            suffix       = " ***",
            borderLength = msg.length + prefix.length + suffix.length,
            border       = new Array(borderLength + 1).join("*");
        console.warn(border);
        console.warn(prefix + msg + suffix);
        console.warn(border);
    }

    var Request = function(props) {
        // From the constructor parameter
        this.url     = props.url;
        this.method  = (props.method || 'GET').toUpperCase();
        this.headers = extendObject({}, props.headers || {});
        this.rawBody = props.rawBody || new Buffer("");
        this.bodyParams = qs.parse(this.rawBody.toString());

        // Calculated
        this.queryParams = url.parse(this.url, true).query;
        Object.defineProperty(this, "getParams", {
            get: function() {
                deprecationWarning("'getParams' is deprecated, use 'queryParams' instead");
                return this.queryParams;
            }
        });

        if (this.url === undefined) {
            throw new InvalidRoboHydraRequestException('url', this.url);
        }
    };

    var Response = function(cb) {
        this.body       = new Buffer(0);
        this.statusCode = 200;
        this.headers    = {};
        this.ended      = false;
        var endHandlers = [];
        if (typeof cb === 'function') { endHandlers.push(cb); }
        this.eventHandlers = {head: [], data: [], end: endHandlers};
    };
    Response.prototype._fireEvent = function(eventName, evtObject) {
        var eventHandlers = this.eventHandlers[eventName];
        if (eventHandlers.length) {
            var finalEventObject = {};
            for (var p in evtObject) { finalEventObject[p] = evtObject[p]; }
            evtObject.type = eventName;
            for (var i = 0, len = eventHandlers.length; i < len; i++) {
                eventHandlers[i].call(this, evtObject);
            }
            return true;
        }
        return false;
    };
    Response.prototype.writeHead = function(statusCode, headers) {
        this.statusCode = statusCode;
        this.headers    = headers || {};
        if (this._fireEvent('head', {statusCode: this.statusCode,
                                     headers: this.headers})) {
            this._hasWrittenHead = true;
        }
    };
    Response.prototype.write = function(chunk) {
        chunk = chunk || "";
        if (typeof chunk === 'string') {
            chunk = new Buffer(chunk);
        }
        var tmp = new Buffer(this.body.length + chunk.length);
        this.body.copy(tmp);
        chunk.copy(tmp, this.body.length);
        this.body = tmp;
        if (! this._hasWrittenHead) {
            this._fireEvent('head', {statusCode: this.statusCode,
                                     headers: this.headers});
            this._hasWrittenHead = true;
        }
        this._fireEvent('data', {data: chunk});
        this._hasWrittenBody = true;
    };
    Response.prototype.send = function(data) {
        this.write(data);
        this.end();
    };
    Response.prototype.end = function() {
        if (! this._hasWrittenHead) {
            this._fireEvent('head', {statusCode: this.statusCode,
                                     headers: this.headers});
        }

        if (! this._hasWrittenBody && this.body.length) {
            this._fireEvent('data', {data: this.body});
        }

        this.ended = true;
        if (! this._fireEvent('end', {response: this})) {
            throw new InvalidRoboHydraResponseException(this);
        }
    };
    Response.prototype.copyFrom = function(res) {
        var self = this;
        ['statusCode', 'headers', 'body'].forEach(function(prop) {
            self[prop] = res[prop];
        });
    };
    Response.prototype.forward = function(res) {
        this.copyFrom(res);
        this.end();
    };
    Response.prototype.on = function(eventName, cb) {
        if (this.eventHandlers.hasOwnProperty(eventName)) {
            this.eventHandlers[eventName].push(cb);
            return this;
        } else {
            throw new InvalidRoboHydraResponseEventException(eventName);
        }
    };
    Response.prototype.chain = function(response) {
        this.on('head', function(evt) {
            response.writeHead(evt.statusCode, evt.headers);
        });
        this.on('data', function(evt) {
            response.write(evt.data);
        });
        this.on('end', function() {
            response.end();
        });
        return this;
    };

    exports.serveStaticFile    = serveStaticFile;
    exports.proxyRequest       = proxyRequest;
    exports.stringForLog       = stringForLog;
    exports.extendObject       = extendObject;
    exports.deprecationWarning = deprecationWarning;
    exports.Request            = Request;
    exports.Response           = Response;
}());
<commit_msg>Hint that eventHandlers in Response is "private"<commit_after>var url   = require('url'),
    http  = require('http'),
    https = require('https'),
    fs    = require('fs'),
    qs    = require('qs'),
    mime  = require('mime');
var exceptions = require('./exceptions'),
    InvalidRoboHydraRequestException =
        exceptions.InvalidRoboHydraRequestException,
    InvalidRoboHydraResponseException =
        exceptions.InvalidRoboHydraResponseException,
    InvalidRoboHydraResponseEventException =
        exceptions.InvalidRoboHydraResponseEventException;

(function () {
    "use strict";

    function serveStaticFile(filePath, res, opts) {
        opts = opts || {};
        var fsObject   = opts.fs      || fs;
        var mimeObject = opts.mime    || mime;
        var headers    = opts.headers || {};
        var indexFiles = opts.indexFiles || ['index.html', 'index.htm',
                                             'home.html',  'home.htm'];
        var path = filePath.split('?')[0];

        fsObject.stat(path, function(err, stats) {
            if (!err) {
                if (stats.isFile()) {
                    var mtime = stats.mtime,
                        modifiedSince = headers['if-modified-since'];

                    // Check modification date, if available
                    if (!modifiedSince || new Date(modifiedSince) < mtime) {
                        fsObject.readFile(path, function(err, data) {
                            res.headers["content-type"]  = mimeObject.lookup(path);
                            res.headers["last-modified"] = mtime.toUTCString();
                            res.send(data);
                        });

                        // 304 - Not Modified
                    } else {
                        res.statusCode = 304;
                        res.end();
                    }
                    // If it's a directory, try to serve one of the index files
                } else if (stats.isDirectory()) {
                    for (var i = 0, len = indexFiles.length; i < len; i++) {
                        var indexFilePath = path + "/" + indexFiles[i];
                        try {
                            // This will throw an exception if the file is
                            // not there
                            fsObject.statSync(indexFilePath);
                            serveStaticFile(indexFilePath, res, opts);
                            return;
                        } catch (e) {
                            // Ignore if the file is not there; otherwise...
                            if (e.code !== 'ENOENT') {
                                throw e;
                            }
                        }
                    }

                    res.statusCode = 403;
                    res.send("Directory listing forbidden");
                }

                // 404 - Not Found
            } else {
                res.statusCode = 404;
                res.send("Not Found");
            }
        });
    }

    function proxyRequest(req, res, proxyTo, opts) {
        opts = opts || {};
        var httpRequestFunction  = opts.httpRequestFunction  || http.request;
        var httpsRequestFunction = opts.httpsRequestFunction || https.request;
        var setHostHeader = opts.setHostHeader;

        var proxyUrl = proxyTo;
        if (typeof(proxyTo) === 'string') {
            proxyUrl = url.parse(proxyTo);
        }
        var proxyToHost = proxyUrl.hostname;
        var proxyToPort = proxyUrl.port ||
                (proxyUrl.protocol === 'https:' ? 443 : 80);
        var proxyToPath = proxyUrl.pathname;
        var requestFunction = (proxyUrl.protocol === 'https:') ?
                httpsRequestFunction : httpRequestFunction;
        var headers = {};
        for (var h in req.headers) { headers[h] = req.headers[h]; }
        if (setHostHeader) {
            headers.host = proxyToHost +
                (proxyUrl.port ? ":" + proxyUrl.port : "");
        }

        var proxyReq = requestFunction(
            {host: proxyToHost,
             port: proxyToPort,
             method: req.method,
             path: proxyToPath,
             headers: headers},
            function (proxyRes) {
                // Copy over headers and status code from proxied request
                res.statusCode = proxyRes.statusCode;
                res.headers    = proxyRes.headers;

                proxyRes.on("data", function (chunk) {
                    res.write(chunk);
                });

                proxyRes.on("end", function () {
                    res.end();
                });
            });

        proxyReq.on('error', function (err) {
            res.statusCode = 502;
            res.send('Bad Gateway! Could not proxy request. Invalid host or proxy destination down? Reported error was: ' + err);
        });

        if (req.rawBody) {
            proxyReq.write(req.rawBody);
        }
        proxyReq.end();
    }

    function stringForLog(req, res) {
        var remoteAddr = req.socket && req.socket.remoteAddress || "-";
        var date = new Date().toUTCString();
        var method = req.method;
        var url = req.url;
        var httpVersion = req.httpVersionMajor + '.' + req.httpVersionMinor;
        var status = res.statusCode;
        var resContentLength = res.headers['content-length'] || "-";
        var referrer = req.headers.referer || req.headers.referrer || "-";
        var userAgent = req.headers['user-agent'] || "-";

        return remoteAddr + " - - [" + date + "] \"" + method + " " +
            url + " HTTP/" + httpVersion + "\" " + status + " " +
            resContentLength + " \"" + referrer + "\" \"" + userAgent + "\"";
    }

    /*
     *  This function extends the given object with any number of
     *  other objects (parameters two, three, etc.), and returns it.
     */
    function extendObject(obj) {
        for (var i = 1, len = arguments.length; i < len; i++) {
            for (var p in arguments[i]) {
                if (arguments[i].hasOwnProperty(p)) {
                    obj[p] = arguments[i][p];
                }
            }
        }

        return obj;
    }

    function deprecationWarning(msg) {
        var prefix       = "*** WARNING: ",
            suffix       = " ***",
            borderLength = msg.length + prefix.length + suffix.length,
            border       = new Array(borderLength + 1).join("*");
        console.warn(border);
        console.warn(prefix + msg + suffix);
        console.warn(border);
    }

    var Request = function(props) {
        // From the constructor parameter
        this.url     = props.url;
        this.method  = (props.method || 'GET').toUpperCase();
        this.headers = extendObject({}, props.headers || {});
        this.rawBody = props.rawBody || new Buffer("");
        this.bodyParams = qs.parse(this.rawBody.toString());

        // Calculated
        this.queryParams = url.parse(this.url, true).query;
        Object.defineProperty(this, "getParams", {
            get: function() {
                deprecationWarning("'getParams' is deprecated, use 'queryParams' instead");
                return this.queryParams;
            }
        });

        if (this.url === undefined) {
            throw new InvalidRoboHydraRequestException('url', this.url);
        }
    };

    var Response = function(cb) {
        this.body       = new Buffer(0);
        this.statusCode = 200;
        this.headers    = {};
        this.ended      = false;
        var endHandlers = [];
        if (typeof cb === 'function') { endHandlers.push(cb); }
        this._eventHandlers = {head: [], data: [], end: endHandlers};
    }
    Response.prototype._fireEvent = function(eventName, evtObject) {
        var eventHandlers = this._eventHandlers[eventName];
        if (eventHandlers.length) {
            var finalEventObject = {};
            for (var p in evtObject) { finalEventObject[p] = evtObject[p]; }
            evtObject.type = eventName;
            for (var i = 0, len = eventHandlers.length; i < len; i++) {
                eventHandlers[i].call(this, evtObject);
            }
            return true;
        }
        return false;
    };
    Response.prototype.writeHead = function(statusCode, headers) {
        this.statusCode = statusCode;
        this.headers    = headers || {};
        if (this._fireEvent('head', {statusCode: this.statusCode,
                                     headers: this.headers})) {
            this._hasWrittenHead = true;
        }
    };
    Response.prototype.write = function(chunk) {
        chunk = chunk || "";
        if (typeof chunk === 'string') {
            chunk = new Buffer(chunk);
        }
        var tmp = new Buffer(this.body.length + chunk.length);
        this.body.copy(tmp);
        chunk.copy(tmp, this.body.length);
        this.body = tmp;
        if (! this._hasWrittenHead) {
            this._fireEvent('head', {statusCode: this.statusCode,
                                     headers: this.headers});
            this._hasWrittenHead = true;
        }
        this._fireEvent('data', {data: chunk});
        this._hasWrittenBody = true;
    };
    Response.prototype.send = function(data) {
        this.write(data);
        this.end();
    };
    Response.prototype.end = function() {
        if (! this._hasWrittenHead) {
            this._fireEvent('head', {statusCode: this.statusCode,
                                     headers: this.headers});
        }

        if (! this._hasWrittenBody && this.body.length) {
            this._fireEvent('data', {data: this.body});
        }

        this.ended = true;
        if (! this._fireEvent('end', {response: this})) {
            throw new InvalidRoboHydraResponseException(this);
        }
    };
    Response.prototype.copyFrom = function(res) {
        var self = this;
        ['statusCode', 'headers', 'body'].forEach(function(prop) {
            self[prop] = res[prop];
        });
    };
    Response.prototype.forward = function(res) {
        this.copyFrom(res);
        this.end();
    };
    Response.prototype.on = function(eventName, cb) {
        if (this._eventHandlers.hasOwnProperty(eventName)) {
            this._eventHandlers[eventName].push(cb);
            return this;
        } else {
            throw new InvalidRoboHydraResponseEventException(eventName);
        }
    };
    Response.prototype.chain = function(response) {
        this.on('head', function(evt) {
            response.writeHead(evt.statusCode, evt.headers);
        });
        this.on('data', function(evt) {
            response.write(evt.data);
        });
        this.on('end', function() {
            response.end();
        });
        return this;
    };

    exports.serveStaticFile    = serveStaticFile;
    exports.proxyRequest       = proxyRequest;
    exports.stringForLog       = stringForLog;
    exports.extendObject       = extendObject;
    exports.deprecationWarning = deprecationWarning;
    exports.Request            = Request;
    exports.Response           = Response;
}());
<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    crypto = require('crypto'),
    extend = require('soak').mixin,
    inherit = require('soak').inherit,
    EventEmitter = require('events').EventEmitter;

module.exports = {
  // Create a base observable object that inherits from EventEmitter. This
  // allows us to create new objects that can trigger events very easily.
  //
  // Example:
  //
  //   var Store = Observable.extend({
  //     save: function () {}
  //   });
  Observable: inherit(EventEmitter),

  // Helper function for creating an index file in a directory. It loads all
  // modules within the provided directory excluding the file provided as
  // "indexpath". These will then be returned.
  //
  // Example:
  //
  //   module.exports = utils.index(__dirname, __filename);
  index: function (dirname, indexpath) {
    var extensions = {js: 1},
        modules = {};

    indexpath = indexpath || path.join(dirname, 'index.js');

    // Load all exported objects into a single module.
    fs.readdirSync(dirname).forEach(function (filename) {
      var fullpath = path.join(dirname, filename),
          parts    = filename.split('.'),
          module, name;

      if (fullpath !== indexpath && extensions[parts.pop()] && '.' !== filename[0]) {
        name = parts.join('.');
        module = require(fullpath);

        // Grab the function name or module name if possible.
        if (typeof module.name === 'string') {
          name = module.name;
        }

        modules[name] = module;
      }
    });

    return modules;
  },

  // Takes an object and a series of method names. Each method will be
  // re-assigned to the object with the object bound as the methods scope. This
  // is generally useful for defining callback methods.
  //
  // An array of method names can also be passed.
  //
  // Example:
  //
  //   object = {onData: function () {}, onEnd: function () {});
  //   utils.bindAll(object, 'onData', 'onEnd');
  //
  //   // Same as doing.
  //   object.onData = object.onData.bind(object);
  //   object.onEnd  = object.onEnd.bind(object);
  bindAll: function (object /* args */) {
    var methods = [].slice.call(arguments, 1);
    if (arguments.length === 2 && Array.isArray(arguments[1])) {
      methods = arguments[1];
    }

    methods.forEach(function (method) {
      if (typeof object[method] === 'function') {
        object[method] = object[method].bind(object);
      }
    });

    return object;
  },

  // Extends the first argument with the properties of the subsequent
  // arguments.
  extend: extend,

  // Simplifies the process of extending existing objects.
  inherit: inherit,

  extract: function (obj /* keys */) {
    var keys = [].slice.call(arguments, 1),
        collected = {};

    keys.forEach(function (key) {
      if (obj[key]) {
        collected[key] = obj[key];
      }
    });

    return collected;
  },
  isAjax: function (req) {
    return (req.get('X-Requested-With') || '').toLowerCase() === 'xmlhttprequest';
  },
  shortcode: function () {
    var vowels = 'aeiou',
        consonants = 'bcdfghjklmnpqrstvwxyz',
        word = '', length = 6, index = 0, set;

    for (; index < length; index += 1) {
      set = (index % 2 === 0) ? vowels : consonants;
      word += set[Math.floor(Math.random() * set.length)];
    }

    return word;
  },
  // Returns a gravatar url for the email address provided. An optional size
  // parameter can be provided to specify the size of the avatar to generate.
  gravatar: function (email, size) {
    email = (email || '').trim().toLowerCase();
    var hash = crypto.createHash('md5').update(email).digest('hex');
    return 'http://www.gravatar.com/avatar/' + hash + '?s=' + (size || 100);
  },
  re: {
    flatten: /\s+/g,
    body: /<body.*?>\s*(.*)/m,
    meta: /<meta name="description" content="(.*?)"/,
    tags: /<[^>]+>/g,
    title: /<title>(.*)<\/title>/
  },
  titleForBin: function (bin) {
    // TODO: Use HTML parser or JSDOM
    var html = (bin.html || '').replace(this.re.flatten, ' '), // flatten
        javascript = (bin.javascript || '').replace(this.re.flatten, ' ').trim(),
        matches = (html.match(this.re.meta) || []);

    if (matches.length === 2 && matches[1].trim()) {
      return matches[1];
    }

    matches = (html.match(this.re.body) || []);

    if (matches.length === 2 && matches[1].trim()) {
      return matches[1].replace(this.re.tags, '').trim();
    }

    // No title return JavaScript.
    if (javascript) {
      return javascript;
    }

    matches = (html.match(this.re.title) || []);
    if (matches.length === 2 && matches[1].trim()) {
      return matches[1];
    }
    return '';
  },
  since: function (date) {
    var diff    = (+new Date() - date) / 1000,
        message = 'a long time',
        timespan;

    if (diff < 60) {
      timespan = Math.floor(diff);
      message  = '{timespan} second';
    }
    else if (diff < 3600) {
      timespan =  Math.floor(diff / 60);
      message  = 'about {timespan} minute';
    }
    else if (diff < 86400) {
      timespan = Math.floor(diff / 3600);
      message  = 'around {timespan} hour';
    }
    else if (diff < 604800) {
      timespan = Math.floor(diff / 86400);
      message  = 'about {timespan} day';
    }
    else if (diff < 2419200) {
      timespan = Math.ceil(diff / 604800);
      message  = 'nearly {timespan} week';
    }
    else if (diff < 29030400) {
      timespan = Math.floor(diff / 2419200);
      message  = 'about {timespan} month';
    }

    if (timespan !== 1 && timespan) {
      message += 's';
    }

    return message.replace('{timespan}', timespan) + ' ago';
  },
  queryStringForBin: function (bin, defaults) {
    var params = [];
    ['html', 'javascript', 'css'].forEach(function (key) {
      if (bin[key] !== defaults[key]) {
        params.push(key);
      }
    });
    return params.join(',');
  }
};
<commit_msg>Now correctly reading content from HTML and offering CSS as content. Fixes #162<commit_after>var fs = require('fs'),
    path = require('path'),
    crypto = require('crypto'),
    extend = require('soak').mixin,
    inherit = require('soak').inherit,
    EventEmitter = require('events').EventEmitter;

module.exports = {
  // Create a base observable object that inherits from EventEmitter. This
  // allows us to create new objects that can trigger events very easily.
  //
  // Example:
  //
  //   var Store = Observable.extend({
  //     save: function () {}
  //   });
  Observable: inherit(EventEmitter),

  // Helper function for creating an index file in a directory. It loads all
  // modules within the provided directory excluding the file provided as
  // "indexpath". These will then be returned.
  //
  // Example:
  //
  //   module.exports = utils.index(__dirname, __filename);
  index: function (dirname, indexpath) {
    var extensions = {js: 1},
        modules = {};

    indexpath = indexpath || path.join(dirname, 'index.js');

    // Load all exported objects into a single module.
    fs.readdirSync(dirname).forEach(function (filename) {
      var fullpath = path.join(dirname, filename),
          parts    = filename.split('.'),
          module, name;

      if (fullpath !== indexpath && extensions[parts.pop()] && '.' !== filename[0]) {
        name = parts.join('.');
        module = require(fullpath);

        // Grab the function name or module name if possible.
        if (typeof module.name === 'string') {
          name = module.name;
        }

        modules[name] = module;
      }
    });

    return modules;
  },

  // Takes an object and a series of method names. Each method will be
  // re-assigned to the object with the object bound as the methods scope. This
  // is generally useful for defining callback methods.
  //
  // An array of method names can also be passed.
  //
  // Example:
  //
  //   object = {onData: function () {}, onEnd: function () {});
  //   utils.bindAll(object, 'onData', 'onEnd');
  //
  //   // Same as doing.
  //   object.onData = object.onData.bind(object);
  //   object.onEnd  = object.onEnd.bind(object);
  bindAll: function (object /* args */) {
    var methods = [].slice.call(arguments, 1);
    if (arguments.length === 2 && Array.isArray(arguments[1])) {
      methods = arguments[1];
    }

    methods.forEach(function (method) {
      if (typeof object[method] === 'function') {
        object[method] = object[method].bind(object);
      }
    });

    return object;
  },

  // Extends the first argument with the properties of the subsequent
  // arguments.
  extend: extend,

  // Simplifies the process of extending existing objects.
  inherit: inherit,

  extract: function (obj /* keys */) {
    var keys = [].slice.call(arguments, 1),
        collected = {};

    keys.forEach(function (key) {
      if (obj[key]) {
        collected[key] = obj[key];
      }
    });

    return collected;
  },
  isAjax: function (req) {
    return (req.get('X-Requested-With') || '').toLowerCase() === 'xmlhttprequest';
  },
  shortcode: function () {
    var vowels = 'aeiou',
        consonants = 'bcdfghjklmnpqrstvwxyz',
        word = '', length = 6, index = 0, set;

    for (; index < length; index += 1) {
      set = (index % 2 === 0) ? vowels : consonants;
      word += set[Math.floor(Math.random() * set.length)];
    }

    return word;
  },
  // Returns a gravatar url for the email address provided. An optional size
  // parameter can be provided to specify the size of the avatar to generate.
  gravatar: function (email, size) {
    email = (email || '').trim().toLowerCase();
    var hash = crypto.createHash('md5').update(email).digest('hex');
    return 'http://www.gravatar.com/avatar/' + hash + '?s=' + (size || 100);
  },
  re: {
    flatten: /\s+/g,
    body: /<body.*?>\s*(.*)/m,
    meta: /<meta name="description" content="(.*?)"/,
    tags: /<[^>]+>/g,
    title: /<title>(.*)<\/title>/
  },
  titleForBin: function (bin) {
    var html = (bin.html || '').replace(this.re.flatten, ' '), // flatten
        javascript = (bin.javascript || '').replace(this.re.flatten, ' ').trim(),
        css = (bin.css || '').replace(this.re.flatten, ' ').trim(),
        matches = (html.match(this.re.meta) || []);

    // try to return the meta[description] first
    if (matches.length === 2 && matches[1].trim()) {
      return matches[1];
    }

    // then some of the body content with tags stripped
    matches = (html.match(this.re.body) || [,''])[1].replace(this.re.tags, '').trim();

    if (matches) {
      return matches;
    }

    // No title return JavaScript.
    if (javascript) {
      return javascript;
    }

    if (css) {
      return css;
    }

    matches = (html.match(this.re.title) || []);
    if (matches.length === 2 && matches[1].trim()) {
      return matches[1];
    }

    return '';
  },
  since: function (date) {
    var diff    = (+new Date() - date) / 1000,
        message = 'a long time',
        timespan;

    if (diff < 60) {
      timespan = Math.floor(diff);
      message  = '{timespan} second';
    }
    else if (diff < 3600) {
      timespan =  Math.floor(diff / 60);
      message  = 'about {timespan} minute';
    }
    else if (diff < 86400) {
      timespan = Math.floor(diff / 3600);
      message  = 'around {timespan} hour';
    }
    else if (diff < 604800) {
      timespan = Math.floor(diff / 86400);
      message  = 'about {timespan} day';
    }
    else if (diff < 2419200) {
      timespan = Math.ceil(diff / 604800);
      message  = 'nearly {timespan} week';
    }
    else if (diff < 29030400) {
      timespan = Math.floor(diff / 2419200);
      message  = 'about {timespan} month';
    }

    if (timespan !== 1 && timespan) {
      message += 's';
    }

    return message.replace('{timespan}', timespan) + ' ago';
  },
  queryStringForBin: function (bin, defaults) {
    var params = [];
    ['html', 'javascript', 'css'].forEach(function (key) {
      if (bin[key] !== defaults[key]) {
        params.push(key);
      }
    });
    return params.join(',');
  }
};
<|endoftext|>


<commit_before>var _    = require('underscore');
var path = require('path');
var fs   = require('fs');
var exists = fs.existsSync || path.existsSync;
var Promise = require('promise');

   // like the python dictionary pop.
   // return obj[prop] and remove property from obj.
   // if obj[prop] doesn't exist, return default value.
exports.pyPop = function (obj, prop, defaultValue){
   obj = (obj === undefined) ? {} : obj;

   if(obj.hasOwnProperty(prop)){
       var rv =  obj[prop];
       delete obj[prop];
       return rv;
   } else {
       return defaultValue;
   }
}

// useful type determination: Function, Object, string, number, Array, null, undefined, RegExp.
exports.trueTypeof = function(value) {
    if (value === null) {
        return "null";
    }
    var t = typeof value;
    switch(t) {
        case "function":
        case "object":
            if (value.constructor) {
                if (value.constructor.name) {
                    return value.constructor.name;
                } else {
                    // Internet Explorer
                    // Anonymous functions are stringified as follows: 'function () {}'
                    // => the regex below does not match
                    var match = value.constructor.toString().match(/^function (.+)\(.*$/);
                    if (match) {
                        return match[1];
                    }
                }
            }
            // fallback, for nameless constructors etc.
            return Object.prototype.toString.call(value).match(/^\[object (.+)\]$/)[1];
        default:
            return t;
    }
};

exports.getTimeLeft = function(target_date) {
  var difference = target_date - new Date();

  // basic math variables
  var _second = 1000,
    _minute = _second * 60,
    _hour = _minute * 60,
    _day = _hour * 24;

  // calculate dates
  var days = Math.floor(difference / _day),
    hours = Math.floor((difference % _day) / _hour),
    minutes = Math.floor((difference % _hour) / _minute),
    seconds = Math.floor((difference % _minute) / _second);

  // fix dates so that it will show two digits
  days = (String(days).length >= 2) ? days : '0' + days;
  hours = (String(hours).length >= 2) ? hours : '0' + hours;
  minutes = (String(minutes).length >= 2) ? minutes : '0' + minutes;
  seconds = (String(seconds).length >= 2) ? seconds : '0' + seconds;

  return [days, hours, minutes, seconds];
}

// route middleware to make sure a user is logged in
var isLoggedIn = function(doRecentCheck, req, res, next) {
  var app = req.app;
  var config = app.loadConfig('auth');

  var failed = !req.isAuthenticated();
  if (!failed && doRecentCheck) {
    //note: loginTime maybe a string since sessions are serialized as json
    failed = !req.session.loginTime ||
      !(new Date() - new Date(req.session.loginTime) <= config.recentLoginTimeoutSeconds*1000);
    if (failed) { //force reauthentication (e.g. for facebook login for example)
      req.session.reauthenticate  = true;
    }
  }

  // if user is not authenticated, redirect to login
  if (failed) {
    // remember original requested url
    req.session.returnTo = req.url;
    req.flash('login.danger', 'You need to login to access this page.');
    res.redirect('/login');
    return;
  }

  if (config.requireEmailVerification
      && isDefined(req, 'user.local.verified') && !req.user.local.verified) {
    if (config.requireEmailVerification == 'nag') {
      req.flash('warning', 'Please confirm your email address: '+ req.user.local.email +" Resend email.");
    } else if (config.requireEmailVerification == 'require') {
      // redirect to the email verification page
      req.session.returnTo = req.url;
      res.redirect('/verification-required');
      return;
    }
  }

  return next();
}

function requirePermission(permission, req, res, next) {
  var checker = req.app.accessControl;
  var user = req.user || checker.policy.defaultPrinciple;
  if (!user || !checker.check(user, req, permission)) {
    res.statusCode = 403;
    return next(new Error("Permission Denied"));
  }
  return next();
}

// route middleware to make sure a user is logged in
exports.isLoggedIn = _.partial(isLoggedIn, false);

// route middleware to make sure a user is logged in
exports.isRecentlyLoggedIn = _.partial(isLoggedIn, true);

// route middleware to make sure a user has permission
exports.requirePermission = function(guard) { return _.partial(requirePermission, guard); }

exports.renderer = function(view) {
  return function(req, res) { res.render(view);};
};

exports.eatErr = function(cb) {
  var startstack = new Error().stack;
  return function() {
    try {
      return cb.apply(cb, arguments);
    } catch (err){
      console.log("caught error:", err.stack);
      console.log("callback set at:", startstack);
    }
  }
};

exports.popAlertMessages = function(flashfunc, types, scopes) {
  var alerts = null;
  scopes = Array.isArray(scopes) ? scopes : [scopes];
  types = Array.isArray(types) ? types : [types];
  types.forEach(function(type){
    var msgs = scopes.reduce(function(current, scope) {
      return current.concat(flashfunc(
        (scope ? scope + '.' : '')+type));
      }, []);

      if (msgs.length) {
        if (!alerts) alerts = {};
        alerts[type] = msgs;
      }
    });
    return alerts;
};

exports.searchPath = function(paths, local) {
  for (var i=0; i< paths.length; i++) {
    var test = path.join(paths[i], local);
    if (exists(test)) {
      return test;
    }
  }
  throw new Error(local + " not found on " + JSON.stringify(paths));
}

// check for nested object properties
var isDefined = exports.isDefined = function(obj, propertyPath) {
  var target = obj;
  var props = propertyPath.split('.');
  for (var i = 0; i < props.length; i++) {
    var propName = props[i];
    if (typeof(target) == 'object' && propName in target) {
      target = target[propName];
    } else {
      return false;
    }
  };
  return true;
}

/*
Returns a promise that resolves any values that are promises.
Semantics are the same as Promise.all().
*/
exports.resolvePromises = function(obj) {
  var keys = _(obj).keys(), values = _(obj).values();
  return Promise.all(values).then(function(result) {
    return _.object(keys, result);
  });
}

/*
Run a list of promises sequentially.

@param stack A list of functions that return promises

Returns promise that resolves when the last promise does.
*/
exports.chainPromises = function(stack) {
//(stack) => stack.reduce((cb,p) => p.then((result) => cb(result)), Promise.resolve())
  var p = Promise.resolve();
  stack.forEach(function(cb){
    p = p.then(function(result) { return cb(result)})
  });
  return p;
}

/*
Like Promise.all() except rejected promises don't abort, instead are passed
through regular results.

@param promises Array of promises
@param onerror (optional) function called to resolve a rejection. (default: returns the rejection)
*/
exports.safeAllPromises = function(promises, onerror) {
  if (!onerror)
    onerror = function(err) { return err; };
  return Promise.all(promises.map(function (p){
    if (p && p.catch) //only if p is a promise
      return p.catch(onerror);
    else
      return p;
  }));
}

exports.exportModel = function(exports, schema) {
 exports.schemas[schema.metadata.modelName] = schema
 //lazily get models
 Object.defineProperty(exports.models, schema.metadata.modelName, {
    get: function() { return schema.getModel();}
 });
 Object.defineProperty(exports, schema.metadata.modelName, {
   get: function() { return schema.getModel();}
 });
}
<commit_msg>email verification copy<commit_after>var _    = require('underscore');
var path = require('path');
var fs   = require('fs');
var exists = fs.existsSync || path.existsSync;
var Promise = require('promise');

   // like the python dictionary pop.
   // return obj[prop] and remove property from obj.
   // if obj[prop] doesn't exist, return default value.
exports.pyPop = function (obj, prop, defaultValue){
   obj = (obj === undefined) ? {} : obj;

   if(obj.hasOwnProperty(prop)){
       var rv =  obj[prop];
       delete obj[prop];
       return rv;
   } else {
       return defaultValue;
   }
}

// useful type determination: Function, Object, string, number, Array, null, undefined, RegExp.
exports.trueTypeof = function(value) {
    if (value === null) {
        return "null";
    }
    var t = typeof value;
    switch(t) {
        case "function":
        case "object":
            if (value.constructor) {
                if (value.constructor.name) {
                    return value.constructor.name;
                } else {
                    // Internet Explorer
                    // Anonymous functions are stringified as follows: 'function () {}'
                    // => the regex below does not match
                    var match = value.constructor.toString().match(/^function (.+)\(.*$/);
                    if (match) {
                        return match[1];
                    }
                }
            }
            // fallback, for nameless constructors etc.
            return Object.prototype.toString.call(value).match(/^\[object (.+)\]$/)[1];
        default:
            return t;
    }
};

exports.getTimeLeft = function(target_date) {
  var difference = target_date - new Date();

  // basic math variables
  var _second = 1000,
    _minute = _second * 60,
    _hour = _minute * 60,
    _day = _hour * 24;

  // calculate dates
  var days = Math.floor(difference / _day),
    hours = Math.floor((difference % _day) / _hour),
    minutes = Math.floor((difference % _hour) / _minute),
    seconds = Math.floor((difference % _minute) / _second);

  // fix dates so that it will show two digits
  days = (String(days).length >= 2) ? days : '0' + days;
  hours = (String(hours).length >= 2) ? hours : '0' + hours;
  minutes = (String(minutes).length >= 2) ? minutes : '0' + minutes;
  seconds = (String(seconds).length >= 2) ? seconds : '0' + seconds;

  return [days, hours, minutes, seconds];
}

// route middleware to make sure a user is logged in
var isLoggedIn = function(doRecentCheck, req, res, next) {
  var app = req.app;
  var config = app.loadConfig('auth');

  var failed = !req.isAuthenticated();
  if (!failed && doRecentCheck) {
    //note: loginTime maybe a string since sessions are serialized as json
    failed = !req.session.loginTime ||
      !(new Date() - new Date(req.session.loginTime) <= config.recentLoginTimeoutSeconds*1000);
    if (failed) { //force reauthentication (e.g. for facebook login for example)
      req.session.reauthenticate  = true;
    }
  }

  // if user is not authenticated, redirect to login
  if (failed) {
    // remember original requested url
    req.session.returnTo = req.url;
    req.flash('login.danger', 'You need to login to access this page.');
    res.redirect('/login');
    return;
  }

  if (config.requireEmailVerification
      && isDefined(req, 'user.local.verified') && !req.user.local.verified) {
    if (config.requireEmailVerification == 'nag') {
      req.flash('warning', 'Please confirm your email address by clicking the link sent to '+ req.user.local.email +" Resend email.");
    } else if (config.requireEmailVerification == 'require') {
      // redirect to the email verification page
      req.session.returnTo = req.url;
      res.redirect('/verification-required');
      return;
    }
  }

  return next();
}

function requirePermission(permission, req, res, next) {
  var checker = req.app.accessControl;
  var user = req.user || checker.policy.defaultPrinciple;
  if (!user || !checker.check(user, req, permission)) {
    res.statusCode = 403;
    return next(new Error("Permission Denied"));
  }
  return next();
}

// route middleware to make sure a user is logged in
exports.isLoggedIn = _.partial(isLoggedIn, false);

// route middleware to make sure a user is logged in
exports.isRecentlyLoggedIn = _.partial(isLoggedIn, true);

// route middleware to make sure a user has permission
exports.requirePermission = function(guard) { return _.partial(requirePermission, guard); }

exports.renderer = function(view) {
  return function(req, res) { res.render(view);};
};

exports.eatErr = function(cb) {
  var startstack = new Error().stack;
  return function() {
    try {
      return cb.apply(cb, arguments);
    } catch (err){
      console.log("caught error:", err.stack);
      console.log("callback set at:", startstack);
    }
  }
};

exports.popAlertMessages = function(flashfunc, types, scopes) {
  var alerts = null;
  scopes = Array.isArray(scopes) ? scopes : [scopes];
  types = Array.isArray(types) ? types : [types];
  types.forEach(function(type){
    var msgs = scopes.reduce(function(current, scope) {
      return current.concat(flashfunc(
        (scope ? scope + '.' : '')+type));
      }, []);

      if (msgs.length) {
        if (!alerts) alerts = {};
        alerts[type] = msgs;
      }
    });
    return alerts;
};

exports.searchPath = function(paths, local) {
  for (var i=0; i< paths.length; i++) {
    var test = path.join(paths[i], local);
    if (exists(test)) {
      return test;
    }
  }
  throw new Error(local + " not found on " + JSON.stringify(paths));
}

// check for nested object properties
var isDefined = exports.isDefined = function(obj, propertyPath) {
  var target = obj;
  var props = propertyPath.split('.');
  for (var i = 0; i < props.length; i++) {
    var propName = props[i];
    if (typeof(target) == 'object' && propName in target) {
      target = target[propName];
    } else {
      return false;
    }
  };
  return true;
}

/*
Returns a promise that resolves any values that are promises.
Semantics are the same as Promise.all().
*/
exports.resolvePromises = function(obj) {
  var keys = _(obj).keys(), values = _(obj).values();
  return Promise.all(values).then(function(result) {
    return _.object(keys, result);
  });
}

/*
Run a list of promises sequentially.

@param stack A list of functions that return promises

Returns promise that resolves when the last promise does.
*/
exports.chainPromises = function(stack) {
//(stack) => stack.reduce((cb,p) => p.then((result) => cb(result)), Promise.resolve())
  var p = Promise.resolve();
  stack.forEach(function(cb){
    p = p.then(function(result) { return cb(result)})
  });
  return p;
}

/*
Like Promise.all() except rejected promises don't abort, instead are passed
through regular results.

@param promises Array of promises
@param onerror (optional) function called to resolve a rejection. (default: returns the rejection)
*/
exports.safeAllPromises = function(promises, onerror) {
  if (!onerror)
    onerror = function(err) { return err; };
  return Promise.all(promises.map(function (p){
    if (p && p.catch) //only if p is a promise
      return p.catch(onerror);
    else
      return p;
  }));
}

exports.exportModel = function(exports, schema) {
 exports.schemas[schema.metadata.modelName] = schema
 //lazily get models
 Object.defineProperty(exports.models, schema.metadata.modelName, {
    get: function() { return schema.getModel();}
 });
 Object.defineProperty(exports, schema.metadata.modelName, {
   get: function() { return schema.getModel();}
 });
}
<|endoftext|>


<commit_before>
var fs = require('fs');
var path = require('path');
var walk = require('fs-walk');
var crypto = require('crypto');

var dupMods = {};
var imageExtname = /jpg|gif|png|tif$/i;
var logFile = __dirname + './../results.txt';
var records = {};
var dupCount = 0;

module.exports = dupMods;

dupMods.prepare = function (fn) {
  console.log('');
  records = {}; // Clear the cached records from previous scans
  dupCount = 0; // Reset the dup count from previous scans
  var now = new Date().toString();
  fs.writeFile(logFile, now + '\r\n\r\n', function (err) {
    if (err) {
      return fn(err);
    }
    fn(null);
  });
};

dupMods.getImages = function (dir, fn) {
  var files = [];
  console.log('fetching images from all directories in ' + dir);
  walk.walkSync(dir, function (basedir, filename) {
    files.push(path.join(basedir, filename));
  });
  fn(null, files.filter(dupMods.isImage));
};

/**
 * Checks whether a filename ends in an image extension
 *
 * @param  {String}  file - The filepath to check
 * @return {Boolean}      - Answers: "Is the filepath to an image?"
 */
dupMods.isImage = function (file) {
  return imageExtname.test(path.extname(file));
};

dupMods.makeHash = function (buffer) {
  var hash = crypto.createHash('sha1');
  hash.update(buffer.toString('base64'));
  return hash.digest('hex');
};

dupMods.dupCheck = function (file, fn) {
  fs.readFile(file, function (err, buffer) {
    if (err) {
      return fn(err);
    }

    var checksum = dupMods.makeHash(buffer);

    if (records[checksum]) {
      dupCount++;
      dupMods.writeLog(dupCount, file, records[checksum]);
      return fn(null, true);
    }

    records[checksum] = file;
    fn(null, false);
  });
};

/**
 * Writes the results of the image-dup scan to log.txt
 *
 * @param  {String} filename1 [description]
 * @param  {String} filename2 [description]
 * @return {Function}       callback with error
 */
dupMods.writeLog = function (dupNo, filename1, filename2) {
  var string1 = dupNo + 'a) ' + filename1 + '\r\n';
  var string2 = dupNo + 'b) ' + filename2 + '\r\n';
  var string = string1 + string2 + '\r\n';

  fs.appendFile(logFile, string, function (err) {
    if (err) throw err;
  });
};

dupMods.done = function (msg) {
  console.log(msg);
};

/**
 * Logs a legibly-spaced console message for http requests
 *
 * @param  {String} requestMethod - eg, "GET", "POST", etc.
 * @param  {String} pathname      - eg. "/home"
 */
dupMods.logRequest = function (requestMethod, pathname) {
  var i;

  var message = requestMethod;
  for (i = requestMethod.length; i < 4; i++)
    message += ' ';

  message += ' ' + pathname;
  for (i = pathname.length; i < 15; i++)
    message += ' ';

  var date = '' + new Date();
  date = date.substr(0, date.indexOf('('));
  message += ' ' + date;

  console.log(message);
};<commit_msg>[update] utils.js (adds more descriptive text content for results.txt)<commit_after>
var fs = require('fs');
var path = require('path');
var walk = require('fs-walk');
var crypto = require('crypto');

var dupMods = {};
var imageExtname = /jpg|gif|png|tif$/i;
var logFile = __dirname + './../results.txt';
var records = {};
var dupCount = 0;

module.exports = dupMods;

dupMods.prepare = function (fn) {
  console.log('');
  records = {}; // Clear the cached records from previous scans
  dupCount = 0; // Reset the dup count from previous scans
  var now = new Date().toString();
  fs.writeFile(logFile, 'Scan complete: ' + now + '\r\n\r\n', function (err) {
    if (err) {
      return fn(err);
    }
    fn(null);
  });
};

dupMods.getImages = function (dir, fn) {
  var files = [];
  console.log('fetching images from all directories in ' + dir);
  walk.walkSync(dir, function (basedir, filename) {
    files.push(path.join(basedir, filename));
  });
  fn(null, files.filter(dupMods.isImage));
};

/**
 * Checks whether a filename ends in an image extension
 *
 * @param  {String}  file - The filepath to check
 * @return {Boolean}      - Answers: "Is the filepath to an image?"
 */
dupMods.isImage = function (file) {
  return imageExtname.test(path.extname(file));
};

dupMods.makeHash = function (buffer) {
  var hash = crypto.createHash('sha1');
  hash.update(buffer.toString('base64'));
  return hash.digest('hex');
};

dupMods.dupCheck = function (file, fn) {
  fs.readFile(file, function (err, buffer) {
    if (err) {
      return fn(err);
    }

    var checksum = dupMods.makeHash(buffer);

    if (records[checksum]) {
      dupCount++;
      dupMods.writeLog(dupCount, file, records[checksum]);
      return fn(null, true);
    }

    records[checksum] = file;
    fn(null, false);
  });
};

/**
 * Writes the results of the image-dup scan to log.txt
 *
 * @param  {String} filename1 [description]
 * @param  {String} filename2 [description]
 * @return {Function}       callback with error
 */
dupMods.writeLog = function (dupNo, filename1, filename2) {
  var string1 = dupNo + 'a) ' + filename1 + '\r\n';
  var string2 = dupNo + 'b) ' + filename2 + '\r\n';
  var string = string1 + string2 + '\r\n';

  fs.appendFile(logFile, string, function (err) {
    if (err) throw err;
  });
};

dupMods.done = function (msg) {
  console.log(msg);
};

/**
 * Logs a legibly-spaced console message for http requests
 *
 * @param  {String} requestMethod - eg, "GET", "POST", etc.
 * @param  {String} pathname      - eg. "/home"
 */
dupMods.logRequest = function (requestMethod, pathname) {
  var i;

  var message = requestMethod;
  for (i = requestMethod.length; i < 4; i++)
    message += ' ';

  message += ' ' + pathname;
  for (i = pathname.length; i < 15; i++)
    message += ' ';

  var date = '' + new Date();
  date = date.substr(0, date.indexOf('('));
  message += ' ' + date;

  console.log(message);
};<|endoftext|>


<commit_before>/**

 */

var dodgercms = dodgercms || {};

dodgercms.utils = (function() {
    'use strict';

    function getFolders(objects) {
        var folders = [];

        // push the root
        folders.push('/');

        // Loop through each object
        for (var i = 0; i < objects.length; i+=1) {
            var object = objects[i];
            var key = object.Key;

            // split and remove last slash for directory
            var parts = key.replace(/\/\s*$/, "").split('/');

            for (var j = 0; j < parts.length; j+=1) {
                var isFolder = false;

                // if the last part in the key has a trailing slash or if the part
                // is in not the last elemenet it is a path
                if ((j === parts.length-1 && key.substr(-1) === '/') || j !== parts.length-1) {
                    isFolder = true;
                }

                if (isFolder) {
                    var folder = parts.slice(0, j+1).join("/") + '/';

                    // push if unique
                    if ($.inArray(folder, folders) < 0) {
                        folders.push(key);
                    }
                }
            }
        }

        return folders;
    };

    function newFolder(key, dataBucket, siteBucket, callback) {
        dodgercms.s3.putObject(key, dataBucket, function(err, data) {
            if (err) {
                console.log(err, err.stack);
            } else {
                dodgercms.s3.putObject(key, siteBucket, function(err, data) {
                    if (err) {
                        console.log(err, err.stack);
                    } else {
                        if (typeof callback !== 'undefined') {
                            callback(null, key);
                        }
                    }
                });
            }
        });
    }

    // The directory is null if the "New Entry" button is used,
    // but if the user right clicks in the tree this should be populated
    function newEntry(folder, bucket, callback) {
        dodgercms.s3.listObjects(bucket, function(err, data) {
            if (err) {
                // TODO: handle error
            } else {
                var folders = getFolders(data.Contents);

                var context = {
                    folders: folders,
                    selectedFolder: (folder) ? folder : null
                };

                callback(null, data);
            }
        });
    }

    return {
        newFolder: newFolder,
        newEntry: newEntry,
        getFolders: getFolders
    };
}());<commit_msg>Fix wrong key being incorrectly pushed onto folders array<commit_after>/**

 */

var dodgercms = dodgercms || {};

dodgercms.utils = (function() {
    'use strict';

    function getFolders(objects) {
        var folders = [];

        // push the root
        folders.push('/');

        // Loop through each object
        for (var i = 0; i < objects.length; i+=1) {
            var object = objects[i];
            var key = object.Key;

            // split and remove last slash for directory
            var parts = key.replace(/\/\s*$/, "").split('/');

            for (var j = 0; j < parts.length; j+=1) {
                var isFolder = false;

                // if the last part in the key has a trailing slash or if the part
                // is in not the last elemenet it is a path
                if ((j === parts.length-1 && key.substr(-1) === '/') || j !== parts.length-1) {
                    isFolder = true;
                }

                if (isFolder) {
                    var folder = parts.slice(0, j).join("/") + '/';
                    // push if unique
                    if ($.inArray(folder, folders) < 0) {
                        folders.push(folder);
                    }
                }
            }
        }

        return folders;
    };

    function newFolder(key, dataBucket, siteBucket, callback) {
        dodgercms.s3.putObject(key, dataBucket, function(err, data) {
            if (err) {
                console.log(err, err.stack);
            } else {
                dodgercms.s3.putObject(key, siteBucket, function(err, data) {
                    if (err) {
                        console.log(err, err.stack);
                    } else {
                        if (typeof callback !== 'undefined') {
                            callback(null, key);
                        }
                    }
                });
            }
        });
    }

    // The directory is null if the "New Entry" button is used,
    // but if the user right clicks in the tree this should be populated
    function newEntry(folder, bucket, callback) {
        dodgercms.s3.listObjects(bucket, function(err, data) {
            if (err) {
                // TODO: handle error
            } else {
                var folders = getFolders(data.Contents);

                var context = {
                    folders: folders,
                    selectedFolder: (folder) ? folder : null
                };

                callback(null, data);
            }
        });
    }

    return {
        newFolder: newFolder,
        newEntry: newEntry,
        getFolders: getFolders
    };
}());<|endoftext|>


<commit_before>findIn = function (someObject /*, target */) {
  var target = _.rest(arguments)
  var currentObject = someObject
  for(it = 0; it < target.length; it++) {
    if (!(currentObject = currentObject[target[it]])) break
  }
  return currentObject || false
}

getSetting = function (fallback /*, keys...*/) {
  var keys = _.rest(arguments)
  return findIn.apply(null, [Meteor.settings].concat(keys)) || fallback
}<commit_msg>Fix a bug in findIn<commit_after>findIn = function (someObject /*, target */) {
  var target = _.rest(arguments)
  var currentObject = someObject || {}
  for(it = 0; it < target.length; it++) {
    if (!(currentObject = currentObject[target[it]])) break
  }
  return currentObject || false
}

getSetting = function (fallback /*, keys...*/) {
  var keys = _.rest(arguments)
  return findIn.apply(null, [Meteor.settings].concat(keys)) || fallback
}<|endoftext|>


<commit_before>/**
 * @module utils
 * @license MIT
 * @version 2017/11/13
 */

'use strict';

const path = require('path');
const util = require('util');
const css = require('@nuintun/css-deps');
const gutil = require('@nuintun/gulp-util');

const join = path.join;
const cache = new Map();
const dirname = path.dirname;
const debug = gutil.debug('gulp-css');

/**
 * @function transport
 * @param {Vinyl} vinyl
 * @param {Object} options
 * @returns {Promise}
 */
function transport(vinyl, options) {
  return gutil.transport(vinyl, options, cache, debug);
}

/**
 * @function resolve
 * @description Resolve a id from file or wwwroot path
 * @param {string} id
 * @param {Vinyl} vinyl
 * @param {string} wwwroot
 * @returns {string}
 */
function resolve(id, vinyl, wwwroot) {
  let path;

  // resolve
  if (gutil.isAbsolute(id)) {
    path = join(wwwroot, id);
  } else {
    path = join(dirname(vinyl.path), id);

    // out of wwwroot
    if (gutil.isOutBound(path, wwwroot)) {
      gutil.throwError('file: %s is out of bound of wwwroot: %s.', gutil.normalize(path), gutil.normalize(wwwroot));
    }
  }

  // debug
  debug('resolve path: %r', path);

  return path;
}

/**
 * @function print
 */
function print() {
  const message = gutil.apply(util.format, null, gutil.slice.call(arguments));

  process.stdout.write(gutil.chalk.reset.cyan.bold('  gulp-css ') + message + '\n');
}

/**
 * @function initOptions
 * @param {Object} options
 * @returns {Object}
 */
function initOptions(options) {
  options = gutil.extend(
    true,
    {
      map: [], // The map
      include: false, // Include
      prefix: null, // CSS prefix
      onpath: null, // CSS resource path callback
      cache: true, // Use memory file cahe
      wwwroot: '' // Web root dir
    },
    options
  );

  // Option wwwroot must be string
  if (!gutil.isString(options.wwwroot)) {
    gutil.throwError("options.wwwroot's value should be string.");
  }

  // Init wwwroot dir
  gutil.readonlyProperty(options, 'wwwroot', join(gutil.cwd, options.wwwroot));
  // Init plugins
  gutil.readonlyProperty(options, 'plugins', gutil.plugins(options.plugins, require('./plugins/index')));

  return options;
}

/**
 * @function transportId
 * @description Transport vinyl id
 * @param {Vinyl} vinyl
 * @param {Object} options
 * @returns {string}
 */
function transportId(vinyl, options) {
  // Parse module id
  let id = gutil.parseId(vinyl, options.wwwroot, vinyl.base);

  // Normalize
  id = gutil.normalize(id);

  // Debug
  debug('module id: %p', id);

  // Parse map
  id = gutil.parseMap(id, options.map, vinyl.base, options.wwwroot);
  // Normalize id
  id = gutil.normalize(id);

  // Rewrite vinyl path
  if (gutil.isAbsolute(id)) {
    vinyl.path = join(options.wwwroot, id);
  } else {
    vinyl.path = join(vinyl.cwd, vinyl.base, id);
  }

  // Set vinyl package info
  vinyl.package = { id: id };

  return id;
}

/**
 * @function transportCssDeps
 * @description Transport css dependencies.
 * @param {Vinyl} vinyl
 * @param {Object} options
 * @returns {Array}
 */
function transportCssDeps(vinyl, options) {
  const deps = [];
  const remote = [];
  const include = [];
  let onpath = options.onpath;
  let prefix = options.prefix;
  const pkg = vinyl.package || {};

  // Init css settings
  onpath = gutil.isFunction(onpath)
    ? (path, property) => {
        return options.onpath(path, vinyl.path, options.wwwroot, property);
      }
    : null;

  prefix = gutil.isFunction(prefix) ? prefix(vinyl.path, options.wwwroot) : prefix;

  // Replace imports and collect dependencies
  vinyl.contents = new Buffer(
    css(
      vinyl.contents,
      id => {
        if (gutil.isLocal(id)) {
          const src = id;

          // Normalize id
          id = gutil.normalize(id);

          // If end with /, find index file
          if (id.substring(id.length - 1) === '/') {
            id += 'index.css';
          }

          // Debug
          debug('module deps: %p', id);

          // Cache dependencie absolute path
          include.push({
            id: src,
            path: resolve(id, vinyl, options.wwwroot)
          });

          // Normalize id
          id = gutil.normalize(id);

          // Only when include is false, map can work
          if (!options.include) {
            // Parse map
            id = gutil.parseMap(id, options.map, vinyl.base, options.wwwroot);
            // Normalize id
            id = gutil.normalize(id);
          }
        } else {
          // Debug
          debug('module remote deps: %p', id);

          // Remote module
          remote.push(id);
        }

        // Cache dependencie id
        deps.push(id);

        // Include import css file
        if (options.include) {
          // Delete all import
          return false;
        }

        // Don't make changes
        return id;
      },
      { prefix: prefix, onpath: onpath }
    )
  );

  // Cache file dependencies
  vinyl.package = gutil.extend(pkg, {
    remote: remote,
    include: include,
    dependencies: deps
  });

  return deps;
}

// Exports
module.exports = {
  debug,
  cache,
  print,
  transport,
  initOptions,
  transportId,
  transportCssDeps
};
<commit_msg>:art: Update files<commit_after>/**
 * @module utils
 * @license MIT
 * @version 2017/11/13
 */

'use strict';

const path = require('path');
const util = require('util');
const css = require('@nuintun/css-deps');
const gutil = require('@nuintun/gulp-util');

const join = path.join;
const dirname = path.dirname;
const cache = new gutil.Cache();
const debug = gutil.debug('gulp-css');

/**
 * @function transport
 * @param {Vinyl} vinyl
 * @param {Object} options
 * @returns {Promise}
 */
function transport(vinyl, options) {
  return gutil.transport(vinyl, options, cache, debug);
}

/**
 * @function resolve
 * @description Resolve a id from file or wwwroot path
 * @param {string} id
 * @param {Vinyl} vinyl
 * @param {string} wwwroot
 * @returns {string}
 */
function resolve(id, vinyl, wwwroot) {
  let path;

  // resolve
  if (gutil.isAbsolute(id)) {
    path = join(wwwroot, id);
  } else {
    path = join(dirname(vinyl.path), id);

    // out of wwwroot
    if (gutil.isOutBound(path, wwwroot)) {
      gutil.throwError('file: %s is out of bound of wwwroot: %s.', gutil.normalize(path), gutil.normalize(wwwroot));
    }
  }

  // debug
  debug('resolve path: %r', path);

  return path;
}

/**
 * @function print
 */
function print() {
  const message = gutil.apply(util.format, null, gutil.slice.call(arguments));

  process.stdout.write(gutil.chalk.reset.cyan.bold('  gulp-css ') + message + '\n');
}

/**
 * @function initOptions
 * @param {Object} options
 * @returns {Object}
 */
function initOptions(options) {
  options = gutil.extend(
    true,
    {
      map: [], // The map
      include: false, // Include
      prefix: null, // CSS prefix
      onpath: null, // CSS resource path callback
      cache: true, // Use memory file cahe
      wwwroot: '' // Web root dir
    },
    options
  );

  // Option wwwroot must be string
  if (!gutil.isString(options.wwwroot)) {
    gutil.throwError("options.wwwroot's value should be string.");
  }

  // Init wwwroot dir
  gutil.readonlyProperty(options, 'wwwroot', join(gutil.cwd, options.wwwroot));
  // Init plugins
  gutil.readonlyProperty(options, 'plugins', gutil.plugins(options.plugins, require('./plugins/index')));

  return options;
}

/**
 * @function transportId
 * @description Transport vinyl id
 * @param {Vinyl} vinyl
 * @param {Object} options
 * @returns {string}
 */
function transportId(vinyl, options) {
  // Parse module id
  let id = gutil.parseId(vinyl, options.wwwroot, vinyl.base);

  // Normalize
  id = gutil.normalize(id);

  // Debug
  debug('module id: %p', id);

  // Parse map
  id = gutil.parseMap(id, options.map, vinyl.base, options.wwwroot);
  // Normalize id
  id = gutil.normalize(id);

  // Rewrite vinyl path
  if (gutil.isAbsolute(id)) {
    vinyl.path = join(options.wwwroot, id);
  } else {
    vinyl.path = join(vinyl.cwd, vinyl.base, id);
  }

  // Set vinyl package info
  vinyl.package = { id: id };

  return id;
}

/**
 * @function transportCssDeps
 * @description Transport css dependencies.
 * @param {Vinyl} vinyl
 * @param {Object} options
 * @returns {Array}
 */
function transportCssDeps(vinyl, options) {
  const deps = [];
  const remote = [];
  const include = [];
  let onpath = options.onpath;
  let prefix = options.prefix;
  const pkg = vinyl.package || {};

  // Init css settings
  onpath = gutil.isFunction(onpath)
    ? (path, property) => {
        return options.onpath(path, vinyl.path, options.wwwroot, property);
      }
    : null;

  prefix = gutil.isFunction(prefix) ? prefix(vinyl.path, options.wwwroot) : prefix;

  // Replace imports and collect dependencies
  vinyl.contents = new Buffer(
    css(
      vinyl.contents,
      id => {
        if (gutil.isLocal(id)) {
          const src = id;

          // Normalize id
          id = gutil.normalize(id);

          // If end with /, find index file
          if (id.substring(id.length - 1) === '/') {
            id += 'index.css';
          }

          // Debug
          debug('module deps: %p', id);

          // Cache dependencie absolute path
          include.push({
            id: src,
            path: resolve(id, vinyl, options.wwwroot)
          });

          // Normalize id
          id = gutil.normalize(id);

          // Only when include is false, map can work
          if (!options.include) {
            // Parse map
            id = gutil.parseMap(id, options.map, vinyl.base, options.wwwroot);
            // Normalize id
            id = gutil.normalize(id);
          }
        } else {
          // Debug
          debug('module remote deps: %p', id);

          // Remote module
          remote.push(id);
        }

        // Cache dependencie id
        deps.push(id);

        // Include import css file
        if (options.include) {
          // Delete all import
          return false;
        }

        // Don't make changes
        return id;
      },
      { prefix: prefix, onpath: onpath }
    )
  );

  // Cache file dependencies
  vinyl.package = gutil.extend(pkg, {
    remote: remote,
    include: include,
    dependencies: deps
  });

  return deps;
}

// Exports
module.exports = {
  debug,
  cache,
  print,
  transport,
  initOptions,
  transportId,
  transportCssDeps
};
<|endoftext|>


<commit_before>const sqlString = require('sqlstring');

/*
 * Pluralize a word based on count
 */
exports.pluralize = (word, count) => {
  return count === 1 ? word : `${word}s`;
};

/*
 * Calculate seconds from midnight for HH:mm:ss / H:m:s
 */
exports.calculateHourTimestamp = time => {
  const split = time.split(':').map(d => Number.parseInt(d, 10));
  if (split.length !== 3) {
    return null;
  }

  return (split[0] * 3600) + (split[1] * 60) + split[2];
};

exports.formatSelectClause = fields => {
  let selectClause = 'SELECT ';
  if (fields.length > 0) {
    selectClause += fields.map(fieldName => sqlString.escapeId(fieldName)).join(', ');
  } else {
    selectClause += '*';
  }

  return selectClause;
};

exports.formatWhereClause = (key, value) => {
  if (Array.isArray(value)) {
    return `${sqlString.escapeId(key)} IN (${value.map(v => sqlString.escape(v)).join(', ')})`;
  }

  if (value === null) {
    return `${sqlString.escapeId(key)} IS NULL`;
  }

  return `${sqlString.escapeId(key)} = ${sqlString.escape(value)}`;
};

exports.formatWhereClauses = query => {
  if (Object.keys(query).length === 0) {
    return '';
  }

  const whereClauses = Object.entries(query).map(([key, value]) => exports.formatWhereClause(key, value));
  return `WHERE ${whereClauses.join(' AND ')}`;
};

exports.formatOrderByClause = orderBy => {
  let orderByClause = '';

  if (orderBy.length > 0) {
    orderByClause += 'ORDER BY ';

    orderByClause += orderBy.map(([key, value]) => {
      const direction = value === 'DESC' ? 'DESC' : 'ASC';
      return `${sqlString.escapeId(key)} ${direction}`;
    }).join(', ');
  }

  return orderByClause;
};
<commit_msg>lints<commit_after>const sqlString = require('sqlstring');

/*
 * Pluralize a word based on count
 */
exports.pluralize = (word, count) => {
  return count === 1 ? word : `${word}s`;
};

/*
 * Calculate seconds from midnight for HH:mm:ss / H:m:s
 */
exports.calculateHourTimestamp = time => {
  const split = time.split(':').map(d => Number.parseInt(d, 10));
  if (split.length !== 3) {
    return null;
  }

  return (split[0] * 3600) + (split[1] * 60) + split[2];
};

exports.formatSelectClause = fields => {
  const selectItem = fields.length > 0 ? fields.map(fieldName => sqlString.escapeId(fieldName)).join(', ') : '*';

  return `SELECT ${selectItem}`;
};

exports.formatWhereClause = (key, value) => {
  if (Array.isArray(value)) {
    return `${sqlString.escapeId(key)} IN (${value.map(v => sqlString.escape(v)).join(', ')})`;
  }

  if (value === null) {
    return `${sqlString.escapeId(key)} IS NULL`;
  }

  return `${sqlString.escapeId(key)} = ${sqlString.escape(value)}`;
};

exports.formatWhereClauses = query => {
  if (Object.keys(query).length === 0) {
    return '';
  }

  const whereClauses = Object.entries(query).map(([key, value]) => exports.formatWhereClause(key, value));
  return `WHERE ${whereClauses.join(' AND ')}`;
};

exports.formatOrderByClause = orderBy => {
  let orderByClause = '';

  if (orderBy.length > 0) {
    orderByClause += 'ORDER BY ';

    orderByClause += orderBy.map(([key, value]) => {
      const direction = value === 'DESC' ? 'DESC' : 'ASC';
      return `${sqlString.escapeId(key)} ${direction}`;
    }).join(', ');
  }

  return orderByClause;
};
<|endoftext|>


<commit_before>// --------------------
// utility functions
// --------------------

// modules
var _ = require('lodash');

// exports
module.exports = {
	// acts on object, inserts key/value pair at 1st position
	unshift: function(obj, key, value) {
		var temp = {};

		for (var thisKey in obj) {
			temp[thisKey] = obj[thisKey];
			delete obj[thisKey];
		}

		obj[key] = value;

		for (thisKey in temp) {
			obj[thisKey] = temp[thisKey];
		}

		return obj;
	},

	// removes obj[key] and returns it
	pop: function(obj, key) {
		var value = obj[key];
		delete obj[key];
		return value;
	},

	// setNoUndef(obj, key [,value] [,value] [,value])
	// sets obj[key] = value, but deleting undefined values
	setNoUndef: function(obj, key) {
		var value;
		for (var i = 2; i < arguments.length; i++) {
			value = arguments[i];
			if (value !== undefined) {
				obj[key] = value;
				break;
			}
		}

		if (value === undefined) delete obj[key];

		return obj;
	},

	// defaultNoUndef(obj, key [,value] [,value] [,value])
	// sets obj[key] = value if obj[key] is undefined
	defaultNoUndef: function(obj, key) {
		if (obj[key] !== undefined) return obj;

		var value;
		for (var i = 2; i < arguments.length; i++) {
			value = arguments[i];
			if (value !== undefined) {
				obj[key] = value;
				break;
			}
		}

		return obj;
	},

	// extendNoUndef: function(obj [,fromObj] [,fromObj] [,fromObj])
	// sets all keys from fromObj onto obj, deleting undefined values
	extendNoUndef: function(obj) {
		var fromObj;
		for (var i = 1; i < arguments.length; i++) {
			fromObj = arguments[i];
			_.forIn(fromObj, function(value, key) {
				if (value === undefined) {
					delete obj[key];
				} else {
					obj[key] = value;
				}
			});
		}

		return obj;
	},

	// defaultsNoUndef: function(obj [,fromObj] [,fromObj] [,fromObj])
	// sets all keys from fromObj onto obj where obj[key] is undefined, ignoring undefined values
	defaultsNoUndef: function(obj) {
		var fromObj;
		for (var i = 1; i < arguments.length; i++) {
			fromObj = arguments[i];
			_.forIn(fromObj, function(value, key) {
				if (obj[key] === undefined && value !== undefined) obj[key] = value;
			});
		}

		return obj;
	},

	// string format conversion from camelCase to human-readable format
	// e.g. 'fooBar' -> 'Foo Bar'
	humanize: function(str) {
		return str[0].toUpperCase() + str.slice(1).replace(/([A-Z])/g, ' $1');
	},

	// checks if str ends with needle
	endsWith: function(str, needle) {
		return str.slice(str.length - needle.length) == needle;
	},

	// if value is function, run it with arguments and return result, otherwise return input
	functionValue: function(val) {
		if (!_.isFunction(val)) return val;

		var args = Array.prototype.slice.call(arguments, 1);
		return val.apply(args);
	}
};
<commit_msg>humanize utility function handles underscore style<commit_after>// --------------------
// utility functions
// --------------------

// modules
var _ = require('lodash');

// exports
module.exports = {
	// acts on object, inserts key/value pair at 1st position
	unshift: function(obj, key, value) {
		var temp = {};

		for (var thisKey in obj) {
			temp[thisKey] = obj[thisKey];
			delete obj[thisKey];
		}

		obj[key] = value;

		for (thisKey in temp) {
			obj[thisKey] = temp[thisKey];
		}

		return obj;
	},

	// removes obj[key] and returns it
	pop: function(obj, key) {
		var value = obj[key];
		delete obj[key];
		return value;
	},

	// setNoUndef(obj, key [,value] [,value] [,value])
	// sets obj[key] = value, but deleting undefined values
	setNoUndef: function(obj, key) {
		var value;
		for (var i = 2; i < arguments.length; i++) {
			value = arguments[i];
			if (value !== undefined) {
				obj[key] = value;
				break;
			}
		}

		if (value === undefined) delete obj[key];

		return obj;
	},

	// defaultNoUndef(obj, key [,value] [,value] [,value])
	// sets obj[key] = value if obj[key] is undefined
	defaultNoUndef: function(obj, key) {
		if (obj[key] !== undefined) return obj;

		var value;
		for (var i = 2; i < arguments.length; i++) {
			value = arguments[i];
			if (value !== undefined) {
				obj[key] = value;
				break;
			}
		}

		return obj;
	},

	// extendNoUndef: function(obj [,fromObj] [,fromObj] [,fromObj])
	// sets all keys from fromObj onto obj, deleting undefined values
	extendNoUndef: function(obj) {
		var fromObj;
		for (var i = 1; i < arguments.length; i++) {
			fromObj = arguments[i];
			_.forIn(fromObj, function(value, key) {
				if (value === undefined) {
					delete obj[key];
				} else {
					obj[key] = value;
				}
			});
		}

		return obj;
	},

	// defaultsNoUndef: function(obj [,fromObj] [,fromObj] [,fromObj])
	// sets all keys from fromObj onto obj where obj[key] is undefined, ignoring undefined values
	defaultsNoUndef: function(obj) {
		var fromObj;
		for (var i = 1; i < arguments.length; i++) {
			fromObj = arguments[i];
			_.forIn(fromObj, function(value, key) {
				if (obj[key] === undefined && value !== undefined) obj[key] = value;
			});
		}

		return obj;
	},

	// string format conversion from camelCase or underscored format to human-readable format
	// e.g. 'fooBar' -> 'Foo Bar', 'foo_bar' -> 'Foo Bar'
	humanize: function(str) {
		str.replace(/[-_\s]+(.)?/g, function(match, c) {return c ? c.toUpperCase() : '';}); // jshint ignore:line
		return str[0].toUpperCase() + str.slice(1).replace(/([A-Z])/g, ' $1');
	},

	// checks if str ends with needle
	endsWith: function(str, needle) {
		return str.slice(str.length - needle.length) == needle;
	},

	// if value is function, run it with arguments and return result, otherwise return input
	functionValue: function(val) {
		if (!_.isFunction(val)) return val;

		var args = Array.prototype.slice.call(arguments, 1);
		return val.apply(args);
	}
};
<|endoftext|>


<commit_before>function buildPrompt(movies) {
  var promptData = {
      searchResults: movies,
      yesAction  : 'addMovie',
      yesResponse: 'Added ' + movies[0].original_title + ' (' + movies[0].year + ')' + ' to your list of movies to download.'
  };

  if (movies.length > 1) {
    promptData.noAction = 'suggestNextMovie';
    promptData.noResponse = 'Ok, did you mean ' + movies[1].original_title + ' (' + movies[1].year + ')' + '?';
  }
  else {
    promptData.noAction = 'endSession';
    promptData.noResponse = 'Ok. I\'m out of suggestions. Sorry about that.';
  }

  return promptData;
}

function sendSearchResponse(movies, resp) {
  if(!movies || !movies.length) {
    return resp.say('No movie found for ' + movieName).send();
  }

  resp
    .say(['Add', movies[0].original_title, '(' + movies[0].year + ')', 'to your list?'].join(' '))
    .session('promptData', buildPrompt(movies))
    .shouldEndSession(false)
    .send();

function formatSearchResults(movies)
{
  try{

    if (movies != undefined)
    {

    var newMovies = [];

  for (var i = 0; i < movies.length; i++)
  { newMovies.push({
    original_title: movies[i].original_title,
    inLibrary: movies[i].in_library,
    year: movies[i].year,
    titles: movies[i].titles,
    imdb: movies[i].imdb });
  }
function formatSearchResults(movies) {

    if (movies != undefined) {

      var newMovies = [];

      for (var i = 0; i < movies.length; i++) {

        newMovies.push({
          original_title: movies[i].original_title,
          inLibrary: isInLibrary(movies[i].in_library),
          year: movies[i].year,
          titles: movies[i].titles,
          imdb: movies[i].imdb
        });
      }

    }

    return newMovies;

}

module.exports = {
  buildPrompt: buildPrompt,
  sendSearchResponse: sendSearchResponse,
  formatSearchResults: formatSearchResults
};

<commit_msg>Formatting fixes<commit_after>function buildPrompt(movies) {
  var promptData = {
      searchResults: movies,
      yesAction  : 'addMovie',
      yesResponse: 'Added ' + movies[0].original_title + ' (' + movies[0].year + ')' + ' to your list of movies to download.'
  };

  if (movies.length > 1) {
    promptData.noAction = 'suggestNextMovie';
    promptData.noResponse = 'Ok, did you mean ' + movies[1].original_title + ' (' + movies[1].year + ')' + '?';
  }
  else {
    promptData.noAction = 'endSession';
    promptData.noResponse = 'Ok. I\'m out of suggestions. Sorry about that.';
  }

  return promptData;
}

function sendSearchResponse(movies, resp) {
  if(!movies || !movies.length) {
    return resp.say('No movie found for ' + movieName).send();
  }

  resp
    .say(['Add', movies[0].original_title, '(' + movies[0].year + ')', 'to your list?'].join(' '))
    .session('promptData', buildPrompt(movies))
    .shouldEndSession(false)
    .send();
}

function formatSearchResults(movies)
{
  try{

    if (movies != undefined)
    {

    var newMovies = [];

  for (var i = 0; i < movies.length; i++)
  { newMovies.push({
    original_title: movies[i].original_title,
    inLibrary: movies[i].in_library,
    year: movies[i].year,
    titles: movies[i].titles,
    imdb: movies[i].imdb });
  }
function formatSearchResults(movies) {

    if (movies != undefined) {

      var newMovies = [];

      for (var i = 0; i < movies.length; i++) {

        newMovies.push({
          original_title: movies[i].original_title,
          inLibrary: isInLibrary(movies[i].in_library),
          year: movies[i].year,
          titles: movies[i].titles,
          imdb: movies[i].imdb
        });

      }

    }

    return newMovies;
}

module.exports = {
  buildPrompt: buildPrompt,
  sendSearchResponse: sendSearchResponse,
  formatSearchResults: formatSearchResults
};

<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const path = require('path');

let controllerDir;
let appName;

/**
 * returns application name
 *
 * The name of the application can be different and this function finds it out.
 *
 * @returns {string}
 */
 function getAppName() {
    const parts = __dirname.replace(/\\/g, '/').split('/');
    return parts[parts.length - 2].split('.')[0];
}

/**
 * looks for js-controller home folder
 *
 * @param {boolean} isInstall
 * @returns {string}
 */
function getControllerDir(isInstall) {
    // Find the js-controller location
    const possibilities = [
        'iobroker.js-controller',
        'ioBroker.js-controller',
    ];
    /** @type {string} */
    let controllerPath;
    for (const pkg of possibilities) {
        try {
            const possiblePath = require.resolve(pkg);
            if (fs.existsSync(possiblePath)) {
                controllerPath = possiblePath;
                break;
            }
        } catch (e) { /* not found */ }
    }
    if (controllerPath == null) {
        if (!isInstall) {
            console.log('Cannot find js-controller');
            process.exit(10);
        } else {
            process.exit();
        }
    }
    // we found the controller
    return path.dirname(controllerPath);
}

/**
 * reads controller base settings
 *
 * @alias getConfig
 * @returns {object}
 */
 function getConfig() {
    let configPath;
    if (fs.existsSync(
        configPath = path.join(controllerDir, 'conf', appName + '.json')
    )) {
        return JSON.parse(fs.readFileSync(configPath, 'utf8'));
    } else if (fs.existsSync(
        configPath = path.join(controllerDir, 'conf', + appName.toLowerCase() + '.json')
    )) {
        return JSON.parse(fs.readFileSync(configPath, 'utf8'));
    } else {
        throw new Error('Cannot find ' + controllerDir + '/conf/' + appName + '.json');
    }
}
appName       = getAppName();
controllerDir = getControllerDir(typeof process !== 'undefined' && process.argv && process.argv.indexOf('--install') !== -1);
const adapter = require(path.join(controllerDir, 'lib/adapter.js'));

exports.controllerDir = controllerDir;
exports.getConfig =     getConfig;
exports.Adapter =       adapter;
exports.appName =       appName;
<commit_msg>remove utils.js<commit_after><|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    inherit = require('soak').inherit,
    EventEmitter = require('events').EventEmitter;

module.exports = {
  // Create a base observable object that inherits from EventEmitter. This
  // allows us to create new objects that can trigger events very easily.
  //
  // Example:
  //
  //   var Store = Observable.extend({
  //     save: function () {}
  //   });
  Observable: inherit(EventEmitter),

  // Helper function for creating an index file in a directory. It loads all
  // modules within the provided directory excluding the file provided as
  // "indexpath". These will then be returned.
  //
  // Example:
  //
  //   module.exports = utils.index(__dirname, __filename);
  index: function (dirname, indexpath) {
    var extensions = {js: 1},
        modules = {};

    indexpath = indexpath || path.join(dirname, 'index.js');

    // Load all exported objects into a single module.
    fs.readdirSync(dirname).forEach(function (filename) {
      var fullpath = path.join(dirname, filename),
          parts    = filename.split('.'),
          module, name;

      if (fullpath !== indexpath && extensions[parts.pop()] && '.' !== filename[0]) {
        name = parts.join('.');
        module = require(fullpath);

        // Grab the function name or module name if possible.
        if (typeof module.name === 'string') {
          name = module.name;
        }

        modules[name] = module;
      }
    });

    return modules;
  },

  // Takes an object and a series of method names. Each method will be
  // re-assigned to the object with the object bound as the methods scope. This
  // is generally useful for defining callback methods.
  //
  // An array of method names can also be passed.
  //
  // Example:
  //
  //   object = {onData: function () {}, onEnd: function () {});
  //   utils.bindAll(object, 'onData', 'onEnd');
  //
  //   // Same as doing.
  //   object.onData = object.onData.bind(object);
  //   object.onEnd  = object.onEnd.bind(object);
  bindAll: function (object /* args */) {
    var methods = [].slice.call(arguments, 1);
    if (arguments.length === 2 && Array.isArray(arguments[1])) {
      methods = arguments[1];
    }

    methods.forEach(function (method) {
      if (typeof object[method] === 'function') {
        object[method] = object[method].bind(object);
      }
    });

    return object;
  },
  extract: function (obj /* keys */) {
    var keys = [].slice.call(arguments, 1),
        collected = {};

    keys.forEach(function (key) {
      if (obj[key]) {
        collected[key] = obj[key];
      }
    });

    return collected;
  },
  isAjax: function (req) {
    return (req.get('X-Requested-With') || '').toLowerCase() === 'xmlhttprequest';
  },
  shortcode: function () {
    var vowels = 'aeiou',
        consonants = 'bcdfghjklmnpqrstvwxyz',
        word = '', length = 6, index = 0, set;

    for (; index < length; index += 1) {
      set = (index % 2 === 0) ? vowels : consonants;
      word += set[Math.floor(Math.random() * set.length)];
    }

    return word;
  },
  re: {
    flatten: /\s+/g,
    body: /<body.*?>\s*(.*)/m,
    meta: /<meta name="description" content="(.*?)"/,
    tags: /<[^>]+>/g,
    title: /<title>(.*)<\/title>/
  },
  titleForBin: function (bin) {
    // TODO: Use HTML parser or JSDOM
    var html = (bin.html || '').replace(this.re.flatten, ' '), // flatten
        javascript = (bin.javascript || '').replace(this.re.flatten, ' ').trim(),
        matches = (html.match(this.re.meta) || []);

    if (matches.length === 2 && matches[1].trim()) {
      return matches[1];
    }

    matches = (html.match(this.re.body) || []);

    if (bin.url === 'abomob') {
      debugger;
    }
    if (matches.length === 2 && matches[1].trim()) {
      return matches[1].replace(this.re.tags, '').trim();
    }

    // No title return JavaScript.
    if (javascript) {
      return javascript;
    }

    matches = (html.match(this.re.title) || []);
    if (matches.length === 2 && matches[1].trim()) {
      return matches[1];
    }
    return '';
  },
  since: function (date) {
    var diff    = (+new Date() - date) / 1000,
        message = 'a long time',
        timespan;

    if (diff < 60) {
      timespan = Math.floor(diff);
      message  = '{timespan} second';
    }
    else if (diff < 3600) {
      timespan =  Math.floor(diff / 60);
      message  = 'about {timespan} minute';
    }
    else if (diff < 86400) {
      timespan = Math.floor(diff / 3600);
      message  = 'around {timespan} hour';
    }
    else if (diff < 604800) {
      timespan = Math.floor(diff / 86400);
      message  = 'about {timespan} day';
    }
    else if (diff < 2419200) {
      timespan = Math.ceil(diff / 604800);
      message  = 'nearly {timespan} week';
    }
    else if (diff < 29030400) {
      timespan = Math.floor(diff / 2419200);
      message  = 'about {timespan} month';
    }

    if (timespan !== 1 && timespan) {
      message += 's';
    }

    return message.replace('{timespan}', timespan) + ' ago';
  },
  queryStringForBin: function (bin, defaults) {
    var params = [];
    ['html', 'javascript', 'css'].forEach(function (key) {
      if (bin[key] !== defaults[key]) {
        params.push(key);
      }
    });
    return params.join(',');
  },
};
<commit_msg>Add utils.extend() for extending objects<commit_after>var fs = require('fs'),
    path = require('path'),
    extend = require('soak').mixin,
    inherit = require('soak').inherit,
    EventEmitter = require('events').EventEmitter;

module.exports = {
  // Create a base observable object that inherits from EventEmitter. This
  // allows us to create new objects that can trigger events very easily.
  //
  // Example:
  //
  //   var Store = Observable.extend({
  //     save: function () {}
  //   });
  Observable: inherit(EventEmitter),

  // Helper function for creating an index file in a directory. It loads all
  // modules within the provided directory excluding the file provided as
  // "indexpath". These will then be returned.
  //
  // Example:
  //
  //   module.exports = utils.index(__dirname, __filename);
  index: function (dirname, indexpath) {
    var extensions = {js: 1},
        modules = {};

    indexpath = indexpath || path.join(dirname, 'index.js');

    // Load all exported objects into a single module.
    fs.readdirSync(dirname).forEach(function (filename) {
      var fullpath = path.join(dirname, filename),
          parts    = filename.split('.'),
          module, name;

      if (fullpath !== indexpath && extensions[parts.pop()] && '.' !== filename[0]) {
        name = parts.join('.');
        module = require(fullpath);

        // Grab the function name or module name if possible.
        if (typeof module.name === 'string') {
          name = module.name;
        }

        modules[name] = module;
      }
    });

    return modules;
  },

  // Takes an object and a series of method names. Each method will be
  // re-assigned to the object with the object bound as the methods scope. This
  // is generally useful for defining callback methods.
  //
  // An array of method names can also be passed.
  //
  // Example:
  //
  //   object = {onData: function () {}, onEnd: function () {});
  //   utils.bindAll(object, 'onData', 'onEnd');
  //
  //   // Same as doing.
  //   object.onData = object.onData.bind(object);
  //   object.onEnd  = object.onEnd.bind(object);
  bindAll: function (object /* args */) {
    var methods = [].slice.call(arguments, 1);
    if (arguments.length === 2 && Array.isArray(arguments[1])) {
      methods = arguments[1];
    }

    methods.forEach(function (method) {
      if (typeof object[method] === 'function') {
        object[method] = object[method].bind(object);
      }
    });

    return object;
  },

  // Extends the first argument with the properties of the subsequent
  // arguments.
  extend: extend,

  extract: function (obj /* keys */) {
    var keys = [].slice.call(arguments, 1),
        collected = {};

    keys.forEach(function (key) {
      if (obj[key]) {
        collected[key] = obj[key];
      }
    });

    return collected;
  },
  isAjax: function (req) {
    return (req.get('X-Requested-With') || '').toLowerCase() === 'xmlhttprequest';
  },
  shortcode: function () {
    var vowels = 'aeiou',
        consonants = 'bcdfghjklmnpqrstvwxyz',
        word = '', length = 6, index = 0, set;

    for (; index < length; index += 1) {
      set = (index % 2 === 0) ? vowels : consonants;
      word += set[Math.floor(Math.random() * set.length)];
    }

    return word;
  },
  re: {
    flatten: /\s+/g,
    body: /<body.*?>\s*(.*)/m,
    meta: /<meta name="description" content="(.*?)"/,
    tags: /<[^>]+>/g,
    title: /<title>(.*)<\/title>/
  },
  titleForBin: function (bin) {
    // TODO: Use HTML parser or JSDOM
    var html = (bin.html || '').replace(this.re.flatten, ' '), // flatten
        javascript = (bin.javascript || '').replace(this.re.flatten, ' ').trim(),
        matches = (html.match(this.re.meta) || []);

    if (matches.length === 2 && matches[1].trim()) {
      return matches[1];
    }

    matches = (html.match(this.re.body) || []);

    if (bin.url === 'abomob') {
      debugger;
    }
    if (matches.length === 2 && matches[1].trim()) {
      return matches[1].replace(this.re.tags, '').trim();
    }

    // No title return JavaScript.
    if (javascript) {
      return javascript;
    }

    matches = (html.match(this.re.title) || []);
    if (matches.length === 2 && matches[1].trim()) {
      return matches[1];
    }
    return '';
  },
  since: function (date) {
    var diff    = (+new Date() - date) / 1000,
        message = 'a long time',
        timespan;

    if (diff < 60) {
      timespan = Math.floor(diff);
      message  = '{timespan} second';
    }
    else if (diff < 3600) {
      timespan =  Math.floor(diff / 60);
      message  = 'about {timespan} minute';
    }
    else if (diff < 86400) {
      timespan = Math.floor(diff / 3600);
      message  = 'around {timespan} hour';
    }
    else if (diff < 604800) {
      timespan = Math.floor(diff / 86400);
      message  = 'about {timespan} day';
    }
    else if (diff < 2419200) {
      timespan = Math.ceil(diff / 604800);
      message  = 'nearly {timespan} week';
    }
    else if (diff < 29030400) {
      timespan = Math.floor(diff / 2419200);
      message  = 'about {timespan} month';
    }

    if (timespan !== 1 && timespan) {
      message += 's';
    }

    return message.replace('{timespan}', timespan) + ' ago';
  },
  queryStringForBin: function (bin, defaults) {
    var params = [];
    ['html', 'javascript', 'css'].forEach(function (key) {
      if (bin[key] !== defaults[key]) {
        params.push(key);
      }
    });
    return params.join(',');
  },
};
<|endoftext|>


<commit_before>const EncodedCharacters = {
    '!': '%21',
    '"': '%22',
    '#': '%23',
    '$': '%24',
    '%': '%25',
    '&': '%26',
    '\'': '%27',
    '(': '%28',
    ')': '%29',
    '*': '%2A',
    '+': '%2B',
    ',': '%2C',
    '-': '%2D',
    '.': '%2E',
    '/': '%2F',
    ' ': '%20',
};

const Utils = {
    UrlPrefix: 'https://stackoverflow.com/jobs/feed?',
    Query: 'q=',
    Location: "&l=",
    Unit: "&u=",
    TechLiked: "&tl=",
    TechDisliked: "&td=",

    EncodeProtectedCharacters(param) {
        const paramSplit = param.split('');
        let encodedCharacterString = '';

        paramSplit.forEach(char => {
            (Object.prototype.hasOwnProperty.call(EncodedCharacters, char)) ? encodedCharacterString += EncodedCharacters[char] : encodedCharacterString += char;
        });

        return encodedCharacterString;
    }
}

module.exports = {
    Utils,
}<commit_msg>JSDOC for new EncodedCharacters function<commit_after>const EncodedCharacters = {
    '!': '%21',
    '"': '%22',
    '#': '%23',
    '$': '%24',
    '%': '%25',
    '&': '%26',
    '\'': '%27',
    '(': '%28',
    ')': '%29',
    '*': '%2A',
    '+': '%2B',
    ',': '%2C',
    '-': '%2D',
    '.': '%2E',
    '/': '%2F',
    ' ': '%20',
};

const Utils = {
    UrlPrefix: 'https://stackoverflow.com/jobs/feed?',
    Query: 'q=',
    Location: "&l=",
    Unit: "&u=",
    TechLiked: "&tl=",
    TechDisliked: "&td=",

    /**
     * Converts protected HTML characters and converts them to their encoded version. Eg:  # -> %23
     * @param {String} param - A string with (potentially) encoded characters
     */
    EncodeProtectedCharacters(param) {
        const paramSplit = param.split('');
        let encodedCharacterString = '';

        paramSplit.forEach(char => {
            (Object.prototype.hasOwnProperty.call(EncodedCharacters, char)) ? encodedCharacterString += EncodedCharacters[char] : encodedCharacterString += char;
        });

        return encodedCharacterString;
    }
}

module.exports = {
    Utils,
}<|endoftext|>