Exemple #1
0
ByteVector Ogg::Page::render() const
{
  ByteVector data;

  data.append(d->header.render());

  if(d->packets.isEmpty()) {
    if(d->file) {
      d->file->seek(d->fileOffset + d->header.size());
      data.append(d->file->readBlock(d->header.dataSize()));
    }
    else
      debug("Ogg::Page::render() -- this page is empty!");
  }
  else {
    ByteVectorList::ConstIterator it = d->packets.begin();
    for(; it != d->packets.end(); ++it)
      data.append(*it);
  }

  // Compute and set the checksum for the Ogg page.  The checksum is taken over
  // the entire page with the 4 bytes reserved for the checksum zeroed and then
  // inserted in bytes 22-25 of the page header.

  const ByteVector checksum = ByteVector::fromUInt(data.checksum(), false);
  std::copy(checksum.begin(), checksum.end(), data.begin() + 22);

  return data;
}
Exemple #2
0
String::String(const ByteVector &v, Type t)
{
  d = new StringPrivate;

  if(v.isEmpty())
    return;

  if(t == Latin1 || t == UTF8) {

    int length = 0;
    d->data.resize(v.size());
    wstring::iterator targetIt = d->data.begin();
    for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) {
      *targetIt = uchar(*it);
      ++targetIt;
      ++length;
    }
    d->data.resize(length);
  }
  else  {
    d->data.resize(v.size() / 2);
    wstring::iterator targetIt = d->data.begin();

    for(ByteVector::ConstIterator it = v.begin();
        it != v.end() && it + 1 != v.end() && combine(*it, *(it + 1));
        it += 2)
    {
      *targetIt = combine(*it, *(it + 1));
      ++targetIt;
    }
  }
  prepare(t);
}
// for 5.17 bootloaders the region 80040e00-80041000 is not added to
// the checksum.
void UpdateChecksum(DWORD& sum, const ByteVector& buffer)
{
    for (ByteVector::const_iterator bufp= buffer.begin() ; bufp != buffer.end() ; bufp+=4)
	{
		sum+=*(const DWORD*)iteratorptr(bufp);
	}
}
	void BufferReader::SetData(uchar* thePtr, int theCount)
	{
		mData.clear();
		mData.reserve(theCount);
		mData.insert(mData.begin(), thePtr, thePtr + theCount);
		mDataBitSize = mData.size() * 8;
	}
