<commit_before>'use strict';

var common = require('./common.js');
var fs = common.fs;
var mock = common.mock;

describe('CLI tests', function () {

    this.timeout(common.timeout);

    before(function (done) {

        // Configure mock filesystem
        mock({
            'src/.userConfig': {
                'access_token': '1234567890',
                'whoami': 'foo'
            },
            'src/.config': {
                'endpoint': 'http://www.foo.bar/',
                'configFile': 'config.yml',
                'ignoreFile': 'ignoreFile',
                'client-id': 'client-id',
                'client-secret': 'client-secret'
            },
            'build': {
                'config.yml': fs.readFileSync('./test/mock/config.yml')
            },
            'build.zip': fs.readFileSync('./test/mock/build.zip'),
            'artifacts.zip': fs.readFileSync('./test/mock/artifacts.zip'),
            'payload.json': fs.readFileSync('./test/mock/payload.json'),
            'token.json': fs.readFileSync('./test/mock/token.json'),
            'buildRequest.json': fs.readFileSync('./test/mock/buildRequest.json')
        }, {
            createTmp: true
        });

        done();
    });

    common.importTest('bin tests', './bin/apb-bin.js');
    common.importTest('help tests', './bin/apb-help.js');
    common.importTest('version tests', './bin/apb-version.js');

    common.importTest('login tests', './api/apb-login.js');
    common.importTest('whoami tests', './api/apb-whoami.js');
    common.importTest('config tests', './api/apb-config.js');
    common.importTest('build tests', './api/apb-build.js');
    common.importTest('status tests', './api/apb-status.js');
    common.importTest('log tests', './api/apb-log.js');
    common.importTest('download tests', './api/apb-download.js');
    common.importTest('logout tests', './api/apb-logout.js');

    // TODO: Create test for integration test (bin execution) for the whole process

    after(function (done) {
        mock.restore();
        done();
    });

});
<commit_msg>Clean-up after every test<commit_after>'use strict';

var common = require('./common.js');
var fs = common.fs;
var mock = common.mock;

describe('CLI tests', function () {

    this.timeout(common.timeout);

    beforeEach(function (done) {

        // Configure mock filesystem
        mock({
            'src/.userConfig': {
                'access_token': '1234567890',
                'whoami': 'foo'
            },
            'src/.config': {
                'endpoint': 'http://www.foo.bar/',
                'configFile': 'config.yml',
                'ignoreFile': 'ignoreFile',
                'client-id': 'client-id',
                'client-secret': 'client-secret'
            },
            'build': {
                'config.yml': fs.readFileSync('./test/mock/config.yml')
            },
            'build.zip': fs.readFileSync('./test/mock/build.zip'),
            'artifacts.zip': fs.readFileSync('./test/mock/artifacts.zip'),
            'payload.json': fs.readFileSync('./test/mock/payload.json'),
            'token.json': fs.readFileSync('./test/mock/token.json'),
            'buildRequest.json': fs.readFileSync('./test/mock/buildRequest.json')
        }, {
            createTmp: true
        });

        done();
    });

    common.importTest('bin tests', './bin/apb-bin.js');
    common.importTest('help tests', './bin/apb-help.js');
    common.importTest('version tests', './bin/apb-version.js');

    common.importTest('login tests', './api/apb-login.js');
    common.importTest('whoami tests', './api/apb-whoami.js');
    common.importTest('config tests', './api/apb-config.js');
    common.importTest('build tests', './api/apb-build.js');
    common.importTest('status tests', './api/apb-status.js');
    common.importTest('log tests', './api/apb-log.js');
    common.importTest('download tests', './api/apb-download.js');
    common.importTest('logout tests', './api/apb-logout.js');

    // TODO: Create test for integration test (bin execution) for the whole process

    afterEach(function (done) {
        mock.restore();
        done();
    });

});
<|endoftext|>


