<commit_before>const Broker = require('./index')
const { secureRandom, createConnection } = require('testHelpers')

describe('Broker > Metadata', () => {
  let topicName, broker

  beforeEach(() => {
    topicName = `test-topic-${secureRandom()}`
    broker = new Broker(createConnection())
  })

  afterEach(async () => {
    broker && (await broker.disconnect())
  })

  test('rejects the Promise if lookupRequest is not defined', async () => {
    await expect(broker.metadata()).rejects.toEqual(new Error('Broker not connected'))
  })

  test('request', async () => {
    await broker.connect()
    const response = await broker.metadata([topicName])
    expect(response).toEqual({
      brokers: [
        {
          host: expect.stringMatching(/\d+\.\d+\.\d+\.\d+/),
          nodeId: expect.any(Number),
          port: expect.any(Number),
          rack: null,
        },
        {
          host: expect.stringMatching(/\d+\.\d+\.\d+\.\d+/),
          nodeId: expect.any(Number),
          port: expect.any(Number),
          rack: null,
        },
        {
          host: expect.stringMatching(/\d+\.\d+\.\d+\.\d+/),
          nodeId: expect.any(Number),
          port: expect.any(Number),
          rack: null,
        },
      ],
      clusterId: expect.stringMatching(/[a-zA-Z0-9-]/),
      controllerId: expect.any(Number),
      topicMetadata: [
        {
          isInternal: false,
          partitionMetadata: [
            {
              isr: expect.any(Array),
              leader: expect.any(Number),
              partitionErrorCode: 0,
              partitionId: 0,
              replicas: expect.any(Array),
            },
          ],
          topic: topicName,
          topicErrorCode: 0,
        },
      ],
    })
  })
})
<commit_msg>Fix broker metadata test<commit_after>const Broker = require('./index')
const { secureRandom, createConnection } = require('testHelpers')

describe('Broker > Metadata', () => {
  let topicName, broker

  beforeEach(() => {
    topicName = `test-topic-${secureRandom()}`
    broker = new Broker(createConnection())
  })

  afterEach(async () => {
    broker && (await broker.disconnect())
  })

  test('rejects the Promise if lookupRequest is not defined', async () => {
    await expect(broker.metadata()).rejects.toEqual(new Error('Broker not connected'))
  })

  test('request', async () => {
    await broker.connect()
    const response = await broker.metadata([topicName])

    expect(response).toMatchObject({
      brokers: expect.arrayContaining([
        {
          host: expect.stringMatching(/\d+\.\d+\.\d+\.\d+/),
          nodeId: expect.any(Number),
          port: expect.any(Number),
          rack: null,
        },
      ]),
      clusterId: expect.stringMatching(/[a-zA-Z0-9-]/),
      controllerId: expect.any(Number),
      topicMetadata: [
        {
          isInternal: false,
          partitionMetadata: [
            {
              isr: expect.any(Array),
              leader: expect.any(Number),
              partitionErrorCode: 0,
              partitionId: 0,
              replicas: expect.any(Array),
            },
          ],
          topic: topicName,
          topicErrorCode: 0,
        },
      ],
    })
  })
})
<|endoftext|>


<commit_before>var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var HtmlMultiplePlugin = require('./HtmlMultiplePlugin')
module.exports = {
    //context: __dirname,
    entry: {
        "welcome": ['webpack-dev-server/client?http://localhost:8080/', 'webpack/hot/dev-server', './src/client/welcome/index.js'],
        "moduletwo": ['webpack-dev-server/client?http://localhost:8080/', 'webpack/hot/dev-server', './src/client/moduletwo/index.js'],
    },

    output: {
        path: path.resolve(__dirname, '..', 'dist'),
        filename: '[name]/[name]-[hash].js',
        publicPath: 'http://localhost:1234/'
    },

    module: {
        loaders: [
            {
                test: /\.(js|jsx)$/,
                loaders: ['babel',
                    'custom-loader'
                ],
                include: path.resolve(__dirname, '..', 'src', 'client'),
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                loader: 'style!css'
            }
        ]
    },
    resolveLoader: {
        alias: {
            "custom-loader": path.join(__dirname, "./hmr")
        }
    },
    devServer: {
        hot: true,
        //quiet: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new HtmlMultiplePlugin()
        // new HtmlWebpackPlugin({
        //     template: path.resolve(__dirname, 'public', 'index.html')
        // })
    ]
}<commit_msg>Made webpack config to run under same dir context<commit_after>var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var HtmlMultiplePlugin = require('./HtmlMultiplePlugin')
var getDevPaths = require('./GetEntryPoints').GetDevEntries
console.log('asd', __dirname)
module.exports = {
    context: __dirname,
    entry: getDevPaths(),
        output: {
        path: path.resolve(__dirname, '..', 'dist'),
        filename: '[name]/[name]-[hash].js',
        publicPath: 'http://localhost:1234/'
    },

    module: {
        loaders: [
            {
                test: /\.(js|jsx)$/,
                loaders: ['babel',
                    'custom-loader'
                ],
                include: path.resolve(__dirname, '..', 'src', 'client'),
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                loader: 'style!css'
            }
        ]
    },
    resolveLoader: {
        alias: {
            "custom-loader": path.join(__dirname, "./hmr")
        }
    },
    devServer: {
        hot: true,
        //quiet: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new HtmlMultiplePlugin()
        // new HtmlWebpackPlugin({
        //     template: path.resolve(__dirname, 'public', 'index.html')
        // })
    ]
}<|endoftext|>


<commit_before>window.c.AdminInputAction = (function(m, h, c){
  return {
    controller: function(args){
      var builder = args.data,
          complete = m.prop(false),
          error = m.prop(false),
          fail = m.prop(false),
          data = {},
          item = args.item,
          key = builder.getKey,
          newValue = m.prop(''),
          updateVM = m.postgrest.filtersVM({contribution_id: 'eq'});

      h.idVM.id(item[builder.updateKey]);
      updateVM.contribution_id(item.contribution_id);

      var l = m.postgrest.loaderWithToken(builder.model.patchOptions(h.idVM.parameters(), data));

      var updateItem = function(data){
        _.extend(item, data[0]);
        complete(true);
      };

      var submit = function(){
        data[key] = newValue();
        l.load().then(updateItem, error);
        return false;
      };

      var unload = function(el, isinit, context){
        context.onunload = function(){
          complete(false);
          newValue('');
        };
      };

      return {
        complete: complete,
        error: error,
        l: l,
        newValue: newValue,
        submit: submit,
        toggler: h.toggleProp(false, true),
        unload: unload
      };
    },
    view: function(ctrl, args){
      var data = args.data,
          btnValue = (ctrl.l()) ? 'por favor, aguarde...' : data.callToAction;

      return m('.w-col.w-col-2',[
        m('button.btn.btn-small.btn-terciary', {
          onclick: ctrl.toggler.toggle
        }, data.outerLabel),
        (ctrl.toggler()) ?
          m('.dropdown-list.card.u-radius.dropdown-list-medium.zindex-10', {config: ctrl.unload},[
            m('form.w-form', {
              onsubmit: ctrl.submit
            }, (!ctrl.complete()) ? [
                  m('label', data.innerLabel),
                  m('input.w-input.text-field[type="text"][placeholder="' + data.placeholder + '"]', {onchange: m.withAttr('value', ctrl.newValue), value: ctrl.newValue()}),
                  m('input.w-button.btn.btn-small[type="submit"][value="' + btnValue + '"]')
                ] : (!ctrl.error()) ? [
                    m('.w-form-done[style="display:block;"]', [
                      m('p', 'Apoio transferido com sucesso!')
                    ])
                  ] : [
                    m('.w-form-error[style="display:block;"]', [
                      m('p', 'Houve um problema na requisição. O apoio não foi transferido!')
                    ])
                  ]
            )
          ])
        : ''
      ]);
    }
  };
}(window.m, window.c.h, window.c));
<commit_msg>Resets error on toggle and request done. Changes response parameter name.<commit_after>window.c.AdminInputAction = (function(m, h, c){
  return {
    controller: function(args){
      var builder = args.data,
          complete = m.prop(false),
          error = m.prop(false),
          fail = m.prop(false),
          data = {},
          item = args.item,
          key = builder.getKey,
          newValue = m.prop(''),
          updateVM = m.postgrest.filtersVM({contribution_id: 'eq'});

      h.idVM.id(item[builder.updateKey]);
      updateVM.contribution_id(item.contribution_id);

      var l = m.postgrest.loaderWithToken(builder.model.patchOptions(h.idVM.parameters(), data));

      var updateItem = function(res){
        _.extend(item, res[0]);
        complete(true);
        error(false);
      };

      var submit = function(){
        data[key] = newValue();
        l.load().then(updateItem, error);
        return false;
      };

      var unload = function(el, isinit, context){
        context.onunload = function(){
          complete(false);
          error(false);
          newValue('');
        };
      };

      return {
        complete: complete,
        error: error,
        l: l,
        newValue: newValue,
        submit: submit,
        toggler: h.toggleProp(false, true),
        unload: unload
      };
    },
    view: function(ctrl, args){
      var data = args.data,
          btnValue = (ctrl.l()) ? 'por favor, aguarde...' : data.callToAction;

      return m('.w-col.w-col-2',[
        m('button.btn.btn-small.btn-terciary', {
          onclick: ctrl.toggler.toggle
        }, data.outerLabel),
        (ctrl.toggler()) ?
          m('.dropdown-list.card.u-radius.dropdown-list-medium.zindex-10', {config: ctrl.unload},[
            m('form.w-form', {
              onsubmit: ctrl.submit
            }, (!ctrl.complete()) ? [
                  m('label', data.innerLabel),
                  m('input.w-input.text-field[type="text"][placeholder="' + data.placeholder + '"]', {onchange: m.withAttr('value', ctrl.newValue), value: ctrl.newValue()}),
                  m('input.w-button.btn.btn-small[type="submit"][value="' + btnValue + '"]')
                ] : (!ctrl.error()) ? [
                    m('.w-form-done[style="display:block;"]', [
                      m('p', 'Apoio transferido com sucesso!')
                    ])
                  ] : [
                    m('.w-form-error[style="display:block;"]', [
                      m('p', 'Houve um problema na requisição. O apoio não foi transferido!')
                    ])
                  ]
            )
          ])
        : ''
      ]);
    }
  };
}(window.m, window.c.h, window.c));
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var CardboardDistorter = require('./cardboard-distorter.js');
var CardboardUI = require('./cardboard-ui.js');
var DeviceInfo = require('./device-info.js');
var Dpdb = require('./dpdb/dpdb.js');
var FusionPoseSensor = require('./sensor-fusion/fusion-pose-sensor.js');
var RotateInstructions = require('./rotate-instructions.js');
var ViewerSelector = require('./viewer-selector.js');
var VRDisplay = require('./base.js').VRDisplay;
var Util = require('./util.js');

var Eye = {
  LEFT: 'left',
  RIGHT: 'right'
};

/**
 * VRDisplay based on mobile device parameters and DeviceMotion APIs.
 */
