<commit_before>var listOfCountries = ['United States','Russia','Australia','Canada','Norway','China','Zimbabwe','Netherlands','South Korea','Croatia',
    'France','Japan','Hungary','Germany','Poland','South Africa','Sweden','Ukraine','Italy','Czech Republic','Austria','Finland','Romania',
    'Great Britain','Jamaica','Singapore','Belarus','Chile','Spain','Tunisia','Brazil','Slovakia','Costa Rica','Bulgaria','Switzerland',
    'New Zealand','Estonia','Kenya','Ethiopia','Trinidad and Tobago','Turkey','Morocco','Bahamas','Slovenia','Armenia','Azerbaijan','India',
    'Puerto Rico','Egypt','Kazakhstan','Iran','Georgia','Lithuania','Cuba','Colombia','Mongolia','Uzbekistan','North Korea','Tajikistan',
    'Kyrgyzstan','Greece','Macedonia','Moldova','Chinese Taipei','Indonesia','Thailand','Vietnam','Latvia','Venezuela','Mexico','Nigeria',
    'Qatar','Serbia','Serbia and Montenegro','Hong Kong','Denmark','Portugal','Argentina','Afghanistan','Gabon','Dominican Republic','Belgium',
    'Kuwait','United Arab Emirates','Cyprus','Israel','Algeria','Montenegro','Iceland','Paraguay','Cameroon','Saudi Arabia','Ireland','Malaysia',
    'Uruguay','Togo','Mauritius','Syria','Botswana','Guatemala','Bahrain','Grenada','Uganda','Sudan','Ecuador','Panama','Eritrea','Sri Lanka',
    'Mozambique','Barbados'];

var columnDefs = [
    // this row just shows the row index, doesn't use any data from the row
    {headerName: "#", width: 50,
        cellRenderer: function(params) {
            return params.node.id + 1;
        },
        // we don't want to sort by the row index, this doesn't make sense as the point
        // of the row index is to know the row index in what came back from the server
        suppressSorting: true,
        suppressMenu: true },
    {headerName: "Athlete", field: "athlete", width: 150, suppressMenu: true},
    {headerName: "Age", field: "age", width: 90, filter: 'number', filterParams: {newRowsAction: 'keep'}},
    {headerName: "Country", field: "country", width: 120, filter: 'set', filterParams: {values: listOfCountries, newRowsAction: 'keep'}},
    {headerName: "Year", field: "year", width: 90, filter: 'set', filterParams: {values: ['2000','2004','2008','2012'], newRowsAction: 'keep'}},
    {headerName: "Date", field: "date", width: 110, suppressMenu: true},
    {headerName: "Sport", field: "sport", width: 110, suppressMenu: true},
    {headerName: "Gold", field: "gold", width: 100, suppressMenu: true},
    {headerName: "Silver", field: "silver", width: 100, suppressMenu: true},
    {headerName: "Bronze", field: "bronze", width: 100, suppressMenu: true},
    {headerName: "Total", field: "total", width: 100, suppressMenu: true}
];

var gridOptions = {
    enableServerSideSorting: true,
    enableServerSideFilter: true,
    enableColResize: true,
    paginationPageSize: 500,
    columnDefs: columnDefs,
    rowModelType: 'pagination',
    rowSelection: 'multiple',
    getRowNodeId: function(item) {
        return item.id;
    }
};

// when json gets loaded, it's put here, and  the datasource reads in from here.
// in a real application, the page will be got from the server.
var allOfTheData;

function setRowData(rowData) {
    allOfTheData = rowData;
    // give each row an id
    allOfTheData.forEach( function(data, index) {
        data.id = 'R' + (index + 1);
    });
    createNewDatasource();
}

function createNewDatasource() {
    if (!allOfTheData) {
        // in case user selected 'onPageSizeChanged()' before the json was loaded
        return;
    }
    var dataSource = {
        //rowCount: ???, - not setting the row count, infinite paging will be used
        getRows: function (params) {
            // this code should contact the server for rows. however for the purposes of the demo,
            // the data is generated locally, a timer is used to give the experience of
            // an asynchronous call
            console.log('asking for ' + params.startRow + ' to ' + params.endRow);
            setTimeout( function() {
                // take a chunk of the array, matching the start and finish times
                var dataAfterSortingAndFiltering = sortAndFilter(params.sortModel, params.filterModel);
                var rowsThisPage = dataAfterSortingAndFiltering.slice(params.startRow, params.endRow);
                // see if we have come to the last page. if we have, set lastRow to
                // the very last row of the last page. if you are getting data from
                // a server, lastRow could be returned separately if the lastRow
                // is not in the current page.
                var lastRow = -1;
                if (dataAfterSortingAndFiltering.length <= params.endRow) {
                    lastRow = dataAfterSortingAndFiltering.length;
                }
                params.successCallback(rowsThisPage, lastRow);
            }, 500);
        }
    };

    gridOptions.api.setDatasource(dataSource);
}

function sortAndFilter(sortModel, filterModel) {
    return sortData(sortModel, filterData(filterModel, allOfTheData))
}

function sortData(sortModel, data) {
    var sortPresent = sortModel && sortModel.length > 0;
    if (!sortPresent) {
        return data;
    }
    // do an in memory sort of the data, across all the fields
    var resultOfSort = data.slice();
    resultOfSort.sort(function(a,b) {
        for (var k = 0; k<sortModel.length; k++) {
            var sortColModel = sortModel[k];
            var valueA = a[sortColModel.colId];
            var valueB = b[sortColModel.colId];
            // this filter didn't find a difference, move onto the next one
            if (valueA==valueB) {
                continue;
            }
            var sortDirection = sortColModel.sort === 'asc' ? 1 : -1;
            if (valueA > valueB) {
                return sortDirection;
            } else {
                return sortDirection * -1;
            }
        }
        // no filters found a difference
        return 0;
    });
    return resultOfSort;
}

function filterData(filterModel, data) {
    var filterPresent = filterModel && Object.keys(filterModel).length > 0;
    if (!filterPresent) {
        return data;
    }

    var resultOfFilter = [];
    for (var i = 0; i<data.length; i++) {
        var item = data[i];

        if (filterModel.age) {
            var age = item.age;
            var allowedAge = parseInt(filterModel.age.filter);
            // EQUALS = 1;
            // LESS_THAN = 2;
            // GREATER_THAN = 3;
            if (filterModel.age.type == 1) {
                if (age !== allowedAge) {
                    continue;
                }
            } else if (filterModel.age.type == 2) {
                if (age >= allowedAge) {
                    continue;
                }
            } else {
                if (age <= allowedAge) {
                    continue;
                }
            }
        }

        if (filterModel.year) {
            if (filterModel.year.indexOf(item.year.toString()) < 0) {
                // year didn't match, so skip this record
                continue;
            }
        }

        if (filterModel.country) {
            if (filterModel.country.indexOf(item.country) < 0) {
                // country didn't match, so skip this record
                continue;
            }
        }

        resultOfFilter.push(item);
    }

    return resultOfFilter;
}

// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function() {
    var gridDiv = document.querySelector('#myGrid');
    new agGrid.Grid(gridDiv, gridOptions);

    // do http request to get our sample data - not using any framework to keep the example self contained.
    // you will probably use a framework like JQuery, Angular or something else to do your HTTP calls.
    var httpRequest = new XMLHttpRequest();
    httpRequest.open('GET', '../olympicWinners.json');
    httpRequest.send();
    httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState == 4 && httpRequest.status == 200) {
            var httpResponse = JSON.parse(httpRequest.responseText);
            setRowData(httpResponse);
        }
    };
});
<commit_msg>fixed bugs with paging<commit_after>var listOfCountries = ['United States','Russia','Australia','Canada','Norway','China','Zimbabwe','Netherlands','South Korea','Croatia',
    'France','Japan','Hungary','Germany','Poland','South Africa','Sweden','Ukraine','Italy','Czech Republic','Austria','Finland','Romania',
    'Great Britain','Jamaica','Singapore','Belarus','Chile','Spain','Tunisia','Brazil','Slovakia','Costa Rica','Bulgaria','Switzerland',
    'New Zealand','Estonia','Kenya','Ethiopia','Trinidad and Tobago','Turkey','Morocco','Bahamas','Slovenia','Armenia','Azerbaijan','India',
    'Puerto Rico','Egypt','Kazakhstan','Iran','Georgia','Lithuania','Cuba','Colombia','Mongolia','Uzbekistan','North Korea','Tajikistan',
    'Kyrgyzstan','Greece','Macedonia','Moldova','Chinese Taipei','Indonesia','Thailand','Vietnam','Latvia','Venezuela','Mexico','Nigeria',
    'Qatar','Serbia','Serbia and Montenegro','Hong Kong','Denmark','Portugal','Argentina','Afghanistan','Gabon','Dominican Republic','Belgium',
    'Kuwait','United Arab Emirates','Cyprus','Israel','Algeria','Montenegro','Iceland','Paraguay','Cameroon','Saudi Arabia','Ireland','Malaysia',
    'Uruguay','Togo','Mauritius','Syria','Botswana','Guatemala','Bahrain','Grenada','Uganda','Sudan','Ecuador','Panama','Eritrea','Sri Lanka',
    'Mozambique','Barbados'];

var columnDefs = [
    // this row just shows the row index, doesn't use any data from the row
    {headerName: "#", width: 50,
        cellRenderer: function(params) {
            return params.node.id + 1;
        },
        // we don't want to sort by the row index, this doesn't make sense as the point
        // of the row index is to know the row index in what came back from the server
        suppressSorting: true,
        suppressMenu: true },
    {headerName: "Athlete", field: "athlete", width: 150, suppressMenu: true},
    {headerName: "Age", field: "age", width: 90, filter: 'number', filterParams: {newRowsAction: 'keep'}},
    {headerName: "Country", field: "country", width: 120, filter: 'set', filterParams: {values: listOfCountries, newRowsAction: 'keep'}},
    {headerName: "Year", field: "year", width: 90, filter: 'set', filterParams: {values: ['2000','2004','2008','2012'], newRowsAction: 'keep'}},
    {headerName: "Date", field: "date", width: 110, suppressMenu: true},
    {headerName: "Sport", field: "sport", width: 110, suppressMenu: true},
    {headerName: "Gold", field: "gold", width: 100, suppressMenu: true},
    {headerName: "Silver", field: "silver", width: 100, suppressMenu: true},
    {headerName: "Bronze", field: "bronze", width: 100, suppressMenu: true},
    {headerName: "Total", field: "total", width: 100, suppressMenu: true}
];

var gridOptions = {
    enableServerSideSorting: true,
    enableServerSideFilter: true,
    enableColResize: true,
    paginationPageSize: 500,
    columnDefs: columnDefs,
    rowModelType: 'pagination',
    rowSelection: 'multiple',
    getRowNodeId: function(item) {
        return item.id;
    }
};