<commit_before><commit_msg>Upload homeless.js<commit_after>GenMap();
  GenPlaceholder();
  GenScatter();

  $(document).ready(function () {
      $("input[type='radio']").on('change', function () {
           var selectedValue = $("input[name='radio']:checked").val();

           if (selectedValue === 'Map') {
               d3.selectAll('#viz_container').remove();
               GenMap();

             }else if(selectedValue === 'Table'){
               d3.selectAll("#viz_container").remove();
               d3.selectAll("#legend").remove();
               d3.select("#edu-tooltip").remove();
               d3.select("svg").remove();
               GenTable();
               GenPlaceholder();

             }
       });
  });

  function GenPlaceholder(){
    var svg = d3.select('#container2').append('svg')
                .attr("width","950px")
                .attr("height","650")
                .style("background-color","rgba(0, 0, 0, 0.7)")
                .attr("x","50")
                .attr("y","20")
                .attr("rx","20")
                .attr("ry","20")
                .text("PLACEHOLDER")
                .style("fill","#FFF");

    svg.append("svg:image")
    .attr('x', 275)
    .attr('y', 150)
    .attr('width', 400)
    .attr('height', 450)
    .attr("xlink:href", "GRUMPYCAT.png")

  }

  function GenScatter(){
    var formatNumber = d3.format("$,");
    var formatNumberNew = d3.format("$,.2");

    var margin = { top: 50, right:0, bottom: 50, left: 120 },
        outerWidth = 700,
        outerHeight = 700,
        width = outerWidth - margin.left - margin.right,
        height = outerHeight - margin.top - margin.bottom;

    var x = d3.scale.linear()
        .range([0, width]).nice();

    var y = d3.scale.linear()
        .range([height, 0]).nice();

    var xCat = "No_Staff",
        yCat = "Amount",
        colorCat = "Bin";

    d3.csv("/data-lab-data/binned_V2.csv", function(data) {
      data.forEach(function(d) {
        d.Amount = +d.Amount;
        d.No_Staff = +d.No_Staff;
      });

      var xMax = d3.max(data, function(d) { return d[xCat]; }) * 1.08,
          xMin = d3.min(data, function(d) { return d[xCat]; }),
          xMin = xMin > 0 ? 0 : xMin,
          yMax = d3.max(data, function(d) { return d[yCat]; }) * 1.08,
          yMin = d3.min(data, function(d) { return d[yCat]; }),
          yMin = yMin > 0 ? 0 : yMin;

      x.domain([xMin, xMax]);
      y.domain([yMin, yMax]);

      var xAxis = d3.svg.axis()
          .scale(x)
          .orient("bottom")
          .tickSize(-height);

      var yAxis = d3.svg.axis()
          .scale(y)
          .orient("left")
          .tickFormat(d3.format("$,"))
          .tickSize(-width);

      var color = d3.scale.category20c();

      var tip = d3.tip()
          .attr("class", "d3-tip")
          .offset([-10, 0])
          .html(function(d) {
            var per = d[yCat]/d[xCat];
            return ""+ d["Recipient"] + "" + "
"
            + "2015 Project grants awarded: " + "" +formatNumber(d[yCat]) + "" +"
"
            + "Number of full-time Research staff: "+ "" + d["Research_number"] + "" +"
"
            + "Number of Instructional staff: "+ "" +d["No_Staff"] + "" + "
"
            + "Grant $s per Instructor: "+ "" +formatNumber(Math.floor(d[yCat]/d[xCat])) + "" +"
"
            + "" + d["Type"] + "";
          });

      var zoomBeh = d3.behavior.zoom()
          .x(x)
          .y(y)
          .scaleExtent([0, 500])
          .on("zoom", zoom);

      var svg = d3.select("#scatter")
        .append("svg")
          .attr("width", outerWidth)
          .attr("height", outerHeight)
        .append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
          .call(zoomBeh);

      svg.call(tip);

      svg.append("rect")
          .attr("width", width)
          .attr("height", height);

      svg.append("g")
          .classed("x axis", true)
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis)
        .append("text")
          .classed("label", true)
          .attr("x", width/2)
          .attr("y", margin.bottom - 10)
          .style("text-anchor", "middle")
          .text("Number of Homeless");

      svg.append("g")
          .classed("y axis", true)
          .call(yAxis)
        .append("text")
          .classed("label", true)
          .attr("transform", "rotate(-90)")
          .attr("x",-100)
          .attr("y",-margin.left+10)
          .attr("dy", ".71em")
          .style("text-anchor", "end")
          .text("Homeless CFDA Program Funds $");

      var objects = svg.append("svg")
          .classed("objects", true)
          .attr("width", width)
          .attr("height", height);

      objects.append("svg:line")
          .classed("axisLine hAxisLine", true)
          .attr("x1", 0)
          .attr("y1", 0)
          .attr("x2", width)
          .attr("y2", 0)
          .attr("transform", "translate(0," + height + ")");

      objects.append("svg:line")
          .classed("axisLine vAxisLine", true)
          .attr("x1", 0)
          .attr("y1", 0)
          .attr("x2", 0)
          .attr("y2", height);

      objects.selectAll(".dot")
          .data(data)
        .enter().append("circle")
          .classed("dot", true)
          .attr("r", function (d) { return 7 * Math.sqrt(4 / Math.PI); })
          .attr("transform", transform)
          .style("fill", function(d) { return color(d[colorCat]); })
          .on("mouseover", tip.show)
          .on("mouseout", tip.hide);

      d3.select("input[type=button]").on("click", change);

      function change() {
        xCat = "No_Staff";
        xMax = d3.max(data, function(d) { return d[xCat]; });
        xMin = d3.min(data, function(d) { return d[xCat]; });
        yCat = "Amount"
        yMax = d3.max(data, function(d) { return d[yCat]; });
        yMin = d3.min(data, function(d) { return d[yCat]; });
        zoomBeh.x(x.domain([0, xMax*1.05])).y(y.domain([0, yMax*1.05]));

        var svg = d3.select("#scatter").transition();

        svg.select(".x.axis").duration(750).call(xAxis).select(".label").text("Number of Homeless");
        svg.select(".y.axis").duration(750).call(yAxis).select(".label").text("Homeless CFDA Program Funds $");

        objects.selectAll(".dot").transition().duration(1000).attr("transform", transform);
      }

      function zoom() {
        svg.select(".x.axis").call(xAxis);
        svg.select(".y.axis").call(yAxis);

        svg.selectAll(".dot")
            .attr("transform", transform);
      }

      function transform(d) {
        return "translate(" + x(d[xCat]) + "," + y(d[yCat]) + ")";
      }
    });
  }

  function GenTable(){

    var column_names = ["Title","Views","Created On","URL"];
    var clicks = {title: 0, views: 0, created_on: 0, url: 0};

    d3.select("#container").append('div').attr("id","viz_container");

    d3.select("#viz_container").append("h3")
      .attr("id", "title")
      .style("text-align","center")
      .text("Continuum of Care Funding")

    d3.select("#viz_container").append("div")
      .attr("class", "SearchBar")
      .append("p")
        .attr("class", "SearchBar")
        .text("Search By Zip Code:");

    d3.select(".SearchBar")
      .append("input")
        .attr("class", "SearchBar")
        .attr("id", "search")
        .attr("type", "text")
        .attr("placeholder", "Search...")
        .style("font-family","inherit")
        .style("font-size","16");

    var table = d3.select("#viz_container").append("table");
    table.append("thead").append("tr");

    var headers = table.select("tr").selectAll("th")
        .data(column_names)
      .enter()
        .append("th")
        .text(function(d) { return d; });

    var rows, row_entries, row_entries_no_anchor, row_entries_with_anchor;

    d3.json("/data-lab-data/data.json", function(data) { // loading data from server

      // draw table body with rows
      table.append("tbody")

      // data bind
      rows = table.select("tbody").selectAll("tr")
        .data(data, function(d){ return d.id; });

      // enter the rows
      rows.enter()
        .append("tr")

      // enter td's in each row
      row_entries = rows.selectAll("td")
          .data(function(d) {
            var arr = [];
            for (var k in d) {
              if (d.hasOwnProperty(k)) {
    		    arr.push(d[k]);
              }
            }
            return [arr[3],arr[1],arr[2],arr[0]];
          })
        .enter()
          .append("td")

      // draw row entries with no anchor
      row_entries_no_anchor = row_entries.filter(function(d) {
        return (/https?:\/\//.test(d) == false)
      })
      row_entries_no_anchor.text(function(d) { return d; })

      // draw row entries with anchor
      row_entries_with_anchor = row_entries.filter(function(d) {
        return (/https?:\/\//.test(d) == true)
      })
      row_entries_with_anchor
        .append("a")
        .attr("href", function(d) { return d; })
        .attr("target", "_blank")
      .text(function(d) { return d; })

      /**  search functionality **/
        d3.select("#search")
          .on("keyup", function() { // filter according to key pressed
            var searched_data = data,
                text = this.value.trim();

            var searchResults = searched_data.map(function(r) {
              var regex = new RegExp("^" + text + ".*", "i");
              if (regex.test(r.title)) { // if there are any results
                return regex.exec(r.title)[0]; // return them to searchResults
              }
            })

    	    // filter blank entries from searchResults
            searchResults = searchResults.filter(function(r){
              return r != undefined;
            })

            // filter dataset with searchResults
            searched_data = searchResults.map(function(r) {
               return data.filter(function(p) {
                return p.title.indexOf(r) != -1;
              })
            })

            // flatten array
    		searched_data = [].concat.apply([], searched_data)

            // data bind with new data
    		rows = table.select("tbody").selectAll("tr")
    		  .data(searched_data, function(d){ return d.id; })

            // enter the rows
            rows.enter()
             .append("tr");

            // enter td's in each row
            row_entries = rows.selectAll("td")
                .data(function(d) {
                  var arr = [];
                  for (var k in d) {
                    if (d.hasOwnProperty(k)) {
    		          arr.push(d[k]);
                    }
                  }
                  return [arr[3],arr[1],arr[2],arr[0]];
                })
              .enter()
                .append("td")

            // draw row entries with no anchor
            row_entries_no_anchor = row_entries.filter(function(d) {
              return (/https?:\/\//.test(d) == false)
            })
            row_entries_no_anchor.text(function(d) { return d; })

            // draw row entries with anchor
            row_entries_with_anchor = row_entries.filter(function(d) {
              return (/https?:\/\//.test(d) == true)
            })
            row_entries_with_anchor
              .append("a")
              .attr("href", function(d) { return d; })
              .attr("target", "_blank")
            .text(function(d) { return d; })

            // exit
            rows.exit().remove();
          })

      /**  sort functionality **/
      headers.on("click", function(d) {
          if (d == "Title") {
            clicks.title++;
            // even number of clicks
            if (clicks.title % 2 == 0) {
              // sort ascending: alphabetically
              rows.sort(function(a,b) {
                if (a.title.toUpperCase()  b.title.toUpperCase()) {
                  return 1;
                } else {
                  return 0;
                }
              });
            // odd number of clicks
            } else if (clicks.title % 2 != 0) {
              // sort descending: alphabetically
              rows.sort(function(a,b) {
                if (a.title.toUpperCase()  b.title.toUpperCase()) {
                  return -1;
                } else {
                  return 0;
                }
              });
            }
          }
          if (d == "Views") {
    	    clicks.views++;
            // even number of clicks
            if (clicks.views % 2 == 0) {
              // sort ascending: numerically
              rows.sort(function(a,b) {
                if (+a.views < +b.views) {
                  return -1;
                } else if (+a.views > +b.views) {
                  return 1;
                } else {
                  return 0;
                }
              });
            // odd number of clicks
            } else if (clicks.views % 2 != 0) {
              // sort descending: numerically
              rows.sort(function(a,b) {
                if (+a.views < +b.views) {
                  return 1;
                } else if (+a.views > +b.views) {
                  return -1;
                } else {
                  return 0;
                }
              });
            }
          }
          if (d == "Created On") {
            clicks.created_on++;
            if (clicks.created_on % 2 == 0) {
              // sort ascending: by date
              rows.sort(function(a,b) {
                // grep date and time, split them apart, make Date objects for comparing
    	        var date = /[\d]{4}-[\d]{2}-[\d]{2}/.exec(a.created_on);
    	        date = date[0].split("-");
    	        var time = /[\d]{2}:[\d]{2}:[\d]{2}/.exec(a.created_on);
    	        time = time[0].split(":");
    	        var a_date_obj = new Date(+date[0],(+date[1]-1),+date[2],+time[0],+time[1],+time[2]);

                date = /[\d]{4}-[\d]{2}-[\d]{2}/.exec(b.created_on);
    	        date = date[0].split("-");
    	        time = /[\d]{2}:[\d]{2}:[\d]{2}/.exec(b.created_on);
    	        time = time[0].split(":");
    	        var b_date_obj = new Date(+date[0],(+date[1]-1),+date[2],+time[0],+time[1],+time[2]);

                if (a_date_obj < b_date_obj) {
                  return -1;
                } else if (a_date_obj > b_date_obj) {
                  return 1;
                } else {
                  return 0;
                }
              });
            // odd number of clicks
            } else if (clicks.created_on % 2 != 0) {
              // sort descending: by date
              rows.sort(function(a,b) {
                // grep date and time, split them apart, make Date objects for comparing
    	        var date = /[\d]{4}-[\d]{2}-[\d]{2}/.exec(a.created_on);
    	        date = date[0].split("-");
    	        var time = /[\d]{2}:[\d]{2}:[\d]{2}/.exec(a.created_on);
    	        time = time[0].split(":");
    	        var a_date_obj = new Date(+date[0],(+date[1]-1),+date[2],+time[0],+time[1],+time[2]);

                date = /[\d]{4}-[\d]{2}-[\d]{2}/.exec(b.created_on);
    	        date = date[0].split("-");
    	        time = /[\d]{2}:[\d]{2}:[\d]{2}/.exec(b.created_on);
    	        time = time[0].split(":");
    	        var b_date_obj = new Date(+date[0],(+date[1]-1),+date[2],+time[0],+time[1],+time[2]);

                if (a_date_obj < b_date_obj) {
                  return 1;
                } else if (a_date_obj > b_date_obj) {
                  return -1;
                } else {
                  return 0;
                }
              });
            }
          }
          if (d == "URL") {
            clicks.url++;
    	    // even number of clicks
            if (clicks.url % 2 == 0) {
              // sort ascending: alphabetically
              rows.sort(function(a,b) {
                if (a.thumb_url_default.toUpperCase()  b.thumb_url_default.toUpperCase()) {
                  return 1;
                } else {
                  return 0;
                }
              });
            // odd number of clicks
            } else if (clicks.url % 2 != 0) {
              // sort descending: alphabetically
              rows.sort(function(a,b) {
                if (a.thumb_url_default.toUpperCase()  b.thumb_url_default.toUpperCase()) {
                  return -1;
                } else {
                  return 0;
                }
              });
            }
          }
        }) // end of click listeners
    });
    d3.select(self.frameElement).style("height", "700px").style("width", "1024px");

  }

  function GenMap(){

    var opts = {
      lines: 9, // The number of lines to draw
      length: 16, // The length of each line
      width: 6.5, // The line thickness
      radius: 14, // The radius of the inner circle
      color: '#EE3124', // #rgb or #rrggbb or array of colors
      speed: 1.9, // Rounds per second
      trail: 40, // Afterglow percentage
      className: 'spinner', // The CSS class to assign to the spinner
    };

    var target = document.getElementById("container");

    var spinner = new Spinner(opts).spin(target);

    d3.select("#container").append('div').attr("id","legend");
    d3.select("#container").append('div').attr("id","viz_container");
    d3.select("#container").append('div').attr("id","edu-tooltip");
    d3.select("#edu-tooltip").append('div').attr("id","edu-tooltipContainer");
    d3.select("#edu-tooltipContainer").append('div').attr("class","edu-department");
    d3.select("#edu-tooltipContainer").append('div').attr("class","edu-rule");
    d3.select("#edu-tooltipContainer").append('div').attr("class","edu-name");
    d3.select("#edu-tooltipContainer").append('div').attr("class","edu-discretion");
    d3.select("#edu-tooltipContainer").append('div').attr("class","edu-valuesContainer");
    d3.select(".edu-valuesContainer").append('span').attr("class","edu-value");
    d3.select("#edu-tooltipContainer").append('div').attr("class","edu-chart");
    d3.select("#edu-tooltipContainer").append('div').attr("class","edu-tail");

    var width = 1024,
        height = 700,
        centered = null;

    // D3 Projection
    var projection = d3.geo.albersUsa()
               .translate([width/2, height/2.5])    // translate to center of screen
               .scale([1200]);          // scale things down so see entire US ---1455

    // Define path generator
    var path = d3.geo.path()               // path generator that will convert GeoJSON to SVG paths
             .projection(projection);  // tell path generator to use albersUsa projection

    var svg = d3.select("#viz_container")
                .append("svg")
                .attr("width", width)
                .attr("height", height);

    var formatNumber = d3.format("$,f");

  d3.json("/data-lab-data/zips_us_topo.json",function(us){
    d3.json("/data-lab-data/us-states.json", function(json) {
      d3.csv("/data-lab-data/zips_2.csv",function(d){return{ zip: d.zip,value: +d.value }},function(data){
        d3.csv("/data-lab-data/State_crosswalk.csv",function(states){

          spinner.stop();

          console.log("US: ",us);
          console.log("JSON-States: ",json);
          console.log("States: ",states);
          console.log("Data: ",data);

          var legendWidth = "1024px";

          var legend = d3.select("#legend")
                         .append("svg")
                         .attr("width","1024px")
                         .attr("height","100px")
                         .attr("padding","50px 0 0 50px");

          var linearGradient = legend.append("linearGradient")
                       .attr("id", "linear-gradient")
                       .attr("transform", "translate(" + 0 + "," + 70 + ")");

              linearGradient.attr("x1", "0%")
                            .attr("y1", "0%")
                            .attr("x2", "100%")
                            .attr("y2", "0%");

                            //Set the color for the start (0%)
              linearGradient.append("stop")
                  .attr("offset", "0%")
                  .attr("stop-color", "#FFF600");

              //Set the color for the end (100%)
              linearGradient.append("stop")
                  .attr("offset", "100%")
                  .attr("stop-color", "#960018");

              legend.append("rect")
                    .attr("width", legendWidth)
              	    .attr("height", 20)
              	    .style("fill", "url(#linear-gradient)");

                    //Append title
              legend.append("text")
              	.attr("class", "legendTitle")
              	.attr("x", 512)
              	.attr("y", 60)
              	.style("text-anchor", "middle")
              	.text("Continuum of Care Funding");

                var min = d3.min(data, function(d) { return d.value; });
                var max = d3.max(data, function(d) { return d.value; });

              //Set scale for x-axis
              var xScale = d3.scale.linear()
              	 .range([0, 1024])
              	 .domain([min,max] );

              //Define x-axis
              var xAxis = d3.svg.axis()
              	  .orient("bottom")
              	  .ticks(4)
              	  .tickFormat(function(d) { return formatNumber(d); })
                  .tickSize([6,0])
              	  .scale(xScale);

            //Set up X axis
            legend.append("g")
            	.attr("class", "axis")
            	.attr("transform", "translate(0," + 22 + ")")
            	.call(xAxis);

            var color = d3.scale.linear()
                                .domain([min,max])
                                .range(["#FFF600","#960018"]);

            var g = svg.append("g")
                        .attr("class", "counties")
                        .selectAll("path")
                        .data(topojson.feature(us, us.objects.zip_codes_for_the_usa).features)
                        .enter().append("path")
                        .attr("class", "zip")
                        .attr("data-zip", function(d) {return d.properties.zip; })
                        .attr("data-state", function(d) {return d.properties.state; })
                        .attr("data-name", function(d) {return d.properties.name; })
                        .attr("d", path)
                        .on("click", clicked)
                        .style("fill",getColor)
                        .on("mouseover",function(d,i) {
                                var el = d3.select(this)
                                var xpos = Number(el.attr('cx'))
                                var ypos = (el.attr('cy') - d.radius - 10)
                                el.style("stroke","#000").style("stroke-width",.25);
                                d3.select("#edu-tooltip")
                                .style("left", (d3.event.pageX-5) + "px")
                                .style("top", (d3.event.pageY-20) + "px")
                                .style('display','block')
                                  .classed('edu-plus', (d.changeCategory > 0))
                                  .classed('edu-minus', (d.changeCategory < 0));
                                d3.select("#edu-tooltip .edu-name").html(d.properties.name)

                                d3.select("#edu-tooltip .edu-discretion").text("text goes here")
                                d3.select("#edu-tooltip .edu-department").text(getState(d))
                                d3.select("#edu-tooltip .edu-value").text(getValue(d))
                              })
                        .on("mouseout",function(d,i) {
                          d3.select(this)
                          .style("stroke-width",.15)
                          .style("stroke","#FFF")
                          d3.select("#edu-tooltip").style('display','none')});

            function clicked(d) {
                     var x, y, k;

                     for(var i=0; i<states.length; i++){
                       if(d.properties.state==states[i].Abbrv){
                         for(var h=0; h<json.features.length; h++){
                           if(states[i].State==json.features[h].properties.NAME){
                             var n = json.features[h];
                             //console.log("clicked n: ",n);
                             if (n && centered !== n) {
                               var centroid = path.centroid(n);
                                          x = centroid[0];
                                          y = centroid[1];

                               //console.log("d: ",d.properties.NAME);
                               if(n.properties.NAME === "Florida"){ k = 5.0}
                               else if(n.properties.NAME === "Michigan"){ k = 5.5}
                               else if(n.properties.NAME === "Idaho"){ k = 3.25}
                               else if(n.properties.NAME === "Alaska"){ k = 5.0}
                               else if(n.properties.NAME === "Hawaii"){ k = 7.0}
                               else if(n.properties.CENSUSAREA <= 15000){ k = 11.0 }
                               else if(n.properties.CENSUSAREA > 15000  &&  n.properties.CENSUSAREA <= 30000) { k = 9.0 }
                               else if(n.properties.CENSUSAREA > 30000 &&  n.properties.CENSUSAREA <= 50000) { k = 8.0 }
                               else if(n.properties.CENSUSAREA > 50000 &&  n.properties.CENSUSAREA <= 70000 ) { k = 6.5 }
                               else if(n.properties.CENSUSAREA > 70000 && n.properties.CENSUSAREA <= 90000) { k = 6.0 }
                               else if(n.properties.CENSUSAREA > 90000 && n.properties.CENSUSAREA <= 110000 ) { k = 5.0 }
                               else if(n.properties.CENSUSAREA > 110000 && n.properties.CENSUSAREA <= 130000) { k = 4.0 }
                               else if(n.properties.CENSUSAREA > 130000 && n.properties.CENSUSAREA <= 150000 ) { k = 3.5 }
                               else{ k = 2.75 };
                               centered = n;

                             } else {
                               x = width / 2;
                               y = height / 2;
                               k = 1;
                               centered = null;

                             }

                             g.selectAll("path")
                                 .classed("active", centered && function(d) { return d === centered; });

                             g.transition()
                                 .duration(750)
                                 .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
                                 .style("stroke-width", .15 / k + "px");
                             }
                           }
                         }
                       }
                     }

            function getColor(d){
              for(var i=0; i<data.length;i++){
                if(d.properties.zip===data[i].zip){
                  return color(data[i].value);
                }
              }
            }

            function getValue(d){
              for(var i=0; i<data.length;i++){
                if(d.properties.zip===data[i].zip){
                  return formatNumber(data[i].value);
                }
              }
            }

            function getState(d){
              for(var i=0; i<states.length;i++){
                if(d.properties.state===states[i].Abbrv){
                  return states[i].State;
                }
              }
            }

        });
      });
    });
  });
}
<|endoftext|>


<commit_before>var socks = require('socksv5');
var url = require('url');
var net = require('net');
var extend = require('extend');
var EventEmitter = require('events').EventEmitter;
var hparser = require('hparser');
var dispatch = require('./https');
var util = require('./util');
var rules = require('./rules');
var socketMgr = require('./socket-mgr');
var rulesUtil = require('./rules/util');
var existsCustomCert = require('./https/util').existsCustomCert;
var pluginMgr = require('./plugins');
var config = require('./config');

var LOCALHOST = '127.0.0.1';
var TUNNEL_HOST_RE = /^[^:\/]+\.[^:\/]+:\d+$/;
var STATUS_CODES = require('http').STATUS_CODES || {};
var getRawHeaderNames = hparser.getRawHeaderNames;
var formatHeaders = hparser.formatHeaders;
var getRawHeaders = hparser.getRawHeaders;
var SNI_UA_RE = /WebKit|Gecko|Trident\/(?:5|6|7)\.0/i;

function tunnelProxy(server, proxy) {
  server.on('connect', function(req, reqSocket, head) {//ws, wss, https proxy
    var tunnelUrl = req.fullUrl = util.setProtocol(TUNNEL_HOST_RE.test(req.url) ? req.url : req.headers.host, true);
    var options;
    var parseUrl = function (_url, port) {
      _url = _url || tunnelUrl;
      options = req.options = url.parse(_url);
      options.port = options.port || port || 443;
      return options;
    };
    parseUrl();
    tunnelUrl = req.fullUrl = 'tunnel://' + options.host;
    proxy.emit('_request', tunnelUrl);
    var resSocket, responsed, reqEmitter, data, rulesMgr, res;
    req.isTunnel = true;
    reqSocket.clientIp = req.clientIp = util.getClientIp(req);
    req.reqId = reqSocket.reqId = util.getReqId();
    var hostname = options.hostname;
    var isICloundCKDB = hostname === 'p22-ckdatabase.icloud.com';
    var isIPHost = !isICloundCKDB && net.isIP(hostname);
    var policy = req.headers[config.WHISTLE_POLICY_HEADER];
    var useTunnelPolicy = policy == 'tunnel';
    var isLocalUIUrl = !useTunnelPolicy && (config.isLocalUIUrl(hostname) || config.isPluginUrl(hostname));
    var _rules = req.rules = (isICloundCKDB || isLocalUIUrl) ? {} : rules.initRules(req);
    rules.resolveRulesFile(req, function() {
      var filter = req.filter;
      var disable = req.disable;
      var isDisabeIntercept = function() {
        return isICloundCKDB || useTunnelPolicy || disable.intercept || disable.https || disable.capture;
      };
      var isEnableIntercept = function() {
        return policy === 'intercept' || (!isIPHost && rulesUtil.properties.get('interceptHttpsConnects'))
          || filter.https || filter.capture || filter.intercept || existsCustomCert(hostname);
      };
      var isIntercept = function() {
        return isLocalUIUrl || (!isDisabeIntercept() && isEnableIntercept());
      };
      var plugin = isIntercept() ? null : pluginMgr.resolveWhistlePlugins(req);
      pluginMgr.getTunnelRules(req, function(_rulesMgr) {
        if (_rulesMgr) {
          rulesMgr = _rulesMgr;
          util.mergeRules(req, rulesMgr.resolveRules(tunnelUrl));
          plugin = pluginMgr.getPluginByRuleUrl(util.rule.getUrl(_rules.rule));
        }
        filter = req.filter;
        disable = req.disable;
        abortIfUnavailable(reqSocket);
        if (req.headers[config.WEBUI_HEAD]) {
          delete req.headers[config.WEBUI_HEAD];
          return reqSocket.destroy();
        }
        if (isIntercept()) {
          var useSNI = !disable.sni && (req.enable.sni || filter.sni
            || SNI_UA_RE.test(req.headers['user-agent']) || net.isIP(hostname));
          reqSocket.rulesHeaders = req.rulesHeaders;
          dispatch(reqSocket, useSNI ? null : hostname, function(_resSocket) {
            resSocket = _resSocket;
          });
          sendEstablished();
          return;
        }
        pluginMgr.postStats(req);
        req.whistleTunnelPlugins = req.whistlePlugins;
        req.whistlePlugins = null;
        reqEmitter = new EventEmitter();
        req.clientPort = reqSocket.remotePort;
        var headers = req.headers;
        var reqRawHeaderNames = getRawHeaderNames(req.rawHeaders) || {};
        var reqData = {
          ip: req.clientIp,
          port: req.clientPort,
          method: util.toUpperCase(req.method) || 'CONNECT',
          httpVersion: req.httpVersion || '1.1',
          headers: headers,
          rawHeaderNames: reqRawHeaderNames
        };
        var resData = {headers: {}};
        var inspect = req.enable.inspect;
        data = reqEmitter.data = {
          id: req.reqId,
          url: options.host,
          startTime: Date.now(),
          rules: _rules,
          req: reqData,
          res: resData,
          isHttps: true,
          inspect: inspect,
          rulesHeaders: req.rulesHeaders
        };
        var cId = headers['x-whistle-composer-id'];
        if (cId) {
          data.cId = cId;
          delete headers['x-whistle-composer-id'];
        }
        if (!filter.hide) {
          proxy.emit('request', reqEmitter);
        }

        if (req.enable.abort || filter.abort || disable.tunnel) {
          return reqSocket.destroy();
        }

        var statusCode = util.getMatcherValue(_rules.statusCode);
        if (statusCode) {
          if (statusCode == 200) {
            resSocket = util.getEmptyRes();
            var reqDelay = util.getMatcherValue(_rules.reqDelay);
            data.requestTime = data.dnsTime = Date.now();
            if (reqDelay > 0) {
              setTimeout(handleConnect, reqDelay);
            } else {
              handleConnect();
            }
            return;
          }
          return sendEstablished(statusCode);
        }

        pluginMgr.loadPlugin(plugin, function() {
          var tunnelPort, proxyUrl;
          if(plugin) {
            tunnelPort = plugin.ports && plugin.ports.tunnelPort;
            if (!tunnelPort) {
              return emitError(new Error('No plugin.tunnelServer'));
            }
            proxyUrl = 'proxy://127.0.0.1:' + tunnelPort;
            pluginMgr.addRuleHeaders(req, _rules);
          }

          var realUrl = _rules.rule && _rules.rule.url.replace('https:', 'tunnel:');
          if (/^tunnel:\/\//.test(realUrl) && realUrl != tunnelUrl) {
            tunnelUrl = realUrl;
            data.realUrl = realUrl.replace('tunnel://', '');
            parseUrl();
          }

          rules.getProxy(tunnelUrl, proxyUrl ? null : req, function(err, hostIp, hostPort) {
            if (!proxyUrl) {
              proxyUrl = _rules.proxy ? _rules.proxy.matcher : null;
            }

            if (proxyUrl) {
              var isSocks = /^socks:\/\//.test(proxyUrl);
              var _url = 'http:' + util.removeProtocol(proxyUrl);
              data.proxy = true;
              resolveHost(_url, function(ip) {
                options = parseUrl(_url, isSocks ? 1080 : 80);
                var isProxyPort = options.port == config.port;
                if (isProxyPort && util.isLocalAddress(ip)) {
                  return emitError(new Error('Unable to proxy to itself'));
                }
                var onConnect = function(proxySocket, _res) {
                  resSocket = proxySocket;
                  res = _res;
                  handleConnect();
                  abortIfUnavailable(resSocket);
                };
                var dstOptions = url.parse(tunnelUrl);
                dstOptions.proxyHost = ip;
                dstOptions.proxyPort = parseInt(options.port, 10);
                resData.port = dstOptions.port = dstOptions.port || 443;
                dstOptions.host = dstOptions.hostname;
                var _headers = extend({}, headers);
                pluginMgr.addRuleHeaders(req, _rules, _headers);
                _headers.host = dstOptions.hostname + ':' + (dstOptions.port || 443);
                util.parseRuleJson(_rules.reqHeaders, function(reqHeaders) {
                  extend(headers, reqHeaders);
                  if (disable.clientIp || disable.clientIP
                    || util.isLocalAddress(headers[config.CLIENT_IP_HEAD])) {
                    delete headers[config.CLIENT_IP_HEAD];
                  } else {
                    var forwardedFor = util.getMatcherValue(_rules.forwardedFor);
                    if (forwardedFor) {
                      headers[config.CLIENT_IP_HEAD] = forwardedFor;
                    }
                  }
                  var delReqHeaders = util.parseDeleteProperties(req).reqHeaders;
                  Object.keys(delReqHeaders).forEach(function(name) {
                    delete headers[name];
                  });
                  dstOptions.headers = formatHeaders(headers, reqRawHeaderNames);
                  if (isSocks) {
                    dstOptions.proxyPort = options.port || 1080;
                    dstOptions.localDNS = false;
                    dstOptions.auths = config.getAuths(options);
                  } else {
                    dstOptions.proxyPort = options.port || 80;
                    dstOptions.proxyAuth = options.auth;
                    if (isProxyPort) {
                      _headers[config.WEBUI_HEAD] = 1;
                    }
                  }
                  var netMgr = isSocks ? socks : config;
                  var reqDelay = util.getMatcherValue(_rules.reqDelay);
                  if (reqDelay > 0) {
                    setTimeout(function() {
                      netMgr.connect(dstOptions, onConnect).on('error', emitError);
                    }, reqDelay);
                  } else {
                    netMgr.connect(dstOptions, onConnect).on('error', emitError);
                  }
                });
              });
            } else {
              tunnel(hostIp, hostPort);
            }
          });
        });

        function tunnel(hostIp, hostPort) {
          resolveHost(tunnelUrl, function(ip, port) {
            if (port) {
              req.hostIp = resData.ip = ip + ':' + port;
              resData.port = port;
            } else {
              req.hostIp = resData.ip = ip;
              resData.port = port = options.port;
            }
            resSocket = net.connect(port, ip, handleConnect);
            abortIfUnavailable(resSocket);
          }, hostIp, hostPort);
        }

        function handleConnect() {
          reqSocket.headers = headers;
          reqSocket.fullUrl = tunnelUrl;
          reqSocket.inspectFrames = useTunnelPolicy || inspect;
          socketMgr.handleConnect(reqSocket, resSocket);
          var resDelay = util.getMatcherValue(_rules.resDelay);
          if (resDelay > 0) {
            setTimeout(sendEstablished, resDelay);
          } else {
            sendEstablished();
          }
        }

        function resolveHost(url, callback, hostIp, hostPort) {
          var hostHandler = function(err, ip, port, host) {
            if (host) {
              _rules.host = host;
            }
            data.requestTime = data.dnsTime = Date.now();
            req.hostIp = resData.ip = ip || LOCALHOST;
            reqEmitter.emit('send', data);
            err ? emitError(err) : callback(ip, port);
          };
          if (hostIp) {
            hostHandler(null, hostIp, hostPort);
          } else {
            rules.resolveHost(url, hostHandler, rulesMgr, req.rulesFileMgr, req.headerRulesMgr);
          }
        }

        function abortIfUnavailable(socket) {
          socket.on('error', emitError).on('close', emitError);
        }

        function sendEstablished(code) {
          if (res) {
            code = res.statusCode;
          } else {
            code = code || 200;
            res = {
              statusCode: code,
              headers: {
                'proxy-agent': config.name
              },
              rawHeaders: ['proxy-agent', 'Proxy-Agent']
            };
          }
          var resHeaders = res.headers;
          pluginMgr.getResRules(req, res, function() {
            var reqRules = req.rules;
            util.parseRuleJson(reqRules.resHeaders, function(newResHeaders) {
              extend(resHeaders, newResHeaders);
              var responseFor = util.getMatcherValue(reqRules.responseFor);
              if (responseFor) {
                resHeaders['x-whistle-response-for'] = responseFor;
              }
              var delResHeaders = util.parseDeleteProperties(req).resHeaders;
              Object.keys(delResHeaders).forEach(function(name) {
                delete resHeaders[name];
              });
              if (!resHeaders['proxy-agent']) {
                resHeaders['proxy-agent'] = config.name;
                res.rawHeaders = res.rawHeaders || [];
                res.rawHeaders.push('proxy-agent', 'Proxy-Agent');
              }
              var message = code == 200 ? 'Connection Established' : (STATUS_CODES[code] || 'unknown');
              var statusLine = ['HTTP/1.1', code, message].join(' ');
              var rawHeaderNames = getRawHeaderNames(res.rawHeaders) || {};
              var rawData = [statusLine, getRawHeaders(formatHeaders(resHeaders, rawHeaderNames))].join('\r\n') + '\r\n\r\n';
              if (code && code != 200) {
                reqSocket.end(rawData);
              } else {
                reqSocket.write(rawData);
              }
              if (reqEmitter) {
                responsed = true;
                data.responseTime = data.endTime = Date.now();
                resData.rawHeaderNames = rawHeaderNames;
                resData.statusCode = code || 200;
                resData.headers = resHeaders;
                reqEmitter.emit('response', data);
                reqEmitter.emit('end', data);
              }
            });
          });
          return reqSocket;
        }

        function emitError(err) {
          if (responsed) {
            return;
          }
          responsed = true;
          resSocket && resSocket.destroy();
          reqSocket.destroy();
          if (!reqEmitter) {
            return;
          }
          data.responseTime = data.endTime = Date.now();

          if (!resData.ip) {
            req.hostIp = resData.ip = LOCALHOST;
          }

          if (!err) {
            err = new Error('Aborted');
            data.reqError = true;
            resData.statusCode ='aborted';
            reqData.body = util.getErrorStack(err);
            reqEmitter.emit('abort', data);
          } else {
            data.resError = true;
            resData.statusCode = resData.statusCode || 502;
            resData.body = util.getErrorStack(err);
            util.emitError(reqEmitter, data);
          }
          resData.headers = {'x-server':'whistle' };
          pluginMgr.postStats(req, resData);
        }
      });
    });
  });

  return server;
}

module.exports = tunnelProxy;
<commit_msg>refactor: capture all requests for ports 80, 443 if enable capture<commit_after>var socks = require('socksv5');
var url = require('url');
var net = require('net');
var extend = require('extend');
var EventEmitter = require('events').EventEmitter;
var hparser = require('hparser');
var dispatch = require('./https');
var util = require('./util');
var rules = require('./rules');
var socketMgr = require('./socket-mgr');
var rulesUtil = require('./rules/util');
var existsCustomCert = require('./https/util').existsCustomCert;
var pluginMgr = require('./plugins');
var config = require('./config');

var LOCALHOST = '127.0.0.1';
var TUNNEL_HOST_RE = /^[^:\/]+\.[^:\/]+:\d+$/;
var STATUS_CODES = require('http').STATUS_CODES || {};
var getRawHeaderNames = hparser.getRawHeaderNames;
var formatHeaders = hparser.formatHeaders;
var getRawHeaders = hparser.getRawHeaders;
var SNI_UA_RE = /WebKit|Gecko|Trident\/(?:5|6|7)\.0/i;

function tunnelProxy(server, proxy) {
  server.on('connect', function(req, reqSocket, head) {//ws, wss, https proxy
    var tunnelUrl = req.fullUrl = util.setProtocol(TUNNEL_HOST_RE.test(req.url) ? req.url : req.headers.host, true);
    var options;
    var parseUrl = function (_url, port) {
      _url = _url || tunnelUrl;
      options = req.options = url.parse(_url);
      options.port = options.port || port || 443;
      return options;
    };
    parseUrl();
    tunnelUrl = req.fullUrl = 'tunnel://' + options.host;
    proxy.emit('_request', tunnelUrl);
    var resSocket, responsed, reqEmitter, data, rulesMgr, res;
    req.isTunnel = true;
    reqSocket.clientIp = req.clientIp = util.getClientIp(req);
    req.reqId = reqSocket.reqId = util.getReqId();
    var hostname = options.hostname;
    var isICloundCKDB = hostname === 'p22-ckdatabase.icloud.com';
    var isIPHost = !isICloundCKDB && net.isIP(hostname);
    var policy = req.headers[config.WHISTLE_POLICY_HEADER];
    var useTunnelPolicy = policy == 'tunnel';
    var isLocalUIUrl = !useTunnelPolicy && (config.isLocalUIUrl(hostname) || config.isPluginUrl(hostname));
    var _rules = req.rules = (isICloundCKDB || isLocalUIUrl) ? {} : rules.initRules(req);
    rules.resolveRulesFile(req, function() {
      var filter = req.filter;
      var disable = req.disable;
      var isDisabeIntercept = function() {
        return isICloundCKDB || useTunnelPolicy || disable.intercept || disable.https || disable.capture;
      };
      var isEnableIntercept = function() {
        if (filter.https || filter.capture || filter.intercept || policy === 'intercept') {
          return true;
        }
        if (!rulesUtil.properties.get('interceptHttpsConnects')) {
          return existsCustomCert(hostname);
        }
        if (isIPHost) {
          return options.port == 80 || options.port == 443;
        }
        return true;
      };
      var isIntercept = function() {
        return isLocalUIUrl || (!isDisabeIntercept() && isEnableIntercept());
      };
      var plugin = isIntercept() ? null : pluginMgr.resolveWhistlePlugins(req);
      pluginMgr.getTunnelRules(req, function(_rulesMgr) {
        if (_rulesMgr) {
          rulesMgr = _rulesMgr;
          util.mergeRules(req, rulesMgr.resolveRules(tunnelUrl));
          plugin = pluginMgr.getPluginByRuleUrl(util.rule.getUrl(_rules.rule));
        }
        filter = req.filter;
        disable = req.disable;
        abortIfUnavailable(reqSocket);
        if (req.headers[config.WEBUI_HEAD]) {
          delete req.headers[config.WEBUI_HEAD];
          return reqSocket.destroy();
        }
        if (isIntercept()) {
          var useSNI = !disable.sni && (isIPHost || req.enable.sni || filter.sni
            || SNI_UA_RE.test(req.headers['user-agent']));
          reqSocket.rulesHeaders = req.rulesHeaders;
          dispatch(reqSocket, useSNI ? null : hostname, function(_resSocket) {
            resSocket = _resSocket;
          });
          sendEstablished();
          return;
        }
        pluginMgr.postStats(req);
        req.whistleTunnelPlugins = req.whistlePlugins;
        req.whistlePlugins = null;
        reqEmitter = new EventEmitter();
        req.clientPort = reqSocket.remotePort;
        var headers = req.headers;
        var reqRawHeaderNames = getRawHeaderNames(req.rawHeaders) || {};
        var reqData = {
          ip: req.clientIp,
          port: req.clientPort,
          method: util.toUpperCase(req.method) || 'CONNECT',
          httpVersion: req.httpVersion || '1.1',
          headers: headers,
          rawHeaderNames: reqRawHeaderNames
        };
        var resData = {headers: {}};
        var inspect = req.enable.inspect;
        data = reqEmitter.data = {
          id: req.reqId,
          url: options.host,
          startTime: Date.now(),
          rules: _rules,
          req: reqData,
          res: resData,
          isHttps: true,
          inspect: inspect,
          rulesHeaders: req.rulesHeaders
        };
        var cId = headers['x-whistle-composer-id'];
        if (cId) {
          data.cId = cId;
          delete headers['x-whistle-composer-id'];
        }
        if (!filter.hide) {
          proxy.emit('request', reqEmitter);
        }

        if (req.enable.abort || filter.abort || disable.tunnel) {
          return reqSocket.destroy();
        }

        var statusCode = util.getMatcherValue(_rules.statusCode);
        if (statusCode) {
          if (statusCode == 200) {
            resSocket = util.getEmptyRes();
            var reqDelay = util.getMatcherValue(_rules.reqDelay);
            data.requestTime = data.dnsTime = Date.now();
            if (reqDelay > 0) {
              setTimeout(handleConnect, reqDelay);
            } else {
              handleConnect();
            }
            return;
          }
          return sendEstablished(statusCode);
        }

        pluginMgr.loadPlugin(plugin, function() {
          var tunnelPort, proxyUrl;
          if(plugin) {
            tunnelPort = plugin.ports && plugin.ports.tunnelPort;
            if (!tunnelPort) {
              return emitError(new Error('No plugin.tunnelServer'));
            }
            proxyUrl = 'proxy://127.0.0.1:' + tunnelPort;
            pluginMgr.addRuleHeaders(req, _rules);
          }

          var realUrl = _rules.rule && _rules.rule.url.replace('https:', 'tunnel:');
          if (/^tunnel:\/\//.test(realUrl) && realUrl != tunnelUrl) {
            tunnelUrl = realUrl;
            data.realUrl = realUrl.replace('tunnel://', '');
            parseUrl();
          }

          rules.getProxy(tunnelUrl, proxyUrl ? null : req, function(err, hostIp, hostPort) {
            if (!proxyUrl) {
              proxyUrl = _rules.proxy ? _rules.proxy.matcher : null;
            }

            if (proxyUrl) {
              var isSocks = /^socks:\/\//.test(proxyUrl);
              var _url = 'http:' + util.removeProtocol(proxyUrl);
              data.proxy = true;
              resolveHost(_url, function(ip) {
                options = parseUrl(_url, isSocks ? 1080 : 80);
                var isProxyPort = options.port == config.port;
                if (isProxyPort && util.isLocalAddress(ip)) {
                  return emitError(new Error('Unable to proxy to itself'));
                }
                var onConnect = function(proxySocket, _res) {
                  resSocket = proxySocket;
                  res = _res;
                  handleConnect();
                  abortIfUnavailable(resSocket);
                };
                var dstOptions = url.parse(tunnelUrl);
                dstOptions.proxyHost = ip;
                dstOptions.proxyPort = parseInt(options.port, 10);
                resData.port = dstOptions.port = dstOptions.port || 443;
                dstOptions.host = dstOptions.hostname;
                var _headers = extend({}, headers);
                pluginMgr.addRuleHeaders(req, _rules, _headers);
                _headers.host = dstOptions.hostname + ':' + (dstOptions.port || 443);
                util.parseRuleJson(_rules.reqHeaders, function(reqHeaders) {
                  extend(headers, reqHeaders);
                  if (disable.clientIp || disable.clientIP
                    || util.isLocalAddress(headers[config.CLIENT_IP_HEAD])) {
                    delete headers[config.CLIENT_IP_HEAD];
                  } else {
                    var forwardedFor = util.getMatcherValue(_rules.forwardedFor);
                    if (forwardedFor) {
                      headers[config.CLIENT_IP_HEAD] = forwardedFor;
                    }
                  }
                  var delReqHeaders = util.parseDeleteProperties(req).reqHeaders;
                  Object.keys(delReqHeaders).forEach(function(name) {
                    delete headers[name];
                  });
                  dstOptions.headers = formatHeaders(headers, reqRawHeaderNames);
                  if (isSocks) {
                    dstOptions.proxyPort = options.port || 1080;
                    dstOptions.localDNS = false;
                    dstOptions.auths = config.getAuths(options);
                  } else {
                    dstOptions.proxyPort = options.port || 80;
                    dstOptions.proxyAuth = options.auth;
                    if (isProxyPort) {
                      _headers[config.WEBUI_HEAD] = 1;
                    }
                  }
                  var netMgr = isSocks ? socks : config;
                  var reqDelay = util.getMatcherValue(_rules.reqDelay);
                  if (reqDelay > 0) {
                    setTimeout(function() {
                      netMgr.connect(dstOptions, onConnect).on('error', emitError);
                    }, reqDelay);
                  } else {
                    netMgr.connect(dstOptions, onConnect).on('error', emitError);
                  }
                });
              });
            } else {
              tunnel(hostIp, hostPort);
            }
          });
        });

        function tunnel(hostIp, hostPort) {
          resolveHost(tunnelUrl, function(ip, port) {
            if (port) {
              req.hostIp = resData.ip = ip + ':' + port;
              resData.port = port;
            } else {
              req.hostIp = resData.ip = ip;
              resData.port = port = options.port;
            }
            resSocket = net.connect(port, ip, handleConnect);
            abortIfUnavailable(resSocket);
          }, hostIp, hostPort);
        }

        function handleConnect() {
          reqSocket.headers = headers;
          reqSocket.fullUrl = tunnelUrl;
          reqSocket.inspectFrames = useTunnelPolicy || inspect;
          socketMgr.handleConnect(reqSocket, resSocket);
          var resDelay = util.getMatcherValue(_rules.resDelay);
          if (resDelay > 0) {
            setTimeout(sendEstablished, resDelay);
          } else {
            sendEstablished();
          }
        }

        function resolveHost(url, callback, hostIp, hostPort) {
          var hostHandler = function(err, ip, port, host) {
            if (host) {
              _rules.host = host;
            }
            data.requestTime = data.dnsTime = Date.now();
            req.hostIp = resData.ip = ip || LOCALHOST;
            reqEmitter.emit('send', data);
            err ? emitError(err) : callback(ip, port);
          };
          if (hostIp) {
            hostHandler(null, hostIp, hostPort);
          } else {
            rules.resolveHost(url, hostHandler, rulesMgr, req.rulesFileMgr, req.headerRulesMgr);
          }
        }

        function abortIfUnavailable(socket) {
          socket.on('error', emitError).on('close', emitError);
        }

        function sendEstablished(code) {
          if (res) {
            code = res.statusCode;
          } else {
            code = code || 200;
            res = {
              statusCode: code,
              headers: {
                'proxy-agent': config.name
              },
              rawHeaders: ['proxy-agent', 'Proxy-Agent']
            };
          }
          var resHeaders = res.headers;
          pluginMgr.getResRules(req, res, function() {
            var reqRules = req.rules;
            util.parseRuleJson(reqRules.resHeaders, function(newResHeaders) {
              extend(resHeaders, newResHeaders);
              var responseFor = util.getMatcherValue(reqRules.responseFor);
              if (responseFor) {
                resHeaders['x-whistle-response-for'] = responseFor;
              }
              var delResHeaders = util.parseDeleteProperties(req).resHeaders;
              Object.keys(delResHeaders).forEach(function(name) {
                delete resHeaders[name];
              });
              if (!resHeaders['proxy-agent']) {
                resHeaders['proxy-agent'] = config.name;
                res.rawHeaders = res.rawHeaders || [];
                res.rawHeaders.push('proxy-agent', 'Proxy-Agent');
              }
              var message = code == 200 ? 'Connection Established' : (STATUS_CODES[code] || 'unknown');
              var statusLine = ['HTTP/1.1', code, message].join(' ');
              var rawHeaderNames = getRawHeaderNames(res.rawHeaders) || {};
              var rawData = [statusLine, getRawHeaders(formatHeaders(resHeaders, rawHeaderNames))].join('\r\n') + '\r\n\r\n';
              if (code && code != 200) {
                reqSocket.end(rawData);
              } else {
                reqSocket.write(rawData);
              }
              if (reqEmitter) {
                responsed = true;
                data.responseTime = data.endTime = Date.now();
                resData.rawHeaderNames = rawHeaderNames;
                resData.statusCode = code || 200;
                resData.headers = resHeaders;
                reqEmitter.emit('response', data);
                reqEmitter.emit('end', data);
              }
            });
          });
          return reqSocket;
        }

        function emitError(err) {
          if (responsed) {
            return;
          }
          responsed = true;
          resSocket && resSocket.destroy();
          reqSocket.destroy();
          if (!reqEmitter) {
            return;
          }
          data.responseTime = data.endTime = Date.now();

          if (!resData.ip) {
            req.hostIp = resData.ip = LOCALHOST;
          }

          if (!err) {
            err = new Error('Aborted');
            data.reqError = true;
            resData.statusCode ='aborted';
            reqData.body = util.getErrorStack(err);
            reqEmitter.emit('abort', data);
          } else {
            data.resError = true;
            resData.statusCode = resData.statusCode || 502;
            resData.body = util.getErrorStack(err);
            util.emitError(reqEmitter, data);
          }
          resData.headers = {'x-server':'whistle' };
          pluginMgr.postStats(req, resData);
        }
      });
    });
  });

  return server;
}

module.exports = tunnelProxy;
<|endoftext|>


<commit_before>(function(timbre) {
    "use strict";

    var fn = timbre.fn;

    fn.register("audio", function(_args) {
        var instance = timbre.apply(null, ["buffer"].concat(_args));

        fn.deferred(instance);

        instance._.isLoaded = false;
        instance._.isEnded  = true;
        instance._.loadedTime  = 0;

        Object.defineProperties(instance, {
            src: {
                set: function(value) {
                    var _ = this._;
                    if (_.value !== value) {
                        if (typeof value === "string") {
                            this._.src = value;
                            this._.isLoaded = false;
                        } else if (timbre.envtype === "browser" && value instanceof File) {
                            this._.src = value;
                            this._.isLoaded = false;
                        }
                    }
                },
                get: function() {
                    return this._.src;
                }
            },
            isLoaded: {
                get: function() {
                    return this._.isLoaded;
                }
            },
            loadedTime: {
                get: function() {
                    return this._.loadedTime;
                }
            }
        });

        instance.load = load;

        return instance;
    });

    var load = (function() {
        if (timbre.envtype === "browser") {
            return getLoadFunctionForBrowser();
        } else if (timbre.envtype === "node") {
            return getLoadFunctionForNodeJS();
        } else {
            return fn.nop;
        }
    })();

    function getLoadFunctionForBrowser() {
        return function() {
            var self = this, _ = this._;

            if (_.deferred.isResolve) {
                // throw error ??
                return this;
            }

            var args = arguments, i = 0;
            if (typeof args[i] === "string") {
                _.src = args[i++];
            } else if (args[i] instanceof File) {
                _.src = args[i++];
            }
            if (!_.src) {
                // throw error ??
                return this;
            }

            var dfd = _.deferred;

            dfd.done(function() {
                this._.emit("done");
            }.bind(this));

            if (typeof args[i] === "function") {
                dfd.done(args[i++]);
                if (typeof args[i] === "function") {
                    dfd.fail(args[i++]);
                }
            }

            _.loadedTime = 0;

            var src = _.src;
            var decoderList;

            if (typeof src === "string") {
                if (src !== "") {
                    var noUseByteData = false;
                    if (/.*\.wav/.test(src)) {
                        decoderList = [wav_decoder];
                    } else {
                        if (webkit_decoder) {
                            decoderList = [webkit_decoder];
                        } else if (moz_decoder) {
                            decoderList = [moz_decoder];
                            noUseByteData = true;
                        }
                    }

                    if (noUseByteData) {
                        then.call(this, decoderList, src, dfd);
                        this._.emit("load");
                    } else {
                        var xhr = new XMLHttpRequest();
                        xhr.open("GET", src, true);
                        xhr.responseType = "arraybuffer";
                        xhr.onload = function() {
                            if (xhr.status === 200) {
                                then.call(self, decoderList,
                                          new Uint8Array(xhr.response), dfd);
                            } else {
                                var msg = xhr.status + " " + xhr.statusText;
                                self._.emit("error", msg);
                                dfd.reject();
                            }
                        };
                        xhr.send();
                        this._.emit("load");
                    }
                } else {
                    dfd.reject();
                }
            } else if (src instanceof File) {
                // TODO:
                var reader = new FileReader();
                reader.onload = function() {
                    then.call(this, null,
                              new Uint8Array(xhr.response), dfd);
                };
                reader.readAsArrayBuffer(src);
                this._.emit("load");
            }
            return this;
        };
    }

    function getLoadFunctionForNodeJS() {
        return function() {
            var fs = require("fs");
            var self = this, _ = this._;

            if (_.deferred.isResolve) {
                // throw error ??
                return this;
            }

            var args = arguments, i = 0;
            if (typeof args[i] === "string") {
                _.src = args[i++];
            }
            if (!_.src) {
                // throw error ??
                return this;
            }

            var dfd = _.deferred;

            if (typeof args[i] === "function") {
                dfd.done(args[i++]);
                if (typeof args[i] === "function") {
                    dfd.fail(args[i++]);
                }
            }

            _.loadedTime = 0;

            var src = _.src;

            if (typeof src === "string") {
                fs.exists(src, function(exists) {
                    if (!exists) {
                        var msg = "file does not exists";
                        self._.emit("error", msg);
                        dfd.reject();
                    }

                    if (/.*\.ogg/.test(src)) {
                        then.call(self, [node_ogg_decoder], src, dfd);
                    } else if (/.*\.mp3/.test(src)) {
                        then.call(self, [node_mp3_decoder], src, dfd);
                    } else {
                        fs.readFile(src, function(err, data) {
                            if (err) {
                                var msg = "can't read file";
                                self._.emit("error", msg);
                                return dfd.reject();
                            }
                            var decoderList;
                            if (typeof src === "string") {
                                if (/.*\.wav/.test(src)) {
                                    decoderList = [wav_decoder];
                                }
                            }
                            then.call(self, decoderList,
                                      new Uint8Array(data), dfd);
                        });
                    }
                });
                this._.emit("load");
            }
            return this;
        };
    }

    var deinterleave = function(list) {
        var result = new list.constructor(list.length>>1);
        var i = list.length, j = result.length;
        if (i % 2) {
            i -= 1;
            j |= 0;
        }
        while (j) {
            result[--j] = (list[--i] + list[--i]) * 0.5;
        }
        return result;
    };

    var _24bit_to_32bit = function(uint8) {
        var b0, b1, b2, bb, x;
        var int32 = new Int32Array(uint8.length / 3);
        for (var i = 0, imax = uint8.length, j = 0; i < imax; ) {
            b0 = uint8[i++] ,b1 = uint8[i++], b2 = uint8[i++];
            bb = b0 + (b1 << 8) + (b2 << 16);
            x = (bb & 0x800000) ? -((bb^0xFFFFFF)+1) : bb;
            int32[j++] = x;
        }
        return int32;
    };

    var then = function(decoderList, data, dfd) {
        var self = this;

        // TODO:
        if (!decoderList) {
            return dfd.reject();
        }

        var onloadedmetadata = function(result) {
            var _ = self._;
            if (result) {
                _.samplerate = result.samplerate;
                _.buffer     = result.buffer;
                _.phase      = 0;
                _.phaseIncr  = result.samplerate / timbre.samplerate;
                _.duration   = result.duration * 1000;
                _.loadedTime = _.duration;
                _.isEnded    = false;
                _.currentTime = 0;
                if (_.isReversed) {
                    _.phaseIncr *= -1;
                    _.phase = result.buffer.length + _.phaseIncr;
                }
                self._.emit("loadedmetadata");
            } else {
                iter();
            }
        };

        var onloadeddata = function() {
            self._.emit("loadeddata");
            dfd.resolveWith(self);
        };

        var iter = function() {
            if (decoderList.length > 0) {
                var decoder = decoderList.shift();
                if (decoder) {
                    decoder.call(self, data, onloadedmetadata, onloadeddata);
                } else {
                    iter();
                }
            } else {
                self._.emit("error", "can't decode");
                dfd.reject();
            }
        };
        iter();
    };

    var webkit_decoder = (function() {
        if (typeof webkitAudioContext !== "undefined") {
            var ctx = new webkitAudioContext();
            return function(data, onloadedmetadata, onloadeddata) {
                var samplerate, duration, buffer;
                try {
                    buffer = ctx.createBuffer(data.buffer, true);
                } catch (e) {
                    return onloadedmetadata(false);
                }

                samplerate = ctx.sampleRate;
                buffer     = buffer.getChannelData(0);
                duration   = buffer.length / samplerate;

                onloadedmetadata({
                    samplerate: samplerate,
                    buffer    : buffer,
                    duration  : duration
                });

                this._.isLoaded  = true;
                this._.plotFlush = true;

                onloadeddata();
            };
        }
    })();

    var moz_decoder = (function() {
        if (typeof Audio === "function" && typeof new Audio().mozSetup === "function") {
            return function(data, onloadedmetadata, onloadeddata) {
                var self = this;
                var samplerate, duration, buffer;
                var writeIndex = 0;

                var audio = new Audio(data);
                audio.volume = 0.0;
                audio.speed  = 2;
                audio.addEventListener("loadedmetadata", function() {
                    samplerate = audio.mozSampleRate;
                    duration = audio.duration;
                    buffer = new Float32Array((audio.duration * samplerate)|0);
                    if (audio.mozChannels === 2) {
                        audio.addEventListener("MozAudioAvailable", function(e) {
                            var samples = e.frameBuffer;
                            for (var i = 0, imax = samples.length; i < imax; i += 2) {
                                buffer[writeIndex++] = (samples[i] + samples[i+1]) * 0.5;
                            }
                            self._.loadedTime = samples.length * 1000 / samplerate;
                        }, false);
                    } else {
                        audio.addEventListener("MozAudioAvailable", function(e) {
                            var samples = e.frameBuffer;
                            for (var i = 0, imax = samples.length; i < imax; ++i) {
                                buffer[writeIndex++] = samples[i];
                            }
                            self._.loadedTime = samples.length * 1000 / samplerate;
                        }, false);
                    }
                    audio.play();
                    setTimeout(function() {
                        onloadedmetadata({
                            samplerate: samplerate,
                            buffer    : buffer,
                            duration  : duration
                        });
                    }, 1000);
                }, false);
                audio.addEventListener("ended", function() {
                    self._.isLoaded  = true;
                    self._.plotFlush = true;
                    onloadeddata();
                }, false);
                audio.addEventListener("error", function() {
                    self._.emit("error");
                }, false);
                audio.load();
            };
        }
    })();

    var wav_decoder = function(data, onloadedmetadata, onloadeddata) {
        if (data[0] !== 0x52 || data[1] !== 0x49 ||
            data[2] !== 0x46 || data[3] !== 0x46) { // 'RIFF'
            // "HeaderError: not exists 'RIFF'"
            return onloadedmetadata(false);
        }

        var l1 = data[4] + (data[5]<<8) + (data[6]<<16) + (data[7]<<24);
        if (l1 + 8 !== data.length) {
            // "HeaderError: invalid data size"
            return onloadedmetadata(false);
        }

        if (data[ 8] !== 0x57 || data[ 9] !== 0x41 ||
            data[10] !== 0x56 || data[11] !== 0x45) { // 'WAVE'
            // "HeaderError: not exists 'WAVE'"
            return onloadedmetadata(false);
        }

        if (data[12] !== 0x66 || data[13] !== 0x6D ||
            data[14] !== 0x74 || data[15] !== 0x20) { // 'fmt '
            // "HeaderError: not exists 'fmt '"
            return onloadedmetadata(false);
        }

        // var byteLength = data[16] + (data[17]<<8) + (data[18]<<16) + (data[19]<<24);
        // var linearPCM  = data[20] + (data[21]<<8);
        var channels   = data[22] + (data[23]<<8);
        var samplerate = data[24] + (data[25]<<8) + (data[26]<<16) + (data[27]<<24);
        // var dataSpeed  = data[28] + (data[29]<<8) + (data[30]<<16) + (data[31]<<24);
        // var blockSize  = data[32] + (data[33]<<8);
        var bitSize    = data[34] + (data[35]<<8);

        if (data[36] !== 0x64 || data[37] !== 0x61 ||
            data[38] !== 0x74 || data[39] !== 0x61) { // 'data'
            // "HeaderError: not exists 'data'"
            return onloadedmetadata(false);
        }

        var l2 = data[40] + (data[41]<<8) + (data[42]<<16) + (data[43]<<24);
        var duration = ((l2 / channels) >> 1) / samplerate;

        if (l2 > data.length - 44) {
            // "HeaderError: not exists data"
            return onloadedmetadata(false);
        }

        var buffer = new Float32Array((duration * samplerate)|0);

        onloadedmetadata({
            samplerate: samplerate,
            buffer    : buffer,
            duration  : duration
        });

        if (bitSize === 8) {
            data = new Int8Array(data.buffer, 44);
        } else if (bitSize === 16) {
            data = new Int16Array(data.buffer, 44);
        } else if (bitSize === 32) {
            data = new Int32Array(data.buffer, 44);
        } else if (bitSize === 24) {
            data = _24bit_to_32bit(new Uint8Array(data.buffer, 44));
        }

        if (channels === 2) {
            data = deinterleave(data);
        }

        var k = 1 / ((1 << (bitSize-1)) - 1);
        for (var i = buffer.length; i--; ) {
            buffer[i] = data[i] * k;
        }

        this._.isLoaded  = true;
        this._.plotFlush = true;

        onloadeddata();
    };

    var node_ogg_decoder = function(filepath, onloadedmetadata) {
        onloadedmetadata(false);
    };

    var node_mp3_decoder = function(filepath, onloadedmetadata, onloadeddata) {
        var fs   = require("fs");
        var lame = require("lame");
        var self = this;
        var decoder = new lame.Decoder();
        var bytes = [];
        var samplerate, duration, buffer;
        var channels, bitDepth;

        decoder.on("format", function(format) {
            // console.log("format", format);
            samplerate = format.sampleRate;
            channels   = format.channels;
            bitDepth   = format.bitDepth;
        });
        decoder.on("data", function(data) {
            for (var i = 0, imax = data.length; i < imax; ++i) {
                bytes.push(data[i]);
            }
        });
        decoder.on("end", function() {
            var length = bytes.length / channels / (bitDepth / 8);

            duration = length / samplerate;
            buffer = new Float32Array(length);

            var uint8 = new Uint8Array(bytes);
            var data;
            if (bitDepth === 16) {
                data = new Int16Array(uint8.buffer);
            } else if (bitDepth === 8) {
                data = new Int8Array(uint8.buffer);
            } else if (bitDepth === 24) {
                data = _24bit_to_32bit(uint8.buffer);
            }

            if (channels === 2) {
                data = deinterleave(data);
            }

            var k = 1 / ((1 << (bitDepth-1)) - 1);
            for (var i = buffer.length; i--; ) {
                buffer[i] = data[i] * k;
            }

            onloadedmetadata({
                samplerate: samplerate,
                buffer    : buffer,
                duration  : duration
            });

            self._.isLoaded  = true;
            self._.plotFlush = true;

            onloadeddata();
        });
        fs.createReadStream(filepath).pipe(decoder);
    };
})(timbre);
<commit_msg>fix support drag&drop<commit_after>(function(timbre) {
    "use strict";

    var fn = timbre.fn;

    fn.register("audio", function(_args) {
        var instance = timbre.apply(null, ["buffer"].concat(_args));

        fn.deferred(instance);

        instance._.isLoaded = false;
        instance._.isEnded  = true;
        instance._.loadedTime  = 0;

        Object.defineProperties(instance, {
            src: {
                set: function(value) {
                    var _ = this._;
                    if (_.value !== value) {
                        if (typeof value === "string") {
                            this._.src = value;
                            this._.isLoaded = false;
                        } else if (timbre.envtype === "browser" && value instanceof File) {
                            this._.src = value;
                            this._.isLoaded = false;
                        }
                    }
                },
                get: function() {
                    return this._.src;
                }
            },
            isLoaded: {
                get: function() {
                    return this._.isLoaded;
                }
            },
            loadedTime: {
                get: function() {
                    return this._.loadedTime;
                }
            }
        });

        instance.load = load;

        return instance;
    });

    var load = (function() {
        if (timbre.envtype === "browser") {
            return getLoadFunctionForBrowser();
        } else if (timbre.envtype === "node") {
            return getLoadFunctionForNodeJS();
        } else {
            return fn.nop;
        }
    })();

    function getLoadFunctionForBrowser() {
        return function() {
            var self = this, _ = this._;

            if (_.deferred.isResolve) {
                // throw error ??
                return this;
            }

            var args = arguments, i = 0;
            if (typeof args[i] === "string") {
                _.src = args[i++];
            } else if (args[i] instanceof File) {
                _.src = args[i++];
            }
            if (!_.src) {
                // throw error ??
                return this;
            }

            var dfd = _.deferred;

            dfd.done(function() {
                this._.emit("done");
            }.bind(this));

            if (typeof args[i] === "function") {
                dfd.done(args[i++]);
                if (typeof args[i] === "function") {
                    dfd.fail(args[i++]);
                }
            }

            _.loadedTime = 0;

            var src = _.src;
            var decoderList;

            if (typeof src === "string") {
                if (src !== "") {
                    var noUseByteData = false;
                    if (/.*\.wav/.test(src)) {
                        decoderList = [wav_decoder];
                    } else {
                        if (webkit_decoder) {
                            decoderList = [webkit_decoder];
                        } else if (moz_decoder) {
                            decoderList = [moz_decoder];
                            noUseByteData = true;
                        }
                    }

                    if (noUseByteData) {
                        then.call(this, decoderList, src, dfd);
                        this._.emit("load");
                    } else {
                        var xhr = new XMLHttpRequest();
                        xhr.open("GET", src, true);
                        xhr.responseType = "arraybuffer";
                        xhr.onload = function() {
                            if (xhr.status === 200) {
                                then.call(self, decoderList,
                                          new Uint8Array(xhr.response), dfd);
                            } else {
                                var msg = xhr.status + " " + xhr.statusText;
                                self._.emit("error", msg);
                                dfd.reject();
                            }
                        };
                        xhr.send();
                        this._.emit("load");
                    }
                } else {
                    dfd.reject();
                }
            } else if (src instanceof File) {
                if (webkit_decoder) {
                    var reader = new FileReader();
                    reader.onload = function(e) {
                        then.call(self, [webkit_decoder],
                                  new Uint8Array(e.target.result), dfd);
                    };
                    reader.readAsArrayBuffer(src);
                    this._.emit("load");
                } else {
                    var msg = "no support";
                    this._.emit("error", msg);
                    dfd.reject();
                }
            }
            return this;
        };
    }

    function getLoadFunctionForNodeJS() {
        return function() {
            var fs = require("fs");
            var self = this, _ = this._;

            if (_.deferred.isResolve) {
                // throw error ??
                return this;
            }

            var args = arguments, i = 0;
            if (typeof args[i] === "string") {
                _.src = args[i++];
            }
            if (!_.src) {
                // throw error ??
                return this;
            }

            var dfd = _.deferred;

            if (typeof args[i] === "function") {
                dfd.done(args[i++]);
                if (typeof args[i] === "function") {
                    dfd.fail(args[i++]);
                }
            }

            _.loadedTime = 0;

            var src = _.src;

            if (typeof src === "string") {
                fs.exists(src, function(exists) {
                    if (!exists) {
                        var msg = "file does not exists";
                        self._.emit("error", msg);
                        dfd.reject();
                    }

                    if (/.*\.ogg/.test(src)) {
                        then.call(self, [node_ogg_decoder], src, dfd);
                    } else if (/.*\.mp3/.test(src)) {
                        then.call(self, [node_mp3_decoder], src, dfd);
                    } else {
                        fs.readFile(src, function(err, data) {
                            if (err) {
                                var msg = "can't read file";
                                self._.emit("error", msg);
                                return dfd.reject();
                            }
                            var decoderList;
                            if (typeof src === "string") {
                                if (/.*\.wav/.test(src)) {
                                    decoderList = [wav_decoder];
                                }
                            }
                            then.call(self, decoderList,
                                      new Uint8Array(data), dfd);
                        });
                    }
                });
                this._.emit("load");
            }
            return this;
        };
    }

    var deinterleave = function(list) {
        var result = new list.constructor(list.length>>1);
        var i = list.length, j = result.length;
        if (i % 2) {
            i -= 1;
            j |= 0;
        }
        while (j) {
            result[--j] = (list[--i] + list[--i]) * 0.5;
        }
        return result;
    };

    var _24bit_to_32bit = function(uint8) {
        var b0, b1, b2, bb, x;
        var int32 = new Int32Array(uint8.length / 3);
        for (var i = 0, imax = uint8.length, j = 0; i < imax; ) {
            b0 = uint8[i++] ,b1 = uint8[i++], b2 = uint8[i++];
            bb = b0 + (b1 << 8) + (b2 << 16);
            x = (bb & 0x800000) ? -((bb^0xFFFFFF)+1) : bb;
            int32[j++] = x;
        }
        return int32;
    };

    var then = function(decoderList, data, dfd) {
        var self = this;

        // TODO:
        if (!decoderList) {
            return dfd.reject();
        }

        var onloadedmetadata = function(result) {
            var _ = self._;
            if (result) {
                _.samplerate = result.samplerate;
                _.buffer     = result.buffer;
                _.phase      = 0;
                _.phaseIncr  = result.samplerate / timbre.samplerate;
                _.duration   = result.duration * 1000;
                _.loadedTime = _.duration;
                _.isEnded    = false;
                _.currentTime = 0;
                if (_.isReversed) {
                    _.phaseIncr *= -1;
                    _.phase = result.buffer.length + _.phaseIncr;
                }
                self._.emit("loadedmetadata");
            } else {
                iter();
            }
        };

        var onloadeddata = function() {
            self._.emit("loadeddata");
            dfd.resolveWith(self);
        };

        var iter = function() {
            if (decoderList.length > 0) {
                var decoder = decoderList.shift();
                if (decoder) {
                    decoder.call(self, data, onloadedmetadata, onloadeddata);
                } else {
                    iter();
                }
            } else {
                self._.emit("error", "can't decode");
                dfd.reject();
            }
        };
        iter();
    };

    var webkit_decoder = (function() {
        if (typeof webkitAudioContext !== "undefined") {
            var ctx = new webkitAudioContext();
            return function(data, onloadedmetadata, onloadeddata) {
                var samplerate, duration, buffer;
                try {
                    buffer = ctx.createBuffer(data.buffer, true);
                } catch (e) {
                    return onloadedmetadata(false);
                }

                samplerate = ctx.sampleRate;
                buffer     = buffer.getChannelData(0);
                duration   = buffer.length / samplerate;

                onloadedmetadata({
                    samplerate: samplerate,
                    buffer    : buffer,
                    duration  : duration
                });

                this._.isLoaded  = true;
                this._.plotFlush = true;

                onloadeddata();
            };
        }
    })();

    var moz_decoder = (function() {
        if (typeof Audio === "function" && typeof new Audio().mozSetup === "function") {
            return function(data, onloadedmetadata, onloadeddata) {
                var self = this;
                var samplerate, duration, buffer;
                var writeIndex = 0;

                var audio = new Audio(data);
                audio.volume = 0.0;
                audio.speed  = 2;
                audio.addEventListener("loadedmetadata", function() {
                    samplerate = audio.mozSampleRate;
                    duration = audio.duration;
                    buffer = new Float32Array((audio.duration * samplerate)|0);
                    if (audio.mozChannels === 2) {
                        audio.addEventListener("MozAudioAvailable", function(e) {
                            var samples = e.frameBuffer;
                            for (var i = 0, imax = samples.length; i < imax; i += 2) {
                                buffer[writeIndex++] = (samples[i] + samples[i+1]) * 0.5;
                            }
                            self._.loadedTime = samples.length * 1000 / samplerate;
                        }, false);
                    } else {
                        audio.addEventListener("MozAudioAvailable", function(e) {
                            var samples = e.frameBuffer;
                            for (var i = 0, imax = samples.length; i < imax; ++i) {
                                buffer[writeIndex++] = samples[i];
                            }
                            self._.loadedTime = samples.length * 1000 / samplerate;
                        }, false);
                    }
                    audio.play();
                    setTimeout(function() {
                        onloadedmetadata({
                            samplerate: samplerate,
                            buffer    : buffer,
                            duration  : duration
                        });
                    }, 1000);
                }, false);
                audio.addEventListener("ended", function() {
                    self._.isLoaded  = true;
                    self._.plotFlush = true;
                    onloadeddata();
                }, false);
                audio.addEventListener("error", function() {
                    self._.emit("error");
                }, false);
                audio.load();
            };
        }
    })();

    var wav_decoder = function(data, onloadedmetadata, onloadeddata) {
        if (data[0] !== 0x52 || data[1] !== 0x49 ||
            data[2] !== 0x46 || data[3] !== 0x46) { // 'RIFF'
            // "HeaderError: not exists 'RIFF'"
            return onloadedmetadata(false);
        }

        var l1 = data[4] + (data[5]<<8) + (data[6]<<16) + (data[7]<<24);
        if (l1 + 8 !== data.length) {
            // "HeaderError: invalid data size"
            return onloadedmetadata(false);
        }

        if (data[ 8] !== 0x57 || data[ 9] !== 0x41 ||
            data[10] !== 0x56 || data[11] !== 0x45) { // 'WAVE'
            // "HeaderError: not exists 'WAVE'"
            return onloadedmetadata(false);
        }

        if (data[12] !== 0x66 || data[13] !== 0x6D ||
            data[14] !== 0x74 || data[15] !== 0x20) { // 'fmt '
            // "HeaderError: not exists 'fmt '"
            return onloadedmetadata(false);
        }

        // var byteLength = data[16] + (data[17]<<8) + (data[18]<<16) + (data[19]<<24);
        // var linearPCM  = data[20] + (data[21]<<8);
        var channels   = data[22] + (data[23]<<8);
        var samplerate = data[24] + (data[25]<<8) + (data[26]<<16) + (data[27]<<24);
        // var dataSpeed  = data[28] + (data[29]<<8) + (data[30]<<16) + (data[31]<<24);
        // var blockSize  = data[32] + (data[33]<<8);
        var bitSize    = data[34] + (data[35]<<8);

        if (data[36] !== 0x64 || data[37] !== 0x61 ||
            data[38] !== 0x74 || data[39] !== 0x61) { // 'data'
            // "HeaderError: not exists 'data'"
            return onloadedmetadata(false);
        }

        var l2 = data[40] + (data[41]<<8) + (data[42]<<16) + (data[43]<<24);
        var duration = ((l2 / channels) >> 1) / samplerate;

        if (l2 > data.length - 44) {
            // "HeaderError: not exists data"
            return onloadedmetadata(false);
        }

        var buffer = new Float32Array((duration * samplerate)|0);

        onloadedmetadata({
            samplerate: samplerate,
            buffer    : buffer,
            duration  : duration
        });

        if (bitSize === 8) {
            data = new Int8Array(data.buffer, 44);
        } else if (bitSize === 16) {
            data = new Int16Array(data.buffer, 44);
        } else if (bitSize === 32) {
            data = new Int32Array(data.buffer, 44);
        } else if (bitSize === 24) {
            data = _24bit_to_32bit(new Uint8Array(data.buffer, 44));
        }

        if (channels === 2) {
            data = deinterleave(data);
        }

        var k = 1 / ((1 << (bitSize-1)) - 1);
        for (var i = buffer.length; i--; ) {
            buffer[i] = data[i] * k;
        }

        this._.isLoaded  = true;
        this._.plotFlush = true;

        onloadeddata();
    };

    var node_ogg_decoder = function(filepath, onloadedmetadata) {
        onloadedmetadata(false);
    };

    var node_mp3_decoder = function(filepath, onloadedmetadata, onloadeddata) {
        var fs   = require("fs");
        var lame = require("lame");
        var self = this;
        var decoder = new lame.Decoder();
        var bytes = [];
        var samplerate, duration, buffer;
        var channels, bitDepth;

        decoder.on("format", function(format) {
            // console.log("format", format);
            samplerate = format.sampleRate;
            channels   = format.channels;
            bitDepth   = format.bitDepth;
        });
        decoder.on("data", function(data) {
            for (var i = 0, imax = data.length; i < imax; ++i) {
                bytes.push(data[i]);
            }
        });
        decoder.on("end", function() {
            var length = bytes.length / channels / (bitDepth / 8);

            duration = length / samplerate;
            buffer = new Float32Array(length);

            var uint8 = new Uint8Array(bytes);
            var data;
            if (bitDepth === 16) {
                data = new Int16Array(uint8.buffer);
            } else if (bitDepth === 8) {
                data = new Int8Array(uint8.buffer);
            } else if (bitDepth === 24) {
                data = _24bit_to_32bit(uint8.buffer);
            }

            if (channels === 2) {
                data = deinterleave(data);
            }

            var k = 1 / ((1 << (bitDepth-1)) - 1);
            for (var i = buffer.length; i--; ) {
                buffer[i] = data[i] * k;
            }

            onloadedmetadata({
                samplerate: samplerate,
                buffer    : buffer,
                duration  : duration
            });

            self._.isLoaded  = true;
            self._.plotFlush = true;

            onloadeddata();
        });
        fs.createReadStream(filepath).pipe(decoder);
    };
})(timbre);
<|endoftext|>


<commit_before>var test = require("tape");
var parse = require("../");
var spawn = require("child_process").spawn;
var fs = require("fs");

try{
    fs.mkdirSync("tmp");
} catch(err){
    // dir exists
}

test("valid json out", function(t){
    t.plan(1);
    var stream = parse("lib/jsdoc-parse.js");
    stream.on("readable", function(){
        var chunk = this.read();
        if (chunk){
            var data = JSON.parse(chunk);
            t.equal(data[0].name, "jsdoc-parse");
        }
    });
});

test("stdin input working", function(t){
    t.plan(1);
    var inputFile = fs.openSync("lib/jsdoc-parse.js", "r");
    var outputFile = fs.openSync("tmp/jsdoc-parse.json", "w");
    var handle = spawn("jsdoc-parse", [], { stdio: [ inputFile, outputFile, process.stderr ]});
    handle.on("close", function(){
        var data = fs.readFileSync("tmp/jsdoc-parse.json", "utf8");
        t.ok(/longname/.test(data));
    });
});
<commit_msg>stdin test added<commit_after>var test = require("tape");
var parse = require("../");
var spawn = require("child_process").spawn;
var fs = require("fs");

try{
    fs.mkdirSync("tmp");
} catch(err){
    // dir exists
}

test("valid json out", function(t){
    t.plan(1);
    var stream = parse("lib/jsdoc-parse.js");
    stream.on("readable", function(){
        var chunk = this.read();
        if (chunk){
            var data = JSON.parse(chunk);
            t.equal(data[0].name, "jsdoc-parse");
        }
    });
});

test("stdin input working", function(t){
    t.plan(1);
    var inputFile = fs.openSync("lib/jsdoc-parse.js", "r");
    var outputFile = fs.openSync("tmp/jsdoc-parse.json", "w");
    var handle = spawn("node", [ "bin/cli.js"], { stdio: [ inputFile, outputFile, process.stderr ]});
    handle.on("close", function(){
        var data = fs.readFileSync("tmp/jsdoc-parse.json", "utf8");
        t.ok(/longname/.test(data));
    });
});
<|endoftext|>