Clump *LoaderDFF::loadFromMemory(FileHandle file) { auto model = new Clump; RWBStream rootStream(file->data, file->length); auto rootID = rootStream.getNextChunk(); if (rootID != CHUNK_CLUMP) { throw DFFLoaderException("Invalid root section ID " + std::to_string(rootID)); } RWBStream modelStream = rootStream.getInnerStream(); auto rootStructID = modelStream.getNextChunk(); if (rootStructID != CHUNK_STRUCT) { throw DFFLoaderException("Clump missing struct chunk"); } // There is only one value in the struct section. auto numAtomics = *(std::uint32_t *)rootStream.getCursor(); RW_UNUSED(numAtomics); GeometryList geometrylist; FrameList framelist; // Process everything inside the clump stream. RWBStream::ChunkID chunkID; while ((chunkID = modelStream.getNextChunk())) { switch (chunkID) { case CHUNK_FRAMELIST: framelist = readFrameList(modelStream); break; case CHUNK_GEOMETRYLIST: geometrylist = readGeometryList(modelStream); break; case CHUNK_ATOMIC: { auto atomic = readAtomic(framelist, geometrylist, modelStream); RW_CHECK(atomic, "Failed to read atomic"); if (!atomic) { // Abort reading the rest of the clump return nullptr; } model->addAtomic(atomic); } break; default: break; } } if (!framelist.empty()) { model->setFrame(framelist[0]); } // Ensure the model has cached metrics model->recalculateMetrics(); return model; }
bool QSslCertificatePrivate::parse(const QByteArray &data) { QAsn1Element root; QDataStream dataStream(data); if (!root.read(dataStream) || root.type() != QAsn1Element::SequenceType) return false; QDataStream rootStream(root.value()); QAsn1Element cert; if (!cert.read(rootStream) || cert.type() != QAsn1Element::SequenceType) return false; // version or serial number QAsn1Element elem; QDataStream certStream(cert.value()); if (!elem.read(certStream)) return false; if (elem.type() == QAsn1Element::Context0Type) { QDataStream versionStream(elem.value()); if (!elem.read(versionStream) || elem.type() != QAsn1Element::IntegerType) return false; versionString = QByteArray::number(elem.value()[0] + 1); if (!elem.read(certStream)) return false; } else { versionString = QByteArray::number(1); } // serial number if (elem.type() != QAsn1Element::IntegerType) return false; serialNumberString = colonSeparatedHex(elem.value()); // algorithm ID if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) return false; // issuer info if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) return false; QByteArray issuerDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length()); issuerInfo = elem.toInfo(); // validity period if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) return false; QDataStream validityStream(elem.value()); if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType)) return false; notValidBefore = elem.toDateTime(); if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType)) return false; notValidAfter = elem.toDateTime(); // subject name if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) return false; QByteArray subjectDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length()); subjectInfo = elem.toInfo(); subjectMatchesIssuer = issuerDer == subjectDer; // public key qint64 keyStart = certStream.device()->pos(); if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) return false; publicKeyDerData.resize(certStream.device()->pos() - keyStart); QDataStream keyStream(elem.value()); if (!elem.read(keyStream) || elem.type() != QAsn1Element::SequenceType) return false; // key algorithm if (!elem.read(elem.value()) || elem.type() != QAsn1Element::ObjectIdentifierType) return false; const QByteArray oid = elem.toObjectId(); if (oid == RSA_ENCRYPTION_OID) publicKeyAlgorithm = QSsl::Rsa; else if (oid == DSA_ENCRYPTION_OID) publicKeyAlgorithm = QSsl::Dsa; else if (oid == EC_ENCRYPTION_OID) publicKeyAlgorithm = QSsl::Ec; else publicKeyAlgorithm = QSsl::Opaque; certStream.device()->seek(keyStart); certStream.readRawData(publicKeyDerData.data(), publicKeyDerData.size()); // extensions while (elem.read(certStream)) { if (elem.type() == QAsn1Element::Context3Type) { if (elem.read(elem.value()) && elem.type() == QAsn1Element::SequenceType) { QDataStream extStream(elem.value()); while (elem.read(extStream) && elem.type() == QAsn1Element::SequenceType) { QSslCertificateExtension extension; if (!parseExtension(elem.value(), &extension)) return false; extensions << extension; if (extension.oid() == QLatin1String("2.5.29.17")) { // subjectAltName QAsn1Element sanElem; if (sanElem.read(extension.value().toByteArray()) && sanElem.type() == QAsn1Element::SequenceType) { QDataStream nameStream(sanElem.value()); QAsn1Element nameElem; while (nameElem.read(nameStream)) { if (nameElem.type() == QAsn1Element::Rfc822NameType) { subjectAlternativeNames.insert(QSsl::EmailEntry, nameElem.toString()); } else if (nameElem.type() == QAsn1Element::DnsNameType) { subjectAlternativeNames.insert(QSsl::DnsEntry, nameElem.toString()); } } } } } } } } derData = data.left(dataStream.device()->pos()); null = false; return true; }