Exemple #1
0
void CommentsFrame::parseFields(const ByteVector &data)
{
  if(data.size() < 5) {
    debug("A comment frame must contain at least 5 bytes.");
    return;
  }

  d->textEncoding = String::Type(data[0]);
  d->language = data.mid(1, 3);

  int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;

  ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);

  if(l.size() == 2) {
    d->description = String(l.front(), d->textEncoding);
    d->text = String(l.back(), d->textEncoding);
  }
}
Exemple #2
0
void ChapterFrame::parseFields(const ByteVector &data)
{
  unsigned int size = data.size();
  if(size < 18) {
    debug("A CHAP frame must contain at least 18 bytes (1 byte element ID "
          "terminated by null and 4x4 bytes for start and end time and offset).");
    return;
  }

  int pos = 0;
  unsigned int embPos = 0;
  d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
  d->startTime = data.toUInt(pos, true);
  pos += 4;
  d->endTime = data.toUInt(pos, true);
  pos += 4;
  d->startOffset = data.toUInt(pos, true);
  pos += 4;
  d->endOffset = data.toUInt(pos, true);
  pos += 4;
  size -= pos;

  // Embedded frames are optional

  if(size < header()->size())
    return;

  while(embPos < size - header()->size()) {
    Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), (d->tagHeader != 0));

    if(!frame)
      return;

    // Checks to make sure that frame parsed correctly.
    if(frame->size() <= 0) {
      delete frame;
      return;
    }

    embPos += frame->size() + header()->size();
    addEmbeddedFrame(frame);
  }
}
void TableOfContentsFrame::parseFields(const ByteVector &data)
{
  TagLib::uint size = data.size();
  if(size < 6) {
    debug("A CTOC frame must contain at least 6 bytes (1 byte element ID terminated by "
          "null, 1 byte flags, 1 byte entry count and 1 byte child element ID terminated "
          "by null.");
    return;
  }

  int pos = 0;
  TagLib::uint embPos = 0;
  d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
  d->isTopLevel = (data.at(pos) & 2) > 0;
  d->isOrdered = (data.at(pos++) & 1) > 0;
  TagLib::uint entryCount = data.at(pos++);
  for(TagLib::uint i = 0; i < entryCount; i++) {
    ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
    d->childElements.append(childElementID);
  }

  size -= pos;

  if(size < header()->size())
    return;

  while(embPos < size - header()->size()) {
    Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);

    if(!frame)
      return;

    // Checks to make sure that frame parsed correctly.
    if(frame->size() <= 0) {
      delete frame;
      return;
    }

    embPos += frame->size() + header()->size();
    addEmbeddedFrame(frame);
  }
}
Exemple #4
0
ByteVector APE::Tag::render() const
{
  ByteVector data;
  uint itemCount = 0;

  {
    for(Map<const String, Item>::ConstIterator it = d->itemListMap.begin();
        it != d->itemListMap.end(); ++it)
    {
      data.append(it->second.render());
      itemCount++;
    }
  }

  d->footer.setItemCount(itemCount);
  d->footer.setTagSize(data.size() + Footer::size());
  d->footer.setHeaderPresent(true);

  return d->footer.renderHeader() + data + d->footer.renderFooter();
}
bool Registry::EnumRegValues(HKEY hkey)
{
    string name;
    name.resize(1024);
    ByteVector data;
    data.resize(1024);
    int i=0;
    while (true)
    {
        DWORD cbName= (DWORD)name.size();
        DWORD cbData= (DWORD)data.size();
        DWORD type;
        LONG rc= RegEnumValue(hkey, i, stringptr(name), &cbName, NULL, &type, vectorptr(data), &cbData);
        if (rc==ERROR_NO_MORE_ITEMS)
            break;
        debug("value %s = %s\n", name.c_str(), ValueToString(type, data).c_str());
        i++;
    }
    return true;
}
Exemple #6
0
MP4::AtomDataList
MP4::Tag::parseData2(const MP4::Atom *atom, int expectedFlags, bool freeForm)
{
  AtomDataList result;
  ByteVector data = d->file->readBlock(atom->length - 8);
  int i = 0;
  unsigned int pos = 0;
  while(pos < data.size()) {
    const int length = static_cast<int>(data.toUInt(pos));
    if(length < 12) {
      debug("MP4: Too short atom");
      return result;
    }

    const ByteVector name = data.mid(pos + 4, 4);
    const int flags = static_cast<int>(data.toUInt(pos + 8));
    if(freeForm && i < 2) {
      if(i == 0 && name != "mean") {
        debug("MP4: Unexpected atom \"" + name + "\", expecting \"mean\"");
        return result;
      }
      else if(i == 1 && name != "name") {
        debug("MP4: Unexpected atom \"" + name + "\", expecting \"name\"");
        return result;
      }
      result.append(AtomData(AtomDataType(flags), data.mid(pos + 12, length - 12)));
    }
    else {
      if(name != "data") {
        debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\"");
        return result;
      }
      if(expectedFlags == -1 || flags == expectedFlags) {
        result.append(AtomData(AtomDataType(flags), data.mid(pos + 16, length - 16)));
      }
    }
    pos += length;
    i++;
  }
  return result;
}
Exemple #7
0
void ID3v2::Tag::read()
{
  if(!d->file)
    return;

  if(!d->file->isOpen())
    return;

  d->file->seek(d->tagOffset);
  d->header.setData(d->file->readBlock(Header::size()));

  // If the tag size is 0, then this is an invalid tag (tags must contain at
  // least one frame)

  if(d->header.tagSize() != 0)
    parse(d->file->readBlock(d->header.tagSize()));

  // Look for duplicate ID3v2 tags and treat them as an extra blank of this one.
  // It leads to overwriting them with zero when saving the tag.

  // This is a workaround for some faulty files that have duplicate ID3v2 tags.
  // Unfortunately, TagLib itself may write such duplicate tags until v1.10.

  unsigned int extraSize = 0;

  while(true) {

    d->file->seek(d->tagOffset + d->header.completeTagSize() + extraSize);

    const ByteVector data = d->file->readBlock(Header::size());
    if(data.size() < Header::size() || !data.startsWith(Header::fileIdentifier()))
      break;

    extraSize += Header(data).completeTagSize();
  }

  if(extraSize != 0) {
    debug("ID3v2::Tag::read() - Duplicate ID3v2 tags found.");
    d->header.setTagSize(d->header.tagSize() + extraSize);
  }
}
// -------------------------------------------------------------------------------------------------
void DataPlot::mousePressEvent(QMouseEvent* evt)
{
    if (evt->button() == Qt::LeftButton || evt->button() == Qt::RightButton)
    {
        ByteVector data = m_dataView->m_currentData.bytes();
        
        // check if there is data displayed
        if (data.size() <= 0)
        {
            return;
        }
        
        double leftDistance = evt->x() - getLeftBegin();
        
        // user clicked in the label area
        if (leftDistance < 0)
        {
            return;
        }
        
        // check if the user clicked too much right
        if (evt->x() > static_cast<int>(m_xPositions.last()))
        {
            return;
        }
        
        double possibleSamplesPerScreen = static_cast<double>(width()) / 
                                          (DEFAULT_POINTS_PER_SAMPLE * m_zoomFactor);
        
        int sample = qRound(leftDistance * possibleSamplesPerScreen / width() + getStartIndex());
        
        if (evt->button() == Qt::LeftButton)
        {
            setLeftMarker(sample);
        }
        else
        {
            setRightMarker(sample);
        }
    }
}
Exemple #9
0
//==============================================================================
void CC_UnitDriver::read_xdata_memory(uint16_t address, size_t count, ByteVector &data)
{
    log_info("programmer, read xdata memory at %04Xh, count: %u", address, count);

    uint8_t header[] = {
        0x40, 0x55, 0x00, 0x72, 0x56, 0xE5, 0x92, 0xBE, 0x57, 0x75,
        0x92, 0x00, 0x74, 0x56, 0xE5, 0x83, 0x76, 0x56, 0xE5, 0x82
    };

    uint8_t footer[] 	= { 0xD4, 0x57, 0x90, 0xC2, 0x57, 0x75, 0x92, 0x90, 0x56, 0x74 };

    uint8_t load_dtpr[] = { 0xBE, 0x57, 0x90, 0x00, 0x00 };
    uint8_t mov_a_dtpr[] = { 0x4E, 0x55, 0xE0 };
    uint8_t inc_dtpr[] 	= { 0x5E, 0x55, 0xA3 };

    ByteVector command;
    vector_append(command, header, sizeof(header));

    load_dtpr[sizeof(load_dtpr) - 1] = address;
    load_dtpr[sizeof(load_dtpr) - 2] = address >> 8;
    vector_append(command, load_dtpr, sizeof(load_dtpr));

    for (size_t i = 0; i < count; i++)
    {
        if (i == (count - 1) || !((i + 1) % 64))
            mov_a_dtpr[0] |= 1;
        else
            mov_a_dtpr[0] &= ~1;

        vector_append(command, mov_a_dtpr, sizeof(mov_a_dtpr));
        vector_append(command, inc_dtpr, sizeof(inc_dtpr));
    }
    vector_append(command, footer, sizeof(footer));

    data.resize(count);

    usb_device_.bulk_write(endpoint_out_, command.size(), &command[0]);
    usb_device_.bulk_read(endpoint_in_, count, &data[0]);

    log_info("programmer, read xdata memory, data: %s", binary_to_hex(&data[0], count, " ").c_str());
}
Exemple #10
0
bool FileStream::writeBlock(const ByteVector &data)
{
  if(!isOpen()) {
    debug("FileStream::writeBlock() -- invalid file.");
    return false;
  }

  if(readOnly()) {
    debug("FileStream::writeBlock() -- read only file.");
    return false;
  }

  size_t nbBytes = writeFile(d->file, data);
  
  if (nbBytes != data.size()) {
	  debug("FileStream::writeBlock() error, 0 bytes written.");
	  return false;
  }
  
  return true;
}
Exemple #11
0
void APE::Item::parse(const ByteVector &data)
{
  // 11 bytes is the minimum size for an APE item

  if(data.size() < 11) {
    debug("APE::Item::parse() -- no data in item");
    return;
  }

  uint valueLength  = data.mid(0, 4).toUInt(false);
  uint flags        = data.mid(4, 4).toUInt(false);

  d->key = String(data.mid(8), String::UTF8);

  d->value = data.mid(8 + d->key.size() + 1, valueLength);

  setReadOnly(flags & 1);
  setType(ItemTypes((flags >> 1) & 3));

  if(Text == d->type)
    d->text = StringList(ByteVectorList::split(d->value, '\0'), String::UTF8);
}
Exemple #12
0
long MPEG::File::nextFrameOffset(long position)
{
  ByteVector frameSyncBytes(2, '\0');

  while(true) {
    seek(position);
    const ByteVector buffer = readBlock(bufferSize());
    if(buffer.isEmpty())
      return -1;

    for(unsigned int i = 0; i < buffer.size(); ++i) {
      frameSyncBytes[0] = frameSyncBytes[1];
      frameSyncBytes[1] = buffer[i];
      if(isFrameSync(frameSyncBytes)) {
        const Header header(this, position + i - 1, true);
        if(header.isValid())
          return position + i - 1;
      }
    }

    position += bufferSize();
  }
}
Exemple #13
0
void
MP4::Tag::parseCovr(MP4::Atom *atom, TagLib::File *file)
{
  MP4::CoverArtList value;
  ByteVector data = file->readBlock(atom->length - 8);
  unsigned int pos = 0;
  while(pos < data.size()) {
    int length = data.mid(pos, 4).toUInt();
    ByteVector name = data.mid(pos + 4, 4);
    int flags = data.mid(pos + 8, 4).toUInt();
    if(name != "data") {
      debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\"");
      return;
    }
    if(flags == MP4::CoverArt::PNG || flags == MP4::CoverArt::JPEG) {
      value.append(MP4::CoverArt(MP4::CoverArt::Format(flags),
                                 data.mid(pos + 16, length - 16)));
    }
    pos += length;
  }
  if(value.size() > 0)
    d->items.insert(atom->name, value);
}
Exemple #14
0
ByteVector RIFF::Info::Tag::render() const
{
  ByteVector data("INFO");

  FieldListMap::ConstIterator it = d->fieldListMap.begin();
  for(; it != d->fieldListMap.end(); ++it) {
    ByteVector text = TagPrivate::stringHandler->render(it->second);
    if(text.isEmpty())
      continue;

    data.append(it->first);
    data.append(ByteVector::fromUInt(text.size() + 1, false));
    data.append(text);
    
    do {
      data.append('\0');
    } while(data.size() & 1);
  }

  if(data.size() == 4)
    return ByteVector();
  else
    return data;
}
Exemple #15
0
ByteVectorList
MP4::Tag::parseData(MP4::Atom *atom, TagLib::File *file, int expectedFlags, bool freeForm)
{
  ByteVectorList result;
  ByteVector data = file->readBlock(atom->length - 8);
  int i = 0;
  unsigned int pos = 0;
  while(pos < data.size()) {
    int length = data.mid(pos, 4).toUInt();
    ByteVector name = data.mid(pos + 4, 4);
    int flags = data.mid(pos + 8, 4).toUInt();
    if(freeForm && i < 2) {
      if(i == 0 && name != "mean") {
        debug("MP4: Unexpected atom \"" + name + "\", expecting \"mean\"");
        return result;
      }
      else if(i == 1 && name != "name") {
        debug("MP4: Unexpected atom \"" + name + "\", expecting \"name\"");
        return result;
      }
      result.append(data.mid(pos + 12, length - 12));
    }
    else {
      if(name != "data") {
        debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\"");
        return result;
      }
      if(expectedFlags == -1 || flags == expectedFlags) {
        result.append(data.mid(pos + 16, length - 16));
      }
    }
    pos += length;
    i++;
  }
  return result;
}
Exemple #16
0
long MPEG::File::previousFrameOffset(long position)
{
  ByteVector frameSyncBytes(2, '\0');

  while(position > 0) {
    const long bufferLength = std::min<long>(position, bufferSize());
    position -= bufferLength;

    seek(position);
    const ByteVector buffer = readBlock(bufferLength);

    for(int i = buffer.size() - 1; i >= 0; --i) {
      frameSyncBytes[1] = frameSyncBytes[0];
      frameSyncBytes[0] = buffer[i];
      if(isFrameSync(frameSyncBytes)) {
        const Header header(this, position + i, true);
        if(header.isValid())
          return position + i + header.frameLength();
      }
    }
  }

  return -1;
}
Exemple #17
0
void
MP4::Tag::parseCovr(MP4::Atom *atom, TagLib::File *file)
{
  MP4::CoverArtList value;
  ByteVector data = file->readBlock(atom->length - 8);
  unsigned int pos = 0;
  while(pos < data.size()) {
    int length = data.mid(pos, 4).toUInt();
    ByteVector name = data.mid(pos + 4, 4);
    int flags = data.mid(pos + 8, 4).toUInt();
    if(name != "data") {
      debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\"");
      break;
    }
	if (flags == 0) { //detect cover format when the cover format bytes are not set
		ByteVector picHeader = data.mid(pos+16,9);
		const char jpeg[] = {0xff, 0xd8, 0xff, 0xe0 };
		const char jfif[] = {0x10, 0x4a, 0x46, 0x49, 0x46 };
		const char png[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00 };
		if ((memcmp(picHeader.data(), png, 9) == 0)) {
			flags = MP4::CoverArt::PNG;
		} else if ((memcmp(picHeader.data(), jpeg, 4) == 0)) {
			flags = MP4::CoverArt::JPEG;
		} else if ((memcmp(picHeader.data(), jfif, 5) == 0)) {
			flags = MP4::CoverArt::JPEG;
		}
	}
    if(flags == MP4::CoverArt::PNG || flags == MP4::CoverArt::JPEG || flags == 0) {
      value.append(MP4::CoverArt(MP4::CoverArt::Format(flags),
                                 data.mid(pos + 16, length - 16)));
    }
    pos += length;
  }
  if(value.size() > 0)
    d->items.insert(atom->name, value);
}
void ByteVectorStream::insert(const ByteVector &data, long long start, size_t replace)
{
  if(data.size() < replace) {
    removeBlock(start + data.size(), replace - data.size());
  }
  else if(data.size() > replace) {
    const size_t sizeDiff = data.size() - replace;
    truncate(length() + sizeDiff);

    const size_t readPosition  = static_cast<size_t>(start + replace);
    const size_t writePosition = static_cast<size_t>(start + data.size());
    ::memmove(
      d->data.data() + writePosition,
      d->data.data() + readPosition,
      static_cast<size_t>(length() - sizeDiff - readPosition));
  }
  seek(start);
  writeBlock(data);
}
Exemple #19
0
bool MPC::File::save()
{
  if(readOnly()) {
    debug("MPC::File::save() -- File is read only.");
    return false;
  }

  // Possibly strip ID3v2 tag

  if(!d->ID3v2Header && d->ID3v2Location >= 0) {
    removeBlock(d->ID3v2Location, d->ID3v2Size);

    if(d->APELocation >= 0)
      d->APELocation -= d->ID3v2Size;

    if(d->ID3v1Location >= 0)
      d->ID3v1Location -= d->ID3v2Size;

    d->ID3v2Location = -1;
    d->ID3v2Size = 0;
  }

  // Update ID3v1 tag

  if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {

    // ID3v1 tag is not empty. Update the old one or create a new one.

    if(d->ID3v1Location >= 0) {
      seek(d->ID3v1Location);
    }
    else {
      seek(0, End);
      d->ID3v1Location = tell();
    }

    writeBlock(ID3v1Tag()->render());
  }
  else {

    // ID3v1 tag is empty. Remove the old one.

    if(d->ID3v1Location >= 0) {
      truncate(d->ID3v1Location);
      d->ID3v1Location = -1;
    }
  }

  // Update APE tag

  if(APETag() && !APETag()->isEmpty()) {

    // APE tag is not empty. Update the old one or create a new one.

    if(d->APELocation < 0) {
      if(d->ID3v1Location >= 0)
        d->APELocation = d->ID3v1Location;
      else
        d->APELocation = length();
    }

    const ByteVector data = APETag()->render();
    insert(data, d->APELocation, d->APESize);

    if(d->ID3v1Location >= 0)
      d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);

    d->APESize = data.size();
  }
  else {

    // APE tag is empty. Remove the old one.

    if(d->APELocation >= 0) {
      removeBlock(d->APELocation, d->APESize);

      if(d->ID3v1Location >= 0)
        d->ID3v1Location -= d->APESize;

      d->APELocation = -1;
      d->APESize = 0;
    }
  }

  return true;
}
Exemple #20
0
void FileStream::insert(const ByteVector &data, ulong start, ulong replace)
{
  if(!isOpen()) {
    debug("File::insert() -- invalid file.");
    return;
  }

  if(readOnly()) {
    debug("File::insert() -- read only file.");
    return;
  }

  if(data.size() == replace) {
    seek(start);
    writeBlock(data);
    return;
  }
  else if(data.size() < replace) {
    seek(start);
    writeBlock(data);
    removeBlock(start + data.size(), replace - data.size());
    return;
  }

  // Woohoo!  Faster (about 20%) than id3lib at last.  I had to get hardcore
  // and avoid TagLib's high level API for rendering just copying parts of
  // the file that don't contain tag data.
  //
  // Now I'll explain the steps in this ugliness:

  // First, make sure that we're working with a buffer that is longer than
  // the *differnce* in the tag sizes.  We want to avoid overwriting parts
  // that aren't yet in memory, so this is necessary.

  ulong bufferLength = bufferSize();

  while(data.size() - replace > bufferLength)
    bufferLength += bufferSize();

  // Set where to start the reading and writing.

  long readPosition = start + replace;
  long writePosition = start;

  ByteVector buffer = data;
  ByteVector aboutToOverwrite(static_cast<uint>(bufferLength));

  while(true)
  {
    // Seek to the current read position and read the data that we're about
    // to overwrite.  Appropriately increment the readPosition.
    
    seek(readPosition);
    const size_t bytesRead = readFile(d->file, aboutToOverwrite);
    aboutToOverwrite.resize(bytesRead);
    readPosition += bufferLength;

    // Check to see if we just read the last block.  We need to call clear()
    // if we did so that the last write succeeds.

    if(bytesRead < bufferLength)
      clear();

    // Seek to the write position and write our buffer.  Increment the
    // writePosition.

    seek(writePosition);
    writeBlock(buffer);

    // We hit the end of the file.

    if(bytesRead == 0)
      break;

    writePosition += buffer.size();

    // Make the current buffer the data that we read in the beginning.
    
    buffer = aboutToOverwrite;
  }
}
Exemple #21
0
bool CHttpServer::parse_request(String &method, String &uri, String &query, HeaderList &headers, String &body )
{
    method.clear();
    uri.clear();
    headers.clear();
    body.clear();

    size_t s = 0;
    ByteVector request;

    bool parsing_headers = true;
    size_t content_length = 0;

    for (;;) {
        if (!receive_request(request))
            return false;

        size_t lim = request.size();
        while (parsing_headers) {
            size_t e;
            for(e = s; e < lim && request[e] != '\r'; ++e);
            if (e >= lim - 1) {
                // Incomplete line, will read further
                break;
            }
            if (request[e + 1] != '\n') {
                if (verbose) RAWLOG_ERROR("Wrong request syntax, line should ends by '\\r\\n'");
                return false;
            }
            
            String line(&request[s], e - s);
            s = e + 2;
            
            if (line.empty()) {
                parsing_headers = false;
                break;
            }
            
            if (uri.empty()) {
                // Parse start line
                if (!parse_startline(line, method, uri, query) || uri.empty())
                    return false;
            }
            else {
                Header hdr;
                if (!parse_header(line, hdr) || hdr.name.empty())
                    return false;
                headers.push_back(hdr);
                
                String low;
                std::transform(hdr.name.begin(), hdr.name.end(), std::back_inserter(low), &::tolower);
                if (low == "content-length") {
                    content_length = ::atoi(hdr.value.c_str());
                }
            }
        }

        if (!parsing_headers) {
            if (content_length == 0)
                return true;

            if (lim - s < content_length)
                continue;

            body.assign(&request[s], &request[s] + content_length);
            return true;
        }
    }
}
Exemple #22
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 #23
0
void ASF::File::read()
{
  if(!isValid())
    return;

  ByteVector guid = readBlock(16);
  if(guid != headerGuid) {
    debug("ASF: Not an ASF file.");
    setValid(false);
    return;
  }

  d->tag = new ASF::Tag();
  d->properties = new ASF::AudioProperties();

  bool ok;
  d->headerSize = readQWORD(this, &ok);
  if(!ok) {
    setValid(false);
    return;
  }
  int numObjects = readDWORD(this, &ok);
  if(!ok) {
    setValid(false);
    return;
  }
  seek(2, Current);

  for(int i = 0; i < numObjects; i++) {
    guid = readBlock(16);
    if(guid.size() != 16) {
      setValid(false);
      break;
    }
    long size = (long)readQWORD(this, &ok);
    if(!ok) {
      setValid(false);
      break;
    }
    FilePrivate::BaseObject *obj;
    if(guid == filePropertiesGuid) {
      obj = new FilePrivate::FilePropertiesObject();
    }
    else if(guid == streamPropertiesGuid) {
      obj = new FilePrivate::StreamPropertiesObject();
    }
    else if(guid == contentDescriptionGuid) {
      obj = new FilePrivate::ContentDescriptionObject();
    }
    else if(guid == extendedContentDescriptionGuid) {
      obj = new FilePrivate::ExtendedContentDescriptionObject();
    }
    else if(guid == headerExtensionGuid) {
      obj = new FilePrivate::HeaderExtensionObject();
    }
    else if(guid == codecListGuid) {
      obj = new FilePrivate::CodecListObject();
    }
    else {
      if(guid == contentEncryptionGuid ||
         guid == extendedContentEncryptionGuid ||
         guid == advancedContentEncryptionGuid) {
        d->properties->setEncrypted(true);
      }
      obj = new FilePrivate::UnknownObject(guid);
    }
    obj->parse(this, size);
    d->objects.append(obj);
  }
}
Exemple #24
0
bool ASF::File::save()
{
  if(readOnly()) {
    debug("ASF::File::save() -- File is read only.");
    return false;
  }

  if(!isValid()) {
    debug("ASF::File::save() -- Trying to save invalid file.");
    return false;
  }

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

  d->extendedContentDescriptionObject->attributeData.clear();
  d->metadataObject->attributeData.clear();
  d->metadataLibraryObject->attributeData.clear();

  const AttributeListMap allAttributes = d->tag->attributeListMap();

  for(AttributeListMap::ConstIterator it = allAttributes.begin(); it != allAttributes.end(); ++it) {

    const String &name = it->first;
    const AttributeList &attributes = it->second;

    bool inExtendedContentDescriptionObject = false;
    bool inMetadataObject = false;

    for(AttributeList::ConstIterator jt = attributes.begin(); jt != attributes.end(); ++jt) {

      const Attribute &attribute = *jt;
      const bool largeValue = (attribute.dataSize() > 65535);
      const bool guid       = (attribute.type() == Attribute::GuidType);

      if(!inExtendedContentDescriptionObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
        d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
        inExtendedContentDescriptionObject = true;
      }
      else if(!inMetadataObject && !guid && !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(List<FilePrivate::BaseObject *>::ConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) {
    data.append((*it)->render(this));
  }

  seek(16);
  writeBlock(ByteVector::fromUInt64LE(data.size() + 30));
  writeBlock(ByteVector::fromUInt32LE(d->objects.size()));
  writeBlock(ByteVector("\x01\x02", 2));

  insert(data, 30, static_cast<size_t>(d->headerSize - 30));

  d->headerSize = data.size() + 30;

  return true;
}
Exemple #25
0
ByteVector
MP4::Tag::renderAtom(const ByteVector &name, const ByteVector &data) const
{
  return ByteVector::fromUInt(data.size() + 8) + name + data;
}
Exemple #26
0
void ID3v2::Tag::parse(const ByteVector &origData)
{
  ByteVector data = origData;

  if(d->header.unsynchronisation() && d->header.majorVersion() <= 3)
    data = SynchData::decode(data);

  uint frameDataPosition = 0;
  uint frameDataLength = data.size();

  // check for extended header

  if(d->header.extendedHeader()) {
    if(!d->extendedHeader)
      d->extendedHeader = new ExtendedHeader;
    d->extendedHeader->setData(data);
    if(d->extendedHeader->size() <= data.size()) {
      frameDataPosition += d->extendedHeader->size();
      frameDataLength -= d->extendedHeader->size();
    }
  }

  // check for footer -- we don't actually need to parse it, as it *must*
  // contain the same data as the header, but we do need to account for its
  // size.

  if(d->header.footerPresent() && Footer::size() <= frameDataLength)
    frameDataLength -= Footer::size();

  // parse frames

  // Make sure that there is at least enough room in the remaining frame data for
  // a frame header.

  while(frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) {

    // If the next data is position is 0, assume that we've hit the padding
    // portion of the frame data.

    if(data.at(frameDataPosition) == 0) {
      if(d->header.footerPresent())
        debug("Padding *and* a footer found.  This is not allowed by the spec.");

      d->paddingSize = frameDataLength - frameDataPosition;
      return;
    }

    Frame *frame = d->factory->createFrame(data.mid(frameDataPosition),
                                           &d->header);

    if(!frame)
      return;

    // Checks to make sure that frame parsed correctly.

    if(frame->size() <= 0) {
      delete frame;
      return;
    }

    frameDataPosition += frame->size() + Frame::headerSize(d->header.majorVersion());
    addFrame(frame);
  }
}
Exemple #27
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;
}
Exemple #28
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 #29
0
void Frame::Header::setData(const ByteVector &data, uint version)
{
  d->version = version;

  switch(version) {
  case 0:
  case 1:
  case 2:
  {
    // ID3v2.2

    if(data.size() < 3) {
      debug("You must at least specify a frame ID.");
      return;
    }

    // Set the frame ID -- the first three bytes

    d->frameID = data.mid(0, 3);

    // If the full header information was not passed in, do not continue to the
    // steps to parse the frame size and flags.

    if(data.size() < 6) {
      d->frameSize = 0;
      return;
    }

    d->frameSize = data.mid(3, 3).toUInt();

    break;
  }
  case 3:
  {
    // ID3v2.3

    if(data.size() < 4) {
      debug("You must at least specify a frame ID.");
      return;
    }

    // Set the frame ID -- the first four bytes

    d->frameID = data.mid(0, 4);

    // If the full header information was not passed in, do not continue to the
    // steps to parse the frame size and flags.

    if(data.size() < 10) {
      d->frameSize = 0;
      return;
    }

    // Set the size -- the frame size is the four bytes starting at byte four in
    // the frame header (structure 4)

    d->frameSize = data.mid(4, 4).toUInt();

    { // read the first byte of flags
      std::bitset<8> flags(data[8]);
      d->tagAlterPreservation  = flags[7]; // (structure 3.3.1.a)
      d->fileAlterPreservation = flags[6]; // (structure 3.3.1.b)
      d->readOnly              = flags[5]; // (structure 3.3.1.c)
    }

    { // read the second byte of flags
      std::bitset<8> flags(data[9]);
      d->compression         = flags[7]; // (structure 3.3.1.i)
      d->encryption          = flags[6]; // (structure 3.3.1.j)
      d->groupingIdentity    = flags[5]; // (structure 3.3.1.k)
    }
    break;
  }
  case 4:
  default:
  {
    // ID3v2.4

    if(data.size() < 4) {
      debug("You must at least specify a frame ID.");
      return;
    }

    // Set the frame ID -- the first four bytes

    d->frameID = data.mid(0, 4);

    // If the full header information was not passed in, do not continue to the
    // steps to parse the frame size and flags.

    if(data.size() < 10) {
      d->frameSize = 0;
      return;
    }

    // Set the size -- the frame size is the four bytes starting at byte four in
    // the frame header (structure 4)

    d->frameSize = SynchData::toUInt(data.mid(4, 4));
#ifndef NO_ITUNES_HACKS
    // iTunes writes v2.4 tags with v2.3-like frame sizes
    if(d->frameSize > 127) {
      if(!isValidFrameID(data.mid(d->frameSize + 10, 4))) {
        unsigned int uintSize = data.mid(4, 4).toUInt();
        if(isValidFrameID(data.mid(uintSize + 10, 4))) {
          d->frameSize = uintSize;
        }
      }
    }
#endif

    { // read the first byte of flags
      std::bitset<8> flags(data[8]);
      d->tagAlterPreservation  = flags[6]; // (structure 4.1.1.a)
      d->fileAlterPreservation = flags[5]; // (structure 4.1.1.b)
      d->readOnly              = flags[4]; // (structure 4.1.1.c)
    }

    { // read the second byte of flags
      std::bitset<8> flags(data[9]);
      d->groupingIdentity    = flags[6]; // (structure 4.1.2.h)
      d->compression         = flags[3]; // (structure 4.1.2.k)
      d->encryption          = flags[2]; // (structure 4.1.2.m)
      d->unsynchronisation   = flags[1]; // (structure 4.1.2.n)
      d->dataLengthIndicator = flags[0]; // (structure 4.1.2.p)
    }
    break;
  }
  }
}
Exemple #30
0
bool ASF::File::save()
{
  if(readOnly()) {
    debug("ASF::File::save() -- File is read only.");
    return false;
  }

  if(!isValid()) {
    debug("ASF::File::save() -- Trying to save invalid file.");
    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];
      const bool largeValue = (attribute.dataSize() > 65535);
      const bool guid       = (attribute.type() == Attribute::GuidType);

      if(!inExtendedContentDescriptionObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
        d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
        inExtendedContentDescriptionObject = true;
      }
      else if(!inMetadataObject && !guid && !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, (TagLib::ulong)d->size);

  return true;
}