<commit_before>/*
 * Copyright 2000-2013 Namics AG. All rights reserved.
 */
/**
 * @author: dnyffenegger, Namics AG
 * @since 07.12.13
 */

var MongoClient = require('mongodb').MongoClient
    , ObjectID = require('mongodb').ObjectID
    , _ = require('underscore')
    , moment = require('moment')
    , Q = require('q')
    ;

module.exports = function(settings) {

    var resolveOrReject = function(deferred, err, errMsg, value) {
        if (err) {
            deferred.reject(errMsg + ': ' + err.message);
        } else {
            if (value && typeof value === "function" )
                deferred.resolve(value());
            else
                deferred.resolve(value);
        }
    };

    var getDb = function() {
        var deferred = Q.defer();
        MongoClient.connect(settings.db, function(err, db) {
            resolveOrReject(deferred, err, 'Fehler beim Verbinden auf die Datenbank', db);
        });
        return deferred.promise;
    };

    var getCollection = function(collectionName) {
        return getDb().then(function(db){
            var deferred = Q.defer();
            db.collection(collectionName, function(err, collection){
                var ctx = {collection: collection, db: db};
                resolveOrReject(deferred, err, 'Fehler beim Zugriff auf ' + collectionName, ctx);
            });
            return deferred.promise;
        });
    };

    var findWithCursor = function(collectionName, query, options) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.find(query, options, function(err, cursor){
                ctx.cursor = cursor;
                resolveOrReject(deferred, err, 'Fehler bei der Abfrage von ' + collectionName, ctx);
            });
            return deferred.promise;
        });
    };

    var findAsArray = function(collectionName, query, options) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.find({}, options).toArray(function(err, docs){
                ctx.docs = docs;
                resolveOrReject(deferred, err, 'Fehler bei der Abfrage von ' + collectionName, ctx);
            });
            return deferred.promise;
        });
    };

    // ATTENTION: assumes the there are no orders on days in future
    var getNextOrderNo = function() {
        // select only orders with order numbers
        var query = { no: { $gt: 0} };
        var sort = [
            ['_id', -1], // first by id descending which means the most recent order
            ['no', -1] // then by order number
        ];
        return findWithCursor("orders", query, {sort: sort, limit: 1}).then(function(ctx){
            var deferred = Q.defer();
            ctx.cursor.nextObject(function(err, doc){
                resolveOrReject(deferred, err, 'Fehler beim Bestimmen der nächsten Bestellnummer', function(){
                    var orderNo = 1;
                    if (doc && moment().startOf('day').isBefore(moment(doc._id.getTimestamp()))) {
                        console.log('Found an order today with a order.no: ' + doc.no);
                        orderNo = doc.no + 1;
                    } else {
                        console.log('No orders yet with an no, use 1');
                    }
                    ctx.orderNo = orderNo;
                    return ctx;
                });
            });
            return deferred.promise;
        });
    };

    var getIdQuery = function(id) {
        return {_id: ObjectID(id)}
    };

    var getAllDocsAsArray = function(collectionName, options) {
        return findAsArray(collectionName, {}, options).then(function(ctx){
            var deferred = Q.defer();
            deferred.resolve(ctx.docs);
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });
    };

    var removeDoc = function(collectionName, id) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.remove(getIdQuery(id), {w: 1}, function(err){
                resolveOrReject(deferred, err, 'Fehler beim Löschen des Dokuments mit der Id ' + id + ' von ' + collectionName, {});
            });
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });

    };

    var insertDoc = function(collectionName, doc) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.insert(doc, {w: 1}, function(err, result){
                resolveOrReject(deferred, err, 'Fehler beim Einfügen des Dokuments ' + JSON.stringify(doc) + ' in ' + collectionName, doc);
            });
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });
    };

    var updateDoc = function(collectionName, id, doc) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.update(getIdQuery(id), doc, {w: 1}, function(err, result){
                resolveOrReject(deferred, err, 'Fehler beim Aktualisieren des Dokuments mit der Id ' + id + ' in ' + collectionName, doc);
            });
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });
    };

    var insertOrUpdateDoc = function(collectionName, doc) {
        if (doc._id) {
            var id = doc._id;
            doc._id = ObjectID(doc._id);
            return updateDoc(collectionName, id, doc);
        } else {
            return insertDoc(collectionName, doc);
        }
    };

    var updateAvailability = function(order) {
        var articleIds = _.map(order.articles, function(article) { return ObjectID(article._id); });
        return getCollection('articles').then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.update({_id: {$in: articleIds}, available: {$gt: 0}}, {$inc:{ available: -1}}, {w: 1, multi: true}, function(err, result){
                resolveOrReject(deferred, err, 'Fehler beim Aktualisieren der Verfügbarkeiten', result);
            });
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });
    };

    var prepareOrderForInsert = function(order, nextOrderNo) {
        order.kitchen = _.findWhere(order.articles, {kitchen: true}) != undefined;
        order.articles = _.map(order.articles, function(article){
            return _.pick(article, 'name', 'receipt', 'price', 'ordered', 'kitchen');
        });
        if (order.kitchen) {
            order.no = nextOrderNo;
        }
    };

    var insertOrder = function(order) {
        return updateAvailability(order).then(function(){
            return getNextOrderNo().then(function(ctx){
                var deferred = Q.defer();
                prepareOrderForInsert(order, ctx.orderNo);
                ctx.collection.insert(order, {w: 1}, function(err, result){
                    resolveOrReject(deferred, err, 'Fehler beim Erstellen der Bestellung', order);
                });
                deferred.promise.finally(function(){ ctx.db.close(); });
                return deferred.promise;
            });
        });
    };

    return {
        getSettings: function() {
            return getCollection('settings').then(function(ctx){
                var deferred = Q.defer();
                ctx.collection.findOne({}, {}, function(err, doc){
                    resolveOrReject(deferred, err, 'Fehler beim Abfragen der Einstellungen', doc || {});
                });
                deferred.promise.finally(function(){ ctx.db.close(); });
                return deferred.promise;
            });
        },
        saveSettings: function(settings) {
            return insertOrUpdateDoc('settings', settings);
        },
        getArticles: function() {
            return getAllDocsAsArray('articles', {sort: {name: 1}});
        },
        removeArticle: function(id) {
            return removeDoc('articles', id);
        },
        saveArticle: function(article) {
            return insertOrUpdateDoc('articles', article);
        },

        getOrders: function() {
            return getAllDocsAsArray('orders', {sort: {_id:-1}});
        },
        insertOrder: insertOrder,
        removeOrder: function(id) {
            // TODO: availablity is not updated...!?
            return removeDoc('orders', id);
        },
        removeAllOrders: function() {
            return getCollection('orders').then(function(ctx){
                var deferred = Q.defer();
                ctx.collection.remove({}, {w: 1}, function(err, result){
                    resolveOrReject(deferred, err, 'Fehler beim Löschen aller Bestellungen', result);
                });
                deferred.promise.finally(function(){ ctx.db.close(); });
                return deferred.promise;
            });
        }
    };
};<commit_msg>Removes log statements<commit_after>/*
 * Copyright 2000-2013 Namics AG. All rights reserved.
 */
/**
 * @author: dnyffenegger, Namics AG
 * @since 07.12.13
 */

var MongoClient = require('mongodb').MongoClient
    , ObjectID = require('mongodb').ObjectID
    , _ = require('underscore')
    , moment = require('moment')
    , Q = require('q')
    ;

