HEX
Server: nginx/1.24.0
System: Linux nowruzgan 6.8.0-57-generic #59-Ubuntu SMP PREEMPT_DYNAMIC Sat Mar 15 17:40:59 UTC 2025 x86_64
User: babak (1000)
PHP: 8.3.6
Disabled: NONE
Upload Files
File: /var/dev/nowruzgan/rest/node_modules/object-hash/index.js
'use strict';

var crypto = require('crypto');

/**
 * Exported function
 *
 * Options:
 *
 *  - `algorithm` hash algo to be used by this instance: *'sha1', 'md5' 
 *  - `excludeValues` {true|*false} hash object keys, values ignored 
 *  - `encoding` hash encoding, supports 'buffer', '*hex', 'binary', 'base64' 
 *  * = default
 *
 * @param {object} value to hash
 * @param {options} hashing options
 * @return {hash value}
 * @api public
 */
exports = module.exports = objectHash;

function objectHash(object, options){
  options = options || {};
  options.algorithm = options.algorithm || 'sha1';
  options.encoding = options.encoding || 'hex';
  options.excludeValues = options.excludeValues ? true : false;
  options.algorithm = options.algorithm.toLowerCase();
  options.encoding = options.encoding.toLowerCase();

  validate(object, options);

  return hash(object, options);
}

/**
 * Exported sugar methods
 *
 * @param {object} value to hash
 * @return {hash value}
 * @api public
 */
exports.sha1 = function(object){
  return objectHash(object);
};
exports.keys = function(object){
  return objectHash(object, {excludeValues: true, algorithm: 'sha1', encoding: 'hex'});
};
exports.MD5 = function(object){
  return objectHash(object, {algorithm: 'md5', encoding: 'hex'});
};
exports.keysMD5 = function(object){
  return objectHash(object, {algorithm: 'md5', encoding: 'hex', excludeValues: true});
};

/**
 * Expose HashTable constructor
 *
 */
exports.HashTable = require('./lib/hashTable');


// Internals
function validate(object, options){
  var hashes = crypto.getHashes ? crypto.getHashes() : ['sha1', 'md5'];
  var encodings = ['buffer', 'hex', 'binary', 'base64'];

  if(typeof object === 'undefined') {
    throw new Error('Object argument required.');
  }

  if(hashes.indexOf(options.algorithm) === -1){
    throw new Error('Algorithm "' + options.algorithm + '"  not supported. ' +
      'supported values: ' + hashes.join(', '));
  }

  if(encodings.indexOf(options.encoding) === -1){
    throw new Error('Encoding "' + options.encoding + '"  not supported. ' +
      'supported values: ' + encodings.join(', '));
  }
}

function hash(object, options){
  var hashFn = crypto.createHash(options.algorithm);

  typeHasher(hashFn, options).dispatch(object);

  return (options.encoding === 'buffer') ? hashFn.digest() :
    hashFn.digest(options.encoding);
}

function typeHasher(hashFn, options){
  return {
    dispatch: function(value){
      var type = typeof value;
      var func = this['_' + type];
      return (value === null) ? this._null() : func(value);
    },
    _object: function(object) {
      var pattern = (/\[object (.*)\]/i);
      var objString = Object.prototype.toString.call(object);
      var objType = pattern.exec(objString)[1] || 'null';
      objType = objType.toLowerCase();

      if(objType !== 'object') {
        if(typeHasher(hashFn, options)['_' + objType]) {
          typeHasher(hashFn, options)['_' + objType](object);
        }else{
          throw new Error('Unknown object type "' + objType + '"');
        }
      }else{
        // TODO, add option for enumerating, for key in obj includePrototypeChain
        var keys = Object.keys(object).sort();
        return keys.forEach(function(key){
          hashFn.update(key);
          if(!options.excludeValues) {
            typeHasher(hashFn, options).dispatch(object[key]);
          }
        });
      }
    },
    _array: function(arr){
      return arr.forEach(function(el){
        typeHasher(hashFn, options).dispatch(el);
      });
    },
    _date: function(date){
      return hashFn.update(date.toString());
    },
    _boolean: function(bool){
      return hashFn.update(bool.toString());
    },
    _string: function(string){
      return hashFn.update(string);
    },
    _function: function(fn){
      return hashFn.update(fn.toString());
    },
    _number: function(number){
      return hashFn.update(number.toString());
    },
    _xml: function(xml){
      return hashFn.update(xml.toString());
    },
    _null: function(){
      return hashFn.update('Null');
    },
    _undefined: function(){
      return hashFn.update('Undefined');
    },
    _regexp: function(regex){
      return hashFn.update(regex.toString());
    },
    _domwindow: function(){
      return hashFn.update('domwindow');
    }
  };
}