// when json gets loaded, it's put here, and  the datasource reads in from here.
// in a real application, the page will be got from the server.
var allOfTheData;

function setRowData(rowData) {
    allOfTheData = rowData;
    // give each row an id
    allOfTheData.forEach( function(data, index) {
        data.id = 'R' + (index + 1);
    });
    createNewDatasource();
}

function createNewDatasource() {
    if (!allOfTheData) {
        // in case user selected 'onPageSizeChanged()' before the json was loaded
        return;
    }
    var dataSource = {
        //rowCount: ???, - not setting the row count, infinite paging will be used
        getRows: function (params) {
            // this code should contact the server for rows. however for the purposes of the demo,
            // the data is generated locally, a timer is used to give the experience of
            // an asynchronous call
            console.log('asking for ' + params.startRow + ' to ' + params.endRow);
            setTimeout( function() {
                // take a chunk of the array, matching the start and finish times
                var dataAfterSortingAndFiltering = sortAndFilter(params.sortModel, params.filterModel);
                var rowsThisPage = dataAfterSortingAndFiltering.slice(params.startRow, params.endRow);
                // see if we have come to the last page. if we have, set lastRow to
                // the very last row of the last page. if you are getting data from
                // a server, lastRow could be returned separately if the lastRow
                // is not in the current page.
                var lastRow = -1;
                if (dataAfterSortingAndFiltering.length <= params.endRow) {
                    lastRow = dataAfterSortingAndFiltering.length;
                }
                params.successCallback(rowsThisPage, lastRow);
            }, 500);
        }
    };

    gridOptions.api.setDatasource(dataSource);
}

function sortAndFilter(sortModel, filterModel) {
    return sortData(sortModel, filterData(filterModel, allOfTheData))
}

function sortData(sortModel, data) {
    var sortPresent = sortModel && sortModel.length > 0;
    if (!sortPresent) {
        return data;
    }
    // do an in memory sort of the data, across all the fields
    var resultOfSort = data.slice();
    resultOfSort.sort(function(a,b) {
        for (var k = 0; k<sortModel.length; k++) {
            var sortColModel = sortModel[k];
            var valueA = a[sortColModel.colId];
            var valueB = b[sortColModel.colId];
            // this filter didn't find a difference, move onto the next one
            if (valueA==valueB) {
                continue;
            }
            var sortDirection = sortColModel.sort === 'asc' ? 1 : -1;
            if (valueA > valueB) {
                return sortDirection;
            } else {
                return sortDirection * -1;
            }
        }
        // no filters found a difference
        return 0;
    });
    return resultOfSort;
}

function filterData(filterModel, data) {
    var filterPresent = filterModel && Object.keys(filterModel).length > 0;
    if (!filterPresent) {
        return data;
    }

    var resultOfFilter = [];
    for (var i = 0; i<data.length; i++) {
        var item = data[i];

        if (filterModel.age) {
            var age = item.age;
            var allowedAge = parseInt(filterModel.age.filter);
            // EQUALS = 1;
            // LESS_THAN = 2;
            // GREATER_THAN = 3;
            if (filterModel.age.type == 'equals') {
                if (age !== allowedAge) {
                    continue;
                }
            } else if (filterModel.age.type == 'notEqual') {
                if (age >= allowedAge) {
                    continue;
                }
            } else {
                if (age <= allowedAge) {
                    continue;
                }
            }
        }

        if (filterModel.year) {
            if (filterModel.year.indexOf(item.year.toString()) < 0) {
                // year didn't match, so skip this record
                continue;
            }
        }

        if (filterModel.country) {
            if (filterModel.country.indexOf(item.country) < 0) {
                // country didn't match, so skip this record
                continue;
            }
        }

        resultOfFilter.push(item);
    }

    return resultOfFilter;
}

// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function() {
    var gridDiv = document.querySelector('#myGrid');
    new agGrid.Grid(gridDiv, gridOptions);

    // do http request to get our sample data - not using any framework to keep the example self contained.
    // you will probably use a framework like JQuery, Angular or something else to do your HTTP calls.
    var httpRequest = new XMLHttpRequest();
    httpRequest.open('GET', '../olympicWinners.json');
    httpRequest.send();
    httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState == 4 && httpRequest.status == 200) {
            var httpResponse = JSON.parse(httpRequest.responseText);
            setRowData(httpResponse);
        }
    };
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 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.
 */

/**
 * @fileoverview Defines the SIGNATURE type used in the OTR protocol.
 *
 * @author rcc@google.com (Ryan Chan)
 */

goog.provide('e2e.otr.message.Signature');

goog.require('e2e.hash.Sha256');
goog.require('e2e.otr');
goog.require('e2e.otr.Data');
goog.require('e2e.otr.Sig');
goog.require('e2e.otr.constants');
goog.require('e2e.otr.constants.MessageType');
goog.require('e2e.otr.message.Message');
goog.require('e2e.otr.util.Iterator');
goog.require('e2e.otr.util.aes128ctr');
goog.require('goog.crypt.Hmac');

goog.scope(function() {

var constants = e2e.otr.constants;
var AUTHSTATE = constants.AUTHSTATE;

/**
 * An OTRv3 SIGNATURE.
 * @constructor
 * @extends {e2e.otr.message.Message}
 * @param {!e2e.otr.Session} session The enclosing session.
 */
e2e.otr.message.Signature = function(session) {
  goog.base(this, session);
};
goog.inherits(e2e.otr.message.Signature, e2e.otr.message.Message);

/**
 * Specifies the type of the message.
 * @type {!e2e.otr.Byte}
 */
e2e.otr.message.Signature.MESSAGE_TYPE = constants.MessageType.SIGNATURE;

/**
 * Serialize the SIGNATURE into a Uint8Array.
 * @return {!Uint8Array} The serialized SIGNATURE.
 */
e2e.otr.message.Signature.prototype.serializeMessageContent = function() {
  var keys = this.session_.deriveKeyValues();
  var keyA = this.session_.keymanager.getKey();
  var ma = new goog.crypt.Hmac(new e2e.hash.Sha256(), keys.m1prime)
      .getHmac(Array.apply([], e2e.otr.serializeBytes([
        keyA.key.generate(),
        this.session_.keymanager.getRemoteKey(new Uint8Array(4)).key,
        this.session_.getPublicKey(),
        keyA.keyid
      ])));

  var xa = Array.apply([], e2e.otr.serializeBytes([
    this.session_.getPublicKey(),
    keyA.keyid,
    new (this.session_.getSigner())(ma)
  ]));

  var sig = new e2e.otr.Data(
      e2e.otr.util.aes128ctr.encrypt(keys.cprime, xa));

  var mac = new goog.crypt.Hmac(new e2e.hash.Sha256(), keys.m2prime)
      .getHmac(Array.apply([], sig.serialize()));

  mac = mac.slice(0, 160 / 8);

  return e2e.otr.serializeBytes([sig, mac]);
};

/**
 * Processes a SIGNATURE message.
 * @param {!e2e.otr.Session} session The enclosing session.
 * @param {!Uint8Array} data The data to be processed.
 */
e2e.otr.message.Signature.process = function(session, data) {
  switch (session.getAuthState()) {
    case AUTHSTATE.AWAITING_SIG:
      var iter = new e2e.otr.util.Iterator(data);
      var aesxa = e2e.otr.Data.parse(iter.nextEncoded()).deconstruct();
      var mac = iter.next(20);

      var keys = session.deriveKeyValues();

      var calculatedMac = new goog.crypt.Hmac(new e2e.hash.Sha256(),
          keys.m2prime).getHmac(Array.apply([], aesxa));

      calculatedMac = calculatedMac.slice(0, 160 / 8);

      if (e2e.otr.compareByteArray(mac, calculatedMac)) {
        // TODO(rcc): Log the error and/or warn the user.
        return;
      }

      var xa = e2e.otr.util.aes128ctr.decrypt(keys.cprime, aesxa);

      iter = new e2e.otr.util.Iterator(xa);

      // TODO(rcc): Make Type.parse accept Iterator to pull appropriate data.
      var pubAType = iter.next(2);
      var pubA = {
        p: Array.apply([], iter.nextEncoded()),
        q: Array.apply([], iter.nextEncoded()),
        g: Array.apply([], iter.nextEncoded()),
        y: Array.apply([], iter.nextEncoded())
      };
      var keyidA = iter.next(4);
      var sigma = e2e.otr.Sig.parse(iter.next(40));

      var ma = new goog.crypt.Hmac(new e2e.hash.Sha256(), keys.m1prime)
          .getHmac(Array.apply([], e2e.otr.serializeBytes([
            session.keymanager.getRemoteKey(new Uint8Array(4)).key,
            session.keymanager.getKey().key.generate(),
            pubA,
            keyidA
          ])));

      if (!e2e.otr.Sig.verify(pubA, ma, sigma)) {
        // TODO(rcc): Log the error and/or warn the user.
        return;
      }

      session.setAuthState(AUTHSTATE.NONE);
      session.setMsgState(constants.MSGSTATE.ENCRYPTED);

      // TODO(rcc): Send any stored messages.

      break;

    case AUTHSTATE.NONE:
    case AUTHSTATE.AWAITING_DHKEY:
    case AUTHSTATE.AWAITING_REVEALSIG:
      return;

    default:
      e2e.otr.assertState(false, 'Invalid auth state.');
  }
};
});  // goog.scope
<commit_msg>OTR fix computation of HMAC in SIGNATURE messages<commit_after>/**
 * @license
 * Copyright 2014 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.
 */

/**
 * @fileoverview Defines the SIGNATURE type used in the OTR protocol.
 *
 * @author rcc@google.com (Ryan Chan)
 */

goog.provide('e2e.otr.message.Signature');

goog.require('e2e.hash.Sha256');
goog.require('e2e.otr');
goog.require('e2e.otr.Data');
goog.require('e2e.otr.Sig');
goog.require('e2e.otr.constants');
goog.require('e2e.otr.constants.MessageType');
goog.require('e2e.otr.message.Message');
goog.require('e2e.otr.util.Iterator');
goog.require('e2e.otr.util.aes128ctr');
goog.require('goog.crypt.Hmac');

