+ }
+ 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 files.\n", __FILE__, __LINE__, fileCollectionCount);
+ collectionFileIndex = 0;
+ firstLink = false;
+ }
+ if (collectionFileIndex < fileCollectionCount) {
+ uint32_t fileTagCount = 0;
+ if (!ensureBufferCapacity(4)) {
+ return NULL;
+ }
+ growingBuffer.read(&fileTagCount, 4);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] will read %d file tags.\n", __FILE__, __LINE__, fileTagCount);
+ StringTag* filenameTag = NULL;
+ uint64_t size = 0;
+ HashTag* hashTag = NULL;
+ for (uint32_t fileTagIndex = 0; fileTagIndex < fileTagCount; fileTagIndex++) {
+ uint8_t tagType = 0;
+ if (!ensureBufferCapacity(1)) {
+ return NULL;
+ }
+ growingBuffer.read(&tagType, 1);
+ tagType &= 0x7f;
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] reading tag type %d.\n", __FILE__, __LINE__, tagType);
+ if (tagType == 0x01) {
+ hashTag = readHashTag();
+ if (!hashTag) {
+ return NULL;
+ }
+ } else if (tagType == 0x02) {
+ StringTag* stringTag = readStringTag();
+ if (!stringTag) {
+ return NULL;
+ }
+ if (stringTag->getId() == 0x01) {
+ filenameTag = stringTag;
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read file name “%s”.\n", __FILE__, __LINE__, (char*) stringTag->getValue());
+ } else if (stringTag->getId() == 0xf6) {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read file comment “%s”.\n", __FILE__, __LINE__, (char*) stringTag->getValue());
+ delete stringTag;
+ }
+ } else if ((tagType == 0x03) || (tagType == 0x08) || (tagType == 0x09) || (tagType == 0x0b)) {
+ if (!ensureBufferCapacity(1)) {
+ return NULL;
+ }
+ uint8_t id = 0;
+ growingBuffer.read(&id, 1);
+ if (id == 0x02) {
+ int neededBytes = (tagType == 0x03) ? 4 : ((tagType == 0x08) ? 2 : ((tagType == 0x09) ? 1 : 8));
+ if (!ensureBufferCapacity(neededBytes)) {
+ return NULL;
+ }
+ growingBuffer.read(&size, neededBytes);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] file size is %llu bytes.\n", __FILE__, __LINE__, size);
+ } else if (id == 0xf7) {
+ uint8_t fileRating = 0;
+ if (!ensureBufferCapacity(1)) {
+ return NULL;
+ }
+ growingBuffer.read(&fileRating, 1);
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] read file rating %d.\n", __FILE__, __LINE__, fileRating);
+ }
+ }
+ }
+ collectionFileIndex++;
+ growingBuffer.cut();
+ if (filenameTag && hashTag) {
+ ED2KLink* ed2kLink = new ED2KLink((char*) filenameTag->getValue(), size, hashTag->getValue());
+ delete filenameTag;
+ delete hashTag;
+ return ed2kLink;
+ } else {
+ GlobalSettings::isVerbose() && fprintf(stderr, "[%s:%d] not enough data to decode file.\n", __FILE__, __LINE__);
+ }
+ if (filenameTag) {
+ delete filenameTag;
+ }
+ if (hashTag) {
+ delete hashTag;
+ }