module.exports = function(settings) {

    var resolveOrReject = function(deferred, err, errMsg, value) {
        if (err) {
            deferred.reject(errMsg + ': ' + err.message);
        } else {
            if (value && typeof value === "function" )
                deferred.resolve(value());
            else
                deferred.resolve(value);
        }
    };

    var getDb = function() {
        var deferred = Q.defer();
        MongoClient.connect(settings.db, function(err, db) {
            resolveOrReject(deferred, err, 'Fehler beim Verbinden auf die Datenbank', db);
        });
        return deferred.promise;
    };

    var getCollection = function(collectionName) {
        return getDb().then(function(db){
            var deferred = Q.defer();
            db.collection(collectionName, function(err, collection){
                var ctx = {collection: collection, db: db};
                resolveOrReject(deferred, err, 'Fehler beim Zugriff auf ' + collectionName, ctx);
            });
            return deferred.promise;
        });
    };

    var findWithCursor = function(collectionName, query, options) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.find(query, options, function(err, cursor){
                ctx.cursor = cursor;
                resolveOrReject(deferred, err, 'Fehler bei der Abfrage von ' + collectionName, ctx);
            });
            return deferred.promise;
        });
    };

    var findAsArray = function(collectionName, query, options) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.find({}, options).toArray(function(err, docs){
                ctx.docs = docs;
                resolveOrReject(deferred, err, 'Fehler bei der Abfrage von ' + collectionName, ctx);
            });
            return deferred.promise;
        });
    };

    // ATTENTION: assumes the there are no orders on days in future
    var getNextOrderNo = function() {
        // select only orders with order numbers
        var query = { no: { $gt: 0} };
        var sort = [
            ['_id', -1], // first by id descending which means the most recent order
            ['no', -1] // then by order number
        ];
        return findWithCursor("orders", query, {sort: sort, limit: 1}).then(function(ctx){
            var deferred = Q.defer();
            ctx.cursor.nextObject(function(err, doc){
                resolveOrReject(deferred, err, 'Fehler beim Bestimmen der nächsten Bestellnummer', function(){
                    var orderNo = 1;
                    if (doc && moment().startOf('day').isBefore(moment(doc._id.getTimestamp()))) {
                        //console.log('Found an order today with a order.no: ' + doc.no);
                        orderNo = doc.no + 1;
                    } else {
                        //console.log('No orders yet with an no, use 1');
                    }
                    ctx.orderNo = orderNo;
                    return ctx;
                });
            });
            return deferred.promise;
        });
    };

    var getIdQuery = function(id) {
        return {_id: ObjectID(id)}
    };

    var getAllDocsAsArray = function(collectionName, options) {
        return findAsArray(collectionName, {}, options).then(function(ctx){
            var deferred = Q.defer();
            deferred.resolve(ctx.docs);
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });
    };

    var removeDoc = function(collectionName, id) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.remove(getIdQuery(id), {w: 1}, function(err){
                resolveOrReject(deferred, err, 'Fehler beim Löschen des Dokuments mit der Id ' + id + ' von ' + collectionName, {});
            });
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });

    };

    var insertDoc = function(collectionName, doc) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.insert(doc, {w: 1}, function(err, result){
                resolveOrReject(deferred, err, 'Fehler beim Einfügen des Dokuments ' + JSON.stringify(doc) + ' in ' + collectionName, doc);
            });
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });
    };

    var updateDoc = function(collectionName, id, doc) {
        return getCollection(collectionName).then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.update(getIdQuery(id), doc, {w: 1}, function(err, result){
                resolveOrReject(deferred, err, 'Fehler beim Aktualisieren des Dokuments mit der Id ' + id + ' in ' + collectionName, doc);
            });
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });
    };

    var insertOrUpdateDoc = function(collectionName, doc) {
        if (doc._id) {
            var id = doc._id;
            doc._id = ObjectID(doc._id);
            return updateDoc(collectionName, id, doc);
        } else {
            return insertDoc(collectionName, doc);
        }
    };

    var updateAvailability = function(order) {
        var articleIds = _.map(order.articles, function(article) { return ObjectID(article._id); });
        return getCollection('articles').then(function(ctx){
            var deferred = Q.defer();
            ctx.collection.update({_id: {$in: articleIds}, available: {$gt: 0}}, {$inc:{ available: -1}}, {w: 1, multi: true}, function(err, result){
                resolveOrReject(deferred, err, 'Fehler beim Aktualisieren der Verfügbarkeiten', result);
            });
            deferred.promise.finally(function(){ ctx.db.close(); });
            return deferred.promise;
        });
    };

    var prepareOrderForInsert = function(order, nextOrderNo) {
        order.kitchen = _.findWhere(order.articles, {kitchen: true}) != undefined;
        order.articles = _.map(order.articles, function(article){
            return _.pick(article, 'name', 'receipt', 'price', 'ordered', 'kitchen');
        });
        if (order.kitchen) {
            order.no = nextOrderNo;
        }
    };

    var insertOrder = function(order) {
        return updateAvailability(order).then(function(){
            return getNextOrderNo().then(function(ctx){
                var deferred = Q.defer();
                prepareOrderForInsert(order, ctx.orderNo);
                ctx.collection.insert(order, {w: 1}, function(err, result){
                    resolveOrReject(deferred, err, 'Fehler beim Erstellen der Bestellung', order);
                });
                deferred.promise.finally(function(){ ctx.db.close(); });
                return deferred.promise;
            });
        });
    };

    return {
        getSettings: function() {
            return getCollection('settings').then(function(ctx){
                var deferred = Q.defer();
                ctx.collection.findOne({}, {}, function(err, doc){
                    resolveOrReject(deferred, err, 'Fehler beim Abfragen der Einstellungen', doc || {});
                });
                deferred.promise.finally(function(){ ctx.db.close(); });
                return deferred.promise;
            });
        },
        saveSettings: function(settings) {
            return insertOrUpdateDoc('settings', settings);
        },
        getArticles: function() {
            return getAllDocsAsArray('articles', {sort: {name: 1}});
        },
        removeArticle: function(id) {
            return removeDoc('articles', id);
        },
        saveArticle: function(article) {
            return insertOrUpdateDoc('articles', article);
        },

        getOrders: function() {
            return getAllDocsAsArray('orders', {sort: {_id:-1}});
        },
        insertOrder: insertOrder,
        removeOrder: function(id) {
            // TODO: availablity is not updated...!?
            return removeDoc('orders', id);
        },
        removeAllOrders: function() {
            return getCollection('orders').then(function(ctx){
                var deferred = Q.defer();
                ctx.collection.remove({}, {w: 1}, function(err, result){
                    resolveOrReject(deferred, err, 'Fehler beim Löschen aller Bestellungen', result);
                });
                deferred.promise.finally(function(){ ctx.db.close(); });
                return deferred.promise;
            });
        }
    };
};<|endoftext|>


<commit_before>import React from 'react'
React.initializeTouchEvents(true)
import * as pages from './pages/pages'
import basePage from './pages/basePage'

const currentPage = pages.findPage(document.location.pathname)

const App = React.createClass({
    componentWillMount: function() {
        currentPage
            .applicationStateProperty(window.INITIAL_STATE)
            .onValue(applicationState => this.replaceState(applicationState))
    },
    render: function() {
        return this.state ?
            basePage(currentPage, this.state, window.CHECKSUMS)
            :
            Loading...
    }
})

React.render(<App/>, document)
<commit_msg>Init app on window.onload<commit_after>import React from 'react'
React.initializeTouchEvents(true)
import * as pages from './pages/pages'
import basePage from './pages/basePage'

const currentPage = pages.findPage(document.location.pathname)

const App = React.createClass({
    componentWillMount: function() {
        currentPage
            .applicationStateProperty(window.INITIAL_STATE)
            .onValue(applicationState => this.replaceState(applicationState))
    },
    render: function() {
        return this.state ?
            basePage(currentPage, this.state, window.CHECKSUMS)
            :
            Loading...
    }
})

window.onload = () => React.render(<App/>, document)
<|endoftext|>


<commit_before>'use strict';

const request = require('request');
const _ = require('lodash');
const async = require('async');
const { Address6 } = require('ip-address');
const fs = require('fs');
const config = require('./config/config');

let log = null;
let requestWithDefaults;
let previousIpRegexAsString = '';
let ipBlocklistRegex = null;

const BASE_URI = 'https://whois.arin.net/rest/ip/';

function startup(logger) {
  log = logger;

  let defaults = {};

  if (typeof config.request.cert === 'string' && config.request.cert.length > 0) {
    defaults.cert = fs.readFileSync(config.request.cert);
  }

  if (typeof config.request.key === 'string' && config.request.key.length > 0) {
    defaults.key = fs.readFileSync(config.request.key);
  }

  if (typeof config.request.passphrase === 'string' && config.request.passphrase.length > 0) {
    defaults.passphrase = config.request.passphrase;
  }

  if (typeof config.request.ca === 'string' && config.request.ca.length > 0) {
    defaults.ca = fs.readFileSync(config.request.ca);
  }

  if (typeof config.request.proxy === 'string' && config.request.proxy.length > 0) {
    defaults.proxy = config.request.proxy;
  }

  if (typeof config.request.rejectUnauthorized === 'boolean') {
    defaults.rejectUnauthorized = config.request.rejectUnauthorized;
  }

  requestWithDefaults = request.defaults(defaults);
}

function _setupRegexBlocklists(options) {
  if (options.ipBlocklistRegex !== previousIpRegexAsString && options.ipBlocklistRegex.length === 0) {
    log.debug('Removing IP Blocklist Regex Filtering');
    previousIpRegexAsString = '';
    ipBlocklistRegex = null;
  } else {
    if (options.ipBlocklistRegex !== previousIpRegexAsString) {
      previousIpRegexAsString = options.ipBlocklistRegex;
      log.debug({ ipBlocklistRegex: previousIpRegexAsString }, 'Modifying IP Blocklist Regex');
      ipBlocklistRegex = new RegExp(options.ipBlocklistRegex, 'i');
    }
  }
}

function doLookup(entities, options, cb) {
  let blocklist = options.blocklist;
  let checkv6 = options.lookupIPv6;
  let lookupResults = [];
  const tasks = [];

  _setupRegexBlocklists(options);

  log.trace({ entities: entities }, 'Entities');

  async.each(
    entities,
    function (entityObj, next) {
      if (_.includes(blocklist, entityObj.value)) {
        next(null);
      } else if (
        (entityObj.isIPv4 && !entityObj.isPrivateIP) ||
        (entityObj.isIPv6 && checkv6 === true && new Address6(entityObj.value).isValid())
      ) {
        if (ipBlocklistRegex !== null) {
          if (ipBlocklistRegex.test(entityObj.value)) {
            log.debug({ ip: entityObj.value }, 'Blocked BlockListed IP Lookup');
            return next(null);
          }
        }

        _lookupEntity(entityObj, options, function (err, result) {
          if (err) {
            next(err);
          } else {
            lookupResults.push(result);
            next(null);
          }
        });
      } else {
        next(null);
      }
    },
    function (err) {
      log.debug({ lookupResults: lookupResults }, 'Result Values:');
      cb(err, lookupResults);
    }
  );
}

function _processRequest(err, response, body, entityObj, cb) {
  if (err) {
    log.error({ err: err }, 'Request Error');
    cb(
      _createJsonErrorPayload('Failed to complete HTTP Request', null, '500', '2A', 'Unable to Process Request', {
        err: err
      })
    );
    return;
  }

  if (response.statusCode === 500) {
    log.error({ err: err }, '500 HTTP Status Code Error');
    cb(
      _createJsonErrorPayload(
        'ARIN server was unable to process your request',
        null,
        '500',
        '2A',
        'Unable to Process Request',
        {
          err: err
        }
      )
    );
    return;
  }

  if (response.statusCode === 404) {
    cb(null, { entity: entityObj, data: null }); //Cache the missed results
    return;
  }

  if (response.statusCode === 400) {
    cb(
      _createJsonErrorPayload('Bad Request', null, '400', '2A', 'Bad Request', {
        entity: entityObj.value,
        err: err,
        response: response
      })
    );
    return;
  }

  if (response.statusCode !== 200) {
    cb(
      _createJsonErrorPayload('Unexpected HTTP Status Code', null, response.statusCode, '2A', 'Unexpected Status', {
        statusCode: response.statusCode,
        body: body,
        entity: entityObj
      })
    );
    return;
  }

  log.trace({ body: body }, 'Printing out the results of Body ');

  if (_.isNil(body) || _.isNil(body.net) || _.isNil(body.net.parentNetRef) || _.isNil(body.net.orgRef)) {
    cb(null, { entity: entityObj, data: null }); //Cache the missed results
    return;
  }

  // If ARIN returns malformed JSON then the `body` object will be a string.  If it's
  // valid JSON that we are expecting then it will be an object.  See why body will be a
  // string on JSON parse error in this issue: https://github.com/request/request/issues/440
  if (response && typeof body === 'string') {
    cb(null, { entity: entityObj, data: null }); //Cache the missed results
    log.trace({ error: err }, 'ARIN Response is not JSON'); // ARIN response not JSON
    return;
  }

  let cidrLength;

  if (Array.isArray(_.get(body, 'net.netBlocks.netBlock'))) {
    cidrLength = _.get(body, 'net.netBlocks.netBlock[0].cidrLength', '0');
  } else {
    cidrLength = _.get(body, 'net.netBlocks.netBlock.cidrLength', '0');
  }

  // The lookup results returned is an array of lookup objects with the following format
  cb(null, {
    // Required: This is the entity object passed into the integration doLookup method
    entity: entityObj,
    // Required: An object containing everything you want passed to the template
    data: {
      // Required: These are the tags that are displayed in your template
      summary: [_.get(body, 'net.orgRef.@name', 'No Org Available')],
      // Data that you want to pass back to the notification window details block
      details: {
        allData: body,
        //Organization
        orgHandle: _.get(body, 'net.orgRef.@handle'),
        orgName: _.get(body, 'net.orgRef.@name'),
        orgRef: _.get(body, 'net.orgRef.$'),
        //Network Details
        netBlockHandle: _.get(body, 'net.handle.$'),
        netBlockName: _.get(body, 'net.name.$'),
        netBlockCIDR: _.get(body, 'net.startAddress.$', '') + '/' + _.get(cidrLength, '$', ''),
        startAddr: _.get(body, 'net.startAddress.$'),
        endAddr: _.get(body, 'net.endAddress.$'),
        netBlockRef: _.get(body, 'net.ref.$'),
        regDate: _.get(body, 'net.registrationDate.$'),
        upDate: _.get(body, 'net.updateDate.$'),
        //Parent Network
        parentHandle: _.get(body, 'net.parentNetRef.@handle'),
        parentName: _.get(body, 'net.parentNetRef.@name'),
        parentRef: _.get(body, 'body.net.parentNetRef.$')
      }
    }
  });
}