goog.scope(function() {

var constants = e2e.otr.constants;
var AUTHSTATE = constants.AUTHSTATE;

/**
 * An OTRv3 SIGNATURE.
 * @constructor
 * @extends {e2e.otr.message.Message}
 * @param {!e2e.otr.Session} session The enclosing session.
 */
e2e.otr.message.Signature = function(session) {
  goog.base(this, session);
};
goog.inherits(e2e.otr.message.Signature, e2e.otr.message.Message);

/**
 * Specifies the type of the message.
 * @type {!e2e.otr.Byte}
 */
e2e.otr.message.Signature.MESSAGE_TYPE = constants.MessageType.SIGNATURE;

/**
 * Serialize the SIGNATURE into a Uint8Array.
 * @return {!Uint8Array} The serialized SIGNATURE.
 */
e2e.otr.message.Signature.prototype.serializeMessageContent = function() {
  var keys = this.session_.deriveKeyValues();
  var keyA = this.session_.keymanager.getKey();
  var ma = new goog.crypt.Hmac(new e2e.hash.Sha256(), keys.m1prime)
      .getHmac(Array.apply([], e2e.otr.serializeBytes([
        keyA.key.generate(),
        this.session_.keymanager.getRemoteKey(new Uint8Array(4)).key,
        this.session_.getPublicKey(),
        keyA.keyid
      ])));

  var xa = Array.apply([], e2e.otr.serializeBytes([
    this.session_.getPublicKey(),
    keyA.keyid,
    new (this.session_.getSigner())(ma)
  ]));

  var sig = new e2e.otr.Data(
      e2e.otr.util.aes128ctr.encrypt(keys.cprime, xa));

  var mac = new goog.crypt.Hmac(new e2e.hash.Sha256(), keys.m2prime)
      .getHmac(Array.apply([], sig.serialize()));

  mac = mac.slice(0, 160 / 8);

  return e2e.otr.serializeBytes([sig, mac]);
};

/**
 * Processes a SIGNATURE message.
 * @param {!e2e.otr.Session} session The enclosing session.
 * @param {!Uint8Array} data The data to be processed.
 */
e2e.otr.message.Signature.process = function(session, data) {
  switch (session.getAuthState()) {
    case AUTHSTATE.AWAITING_SIG:
      var iter = new e2e.otr.util.Iterator(data);
      var aesxa = iter.nextEncoded();
      var mac = iter.next(20);

      var keys = session.deriveKeyValues();

      var calculatedMac = new goog.crypt.Hmac(new e2e.hash.Sha256(),
          keys.m2prime).getHmac(Array.apply([], aesxa));

      calculatedMac = calculatedMac.slice(0, 160 / 8);

      if (e2e.otr.compareByteArray(mac, calculatedMac)) {
        // TODO(rcc): Log the error and/or warn the user.
        return;
      }

      var xa = e2e.otr.util.aes128ctr.decrypt(keys.cprime,
          e2e.otr.Data.parse(aesxa).deconstruct());

      iter = new e2e.otr.util.Iterator(xa);

      // TODO(rcc): Make Type.parse accept Iterator to pull appropriate data.
      var pubAType = iter.next(2);
      var pubA = {
        p: Array.apply([], iter.nextEncoded()),
        q: Array.apply([], iter.nextEncoded()),
        g: Array.apply([], iter.nextEncoded()),
        y: Array.apply([], iter.nextEncoded())
      };
      var keyidA = iter.next(4);
      var sigma = e2e.otr.Sig.parse(iter.next(40));

      var ma = new goog.crypt.Hmac(new e2e.hash.Sha256(), keys.m1prime)
          .getHmac(Array.apply([], e2e.otr.serializeBytes([
            session.keymanager.getRemoteKey(new Uint8Array(4)).key,
            session.keymanager.getKey().key.generate(),
            pubA,
            keyidA
          ])));

      if (!e2e.otr.Sig.verify(pubA, ma, sigma)) {
        // TODO(rcc): Log the error and/or warn the user.
        return;
      }

      session.setAuthState(AUTHSTATE.NONE);
      session.setMsgState(constants.MSGSTATE.ENCRYPTED);

      // TODO(rcc): Send any stored messages.

      break;

    case AUTHSTATE.NONE:
    case AUTHSTATE.AWAITING_DHKEY:
    case AUTHSTATE.AWAITING_REVEALSIG:
      return;

    default:
      e2e.otr.assertState(false, 'Invalid auth state.');
  }
};
});  // goog.scope
<|endoftext|>


<commit_before>/**
 * jquery.plupload.queue.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

// JSLint defined globals
/*global plupload:false, jQuery:false, alert:false */

