bool
WaveReader::LoadListChunk(uint32_t aChunkSize,
    nsAutoPtr<nsHTMLMediaElement::MetadataTags> &aTags)
{
  // List chunks are always word (two byte) aligned.
  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
                    "LoadListChunk called with unaligned resource");

  static const unsigned int MAX_CHUNK_SIZE = 1 << 16;
  PR_STATIC_ASSERT(MAX_CHUNK_SIZE < UINT_MAX / sizeof(char));

  if (aChunkSize > MAX_CHUNK_SIZE) {
    return false;
  }

  nsAutoArrayPtr<char> chunk(new char[aChunkSize]);
  if (!ReadAll(chunk.get(), aChunkSize)) {
    return false;
  }

  static const uint32_t INFO_LIST_MAGIC = 0x494e464f;
  const char *p = chunk.get();
  if (ReadUint32BE(&p) != INFO_LIST_MAGIC) {
    return false;
  }

  const waveIdToName ID_TO_NAME[] = {
    { 0x49415254, NS_LITERAL_CSTRING("artist") },   // IART
    { 0x49434d54, NS_LITERAL_CSTRING("comments") }, // ICMT
    { 0x49474e52, NS_LITERAL_CSTRING("genre") },    // IGNR
    { 0x494e414d, NS_LITERAL_CSTRING("name") },     // INAM
  };

  const char* const end = chunk.get() + aChunkSize;

  aTags = new nsHTMLMediaElement::MetadataTags;
  aTags->Init();

  while (p + 8 < end) {
    uint32_t id = ReadUint32BE(&p);
    // Uppercase tag id, inspired by GStreamer's Wave parser.
    id &= 0xDFDFDFDF;

    uint32_t length = ReadUint32LE(&p);

    // Subchunk shall not exceed parent chunk.
    if (p + length > end) {
      break;
    }

    nsCString val(p, length);
    if (val[length - 1] == '\0') {
      val.SetLength(length - 1);
    }

    // Chunks in List::INFO are always word (two byte) aligned. So round up if
    // necessary.
    length += length % 2;
    p += length;

    if (!IsUTF8(val)) {
      continue;
    }

    for (size_t i = 0; i < mozilla::ArrayLength(ID_TO_NAME); ++i) {
      if (id == ID_TO_NAME[i].id) {
        aTags->Put(ID_TO_NAME[i].name, val);
        break;
      }
    }
  }

  return true;
}
bool
WaveReader::LoadFormatChunk(uint32_t aChunkSize)
{
  uint32_t rate, channels, frameSize, sampleFormat;
  char waveFormat[WAVE_FORMAT_CHUNK_SIZE];
  const char* p = waveFormat;

  // RIFF chunks are always word (two byte) aligned.
  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
                    "LoadFormatChunk called with unaligned resource");

  if (!ReadAll(waveFormat, sizeof(waveFormat))) {
    return false;
  }

  PR_STATIC_ASSERT(sizeof(uint16_t) +
                   sizeof(uint16_t) +
                   sizeof(uint32_t) +
                   4 +
                   sizeof(uint16_t) +
                   sizeof(uint16_t) <= sizeof(waveFormat));
  if (ReadUint16LE(&p) != WAVE_FORMAT_ENCODING_PCM) {
    NS_WARNING("WAVE is not uncompressed PCM, compressed encodings are not supported");
    return false;
  }

  channels = ReadUint16LE(&p);
  rate = ReadUint32LE(&p);

  // Skip over average bytes per second field.
  p += 4;

  frameSize = ReadUint16LE(&p);

  sampleFormat = ReadUint16LE(&p);

  // PCM encoded WAVEs are not expected to have an extended "format" chunk,
  // but I have found WAVEs that have a extended "format" chunk with an
  // extension size of 0 bytes.  Be polite and handle this rather than
  // considering the file invalid.  This code skips any extension of the
  // "format" chunk.
  if (aChunkSize > WAVE_FORMAT_CHUNK_SIZE) {
    char extLength[2];
    const char* p = extLength;

    if (!ReadAll(extLength, sizeof(extLength))) {
      return false;
    }

    PR_STATIC_ASSERT(sizeof(uint16_t) <= sizeof(extLength));
    uint16_t extra = ReadUint16LE(&p);
    if (aChunkSize - (WAVE_FORMAT_CHUNK_SIZE + 2) != extra) {
      NS_WARNING("Invalid extended format chunk size");
      return false;
    }
    extra += extra % 2;

    if (extra > 0) {
      PR_STATIC_ASSERT(UINT16_MAX + (UINT16_MAX % 2) < UINT_MAX / sizeof(char));
      nsAutoArrayPtr<char> chunkExtension(new char[extra]);
      if (!ReadAll(chunkExtension.get(), extra)) {
        return false;
      }
    }
  }

  // RIFF chunks are always word (two byte) aligned.
  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
                    "LoadFormatChunk left resource unaligned");

  // Make sure metadata is fairly sane.  The rate check is fairly arbitrary,
  // but the channels check is intentionally limited to mono or stereo
  // because that's what the audio backend currently supports.
  unsigned int actualFrameSize = sampleFormat == 8 ? 1 : 2 * channels;
  if (rate < 100 || rate > 96000 ||
      channels < 1 || channels > MAX_CHANNELS ||
      (frameSize != 1 && frameSize != 2 && frameSize != 4) ||
      (sampleFormat != 8 && sampleFormat != 16) ||
      frameSize != actualFrameSize) {
    NS_WARNING("Invalid WAVE metadata");
    return false;
  }

  ReentrantMonitorAutoEnter monitor(mDecoder->GetReentrantMonitor());
  mSampleRate = rate;
  mChannels = channels;
  mFrameSize = frameSize;
  if (sampleFormat == 8) {
    mSampleFormat = FORMAT_U8;
  } else {
    mSampleFormat = FORMAT_S16;
  }
  return true;
}
bool
WaveReader::LoadAllChunks(nsAutoPtr<HTMLMediaElement::MetadataTags> &aTags)
{
  // Chunks are always word (two byte) aligned.
  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
                    "LoadAllChunks called with unaligned resource");

  bool loadFormatChunk = false;
  bool findDataOffset = false;

  for (;;) {
    static const unsigned int CHUNK_HEADER_SIZE = 8;
    char chunkHeader[CHUNK_HEADER_SIZE];
    const char* p = chunkHeader;

    if (!ReadAll(chunkHeader, sizeof(chunkHeader))) {
      return false;
    }

    PR_STATIC_ASSERT(sizeof(uint32_t) * 2 <= CHUNK_HEADER_SIZE);

    uint32_t magic = ReadUint32BE(&p);
    uint32_t chunkSize = ReadUint32LE(&p);
    int64_t chunkStart = GetPosition();

    switch (magic) {
      case FRMT_CHUNK_MAGIC:
        loadFormatChunk = LoadFormatChunk(chunkSize);
        if (!loadFormatChunk) {
          return false;
        }
        break;

      case LIST_CHUNK_MAGIC:
        if (!aTags) {
          LoadListChunk(chunkSize, aTags);
        }
        break;

      case DATA_CHUNK_MAGIC:
        findDataOffset = FindDataOffset(chunkSize);
        return loadFormatChunk && findDataOffset;

      default:
        break;
    }

    // RIFF chunks are two-byte aligned, so round up if necessary.
    chunkSize += chunkSize % 2;

    // Move forward to next chunk
    CheckedInt64 forward = CheckedInt64(chunkStart) + chunkSize - GetPosition();

    if (!forward.isValid() || forward.value() < 0) {
      return false;
    }

    static const int64_t MAX_CHUNK_SIZE = 1 << 16;
    PR_STATIC_ASSERT(uint64_t(MAX_CHUNK_SIZE) < UINT_MAX / sizeof(char));
    nsAutoArrayPtr<char> chunk(new char[MAX_CHUNK_SIZE]);
    while (forward.value() > 0) {
      int64_t size = std::min(forward.value(), MAX_CHUNK_SIZE);
      if (!ReadAll(chunk.get(), size)) {
        return false;
      }
      forward -= size;
    }
  }

  return false;
}
//--------------------------------------------------------------------
//----- CommandRecognizing()
//-------- sd - socket descriptor
//--------------------------------------------------------------------
void
CommandRecognizing (int sd)
{
  RD cmd;
  int res, links=0;
  int IsName = 0;
  int IsWorking = 1;		// sign of break or end connection by client
  char ClientName[256];
  struct sockaddr_in addr;
  int addr_size = sizeof (addr);
  c_tree con_tree;
  ClientName[0] = 0;

  int last_error;

  res = getpeername (sd, (struct sockaddr *) &addr, (socklen_t *) & addr_size);
  
  last_error = errno;
  
  if (res != 0)
  {
    fprintf (stderr,"(%d) connector.c getpeername() ERROR(%d)\n", sd, last_error);fflush(stdout);
    return;
  }

  ConnectorsCounter++;
  CreateList (&con_tree);
  while (IsWorking > 0)
  {
    if( WaitNetDataExt(sd,5000) > 0)
    {
      if (STOP_TASK)
      {
        cmd.command = 88;
        break;
      }
      cmd.command = 80;
      IsWorking = recv (sd, &cmd, sizeof (cmd), MSG_WAITALL);
      //	gettimeofday(&tv1, NULL);
      //	printf("(%d)Connector recv: command = %d, work = %d, IsWorking = %d\n", sd, cmd.command, cmd.work, IsWorking);fflush(stdout);
      if (IsWorking > 0)
      {
        switch (cmd.command)
        {
        case GET_UNIT_IDENT_BY_NAME:
          IsWorking = GetUnitIdentByName (sd, cmd.work);
          break;
        case ACCEPT_ITEM:
          IsWorking = AcceptItem (sd, (ident_t) cmd.work);
          break;
        case FREE_ITEM:
          IsWorking = FreeItem (sd, (ident_t) cmd.work);
          break;
        case FREE_EXT_ITEM:
          IsWorking = FreeExtItem (sd, (ident_t) cmd.work, &con_tree);
          break;
        case READ_BY_IDENT:
          IsWorking = ReadByIdent (sd, (ident_t) cmd.work);
          break;
        case WRITE_BY_IDENT:
          IsWorking = WriteByIdent (sd, (ident_t) cmd.work);
          break;
        case END_SESSION:
          IsWorking = EndSession (sd);
          break;
        case READ_ALL:
          IsWorking = ReadAll (sd, &con_tree);
          break;
        case READ_NEW:
          IsWorking = ReadNew (sd, &con_tree);
          break;
        case LINK_ITEM_BY_NAME:
          IsWorking = LinkItem (sd, cmd.work, &con_tree);
          if(IsWorking)
            links++;
          break;
        case BEGIN_SESSION:
          recv (sd, ClientName, cmd.work, MSG_WAITALL);
          IsName = 1;
          break;
        case INIT_DB:
          init_reload();
          IsName = 1;
          fprintf
              (stdout,"<%s> init reload DB [sd=(%d) %s:%d]. Now are %2d clients.\n",
               ClientName[0] ? ClientName : "Unknown", sd,
               inet_ntoa (addr.sin_addr), ntohs (addr.sin_port),
               ConnectorsCounter);

          break;
        case WRITE_MULTIPLE:
          IsWorking = WriteMultiple(sd, cmd.work);
          break;
        default:
          fprintf (stderr,"Unrecognized command %d \n", cmd.command);fflush(stdout);
          break;
        }
        if (IsName < 2)
        {
          fprintf
              (stderr,"<%s> has been connected [sd=(%d) %s:%d]. Now are %2d clients.\n",
               ClientName[0] ? ClientName : "Unknown", sd,
               inet_ntoa (addr.sin_addr), ntohs (addr.sin_port),
               ConnectorsCounter);fflush(stdout);
          IsName = 2;
        }
      }
    }
    else
    {
      fprintf (stderr, "Connector() TIMEOUT\n");fflush(stdout);
      break;
    }
  }
  ClearList (&con_tree);
  res = ServerFreeAll (sd);
  ConnectorsCounter--;
  fprintf
    (stderr,
     "(cmd=%d)(links=%d)<%s> has been disconnected [sd=(%d) %s:%d]. Now are %2d clients.\n",
     cmd.command,links,
     ClientName[0] ? ClientName : "Unknown", sd, inet_ntoa (addr.sin_addr),
     ntohs (addr.sin_port), ConnectorsCounter);fflush(stdout);
}
bool
WaveReader::LoadListChunk(uint32_t aChunkSize,
                          nsAutoPtr<dom::HTMLMediaElement::MetadataTags> &aTags)
{
  MOZ_ASSERT(OnTaskQueue());

  // List chunks are always word (two byte) aligned.
  MOZ_ASSERT(mResource.Tell() % 2 == 0,
             "LoadListChunk called with unaligned resource");

  static const unsigned int MAX_CHUNK_SIZE = 1 << 16;
  static_assert(uint64_t(MAX_CHUNK_SIZE) < UINT_MAX / sizeof(char),
                "MAX_CHUNK_SIZE too large for enumerator.");

  if (aChunkSize > MAX_CHUNK_SIZE || aChunkSize < 4) {
    return false;
  }

  nsAutoArrayPtr<char> chunk(new char[aChunkSize]);
  if (!ReadAll(chunk.get(), aChunkSize)) {
    return false;
  }

  static const uint32_t INFO_LIST_MAGIC = 0x494e464f;
  const char* p = chunk.get();
  if (ReadUint32BE(&p) != INFO_LIST_MAGIC) {
    return false;
  }

  const waveIdToName ID_TO_NAME[] = {
    { 0x49415254, NS_LITERAL_CSTRING("artist") },   // IART
    { 0x49434d54, NS_LITERAL_CSTRING("comments") }, // ICMT
    { 0x49474e52, NS_LITERAL_CSTRING("genre") },    // IGNR
    { 0x494e414d, NS_LITERAL_CSTRING("name") },     // INAM
  };

  const char* const end = chunk.get() + aChunkSize;

  aTags = new dom::HTMLMediaElement::MetadataTags;

  while (p + 8 < end) {
    uint32_t id = ReadUint32BE(&p);
    // Uppercase tag id, inspired by GStreamer's Wave parser.
    id &= 0xDFDFDFDF;

    uint32_t length = ReadUint32LE(&p);

    // Subchunk shall not exceed parent chunk.
    if (uint32_t(end - p) < length) {
      break;
    }

    // Wrap the string, adjusting length to account for optional
    // null termination in the chunk.
    nsCString val(p, length);
    if (length > 0 && val[length - 1] == '\0') {
      val.SetLength(length - 1);
    }

    // Chunks in List::INFO are always word (two byte) aligned. So round up if
    // necessary.
    length += length % 2;
    p += length;

    if (!IsUTF8(val)) {
      continue;
    }

    for (size_t i = 0; i < mozilla::ArrayLength(ID_TO_NAME); ++i) {
      if (id == ID_TO_NAME[i].id) {
        aTags->Put(ID_TO_NAME[i].name, val);
        break;
      }
    }
  }

  return true;
}
Exemple #6
0
sBool sMiniFTPClient::ListFiles(const sChar *basepath,sArray<sChar> &listing)
{
  listing.Clear();
  if(State == CS_NOTARGET)
    return sFALSE;

  for(;;)
  {
    if(State != CS_CONNECTED && !TryReconnect(RetryCount))
      break;
  
    sU8 sizeBuf[8];
    if(SendCommand(sMFC_LIST,basepath,0) && ReadAll(sizeBuf,8))
    {
      sSize totalSize;
      sUnalignedLittleEndianLoad64(sizeBuf,(sU64&) totalSize);
      if((totalSize & 1)              // we expect 16bit chars
        || totalSize > 16*1024*1024)  // 16MB limit for directory listings (for now)
        return sFALSE;

      if(!Progress(basepath,0,totalSize,ProgressUser))
        return MaybeNextTime();

      sFixedArray<sU8> ioBuf((sInt) totalSize);
      sSize currentPos = 0;
      while(currentPos < totalSize)
      {
        sDInt size = (sDInt) (totalSize-currentPos);
        sDInt read;

        if(!Socket.Read(&ioBuf[(sInt) currentPos],size,read) || !read)
        {
          MaybeNextTime();
          break;
        }

        currentPos += read;
        if(!Progress(basepath,currentPos,totalSize,ProgressUser))
          return MaybeNextTime();
      }

      if(currentPos == totalSize)
      {
        listing.HintSize(sU32(totalSize/2));
        listing.AddMany(sU32(totalSize/2));

        for(sInt i=0;i<totalSize/2;i++)
        {
          sU16 v;
          sUnalignedLittleEndianLoad16(&ioBuf[i*2],v);
          listing[i] = v;
        }

        return sTRUE;
      }
    }
    else if(Error == sMFE_OK)
      MaybeNextTime();
    else
      break;
  }

  return sFALSE;
}