Exemple #5
0
void 
IpmiPayload::serializeEncryptedRmcpp(ByteVector& out, const ByteVector& key, const IpmiPayloadData& payload)
{
    IpmiPayloadData cryptedPayload;
    // generate random IV
    ByteVector iv;
    CryptoProxy::getInstance()->genRand(16, iv);
    
    // calculate padding length
    byte_t padLength = (16 - static_cast<byte_t>((payload.data.length() + 1/*for padLength field*/) % 16)) % 16;
    ByteVector payloadToCrypt(payload.data);
    
    // append padding
    for (byte_t i = 1; i <= padLength; ++i)
    {
        payloadToCrypt += i;
    }
    // append padding length
    payloadToCrypt += padLength;
    
    // crypt payload
    CryptoProxy::getInstance()->encrypt(key, iv, payloadToCrypt, cryptedPayload.data);
    
    // prefix crypted payload with IV
    cryptedPayload.data.insert(cryptedPayload.data.begin(), iv.begin(), iv.end());
    // serialize payload
    serializeRmcpp(out, cryptedPayload);
}
// --------- typed value to specific type conversions
bool Registry::ValueToStringList(const ByteVector& value, StringList& list)
{
    ByteVector::const_iterator str_start= value.begin();
    for (ByteVector::const_iterator i= value.begin() ; i!=value.end() ; ++i)
    {
        if (*i==0)
        {
            list.push_back(string(str_start, i));
            str_start= i+1;
        }
    }
    if (str_start!=value.end())
    {
        list.push_back(string(str_start, value.end()));
        str_start= value.end();
    }
    return true;
}
bool Registry::ValueToString(const ByteVector& value, std::string& str)
{
    str.clear();
    for (ByteVector::const_iterator i=value.begin() ; i!=value.end() && (*i)!=0 ; ++i)
    {
        str += (char)(*i);
    }
    return true;
}
unsigned long calculateDistance(Byte inBaseValue,const ByteVector& inVector)
{
    unsigned long result = 0;
    
    ByteVector::const_iterator it = inVector.begin();
    for(; it != inVector.end();++it)
        result+=std::abs(*it-inBaseValue);
    
    return result;
}
Exemple #9
0
//==============================================================================
void CC_UnitDriver::convert_lock_data_std_set(
    const StringVector& qualifiers,
    const ByteVector& lock_sizes,
    ByteVector& lock_data)
{
    ByteVector data(1, 0x1F);

    foreach (const String &item, qualifiers)
    {
        if (item == "debug")
            data[0] &= ~1;
        else if (item == "boot")
            data[0] &= ~0x10;
        else if (item == "flash" || item == "pages")
            data[0] &= ~0x0E;
        else if (item.find("flash:") == 0)
        {
            uint_t size = 0;
            String arg = item.substr(ARRAY_SIZE("flash:") - 1);
            if (!string_to_number(arg, size))
                throw std::runtime_error("incorrect flash size value");

            ByteVector::const_iterator it = std::find(
                                                lock_sizes.begin(),
                                                lock_sizes.end(),
                                                size);

            if (it == lock_sizes.end())
                throw std::runtime_error("target unsupport flash size " + arg);

            uint8_t index = (uint8_t)(it - lock_sizes.begin());

            data[0] &= ~(7 << 1); // clear out prev lock size data
            data[0] |= (~index & 0x07) << 1;
        }
        else
            throw std::runtime_error("unknown lock qualifyer: " + item);
    }
    lock_data = data;
}
Exemple #10
0
bool Registry::StringListToValue(const StringList& list, ByteVector& value)
{
    value.clear();
    ByteVector::iterator out= value.begin();
    for (StringList::const_iterator i= list.begin() ; i!=list.end() ; ++i)
    {
        value.reserve(value.size() + (*i).size()+1);
        copy((*i).begin(), (*i).end(), out);
        *out++= 0;
    }
    *out++= 0;
    return true;
}
Exemple #11
0
static void setIpAddr(ByteVector &result,mg_con_t *mgp)
{
	// This is the IP address, only IPv4 supported.
	// If the MS asks for IPv6, it is supposed to accept IPv4 anyway.
	result = ByteVector(6);// IPv4 address + 2 byte header.
	// 3GPP 24.008 10.5.6.4
	result.setByte(0,0x01); // IETF allocated address, which is all we support.
	result.setByte(1,0x21);	// IPv4.
	// This is a special case - we cannot use setUIint32 because it converts to network order,
	// but the ip address is already in network order, which is what 3GPP requires, so just copy it.
	memcpy(result.begin()+2, &mgp->mg_ip, 4);
	printf("IP address: %0x\n",mgp->mg_ip);
}
Exemple #12
0
void 
IpmiPayload::deserializeEncryptedRmcpp(ByteVector& outData, const ByteVector& key, const ByteVector& in, size_t& pos)
{
    // deserialize payload
    deserializeRmcpp(outData, in, pos);
    // strip IV from payload
    ByteVector iv(outData.c_ptr(), 16);

    outData.erase(outData.begin(), outData.begin() + 16);
    // decrypt payload
    ByteVector decryptedPayload;
    CryptoProxy::getInstance()->decrypt(key, iv, outData, decryptedPayload);
    // verify padding
    byte_t padLength = decryptedPayload[decryptedPayload.length() - 1];
    const byte_t* pad = decryptedPayload.c_ptr(decryptedPayload.length() - padLength -1);
    for (byte_t i = 1; i <= padLength; ++i, ++pad)
    {
        if (*pad != i)
            throw runtime_error("Incorrect padding on incoming encrypted message");
    }
    // strip padding
    outData.assign(decryptedPayload.begin(), decryptedPayload.end() - padLength -1);
}
Exemple #13
0
void Header::parse(const ByteVector &data)
{
  if(data.size() < size())
    return;


  // do some sanity checking -- even in ID3v2.3.0 and less the tag size is a
  // synch-safe integer, so all bytes must be less than 128.  If this is not
  // true then this is an invalid tag.

  // note that we're doing things a little out of order here -- the size is
  // later in the bytestream than the version

  ByteVector sizeData = data.mid(6, 4);

  if(sizeData.size() != 4) {
    d->tagSize = 0;
    debug("TagLib::ID3v2::Header::parse() - The tag size as read was 0 bytes!");
    return;
  }

  for(ByteVector::Iterator it = sizeData.begin(); it != sizeData.end(); it++) {
    if(uchar(*it) >= 128) {
      d->tagSize = 0;
      debug("TagLib::ID3v2::Header::parse() - One of the size bytes in the id3v2 header was greater than the allowed 128.");
      return;
    }
  }

  // The first three bytes, data[0..2], are the File Identifier, "ID3". (structure 3.1 "file identifier")

  // Read the version number from the fourth and fifth bytes.
  d->majorVersion = data[3];   // (structure 3.1 "major version")
  d->revisionNumber = data[4]; // (structure 3.1 "revision number")

  // Read the flags, the first four bits of the sixth byte.
  std::bitset<8> flags(data[5]);

  d->unsynchronisation     = flags[7]; // (structure 3.1.a)
  d->extendedHeader        = flags[6]; // (structure 3.1.b)
  d->experimentalIndicator = flags[5]; // (structure 3.1.c)
  d->footerPresent         = flags[4]; // (structure 3.1.d)

  // Get the size from the remaining four bytes (read above)

  d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size")
}
Exemple #14
0
ByteVector ID3v2::Tag::render(int version) const
{
  // We need to render the "tag data" first so that we have to correct size to
  // render in the tag's header.  The "tag data" -- everything that is included
  // in ID3v2::Header::tagSize() -- includes the extended header, frames and
  // padding, but does not include the tag's header or footer.

  if(version != 3 && version != 4) {
    debug("Unknown ID3v2 version, using ID3v2.4");
    version = 4;
  }

  // TODO: Render the extended header.

  // Downgrade the frames that ID3v2.3 doesn't support.

  FrameList newFrames;
  newFrames.setAutoDelete(true);

  FrameList frameList;
  if(version == 4) {
    frameList = d->frameList;
  }
  else {
    downgradeFrames(&frameList, &newFrames);
  }

  // Reserve a 10-byte blank space for an ID3v2 tag header.

  ByteVector tagData(Header::size(), '\0');

  // Loop through the frames rendering them and adding them to the tagData.

  for(FrameList::ConstIterator it = frameList.begin(); it != frameList.end(); it++) {
    (*it)->header()->setVersion(version);
    if((*it)->header()->frameID().size() != 4) {
      debug("An ID3v2 frame of unsupported or unknown type \'"
          + String((*it)->header()->frameID()) + "\' has been discarded");
      continue;
    }
    if(!(*it)->header()->tagAlterPreservation()) {
      const ByteVector frameData = (*it)->render();
      if(frameData.size() == Frame::headerSize((*it)->header()->version())) {
        debug("An empty ID3v2 frame \'"
          + String((*it)->header()->frameID()) + "\' has been discarded");
        continue;
      }
      tagData.append(frameData);
    }
  }

  // Compute the amount of padding, and append that to tagData.
  // TODO: Should be calculated in long long in taglib2.

  long originalSize = d->header.tagSize();
  long paddingSize = originalSize - (tagData.size() - Header::size());

  if(paddingSize <= 0) {
    paddingSize = MinPaddingSize;
  }
  else {
    // Padding won't increase beyond 1% of the file size or 1MB.

    long threshold = d->file ? d->file->length() / 100 : 0;
    threshold = std::max(threshold, MinPaddingSize);
    threshold = std::min(threshold, MaxPaddingSize);

    if(paddingSize > threshold)
      paddingSize = MinPaddingSize;
  }

  tagData.resize(static_cast<unsigned int>(tagData.size() + paddingSize), '\0');

  // Set the version and data size.
  d->header.setMajorVersion(version);
  d->header.setTagSize(tagData.size() - Header::size());

  // TODO: This should eventually include d->footer->render().
  const ByteVector headerData = d->header.render();
  std::copy(headerData.begin(), headerData.end(), tagData.begin());

  return tagData;
}
Exemple #15
0
Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) const
{
  ByteVector data = origData;
  uint version = tagHeader->majorVersion();
  Frame::Header *header = new Frame::Header(data, version);
  ByteVector frameID = header->frameID();

  // A quick sanity check -- make sure that the frameID is 4 uppercase Latin1
  // characters.  Also make sure that there is data in the frame.

  if(!frameID.size() == (version < 3 ? 3 : 4) ||
     header->frameSize() <= uint(header->dataLengthIndicator() ? 4 : 0) ||
     header->frameSize() > data.size())
  {
    delete header;
    return 0;
  }

  for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) {
    if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) {
      delete header;
      return 0;
    }
  }

  if(version > 3 && (tagHeader->unsynchronisation() || header->unsynchronisation())) {
    // Data lengths are not part of the encoded data, but since they are synch-safe
    // integers they will be never actually encoded.
    ByteVector frameData = data.mid(Frame::Header::size(version), header->frameSize());
    frameData = SynchData::decode(frameData);
    data = data.mid(0, Frame::Header::size(version)) + frameData;
  }

  // TagLib doesn't mess with encrypted frames, so just treat them
  // as unknown frames.

