<commit_before>//This is the main entrypoint for starting up our server.
//If loaded as the main module, will start the server and start fetching
//comments from wordpress.  See bottom of file for the startup code

//Tested on node v6.10.2

//Run this in an anonymous function to avoid accidentally creating global variables
(function() {

//Dependencies
var pg = require('pg');
var fs = require('fs');
var fibers = require('fibers');
var block = require('./block');
var Block = block.Block;
var request = require('request');
var querystring = require('querystring');
var express = require('express');
var url = require('url')

//How soon we kick off the loading-new-comments process after the last one finishes
var LOAD_COMMENTS_EVERY = 10*1000;
//How long we wait before retrying the loading-new-comments process if it fails
var FAIL_RETRY = 5*60*1000;
//The number of pages of results we load before committing the transaction
var MAX_PAGES = 10;

//cache our loaded configuration
var _config_cache;

//Track how caught up we are
var latestTimestamp = null;
//If we hit an error fetching comments, save it
var lastError = null;

//Loads our configuration from config.json.  This is a git-ignored file
//that we use to store credentials + settings that we don't want to check
//into git
function get_config() {
    //If we haven't yet, load it from disk
    if (!_config_cache) {
        try {
            _config_cache = JSON.parse(fs.readFileSync('config.json', 'utf8'));
        } catch (err) {
            //If we can't load config, we have to shutdown
            console.log('Unable to load and parse config.json.  Error was:');
            console.log(err.stack);
            process.exit(1);
        }
    }
    return _config_cache;
}

//store our pool of postgres clients
var _pool_cache;

//Returns our pool of postgres clients
function get_pool() {
    //If we haven't created a pool yet, create it now
    if (!_pool_cache) {
        var postgres = get_config().postgres;
        if (!postgres) {
            //If we don't have settings for postgres, this is a fatal error
            var msg = 'No "postgres" object found in config.json.  Expecting an object';
            msg += ' with some or all of these fields: "user", "database", "password",';
            msg += ' "host", "port", "max", "idleTimeoutMillis".  See new pg.Pool at ';
            msg += 'https://github.com/brianc/node-postgres';
            console.log(msg);

            process.exit(1);
        }
        _pool_cache = new pg.Pool(postgres);
    }
    return _pool_cache;
}

//Runs a function passing in a postgres client with a sync query function, which we release on completion
function withClient(fn) {
    var client = block.await(get_pool().connect())
    try {
        var c = {
            query: function (sql, params) {
                return block.await(client.query(sql, params));
            }
        }
        return fn(c);
    } finally {
        client.release();
    }
}

//Runs a function passing in a postgres client.  Starts a transaction, and automatically
//rolls back on error or commits on success
function transaction(fn) {
    withClient(function(client) {
        try {
            client.query('BEGIN');
            ret = fn(client);
            client.query('COMMIT');
            return ret;
        } catch (err) {
            client.query('ROLLBACK');
            throw err;
        }
    });
}

//Fetches all the comments that have come in since we last fetched,
//and persists them to the database as a single transaction.
function fetchComments() {
    //Track the latest timestamp for this operation.  On commit, we update the global
    //latestTimestamp variable
    var lt = null;

    //We run this entire operation as a transaction to protect against accidentally
    //having two comment-fetching processes running at once
    transaction(function(client) {
        //Acquire a lock so that only one process does this at a time
        client.query('SELECT pg_advisory_xact_lock(352342)');

        //Find our most recent comment, so we can get comments after that one
        var res = client.query('SELECT timestamp FROM public.comments ORDER BY timestamp DESC LIMIT 1');
        var start;
        if (res.rows[0]) {
             start = parseInt(res.rows[0].timestamp);
        } else {
            //Start from the beginning of time (plus a bit because Wordpress errors if start = 0)
            start = 86400000;
        }

        //We maintain a cache of comment ids to author names, because comments will
        //generally be in reply to recently posted comments, so it makes sense to remember
        //so we don't have to constantly query the database
        var ids_to_author_name = {}

        //Given a comment id, looks up the author name
        function getAuthorName(id) {
            //If we have it already, just return it
            if (ids_to_author_name[id]) {
                return ids_to_author_name[id];
            }

            //Otherwise, look it up from the database
            res = client.query("SELECT data->'author_name'::text as author_name FROM public.comments WHERE id = $1", [id])
            if (!res.rows[0] || !res.rows[0].author_name) { return null; }
            ids_to_author_name[id] = res.rows[0].author_name;
            return ids_to_author_name[id];
        }

        //Start from the first page of results, and go until there are no more results
        //or we are at MAX_PAGES
        var page = 1;
        while (page <= MAX_PAGES) {

            //Build the parameters to make the call to the wordpress API
            var url = get_config().api_base + '/wp-json/wp/v2/comments?'
            var params = {
                page: page,
                per_page: 100,
                after: (new Date(start)).toISOString(),
                order: 'asc'
            }
            url = url + querystring.stringify(params);

            //Temporary debugging:
            //console.log('Fetching ' + url);

            //Do the request and error if it's not a 200 response
            var block = Block();
            request(url, block.make_cb());
            response = block.wait();
            if (response.statusCode !== 200) {
                throw new Error('Non-200 response from ' + url + ': ' + response.statusCode + ' ' + response.body)
            }

            var comments = JSON.parse(response.body);

            //If there are no comments, we're at the end of the pagination, so break out of the while loop
            if (comments.length === 0) { break; }

            //Go through each comment, calculate the timestamp and in_reply_to fields,
            //and persist to the database
            var comment, timestamp, in_reply_to, params;
            for (var i = 0; i < comments.length; i++) {
                comment = comments[i];

                //update our ids_to_author_name hash
                ids_to_author_name[comment.id] = comment.author_name;

                timestamp = (new Date(comment.date_gmt)).valueOf();
                if (timestamp < lt) {
                    throw new Error('assertion error: got out-of-order timestamps');
                }
                lt = timestamp

                in_reply_to = []

                //See if there any explicit @ references
                //Currently, we count anything from an @ to a non-alphanumeric, non-space
                //character as the author name.  (This is because usually they'll be a
                //comma or a <p> at the end of the name).
                //We trim whitespace
                var regex = /@([a-zA-Z0-9\. ]+)/g
                while (match = regex.exec(comment.content.rendered)) {
                    in_reply_to.push(match[1].trim());

                    //TODO: can we compare unrecognized author names against our comment
                    //database and see if we can guess who they were referring to?
                }

                //See if there is a parent post
                if (comment.parent && getAuthorName(comment.parent)) {
                    in_reply_to.push(getAuthorName(comment.parent));
                }

                //Write the comment to postgres
                params = [comment.id, comment, timestamp, in_reply_to]
                client.query("INSERT INTO public.comments (id, data, timestamp, in_reply_to) VALUES ($1,$2,$3,$4)", params)

                //Temporary debugging
                //console.log('Added: ' + JSON.stringify(params, null, 4));
            }

            page++;
        }
    });

    //We've successfully committed, so update the latest timestamp,
    //and clear last error
    if (lt === null) {
        latestTimestamp = 'up-to-date';
    } else {
        latestTimestamp = lt;
    }
    lastError = null;

    //Temporary debugging
    //console.log('Successfully committed');
}

//Express route that displays the status of the comment downloading
function statusEndpoint (req, res, next) {
    try {
        var msg = 'Status: ';
        if (lastError) {
            msg += 'unhealthy\n\nLast error:\n' + lastError.stack
        } else if (latestTimestamp) {
            msg += 'healthy'
        } else {
            msg += 'starting up'
        }
        if (latestTimestamp === 'up-to-date') {
            msg += '\n\n\nCaught up to the present time'
        } else if (latestTimestamp) {
            msg += '\n\n\nCaught up to: ' + String(new Date(latestTimestamp))
        }
        res.end(msg);

    } catch (err) {
        console.log(err);
        next(err);
    }
}

//Express route that returns a JSON list of replies
function replies(req, res, next) {
    //Run this on a synchronous coroutine to enable waiting
    block.run(function() {
        try {
            //Parse the querystring.  We support author_name, from, page
            var params, author_name, from, page, page_size;
            params = url.parse(req.url, true).query;
            author_name = params.author_name;
            from = parseInt(params.from);
            if (params.page) {
                page = parseInt(params.page);
            } else {
                page = 1;
            }
            if (params.page_size) {
                page_size = parseInt(params.page_size);
            } else {
                page_size = 10;
            }

            //Sends a 400 message to the client
            function return400 (msg) {
                res.statusCode = 400;
                res.end(msg);
            }

            //Validate the parameters
            if (!author_name) {
                return return400('Missing "author_name" parameter in querystring');
            }
            if (Number.isNaN(from)) {
                return return400('Invalid or missing "from" paramater: should be a unix timestamp in miliseconds');
            }
            if (Number.isNaN(page) || page < 1) {
                return return400('Invalid "page" parameter: should be an integer >= 1');
            }
            if (Number.isNaN(page_size) || page_size < 1 || page_size > 100) {
                return return400('Invalid "page_size" parameter: should be an integer between 1 and 100');
            }

            //Get a postgres client and do a search for comments that match these parameters
            var rows = withClient(function(client) {
                var limit, offset;
                //Currently we return at most 100 replies per call
                limit = page_size;
                offset = limit * (page - 1);

                sql = "SELECT data FROM public.comments WHERE in_reply_to @> ARRAY[$1] AND timestamp > $2 ORDER BY timestamp LIMIT $3 OFFSET $4";

                return client.query(sql, [author_name, from, limit, offset]).rows;
            });

            //Build the results to return to the client
            var results = [];
            for (var i = 0; i < rows.length; i++) {
                results.push(rows[i].data);
            }

            //And send them
            res.end(JSON.stringify(results));

        } catch (err) {
            //On error, log it, then return to the client
            console.log('Error handling ' + req.url + ':');
            console.log(err.stack);
            next(err);
        }
    });
}

//Starts up our API server
function startServer() {
    var app = express();

    //install the replies endpoint
    app.get('/replies', replies);

    //install the status endpoint
    app.get('/', statusEndpoint);

    port = get_config().port;
    app.listen(port, function(err) {
        if (err) {
            console.log('Unable to listen on port ' + port + ': ');
            console.log(err);
            process.exit(1);
        }
        console.log('Listening on port ' + port);
    });
}

//Reads in the latest comments from the WordPress api, processes them,
//and then persists them to our postgres database
function getLatestComments() {
    //Kick off a synchronous coroutine
    block.run(function() {
        try {
            fetchComments();

            //We successfully completed, so do this again in 30 seconds
            setTimeout(getLatestComments, LOAD_COMMENTS_EVERY);
        }
        catch (err) {
            //Record the latest failure for monitoring purposes
            lastError = err;

            //Try again in 5 minutes
            console.log('error fetching comments:');
            console.log(err.stack);
            setTimeout(getLatestComments, FAIL_RETRY);
        }
    });
}

//If this file is the entry point, start up our server and begin
//fetching comments
if (require.main === module) {
    //Confirm we've configured an api base url
    if (!get_config().api_base) {
        console.log('Please set "api_base" in config.json.  E.g., http://slatestarcodex.com');
        process.exit(1);
    }
    //Confirm we've configured a port to listen on
    if (!get_config().port) {
        console.log('Please set "port" in config.json. E.g., 80.');
        process.exit(1);
    }

    startServer();
    getLatestComments();

    //if we have an uncaught exception, we want to log it (but not immediately exit)
    process.on('uncaughtException', function (err) {
        console.log('uncaught exception:');
        console.log(err.stack);
    });
}

})()<commit_msg>adding access control credentials<commit_after>//This is the main entrypoint for starting up our server.
//If loaded as the main module, will start the server and start fetching
//comments from wordpress.  See bottom of file for the startup code