function CardboardVRDisplay() {
  this.displayName = 'Cardboard VRDisplay (webvr-polyfill)';

  this.capabilities.hasOrientation = true;
  this.capabilities.canPresent = true;

  // "Private" members.
  this.bufferScale_ = WebVRConfig.BUFFER_SCALE;
  this.poseSensor_ = new FusionPoseSensor();
  this.distorter_ = null;
  this.cardboardUI_ = null;

  this.dpdb_ = new Dpdb(true, this.onDeviceParamsUpdated_.bind(this));
  this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams());

  this.viewerSelector_ = new ViewerSelector();
  this.viewerSelector_.on('change', this.onViewerChanged_.bind(this));

  // Set the correct initial viewer.
  this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer());

  if (!WebVRConfig.ROTATE_INSTRUCTIONS_DISABLED) {
    this.rotateInstructions_ = new RotateInstructions();
  }
}
CardboardVRDisplay.prototype = new VRDisplay();

CardboardVRDisplay.prototype.getImmediatePose = function() {
  return {
    position: this.poseSensor_.getPosition(),
    orientation: this.poseSensor_.getOrientation(),
    linearVelocity: null,
    linearAcceleration: null,
    angularVelocity: null,
    angularAcceleration: null
  };
};

CardboardVRDisplay.prototype.resetPose = function() {
  this.poseSensor_.resetPose();
};

CardboardVRDisplay.prototype.getEyeParameters = function(whichEye) {
  var offset = [this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0];
  var fieldOfView;

  // TODO: FoV can be a little expensive to compute. Cache when device params change.
  if (whichEye == Eye.LEFT) {
    offset[0] *= -1.0;
    fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye();
  } else if (whichEye == Eye.RIGHT) {
    fieldOfView = this.deviceInfo_.getFieldOfViewRightEye();
  } else {
    console.error('Invalid eye provided: %s', whichEye);
    return null;
  }

  return {
    fieldOfView: fieldOfView,
    offset: offset,
    // TODO: Should be able to provide better values than these.
    renderWidth: this.deviceInfo_.device.width * 0.5 * this.bufferScale_,
    renderHeight: this.deviceInfo_.device.height * this.bufferScale_,
  };
};

CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function(newParams) {
  console.log('DPDB reported that device params were updated.');
  this.deviceInfo_.updateDeviceParams(newParams);

  if (this.distorter_) {
    this.distorter.updateDeviceInfo(this.deviceInfo_);
  }
};

CardboardVRDisplay.prototype.beginPresent_ = function() {
  var gl = this.layer_.source.getContext('webgl');
  if (!gl)
    gl = this.layer_.source.getContext('experimental-webgl');
  if (!gl)
    gl = this.layer_.source.getContext('webgl2');

  if (!gl)
    return; // Can't do distortion without a WebGL context.

  // Provides a way to opt out of distortion
  if (this.layer_.predistorted) {
    if (!WebVRConfig.CARDBOARD_UI_DISABLED) {
      gl.canvas.width = Util.getScreenWidth() * this.bufferScale_;
      gl.canvas.height = Util.getScreenHeight() * this.bufferScale_;
      this.cardboardUI_ = new CardboardUI(gl);
    }
  } else {
    // Create a new distorter for the target context
    this.distorter_ = new CardboardDistorter(gl);
    this.distorter_.updateDeviceInfo(this.deviceInfo_);
    this.cardboardUI_ = this.distorter_.cardboardUI;

    if (this.layer_.leftBounds || this.layer_.rightBounds) {
      this.distorter_.setTextureBounds(this.layer_.leftBounds, this.layer_.rightBounds);
    }
  }

  if (this.cardboardUI_) {
    this.cardboardUI_.listen(function(e) {
      // Options clicked.
      this.viewerSelector_.show(this.layer_.source.parentElement);
      e.stopPropagation();
      e.preventDefault();
    }.bind(this), function(e) {
      // Back clicked.
      this.exitPresent();
      e.stopPropagation();
      e.preventDefault();
    }.bind(this));
  }

  if (this.rotateInstructions_) {
    if (Util.isLandscapeMode() && Util.isMobile()) {
      // In landscape mode, temporarily show the "put into Cardboard"
      // interstitial. Otherwise, do the default thing.
      this.rotateInstructions_.showTemporarily(3000, this.layer_.source.parentElement);
    } else {
      this.rotateInstructions_.update();
    }
  }

  // Listen for orientation change events in order to show interstitial.
  this.orientationHandler = this.onOrientationChange_.bind(this);
  window.addEventListener('orientationchange', this.orientationHandler);

  // Fire this event initially, to give geometry-distortion clients the chance
  // to do something custom.
  this.fireVRDisplayDeviceParamsChange_();
};

CardboardVRDisplay.prototype.endPresent_ = function() {
  if (this.distorter_) {
    this.distorter_.destroy();
    this.distorter_ = null;
  }
  if (this.cardboardUI_) {
    this.cardboardUI_.destroy();
    this.cardboardUI_ = null;
  }

  if (this.rotateInstructions_) {
    this.rotateInstructions_.hide();
  }
  this.viewerSelector_.hide();

  window.removeEventListener('orientationchange', this.orientationHandler);
};

CardboardVRDisplay.prototype.submitFrame = function(pose) {
  if (this.distorter_) {
    this.distorter_.submitFrame();
  } else if (this.cardboardUI_) {
    this.cardboardUI_.render();
  }
};

CardboardVRDisplay.prototype.onOrientationChange_ = function(e) {
  console.log('onOrientationChange_');

  // Hide the viewer selector.
  this.viewerSelector_.hide();

  // Update the rotate instructions.
  if (this.rotateInstructions_) {
    this.rotateInstructions_.update();
  }

  // iOS workaround (for https://bugs.webkit.org/show_bug.cgi?id=152556).
  if (Util.isIOS()) {
    var gl = this.layer_.source.getContext('webgl');
    var canvas = gl.canvas;

    // TODO(smus): Remove this workaround when Safari for iOS is fixed.
    var width = canvas.style.width;
    canvas.style.width = 0;
    setTimeout(function() {
      canvas.style.width = width;
    }, 100);
  }
};

CardboardVRDisplay.prototype.onViewerChanged_ = function(viewer) {
  this.deviceInfo_.setViewer(viewer);

  if (this.distorter_) {
    // Update the distortion appropriately.
    this.distorter_.updateDeviceInfo(this.deviceInfo_);
  }

  // Fire a new event containing viewer and device parameters for clients that
  // want to implement their own geometry-based distortion.
  this.fireVRDisplayDeviceParamsChange_();
};

CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = function() {
  var event = new CustomEvent('vrdisplaydeviceparamschange', {
    detail: {
      vrdisplay: this,
      deviceInfo: this.deviceInfo_,
    }
  });
  window.dispatchEvent(event);
};

module.exports = CardboardVRDisplay;
<commit_msg>Hack for ensuring the UI is at the right scale.<commit_after>/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var CardboardDistorter = require('./cardboard-distorter.js');
var CardboardUI = require('./cardboard-ui.js');
var DeviceInfo = require('./device-info.js');
var Dpdb = require('./dpdb/dpdb.js');
var FusionPoseSensor = require('./sensor-fusion/fusion-pose-sensor.js');
var RotateInstructions = require('./rotate-instructions.js');
var ViewerSelector = require('./viewer-selector.js');
var VRDisplay = require('./base.js').VRDisplay;
var Util = require('./util.js');

var Eye = {
  LEFT: 'left',
  RIGHT: 'right'
};

/**
 * VRDisplay based on mobile device parameters and DeviceMotion APIs.
 */
function CardboardVRDisplay() {
  this.displayName = 'Cardboard VRDisplay (webvr-polyfill)';

  this.capabilities.hasOrientation = true;
  this.capabilities.canPresent = true;

  // "Private" members.
  this.bufferScale_ = WebVRConfig.BUFFER_SCALE;
  this.poseSensor_ = new FusionPoseSensor();
  this.distorter_ = null;
  this.cardboardUI_ = null;

  this.dpdb_ = new Dpdb(true, this.onDeviceParamsUpdated_.bind(this));
  this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams());

  this.viewerSelector_ = new ViewerSelector();
  this.viewerSelector_.on('change', this.onViewerChanged_.bind(this));

  // Set the correct initial viewer.
  this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer());

  if (!WebVRConfig.ROTATE_INSTRUCTIONS_DISABLED) {
    this.rotateInstructions_ = new RotateInstructions();
  }
}
CardboardVRDisplay.prototype = new VRDisplay();

CardboardVRDisplay.prototype.getImmediatePose = function() {
  return {
    position: this.poseSensor_.getPosition(),
    orientation: this.poseSensor_.getOrientation(),
    linearVelocity: null,
    linearAcceleration: null,
    angularVelocity: null,
    angularAcceleration: null
  };
};

CardboardVRDisplay.prototype.resetPose = function() {
  this.poseSensor_.resetPose();
};

CardboardVRDisplay.prototype.getEyeParameters = function(whichEye) {
  var offset = [this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0];
  var fieldOfView;

  // TODO: FoV can be a little expensive to compute. Cache when device params change.
  if (whichEye == Eye.LEFT) {
    offset[0] *= -1.0;
    fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye();
  } else if (whichEye == Eye.RIGHT) {
    fieldOfView = this.deviceInfo_.getFieldOfViewRightEye();
  } else {
    console.error('Invalid eye provided: %s', whichEye);
    return null;
  }

  return {
    fieldOfView: fieldOfView,
    offset: offset,
    // TODO: Should be able to provide better values than these.
    renderWidth: this.deviceInfo_.device.width * 0.5 * this.bufferScale_,
    renderHeight: this.deviceInfo_.device.height * this.bufferScale_,
  };
};

CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function(newParams) {
  console.log('DPDB reported that device params were updated.');
  this.deviceInfo_.updateDeviceParams(newParams);

  if (this.distorter_) {
    this.distorter.updateDeviceInfo(this.deviceInfo_);
  }
};

CardboardVRDisplay.prototype.beginPresent_ = function() {
  var gl = this.layer_.source.getContext('webgl');
  if (!gl)
    gl = this.layer_.source.getContext('experimental-webgl');
  if (!gl)
    gl = this.layer_.source.getContext('webgl2');

  if (!gl)
    return; // Can't do distortion without a WebGL context.

  // Provides a way to opt out of distortion
  if (this.layer_.predistorted) {
    if (!WebVRConfig.CARDBOARD_UI_DISABLED) {
      gl.canvas.width = Util.getScreenWidth() * this.bufferScale_;
      gl.canvas.height = Util.getScreenHeight() * this.bufferScale_;
      this.cardboardUI_ = new CardboardUI(gl);
    }
  } else {
    // Create a new distorter for the target context
    this.distorter_ = new CardboardDistorter(gl);
    this.distorter_.updateDeviceInfo(this.deviceInfo_);
    this.cardboardUI_ = this.distorter_.cardboardUI;

    if (this.layer_.leftBounds || this.layer_.rightBounds) {
      this.distorter_.setTextureBounds(this.layer_.leftBounds, this.layer_.rightBounds);
    }
  }

  if (this.cardboardUI_) {
    this.cardboardUI_.listen(function(e) {
      // Options clicked.
      this.viewerSelector_.show(this.layer_.source.parentElement);
      e.stopPropagation();
      e.preventDefault();
    }.bind(this), function(e) {
      // Back clicked.
      this.exitPresent();
      e.stopPropagation();
      e.preventDefault();
    }.bind(this));
  }

  if (this.rotateInstructions_) {
    if (Util.isLandscapeMode() && Util.isMobile()) {
      // In landscape mode, temporarily show the "put into Cardboard"
      // interstitial. Otherwise, do the default thing.
      this.rotateInstructions_.showTemporarily(3000, this.layer_.source.parentElement);
    } else {
      this.rotateInstructions_.update();
    }
  }

  // Listen for orientation change events in order to show interstitial.
  this.orientationHandler = this.onOrientationChange_.bind(this);
  window.addEventListener('orientationchange', this.orientationHandler);

  // Fire this event initially, to give geometry-distortion clients the chance
  // to do something custom.
  this.fireVRDisplayDeviceParamsChange_();
};