(function($) {
	var uploaders = {};

	function _(str) {
		return plupload.translate(str) || str;
	}

	function renderUI(id, target) {
		// Remove all existing non plupload items
		target.contents().each(function(i, node) {
			node = $(node);

			if (!node.is('.plupload')) {
				node.remove();
			}
		});

		target.prepend(
			'
' +
				'
' +
					'
' +
						'
' +
							'
' +
								'
' + _('Select files') + '
' +
								'
' + _('Add files to the upload queue and click the start button.') + '
' +
							'
' +
						'
' +

						'
' +
							'
' +
								'
' + _('Filename') + '
' +
								'

' +
								'
' + _('Status') + '
' +
								'
' + _('Size') + '
' +
								'

' +
							'
' +

							'

' +

							'
' +
								'
' +
									'
' +
										'' + _('Add Files') + '' +
										'' + _('Start Upload') + '' +
									'
' +
									'' +
								'
' +
								'

' +
								'
0%
' +
								'
0 b
' +
								'
' +
									'
' +
										'

' +
									'
' +
								'
' +
								'

' +
							'
' +
						'
' +
					'
' +
				'
' +
				'<input type="hidden" id="' + id + '_count" name="' + id + '_count" value="0" />' +
			'
'
		);
	}

	$.fn.pluploadQueue = function(settings) {
		if (settings) {
			this.each(function() {
				var uploader, target, id;

				target = $(this);
				id = target.attr('id');

				if (!id) {
					id = plupload.guid();
					target.attr('id', id);
				}

				uploader = new plupload.Uploader($.extend({
					dragdrop : true,
					container : id
				}, settings));

				uploaders[id] = uploader;

				function handleStatus(file) {
					var actionClass;

					if (file.status == plupload.DONE) {
						actionClass = 'plupload_done';
					}

					if (file.status == plupload.FAILED) {
						actionClass = 'plupload_failed';
					}

					if (file.status == plupload.QUEUED) {
						actionClass = 'plupload_delete';
					}

					if (file.status == plupload.UPLOADING) {
						actionClass = 'plupload_uploading';
					}

					var icon = $('#' + file.id).attr('class', actionClass).find('a').css('display', 'block');
					if (file.hint) {
						icon.attr('title', file.hint);
					}
				}

				function updateTotalProgress() {
					$('span.plupload_total_status', target).html(uploader.total.percent + '%');
					$('div.plupload_progress_bar', target).css('width', uploader.total.percent + '%');
					$('span.plupload_upload_status', target).text(
						_('Uploaded %d/%d files').replace(/%d\/%d/, uploader.total.uploaded+'/'+uploader.files.length)
					);
				}

				function updateList() {
					var fileList = $('ul.plupload_filelist', target).html(''), inputCount = 0, inputHTML;

					$.each(uploader.files, function(i, file) {
						inputHTML = '';

						if (file.status == plupload.DONE) {
							if (file.target_name) {
								inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_tmpname" value="' + plupload.xmlEncode(file.target_name) + '" />';
							}

							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_name" value="' + plupload.xmlEncode(file.name) + '" />';
							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_status" value="' + (file.status == plupload.DONE ? 'done' : 'failed') + '" />';

							inputCount++;

							$('#' + id + '_count').val(inputCount);
						}

						fileList.append(
							'
' +
								'
' + file.name + '
' +
								'

' +
								'
' + file.percent + '%
' +
								'
' + plupload.formatSize(file.size) + '
' +
								'

' +
								inputHTML +
							'
'
						);

						handleStatus(file);

						$('#' + file.id + '.plupload_delete a').click(function(e) {
							$('#' + file.id).remove();
							uploader.removeFile(file);

							e.preventDefault();
						});
					});

					$('span.plupload_total_file_size', target).html(plupload.formatSize(uploader.total.size));

					if (uploader.total.queued === 0) {
						$('span.plupload_add_text', target).text(_('Add Files'));
					} else {
						$('span.plupload_add_text', target).text(_('%d files queued').replace(/%d/, uploader.total.queued));
					}

					$('a.plupload_start', target).toggleClass('plupload_disabled', uploader.files.length == (uploader.total.uploaded + uploader.total.failed));

					// Scroll to end of file list
					fileList[0].scrollTop = fileList[0].scrollHeight;

					updateTotalProgress();

					// Re-add drag message if there is no files
					if (!uploader.files.length && uploader.features.dragdrop && uploader.settings.dragdrop) {
						$('#' + id + '_filelist').append('
' + _("Drag files here.") + '
');
					}
				}

				uploader.bind("UploadFile", function(up, file) {
					$('#' + file.id).addClass('plupload_current_file');
				});

				uploader.bind('Init', function(up, res) {
					renderUI(id, target);

					// Enable rename support
					if (!settings.unique_names && settings.rename) {
						$('#' + id + '_filelist div.plupload_file_name span', target).delegate('', 'click', function(e) {
							var targetSpan = $(e.target), file, parts, name, ext = "";

							// Get file name and split out name and extension
							file = up.getFile(targetSpan.parents('li')[0].id);
							name = file.name;
							parts = /^(.+)(\.[^.]+)$/.exec(name);
							if (parts) {
								name = parts[1];
								ext = parts[2];
							}

							// Display input element
							targetSpan.hide().after('<input type="text" />');
							targetSpan.next().val(name).focus().blur(function() {
								targetSpan.show().next().remove();
							}).keydown(function(e) {
								var targetInput = $(this);

								if (e.keyCode == 13) {
									e.preventDefault();

									// Rename file and glue extension back on
									file.name = targetInput.val() + ext;
									targetSpan.text(file.name);
									targetInput.blur();
								}
							});
						});
					}

					$('a.plupload_add', target).attr('id', id + '_browse');

					up.settings.browse_button = id + '_browse';

					// Enable drag/drop (see PostInit handler as well)
					if (up.settings.dragdrop) {
						up.settings.drop_element = id + '_filelist';
					}

					$('#' + id + '_container').attr('title', 'Using runtime: ' + res.runtime);

					$('a.plupload_start', target).click(function(e) {
						if (!$(this).hasClass('plupload_disabled')) {
							uploader.start();
						}

						e.preventDefault();
					});

					$('a.plupload_stop', target).click(function(e) {
						e.preventDefault();
						uploader.stop();
					});

					$('a.plupload_start', target).addClass('plupload_disabled');
				});

				uploader.bind("PostInit", function(up) {
					// features are populated only after input components are fully instantiated
					if (up.settings.dragdrop && up.features.dragdrop) {
						$('#' + id + '_filelist').append('
' + _("Drag files here.") + '
');
					}
				});

				uploader.init();

				uploader.bind("Error", function(up, err) {
					var file = err.file, message;

					if (file) {
						message = err.message;

						if (err.details) {
							message += " (" + err.details + ")";
						}

						if (err.code == plupload.FILE_SIZE_ERROR) {
							alert(_("Error: File too large:") + " " + file.name);
						}

						if (err.code == plupload.FILE_EXTENSION_ERROR) {
							alert(_("Error: Invalid file extension:") + " " + file.name);
						}

						file.hint = message;
						$('#' + file.id).attr('class', 'plupload_failed').find('a').css('display', 'block').attr('title', message);
					}
				});

				uploader.bind('StateChanged', function() {
					if (uploader.state === plupload.STARTED) {
						$('li.plupload_delete a,div.plupload_buttons', target).hide();
						$('span.plupload_upload_status,div.plupload_progress,a.plupload_stop', target).css('display', 'block');
						$('span.plupload_upload_status', target).text('Uploaded ' + uploader.total.uploaded + '/' + uploader.files.length + ' files');

						if (settings.multiple_queues) {
							$('span.plupload_total_status,span.plupload_total_file_size', target).show();
						}
					} else {
						updateList();
						$('a.plupload_stop,div.plupload_progress', target).hide();
						$('a.plupload_delete', target).css('display', 'block');
					}
				});

				uploader.bind('QueueChanged', updateList);

				uploader.bind('FileUploaded', function(up, file) {
					handleStatus(file);
				});

				uploader.bind("UploadProgress", function(up, file) {
					// Set file specific progress
					$('#' + file.id + ' div.plupload_file_status', target).html(file.percent + '%');

					handleStatus(file);
					updateTotalProgress();

					if (settings.multiple_queues && uploader.total.uploaded + uploader.total.failed == uploader.files.length) {
						$(".plupload_buttons,.plupload_upload_status", target).css("display", "inline");
						$(".plupload_start", target).addClass("plupload_disabled");
						$('span.plupload_total_status,span.plupload_total_file_size', target).hide();
					}
				});

				// Call setup function
				if (settings.setup) {
					settings.setup(uploader);
				}
			});

			return this;
		} else {
			// Get uploader instance for specified element
			return uploaders[$(this[0]).attr('id')];
		}
	};
})(jQuery);
<commit_msg>Queue: Use on() instead of delegate() or live(). Requires jQuery 1.7+.<commit_after>/**
 * jquery.plupload.queue.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

// JSLint defined globals
/*global plupload:false, jQuery:false, alert:false */

(function($) {
	var uploaders = {};

	function _(str) {
		return plupload.translate(str) || str;
	}

	function renderUI(id, target) {
		// Remove all existing non plupload items
		target.contents().each(function(i, node) {
			node = $(node);

			if (!node.is('.plupload')) {
				node.remove();
			}
		});

		target.prepend(
			'
' +
				'
' +
					'
' +
						'
' +
							'
' +
								'
' + _('Select files') + '
' +
								'
' + _('Add files to the upload queue and click the start button.') + '
' +
							'
' +
						'
' +

						'
' +
							'
' +
								'
' + _('Filename') + '
' +
								'

' +
								'
' + _('Status') + '
' +
								'
' + _('Size') + '
' +
								'

' +
							'
' +

							'

' +

							'
' +
								'
' +
									'
' +
										'' + _('Add Files') + '' +
										'' + _('Start Upload') + '' +
									'
' +
									'' +
								'
' +
								'

' +
								'
0%
' +
								'
0 b
' +
								'
' +
									'
' +
										'

' +
									'
' +
								'
' +
								'

' +
							'
' +
						'
' +
					'
' +
				'
' +
				'<input type="hidden" id="' + id + '_count" name="' + id + '_count" value="0" />' +
			'
'
		);
	}

	$.fn.pluploadQueue = function(settings) {
		if (settings) {
			this.each(function() {
				var uploader, target, id;

				target = $(this);
				id = target.attr('id');

				if (!id) {
					id = plupload.guid();
					target.attr('id', id);
				}

				uploader = new plupload.Uploader($.extend({
					dragdrop : true,
					container : id
				}, settings));

				uploaders[id] = uploader;

				function handleStatus(file) {
					var actionClass;

					if (file.status == plupload.DONE) {
						actionClass = 'plupload_done';
					}

					if (file.status == plupload.FAILED) {
						actionClass = 'plupload_failed';
					}

					if (file.status == plupload.QUEUED) {
						actionClass = 'plupload_delete';
					}

					if (file.status == plupload.UPLOADING) {
						actionClass = 'plupload_uploading';
					}

					var icon = $('#' + file.id).attr('class', actionClass).find('a').css('display', 'block');
					if (file.hint) {
						icon.attr('title', file.hint);
					}
				}

				function updateTotalProgress() {
					$('span.plupload_total_status', target).html(uploader.total.percent + '%');
					$('div.plupload_progress_bar', target).css('width', uploader.total.percent + '%');
					$('span.plupload_upload_status', target).text(
						_('Uploaded %d/%d files').replace(/%d\/%d/, uploader.total.uploaded+'/'+uploader.files.length)
					);
				}

				function updateList() {
					var fileList = $('ul.plupload_filelist', target).html(''), inputCount = 0, inputHTML;

					$.each(uploader.files, function(i, file) {
						inputHTML = '';

						if (file.status == plupload.DONE) {
							if (file.target_name) {
								inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_tmpname" value="' + plupload.xmlEncode(file.target_name) + '" />';
							}

							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_name" value="' + plupload.xmlEncode(file.name) + '" />';
							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_status" value="' + (file.status == plupload.DONE ? 'done' : 'failed') + '" />';

							inputCount++;

							$('#' + id + '_count').val(inputCount);
						}

						fileList.append(
							'
' +
								'
' + file.name + '
' +
								'

' +
								'
' + file.percent + '%
' +
								'
' + plupload.formatSize(file.size) + '
' +
								'

' +
								inputHTML +
							'
'
						);

						handleStatus(file);

						$('#' + file.id + '.plupload_delete a').click(function(e) {
							$('#' + file.id).remove();
							uploader.removeFile(file);

							e.preventDefault();
						});
					});

					$('span.plupload_total_file_size', target).html(plupload.formatSize(uploader.total.size));

					if (uploader.total.queued === 0) {
						$('span.plupload_add_text', target).text(_('Add Files'));
					} else {
						$('span.plupload_add_text', target).text(_('%d files queued').replace(/%d/, uploader.total.queued));
					}

					$('a.plupload_start', target).toggleClass('plupload_disabled', uploader.files.length == (uploader.total.uploaded + uploader.total.failed));

					// Scroll to end of file list
					fileList[0].scrollTop = fileList[0].scrollHeight;

					updateTotalProgress();

					// Re-add drag message if there is no files
					if (!uploader.files.length && uploader.features.dragdrop && uploader.settings.dragdrop) {
						$('#' + id + '_filelist').append('
' + _("Drag files here.") + '
');
					}
				}

				uploader.bind("UploadFile", function(up, file) {
					$('#' + file.id).addClass('plupload_current_file');
				});

				uploader.bind('Init', function(up, res) {
					renderUI(id, target);

					// Enable rename support
					if (!settings.unique_names && settings.rename) {
						target.on('click', '#' + id + '_filelist div.plupload_file_name span', function(e) {
							var targetSpan = $(e.target), file, parts, name, ext = "";

							// Get file name and split out name and extension
							file = up.getFile(targetSpan.parents('li')[0].id);
							name = file.name;
							parts = /^(.+)(\.[^.]+)$/.exec(name);
							if (parts) {
								name = parts[1];
								ext = parts[2];
							}

							// Display input element
							targetSpan.hide().after('<input type="text" />');
							targetSpan.next().val(name).focus().blur(function() {
								targetSpan.show().next().remove();
							}).keydown(function(e) {
								var targetInput = $(this);

								if (e.keyCode == 13) {
									e.preventDefault();

									// Rename file and glue extension back on
									file.name = targetInput.val() + ext;
									targetSpan.text(file.name);
									targetInput.blur();
								}
							});
						});
					}

					$('a.plupload_add', target).attr('id', id + '_browse');

					up.settings.browse_button = id + '_browse';

					// Enable drag/drop (see PostInit handler as well)
					if (up.settings.dragdrop) {
						up.settings.drop_element = id + '_filelist';
					}

					$('#' + id + '_container').attr('title', 'Using runtime: ' + res.runtime);

					$('a.plupload_start', target).click(function(e) {
						if (!$(this).hasClass('plupload_disabled')) {
							uploader.start();
						}

						e.preventDefault();
					});

					$('a.plupload_stop', target).click(function(e) {
						e.preventDefault();
						uploader.stop();
					});

					$('a.plupload_start', target).addClass('plupload_disabled');
				});

				uploader.bind("PostInit", function(up) {
					// features are populated only after input components are fully instantiated
					if (up.settings.dragdrop && up.features.dragdrop) {
						$('#' + id + '_filelist').append('
' + _("Drag files here.") + '
');
					}
				});

				uploader.init();

				uploader.bind("Error", function(up, err) {
					var file = err.file, message;

					if (file) {
						message = err.message;

						if (err.details) {
							message += " (" + err.details + ")";
						}

						if (err.code == plupload.FILE_SIZE_ERROR) {
							alert(_("Error: File too large:") + " " + file.name);
						}

						if (err.code == plupload.FILE_EXTENSION_ERROR) {
							alert(_("Error: Invalid file extension:") + " " + file.name);
						}

						file.hint = message;
						$('#' + file.id).attr('class', 'plupload_failed').find('a').css('display', 'block').attr('title', message);
					}
				});

				uploader.bind('StateChanged', function() {
					if (uploader.state === plupload.STARTED) {
						$('li.plupload_delete a,div.plupload_buttons', target).hide();
						$('span.plupload_upload_status,div.plupload_progress,a.plupload_stop', target).css('display', 'block');
						$('span.plupload_upload_status', target).text('Uploaded ' + uploader.total.uploaded + '/' + uploader.files.length + ' files');

						if (settings.multiple_queues) {
							$('span.plupload_total_status,span.plupload_total_file_size', target).show();
						}
					} else {
						updateList();
						$('a.plupload_stop,div.plupload_progress', target).hide();
						$('a.plupload_delete', target).css('display', 'block');
					}
				});

				uploader.bind('QueueChanged', updateList);

				uploader.bind('FileUploaded', function(up, file) {
					handleStatus(file);
				});

				uploader.bind("UploadProgress", function(up, file) {
					// Set file specific progress
					$('#' + file.id + ' div.plupload_file_status', target).html(file.percent + '%');

					handleStatus(file);
					updateTotalProgress();

					if (settings.multiple_queues && uploader.total.uploaded + uploader.total.failed == uploader.files.length) {
						$(".plupload_buttons,.plupload_upload_status", target).css("display", "inline");
						$(".plupload_start", target).addClass("plupload_disabled");
						$('span.plupload_total_status,span.plupload_total_file_size', target).hide();
					}
				});

				// Call setup function
				if (settings.setup) {
					settings.setup(uploader);
				}
			});

			return this;
		} else {
			// Get uploader instance for specified element
			return uploaders[$(this[0]).attr('id')];
		}
	};
})(jQuery);
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2018-2019  The Software Heritage developers
 * See the AUTHORS file at the top-level directory of this distribution
 * License: GNU Affero General Public License version 3, or any later version
 * See top-level LICENSE file for more information
 */

// webpack configuration for compiling static assets in development mode

// import required node modules and webpack plugins
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const BundleTracker = require('webpack-bundle-tracker');
const RobotstxtPlugin = require('robotstxt-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FixSwhSourceMapsPlugin = require('./webpack-plugins/fix-swh-source-maps-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const GenerateWebLabelsPlugin = require('./webpack-plugins/generate-weblabels-webpack-plugin');

// are we running webpack-dev-server ?
const isDevServer = process.argv.find(v => v.includes('webpack-dev-server'));
// webpack-dev-server configuration
const devServerPort = 3000;
const devServerPublicPath = 'http://localhost:' + devServerPort + '/static/';
// set publicPath according if we are using webpack-dev-server to serve
// our assets or not
const publicPath = isDevServer ? devServerPublicPath : '/static/';

const nodeModules = path.resolve(__dirname, '../../../../node_modules/');

// collect all bundles we want to produce with webpack
var bundles = {};
const bundlesDir = path.join(__dirname, '../src/bundles');
fs.readdirSync(bundlesDir).forEach(file => {
  bundles[file] = ['bundles/' + file + '/index.js'];
});

// common loaders for css related assets (css, sass, less)
let cssLoaders = [
  MiniCssExtractPlugin.loader,
  {
    loader: 'cache-loader'
  },
  {
    loader: 'css-loader',
    options: {
      sourceMap: !isDevServer
    }
  },
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      sourceMap: !isDevServer,
      plugins: [
        // lint swh-web stylesheets
        require('stylelint')({
          'config': {
            'extends': 'stylelint-config-standard',
            'rules': {
              'indentation': 4,
              'font-family-no-missing-generic-family-keyword': null,
              'no-descending-specificity': null
            },
            'ignoreFiles': ['node_modules/**/*.css',
                            'swh/web/assets/src/thirdparty/**/*.css']
          }
        }),
        // automatically add vendor prefixes to css rules
        require('autoprefixer')(),
        require('postcss-normalize')()
      ]
    }
  }
];

// webpack development configuration
module.exports = {
  // use caching to speedup incremental builds
  cache: true,
  // set mode to development
  mode: 'development',
  // use eval source maps when using webpack-dev-server for quick debugging,
  // otherwise generate source map files (more expensive)
  devtool: isDevServer ? 'eval' : 'source-map',
  // webpack-dev-server configuration
  devServer: {
    clientLogLevel: 'warning',
    port: devServerPort,
    publicPath: devServerPublicPath,
    // enable to serve static assets not managed by webpack
    contentBase: path.resolve('./swh/web/'),
    // we do not use hot reloading here (as a framework like React needs to be used in order to fully benefit from that feature)
    // and prefere to fully reload the frontend application in the browser instead
    hot: false,
    inline: true,
    historyApiFallback: true,
    headers: {
      'Access-Control-Allow-Origin': '*'
    },
    compress: true,
    stats: {
      colors: true
    },
    overlay: {
      warnings: true,
      errors: true
    }
  },
  // set entries to the bundles we want to produce
  entry: bundles,
  // assets output configuration
  output: {
    path: path.resolve('./swh/web/static/'),
    filename: 'js/[name].[chunkhash].js',
    chunkFilename: 'js/[name].[chunkhash].js',
    publicPath: publicPath,
    // each bundle will be compiled as a umd module with its own namespace
    // in order to easily use them in django templates
    library: ['swh', '[name]'],
    libraryTarget: 'umd'
  },
  // module resolving configuration
  resolve: {
    // alias pdfjs to its minified version
    alias: {
      'pdfjs-dist': 'pdfjs-dist/build/pdf.min.js'
    },
    // configure base paths for resolving modules with webpack
    modules: [
      'node_modules',
      path.resolve(__dirname, '../src')
    ]
  },
  // module import configuration
  module: {
    rules: [
      {
      // Preprocess all js files with eslint for consistent code style
      // and avoid bad js development practices.
        enforce: 'pre',
        test: /\.js$/,
        exclude: /node_modules/,
        use: [{
          loader: 'eslint-loader',
          options: {
            configFile: path.join(__dirname, '.eslintrc'),
            ignorePath: path.join(__dirname, '.eslintignore'),
            emitWarning: true
          }
        }]
      },
      {
      // Use babel-loader in order to use es6 syntax in js files
      // but also advanced js features like async/await syntax.
      // All code get transpiled to es5 in order to be executed
      // in a large majority of browsers.
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'babel-loader',
            options: {
              presets: [
                // use env babel presets to benefit from es6 syntax
                ['@babel/preset-env', {
                  // Do not transform es6 module syntax to another module type
                  // in order to benefit from dead code elimination (aka tree shaking)
                  // when running webpack in production mode
                  'loose': true,
                  'modules': false
                }]
              ],
              plugins: [
              // use babel transform-runtime plugin in order to use aync/await syntax
                ['@babel/plugin-transform-runtime', {
                  'corejs': 2,
                  'regenerator': true
                }],
                // use other babel plugins to benefit from advanced js features (es2017)
                '@babel/plugin-syntax-dynamic-import'
              ]
            }
          }]
      },
      // expose jquery to the global context as $ and jQuery when importing it
      {
        test: require.resolve('jquery'),
        use: [{
          loader: 'expose-loader',
          options: 'jQuery'
        }, {
          loader: 'expose-loader',
          options: '$'
        }]
      },
      // expose highlightjs to the global context as hljs when importing it
      {
        test: require.resolve('highlight.js'),
        use: [{
          loader: 'expose-loader',
          options: 'hljs'
        }]
      },
      {
        test: require.resolve('js-cookie'),
        use: [{
          loader: 'expose-loader',
          options: 'Cookies'
        }]
      },
      // css import configuration:
      //  - first process it with postcss
      //  - then extract it to a dedicated file associated to each bundle
      {
        test: /\.css$/,
        use: cssLoaders
      },
      // sass import configuration:
      //  - generate css with sass-loader
      //  - process it with postcss
      //  - then extract it to a dedicated file associated to each bundle
      {
        test: /\.scss$/,
        use: cssLoaders.concat([
          {
            loader: 'sass-loader',
            options: {
              sourceMap: !isDevServer
            }
          }
        ])
      },
      // less import configuration:
      //  - generate css with less-loader
      //  - process it with postcss
      //  - then extract it to a dedicated file associated to each bundle
      {
        test: /\.less$/,
        use: cssLoaders.concat([
          {
            loader: 'less-loader',
            options: {
              sourceMap: !isDevServer
            }
          }
        ])
      },
      // web fonts import configuration
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }, {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }, {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }, {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }, {
        test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }
    ],
    // tell webpack to not parse minified pdfjs file to speedup build process
    noParse: [path.resolve(nodeModules, 'pdfjs-dist/build/pdf.min.js')]
  },
  // webpack plugins
  plugins: [
    // cleanup previously generated assets
    new CleanWebpackPlugin({
      verbose: true,
      cleanOnceBeforeBuildPatterns: ['**/*', '!xml', '!xml/*', '!img', '!img/*',
                                     '!img/logos', '!img/logos/*', '!img/icons',
                                     '!img/icons/*']
    }),
    // needed in order to use django_webpack_loader
    new BundleTracker({
      filename: './swh/web/static/webpack-stats.json'
    }),
    // for generating the robots.txt file
    new RobotstxtPlugin({
      policy: [{
        userAgent: '*',
        disallow: '/api/'
      }]
    }),
    // for extracting all stylesheets in separate css files
    new MiniCssExtractPlugin({
      filename: 'css/[name].[chunkhash].css',
      chunkFilename: 'css/[name].[chunkhash].css'
    }),
    // fix generated asset sourcemaps to workaround a Firefox issue
    new FixSwhSourceMapsPlugin(),
    // define some global variables accessible from js code
    new webpack.DefinePlugin({
      __STATIC__: JSON.stringify(publicPath)
    }),
    // needed in order to use bootstrap 4.x
    new webpack.ProvidePlugin({
      Popper: ['popper.js', 'default'],
      Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
      Button: 'exports-loader?Button!bootstrap/js/dist/button',
      Carousel: 'exports-loader?Carousel!bootstrap/js/dist/carousel',
      Collapse: 'exports-loader?Collapse!bootstrap/js/dist/collapse',
      Dropdown: 'exports-loader?Dropdown!bootstrap/js/dist/dropdown',
      Modal: 'exports-loader?Modal!bootstrap/js/dist/modal',
      Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
      Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
      Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',
      Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip',
      Util: 'exports-loader?Util!bootstrap/js/dist/util'
    }),
    // needed in order to use pdf.js
    new webpack.IgnorePlugin(/^\.\/pdf.worker.js$/),
    new CopyWebpackPlugin([{
      from: path.resolve(nodeModules, 'pdfjs-dist/build/pdf.worker.min.js'),
      to: path.resolve(__dirname, '../../static/js/')
    }]),
    new GenerateWebLabelsPlugin({
      outputType: 'json',
      exclude: ['mini-css-extract-plugin',
                'bootstrap-loader'],
      srcReplace: {
        './node_modules/pdfjs-dist/build/pdf.min.js':
        './node_modules/pdfjs-dist/build/pdf.js',
        './node_modules/admin-lte/dist/js/adminlte.min.js':
        './node_modules/admin-lte/dist/js/adminlte.js'
      },
      licenseOverride: {
        './swh/web/assets/src/thirdparty/highlightjs-line-numbers/highlightjs-line-numbers.js': {
          'spdxLicenseExpression': 'MIT',
          'licenseFilePath': './swh/web/assets/src/thirdparty/highlightjs-line-numbers/LICENSE'
        },
        './swh/web/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js': {
          'spdxLicenseExpression': 'GPL-3.0',
          'licenseFilePath': './swh/web/assets/src/thirdparty/jquery.tabSlideOut/LICENSE'
        }
      },
      additionalScripts: {
        'js/pdf.worker.min.js': [
          {
            'id': 'pdfjs-dist/build/pdf.worker.js',
            'path': './node_modules/pdfjs-dist/build/pdf.worker.js',
            'spdxLicenseExpression': 'Apache-2.0',
            'licenseFilePath': './node_modules/pdfjs-dist/LICENSE'

          }
        ]
      }
    })
  ],
  // webpack optimizations
  optimization: {
    // ensure the vendors bundle gets emitted in a single chunk
    splitChunks: {
      cacheGroups: {
        vendors: {
          test: 'vendors',
          chunks: 'all',
          name: 'vendors',
          enforce: true
        }
      }
    }
  },
  // disable webpack warnings about bundle sizes
  performance: {
    hints: false
  }
};
<commit_msg>webpack: Remove verbose output of CleanWebpackPlugin<commit_after>/**
 * Copyright (C) 2018-2019  The Software Heritage developers
 * See the AUTHORS file at the top-level directory of this distribution
 * License: GNU Affero General Public License version 3, or any later version
 * See top-level LICENSE file for more information
 */