#if HAVE_ZLIB == 0
  if(header->compression()) {
    debug("Compressed frames are currently not supported.");
    return new UnknownFrame(data, header);
  }
#endif
  if(header->encryption()) {
    debug("Encrypted frames are currently not supported.");
    return new UnknownFrame(data, header);
  }

  if(!updateFrame(header)) {
    header->setTagAlterPreservation(true);
    return new UnknownFrame(data, header);
  }

  // updateFrame() might have updated the frame ID.

  frameID = header->frameID();

  // This is where things get necissarily nasty.  Here we determine which
  // Frame subclass (or if none is found simply an Frame) based
  // on the frame ID.  Since there are a lot of possibilities, that means
  // a lot of if blocks.

  // Text Identification (frames 4.2)

  if(frameID.startsWith("T")) {

    TextIdentificationFrame *f = frameID != "TXXX"
      ? new TextIdentificationFrame(data, header)
      : new UserTextIdentificationFrame(data, header);

    d->setTextEncoding(f);

    if(frameID == "TCON")
      updateGenre(f);

    return f;
  }

  // Comments (frames 4.10)

  if(frameID == "COMM") {
    CommentsFrame *f = new CommentsFrame(data, header);
    d->setTextEncoding(f);
    return f;
  }

  // Attached Picture (frames 4.14)

  if(frameID == "APIC") {
    AttachedPictureFrame *f = new AttachedPictureFrame(data, header);
    d->setTextEncoding(f);
    return f;
  }

  // ID3v2.2 Attached Picture

	if(frameID == "PIC") {
    AttachedPictureFrame *f = new AttachedPictureFrameV22(data, header);
    d->setTextEncoding(f);
    return f;
  }

	// Relative Volume Adjustment (frames 4.11)

  if(frameID == "RVA2")
    return new RelativeVolumeFrame(data, header);

  // Unique File Identifier (frames 4.1)

  if(frameID == "UFID")
    return new UniqueFileIdentifierFrame(data, header);

  // General Encapsulated Object (frames 4.15)

  if(frameID == "GEOB") {
    GeneralEncapsulatedObjectFrame *f = new GeneralEncapsulatedObjectFrame(data, header);
    d->setTextEncoding(f);
    return f;
  }

  // URL link (frames 4.3)

  if(frameID.startsWith("W")) {
    if(frameID != "WXXX") {
      return new UrlLinkFrame(data, header);
    }
    else {
      UserUrlLinkFrame *f = new UserUrlLinkFrame(data, header);
      d->setTextEncoding(f);
      return f;
    }
  }

  // Unsynchronized lyric/text transcription (frames 4.8)

  if(frameID == "USLT") {
    UnsynchronizedLyricsFrame *f = new UnsynchronizedLyricsFrame(data, header);
    if(d->useDefaultEncoding)
      f->setTextEncoding(d->defaultEncoding);
    return f;
  }

  // Popularimeter (frames 4.17)

  if(frameID == "POPM")
    return new PopularimeterFrame(data, header);

  // Private (frames 4.27)

  if(frameID == "PRIV")
    return new PrivateFrame(data, header);

  return new UnknownFrame(data, header);
}
Exemple #16
0
List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
                                      PaginationStrategy strategy,
                                      uint streamSerialNumber,
                                      int firstPage,
                                      bool firstPacketContinued,
                                      bool lastPacketCompleted,
                                      bool containsLastPacket)
{
  List<Page *> l;

  int totalSize = 0;

  for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it)
    totalSize += (*it).size();

  // Handle creation of multiple pages with appropriate pagination.
  if(strategy == Repaginate || totalSize + packets.size() > 255 * 255) {

    // SPLITSIZE must be a multiple of 255 in order to get the lacing values right
    // create pages of about 8KB each
#define SPLITSIZE (32*255)

    int pageIndex = 0;

    for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {
      bool continued = false;

      // mark very first packet?
      if(firstPacketContinued && it==packets.begin()) {
        continued = true;
      }

      // append to buf
      ByteVector packetBuf;
      packetBuf.append(*it);

      while(packetBuf.size() > SPLITSIZE) {
        // output a Page
        ByteVector packetForOnePage;
        packetForOnePage.resize(SPLITSIZE);
        std::copy(packetBuf.begin(), packetBuf.begin() + SPLITSIZE, packetForOnePage.begin());

        ByteVectorList packetList;
        packetList.append(packetForOnePage);
        Page *p = new Page(packetList, streamSerialNumber, firstPage+pageIndex, continued, false, false);
        l.append(p);

        pageIndex++;
        continued = true;
        packetBuf = packetBuf.mid(SPLITSIZE);
      }

      ByteVectorList::ConstIterator jt = it;
      ++jt;
      bool lastPacketInList = (jt == packets.end());

      // output a page for the rest (we output one packet per page, so this one should be completed)
      ByteVectorList packetList;
      packetList.append(packetBuf);

      bool isVeryLastPacket = false;
      if(containsLastPacket) {
        // mark the very last output page as last of stream
        ByteVectorList::ConstIterator jt = it;
        ++jt;
        if(jt == packets.end()) {
          isVeryLastPacket = true;
        }
      }

      Page *p = new Page(packetList, streamSerialNumber, firstPage+pageIndex, continued,
                         lastPacketInList ? lastPacketCompleted : true,
                         isVeryLastPacket);
      pageIndex++;

      l.append(p);
    }
  }
  else {
    Page *p = new Page(packets, streamSerialNumber, firstPage, firstPacketContinued,
                       lastPacketCompleted, containsLastPacket);
    l.append(p);
  }

  return l;
}
Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const
{
  Frame::Header *header = new Frame::Header(data, version);
  ByteVector frameID = header->frameID();

  // A quick sanity check -- make sure that the frameID is 4 uppercase Latin1
  // characters.  Also make sure that there is data in the frame.

  if(!frameID.size() == (version < 3 ? 3 : 4) ||
     header->frameSize() <= 0 ||
     header->frameSize() > data.size())
  {
    delete header;
    return 0;
  }

  for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) {
    if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) {
      delete header;
      return 0;
    }
  }

  // TagLib doesn't mess with encrypted frames, so just treat them
  // as unknown frames.