function _lookupEntity(entityObj, options, cb) {
  requestWithDefaults(
    {
      uri: BASE_URI + entityObj.value,
      method: 'GET',
      json: true,
      headers: {
        Accept: 'application/json'
      }
    },
    function (err, response, body) {
      _processRequest(err, response, body, entityObj, cb);
    }
  );
}

// function that takes the ErrorObject and passes the error message to the notification window
let _createJsonErrorPayload = function (msg, pointer, httpCode, code, title, meta) {
  return {
    errors: [_createJsonErrorObject(msg, pointer, httpCode, code, title, meta)]
  };
};

// function that creates the Json object to be passed to the payload
let _createJsonErrorObject = function (msg, pointer, httpCode, code, title, meta) {
  let error = {
    detail: msg,
    status: httpCode.toString(),
    title: title,
    code: 'ARIN_' + code.toString()
  };

  if (pointer) {
    error.source = {
      pointer: pointer
    };
  }

  if (meta) {
    error.meta = meta;
  }

  return error;
};

module.exports = {
  doLookup: doLookup,
  startup: startup,
  _processRequest: _processRequest // export for testing purposes
};
<commit_msg>Max parallel lookups set to 5<commit_after>'use strict';

const request = require('request');
const _ = require('lodash');
const async = require('async');
const { Address6 } = require('ip-address');
const fs = require('fs');
const config = require('./config/config');

let log = null;
let requestWithDefaults;
let previousIpRegexAsString = '';
let ipBlocklistRegex = null;

const BASE_URI = 'https://whois.arin.net/rest/ip/';
const MAX_PARALLEL_LOOKUPS = 5;

function startup(logger) {
  log = logger;

  let defaults = {};

  if (typeof config.request.cert === 'string' && config.request.cert.length > 0) {
    defaults.cert = fs.readFileSync(config.request.cert);
  }

  if (typeof config.request.key === 'string' && config.request.key.length > 0) {
    defaults.key = fs.readFileSync(config.request.key);
  }

  if (typeof config.request.passphrase === 'string' && config.request.passphrase.length > 0) {
    defaults.passphrase = config.request.passphrase;
  }

  if (typeof config.request.ca === 'string' && config.request.ca.length > 0) {
    defaults.ca = fs.readFileSync(config.request.ca);
  }

  if (typeof config.request.proxy === 'string' && config.request.proxy.length > 0) {
    defaults.proxy = config.request.proxy;
  }

  if (typeof config.request.rejectUnauthorized === 'boolean') {
    defaults.rejectUnauthorized = config.request.rejectUnauthorized;
  }

  requestWithDefaults = request.defaults(defaults);
}

function _setupRegexBlocklists(options) {
  if (options.ipBlocklistRegex !== previousIpRegexAsString && options.ipBlocklistRegex.length === 0) {
    log.debug('Removing IP Blocklist Regex Filtering');
    previousIpRegexAsString = '';
    ipBlocklistRegex = null;
  } else {
    if (options.ipBlocklistRegex !== previousIpRegexAsString) {
      previousIpRegexAsString = options.ipBlocklistRegex;
      log.debug({ ipBlocklistRegex: previousIpRegexAsString }, 'Modifying IP Blocklist Regex');
      ipBlocklistRegex = new RegExp(options.ipBlocklistRegex, 'i');
    }
  }
}

function isValidIpToLookup(entity, options) {
  const checkv6 = options.lookupIPv6;
  const blocklist = options.blocklist;

  if (_.includes(blocklist, entity.value)) {
    return false;
  } else if (
    (entity.isIPv4 && !entity.isPrivateIP) ||
    (entity.isIPv6 && new Address6(entity.value).isValid())
  ) {
    if (ipBlocklistRegex !== null) {
      if (ipBlocklistRegex.test(entity.value)) {
        log.debug({ ip: entity.value }, 'Blocked BlockListed IP Lookup');
        return false;
      }
    }

    return true;
  }
  return false;
}

function doLookup(entities, options, cb) {
  const lookupResults = [];

  _setupRegexBlocklists(options);

  log.trace({ entities: entities }, 'Entities');

  const tasks = entities.map((entity) => (done) => {
    if (isValidIpToLookup(entity, options)) {
      _lookupEntity(entity, options, done);
    } else {
      done();
    }
  });

  async.parallelLimit(tasks, MAX_PARALLEL_LOOKUPS, (err, results) => {
    if (err) {
      return cb(err);
    }
    results.forEach((result) => {
      if(result){
        lookupResults.push(result);
      }
    });
    cb(null, lookupResults);
  });
}

function _processRequest(err, response, body, entityObj, cb) {
  if (err) {
    log.error({ err: err }, 'Request Error');
    cb(
      _createJsonErrorPayload('Failed to complete HTTP Request', null, '500', '2A', 'Unable to Process Request', {
        err: err
      })
    );
    return;
  }

  if (response.statusCode === 500) {
    log.error({ err: err }, '500 HTTP Status Code Error');
    cb(
      _createJsonErrorPayload(
        'ARIN server was unable to process your request',
        null,
        '500',
        '2A',
        'Unable to Process Request',
        {
          err: err
        }
      )
    );
    return;
  }

  if (response.statusCode === 404) {
    cb(null, { entity: entityObj, data: null }); //Cache the missed results
    return;
  }

  if (response.statusCode === 400) {
    cb(
      _createJsonErrorPayload('Bad Request', null, '400', '2A', 'Bad Request', {
        entity: entityObj.value,
        err: err,
        response: response
      })
    );
    return;
  }

  if (response.statusCode !== 200) {
    cb(
      _createJsonErrorPayload('Unexpected HTTP Status Code', null, response.statusCode, '2A', 'Unexpected Status', {
        statusCode: response.statusCode,
        body: body,
        entity: entityObj
      })
    );
    return;
  }

  log.trace({ body: body }, 'Printing out the results of Body ');

  if (_.isNil(body) || _.isNil(body.net) || _.isNil(body.net.parentNetRef) || _.isNil(body.net.orgRef)) {
    cb(null, { entity: entityObj, data: null }); //Cache the missed results
    return;
  }

  // If ARIN returns malformed JSON then the `body` object will be a string.  If it's
  // valid JSON that we are expecting then it will be an object.  See why body will be a
  // string on JSON parse error in this issue: https://github.com/request/request/issues/440
  if (response && typeof body === 'string') {
    cb(null, { entity: entityObj, data: null }); //Cache the missed results
    log.trace({ error: err }, 'ARIN Response is not JSON'); // ARIN response not JSON
    return;
  }

  let cidrLength;

  if (Array.isArray(_.get(body, 'net.netBlocks.netBlock'))) {
    cidrLength = _.get(body, 'net.netBlocks.netBlock[0].cidrLength', '0');
  } else {
    cidrLength = _.get(body, 'net.netBlocks.netBlock.cidrLength', '0');
  }

  // The lookup results returned is an array of lookup objects with the following format
  cb(null, {
    // Required: This is the entity object passed into the integration doLookup method
    entity: entityObj,
    // Required: An object containing everything you want passed to the template
    data: {
      // Required: These are the tags that are displayed in your template
      summary: [_.get(body, 'net.orgRef.@name', 'No Org Available')],
      // Data that you want to pass back to the notification window details block
      details: {
        allData: body,
        //Organization
        orgHandle: _.get(body, 'net.orgRef.@handle'),
        orgName: _.get(body, 'net.orgRef.@name'),
        orgRef: _.get(body, 'net.orgRef.$'),
        //Network Details
        netBlockHandle: _.get(body, 'net.handle.$'),
        netBlockName: _.get(body, 'net.name.$'),
        netBlockCIDR: _.get(body, 'net.startAddress.$', '') + '/' + _.get(cidrLength, '$', ''),
        startAddr: _.get(body, 'net.startAddress.$'),
        endAddr: _.get(body, 'net.endAddress.$'),
        netBlockRef: _.get(body, 'net.ref.$'),
        regDate: _.get(body, 'net.registrationDate.$'),
        upDate: _.get(body, 'net.updateDate.$'),
        //Parent Network
        parentHandle: _.get(body, 'net.parentNetRef.@handle'),
        parentName: _.get(body, 'net.parentNetRef.@name'),
        parentRef: _.get(body, 'body.net.parentNetRef.$')
      }
    }
  });
}

function _lookupEntity(entityObj, options, cb) {
  requestWithDefaults(
    {
      uri: BASE_URI + entityObj.value,
      method: 'GET',
      json: true,
      headers: {
        Accept: 'application/json'
      }
    },
    function (err, response, body) {
      _processRequest(err, response, body, entityObj, cb);
    }
  );
}

// function that takes the ErrorObject and passes the error message to the notification window
let _createJsonErrorPayload = function (msg, pointer, httpCode, code, title, meta) {
  return {
    errors: [_createJsonErrorObject(msg, pointer, httpCode, code, title, meta)]
  };
};

// function that creates the Json object to be passed to the payload
let _createJsonErrorObject = function (msg, pointer, httpCode, code, title, meta) {
  let error = {
    detail: msg,
    status: httpCode.toString(),
    title: title,
    code: 'ARIN_' + code.toString()
  };

  if (pointer) {
    error.source = {
      pointer: pointer
    };
  }

  if (meta) {
    error.meta = meta;
  }

  return error;
};

module.exports = {
  doLookup: doLookup,
  startup: startup,
  _processRequest: _processRequest // export for testing purposes
};
<|endoftext|>