//Tested on node v6.10.2

//Run this in an anonymous function to avoid accidentally creating global variables
(function() {

//Dependencies
var pg = require('pg');
var fs = require('fs');
var fibers = require('fibers');
var block = require('./block');
var Block = block.Block;
var request = require('request');
var querystring = require('querystring');
var express = require('express');
var url = require('url')

//How soon we kick off the loading-new-comments process after the last one finishes
var LOAD_COMMENTS_EVERY = 10*1000;
//How long we wait before retrying the loading-new-comments process if it fails
var FAIL_RETRY = 5*60*1000;
//The number of pages of results we load before committing the transaction
var MAX_PAGES = 10;

//cache our loaded configuration
var _config_cache;

//Track how caught up we are
var latestTimestamp = null;
//If we hit an error fetching comments, save it
var lastError = null;

//Loads our configuration from config.json.  This is a git-ignored file
//that we use to store credentials + settings that we don't want to check
//into git
function get_config() {
    //If we haven't yet, load it from disk
    if (!_config_cache) {
        try {
            _config_cache = JSON.parse(fs.readFileSync('config.json', 'utf8'));
        } catch (err) {
            //If we can't load config, we have to shutdown
            console.log('Unable to load and parse config.json.  Error was:');
            console.log(err.stack);
            process.exit(1);
        }
    }
    return _config_cache;
}

//store our pool of postgres clients
var _pool_cache;

//Returns our pool of postgres clients
function get_pool() {
    //If we haven't created a pool yet, create it now
    if (!_pool_cache) {
        var postgres = get_config().postgres;
        if (!postgres) {
            //If we don't have settings for postgres, this is a fatal error
            var msg = 'No "postgres" object found in config.json.  Expecting an object';
            msg += ' with some or all of these fields: "user", "database", "password",';
            msg += ' "host", "port", "max", "idleTimeoutMillis".  See new pg.Pool at ';
            msg += 'https://github.com/brianc/node-postgres';
            console.log(msg);

            process.exit(1);
        }
        _pool_cache = new pg.Pool(postgres);
    }
    return _pool_cache;
}

//Runs a function passing in a postgres client with a sync query function, which we release on completion
function withClient(fn) {
    var client = block.await(get_pool().connect())
    try {
        var c = {
            query: function (sql, params) {
                return block.await(client.query(sql, params));
            }
        }
        return fn(c);
    } finally {
        client.release();
    }
}

//Runs a function passing in a postgres client.  Starts a transaction, and automatically
//rolls back on error or commits on success
function transaction(fn) {
    withClient(function(client) {
        try {
            client.query('BEGIN');
            ret = fn(client);
            client.query('COMMIT');
            return ret;
        } catch (err) {
            client.query('ROLLBACK');
            throw err;
        }
    });
}

//Fetches all the comments that have come in since we last fetched,
//and persists them to the database as a single transaction.
function fetchComments() {
    //Track the latest timestamp for this operation.  On commit, we update the global
    //latestTimestamp variable
    var lt = null;

    //We run this entire operation as a transaction to protect against accidentally
    //having two comment-fetching processes running at once
    transaction(function(client) {
        //Acquire a lock so that only one process does this at a time
        client.query('SELECT pg_advisory_xact_lock(352342)');

        //Find our most recent comment, so we can get comments after that one
        var res = client.query('SELECT timestamp FROM public.comments ORDER BY timestamp DESC LIMIT 1');
        var start;
        if (res.rows[0]) {
             start = parseInt(res.rows[0].timestamp);
        } else {
            //Start from the beginning of time (plus a bit because Wordpress errors if start = 0)
            start = 86400000;
        }

        //We maintain a cache of comment ids to author names, because comments will
        //generally be in reply to recently posted comments, so it makes sense to remember
        //so we don't have to constantly query the database
        var ids_to_author_name = {}

        //Given a comment id, looks up the author name
        function getAuthorName(id) {
            //If we have it already, just return it
            if (ids_to_author_name[id]) {
                return ids_to_author_name[id];
            }

            //Otherwise, look it up from the database
            res = client.query("SELECT data->'author_name'::text as author_name FROM public.comments WHERE id = $1", [id])
            if (!res.rows[0] || !res.rows[0].author_name) { return null; }
            ids_to_author_name[id] = res.rows[0].author_name;
            return ids_to_author_name[id];
        }

        //Start from the first page of results, and go until there are no more results
        //or we are at MAX_PAGES
        var page = 1;
        while (page <= MAX_PAGES) {

            //Build the parameters to make the call to the wordpress API
            var url = get_config().api_base + '/wp-json/wp/v2/comments?'
            var params = {
                page: page,
                per_page: 100,
                after: (new Date(start)).toISOString(),
                order: 'asc'
            }
            url = url + querystring.stringify(params);

            //Temporary debugging:
            //console.log('Fetching ' + url);

            //Do the request and error if it's not a 200 response
            var block = Block();
            request(url, block.make_cb());
            response = block.wait();
            if (response.statusCode !== 200) {
                throw new Error('Non-200 response from ' + url + ': ' + response.statusCode + ' ' + response.body)
            }

            var comments = JSON.parse(response.body);

            //If there are no comments, we're at the end of the pagination, so break out of the while loop
            if (comments.length === 0) { break; }

            //Go through each comment, calculate the timestamp and in_reply_to fields,
            //and persist to the database
            var comment, timestamp, in_reply_to, params;
            for (var i = 0; i < comments.length; i++) {
                comment = comments[i];

                //update our ids_to_author_name hash
                ids_to_author_name[comment.id] = comment.author_name;

                timestamp = (new Date(comment.date_gmt)).valueOf();
                if (timestamp < lt) {
                    throw new Error('assertion error: got out-of-order timestamps');
                }
                lt = timestamp

                in_reply_to = []

                //See if there any explicit @ references
                //Currently, we count anything from an @ to a non-alphanumeric, non-space
                //character as the author name.  (This is because usually they'll be a
                //comma or a <p> at the end of the name).
                //We trim whitespace
                var regex = /@([a-zA-Z0-9\. ]+)/g
                while (match = regex.exec(comment.content.rendered)) {
                    in_reply_to.push(match[1].trim());

                    //TODO: can we compare unrecognized author names against our comment
                    //database and see if we can guess who they were referring to?
                }

                //See if there is a parent post
                if (comment.parent && getAuthorName(comment.parent)) {
                    in_reply_to.push(getAuthorName(comment.parent));
                }

                //Write the comment to postgres
                params = [comment.id, comment, timestamp, in_reply_to]
                client.query("INSERT INTO public.comments (id, data, timestamp, in_reply_to) VALUES ($1,$2,$3,$4)", params)

                //Temporary debugging
                //console.log('Added: ' + JSON.stringify(params, null, 4));
            }

            page++;
        }
    });

    //We've successfully committed, so update the latest timestamp,
    //and clear last error
    if (lt === null) {
        latestTimestamp = 'up-to-date';
    } else {
        latestTimestamp = lt;
    }
    lastError = null;

    //Temporary debugging
    //console.log('Successfully committed');
}

//Express route that displays the status of the comment downloading
function statusEndpoint (req, res, next) {
    try {
        var msg = 'Status: ';
        if (lastError) {
            msg += 'unhealthy\n\nLast error:\n' + lastError.stack
        } else if (latestTimestamp) {
            msg += 'healthy'
        } else {
            msg += 'starting up'
        }
        if (latestTimestamp === 'up-to-date') {
            msg += '\n\n\nCaught up to the present time'
        } else if (latestTimestamp) {
            msg += '\n\n\nCaught up to: ' + String(new Date(latestTimestamp))
        }
        res.end(msg);

    } catch (err) {
        console.log(err);
        next(err);
    }
}

//Express route that returns a JSON list of replies
function replies(req, res, next) {
    //Run this on a synchronous coroutine to enable waiting
    block.run(function() {
        try {
            //set headers
            res.setHeader('Access-Control-Allow-Origin', '*');
            res.setHeader('Access-Control-Allow-Credentials', 'true');

            //Parse the querystring.  We support author_name, from, page
            var params, author_name, from, page, page_size;
            params = url.parse(req.url, true).query;
            author_name = params.author_name;
            from = parseInt(params.from);
            if (params.page) {
                page = parseInt(params.page);
            } else {
                page = 1;
            }
            if (params.page_size) {
                page_size = parseInt(params.page_size);
            } else {
                page_size = 10;
            }

            //Sends a 400 message to the client
            function return400 (msg) {
                res.statusCode = 400;
                res.end(msg);
            }

            //Validate the parameters
            if (!author_name) {
                return return400('Missing "author_name" parameter in querystring');
            }
            if (Number.isNaN(from)) {
                return return400('Invalid or missing "from" paramater: should be a unix timestamp in miliseconds');
            }
            if (Number.isNaN(page) || page < 1) {
                return return400('Invalid "page" parameter: should be an integer >= 1');
            }
            if (Number.isNaN(page_size) || page_size < 1 || page_size > 100) {
                return return400('Invalid "page_size" parameter: should be an integer between 1 and 100');
            }

            //Get a postgres client and do a search for comments that match these parameters
            var rows = withClient(function(client) {
                var limit, offset;
                //Currently we return at most 100 replies per call
                limit = page_size;
                offset = limit * (page - 1);

                sql = "SELECT data FROM public.comments WHERE in_reply_to @> ARRAY[$1] AND timestamp > $2 ORDER BY timestamp LIMIT $3 OFFSET $4";

                return client.query(sql, [author_name, from, limit, offset]).rows;
            });

            //Build the results to return to the client
            var results = [];
            for (var i = 0; i < rows.length; i++) {
                results.push(rows[i].data);
            }

            //And send them
            res.end(JSON.stringify(results));

        } catch (err) {
            //On error, log it, then return to the client
            console.log('Error handling ' + req.url + ':');
            console.log(err.stack);
            next(err);
        }
    });
}

//Starts up our API server
function startServer() {
    var app = express();

    //install the replies endpoint
    app.get('/replies', replies);

    //install the status endpoint
    app.get('/', statusEndpoint);

    port = get_config().port;
    app.listen(port, function(err) {
        if (err) {
            console.log('Unable to listen on port ' + port + ': ');
            console.log(err);
            process.exit(1);
        }
        console.log('Listening on port ' + port);
    });
}

//Reads in the latest comments from the WordPress api, processes them,
//and then persists them to our postgres database
function getLatestComments() {
    //Kick off a synchronous coroutine
    block.run(function() {
        try {
            fetchComments();

            //We successfully completed, so do this again in 30 seconds
            setTimeout(getLatestComments, LOAD_COMMENTS_EVERY);
        }
        catch (err) {
            //Record the latest failure for monitoring purposes
            lastError = err;

            //Try again in 5 minutes
            console.log('error fetching comments:');
            console.log(err.stack);
            setTimeout(getLatestComments, FAIL_RETRY);
        }
    });
}

//If this file is the entry point, start up our server and begin
//fetching comments
if (require.main === module) {
    //Confirm we've configured an api base url
    if (!get_config().api_base) {
        console.log('Please set "api_base" in config.json.  E.g., http://slatestarcodex.com');
        process.exit(1);
    }
    //Confirm we've configured a port to listen on
    if (!get_config().port) {
        console.log('Please set "port" in config.json. E.g., 80.');
        process.exit(1);
    }

    startServer();
    getLatestComments();

    //if we have an uncaught exception, we want to log it (but not immediately exit)
    process.on('uncaughtException', function (err) {
        console.log('uncaught exception:');
        console.log(err.stack);
    });
}

})()<|endoftext|>