CardboardVRDisplay.prototype.endPresent_ = function() {
  if (this.distorter_) {
    this.distorter_.destroy();
    this.distorter_ = null;
  }
  if (this.cardboardUI_) {
    this.cardboardUI_.destroy();
    this.cardboardUI_ = null;
  }

  if (this.rotateInstructions_) {
    this.rotateInstructions_.hide();
  }
  this.viewerSelector_.hide();

  window.removeEventListener('orientationchange', this.orientationHandler);
};

CardboardVRDisplay.prototype.submitFrame = function(pose) {
  if (this.distorter_) {
    this.distorter_.submitFrame();
  } else if (this.cardboardUI_ && this.layer_) {
    // Hack for predistorted: true.
    var canvas = this.layer_.source.getContext('webgl').canvas;
    if (canvas.width != this.lastWidth || canvas.height != this.lastHeight) {
      this.cardboardUI_.onResize();
    }
    this.cardboardUI_.render();
    this.lastWidth = canvas.width;
    this.lastHeight = canvas.height;
  }
};

CardboardVRDisplay.prototype.onOrientationChange_ = function(e) {
  console.log('onOrientationChange_');

  // Hide the viewer selector.
  this.viewerSelector_.hide();

  // Update the rotate instructions.
  if (this.rotateInstructions_) {
    this.rotateInstructions_.update();
  }

  // iOS workaround (for https://bugs.webkit.org/show_bug.cgi?id=152556).
  if (Util.isIOS()) {
    var gl = this.layer_.source.getContext('webgl');
    var canvas = gl.canvas;

    // TODO(smus): Remove this workaround when Safari for iOS is fixed.
    var width = canvas.style.width;
    canvas.style.width = 0;
    setTimeout(function() {
      canvas.style.width = width;
    }, 100);
  }
};

CardboardVRDisplay.prototype.onViewerChanged_ = function(viewer) {
  this.deviceInfo_.setViewer(viewer);

  if (this.distorter_) {
    // Update the distortion appropriately.
    this.distorter_.updateDeviceInfo(this.deviceInfo_);
  }

  // Fire a new event containing viewer and device parameters for clients that
  // want to implement their own geometry-based distortion.
  this.fireVRDisplayDeviceParamsChange_();
};

CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = function() {
  var event = new CustomEvent('vrdisplaydeviceparamschange', {
    detail: {
      vrdisplay: this,
      deviceInfo: this.deviceInfo_,
    }
  });
  window.dispatchEvent(event);
};

module.exports = CardboardVRDisplay;
<|endoftext|>


<commit_before>const { errors } = require('arsenal');
const { metadataValidateBucket } = require('../metadata/metadataUtils');
const { pushMetric } = require('../utapi/utilities');
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
const ObjectLockConfiguration =
  require('arsenal').models.ObjectLockConfiguration;

// Format of the xml response:
/**
 *    <ObjectLockConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
 *        <ObjectLockEnabled>string</ObjectLockEnabled>
 *        <Rule>
 *            <DefaultRetention>
 *                <Mode>string</Mode>
 *                <Days>integer</Days>
 *                <Years>integer</Years>
 *            </DefaultRetention>
 *        </Rule>
 *    </ObjectLockConfiguration>
 */

/**
 * bucketGetObjectLock - Return object lock configuration for the bucket
 * @param {AuthInfo} authInfo - Instance of AuthInfo class with requester's info
 * @param {object} request - http request object
 * @param {object} log - Werelogs logger
 * @param {function} callback - callback to respond to http request
 * @return {undefined}
 */
function bucketGetObjectLock(authInfo, request, log, callback) {
    log.debug('processing request', { method: 'bucketGetObjectLock' });
    const { bucketName, headers, method } = request;
    const metadataValParams = {
        authInfo,
        bucketName,
        requestType: 'bucketGetObjectLock',
    };
    return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
        const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
        if (err) {
            log.debug('error processing request', {
                error: err,
                method: 'bucketGetObjectLock',
            });
            return callback(err, null, corsHeaders);
        }
        const objectLockEnabled = bucket._objectLockEnabled;
        const objectLockConfig = bucket._objectLockConfiguration ?
            bucket._objectLockConfiguration :
            {};
        if (!objectLockEnabled) {
            log.debug('object lock is not enabled', {
                error: errors.ObjectLockConfigurationNotFoundError,
                method: 'bucketGetObjectLock',
            });
            return callback(errors.ObjectLockConfigurationNotFoundError, null,
                corsHeaders);
        }
        const xml = ObjectLockConfiguration.getConfigXML(objectLockConfig);
        pushMetric('getBucketObjectLock', log, {
            authInfo,
            bucket: bucketName,
        });
        return callback(null, xml, corsHeaders);
    });
}

module.exports = bucketGetObjectLock;
<commit_msg>improvement: S3C-3120 bucket get object lock use setter<commit_after>const { errors } = require('arsenal');
const { metadataValidateBucket } = require('../metadata/metadataUtils');
const { pushMetric } = require('../utapi/utilities');
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
const ObjectLockConfiguration =
  require('arsenal').models.ObjectLockConfiguration;

// Format of the xml response:
/**
 *    <ObjectLockConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
 *        <ObjectLockEnabled>string</ObjectLockEnabled>
 *        <Rule>
 *            <DefaultRetention>
 *                <Mode>string</Mode>
 *                <Days>integer</Days>
 *                <Years>integer</Years>
 *            </DefaultRetention>
 *        </Rule>
 *    </ObjectLockConfiguration>
 */

/**
 * bucketGetObjectLock - Return object lock configuration for the bucket
 * @param {AuthInfo} authInfo - Instance of AuthInfo class with requester's info
 * @param {object} request - http request object
 * @param {object} log - Werelogs logger
 * @param {function} callback - callback to respond to http request
 * @return {undefined}
 */
function bucketGetObjectLock(authInfo, request, log, callback) {
    log.debug('processing request', { method: 'bucketGetObjectLock' });
    const { bucketName, headers, method } = request;
    const metadataValParams = {
        authInfo,
        bucketName,
        requestType: 'bucketGetObjectLock',
    };
    return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
        const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
        if (err) {
            log.debug('error processing request', {
                error: err,
                method: 'bucketGetObjectLock',
            });
            return callback(err, null, corsHeaders);
        }
        const objectLockEnabled = bucket.isObjectLockEnabled();
        const bucketObjLockConfig = bucket.getObjectLockConfiguration();
        const objLockConfig = bucketObjLockConfig || {};
        if (!objectLockEnabled) {
            log.debug('object lock is not enabled', {
                error: errors.ObjectLockConfigurationNotFoundError,
                method: 'bucketGetObjectLock',
            });
            return callback(errors.ObjectLockConfigurationNotFoundError, null,
                corsHeaders);
        }
        const xml = ObjectLockConfiguration.getConfigXML(objLockConfig);
        pushMetric('getBucketObjectLock', log, {
            authInfo,
            bucket: bucketName,
        });
        return callback(null, xml, corsHeaders);
    });
}

module.exports = bucketGetObjectLock;
<|endoftext|>