#if HAVE_ZLIB == 0
  if(header->compression()) {
    debug("Compressed frames are currently not supported.");
    return new UnknownFrame(data, header);
  }
#endif
  if(header->encryption()) {
    debug("Encrypted frames are currently not supported.");
    return new UnknownFrame(data, header);
  }

  if(!updateFrame(header)) {
    header->setTagAlterPreservation(true);
    return new UnknownFrame(data, header);
  }

  // updateFrame() might have updated the frame ID.

  frameID = header->frameID();

  // This is where things get necissarily nasty.  Here we determine which
  // Frame subclass (or if none is found simply an Frame) based
  // on the frame ID.  Since there are a lot of possibilities, that means
  // a lot of if blocks.

  // Text Identification (frames 4.2)

  if(frameID.startsWith("T")) {
    TextIdentificationFrame *f = frameID != "TXXX"
      ? new TextIdentificationFrame(data, header)
      : new UserTextIdentificationFrame(data, header);

    if(d->useDefaultEncoding)
      f->setTextEncoding(d->defaultEncoding);

    if(frameID == "TCON")
      updateGenre(f);

    return f;
  }

  // Comments (frames 4.10)

  if(frameID == "COMM") {
    CommentsFrame *f = new CommentsFrame(data, header);
    if(d->useDefaultEncoding)
      f->setTextEncoding(d->defaultEncoding);
    return f;
  }

  // Attached Picture (frames 4.14)

  if(frameID == "APIC") {
    AttachedPictureFrame *f = new AttachedPictureFrame(data, header);
    if(d->useDefaultEncoding)
      f->setTextEncoding(d->defaultEncoding);
    return f;
  }

  // Relative Volume Adjustment (frames 4.11)

  if(frameID == "RVA2")
    return new RelativeVolumeFrame(data, header);

  // Unique File Identifier (frames 4.1)

  if(frameID == "UFID")
    return new UniqueFileIdentifierFrame(data, header);

  // General Encapsulated Object (frames 4.15)

  if(frameID == "GEOB")
    return new GeneralEncapsulatedObjectFrame(data, header);

  return new UnknownFrame(data, header);
}
Exemple #18
0
bool Registry::StringToValue(const std::string& str, ByteVector& value)
{
    value.resize(str.size());
    copy(str.begin(), str.end(), value.begin());
    return true;
}
/**
 * Runs the operation.
 */
