<commit_before>// Color parser
function parseChannelValues(channels) {
    for (var i=0; i<channels.length; i++) {
        if (channels[i].indexOf('%') !== -1) {
            channels[i] = channels[i].substr(0, channels[i].length - 1) / 100;
        } else {
            channels[i] = channels[i] / 255;
        }
        if (channels[i] > 1) {
            channels[i] = 1;
        }
    }
    return channels;
}
function parse(value, currentColor, currentHslColor, isHsl) {
    var parts, i, alpha, hue;
    if (typeof value === 'string') {
        value = value.replace(/\s+/g, '');
        if (/^#/.test(value)) { // hex
            if (/^#([0-9a-f]{3}){1,2}$/i.test(value)) {
                if (value.length === 4) {
                    value = value.replace(/[0-9a-f]/gi, replaceCallback);
                }
                currentColor = hexa2rgb(value);
                currentColor.a = 1;
                isHsl = false;
            } else if (/^#([0-9a-f]{4}){1,2}$/i.test(value)) {
                if (value.length === 5) {
                    value = value.replace(/[0-9a-f]/gi, replaceCallback);
                }
                currentColor = hexa2rgb(value);
                isHsl = false;
            }
        } else if (/^rgba/.test(value)) {
            parts = value.match(/^rgba\((\d+%?),(\d+%?),(\d+%?),(\.\d+|\d+\.?\d*)\)$/);
            if (parts && parts.length === 5) {
                parts.shift();
                alpha = parts.pop() / 1; // Divide by 1 to convert string to number
                if (alpha > 1) {
                    alpha = 1;
                }
                parts = parseChannelValues(parts);
                currentColor.r = parts[0];
                currentColor.g = parts[1];
                currentColor.b = parts[2];
                currentColor.a = alpha;
                isHsl = false;
            }
        } else if (/^rgb/.test(value)) {
            parts = value.match(/^rgb\((\d+%?),(\d+%?),(\d+%?)\)$/);
            if (parts && parts.length === 4) {
                parts.shift();
                parts = parseChannelValues(parts);
                currentColor.r = parts[0];
                currentColor.g = parts[1];
                currentColor.b = parts[2];
                currentColor.a = 1;
                isHsl = false;
            }
        } else if (/^hsla/.test(value)) {
            parts = value.match(/^hsla\((-?\d+),(\d+%),(\d+%),(\.\d+|\d+\.?\d*)\)$/);
            if (parts && parts.length === 5) {
                parts.shift();
                hue = parts.shift() / 360;
                hue = hue - Math.floor(hue);
                alpha = parts.pop() / 1; // Divide by 1 to convert string to number
                if (alpha > 1) {
                    alpha = 1;
                }
                parts = parseChannelValues(parts);
                isHsl = true;
                currentHslColor = {
                    h: hue,
                    s: parts[0],
                    l: parts[1],
                    a: alpha
                };
            }
        } else if (/^hsl/.test(value)) {
            parts = value.match(/^hsl\((-?\d+),(\d+%),(\d+%)\)$/);
            if (parts && parts.length === 4) {
                parts.shift();
                hue = parts.shift() / 360;
                hue = hue - Math.floor(hue);
                parts = parseChannelValues(parts);
                isHsl = true;
                currentHslColor = {
                    h: hue,
                    s: parts[0],
                    l: parts[1],
                    a: 1
                };
            }
        } else if (/^device-cmyk/.test(value)) {
            parts = value.match(/^device-cmyk\((\.\d+|\d+\.?\d*),(\.\d+|\d+\.?\d*),(\.\d+|\d+\.?\d*),(\.\d+|\d+\.?\d*)\)$/);
            if (parts && parts.length === 5) {
                parts.shift();
                for (i=0; i<parts.length; i++) {
                    parts[i] = parts[i] / 1; // Divide by 1 to convert string to number
                    if (parts[i] > 1) {
                        parts[i] = 1;
                    }
                }
                currentColor = cmyk2rgb({
                    c: parts[0],
                    m: parts[1],
                    y: parts[2],
                    k: parts[3]
                });
                isHsl = false;
            }
        }
    } else if (value instanceof Color) {
        currentColor = clone(value.getRgba());
        isHsl = false;
    } else if (typeof value === 'object') {
        var clonedValue = clone(value, parseFloat);
        if (haveFields(clonedValue, 'sl') && ! isNaN(clonedValue.h)) {
            isHsl = true;
            clonedValue.h = clonedValue.h - Math.floor(clonedValue.h);
            currentHslColor = clonedValue;
            alpha = 1;
            if (haveFields(clonedValue, 'a')) {
                alpha = clonedValue.a;
            }
            currentHslColor.a = alpha;
        } else if (haveFields(clonedValue, 'rgb')) {
            currentColor = clonedValue;
            alpha = 1;
            if (haveFields(clonedValue, 'a')) {
                alpha = clonedValue.a;
            }
            currentColor.a = alpha;
            isHsl = false;
        } else if (haveFields(clonedValue, 'cmyk')) {
            currentColor = cmyk2rgb(clonedValue);
            currentColor.a = 1;
            isHsl = false;
        }
    }
    if (isHsl) {
        return {
            rgba: hsl2rgb(currentHslColor),
            hsla: currentHslColor,
            isHsl: isHsl
        };
    } else {
        return {
            rgba: currentColor,
            hsla: rgb2hsl(currentColor),
            isHsl: isHsl
        };
    }
}<commit_msg>Refactored parse function<commit_after>// Color parser
function parseChannelValues(channels) {
    for (var i=0; i<channels.length; i++) {
        if (channels[i].indexOf('%') !== -1) {
            channels[i] = channels[i].substr(0, channels[i].length - 1) / 100;
        } else {
            channels[i] = channels[i] / 255;
        }
        if (channels[i] > 1) {
            channels[i] = 1;
        }
    }
    return channels;
}
function parseString(value, currentColor, currentHslColor, isHsl) {
    var parts, i, alpha, hue;
    value = value.replace(/\s+/g, '');
    if (/^#/.test(value)) { // hex
        if (/^#([0-9a-f]{3}){1,2}$/i.test(value)) {
            if (value.length === 4) {
                value = value.replace(/[0-9a-f]/gi, replaceCallback);
            }
            currentColor = hexa2rgb(value);
            currentColor.a = 1;
            isHsl = false;
        } else if (/^#([0-9a-f]{4}){1,2}$/i.test(value)) {
            if (value.length === 5) {
                value = value.replace(/[0-9a-f]/gi, replaceCallback);
            }
            currentColor = hexa2rgb(value);
            isHsl = false;
        }
    } else if (/^rgba/.test(value)) {
        parts = value.match(/^rgba\((\d+%?),(\d+%?),(\d+%?),(\.\d+|\d+\.?\d*)\)$/);
        if (parts && parts.length === 5) {
            parts.shift();
            alpha = parts.pop() / 1; // Divide by 1 to convert string to number
            if (alpha > 1) {
                alpha = 1;
            }
            parts = parseChannelValues(parts);
            currentColor.r = parts[0];
            currentColor.g = parts[1];
            currentColor.b = parts[2];
            currentColor.a = alpha;
            isHsl = false;
        }
    } else if (/^rgb/.test(value)) {
        parts = value.match(/^rgb\((\d+%?),(\d+%?),(\d+%?)\)$/);
        if (parts && parts.length === 4) {
            parts.shift();
            parts = parseChannelValues(parts);
            currentColor.r = parts[0];
            currentColor.g = parts[1];
            currentColor.b = parts[2];
            currentColor.a = 1;
            isHsl = false;
        }
    } else if (/^hsla/.test(value)) {
        parts = value.match(/^hsla\((-?\d+),(\d+%),(\d+%),(\.\d+|\d+\.?\d*)\)$/);
        if (parts && parts.length === 5) {
            parts.shift();
            hue = parts.shift() / 360;
            hue = hue - Math.floor(hue);
            alpha = parts.pop() / 1; // Divide by 1 to convert string to number
            if (alpha > 1) {
                alpha = 1;
            }
            parts = parseChannelValues(parts);
            isHsl = true;
            currentHslColor = {
                h: hue,
                s: parts[0],
                l: parts[1],
                a: alpha
            };
        }
    } else if (/^hsl/.test(value)) {
        parts = value.match(/^hsl\((-?\d+),(\d+%),(\d+%)\)$/);
        if (parts && parts.length === 4) {
            parts.shift();
            hue = parts.shift() / 360;
            hue = hue - Math.floor(hue);
            parts = parseChannelValues(parts);
            isHsl = true;
            currentHslColor = {
                h: hue,
                s: parts[0],
                l: parts[1],
                a: 1
            };
        }
    } else if (/^device-cmyk/.test(value)) {
        parts = value.match(/^device-cmyk\((\.\d+|\d+\.?\d*),(\.\d+|\d+\.?\d*),(\.\d+|\d+\.?\d*),(\.\d+|\d+\.?\d*)\)$/);
        if (parts && parts.length === 5) {
            parts.shift();
            for (i=0; i<parts.length; i++) {
                parts[i] = parts[i] / 1; // Divide by 1 to convert string to number
                if (parts[i] > 1) {
                    parts[i] = 1;
                }
            }
            currentColor = cmyk2rgb({
                c: parts[0],
                m: parts[1],
                y: parts[2],
                k: parts[3]
            });
            isHsl = false;
        }
    }
    if (isHsl) {
        return {
            rgba: hsl2rgb(currentHslColor),
            hsla: currentHslColor,
            isHsl: isHsl
        };
    } else {
        return {
            rgba: currentColor,
            hsla: rgb2hsl(currentColor),
            isHsl: isHsl
        };
    }
}
function parseObject(value, currentColor, currentHslColor, isHsl) {
    var alpha, clonedValue = clone(value, parseFloat);
    if (haveFields(clonedValue, 'sl') && ! isNaN(clonedValue.h)) {
        isHsl = true;
        clonedValue.h = clonedValue.h - Math.floor(clonedValue.h);
        currentHslColor = clonedValue;
        alpha = 1;
        if (haveFields(clonedValue, 'a')) {
            alpha = clonedValue.a;
        }
        currentHslColor.a = alpha;
    } else if (haveFields(clonedValue, 'rgb')) {
        currentColor = clonedValue;
        alpha = 1;
        if (haveFields(clonedValue, 'a')) {
            alpha = clonedValue.a;
        }
        currentColor.a = alpha;
        isHsl = false;
    } else if (haveFields(clonedValue, 'cmyk')) {
        currentColor = cmyk2rgb(clonedValue);
        currentColor.a = 1;
        isHsl = false;
    }
    if (isHsl) {
        return {
            rgba: hsl2rgb(currentHslColor),
            hsla: currentHslColor,
            isHsl: isHsl
        };
    } else {
        return {
            rgba: currentColor,
            hsla: rgb2hsl(currentColor),
            isHsl: isHsl
        };
    }
}
function parse(value, currentColor, currentHslColor, isHsl) {
    if (typeof value === 'string') {
        return parseString(value, currentColor, currentHslColor, isHsl);
    } else if (value instanceof Color) {
        value = value.getRgba();
        return {
            rgba: clone(value),
            hsla: rgb2hsl(value),
            isHsl: false
        };
    } else if (typeof value === 'object') {
        return parseObject(value, currentColor, currentHslColor, isHsl);
    }
    return {
        rgba: currentColor,
        hsla: currentHslColor,
        isHsl: isHsl
    };
}<|endoftext|>