<commit_before>var multiParty = function() {};
(function(){

var publicKeys = {};
var sharedSecrets = {};
var fingerprints = {};
var myPrivateKey;
var myPublicKey;

multiParty.requestRegEx = /^\?:3multiParty:3\?:keyRequest$/;
multiParty.publicKeyRegEx = /^\?:3multiParty:3\?:publicKey:(\w|=)+$/;

// AES-CTR-256 encryption
// No padding, starting IV of 0
// Input: UTF8, Output: Base64
// Key input: hexademical
encryptAES = function(msg, c, iv) {
	var opts = {
		mode: CryptoJS.mode.CTR,
		iv: CryptoJS.enc.Base64.parse(iv),
		padding: CryptoJS.pad.NoPadding
	}
	var aesctr = CryptoJS.AES.encrypt (
		CryptoJS.enc.Utf8.parse(msg),
		CryptoJS.enc.Hex.parse(c),
		opts
	)
	return aesctr.toString();
}

// AES-CTR-256 decryption
// No padding, starting IV of 0
// Input: Base64, Output: UTF8
// Key input: hexadecimal
decryptAES = function(msg, c, iv) {
	msg = CryptoJS.enc.Base64.parse(msg);
	var opts = {
		mode: CryptoJS.mode.CTR,
		iv: CryptoJS.enc.Base64.parse(iv),
		padding: CryptoJS.pad.NoPadding
	}
	var aesctr = CryptoJS.AES.decrypt(
		CryptoJS.enc.Base64.stringify(msg),
		CryptoJS.enc.Hex.parse(c),
		opts
	)
	return aesctr.toString(CryptoJS.enc.Utf8);
}

// HMAC-SHA512
// Output: Base64
// Key input: Hexademical
HMAC = function (msg, key) {
	return CryptoJS.HmacSHA512(
		msg, CryptoJS.enc.Hex.parse(key)
	).toString(CryptoJS.enc.Base64);
}

// Check if received public key is within safe size parameters
checkSize = function(publicKey) {
	var z = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4096, 0];
	publicKey = BigInt.str2bigInt(publicKey, 64);
	if ((BigInt.equals(publicKey, Curve25519.p25519)
		|| BigInt.greater(publicKey, Curve25519.p25519)
		|| BigInt.greater(z, publicKey))) {
		console.log('multiParty: unsafe key size');
		return false;
	}
	else {
		return true;
	}
}

// Generate private key (32 byte random number)
// Represented in decimal
multiParty.genPrivateKey = function() {
	myPrivateKey = Cryptocat.randomString(32, 0, 0, 1);
	return myPrivateKey;
}

// Set a previously generated private key (32 byte random number)
// Represented in decimal
multiParty.setPrivateKey = function(privateKey) {
	myPrivateKey = privateKey;
}

// Generate public key (Curve 25519 Diffie-Hellman with basePoint 9)
// Represented in Base64
multiParty.genPublicKey = function() {
	myPublicKey = BigInt.bigInt2str(Curve25519.ecDH(myPrivateKey), 64);
	return myPublicKey;
}

// Generate shared secrets
// First 256 bytes are for encryption, last 256 bytes are for HMAC.
// Represented in hexadecimal
multiParty.genSharedSecret = function(user) {
	sharedSecret = CryptoJS.SHA512(
		Curve25519.ecDH(
			myPrivateKey, BigInt.str2bigInt(
				publicKeys[user], 64
			)
		)
	).toString();
	sharedSecrets[user] = {
		'message': sharedSecret.substring(0, 64),
		'hmac': sharedSecret.substring(64, 128)
	}
	// console.log(sharedSecrets);
}

// Get fingerprint fingerprint
// If user is null, returns own fingerprint
multiParty.genFingerprint = function(user) {
	if (!user) {
		var key = myPublicKey;
	}
	else {
		var key = publicKeys[user];
	}
	return fingerprints[user] = CryptoJS.SHA512(key)
		.toString()
		.substring(0, 40)
		.toUpperCase();
}

// Send public key request string.
multiParty.sendPublicKeyRequest = function(user) {
	var request = {};
	request['text'][user] = {};
	request['text'][user]['message'] = '?:3multiParty:3?:keyRequest';
	return JSON.stringify(request);
}

// Send my public key in response to a public key request.
multiParty.sendPublicKey = function(user) {
	var answer = {};
	answer['text'] = {}
	answer['text'][user] = {};
	answer['text'][user]['message'] = '?:3multiParty:3?:publicKey:' + myPublicKey;
	return JSON.stringify(answer);
}

// Return number of users
multiParty.userCount = function() {
	return Object.keys(sharedSecrets).length;
}

// Generate messasge hash
multiParty.messageHash = function(message) {
	for (var i = 0; i !== 32; i++) {
		message = CryptoJS.SHA512(message);
	}
	return message.toString(CryptoJS.enc.Base64);
}

// Send message.
multiParty.sendMessage = function(message) {
	message += Cryptocat.randomString(64, 1, 1, 1, 0);
	var encrypted = {};
	encrypted['text'] = {};
	encrypted['hash'] = message;
	var concatenatedCiphertext = '';
	var sortedRecipients = Object.keys(sharedSecrets).sort();
	for (var i = 0; i !== sortedRecipients.length; i++) {
		var iv = CryptoJS.enc.Hex.parse(Cryptocat.randomString(24, 0, 0, 0, 1)).toString(CryptoJS.enc.Base64);
		encrypted['text'][sortedRecipients[i]] = {};
		encrypted['text'][sortedRecipients[i]]['message'] = encryptAES(message, sharedSecrets[sortedRecipients[i]]['message'], iv);
		encrypted['text'][sortedRecipients[i]]['iv'] = iv;
		concatenatedCiphertext += encrypted['text'][sortedRecipients[i]]['message'] + encrypted['text'][sortedRecipients[i]]['iv'];
	}
	for (var i = 0; i !== sortedRecipients.length; i++) {
		encrypted['text'][sortedRecipients[i]]['hmac'] = HMAC(concatenatedCiphertext, sharedSecrets[sortedRecipients[i]]['hmac']);
		encrypted['hash'] += encrypted['text'][sortedRecipients[i]]['hmac'];
	}
	encrypted['hash'] = multiParty.messageHash(encrypted['hash']);
	// console.log(encrypted);
	return JSON.stringify(encrypted);
}

// Receive message. Detects requests/reception of public keys.
multiParty.receiveMessage = function(sender, myName, message) {
	try {
		message = JSON.parse(message);
	}
	catch(err) {
		console.log('multiParty: failed to parse message object');
		return false;
	}
	if (typeof(message['text'][myName]) === 'object' &&
		typeof(message['text'][myName]['message']) === 'string') {
		// Detect public key reception, store public key and generate shared secret
		if (message['text'][myName]['message'].match(multiParty.publicKeyRegEx)) {
			if (!publicKeys.hasOwnProperty(sender)) {
				var publicKey = message['text'][myName]['message'].substring(27);
				if (checkSize(publicKey)) {
					publicKeys[sender] = publicKey;
					multiParty.genFingerprint(sender);
					multiParty.genSharedSecret(sender);
				}
			}
			return false;
		}
		// Detect public key request and send public key
		else if (message['text'][myName]['message'].match(multiParty.requestRegEx)) {
			multiParty.sendPublicKey(sender);
		}
		// Decrypt message
		else if (sharedSecrets.hasOwnProperty(sender)) {
			// console.log(message);
			var concatenatedCiphertext = '';
			var sortedRecipients = Object.keys(message['text']).sort();
			for (var i = 0; i !== sortedRecipients.length; i++) {
				concatenatedCiphertext += message['text'][sortedRecipients[i]]['message'] + message['text'][sortedRecipients[i]]['iv'];
			}
			if (message['text'][myName]['hmac'] === HMAC(concatenatedCiphertext, sharedSecrets[sender]['hmac'])) {
				var plaintext = decryptAES(message['text'][myName]['message'], sharedSecrets[sender]['message'], message['text'][myName]['iv']);
				var messageHash = plaintext;
				for (var i = 0; i !== sortedRecipients.length; i++) {
					messageHash += message['text'][sortedRecipients[i]]['hmac'];
				}
				if (multiParty.messageHash(messageHash) === message['hash']) {
					return plaintext.substring(0, plaintext.length - 64);
				}
				else {
					console.log('multiParty: message hash failure');
					return false;
				}
			}
			else {
				console.log('multiParty: HMAC failure');
				return false;
			}
		}
	}
	return false;
}

// Rename keys (useful in case of nickname change)
multiParty.renameKeys = function(oldName, newName) {
	publicKeys[newName] = publicKeys[oldName];
	sharedSecrets[newName] = sharedSecrets[oldName];
	multiParty.genFingerprint(newName);
	multiParty.removeKeys(oldName);
}

// Remove user keys and information
multiParty.removeKeys = function(user) {
	delete publicKeys[user];
	delete sharedSecrets[user];
	delete fingerprints[user];
}

// Remove ALL user keys and information
multiParty.resetKeys = function() {
	publicKeys = {};
	sharedSecrets = {};
	fingerprints = {};
}

})();//:3<commit_msg>Add error<commit_after>var multiParty = function() {};
(function(){

var publicKeys = {};
var sharedSecrets = {};
var fingerprints = {};
var myPrivateKey;
var myPublicKey;

multiParty.requestRegEx = /^\?:3multiParty:3\?:keyRequest$/;
multiParty.publicKeyRegEx = /^\?:3multiParty:3\?:publicKey:(\w|=)+$/;

// AES-CTR-256 encryption
// No padding, starting IV of 0
// Input: UTF8, Output: Base64
// Key input: hexademical
encryptAES = function(msg, c, iv) {
	var opts = {
		mode: CryptoJS.mode.CTR,
		iv: CryptoJS.enc.Base64.parse(iv),
		padding: CryptoJS.pad.NoPadding
	}
	var aesctr = CryptoJS.AES.encrypt (
		CryptoJS.enc.Utf8.parse(msg),
		CryptoJS.enc.Hex.parse(c),
		opts
	)
	return aesctr.toString();
}

// AES-CTR-256 decryption
// No padding, starting IV of 0
// Input: Base64, Output: UTF8
// Key input: hexadecimal
decryptAES = function(msg, c, iv) {
	msg = CryptoJS.enc.Base64.parse(msg);
	var opts = {
		mode: CryptoJS.mode.CTR,
		iv: CryptoJS.enc.Base64.parse(iv),
		padding: CryptoJS.pad.NoPadding
	}
	var aesctr = CryptoJS.AES.decrypt(
		CryptoJS.enc.Base64.stringify(msg),
		CryptoJS.enc.Hex.parse(c),
		opts
	)
	return aesctr.toString(CryptoJS.enc.Utf8);
}

// HMAC-SHA512
// Output: Base64
// Key input: Hexademical
HMAC = function (msg, key) {
	return CryptoJS.HmacSHA512(
		msg, CryptoJS.enc.Hex.parse(key)
	).toString(CryptoJS.enc.Base64);
}

// Check if received public key is within safe size parameters
checkSize = function(publicKey) {
	var z = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4096, 0];
	publicKey = BigInt.str2bigInt(publicKey, 64);
	if ((BigInt.equals(publicKey, Curve25519.p25519)
		|| BigInt.greater(publicKey, Curve25519.p25519)
		|| BigInt.greater(z, publicKey))) {
		console.log('multiParty: unsafe key size');
		return false;
	}
	else {
		return true;
	}
}

// Generate private key (32 byte random number)
// Represented in decimal
multiParty.genPrivateKey = function() {
	myPrivateKey = Cryptocat.randomString(32, 0, 0, 1);
	return myPrivateKey;
}

// Set a previously generated private key (32 byte random number)
// Represented in decimal
multiParty.setPrivateKey = function(privateKey) {
	myPrivateKey = privateKey;
}

// Generate public key (Curve 25519 Diffie-Hellman with basePoint 9)
// Represented in Base64
multiParty.genPublicKey = function() {
	myPublicKey = BigInt.bigInt2str(Curve25519.ecDH(myPrivateKey), 64);
	return myPublicKey;
}

// Generate shared secrets
// First 256 bytes are for encryption, last 256 bytes are for HMAC.
// Represented in hexadecimal
multiParty.genSharedSecret = function(user) {
	sharedSecret = CryptoJS.SHA512(
		Curve25519.ecDH(
			myPrivateKey, BigInt.str2bigInt(
				publicKeys[user], 64
			)
		)
	).toString();
	sharedSecrets[user] = {
		'message': sharedSecret.substring(0, 64),
		'hmac': sharedSecret.substring(64, 128)
	}
	// console.log(sharedSecrets);
}

// Get fingerprint fingerprint
// If user is null, returns own fingerprint
multiParty.genFingerprint = function(user) {
	if (!user) {
		var key = myPublicKey;
	}
	else {
		var key = publicKeys[user];
	}
	return fingerprints[user] = CryptoJS.SHA512(key)
		.toString()
		.substring(0, 40)
		.toUpperCase();
}

// Send public key request string.
multiParty.sendPublicKeyRequest = function(user) {
	var request = {};
	request['text'][user] = {};
	request['text'][user]['message'] = '?:3multiParty:3?:keyRequest';
	return JSON.stringify(request);
}

// Send my public key in response to a public key request.
multiParty.sendPublicKey = function(user) {
	var answer = {};
	answer['text'] = {}
	answer['text'][user] = {};
	answer['text'][user]['message'] = '?:3multiParty:3?:publicKey:' + myPublicKey;
	return JSON.stringify(answer);
}

// Return number of users
multiParty.userCount = function() {
	return Object.keys(sharedSecrets).length;
}

// Generate messasge hash
multiParty.messageHash = function(message) {
	for (var i = 0; i !== 32; i++) {
		message = CryptoJS.SHA512(message);
	}
	return message.toString(CryptoJS.enc.Base64);
}

// Send message.
multiParty.sendMessage = function(message) {
	message += Cryptocat.randomString(64, 1, 1, 1, 0);
	var encrypted = {};
	encrypted['text'] = {};
	encrypted['hash'] = message;
	var concatenatedCiphertext = '';
	var sortedRecipients = Object.keys(sharedSecrets).sort();
	for (var i = 0; i !== sortedRecipients.length; i++) {
		var iv = CryptoJS.enc.Hex.parse(Cryptocat.randomString(24, 0, 0, 0, 1)).toString(CryptoJS.enc.Base64);
		encrypted['text'][sortedRecipients[i]] = {};
		encrypted['text'][sortedRecipients[i]]['message'] = encryptAES(message, sharedSecrets[sortedRecipients[i]]['message'], iv);
		encrypted['text'][sortedRecipients[i]]['iv'] = iv;
		concatenatedCiphertext += encrypted['text'][sortedRecipients[i]]['message'] + encrypted['text'][sortedRecipients[i]]['iv'];
	}
	for (var i = 0; i !== sortedRecipients.length; i++) {
		encrypted['text'][sortedRecipients[i]]['hmac'] = HMAC(concatenatedCiphertext, sharedSecrets[sortedRecipients[i]]['hmac']);
		encrypted['hash'] += encrypted['text'][sortedRecipients[i]]['hmac'];
	}
	encrypted['hash'] = multiParty.messageHash(encrypted['hash']);
	// console.log(encrypted);
	return JSON.stringify(encrypted);
}

// Receive message. Detects requests/reception of public keys.
multiParty.receiveMessage = function(sender, myName, message) {
	try {
		message = JSON.parse(message);
	}
	catch(err) {
		console.log('multiParty: failed to parse message object');
		return false;
	}
	if (typeof(message['text'][myName]) === 'object' &&
		typeof(message['text'][myName]['message']) === 'string') {
		// Detect public key reception, store public key and generate shared secret
		if (message['text'][myName]['message'].match(multiParty.publicKeyRegEx)) {
			if (!publicKeys.hasOwnProperty(sender)) {
				var publicKey = message['text'][myName]['message'].substring(27);
				if (checkSize(publicKey)) {
					publicKeys[sender] = publicKey;
					multiParty.genFingerprint(sender);
					multiParty.genSharedSecret(sender);
				}
			}
			return false;
		}
		// Detect public key request and send public key
		else if (message['text'][myName]['message'].match(multiParty.requestRegEx)) {
			multiParty.sendPublicKey(sender);
		}
		// Decrypt message
		else if (sharedSecrets.hasOwnProperty(sender)) {
			// console.log(message);
			var concatenatedCiphertext = '';
			var sortedRecipients = Object.keys(message['text']).sort();
			for (var i = 0; i !== sortedRecipients.length; i++) {
				concatenatedCiphertext += message['text'][sortedRecipients[i]]['message'] + message['text'][sortedRecipients[i]]['iv'];
			}
			if (message['text'][myName]['hmac'] === HMAC(concatenatedCiphertext, sharedSecrets[sender]['hmac'])) {
				var plaintext = decryptAES(message['text'][myName]['message'], sharedSecrets[sender]['message'], message['text'][myName]['iv']);
				var messageHash = plaintext;
				for (var i = 0; i !== sortedRecipients.length; i++) {
					messageHash += message['text'][sortedRecipients[i]]['hmac'];
				}
				if (multiParty.messageHash(messageHash) === message['hash']) {
					if (plaintext.length >= 64) {
						return plaintext.substring(0, plaintext.length - 64);
					}
					else {
						console.log('multiParty: invalid plaintext size');
						return false;
					}
				}
				else {
					console.log('multiParty: message hash failure');
					return false;
				}
			}
			else {
				console.log('multiParty: HMAC failure');
				return false;
			}
		}
	}
	return false;
}

// Rename keys (useful in case of nickname change)
multiParty.renameKeys = function(oldName, newName) {
	publicKeys[newName] = publicKeys[oldName];
	sharedSecrets[newName] = sharedSecrets[oldName];
	multiParty.genFingerprint(newName);
	multiParty.removeKeys(oldName);
}

// Remove user keys and information
multiParty.removeKeys = function(user) {
	delete publicKeys[user];
	delete sharedSecrets[user];
	delete fingerprints[user];
}

// Remove ALL user keys and information
multiParty.resetKeys = function() {
	publicKeys = {};
	sharedSecrets = {};
	fingerprints = {};
}

})();//:3<|endoftext|>


