Project

General

Profile

Bug #533 » fix_jpg_parser.patch

Redmine Admin, 10 Oct 2008 17:43

View differences:

exiv2-svn/src/jpgimage.hpp (Arbeitskopie)
95 95
                                 uint32_t *const sizeHdr,
96 96
                                 uint32_t *const sizeData);
97 97
        /*!
98
          @brief Set the new IPTC IRB, keeps existing IRBs but removes the
99
                 IPTC block if there is no new IPTC data to write.
98
          @brief Set the new IPTC IRB, keeps existing IRBs
100 99

  
101
          @param pPsData    Existing IRB buffer
102
          @param sizePsData Size of the IRB buffer, may be 0
103
          @param iptcData   Iptc data to embed, may be empty
100
          @param pPsData        Existing IRB buffer
101
          @param sizePsData     Size of the IRB buffer, may be 0
102
          @param iptcData       Iptc data to embed, may be empty
103
          @param keepEmptyBlock Whether to keep the IPTC block even
104
                                when there is no new IPTC data to write
104 105
          @return A data buffer containing the new IRB buffer, may have 0 size
105 106
        */
106 107
        static DataBuf setIptcIrb(const byte*     pPsData,
107 108
                                  long            sizePsData,
108
                                  const IptcData& iptcData);
109
                                  const IptcData& iptcData,
110
                                  bool            keepEmptyBlock=false);
109 111

  
110 112
    }; // class Photoshop
111 113

  
exiv2-svn/src/jpgimage.cpp (Arbeitskopie)
106 106
        std::cerr << "Photoshop::locateIrb: ";
107 107
#endif
108 108
        // Data should follow Photoshop format, if not exit