<commit_before>"use strict";
var zlib = require("zlib");
var path = require("path");
var filebuilder = require("../efront/filebuilder");
var checkAccess = require("./checkAccess");
var doFile = require("./doFile");
var doCross = require("./doCross");
var isDevelop = require("../efront/isDevelop");
var memery = require("../efront/memery");
var transfer = require("./transfer");
var parseURL = require("../basic/parseURL");
var isObject = require("../basic/isObject");
var FILE_BUFFER_SIZE = 64 * 1024 * 1024;
var PUBLIC_PATH = memery.PUBLIC_PATH;
var APPS_PATH = memery.PAGE_PATH;
var SERVER_ROOT_PATH = isDevelop ? APPS_PATH : PUBLIC_PATH;
var getfile = require("../efront/cache")(SERVER_ROOT_PATH, function (data, filename, fullpath) {
    var origin_size = data.length;
    var data = filebuilder.apply(this, arguments);
    if (/\.css$/i.test(fullpath)) {
        if (memery.APP) {
            var real = path.dirname(path.relative(SERVER_ROOT_PATH, fullpath).replace(/\\/g, '/'));
            data = Buffer.from(data.toString().replace(/url\s*\(\s*(['"]?)([^\)]*)\1\s*\)/gi, function (a, q, s) {
                if (!/^\/|^\w+\:/i.test(s)) {
                    s = path.join(`/${real}/`, s).replace(/\\/g, '/');
                }
                return `url(${q || ''}${s}${q || ''})`;
            }));
        }
    }
    if (memery.TRANSFER && /\.(m?[tj]sx?|html?|json|css|less)$/i.test(fullpath)) {
        data = Buffer.from(transfer(data));
    }
    return new Promise(function (ok, oh) {
        if (data instanceof Function) {
            if (checkAccess(fullpath)) {
                oh(new Error('请不要在共享路径中创建服务器脚本！'));
                return;
            }
            return ok(data);
        }
        data.origin_size = origin_size;
        zlib.gzip(data, function (error, result) {
            if (error) {
                oh(error);
            } else if (data.length > result.length) {
                result.origin_size = origin_size;
                result.isgzip = true;
                ok(result);
            } else {
                ok(data);
            }
        });
    });
}, FILE_BUFFER_SIZE).async;
var mimes = require("../efront/mime");
var message = require("../message");
var proxy = require("./url-proxy");
/**
 * 返回数据
 * @param {Buffer} data
 * @param {string} url
 * @param {httpRequest} req
 * @param {httpResponse} res
 */
var response = function (data, url, req, res) {
    message.count({ path: url, update: true });
    var requiredVersion = req.headers["if-modified-since"];
    if (requiredVersion && data.stat && new Date(requiredVersion) - new Date(data.stat.mtime.toUTCString()) >= 0) {
        res.writeHead(304, {});
    }
    else {
        var extend = (data.name || url).match(/\.([^\.]*?)$/);
        var headers = {
            "Content-Length": data.length
        };
        if (extend) {
            var mime = mimes[extend[1]];
            if (mime) {
                headers['Content-Type'] = mime;
            }
            else if (/^(php|asp|jsp)$/i.test(extend[1])) {
                if (/^\s*\<\!/.test(data)) headers['Content-Type'] = 'text/html;charset=utf-8';
                else headers['Content-Type'] = 'text/plain;charset=utf-8';
            }
        }
        var status = 200;
        if (data.stat) {
            headers["Last-Modified"] = data.stat.mtime.toUTCString();
            if ((data.origin_size || data.length) < data.stat.size) {
                return doFile(req, res);
                // headers["Accept-Ranges"] = "bytes";
                // headers["Content-Range"] = "bytes 0-" + (data.length - 1) + "/" + data.stat.size;
                // headers["Content-Length"] = data.length;

                // status = 206;
            }
        }
        if (data.isgzip) {
            headers["Content-Encoding"] = "gzip";
        }
        res.writeHead(status, headers);
        res.write(data);
    }
    return res.end();
};
/**
 * 根据数据类型进行不同的响应处理
 * @param {Buffer|Object|string} data
 * @param {string} url
 * @param {httpRequest} req
 * @param {httpResponse} res
 */
var adapter = function (data, url, req, res) {
    if (data instanceof Buffer) {
        return response(data, url, req, res);
    }
    if (data instanceof Error) {
        res.writeHead(404, {});
        return res.end(String(data));
    }
    if (data instanceof Function) {
        data = data(req, res);
    }
    if (data instanceof Promise) {
        return data.then(function (data) {
            adapter(data, url, req, res);
        }).catch(function (error) {
            res.writeHead(500, {});
            res.end(String(error));
        });
    }
    if (isObject(data) && !/\/$/.test(url)) {
        data = url + '/';
    }
    if (typeof data === "string") {
        var new_url = data[0] === "/" ? data : "/" + data;
        if (new_url !== req.url) {
            res.writeHead(302, {
                'Location': new_url
            });
            return res.end();
        }
    }
    if (url) {
        data = getfile(url, [
            'default.html',
            'index.html', 'index.htm',
            'index.jsp', 'index.asp', 'index.php',
        ]);
        return adapter(data, "", req, res);
    }
    if (!req.direct && memery.DIRECT) {
        var direct = req.direct = memery.DIRECT;
        if (typeof direct === 'function') direct = direct(req.url);
        data = getfile(direct, ['', 'default.html', "index.html", 'index.htm', 'index.jsp', 'index.asp', 'index.php']);
        return adapter(data, direct, req, res);
    }
    if (typeof memery.TRANSFER === "string") {
        var p = parseURL(memery.TRANSFER);
        req.url = "/" + (/^https:/i.test(p.protocol) ? '~~' : !p.protocol ? "&" : "~") + p.host + p.path + req.url;
        return doCross(req, res);
    }

    res.writeHead(404, {});
    res.end("not found");
};
/**
 * doGet
 */
module.exports = function (req, res) {
    try {
        req.url = decodeURI(req.url);
    } catch (e) {
        req.url = unescape(req.url);
    }
    var url = proxy(req);
    url = url.replace(/[\:\?#][\s\S]*/g, "");
    var id = /\:/.test(req.url) ? req.url.replace(/^[\s\S]*?\:([\s\S]*?)([\?][\s\S]*)?$/, "$1") : null;
    req.id = id;
    var exts = [''];
    if (url[url.length - 1] !== '/') exts.push(
        '.html',
        '.jsp',
        '.asp',
        '.php'
    );
    var data = getfile(url, exts);
    if (data instanceof Promise) {
        return data.then(function (data) {
            adapter(data, url, req, res);
        }).catch(function (error) {
            res.writeHead(500, {});
            res.end(String(error));
        });
    } else {
        adapter(data, url, req, res);
    }
};
module.exports.reset = getfile.reset;<commit_msg>重定向时默认指向文件夹而不是文件<commit_after>"use strict";
var zlib = require("zlib");
var path = require("path");
var filebuilder = require("../efront/filebuilder");
var checkAccess = require("./checkAccess");
var doFile = require("./doFile");
var doCross = require("./doCross");
var isDevelop = require("../efront/isDevelop");
var memery = require("../efront/memery");
var transfer = require("./transfer");
var parseURL = require("../basic/parseURL");
var isObject = require("../basic/isObject");
var FILE_BUFFER_SIZE = 64 * 1024 * 1024;
var PUBLIC_PATH = memery.PUBLIC_PATH;
var APPS_PATH = memery.PAGE_PATH;
var SERVER_ROOT_PATH = isDevelop ? APPS_PATH : PUBLIC_PATH;
var getfile = require("../efront/cache")(SERVER_ROOT_PATH, function (data, filename, fullpath) {
    var origin_size = data.length;
    var data = filebuilder.apply(this, arguments);
    if (/\.css$/i.test(fullpath)) {
        if (memery.APP) {
            var real = path.dirname(path.relative(SERVER_ROOT_PATH, fullpath).replace(/\\/g, '/'));
            data = Buffer.from(data.toString().replace(/url\s*\(\s*(['"]?)([^\)]*)\1\s*\)/gi, function (a, q, s) {
                if (!/^\/|^\w+\:/i.test(s)) {
                    s = path.join(`/${real}/`, s).replace(/\\/g, '/');
                }
                return `url(${q || ''}${s}${q || ''})`;
            }));
        }
    }
    if (memery.TRANSFER && /\.(m?[tj]sx?|html?|json|css|less)$/i.test(fullpath)) {
        data = Buffer.from(transfer(data));
    }
    return new Promise(function (ok, oh) {
        if (data instanceof Function) {
            if (checkAccess(fullpath)) {
                oh(new Error('请不要在共享路径中创建服务器脚本！'));
                return;
            }
            return ok(data);
        }
        data.origin_size = origin_size;
        zlib.gzip(data, function (error, result) {
            if (error) {
                oh(error);
            } else if (data.length > result.length) {
                result.origin_size = origin_size;
                result.isgzip = true;
                ok(result);
            } else {
                ok(data);
            }
        });
    });
}, FILE_BUFFER_SIZE).async;
var mimes = require("../efront/mime");
var message = require("../message");
var proxy = require("./url-proxy");
/**
 * 返回数据
 * @param {Buffer} data
 * @param {string} url
 * @param {httpRequest} req
 * @param {httpResponse} res
 */
var response = function (data, url, req, res) {
    message.count({ path: url, update: true });
    var requiredVersion = req.headers["if-modified-since"];
    if (requiredVersion && data.stat && new Date(requiredVersion) - new Date(data.stat.mtime.toUTCString()) >= 0) {
        res.writeHead(304, {});
    }
    else {
        var extend = (data.name || url).match(/\.([^\.]*?)$/);
        var headers = {
            "Content-Length": data.length
        };
        if (extend) {
            var mime = mimes[extend[1]];
            if (mime) {
                headers['Content-Type'] = mime;
            }
            else if (/^(php|asp|jsp)$/i.test(extend[1])) {
                if (/^\s*\<\!/.test(data)) headers['Content-Type'] = 'text/html;charset=utf-8';
                else headers['Content-Type'] = 'text/plain;charset=utf-8';
            }
        }
        var status = 200;
        if (data.stat) {
            headers["Last-Modified"] = data.stat.mtime.toUTCString();
            if ((data.origin_size || data.length) < data.stat.size) {
                return doFile(req, res);
                // headers["Accept-Ranges"] = "bytes";
                // headers["Content-Range"] = "bytes 0-" + (data.length - 1) + "/" + data.stat.size;
                // headers["Content-Length"] = data.length;

                // status = 206;
            }
        }
        if (data.isgzip) {
            headers["Content-Encoding"] = "gzip";
        }
        res.writeHead(status, headers);
        res.write(data);
    }
    return res.end();
};
/**
 * 根据数据类型进行不同的响应处理
 * @param {Buffer|Object|string} data
 * @param {string} url
 * @param {httpRequest} req
 * @param {httpResponse} res
 */
var adapter = function (data, url, req, res) {
    if (data instanceof Buffer) {
        return response(data, url, req, res);
    }
    if (data instanceof Error) {
        res.writeHead(404, {});
        return res.end(String(data));
    }
    if (data instanceof Function) {
        data = data(req, res);
    }
    if (data instanceof Promise) {
        return data.then(function (data) {
            adapter(data, url, req, res);
        }).catch(function (error) {
            res.writeHead(500, {});
            res.end(String(error));
        });
    }
    if (isObject(data) && !/\/$/.test(url)) {
        data = url + '/';
    }
    if (typeof data === "string") {
        var new_url = data[0] === "/" ? data : "/" + data;
        new_url = new_url.replace(/(default|index)\.(\w+)$/i, '');
        if (new_url !== req.url) {
            res.writeHead(302, {
                'Location': new_url
            });
            return res.end();
        }
    }
    if (url) {
        data = getfile(url, [
            'default.html',
            'index.html', 'index.htm',
            'index.jsp', 'index.asp', 'index.php',
        ]);
        return adapter(data, "", req, res);
    }
    if (!req.direct && memery.DIRECT) {
        var direct = req.direct = memery.DIRECT;
        if (typeof direct === 'function') direct = direct(req.url);
        data = getfile(direct, ['', 'default.html', "index.html", 'index.htm', 'index.jsp', 'index.asp', 'index.php']);
        return adapter(data, direct, req, res);
    }
    if (typeof memery.TRANSFER === "string") {
        var p = parseURL(memery.TRANSFER);
        req.url = "/" + (/^https:/i.test(p.protocol) ? '~~' : !p.protocol ? "&" : "~") + p.host + p.path + req.url;
        return doCross(req, res);
    }

    res.writeHead(404, {});
    res.end("not found");
};
/**
 * doGet
 */
module.exports = function (req, res) {
    try {
        req.url = decodeURI(req.url);
    } catch (e) {
        req.url = unescape(req.url);
    }
    var url = proxy(req);
    url = url.replace(/[\:\?#][\s\S]*/g, "");
    var id = /\:/.test(req.url) ? req.url.replace(/^[\s\S]*?\:([\s\S]*?)([\?][\s\S]*)?$/, "$1") : null;
    req.id = id;
    var exts = [''];
    if (url[url.length - 1] !== '/') exts.push(
        '.html',
        '.jsp',
        '.asp',
        '.php'
    );
    var data = getfile(url, exts);
    if (data instanceof Promise) {
        return data.then(function (data) {
            adapter(data, url, req, res);
        }).catch(function (error) {
            res.writeHead(500, {});
            res.end(String(error));
        });
    } else {
        adapter(data, url, req, res);
    }
};
module.exports.reset = getfile.reset;<|endoftext|>


<commit_before>/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 2, maxerr: 50 */
/*global define, brackets */

define(function (require, exports, module) {
  "use strict";

  var CommandManager  = brackets.getModule("command/CommandManager"),
      Menus           = brackets.getModule("command/Menus"),
      EditorManager   = brackets.getModule("editor/EditorManager"),
      DocumentManager = brackets.getModule("document/DocumentManager");

  function clean() {
    var txt = DocumentManager.getCurrentDocument().getText();
    // remove trailing whitespace
    txt = txt.replace(/[^\S\n]+$/gm, "");
    // add newline if there is no newline
    var lastChar = txt.charAt(txt.length-1);
    if (lastChar !== "\n") {
      txt += "\n";
    }
    // get cursor position
    var cursorPos = EditorManager.getCurrentFullEditor().getCursorPos();
    // add cleaned text
    DocumentManager.getCurrentDocument().setText(txt);
    // apply cursor position
    EditorManager.getCurrentFullEditor().setCursorPos(cursorPos);
  }

  var FORMAT_ID = "cezarywojcik.clean";
  CommandManager.register("Clean", FORMAT_ID, clean);

  var menu = Menus.getMenu(Menus.AppMenuBar.EDIT_MENU);
  menu.addMenuItem(FORMAT_ID, "Ctrl-Alt-C");
});
<commit_msg>replace tabs with spaces<commit_after>/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 2, maxerr: 50 */
/*global define, brackets */

define(function (require, exports, module) {
  "use strict";

  var CommandManager  = brackets.getModule("command/CommandManager"),
      Menus           = brackets.getModule("command/Menus"),
      EditorManager   = brackets.getModule("editor/EditorManager"),
      Editor          = brackets.getModule("editor/Editor").Editor,
      DocumentManager = brackets.getModule("document/DocumentManager");

  function clean() {
    // get doc and editor
    var CurrentEditor = EditorManager.getCurrentFullEditor();
    var Document = DocumentManager.getCurrentDocument();

    // get document content
    var txt = Document.getText();

    // remove trailing whitespace
    txt = txt.replace(/[^\S\n]+$/gm, "");

    // replace any tabs with spaces
    if (!Editor.getUseTabChar()) {
      var tabSize = Editor.getSpaceUnits();
      var spaces = new Array(tabSize+1).join(" ");
      txt = txt.replace(/\t/gm, spaces);
    }

    // add newline at end of file if there is no newline
    var lastChar = txt.charAt(txt.length-1);
    if (lastChar !== "\n") {
      txt += "\n";
    }

    // get cursor position
    var cursorPos = CurrentEditor.getCursorPos();

    // add cleaned text
    Document.setText(txt);

    // apply cursor position
    CurrentEditor.setCursorPos(cursorPos);
  }

  var FORMAT_ID = "cezarywojcik.clean";
  CommandManager.register("Clean", FORMAT_ID, clean);

  var menu = Menus.getMenu(Menus.AppMenuBar.EDIT_MENU);
  menu.addMenuDivider();
  menu.addMenuItem(FORMAT_ID, "Ctrl-Alt-C");
});
<|endoftext|>


<commit_before>$(document).ready(function(){

	$('ul.dndList').each(function() {
		var id = $(this).attr('id');

		$('#'+id).dndList({
			onDropInterline : function(opt){
				move_to_next_sibling_menu_node(opt.src, opt.dst);
			},
			onDropElement : function(opt){
				update_parent_menu_node(opt.src, opt.dst);
			}
		});
	});
});

function update_parent_menu_node(src, dst) {
	var datas = {
		"src" : src,
		"dst" : dst
	};
	$.post(
			baseUrl+'/ajax/menu/updateParent',
		datas,
		function(results) {
			if (results['error'])
			{
				if (results['message'])
					alert("Une erreur est survenue :\n" + results["message"]);
				else
					alert("Une erreur est survenue ...\nActualisez la page et réessayez.");
			}
		},
		"json"
	);
}

function move_to_next_sibling_menu_node(src, dst) {
	var datas = {
		"src" : src,
		"dst" : dst
	};
	$.post(
			baseUrl+'/ajax/menu/moveprevioussibling',
		datas,
		function(results) {
			if (results['error'])
			{
				if (results['message'])
					alert("Une erreur est survenue :\n" + results["message"]);
				else
					alert("Une erreur est survenue ...\nActualisez la page et réessayez.");
			}
		},
		"json"
	);
}<commit_msg>Menu : add confirmation to delete<commit_after>$(document).ready(function(){

	$('ul.dndList').each(function() {
		var id = $(this).attr('id');

		$('#'+id).dndList({
			onDropInterline : function(opt){
				move_to_next_sibling_menu_node(opt.src, opt.dst);
			},
			onDropElement : function(opt){
				update_parent_menu_node(opt.src, opt.dst);
			}
		});
	});

	$('.confirmDeleteMenuFolder').on('click', function(e){
		e.preventDefault();

		var href = $(this).attr('href');

		bootbox.dialog(I18n.t("confirm_delete_folder"), [{
		    "label" : I18n.t("confirm_delete_folder_label_button_folder_only"),
		    "class" : "btn-danger",
		    "callback": function() {
		    	window.location.href = href;
		    }
		},{
		    "label" : I18n.t("confirm_delete_folder_label_button_folder_and_items"),
		    "class" : "btn-danger",
		    "callback": function() {
		    	window.location.href = href+'/deletechildren';
		    }
		},{
		    "label" : I18n.t("confirm_delete_folder_label_button_folder_and_items_and_contents"),
		    "class" : "btn-danger",
		    "callback": function() {
		    	window.location.href = href+'/deletechildrenandcontent';
		    }
		}, {
		    "label" : I18n.t("cancel"),
		    "class" : "btn-default"
		},]);
	});

	$('.confirmDeleteMenuItemWhitContent').on('click', function(e){
		e.preventDefault();

		var href = $(this).attr('href');

		bootbox.dialog(I18n.t("confirm_delete_item"), [{
		    "label" : I18n.t("confirm_delete_item_label_button_item_only"),
		    "class" : "btn-danger",
		    "callback": function() {
		    	window.location.href = href;
		    }
		},{
		    "label" : I18n.t("confirm_delete_item_label_button_item_only_and_content"),
		    "class" : "btn-danger",
		    "callback": function() {
		    	window.location.href = href+'/deletecontent';
		    }
		}, {
		    "label" : I18n.t("cancel"),
		    "class" : "btn-default"
		},]);
	});

	$('.confirmDeleteMenuItem').on('click', function(e){
		e.preventDefault();

		var href = $(this).attr('href');

		bootbox.dialog(I18n.t("confirm_delete_item"), [{
		    "label" : I18n.t("delete"),
		    "class" : "btn-danger",
		    "callback": function() {
		    	window.location.href = href;
		    }
		}, {
		    "label" : I18n.t("cancel"),
		    "class" : "btn-default"
		},]);
	});

	$('.confirmDeleteMenu').on('click', function(e){
		e.preventDefault();

		var href = $(this).attr('href');

		bootbox.dialog(I18n.t("confirm_delete_menu"), [{
		    "label" : I18n.t("delete"),
		    "class" : "btn-danger",
		    "callback": function() {
		    	window.location.href = href;
		    }
		}, {
		    "label" : I18n.t("cancel"),
		    "class" : "btn-default"
		},]);
	});
});

function update_parent_menu_node(src, dst) {
	var datas = {
		"src" : src,
		"dst" : dst
	};
	$.post(
			baseUrl+'/ajax/menu/updateParent',
		datas,
		function(results) {
			if (results['error'])
			{
				if (results['message'])
					alert("Une erreur est survenue :\n" + results["message"]);
				else
					alert("Une erreur est survenue ...\nActualisez la page et réessayez.");
			}
		},
		"json"
	);
}

function move_to_next_sibling_menu_node(src, dst) {
	var datas = {
		"src" : src,
		"dst" : dst
	};
	$.post(
			baseUrl+'/ajax/menu/moveprevioussibling',
		datas,
		function(results) {
			if (results['error'])
			{
				if (results['message'])
					alert("Une erreur est survenue :\n" + results["message"]);
				else
					alert("Une erreur est survenue ...\nActualisez la page et réessayez.");
			}
		},
		"json"
	);
}<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var utils = require('./utils');
var _  = require('lodash');
var dotAccess = require('dot-access');

var _workdir = process.cwd();

module.exports = browserifyBower;
module.exports.workdir = function(workdir) {
	_workdir = workdir || _workdir;
	return workdir && browserifyBower || _workdir;
};

//////////////////////////////////////////////////////////////////////////////

function browserifyBower(browserify, options) {
	if (_.isEmpty(options)) {
		options = { "require": utils.componentNames(_workdir) };
	}

	if (options.workdir) _workdir = options.workdir;
	if (options.conf) {
		var confjson = require(path.join(_workdir, options.conf));
		options = options.confnode && dotAccess.get(confjson, options.confnode) || confjson;
	}

	_.forEach(options, function(config, action) {
		if (_(['require', 'external']).contains(action)) {
			if (_(config).isArray()) config = { "include": config };

			var aliasConfigs = _(config.include)
				.filter(function(name) {
					return name.indexOf(':') > 0
						&& !_(config.alias).any(function(name1) {
								return name.split(':')[0] === name1.split(':')[0];
							});
				})
				.union(config.alias)
				.map(function(rawname) {
					return {
						name: rawname.split(':')[0],
						alias: rawname.split(':')[1]
					}
				})
				.value();

			var workinglist = _(config.include || utils.componentNames(_workdir))
				// process '*' including
				.map(function(name) {
					return (name === '*') ? utils.componentNames(_workdir) : name;
				})
				.flatten()
				// filter out excluded names
				.filter(function(name) {
					return !_(config.exclude).map(function(name1) {
						return name1.split(':')[0];
					}).contains(name.split(':')[0]);
				})
				// resolve name and deps
				.uniq()
				.map(function(rawname) {
					var name = rawname.split(':')[0];
					return utils.resolve(name, _workdir);
				})
				// prepare the working list
				.flatten()
				.groupBy(function(item) {
					return item.name;
				})
				.map(function(list, name) {
					return {
						name: name,
						path: list[0].path
					};
				})
				// merge in alias configs
				.map(function(item) {
					var found  = _.find(aliasConfigs, { name: item.name });
					item.alias = found ? found.alias : item.name;
					return item;
				});

			///
			if (action === 'require') {
				workinglist.forEach(function(item) {
					browserify.require(item.path, { expose: item.alias });
				}).value();
			} else { // external
				workinglist.forEach(function(item) {
					browserify.external(item.alias);
				}).value();
			}
		}
	});
};
<commit_msg>code refactor and enhancement<commit_after>'use strict';

var path = require('path');
var utils = require('./utils');
var _  = require('lodash');
var dotAccess = require('dot-access');

var _workdir = process.cwd();

module.exports = browserifyBower;
module.exports.workdir = function(workdir) {
	_workdir = workdir || _workdir;
	return workdir && browserifyBower || _workdir;
};

//////////////////////////////////////////////////////////////////////////////
/**
 * alias can be configured at: options.alias > currConfig.alias > currConfig.include (later can override former)
 **/
function getAliasConfigs(options, currConfig) {
	var aliasConfigs = {};

	_.forEach((options.alias || []).concat(currConfig.alias || []).concat(currConfig.include || []),
		function(rawname) {
			if (rawname.indexOf(':') > 0) {
				var name = rawname.split(':')[0],
						alias= rawname.split(':')[1];

				aliasConfigs[name] = alias;
			}
		});

	return aliasConfigs;
}

function getWorkingLists(options) {
	var workinglists = {};

	_.forEach(options, function(config, action) {
		if (_(['require', 'external']).contains(action)) {
			if (_(config).isArray()) config = { "include": config };

			var aliasConfigs = getAliasConfigs(options, config);

			var workinglist = _(config.include || utils.componentNames(_workdir))
				// process '*' including
				.map(function(name) {
					return (name === '*') ? utils.componentNames(_workdir) : name;
				})
				.flatten()
				// filter out excluded names
				.filter(function(name) {
					return !_(config.exclude).map(function(name1) {
						return name1.split(':')[0];
					}).contains(name.split(':')[0]);
				})
				// resolve name and deps
				.uniq()
				.map(function(rawname) {
					var name = rawname.split(':')[0];
					return utils.resolve(name, _workdir);
				})
				// prepare the working list
				.flatten()
				.groupBy(function(item) {
					return item.name;
				})
				.map(function(list, name) {
					return {
						name : name,
						alias: aliasConfigs[name] || name, // merge in alias configs
						path : list[0].path
					};
				}).value();

			///
			workinglists[action] = workinglist;
		}
	});

	return workinglists;
}

function browserifyBower(browserify, options) {
	options = options || {};
	options.require = options.require || utils.componentNames(_workdir);

	if (options.workdir) _workdir = options.workdir;
	if (options.conf) {
		var confjson = require(path.join(_workdir, options.conf));
		options = options.confnode && dotAccess.get(confjson, options.confnode) || confjson;
	}

	///
	var workinglists = getWorkingLists(options);

	// if an item existed in both 'require' and 'external' lists, let's remove it from 'require' list
	workinglists.require = _.filter(workinglists.require || [], function(item) {
		return ! _.find(workinglists.external || [], { name: item.name });
	});

	///
	_.forEach(workinglists.require  || [], function(item) {
		browserify.require(item.path, { expose: item.alias });
	});

	_.forEach(workinglists.external || [], function(item) {
		browserify.external(item.alias);
	});
};
<|endoftext|>


<commit_before>var utils = require('../../utils');
var et = require('elementtree');
var _ = require('underscore');

/** Adds versionone field to devops if version_one related api_config is present
 * @param {object} devops devops object
 *
 * The MetaAPI which includes all our custom fields is available here:
 * https://www15.v1host.com/RACKSPCE/meta.v1/?xsl=api.xsl
 *
 * http://community.versionone.com/sdk/Documentation/DataAPI.aspx
 * Date Created isn't a default value, so we have to query it manually.
 *
 */

var selection = ["Custom_Severity.Name",
                "ChangedBy",
                "CreateDate",
                "Owners",
                "SecurityScope",
                "AssetState",
                "Owners",
                "AssetType",
                "Status",
                "Number",
                "Order",
                "Description",
                "Scope.Name",
                "Name",
                "ResolutionReason",
                "Timebox",
                "Resolution",
                "Scope",
                "Priority"];

module.exports = utils.create_middleware('version_one', function(req, res, next, payload, api_config) {
  var options = {
    port: api_config.port,
    host: api_config.host,
    path: ['/',
           req.devops.related_apis.version_one.name,
           "/rest-1.v1/Data/Defect?sel=",
           selection,
           "&where=AssetState='0','64';Scope='Scope:",
           req.devops.related_apis.version_one.project,
           "'"].join(""),
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Basic ' + new Buffer(api_config.auth).toString('base64')
    }
  };

  utils.request_maker(options,
    function(error, data){
      var byAge = {};
      var now = new Date();
      var defectCreateDate;
      var assets;
      var diff;
      var severity;
      var type;
      var age0 = 'defects Today';
      var age1 = 'defects 1 - 5 days old';
      var age2 = 'defects 5 - 10 days old';
      var age3 = 'defects 10 - 30 days old';
      var age4 = 'defects more than 30 days old';
      var ageUnknown = 'defects of unknown age (wtf?)';
      byAge[age0] = defDict();
      byAge[age1] = defDict();
      byAge[age2] = defDict();
      byAge[age3] = defDict();
      byAge[age4] = defDict();
      byAge[ageUnknown] = defDict();
      var type = age0;

      if (error){
        payload.error = error;
        return next();
      }
      var etree = et.parse(data);
      if (!_.isEmpty(data.error)){
        payload.error = data.error.code + ": " + data.error.message;
      }
      else {
        assets = etree.getroot().findall('./Asset').map(makeAsset);
        _.each (assets, function(asset) {
          defectCreateDate = new Date(asset.attributes['CreateDate']);
          diff = Math.ceil((now.getTime()-defectCreateDate.getTime())/(1000*60*60*24));
          if (diff <= 1) { type = age0; }
          else if (diff <= 5 && diff > 1) { type = age1; }
          else if (diff <= 10 && diff > 5){ type = age2; }
          else if (diff <= 30 && diff > 10){ type = age3; }
          else if (diff > 30){ type = age4; }
          else { type = ageUnknown; }
          byAge[type].defects.push(asset);
          byAge[type].total_count += 1;
          severity = asset.attributes['Custom_Severity.Name'];
          if (severity && severity !== "") {
            severity = severity[0];
          } else {
            severity = '?';
          }
          asset.severity = severity;
          byAge[type].sev_count[severity] += 1;
        });
        payload.data = {
          'total': etree.getroot().attrib.total,
          'byAge': byAge
        };
      }
      next();
  });
});

/**
 *
 * @returns A default dictionary for defects aggregation
 */
function defDict() {
  return {
    total_count: 0,
    sev_count: {
      1: 0,
      2: 0,
      3: 0,
      4: 0,
      '?': 0
    },
    defects: []
  };
}

/** an asset is a generic v1 object */
function Asset() {
  this.href = null;
  this.id = null;
  this.idref = null;
  this.attributes = {};
  this.relations = {};
}

/** an attribute is a (name, text) tuple. */
function makeAttribute(element) {
  return { name: element.attrib.name, text: element.text };
}

/** a relation is a (name, asset) tuple where the asset is optional. */
function makeRelation(element) {
  var asset = element.findall('./Asset');
  // this works as long as the assumption that each relation has one or zero assets.
  asset = asset.length > 0 ? makeAsset(asset[0]) : undefined;
  return { name: element.attrib.name, asset: asset };
}

/**
 * create an asset from some xml.
 * @param {ElementTree} element must be a single Asset.
 */
function makeAsset(element) {
  if (element.tag !== 'Asset') {
    return null;
  }
  var ass = new Asset();
  ass.href = element.attrib.href;
  ass.id = element.attrib.id;
  ass.idref = element.attrib.idref;
  ass.attributes = element.findall('./Attribute').map(makeAttribute).reduce(function(hash, named) {
    hash[named.name] = named.text;
    return hash;
  }, {});
  ass.relations = element.findall('./Relation').map(makeRelation).reduce(function(hash, named) {
    hash[named.name] = named.asset;
    return hash;
  }, {});
  return ass;
}
<commit_msg>Nuke unknown age thing. Don't declare type twice. Simplify if/else<commit_after>var utils = require('../../utils');
var et = require('elementtree');
var _ = require('underscore');

/** Adds versionone field to devops if version_one related api_config is present
 * @param {object} devops devops object
 *
 * The MetaAPI which includes all our custom fields is available here:
 * https://www15.v1host.com/RACKSPCE/meta.v1/?xsl=api.xsl
 *
 * http://community.versionone.com/sdk/Documentation/DataAPI.aspx
 * Date Created isn't a default value, so we have to query it manually.
 *
 */

var selection = ["Custom_Severity.Name",
                "ChangedBy",
                "CreateDate",
                "Owners",
                "SecurityScope",
                "AssetState",
                "Owners",
                "AssetType",
                "Status",
                "Number",
                "Order",
                "Description",
                "Scope.Name",
                "Name",
                "ResolutionReason",
                "Timebox",
                "Resolution",
                "Scope",
                "Priority"];

module.exports = utils.create_middleware('version_one', function(req, res, next, payload, api_config) {
  var options = {
    port: api_config.port,
    host: api_config.host,
    path: ['/',
           req.devops.related_apis.version_one.name,
           "/rest-1.v1/Data/Defect?sel=",
           selection,
           "&where=AssetState='0','64';Scope='Scope:",
           req.devops.related_apis.version_one.project,
           "'"].join(""),
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Basic ' + new Buffer(api_config.auth).toString('base64')
    }
  };

  utils.request_maker(options,
    function(error, data){
      var byAge = {};
      var now = new Date();
      var defectCreateDate;
      var assets;
      var diff;
      var severity;
      var type;
      var age0 = 'defects Today';
      var age1 = 'defects 1 - 5 days old';
      var age2 = 'defects 5 - 10 days old';
      var age3 = 'defects 10 - 30 days old';
      var age4 = 'defects more than 30 days old';
      byAge[age0] = defDict();
      byAge[age1] = defDict();
      byAge[age2] = defDict();
      byAge[age3] = defDict();
      byAge[age4] = defDict();

      if (error){
        payload.error = error;
        return next();
      }
      var etree = et.parse(data);
      if (!_.isEmpty(data.error)){
        payload.error = data.error.code + ": " + data.error.message;
      }
      else {
        assets = etree.getroot().findall('./Asset').map(makeAsset);
        _.each (assets, function(asset) {
          defectCreateDate = new Date(asset.attributes['CreateDate']);
          diff = Math.ceil((now.getTime()-defectCreateDate.getTime())/(1000*60*60*24));
          if (diff <= 1) { type = age0; }
          else if (diff <= 5) { type = age1; }
          else if (diff <= 10){ type = age2; }
          else if (diff <= 30){ type = age3; }
          else if (diff > 30){ type = age4; }
          else { type = age0; }
          byAge[type].defects.push(asset);
          byAge[type].total_count += 1;
          severity = asset.attributes['Custom_Severity.Name'];
          if (severity && severity !== "") {
            severity = severity[0];
          } else {
            severity = '?';
          }
          asset.severity = severity;
          byAge[type].sev_count[severity] += 1;
        });
        payload.data = {
          'total': etree.getroot().attrib.total,
          'byAge': byAge
        };
      }
      next();
  });
});

/**
 *
 * @returns A default dictionary for defects aggregation
 */
function defDict() {
  return {
    total_count: 0,
    sev_count: {
      1: 0,
      2: 0,
      3: 0,
      4: 0,
      '?': 0
    },
    defects: []
  };
}

/** an asset is a generic v1 object */
function Asset() {
  this.href = null;
  this.id = null;
  this.idref = null;
  this.attributes = {};
  this.relations = {};
}

/** an attribute is a (name, text) tuple. */
function makeAttribute(element) {
  return { name: element.attrib.name, text: element.text };
}

/** a relation is a (name, asset) tuple where the asset is optional. */
function makeRelation(element) {
  var asset = element.findall('./Asset');
  // this works as long as the assumption that each relation has one or zero assets.
  asset = asset.length > 0 ? makeAsset(asset[0]) : undefined;
  return { name: element.attrib.name, asset: asset };
}

/**
 * create an asset from some xml.
 * @param {ElementTree} element must be a single Asset.
 */
function makeAsset(element) {
  if (element.tag !== 'Asset') {
    return null;
  }
  var ass = new Asset();
  ass.href = element.attrib.href;
  ass.id = element.attrib.id;
  ass.idref = element.attrib.idref;
  ass.attributes = element.findall('./Attribute').map(makeAttribute).reduce(function(hash, named) {
    hash[named.name] = named.text;
    return hash;
  }, {});
  ass.relations = element.findall('./Relation').map(makeRelation).reduce(function(hash, named) {
    hash[named.name] = named.asset;
    return hash;
  }, {});
  return ass;
}
<|endoftext|>


<commit_before>//
// Get a multi-sig wallet at BitGo.
// This makes use of the convenience function wallets().get()
//
// This tool will help you see how to use the BitGo API to easily get
// information about a wallet.
//
// Copyright 2018, BitGo, Inc.  All Rights Reserved.
//

const BitGoJS = require('../../src/index.js');
const bitgo = new BitGoJS.BitGo({ env: 'test' });
const Promise = require('bluebird');

// TODO: set your access token here
// You can get this from User Settings > Developer Options > Add Access Token
const accessToken = null;

// TODO: get the wallet with this id
const id = null;

const coin = 'tltc';

// Create the wallet
Promise.coroutine(function *() {
  bitgo.authenticateWithAccessToken({ accessToken });

  const wallet = yield bitgo.coin(coin).wallets().get({ id });

  console.log(`Wallet label: ${wallet.label()}`);
})();
<commit_msg>add comments to get wallet<commit_after>//
// Get a multi-sig wallet at BitGo.
// This makes use of the convenience function wallets().get()
//
// This tool will help you see how to use the BitGo API to easily get
// information about a wallet.
//
// Copyright 2018, BitGo, Inc.  All Rights Reserved.
//

const BitGoJS = require('../../src/index.js');
const bitgo = new BitGoJS.BitGo({ env: 'test' });
const Promise = require('bluebird');

// TODO: set your access token here
// You can get this from User Settings > Developer Options > Add Access Token
const accessToken = null;

// TODO: get the wallet with this id
const id = null;

const coin = 'tltc';

// Create the wallet with Bluebird coroutines
Promise.coroutine(function *() {
  bitgo.authenticateWithAccessToken({ accessToken });

  const wallet = yield bitgo.coin(coin).wallets().get({ id });

  console.log(`Wallet label: ${wallet.label()}`);
})();
<|endoftext|>


<commit_before>var FormData = this.FormData;
var cookiesMap = {};
//               /////  1   ////////// 2 /////// 3 ////    4  //
var domainReg = /^(?:(https?)\:)?\/\/(.*?)(?:\/(.*?))?([\?#].*)?$/i;
var base = domainReg.test(location.href) ? '/' : "http://efront.cc/";
var location_host = location.href.replace(domainReg, '$1://$2/');
var setHost = function (host) {
    var parsed = parseURL(host);
    if (!host) return console.error("cross_host格式不正确", host);
    var host = parsed.host + (parsed.pathname || '/');
    host = (/^https/.test(location_host) ? "https://" : "http://") + host;
    base = host;
};
var { efrontURI, cross_host = efrontURI } = this;
if (cross_host) setHost(cross_host);
var HeadersKeys = ["Content-Type"];
var cookieItemsInSessionStorageKey = "--zimoli-coms-cross";
var cookiesData = sessionStorage.getItem(cookieItemsInSessionStorageKey);
var cors_hosts = [];
if (cookiesData) {
    try {
        extend(cookiesMap, JSON.parse(cookiesData));
    } catch (e) {
        console.warn("加载cookie出错！");
    }
}
function getDomainPath(url) {
    return url.replace(domainReg, "$2/$3");
}
function getRequestProtocol(url) {
    if (/^https:/i.test(url)) {
        return "https:";
    }
    return "http:";
}
function getCookies(domainPath) {
    var cookieObject = {};
    var splited = domainPath.split("/");
    var domain = splited[0];
    do {
        var copy = splited.slice(0);
        do {
            domainPath = copy.join("/");
            var cookie = cookiesMap[domainPath];
            if (cookie) {
                for (var k in cookie) {
                    if (!cookieObject[k]) {
                        cookieObject[k] = cookie[k];
                    }
                }
            }
            copy.pop();
        } while (copy.length);
        domain = domain.replace(/^.*?(\.|$)/, "");
        splited[0] = domain;
    } while (domain.length);
    return serialize(cookieObject, ";");
}
function addCookie(cookie, originDomain = "") {
    if (cookie) {
        clearTimeout(addCookie.save_timer);
        addCookie.save_timer = setTimeout(function () {
            sessionStorage.setItem(cookieItemsInSessionStorageKey, JSON.stringify(cookiesMap));
        }, 20);
        cookie.replace(/(^|;|,)\s*(expires)=(\w*),([^=]*)(;|$)/ig, "$1$2=$3.$4$5")
            .split(/,\s*/).map(function (cookie) {
                var cookieObject = {};
                var result = cookie.split(/;\s*/);
                result.slice(1).map(function (kev) {
                    var kvs = /^(.+?)\=(.+?)$/.exec(kev);
                    if (kvs) {
                        var [, k, v] = kvs;
                        cookieObject[k.toLowerCase()] = v;
                    }
                });
                var { path, domain } = cookieObject;
                if (!domain) {
                    domain = originDomain.replace(/[^\/]+$/, "");
                }
                if (/^\./.test(domain)) {
                    domain = domain.replace(/^\.+/, "");
                }
                var destPath;
                if (/^\//.test(path)) {
                    destPath = domain.replace(/\/.*$/, "") + path;
                } else {
                    destPath = domain;
                }
                destPath = destPath.replace(/\/+$/, "");
                if (originDomain.indexOf(destPath) >= 0) {
                    var cookieMap = parseKV(result[0], ";");
                    if (!cookiesMap[destPath]) {
                        cookiesMap[destPath] = cookieMap;
                    } else {
                        extend(cookiesMap[destPath], cookieMap);
                    }
                }
            });
    }
}
function isChildPath(relative, path) {
    return relative.replace(/^(.*\/)[^\/]*$/, path);
}
var digest = function () {
    dispatch('render', window);
};

var getCrossUrl = function (domain, headers) {
    if (notCross(domain)) return domain;
    var originDomain = getDomainPath(domain);
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    _headers = serialize(_headers);
    if (_headers) _headers = "," + _headers;
    return domain
        .replace(/^(s?)(\/\/)/i, "http$1:$2")
        .replace(domainReg, base + `*${/^(https\:|s\/\/)/i.test(domain) ? "*" : ""}$2${_headers}/$3$4`);
};
function cross(method, url, headers) {
    var originDomain = getDomainPath(url);
    if (!originDomain) throw new Error("Unsupposed url format!");
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    if (/^[mc]/i.test(method)) {
        _headers["User-Agent"] = /^m/i.test(method)
            ? "Efront/1.9 (iPhone) Safari/602.1"
            : "Efront/1.9 (Windows) Chrome/77.0.3865.90";
        method = method.slice(1);
    }
    if (/^jsonp/i.test(method)) {
        var cb = method.split('\-')[1] || 'callback';
        setTimeout(function () {
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                datas = serialize(jsondata);
            }
            if (datas) {
                xhr.src += "&" + datas;
            }
        });
        var xhr = jsonp(url, {
            [cb](a) {
                xhr.response = xhr.responseText = JSON.stringify(a);
                onload(xhr);
            }
        });
        xhr.onerror = function (e) {
            onerror(e);
        };
    } else {
        var nocross = notCross(url);
        var xhr = new XMLHttpRequest;
        var abort = xhr.abort;
        xhr.abort = function () {
            xhr.onreadystatechange = null;
            abort.call(this);
        };

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.getResponseHeader && !nocross) {
                    var cookie = xhr.getResponseHeader("efront-cookie");
                    addCookie(cookie, originDomain);
                }
                switch (xhr.status) {
                    case 0:
                        if (!navigator.onLine) {
                            onerror({ status: "网络断开" });
                            break;
                        }
                        if (!navigator.response) {
                            onerror({ status: "服务器无响应" });
                            break;
                        }
                    case 200:
                    case 201:
                    case 304:
                        onload(xhr);
                        break;
                    case 302:
                    case 301:
                        if (xhr.isRedirected > 2 || nocross) break;
                        var location = xhr.getResponseHeader("efront-location");
                        if (!domainReg.test(location)) {
                            if (/^\//.test(location)) {
                                location = originDomain.replace(/\/.*$/, location);
                            } else {
                                location = originDomain.replace(/[^\/+]$/, location);
                            }
                            location = getRequestProtocol(url) + "//" + location;
                        }
                        var crs = cross("get", location, headers);
                        crs.isRedirected = (xhr.isRedirected || 0) + 1;
                        crs.done(onload, false);
                        crs.error(onerror, false);
                        break;
                    default:
                        onerror(xhr);
                }
                dispatch(window, 'render');
            }
        };
        var setRequestHeader = xhr.setRequestHeader;
        var realHeaders = Object.create(null);
        xhr.setRequestHeader = function (key, value) {
            realHeaders[key] = value;
        };
        xhr.then = function (ok, oh) {
            onloads.push(ok);
            onerrors.push(oh);
            flush();
        };
        setTimeout(function () {
            digest();
            var isform = /^f/i.test(method);
            if (isform) {
                if (method === 'form') method = 'post';
                else method = method.slice(1);
            }
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                if (/^(get|head|trace)$/i.test(method)) {
                    url = url.replace(/#[\s\S]*/, '');
                    datas = serialize(jsondata);
                    if (datas) url += (/\?/.test(url) ? "&" : "?") + datas;
                } else if (isform) {
                    xhr.form(jsondata);
                } else {
                    datas = JSON.stringify(jsondata);
                    if (datas === "{}" || datas === "[]") {
                        datas = '';
                    } else {
                        realHeaders["Content-Type"] = "application/json;charset=UTF-8";
                    }
                }
            }
            if (nocross) {
                extend(realHeaders, _headers);
                xhr.open(method, url);
            } else {
                xhr.open(method, getCrossUrl(url, _headers));
            }
            Object.keys(realHeaders).forEach(key => setRequestHeader.call(xhr, key, realHeaders[key]));
            send.call(xhr, datas);
        }, 0);
    }
    var loaded, errored;
    var onload = function (xhr) {
        if (xhr.decoder) {
            xhr = xhr.decoder(xhr);
        }
        loaded = xhr;
        flush();
        digest();
    };
    var onerror = function (xhr) {
        errored = xhr;
        flush();
        digest();
    };
    var flush = function () {
        var then = xhr.then;
        delete xhr.then;
        if (loaded) onloads.splice(0, onloads.length).map(e => e instanceof Function && e(xhr));
        if (errored) onerrors.splice(0, onerrors.length).map(e => e instanceof Function && e(xhr));
        xhr.then = then;
    };
    var onloads = [], onerrors = [];
    xhr.done = xhr.success = function (on, asqueue = true) {
        if (!asqueue) onloads.splice(0, onloads.length);
        onloads.push(on);
        flush();
        return xhr;
    };
    var send = xhr.send;
    var datas = "";
    var jsondata = null;
    xhr.json = xhr.data = xhr.send = function (data, value) {
        if (!jsondata && !(isEmpty(data) && isEmpty(value))) jsondata = data instanceof Array ? [] : {};
        if (FormData && data instanceof FormData) {
            datas = data;
        } else if (isObject(data) && !isFile(data)) {
            extend(jsondata, data);
        } else if (!isEmpty(value)) {
            extend(jsondata, { [data]: value });
        } else if (isString(data) && value !== false && /^\s*\{|\=/.test(data)) {
            var data = /^\s*\{/.test(data) ? JSON.parse(data) : parseKV(data, "&", "=");
            extend(jsondata, data);
        } else {
            datas = data;
        }
        return xhr;
    };
    xhr.form = function (data) {
        xhr.data(data);
        if (FormData) {
            datas = new FormData;
            for (var k in jsondata) {
                datas.append(k, jsondata[k]);
            }
        } else {
            realHeaders["Content-Type"] = "application/x-www-form-urlencoded";
            datas = serialize(jsondata, "&", "=");
        }
    };
    xhr.fail = xhr.error = function (on, asqueue = true) {
        if (!asqueue) {
            onerrors.splice(0, onerrors.length);
        }
        onerrors.push(on);
        flush();
        return xhr;
    };
    return xhr;
}
function addDirect(a) {
    if (typeof a === 'string' || a instanceof RegExp) cors_hosts.push(a);
}
function notCross(domain) {
    if (location_host === domain.slice(0, location_host.length) || !/^https?\:\/\/|^s?\/\//.test(domain)) return true;
    for (var cx = 0, dx = cors_hosts.length; cx < dx; cx++) {
        var host = cors_hosts[cx];
        if (host instanceof RegExp) {
            if (host.test(domain)) return true;
        } else {
            host = host.replace(domainReg, '$2/$3');
            if (domain.replace(domainReg, '$2/$3').slice(0, host.length) === host) return true;
        }
    }
    return false;
}
extend(cross, {
    setHost,
    getCookies,
    addCookie,
    addDirect,
    getCrossUrl
});<commit_msg>CORS错误时报错<commit_after>var FormData = this.FormData;
var cookiesMap = {};
//               /////  1   ////////// 2 /////// 3 ////    4  //
var domainReg = /^(?:(https?)\:)?\/\/(.*?)(?:\/(.*?))?([\?#].*)?$/i;
var base = domainReg.test(location.href) ? '/' : "http://efront.cc/";
var location_host = location.href.replace(domainReg, '$1://$2/');
var setHost = function (host) {
    var parsed = parseURL(host);
    if (!host) return console.error("cross_host格式不正确", host);
    var host = parsed.host + (parsed.pathname || '/');
    host = (/^https/.test(location_host) ? "https://" : "http://") + host;
    base = host;
};
var { efrontURI, cross_host = efrontURI } = this;
if (cross_host) setHost(cross_host);
var HeadersKeys = ["Content-Type"];
var cookieItemsInSessionStorageKey = "--zimoli-coms-cross";
var cookiesData = sessionStorage.getItem(cookieItemsInSessionStorageKey);
var cors_hosts = [];
if (cookiesData) {
    try {
        extend(cookiesMap, JSON.parse(cookiesData));
    } catch (e) {
        console.warn("加载cookie出错！");
    }
}
function getDomainPath(url) {
    return url.replace(domainReg, "$2/$3");
}
function getRequestProtocol(url) {
    if (/^https:/i.test(url)) {
        return "https:";
    }
    return "http:";
}
function getCookies(domainPath) {
    var cookieObject = {};
    var splited = domainPath.split("/");
    var domain = splited[0];
    do {
        var copy = splited.slice(0);
        do {
            domainPath = copy.join("/");
            var cookie = cookiesMap[domainPath];
            if (cookie) {
                for (var k in cookie) {
                    if (!cookieObject[k]) {
                        cookieObject[k] = cookie[k];
                    }
                }
            }
            copy.pop();
        } while (copy.length);
        domain = domain.replace(/^.*?(\.|$)/, "");
        splited[0] = domain;
    } while (domain.length);
    return serialize(cookieObject, ";");
}
function addCookie(cookie, originDomain = "") {
    if (cookie) {
        clearTimeout(addCookie.save_timer);
        addCookie.save_timer = setTimeout(function () {
            sessionStorage.setItem(cookieItemsInSessionStorageKey, JSON.stringify(cookiesMap));
        }, 20);
        cookie.replace(/(^|;|,)\s*(expires)=(\w*),([^=]*)(;|$)/ig, "$1$2=$3.$4$5")
            .split(/,\s*/).map(function (cookie) {
                var cookieObject = {};
                var result = cookie.split(/;\s*/);
                result.slice(1).map(function (kev) {
                    var kvs = /^(.+?)\=(.+?)$/.exec(kev);
                    if (kvs) {
                        var [, k, v] = kvs;
                        cookieObject[k.toLowerCase()] = v;
                    }
                });
                var { path, domain } = cookieObject;
                if (!domain) {
                    domain = originDomain.replace(/[^\/]+$/, "");
                }
                if (/^\./.test(domain)) {
                    domain = domain.replace(/^\.+/, "");
                }
                var destPath;
                if (/^\//.test(path)) {
                    destPath = domain.replace(/\/.*$/, "") + path;
                } else {
                    destPath = domain;
                }
                destPath = destPath.replace(/\/+$/, "");
                if (originDomain.indexOf(destPath) >= 0) {
                    var cookieMap = parseKV(result[0], ";");
                    if (!cookiesMap[destPath]) {
                        cookiesMap[destPath] = cookieMap;
                    } else {
                        extend(cookiesMap[destPath], cookieMap);
                    }
                }
            });
    }
}
function isChildPath(relative, path) {
    return relative.replace(/^(.*\/)[^\/]*$/, path);
}
var digest = function () {
    dispatch('render', window);
};

var getCrossUrl = function (domain, headers) {
    if (notCross(domain)) return domain;
    var originDomain = getDomainPath(domain);
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    _headers = serialize(_headers);
    if (_headers) _headers = "," + _headers;
    return domain
        .replace(/^(s?)(\/\/)/i, "http$1:$2")
        .replace(domainReg, base + `*${/^(https\:|s\/\/)/i.test(domain) ? "*" : ""}$2${_headers}/$3$4`);
};
function cross(method, url, headers) {
    var originDomain = getDomainPath(url);
    if (!originDomain) throw new Error("Unsupposed url format!");
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    if (/^[mc]/i.test(method)) {
        _headers["User-Agent"] = /^m/i.test(method)
            ? "Efront/1.9 (iPhone) Safari/602.1"
            : "Efront/1.9 (Windows) Chrome/77.0.3865.90";
        method = method.slice(1);
    }
    if (/^jsonp/i.test(method)) {
        var cb = method.split('\-')[1] || 'callback';
        setTimeout(function () {
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                datas = serialize(jsondata);
            }
            if (datas) {
                xhr.src += "&" + datas;
            }
        });
        var xhr = jsonp(url, {
            [cb](a) {
                xhr.response = xhr.responseText = JSON.stringify(a);
                onload(xhr);
            }
        });
        xhr.onerror = function (e) {
            onerror(e);
        };
    } else {
        var nocross = notCross(url);
        var xhr = new XMLHttpRequest;
        var abort = xhr.abort;
        xhr.abort = function () {
            xhr.onreadystatechange = null;
            abort.call(this);
        };

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.getResponseHeader && !nocross) {
                    var cookie = xhr.getResponseHeader("efront-cookie");
                    addCookie(cookie, originDomain);
                }
                switch (xhr.status) {
                    case 0:
                        if (!navigator.onLine) {
                            onerror({ status: "网络断开" });
                            break;
                        }
                        if (!xhr.response) {
                            onerror({ status: "无法访问服务器" });
                            break;
                        }
                    case 200:
                    case 201:
                    case 304:
                        onload(xhr);
                        break;
                    case 302:
                    case 301:
                        if (xhr.isRedirected > 2 || nocross) break;
                        var location = xhr.getResponseHeader("efront-location");
                        if (!domainReg.test(location)) {
                            if (/^\//.test(location)) {
                                location = originDomain.replace(/\/.*$/, location);
                            } else {
                                location = originDomain.replace(/[^\/+]$/, location);
                            }
                            location = getRequestProtocol(url) + "//" + location;
                        }
                        var crs = cross("get", location, headers);
                        crs.isRedirected = (xhr.isRedirected || 0) + 1;
                        crs.done(onload, false);
                        crs.error(onerror, false);
                        break;
                    default:
                        onerror(xhr);
                }
                dispatch(window, 'render');
            }
        };
        var setRequestHeader = xhr.setRequestHeader;
        var realHeaders = Object.create(null);
        xhr.setRequestHeader = function (key, value) {
            realHeaders[key] = value;
        };
        xhr.then = function (ok, oh) {
            onloads.push(ok);
            onerrors.push(oh);
            flush();
        };
        setTimeout(function () {
            digest();
            var isform = /^f/i.test(method);
            if (isform) {
                if (method === 'form') method = 'post';
                else method = method.slice(1);
            }
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                if (/^(get|head|trace)$/i.test(method)) {
                    url = url.replace(/#[\s\S]*/, '');
                    datas = serialize(jsondata);
                    if (datas) url += (/\?/.test(url) ? "&" : "?") + datas;
                } else if (isform) {
                    xhr.form(jsondata);
                } else {
                    datas = JSON.stringify(jsondata);
                    if (datas === "{}" || datas === "[]") {
                        datas = '';
                    } else {
                        realHeaders["Content-Type"] = "application/json;charset=UTF-8";
                    }
                }
            }
            if (nocross) {
                extend(realHeaders, _headers);
                xhr.open(method, url);
            } else {
                xhr.open(method, getCrossUrl(url, _headers));
            }
            Object.keys(realHeaders).forEach(key => setRequestHeader.call(xhr, key, realHeaders[key]));
            send.call(xhr, datas);
        }, 0);
    }
    var loaded, errored;
    var onload = function (xhr) {
        if (xhr.decoder) {
            xhr = xhr.decoder(xhr);
        }
        loaded = xhr;
        flush();
        digest();
    };
    var onerror = function (xhr) {
        errored = xhr;
        flush();
        digest();
    };
    var flush = function () {
        var then = xhr.then;
        delete xhr.then;
        if (loaded) onloads.splice(0, onloads.length).map(e => e instanceof Function && e(xhr));
        if (errored) onerrors.splice(0, onerrors.length).map(e => e instanceof Function && e(errored));
        xhr.then = then;
    };
    var onloads = [], onerrors = [];
    xhr.done = xhr.success = function (on, asqueue = true) {
        if (!asqueue) onloads.splice(0, onloads.length);
        onloads.push(on);
        flush();
        return xhr;
    };
    var send = xhr.send;
    var datas = "";
    var jsondata = null;
    xhr.json = xhr.data = xhr.send = function (data, value) {
        if (!jsondata && !(isEmpty(data) && isEmpty(value))) jsondata = data instanceof Array ? [] : {};
        if (FormData && data instanceof FormData) {
            datas = data;
        } else if (isObject(data) && !isFile(data)) {
            extend(jsondata, data);
        } else if (!isEmpty(value)) {
            extend(jsondata, { [data]: value });
        } else if (isString(data) && value !== false && /^\s*\{|\=/.test(data)) {
            var data = /^\s*\{/.test(data) ? JSON.parse(data) : parseKV(data, "&", "=");
            extend(jsondata, data);
        } else {
            datas = data;
        }
        return xhr;
    };
    xhr.form = function (data) {
        xhr.data(data);
        if (FormData) {
            datas = new FormData;
            for (var k in jsondata) {
                datas.append(k, jsondata[k]);
            }
        } else {
            realHeaders["Content-Type"] = "application/x-www-form-urlencoded";
            datas = serialize(jsondata, "&", "=");
        }
    };
    xhr.fail = xhr.error = function (on, asqueue = true) {
        if (!asqueue) {
            onerrors.splice(0, onerrors.length);
        }
        onerrors.push(on);
        flush();
        return xhr;
    };
    return xhr;
}
function addDirect(a) {
    if (typeof a === 'string' || a instanceof RegExp) cors_hosts.push(a);
}
function notCross(domain) {
    if (location_host === domain.slice(0, location_host.length) || !/^https?\:\/\/|^s?\/\//.test(domain)) return true;
    for (var cx = 0, dx = cors_hosts.length; cx < dx; cx++) {
        var host = cors_hosts[cx];
        if (host instanceof RegExp) {
            if (host.test(domain)) return true;
        } else {
            host = host.replace(domainReg, '$2/$3');
            if (domain.replace(domainReg, '$2/$3').slice(0, host.length) === host) return true;
        }
    }
    return false;
}
extend(cross, {
    setHost,
    getCookies,
    addCookie,
    addDirect,
    getCrossUrl
});<|endoftext|>


<commit_before>define(["github/adioo/bind-list/v0.2.2/list"], function(List) {

    var self;

    function init(config) {

        config.crud = {
            create: "create",
            read:   "read",
            update: "update",
            // "delete" is considered a keywork by some browsers
            "delete": "remove"
        }

        if (config.sample) {
            // this reads the sample configuration if this is a sample list
            buildSampleConfig(config);
        }

        self = List(this, config);
    }

    function buildSampleConfig(config) {

        // (mandatory) what to render fot each data item
        config.template = {
            type: "selector", // "url", "html"
            value: ".template",
            binds: [
                {
                    target: ".delete",
                    on: [{
                        name: "click",
                        handler: "removeItem"
                    }]
                },
                {
                    on: [{
                        name: "click",
                        handler: "selectItem"
                    }]
                },
                {
                    attr: [
                        {
                            name: "id",
                            value: {
                                source: "id",
                                filter: [
                                    { name: "prefix", args: "itm", library: "/aasdsda" }
                                ]
                            }
                        }
                    ],
                },
                {
                    target: ".itemText",
                    html: {
                        source: "text"
                    }
                }
            ]
        };

        // (mandatory) where to display rendered items
        config.container = ".content";

        // (mandatory) the CRUD operations are module operations
        config.crud = {
            create: "create",
            read:   "read",
            update: "update",
            "delete": "remove"
        };

        // (optional) options
        config.options = {
            selection: "multiple", // "single", "multiple"
            autofetch: true,
            classes: {
                selected: "selected"
            },
            id: "_id",
            pagination: {
                size: 5,
                controls: {
                    next: ".next",
                    previous: ".prev",
                    disable: "disabled"
                },
                classes: {
                    disable: "disabled"
                }
            }
        };

        // (optional) selectors as handles for core list operations
        config.controls = {
            add: ".create",
            "delete": ".delete"
        };

        // (optional) additional functionality through bind objects
        config.binds = [
            {
                target: "create",
                on: [{
                    name: "click",
                    emit: "newItem"
                }]
            }
        ];
    }

    return init;
});

<commit_msg>Updated version number to 0.3.0<commit_after>define(["github/adioo/bind-list/v0.3.0/list"], function(List) {

    var self;

    function init(config) {

        config.crud = {
            create: "create",
            read:   "read",
            update: "update",
            // "delete" is considered a keywork by some browsers
            "delete": "remove"
        }

        if (config.sample) {
            // this reads the sample configuration if this is a sample list
            buildSampleConfig(config);
        }

        self = List(this, config);
    }

    function buildSampleConfig(config) {

        // (mandatory) what to render fot each data item
        config.template = {
            type: "selector", // "url", "html"
            value: ".template",
            binds: [
                {
                    target: ".delete",
                    on: [{
                        name: "click",
                        handler: "removeItem"
                    }]
                },
                {
                    on: [{
                        name: "click",
                        handler: "selectItem"
                    }]
                },
                {
                    attr: [
                        {
                            name: "id",
                            value: {
                                source: "id",
                                filter: [
                                    { name: "prefix", args: "itm", library: "/aasdsda" }
                                ]
                            }
                        }
                    ],
                },
                {
                    target: ".itemText",
                    html: {
                        source: "text"
                    }
                }
            ]
        };

        // (mandatory) where to display rendered items
        config.container = ".content";

        // (mandatory) the CRUD operations are module operations
        config.crud = {
            create: "create",
            read:   "read",
            update: "update",
            "delete": "remove"
        };

        // (optional) options
        config.options = {
            selection: "multiple", // "single", "multiple"
            autofetch: true,
            classes: {
                selected: "selected"
            },
            id: "_id",
            pagination: {
                size: 5,
                controls: {
                    next: ".next",
                    previous: ".prev",
                    disable: "disabled"
                },
                classes: {
                    disable: "disabled"
                }
            }
        };

        // (optional) selectors as handles for core list operations
        config.controls = {
            add: ".create",
            "delete": ".delete"
        };

        // (optional) additional functionality through bind objects
        config.binds = [
            {
                target: "create",
                on: [{
                    name: "click",
                    emit: "newItem"
                }]
            }
        ];
    }

    return init;
});

<|endoftext|>