<commit_before>var Matcher = require('./matcher'),
    Server = require('./static'),
    url = require('url'),
    events = require('events'),
    util = require('util'),
    utils = require('./utils');

/**
 * Constructor Method
 */
var Card = module.exports = function Card(options) {

  if(!(this instanceof Card)) {
    return new Card(options);
  }

  this.options = options;
  this.router = {};
};

util.inherits(Card, events.EventEmitter);

/**
 * Main Routing Function
 *
 * @params
 * req {http.ServerRequest} - The server request object
 * res {http.ServerResponse} - The server response object
 *
 * Called from a Card's dispatch method. Responsible
 * for matching up a pathname to a Card's router. It will also
 * attempt to serve up a Card's static assets if a static directory
 * is set.
 */
Card.prototype.route = function route(req, res) {
  var self = this;

  if(this._static) {
    this._static.serve(req, res, function(err) {
      if(err) self.match(req, res);
    });
  }
  else {
    self.match(req, res);
  }
};

/**
 * Match Function
 *
 * @params
 * req {http.ServerRequest} - The server request object
 * res {http.ServerResponse} - The server response object
 *
 * Attempts to match a URL pathname to a route from the
 * route object. If found call the route function with
 * correct scope and parameters.
 */
Card.prototype.match = function match(req, res) {
  var self = this,
      uri = url.parse(req.url).pathname,
      path = utils.splice_path(uri, 2),
      routes = this.router[req.method.toLowerCase()];

  var matcher = new Matcher(path, routes);

  matcher.on('matched', function(obj) {
    obj.route.call(self, req, res, obj.params);
  });

  matcher.on('error', function(error) {
    res.writeHead(404, {'content-type': 'text/plain'});
    res.end(error.status.toString());
  });

  matcher.match();
};

/**
 * Set Static Directory
 *
 * @params
 * root {String} - a directory to use for serving files
 * options {Object} - any options available to node-static
 *
 * Sets a directory to serve static assets from. This allows
 * each card to have their own assets including stylesheets and
 * javascript files. Should meet the goal of having stand alone
 * cards that can function independently.
 */
Card.prototype.set_static = function set_static(root, options) {
  options = options || {};

  // root required
  if (!root) throw new Error('set_static() root path required');

  // clear out server instance if it exists
  if(this._static) delete this._static;

  this._static = new Server(root, options);
};

// Helper function for accessing slug property
Card.prototype.slug = function slug() {
  return this.slug || '';
};

// Helper function for accessing name property
Card.prototype.name = function name() {
  return this.name || '';
};<commit_msg>emit an error instead of rendering a response<commit_after>var Matcher = require('./matcher'),
    Server = require('./static'),
    url = require('url'),
    events = require('events'),
    util = require('util'),
    utils = require('./utils');

/**
 * Constructor Method
 */
var Card = module.exports = function Card(options) {

  if(!(this instanceof Card)) {
    return new Card(options);
  }

  this.options = options;
  this.router = {};
};

util.inherits(Card, events.EventEmitter);

/**
 * Main Routing Function
 *
 * @params
 * req {http.ServerRequest} - The server request object
 * res {http.ServerResponse} - The server response object
 *
 * Called from a Card's dispatch method. Responsible
 * for matching up a pathname to a Card's router. It will also
 * attempt to serve up a Card's static assets if a static directory
 * is set.
 */
Card.prototype.route = function route(req, res) {
  var self = this;

  if(this._static) {
    this._static.serve(req, res, function(err) {
      if(err) self.match(req, res);
    });
  }
  else {
    self.match(req, res);
  }
};

/**
 * Match Function
 *
 * @params
 * req {http.ServerRequest} - The server request object
 * res {http.ServerResponse} - The server response object
 *
 * Attempts to match a URL pathname to a route from the
 * route object. If found call the route function with
 * correct scope and parameters.
 */
Card.prototype.match = function match(req, res) {
  var self = this,
      uri = url.parse(req.url).pathname,
      path = utils.splice_path(uri, 2),
      routes = this.router[req.method.toLowerCase()];

  var matcher = new Matcher(path, routes);

  matcher.on('matched', function(obj) {
    obj.route.call(self, req, res, obj.params);
  });

  matcher.on('error', function(error) {
    self.emit('error', error);
  });

  matcher.match();
};

/**
 * Set Static Directory
 *
 * @params
 * root {String} - a directory to use for serving files
 * options {Object} - any options available to node-static
 *
 * Sets a directory to serve static assets from. This allows
 * each card to have their own assets including stylesheets and
 * javascript files. Should meet the goal of having stand alone
 * cards that can function independently.
 */
Card.prototype.set_static = function set_static(root, options) {
  options = options || {};

  // root required
  if (!root) throw new Error('set_static() root path required');

  // clear out server instance if it exists
  if(this._static) delete this._static;

  this._static = new Server(root, options);
};

// Helper function for accessing slug property
Card.prototype.slug = function slug() {
  return this.slug || '';
};

// Helper function for accessing name property
Card.prototype.name = function name() {
  return this.name || '';
};<|endoftext|>


<commit_before>const HEADINGS = new Set([
    'Added',
    'Updated',
    'Removed'
]);

function isUnreleased(node) {
    return node.type === 'heading' && HEADINGS.has(node.children[0].value) || node.type === 'list';
}

export default function () {
    return {
        command: 'release [version]',
        describe: 'Groups all your new features and marks a new release on your CHANGELOG.md.',
        handler(parser, argv, write) {
            if ( !parser.exists() ) {
                throw new Error('CHANGELOG.md does not exists. You can run: chan init in order to create a fresh new one.');
            }

            const version = argv.version;

            if (!version) {
                throw new Error('Missing argument: version.');
            }

            // do nothing if unreleased is empty.
            if (parser.root.children.length <= parser.MARKERS.UNRELEASED) return;

            const m = parser.createMDAST;
            const unchanged = parser.root.children.slice(parser.MARKERS.INITIAL, parser.MARKERS.UNRELEASED);
            const childrens = parser.root.children.slice(parser.MARKERS.UNRELEASED, parser.root.children.length - 1);

            let pos = parser.MARKERS.UNRELEASED;
            const unreleased = [];
            for (let node of childrens) {
                if (node.type === 'heading' && node.depth === 2) {
                    break;
                }
                if (isUnreleased(node)) {
                    unreleased.push(node);
                } else {
                    break;
                }
                pos++;
            }

            if (pos === parser.MARKERS.UNRELEASED) return;
            const previousVersions = parser.root.children.slice(pos, parser.root.children.length);
            const date = new Date();
            const newVersion = m(`## [${version}] - ${date.getUTCFullYear()}-${date.getUTCMonth() + 1}-${date.getUTCDate()}`);
            let newRoot = [...unchanged, newVersion, ...unreleased, ...previousVersions ];
            // update the rootz
            parser.root.children = newRoot;
            write();
        }
    };
}
<commit_msg>Update: some comments<commit_after>const HEADINGS = new Set([
    'Added',
    'Updated',
    'Removed'
]);

function isUnreleased(node) {
    return node.type === 'heading' && HEADINGS.has(node.children[0].value) || node.type === 'list';
}