109
        while (   position <= sizePsData - 14
109
        while (   position <= sizePsData - 12
110 110
               && memcmp(pPsData + position, Photoshop::bimId_, 4) == 0) {
111 111
            const byte *hrd = pPsData + position;
112 112
            position += 4;
......
173 173

  
174 174
    DataBuf Photoshop::setIptcIrb(const byte*     pPsData,
175 175
                                  long            sizePsData,
176
                                  const IptcData& iptcData)
176
                                  const IptcData& iptcData,
177
                                  bool            keepEmptyBlock)
177 178
    {
178 179
        if (sizePsData > 0) assert(pPsData);
179 180
#ifdef DEBUG
......
198 199
        }
199 200
        // Write new iptc record if we have it
200 201
        DataBuf rawIptc = IptcParser::encode(iptcData);
201
        if (rawIptc.size_ > 0) {
202
        if (rawIptc.size_ > 0 || keepEmptyBlock) {
202 203
            byte tmpBuf[12];
203 204
            std::memcpy(tmpBuf, Photoshop::bimId_, 4);
204 205
            us2Data(tmpBuf + 4, iptc_, bigEndian);
......
281 282
        const long bufMinSize = 36;
282 283
        long bufRead = 0;
283 284
        DataBuf buf(bufMinSize);
284
        Blob iptcBlob;
285 285
        bool foundPsData = false;
286 286

  
287 287
        // Read section marker
......
296 296
            if (bufRead < 2) throw Error(15);
297 297
            uint16_t size = getUShort(buf.pData_, bigEndian);
298 298

  
299
            if (foundPsData && marker != app13_) {
300
                // For IPTC, decrement search only after all app13 segments are
301
                // loaded, assuming they all appear in sequence. But decode IPTC
302
                // data after the loop, in case an app13 is the last segment
303
                // before sos or eoi.
304
                foundPsData = false;
305
                if (--search == 0) break;
306
            }
307

  
308 299
            if (marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) {
309 300
                if (size < 8) {
310 301
                    rc = 1;
......
344 335
                --search;
345 336
            }
346 337
            else if (   marker == app13_
338
                     && !foundPsData
347 339
                     && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) {
348 340
                if (size < 16) {
349 341
                    rc = 2;
......
354 346
                DataBuf psData(size - 16);
355 347
                io_->read(psData.pData_, psData.size_);
356 348
                if (io_->error() || io_->eof()) throw Error(14);
349
                Blob iptcBlob;
357 350
                const byte *record = 0;
358 351
                uint32_t sizeIptc = 0;
359 352
                uint32_t sizeHdr = 0;
......
370 363
                                                        &record,
371 364
                                                        &sizeHdr,
372 365
                                                        &sizeIptc)) {
373
                    if (sizeIptc) {
374 366
#ifdef DEBUG
375
                        std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n";
367
                    std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n";
376 368
#endif
369
                    if (sizeIptc) {
377 370
                        append(iptcBlob, record + sizeHdr, sizeIptc);
378 371
                    }
379 372
                    pCur = record + sizeHdr + sizeIptc;
380 373
                    pCur += (sizeIptc & 1);
381 374
                }
375
                if (   iptcBlob.size() > 0
376
                    && IptcParser::decode(iptcData_,
377
                                          &iptcBlob[0],
378
                                          static_cast<uint32_t>(iptcBlob.size()))) {
379
#ifndef SUPPRESS_WARNINGS
380
                    std::cerr << "Warning: Failed to decode IPTC metadata.\n";
381
#endif
382
                    iptcData_.clear();
383
                }
382 384
                foundPsData = true;
385
                --search;
383 386
            }
384 387
            else if (marker == com_ && comment_.empty())
385 388
            {
......
434 437
            }
435 438
        } // while there are segments to process
436 439

  
437
        if (   iptcBlob.size() > 0
438
            && IptcParser::decode(iptcData_,
439
                                  &iptcBlob[0],
440
                                  static_cast<uint32_t>(iptcBlob.size()))) {
441
#ifndef SUPPRESS_WARNINGS
442
            std::cerr << "Warning: Failed to decode IPTC metadata.\n";
443
#endif
444
            iptcData_.clear();
445
        }
446

  
447 440
        if (rc != 0) {
448 441
#ifndef SUPPRESS_WARNINGS
449 442
            std::cerr << "Warning: JPEG format error, rc = " << rc << "\n";
......
487 480
        int skipApp1Xmp = -1;
488 481
        int skipApp13Ps3 = -1;
489 482
        int skipCom = -1;
483
        bool multipleApp13Ps3 = false;
490 484
        DataBuf psData;
491 485
        DataBuf rawExif;
492 486

  
......
511 505
                insertPos = count + 1;
512 506
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
513 507
            }
514
            else if (marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) {
508
            else if (marker == app1_ && skipApp1Exif == -1
509
                     && memcmp(buf.pData_ + 2, exifId_, 6) == 0) {
515 510
                if (size < 8) throw Error(22);
516 511
                skipApp1Exif = count;
517 512
                ++search;
......
521 516
                io_->read(rawExif.pData_, rawExif.size_);
522 517
                if (io_->error() || io_->eof()) throw Error(22);
523 518
            }
524
            else if (marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) {
519
            else if (marker == app1_ && skipApp1Xmp == -1
520
                     && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) {
525 521
                if (size < 31) throw Error(22);
526 522
                skipApp1Xmp = count;
527 523
                ++search;
528 524
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
529 525
            }
530 526
            else if (marker == app13_ && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) {
527
                if (skipApp13Ps3 == -1) {
531 528
#ifdef DEBUG
532
                std::cerr << "Found APP13 Photoshop PS3 segment\n";
529
                    std::cerr << "Found APP13 Photoshop PS3 segment\n";
533 530
#endif
534
                if (size < 16) throw Error(22);
535
                skipApp13Ps3 = count;
536
                ++search;
537
                io_->seek(16 - bufRead, BasicIo::cur);
538
                psData.alloc(size - 16);
539
                // Load PS data now to allow reinsertion at any point
540
                io_->read(psData.pData_, size - 16);
541
                if (io_->error() || io_->eof()) throw Error(20);
531
                    if (size < 16) throw Error(22);
532
                    skipApp13Ps3 = count;
533
                    ++search;
534
                    io_->seek(16 - bufRead, BasicIo::cur);
535
                    psData.alloc(size - 16);
536
                    // Load PS data now to allow reinsertion at any point
537
                    io_->read(psData.pData_, size - 16);
538
                    if (io_->error() || io_->eof()) throw Error(20);
539
                } else {
540
#ifdef DEBUG
541
                    std::cerr << "Found another APP13 Photoshop PS3 segment\n";
542
#endif
543
                    multipleApp13Ps3 = true;
544
                }
542 545
            }
543 546
            else if (marker == com_ && skipCom == -1) {
544 547
                if (size < 2) throw Error(22);
......
658 661
                if (psData.size_ > 0 || iptcData_.count() > 0) {
659 662
                    // Set the new IPTC IRB, keeps existing IRBs but removes the
660 663
                    // IPTC block if there is no new IPTC data to write
664
                    // and no other IPTC IRBs are following
661 665
                    DataBuf newPsData = Photoshop::setIptcIrb(psData.pData_,
662 666
                                                              psData.size_,
663
                                                              iptcData_);
667
                                                              iptcData_,
668
                                                              multipleApp13Ps3);
664 669
                    if (newPsData.size_ > 0) {
665 670
                        // Write APP13 marker, new size, and ps3Id
666 671
                        tmpBuf[0] = 0xff;
(1-1/4)