<commit_before>/* eslint no-new:false */
import React from 'react';
import { ipcRenderer, remote } from 'electron';

const config = remote.require('./config');

export default class Config extends React.Component {

  constructor () {
    super();
    this.state = {
      config: config.getConfig()
    };
    this.onChange = this.onChange.bind(this);
  }

  onChange () {
    new Notification('HyperTerm configuration reloaded!');
    this.setState({ config: config.getConfig() });
  }

  componentDidMount () {
    ipcRenderer.on('config change', this.onChange);
    ipcRenderer.on('plugins change', this.onChange);
  }

  // passes `config` as props to the decorated component
  render () {
    const child = React.Children.only(this.props.children);
    const { config } = this.state;
    const decorate = remote.require('./plugins').decorateConfig;
    return React.cloneElement(child, { config: decorate(config) });
  }

  componentWillUnmount () {
    ipcRenderer.removeListener('config change', this.onChange);
    ipcRenderer.removeListener('plugins change', this.onChange);
  }

}
<commit_msg>whitelist `Notification` global<commit_after>/* global Notification */
/* eslint no-new:0 */
import React from 'react';
import { ipcRenderer, remote } from 'electron';

const config = remote.require('./config');

export default class Config extends React.Component {

  constructor () {
    super();
    this.state = {
      config: config.getConfig()
    };
    this.onChange = this.onChange.bind(this);
  }

  onChange () {
    new Notification('HyperTerm configuration reloaded!');
    this.setState({ config: config.getConfig() });
  }

  componentDidMount () {
    ipcRenderer.on('config change', this.onChange);
    ipcRenderer.on('plugins change', this.onChange);
  }

  // passes `config` as props to the decorated component
  render () {
    const child = React.Children.only(this.props.children);
    const { config } = this.state;
    const decorate = remote.require('./plugins').decorateConfig;
    return React.cloneElement(child, { config: decorate(config) });
  }

  componentWillUnmount () {
    ipcRenderer.removeListener('config change', this.onChange);
    ipcRenderer.removeListener('plugins change', this.onChange);
  }

}
<|endoftext|>


<commit_before>/**
 * @description
 * This module sets all configuration
 *
 * policyCompassConfig is exposed as a global variable in order to use it in
 * the main app.js file. If there's a way to do the same with dependency
 * injection, this should be fixed.
 */

var policyCompassConfig = {
    'URL': '/api/v1',
    'METRICS_MANAGER_URL': '/api/v1/metricsmanager',
    'VISUALIZATIONS_MANAGER_URL': '/api/v1/visualizationsmanager',
    'EVENTS_MANAGER_URL': '/api/v1/eventsmanager',
    'REFERENCE_POOL_URL': '/api/v1/references',
    'FCM_URL': '/api/v1/fcmmanager',
    'ELASTIC_URL' : 'localhost:9000',
    'ELASTIC_INDEX_NAME' : 'policycompass_search',
    'ENABLE_ADHOCRACY': false,
    'ADHOCRACY_BACKEND_URL': 'http://localhost:6541',
    'ADHOCRACY_FRONTEND_URL': 'http://localhost:6551'
};

angular.module('pcApp.config', [])

.constant('API_CONF', policyCompassConfig);
<commit_msg>Enable adhocracy by default<commit_after>/**
 * @description
 * This module sets all configuration
 *
 * policyCompassConfig is exposed as a global variable in order to use it in
 * the main app.js file. If there's a way to do the same with dependency
 * injection, this should be fixed.
 */

var policyCompassConfig = {
    'URL': '/api/v1',
    'METRICS_MANAGER_URL': '/api/v1/metricsmanager',
    'VISUALIZATIONS_MANAGER_URL': '/api/v1/visualizationsmanager',
    'EVENTS_MANAGER_URL': '/api/v1/eventsmanager',
    'REFERENCE_POOL_URL': '/api/v1/references',
    'FCM_URL': '/api/v1/fcmmanager',
    'ELASTIC_URL' : 'localhost:9000',
    'ELASTIC_INDEX_NAME' : 'policycompass_search',
    // FIXME: disabling adhocracy doesn't work due to use of
    // UserState controller in index.html
    'ENABLE_ADHOCRACY': true,
    'ADHOCRACY_BACKEND_URL': 'http://localhost:6541',
    'ADHOCRACY_FRONTEND_URL': 'http://localhost:6551'
};

angular.module('pcApp.config', [])

.constant('API_CONF', policyCompassConfig);
<|endoftext|>


<commit_before>window.Config = {
    //baseUrl: "http://boluomi.dev:8081",
    //baseUrl:"http://www.boluomi1314.com:8081",
    baseUrl:"http://localhost",
    //uploadAPI: "http://boluomi.dev:8083/upload.php",
    uploadAPI:"http://www.boluomi1314.com:8083/upload.php",
    //uploadFolder: "http://boluomi.dev:8083/data/upload/"
    uploadFolder:"http://www.boluomi1314.com:8084/"
};<commit_msg>修改后台连接API<commit_after>window.Config = {
    //baseUrl: "http://boluomi.dev:8081",
    baseUrl:"http://www.boluomi1314.com:8081",
    //baseUrl:"http://localhost",
    //uploadAPI: "http://boluomi.dev:8083/upload.php",
    uploadAPI:"http://www.boluomi1314.com:8083/upload.php",
    //uploadFolder: "http://boluomi.dev:8083/data/upload/"
    uploadFolder:"http://www.boluomi1314.com:8084/"
};<|endoftext|>


<commit_before>// [int17](http://neocotic.com/int17) 0.0.1
// (c) 2013 Alasdair Mercer
// Freely distributable under the MIT license.
// For all details and documentation:
// <http://neocotic.com/int17>