export default function () {
    return {
        command: 'release [version]',
        describe: 'Groups all your new features and marks a new release on your CHANGELOG.md.',
        handler(parser, argv, write) {
            if ( !parser.exists() ) {
                throw new Error('CHANGELOG.md does not exists. You can run: chan init in order to create a fresh new one.');
            }

            const version = argv.version;

            if (!version) {
                throw new Error('Missing argument: version.');
            }

            // do nothing if unreleased is empty.
            if (parser.root.children.length <= parser.MARKERS.UNRELEASED) return;

            const m = parser.createMDAST;
            // the header part of the CHANGELOG
            const unchanged = parser.root.children.slice(parser.MARKERS.INITIAL, parser.MARKERS.UNRELEASED);
            // Unreleased section "childrens"
            const childrens = parser.root.children.slice(parser.MARKERS.UNRELEASED, parser.root.children.length - 1);

            let pos = parser.MARKERS.UNRELEASED;
            const unreleased = [];
            for (let node of childrens) {
                if (node.type === 'heading' && node.depth === 2) {
                    break;
                }
                if (isUnreleased(node)) {
                    unreleased.push(node);
                } else {
                    break;
                }
                pos++;
            }

            if (pos === parser.MARKERS.UNRELEASED) return;
            const previousVersions = parser.root.children.slice(pos, parser.root.children.length);
            const date = new Date();
            const newVersion = m(`## [${version}] - ${date.getUTCFullYear()}-${date.getUTCMonth() + 1}-${date.getUTCDate()}`);
            let newRoot = [...unchanged, newVersion, ...unreleased, ...previousVersions ];
            // update the rootz
            parser.root.children = newRoot;
            write();
        }
    };
}
<|endoftext|>


<commit_before>/*
 * marry.js - Marry your imaginary waifu or someone
 *
 * Contributed by Capuccino and Ovyerus
 */

/* eslint-env node */

exports.commands = [
    'marry',
    'divorce'
];

exports.marry = {
    desc: 'Marry someone.',
    usage: '<mention>',
    main(bot, ctx) {
        return new Promise((resolve, reject) => {
            if (ctx.args.length === 0 || ctx.mentionStrings.length === 0) {
                ctx.createMessage('Please mention your partner.').then(resolve).catch(reject);
            } else if (ctx.mentionStrings[0] === ctx.author.id) {
                ctx.createMessage("Hey! You're not allowed to marry yourself.").then(resolve).catch(reject);
            } else if (ctx.mentionStrings.length > 1) {
                ctx.createMessage('One wife only!');
            } else if (ctx.mentionStrings[0] === bot.user.id) {
                ctx.createMessage("I-It's not like I'll say yes or anything >.<");
            } else {
                ctx.createMessage(`<@${ctx.mentionStrings[0]}> will you marry ${ctx.author.mention}?\nRespond with yes or no. (30 seconds)`).then(() => {
                    return bot.awaitMessage(ctx.channel.id, ctx.mentionStrings[0], () => true, 30000);
                }).then(m => {
                    if (/y(es)?/i.test(m.content)) {
                        return ctx.createMessage(`I hereby pronounce <@${ctx.mentionStrings[0]}> and ${ctx.author.mention} as husband and wife. :sparkling_heart:`);
                    } else if (/no?/i.test(m.content)) {
                        return ctx.createMessage(`${ctx.author.mention}, unfortunately, your partner declined.`);
                    } else {
                        return ctx.createMessage(`<@${ctx.mentionStrings[0]}> that is not a valid answer.`);
                    }
                }).then(resolve).catch(err => {
                    if (err.message && err.message === 'Message await expired.') {
                        return ctx.createMessage(`${ctx.author.mention} your partner did not respond in time.`);
                    } else {
                        reject(err);
                    }
                }).then(resolve);
            }
        });
    }
};

exports.divorce = {
    desc: 'Divorce your partner.',
    usage: '<mention>',
    main(bot, ctx) {
        return new Promise((resolve, reject) => {
            if (ctx.args.length === 0 || ctx.mentionStrings.length === 0) {
                ctx.createMessage('Please mention your partner.').then(resolve).catch(reject);
            } else if (ctx.mentionStrings[0] === ctx.author.id) {
                ctx.createMessage("Hey! You can't divorce yourself.").then(resolve).catch(reject);
            } else {
                ctx.createMessage(`<@${ctx.mentionStrings[0]}>, will you let go of ${ctx.author.mention}?\nRespond with yes or no. (30 seconds)`).then(() => {
                    return bot.awaitMessage(ctx.channel.id, ctx.mentionStrings[0], () => true, 30000);
                }).then(m => {
                    if (/y(es)?/i.test(m.content)) {
                        return ctx.createMessage(`${ctx.author.mention} you're no longer married to <@${ctx.mentionStrings[0]}>.`);
                    } else if (/no?/i.test(m.content)) {
                        return ctx.createMessage(`${ctx.author.mention}, your partner won't let go.`);
                    } else {
                        return ctx.createMessage(`<@${ctx.mentionStrings[0]}> that is not a valid answer.`);
                    }
                }).then(resolve).catch(err => {
                    if (err.message && err.message === 'Message await expired.') {
                        return ctx.createMessage(`${ctx.author.mention} your partner did not respond in time.`);
                    } else {
                        reject(err);
                    }
                }).then(resolve);
            }
        });
    }
};<commit_msg>try to fix broken no matcher on marry<commit_after>/*
 * marry.js - Marry your imaginary waifu or someone
 *
 * Contributed by Capuccino and Ovyerus
 */

/* eslint-env node */

exports.commands = [
    'marry',
    'divorce'
];

exports.marry = {
    desc: 'Marry someone.',
    usage: '<mention>',
    main(bot, ctx) {
        return new Promise((resolve, reject) => {
            if (ctx.args.length === 0 || ctx.mentionStrings.length === 0) {
                ctx.createMessage('Please mention your partner.').then(resolve).catch(reject);
            } else if (ctx.mentionStrings[0] === ctx.author.id) {
                ctx.createMessage("Hey! You're not allowed to marry yourself.").then(resolve).catch(reject);
            } else if (ctx.mentionStrings.length > 1) {
                ctx.createMessage('One wife only!');
            } else if (ctx.mentionStrings[0] === bot.user.id) {
                ctx.createMessage("I-It's not like I'll say yes or anything >.<");
            } else {
                ctx.createMessage(`<@${ctx.mentionStrings[0]}> will you marry ${ctx.author.mention}?\nRespond with yes or no. (30 seconds)`).then(() => {
                    return bot.awaitMessage(ctx.channel.id, ctx.mentionStrings[0], () => true, 30000);
                }).then(m => {
                    if (/y(es)?/i.test(m.content)) {
                        return ctx.createMessage(`I hereby pronounce <@${ctx.mentionStrings[0]}> and ${ctx.author.mention} as husband and wife. :sparkling_heart:`);
                    } else if (/no?/i.test(m.content)) {
                        return ctx.createMessage(`${ctx.author.mention}, unfortunately, your partner declined.`);
                    } else {
                        return ctx.createMessage(`<@${ctx.mentionStrings[0]}> that is not a valid answer.`);
                    }
                }).then(resolve).catch(err => {
                    if (err.message && err.message === 'Message await expired.') {
                        return ctx.createMessage(`${ctx.author.mention} your partner did not respond in time.`);
                    } else {
                        reject(err);
                    }
                }).then(resolve);
            }
        });
    }
};

exports.divorce = {
    desc: 'Divorce your partner.',
    usage: '<mention>',
    main(bot, ctx) {
        return new Promise((resolve, reject) => {
            if (ctx.args.length === 0 || ctx.mentionStrings.length === 0) {
                ctx.createMessage('Please mention your partner.').then(resolve).catch(reject);
            } else if (ctx.mentionStrings[0] === ctx.author.id) {
                ctx.createMessage("Hey! You can't divorce yourself.").then(resolve).catch(reject);
            } else {
                ctx.createMessage(`<@${ctx.mentionStrings[0]}>, will you let go of ${ctx.author.mention}?\nRespond with yes or no. (30 seconds)`).then(() => {
                    return bot.awaitMessage(ctx.channel.id, ctx.mentionStrings[0], () => true, 30000);
                }).then(m => {
                    if (/y(es)?/i.test(m.content)) {
                        return ctx.createMessage(`${ctx.author.mention} you're no longer married to <@${ctx.mentionStrings[0]}>.`);
                    } else if (/(o)?/i.test(m.content)) {
                        return ctx.createMessage(`${ctx.author.mention}, your partner won't let go.`);
                    } else {
                        return ctx.createMessage(`<@${ctx.mentionStrings[0]}> that is not a valid answer.`);
                    }
                }).then(resolve).catch(err => {
                    if (err.message && err.message === 'Message await expired.') {
                        return ctx.createMessage(`${ctx.author.mention} your partner did not respond in time.`);
                    } else {
                        reject(err);
                    }
                }).then(resolve);
            }
        });
    }
};<|endoftext|>


<commit_before>const config = require("./../../config.json");
const MSS = require("./../../functions/");
const meta = require("./meta.json");

module.exports = function screenshot(message) {
	if(MSS.msg.isadmin(message)) {
		let fetch = "";
		let del = "";

		message.channel.fetchMessages({limit: 100})
			.then(messages => {
				console.log(messages.length);
				message.channel.bulkDelete(messages.filter((message) => {return message.author.id === client.user.id}))
			})
			.catch((err)=>{fetch = err.fetch;});

		if(fetch || del) message.channel.send(`${meta[message.data.lang] && meta[message.data.lang].err_prune || "err_prune"}\n${fetch}\n${del}`)
	}
}
<commit_msg>log size<commit_after>const config = require("./../../config.json");
const MSS = require("./../../functions/");
const meta = require("./meta.json");

module.exports = function screenshot(message) {
	if(MSS.msg.isadmin(message)) {
		let fetch = "";
		let del = "";

		message.channel.fetchMessages({limit: 100})
			.then(messages => {
				console.log(messages.size);
				message.channel.bulkDelete(messages.filter((message) => {return message.author.id === client.user.id}))
			})
			.catch((err)=>{fetch = err.fetch;});

		if(fetch || del) message.channel.send(`${meta[message.data.lang] && meta[message.data.lang].err_prune || "err_prune"}\n${fetch}\n${del}`)
	}
}
<|endoftext|>


