text: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements. See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership. The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License. You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied. See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  
  /*
   * XSEC
   *
   * TXFMHash := Class that performs a hash/HMAC transform
   *
   * $Id: TXFMHash.cpp 1833341 2018-06-11 16:25:41Z scantor $
   *
   */
  
  #include <xsec/framework/XSECException.hpp>
  #include <xsec/transformers/TXFMHash.hpp>
  #include <xsec/utils/XSECPlatformUtils.hpp>
  
  XERCES_CPP_NAMESPACE_USE
  
  TXFMHash::TXFMHash(DOMDocument* doc, XSECCryptoHash::HashType type, const XSECCryptoKey* key) :
      TXFMBase(doc), mp_h(NULL), md_value(NULL), md_len(0), toOutput(0) {
  
      if (key == NULL) {
          // Get a hash worker
          mp_h = XSECPlatformUtils::g_cryptoProvider->hash(type);
          if (!mp_h) {
              throw XSECException(XSECException::CryptoProviderError,
                  "Error requesting hash object from Crypto Provider");
          }
      } 
      else {
          // Get an HMAC worker
  
          mp_h = XSECPlatformUtils::g_cryptoProvider->HMAC(type);
          if (!mp_h) {
              throw XSECException(XSECException::CryptoProviderError,
                      "Error requesting HMAC object from Crypto Provider");
          }
          mp_h->setKey(key);
      }
  
      md_value = new unsigned char[XSECPlatformUtils::g_cryptoProvider->getMaxHashSize()];
      if (!md_value) {
          delete mp_h;
      }
  };
  
  TXFMHash::~TXFMHash() {
  
      // Clean up
      if (mp_h)
          delete mp_h;
  
      if (md_value)
          delete[] md_value;
  };
  
      // Methods to set the inputs
  
  //void TXFMHash::setInput(TXFMBase *input);
  
      // Methods to get tranform output type and input requirement
  
  TXFMBase::ioType TXFMHash::getInputType() const {
      return TXFMBase::BYTE_STREAM;
  }
  
  TXFMBase::ioType TXFMHash::getOutputType() const {
      return TXFMBase::BYTE_STREAM;
  }
  
  TXFMBase::nodeType TXFMHash::getNodeType() const {
      return TXFMBase::DOM_NODE_NONE;
  }
  
      // Methods to set input data
  
  void TXFMHash::setInput(TXFMBase* inputT) {
  
      input = inputT;
  
      keepComments = input->getCommentsStatus();
  
      // Now run through the data
      unsigned char buffer[1024];
      unsigned int size;
  
      while ((size = input->readBytes((XMLByte *) buffer, 1024)) != 0) {
          mp_h->hash(buffer, size);
      }
  
      // Finalise
  
      md_len = mp_h->finish(md_value, XSECPlatformUtils::g_cryptoProvider->getMaxHashSize());
  
      toOutput = md_len;
  }
  
  
  unsigned int TXFMHash::readBytes(XMLByte * const toFill, unsigned int maxToFill) {
  
      unsigned int ret;
  
      if (toOutput == 0)
          return 0;
  
      // Check if we can just output everything left
      if (toOutput <= maxToFill) {
  
          memcpy((char *) toFill, &md_value[md_len - toOutput], toOutput);
          ret = toOutput;
          toOutput = 0;
  
          return ret;
  
      }
  
      // Output just some
  
      memcpy((char *) toFill, &md_value[md_len - toOutput], maxToFill);
      ret = maxToFill;
      toOutput -= maxToFill;
  
      return ret;
  }
  