(function() {

  // Private constants
  // -----------------

      // TODO: Comment
  var DEFAULT_LOCALE = 'en'
      // Error message for subsequent initialization attempts for `int17`.
    , ERR_INIT       = 'int17 is already initialized'
      // Save the previous value of the global `int17` variable.
    , PREVIOUS_INT17 = this.int17
      // Regular expression used to replace arguments in messages.
    , R_ARGUMENT     = /\$([1-9]\d*)/gi
      // Regular expression used to replace placeholders in messages.
    , R_PLACEHOLDER  = /\$(\w+)\$/gi
      // Regular expression used to seperate key/value pairs.
    , R_VALUES       = /^([^:]+):(.+)$/
      // Regular expression used to replace whitespace.
    , R_WHITESPACE   = /\s/g;

  // Private variables
  // -----------------

      // TODO: Comment
  var initialized = false
      // TODO: Comment
    , root        = this;

  // Private functions
  // -----------------

  // TODO: Comment
  function callOrThrow(context, callback) {
    var args = [].slice.call(arguments, 2);
    if (typeof callback === 'function') {
      callback.apply(context, args);
    } else if (args[0]) {
      throw args[0];
    }
  }

  // TODO: Comment
  function configure(int17, options) {
    // TODO: Apply options
  }

  // TODO: Comment
  function extractLocale() {
    var html = document.getElementsByTagName('html')[0];
    if (html && html.lang) return html.lang;
    // TODO: Code other possible derivations (e.g. `navigator.language`)
  }

  // TODO: Comment
  function findProp(obj, target, ignoreCase) {
    if (!ignoreCase) return obj[target];
    target = target.toLowerCase();
    for (var prop in obj) {
      if (target === prop.toLowerCase()) return obj[prop];
    }
  }

  // TODO: Comment
  function replaceOptimized(placeholders, placeholder, name) {
    return function(placeholder, name) {
      var replacement = findProp(placeholders, name.toLowerCase(), false);
      return String(replacement || placeholder);
    };
  }

  // TODO: Comment
  function replacer(placeholders, optimized) {
    return (optimized ? replaceOptimized : replaceStandard)(placeholders);
  }

  // TODO: Comment
  function replaceStandard(placeholders, placeholder, name) {
    return function(placeholder, name) {
      var replacement = findProp(placeholders, name.toLowerCase(), true);
      return String((replacement && replacement.content) || placeholder);
    };
  }

  // TODO: Comment
  function resolve(url) {
    if (!url) return url;
    var ele  = document.createElement('a');
    ele.href = url;
    return ele.href;
  }

  // TODO: Comment
  function validateMessage(messageName, message) {
    var prefix = 'Message[' + messageName + ']';
    if (typeof message !== 'object') {
      throw new TypeError(prefix + ' is not an object');
    } else if (typeof message.message !== 'string') {
      throw new TypeError(prefix + '.message is not a string');
    } else if (message.hasOwnProperty('placeholders')
        && typeof message.placeholders !== 'object') {
      throw new TypeError(prefix + '.placeholders is not an object');
    }
  }

  // TODO: Comment
  function validatePlaceholder(messageName, placeholderName, placeholder) {
    var prefix = 'Message[' + messageName + '].placeholders[' + placeholderName
        + ']';
    if (typeof placeholder !== 'object') {
      throw new TypeError(prefix + ' is not an object');
    } else if (typeof placeholder.content !== 'string') {
      throw new TypeError(prefix + '.content is not a string');
    }
  }

  // Handlers
  // --------

      // Mapping for internationalization handlers.
      // Each handler represents an attribute (based on the property name) and
      // is called for each attribute found within the node currently being
      // processed.
  var handlers = {
          // Replace the HTML content of `element` with the named message
          // looked up for `name`.
          'int17-content': function(element, name) {
            element.innerHTML = this.get(name);
          }
          // Adds options to the `select` element with the messages looked up
          // for `names`.
        , 'int17-options': function(select, names) {
            names = names.replace(R_WHITESPACE, '').split(',');
            if (!names) return;
            var i, option;
            for (i = 0; i < names.length; i++) {
              option = document.createElement('option');
              option.innerHTML = this.get(names[i]);
              select.appendChild(option);
            }
          }
          // Replace the value of the properties and/or attributes of `element`
          // with the messages looked up for their corresponding values.
        , 'int17-values': function(element, map) {
            map = map.replace(R_WHITESPACE, '').split(';');
            if (!map) return;
            var expression, i, name, obj, paths, property;
            for (i = 0; i < map.length; i++) {
              property = map.match(R_VALUES);
              if (!property) continue;
              name       = property[1];
              expression = property[2];
              if (name[0] === '.') {
                paths = name.slice(1).split('.');
                obj   = element;
                while (obj && paths.length > 1) {
                  obj = obj[paths.shift()];
                }
                if (obj) {
                  obj[paths[0]] = this.get(expression);
                  this.traverse(element);
                }
              } else {
                element.setAttribute(name, this.get(expression));
              }
            }
          }
    }
    // List of internationalization attributes/handlers available.
  , attributes = (function() {
      var attribute, results = [];
      for (attribute in handler) {
        if (handler.hasOwnProperty(attribute)) results.push(attribute);
      }
      return results;
    }())
    // Selector containing the available internationalization
    // attributes/handlers which is used by `traverse` to query all elements.
  , selector   = '[' + attributes.join('],[') + ']';

  // Messenger
  // ---------

  // TODO: Comment
  function Messenger() {
    // TODO: Complete
    this.localeExtension = '.json';
    this.localePath      = './locales';
    this.optimize        = true;
    this.validate        = true;
  }

  // TODO: Comment
  Messenger.prototype.checkMessage = function(name, message) {
    var key, value;
    if (this.validate) validateMessage(name, message);
    for (key in message) {
      if (!message.hasOwnProperty(key)) continue;
      value = message[key];
      switch (key) {
        case 'placeholders':
          if (typeof value === 'object') this.checkPlaceholders(name, value);
        case 'message':
          break;
        default:
          if (this.optimize) delete message[key];
      }
    }
    return message;
  };

  // TODO: Comment
  Messenger.prototype.checkMessages = function(messages) {
    var name;
    for (name in messages) {
      if (!messages.hasOwnProperty(name)) continue;
      this.checkMessage(name, messages[name]);
    }
    return messages;
  };

  // TODO: Comment
  Messenger.prototype.checkPlaceholders = function(messageName, placeholders) {
    var lcName, name, placeholder;
    for (name in placeholders) {
      if (!placeholders.hasOwnProperty(name)) continue;
      placeholder = placeholders[name];
      if (this.validate) validatePlaceholder(messageName, name, placeholder);
      if (optimize) {
        lcName = name.toLowerCase();
        delete placeholders[name];
        placeholders[lcName] = placeholder.content;
      }
    }
    return placeholders;
  };

  // TODO: Comment
  Messenger.prototype.deriveLocale = function() {
    this.locale = this.locale || extractLocale() || DEFAULT_LOCALE;
    // TODO: Sanatize locale (e.g. replace '-' with '_')
    return this.locale;
  };

  // TODO: Comment
  Messenger.prototype.getMessage = function(messageName) {
    return this.messages[messageName];
  };

  // TODO: Comment
  Messenger.prototype.loadMessages = function(callback) {
    if (this.messages) return callback(null, this.messages);
    this.deriveLocale();
    var that = this
      , xhr  = new XMLHttpRequest();
    xhr.open('GET', this.resolvePath(), true);
    xhr.onreadystatechange = function(e) {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          try {
            that.messages = that.parseMessages(xhr.responseText);
            callback(null, that.messages);
          } catch (err) {
            callback(err);
          }
        } else {
          callback(new Error(xhr.statusText));
        }
      }
    };
    xhr.send(null);
  };

  // TODO: Comment
  Messenger.prototype.loadMessagesSync = function() {
    if (this.messages) return this.messages;
    this.deriveLocale();
    var xhr = new XMLHttpRequest();
    xhr.open('GET', this.resolvePath(), false);
    xhr.send(null);
    if (xhr.status === 200) {
      return this.messages = this.parseMessages(xhr.responseText);
    } else {
      throw new Error(xhr.statusText);
    }
  };

  // TODO: Comment
  Messenger.prototype.parseMessages = function(str) {
    var messages = JSON.parse(str);
    if (this.optimize || this.validate) this.checkMessages(messages);
    return messages;
  };

  // TODO: Comment
  Messenger.prototype.resolvePath = function() {
    return resolve(this.localePath + '/' + this.locale + this.localeExtension);
  };

  // Internationalization
  // --------------------

  // TODO: Comment
  function Internationalization() {
    this.messenger = new Messenger();
  }

  // TODO: Comment
  Internationalization.prototype.get = function(name) {
    if (!name) return;
    var args    = [].slice.call(arguments, 1);
      , message = this.messenger.getMessage(name);
    return message && this.substitute(message, args);
  };

  // TODO: Comment
  Internationalization.prototype.init = function(options, callback) {
    if (initialized) callOrThrow(this, callback, new Error(ERR_INIT));
    var that = this;
    configure(this, options);
    this.messenger.loadMessages(function(err, messages) {
      initialized = !err;
      callOrThrow(that, callback, err, messages);
    });
  };

  // TODO: Comment
  Internationalization.prototype.initSync = function(options) {
    if (initialized) throw new Error(ERR_INIT);
    configure(this, options);
    this.messenger.loadMessagesSync();
    initialized = true;
    return this;
  };

  // TODO: Comment
  Internationalization.prototype.substitute = function(message, args) {
    var optimized    = this.messenger.optimize
      , placeholders = message.placeholders
      , str          = message.message || '';
    if (placeholders) {
      str = str.replace(R_PLACEHOLDER, replacer(placeholders, optimized));
    }
    if (args && args.length) {
      str = str.replace(R_ARGUMENT, function(arg, index) {
        return String(args[index - 1] || arg);
      });
    }
    return str;
  };

  // TODO: Comment
  Internationalization.prototype.traverse = function(element) {
    if (!element) element = document;
    var attribute, child, i, j, value
      , children = element.querySelectorAll(selector);
    for (i = 0; i < children.length; i++) {
      child = children[i];
      for (j = 0; j < attributes.length; j++) {
        attribute = attributes[j];
        value     = child.getAttribute(attribute);
        if (value) handlers[attribute].call(this, child, value);
      }
    }
  };

  // int17 setup
  // -----------

  // TODO: Comment
  var int17 = new Internationalization();

  // Public constants
  // ----------------

  // Current version of int17.
  int17.VERSION = '0.0.1';

  // Public functions
  // ----------------

  // Run int17 in *noConflict* mode, returning the `int17` variable to its
  // previous owner.
  // Returns a reference to `int17`.
  int17.noConflict = function() {
    root.int17 = PREVIOUS_INT17;
    return int17;
  };

  // Finalize
  // --------

  // Build the publicly exposed API.
  if (typeof module === 'object' && module.exports) {
    require('./node').override(int17);
    module.exports = int17;
  } else if (typeof define === 'function' && define.amd) {
    define('int17', function() {
      return int17;
    });
  } else {
    this.int17 = int17;
  }

}).call(this);
<commit_msg>fixed bug with replacements<commit_after>// [int17](http://neocotic.com/int17) 0.0.1
// (c) 2013 Alasdair Mercer
// Freely distributable under the MIT license.
// For all details and documentation:
// <http://neocotic.com/int17>

