text:
#include <ortc/internal/ortc_RTPPacket.h>
#include <ortc/internal/ortc_Helper.h>
#include <ortc/internal/ortc_RTPUtils.h>
#include <ortc/internal/platform.h>

#include <ortc/services/IHelper.h>

//#include <ortc/services/IHTTP.h>
//
//#include <zsLib/Stringize.h>
//#include <zsLib/Log.h>
#include <zsLib/XML.h>

#include <cryptopp/integer.h>

#include <sstream>

#ifdef _DEBUG
#define ASSERT(x) ZS_THROW_BAD_STATE_IF(!(x))
#else
#define ASSERT(x)
#endif //_DEBUG

#define RTP_HEADER_EXTENSION_BIT (0x10)

#define RTP_HEADER_VERSION(buffer) (((buffer[0]) & 0xC0) >> 6)
#define RTP_HEADER_PADDING(buffer) (0 != ((buffer[0]) & 0x20))
#define RTP_HEADER_EXTENSION(buffer) (0 != ((buffer[0] & RTP_HEADER_EXTENSION_BIT)))
#define RTP_HEADER_CC(buffer) ((buffer[0]) & 0xF)
#define RTP_HEADER_M(buffer) (0 != ((buffer[1]) & 0x80))
#define RTP_HEADER_PT(buffer) ((buffer[1]) & 0x7F)

#define RTP_IS_FLAG_SET(xByte, xBitPos) (0 != ((xByte) & (1 << xBitPos)))
#define RTP_GET_BITS(xByte, xBitPattern, xLowestBit) (((xByte) >> (xLowestBit)) & (xBitPattern))
#define RTP_PACK_BITS(xByte, xBitPattern, xLowestBit) (((xByte) & (xBitPattern)) << (xLowestBit))

namespace ortc { ZS_DECLARE_SUBSYSTEM(ortclib_rtp_rtcp_packet) }

namespace ortc
{
  ZS_DECLARE_TYPEDEF_PTR(ortc::services::IHelper, UseServicesHelper)
//  ZS_DECLARE_TYPEDEF_PTR(ortc::services::IHTTP, UseHTTP)
//
//  typedef ortc::services::Hasher<CryptoPP::SHA1> SHA1Hasher;

  namespace internal
  {
    ZS_DECLARE_TYPEDEF_PTR(ortc::internal::Helper, UseHelper)

    using CryptoPP::Integer;

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark (helpers)
    #pragma mark

    static const size_t kMinRtpPacketLen = 12;
    static const BYTE kRtpVersion = 2;

    //-------------------------------------------------------------------------
    static bool requiredExtension(
                                  RTPPacket::HeaderExtension *firstExtension,
                                  BYTE headerExtensionAppBits,
                                  size_t headerExtensionPrepaddedSize,
                                  const BYTE *headerExtensionParseStoppedPos
                                  )
    {
      return (NULL != firstExtension) ||
      (0 != headerExtensionAppBits) ||
      (0 != headerExtensionPrepaddedSize) ||
      (NULL != headerExtensionParseStoppedPos);
    }