<commit_before>
/*
A set of rendering and date-related methods for a visual component comprised of one or more rows of day columns.
Prerequisite: the object being mixed into needs to be a *Grid*
*/
var DayTableMixin = FC.DayTableMixin = {

	breakOnWeeks: false, // should create a new row for each week?
	dayDates: null, // whole-day dates for each column. left to right
	dayIndices: null, // for each day from start, the offset
	daysPerRow: null,
	rowCnt: null,
	colCnt: null,
	colHeadFormat: null,

	// Populates internal variables used for date calculation and rendering
	updateDayTable: function() {
		var view = this.view;
		var date = this.start.clone();
		var dayIndex = -1;
		var dayIndices = [];
		var dayDates = [];
		var daysPerRow;
		var firstDay;
		var rowCnt;

		while (date.isBefore(this.end)) { // loop each day from start to end
			if (view.isHiddenDay(date)) {
				dayIndices.push(dayIndex + 0.5); // mark that it's between indices
			}
			else {
				dayIndex++;
				dayIndices.push(dayIndex);
				dayDates.push(date.clone());
			}
			date.add(1, 'days');
		}

		if (this.breakOnWeeks) {
			// count columns until the day-of-week repeats
			firstDay = dayDates[0].day();
			for (daysPerRow = 1; daysPerRow < dayDates.length; daysPerRow++) {
				if (dayDates[daysPerRow].day() == firstDay) {
					break;
				}
			}
			rowCnt = Math.ceil(dayDates.length / daysPerRow);
		}
		else {
			rowCnt = 1;
			daysPerRow = dayDates.length;
		}

		this.dayDates = dayDates;
		this.dayIndices = dayIndices;
		this.daysPerRow = daysPerRow;
		this.rowCnt = rowCnt;

		this.updateDayTableCols();
	},

	// Computes and assigned the colCnt property and updates any options that may be computed from it
	updateDayTableCols: function() {
		this.colCnt = this.computeColCnt();
		this.colHeadFormat = this.view.opt('columnFormat') || this.computeColHeadFormat();
	},

	// Determines how many columns there should be in the table
	computeColCnt: function() {
		return this.daysPerRow;
	},

	// Computes the ambiguously-timed moment for the given cell
	getCellDate: function(row, col) {
		return this.dayDates[
				this.getCellDayIndex(row, col)
			].clone();
	},

	// Computes the ambiguously-timed date range for the given cell
	getCellRange: function(row, col) {
		var start = this.getCellDate(row, col);
		var end = start.clone().add(1, 'days');

		return { start: start, end: end };
	},

	// Returns the number of day cells, chronologically, from the first of the grid (0-based)
	getCellDayIndex: function(row, col) {
		return row * this.daysPerRow + this.getColDayIndex(col);
	},

	// Returns the numner of day cells, chronologically, from the first cell in *any given row*
	getColDayIndex: function(col) {
		if (this.isRTL) {
			return this.colCnt - 1 - col;
		}
		else {
			return col;
		}
	},

	// Given a date, returns its chronolocial cell-index from the first cell of the grid.
	// If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
	// If before the first offset, returns a negative number.
	// If after the last offset, returns an offset past the last cell offset.
	// Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
	getDateDayIndex: function(date) {
		var dayIndices = this.dayIndices;
		var dayOffset = date.diff(this.start, 'days');

		if (dayOffset < 0) {
			return dayIndices[0] - 1;
		}
		else if (dayOffset >= dayIndices.length) {
			return dayIndices[dayIndices.length - 1] + 1;
		}
		else {
			return dayIndices[dayOffset];
		}
	},

	/* Options
	------------------------------------------------------------------------------------------------------------------*/

	// Computes a default column header formatting string if `colFormat` is not explicitly defined
	computeColHeadFormat: function() {
		// if more than one week row, or if there are a lot of columns with not much space,
		// put just the day numbers will be in each cell
		if (this.rowCnt > 1 || this.colCnt > 10) {
			return 'ddd'; // "Sat"
		}
		// multiple days, so full single date string WON'T be in title text
		else if (this.colCnt > 1) {
			return this.view.opt('dayOfMonthFormat'); // "Sat 12/10"
		}
		// single day, so full single date string will probably be in title text
		else {
			return 'dddd'; // "Saturday"
		}
	},

	/* Slicing
	------------------------------------------------------------------------------------------------------------------*/

	// Slices up a date range into a segment for every week-row it intersects with
	sliceRangeByRow: function(range) {
		var daysPerRow = this.daysPerRow;
		var normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold
		var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index
		var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index
		var segs = [];
		var row;
		var rowFirst, rowLast; // inclusive day-index range for current row
		var segFirst, segLast; // inclusive day-index range for segment

		for (row = 0; row < this.rowCnt; row++) {
			rowFirst = row * daysPerRow;
			rowLast = rowFirst + daysPerRow - 1;

			// intersect segment's offset range with the row's
			segFirst = Math.max(rangeFirst, rowFirst);
			segLast = Math.min(rangeLast, rowLast);

			// deal with in-between indices
			segFirst = Math.ceil(segFirst); // in-between starts round to next cell
			segLast = Math.floor(segLast); // in-between ends round to prev cell

			if (segFirst <= segLast) { // was there any intersection with the current row?
				segs.push({
					row: row,

					// normalize to start of row
					firstRowDayIndex: segFirst - rowFirst,
					lastRowDayIndex: segLast - rowFirst,

					// must be matching integers to be the segment's start/end
					isStart: segFirst === rangeFirst,
					isEnd: segLast === rangeLast
				});
			}
		}

		return segs;
	},

	// Slices up a date range into a segment for every day-cell it intersects with.
	// TODO: make more DRY with sliceRangeByRow somehow.
	sliceRangeByDay: function(range) {
		var daysPerRow = this.daysPerRow;
		var normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold
		var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index
		var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index
		var segs = [];
		var row;
		var rowFirst, rowLast; // inclusive day-index range for current row
		var i;
		var segFirst, segLast; // inclusive day-index range for segment

		for (row = 0; row < this.rowCnt; row++) {
			rowFirst = row * daysPerRow;
			rowLast = rowFirst + daysPerRow - 1;

			for (i = rowFirst; i <= rowLast; i++) {

				// intersect segment's offset range with the row's
				segFirst = Math.max(rangeFirst, i);
				segLast = Math.min(rangeLast, i);

				// deal with in-between indices
				segFirst = Math.ceil(segFirst); // in-between starts round to next cell
				segLast = Math.floor(segLast); // in-between ends round to prev cell

				if (segFirst <= segLast) { // was there any intersection with the current row?
					segs.push({
						row: row,

						// normalize to start of row
						firstRowDayIndex: segFirst - rowFirst,
						lastRowDayIndex: segLast - rowFirst,

						// must be matching integers to be the segment's start/end
						isStart: segFirst === rangeFirst,
						isEnd: segLast === rangeLast
					});
				}
			}
		}

		return segs;
	},

	/* Header Rendering
	------------------------------------------------------------------------------------------------------------------*/

	renderHeadHtml: function() {
		var view = this.view;

		return '' +
			'
' +
				'
' +
					'
' +
						this.renderHeadTrHtml() +
					'
' +
				'
' +
			'
';
	},

	renderHeadIntroHtml: function() {
		return this.renderIntroHtml(); // fall back to generic
	},

	renderHeadTrHtml: function() {
		return '' +
			'
' +
				(this.isRTL ? '' : this.renderHeadIntroHtml()) +
				this.renderHeadDateCellsHtml() +
				(this.isRTL ? this.renderHeadIntroHtml() : '') +
			'
';
	},

	renderHeadDateCellsHtml: function() {
		var htmls = [];
		var col, date;

		for (col = 0; col < this.colCnt; col++) {
			date = this.getCellDate(0, col);
			htmls.push(this.renderHeadDateCellHtml(date));
		}

		return htmls.join('');
	},

	// TODO: when internalApiVersion, accept an object for HTML attributes
	// (colspan should be no different)
	renderHeadDateCellHtml: function(date, colspan, otherAttrs) {
		var view = this.view;

        var todayClass = date.isSame(view.calendar.getNow(), 'day') ? ' fc-today' : '';

		return '' +
            ' 1 ?
					' colspan="' + colspan + '"' :
					'') +
				(otherAttrs ?
					' ' + otherAttrs :
					'') +
				'>' +
				// don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
				view.buildGotoAnchorHtml(
					{ date: date, forceOff: this.rowCnt > 1 || this.colCnt === 1 },
					htmlEscape(date.format(this.colHeadFormat)) // inner HTML
				) +
			'	';
	},

	/* Background Rendering
	------------------------------------------------------------------------------------------------------------------*/

	renderBgTrHtml: function(row) {
		return '' +
			'
' +
				(this.isRTL ? '' : this.renderBgIntroHtml(row)) +
				this.renderBgCellsHtml(row) +
				(this.isRTL ? this.renderBgIntroHtml(row) : '') +
			'
';
	},

	renderBgIntroHtml: function(row) {
		return this.renderIntroHtml(); // fall back to generic
	},

	renderBgCellsHtml: function(row) {
		var htmls = [];
		var col, date;

		for (col = 0; col < this.colCnt; col++) {
			date = this.getCellDate(row, col);
			htmls.push(this.renderBgCellHtml(date));
		}

		return htmls.join('');
	},

	renderBgCellHtml: function(date, otherAttrs) {
		var view = this.view;
		var classes = this.getDayClasses(date);

		classes.unshift('fc-day', view.widgetContentClass);

		return '	';
	},

	/* Generic
	------------------------------------------------------------------------------------------------------------------*/

	// Generates the default HTML intro for any row. User classes should override
	renderIntroHtml: function() {
	},

	// TODO: a generic method for dealing with
