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; }
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; }