(function() {

  // Private constants
  // -----------------

      // TODO: Comment
  var DEFAULT_LOCALE = 'en'
      // Error message for subsequent initialization attempts for `int17`.
    , ERR_INIT       = 'int17 is already initialized'
      // Save the previous value of the global `int17` variable.
    , PREVIOUS_INT17 = this.int17
      // Regular expression used to replace arguments in messages.
    , R_ARGUMENT     = /\$([1-9]\d*)/gi
      // Regular expression used to replace placeholders in messages.
    , R_PLACEHOLDER  = /\$(\w+)\$/gi
      // Regular expression used to seperate key/value pairs.
    , R_VALUES       = /^([^:]+):(.+)$/
      // Regular expression used to replace whitespace.
    , R_WHITESPACE   = /\s/g;

  // Private variables
  // -----------------

      // TODO: Comment
  var initialized = false
      // TODO: Comment
    , root        = this;

  // Private functions
  // -----------------

  // TODO: Comment
  function callOrThrow(context, callback) {
    var args = [].slice.call(arguments, 2);
    if (typeof callback === 'function') {
      callback.apply(context, args);
    } else if (args[0]) {
      throw args[0];
    }
  }

  // TODO: Comment
  function configure(int17, options) {
    // TODO: Apply options
  }

  // TODO: Comment
  function extractLocale() {
    var html = document.getElementsByTagName('html')[0];
    if (html && html.lang) return html.lang;
    // TODO: Code other possible derivations (e.g. `navigator.language`)
  }

  // TODO: Comment
  function findProp(obj, target, ignoreCase) {
    if (!ignoreCase) return obj[target];
    target = target.toLowerCase();
    for (var prop in obj) {
      if (target === prop.toLowerCase()) return obj[prop];
    }
  }

  // TODO: Comment
  function replaceOptimized(placeholders, placeholder, name) {
    return function(placeholder, name) {
      var replacement = findProp(placeholders, name.toLowerCase(), false);
      return typeof replacement === 'string' ? replacement : placeholder;
    };
  }

  // TODO: Comment
  function replacer(placeholders, optimized) {
    return (optimized ? replaceOptimized : replaceStandard)(placeholders);
  }

  // TODO: Comment
  function replaceStandard(placeholders, placeholder, name) {
    return function(placeholder, name) {
      var replacement = findProp(placeholders, name.toLowerCase(), true);
      replacement     = replacement && replacement.content;
      return typeof replacement === 'string' ? replacement : placeholder;
    };
  }

  // TODO: Comment
  function resolve(url) {
    if (!url) return url;
    var ele  = document.createElement('a');
    ele.href = url;
    return ele.href;
  }

  // TODO: Comment
  function validateMessage(messageName, message) {
    var prefix = 'Message[' + messageName + ']';
    if (typeof message !== 'object') {
      throw new TypeError(prefix + ' is not an object');
    } else if (typeof message.message !== 'string') {
      throw new TypeError(prefix + '.message is not a string');
    } else if (message.hasOwnProperty('placeholders')
        && typeof message.placeholders !== 'object') {
      throw new TypeError(prefix + '.placeholders is not an object');
    }
  }

  // TODO: Comment
  function validatePlaceholder(messageName, placeholderName, placeholder) {
    var prefix = 'Message[' + messageName + '].placeholders[' + placeholderName
        + ']';
    if (typeof placeholder !== 'object') {
      throw new TypeError(prefix + ' is not an object');
    } else if (typeof placeholder.content !== 'string') {
      throw new TypeError(prefix + '.content is not a string');
    }
  }

  // Handlers
  // --------

      // Mapping for internationalization handlers.
      // Each handler represents an attribute (based on the property name) and
      // is called for each attribute found within the node currently being
      // processed.
  var handlers = {
          // Replace the HTML content of `element` with the named message
          // looked up for `name`.
          'int17-content': function(element, name) {
            element.innerHTML = this.get(name);
          }
          // Adds options to the `select` element with the messages looked up
          // for `names`.
        , 'int17-options': function(select, names) {
            names = names.replace(R_WHITESPACE, '').split(',');
            if (!names) return;
            var i, option;
            for (i = 0; i < names.length; i++) {
              option = document.createElement('option');
              option.innerHTML = this.get(names[i]);
              select.appendChild(option);
            }
          }
          // Replace the value of the properties and/or attributes of `element`
          // with the messages looked up for their corresponding values.
        , 'int17-values': function(element, map) {
            map = map.replace(R_WHITESPACE, '').split(';');
            if (!map) return;
            var expression, i, name, obj, paths, property;
            for (i = 0; i < map.length; i++) {
              property = map.match(R_VALUES);
              if (!property) continue;
              name       = property[1];
              expression = property[2];
              if (name[0] === '.') {
                paths = name.slice(1).split('.');
                obj   = element;
                while (obj && paths.length > 1) {
                  obj = obj[paths.shift()];
                }
                if (obj) {
                  obj[paths[0]] = this.get(expression);
                  this.traverse(element);
                }
              } else {
                element.setAttribute(name, this.get(expression));
              }
            }
          }
    }
    // List of internationalization attributes/handlers available.
  , attributes = (function() {
      var attribute, results = [];
      for (attribute in handler) {
        if (handler.hasOwnProperty(attribute)) results.push(attribute);
      }
      return results;
    }())
    // Selector containing the available internationalization
    // attributes/handlers which is used by `traverse` to query all elements.
  , selector   = '[' + attributes.join('],[') + ']';

  // Messenger
  // ---------

  // TODO: Comment
  function Messenger() {
    // TODO: Complete
    this.localeExtension = '.json';
    this.localePath      = './locales';
    this.optimize        = true;
    this.validate        = true;
  }

  // TODO: Comment
  Messenger.prototype.checkMessage = function(name, message) {
    var key, value;
    if (this.validate) validateMessage(name, message);
    for (key in message) {
      if (!message.hasOwnProperty(key)) continue;
      value = message[key];
      switch (key) {
        case 'placeholders':
          if (typeof value === 'object') this.checkPlaceholders(name, value);
        case 'message':
          break;
        default:
          if (this.optimize) delete message[key];
      }
    }
    return message;
  };

  // TODO: Comment
  Messenger.prototype.checkMessages = function(messages) {
    var name;
    for (name in messages) {
      if (!messages.hasOwnProperty(name)) continue;
      this.checkMessage(name, messages[name]);
    }
    return messages;
  };

  // TODO: Comment
  Messenger.prototype.checkPlaceholders = function(messageName, placeholders) {
    var lcName, name, placeholder;
    for (name in placeholders) {
      if (!placeholders.hasOwnProperty(name)) continue;
      placeholder = placeholders[name];
      if (this.validate) validatePlaceholder(messageName, name, placeholder);
      if (optimize) {
        lcName = name.toLowerCase();
        delete placeholders[name];
        placeholders[lcName] = placeholder.content;
      }
    }
    return placeholders;
  };

  // TODO: Comment
  Messenger.prototype.deriveLocale = function() {
    this.locale = this.locale || extractLocale() || DEFAULT_LOCALE;
    // TODO: Sanatize locale (e.g. replace '-' with '_')
    return this.locale;
  };

  // TODO: Comment
  Messenger.prototype.getMessage = function(messageName) {
    return this.messages[messageName];
  };

  // TODO: Comment
  Messenger.prototype.loadMessages = function(callback) {
    if (this.messages) return callback(null, this.messages);
    this.deriveLocale();
    var that = this
      , xhr  = new XMLHttpRequest();
    xhr.open('GET', this.resolvePath(), true);
    xhr.onreadystatechange = function(e) {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          try {
            that.messages = that.parseMessages(xhr.responseText);
            callback(null, that.messages);
          } catch (err) {
            callback(err);
          }
        } else {
          callback(new Error(xhr.statusText));
        }
      }
    };
    xhr.send(null);
  };

  // TODO: Comment
  Messenger.prototype.loadMessagesSync = function() {
    if (this.messages) return this.messages;
    this.deriveLocale();
    var xhr = new XMLHttpRequest();
    xhr.open('GET', this.resolvePath(), false);
    xhr.send(null);
    if (xhr.status === 200) {
      return this.messages = this.parseMessages(xhr.responseText);
    } else {
      throw new Error(xhr.statusText);
    }
  };

  // TODO: Comment
  Messenger.prototype.parseMessages = function(str) {
    var messages = JSON.parse(str);
    if (this.optimize || this.validate) this.checkMessages(messages);
    return messages;
  };

  // TODO: Comment
  Messenger.prototype.resolvePath = function() {
    return resolve(this.localePath + '/' + this.locale + this.localeExtension);
  };

  // Internationalization
  // --------------------

  // TODO: Comment
  function Internationalization() {
    this.messenger = new Messenger();
  }

  // TODO: Comment
  Internationalization.prototype.get = function(name) {
    if (!name) return;
    var args    = [].slice.call(arguments, 1);
      , message = this.messenger.getMessage(name);
    return message && this.substitute(message, args);
  };

  // TODO: Comment
  Internationalization.prototype.init = function(options, callback) {
    if (initialized) callOrThrow(this, callback, new Error(ERR_INIT));
    var that = this;
    configure(this, options);
    this.messenger.loadMessages(function(err, messages) {
      initialized = !err;
      callOrThrow(that, callback, err, messages);
    });
  };

  // TODO: Comment
  Internationalization.prototype.initSync = function(options) {
    if (initialized) throw new Error(ERR_INIT);
    configure(this, options);
    this.messenger.loadMessagesSync();
    initialized = true;
    return this;
  };

  // TODO: Comment
  Internationalization.prototype.substitute = function(message, args) {
    var optimized    = this.messenger.optimize
      , placeholders = message.placeholders
      , str          = message.message || '';
    if (placeholders) {
      str = str.replace(R_PLACEHOLDER, replacer(placeholders, optimized));
    }
    if (args && args.length) {
      str = str.replace(R_ARGUMENT, function(arg, index) {
        index = index - 1;
        return typeof args[index] === 'string' ? args[index] : arg;
      });
    }
    return str;
  };

  // TODO: Comment
  Internationalization.prototype.traverse = function(element) {
    if (!element) element = document;
    var attribute, child, i, j, value
      , children = element.querySelectorAll(selector);
    for (i = 0; i < children.length; i++) {
      child = children[i];
      for (j = 0; j < attributes.length; j++) {
        attribute = attributes[j];
        value     = child.getAttribute(attribute);
        if (value) handlers[attribute].call(this, child, value);
      }
    }
  };

  // int17 setup
  // -----------

  // TODO: Comment
  var int17 = new Internationalization();

  // Public constants
  // ----------------

  // Current version of int17.
  int17.VERSION = '0.0.1';

  // Public functions
  // ----------------

  // Run int17 in *noConflict* mode, returning the `int17` variable to its
  // previous owner.
  // Returns a reference to `int17`.
  int17.noConflict = function() {
    root.int17 = PREVIOUS_INT17;
    return int17;
  };

  // Finalize
  // --------

  // Build the publicly exposed API.
  if (typeof module === 'object' && module.exports) {
    require('./node').override(int17);
    module.exports = int17;
  } else if (typeof define === 'function' && define.amd) {
    define('int17', function() {
      return int17;
    });
  } else {
    this.int17 = int17;
  }

}).call(this);
<|endoftext|>


<commit_before>// ==UserScript==
// @name         ProgrammersForumQuickQuote
// @namespace    http://programmersforum.ru/
// @version      0.3
// @description  adds a button to quote selected text, also changes the reply/quote button to not reload page
// @author       Alex P
// @include      http://programmersforum.ru/*
// @include      http://www.programmersforum.ru/*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
// @grant        none
// @downloadURL  https://github.com/AlexP11223/ProgForumRuUserscripts/raw/master/pf_quick_quote.user.js
// ==/UserScript==

// @grant must be none, otherwise cannot access vB_Editor in Firefox