, RTL, intro
	// when increment internalApiVersion
	// wrapTr (scheduler)

	/* Utils
	------------------------------------------------------------------------------------------------------------------*/

	// Applies the generic "intro" and "outro" HTML to the given cells.
	// Intro means the leftmost cell when the calendar is LTR and the rightmost cell when RTL. Vice-versa for outro.
	bookendCells: function(trEl) {
		var introHtml = this.renderIntroHtml();

		if (introHtml) {
			if (this.isRTL) {
				trEl.append(introHtml);
			}
			else {
				trEl.prepend(introHtml);
			}
		}
	}

};
<commit_msg>Fixes #3361 using getDayClasses<commit_after>
/*
A set of rendering and date-related methods for a visual component comprised of one or more rows of day columns.
Prerequisite: the object being mixed into needs to be a *Grid*
*/
var DayTableMixin = FC.DayTableMixin = {

	breakOnWeeks: false, // should create a new row for each week?
	dayDates: null, // whole-day dates for each column. left to right
	dayIndices: null, // for each day from start, the offset
	daysPerRow: null,
	rowCnt: null,
	colCnt: null,
	colHeadFormat: null,

	// Populates internal variables used for date calculation and rendering
	updateDayTable: function() {
		var view = this.view;
		var date = this.start.clone();
		var dayIndex = -1;
		var dayIndices = [];
		var dayDates = [];
		var daysPerRow;
		var firstDay;
		var rowCnt;

		while (date.isBefore(this.end)) { // loop each day from start to end
			if (view.isHiddenDay(date)) {
				dayIndices.push(dayIndex + 0.5); // mark that it's between indices
			}
			else {
				dayIndex++;
				dayIndices.push(dayIndex);
				dayDates.push(date.clone());
			}
			date.add(1, 'days');
		}

		if (this.breakOnWeeks) {
			// count columns until the day-of-week repeats
			firstDay = dayDates[0].day();
			for (daysPerRow = 1; daysPerRow < dayDates.length; daysPerRow++) {
				if (dayDates[daysPerRow].day() == firstDay) {
					break;
				}
			}
			rowCnt = Math.ceil(dayDates.length / daysPerRow);
		}
		else {
			rowCnt = 1;
			daysPerRow = dayDates.length;
		}

		this.dayDates = dayDates;
		this.dayIndices = dayIndices;
		this.daysPerRow = daysPerRow;
		this.rowCnt = rowCnt;

		this.updateDayTableCols();
	},

	// Computes and assigned the colCnt property and updates any options that may be computed from it
	updateDayTableCols: function() {
		this.colCnt = this.computeColCnt();
		this.colHeadFormat = this.view.opt('columnFormat') || this.computeColHeadFormat();
	},

	// Determines how many columns there should be in the table
	computeColCnt: function() {
		return this.daysPerRow;
	},

	// Computes the ambiguously-timed moment for the given cell
	getCellDate: function(row, col) {
		return this.dayDates[
				this.getCellDayIndex(row, col)
			].clone();
	},

	// Computes the ambiguously-timed date range for the given cell
	getCellRange: function(row, col) {
		var start = this.getCellDate(row, col);
		var end = start.clone().add(1, 'days');

		return { start: start, end: end };
	},

	// Returns the number of day cells, chronologically, from the first of the grid (0-based)
	getCellDayIndex: function(row, col) {
		return row * this.daysPerRow + this.getColDayIndex(col);
	},

	// Returns the numner of day cells, chronologically, from the first cell in *any given row*
	getColDayIndex: function(col) {
		if (this.isRTL) {
			return this.colCnt - 1 - col;
		}
		else {
			return col;
		}
	},

	// Given a date, returns its chronolocial cell-index from the first cell of the grid.
	// If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
	// If before the first offset, returns a negative number.
	// If after the last offset, returns an offset past the last cell offset.
	// Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
	getDateDayIndex: function(date) {
		var dayIndices = this.dayIndices;
		var dayOffset = date.diff(this.start, 'days');

		if (dayOffset < 0) {
			return dayIndices[0] - 1;
		}
		else if (dayOffset >= dayIndices.length) {
			return dayIndices[dayIndices.length - 1] + 1;
		}
		else {
			return dayIndices[dayOffset];
		}
	},

	/* Options
	------------------------------------------------------------------------------------------------------------------*/

	// Computes a default column header formatting string if `colFormat` is not explicitly defined
	computeColHeadFormat: function() {
		// if more than one week row, or if there are a lot of columns with not much space,
		// put just the day numbers will be in each cell
		if (this.rowCnt > 1 || this.colCnt > 10) {
			return 'ddd'; // "Sat"
		}
		// multiple days, so full single date string WON'T be in title text
		else if (this.colCnt > 1) {
			return this.view.opt('dayOfMonthFormat'); // "Sat 12/10"
		}
		// single day, so full single date string will probably be in title text
		else {
			return 'dddd'; // "Saturday"
		}
	},

	/* Slicing
	------------------------------------------------------------------------------------------------------------------*/

	// Slices up a date range into a segment for every week-row it intersects with
	sliceRangeByRow: function(range) {
		var daysPerRow = this.daysPerRow;
		var normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold
		var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index
		var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index
		var segs = [];
		var row;
		var rowFirst, rowLast; // inclusive day-index range for current row
		var segFirst, segLast; // inclusive day-index range for segment

		for (row = 0; row < this.rowCnt; row++) {
			rowFirst = row * daysPerRow;
			rowLast = rowFirst + daysPerRow - 1;

			// intersect segment's offset range with the row's
			segFirst = Math.max(rangeFirst, rowFirst);
			segLast = Math.min(rangeLast, rowLast);

			// deal with in-between indices
			segFirst = Math.ceil(segFirst); // in-between starts round to next cell
			segLast = Math.floor(segLast); // in-between ends round to prev cell

			if (segFirst <= segLast) { // was there any intersection with the current row?
				segs.push({
					row: row,

					// normalize to start of row
					firstRowDayIndex: segFirst - rowFirst,
					lastRowDayIndex: segLast - rowFirst,

					// must be matching integers to be the segment's start/end
					isStart: segFirst === rangeFirst,
					isEnd: segLast === rangeLast
				});
			}
		}

		return segs;
	},

	// Slices up a date range into a segment for every day-cell it intersects with.
	// TODO: make more DRY with sliceRangeByRow somehow.
	sliceRangeByDay: function(range) {
		var daysPerRow = this.daysPerRow;
		var normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold
		var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index
		var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index
		var segs = [];
		var row;
		var rowFirst, rowLast; // inclusive day-index range for current row
		var i;
		var segFirst, segLast; // inclusive day-index range for segment

		for (row = 0; row < this.rowCnt; row++) {
			rowFirst = row * daysPerRow;
			rowLast = rowFirst + daysPerRow - 1;

			for (i = rowFirst; i <= rowLast; i++) {

				// intersect segment's offset range with the row's
				segFirst = Math.max(rangeFirst, i);
				segLast = Math.min(rangeLast, i);

				// deal with in-between indices
				segFirst = Math.ceil(segFirst); // in-between starts round to next cell
				segLast = Math.floor(segLast); // in-between ends round to prev cell

				if (segFirst <= segLast) { // was there any intersection with the current row?
					segs.push({
						row: row,

						// normalize to start of row
						firstRowDayIndex: segFirst - rowFirst,
						lastRowDayIndex: segLast - rowFirst,

						// must be matching integers to be the segment's start/end
						isStart: segFirst === rangeFirst,
						isEnd: segLast === rangeLast
					});
				}
			}
		}

		return segs;
	},

	/* Header Rendering
	------------------------------------------------------------------------------------------------------------------*/

	renderHeadHtml: function() {
		var view = this.view;

		return '' +
			'
' +
				'
' +
					'
' +
						this.renderHeadTrHtml() +
					'
' +
				'
' +
			'
';
	},

	renderHeadIntroHtml: function() {
		return this.renderIntroHtml(); // fall back to generic
	},

	renderHeadTrHtml: function() {
		return '' +
			'
' +
				(this.isRTL ? '' : this.renderHeadIntroHtml()) +
				this.renderHeadDateCellsHtml() +
				(this.isRTL ? this.renderHeadIntroHtml() : '') +
			'
';
	},

	renderHeadDateCellsHtml: function() {
		var htmls = [];
		var col, date;

		for (col = 0; col < this.colCnt; col++) {
			date = this.getCellDate(0, col);
			htmls.push(this.renderHeadDateCellHtml(date));
		}

		return htmls.join('');
	},

	// TODO: when internalApiVersion, accept an object for HTML attributes
	// (colspan should be no different)
	renderHeadDateCellHtml: function(date, colspan, otherAttrs) {
		var view = this.view;

		var todayClass = (this.rowCnt === 1) ? this.getDayClasses(date).join(' ')
		        : 'fc-' + dayIDs[date.day()];

		return '' +
            ' 1 ?
					' colspan="' + colspan + '"' :
					'') +
				(otherAttrs ?
					' ' + otherAttrs :
					'') +
				'>' +
				// don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
				view.buildGotoAnchorHtml(
					{ date: date, forceOff: this.rowCnt > 1 || this.colCnt === 1 },
					htmlEscape(date.format(this.colHeadFormat)) // inner HTML
				) +
			'	';
	},

	/* Background Rendering
	------------------------------------------------------------------------------------------------------------------*/

	renderBgTrHtml: function(row) {
		return '' +
			'
' +
				(this.isRTL ? '' : this.renderBgIntroHtml(row)) +
				this.renderBgCellsHtml(row) +
				(this.isRTL ? this.renderBgIntroHtml(row) : '') +
			'
';
	},

	renderBgIntroHtml: function(row) {
		return this.renderIntroHtml(); // fall back to generic
	},

	renderBgCellsHtml: function(row) {
		var htmls = [];
		var col, date;

		for (col = 0; col < this.colCnt; col++) {
			date = this.getCellDate(row, col);
			htmls.push(this.renderBgCellHtml(date));
		}

		return htmls.join('');
	},

	renderBgCellHtml: function(date, otherAttrs) {
		var view = this.view;
		var classes = this.getDayClasses(date);

		classes.unshift('fc-day', view.widgetContentClass);

		return '	';
	},

	/* Generic
	------------------------------------------------------------------------------------------------------------------*/

	// Generates the default HTML intro for any row. User classes should override
	renderIntroHtml: function() {
	},

	// TODO: a generic method for dealing with
, RTL, intro
	// when increment internalApiVersion
	// wrapTr (scheduler)

	/* Utils
	------------------------------------------------------------------------------------------------------------------*/

	// Applies the generic "intro" and "outro" HTML to the given cells.
	// Intro means the leftmost cell when the calendar is LTR and the rightmost cell when RTL. Vice-versa for outro.
	bookendCells: function(trEl) {
		var introHtml = this.renderIntroHtml();

		if (introHtml) {
			if (this.isRTL) {
				trEl.append(introHtml);
			}
			else {
				trEl.prepend(introHtml);
			}
		}
	}

};
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import ReactGA from 'react-ga';

let log = () => {};
if (process.env.NODE_ENV === 'production') {
  ReactGA.initialize(process.env.GA_ID);
  let lastPathname;
  log = () => {
    const { pathname } = window.location;
    if (pathname !== lastPathname) {
      /* global window */
      ReactGA.set({ page: window.location.pathname });
      ReactGA.pageview(window.location.pathname);
    }
    lastPathname = pathname;
  };
}

const App = ({ renderProps, store }) => (
  <Provider store={store}>
    <Router {...renderProps} onUpdate={log} />
  </Provider>
);

App.propTypes = {
  renderProps: PropTypes.any.isRequired,
  store: PropTypes.any.isRequired,
};

export default App;
<commit_msg>Fix AppClient component name.<commit_after>import React, { PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import ReactGA from 'react-ga';

let log = () => {};
if (process.env.NODE_ENV === 'production') {
  ReactGA.initialize(process.env.GA_ID);
  let lastPathname;
  log = () => {
    const { pathname } = window.location;
    if (pathname !== lastPathname) {
      /* global window */
      ReactGA.set({ page: window.location.pathname });
      ReactGA.pageview(window.location.pathname);
    }
    lastPathname = pathname;
  };
}

const AppClient = ({ renderProps, store }) => (
  <Provider store={store}>
    <Router {...renderProps} onUpdate={log} />
  </Provider>
);

AppClient.propTypes = {
  renderProps: PropTypes.any.isRequired,
  store: PropTypes.any.isRequired,
};

export default AppClient;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import Book from './Book';

class BookShelf extends Component {
  static propTypes = {
    title: PropTypes.string.isRequired,
    books: PropTypes.array.isRequired
  };

  render() {
    return (

{this.props.title}

          {this.props.books.map((book, idx) =>
              <Book key={idx} book={book}/>
            )}

    );
  }
}

export default BookShelf<commit_msg>BookShelf > Rewritten as functional stateless component<commit_after>import React from 'react';
import PropTypes from 'prop-types';

import Book from './Book';

const BookShelf = function (props) {
  const { title, books } = props;

  return (

{title}

          {books.map((book, idx) =>
            <Book key={idx} book={book} />
          )}

  );
}

BookShelf.propTypes = {
  title: PropTypes.string.isRequired,
  books: PropTypes.array.isRequired
};

export default BookShelf<|endoftext|>