<commit_before>var api = (function (extend) {

    "use strict";

    const protectedIps = ['::1'];

    var _           = require('lodash'),
        os          = require('os'),
        util        = require('util'),
        promise     = require('bluebird'),
        utils       = require('./utils'),
        pkg         = require('../package.json'),
        fs          = promise.promisifyAll(require('fs')),
        options     = {

            // group hosts by ip
            group:  true,
            // override validation
            force:  false
        },

        /**
         * setup
         *
         * default options
         */
        setup = function (setup) {

            options = _.extend(options, setup || {});

            // console.log(options);
            //
            return this;
        },

        /**
         * [add description]
         *
         * @method add
         *
         * @param  {[type]} ip        [description]
         * @param  {[type]} hostNames [description]
         */
        add = function (ip, hostNames) {

            ip          = ip.trim();
            hostNames   = _.isArray(hostNames) ? hostNames : [hostNames];

            return new promise(function (resolve, reject) {

                if (!utils.validateIP(ip)) {
                    return reject(util.format('Invalid IP address %s was supplied.', ip));
                }

                hostNames.forEach(function(host) {
                    if (!utils.validateHost(host)) {
                        return reject(util.format('Invalid hostname %s was supplied.', host));
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        let row = hosts[ip];

                        if (!row) {
                           row = hostNames;
                        } else {
                           row = row.concat(hostNames);
                        }

                        hosts[ip] = _.uniq(row);

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * remove
         *
         * removes a line by ip address
         *
         * @return {[type]} [description]
         */
        remove = function (ips) {

            ips = _.isArray(ips) ? ips : [ips];

            return new promise(function (resolve, reject) {

                if (!ips.length) {
                    return reject('No IP addresses provided');
                }

                ips.forEach(function(ip) {
                    if (!utils.validateIP(ip)) {
                        return reject('Invalid IP address was supplied.');
                    }
                });

                ips.forEach(function(ip) {
                    if (protectedIps.indexOf(ip) > -1) {
                        return reject(util.format('%s is protected by the OS and cannot be removed. Use --force to override this.', ip));
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        ips.forEach(function(ip) {

                            if (hosts[ip]) {
                                delete hosts[ip];
                            } else {
                                return reject(util.format('IP %s not in file.', ip));
                            }
                        });

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * disable
         *
         * disables a line by ip address
         *
         * @return {[type]} [description]
         */
        disable = function (ips) {

            ips = _.isArray(ips) ? ips : [ips];

            return new promise(function (resolve, reject) {

                if (!ips.length) {
                    return reject('No IP address provided');
                }

                ips.forEach(function(ip) {
                    if (!utils.validateIP(ip)) {
                        return reject('Invalid IP address was supplied.');
                    }
                });

                ips.forEach(function(ip) {
                    if (protectedIps.indexOf(ip) > -1) {
                        return reject(util.format('%s is protected by the OS and cannot be removed. Use --force to override this.', ip));
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        // console.log(hosts);

                        ips.forEach(function(ip) {

                            // console.log(hosts[ip], ip);

                            var commentBlock = util.format('# %s', ip);

                            if (hosts[ip]) {
                                hosts[commentBlock] = hosts[ip];
                                delete hosts[ip];
                            } else {
                                return reject(util.format('IP %s not in file.', ip));
                            }
                        });

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * enable
         *
         * renables an previously muted entry
         *
         * @return {[type]} [description]
         */
        enable = function (ips) {

            ips = _.isArray(ips) ? ips : [ips];

            return new promise(function (resolve, reject) {

                if (!ips.length) {
                    return reject('No IP addresses provided');
                }

                ips.forEach(function(ip) {
                    if (!utils.validateIP(ip)) {
                        return reject('Invalid IP address was supplied.');
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        ips.forEach(function(ip) {

                            var commentBlock = util.format('# %s', ip);

                            if (hosts[commentBlock]) {
                                hosts[ip] = _.clone(hosts[commentBlock]);
                                // delete hosts[commentBlock];
                            } else {
                                return reject(util.format('IP %s not in file.', ip));
                            }

                            // console.log(commentBlock, hosts[commentBlock]);
                        });

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * purge
         *
         * removes hosts from an ip mapping
         *
         * @return {[type]} [description]
         */
        purge = function (hostNames) {

            hostNames = _.isArray(hostNames) ? hostNames : [hostNames];

            return new promise(function (resolve, reject) {

                hostNames.forEach(function(host) {
                    if (!host.match(/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/i)) {
                        return reject(util.format("Invalid host %s supplied", host));
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        // loop supplied hostnames
                        _.each(hostNames, function(hostName) {

                            // loop the hosts against the ip
                            _.each(hosts, function (hostList, ip) {

                                // purge the matching
                                _.remove(hostList, function(host) {
                                    return host.toLowerCase().trim() === hostName.toLowerCase().trim();
                                });

                                // if the purge leaves the ip hostnbame bindings empty, bin it off
                                if (!hostList.length) {
                                    try {
                                        delete hosts[ip];
                                    } catch (e) {}
                                }
                            });
                        });

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * [list description]
         *
         * @method list
         *
         * @return {[type]} [description]
         */
        list = function (filter) {

            return loadHosts(filter);
        },

        /**
         * [getHostFilePath description]
         *
         * Operating System	Version(s)	 Location
         * Unix, Unix-like, POSIX		 /etc/hosts
         * Microsoft Windows	         3.1	%WinDir%\HOSTS
         * 95, 98, ME	                 %WinDir%\hosts
         * NT, 2000, XP,[5] 2003, Vista,
         * 2008, 7, 2012, 8, 10	         %SystemRoot%\System32\drivers\etc\hosts
         * Mac OS X 10.0–10.1.5	         (Added through NetInfo or niload)
         * Mac OS X 10.2 and newer	     /etc/hosts (a symbolic link to /private/etc/hosts)
         *
         * 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', 'x64', and 'x86'
         *
         * @method getHostFilePath
         *
         * @return {[type]}        [description]
         */
        getHostFilePath = function () {

            var path;

            // path was set by user via options
            if (options.path) {
                path = options.path;

            } else {

                // calculate the path
                switch (os.platform()) {

                    case 'linux':
                    case 'darwin':
                    case 'freebsd':
                    case 'openbsd':
                        //
                        path = '/etc/hosts';
                        break;

                    case 'win32':
                        //
                        path = process.env.windir || process.env.WINDIR;

                        if (path) {
                            path = fs.resolve(util.format('%s\%s', path, 'System32\drivers\etc\hosts'));
                        }
                        break;
                    default:
                }
            }

            // console.log('Resolved OS "%s" target path to %s', os.platform(), path);

            // now resolve it
            return fs.realpathAsync(path);
        },

        /**
         * loadHosts
         *
         * @method loadHosts
         *
         * @return object of entries in the host file
         */
        loadHosts = function (filter) {

            return getHostFilePath()
                .then(function(path) {

                    return fs
                    .readFileAsync(path)
                    .then(function(file) {

                        let hosts = {
                                // comments: []
                            },
                            expression = /((^\#\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))/;

                        file.toString().split("\n").map(function(line) {

                            // comments are ignored
                            // this needs to be better
                            if (line.indexOf('#') === 0) {
                                // console.log("got comment", line.replace(/\#\ /ig, ''));
                                // if (utils.validateHost(line.replace(/\#\ /ig, ''))) {
                                //     // hosts.comments.push(line);
                                //     console.log('got disabled', line);
                                // }
                                return;
                            }

                            // split the string to get the ip and hosts
                            line = line .replace(/(\s)+/g, ' ')
                                        .split(' ');

                            if (!line.length || line.length < 2) {

                            } else {

                                // duplicate ip, so merge them
                                if (line[0].length) {

                                    let ip = hosts[line[0]];

                                    if (ip) {
                                        ip = ip.concat(_.compact(line.slice(1)));
                                    } else {
                                        ip = _.compact(line.slice(1));
                                    }

                                    // only return matching hosts
                                    if (filter) {

                                        var matching = _.filter(ip, function(ip) {
                                            return ip.indexOf(filter) > -1;
                                        });

                                        if (matching.length) {
                                            ip = matching;
                                        } else {
                                            return;
                                        }
                                    }

                                    hosts[line[0]] = _.uniq(ip);
                                }
                            }
                        });

                        return hosts;
                    })
                    // format the ips
                    .then(function(hosts) {

                        return utils.sortEntries(hosts);
                    });
                })
                .catch(function(e) {
                    console.error(e);
                });

        },

        /**
         * saveToFile
         *
         *
         */
        saveToFile = function (hosts) {

            // sort the dictionary of entries
            hosts = utils.sortEntries(hosts);

            return new promise(function(resolve, reject) {

                getHostFilePath()
                    .then(function(path) {

                        let contents = [
                            util.format('# '),
                            util.format('#    /)'),
                            util.format('#  (/   ___ _  _/___   _   __ _/_)        v%s / %s', pkg.version, new Date()),
                            util.format('#  / )_(_) /_)_(__/_)_(_(_/ (_(__(_/_     %s', pkg.repository),
                            util.format('#              .-/              .-/'),
                            util.format('#             (_/              (_/'),
                            util.format('')
                        ];

                        _.each(hosts, function(hosts, ip) {

                            // group the hosts by IP
                            if (options.group) {

                                contents.push(util.format('%s %s', ip, hosts.join(' ')));
                            } else {

                                // don't group - 1 line per IP
                                hosts.forEach(function(host) {
                                    contents.push(util.format('%s %s', ip, host));
                                });
                            }
                        });

                        //
                        return fs
                            .writeFileAsync(path, util.format("%s%s", contents.join("\n"), "\n"))
                            .then(resolve)
                            .catch(function(e) {

                                var message     = 'Error writing file',
                                    elevated    = (os.platform().match(/^win/i) ? 'Administrator' : 'root');

                                // access denied?
                                switch (e.code) {
                                    case 'EACCES':
                                        message = util.format('Write permission denied on %s. Try running as %s.', path, elevated);
                                        break;
                                }

                                reject(message);
                            });

                    }).catch(reject);
            });
        };

    return {
        setup:      setup,
        add:        add,
        remove:     remove,
        list:       list,
        purge:      purge,
        // disable:    disable,
        // enable:     enable
    };
})();

module.exports = api;
<commit_msg>Implemented force flag<commit_after>var api = (function (extend) {

    "use strict";

    const protectedEntries = {
        ips:    ['::1', 'fe80::1%lo0'],
        hosts:  ['localhost']
    };

    var _           = require('lodash'),
        os          = require('os'),
        util        = require('util'),
        promise     = require('bluebird'),
        utils       = require('./utils'),
        pkg         = require('../package.json'),
        fs          = promise.promisifyAll(require('fs')),
        options     = {

            // group hosts by ip
            group:  true,
            // override validation
            force:  false
        },

        /**
         * setup
         *
         * default options
         */
        setup = function (setup) {

            options = _.extend(options, setup || {});

            // console.log(options);
            //
            return this;
        },

        /**
         * [add description]
         *
         * @method add
         *
         * @param  {[type]} ip        [description]
         * @param  {[type]} hostNames [description]
         */
        add = function (ip, hostNames) {

            ip          = ip.trim();
            hostNames   = _.isArray(hostNames) ? hostNames : [hostNames];

            return new promise(function (resolve, reject) {

                if (!utils.validateIP(ip)) {
                    return reject(util.format('Invalid IP address %s was supplied.', ip));
                }

                hostNames.forEach(function(host) {
                    if (!utils.validateHost(host)) {
                        return reject(util.format('Invalid hostname %s was supplied.', host));
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        let row = hosts[ip];

                        if (!row) {
                           row = hostNames;
                        } else {
                           row = row.concat(hostNames);
                        }

                        hosts[ip] = _.uniq(row);

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * remove
         *
         * removes a line by ip address
         *
         * @return {[type]} [description]
         */
        remove = function (ips) {

            ips = _.isArray(ips) ? ips : [ips];

            return new promise(function (resolve, reject) {

                if (!ips.length) {
                    return reject('No IP addresses provided');
                }

                ips.forEach(function(ip) {
                    if (!utils.validateIP(ip)) {
                        return reject('Invalid IP address was supplied.');
                    }
                });

                ips.forEach(function(ip) {
                    if (protectedEntries.ips.indexOf(ip) > -1) {
                        if (!options.force) {
                            return reject(util.format('%s is protected by the OS and cannot be removed. Use --force to override this.', ip));
                        }
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        ips.forEach(function(ip) {

                            if (hosts[ip]) {
                                delete hosts[ip];
                            } else {
                                return reject(util.format('IP %s not in file.', ip));
                            }
                        });

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * disable
         *
         * disables a line by ip address
         *
         * @return {[type]} [description]
         */
        disable = function (ips) {

            ips = _.isArray(ips) ? ips : [ips];

            return new promise(function (resolve, reject) {

                if (!ips.length) {
                    return reject('No IP address provided');
                }

                ips.forEach(function(ip) {
                    if (!utils.validateIP(ip)) {
                        return reject('Invalid IP address was supplied.');
                    }
                });

                ips.forEach(function(ip) {
                    if (protectedEntries.ips.indexOf(ip) > -1) {
                        if (!options.force) {
                            return reject(util.format('%s is protected by the OS and cannot be removed. Use --force to override this.', ip));
                        }
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        // console.log(hosts);

                        ips.forEach(function(ip) {

                            // console.log(hosts[ip], ip);

                            var commentBlock = util.format('# %s', ip);

                            if (hosts[ip]) {
                                hosts[commentBlock] = hosts[ip];
                                delete hosts[ip];
                            } else {
                                return reject(util.format('IP %s not in file.', ip));
                            }
                        });

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * enable
         *
         * renables an previously muted entry
         *
         * @return {[type]} [description]
         */
        enable = function (ips) {

            ips = _.isArray(ips) ? ips : [ips];

            return new promise(function (resolve, reject) {

                if (!ips.length) {
                    return reject('No IP addresses provided');
                }

                ips.forEach(function(ip) {
                    if (!utils.validateIP(ip)) {
                        return reject('Invalid IP address was supplied.');
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        ips.forEach(function(ip) {

                            var commentBlock = util.format('# %s', ip);

                            if (hosts[commentBlock]) {
                                hosts[ip] = _.clone(hosts[commentBlock]);
                                // delete hosts[commentBlock];
                            } else {
                                return reject(util.format('IP %s not in file.', ip));
                            }

                            // console.log(commentBlock, hosts[commentBlock]);
                        });

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * purge
         *
         * removes hosts from an ip mapping
         *
         * @return {[type]} [description]
         */
        purge = function (hostNames) {

            hostNames = _.isArray(hostNames) ? hostNames : [hostNames];

            return new promise(function (resolve, reject) {

                hostNames.forEach(function(host) {
                    if (!utils.validateHost(host)) {
                        return reject(util.format("Invalid host %s supplied", host));
                    }
                });

                loadHosts()
                    .then(function(hosts) {

                        // loop supplied hostnames
                        _.each(hostNames, function(hostName) {

                            // loop the hosts against the ip
                            _.each(hosts, function (hostList, ip) {

                                // purge the matching
                                _.remove(hostList, function(host) {
                                    return host.toLowerCase().trim() === hostName.toLowerCase().trim();
                                });

                                // if the purge leaves the ip hostnbame bindings empty, bin it off
                                if (!hostList.length) {
                                    try {
                                        delete hosts[ip];
                                    } catch (e) {}
                                }
                            });
                        });

                        return hosts;
                    })
                    .then(function(hosts) {

                        return saveToFile(hosts).then(resolve);
                    })
                    .catch(reject);
            });
        },

        /**
         * [list description]
         *
         * @method list
         *
         * @return {[type]} [description]
         */
        list = function (filter) {

            return loadHosts(filter);
        },

        /**
         * [getHostFilePath description]
         *
         * Operating System	Version(s)	 Location
         * Unix, Unix-like, POSIX		 /etc/hosts
         * Microsoft Windows	         3.1	%WinDir%\HOSTS
         * 95, 98, ME	                 %WinDir%\hosts
         * NT, 2000, XP,[5] 2003, Vista,
         * 2008, 7, 2012, 8, 10	         %SystemRoot%\System32\drivers\etc\hosts
         * Mac OS X 10.0–10.1.5	         (Added through NetInfo or niload)
         * Mac OS X 10.2 and newer	     /etc/hosts (a symbolic link to /private/etc/hosts)
         *
         * 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', 'x64', and 'x86'
         *
         * @method getHostFilePath
         *
         * @return {[type]}        [description]
         */
        getHostFilePath = function () {

            var path;

            // path was set by user via options
            if (options.path) {
                path = options.path;

            } else {

                // calculate the path
                switch (os.platform()) {

                    case 'linux':
                    case 'darwin':
                    case 'freebsd':
                    case 'openbsd':
                        //
                        path = '/etc/hosts';
                        break;

                    case 'win32':
                        //
                        path = process.env.windir || process.env.WINDIR;

                        if (path) {
                            path = fs.resolve(util.format('%s\%s', path, 'System32\drivers\etc\hosts'));
                        }
                        break;
                    default:
                }
            }

            // console.log('Resolved OS "%s" target path to %s', os.platform(), path);

            // now resolve it
            return fs.realpathAsync(path);
        },

        /**
         * loadHosts
         *
         * @method loadHosts
         *
         * @return object of entries in the host file
         */
        loadHosts = function (filter) {

            return getHostFilePath()
                .then(function(path) {

                    return fs
                    .readFileAsync(path)
                    .then(function(file) {

                        let hosts = {
                                // comments: []
                            },
                            expression = /((^\#\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))/;

                        file.toString().split("\n").map(function(line) {

                            // comments are ignored
                            // this needs to be better
                            if (line.indexOf('#') === 0) {
                                // console.log("got comment", line.replace(/\#\ /ig, ''));
                                // if (utils.validateHost(line.replace(/\#\ /ig, ''))) {
                                //     // hosts.comments.push(line);
                                //     console.log('got disabled', line);
                                // }
                                return;
                            }

                            // split the string to get the ip and hosts
                            line = line .replace(/(\s)+/g, ' ')
                                        .split(' ');

                            if (!line.length || line.length < 2) {

                            } else {

                                // duplicate ip, so merge them
                                if (line[0].length) {

                                    let ip = hosts[line[0]];

                                    if (ip) {
                                        ip = ip.concat(_.compact(line.slice(1)));
                                    } else {
                                        ip = _.compact(line.slice(1));
                                    }

                                    // only return matching hosts
                                    if (filter) {

                                        var matching = _.filter(ip, function(ip) {
                                            return ip.indexOf(filter) > -1;
                                        });

                                        if (matching.length) {
                                            ip = matching;
                                        } else {
                                            return;
                                        }
                                    }

                                    hosts[line[0]] = _.uniq(ip);
                                }
                            }
                        });

                        return hosts;
                    })
                    // format the ips
                    .then(function(hosts) {

                        return utils.sortEntries(hosts);
                    });
                })
                .catch(function(e) {
                    console.error(e);
                });

        },

        /**
         * saveToFile
         *
         *
         */
        saveToFile = function (hosts) {

            // sort the dictionary of entries
            hosts = utils.sortEntries(hosts);

            return new promise(function(resolve, reject) {

                getHostFilePath()
                    .then(function(path) {

                        let contents = [
                            util.format('# '),
                            util.format('#    /)'),
                            util.format('#  (/   ___ _  _/___   _   __ _/_)        v%s / %s', pkg.version, new Date()),
                            util.format('#  / )_(_) /_)_(__/_)_(_(_/ (_(__(_/_     %s', pkg.repository),
                            util.format('#              .-/              .-/'),
                            util.format('#             (_/              (_/'),
                            util.format('')
                        ];

                        _.each(hosts, function(hosts, ip) {

                            // group the hosts by IP
                            if (options.group) {

                                contents.push(util.format('%s %s', ip, hosts.join(' ')));
                            } else {

                                // don't group - 1 line per IP
                                hosts.forEach(function(host) {
                                    contents.push(util.format('%s %s', ip, host));
                                });
                            }
                        });

                        //
                        return fs
                            .writeFileAsync(path, util.format("%s%s", contents.join("\n"), "\n"))
                            .then(resolve)
                            .catch(function(e) {

                                var message     = 'Error writing file',
                                    elevated    = (os.platform().match(/^win/i) ? 'Administrator' : 'root');

                                // access denied?
                                switch (e.code) {
                                    case 'EACCES':
                                        message = util.format('Write permission denied on %s. Try running as %s.', path, elevated);
                                        break;
                                }

                                reject(message);
                            });

                    }).catch(reject);
            });
        };

    return {
        setup:      setup,
        add:        add,
        remove:     remove,
        list:       list,
        purge:      purge,
        // disable:    disable,
        // enable:     enable
    };
})();

module.exports = api;
<|endoftext|>


<commit_before>var pkg = require('./package.json');

var banner = '/**\n' +
      ' * <%= pkg.description %>\n' +
      ' * @version v<%= pkg.version %>\n' +
      ' * @link <%= pkg.homepage %>\n' +
      ' * @author <%= pkg.author %>\n' +
      ' * @license MIT License, http://www.opensource.org/licenses/MIT\n' +
      ' */\n\n';

var gulp = require('gulp'),
    karma = require('karma').server,
    jshint = require('gulp-jshint'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    sass = require('gulp-sass');
    autoprefixer = require('gulp-autoprefixer'),
    minifycss = require('gulp-minify-css'),
    header = require('gulp-header');

gulp.task('lint', function() {
  return gulp.src([
      'src/vAccordion/**/*.js',
      'test/**/*Spec.js'
    ])
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

gulp.task('scripts', function() {
  gulp.src([
      'src/vAccordion/vAccordion.prefix',
      'src/vAccordion/**/*.js',
      'src/vAccordion/vAccordion.suffix'
    ])
    .pipe(concat('v-accordion.js'))
    .pipe(header(banner, { pkg : pkg } ))
    .pipe(gulp.dest('./dist/'))
    .pipe(uglify())
    .pipe(rename('v-accordion.min.js'))
    .pipe(header(banner, { pkg : pkg } ))
    .pipe(gulp.dest('./dist'))
});

gulp.task('styles', function() {
  return gulp.src('src/vAccordion/styles/v-accordion.scss')
    .pipe(sass({style: 'expanded'}))
    .pipe(autoprefixer('last 2 version'))
    .pipe(header(banner, { pkg : pkg } ))
    .pipe(gulp.dest('dist/'))
    .pipe(rename({suffix: '.min'} ))
    .pipe(minifycss())
    .pipe(header(banner, { pkg : pkg } ))
    .pipe(gulp.dest('dist/'))
});

gulp.task('test', function (done) {
  karma.start({
    configFile: __dirname + '/karma.conf.js',
    singleRun: true
  }, done);
});

gulp.task('default', ['lint', 'test', 'scripts', 'styles']);

gulp.task('watch', function() {
  gulp.watch('src/vAccordion/**/*.js', ['lint', 'scripts']);
  gulp.watch('src/vAccordion/styles/**/*.scss', ['styles']);
  gulp.watch('test/**/*Spec.js', ['lint', 'test']);
});<commit_msg>refactor gulpfile.js<commit_after>var pkg = require('./package.json');

var banner = '/**\n' +
      ' * <%= pkg.description %>\n' +
      ' * @version v<%= pkg.version %>\n' +
      ' * @link <%= pkg.homepage %>\n' +
      ' * @author <%= pkg.author %>\n' +
      ' * @license MIT License, http://www.opensource.org/licenses/MIT\n' +
      ' */\n\n';

var gulp = require('gulp'),
    karma = require('karma').server,
    jshint = require('gulp-jshint'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    sass = require('gulp-sass');
    autoprefixer = require('gulp-autoprefixer'),
    minifycss = require('gulp-minify-css'),
    header = require('gulp-header');

gulp.task('scripts', function() {
  gulp.src([
      'src/vAccordion/vAccordion.prefix',
      'src/vAccordion/**/*.js',
      'src/vAccordion/vAccordion.suffix'
    ])
    .pipe(concat('v-accordion.js'))
    .pipe(header(banner, { pkg : pkg } ))
    .pipe(gulp.dest('./dist/'))
    .pipe(uglify())
    .pipe(rename('v-accordion.min.js'))
    .pipe(header(banner, { pkg : pkg } ))
    .pipe(gulp.dest('./dist'))
});

gulp.task('styles', function() {
  return gulp.src('src/vAccordion/styles/v-accordion.scss')
    .pipe(sass({style: 'expanded'}))
    .pipe(autoprefixer('last 2 version'))
    .pipe(header(banner, { pkg : pkg } ))
    .pipe(gulp.dest('dist/'))
    .pipe(rename({suffix: '.min'} ))
    .pipe(minifycss())
    .pipe(header(banner, { pkg : pkg } ))
    .pipe(gulp.dest('dist/'))
});

gulp.task('test', function (done) {
  karma.start({
    configFile: __dirname + '/karma.conf.js',
    singleRun: true
  }, done);
});

gulp.task('lint-src', function() {
  return gulp.src([
      'src/vAccordion/**/*.js',
    ])
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

gulp.task('lint-tests', function() {
  return gulp.src([
      'test/**/*Spec.js'
    ])
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

gulp.task('default', ['lint-src', 'test', 'scripts', 'styles']);

gulp.task('watch', function() {
  gulp.watch('src/vAccordion/**/*.js', ['lint-src', 'scripts']);
  gulp.watch('test/**/*Spec.js', ['lint-tests', 'test']);

  gulp.watch('src/vAccordion/styles/**/*.scss', ['styles']);
});<|endoftext|>


<commit_before>/**
 * Expose the parse function.
 */
module.exports = parse;

var
	/**
	 * Dependencies.
	 */
	debug = require('debug')('cpim:parse'),
	debugerror = require('debug')('cpim:ERROR:parse'),
	grammar = require('./grammar'),
	Message = require('./Message'),

	/**
 	 * Constants.
 	 */
	REGEXP_VALID_HEADER = /^(([a-zA-Z0-9!#$%&'+,\-\^_`|~]+)\.)?([a-zA-Z0-9!#$%&'+,\-\^_`|~]+):[^ ]* (.+)$/,
	REGEXP_VALID_MIME_HEADER = /^([a-zA-Z0-9!#$%&'+,\-\^_`|~]+)[ \t]*:[ \t]*(.+)$/;  // TODO: RFC 2045

debugerror.log = console.warn.bind(console);

function parse(raw) {
	debug('parse()');

	var
		headersEnd,
		mimeHeadersEnd,
		rawHeaders,
		rawMimeHeaders,
		rawBody,
		message;

	if (typeof raw !== 'string') {
		throw new Error('given data must be a string');
	}

	headersEnd = raw.indexOf('\r\n\r\n');
	if (headersEnd === -1) {
		debugerror('wrong headers');
		return false;
	}
	rawHeaders = raw.slice(0, headersEnd);

	mimeHeadersEnd = raw.indexOf('\r\n\r\n', headersEnd + 1);
	rawMimeHeaders = raw.slice(headersEnd + 4, mimeHeadersEnd).trim();

	if (mimeHeadersEnd !== -1) {
		rawBody = raw.slice(mimeHeadersEnd + 4, -1);
	}

	// Init the Message instance.
	message = new Message();

	// Parse headers.
	if (!parseHeaders(rawHeaders)) {
		return false;
	}

	// Parse MIME headers.
	if (!parseMimeHeaders(rawMimeHeaders)) {
		return false;
	}

	// Get body.
	if (rawBody) {
		message._body = rawBody;
	}

	return message;

	function parseHeaders(rawHeaders) {
		var
			lines = rawHeaders.split('\r\n'),
			i, len,
			currentDefaultNSUri,
			ns = {};  // key: prefix, value: uri.

		for (i = 0, len = lines.length; i < len; i++) {
			if (!parseHeader(lines[i])) {
				debugerror('discarding message due to invalid header: "%s"', lines[i]);
				return false;
			}
		}

		return true;

		function parseHeader(line) {
			var
				match = line.match(REGEXP_VALID_HEADER),
				prefix,
				name,
				value,
				nsUri,
				rule,
				parsedValue,
				i, len,
				data = {};

			if (!match) {
				debugerror('invalid header "%s"', line);
				return false;
			}

			prefix = match[2];
			name = match[3];
			value = match[4];

			if (prefix) {
				nsUri = ns[prefix];

				if (!ns[prefix]) {
					debugerror('non declared prefix in line "%s"', line);
					return false;
				}
			// Don't apply defualt prefix if header is a NS.
			} else if (currentDefaultNSUri && name !== 'NS') {
				nsUri = currentDefaultNSUri;
			}

			// Ignore prefixes to the CORE NS URI ('urn:ietf:params:cpim-headers:').
			if (nsUri === grammar.NS_PREFIX_CORE) {
				nsUri = undefined;
			}

			// Complete the header name with its prefix URI.
			if (nsUri) {
				name = nsUri + '@' + name;
			}

			if (message._cpimHeaders[name] && grammar.isSingleCpimHeader(name)) {
				debugerror('"%s" header can only appear once', name);
				return false;
			}

			rule = grammar.cpimHeaderRules[name] || grammar.unknownCpimHeaderRule;

			if (typeof rule.reg !== 'function') {
				parsedValue = value.match(rule.reg);
				if (!parsedValue) {
					debugerror('wrong header: "%s"', line);
					return false;
				}

				for (i = 0, len = rule.names.length; i < len; i++) {
					if (parsedValue[i + 1] !== undefined) {
						data[rule.names[i]] = parsedValue[i + 1];
					}
				}
			} else {
				data = rule.reg(value);
				if (!data) {
					debugerror('wrong header: "%s"', line);
					return false;
				}
			}
			data.value = value;

			// Special treatment for NS headers.
			if (name === 'NS') {
				if (data.prefix) {
					ns[data.prefix] = data.uri.toLowerCase();
				} else {
					currentDefaultNSUri = data.uri.toLowerCase();
				}

				message.addNS(data.uri.toLowerCase());
			}

			(message._cpimHeaders[name] = message._cpimHeaders[name] || []).push(data);
			return true;
		}
	}

	function parseMimeHeaders(rawMimeHeaders) {
		var
			lines = rawMimeHeaders.split('\r\n'),
			i, len;

		for (i = 0, len = lines.length; i < len; i++) {
			if (!parseMimeHeader(lines[i])) {
				debugerror('discarding message due to invalid MIME header: "%s"', lines[i]);
				return false;
			}
		}

		return true;

		function parseMimeHeader(line) {
			var
				match = line.match(REGEXP_VALID_MIME_HEADER),
				name,
				value,
				rule,
				parsedValue,
				i, len,
				data = {};

			if (!match) {
				debugerror('invalid MIME header "%s"', line);
				return false;
			}

			name = grammar.headerize(match[1]);
			value = match[2];

			rule = grammar.mimeHeaderRules[name] || grammar.unknownMimeHeaderRule;

			if (typeof rule.reg !== 'function') {
				parsedValue = value.match(rule.reg);
				if (!parsedValue) {
					debugerror('wrong MIME header: "%s"', line);
					return false;
				}

				for (i = 0, len = rule.names.length; i < len; i++) {
					if (parsedValue[i + 1] !== undefined) {
						data[rule.names[i]] = parsedValue[i + 1];
					}
				}
			} else {
				data = rule.reg(value);
				if (!data) {
					debugerror('wrong MIME header: "%s"', line);
					return false;
				}
			}
			data.value = value;

			message._mimeHeaders[name] = data;
			return true;
		}
	}
}
<commit_msg>Fix body parsing.<commit_after>/**
 * Expose the parse function.
 */
module.exports = parse;

var
	/**
	 * Dependencies.
	 */
	debug = require('debug')('cpim:parse'),
	debugerror = require('debug')('cpim:ERROR:parse'),
	grammar = require('./grammar'),
	Message = require('./Message'),

	/**
 	 * Constants.
 	 */
	REGEXP_VALID_HEADER = /^(([a-zA-Z0-9!#$%&'+,\-\^_`|~]+)\.)?([a-zA-Z0-9!#$%&'+,\-\^_`|~]+):[^ ]* (.+)$/,
	REGEXP_VALID_MIME_HEADER = /^([a-zA-Z0-9!#$%&'+,\-\^_`|~]+)[ \t]*:[ \t]*(.+)$/;  // TODO: RFC 2045

debugerror.log = console.warn.bind(console);

function parse(raw) {
	debug('parse()');

	var
		headersEnd,
		mimeHeadersEnd,
		rawHeaders,
		rawMimeHeaders,
		rawBody,
		message;

	if (typeof raw !== 'string') {
		throw new Error('given data must be a string');
	}

	headersEnd = raw.indexOf('\r\n\r\n');
	if (headersEnd === -1) {
		debugerror('wrong headers');
		return false;
	}
	rawHeaders = raw.slice(0, headersEnd);

	mimeHeadersEnd = raw.indexOf('\r\n\r\n', headersEnd + 1);
	rawMimeHeaders = raw.slice(headersEnd + 4, mimeHeadersEnd);

	if (mimeHeadersEnd !== -1) {
		rawBody = raw.slice(mimeHeadersEnd + 4);
	}

	// Init the Message instance.
	message = new Message();

	// Parse headers.
	if (!parseHeaders(rawHeaders)) {
		return false;
	}

	// Parse MIME headers.
	if (!parseMimeHeaders(rawMimeHeaders)) {
		return false;
	}

	// Get body.
	if (rawBody) {
		message._body = rawBody;
	}

	return message;

	function parseHeaders(rawHeaders) {
		var
			lines = rawHeaders.split('\r\n'),
			i, len,
			currentDefaultNSUri,
			ns = {};  // key: prefix, value: uri.

		for (i = 0, len = lines.length; i < len; i++) {
			if (!parseHeader(lines[i])) {
				debugerror('discarding message due to invalid header: "%s"', lines[i]);
				return false;
			}
		}

		return true;

		function parseHeader(line) {
			var
				match = line.match(REGEXP_VALID_HEADER),
				prefix,
				name,
				value,
				nsUri,
				rule,
				parsedValue,
				i, len,
				data = {};

			if (!match) {
				debugerror('invalid header "%s"', line);
				return false;
			}

			prefix = match[2];
			name = match[3];
			value = match[4];

			if (prefix) {
				nsUri = ns[prefix];

				if (!ns[prefix]) {
					debugerror('non declared prefix in line "%s"', line);
					return false;
				}
			// Don't apply defualt prefix if header is a NS.
			} else if (currentDefaultNSUri && name !== 'NS') {
				nsUri = currentDefaultNSUri;
			}

			// Ignore prefixes to the CORE NS URI ('urn:ietf:params:cpim-headers:').
			if (nsUri === grammar.NS_PREFIX_CORE) {
				nsUri = undefined;
			}

			// Complete the header name with its prefix URI.
			if (nsUri) {
				name = nsUri + '@' + name;
			}

			if (message._cpimHeaders[name] && grammar.isSingleCpimHeader(name)) {
				debugerror('"%s" header can only appear once', name);
				return false;
			}

			rule = grammar.cpimHeaderRules[name] || grammar.unknownCpimHeaderRule;

			if (typeof rule.reg !== 'function') {
				parsedValue = value.match(rule.reg);
				if (!parsedValue) {
					debugerror('wrong header: "%s"', line);
					return false;
				}

				for (i = 0, len = rule.names.length; i < len; i++) {
					if (parsedValue[i + 1] !== undefined) {
						data[rule.names[i]] = parsedValue[i + 1];
					}
				}
			} else {
				data = rule.reg(value);
				if (!data) {
					debugerror('wrong header: "%s"', line);
					return false;
				}
			}
			data.value = value;

			// Special treatment for NS headers.
			if (name === 'NS') {
				if (data.prefix) {
					ns[data.prefix] = data.uri.toLowerCase();
				} else {
					currentDefaultNSUri = data.uri.toLowerCase();
				}

				message.addNS(data.uri.toLowerCase());
			}

			(message._cpimHeaders[name] = message._cpimHeaders[name] || []).push(data);
			return true;
		}
	}

	function parseMimeHeaders(rawMimeHeaders) {
		var
			lines = rawMimeHeaders.split('\r\n'),
			i, len;

		for (i = 0, len = lines.length; i < len; i++) {
			if (!parseMimeHeader(lines[i])) {
				debugerror('discarding message due to invalid MIME header: "%s"', lines[i]);
				return false;
			}
		}

		return true;

		function parseMimeHeader(line) {
			var
				match = line.match(REGEXP_VALID_MIME_HEADER),
				name,
				value,
				rule,
				parsedValue,
				i, len,
				data = {};

			if (!match) {
				debugerror('invalid MIME header "%s"', line);
				return false;
			}

			name = grammar.headerize(match[1]);
			value = match[2];

			rule = grammar.mimeHeaderRules[name] || grammar.unknownMimeHeaderRule;

			if (typeof rule.reg !== 'function') {
				parsedValue = value.match(rule.reg);
				if (!parsedValue) {
					debugerror('wrong MIME header: "%s"', line);
					return false;
				}

				for (i = 0, len = rule.names.length; i < len; i++) {
					if (parsedValue[i + 1] !== undefined) {
						data[rule.names[i]] = parsedValue[i + 1];
					}
				}
			} else {
				data = rule.reg(value);
				if (!data) {
					debugerror('wrong MIME header: "%s"', line);
					return false;
				}
			}
			data.value = value;

			message._mimeHeaders[name] = data;
			return true;
		}
	}
}
<|endoftext|>


<commit_before>const { ObjectID } = require('mongodb');
const errors = require('@feathersjs/errors');
const { _ } = require('@feathersjs/commons');
const { AdapterService, select } = require('@feathersjs/adapter-commons');

const errorHandler = require('./error-handler');

// Create the service.
class Service extends AdapterService {
  constructor (options) {
    if (!options) {
      throw new Error('MongoDB options have to be provided');
    }

    super(Object.assign({
      id: '_id'
    }, options));
  }

  get Model () {
    return this.options.Model;
  }

  _objectifyId (id) {
    if (this.id === '_id' && ObjectID.isValid(id)) {
      id = new ObjectID(id.toString());
    }

    return id;
  }

  _multiOptions (id, params) {
    const { query } = this.filterQuery(params);
    const options = Object.assign({ multi: true }, params.mongodb || params.options);

    if (id !== null) {
      options.multi = false;
      query[this.id] = this._objectifyId(id);
    }

    return { query, options };
  }

  _getSelect (select) {
    if (Array.isArray(select)) {
      var result = {};
      select.forEach(name => {
        result[name] = 1;
      });
      return result;
    }

    return select;
  }

  _findOrGet (id, params) {
    if (id === null) {
      return this._find(params);
    }

    return this._get(id, params);
  }

  _normalizeId (id, data) {
    if (this.id === '_id') {
      // Default Mongo IDs cannot be updated. The Mongo library handles
      // this automatically.
      return _.omit(data, this.id);
    } else if (id !== null) {
      // If not using the default Mongo _id field set the ID to its
      // previous value. This prevents orphaned documents.
      return Object.assign({}, data, { [this.id]: id });
    } else {
      return data;
    }
  }

  // Map stray records into $set
  _remapModifiers (data) {
    var set = {};
    // Step through the rooot
    for (var key in data) {
      // Check for keys that aren't modifiers
      if (key.charAt(0) !== '$') {
        // Move them to set, and remove their record
        set[key] = data[key];
        delete data[key];
      }
      // If the '$set' modifier is used, add that to the temp variable
      if (key === '$set') {
        set = Object.assign(set, data[key]);
        delete data[key];
      }
    }
    // If we have a $set, then attach to the data object
    if (Object.keys(set).length > 0) {
      data['$set'] = set;
    }
    return data;
  }

  _find (params) {
    // Start with finding all, and limit when necessary.
    const { filters, query, paginate } = this.filterQuery(params);

    // Objectify the id field if it's present
    if (query[this.id]) {
      query[this.id] = this._objectifyId(query[this.id]);
    }

    const q = this.Model.find(query);

    if (filters.$select) {
      q.project(this._getSelect(filters.$select));
    }

    if (filters.$sort) {
      q.sort(filters.$sort);
    }

    if (params.collation) {
      q.collation(params.collation);
    }

    if (params.hint) {
      q.hint(params.hint);
    }

    if (filters.$limit) {
      q.limit(filters.$limit);
    }

    if (filters.$skip) {
      q.skip(filters.$skip);
    }

    let runQuery = total => {
      return q.toArray().then(data => {
        return {
          total,
          limit: filters.$limit,
          skip: filters.$skip || 0,
          data
        };
      });
    };

    if (filters.$limit === 0) {
      runQuery = total => {
        return Promise.resolve({
          total,
          limit: filters.$limit,
          skip: filters.$skip || 0,
          data: []
        });
      };
    }

    if (paginate && paginate.default) {
      return this.Model.countDocuments(query).then(runQuery);
    }

    return runQuery().then(page => page.data);
  }

  _get (id, params) {
    const { query } = this.filterQuery(params);

    query[this.id] = this._objectifyId(id);

    return this.Model.findOne(query).then(data => {
      if (!data) {
        throw new errors.NotFound(`No record found for id '${id}'`);
      }

      return data;
    }).then(select(params, this.id)).catch(errorHandler);
  }

  _create (data, params) {
    const setId = item => {
      const entry = Object.assign({}, item);

      // Generate a MongoId if we use a custom id
      if (this.id !== '_id' && typeof entry[this.id] === 'undefined') {
        entry[this.id] = new ObjectID().toHexString();
      }

      return entry;
    };

    const promise = Array.isArray(data)
      ? this.Model.insertMany(data.map(setId))
      : this.Model.insertOne(setId(data));

    return promise.then(result => result.ops.length > 1 ? result.ops : result.ops[0])
      .then(select(params, this.id))
      .catch(errorHandler);
  }

  _patch (id, data, params) {
    let { query, options } = this._multiOptions(id, params);

    if (params.collation) {
      query = Object.assign(query, { collation: params.collation });
    }

    const findParams = Object.assign({}, params, {
      paginate: false
    });
    const remapModifier = this._remapModifiers(this._normalizeId(id, data));

    return this.Model.updateMany(query, remapModifier, options)
      .then(() => this._findOrGet(id, findParams))
      .then(select(params, this.id))
      .catch(errorHandler);
  }

  _update (id, data, params) {
    if (Array.isArray(data) || id === null) {
      return Promise.reject(
        new errors.BadRequest('Not replacing multiple records. Did you mean `patch`?')
      );
    }

    const { query, options } = this._multiOptions(id, params);

    return this.Model.replaceOne(query, this._normalizeId(id, data), options)
      .then(() => this._findOrGet(id, params))
      .then(select(params, this.id))
      .catch(errorHandler);
  }

  _remove (id, params) {
    let { query } = this._multiOptions(id, params);

    if (params.collation) {
      query = Object.assign(query, { collation: params.collation });
    }

    const findParams = Object.assign({}, params, {
      paginate: false,
      query
    });

    return this._findOrGet(id, findParams)
      .then(items => {
        return this.Model.deleteMany(query)
          .then(() => items)
          .then(select(params, this.id));
      }).catch(errorHandler);
  }
}

module.exports = function init (options) {
  return new Service(options);
};

module.exports.Service = Service;
<commit_msg>Add default params to hook-less service methods (#133)<commit_after>const { ObjectID } = require('mongodb');
const errors = require('@feathersjs/errors');
const { _ } = require('@feathersjs/commons');
const { AdapterService, select } = require('@feathersjs/adapter-commons');

const errorHandler = require('./error-handler');

// Create the service.
class Service extends AdapterService {
  constructor (options) {
    if (!options) {
      throw new Error('MongoDB options have to be provided');
    }

    super(Object.assign({
      id: '_id'
    }, options));
  }

  get Model () {
    return this.options.Model;
  }

  _objectifyId (id) {
    if (this.id === '_id' && ObjectID.isValid(id)) {
      id = new ObjectID(id.toString());
    }

    return id;
  }

  _multiOptions (id, params = {}) {
    const { query } = this.filterQuery(params);
    const options = Object.assign({ multi: true }, params.mongodb || params.options);

    if (id !== null) {
      options.multi = false;
      query[this.id] = this._objectifyId(id);
    }

    return { query, options };
  }

  _getSelect (select) {
    if (Array.isArray(select)) {
      var result = {};
      select.forEach(name => {
        result[name] = 1;
      });
      return result;
    }

    return select;
  }

  _findOrGet (id, params = {}) {
    if (id === null) {
      return this._find(params);
    }

    return this._get(id, params);
  }

  _normalizeId (id, data) {
    if (this.id === '_id') {
      // Default Mongo IDs cannot be updated. The Mongo library handles
      // this automatically.
      return _.omit(data, this.id);
    } else if (id !== null) {
      // If not using the default Mongo _id field set the ID to its
      // previous value. This prevents orphaned documents.
      return Object.assign({}, data, { [this.id]: id });
    } else {
      return data;
    }
  }

  // Map stray records into $set
  _remapModifiers (data) {
    var set = {};
    // Step through the rooot
    for (var key in data) {
      // Check for keys that aren't modifiers
      if (key.charAt(0) !== '$') {
        // Move them to set, and remove their record
        set[key] = data[key];
        delete data[key];
      }
      // If the '$set' modifier is used, add that to the temp variable
      if (key === '$set') {
        set = Object.assign(set, data[key]);
        delete data[key];
      }
    }
    // If we have a $set, then attach to the data object
    if (Object.keys(set).length > 0) {
      data['$set'] = set;
    }
    return data;
  }

  _find (params = {}) {
    // Start with finding all, and limit when necessary.
    const { filters, query, paginate } = this.filterQuery(params);

    // Objectify the id field if it's present
    if (query[this.id]) {
      query[this.id] = this._objectifyId(query[this.id]);
    }

    const q = this.Model.find(query);

    if (filters.$select) {
      q.project(this._getSelect(filters.$select));
    }

    if (filters.$sort) {
      q.sort(filters.$sort);
    }

    if (params.collation) {
      q.collation(params.collation);
    }

    if (params.hint) {
      q.hint(params.hint);
    }

    if (filters.$limit) {
      q.limit(filters.$limit);
    }

    if (filters.$skip) {
      q.skip(filters.$skip);
    }

    let runQuery = total => {
      return q.toArray().then(data => {
        return {
          total,
          limit: filters.$limit,
          skip: filters.$skip || 0,
          data
        };
      });
    };

    if (filters.$limit === 0) {
      runQuery = total => {
        return Promise.resolve({
          total,
          limit: filters.$limit,
          skip: filters.$skip || 0,
          data: []
        });
      };
    }

    if (paginate && paginate.default) {
      return this.Model.countDocuments(query).then(runQuery);
    }

    return runQuery().then(page => page.data);
  }

  _get (id, params = {}) {
    const { query } = this.filterQuery(params);

    query[this.id] = this._objectifyId(id);

    return this.Model.findOne(query).then(data => {
      if (!data) {
        throw new errors.NotFound(`No record found for id '${id}'`);
      }

      return data;
    }).then(select(params, this.id)).catch(errorHandler);
  }

  _create (data, params = {}) {
    const setId = item => {
      const entry = Object.assign({}, item);

      // Generate a MongoId if we use a custom id
      if (this.id !== '_id' && typeof entry[this.id] === 'undefined') {
        entry[this.id] = new ObjectID().toHexString();
      }

      return entry;
    };

    const promise = Array.isArray(data)
      ? this.Model.insertMany(data.map(setId))
      : this.Model.insertOne(setId(data));

    return promise.then(result => result.ops.length > 1 ? result.ops : result.ops[0])
      .then(select(params, this.id))
      .catch(errorHandler);
  }

  _patch (id, data, params = {}) {
    let { query, options } = this._multiOptions(id, params);

    if (params.collation) {
      query = Object.assign(query, { collation: params.collation });
    }

    const findParams = Object.assign({}, params, {
      paginate: false
    });
    const remapModifier = this._remapModifiers(this._normalizeId(id, data));

    return this.Model.updateMany(query, remapModifier, options)
      .then(() => this._findOrGet(id, findParams))
      .then(select(params, this.id))
      .catch(errorHandler);
  }

  _update (id, data, params = {}) {
    if (Array.isArray(data) || id === null) {
      return Promise.reject(
        new errors.BadRequest('Not replacing multiple records. Did you mean `patch`?')
      );
    }

    const { query, options } = this._multiOptions(id, params);

    return this.Model.replaceOne(query, this._normalizeId(id, data), options)
      .then(() => this._findOrGet(id, params))
      .then(select(params, this.id))
      .catch(errorHandler);
  }

  _remove (id, params = {}) {
    let { query } = this._multiOptions(id, params);

    if (params.collation) {
      query = Object.assign(query, { collation: params.collation });
    }

    const findParams = Object.assign({}, params, {
      paginate: false,
      query
    });

    return this._findOrGet(id, findParams)
      .then(items => {
        return this.Model.deleteMany(query)
          .then(() => items)
          .then(select(params, this.id));
      }).catch(errorHandler);
  }
}

module.exports = function init (options) {
  return new Service(options);
};

module.exports.Service = Service;
<|endoftext|>


<commit_before>var gulp = require('gulp'),
    gutil = require('gulp-util')
    concat = require('gulp-concat')
    sourcemaps = require('gulp-sourcemaps')
    uglify = require('gulp-uglify'),
    sass = require('gulp-sass'),
    uglifycss = require('gulp-uglifycss');

gulp.task("default",['watch']);

//gulp watch task for sorce code
gulp.task("watch",['build-lib'], function(){
	gulp.watch("src/sass/*",['build-sass']);
	gulp.watch("src/assets/css/**/*.css",['product-css']);

});

//Getting minified libs and put to distribution
gulp.task("build-lib",function(){
	return gulp.src(["src/assets/libs/**/*.min.js","src/assets/libs/**/*.min.css"])
					.pipe(gulp.dest('dist/assets/libs/'));
});

//Compiling sass to css in source
gulp.task("build-sass",function(){
	return gulp.src('src/sass/*.scss')
      .pipe(sass())
    .pipe(gulp.dest('src/assets/css/'));
});

//Build, Minified css for distribution
gulp.task("product-css", function(){
	return gulp.src("src/assets/css/**/*.css")
			.pipe(sourcemaps.init())
			.pipe(concat("main.min.css"))
			.pipe(uglifycss())
			.pipe(sourcemaps.write())
			.pipe(gulp.dest('dist/assets/css/'));
});
<commit_msg>Gulp task added to automate javascript build for distribution<commit_after>var gulp = require('gulp'),
    gutil = require('gulp-util')
    concat = require('gulp-concat')
    sourcemaps = require('gulp-sourcemaps')
    uglify = require('gulp-uglify'),
    sass = require('gulp-sass'),
    uglifycss = require('gulp-uglifycss');

gulp.task("default",['watch']);

//gulp watch task for sorce code
gulp.task("watch",['build-lib'], function(){
	gulp.watch("src/sass/*",['build-sass']);
	gulp.watch("src/assets/css/**/*.css",['product-css']);
	gulp.watch("src/assets/js/**/*.js",['product-js']);

});

//Getting minified libs and put to distribution
gulp.task("build-lib",function(){
	return gulp.src(["src/assets/libs/**/*.min.js","src/assets/libs/**/*.min.css"])
					.pipe(gulp.dest('dist/assets/libs/'));
});

//Compiling sass to css in source
gulp.task("build-sass",function(){
	return gulp.src('src/sass/*.scss')
      .pipe(sass())
    .pipe(gulp.dest('src/assets/css/'));
});

//Build, Minified css for distribution
gulp.task("product-css", function(){
	return gulp.src("src/assets/css/**/*.css")
			.pipe(sourcemaps.init())
			.pipe(concat("main.min.css"))
			.pipe(uglifycss())
			.pipe(sourcemaps.write())
			.pipe(gulp.dest('dist/assets/css/'));
});

//Build, minify all javascript for distribution
gulp.task("product-js", function(){
	return gulp.src('src/assets/js/*.js')
	   .pipe(sourcemaps.init())
		.pipe(concat('main.min.js'))
	    .pipe(uglify())
	    .pipe(sourcemaps.write())
		.pipe(gulp.dest('dist/assets/js/'));
});
<|endoftext|>


<commit_before>// Include Gulp
var gulp = require('gulp');

// Include Plugins
var browserSync = require('browser-sync').create();
var bootlint = require('gulp-bootlint');
var rename = require('gulp-rename');
var sass = require('gulp-sass');
var jshint = require('gulp-jshint');

// Init BrowserSync
gulp.task('browserSync', function() {
	browserSync.init({
    	server: {
      		baseDir: 'dist'
    	},
  	});
});

// Lint Bootstrap
gulp.task('bootlint', function() {
    return gulp.src('src/*.html')
        .pipe(bootlint());
});

// Compile Sass
gulp.task('sass', function() {
  	return gulp.src('src/sass/main.scss')
  		.pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError))
    	.pipe(rename('cards.css'))
    	.pipe(gulp.dest('dist/css'))
    	.pipe(browserSync.reload({
      		stream: true
    	}));
});

// Lint JS
gulp.task('lint', function() {
    return gulp.src('src/js/**/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'));
});

// Copy JS
gulp.task('copyJS', function() {
    return gulp.src('src/js/**/*.js')
        .pipe(gulp.dest('dist/js'));
});

// Copy HTML
gulp.task('copyHTML', function () {
    return gulp.src('src/*.html')
        .pipe(gulp.dest('dist'));
});

// Copy Images
gulp.task('copyImg', function () {
    return gulp.src('src/img/*.*')
        .pipe(gulp.dest('dist/img'));
});

// Copy Fonts
gulp.task('copyFonts', function () {
    return gulp.src('src/fonts/*.*')
        .pipe(gulp.dest('dist/fonts'));
});

// Watch Files For Changes
gulp.task('watch', ['browserSync', 'bootlint', 'sass', 'lint', 'copyJS', 'copyHTML', 'copyImg', 'copyFonts'], function() {
    gulp.watch('src/sass/**/*.scss', ['sass']);
    gulp.watch('src/js/**/*.js', ['lint', 'copyJS']);
    gulp.watch('src/*.html', ['bootlint', 'copyHTML']);
    gulp.watch('src/img/*.*', ['copyImg']);
    gulp.watch('src/fonts/*.*', ['copyFonts']);
    gulp.watch('src/*.html', browserSync.reload);
    gulp.watch('js/**/*.js', browserSync.reload);
    gulp.watch('src/img', browserSync.reload);
    gulp.watch('src/fonts', browserSync.reload);
});

// Default Task
gulp.task('default', ['watch']);<commit_msg>Indentation Fixes<commit_after>// Include Gulp
var gulp = require('gulp');

// Include Plugins
var browserSync = require('browser-sync').create();
var bootlint = require('gulp-bootlint');
var rename = require('gulp-rename');
var sass = require('gulp-sass');
var jshint = require('gulp-jshint');

// Init BrowserSync
gulp.task('browserSync', function() {
    browserSync.init({ server: { baseDir: 'dist' } });
});

// Lint Bootstrap
gulp.task('bootlint', function() {
    return gulp.src('src/*.html')
    .pipe(bootlint());
});

// Compile Sass
gulp.task('sass', function() {
    return gulp.src('src/sass/main.scss')
    .pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError))
    .pipe(rename('cards.css'))
    .pipe(gulp.dest('dist/css'))
    .pipe(browserSync.reload({stream: true}));
});

// Lint JS
gulp.task('lint', function() {
    return gulp.src('src/js/**/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter('default'));
});

// Copy JS
gulp.task('copyJS', function() {
    return gulp.src('src/js/**/*.js')
    .pipe(gulp.dest('dist/js'));
});

// Copy HTML
gulp.task('copyHTML', function () {
    return gulp.src('src/*.html')
    .pipe(gulp.dest('dist'));
});

// Copy Images
gulp.task('copyImg', function () {
    return gulp.src('src/img/*.*')
    .pipe(gulp.dest('dist/img'));
});

// Copy Fonts
gulp.task('copyFonts', function () {
    return gulp.src('src/fonts/*.*')
    .pipe(gulp.dest('dist/fonts'));
});

// Watch Files For Changes
gulp.task('watch', ['browserSync', 'bootlint', 'sass', 'lint', 'copyJS', 'copyHTML', 'copyImg', 'copyFonts'], function() {
    gulp.watch('src/sass/**/*.scss', ['sass']);
    gulp.watch('src/js/**/*.js', ['lint', 'copyJS']);
    gulp.watch('src/*.html', ['bootlint', 'copyHTML']);
    gulp.watch('src/img/*.*', ['copyImg']);
    gulp.watch('src/fonts/*.*', ['copyFonts']);
    gulp.watch('src/*.html', browserSync.reload);
    gulp.watch('js/**/*.js', browserSync.reload);
    gulp.watch('src/img', browserSync.reload);
    gulp.watch('src/fonts', browserSync.reload);
});

// Default Task
gulp.task('default', ['watch']);<|endoftext|>


<commit_before>// Load modules

var Boom = require('boom');
var Hoek = require('hoek');
var HttpSignature = require('http-signature');

// Declare internals

var internals = {};

exports.register = function (plugin, options, next) {

  plugin.auth.scheme('signature', internals.implementation);
  next();
};

exports.register.attributes = {
  pkg: require('../package.json')
};

internals.implementation = function (server, options) {

  Hoek.assert(options, 'Missing signature auth strategy options');
  Hoek.assert(typeof options.validateFunc === 'function', 'options.validateFunc must be a valid function in signature scheme');

  var settings = Hoek.clone(options);

  var scheme = {
    authenticate: function (request, reply) {

      var req = request.raw.req;
      if (!req.headers.authorization) {
        return reply(Boom.unauthorized(null, 'Signature'));
      }

      var parsedSignature = HttpSignature.parseRequest(req);
      if (!parsedSignature) {
        return reply(Boom.unauthorized('HTTP authentication header missing signature', 'Signature'));
      }

      settings.validateFunc(request, parsedSignature, function (err, isValid, credentials) {

        credentials = credentials || null;

        if (err) {
          return reply(err, { credentials: credentials, log: { tags: ['auth', 'signature'], data: err } });
        }

        if (!isValid) {
          return reply(Boom.unauthorized('Bad signature', 'Signature'), { credentials: credentials });
        }

        if (!credentials ||
            typeof credentials !== 'object') {

          return reply(Boom.badImplementation('Bad credentials object received for Signature auth validation'), { log: { tags: ['auth', 'credentials'] } });
        }

        // Authenticated

        return reply(null, { credentials: credentials });
      });
    }
  };

  return scheme;
};<commit_msg>Use the new auth succeed reply interface<commit_after>// Load modules

var Boom = require('boom');
var Hoek = require('hoek');
var HttpSignature = require('http-signature');

// Declare internals

var internals = {};

exports.register = function (plugin, options, next) {

  plugin.auth.scheme('signature', internals.implementation);
  next();
};

exports.register.attributes = {
  pkg: require('../package.json')
};

internals.implementation = function (server, options) {

  Hoek.assert(options, 'Missing signature auth strategy options');
  Hoek.assert(typeof options.validateFunc === 'function', 'options.validateFunc must be a valid function in signature scheme');

  var settings = Hoek.clone(options);

  var scheme = {
    authenticate: function (request, reply) {

      var req = request.raw.req;
      if (!req.headers.authorization) {
        return reply(Boom.unauthorized(null, 'Signature'));
      }

      var parsedSignature = HttpSignature.parseRequest(req);
      if (!parsedSignature) {
        return reply(Boom.unauthorized('HTTP authentication header missing signature', 'Signature'));
      }

      settings.validateFunc(request, parsedSignature, function (err, isValid, credentials) {

        credentials = credentials || null;

        if (err) {
          return reply(err, { credentials: credentials, log: { tags: ['auth', 'signature'], data: err } });
        }

        if (!isValid) {
          return reply(Boom.unauthorized('Bad signature', 'Signature'), { credentials: credentials });
        }

        if (!credentials ||
            typeof credentials !== 'object') {

          return reply(Boom.badImplementation('Bad credentials object received for Signature auth validation'), { log: { tags: ['auth', 'credentials'] } });
        }

        // Authenticated

        return reply.continue({ credentials: credentials });
      });
    }
  };

  return scheme;
};<|endoftext|>