// webpack configuration for compiling static assets in development mode

// import required node modules and webpack plugins
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const BundleTracker = require('webpack-bundle-tracker');
const RobotstxtPlugin = require('robotstxt-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FixSwhSourceMapsPlugin = require('./webpack-plugins/fix-swh-source-maps-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const GenerateWebLabelsPlugin = require('./webpack-plugins/generate-weblabels-webpack-plugin');

// are we running webpack-dev-server ?
const isDevServer = process.argv.find(v => v.includes('webpack-dev-server'));
// webpack-dev-server configuration
const devServerPort = 3000;
const devServerPublicPath = 'http://localhost:' + devServerPort + '/static/';
// set publicPath according if we are using webpack-dev-server to serve
// our assets or not
const publicPath = isDevServer ? devServerPublicPath : '/static/';

const nodeModules = path.resolve(__dirname, '../../../../node_modules/');

// collect all bundles we want to produce with webpack
var bundles = {};
const bundlesDir = path.join(__dirname, '../src/bundles');
fs.readdirSync(bundlesDir).forEach(file => {
  bundles[file] = ['bundles/' + file + '/index.js'];
});

// common loaders for css related assets (css, sass, less)
let cssLoaders = [
  MiniCssExtractPlugin.loader,
  {
    loader: 'cache-loader'
  },
  {
    loader: 'css-loader',
    options: {
      sourceMap: !isDevServer
    }
  },
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      sourceMap: !isDevServer,
      plugins: [
        // lint swh-web stylesheets
        require('stylelint')({
          'config': {
            'extends': 'stylelint-config-standard',
            'rules': {
              'indentation': 4,
              'font-family-no-missing-generic-family-keyword': null,
              'no-descending-specificity': null
            },
            'ignoreFiles': ['node_modules/**/*.css',
                            'swh/web/assets/src/thirdparty/**/*.css']
          }
        }),
        // automatically add vendor prefixes to css rules
        require('autoprefixer')(),
        require('postcss-normalize')()
      ]
    }
  }
];