void ReadWriteThread::run()
    throw ()
{
    try {
        if (m_card.getType() != MemoryCard::TMemoryCard) {
            m_exception = new ReadWriteException(QObject::tr("There's no memory card in your "
                "reader.\nUse the test function in the configuration\ndialog to set up your "
                "reader properly."), ReadWriteException::CSmartcardError);
            return;
        }

        if (m_write && !m_pin.isNull()) {
            // try to unlock
            qDebug() << CURRENT_FUNCTION << "Trying to unlock the card ...";
            m_card.verify(m_pin);
        }

        if (!m_card.selectFile()) {
            m_exception = new ReadWriteException(QObject::tr("<qt>It was not possible to select the "
                "file on the smartcard</qt>"), ReadWriteException::CSmartcardError);
            return;
        }

        if (m_write) {
            // write the random number
            ByteVector byteVector(1);
            byteVector[0] = m_randomNumber;
            qDebug() << CURRENT_FUNCTION << "Writing random =" << byteVector[0];
            m_card.write(0, byteVector);

            // write the password hash and include a length information
            ByteVector pwHash = PasswordHash::generateHash(m_password);
            pwHash.insert(pwHash.begin(), pwHash.size());
            m_card.write(1, pwHash);

            qDebug() << CURRENT_FUNCTION << "Password hash length = " << (pwHash.size()-1);

            // then write the number of bytes
            int numberOfBytes = m_bytes.size();
            byteVector.resize(3);
            byteVector[0] = (numberOfBytes & 0xFF00) >> 8;
            byteVector[1] = numberOfBytes & 0xFF;
            byteVector[2] = 0; // fillbyte
            m_card.write(PasswordHash::MAX_HASH_LENGTH+2, byteVector);

            // and finally write the data
            m_card.write(PasswordHash::MAX_HASH_LENGTH+5, m_bytes);

        } else {
            // read the random number
            if (m_card.read(0, 1)[0] != m_randomNumber) {
                m_exception = new ReadWriteException(QObject::tr("You inserted the wrong smartcard!"),
                    ReadWriteException::CSmartcardError);
                return;
            }

            qDebug() << CURRENT_FUNCTION << "Read randomNumber =" << m_randomNumber;

            // read the password hash, check the password and throw a exception if necessary
            unsigned char len = m_card.read(1, 1)[0];
            ByteVector pwHash = m_card.read(2, len);

            qDebug() << CURRENT_FUNCTION << "Password hash length =" << len;

            if (!PasswordHash::isCorrect(m_password, pwHash)) {
                m_exception = new ReadWriteException(QObject::tr("The given password was wrong."),
                    ReadWriteException::CWrongPassword);
                return;
            }

            // read the number
            ByteVector vec = m_card.read(PasswordHash::MAX_HASH_LENGTH + 2, 2);
            int numberOfBytes = (vec[0] << 8) + (vec[1]);

            qDebug() << CURRENT_FUNCTION << "Read numberOfBytes =" << numberOfBytes;

            Q_ASSERT(numberOfBytes >= 0);

            // read the bytes
            m_bytes = m_card.read(PasswordHash::MAX_HASH_LENGTH+5, numberOfBytes);
        }
    } catch (const CardException& e) {
Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHeader) const
{
  ByteVector data = origData;
  unsigned int version = tagHeader->majorVersion();
  Frame::Header *header = new Frame::Header(data, version);
  ByteVector frameID = header->frameID();

  // A quick sanity check -- make sure that the frameID is 4 uppercase Latin1
  // characters.  Also make sure that there is data in the frame.

  if(frameID.size() != (version < 3 ? 3 : 4) ||
     header->frameSize() <= static_cast<unsigned int>(header->dataLengthIndicator() ? 4 : 0) ||
     header->frameSize() > data.size())
  {
    delete header;
    return 0;
  }

#ifndef NO_ITUNES_HACKS
  if(version == 3 && frameID.size() == 4 && frameID[3] == '\0') {
    // iTunes v2.3 tags store v2.2 frames - convert now
    frameID = frameID.mid(0, 3);
    header->setFrameID(frameID);
    header->setVersion(2);
    updateFrame(header);
    header->setVersion(3);
  }
#endif

  for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) {
    if( (*it < 'A' || *it > 'Z') && (*it < '0' || *it > '9') ) {
      delete header;
      return 0;
    }
  }

  if(version > 3 && (tagHeader->unsynchronisation() || header->unsynchronisation())) {
    // Data lengths are not part of the encoded data, but since they are synch-safe
    // integers they will be never actually encoded.
    ByteVector frameData = data.mid(Frame::Header::size(version), header->frameSize());
    frameData = SynchData::decode(frameData);
    data = data.mid(0, Frame::Header::size(version)) + frameData;
  }

  // TagLib doesn't mess with encrypted frames, so just treat them
  // as unknown frames.

#if !defined(HAVE_ZLIB) || HAVE_ZLIB == 0
  if(header->compression()) {
    debug("Compressed frames are currently not supported.");
    return new UnknownFrame(data, header);
  }
#endif
  if(header->encryption()) {
    debug("Encrypted frames are currently not supported.");
    return new UnknownFrame(data, header);
  }

  if(!updateFrame(header)) {
    header->setTagAlterPreservation(true);
    return new UnknownFrame(data, header);
  }

  // updateFrame() might have updated the frame ID.

  frameID = header->frameID();

  // This is where things get necissarily nasty.  Here we determine which
  // Frame subclass (or if none is found simply an Frame) based
  // on the frame ID.  Since there are a lot of possibilities, that means
  // a lot of if blocks.

  // Text Identification (frames 4.2)

  // Apple proprietary WFED (Podcast URL) is in fact a text frame.
  if(frameID.startsWith("T") || frameID == "WFED") {

    TextIdentificationFrame *f = frameID != "TXXX"
      ? new TextIdentificationFrame(data, header)
      : new UserTextIdentificationFrame(data, header);

    d->setTextEncoding(f);

    if(frameID == "TCON")
      updateGenre(f);

    return f;
  }

  // Comments (frames 4.10)

  if(frameID == "COMM") {
    CommentsFrame *f = new CommentsFrame(data, header);
    d->setTextEncoding(f);
    return f;
  }

  // Attached Picture (frames 4.14)

  if(frameID == "APIC") {
    AttachedPictureFrame *f = new AttachedPictureFrame(data, header);
    d->setTextEncoding(f);
    return f;
  }

  // ID3v2.2 Attached Picture

  if(frameID == "PIC") {
    AttachedPictureFrame *f = new AttachedPictureFrameV22(data, header);
    d->setTextEncoding(f);
    return f;
  }

  // Relative Volume Adjustment (frames 4.11)

  if(frameID == "RVA2")
    return new RelativeVolumeFrame(data, header);

  // Unique File Identifier (frames 4.1)

  if(frameID == "UFID")
    return new UniqueFileIdentifierFrame(data, header);

  // General Encapsulated Object (frames 4.15)

  if(frameID == "GEOB") {
    GeneralEncapsulatedObjectFrame *f = new GeneralEncapsulatedObjectFrame(data, header);
    d->setTextEncoding(f);
    return f;
  }

  // URL link (frames 4.3)

  if(frameID.startsWith("W")) {
    if(frameID != "WXXX") {
      return new UrlLinkFrame(data, header);
    }
    else {
      UserUrlLinkFrame *f = new UserUrlLinkFrame(data, header);
      d->setTextEncoding(f);
      return f;
    }
  }

  // Unsynchronized lyric/text transcription (frames 4.8)

  if(frameID == "USLT") {
    UnsynchronizedLyricsFrame *f = new UnsynchronizedLyricsFrame(data, header);
    if(d->useDefaultEncoding)
      f->setTextEncoding(d->defaultEncoding);
    return f;
  }

  // Synchronised lyrics/text (frames 4.9)

  if(frameID == "SYLT") {
    SynchronizedLyricsFrame *f = new SynchronizedLyricsFrame(data, header);
    if(d->useDefaultEncoding)
      f->setTextEncoding(d->defaultEncoding);
    return f;
  }

  // Event timing codes (frames 4.5)

  if(frameID == "ETCO")
    return new EventTimingCodesFrame(data, header);

  // Popularimeter (frames 4.17)

  if(frameID == "POPM")
    return new PopularimeterFrame(data, header);

  // Private (frames 4.27)

  if(frameID == "PRIV")
    return new PrivateFrame(data, header);

  // Ownership (frames 4.22)

  if(frameID == "OWNE") {
    OwnershipFrame *f = new OwnershipFrame(data, header);
    d->setTextEncoding(f);
    return f;
  }

  // Chapter (ID3v2 chapters 1.0)

  if(frameID == "CHAP")
    return new ChapterFrame(tagHeader, data, header);

  // Table of contents (ID3v2 chapters 1.0)

  if(frameID == "CTOC")
    return new TableOfContentsFrame(tagHeader, data, header);

  // Apple proprietary PCST (Podcast)

  if(frameID == "PCST")
    return new PodcastFrame(data, header);

  return new UnknownFrame(data, header);
}
Exemple #21
0
// Call this to update the PCO for retransmission to the MS.
// We cannot just make up a PCO ahead of time and then send it out to
// all the MS for two reasons:
// o The incoming options have uniquifying transaction identifiers that are
// different each time, so we must modify the incoming pcoReq each time while
// carefully preserving those modifiers.
// o There are two major formats for the PCO options - see below.
static void setPco(ByteVector &resultpco, ByteVector &pcoReq, mg_con_t *mgp)
{
	if (mg_dns[0] == 0) { ip_finddns(mg_dns); }

	// GSM 24.008 10.5.6.3: Procotol Configuration Options.
	// These are the "negotiated" address params wrapped in PPP,
	// except they are not very negotiated; we are going to cram them
	// into the MS and it can accept them or die.
	// The first byte is the header, followed by any number of:
	//	protocol id (2 octets)
	//	length of contents (1 octet)
	// I have seen this supplied by the MS in two different ways:
	// - as two separate 0x8021 requests, each with a single option request
	//	(Blackberry)
	// - as a single 0x8021 request with two option requests for the two DNS servers.
	//	(Samsung phone)
	resultpco.clone(pcoReq);
	unsigned char *pc = resultpco.begin();
	unsigned char *end = pc + resultpco.size();
	 __attribute__((unused)) const char *protname = "";
	if (pc == NULL) {
		MGERROR("SGSN: Empty PCO field")
	}
	else if (*pc++ != 0x80) {
		MGERROR("SGSN: Unrecognized PCO Config Protocol: %d\n",pc[-1]);
	} else while (pc < end) {
		unsigned proto = (pc[0] << 8) + pc[1];
		pc += 2;
		unsigned ipcplen = *pc++;
		if (proto == 0x8021) {	// IP Control Protocol.
			// IPCP looks like this:
			// 1 byte: command: 1 => configure-request
			// 1 byte: transaction uniquifying identifier.
			// 2 bytes: total length of ipcp (even though length above was a byte)
			// Followed by IPCP options, where each option is:
			//		1 byte: option code
			//		1 byte: total option length N (should be 6)
			//		N bytes: data
			if (pc[0] == 1) {	// command = configure-request
				// pc[1] is the uniquifying identifier, leave it alone.
				// pc[2]&pc[3] are another length.
				// Followed by one or more 6 byte option consisting of:
					// pc[4]: IPCP option code
					// pc[5]: length (6)
					// pc[6-9]: data
				// Note: the 4 byte header length is included in the option_len
				unsigned ipcp_len = pc[3];  // pc[2] better be 0.
				unsigned char *op;
				for (op = &pc[4]; op < pc + ipcp_len; op += op[1]) {
					const char *what = "";
					switch (op[0]) {
					case 0x03:
						pc[0] = 2;
                                                if (op[1] < 6) { goto bad_ipcp_opt_len; }
						memcpy(&op[2], &mgp->mg_ip, 4);
						break;
					case 0x81:	// primary dns.
						pc[0] = 2;	// IPCP command = ACK
						if (op[1] < 6) {
							bad_ipcp_opt_len:
							MGERROR("SGSN: Invalid PCO IPCP Config Option Length: opt=0x%x len=%d\n",
							op[0], op[1]);
							goto next_protocol;
						}
						memcpy(&op[2], &mg_dns[0], 4);	// addr in network order.
						break;
					case 0x83:	// secondary dns
						pc[0] = 2;	// IPCP command = ACK
						if (op[1] < 6) { goto bad_ipcp_opt_len; }
						memcpy(&op[2], &mg_dns[mg_dns[1] ? 1 : 0], 4);	// addr in network order.
						break;
					case 2:
						what = "IP Compression Protocol"; goto bad_ipcp;
					case 0x82:
						what = "primary NBNS [NetBios Name Service]"; goto bad_ipcp;
					case 0x84:
						what = "secondary NBNS [NetBios Name Service]"; goto bad_ipcp;
					default: bad_ipcp:
						// It would be nice to send an SMS message that the phone is set up improperly.
						MGWARN("SGSN: warning: ignoring PDP Context activation IPCP option %d %s\n",pc[4],what);
						break;
					}
				}
			}
		} else if (proto == 0xc021) {	// LCP: 
			protname = "(LCP [Link Control Protocol] for PPP)";
			goto unsupported_protocol;
		} else if (proto == 0xc223) {	// CHAP:
			protname = "(CHAP [Challenge-Handshake Authentication Protocol] for PPP)";
			goto unsupported_protocol;
		} else if (proto == 0xc023) {	// PAP: Password authentication protocol.
			protname = "(PAP [Password Authentication Protocol] for PPP)";
			// 6-12: Remove this message for the 3.0 release because we get
			// lots of bogus complaints about PAP.
			//goto unsupported_protocol;
			goto next_protocol;
		} else {
			// If we see any of these options are non-empty, the MS may be configured to use PPP.
			// It is hopeless; user must reconfigure the MS.
			unsupported_protocol:
			if (ipcplen) {
				MGWARN("SGSN: warning: ignoring PDP Context activation sub-protocol 0x%x %s; MS may require reconfiguration.\n",proto,protname);
			}
		}
		next_protocol:
		pc += ipcplen;
	}
}
Byte calculateImageBrightnessFactor(const std::string& inImageFilePath)
{
    BrightnessState state;
    InputFile inputFile;
    ByteVector brightnessValues;
    DistanceAndBrightnessVector valuesForAverage;
    
    inputFile.OpenFile(inImageFilePath);
    
    state.mStream = inputFile.GetInputStream();
    InitializeDecodingState(state);
    StartRead(state);
    
    LongBufferSizeType samplesSkipping = 1; // max samples 20
    if(state.mJPGState.output_width > 500)
        samplesSkipping = state.mJPGState.output_width / 50; // max samples - 50
    else if(state.mJPGState.output_width > 20)
        samplesSkipping = 10; // max samples - 50
    
    LongBufferSizeType rowsSkipping = 1; // max samples 20
    if(state.mJPGState.output_height > 500)
        rowsSkipping = state.mJPGState.output_height / 50; // max samples - 50
    else if(state.mJPGState.output_height > 20)
        rowsSkipping = 10; // max samples - 50
    
    LongBufferSizeType rowCounter = 0;
    
    
    // read samples from image, converting to hsb and keeping the "b" component, as a brightness factor
    while(state.mJPGState.output_scanline < state.mJPGState.output_height)
    {
        try
        {
            state.mTotalSampleRows = jpeg_read_scanlines(&(state.mJPGState), state.mSamplesBuffer, state.mJPGState.rec_outbuf_height);
            ++rowCounter;
            if(rowCounter >= rowsSkipping)
                rowCounter = 0;
            else if(rowCounter != 1)
                continue;
        }
        catch(HummusJPGException)
        {
            state.mTotalSampleRows = 0;
        }
        state.mIndexInRow = 0;
        state.mCurrentSampleRow = 0;
        
        while(state.mCurrentSampleRow < state.mTotalSampleRows)
        {
            LongBufferSizeType row_stride = state.mJPGState.output_width * state.mJPGState.output_components;
            
            // convert samples to HSB (note that some samples are skipped)
            for(LongBufferSizeType i=0;i<row_stride;i+=(state.mJPGState.output_components*samplesSkipping))
            {
                // get rgb
                Byte r = state.mSamplesBuffer[state.mCurrentSampleRow][i];
                Byte g = state.mSamplesBuffer[state.mCurrentSampleRow][i+1];
                Byte b = state.mSamplesBuffer[state.mCurrentSampleRow][i+2];
                
                // calculate brightness [converting to HSB]
                brightnessValues.push_back(RGBtoHSVtoBrightness(r,g,b));
            }
            
            
            ++state.mCurrentSampleRow;
        }
    }
    FinalizeDecoding(state);
    
    // prepare distance data and sort, to remove extremes from calculation
    ByteVector::const_iterator it = brightnessValues.begin();
    for(;it!=brightnessValues.end();++it)
        valuesForAverage.push_back(DistanceAndBrightness(*it,calculateDistance(*it,brightnessValues)));
    
    std::sort(valuesForAverage.begin(),valuesForAverage.end(),DistanceAndBrightnessSort);
    
    
    // now simply calculate the average based on the first 2/3 of the vector, to reduce the effects of extremes
    double average = 0;
    DistanceAndBrightnessVector::const_iterator itCurrent = valuesForAverage.begin();
    unsigned long interestingItemsCount = floor(valuesForAverage.size()*2.0/3.0);
    DistanceAndBrightnessVector::const_iterator itEnd = valuesForAverage.begin()+interestingItemsCount;
    for(itCurrent = valuesForAverage.begin();itCurrent!=itEnd;++itCurrent)
        average+=(double)(itCurrent->brightness)/interestingItemsCount;
    return ceil(average);
}
Exemple #23
0
void SoftwareBreakpointManager::getOpcode(uint32_t type,
                                          ByteVector &opcode) const {
#if defined(OS_WIN32) && defined(ARCH_ARM)
  if (type == 4) {
    static const uint32_t WinARMBPType = 2;
    DS2LOG(Warning,
           "requesting a breakpoint of size %u on Windows ARM, "
           "adjusting to type %u",
           type, WinARMBPType);
    type = WinARMBPType;
  }
#endif

  opcode.clear();

  // TODO: We shouldn't have preprocessor checks for ARCH_ARM vs ARCH_ARM64
  // because we might be an ARM64 binary debugging an ARM inferior.
  switch (type) {
#if defined(ARCH_ARM)
  case 2: // udf #1
    opcode.push_back('\xde');
#if defined(OS_POSIX)
    opcode.push_back('\x01');
#elif defined(OS_WIN32)
    opcode.push_back('\xfe');
#endif
    break;
  case 3: // udf.w #0
    opcode.push_back('\xa0');
    opcode.push_back('\x00');
    opcode.push_back('\xf7');
    opcode.push_back('\xf0');
    break;
  case 4: // udf #16
    opcode.push_back('\xe7');
    opcode.push_back('\xf0');
    opcode.push_back('\x01');
    opcode.push_back('\xf0');
    break;
#elif defined(ARCH_ARM64)
  case 4:
    opcode.push_back('\xd4');
    opcode.push_back('\x20');
    opcode.push_back('\x20');
    opcode.push_back('\x00');
    break;
#endif
  default:
    DS2LOG(Error, "invalid breakpoint type %d", type);
    DS2BUG("invalid breakpoint type");
    break;
  }

#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
#error "Target not supported."
#endif

#if defined(ENDIAN_LITTLE)
  std::reverse(opcode.begin(), opcode.end());
#endif
}
Exemple #24
0
bool CHttpServer::receive_request(ByteVector &request)
{
	if (verbose) RAWTRACE("Receiving request...");

	ByteVector r;
    char buf[BUF_SIZE];
    int attempts = 0;
    for(;;) {
        if (verbose) RAWTRACE("Read portion of data from socket...");
        int n = recv(m_sock, &buf[0], sizeof(buf), 0);
        //RAWTRACE1("RECV: %d", n);
        if (n == -1) {
            int e = RHO_NET_ERROR_CODE;
            if (verbose) RAWTRACE1("RECV ERROR: %d", e);
#if !defined(WINDOWS_PLATFORM)
            if (e == EINTR)
                continue;
#else
			if (e == WSAEINTR)
				continue;
#endif

#if defined(OS_WP8) || (defined(RHODES_QT_PLATFORM) && defined(OS_WINDOWS_DESKTOP)) || defined(OS_WINCE)
            if (e == EAGAIN || e == WSAEWOULDBLOCK) {
#else
            if (e == EAGAIN) {
#endif
                if (!r.empty())
                    break;
                
                if(++attempts > (HTTP_EAGAIN_TIMEOUT*10))
                {
                    if (verbose) RAWLOG_ERROR("Error when receiving data from socket. Client does not send data for " HTTP_EAGAIN_TIMEOUT_STR " sec. Cancel recieve.");
                    return false;
                }

                fd_set fds;
                FD_ZERO(&fds);
                FD_SET(m_sock, &fds);
                timeval tv = {0};
				tv.tv_usec = 100000;//100 MS
                select(m_sock + 1, &fds, 0, 0, &tv);
                continue;
            }
            
            if (verbose) RAWLOG_ERROR1("Error when receiving data from socket: %d", e);
            return false;
        }
        
        if (n == 0) {
            if(!r.empty()) {
                if (verbose) RAWTRACE("Client closed connection gracefully");
                break;
            } else {
                if (verbose) RAWLOG_ERROR("Connection gracefully closed before we receive any data");
                return false;
            }
        } else {
            if (verbose) RAWTRACE1("Actually read %d bytes", n);
            r.insert(r.end(), &buf[0], &buf[0] + n);
        }
    }
    
    if (!r.empty()) {
        request.insert(request.end(), r.begin(), r.end());
        if ( !rho_conf_getBool("log_skip_post") ) {
            String strRequest(request.begin(),request.end());
            if (verbose) RAWTRACE1("Received request:\n%s", strRequest.c_str());
        }
    }
    return true;
}

bool CHttpServer::send_response_impl(String const &data, bool continuation)
{
#ifdef OS_MACOSX
    if ( m_localResponseWriter != 0 ) {
      m_localResponseWriter->writeResponse( data );
      return true;
    }
#endif

    if (verbose) {
        if (continuation)
            if (verbose) RAWTRACE("Send continuation data...");
        else
            if (verbose) RAWTRACE("Sending response...");
    }
    
    // First of all, make socket blocking
#if defined(WINDOWS_PLATFORM)
    unsigned long optval = 0;
        if(::ioctlsocket(m_sock, FIONBIO, &optval) == SOCKET_ERROR) {
        RAWLOG_ERROR1("Can not set blocking socket mode: %d", RHO_NET_ERROR_CODE);
        return false;
    }
#else
    int flags = fcntl(m_sock, F_GETFL);
    if (flags == -1) {
        if (verbose) RAWLOG_ERROR1("Can not get current socket mode: %d", errno);
        return false;
    }
    if (fcntl(m_sock, F_SETFL, flags & ~O_NONBLOCK) == -1) {
        if (verbose) RAWLOG_ERROR1("Can not set blocking socket mode: %d", errno);
        return false;
    }
#endif
    
    size_t pos = 0;
    for(; pos < data.size();) {
        int n = send(m_sock, data.c_str() + pos, data.size() - pos, 0);
        if (n == -1) {
            int e = RHO_NET_ERROR_CODE;
#if !defined(WINDOWS_PLATFORM)
            if (e == EINTR)
                continue;
#endif
            
            if (verbose) RAWLOG_ERROR1("Can not send response data: %d", e);
            return false;
        }
        
        if (n == 0)
            break;
        
        pos += n;
    }
    
    //String dbg_response = response.size() > 100 ? response.substr(0, 100) : response;
    //RAWTRACE2("Sent response:\n%s%s", dbg_response.c_str(), response.size() > 100 ? "..." : "   ");
    if (continuation) {
        if (verbose) RAWTRACE1("Sent response body: %d bytes", data.size());
    }
    else if ( !rho_conf_getBool("log_skip_post") ) {
        if (verbose) RAWTRACE1("Sent response (only headers displayed):\n%s", data.c_str());
    }

    return true;
}

bool CHttpServer::send_response(String const &response, bool redirect)
{
#ifdef OS_ANDROID
    if (redirect) {
        CAutoPtr<IRhoThreadImpl> ptrThread = rho_get_RhoClassFactory()->createThreadImpl();
        ptrThread->sleep(20);
    }
#endif
    return send_response_impl(response, false);
}

String CHttpServer::create_response(String const &reason)
{
    return create_response(reason, "");
}

String CHttpServer::create_response(String const &reason, HeaderList const &headers)
{
    return create_response(reason, headers, "");
}

String CHttpServer::create_response(String const &reason, String const &body)
{
    return create_response(reason, HeaderList(), body);
}

String CHttpServer::create_response(String const &reason, HeaderList const &hdrs, String const &body)
{
    String response = "HTTP/1.1 ";
    response += reason;
    response += "\r\n";
    
    char buf[50];
    snprintf(buf, sizeof(buf), "%d", m_port);
    
    HeaderList headers;
    headers.push_back(Header("Host", String("127.0.0.1:") + buf));
    headers.push_back(Header("Connection", "close"));
    headers.push_back(HttpHeader("Access-Control-Allow-Origin", "*"));
    std::copy(hdrs.begin(), hdrs.end(), std::back_inserter(headers));
    
    for(HeaderList::const_iterator it = headers.begin(), lim = headers.end();
        it != lim; ++it) {
        response += it->name;
        response += ": ";
        response += it->value;
        response += "\r\n";
    }
    
    response += "\r\n";
    
    response += body;
    
    return response;
}
int CryptoManager::verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
	int err = X509_STORE_CTX_get_error(ctx);
	SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
	SSLVerifyData* verifyData = (SSLVerifyData*)SSL_get_ex_data(ssl, CryptoManager::idxVerifyData);

	// TODO: we should make sure that the trusted certificate store never overules KeyPrint, if present, because certificate pinning on an individual certificate is a stronger method of verification.

	// verifyData is unset only when KeyPrint has been pinned and we are not skipping errors due to incomplete chains
	// we can fail here f.ex. if the certificate has expired but is still pinned with KeyPrint
	if (!verifyData)
		return preverify_ok;

	bool allowUntrusted = verifyData->first;
	string keyp = verifyData->second;

	if (!keyp.empty()) {
		X509* cert = X509_STORE_CTX_get_current_cert(ctx);
		if (!cert)
			return 0;

		string kp2(keyp);
		if (kp2.compare(0, 12, "trusted_keyp") == 0) {
			// Possible follow up errors, after verification of a partial chain
			if (err == X509_V_ERR_CERT_UNTRUSTED || err == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) {
				X509_STORE_CTX_set_error(ctx, X509_V_OK);
				return 1;
			}
		} else if (kp2.compare(0, 7, "SHA256/") != 0)
			return allowUntrusted ? 1 : 0;

		ByteVector kp = ssl::X509_digest(cert, EVP_sha256());
		ByteVector kp2v(kp.size());

		Encoder::fromBase32(&kp2[7], &kp2v[0], kp2v.size());
		if (std::equal(kp.begin(), kp.end(), kp2v.begin())) {
			// KeyPrint validated, we can get rid of it (to avoid unnecessary passes)
			SSL_set_ex_data(ssl, CryptoManager::idxVerifyData, NULL);

			if (err != X509_V_OK) {
				// This is the right way to get the certificate store, although it is rather roundabout
				X509_STORE* store = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(ssl));
				dcassert(store == ctx->ctx);

				// Hide the potential library error about trying to add a dupe
				ERR_set_mark();
				if (X509_STORE_add_cert(store, cert)) {
					X509_STORE_CTX_set_error(ctx, X509_V_OK);
					X509_verify_cert(ctx);
					err = X509_STORE_CTX_get_error(ctx);
				} else ERR_pop_to_mark();

				// KeyPrint was not root certificate or we don't have the issuer certificate, the best we can do is trust the pinned KeyPrint
				if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY || err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) {
					X509_STORE_CTX_set_error(ctx, X509_V_OK);
					// Set this to allow ignoring any follow up errors caused by the incomplete chain
					SSL_set_ex_data(ssl, CryptoManager::idxVerifyData, &CryptoManager::trustedKeyprint);
					return 1;
				}
			}

			return (err == X509_V_OK) ? 1 : 0;
		} else {
			if (X509_STORE_CTX_get_error_depth(ctx) > 0)
				return 1;
		}
	}

	if (allowUntrusted) {
		/*
		// We let untrusted certificates through unconditionally, when allowed, but we like to complain
		if (!preverify_ok && err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) {
			X509* cert = NULL;
			if ((cert = X509_STORE_CTX_get_current_cert(ctx)) != NULL) {
				X509_NAME* subject = X509_get_subject_name(cert);
				string tmp, line;

				tmp = getNameEntryByNID(subject, NID_commonName);
				if (!tmp.empty()) {
					CID certCID(tmp);
					if (certCID)
						tmp = Util::listToString(ClientManager::getInstance()->getNicks(certCID));
					line += (!line.empty() ? ", " : "") + tmp;
				}

				tmp = getNameEntryByNID(subject, NID_organizationName);
				if (!tmp.empty())
					line += (!line.empty() ? ", " : "") + tmp;

				ByteVector kp = ssl::X509_digest(cert, EVP_sha256());
				string keyp = "SHA256/" + Encoder::toBase32(&kp[0], kp.size());

				LogManager::getInstance()->message(STRING_F(VERIFY_CERT_FAILED, line % X509_verify_cert_error_string(err) % keyp), LogManager::LOG_INFO);
			}
		}*/

		return 1;
	}

	return preverify_ok;
}