return indexOfLineBreak != (size_t) -1;
}
+StringTag* CollectionReader::readStringTag(bool header) {
+ if (header) {
+ uint16_t unknown = 0;
+ if (!ensureBufferCapacity(2)) {
+ return NULL;
+ }
+ growingBuffer.read(&unknown, 2);
+ }
+ uint8_t tagName = 0;
+ if (!ensureBufferCapacity(1)) {
+ return NULL;
+ }
+ growingBuffer.read(&tagName, 1);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag name %d.\n", __FILE__, __LINE__, tagName);
+ uint16_t tagLength = 0;
+ if (!ensureBufferCapacity(2)) {
+ return NULL;
+ }
+ growingBuffer.read(&tagLength, 2);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag length %d.\n", __FILE__, __LINE__, tagLength);
+ char* tagValue = (char*) malloc(tagLength + 1);
+ if (!ensureBufferCapacity(tagLength)) {
+ return NULL;
+ }
+ growingBuffer.read(tagValue, tagLength);
+ tagValue[tagLength] = '\0';
+ StringTag* stringTag = new StringTag(tagName, tagValue);
+ free(tagValue);
+ return stringTag;
+}
+
+BlobTag* CollectionReader::readBlobTag(bool header) {
+ if (header) {
+ uint16_t unknown = 0;
+ if (!ensureBufferCapacity(2)) {
+ return NULL;
+ }
+ growingBuffer.read(&unknown, 2);
+ }
+ uint8_t tagName = 0;
+ if (!ensureBufferCapacity(1)) {
+ return NULL;
+ }
+ growingBuffer.read(&tagName, 1);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag name %d.\n", __FILE__, __LINE__, tagName);
+ uint32_t tagLength = 0;
+ if (!ensureBufferCapacity(4)) {
+ return NULL;
+ }
+ growingBuffer.read(&tagLength, 4);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag length %d.\n", __FILE__, __LINE__, tagLength);
+ void* tagValue = (char*) malloc(tagLength);
+ if (!ensureBufferCapacity(tagLength)) {
+ return NULL;
+ }
+ growingBuffer.read(tagValue, tagLength);
+ BlobTag* blobTag = new BlobTag(tagName, tagValue, tagLength);
+ free(tagValue);
+ return blobTag;
+}
+
ED2KLink* CollectionReader::getNextLink() {
- if (readerInput->isEOF()) {
+ if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
return NULL;
}
if (firstLink) {
identifyCollectionType();
- if (readerInput->isEOF()) {
+ if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
return NULL;
}
- firstLink = false;
}
if (isTextCollection) {
while (!readerInput->isEOF() && !isLineBreakPresent()) {
readMoreBytes();
}
- if (readerInput->isEOF()) {
+ if (readerInput->isEOF() && !growingBuffer.getRemaining()) {
GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] readInput EOF reached.\n", __FILE__, __LINE__);
return NULL;
}
size_t indexOfLineBreak = growingBuffer.indexOf('\n');
- char* line = (char*) calloc(indexOfLineBreak + 1, 1);
- growingBuffer.read(line, indexOfLineBreak + 1);
- line[indexOfLineBreak] = '\0';
- if (line[indexOfLineBreak - 1] == '\r') {
- line[indexOfLineBreak - 1] = '\0';
+ char* line;
+ if (indexOfLineBreak == (size_t) -1) {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] could not find line break, using remainder of file.\n", __FILE__, __LINE__);
+ indexOfLineBreak = growingBuffer.getRemaining();
+ line = (char*) malloc(indexOfLineBreak + 1);
+ growingBuffer.read(line, indexOfLineBreak);
+ line[indexOfLineBreak] = '\0';
+ } else {
+ line = (char*) malloc(indexOfLineBreak + 1);
+ growingBuffer.read(line, indexOfLineBreak + 1);
+ if (line[indexOfLineBreak] == '\n') {
+ line[indexOfLineBreak] = '\0';
+ }
+ if (line[indexOfLineBreak - 1] == '\r') {
+ line[indexOfLineBreak - 1] = '\0';
+ }
}
growingBuffer.cut();
GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] got line: %s\n", __FILE__, __LINE__, line);
ED2KLink* ed2kLink = ED2KLink::parseED2KLink(line);
free(line);
return ed2kLink;
+ }
+ if (firstLink) {
+ /* read header */
+ if (!ensureBufferCapacity(4)) {
+ return NULL;
+ }
+ uint32_t headerTagCount = 0;
+ growingBuffer.read(&headerTagCount, 4);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] will read %d header tags.\n", __FILE__, __LINE__, headerTagCount);
+ for (uint32_t headerTagIndex = 0; headerTagIndex < headerTagCount; headerTagIndex++) {
+ uint8_t tagType = 0;
+ if (!ensureBufferCapacity(1)) {
+ return NULL;
+ }
+ growingBuffer.read(&tagType, 1);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read tag type %d.\n", __FILE__, __LINE__, tagType);
+ if (tagType == 0x02) {
+ StringTag* stringTag = readStringTag(true);
+ if (stringTag->getId() == 0x01) {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_FILENAME: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
+ } else if (stringTag->getId() == 0x31) {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_COLLECTIONAUTHOR: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
+ } else {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown string in header: “%s”\n", __FILE__, __LINE__, (char*) stringTag->getValue());
+ }
+ } else if (tagType == 0x07) {
+ BlobTag* blobTag = readBlobTag(true);
+ if (blobTag->getId() == 0x32) {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] FT_COLLECTIONAUTHORKEY: %d bytes.\n", __FILE__, __LINE__, blobTag->getSize());
+ } else {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown block in header: %d bytes.\n", __FILE__, __LINE__, blobTag->getSize());
+ }
+ } else {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] unknown tag type: %02x.\n", __FILE__, __LINE__, tagType);
+ }
+ }
+ fileCollectionCount = 0;
+ if (!ensureBufferCapacity(4)) {
+ return NULL;
+ }
+ growingBuffer.read(&fileCollectionCount, 4);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] will read %d file tags.\n", __FILE__, __LINE__, fileCollectionCount);
+ collectionFileIndex = 0;
+ firstLink = false;
+ }
+ if (collectionFileIndex < fileCollectionCount) {
} else {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] reached end of collection.\n", __FILE__, __LINE__);
}
return NULL;
}
+bool CollectionReader::ensureBufferCapacity(size_t byteCount) {
+ while (!readerInput->isEOF() && (growingBuffer.getRemaining() < byteCount)) {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] only %d bytes remaning, need at least %d, reading more bytes.\n", __FILE__, __LINE__, growingBuffer.getRemaining(), byteCount);
+ readMoreBytes();
+ }
+ if (readerInput->isEOF() && (growingBuffer.getRemaining() < byteCount)) {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] need %d more bytes, but file is EOF.\n", __FILE__, __LINE__, (byteCount - growingBuffer.getRemaining()));
+ return false;
+ }
+ return true;
+}
+
void CollectionReader::readMoreBytes() {
char buffer[1024];
size_t readBytes;
}
void CollectionReader::identifyCollectionType() {
- int version;
size_t readBytes;
readBytes = readerInput->read(&version, 4);
} else if (!strncmp("ed2k", (char*) &version, 4)) {
isTextCollection = true;
growingBuffer.write(&version, 4);
+ version = 0;
GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] identified text collection\n", __FILE__, __LINE__);
} else {
GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] could not identify collection!\n", __FILE__, __LINE__);