Beispiel #1
0
ByteVector
MP4::Tag::renderFreeForm(const String &name, const MP4::Item &item) const
{
  StringList header = StringList::split(name, ":");
  if (header.size() != 3) {
    debug("MP4: Invalid free-form item name \"" + name + "\"");
    return ByteVector::null;
  }
  ByteVector data;
  data.append(renderAtom("mean", ByteVector::fromUInt(0) + header[1].data(String::UTF8)));
  data.append(renderAtom("name", ByteVector::fromUInt(0) + header[2].data(String::UTF8)));
  AtomDataType type = item.atomDataType();
  if(type == TypeUndefined) {
    if(!item.toStringList().isEmpty()) {
      type = TypeUTF8;
    }
    else {
      type = TypeImplicit;
    }
  }
  if(type == TypeUTF8) {
    StringList value = item.toStringList();
    for(unsigned int i = 0; i < value.size(); i++) {
      data.append(renderAtom("data", ByteVector::fromUInt(type) + ByteVector(4, '\0') + value[i].data(String::UTF8)));
    }
  }
  else {
    ByteVectorList value = item.toByteVectorList();
    for(unsigned int i = 0; i < value.size(); i++) {
      data.append(renderAtom("data", ByteVector::fromUInt(type) + ByteVector(4, '\0') + value[i]));
    }
  }
  return renderAtom("----", data);
}
Beispiel #2
0
ByteVector Ogg::Page::render() const
{
  ByteVector data;

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

  if(d->packets.isEmpty()) {
    if(d->file) {
      d->file->seek(d->packetOffset);
      data.append(d->file->readBlock(d->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.

  ByteVector checksum = ByteVector::fromUInt(data.checksum(), false);
  for(int i = 0; i < 4; i++)
    data[i + 22] = checksum[i];

  return data;
}
Beispiel #3
0
CryptoKey::CryptoKey(HCRYPTPROV cryptProv, const ByteVector& keyMaterial, const ByteVector& iv)
         :handle(NULL)
{
    if (keyMaterial.size() != 0x10)
        throw logic_error("Invalid key length. Expected 128b");
    if (iv.size() != 0x10)
        throw logic_error("Invalid IV length. Expected 128b");

    byte_t blobHeader[] = { 
        // Header
        0x08,                               //plaintextblob
        CUR_BLOB_VERSION, 
        0x00, 0x00,
        ALG_SID_AES_128, 0x66, 0x00, 0x00,  //ALG_ID
        0x10, 0x00, 0x00, 0x00};            //key length in bytes
    
    ByteVector keyToImport;
    keyToImport.append(blobHeader, sizeof(blobHeader));
    keyToImport.append(keyMaterial);

    // import key
    TOE(CryptImportKey(cryptProv, keyToImport.c_ptr(), static_cast<DWORD>(keyToImport.size()),
                       0, 0, &handle), "CryptImportKey");
    
    // set IV
    TOE(CryptSetKeyParam(handle, KP_IV, const_cast<byte_t*>(iv.c_ptr()), 0), "CryptSetKeyParam(IV)");
}
Beispiel #4
0
ByteVector Header::render() const
{
  ByteVector v;

  // add the file identifier -- "ID3"
  v.append(fileIdentifier());

  // add the version number -- we always render a 2.4.0 tag regardless of what
  // the tag originally was.

  v.append(char(4));
  v.append(char(0));

  // Currently we don't actually support writing extended headers, footers or
  // unsynchronized tags, make sure that the flags are set accordingly.

  d->extendedHeader = false;
  d->footerPresent = false;
  d->unsynchronisation = false;

  // render and add the flags
  std::bitset<8> flags;

  flags[7] = d->unsynchronisation;
  flags[6] = d->extendedHeader;
  flags[5] = d->experimentalIndicator;
  flags[4] = d->footerPresent;

  v.append(char(flags.to_ulong()));

  // add the size
  v.append(SynchData::fromUInt(d->tagSize));

  return v;
}
ByteVector Ogg::PageHeader::lacingValues() const
{
  ByteVector data;

  List<int> sizes = d->packetSizes;
  for(List<int>::ConstIterator it = sizes.begin(); it != sizes.end(); ++it) {

    // The size of a packet in an Ogg page is indicated by a series of "lacing
    // values" where the sum of the values is the packet size in bytes.  Each of
    // these values is a byte.  A value of less than 255 (0xff) indicates the end
    // of the packet.

    div_t n = div(*it, 255);

    for(int i = 0; i < n.quot; i++)
      data.append(char(uchar(255)));

	 
	List<int>::ConstIterator last = sizes.end();
	--last;
    if(it != last || d->lastPacketCompleted)
      data.append(char(uchar(n.rem)));
  }

  return data;
}
Beispiel #6
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.

  ByteVector tagData;

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

  // TODO: Render the extended header.

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

  FrameList newFrames;
  newFrames.setAutoDelete(true);

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

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

  // Compute the amount of padding, and append that to tagData.

  uint paddingSize = 0;
  uint originalSize = d->header.tagSize();

  if(tagData.size() < originalSize)
    paddingSize = originalSize - tagData.size();
  else
    paddingSize = 1024;

  tagData.append(ByteVector(paddingSize, char(0)));

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

  // TODO: This should eventually include d->footer->render().
  return d->header.render() + tagData;
}
Beispiel #7
0
ByteVector PrivateFrame::renderFields() const
{
    ByteVector v;

    v.append(d->owner.data(String::Latin1));
    v.append(textDelimiter(String::Latin1));
    v.append(d->data);

    return v;
}
ByteVector UniqueFileIdentifierFrame::renderFields() const
{
  ByteVector data;

  data.append(d->owner.data(String::Latin1));
  data.append(char(0));
  data.append(d->identifier);

  return data;
}
Beispiel #9
0
ByteVector APE::Item::render() const
{
  ByteVector data;
  TagLib::uint flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
  ByteVector value;

  if(isEmpty())
    return data;

  if(d->type == Text) {
    StringList::ConstIterator it = d->text.begin();

    value.append(it->data(String::UTF8));
    it++;
    for(; it != d->text.end(); ++it) {
      value.append('\0');
      value.append(it->data(String::UTF8));
    }
    d->value = value;
  }
  else
    value.append(d->value);

  data.append(ByteVector::fromUInt(value.size(), false));
  data.append(ByteVector::fromUInt(flags, false));
  data.append(d->key.data(String::UTF8));
  data.append(ByteVector('\0'));
  data.append(value);

  return data;
}
ByteVector SynchronizedLyricsFrame::renderFields() const
{
  ByteVector v;

  String::Type encoding = d->textEncoding;

  encoding = checkTextEncoding(d->description, encoding);
  for(SynchedTextList::ConstIterator it = d->synchedText.begin();
      it != d->synchedText.end();
      ++it) {
    encoding = checkTextEncoding(it->text, encoding);
  }

  v.append(char(encoding));
  v.append(d->language.size() == 3 ? d->language : "XXX");
  v.append(char(d->timestampFormat));
  v.append(char(d->type));
  v.append(d->description.data(encoding));
  v.append(textDelimiter(encoding));
  for(SynchedTextList::ConstIterator it = d->synchedText.begin();
      it != d->synchedText.end();
      ++it) {
    const SynchedText &entry = *it;
    v.append(entry.text.data(encoding));
    v.append(textDelimiter(encoding));
    v.append(ByteVector::fromUInt(entry.time));
  }

  return v;
}
ByteVector PopularimeterFrame::renderFields() const
{
    ByteVector data;

    data.append(d->email.data(String::Latin1));
    data.append(textDelimiter(String::Latin1));
    data.append(char(d->rating));
    data.append(ByteVector::fromUInt(d->counter));

    return data;
}
Beispiel #12
0
ByteVector CommentsFrame::renderFields() const
{
    ByteVector v;

    v.append(char(d->textEncoding));
    v.append(d->language.size() == 3 ? d->language : "   ");
    v.append(d->description.data(d->textEncoding));
    v.append(textDelimiter(d->textEncoding));
    v.append(d->text.data(d->textEncoding));

    return v;
}
ByteVector UnsynchronizedLyricsFrame::renderFields() const
{
  ByteVector v;

  v.append(char(d->textEncoding));
  v.append(d->language.size() == 3 ? d->language : "XXX");
  v.append(d->description.data(d->textEncoding));
  v.append(textDelimiter(d->textEncoding));
  v.append(d->text.data(d->textEncoding));

  return v;
}
Beispiel #14
0
bool
MP4::Tag::save()
{
  ByteVector data;
  for(MP4::ItemMap::ConstIterator it = d->items.begin(); it != d->items.end(); ++it) {
    const String name = it->first;
    if(name.startsWith("----")) {
      data.append(renderFreeForm(name, it->second));
    }
    else if(name == "trkn") {
      data.append(renderIntPair(name.data(String::Latin1), it->second));
    }
    else if(name == "disk") {
      data.append(renderIntPairNoTrailing(name.data(String::Latin1), it->second));
    }
    else if(name == "cpil" || name == "pgap" || name == "pcst" || name == "hdvd") {
      data.append(renderBool(name.data(String::Latin1), it->second));
    }
    else if(name == "tmpo") {
      data.append(renderInt(name.data(String::Latin1), it->second));
    }
    else if(name == "tvsn" || name == "tves" || name == "cnID" ||
            name == "sfID" || name == "atID" || name == "geID") {
      data.append(renderUInt(name.data(String::Latin1), it->second));
    }
    else if(name == "plID") {
      data.append(renderLongLong(name.data(String::Latin1), it->second));
    }
    else if(name == "stik" || name == "rtng" || name == "akID") {
      data.append(renderByte(name.data(String::Latin1), it->second));
    }
    else if(name == "covr") {
      data.append(renderCovr(name.data(String::Latin1), it->second));
    }
    else if(name.size() == 4){
      data.append(renderText(name.data(String::Latin1), it->second));
    }
    else {
      debug("MP4: Unknown item name \"" + name + "\"");
    }
  }
  data = renderAtom("ilst", data);

  AtomList path = d->atoms->path("moov", "udta", "meta", "ilst");
  if(path.size() == 4) {
    saveExisting(data, path);
  }
  else {
    saveNew(data);
  }

  return true;
}
Beispiel #15
0
ByteVector UserUrlLinkFrame::renderFields() const
{
  ByteVector v;

  String::Type encoding = checkTextEncoding(d->description, d->textEncoding);

  v.append(char(encoding));
  v.append(d->description.data(encoding));
  v.append(textDelimiter(encoding));
  v.append(url().data(String::Latin1));

  return v;
}
Beispiel #16
0
void
MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
{
  AtomList::ConstIterator it = path.end();

  MP4::Atom *ilst = *(--it);
  long offset = ilst->offset;
  long length = ilst->length;

  MP4::Atom *meta = *(--it);
  AtomList::ConstIterator index = meta->children.find(ilst);

  // check if there is an atom before 'ilst', and possibly use it as padding
  if(index != meta->children.begin()) {
    AtomList::ConstIterator prevIndex = index;
    prevIndex--;
    MP4::Atom *prev = *prevIndex;
    if(prev->name == "free") {
      offset = prev->offset;
      length += prev->length;
    }
  }
  // check if there is an atom after 'ilst', and possibly use it as padding
  AtomList::ConstIterator nextIndex = index;
  nextIndex++;
  if(nextIndex != meta->children.end()) {
    MP4::Atom *next = *nextIndex;
    if(next->name == "free") {
      length += next->length;
    }
  }

  long delta = data.size() - length;
  if(delta > 0 || (delta < 0 && delta > -8)) {
    data.append(padIlst(data));
    delta = data.size() - length;
  }
  else if(delta < 0) {
    data.append(padIlst(data, -delta - 8));
    delta = 0;
  }

  d->file->insert(data, offset, length);

  if(delta) {
    updateParents(path, delta, 1);
    updateOffsets(delta, offset);
  }
}
Beispiel #17
0
ByteVector ASF::Attribute::render(const String &name, int kind) const
{
  ByteVector data;

  switch (d->type) {
  case WordType:
    data.append(ByteVector::fromShort(d->shortValue, false));
    break;

  case BoolType:
    if(kind == 0) {
      data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false));
    }
    else {
      data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false));
    }
    break;

  case DWordType:
    data.append(ByteVector::fromUInt(d->intValue, false));
    break;

  case QWordType:
    data.append(ByteVector::fromLongLong(d->longLongValue, false));
    break;

  case UnicodeType:
    data.append(File::renderString(d->stringValue));
    break;

  case BytesType:
    if(d->pictureValue.isValid()) {
      data.append(d->pictureValue.render());
      break;
    }
  case GuidType:
    data.append(d->byteVectorValue);
    break;
  }

  if(kind == 0) {
    data = File::renderString(name, true) +
           ByteVector::fromShort((int)d->type, false) +
           ByteVector::fromShort(data.size(), false) +
           data;
  }
  else {
    ByteVector nameData = File::renderString(name);
    data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
           ByteVector::fromShort(d->stream, false) +
           ByteVector::fromShort(nameData.size(), false) +
           ByteVector::fromShort((int)d->type, false) +
           ByteVector::fromUInt(data.size(), false) +
           nameData +
           data;
  }

  return data;
}
ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const
{
  ByteVector v;

  ConstIterator it = begin();

  while(it != end()) {
    v.append(*it);
    it++;
    if(it != end())
      v.append(separator);
  }

  return v;
}
Beispiel #19
0
void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
                            ulong offset, ulong replace, uint leadingPadding)
{
  ByteVector combined;
  if(leadingPadding) {
    combined.append(ByteVector(leadingPadding, '\x00'));
  }
  combined.append(name);
  combined.append(ByteVector::fromUInt(data.size(), d->endianness == BigEndian));
  combined.append(data);
  if((data.size() & 0x01) != 0) {
    combined.append('\x00');
  }
  insert(combined, offset, replace);
}
Beispiel #20
0
ByteVector Frame::textDelimiter(String::Type t)
{
  ByteVector d = char(0);
  if(t == String::UTF16 || t == String::UTF16BE || t == String::UTF16LE)
    d.append(char(0));
  return d;
}
Beispiel #21
0
bool ASF::File::save()
{
  if(readOnly()) {
    debug("ASF: File is read-only.");
    return false;
  }

  if(!d->contentDescriptionObject) {
    d->contentDescriptionObject = new ContentDescriptionObject();
    d->objects.append(d->contentDescriptionObject);
  }
  if(!d->extendedContentDescriptionObject) {
    d->extendedContentDescriptionObject = new ExtendedContentDescriptionObject();
    d->objects.append(d->extendedContentDescriptionObject);
  }
  if(!d->headerExtensionObject) {
    d->headerExtensionObject = new HeaderExtensionObject();
    d->objects.append(d->headerExtensionObject);
  }
  if(!d->metadataObject) {
    d->metadataObject = new MetadataObject();
    d->headerExtensionObject->objects.append(d->metadataObject);
  }
  if(!d->metadataLibraryObject) {
    d->metadataLibraryObject = new MetadataLibraryObject();
    d->headerExtensionObject->objects.append(d->metadataLibraryObject);
  }

  ASF::AttributeListMap::ConstIterator it = d->tag->attributeListMap().begin();
  for(; it != d->tag->attributeListMap().end(); it++) {
    const String &name = it->first;
    const AttributeList &attributes = it->second;
    bool inExtendedContentDescriptionObject = false;
    bool inMetadataObject = false;
    for(unsigned int j = 0; j < attributes.size(); j++) {
      const Attribute &attribute = attributes[j];
      bool largeValue = attribute.dataSize() > 65535;
      if(!inExtendedContentDescriptionObject && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
        d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
        inExtendedContentDescriptionObject = true;
      }
      else if(!inMetadataObject && !largeValue && attribute.language() == 0 && attribute.stream() != 0) {
        d->metadataObject->attributeData.append(attribute.render(name, 1));
        inMetadataObject = true;
      }
      else {
        d->metadataLibraryObject->attributeData.append(attribute.render(name, 2));
      }
    }
  }

  ByteVector data;
  for(unsigned int i = 0; i < d->objects.size(); i++) {
    data.append(d->objects[i]->render(this));
  }
  data = headerGuid + ByteVector::fromLongLong(data.size() + 30, false) + ByteVector::fromUInt(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data;
  insert(data, 0, d->size);

  return true;
}
Beispiel #22
0
void
CryptoProxy::encrypt(CryptoKey* key, const ByteVector& data, ByteVector& encryptedData)
{
    if ((data.length() % 16) > 0)
        throw runtime_error("encrypt: incorrect data length");
    encryptedData = data; //Crypto encrypts in-place
    // NOTE: do not reserve block for padding, specify final = FALSE instead
    //encryptedData.append(0x00, 16); // add one extra block as MS wants it for padding
    const DWORD bytesToEncrypt = static_cast<DWORD>(data.size());
    DWORD dataSize = bytesToEncrypt;
    try
    {
        TOE(CryptEncrypt(*key, 0, FALSE/*final*/, 0/*flags*/, &encryptedData.front(),
                         &dataSize, static_cast<DWORD>(encryptedData.size())), "CryptEncrypt 1st");
    }
    catch (WinApiError& e)
    {
        // larger buffer is required??
        if (e.getErr() == ERROR_MORE_DATA)
        {
            encryptedData.append(0x00, dataSize - encryptedData.size());
            // try again, no second catch this time
            dataSize = bytesToEncrypt; //set again to input data length
            TOE(CryptEncrypt(*key, 0, FALSE/*final*/, 0/*flags*/, &encryptedData.front(),
                             &dataSize, static_cast<DWORD>(encryptedData.size())), "CryptEncrypt 2nd");
        }
        else
            throw; // another error -> re-throw
    }
    // strip the padding
    encryptedData.resize(bytesToEncrypt);
}
Beispiel #23
0
Ogg::Page::Page(const ByteVectorList &packets,
                uint streamSerialNumber,
                int pageNumber,
                bool firstPacketContinued,
                bool lastPacketCompleted,
                bool containsLastPacket)
{
  d = new PagePrivate;

  ByteVector data;
  List<int> packetSizes;

  d->header.setFirstPageOfStream(pageNumber == 0 && !firstPacketContinued);
  d->header.setLastPageOfStream(containsLastPacket);
  d->header.setFirstPacketContinued(firstPacketContinued);
  d->header.setLastPacketCompleted(lastPacketCompleted);
  d->header.setStreamSerialNumber(streamSerialNumber);
  d->header.setPageSequenceNumber(pageNumber);

  // Build a page from the list of packets.

  for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {
    packetSizes.append((*it).size());
    data.append(*it);
  }
  d->packets = packets;
  d->header.setPacketSizes(packetSizes);
}
ByteVector UnsynchronizedLyricsFrame::renderFields() const
{
  ByteVector v;

  //=== Alex. There is a problem with the Writing of UNICODE strings. That's why we manually set the encoding
  String::Type encoding = String::UTF8;
  v.append(char(encoding));
  v.append(d->language.size() == 3 ? d->language : "XXX");
  v.append(d->description.data(encoding));
  v.append(textDelimiter(encoding));
  v.append(d->text.data(encoding));
  //=== Alex END. There is a problem


  return v;
}
Beispiel #25
0
bool Ogg::FLAC::File::save()
{
  d->xiphCommentData = d->comment->render(false);

  // Create FLAC metadata-block:

  // Put the size in the first 32 bit (I assume no more than 24 bit are used)

  ByteVector v = ByteVector::fromUInt(d->xiphCommentData.size());

  // Set the type of the metadata-block to be a Xiph / Vorbis comment

  v[0] = 4;

  // Append the comment-data after the 32 bit header

  v.append(d->xiphCommentData);

  // Save the packet at the old spot
  // FIXME: Use padding if size is increasing

  setPacket(d->commentPacket, v);

  return Ogg::File::save();
}
Beispiel #26
0
ByteVector
MP4::Tag::renderFreeForm(const String &name, MP4::Item &item)
{
  StringList header = StringList::split(name, ":");
  if (header.size() != 3) {
    debug("MP4: Invalid free-form item name \"" + name + "\"");
    return ByteVector::null;
  }
  ByteVector data;
  data.append(renderAtom("mean", ByteVector::fromUInt(0) + header[1].data(String::UTF8)));
  data.append(renderAtom("name", ByteVector::fromUInt(0) + header[2].data(String::UTF8)));
  StringList value = item.toStringList();
  for(unsigned int i = 0; i < value.size(); i++) {
    data.append(renderAtom("data", ByteVector::fromUInt(1) + ByteVector(4, '\0') + value[i].data(String::UTF8)));
  }
  return renderAtom("----", data);
}
Beispiel #27
0
void
IpmiPayload::serializeRmcpp(ByteVector& out, const IpmiPayloadData& payload)
{
    // 2-bytes length
    out += static_cast<byte_t>(payload.data.length() & 0xff);
    out += static_cast<byte_t>((payload.data.length() >> 8) & 0xff);
    out.append(payload.data);
}
Beispiel #28
0
ByteVector CommentsFrame::renderFields() const
{
  ByteVector v;

  String::Type encoding = d->textEncoding;

  encoding = checkEncoding(d->description, encoding);
  encoding = checkEncoding(d->text, encoding);

  v.append(char(encoding));
  v.append(d->language.size() == 3 ? d->language : "XXX");
  v.append(d->description.data(encoding));
  v.append(textDelimiter(encoding));
  v.append(d->text.data(encoding));

  return v;
}
Beispiel #29
0
ByteVector OwnershipFrame::renderFields() const
{
  StringList sl;
  sl.append(d->seller);

  const String::Type encoding = checkTextEncoding(sl, d->textEncoding);

  ByteVector v;

  v.append(char(encoding));
  v.append(d->pricePaid.data(String::Latin1));
  v.append(textDelimiter(String::Latin1));
  v.append(d->datePurchased.data(String::Latin1));
  v.append(d->seller.data(encoding));

  return v;
}
ByteVector TableOfContentsFrame::renderFields() const
{
  ByteVector data;

  data.append(d->elementID);
  data.append('\0');
  char flags = 0;
  if(d->isTopLevel)
    flags += 2;
  if(d->isOrdered)
    flags += 1;
  data.append(flags);
  data.append((char)(entryCount()));
  ByteVectorList::ConstIterator it = d->childElements.begin();
  while(it != d->childElements.end()) {
    data.append(*it);
    data.append('\0');
    it++;
  }
  FrameList l = d->embeddedFrameList;
  for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
    data.append((*it)->render());

  return data;
}