// webpack development configuration
module.exports = {
  // use caching to speedup incremental builds
  cache: true,
  // set mode to development
  mode: 'development',
  // use eval source maps when using webpack-dev-server for quick debugging,
  // otherwise generate source map files (more expensive)
  devtool: isDevServer ? 'eval' : 'source-map',
  // webpack-dev-server configuration
  devServer: {
    clientLogLevel: 'warning',
    port: devServerPort,
    publicPath: devServerPublicPath,
    // enable to serve static assets not managed by webpack
    contentBase: path.resolve('./swh/web/'),
    // we do not use hot reloading here (as a framework like React needs to be used in order to fully benefit from that feature)
    // and prefere to fully reload the frontend application in the browser instead
    hot: false,
    inline: true,
    historyApiFallback: true,
    headers: {
      'Access-Control-Allow-Origin': '*'
    },
    compress: true,
    stats: {
      colors: true
    },
    overlay: {
      warnings: true,
      errors: true
    }
  },
  // set entries to the bundles we want to produce
  entry: bundles,
  // assets output configuration
  output: {
    path: path.resolve('./swh/web/static/'),
    filename: 'js/[name].[chunkhash].js',
    chunkFilename: 'js/[name].[chunkhash].js',
    publicPath: publicPath,
    // each bundle will be compiled as a umd module with its own namespace
    // in order to easily use them in django templates
    library: ['swh', '[name]'],
    libraryTarget: 'umd'
  },
  // module resolving configuration
  resolve: {
    // alias pdfjs to its minified version
    alias: {
      'pdfjs-dist': 'pdfjs-dist/build/pdf.min.js'
    },
    // configure base paths for resolving modules with webpack
    modules: [
      'node_modules',
      path.resolve(__dirname, '../src')
    ]
  },
  // module import configuration
  module: {
    rules: [
      {
      // Preprocess all js files with eslint for consistent code style
      // and avoid bad js development practices.
        enforce: 'pre',
        test: /\.js$/,
        exclude: /node_modules/,
        use: [{
          loader: 'eslint-loader',
          options: {
            configFile: path.join(__dirname, '.eslintrc'),
            ignorePath: path.join(__dirname, '.eslintignore'),
            emitWarning: true
          }
        }]
      },
      {
      // Use babel-loader in order to use es6 syntax in js files
      // but also advanced js features like async/await syntax.
      // All code get transpiled to es5 in order to be executed
      // in a large majority of browsers.
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'babel-loader',
            options: {
              presets: [
                // use env babel presets to benefit from es6 syntax
                ['@babel/preset-env', {
                  // Do not transform es6 module syntax to another module type
                  // in order to benefit from dead code elimination (aka tree shaking)
                  // when running webpack in production mode
                  'loose': true,
                  'modules': false
                }]
              ],
              plugins: [
              // use babel transform-runtime plugin in order to use aync/await syntax
                ['@babel/plugin-transform-runtime', {
                  'corejs': 2,
                  'regenerator': true
                }],
                // use other babel plugins to benefit from advanced js features (es2017)
                '@babel/plugin-syntax-dynamic-import'
              ]
            }
          }]
      },
      // expose jquery to the global context as $ and jQuery when importing it
      {
        test: require.resolve('jquery'),
        use: [{
          loader: 'expose-loader',
          options: 'jQuery'
        }, {
          loader: 'expose-loader',
          options: '$'
        }]
      },
      // expose highlightjs to the global context as hljs when importing it
      {
        test: require.resolve('highlight.js'),
        use: [{
          loader: 'expose-loader',
          options: 'hljs'
        }]
      },
      {
        test: require.resolve('js-cookie'),
        use: [{
          loader: 'expose-loader',
          options: 'Cookies'
        }]
      },
      // css import configuration:
      //  - first process it with postcss
      //  - then extract it to a dedicated file associated to each bundle
      {
        test: /\.css$/,
        use: cssLoaders
      },
      // sass import configuration:
      //  - generate css with sass-loader
      //  - process it with postcss
      //  - then extract it to a dedicated file associated to each bundle
      {
        test: /\.scss$/,
        use: cssLoaders.concat([
          {
            loader: 'sass-loader',
            options: {
              sourceMap: !isDevServer
            }
          }
        ])
      },
      // less import configuration:
      //  - generate css with less-loader
      //  - process it with postcss
      //  - then extract it to a dedicated file associated to each bundle
      {
        test: /\.less$/,
        use: cssLoaders.concat([
          {
            loader: 'less-loader',
            options: {
              sourceMap: !isDevServer
            }
          }
        ])
      },
      // web fonts import configuration
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }, {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }, {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }, {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }, {
        test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        }]
      }
    ],
    // tell webpack to not parse minified pdfjs file to speedup build process
    noParse: [path.resolve(nodeModules, 'pdfjs-dist/build/pdf.min.js')]
  },
  // webpack plugins
  plugins: [
    // cleanup previously generated assets
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: ['**/*', '!xml', '!xml/*', '!img', '!img/*',
                                     '!img/logos', '!img/logos/*', '!img/icons',
                                     '!img/icons/*']
    }),
    // needed in order to use django_webpack_loader
    new BundleTracker({
      filename: './swh/web/static/webpack-stats.json'
    }),
    // for generating the robots.txt file
    new RobotstxtPlugin({
      policy: [{
        userAgent: '*',
        disallow: '/api/'
      }]
    }),
    // for extracting all stylesheets in separate css files
    new MiniCssExtractPlugin({
      filename: 'css/[name].[chunkhash].css',
      chunkFilename: 'css/[name].[chunkhash].css'
    }),
    // fix generated asset sourcemaps to workaround a Firefox issue
    new FixSwhSourceMapsPlugin(),
    // define some global variables accessible from js code
    new webpack.DefinePlugin({
      __STATIC__: JSON.stringify(publicPath)
    }),
    // needed in order to use bootstrap 4.x
    new webpack.ProvidePlugin({
      Popper: ['popper.js', 'default'],
      Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
      Button: 'exports-loader?Button!bootstrap/js/dist/button',
      Carousel: 'exports-loader?Carousel!bootstrap/js/dist/carousel',
      Collapse: 'exports-loader?Collapse!bootstrap/js/dist/collapse',
      Dropdown: 'exports-loader?Dropdown!bootstrap/js/dist/dropdown',
      Modal: 'exports-loader?Modal!bootstrap/js/dist/modal',
      Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
      Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
      Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',
      Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip',
      Util: 'exports-loader?Util!bootstrap/js/dist/util'
    }),
    // needed in order to use pdf.js
    new webpack.IgnorePlugin(/^\.\/pdf.worker.js$/),
    new CopyWebpackPlugin([{
      from: path.resolve(nodeModules, 'pdfjs-dist/build/pdf.worker.min.js'),
      to: path.resolve(__dirname, '../../static/js/')
    }]),
    new GenerateWebLabelsPlugin({
      outputType: 'json',
      exclude: ['mini-css-extract-plugin',
                'bootstrap-loader'],
      srcReplace: {
        './node_modules/pdfjs-dist/build/pdf.min.js':
        './node_modules/pdfjs-dist/build/pdf.js',
        './node_modules/admin-lte/dist/js/adminlte.min.js':
        './node_modules/admin-lte/dist/js/adminlte.js'
      },
      licenseOverride: {
        './swh/web/assets/src/thirdparty/highlightjs-line-numbers/highlightjs-line-numbers.js': {
          'spdxLicenseExpression': 'MIT',
          'licenseFilePath': './swh/web/assets/src/thirdparty/highlightjs-line-numbers/LICENSE'
        },
        './swh/web/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js': {
          'spdxLicenseExpression': 'GPL-3.0',
          'licenseFilePath': './swh/web/assets/src/thirdparty/jquery.tabSlideOut/LICENSE'
        }
      },
      additionalScripts: {
        'js/pdf.worker.min.js': [
          {
            'id': 'pdfjs-dist/build/pdf.worker.js',
            'path': './node_modules/pdfjs-dist/build/pdf.worker.js',
            'spdxLicenseExpression': 'Apache-2.0',
            'licenseFilePath': './node_modules/pdfjs-dist/LICENSE'

          }
        ]
      }
    })
  ],
  // webpack optimizations
  optimization: {
    // ensure the vendors bundle gets emitted in a single chunk
    splitChunks: {
      cacheGroups: {
        vendors: {
          test: 'vendors',
          chunks: 'all',
          name: 'vendors',
          enforce: true
        }
      }
    }
  },
  // disable webpack warnings about bundle sizes
  performance: {
    hints: false
  }
};
<|endoftext|>