    //-------------------------------------------------------------------------
    static void getHeaderExtensionSize(
                                       RTPPacket::HeaderExtension *firstExtension,
                                       bool twoByteHeader,
                                       size_t headerExtensionPrepaddedSize,
                                       size_t headerExtensionParseStoppedSize,
                                       size_t &outSizeInBytes,
                                       size_t &outTotalHeaderExtensions
                                       )
    {
      typedef RTPPacket::HeaderExtension HeaderExtension;

      outSizeInBytes = sizeof(DWORD) + headerExtensionPrepaddedSize + headerExtensionParseStoppedSize;

      outTotalHeaderExtensions = 0;
      for (HeaderExtension *current = firstExtension; NULL != current; current = current->mNext) {
        ++outTotalHeaderExtensions;
        outSizeInBytes += (twoByteHeader ? 2 : 1) + (current->mDataSizeInBytes) + current->mPostPaddingSize;
      }

      size_t modulas = (outSizeInBytes % sizeof(DWORD));

      if (0 != modulas) {
        outSizeInBytes += (sizeof(DWORD) - modulas);
      }
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket::ClientToMixerExtension
    #pragma mark

    //-------------------------------------------------------------------------
    RTPPacket::ClientToMixerExtension::ClientToMixerExtension(const HeaderExtension &header)
    {
      mID = header.mID;
      mDataSizeInBytes = header.mDataSizeInBytes;
      mPostPaddingSize = header.mPostPaddingSize;
      if (NULL == header.mData) mDataSizeInBytes = 0;
      if (0 == mDataSizeInBytes) mData = NULL;

      if (sizeof(BYTE) == header.mDataSizeInBytes) {
        memcpy(&mLevelBuffer, header.mData, sizeof(BYTE));
        mData = &mLevelBuffer;
      }
    }

    //-------------------------------------------------------------------------
    RTPPacket::ClientToMixerExtension::ClientToMixerExtension(
                                                              BYTE id,
                                                              bool voiceActivity,
                                                              BYTE level
                                                              )
    {
      mID = id;
      mData = &mLevelBuffer;
      mDataSizeInBytes = sizeof(BYTE);

      mLevelBuffer = static_cast<BYTE>(voiceActivity ? 0x80 : 0x00) | (level & 0x7F);
    }

    //-------------------------------------------------------------------------
    bool RTPPacket::ClientToMixerExtension::voiceActivity() const
    {
      return RTP_IS_FLAG_SET(mLevelBuffer, 7);
    }

    //-------------------------------------------------------------------------
    BYTE RTPPacket::ClientToMixerExtension::level() const
    {
      return RTP_GET_BITS(mLevelBuffer, 0x7F, 0);
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket::MixerToClientExtension
    #pragma mark

    //-------------------------------------------------------------------------
    RTPPacket::MixerToClientExtension::MixerToClientExtension(const HeaderExtension &header)
    {
      mID = header.mID;
      mDataSizeInBytes = header.mDataSizeInBytes;
      mPostPaddingSize = header.mPostPaddingSize;
      if (NULL == header.mData) mDataSizeInBytes = 0;
      if (0 == mDataSizeInBytes) mData = NULL;

      size_t copySize = header.mDataSizeInBytes;
      if (copySize > sizeof(mLevelBuffer)) copySize = sizeof(mLevelBuffer);

      if (0 != copySize) {
        memcpy(&(mLevelBuffer[0]), header.mData, copySize);
        mData = &(mLevelBuffer[0]);
      }
      mDataSizeInBytes = copySize;
    }

    //-------------------------------------------------------------------------
    RTPPacket::MixerToClientExtension::MixerToClientExtension(
                                                              BYTE id,
                                                              BYTE *levels,
                                                              size_t count
                                                              )
    {
      mID = id;
      mDataSizeInBytes = count * sizeof(BYTE);

      if (mDataSizeInBytes > sizeof(mLevelBuffer)) {
        count = sizeof(mLevelBuffer)/sizeof(BYTE);
      }

      if (0 != mDataSizeInBytes) {
        mData = &(mLevelBuffer[0]);
        memcpy(&(mLevelBuffer[0]), levels, mDataSizeInBytes);
      }
    }

    //-------------------------------------------------------------------------
    size_t RTPPacket::MixerToClientExtension::levelsCount() const
    {
      return mDataSizeInBytes / sizeof(BYTE);
    }

    //-------------------------------------------------------------------------
    BYTE RTPPacket::MixerToClientExtension::unusedBit(size_t index) const
    {
      ASSERT(index < levelsCount())
      return RTP_GET_BITS(mLevelBuffer[index], 0x80, 7);
    }

    //-------------------------------------------------------------------------
    BYTE RTPPacket::MixerToClientExtension::level(size_t index) const
    {
      ASSERT(index < levelsCount())
      return RTP_GET_BITS(mLevelBuffer[index], 0x7F, 0);
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket::StringHeaderExtension
    #pragma mark

    //-------------------------------------------------------------------------
    RTPPacket::StringHeaderExtension::StringHeaderExtension(const HeaderExtension &header)
    {
      ASSERT(sizeof(char) == sizeof(BYTE))

      mID = header.mID;
      mDataSizeInBytes = header.mDataSizeInBytes;
      mPostPaddingSize = header.mPostPaddingSize;
      if (NULL == header.mData) mDataSizeInBytes = 0;
      if (0 == mDataSizeInBytes) mData = NULL;

      size_t copySize = header.mDataSizeInBytes;
      if (copySize > (sizeof(BYTE)*kMaxStringLength)) copySize = (sizeof(BYTE)*kMaxStringLength);

      if (0 != copySize) {
        memcpy(&(mStringBuffer[0]), header.mData, copySize);
        mData = &(mStringBuffer[0]);
      }
      mDataSizeInBytes = copySize;
    }

    //-------------------------------------------------------------------------
    RTPPacket::StringHeaderExtension::StringHeaderExtension(
                                                  BYTE id,
                                                  const char *mid
                                                  )
    {
      mID = id;
      mData = &(mStringBuffer[0]);
      mDataSizeInBytes = sizeof(char)*(NULL != mid ? strlen(mid) : 0);

      if (mDataSizeInBytes > (sizeof(BYTE)*kMaxStringLength)) mDataSizeInBytes = (sizeof(BYTE)*kMaxStringLength);

      if (0 != mDataSizeInBytes) {
        memcpy(&(mStringBuffer[0]), mid, mDataSizeInBytes);
      }
    }

    //-------------------------------------------------------------------------
    const char *RTPPacket::StringHeaderExtension::str() const
    {
      return reinterpret_cast<const char *>(&mStringBuffer[0]);
    }

    //-------------------------------------------------------------------------
    ElementPtr RTPPacket::StringHeaderExtension::toDebug() const
    {
      ElementPtr result = Element::create("ortc::RTPPacket::StringHeaderExtension");

      UseServicesHelper::debugAppend(result, "str", str());

      return result;
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket::StringHeaderExtension
    #pragma mark

    //-------------------------------------------------------------------------
    RTPPacket::NumberHeaderExtension::NumberHeaderExtension(const HeaderExtension &header)
    {
      ASSERT(sizeof(char) == sizeof(BYTE))

      mID = header.mID;
      mDataSizeInBytes = header.mDataSizeInBytes;
      mPostPaddingSize = header.mPostPaddingSize;
      if (NULL == header.mData) mDataSizeInBytes = 0;
      if (0 == mDataSizeInBytes) mData = NULL;

      size_t copySize = header.mDataSizeInBytes;
      if (copySize > (sizeof(BYTE)*kMaxNumberByteLength)) copySize = (sizeof(BYTE)*kMaxNumberByteLength);

      if (0 != copySize) {
        memcpy(&(mNumberBuffer[0]), header.mData, copySize);
        mData = &(mNumberBuffer[0]);
      }
      mDataSizeInBytes = copySize;
    }

    //-------------------------------------------------------------------------
    RTPPacket::NumberHeaderExtension::NumberHeaderExtension(
                                                            BYTE id,
                                                            const BYTE *number,
                                                            size_t lengthInBytes
                                                            )
    {
      mID = id;
      mData = &(mNumberBuffer[0]);
      mDataSizeInBytes = sizeof(char)*(NULL != number ? lengthInBytes : 0);

      if (mDataSizeInBytes > (sizeof(BYTE)*kMaxNumberByteLength)) mDataSizeInBytes = (sizeof(BYTE)*kMaxNumberByteLength);

      if (0 != mDataSizeInBytes) {
        memcpy(&(mNumberBuffer[0]), number, mDataSizeInBytes);
      }
    }

    //-------------------------------------------------------------------------
    RTPPacket::NumberHeaderExtension::NumberHeaderExtension(
                                                            BYTE id,
                                                            const char *valueInBase10
                                                            )
    {
      mID = id;
      mData = &(mNumberBuffer[0]);
      mDataSizeInBytes = 1;

      String str(valueInBase10);

      try {
        Integer value(str); // convert from base 10 into big number class

        size_t minSizeNeeded = value.MinEncodedSize();
        ORTC_THROW_INVALID_PARAMETERS_IF(minSizeNeeded > kMaxNumberByteLength)

        // this will encode in big endian and pad with most significant "0"
        // values as needed
        value.Encode(&(mNumberBuffer[0]), minSizeNeeded);

        mDataSizeInBytes = minSizeNeeded;

      } catch(...) {
        ORTC_THROW_INVALID_PARAMETERS("unable to convert integer: " + str)
      }
    }

    //-------------------------------------------------------------------------
    const BYTE *RTPPacket::NumberHeaderExtension::number() const
    {
      return &(mNumberBuffer[0]);
    }

    //-------------------------------------------------------------------------
    size_t RTPPacket::NumberHeaderExtension::length() const
    {
      return mDataSizeInBytes;
    }

    //-------------------------------------------------------------------------
    String RTPPacket::NumberHeaderExtension::str() const
    {
      if (mDataSizeInBytes < 1) return String();

      Integer value(&(mNumberBuffer[0]), mDataSizeInBytes);

      std::stringstream output;

      output << value;

      return output.str();
    }

    //-------------------------------------------------------------------------
    ElementPtr RTPPacket::NumberHeaderExtension::toDebug() const
    {
      ElementPtr result = Element::create("ortc::RTPPacket::NumberHeaderExtension");

      Integer value(number(), length());

      UseServicesHelper::debugAppend(result, "number", str());

      return result;
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket::MidHeaderExtension
    #pragma mark

    //-------------------------------------------------------------------------
    ElementPtr RTPPacket::MidHeaderExtension::toDebug() const
    {
      ElementPtr result = Element::create("ortc::RTPPacket::MidHeaderExtension");

      UseServicesHelper::debugAppend(result, "mid", mid());

      return result;
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket::RidHeaderExtension
    #pragma mark

    //-------------------------------------------------------------------------
    ElementPtr RTPPacket::RidHeaderExtension::toDebug() const
    {
      ElementPtr result = Element::create("ortc::RTPPacket::RidHeaderExtension");

      UseServicesHelper::debugAppend(result, "rid", rid());

      return result;
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket::VideoOrientationHeaderExtension
    #pragma mark

    //-------------------------------------------------------------------------
    RTPPacket::VideoOrientationHeaderExtension::VideoOrientationHeaderExtension(const HeaderExtension &header)
    {
      mID = header.mID;
      mDataSizeInBytes = header.mDataSizeInBytes;
      mPostPaddingSize = header.mPostPaddingSize;
      if (NULL == header.mData) mDataSizeInBytes = 0;

      if (mDataSizeInBytes < sizeof(mEncoded)) return; // cannot decrypt this packet
    }

    //-------------------------------------------------------------------------
    RTPPacket::VideoOrientationHeaderExtension::VideoOrientationHeaderExtension(const VideoOrientation6HeaderExtension &)
    {
      mData = &(mEncoded[0]);
      mDataSizeInBytes = sizeof(mEncoded);
    }

    //-------------------------------------------------------------------------
    RTPPacket::VideoOrientationHeaderExtension::VideoOrientationHeaderExtension(
                                                                                const Clockwise &,
                                                                                bool frontFacingCamera,
                                                                                bool flip,
                                                                                UINT orientation
                                                                                )
    {
      mData = &(mEncoded[0]);
      mDataSizeInBytes = sizeof(mEncoded);

      orientation %= 360;

      // find closest approximation to the video orientation for the 2 bit allowance
      orientation += 45;  // range is now 45 -> 404
      orientation /= 90;
      orientation %= 4;   // range is now 0..3

      // Bit#       7   6   5   4   3   2    1     0 (LSB)
      // Definition 0   0   0   0   C   F   R1    R0

      mEncoded[0] = RTP_PACK_BITS(frontFacingCamera ? 1 : 0, 0x1, 3) |
                    RTP_PACK_BITS(flip ? 1 : 0, 0x1, 2) |
                    RTP_PACK_BITS(static_cast<BYTE>(orientation), 0x3, 0);
    }

    //-------------------------------------------------------------------------
    RTPPacket::VideoOrientationHeaderExtension::VideoOrientationHeaderExtension(
                                                                                const CounterClockwise &,
                                                                                bool frontFacingCamera, // true = front facing, false = backfacing
                                                                                bool flip, // horizontal left-right flip (mirro)
                                                                                UINT orientation
                                                                                ) :
      VideoOrientationHeaderExtension(Clockwise {}, frontFacingCamera, flip, 360-(orientation%360))
    {
    }

    //-------------------------------------------------------------------------
    bool RTPPacket::VideoOrientationHeaderExtension::frontFacing() const
    {
      if (NULL == mData) return false;
      return (0 != RTP_GET_BITS(mData[0], 0x1, 3));
    }

    //-------------------------------------------------------------------------
    bool RTPPacket::VideoOrientationHeaderExtension::backFacing() const
    {
      if (NULL == mData) return false;
      return (0 == RTP_GET_BITS(mData[0], 0x1, 3));
    }

    //-------------------------------------------------------------------------
    bool RTPPacket::VideoOrientationHeaderExtension::flip() const
    {
      if (NULL == mData) return false;
      return (0 == RTP_GET_BITS(mData[0], 0x1, 2));
    }

    //-------------------------------------------------------------------------
    UINT RTPPacket::VideoOrientationHeaderExtension::degreesClockwise() const
    {
      if (NULL == mData) return 0;
      UINT degrees = static_cast<UINT>(RTP_GET_BITS(mData[0], 0x3, 0));

      degrees *= 90;

      return degrees;
    }

    //-------------------------------------------------------------------------
    UINT RTPPacket::VideoOrientationHeaderExtension::degreesCounterClockwise() const
    {
      return (360-degreesClockwise())%360;
    }

    //-------------------------------------------------------------------------
    ElementPtr RTPPacket::VideoOrientationHeaderExtension::toDebug() const
    {
      ElementPtr result = Element::create("ortc::RTPPacket::VideoOrientationHeaderExtension");

      UseServicesHelper::debugAppend(result, "front facing", frontFacing());
      UseServicesHelper::debugAppend(result, "flip", flip());
      UseServicesHelper::debugAppend(result, "degrees", degreesClockwise());

      return result;
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket::VideoOrientation6HeaderExtension
    #pragma mark

    //-------------------------------------------------------------------------
    RTPPacket::VideoOrientation6HeaderExtension::VideoOrientation6HeaderExtension(const HeaderExtension &header) :
      VideoOrientationHeaderExtension(header)
    {
    }

    //-------------------------------------------------------------------------
    RTPPacket::VideoOrientation6HeaderExtension::VideoOrientation6HeaderExtension(
                                                                                const Clockwise &,
                                                                                bool frontFacingCamera,
                                                                                bool flip,
                                                                                UINT orientation
                                                                                ) :
      VideoOrientationHeaderExtension(*this)
    {
      // find closest approximation to the video orientation for the 6 bit allowance
      orientation %= 360;

      // r = x * 360
      //     -------
      //        64
      //
      // r * 64 = x * 360
      //
      // x = r * 64
      //     ------
      //      360

      orientation *= 64;
      orientation /= 360;
      orientation %= 64;

      //  Bit#         7   6     5     4     3     2     1     0 (LSB)
      //  Definition  R5  R4    R3    R2     C     F    R1    R0

      // R1	R0	R5	R4	R3	R2
      // 0  0   0   0   0   0   = 0
      // 0  0   0   0   0   1   = 1
      // 1  1   1   1   1   1   = 63

      BYTE ordered = static_cast<BYTE>(orientation) & 0x3F;

      mEncoded[0] = RTP_PACK_BITS(frontFacingCamera ? 1 : 0, 0x1, 3) |
                    RTP_PACK_BITS(flip ? 1 : 0, 0x1, 2) |
                    RTP_PACK_BITS(RTP_GET_BITS(ordered, 0x3, 4), 0x3, 0) |
                    RTP_PACK_BITS(RTP_GET_BITS(ordered, 0xF, 0), 0xF, 4);
    }

    //-------------------------------------------------------------------------
    RTPPacket::VideoOrientation6HeaderExtension::VideoOrientation6HeaderExtension(
                                                                                const CounterClockwise &,
                                                                                bool frontFacingCamera,
                                                                                bool flip,
                                                                                UINT orientation
                                                                                ) :
      VideoOrientation6HeaderExtension(Clockwise{}, frontFacingCamera, flip, 360-(orientation % 360))
    {
    }

    //-------------------------------------------------------------------------
    UINT RTPPacket::VideoOrientation6HeaderExtension::degreesClockwise() const
    {
      if (NULL == mData) return 0;

      BYTE ordered = RTP_PACK_BITS(RTP_GET_BITS(mData[0], 0x3, 0), 0x3, 4) |
                     RTP_PACK_BITS(RTP_GET_BITS(mData[0], 0xF, 4), 0xF, 0);

      UINT degrees = (static_cast<UINT>(ordered)*360)/64;
      return degrees % 360;
    }

    //-------------------------------------------------------------------------
    UINT RTPPacket::VideoOrientation6HeaderExtension::degreesCounterClockwise() const
    {
      return (360-degreesClockwise())%360;
    }

    //-------------------------------------------------------------------------
    ElementPtr RTPPacket::VideoOrientation6HeaderExtension::toDebug() const
    {
      ElementPtr result = Element::create("ortc::RTPPacket::VideoOrientation6HeaderExtension");

      UseServicesHelper::debugAppend(result, "front facing", frontFacing());
      UseServicesHelper::debugAppend(result, "flip", flip());
      UseServicesHelper::debugAppend(result, "degrees", degreesClockwise());

      return result;
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket (public)
    #pragma mark

    //-------------------------------------------------------------------------
    RTPPacket::RTPPacket(const make_private &)
    {
    }

    //-------------------------------------------------------------------------
    RTPPacket::~RTPPacket()
    {
      if (mHeaderExtensions) {
        delete [] mHeaderExtensions;
        mHeaderExtensions = NULL;
      }
    }

    //-------------------------------------------------------------------------
    RTPPacketPtr RTPPacket::create(const RTPPacket &packet)
    {
      RTPPacketPtr pThis(make_shared<RTPPacket>(make_private{}));
      pThis->generate(packet);
      return pThis;
    }

    //-------------------------------------------------------------------------
    RTPPacketPtr RTPPacket::create(const CreationParams &params)
    {
      RTPPacketPtr pThis(make_shared<RTPPacket>(make_private{}));
      pThis->generate(params);
      return pThis;
    }

    //-------------------------------------------------------------------------
    RTPPacketPtr RTPPacket::create(const BYTE *buffer, size_t bufferLengthInBytes)
    {
      ORTC_THROW_INVALID_PARAMETERS_IF(!buffer)
      ORTC_THROW_INVALID_PARAMETERS_IF(0 == bufferLengthInBytes)
      return RTPPacket::create(UseServicesHelper::convertToBuffer(buffer, bufferLengthInBytes));
    }

    //-------------------------------------------------------------------------
    RTPPacketPtr RTPPacket::create(const SecureByteBlock &buffer)
    {
      return RTPPacket::create(buffer.BytePtr(), buffer.SizeInBytes());
    }

    //-------------------------------------------------------------------------
    RTPPacketPtr RTPPacket::create(SecureByteBlockPtr buffer)
    {
      RTPPacketPtr pThis(make_shared<RTPPacket>(make_private{}));
      pThis->mBuffer = buffer;
      if (!pThis->parse()) {
        ZS_LOG_WARNING(Debug, pThis->log("packet could not be parsed"))
        return RTPPacketPtr();
      }
      return pThis;
    }

    //-------------------------------------------------------------------------
    const BYTE *RTPPacket::ptr() const
    {
      return mBuffer->BytePtr();
    }

    //-------------------------------------------------------------------------
    size_t RTPPacket::size() const
    {
      return mBuffer->SizeInBytes();
    }

    //-------------------------------------------------------------------------
    SecureByteBlockPtr RTPPacket::buffer() const
    {
      return mBuffer;
    }

    //-------------------------------------------------------------------------
    DWORD RTPPacket::getCSRC(size_t index) const
    {
      ASSERT(index < cc())
      return RTPUtils::getBE32(&((ptr())[kMinRtpPacketLen + (sizeof(DWORD)*index)]));
    }

    //-------------------------------------------------------------------------
    const BYTE *RTPPacket::payload() const
    {
      if (0 == mPayloadSize) return NULL;
      const BYTE *buffer = ptr();
      return &(buffer[mHeaderSize + mHeaderExtensionSize]);
    }

    //-------------------------------------------------------------------------
    RTPPacket::HeaderExtension *RTPPacket::getHeaderExtensionAtIndex(size_t index) const
    {
      if (index >= mTotalHeaderExtensions) return NULL;
      return &(mHeaderExtensions[index]);
    }

    //-------------------------------------------------------------------------
    ElementPtr RTPPacket::toDebug() const
    {
      ElementPtr objectEl = Element::create("ortc::RTPPacket");

      UseServicesHelper::debugAppend(objectEl, "buffer", mBuffer ? mBuffer->SizeInBytes() : 0);

      UseServicesHelper::debugAppend(objectEl, "version", mVersion);
      UseServicesHelper::debugAppend(objectEl, "padding", mPadding);
      UseServicesHelper::debugAppend(objectEl, "cc", mCC);
      UseServicesHelper::debugAppend(objectEl, "m", mM);
      UseServicesHelper::debugAppend(objectEl, "pt", mPT);
      UseServicesHelper::debugAppend(objectEl, "sequence number", mSequenceNumber);
      UseServicesHelper::debugAppend(objectEl, "timestamp", mTimestamp);
      UseServicesHelper::debugAppend(objectEl, "ssrc", mSSRC);

      UseServicesHelper::debugAppend(objectEl, "header size", mHeaderSize);
      UseServicesHelper::debugAppend(objectEl, "extension header size", mHeaderExtensionSize);
      UseServicesHelper::debugAppend(objectEl, "payload size", mPayloadSize);

      UseServicesHelper::debugAppend(objectEl, "total header extensions", mTotalHeaderExtensions);

      for (auto current = mHeaderExtensions; NULL != current; current = current->mNext)
      {
        ElementPtr extensionEl = Element::create("extension");
        UseServicesHelper::debugAppend(extensionEl, "id", current->mID);
        UseServicesHelper::debugAppend(extensionEl, "size", current->mDataSizeInBytes);
        UseServicesHelper::debugAppend(extensionEl, "data", (NULL != current->mData) ? UseServicesHelper::convertToHex(current->mData, current->mDataSizeInBytes) : String());
        UseServicesHelper::debugAppend(extensionEl, "padding", current->mPostPaddingSize);
        UseServicesHelper::debugAppend(objectEl, extensionEl);
      }

      UseServicesHelper::debugAppend(objectEl, "header extension appbits", mHeaderExtensionAppBits);

      UseServicesHelper::debugAppend(objectEl, "header extension prepadding size", mHeaderExtensionPrepaddedSize);
      UseServicesHelper::debugAppend(objectEl, "header extension parse stopped pos", (NULL != mHeaderExtensionParseStoppedPos) ? ((PTRNUMBER)(mHeaderExtensionParseStoppedPos - ptr())) : 0);
      UseServicesHelper::debugAppend(objectEl, "header extension parse stopped size", mHeaderExtensionParseStoppedSize);

      return objectEl;
    }

    //-------------------------------------------------------------------------
    static bool requiresTwoByteHeader(
                                      RTPPacket::HeaderExtension *firstExtension,
                                      BYTE headerExtensionAppBits
                                      )
    {
      typedef RTPPacket::HeaderExtension HeaderExtension;

      bool twoByteHeader = (0 != headerExtensionAppBits);
      if (!twoByteHeader) {
        for (HeaderExtension *current = firstExtension; NULL != current; current = current->mNext) {
          ASSERT(0 != current->mID) // not legal

          if (current->mID > 14) {
            twoByteHeader = true;
            break;
          }
          if (0 == current->mDataSizeInBytes) {
            twoByteHeader = true;
            break;
          }
          if (current->mDataSizeInBytes > 16) {
            ASSERT(current->mDataSizeInBytes < 255)
            twoByteHeader = true;
            break;
          }
        }
      }
      return twoByteHeader;
    }

    //-------------------------------------------------------------------------
    void RTPPacket::changeHeaderExtensions(HeaderExtension *firstExtension)
    {
      bool twoByteHeader = requiresTwoByteHeader(firstExtension, mHeaderExtensionAppBits);

      if (twoByteHeader) {
        ORTC_THROW_INVALID_STATE_IF(NULL != mHeaderExtensionParseStoppedPos)  // requires a 1 byte header to append this data
      }

      bool requiresExtension = requiredExtension(firstExtension, mHeaderExtensionAppBits, mHeaderExtensionPrepaddedSize, mHeaderExtensionParseStoppedPos);

      const BYTE *buffer = ptr();

      ASSERT(NULL != buffer)

      size_t existingHeaderExtensionSize = mHeaderExtensionSize;
      size_t postHeaderExtensionSize = mPayloadSize + mPadding;

      ASSERT(size() == (mHeaderSize + existingHeaderExtensionSize + postHeaderExtensionSize))

      if (!requiresExtension) {
        // going to strip the extension header out entirely

        if (RTP_HEADER_EXTENSION(buffer)) {
          ZS_LOG_INSANE(log("no extension present (thus no need to strip extension from RTP packet)"))
          return;
        }

        ASSERT(size() == (mHeaderSize + existingHeaderExtensionSize + postHeaderExtensionSize))

        size_t newSize = mHeaderSize + postHeaderExtensionSize;

        SecureByteBlockPtr tempBuffer(make_shared<SecureByteBlock>(newSize));

        BYTE *newBuffer = tempBuffer->BytePtr();

        // copy the bytes before the extension header to the new buffer
        memcpy(newBuffer, buffer, mHeaderSize);

        // copy the bytes from after the extension header in the older buffer to the new buffer
        memcpy(&(newBuffer[mHeaderSize]), &(buffer[mHeaderSize + existingHeaderExtensionSize]), postHeaderExtensionSize);

        // strip the extension bit
        newBuffer[0] = newBuffer[0] & (0xFF ^ RTP_HEADER_EXTENSION_BIT);

        mBuffer = tempBuffer;

        mHeaderExtensionSize = 0;

        mTotalHeaderExtensions = 0;
        if (mHeaderExtensions) {
          delete [] mHeaderExtensions;
          mHeaderExtensions = NULL;
        }
        mHeaderExtensionAppBits = 0;
        mHeaderExtensionPrepaddedSize = 0;
        mHeaderExtensionParseStoppedPos = NULL;
        mHeaderExtensionParseStoppedSize = 0;

        ZS_LOG_INSANE(debug("stripped existing extension header"))
        return;
      }

      mHeaderExtensionSize = 0;
      mTotalHeaderExtensions = 0;
      getHeaderExtensionSize(firstExtension, twoByteHeader, mHeaderExtensionPrepaddedSize, mHeaderExtensionParseStoppedSize, mHeaderExtensionSize, mTotalHeaderExtensions);

      size_t newSize = mHeaderSize + mHeaderExtensionSize + postHeaderExtensionSize;

      SecureByteBlockPtr oldBuffer = mBuffer; // temporary to keep previous allocation alive during swap

      mBuffer = make_shared<SecureByteBlock>(newSize);

      BYTE *newBuffer = mBuffer->BytePtr();

      // copy the bytes before the extension header to the new buffer
      memcpy(newBuffer, buffer, mHeaderSize);

      // copy the bytes from after the extension header in the older buffer to the new buffer
      memcpy(&(newBuffer[mHeaderSize + mHeaderExtensionSize]), &(buffer[mHeaderSize + existingHeaderExtensionSize]), postHeaderExtensionSize);

      writeHeaderExtensions(firstExtension, twoByteHeader);

      ZS_LOG_INSANE(debug("header extension changed"))
    }

    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    #pragma mark
    #pragma mark RTPPacket (internal)
    #pragma mark

    //-------------------------------------------------------------------------
    Log::Params RTPPacket::slog(const char *message)
    {
      ElementPtr objectEl = Element::create("ortc::RTPPacket");
      return Log::Params(message, objectEl);
    }

    //-------------------------------------------------------------------------
    Log::Params RTPPacket::log(const char *message) const
    {
      ElementPtr objectEl = Element::create("ortc::RTPPacket");
      return Log::Params(message, objectEl);
    }

    //-------------------------------------------------------------------------
    Log::Params RTPPacket::debug(const char *message) const
    {
      return Log::Params(message, toDebug());
    }

    //-------------------------------------------------------------------------
    bool RTPPacket::parse()
    {
      const BYTE *buffer = mBuffer->BytePtr();
      size_t size = mBuffer->SizeInBytes();

      if (size < kMinRtpPacketLen) {
        ZS_LOG_WARNING(Trace, log("packet length is too short") + ZS_PARAM("length", size))
        return false;
      }

      mVersion = RTP_HEADER_VERSION(buffer);
      if (mVersion != kRtpVersion) {
        ZS_LOG_WARNING(Trace, log("not an RTP packet"))
        return false;
      }

      if (RTPUtils::isRTCPPacketType(buffer, size)) {
        ZS_LOG_WARNING(Trace, log("packet is RTCP not RTP") + ZS_PARAM("length", size))
        return false;
      }

      bool hasPadding = RTP_HEADER_PADDING(buffer);
      mCC = RTP_HEADER_CC(buffer);
      mM = RTP_HEADER_M(buffer);
      mPT = RTP_HEADER_PT(buffer);
      mSequenceNumber = RTPUtils::getBE16(&(buffer[2]));
      mTimestamp = RTPUtils::getBE32(&(buffer[4]));
      mSSRC = RTPUtils::getBE32(&(buffer[8]));

      mHeaderSize = kMinRtpPacketLen + (static_cast<size_t>(mCC) * sizeof(DWORD));

      if (size < mHeaderSize) {
        ZS_LOG_WARNING(Trace, debug("illegal RTP packet"))
        return false;
      }

      if (RTP_HEADER_EXTENSION(buffer)) {
        if (size < (mHeaderSize + sizeof(DWORD))) {
          ZS_LOG_WARNING(Trace, debug("illegal RTP packet"))
          return false;
        }

        mHeaderExtensionSize = (static_cast<size_t>(RTPUtils::getBE16(&(buffer[mHeaderSize + 2]))) * sizeof(DWORD)) + sizeof(DWORD);
        if (size < (mHeaderSize + mHeaderExtensionSize)) {
          ZS_LOG_WARNING(Trace, debug("illegal RTP packet"))
          return false;
        }
      }

      if (hasPadding) {
        mPadding = static_cast<size_t>(buffer[size-1]);
        if (0 == mPadding) {
          ZS_LOG_WARNING(Trace, debug("illegal RTP packet (no padding size)"))
          return false;
        }

        if (size < (mHeaderSize + mHeaderExtensionSize + mPadding)) {
          ZS_LOG_WARNING(Trace, debug("illegal RTP packet"))
          return false;
        }
      }

      mPayloadSize = size - (mHeaderSize + mHeaderExtensionSize + mPadding);

      if (0 == mHeaderExtensionSize) {
        // no extensions present
        ZS_LOG_INSANE(debug("parsed"))
        return true;
      }

      const BYTE *profilePos = &(buffer[mHeaderSize]);

      bool oneByte = false;

      if ((0xBE == profilePos[0]) &&
          (0xDE == profilePos[1])) {
        oneByte = true;
      } else {
        WORD twoByteHeader = RTPUtils::getBE16(profilePos);
        mHeaderExtensionAppBits = (twoByteHeader & 0xF);

        if (0x100 != ((twoByteHeader & 0xFFF0) >> 4)) {
          ZS_LOG_WARNING(Trace, log("header extension profile is not understood") + ZS_PARAM("profile", twoByteHeader))
          return false;
        }
      }

      size_t remaining = mHeaderExtensionSize - sizeof(DWORD);
      if (0 == remaining) {
        ZS_LOG_INSANE(debug("parsed"))
        return true;
      }

      const BYTE *pos = &(profilePos[4]);

      size_t totalPossibleHeaderExtensions = (remaining / sizeof(WORD)) + ((0 != (remaining % sizeof(WORD))) ? 1 : 0);

      mHeaderExtensions = new HeaderExtension[totalPossibleHeaderExtensions] {};

      size_t totalFound = 0;

      while ((remaining > 0) &&
             (totalFound < totalPossibleHeaderExtensions)) {

        HeaderExtension *current = &(mHeaderExtensions[totalFound]);

        if (0 == pos[0]) {
          // see https://tools.ietf.org/html/rfc5285 4.1

          // A sequence of extension elements, possibly with padding, forms the
          // header extension defined in the RTP specification.  There are as many
          // extension elements as fit into the length as indicated in the RTP
          // header extension length.  Since this length is signaled in full 32-
          // bit words, padding bytes are used to pad to a 32-bit boundary.  The
          // entire extension is parsed byte-by-byte to find each extension
          // element (no alignment is required), and parsing stops at the earlier
          // of the end of the entire header extension, or, in one-byte headers,
          // on encountering an identifier with the reserved value of 15.

          // In both forms, padding bytes have the value of 0 (zero).  They may be
          // placed between extension elements, if desired for alignment, or after
          // the last extension element, if needed for padding.  A padding byte
          // does not supply the ID of an element, nor the length field.  When a
          // padding byte is found, it is ignored and the parser moves on to
          // interpreting the next byte.

          // skip padding byte
          ++pos;
          --remaining;
          if (0 == totalFound) {
            ++mHeaderExtensionPrepaddedSize;
          } else {
            ++(mHeaderExtensions[totalFound-1].mPostPaddingSize);
          }
          continue;
        }

        if (oneByte) {
          BYTE id = ((pos[0] & 0xF0) >> 4);
          if (id == 0xF) {
            // see https://tools.ietf.org/html/rfc5285 4.2

            // The local identifier value 15 is reserved for future extension and
            // MUST NOT be used as an identifier.  If the ID value 15 is
            // encountered, its length field should be ignored, processing of the
            // entire extension should terminate at that point, and only the
            // extension elements present prior to the element with ID 15
            // considered.
            mHeaderExtensionParseStoppedPos = pos;
            mHeaderExtensionParseStoppedSize = remaining;
            break;
          }

          // The 4-bit length is the number minus one of data bytes of this header
          // extension element following the one-byte header.  Therefore, the
          // value zero in this field indicates that one byte of data follows, and
          // a value of 15 (the maximum) indicates element data of 16 bytes.
          // (This permits carriage of 16-byte values, which is a common length of
          // labels and identifiers, while losing the possibility of zero-length
          // values -- which would often be padded anyway.)

          size_t length = static_cast<size_t>((pos[0] & 0x0F) + 1);

          if (remaining < (1 + length)) {
            ZS_LOG_WARNING(Trace, log("extension header is not valid") + ZS_PARAM("id", id) + ZS_PARAM("remaining", remaining) + ZS_PARAM("length", length))
            return false;
          }

          current->mID = id;
          current->mDataSizeInBytes = length;
          current->mData = &(pos[1]);
          if (0 != totalFound) {
            mHeaderExtensions[totalFound-1].mNext = current;
          }

          remaining -= (1 + length);
          pos += (1 + length);
          ++totalFound;
          continue;
        }

        // must be a two byte header format

        if (remaining < sizeof(WORD)) {
          ZS_LOG_WARNING(Trace, log("extension header is not valid") + ZS_PARAM("remaining", remaining))
          return false;
        }

        BYTE id = (pos[0]);
        size_t length = (pos[1]);

        if (remaining < (sizeof(WORD) + length)) {
          ZS_LOG_WARNING(Trace, log("extension header is not valid") + ZS_PARAM("id", id) + ZS_PARAM("remaining", remaining) + ZS_PARAM("length", length))
          return false;
        }

        current->mID = id;
        current->mDataSizeInBytes = length;
        if (0 != length) {
          current->mData = &(pos[2]);
        }
        if (0 != totalFound) {
          mHeaderExtensions[totalFound-1].mNext = current;
        }

        remaining -= (2 + length);
        pos += (2 + length);
        ++totalFound;
        continue;
      }

      mTotalHeaderExtensions = totalFound;

      ZS_LOG_INSANE(debug("parsed"))
      return true;
    }

    //-------------------------------------------------------------------------
    void RTPPacket::writeHeaderExtensions(
                                          HeaderExtension *firstExtension,
                                          bool twoByteHeader
                                          )
    {
      ASSERT((bool)mBuffer)
      ASSERT(0 != mBuffer->SizeInBytes())
      ASSERT(0 != mHeaderSize)
      //ASSERT(mHeaderExtensionAppBits)           // needs to be set (but no way to verify here)
      //ASSERT(mTotalHeaderExtensions)            // needs to be set (but no way to verify here)
      //ASSERT(mHeaderExtensionPrepaddedSize)     // needs to be set (but no way to verify here)
      //ASSSRT(mHeaderExtensionParseStoppedSize)  // needs to be set (but no way to verify here)
      //ASSERT(mHeaderExtensionParseStoppedPos)   // needs to be set (but no way to verify here)
      ASSERT(0 != mHeaderExtensionSize)

      BYTE *newBuffer = mBuffer->BytePtr();

      // set the extension bit
      newBuffer[0] = newBuffer[0] | RTP_HEADER_EXTENSION_BIT;

      BYTE *newProfilePos = &(newBuffer[mHeaderSize]);

      if (twoByteHeader) {
        WORD profileType = (0x100 << 4) | (mHeaderExtensionAppBits & 0xF);
        newProfilePos[0] = static_cast<BYTE>((profileType & 0xFF00) >> 8);
        newProfilePos[1] = static_cast<BYTE>(profileType & 0xFF);
      } else {
        newProfilePos[0] = 0xBE;
        newProfilePos[1] = 0xDE;
      }

      WORD totalDWORDsLength = static_cast<WORD>(((mHeaderExtensionSize - sizeof(DWORD)) / sizeof(DWORD)));
      newProfilePos[2] = static_cast<BYTE>((totalDWORDsLength & 0xFF00) >> 8);
      newProfilePos[3] = static_cast<BYTE>(totalDWORDsLength & 0xFF);

      BYTE *pos = &(newProfilePos[sizeof(DWORD)]) + mHeaderExtensionPrepaddedSize;

      HeaderExtension *newExtensions = NULL;
      if (0 != mTotalHeaderExtensions) {
        newExtensions = new HeaderExtension[mTotalHeaderExtensions] {};
      }

      size_t index = 0;
      for (HeaderExtension *current = firstExtension; NULL != current; current = current->mNext, ++index) {
        HeaderExtension *newCurrent = &(newExtensions[index]);
        if (0 != index) {
          newExtensions[index-1].mNext = newCurrent;
        }

        if (twoByteHeader) {
          pos[0] = current->mID;
          pos[1] = static_cast<BYTE>(current->mDataSizeInBytes);
          pos += 2;
        } else {
          pos[0] = ((current->mID) << 4) | ((current->mDataSizeInBytes - 1) & 0xF);
          ++pos;
        }

        newCurrent->mID = current->mID;
        newCurrent->mData = pos;
        newCurrent->mDataSizeInBytes = current->mDataSizeInBytes;
        newCurrent->mPostPaddingSize = current->mPostPaddingSize;

        if (0 != current->mDataSizeInBytes) {
          memcpy(pos, current->mData, current->mDataSizeInBytes);
          pos += current->mDataSizeInBytes;
        }
        pos += current->mPostPaddingSize;
      }

      if (0 != mHeaderExtensionParseStoppedSize) {
        ASSERT(NULL != mHeaderExtensionParseStoppedPos)

        memcpy(pos, mHeaderExtensionParseStoppedPos, mHeaderExtensionParseStoppedSize);
        mHeaderExtensionParseStoppedPos = pos;
      } else {
        mHeaderExtensionParseStoppedPos = NULL;
      }

      ASSERT(index == mTotalHeaderExtensions)

      mTotalHeaderExtensions = index;
      if (NULL != mHeaderExtensions) {
        delete [] mHeaderExtensions;
        mHeaderExtensions = NULL;
      }
      mHeaderExtensions = newExtensions;
    }

    //-------------------------------------------------------------------------
    void RTPPacket::generate(const RTPPacket &packet)
    {
      CreationParams params;

      params.mVersion = packet.version();
      params.mPadding = packet.padding();
      params.mM = packet.m();
      params.mPT = packet.pt();
      params.mSequenceNumber = packet.sequenceNumber();
      params.mTimestamp = packet.timestamp();
      params.mSSRC = packet.ssrc();

      params.mCC = packet.cc();
      params.mCC = (static_cast<BYTE>(packet.cc()) & 0xF);

      DWORD tmpCCList[0xF];
      if (params.mCC > 0) {
        for (decltype(params.mCC) index = 0; index < params.mCC; ++index) {
          tmpCCList[index] = packet.getCSRC(index);
        }
        params.mCSRCList = &(tmpCCList[0]);
      }

      params.mPayload = packet.payload();
      params.mPayloadSize = packet.payloadSize();
      params.mFirstHeaderExtension = packet.firstHeaderExtension();
      params.mHeaderExtensionAppBits = packet.headerExtensionAppBits();

      params.mHeaderExtensionPrepaddedSize = packet.headerExtensionPrepaddedSize();
      params.mHeaderExtensionStopParsePos = packet.headerExtensionParseStopped();
      params.mHeaderExtensionStopParseSize = packet.headerExtensionParseStoppedSize();

      generate(params);
    }

    //-------------------------------------------------------------------------
    void RTPPacket::generate(const CreationParams &params)
    {
      ASSERT(params.mVersion <= 0x3)
      ASSERT(params.mPadding <= 0xFF)
      ASSERT(params.mCC <= 0xF)
      ASSERT(params.mPT <= 0x7F)

      ASSERT(0 == params.mCC ? (NULL == params.mCSRCList) : (NULL != params.mCSRCList))
      ASSERT(0 == params.mPayloadSize ? (NULL == params.mPayload) : (NULL != params.mPayload))

      mVersion = params.mVersion & 0x3;
      mPadding = params.mPadding;
      mCC = (static_cast<BYTE>(params.mCC) & 0xF);
      mM = params.mM;
      mPT = (params.mPT & 0x7F);
      mSequenceNumber = params.mSequenceNumber;
      mTimestamp = params.mTimestamp;
      mSSRC = params.mSSRC;

      mHeaderSize = kMinRtpPacketLen + (static_cast<size_t>(mCC) * sizeof(DWORD));
      //mHeaderExtensionSize = 0; // filled in later
      mPayloadSize = params.mPayloadSize;

      //mTotalHeaderExtensions (later)
      //mHeaderExtensions (later)
      mHeaderExtensionAppBits = params.mHeaderExtensionAppBits;

      mHeaderExtensionPrepaddedSize = params.mHeaderExtensionPrepaddedSize;
      mHeaderExtensionParseStoppedPos = params.mHeaderExtensionStopParsePos;
      mHeaderExtensionParseStoppedSize = params.mHeaderExtensionStopParseSize;

      bool twoByteHeader = requiresTwoByteHeader(params.mFirstHeaderExtension, mHeaderExtensionAppBits);

      if (twoByteHeader) {
        ORTC_THROW_INVALID_STATE_IF(NULL != mHeaderExtensionParseStoppedPos)  // requires a 1 byte header to append this data
      }

      bool requiresExtension = requiredExtension(params.mFirstHeaderExtension, mHeaderExtensionAppBits, mHeaderExtensionPrepaddedSize, mHeaderExtensionParseStoppedPos);

      if (requiresExtension) {
        mHeaderExtensionSize = 0;
        mTotalHeaderExtensions = 0;
        getHeaderExtensionSize(params.mFirstHeaderExtension, twoByteHeader, mHeaderExtensionPrepaddedSize, mHeaderExtensionParseStoppedSize, mHeaderExtensionSize, mTotalHeaderExtensions);
      }

      size_t postHeaderExtensionSize = mPayloadSize + mPadding;

      size_t newSize = mHeaderSize + mHeaderExtensionSize + postHeaderExtensionSize;

      mBuffer = make_shared<SecureByteBlock>(newSize);

      BYTE *newBuffer = mBuffer->BytePtr();

      // fill standard header

      BYTE *pos = newBuffer;
      pos[0] = RTP_PACK_BITS(mVersion, 0x3, 6) |
               RTP_PACK_BITS(0 != mPadding ? 1 : 0, 0x1, 5) |
               RTP_PACK_BITS(requiresExtension ? 1 : 0, 0x1, 4) |
               RTP_PACK_BITS(mCC, 0xF, 0);
      pos[1] = RTP_PACK_BITS(mM ? 1 : 0, 0x1, 7) |
               RTP_PACK_BITS(mPT, 0x7F, 0);

      RTPUtils::setBE16(&(pos[2]), mSequenceNumber);
      RTPUtils::setBE32(&(pos[4]), mTimestamp);
      RTPUtils::setBE32(&(pos[8]), mSSRC);

      // write CSRC list (if any)
      for (size_t index = 0; index < static_cast<size_t>(mCC); ++index) {
        RTPUtils::setBE32(&(pos[12+(sizeof(DWORD)*index)]), params.mCSRCList[index]);
      }

      if (requiresExtension) {
        writeHeaderExtensions(params.mFirstHeaderExtension, twoByteHeader);
      }

      if (0 != mPayloadSize) {
        memcpy(&(pos[mHeaderSize+mHeaderExtensionSize]), params.mPayload, mPayloadSize);
      }

      if (0 != mPadding) {
        newBuffer[newSize-1] = static_cast<BYTE>(mPadding);
      }

      ZS_LOG_INSANE(debug("generated RTP packet"))
    }
  }

}


text:
<?php

require_once __DIR__ . '/../lib/base.php';

\header('Content-type: application/xml');

$request = \OC::$server->getRequest();

$url = $request->getServerProtocol() . '://' . \substr($request->getServerHost() . $request->getRequestUri(), 0, -17).'ocs/v1.php/';

$writer = new XMLWriter();
$writer->openURI('php://output');
$writer->startDocument('1.0', 'UTF-8');
$writer->setIndent(4);
$writer->startElement('providers');
$writer->startElement('provider');
$writer->writeElement('id', 'ownCloud');
$writer->writeElement('location', $url);
$writer->writeElement('name', 'ownCloud');
$writer->writeElement('icon', '');
$writer->writeElement('termsofuse', '');
$writer->writeElement('register', '');
$writer->startElement('services');
$writer->startElement('config');
$writer->writeAttribute('ocsversion', '1.7');
$writer->endElement();
$writer->startElement('activity');
$writer->writeAttribute('ocsversion', '1.7');
$writer->endElement();
$writer->startElement('cloud');
$writer->writeAttribute('ocsversion', '1.7');
$writer->endElement();
$writer->endElement();
$writer->endElement();
$writer->endDocument();
$writer->flush();

redpajama_set_name: RedPajamaGithub


text:
/***************************************************************
 * Generated by Hottentot CC Generator
 * Date: 02-05-2016 05:11:23
 * Name: calculator_service.h
 * Description:
 *   This file contains definition of service interface.
 ***************************************************************/

#ifndef _IR_NTNAEEM_HOTTENTOT_EXAMPLES_CALC__SERVICE__CALCULATOR_SERVICE_H_
#define _IR_NTNAEEM_HOTTENTOT_EXAMPLES_CALC__SERVICE__CALCULATOR_SERVICE_H_

#ifdef _MSC_VER
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif

#include <string>

#include <org/labcrypto/hottentot/primitives.h>
#include <org/labcrypto/hottentot/runtime/service/hot_context.h>

namespace ir {
namespace ntnaeem {
namespace hottentot {
namespace examples {
namespace calc {
namespace service {
  class CalculatorService {
  public:
     CalculatorService() {}
     virtual ~CalculatorService() {}
  public:
    virtual void Add(
      ::org::labcrypto::hottentot::UInt16 &a,
      ::org::labcrypto::hottentot::UInt16 &b,
      ::org::labcrypto::hottentot::UInt16 &out,
      ::org::labcrypto::hottentot::runtime::service::HotContext &hotContext
    ) = 0;
    virtual void Mul(
      ::org::labcrypto::hottentot::Int16 &a,
      ::org::labcrypto::hottentot::Int16 &b,
      ::org::labcrypto::hottentot::Int16 &out,
      ::org::labcrypto::hottentot::runtime::service::HotContext &hotContext
    ) = 0;
  };
} // END OF NAMESPACE service
} // END OF NAMESPACE calc
} // END OF NAMESPACE examples
} // END OF NAMESPACE hottentot
} // END OF NAMESPACE ntnaeem
} // END OF NAMESPACE ir

#endif


text:
package com.koch.ambeth.stream.binary;

import java.io.ByteArrayInputStream;

public class ReusableByteArrayInputStream extends ByteArrayInputStream {
	public ReusableByteArrayInputStream(byte[] buf) {
		super(buf);
	}

	public ReusableByteArrayInputStream(byte[] buf, int offset, int length) {
		super(buf, offset, length);
	}

	public void reset(byte[] buf) {
		mark = 0;
		pos = 0;
		this.buf = buf;
		count = buf.length;
	}
}


text:
package com.google.schemaorg.core;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.schemaorg.SchemaOrgType;
import com.google.schemaorg.SchemaOrgTypeImpl;
import com.google.schemaorg.ValueType;
import com.google.schemaorg.core.datatype.Text;
import com.google.schemaorg.core.datatype.URL;
import com.google.schemaorg.goog.GoogConstants;
import com.google.schemaorg.goog.PopularityScoreSpecification;

/** Implementation of {@link AnatomicalStructure}. */
public class AnatomicalStructureImpl extends MedicalEntityImpl implements AnatomicalStructure {
  private static final ImmutableSet<String> PROPERTY_SET = initializePropertySet();

  private static ImmutableSet<String> initializePropertySet() {
    ImmutableSet.Builder<String> builder = ImmutableSet.builder();

    builder.add(CoreConstants.PROPERTY_ADDITIONAL_TYPE);

    builder.add(CoreConstants.PROPERTY_ALTERNATE_NAME);

    builder.add(CoreConstants.PROPERTY_ASSOCIATED_PATHOPHYSIOLOGY);

    builder.add(CoreConstants.PROPERTY_BODY_LOCATION);

    builder.add(CoreConstants.PROPERTY_CODE);

    builder.add(CoreConstants.PROPERTY_CONNECTED_TO);

    builder.add(CoreConstants.PROPERTY_DESCRIPTION);

    builder.add(CoreConstants.PROPERTY_DIAGRAM);

    builder.add(CoreConstants.PROPERTY_FUNCTION);

    builder.add(CoreConstants.PROPERTY_GUIDELINE);

    builder.add(CoreConstants.PROPERTY_IMAGE);

    builder.add(CoreConstants.PROPERTY_MAIN_ENTITY_OF_PAGE);

    builder.add(CoreConstants.PROPERTY_MEDICINE_SYSTEM);

    builder.add(CoreConstants.PROPERTY_NAME);

    builder.add(CoreConstants.PROPERTY_PART_OF_SYSTEM);

    builder.add(CoreConstants.PROPERTY_POTENTIAL_ACTION);

    builder.add(CoreConstants.PROPERTY_RECOGNIZING_AUTHORITY);

    builder.add(CoreConstants.PROPERTY_RELATED_CONDITION);

    builder.add(CoreConstants.PROPERTY_RELATED_THERAPY);

    builder.add(CoreConstants.PROPERTY_RELEVANT_SPECIALTY);

    builder.add(CoreConstants.PROPERTY_SAME_AS);

    builder.add(CoreConstants.PROPERTY_STUDY);

    builder.add(CoreConstants.PROPERTY_SUB_STRUCTURE);

    builder.add(CoreConstants.PROPERTY_URL);

    builder.add(GoogConstants.PROPERTY_DETAILED_DESCRIPTION);

    builder.add(GoogConstants.PROPERTY_POPULARITY_SCORE);

    return builder.build();
  }

  static final class BuilderImpl extends SchemaOrgTypeImpl.BuilderImpl<AnatomicalStructure.Builder>
      implements AnatomicalStructure.Builder {

    @Override
    public AnatomicalStructure.Builder addAdditionalType(URL value) {
      return addProperty(CoreConstants.PROPERTY_ADDITIONAL_TYPE, value);
    }

    @Override
    public AnatomicalStructure.Builder addAdditionalType(String value) {
      return addProperty(CoreConstants.PROPERTY_ADDITIONAL_TYPE, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addAlternateName(Text value) {
      return addProperty(CoreConstants.PROPERTY_ALTERNATE_NAME, value);
    }

    @Override
    public AnatomicalStructure.Builder addAlternateName(String value) {
      return addProperty(CoreConstants.PROPERTY_ALTERNATE_NAME, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addAssociatedPathophysiology(Text value) {
      return addProperty(CoreConstants.PROPERTY_ASSOCIATED_PATHOPHYSIOLOGY, value);
    }

    @Override
    public AnatomicalStructure.Builder addAssociatedPathophysiology(String value) {
      return addProperty(CoreConstants.PROPERTY_ASSOCIATED_PATHOPHYSIOLOGY, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addBodyLocation(Text value) {
      return addProperty(CoreConstants.PROPERTY_BODY_LOCATION, value);
    }

    @Override
    public AnatomicalStructure.Builder addBodyLocation(String value) {
      return addProperty(CoreConstants.PROPERTY_BODY_LOCATION, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addCode(MedicalCode value) {
      return addProperty(CoreConstants.PROPERTY_CODE, value);
    }

    @Override
    public AnatomicalStructure.Builder addCode(MedicalCode.Builder value) {
      return addProperty(CoreConstants.PROPERTY_CODE, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addCode(String value) {
      return addProperty(CoreConstants.PROPERTY_CODE, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addConnectedTo(AnatomicalStructure value) {
      return addProperty(CoreConstants.PROPERTY_CONNECTED_TO, value);
    }

    @Override
    public AnatomicalStructure.Builder addConnectedTo(AnatomicalStructure.Builder value) {
      return addProperty(CoreConstants.PROPERTY_CONNECTED_TO, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addConnectedTo(String value) {
      return addProperty(CoreConstants.PROPERTY_CONNECTED_TO, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addDescription(Text value) {
      return addProperty(CoreConstants.PROPERTY_DESCRIPTION, value);
    }

    @Override
    public AnatomicalStructure.Builder addDescription(String value) {
      return addProperty(CoreConstants.PROPERTY_DESCRIPTION, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addDiagram(ImageObject value) {
      return addProperty(CoreConstants.PROPERTY_DIAGRAM, value);
    }

    @Override
    public AnatomicalStructure.Builder addDiagram(ImageObject.Builder value) {
      return addProperty(CoreConstants.PROPERTY_DIAGRAM, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addDiagram(String value) {
      return addProperty(CoreConstants.PROPERTY_DIAGRAM, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addFunction(Text value) {
      return addProperty(CoreConstants.PROPERTY_FUNCTION, value);
    }

    @Override
    public AnatomicalStructure.Builder addFunction(String value) {
      return addProperty(CoreConstants.PROPERTY_FUNCTION, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addGuideline(MedicalGuideline value) {
      return addProperty(CoreConstants.PROPERTY_GUIDELINE, value);
    }

    @Override
    public AnatomicalStructure.Builder addGuideline(MedicalGuideline.Builder value) {
      return addProperty(CoreConstants.PROPERTY_GUIDELINE, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addGuideline(String value) {
      return addProperty(CoreConstants.PROPERTY_GUIDELINE, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addImage(ImageObject value) {
      return addProperty(CoreConstants.PROPERTY_IMAGE, value);
    }

    @Override
    public AnatomicalStructure.Builder addImage(ImageObject.Builder value) {
      return addProperty(CoreConstants.PROPERTY_IMAGE, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addImage(URL value) {
      return addProperty(CoreConstants.PROPERTY_IMAGE, value);
    }

    @Override
    public AnatomicalStructure.Builder addImage(String value) {
      return addProperty(CoreConstants.PROPERTY_IMAGE, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addMainEntityOfPage(CreativeWork value) {
      return addProperty(CoreConstants.PROPERTY_MAIN_ENTITY_OF_PAGE, value);
    }

    @Override
    public AnatomicalStructure.Builder addMainEntityOfPage(CreativeWork.Builder value) {
      return addProperty(CoreConstants.PROPERTY_MAIN_ENTITY_OF_PAGE, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addMainEntityOfPage(URL value) {
      return addProperty(CoreConstants.PROPERTY_MAIN_ENTITY_OF_PAGE, value);
    }

    @Override
    public AnatomicalStructure.Builder addMainEntityOfPage(String value) {
      return addProperty(CoreConstants.PROPERTY_MAIN_ENTITY_OF_PAGE, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addMedicineSystem(MedicineSystem value) {
      return addProperty(CoreConstants.PROPERTY_MEDICINE_SYSTEM, value);
    }

    @Override
    public AnatomicalStructure.Builder addMedicineSystem(String value) {
      return addProperty(CoreConstants.PROPERTY_MEDICINE_SYSTEM, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addName(Text value) {
      return addProperty(CoreConstants.PROPERTY_NAME, value);
    }

    @Override
    public AnatomicalStructure.Builder addName(String value) {
      return addProperty(CoreConstants.PROPERTY_NAME, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addPartOfSystem(AnatomicalSystem value) {
      return addProperty(CoreConstants.PROPERTY_PART_OF_SYSTEM, value);
    }

    @Override
    public AnatomicalStructure.Builder addPartOfSystem(AnatomicalSystem.Builder value) {
      return addProperty(CoreConstants.PROPERTY_PART_OF_SYSTEM, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addPartOfSystem(String value) {
      return addProperty(CoreConstants.PROPERTY_PART_OF_SYSTEM, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addPotentialAction(Action value) {
      return addProperty(CoreConstants.PROPERTY_POTENTIAL_ACTION, value);
    }

    @Override
    public AnatomicalStructure.Builder addPotentialAction(Action.Builder value) {
      return addProperty(CoreConstants.PROPERTY_POTENTIAL_ACTION, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addPotentialAction(String value) {
      return addProperty(CoreConstants.PROPERTY_POTENTIAL_ACTION, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addRecognizingAuthority(Organization value) {
      return addProperty(CoreConstants.PROPERTY_RECOGNIZING_AUTHORITY, value);
    }

    @Override
    public AnatomicalStructure.Builder addRecognizingAuthority(Organization.Builder value) {
      return addProperty(CoreConstants.PROPERTY_RECOGNIZING_AUTHORITY, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addRecognizingAuthority(String value) {
      return addProperty(CoreConstants.PROPERTY_RECOGNIZING_AUTHORITY, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addRelatedCondition(MedicalCondition value) {
      return addProperty(CoreConstants.PROPERTY_RELATED_CONDITION, value);
    }

    @Override
    public AnatomicalStructure.Builder addRelatedCondition(MedicalCondition.Builder value) {
      return addProperty(CoreConstants.PROPERTY_RELATED_CONDITION, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addRelatedCondition(String value) {
      return addProperty(CoreConstants.PROPERTY_RELATED_CONDITION, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addRelatedTherapy(MedicalTherapy value) {
      return addProperty(CoreConstants.PROPERTY_RELATED_THERAPY, value);
    }

    @Override
    public AnatomicalStructure.Builder addRelatedTherapy(MedicalTherapy.Builder value) {
      return addProperty(CoreConstants.PROPERTY_RELATED_THERAPY, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addRelatedTherapy(String value) {
      return addProperty(CoreConstants.PROPERTY_RELATED_THERAPY, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addRelevantSpecialty(MedicalSpecialty value) {
      return addProperty(CoreConstants.PROPERTY_RELEVANT_SPECIALTY, value);
    }

    @Override
    public AnatomicalStructure.Builder addRelevantSpecialty(String value) {
      return addProperty(CoreConstants.PROPERTY_RELEVANT_SPECIALTY, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addSameAs(URL value) {
      return addProperty(CoreConstants.PROPERTY_SAME_AS, value);
    }

    @Override
    public AnatomicalStructure.Builder addSameAs(String value) {
      return addProperty(CoreConstants.PROPERTY_SAME_AS, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addStudy(MedicalStudy value) {
      return addProperty(CoreConstants.PROPERTY_STUDY, value);
    }

    @Override
    public AnatomicalStructure.Builder addStudy(MedicalStudy.Builder value) {
      return addProperty(CoreConstants.PROPERTY_STUDY, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addStudy(String value) {
      return addProperty(CoreConstants.PROPERTY_STUDY, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addSubStructure(AnatomicalStructure value) {
      return addProperty(CoreConstants.PROPERTY_SUB_STRUCTURE, value);
    }

    @Override
    public AnatomicalStructure.Builder addSubStructure(AnatomicalStructure.Builder value) {
      return addProperty(CoreConstants.PROPERTY_SUB_STRUCTURE, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addSubStructure(String value) {
      return addProperty(CoreConstants.PROPERTY_SUB_STRUCTURE, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addUrl(URL value) {
      return addProperty(CoreConstants.PROPERTY_URL, value);
    }

    @Override
    public AnatomicalStructure.Builder addUrl(String value) {
      return addProperty(CoreConstants.PROPERTY_URL, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addDetailedDescription(Article value) {
      return addProperty(GoogConstants.PROPERTY_DETAILED_DESCRIPTION, value);
    }

    @Override
    public AnatomicalStructure.Builder addDetailedDescription(Article.Builder value) {
      return addProperty(GoogConstants.PROPERTY_DETAILED_DESCRIPTION, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addDetailedDescription(String value) {
      return addProperty(GoogConstants.PROPERTY_DETAILED_DESCRIPTION, Text.of(value));
    }

    @Override
    public AnatomicalStructure.Builder addPopularityScore(PopularityScoreSpecification value) {
      return addProperty(GoogConstants.PROPERTY_POPULARITY_SCORE, value);
    }

    @Override
    public AnatomicalStructure.Builder addPopularityScore(
        PopularityScoreSpecification.Builder value) {
      return addProperty(GoogConstants.PROPERTY_POPULARITY_SCORE, value.build());
    }

    @Override
    public AnatomicalStructure.Builder addPopularityScore(String value) {
      return addProperty(GoogConstants.PROPERTY_POPULARITY_SCORE, Text.of(value));
    }

    @Override
    public AnatomicalStructure build() {
      return new AnatomicalStructureImpl(properties, reverseMap);
    }
  }

  public AnatomicalStructureImpl(
      Multimap<String, ValueType> properties, Multimap<String, Thing> reverseMap) {
    super(properties, reverseMap);
  }

  @Override
  public String getFullTypeName() {
    return CoreConstants.TYPE_ANATOMICAL_STRUCTURE;
  }

  @Override
  public boolean includesProperty(String property) {
    return PROPERTY_SET.contains(CoreConstants.NAMESPACE + property)
        || PROPERTY_SET.contains(GoogConstants.NAMESPACE + property)
        || PROPERTY_SET.contains(property);
  }

  @Override
  public ImmutableList<SchemaOrgType> getAssociatedPathophysiologyList() {
    return getProperty(CoreConstants.PROPERTY_ASSOCIATED_PATHOPHYSIOLOGY);
  }

  @Override
  public ImmutableList<SchemaOrgType> getBodyLocationList() {
    return getProperty(CoreConstants.PROPERTY_BODY_LOCATION);
  }

  @Override
  public ImmutableList<SchemaOrgType> getConnectedToList() {
    return getProperty(CoreConstants.PROPERTY_CONNECTED_TO);
  }

  @Override
  public ImmutableList<SchemaOrgType> getDiagramList() {
    return getProperty(CoreConstants.PROPERTY_DIAGRAM);
  }

  @Override
  public ImmutableList<SchemaOrgType> getFunctionList() {
    return getProperty(CoreConstants.PROPERTY_FUNCTION);
  }

  @Override
  public ImmutableList<SchemaOrgType> getPartOfSystemList() {
    return getProperty(CoreConstants.PROPERTY_PART_OF_SYSTEM);
  }

  @Override
  public ImmutableList<SchemaOrgType> getRelatedConditionList() {
    return getProperty(CoreConstants.PROPERTY_RELATED_CONDITION);
  }

  @Override
  public ImmutableList<SchemaOrgType> getRelatedTherapyList() {
    return getProperty(CoreConstants.PROPERTY_RELATED_THERAPY);
  }

  @Override
  public ImmutableList<SchemaOrgType> getSubStructureList() {
    return getProperty(CoreConstants.PROPERTY_SUB_STRUCTURE);
  }
}


text:
package utils;

import models.SiteAdmin;
import org.apache.commons.lang3.ObjectUtils;
import play.Configuration;
import play.mvc.Http;

import java.io.IOException;
import java.net.*;
import java.nio.charset.Charset;
import java.util.Enumeration;

public class Config {
    public static final String DEFAULT_SCHEME = "http";
    private static final String YONA_DATA = "yona.data"; //property from java -Dyona.data option string
    public static boolean isConnectableToGravatarServer = true;

    public static void onStart() {
        Diagnostic.register(new SimpleDiagnostic() {
            @Override
            public String checkOne() {
                Configuration config = Configuration.root();

                if (config.getInt("application.port") != null
                        && config.getString("application.hostname") == null) {
                    return "application.port may be ignored because " +
                            "application.hostname is not configured.";
                } else {
                    return null;
                }
            }
        });

        isConnectableToGravatarServer = isConnectableToGravatar();
    }

    public static String getSiteName() {
        return ObjectUtils.defaultIfNull(
                play.Configuration.root().getString("application.siteName"), "Yona");
    }

    public static String getContextRoot(){
        return play.Configuration.root().getString("application.context", "/");
    }

    public static String getHostport(String defaultValue) {
        String hostname = play.Configuration.root().getString("application.hostname");

        if (hostname != null && !hostname.isEmpty()) {
            Integer port = play.Configuration.root().getInt("application.port");

            if (port != null && !port.equals(80)) {
               return hostname + ":" + port.toString();
            } else {
               return hostname;
            }
        } else {
           return defaultValue;
        }
    }

    /**
     * @return the default IP address
     * @throws SocketException
     * @throws UnknownHostException
     */
    private static InetAddress getDefaultAddress() throws SocketException, UnknownHostException {
        Enumeration<NetworkInterface> n = NetworkInterface.getNetworkInterfaces();
        while(n.hasMoreElements())  {
            Enumeration<InetAddress> a = n.nextElement().getInetAddresses();
            while(a.hasMoreElements()) {
                InetAddress address = a.nextElement();
                if (!address.isAnyLocalAddress() && (address instanceof Inet4Address)) {
                    return address;
                }
            }
        }
        return InetAddress.getLocalHost();
    }

    /**
     * Detect the hostname.
     *
     * Return {@code application.hostname} from the Yobi's configuration if
     * available or the hostname from the IP address from
     * {@link #getDefaultAddress()}.
     *
     * @return the hostname
     */
    public static String getHostname() {
        play.Configuration config = play.Configuration.root();

        String hostname = play.Configuration.root().getString("application.hostname");
        if (hostname != null && !hostname.isEmpty()) {
            return hostname;
        }

        try {
            return getDefaultAddress().getHostName();
        } catch (Exception e) {
            play.Logger.warn("Failed to get the hostname", e);
            return "localhost";
        }
    }

    public static String getHostport() {
        Http.Context context = Http.Context.current.get();

        if (context != null) {
            return getHostport(context.request().host());
        } else {
            try {
                return getDefaultAddress().getHostAddress();
            } catch (Exception e) {
                play.Logger.warn("Failed to get the host address", e);
                return "localhost";
            }
        }
    }

    public static String getScheme(String defaultValue) {
        play.Configuration config = play.Configuration.root();

        String scheme = config.getString("application.scheme");

        if (scheme == null || scheme.isEmpty()) {
            return defaultValue;
        } else {
            return scheme;
        }
    }

    public static String getScheme() {
        Http.Context context = Http.Context.current.get();

        if (context != null) {
            try {
                return getScheme(getSchemeFromRequestURI(context.request()));
            } catch (URISyntaxException e) {
                play.Logger.warn("Failed to get the scheme part from the request-uri", e);
                return getScheme(DEFAULT_SCHEME);
            }
        } else {
            return getScheme(DEFAULT_SCHEME);
        }
    }

    private static String getSchemeFromRequestURI(Http.Request request) throws URISyntaxException {
        String scheme = new URI(request.uri()).getScheme();
        if (scheme == null) {
            return DEFAULT_SCHEME;
        } else {
            return scheme;
        }
    }

    public static String getSystemEmailAddress() {
        String email = getEmailFromSmtp();

        if (email != null) {
            return email;
        }

        models.User admin = (new SiteAdmin()).admin;

        if (admin != null && admin.email != null) {
            return admin.email;
        }

        return "yona@yona.io";
    }

    public static String getEmailFromSmtp() {
        return getEmail("smtp");
    }

    /**
     * Make a full URI from the given {@code uri} and the configuration.
     *
     * The new url is created by copying the given url and fill scheme and
     * authority if they are empty.
     *
     * @param uri
     * @return
     * @throws URISyntaxException
     */
    public static URI createFullURI(URI uri) throws URISyntaxException {
        String scheme = uri.getScheme();
        String authority = uri.getAuthority();

        scheme = (scheme != null) ? scheme : getScheme();
        authority = (authority != null) ? authority : getHostport();

        return new URI(
                scheme, authority, uri.getPath(), uri.getQuery(), uri.getFragment());
    }

    /**
     * Make URI from the given {@code uri} and the configuration.
     *
     * @return uri
     * @throws URISyntaxException
     * @see {@link #createFullURI(java.net.URI)}
     */
    public static URI createFullURI(String uri) throws URISyntaxException {
        return createFullURI(new URI(uri));
    }

    /**
     * Convert the given version to be compatible with
     * semver.
     *
     * Examples:
     *   v0.5.7 -> 0.5.7
     *   0.5 -> 0.5.0
     *   0.4.0.pre -> 0.4.0-pre
     *
     * @param ver  a version string to be semverized
     * @return     the semverized string
     */
    public static String semverize(String ver) {
        // v0.5.7 -> 0.5.7
        ver = ver.replaceFirst("^v", "");

        // 0.4.0.pre -> 0.4.0-pre
        ver = ver.replaceAll("\\.([^\\d]+)","-$1");

        // 0.5 -> 0.5.0
        // 0.5-alpha -> 0.5.0-alpha
        ver = ver.replaceFirst("^(\\d+\\.\\d+)($|-)", "$1.0$2");

        return ver;
    }

    /**
     * Return the version of Yobi installed currently.
     *
     * @return  the current version
     */
    public static String getCurrentVersion() {
        return yona.BuildInfo.version();
    }

    public static String getEmailFromImap() {
        return Configuration.root().getString("imap.address", getEmail("imap"));
    }

    private static String getEmail(String prefix) {
        Configuration config = Configuration.root();
        String user = config.getString(prefix + ".user");

        if (user == null) {
            return null;
        }

        if (user.contains("@")) {
            return user;
        } else {
            return user + "@" + config.getString(prefix + ".domain", getHostname());
        }
    }

    public static Charset getCharset() {
        return Charset.forName("UTF-8");
    }

    public static String getYonaDataDir() {
        return System.getProperty(YONA_DATA);
    }

    public static String getYonaDataDir(String defaultValue) {
        return System.getProperty(YONA_DATA, defaultValue);
    }

    public static boolean displayPrivateRepositories() {
        return Configuration.root().getBoolean("application.displayPrivateRepositories", Boolean.FALSE);
    }

    private static boolean isConnectableToGravatar() {
        try {
            return InetAddress.getByName("ko.gravatar.com").isReachable(100)
                    && InetAddress.getByName("www.gravatar.com").isReachable(100);
        } catch (IOException e) {
            play.Logger.warn("Gravatar server is unreachable. Gravatar service will not work.");
            return false;
        }
    }
}


text:
Heap.js
=======

[![Build Status](https://travis-ci.org/qiao/heap.js.svg?branch=master)](https://travis-ci.org/qiao/heap.js)

A binary heap implementation in CoffeeScript/JavaScript. Ported from Python's [heapq](http://docs.python.org/library/heapq.html) module.

Download
--------

This module can be used in either the browser or node.js.

for browser use, you may [download the script](https://raw.github.com/qiao/heap.js/master/lib/heap.js) and include it in you web page.

```html
<script type="text/javascript" src="./heap.js"></script>
```

for node.js, you may install it via npm:

```bash
npm install heap
```

then require it:

```
var Heap = require('heap');
```

Examples
-------

push and pop

```js
var heap = new Heap();
heap.push(3);
heap.push(1);
heap.push(2);
heap.pop(); // 1
```

custom comparison function

```js
var heap = new Heap(function(a, b) {
    return a.foo - b.foo;
});
heap.push({foo: 3});
heap.push({foo: 1});
heap.push({foo: 2});
heap.pop(); // {foo: 1}
```

find 3 largest/smallest items in an array

```js
var array = [1, 3, 4, 2, 5];
Heap.nlargest(array, 3);  // [5, 4, 3]
Heap.nsmallest(array, 3); // [1, 2, 3]
```

Document
--------

This module exposes only one object, namely the Heap class.

### Constructor: Heap([cmp]) ###

The constructor receives a comparison function as an optional parameter. If omitted, the heap is built as a min-heap, which means that the smallest element will be popped out first.

If the comparison function is supplied, the heap will be built according to the
return value of the comparison function.

* if cmp(a, b) < 0, then item a will come prior to b
* if cmp(a, b) > 0, then item b will come prior to a

So, the comparison function has the following form:

```js
function cmp(a, b) {
  if (a is prior to b) {
    return -1;
  }
  if (b is prior to a) {
    return 1;
  }
  return 0;
}
```

To compare numbers, simply:

```js
function cmp(a, b) {
  return a - b;
}
```

### Instance Methods ###

**push(item)** (alias: **insert**)

Push item onto heap.

**pop()**

Pop the smallest item off the heap and return it.

**peek()** (alias: **top** / **front**)

Return the smallest item of the heap.

**replace(item)**

Pop and return the current smallest value, and add the new item.

This is more efficient than pop() followed by push(), and can be
more appropriate when using a fixed size heap. Note that the value
returned may be larger than item!

**pushpop(item)**

Fast version of a push followed by a pop.

**heapify()**

Rebuild the heap. This method may come handy when the priority of the
internal data is being modified.

**updateItem(item)**

Update the position of the given item in the heap.
This function should be called every time the item is being modified.

**empty()**

Determine whether the heap is empty.

**size()**

Get the number of elements stored in the heap.

**toArray()**

Return the array representation of the heap. (note: the array is a shallow copy of the heap's internal nodes)

**clone()** (alias: **copy**)

Return a clone of the heap. (note: the internal data is a shallow copy of the original one)

### Static Methods ###

NOTE: All the static methods are designed to be applied on arrays.

**push(array, item, [cmp])**

Push item onto array, maintaining the heap invariant.

**pop(array, [cmp])**

Pop the smallest item off the array, maintaining the heap invariant.

**replace(array, item, [cmp])**

Pop and return the current smallest value, and add the new item.

This is more efficient than heappop() followed by heappush(), and can be
more appropriate when using a fixed size heap. Note that the value
returned may be larger than item!

**pushpop(array, item, [cmp])**

Fast version of a heappush followed by a heappop.

**heapify(array, [cmp])**

Build the heap.

**updateItem(array, item, [cmp])**

Update the position of the given item in the heap.
This function should be called every time the item is being modified.

**nlargest(array, n, [cmp])**

Find the n largest elements in a dataset.

**nsmallest(array, n, [cmp])**

Find the n smallest elements in a dataset.

License
-------

Ported by Xueqiao Xu <xueqiaoxu@gmail.com>

PSF LICENSE AGREEMENT FOR PYTHON 2.7.2

1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 2.7.2 software in source or binary form and its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.7.2 alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright © 2001-2012 Python Software Foundation; All Rights Reserved" are retained in Python 2.7.2 alone or in any derivative version prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.7.2 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.7.2.
4. PSF is making Python 2.7.2 available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.7.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.2 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.2, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python 2.7.2, Licensee agrees to be bound by the terms and conditions of this License Agreement.


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/custom_toast_container"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="8dp"
    android:background="#ddaaaaaa">

    <ImageView
        app:srcCompat="@drawable/ic_success"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="8dp" />

    <TextView android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#b10000" />

</LinearLayout>


text:
package main

import (
	"fmt"
	"menteslibres.net/gosexy/canvas"
)

func main() {
	image := canvas.New()

	// Opening some image from disk.
	err := image.Open("input/example.png")

	if err == nil {

		defer image.Destroy()

		// Photo auto orientation based on EXIF tags.
		image.AutoOrientate()

		// Creating a squared thumbnail
		image.Thumbnail(100, 100)

		// Saving the thumbnail to disk.
		image.Write("output/example-thumbnail.png")
	} else {
		fmt.Printf("Could not open image: %s\n", err)
	}
}


text:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawer_layout"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="in.voiceme.app.voiceme.login.LoginUserDetails"
tools:showIn="@layout/activity_login_user_details">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/include_toolbar3" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="20dp">

        <com.emmasuzuki.easyform.EasyForm
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="12dp" >

            <com.emmasuzuki.easyform.EasyTextInputLayout
                android:id="@+id/login_start_username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:hint="Enter Your Username"
                app:errorMessage="Username should be 5-25 chars"
                app:maxChars="20"
                app:minChars="5" />

        </com.emmasuzuki.easyform.EasyForm>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:id="@+id/submit_user_data_button"
        android:text="Submit"
        android:layout_gravity="center_horizontal"/>

    </LinearLayout>

</LinearLayout>

<include layout="@layout/include_main_nav_drawer" />

</android.support.v4.widget.DrawerLayout>