(function() {
    'use strict';

    function addStyle(css) {
        var head = document.getElementsByTagName('head')[0];
        var style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = css;
        head.appendChild(style);
    }

    function getSelectedText() {
        return window.getSelection().toString();
    }

    function onPostClicked(e) {
        var selectedText = $.trim(getSelectedText());
        if (selectedText) {
            qqBtn.css({ top: (e.pageY + 10) + 'px', left: e.pageX + 'px'});
            qqBtn.show();

            qqBtn.delay(3000).fadeOut();

            var postContainer = $(this).closest('table');

            currPostId = postContainer.attr('id').replace('post', '');
            currAuthorName = postContainer.find('.bigusername').first().text();

            currSelectedText = selectedText;
        }
        else {
            qqBtn.hide();
        }
    }

    function appendText(text) {
        if (vB_Editor[QR_EditorID].get_editor_contents().length > 0) {
            text = '\n' + text;
        }
        vB_Editor[QR_EditorID].insert_text(text);
        vB_Editor[QR_EditorID].collapse_selection_end();
    }

    function appendQuote(text) {
        appendText('[QUOTE=' + currAuthorName + ';' + currPostId + ']' + text + '[/QUOTE]\n');
    }

    function quoteSelected() {
        appendQuote(currSelectedText);

        qqBtn.hide();
    }

    function quotePost(postQuoteUrl, progressIndicator) {
        progressIndicator.show();

        $.get(postQuoteUrl, function(response) {
                var html = $.parseHTML(response);

                var quote = $.trim($(html).find('#vB_Editor_001_textarea').text());

                if (quote) {
                    appendText(quote);
                }
            }).done(function() {
            progressIndicator.hide();
        });
    }

    addStyle('.qq-btn { z-index: 999;' +
        'position: absolute;' +
        'border: 1px solid midnightblue;' +
        'padding: 3px;' +
        'font-weight: bold;' +
        'cursor: pointer;' +
        'background-color: lightyellow; }');

    $('
Цитировать
').prependTo($('body'));

    var qqBtn = $('#quick_quote_btn');

    qqBtn.click(quoteSelected);

    qqBtn.hover(function() {
            qqBtn.stop(true, true);
        },
        function() {
            qqBtn.delay(3000).fadeOut();
        });

    $('#posts').on('mouseup', 'div[id^="post_message"]', onPostClicked);

    var currSelectedText = '';
    var currPostId = '';
    var currAuthorName = '';

    $('#posts').find('a:has(img[src*="quote."])').click( function(e) {
        e.preventDefault();

        var url = $(this).attr('href');
        var progressIndicator = $(this).prevAll('img[id^="progress"]').first();

        quotePost(url, progressIndicator);
    });
})();
<commit_msg>fix fadeout<commit_after>// ==UserScript==
// @name         ProgrammersForumQuickQuote
// @namespace    http://programmersforum.ru/
// @version      0.4
// @description  adds a button to quote selected text, also changes the reply/quote button to not reload page
// @author       Alex P
// @include      http://programmersforum.ru/*
// @include      http://www.programmersforum.ru/*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
// @grant        none
// @downloadURL  https://github.com/AlexP11223/ProgForumRuUserscripts/raw/master/pf_quick_quote.user.js
// ==/UserScript==

// @grant must be none, otherwise cannot access vB_Editor in Firefox

(function() {
    'use strict';

    function addStyle(css) {
        var head = document.getElementsByTagName('head')[0];
        var style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = css;
        head.appendChild(style);
    }

    function getSelectedText() {
        return window.getSelection().toString();
    }

    function onPostClicked(e) {
        var selectedText = $.trim(getSelectedText());
        if (selectedText) {
            qqBtn.stop(true, true);

            qqBtn.css({ top: (e.pageY + 10) + 'px', left: e.pageX + 'px'});
            qqBtn.show();

            qqBtn.delay(3000).fadeOut();

            var postContainer = $(this).closest('table');

            currPostId = postContainer.attr('id').replace('post', '');
            currAuthorName = postContainer.find('.bigusername').first().text();

            currSelectedText = selectedText;
        }
        else {
            qqBtn.hide();
        }
    }

    function appendText(text) {
        if (vB_Editor[QR_EditorID].get_editor_contents().length > 0) {
            text = '\n' + text;
        }
        vB_Editor[QR_EditorID].insert_text(text);
        vB_Editor[QR_EditorID].collapse_selection_end();
    }

    function appendQuote(text) {
        appendText('[QUOTE=' + currAuthorName + ';' + currPostId + ']' + text + '[/QUOTE]\n');
    }

    function quoteSelected() {
        appendQuote(currSelectedText);

        qqBtn.hide();
    }

    function quotePost(postQuoteUrl, progressIndicator) {
        progressIndicator.show();

        $.get(postQuoteUrl, function(response) {
                var html = $.parseHTML(response);

                var quote = $.trim($(html).find('#vB_Editor_001_textarea').text());

                if (quote) {
                    appendText(quote);
                }
            }).done(function() {
            progressIndicator.hide();
        });
    }

    addStyle('.qq-btn { z-index: 999;' +
        'position: absolute;' +
        'border: 1px solid midnightblue;' +
        'padding: 3px;' +
        'font-weight: bold;' +
        'cursor: pointer;' +
        'background-color: lightyellow; }');

    $('
Цитировать
').prependTo($('body'));

    var qqBtn = $('#quick_quote_btn');

    qqBtn.click(quoteSelected);

    qqBtn.hover(function() {
            qqBtn.stop(true, true);
        },
        function() {
            qqBtn.delay(3000).fadeOut();
        });

    $('#posts').on('mouseup', 'div[id^="post_message"]', onPostClicked);

    var currSelectedText = '';
    var currPostId = '';
    var currAuthorName = '';

    $('#posts').find('a:has(img[src*="quote."])').click( function(e) {
        e.preventDefault();

        var url = $(this).attr('href');
        var progressIndicator = $(this).prevAll('img[id^="progress"]').first();

        quotePost(url, progressIndicator);
    });
})();
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------

function loadCard()
{
	function stringValueFormatter(startValue,changePerDay,unit,seconds)
	{
		return startValue+' '+unit;
	}

	function dateValueFormatter(startValue,changePerDay,unit,seconds)
	{
	}

	function euroValueFormatter(startValue,changePerDay,unit,seconds)
	{
		var value = startValue;
		if(0<changePerDay) {
			value = seconds*changePerDay/24/60/60;
		}

		if(value<1000) {
			value = parseInt(value*100);
			value = value.toString();
			while(value.length<3) {
				value = '0'+value;
			}
			value = value.substr(0,value.length-2)+','+value.substr(-2);
		} else {
			value = parseInt(value).toString();
			if(value.length>3) {
				value = value.substr(0,value.length-3)+'.'+value.substr(-3);
			}
			if(value.length>11) {
				value = parseInt(parseInt(value.substr(0,value.length-4))/1000000);
				value = value.toString();
				value = value+' Mrd ';
			} else if(value.length>10) {
				value = parseInt(parseInt(value.substr(0,value.length-4))/100000);
				value = value.toString();
				value = value.substr(0,value.length-1)+','+value.substr(-1)+' Mrd ';
			} else if(value.length>8) {
				value = parseInt(parseInt(value.substr(0,value.length-4))/1000);
				value = value.toString();
				value = value+' Mio ';
			} else if(value.length>7) {
				value = parseInt(parseInt(value.substr(0,value.length-4))/100);
				value = value.toString();
				value = value.substr(0,value.length-1)+','+value.substr(-1)+' Mio ';
			}
		}
		return value+' '+unit;
	}

	function createCard(data)
	{
		data = data || {};
		data.front = data.front || {};
		data.front.textTop = data.front.textTop || '';
		data.front.textButton = data.front.textButton || '';
		data.front.value = data.front.value || '';
		data.front.unit = data.front.unit || '';
		data.front.changePerDay = data.front.changePerDay || '';
		data.front.format = data.front.format || '';
		data.front.background = data.front.background || '';
		data.front.color = data.front.color || '';
		data.front.cssClass = data.front.cssClass || '';
		data.back = data.back || {};
		data.back.text = data.back.text || '';
		data.back.color = data.back.color || '';
		data.back.background = data.back.background || '';
		data.back.cssClass = data.back.cssClass || '';

		var value = data.front.value+' '+data.front.unit;
		var valueFormatter = stringValueFormatter;
		if('date'==data.front.format) {
			var d1 = new Date();
			var d2 = new Date(data.front.value);
			var diff = (d2-d1)/1000/60/60/24;
			if(diff<1) {
				value = '- Tage';
			} else if(diff<2) {
				value = '1 Tag';
			} else {
				value = parseInt(diff)+' Tage';
			}
		} else if('euro'==data.front.format) {
			valueFormatter = euroValueFormatter;
			value = valueFormatter(data.front.value,0,data.front.unit,0);
		}
		var front = data.front.textTop+'
'+value+'
'+data.front.textButton;
		var frontTextColor = 'color:'+data.front.color+';';
		var frontBGImage = data.front.background;
		var frontCSSClass = data.front.cssClass;
		var back = data.back.text;
		var backTextColor = 'color:'+data.back.color+';';
		var backBGImage = data.back.background;
		var backCSSClass = data.back.cssClass;
		var changePerDay = data.front.changePerDay;

		createNewCard({
			front:{text:front,image:frontBGImage,style:frontTextColor,css:frontCSSClass+' display'},
			back:{text:back,image:backBGImage,style:backTextColor,css:backCSSClass},
			data:{value:data.front.value,unit:data.front.unit,change:changePerDay,formatter:valueFormatter},
		});
	}

	if(config.loaded < config.cards.length) {
		var url = config.cards[config.loaded];
		$.ajax(url)
		.done(function(json){
			var data = jQuery.parseJSON(json);
			createCard(data);
		})
		.fail(function(jqXHR, textStatus){
			if('parsererror'==textStatus) {
				var data = jQuery.parseJSON(jqXHR.responseText);
				if( typeof data.location != 'undefined') {
					createCard(data);
					return;
				}
			}
			createNewCard({
				front:{text:textStatus,css:'card1line'},
				back:{text:'Error in reading '+url,css:''},
			});
		})
		.always(function(){
			// make the back of the card invisible
			// show back
			recalcBoard(); // re-calc all positions
			// load all pending images
			// flip card to front
			// make the back of the card visible

			++config.loaded;
			loadCard();
		});
	}
}

//-----------------------------------------------------------------------

function createNewCard(card)
{
	card = card || {};
	card.front = card.front || {};
	card.front.css = card.front.css || '';
	card.front.image = card.front.image || '';
	card.front.style = card.front.style || '';
	card.front.text = card.front.text || '';
	card.back = card.back || {};
	card.back.css = card.back.css || '';
	card.back.image = card.back.image || '';
	card.back.style = card.back.style || '';
	card.back.text = card.back.text || '';
	card.data = card.data || {};
	card.data.value = card.data.value || '';
	card.data.unit = card.data.unit || '';
	card.data.change = card.data.change || 0;
	card.data.formatter = card.data.formatter || function() { return ''; };

	if(''!==card.front.image) {
		card.front.css = 'transparent '+card.front.css;
		card.front.text = '
'+card.front.text+'
';
	} else {
		card.front.text = '
'+card.front.text+'
';
	}
	if(''!==card.back.image) {
		card.back.css = 'transparent';
		card.back.text = '';
	} else {
		card.back.text = '
'+card.back.text+'
';
	}

	var str = '

'+card.front.text+'

'+card.back.text+'

';

	$( '
', {
		class: 'card',
		html: str
	})
	.insertBefore('section.endcard')
	.click(function() {
		$(this).children().first().toggleClass('flipped');
	});

	if( card.data.change > 0) {
		var elem = $( 'section:nth-last-child(2) div figure.front span');
		config.updates.push({
			dom:elem,
			value:card.data.value,
			change:card.data.change,
			unit:card.data.unit,
			formatter: card.data.formatter,
		});
	}
}

//-----------------------------------------------------------------------

function installEvents()
{
	var resizeTimer;
	$(window).resize(function() {
		clearTimeout(resizeTimer);
		resizeTimer = setTimeout(recalcPositions, 50);
	});

	function recalcPositions() {
		var elements = $('#board').children();
		var lastTop;
		var y = 0;
		for(var i = 0; i < (elements.length-1); ++i) {
			var e = $(elements[i]);
			var top = parseInt(e.position().top);
			if((0===i) || (lastTop === top)) {
				e.css('margin-left','0');
			} else {
				++y;
				e.css('margin-left',y%2?'6.55em':'0');
			}
			lastTop = top;
		};
	};
}

//-----------------------------------------------------------------------

function installTimer()
{
	var startTime = (new Date()).getTime();
	var delay = 100;

	function timerFunc() {
		try {
			var diffTime = parseInt(((new Date()).getTime() - startTime) / 1000);
			for(var i = 0; i< config.updates.length; ++i) {
				var update = config.updates[i];
				update.dom.text( update.formatter(update.value,update.change,update.unit,diffTime));
			}
		} catch(e) {
//			console.log(e);
		}

		setTimeout(timerFunc, delay);
	}

	setTimeout(timerFunc, delay);
}

//-----------------------------------------------------------------------

function recalcBoard()
{
	$(window).trigger('resize');
}

//-----------------------------------------------------------------------

function test()
{
	// http://daten.berlin.de/datensaetze/web-service-last-und-erzeugung-berlin
	// http://www.stromnetz-berlin.de/de/file/Erl_uterungen-Livedaten-Zugriff-Stromnetz-Berlin-SMeter_Engine_93664683.pdf

	var url = 'https://www.vattenfall.de/SmeterEngine/energyProjection';
	var xml = '<smeterengine start="2013-06-12T09:00:00" end="2013-06-12T11:00:00">'
			+ '    <cities> '
			+ '    <city>BERLIN</city> '
			+ '    <latitude>52.30</latitude> '
			+ '    <longitude>13.25</longitude> '
			+ '    </cities>           '
			+ '</smeterengine> ';
	$.ajax({
		url: url,
		data: xml,
		type: 'POST',
		contentType: 'text/xml',
		dataType: 'text',
		success : function(){
			console.log('xx');
		},
		error : function(xhr, ajaxOptions, thrownError){
			console.log(xhr);
			console.log(xhr.status);
			console.log(thrownError);
		}
	});
}

//-----------------------------------------------------------------------

$(document).ready(function() {
	installEvents();
	installTimer();
	recalcBoard();

	config.loaded = 0;
	config.updates = new Array();

	loadCard();

//	test();
});

//-----------------------------------------------------------------------
<commit_msg>added intValueFormatter<commit_after>//-----------------------------------------------------------------------

function loadCard()
{
	function stringValueFormatter(startValue,changePerDay,unit,seconds)
	{
		return startValue+' '+unit;
	}

	function dateValueFormatter(startValue,changePerDay,unit,seconds)
	{
	}

	function intValueFormatter(startValue,changePerDay,unit,seconds)
	{
		var value = startValue;
		if(''==value) {
			value = 0;
		}
		if(0<changePerDay) {
			value = seconds*changePerDay/24/60/60;
		}
		value = parseInt(value);

		if(value>1000) {
			value = value.toString();
			value = value.substr(0,value.length-3)+'.'+value.substr(-3);
		}
		return value+' '+unit;
	}

	function euroValueFormatter(startValue,changePerDay,unit,seconds)
	{
		var value = startValue;
		if(0<changePerDay) {
			value = seconds*changePerDay/24/60/60;
		}

		if(value<1000) {
			value = parseInt(value*100);
			value = value.toString();
			while(value.length<3) {
				value = '0'+value;
			}
			value = value.substr(0,value.length-2)+','+value.substr(-2);
		} else {
			value = parseInt(value).toString();
			if(value.length>3) {
				value = value.substr(0,value.length-3)+'.'+value.substr(-3);
			}
			if(value.length>11) {
				value = parseInt(parseInt(value.substr(0,value.length-4))/1000000);
				value = value.toString();
				value = value+' Mrd ';
			} else if(value.length>10) {
				value = parseInt(parseInt(value.substr(0,value.length-4))/100000);
				value = value.toString();
				value = value.substr(0,value.length-1)+','+value.substr(-1)+' Mrd ';
			} else if(value.length>8) {
				value = parseInt(parseInt(value.substr(0,value.length-4))/1000);
				value = value.toString();
				value = value+' Mio ';
			} else if(value.length>7) {
				value = parseInt(parseInt(value.substr(0,value.length-4))/100);
				value = value.toString();
				value = value.substr(0,value.length-1)+','+value.substr(-1)+' Mio ';
			}
		}
		return value+' '+unit;
	}

	function createCard(data)
	{
		data = data || {};
		data.front = data.front || {};
		data.front.textTop = data.front.textTop || '';
		data.front.textButton = data.front.textButton || '';
		data.front.value = data.front.value || '';
		data.front.unit = data.front.unit || '';
		data.front.changePerDay = data.front.changePerDay || '';
		data.front.format = data.front.format || '';
		data.front.background = data.front.background || '';
		data.front.color = data.front.color || '';
		data.front.cssClass = data.front.cssClass || '';
		data.back = data.back || {};
		data.back.text = data.back.text || '';
		data.back.color = data.back.color || '';
		data.back.background = data.back.background || '';
		data.back.cssClass = data.back.cssClass || '';

		var value = data.front.value+' '+data.front.unit;
		var valueFormatter = stringValueFormatter;
		if('date'==data.front.format) {
			var d1 = new Date();
			var d2 = new Date(data.front.value);
			var diff = (d2-d1)/1000/60/60/24;
			if(diff<1) {
				value = '- Tage';
			} else if(diff<2) {
				value = '1 Tag';
			} else {
				value = parseInt(diff)+' Tage';
			}
		} else if('euro'==data.front.format) {
			valueFormatter = euroValueFormatter;
			value = valueFormatter(data.front.value,0,data.front.unit,0);
		} else if('int'==data.front.format) {
			valueFormatter = intValueFormatter;
			value = valueFormatter(data.front.value,0,data.front.unit,0);
		}
		var front = data.front.textTop+'
'+value+'
'+data.front.textButton;
		var frontTextColor = 'color:'+data.front.color+';';
		var frontBGImage = data.front.background;
		var frontCSSClass = data.front.cssClass;
		var back = data.back.text;
		var backTextColor = 'color:'+data.back.color+';';
		var backBGImage = data.back.background;
		var backCSSClass = data.back.cssClass;
		var changePerDay = data.front.changePerDay;

		createNewCard({
			front:{text:front,image:frontBGImage,style:frontTextColor,css:frontCSSClass+' display'},
			back:{text:back,image:backBGImage,style:backTextColor,css:backCSSClass},
			data:{value:data.front.value,unit:data.front.unit,change:changePerDay,formatter:valueFormatter},
		});
	}

	if(config.loaded < config.cards.length) {
		var url = config.cards[config.loaded];
		$.ajax(url)
		.done(function(json){
			var data = jQuery.parseJSON(json);
			createCard(data);
		})
		.fail(function(jqXHR, textStatus){
			if('parsererror'==textStatus) {
				var data = jQuery.parseJSON(jqXHR.responseText);
				if( typeof data.location != 'undefined') {
					createCard(data);
					return;
				}
			}
			createNewCard({
				front:{text:textStatus,css:'card1line'},
				back:{text:'Error in reading '+url,css:''},
			});
		})
		.always(function(){
			// make the back of the card invisible
			// show back
			recalcBoard(); // re-calc all positions
			// load all pending images
			// flip card to front
			// make the back of the card visible

			++config.loaded;
			loadCard();
		});
	}
}

//-----------------------------------------------------------------------

function createNewCard(card)
{
	card = card || {};
	card.front = card.front || {};
	card.front.css = card.front.css || '';
	card.front.image = card.front.image || '';
	card.front.style = card.front.style || '';
	card.front.text = card.front.text || '';
	card.back = card.back || {};
	card.back.css = card.back.css || '';
	card.back.image = card.back.image || '';
	card.back.style = card.back.style || '';
	card.back.text = card.back.text || '';
	card.data = card.data || {};
	card.data.value = card.data.value || '';
	card.data.unit = card.data.unit || '';
	card.data.change = card.data.change || 0;
	card.data.formatter = card.data.formatter || function() { return ''; };

	if(''!==card.front.image) {
		card.front.css = 'transparent '+card.front.css;
		card.front.text = '
'+card.front.text+'
';
	} else {
		card.front.text = '
'+card.front.text+'
';
	}
	if(''!==card.back.image) {
		card.back.css = 'transparent';
		card.back.text = '';
	} else {
		card.back.text = '
'+card.back.text+'
';
	}

	var str = '

'+card.front.text+'

'+card.back.text+'

';

	$( '
', {
		class: 'card',
		html: str
	})
	.insertBefore('section.endcard')
	.click(function() {
		$(this).children().first().toggleClass('flipped');
	});

	if( card.data.change > 0) {
		var elem = $( 'section:nth-last-child(2) div figure.front span');
		config.updates.push({
			dom:elem,
			value:card.data.value,
			change:card.data.change,
			unit:card.data.unit,
			formatter: card.data.formatter,
		});
	}
}