<commit_before>describe('epo', function() {

    function localStoreageHasData( key ) {
        return localStorage.getItem( key ) !== undefined;
    }

    describe('creating', function() {
        var ls;

        it('initializes with namespace', function() {
            ls = epo('mystash');

            expect( ls ).not.toBeNull();
        });

        it('initializes without namespace', function() {
            ls = epo();

            expect( ls ).not.toBeNull();
        });
    });

    describe('when handling strings', function() {
        var ls, store;

        beforeEach(function() {
            ls = epo('strings');
        });

        it('persists and retrieves simple string', function() {
            var key = 'simple',
                value = 'Simple String';

            ls.set(key, value);

            expect( ls.get(key) ).toEqual( value );
        });

        it('persists and retrieves string with crazy characters', function() {
            var key = 'complex',
                value = 'Some overly c\'omplex string/ with "quoted" and *strred* and & etc...';

            ls.set(key, value);

            expect( ls.get(key) ).toEqual( value );
        });
    });
});<commit_msg>Specs for initialization and #set / #get for strings<commit_after>describe('epo', function() {

    function localStoreageHasData( key ) {
        return localStorage.getItem( key ) !== undefined;
    }

    describe('creating', function() {
        var ls;

        it('initializes with namespace', function() {
            ls = epo('mystash');

            expect( ls ).not.toBeNull();
        });

        it('initializes without namespace', function() {
            ls = epo();

            expect( ls ).not.toBeNull();
        });
    });

    describe('when handling strings', function() {
        var ls, store;

        beforeEach(function() {
            ls = epo('strings');
            localStorage.clear();
        });

        it('persists and retrieves simple string', function() {
            var key = 'simple',
                value = 'Simple String';

            ls.set(key, value);

            expect( ls.get(key) ).toEqual( value );
        });

        it('persists and retrieves string with crazy characters', function() {
            var key = 'complex',
                value = 'Some overly c\'omplex string/ with "quoted" and *strred* and & etc...';

            ls.set(key, value);

            expect( ls.get(key) ).toEqual( value );
        });
    });
});<|endoftext|>