//-----------------------------------------------------------------------

function installEvents()
{
	var resizeTimer;
	$(window).resize(function() {
		clearTimeout(resizeTimer);
		resizeTimer = setTimeout(recalcPositions, 50);
	});

	function recalcPositions() {
		var elements = $('#board').children();
		var lastTop;
		var y = 0;
		for(var i = 0; i < (elements.length-1); ++i) {
			var e = $(elements[i]);
			var top = parseInt(e.position().top);
			if((0===i) || (lastTop === top)) {
				e.css('margin-left','0');
			} else {
				++y;
				e.css('margin-left',y%2?'6.55em':'0');
			}
			lastTop = top;
		};
	};
}

//-----------------------------------------------------------------------

function installTimer()
{
	var startTime = (new Date()).getTime();
	var delay = 100;

	function timerFunc() {
		try {
			var diffTime = parseInt(((new Date()).getTime() - startTime) / 1000);
			for(var i = 0; i< config.updates.length; ++i) {
				var update = config.updates[i];
				update.dom.text( update.formatter(update.value,update.change,update.unit,diffTime));
			}
		} catch(e) {
//			console.log(e);
		}

		setTimeout(timerFunc, delay);
	}

	setTimeout(timerFunc, delay);
}

//-----------------------------------------------------------------------

function recalcBoard()
{
	$(window).trigger('resize');
}

//-----------------------------------------------------------------------

function test()
{
	// http://daten.berlin.de/datensaetze/web-service-last-und-erzeugung-berlin
	// http://www.stromnetz-berlin.de/de/file/Erl_uterungen-Livedaten-Zugriff-Stromnetz-Berlin-SMeter_Engine_93664683.pdf

	var url = 'https://www.vattenfall.de/SmeterEngine/energyProjection';
	var xml = '<smeterengine start="2013-06-12T09:00:00" end="2013-06-12T11:00:00">'
			+ '    <cities> '
			+ '    <city>BERLIN</city> '
			+ '    <latitude>52.30</latitude> '
			+ '    <longitude>13.25</longitude> '
			+ '    </cities>           '
			+ '</smeterengine> ';
	$.ajax({
		url: url,
		data: xml,
		type: 'POST',
		contentType: 'text/xml',
		dataType: 'text',
		success : function(){
			console.log('xx');
		},
		error : function(xhr, ajaxOptions, thrownError){
			console.log(xhr);
			console.log(xhr.status);
			console.log(thrownError);
		}
	});
}

//-----------------------------------------------------------------------

$(document).ready(function() {
	installEvents();
	installTimer();
	recalcBoard();

	config.loaded = 0;
	config.updates = new Array();

	loadCard();

//	test();
});

//-----------------------------------------------------------------------
<|endoftext|>