<commit_before>(function () {
  'use strict';

  function ready () {
    $.removeNodes('iframe, #adblock_detect, .popupOverlay');

    var node = $.$('#continuetoimage > form input');
    if (node) {
      // first pass
      _.wait(500).then(function () {
        node.removeAttribute('disabled');
        return _.wait(500);
      }).then(function () {
        // tricky hack, some sites can not receive the click event without focus
        node.focus();
        node.click();
        node.click();
      });
      return;
    }

    // second pass
    var i = $('img[class^=centred]');
    $.openImage(i.src);
  }

  $.register({
    rule: [
      {
        host: [
          // com
          // starts with image
          /^image(ontime|corn|picsa|horse)\.com$/,
          // ends with image
          /^(zonezeed|zelje|croft|myhot|bok|hostur|greasy)image\.com$/,
          // starts with img
          /^img(icy|next|savvy|\.spicyzilla|twyti|xyz|devil|tzar|ban|pu|beer|wet|tornado|kicks|-pay|nimz|binbou|2share|22|cover|hit|main|trial)\.com$/,
          // starts with img-
          /^img-(zone|planet)\.com$/,
          // starts with www
          /^www\.(imagefolks|img(blow|lemon))\.com$/,
          // starts with xxx
          /^xxx(\.pornprimehd|imagenow|screens)\.com$/,
          // else
          /^(picstwist|ericsony|wpc8|uplimg|lexiit|thumbnailus|newimagepost|fapingpics|dimtus|tinizo)\.com$/,
          /^((i|hentai)\.)?imgslip\.com$/,
          /^(i|xxx)\.hentaiyoutube\.com$/,
          /^(go|er)imge\.com$/,
          /^(like\.)?08lkk\.com$/,
          /^(www\.)?\.imgult\.com$/,
          /^nim(plus|zshare)\.com$/,
          /^nudeximg\.com$/,
          /imgseeds?\.com$/,
          /xxxsparrow?\.com$/,
          /damimage\.com$/,
          /imagedecode\.com$/,
          // net
          /^img(serve|coin|fap|candy|master|-view|run|boom|project|python|pics)\.net$/,
          /^(gallerycloud|imagelaser|picture-bang|project-photo|pix-link|funimg|golfpit|xximg)\.net$/,
          // org
          /^(shot|adult)img\.org$/,
          /^img(studio|spot)\.org$/,
          /^image(\.adlock|on|team)\.org$/,
          /^(drag|teen|mega)image\.org$/,
          /^teenshot\.org$/,
          // else
          /^(hotimages|55888)\.eu$/,
          /^img(cloud|mag)\.co$/,
          /^pixup\.us$/,
          /^(bulkimg|photo-up|myimg|pop-img|img-pop|ads-img)\.info$/,
          /^img\.yt$/,
          /^vava\.in$/,
          /^(pixxx|picspornfree|imgload|fapat)\.me$/,
          /^(porno-pirat|24avarii|loftlm|18pron|imgplus)\.ru$/,
          /^www\.hotimage\.uk$/,
          /^imgease\.re$/,
          /^goimg\.xyz$/,
          /^pic2pic\.site$/,
          /^darpix\.ga$/,
          /^sxpics\.nl$/,
          /^darpix\.desi$/,
          /^pic4you\.top$/,
          /^imgsen\.se$/,
        ],
        path: /^\/img-.*\.html/,
      },
      {
        host: [
          /^img(run|twyti)\.net$/,
          /^imgtwyti\.com$/,
        ],
        path: /^\/t\/img-.*\.html/,
      },
      {
        host: /^imgking\.co$/,
        path: /^\/img-.*\.html/,
      },
      {
        host: /^imgbb\.net$/,
        path: /^\/.-.+$/,
      },
    ],
    ready: ready,
  });

  // TODO need to refactor the cookie rule
  $.register({
    rule: {
      host: [
        /^www\.img(taxi|adult|wallet)\.com$/,
        /^www\.imgdrive\.net$/,
      ],
      path: /^\/img-.*\.html$/,
    },
    start: function () {
      var c = $.getCookie('img_c_d') || $.getCookie('img_p_d');
      if (c) {
        return;
      }
      $.post(window.location.href.toString(), {
        cti: 1,
        ref: '',
        rc: 1,
      }).then(function (data) {
        window.location.reload();
      });
    },
    ready: function () {
      $.removeNodes('iframe');

      var node = $.$('#continuetoimage > form input');
      if (node) {
        // first pass
        node.click();
        // somehow imgrun.net need to click twice
        node.click();
        return;
      }

      // the cookies are shared in the whole domain
      // we have to reset cookies to prevent wrong state
      $.resetCookies();

      // second pass
      var i = $('img[class^=centred]');
      $.openImage(i.src);
    },
  });

  function helper () {
    // crack the shitty qqc.co visitScript 5440
    $.window.setTimeout = _.nop;

    // this site checks cookie that caculate from session
    // do an AJAX to skip checking
    return $.get(window.location.toString()).then(function (data) {
      return $.toDOM(data);
    });
  }

  $.register({
    rule: {
      host: /^08lkk\.com$/,
      path: /^\/Photo\/img-.+\.html$/,
    },
    start: function () {
      helper().then(function (page) {
        var i = $('img[class^=centred]', page);
        $.openImage(i.src);
      });
    },
  });

  $.register({
    rule: {
      host: /^08lkk\.com$/,
      path: /^\/\d+\/img-.*\.html$/,
    },
    start: function () {
      helper().then(function (page) {
        var bbcode = $.$('#imagecodes input', page);
        bbcode = bbcode.value.match(/.+\[IMG\]([^\[]+)\[\/IMG\].+/);
        bbcode = bbcode[1];
        bbcode = bbcode.replace('small', 'big');

        $.openImage(bbcode);
      });
    },
  });

  $.register({
    rule: [
      {
        host: /^imgking\.co$/,
        path: /^\/img3-.*\.html/,
      },
      {
        host: /^imgkings\.com$/,
        path: /^\/img-.*\.html/,
      },
    ],
    ready: function () {
      var url = $.window.linkid;
      $.openImage(url);
    },
  });

  $.register({
    rule: [
      {
        host: /^imgking\.co$/,
        path: /^\/img4-.*\.html/,
      },
      {
        host: /^imgkings\.com$/,
        path: /^\/img2-.*\.html/,
      },
    ],
    ready: ready,
  });

})();

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>added naughtygate.net<commit_after>(function () {
  'use strict';

  function ready () {
    $.removeNodes('iframe, #adblock_detect, .popupOverlay');

    var node = $.$('#continuetoimage > form input');
    if (node) {
      // first pass
      _.wait(500).then(function () {
        node.removeAttribute('disabled');
        return _.wait(500);
      }).then(function () {
        // tricky hack, some sites can not receive the click event without focus
        node.focus();
        node.click();
        node.click();
      });
      return;
    }

    // second pass
    var i = $('img[class^=centred]');
    $.openImage(i.src);
  }

  $.register({
    rule: [
      {
        host: [
          // com
          // starts with image
          /^image(ontime|corn|picsa|horse)\.com$/,
          // ends with image
          /^(zonezeed|zelje|croft|myhot|bok|hostur|greasy)image\.com$/,
          // starts with img
          /^img(icy|next|savvy|\.spicyzilla|twyti|xyz|devil|tzar|ban|pu|beer|wet|tornado|kicks|-pay|nimz|binbou|2share|22|cover|hit|main|trial)\.com$/,
          // starts with img-
          /^img-(zone|planet)\.com$/,
          // starts with www
          /^www\.(imagefolks|img(blow|lemon))\.com$/,
          // starts with xxx
          /^xxx(\.pornprimehd|imagenow|screens)\.com$/,
          // else
          /^(picstwist|ericsony|wpc8|uplimg|lexiit|thumbnailus|newimagepost|fapingpics|dimtus|tinizo)\.com$/,
          /^((i|hentai)\.)?imgslip\.com$/,
          /^(i|xxx)\.hentaiyoutube\.com$/,
          /^(go|er)imge\.com$/,
          /^(like\.)?08lkk\.com$/,
          /^(www\.)?\.imgult\.com$/,
          /^nim(plus|zshare)\.com$/,
          /^nudeximg\.com$/,
          /imgseeds?\.com$/,
          /xxxsparrow?\.com$/,
          /damimage\.com$/,
          /imagedecode\.com$/,
          // net
          /^img(serve|coin|fap|candy|master|-view|run|boom|project|python|pics)\.net$/,
          /^(naughtygate|gallerycloud|imagelaser|picture-bang|project-photo|pix-link|funimg|golfpit|xximg)\.net$/,
          // org
          /^(shot|adult)img\.org$/,
          /^img(studio|spot)\.org$/,
          /^image(\.adlock|on|team)\.org$/,
          /^(drag|teen|mega)image\.org$/,
          /^teenshot\.org$/,
          // else
          /^(hotimages|55888)\.eu$/,
          /^img(cloud|mag)\.co$/,
          /^pixup\.us$/,
          /^(bulkimg|photo-up|myimg|pop-img|img-pop|ads-img)\.info$/,
          /^img\.yt$/,
          /^vava\.in$/,
          /^(pixxx|picspornfree|imgload|fapat)\.me$/,
          /^(porno-pirat|24avarii|loftlm|18pron|imgplus)\.ru$/,
          /^www\.hotimage\.uk$/,
          /^imgease\.re$/,
          /^goimg\.xyz$/,
          /^pic2pic\.site$/,
          /^darpix\.ga$/,
          /^sxpics\.nl$/,
          /^darpix\.desi$/,
          /^pic4you\.top$/,
          /^imgsen\.se$/,
        ],
        path: /^\/img-.*\.html/,
      },
      {
        host: [
          /^img(run|twyti)\.net$/,
          /^imgtwyti\.com$/,
        ],
        path: /^\/t\/img-.*\.html/,
      },
      {
        host: /^imgking\.co$/,
        path: /^\/img-.*\.html/,
      },
      {
        host: /^imgbb\.net$/,
        path: /^\/.-.+$/,
      },
    ],
    ready: ready,
  });

  // TODO need to refactor the cookie rule
  $.register({
    rule: {
      host: [
        /^www\.img(taxi|adult|wallet)\.com$/,
        /^www\.imgdrive\.net$/,
      ],
      path: /^\/img-.*\.html$/,
    },
    start: function () {
      var c = $.getCookie('img_c_d') || $.getCookie('img_p_d');
      if (c) {
        return;
      }
      $.post(window.location.href.toString(), {
        cti: 1,
        ref: '',
        rc: 1,
      }).then(function (data) {
        window.location.reload();
      });
    },
    ready: function () {
      $.removeNodes('iframe');

      var node = $.$('#continuetoimage > form input');
      if (node) {
        // first pass
        node.click();
        // somehow imgrun.net need to click twice
        node.click();
        return;
      }

      // the cookies are shared in the whole domain
      // we have to reset cookies to prevent wrong state
      $.resetCookies();

      // second pass
      var i = $('img[class^=centred]');
      $.openImage(i.src);
    },
  });

  function helper () {
    // crack the shitty qqc.co visitScript 5440
    $.window.setTimeout = _.nop;

    // this site checks cookie that caculate from session
    // do an AJAX to skip checking
    return $.get(window.location.toString()).then(function (data) {
      return $.toDOM(data);
    });
  }

  $.register({
    rule: {
      host: /^08lkk\.com$/,
      path: /^\/Photo\/img-.+\.html$/,
    },
    start: function () {
      helper().then(function (page) {
        var i = $('img[class^=centred]', page);
        $.openImage(i.src);
      });
    },
  });

  $.register({
    rule: {
      host: /^08lkk\.com$/,
      path: /^\/\d+\/img-.*\.html$/,
    },
    start: function () {
      helper().then(function (page) {
        var bbcode = $.$('#imagecodes input', page);
        bbcode = bbcode.value.match(/.+\[IMG\]([^\[]+)\[\/IMG\].+/);
        bbcode = bbcode[1];
        bbcode = bbcode.replace('small', 'big');

        $.openImage(bbcode);
      });
    },
  });

  $.register({
    rule: [
      {
        host: /^imgking\.co$/,
        path: /^\/img3-.*\.html/,
      },
      {
        host: /^imgkings\.com$/,
        path: /^\/img-.*\.html/,
      },
    ],
    ready: function () {
      var url = $.window.linkid;
      $.openImage(url);
    },
  });

  $.register({
    rule: [
      {
        host: /^imgking\.co$/,
        path: /^\/img4-.*\.html/,
      },
      {
        host: /^imgkings\.com$/,
        path: /^\/img2-.*\.html/,
      },
    ],
    ready: ready,
  });

})();

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>/*
 * tabs_options.js
 */
(function($) {

module("tabs: options");

test('ajaxOptions', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('cache', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('collapsible', function() {
	expect(4);

	el = $('#tabs1');

	el.tabs({ collapsible: true });
	equals(el.tabs('option', 'collapsible'), true, 'option set');
	ok(el.is('.ui-tabs-collapsible'), 'extra class "ui-tabs-collapsible" attached');
	el.tabs('select', 0);
	equals($('div.ui-tabs-hide', '#tabs1').length, 3, 'all panels should be hidden');
	el.tabs('option', 'collapsible', false);
	ok(el.is(':not(.ui-tabs-collapsible)'), 'extra class "ui-tabs-collapsible" not attached');

});

test('cookie', function() {
	expect(6);

	el = $('#tabs1');
	var cookieName = 'tabs_test', cookieObj = { name: cookieName };
	$.cookie(cookieName, null); // blank state
	var cookie = function() {
		return parseInt($.cookie(cookieName), 10);
	};

	el.tabs({ cookie: cookieObj });
	equals(cookie(), 0, 'initial cookie value');

	el.tabs('destroy');
	el.tabs({ selected: 1, cookie: cookieObj });
	equals(cookie(), 1, 'initial cookie value, from selected property');

	el.tabs('select', 2);
	equals(cookie(), 2, 'cookie value updated after select');

	el.tabs('destroy');
	$.cookie(cookieName, 1);
	el.tabs({ cookie: cookieObj });
	equals(cookie(), 1, 'initial cookie value, from existing cookie');

	el.tabs('destroy');
	el.tabs({ cookie: cookieObj, collapsible: true });
	el.tabs('select', 0);
	equals(cookie(), -1, 'cookie value for all tabs unselected');

	el.tabs('destroy');
	ok($.cookie(cookieName) === null, 'erase cookie after destroy');

});

// deprecated... shadows collapsible
test('deselectable (deprecated)', function() {
	expect(4);

	el = $('#tabs1');

	el.tabs({ deselectable: true });
	equals(el.tabs('option', 'collapsible'), true, 'option set');
	ok(el.is('.ui-tabs-collapsible'), 'extra class "ui-tabs-collapsible" attached');
	el.tabs('select', 0);
	equals($('div.ui-tabs-hide', '#tabs1').length, 3, 'all panels should be hidden');
	el.tabs('option', 'deselectable', false);
	ok(el.is(':not(.ui-tabs-collapsible)'), 'extra class "ui-tabs-collapsible" not attached');

});

test('disabled', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('event', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('fx', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('idPrefix', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('panelTemplate', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('selected', function() {
	expect(8);

	el = $('#tabs1').tabs();
	equals(el.tabs('option', 'selected'), 0, 'should be 0 by default');

	el.tabs('destroy');
	el.tabs({ selected: -1 });
	equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected');
	equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be selected' );
	equals( $('div.ui-tabs-hide', '#tabs1').length, 3, 'all panels should be hidden' );

	el.tabs('destroy');
	el.tabs({ selected: null });
	equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected with value null (deprecated)');

	el.tabs('destroy');
	el.tabs({ selected: 1 });
	equals(el.tabs('option', 'selected'), 1, 'should be specified tab');

	el.tabs('destroy');
	el.tabs({ selected: 99 });
	equals(el.tabs('option', 'selected'), 0, 'selected should default to zero if given value is out of index');

	el.tabs('destroy');
	el.tabs({ collapsible: true });
	el.tabs('option', 'selected', 0);
	equals(el.tabs('option', 'selected'), 0, 'should not collapse tab if value is same as selected');
});

test('spinner', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('tabTemplate', function() {
	ok(false, "missing test - untested code is broken code.");
});

})(jQuery);
<commit_msg>updated unit test for #4031 - Tabs: Remove deselectable option<commit_after>/*
 * tabs_options.js
 */
(function($) {

module("tabs: options");

test('ajaxOptions', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('cache', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('collapsible', function() {
	expect(4);

	el = $('#tabs1');

	el.tabs({ collapsible: true });
	equals(el.tabs('option', 'collapsible'), true, 'option set');
	ok(el.is('.ui-tabs-collapsible'), 'extra class "ui-tabs-collapsible" attached');
	el.tabs('select', 0);
	equals($('div.ui-tabs-hide', '#tabs1').length, 3, 'all panels should be hidden');
	el.tabs('option', 'collapsible', false);
	ok(el.is(':not(.ui-tabs-collapsible)'), 'extra class "ui-tabs-collapsible" not attached');

});

test('cookie', function() {
	expect(6);

	el = $('#tabs1');
	var cookieName = 'tabs_test', cookieObj = { name: cookieName };
	$.cookie(cookieName, null); // blank state
	var cookie = function() {
		return parseInt($.cookie(cookieName), 10);
	};

	el.tabs({ cookie: cookieObj });
	equals(cookie(), 0, 'initial cookie value');

	el.tabs('destroy');
	el.tabs({ selected: 1, cookie: cookieObj });
	equals(cookie(), 1, 'initial cookie value, from selected property');

	el.tabs('select', 2);
	equals(cookie(), 2, 'cookie value updated after select');

	el.tabs('destroy');
	$.cookie(cookieName, 1);
	el.tabs({ cookie: cookieObj });
	equals(cookie(), 1, 'initial cookie value, from existing cookie');

	el.tabs('destroy');
	el.tabs({ cookie: cookieObj, collapsible: true });
	el.tabs('select', 0);
	equals(cookie(), -1, 'cookie value for all tabs unselected');

	el.tabs('destroy');
	ok($.cookie(cookieName) === null, 'erase cookie after destroy');

});

test('disabled', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('event', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('fx', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('idPrefix', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('panelTemplate', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('selected', function() {
	expect(8);

	el = $('#tabs1').tabs();
	equals(el.tabs('option', 'selected'), 0, 'should be 0 by default');

	el.tabs('destroy');
	el.tabs({ selected: -1 });
	equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected');
	equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be selected' );
	equals( $('div.ui-tabs-hide', '#tabs1').length, 3, 'all panels should be hidden' );

	el.tabs('destroy');
	el.tabs({ selected: null });
	equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected with value null (deprecated)');

	el.tabs('destroy');
	el.tabs({ selected: 1 });
	equals(el.tabs('option', 'selected'), 1, 'should be specified tab');

	el.tabs('destroy');
	el.tabs({ selected: 99 });
	equals(el.tabs('option', 'selected'), 0, 'selected should default to zero if given value is out of index');

	el.tabs('destroy');
	el.tabs({ collapsible: true });
	el.tabs('option', 'selected', 0);
	equals(el.tabs('option', 'selected'), 0, 'should not collapse tab if value is same as selected');
});

test('spinner', function() {
	ok(false, "missing test - untested code is broken code.");
});

test('tabTemplate', function() {
	ok(false, "missing test - untested code is broken code.");
});

})(jQuery);
<|endoftext|>