Blame src/actions.cpp

Packit Service 21b5d1
// ***************************************************************** -*- C++ -*-
Packit Service 21b5d1
/*
Packit Service 21b5d1
 * Copyright (C) 2004-2018 Exiv2 authors
Packit Service 21b5d1
 * This program is part of the Exiv2 distribution.
Packit Service 21b5d1
 *
Packit Service 21b5d1
 * This program is free software; you can redistribute it and/or
Packit Service 21b5d1
 * modify it under the terms of the GNU General Public License
Packit Service 21b5d1
 * as published by the Free Software Foundation; either version 2
Packit Service 21b5d1
 * of the License, or (at your option) any later version.
Packit Service 21b5d1
 *
Packit Service 21b5d1
 * This program is distributed in the hope that it will be useful,
Packit Service 21b5d1
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 21b5d1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 21b5d1
 * GNU General Public License for more details.
Packit Service 21b5d1
 *
Packit Service 21b5d1
 * You should have received a copy of the GNU General Public License
Packit Service 21b5d1
 * along with this program; if not, write to the Free Software
Packit Service 21b5d1
 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
Packit Service 21b5d1
 */
Packit Service 21b5d1
/*
Packit Service 21b5d1
  File:      actions.cpp
Packit Service 21b5d1
 */
Packit Service 21b5d1
// *****************************************************************************
Packit Service 21b5d1
// included header files
Packit Service 21b5d1
#include "config.h"
Packit Service 21b5d1
Packit Service 21b5d1
#include "actions.hpp"
Packit Service 21b5d1
#include "exiv2app.hpp"
Packit Service 21b5d1
#include "image.hpp"
Packit Service 21b5d1
#include "jpgimage.hpp"
Packit Service 21b5d1
#include "xmpsidecar.hpp"
Packit Service 21b5d1
#include "utils.hpp"
Packit Service 21b5d1
#include "types.hpp"
Packit Service 21b5d1
#include "exif.hpp"
Packit Service 21b5d1
#include "easyaccess.hpp"
Packit Service 21b5d1
#include "iptc.hpp"
Packit Service 21b5d1
#include "xmp_exiv2.hpp"
Packit Service 21b5d1
#include "preview.hpp"
Packit Service 21b5d1
#include "futils.hpp"
Packit Service 21b5d1
#include "i18n.h"                // NLS support.
Packit Service 21b5d1
Packit Service 21b5d1
// + standard includes
Packit Service 21b5d1
#include <string>
Packit Service 21b5d1
#include <iostream>
Packit Service 21b5d1
#include <iomanip>
Packit Service 21b5d1
#include <fstream>
Packit Service 21b5d1
#include <sstream>
Packit Service 21b5d1
#include <cstring>
Packit Service 21b5d1
#include <cstdio>
Packit Service 21b5d1
#include <ctime>
Packit Service 21b5d1
#include <cmath>
Packit Service 21b5d1
#include <cassert>
Packit Service 21b5d1
#include <stdexcept>
Packit Service 21b5d1
#include <sys/types.h>                  // for stat()
Packit Service 21b5d1
#include <sys/stat.h>                   // for stat()
Packit Service 21b5d1
#ifdef EXV_HAVE_UNISTD_H
Packit Service 21b5d1
# include <unistd.h>                    // for stat()
Packit Service 21b5d1
#endif
Packit Service 21b5d1
#ifdef _MSC_VER
Packit Service 21b5d1
# include <sys/utime.h>
Packit Service 21b5d1
#else
Packit Service 21b5d1
# include <utime.h>
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
#if !defined(__MINGW__) && !defined(_MSC_VER)
Packit Service 21b5d1
#define _fileno(a) a
Packit Service 21b5d1
#define _setmode(a,b)
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
// *****************************************************************************
Packit Service 21b5d1
// local declarations
Packit Service 21b5d1
namespace {
Packit Service 21b5d1
Packit Service 21b5d1
    //! Helper class to set the timestamp of a file to that of another file
Packit Service 21b5d1
    class Timestamp {
Packit Service 21b5d1
    public:
Packit Service 21b5d1
        //! C'tor
Packit Service 21b5d1
        Timestamp() : actime_(0), modtime_(0) {}
Packit Service 21b5d1
        //! Read the timestamp of a file
Packit Service 21b5d1
        int read(const std::string& path);
Packit Service 21b5d1
        //! Read the timestamp from a broken-down time in buffer \em tm.
Packit Service 21b5d1
        int read(struct tm* tm);
Packit Service 21b5d1
        //! Set the timestamp of a file
Packit Service 21b5d1
        int touch(const std::string& path);
Packit Service 21b5d1
Packit Service 21b5d1
    private:
Packit Service 21b5d1
        time_t actime_;
Packit Service 21b5d1
        time_t modtime_;
Packit Service 21b5d1
    };
Packit Service 21b5d1
Packit Service 21b5d1
    /*!
Packit Service 21b5d1
      @brief Convert a string "YYYY:MM:DD HH:MI:SS" to a struct tm type,
Packit Service 21b5d1
             returns 0 if successful
Packit Service 21b5d1
     */
Packit Service 21b5d1
    int str2Tm(const std::string& timeStr, struct tm* tm);
Packit Service 21b5d1
Packit Service 21b5d1
    //! Convert a localtime to a string "YYYY:MM:DD HH:MI:SS", "" on error
Packit Service 21b5d1
    std::string time2Str(time_t time);
Packit Service 21b5d1
Packit Service 21b5d1
    //! Convert a tm structure to a string "YYYY:MM:DD HH:MI:SS", "" on error
Packit Service 21b5d1
    std::string tm2Str(const struct tm* tm);
Packit Service 21b5d1
Packit Service 21b5d1
    /*!
Packit Service 21b5d1
      @brief Copy metadata from source to target according to Params::copyXyz
Packit Service 21b5d1
Packit Service 21b5d1
      @param source Source file path
Packit Service 21b5d1
      @param target Target file path. An *.exv file is created if target doesn't
Packit Service 21b5d1
                    exist.
Packit Service 21b5d1
      @param targetType Image type for the target image in case it needs to be
Packit Service 21b5d1
                    created.
Packit Service 21b5d1
      @param preserve Indicates if existing metadata in the target file should
Packit Service 21b5d1
                    be kept.
Packit Service 21b5d1
      @return 0 if successful, else an error code
Packit Service 21b5d1
    */
Packit Service 21b5d1
    int metacopy(const std::string& source,
Packit Service 21b5d1
                 const std::string& target,
Packit Service 21b5d1
                 int targetType,
Packit Service 21b5d1
                 bool preserve);
Packit Service 21b5d1
Packit Service 21b5d1
    /*!
Packit Service 21b5d1
      @brief Rename a file according to a timestamp value.
Packit Service 21b5d1
Packit Service 21b5d1
      @param path The original file path. Contains the new path on exit.
Packit Service 21b5d1
      @param tm   Pointer to a buffer with the broken-down time to rename
Packit Service 21b5d1
                  the file to.
Packit Service 21b5d1
      @return 0 if successful, -1 if the file was skipped, 1 on error.
Packit Service 21b5d1
    */
Packit Service 21b5d1
    int renameFile(std::string& path, const struct tm* tm);
Packit Service 21b5d1
Packit Service 21b5d1
    /*!
Packit Service 21b5d1
      @brief Make a file path from the current file path, destination
Packit Service 21b5d1
             directory (if any) and the filename extension passed in.
Packit Service 21b5d1
Packit Service 21b5d1
      @param path Path of the existing file
Packit Service 21b5d1
      @param ext  New filename extension (incl. the dot '.' if required)
Packit Service 21b5d1
      @return 0 if successful, 1 if the new file exists and the user
Packit Service 21b5d1
             chose not to overwrite it.
Packit Service 21b5d1
     */
Packit Service 21b5d1
    std::string newFilePath(const std::string& path, const std::string& ext);
Packit Service 21b5d1
Packit Service 21b5d1
    /*!
Packit Service 21b5d1
      @brief Check if file \em path exists and whether it should be
Packit Service 21b5d1
             overwritten. Ask user if necessary. Return 1 if the file
Packit Service 21b5d1
             exists and shouldn't be overwritten, else 0.
Packit Service 21b5d1
     */
Packit Service 21b5d1
    int dontOverwrite(const std::string& path);
Packit Service 21b5d1
Packit Service 21b5d1
    /*!
Packit Service 21b5d1
      @brief Output a text with a given minimum number of chars, honoring
Packit Service 21b5d1
             multi-byte characters correctly. Replace code in the form
Packit Service 21b5d1
             os << setw(width) << myString
Packit Service 21b5d1
             with
Packit Service 21b5d1
             os << make_pair( myString, width)
Packit Service 21b5d1
     */
Packit Service 21b5d1
    std::ostream& operator<<( std::ostream& os, std::pair<std::string, int> strAndWidth);
Packit Service 21b5d1
Packit Service 21b5d1
    //! Print image Structure information
Packit Service 21b5d1
    int printStructure(std::ostream& out, Exiv2::PrintStructureOption option, const std::string &path);
Packit Service 21b5d1
}
Packit Service 21b5d1
Packit Service 21b5d1
// *****************************************************************************
Packit Service 21b5d1
// class member definitions
Packit Service 21b5d1
namespace Action {
Packit Service 21b5d1
Packit Service 21b5d1
    Task::~Task()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Task::AutoPtr Task::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    TaskFactory* TaskFactory::instance_ = 0;
Packit Service 21b5d1
Packit Service 21b5d1
    TaskFactory& TaskFactory::instance()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (0 == instance_) {
Packit Service 21b5d1
            instance_ = new TaskFactory;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return *instance_;
Packit Service 21b5d1
    } // TaskFactory::instance
Packit Service 21b5d1
Packit Service 21b5d1
    void TaskFactory::cleanup()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (instance_ != 0) {
Packit Service 21b5d1
            Registry::iterator e = registry_.end();
Packit Service 21b5d1
            for (Registry::iterator i = registry_.begin(); i != e; ++i) {
Packit Service 21b5d1
                delete i->second;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            delete instance_;
Packit Service 21b5d1
            instance_ = 0;
Packit Service 21b5d1
        }
Packit Service 21b5d1
    } //TaskFactory::cleanup
Packit Service 21b5d1
Packit Service 21b5d1
    void TaskFactory::registerTask(TaskType type, Task::AutoPtr task)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        Registry::iterator i = registry_.find(type);
Packit Service 21b5d1
        if (i != registry_.end()) {
Packit Service 21b5d1
            delete i->second;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        registry_[type] = task.release();
Packit Service 21b5d1
    } // TaskFactory::registerTask
Packit Service 21b5d1
Packit Service 21b5d1
    TaskFactory::TaskFactory()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        // Register a prototype of each known task
Packit Service 21b5d1
        registerTask(adjust,  Task::AutoPtr(new Adjust));
Packit Service 21b5d1
        registerTask(print,   Task::AutoPtr(new Print));
Packit Service 21b5d1
        registerTask(rename,  Task::AutoPtr(new Rename));
Packit Service 21b5d1
        registerTask(erase,   Task::AutoPtr(new Erase));
Packit Service 21b5d1
        registerTask(extract, Task::AutoPtr(new Extract));
Packit Service 21b5d1
        registerTask(insert,  Task::AutoPtr(new Insert));
Packit Service 21b5d1
        registerTask(modify,  Task::AutoPtr(new Modify));
Packit Service 21b5d1
        registerTask(fixiso,  Task::AutoPtr(new FixIso));
Packit Service 21b5d1
        registerTask(fixcom,  Task::AutoPtr(new FixCom));
Packit Service 21b5d1
    } // TaskFactory c'tor
Packit Service 21b5d1
Packit Service 21b5d1
    Task::AutoPtr TaskFactory::create(TaskType type)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        Registry::const_iterator i = registry_.find(type);
Packit Service 21b5d1
        if (i != registry_.end() && i->second != 0) {
Packit Service 21b5d1
            Task* t = i->second;
Packit Service 21b5d1
            return t->clone();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return Task::AutoPtr(0);
Packit Service 21b5d1
    } // TaskFactory::create
Packit Service 21b5d1
Packit Service 21b5d1
    Print::~Print()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int setModeAndPrintStructure(Exiv2::PrintStructureOption option, const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        _setmode(_fileno(stdout),O_BINARY);
Packit Service 21b5d1
        return printStructure(std::cout, option, path);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Print::run(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        try {
Packit Service 21b5d1
            path_ = path;
Packit Service 21b5d1
            int rc = 0;
Packit Service 21b5d1
            Exiv2::PrintStructureOption option = Exiv2::kpsNone ;
Packit Service 21b5d1
            switch (Params::instance().printMode_) {
Packit Service 21b5d1
                case Params::pmSummary:   rc = Params::instance().greps_.empty() ? printSummary() : printList(); break;
Packit Service 21b5d1
                case Params::pmList:      rc = printList();        break;
Packit Service 21b5d1
                case Params::pmComment:   rc = printComment();     break;
Packit Service 21b5d1
                case Params::pmPreview:   rc = printPreviewList(); break;
Packit Service 21b5d1
                case Params::pmStructure: rc = printStructure(std::cout,Exiv2::kpsBasic, path_)     ; break;
Packit Service 21b5d1
                case Params::pmRecursive: rc = printStructure(std::cout,Exiv2::kpsRecursive, path_) ; break;
Packit Service 21b5d1
                case Params::pmXMP:
Packit Service 21b5d1
                    if (option == Exiv2::kpsNone)
Packit Service 21b5d1
                        option = Exiv2::kpsXMP;
Packit Service 21b5d1
                    rc = setModeAndPrintStructure(option, path_);
Packit Service 21b5d1
                    break;
Packit Service 21b5d1
                case Params::pmIccProfile:
Packit Service 21b5d1
                    if (option == Exiv2::kpsNone)
Packit Service 21b5d1
                        option = Exiv2::kpsIccProfile;
Packit Service 21b5d1
                    rc = setModeAndPrintStructure(option, path_);
Packit Service 21b5d1
                    break;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            return rc;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        catch(const Exiv2::AnyError& e) {
Packit Service 21b5d1
            std::cerr << "Exiv2 exception in print action for file "
Packit Service 21b5d1
                      << path << ":\n" << e << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        catch(const std::overflow_error& e) {
Packit Service 21b5d1
            std::cerr << "std::overflow_error exception in print action for file "
Packit Service 21b5d1
                      << path << ":\n" << e.what() << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Print::printSummary()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path_, true)) {
Packit Service 21b5d1
            std::cerr << path_ << ": "
Packit Service 21b5d1
                      << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        Exiv2::ExifData& exifData = image->exifData();
Packit Service 21b5d1
        align_ = 16;
Packit Service 21b5d1
Packit Service 21b5d1
        // Filename
Packit Service 21b5d1
        printLabel(_("File name"));
Packit Service 21b5d1
        std::cout << path_ << std::endl;
Packit Service 21b5d1
Packit Service 21b5d1
        // Filesize
Packit Service 21b5d1
        struct stat buf;
Packit Service 21b5d1
        if (0 == stat(path_.c_str(), &buf)) {
Packit Service 21b5d1
            printLabel(_("File size"));
Packit Service 21b5d1
            std::cout << buf.st_size << " " << _("Bytes") << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // MIME type
Packit Service 21b5d1
        printLabel(_("MIME type"));
Packit Service 21b5d1
        std::cout << image->mimeType() << std::endl;
Packit Service 21b5d1
Packit Service 21b5d1
        // Image size
Packit Service 21b5d1
        printLabel(_("Image size"));
Packit Service 21b5d1
        std::cout << image->pixelWidth() << " x " << image->pixelHeight() << std::endl;
Packit Service 21b5d1
Packit Service 21b5d1
        if (exifData.empty()) {
Packit Service 21b5d1
            std::cerr << path_ << ": "
Packit Service 21b5d1
                      << _("No Exif data found in the file\n");
Packit Service 21b5d1
            return -3;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // Camera make
Packit Service 21b5d1
        printTag(exifData, "Exif.Image.Make", _("Camera make"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Camera model
Packit Service 21b5d1
        printTag(exifData, "Exif.Image.Model", _("Camera model"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Image Timestamp
Packit Service 21b5d1
        printTag(exifData, "Exif.Photo.DateTimeOriginal", _("Image timestamp"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Image number
Packit Service 21b5d1
        // Todo: Image number for cameras other than Canon
Packit Service 21b5d1
        printTag(exifData, "Exif.Canon.FileNumber", _("Image number"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Exposure time
Packit Service 21b5d1
        // From ExposureTime, failing that, try ShutterSpeedValue
Packit Service 21b5d1
        printLabel(_("Exposure time"));
Packit Service 21b5d1
        bool done = 0 != printTag(exifData, "Exif.Photo.ExposureTime");
Packit Service 21b5d1
        if (!done) {
Packit Service 21b5d1
            done = 0 != printTag(exifData, "Exif.Photo.ShutterSpeedValue");
Packit Service 21b5d1
        }
Packit Service 21b5d1
        std::cout << std::endl;
Packit Service 21b5d1
Packit Service 21b5d1
        // Aperture
Packit Service 21b5d1
        // Get if from FNumber and, failing that, try ApertureValue
Packit Service 21b5d1
        {
Packit Service 21b5d1
            printLabel(_("Aperture"));
Packit Service 21b5d1
            bool done = 0 != printTag(exifData, "Exif.Photo.FNumber");
Packit Service 21b5d1
            if (!done) {
Packit Service 21b5d1
                done = 0 != printTag(exifData, "Exif.Photo.ApertureValue");
Packit Service 21b5d1
            }
Packit Service 21b5d1
            std::cout << std::endl;
Packit Service 21b5d1
Packit Service 21b5d1
            // Exposure bias
Packit Service 21b5d1
            printTag(exifData, "Exif.Photo.ExposureBiasValue", _("Exposure bias"));
Packit Service 21b5d1
Packit Service 21b5d1
            // Flash
Packit Service 21b5d1
            printTag(exifData, "Exif.Photo.Flash", _("Flash"));
Packit Service 21b5d1
Packit Service 21b5d1
            // Flash bias
Packit Service 21b5d1
            printTag(exifData, Exiv2::flashBias, _("Flash bias"));
Packit Service 21b5d1
Packit Service 21b5d1
            // Actual focal length and 35 mm equivalent
Packit Service 21b5d1
            // Todo: Calculate 35 mm equivalent a la jhead
Packit Service 21b5d1
            Exiv2::ExifData::const_iterator md;
Packit Service 21b5d1
            printLabel(_("Focal length"));
Packit Service 21b5d1
            if (1 == printTag(exifData, "Exif.Photo.FocalLength")) {
Packit Service 21b5d1
                md = exifData.findKey(
Packit Service 21b5d1
                    Exiv2::ExifKey("Exif.Photo.FocalLengthIn35mmFilm"));
Packit Service 21b5d1
                if (md != exifData.end()) {
Packit Service 21b5d1
                    std::cout << " ("<< _("35 mm equivalent") << ": "
Packit Service 21b5d1
                              << md->print(&exifData) << ")";
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
            else {
Packit Service 21b5d1
                printTag(exifData, "Exif.Canon.FocalLength");
Packit Service 21b5d1
            }
Packit Service 21b5d1
            std::cout << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // Subject distance
Packit Service 21b5d1
        {
Packit Service 21b5d1
            printLabel(_("Subject distance"));
Packit Service 21b5d1
            bool done = 0 != printTag(exifData, "Exif.Photo.SubjectDistance");
Packit Service 21b5d1
            if (!done) {
Packit Service 21b5d1
                printTag(exifData, "Exif.CanonSi.SubjectDistance");
Packit Service 21b5d1
                printTag(exifData, "Exif.CanonFi.FocusDistanceLower");
Packit Service 21b5d1
                printTag(exifData, "Exif.CanonFi.FocusDistanceUpper");
Packit Service 21b5d1
            }
Packit Service 21b5d1
            std::cout << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // ISO speed
Packit Service 21b5d1
        printTag(exifData, Exiv2::isoSpeed, _("ISO speed"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Exposure mode
Packit Service 21b5d1
        printTag(exifData, Exiv2::exposureMode, _("Exposure mode"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Metering mode
Packit Service 21b5d1
        printTag(exifData, "Exif.Photo.MeteringMode", _("Metering mode"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Macro mode
Packit Service 21b5d1
        printTag(exifData, Exiv2::macroMode, _("Macro mode"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Image quality setting (compression)
Packit Service 21b5d1
        printTag(exifData, Exiv2::imageQuality, _("Image quality"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Exif Resolution
Packit Service 21b5d1
        {
Packit Service 21b5d1
            printLabel(_("Exif Resolution"));
Packit Service 21b5d1
            long xdim = 0;
Packit Service 21b5d1
            long ydim = 0;
Packit Service 21b5d1
            if (image->mimeType() == "image/tiff") {
Packit Service 21b5d1
                xdim = image->pixelWidth();
Packit Service 21b5d1
                ydim = image->pixelHeight();
Packit Service 21b5d1
            }
Packit Service 21b5d1
            else {
Packit Service 21b5d1
                Exiv2::ExifData::const_iterator md = exifData.findKey(Exiv2::ExifKey("Exif.Image.ImageWidth"));
Packit Service 21b5d1
                if (md == exifData.end()) {
Packit Service 21b5d1
                    md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension"));
Packit Service 21b5d1
                }
Packit Service 21b5d1
                if (md != exifData.end() && md->count() > 0) {
Packit Service 21b5d1
                    xdim = md->toLong();
Packit Service 21b5d1
                }
Packit Service 21b5d1
                md = exifData.findKey(Exiv2::ExifKey("Exif.Image.ImageLength"));
Packit Service 21b5d1
                if (md == exifData.end()) {
Packit Service 21b5d1
                    md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension"));
Packit Service 21b5d1
                }
Packit Service 21b5d1
                if (md != exifData.end() && md->count() > 0) {
Packit Service 21b5d1
                    ydim = md->toLong();
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (xdim != 0 && ydim != 0) {
Packit Service 21b5d1
                std::cout << xdim << " x " << ydim;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            std::cout << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // White balance
Packit Service 21b5d1
        printTag(exifData, Exiv2::whiteBalance, _("White balance"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Thumbnail
Packit Service 21b5d1
        printLabel(_("Thumbnail"));
Packit Service 21b5d1
        Exiv2::ExifThumbC exifThumb(exifData);
Packit Service 21b5d1
        std::string thumbExt = exifThumb.extension();
Packit Service 21b5d1
        if (thumbExt.empty()) {
Packit Service 21b5d1
            std::cout << _("None");
Packit Service 21b5d1
        }
Packit Service 21b5d1
        else {
Packit Service 21b5d1
            Exiv2::DataBuf buf = exifThumb.copy();
Packit Service 21b5d1
            if (buf.size_ == 0) {
Packit Service 21b5d1
                std::cout << _("None");
Packit Service 21b5d1
            }
Packit Service 21b5d1
            else {
Packit Service 21b5d1
                std::cout << exifThumb.mimeType() << ", "
Packit Service 21b5d1
                          << buf.size_ << " " << _("Bytes");
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        std::cout << std::endl;
Packit Service 21b5d1
Packit Service 21b5d1
        // Copyright
Packit Service 21b5d1
        printTag(exifData, "Exif.Image.Copyright", _("Copyright"));
Packit Service 21b5d1
Packit Service 21b5d1
        // Exif Comment
Packit Service 21b5d1
        printTag(exifData, "Exif.Photo.UserComment", _("Exif comment"));
Packit Service 21b5d1
        std::cout << std::endl;
Packit Service 21b5d1
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    } // Print::printSummary
Packit Service 21b5d1
Packit Service 21b5d1
    void Print::printLabel(const std::string& label) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::cout << std::setfill(' ') << std::left;
Packit Service 21b5d1
        if (Params::instance().files_.size() > 1) {
Packit Service 21b5d1
            std::cout << std::setw(20) << path_ << " ";
Packit Service 21b5d1
        }
Packit Service 21b5d1
        std::cout << std::make_pair( label, align_)
Packit Service 21b5d1
                  << ": ";
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Print::printTag(const Exiv2::ExifData& exifData,
Packit Service 21b5d1
                        const std::string& key,
Packit Service 21b5d1
                        const std::string& label) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        if (!label.empty()) {
Packit Service 21b5d1
            printLabel(label);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::ExifKey ek(key);
Packit Service 21b5d1
        Exiv2::ExifData::const_iterator md = exifData.findKey(ek);
Packit Service 21b5d1
        if (md != exifData.end()) {
Packit Service 21b5d1
            md->write(std::cout, &exifData);
Packit Service 21b5d1
            rc = 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (!label.empty()) std::cout << std::endl;
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // Print::printTag
Packit Service 21b5d1
Packit Service 21b5d1
    int Print::printTag(const Exiv2::ExifData& exifData,
Packit Service 21b5d1
                        EasyAccessFct easyAccessFct,
Packit Service 21b5d1
                        const std::string& label) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        if (!label.empty()) {
Packit Service 21b5d1
            printLabel(label);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::ExifData::const_iterator md = easyAccessFct(exifData);
Packit Service 21b5d1
        if (md != exifData.end()) {
Packit Service 21b5d1
            md->write(std::cout, &exifData);
Packit Service 21b5d1
            rc = 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (!label.empty()) std::cout << std::endl;
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // Print::printTag
Packit Service 21b5d1
Packit Service 21b5d1
    int Print::printList()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path_, true)) {
Packit Service 21b5d1
            std::cerr << path_
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        // Set defaults for metadata types and data columns
Packit Service 21b5d1
        if (Params::instance().printTags_ == Exiv2::mdNone) {
Packit Service 21b5d1
            Params::instance().printTags_ = Exiv2::mdExif | Exiv2::mdIptc | Exiv2::mdXmp;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ == 0) {
Packit Service 21b5d1
            Params::instance().printItems_ = Params::prKey | Params::prType | Params::prCount | Params::prTrans;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return printMetadata(image.get());
Packit Service 21b5d1
    } // Print::printList
Packit Service 21b5d1
Packit Service 21b5d1
    int Print::printMetadata(const Exiv2::Image* image)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        bool ret = false;
Packit Service 21b5d1
        bool noExif = false;
Packit Service 21b5d1
        if (Params::instance().printTags_ & Exiv2::mdExif) {
Packit Service 21b5d1
            const Exiv2::ExifData& exifData = image->exifData();
Packit Service 21b5d1
            for (Exiv2::ExifData::const_iterator md = exifData.begin();
Packit Service 21b5d1
                 md != exifData.end(); ++md) {
Packit Service 21b5d1
                ret |= printMetadatum(*md, image);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (exifData.empty()) noExif = true;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        bool noIptc = false;
Packit Service 21b5d1
        if (Params::instance().printTags_ & Exiv2::mdIptc) {
Packit Service 21b5d1
            const Exiv2::IptcData& iptcData = image->iptcData();
Packit Service 21b5d1
            for (Exiv2::IptcData::const_iterator md = iptcData.begin();
Packit Service 21b5d1
                 md != iptcData.end(); ++md) {
Packit Service 21b5d1
                ret |= printMetadatum(*md, image);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (iptcData.empty()) noIptc = true;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        bool noXmp = false;
Packit Service 21b5d1
        if (Params::instance().printTags_ & Exiv2::mdXmp) {
Packit Service 21b5d1
            const Exiv2::XmpData& xmpData = image->xmpData();
Packit Service 21b5d1
            for (Exiv2::XmpData::const_iterator md = xmpData.begin();
Packit Service 21b5d1
                 md != xmpData.end(); ++md) {
Packit Service 21b5d1
                ret |= printMetadatum(*md, image);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (xmpData.empty()) noXmp = true;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // With -v, inform about the absence of any (requested) type of metadata
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            if (noExif) std::cerr << path_ << ": " << _("No Exif data found in the file\n");
Packit Service 21b5d1
            if (noIptc) std::cerr << path_ << ": " << _("No IPTC data found in the file\n");
Packit Service 21b5d1
            if (noXmp)  std::cerr << path_ << ": " << _("No XMP data found in the file\n");
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // With -g or -K, return -3 if no matching tags were found
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        if ((!Params::instance().greps_.empty() || !Params::instance().keys_.empty()) && !ret) rc = 1;
Packit Service 21b5d1
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // Print::printMetadata
Packit Service 21b5d1
Packit Service 21b5d1
    bool Print::grepTag(const std::string& key)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        bool result=Params::instance().greps_.empty();
Packit Service 21b5d1
        for (Params::Greps::const_iterator g = Params::instance().greps_.begin();
Packit Service 21b5d1
                !result && g != Params::instance().greps_.end(); ++g)
Packit Service 21b5d1
        {
Packit Service 21b5d1
#if defined(EXV_HAVE_REGEX_H)
Packit Service 21b5d1
            result = regexec( &(*g), key.c_str(), 0, NULL, 0) == 0 ;
Packit Service 21b5d1
#else
Packit Service 21b5d1
            std::string Pattern(g->pattern_);
Packit Service 21b5d1
            std::string Key(key);
Packit Service 21b5d1
            if ( g->bIgnoreCase_ ) {
Packit Service 21b5d1
                // https://notfaq.wordpress.com/2007/08/04/cc-convert-string-to-upperlower-case/
Packit Service 21b5d1
                std::transform(Pattern.begin(), Pattern.end(),Pattern.begin(), ::tolower);
Packit Service 21b5d1
                std::transform(Key.begin()    , Key.end()    ,Key.begin()    , ::tolower);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            result = Key.find(Pattern) != std::string::npos;
Packit Service 21b5d1
#endif
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return result ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    bool Print::keyTag(const std::string& key)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        bool result=Params::instance().keys_.empty();
Packit Service 21b5d1
        for (Params::Keys::const_iterator k = Params::instance().keys_.begin();
Packit Service 21b5d1
                !result && k != Params::instance().keys_.end(); ++k)
Packit Service 21b5d1
        {
Packit Service 21b5d1
            result = key.compare(*k) == 0;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return result ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    bool Print::printMetadatum(const Exiv2::Metadatum& md, const Exiv2::Image* pImage)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!grepTag(md.key()))
Packit Service 21b5d1
            return false;
Packit Service 21b5d1
        if (!keyTag(md.key()))
Packit Service 21b5d1
            return false;
Packit Service 21b5d1
Packit Service 21b5d1
        if (Params::instance().unknown_ && md.tagName().substr(0, 2) == "0x") {
Packit Service 21b5d1
            return false;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        bool const manyFiles = Params::instance().files_.size() > 1;
Packit Service 21b5d1
        if (manyFiles) {
Packit Service 21b5d1
            std::cout << std::setfill(' ') << std::left << std::setw(20) << path_ << "  ";
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        bool first = true;
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prTag) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << md.tag();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prSet) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << "set";
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prGroup) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << std::setw(12) << std::setfill(' ') << std::left << md.groupName();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prKey) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << std::setfill(' ') << std::left << std::setw(44) << md.key();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prName) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << std::setw(27) << std::setfill(' ') << std::left << md.tagName();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prLabel) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << std::setw(30) << std::setfill(' ') << std::left << md.tagLabel();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prType) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << std::setw(9) << std::setfill(' ') << std::left;
Packit Service 21b5d1
            const char* tn = md.typeName();
Packit Service 21b5d1
            if (tn) {
Packit Service 21b5d1
                std::cout << tn;
Packit Service 21b5d1
            } else {
Packit Service 21b5d1
                std::ostringstream os;
Packit Service 21b5d1
                os << "0x" << std::setw(4) << std::setfill('0') << std::hex << md.typeId();
Packit Service 21b5d1
                std::cout << os.str();
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prCount) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << std::dec << std::setw(3) << std::setfill(' ') << std::right << md.count();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prSize) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << " ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            std::cout << std::dec << std::setw(3) << std::setfill(' ') << std::right << md.size();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prValue && md.size() > 0) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << "  ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            if (md.size() > 128 && Params::instance().binary_ &&
Packit Service 21b5d1
                (md.typeId() == Exiv2::undefined || md.typeId() == Exiv2::unsignedByte ||
Packit Service 21b5d1
                 md.typeId() == Exiv2::signedByte)) {
Packit Service 21b5d1
                std::cout << _("(Binary value suppressed)") << std::endl;
Packit Service 21b5d1
                return true;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            bool done = false;
Packit Service 21b5d1
            if (0 == strcmp(md.key().c_str(), "Exif.Photo.UserComment")) {
Packit Service 21b5d1
                const Exiv2::CommentValue* pcv = dynamic_cast<const Exiv2::CommentValue*>(&md.value());
Packit Service 21b5d1
                if (pcv) {
Packit Service 21b5d1
                    Exiv2::CommentValue::CharsetId csId = pcv->charsetId();
Packit Service 21b5d1
                    if (csId != Exiv2::CommentValue::undefined) {
Packit Service 21b5d1
                        std::cout << "charset=\"" << Exiv2::CommentValue::CharsetInfo::name(csId) << "\" ";
Packit Service 21b5d1
                    }
Packit Service 21b5d1
                    std::cout << pcv->comment(Params::instance().charset_.c_str());
Packit Service 21b5d1
                    done = true;
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (!done) {
Packit Service 21b5d1
                // #1114 - show negative values for SByte
Packit Service 21b5d1
                if (md.typeId() != Exiv2::signedByte) {
Packit Service 21b5d1
                    std::cout << std::dec << md.value();
Packit Service 21b5d1
                } else {
Packit Service 21b5d1
                    int value = md.value().toLong();
Packit Service 21b5d1
                    std::cout << std::dec << (value < 128 ? value : value - 256);
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prTrans) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << "  ";
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            if (Params::instance().binary_ &&
Packit Service 21b5d1
                (md.typeId() == Exiv2::undefined || md.typeId() == Exiv2::unsignedByte ||
Packit Service 21b5d1
                 md.typeId() == Exiv2::signedByte) &&
Packit Service 21b5d1
                md.size() > 128) {
Packit Service 21b5d1
                std::cout << _("(Binary value suppressed)") << std::endl;
Packit Service 21b5d1
                return true;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            bool done = false;
Packit Service 21b5d1
            if (0 == strcmp(md.key().c_str(), "Exif.Photo.UserComment")) {
Packit Service 21b5d1
                const Exiv2::CommentValue* pcv = dynamic_cast<const Exiv2::CommentValue*>(&md.value());
Packit Service 21b5d1
                if (pcv) {
Packit Service 21b5d1
                    std::cout << pcv->comment(Params::instance().charset_.c_str());
Packit Service 21b5d1
                    done = true;
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (!done)
Packit Service 21b5d1
                std::cout << std::dec << md.print(&pImage->exifData());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().printItems_ & Params::prHex) {
Packit Service 21b5d1
            if (!first)
Packit Service 21b5d1
                std::cout << std::endl;
Packit Service 21b5d1
            first = false;
Packit Service 21b5d1
            if (Params::instance().binary_ &&
Packit Service 21b5d1
                (md.typeId() == Exiv2::undefined || md.typeId() == Exiv2::unsignedByte ||
Packit Service 21b5d1
                 md.typeId() == Exiv2::signedByte) &&
Packit Service 21b5d1
                md.size() > 128) {
Packit Service 21b5d1
                std::cout << _("(Binary value suppressed)") << std::endl;
Packit Service 21b5d1
                return true;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            Exiv2::DataBuf buf(md.size());
Packit Service 21b5d1
            md.copy(buf.pData_, pImage->byteOrder());
Packit Service 21b5d1
            Exiv2::hexdump(std::cout, buf.pData_, buf.size_);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        std::cout << std::endl;
Packit Service 21b5d1
        return true;
Packit Service 21b5d1
    }  // Print::printMetadatum
Packit Service 21b5d1
Packit Service 21b5d1
    int Print::printComment()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path_, true)) {
Packit Service 21b5d1
            std::cerr << path_
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("JPEG comment") << ": ";
Packit Service 21b5d1
        }
Packit Service 21b5d1
        std::cout << image->comment() << std::endl;
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    } // Print::printComment
Packit Service 21b5d1
Packit Service 21b5d1
    int Print::printPreviewList()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path_, true)) {
Packit Service 21b5d1
            std::cerr << path_
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        bool const manyFiles = Params::instance().files_.size() > 1;
Packit Service 21b5d1
        int cnt = 0;
Packit Service 21b5d1
        Exiv2::PreviewManager pm(*image);
Packit Service 21b5d1
        Exiv2::PreviewPropertiesList list = pm.getPreviewProperties();
Packit Service 21b5d1
        for (Exiv2::PreviewPropertiesList::const_iterator pos = list.begin(); pos != list.end(); ++pos) {
Packit Service 21b5d1
            if (manyFiles) {
Packit Service 21b5d1
                std::cout << std::setfill(' ') << std::left << std::setw(20)
Packit Service 21b5d1
                          << path_ << "  ";
Packit Service 21b5d1
            }
Packit Service 21b5d1
            std::cout << _("Preview") << " " << ++cnt << ": "
Packit Service 21b5d1
                      << pos->mimeType_ << ", ";
Packit Service 21b5d1
            if (pos->width_ != 0 && pos->height_ != 0) {
Packit Service 21b5d1
                std::cout << pos->width_ << "x" << pos->height_ << " "
Packit Service 21b5d1
                          << _("pixels") << ", ";
Packit Service 21b5d1
            }
Packit Service 21b5d1
            std::cout << pos->size_ << " " << _("bytes") << "\n";
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    } // Print::printPreviewList
Packit Service 21b5d1
Packit Service 21b5d1
    Print::AutoPtr Print::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Print* Print::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new Print(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Rename::~Rename()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Rename::run(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
    try {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Timestamp ts;
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.read(path);
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        Exiv2::ExifData& exifData = image->exifData();
Packit Service 21b5d1
        if (exifData.empty()) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("No Exif data found in the file\n");
Packit Service 21b5d1
            return -3;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::ExifKey key("Exif.Photo.DateTimeOriginal");
Packit Service 21b5d1
        Exiv2::ExifData::iterator md = exifData.findKey(key);
Packit Service 21b5d1
        if (md == exifData.end()) {
Packit Service 21b5d1
            key = Exiv2::ExifKey("Exif.Image.DateTime");
Packit Service 21b5d1
            md = exifData.findKey(key);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (md == exifData.end()) {
Packit Service 21b5d1
            std::cerr << _("Neither tag") << " `Exif.Photo.DateTimeOriginal' "
Packit Service 21b5d1
                      << _("nor") << " `Exif.Image.DateTime' "
Packit Service 21b5d1
                      << _("found in the file") << " " << path << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        std::string v = md->toString();
Packit Service 21b5d1
        if (v.length() == 0 || v[0] == ' ') {
Packit Service 21b5d1
            std::cerr << _("Image file creation timestamp not set in the file")
Packit Service 21b5d1
                      << " " << path << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        struct tm tm;
Packit Service 21b5d1
        if (str2Tm(v, &tm) != 0) {
Packit Service 21b5d1
            std::cerr << _("Failed to parse timestamp") << " `" << v
Packit Service 21b5d1
                      << "' " << _("in the file") << " " << path << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (   Params::instance().timestamp_
Packit Service 21b5d1
            || Params::instance().timestampOnly_) {
Packit Service 21b5d1
            ts.read(&tm;;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        std::string newPath = path;
Packit Service 21b5d1
        if (Params::instance().timestampOnly_) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("Updating timestamp to") << " " << v << std::endl;
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        else {
Packit Service 21b5d1
            rc = renameFile(newPath, &tm;;
Packit Service 21b5d1
            if (rc == -1) return 0; // skip
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (   0 == rc
Packit Service 21b5d1
            && (   Params::instance().preserve_
Packit Service 21b5d1
                || Params::instance().timestamp_
Packit Service 21b5d1
                || Params::instance().timestampOnly_)) {
Packit Service 21b5d1
            ts.touch(newPath);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    catch(const Exiv2::AnyError& e)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::cerr << "Exiv2 exception in rename action for file " << path
Packit Service 21b5d1
                  << ":\n" << e << "\n";
Packit Service 21b5d1
        return 1;
Packit Service 21b5d1
    }} // Rename::run
Packit Service 21b5d1
Packit Service 21b5d1
    Rename::AutoPtr Rename::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Rename* Rename::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new Rename(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Erase::~Erase()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Erase::run(const std::string& path)
Packit Service 21b5d1
    try {
Packit Service 21b5d1
        path_ = path;
Packit Service 21b5d1
Packit Service 21b5d1
        if (!Exiv2::fileExists(path_, true)) {
Packit Service 21b5d1
            std::cerr << path_
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Timestamp ts;
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.read(path);
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        // Thumbnail must be before Exif
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        if (Params::instance().target_ & Params::ctThumb) {
Packit Service 21b5d1
            rc = eraseThumbnail(image.get());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (0 == rc && Params::instance().target_ & Params::ctExif) {
Packit Service 21b5d1
            rc = eraseExifData(image.get());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (0 == rc && Params::instance().target_ & Params::ctIptc) {
Packit Service 21b5d1
            rc = eraseIptcData(image.get());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (0 == rc && Params::instance().target_ & Params::ctComment) {
Packit Service 21b5d1
            rc = eraseComment(image.get());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (0 == rc && Params::instance().target_ & Params::ctXmp) {
Packit Service 21b5d1
            rc = eraseXmpData(image.get());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (0 == rc && Params::instance().target_ & Params::ctIccProfile) {
Packit Service 21b5d1
            rc = eraseIccProfile(image.get());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (0 == rc && Params::instance().target_ & Params::ctIptcRaw) {
Packit Service 21b5d1
            rc = printStructure(std::cout,Exiv2::kpsIptcErase,path_);
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        if (0 == rc) {
Packit Service 21b5d1
            image->writeMetadata();
Packit Service 21b5d1
            if (Params::instance().preserve_) ts.touch(path);
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    catch(const Exiv2::AnyError& e)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::cerr << "Exiv2 exception in erase action for file " << path
Packit Service 21b5d1
                  << ":\n" << e << "\n";
Packit Service 21b5d1
        return 1;
Packit Service 21b5d1
    } // Erase::run
Packit Service 21b5d1
Packit Service 21b5d1
    int Erase::eraseThumbnail(Exiv2::Image* image) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        Exiv2::ExifThumb exifThumb(image->exifData());
Packit Service 21b5d1
        std::string thumbExt = exifThumb.extension();
Packit Service 21b5d1
        if (thumbExt.empty()) {
Packit Service 21b5d1
            return 0;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        exifThumb.erase();
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("Erasing thumbnail data") << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Erase::eraseExifData(Exiv2::Image* image) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_ && image->exifData().count() > 0) {
Packit Service 21b5d1
            std::cout << _("Erasing Exif data from the file") << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        image->clearExifData();
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Erase::eraseIptcData(Exiv2::Image* image) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_ && image->iptcData().count() > 0) {
Packit Service 21b5d1
            std::cout << _("Erasing IPTC data from the file") << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        image->clearIptcData();
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Erase::eraseComment(Exiv2::Image* image) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_ && image->comment().size() > 0) {
Packit Service 21b5d1
            std::cout << _("Erasing JPEG comment from the file") << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        image->clearComment();
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Erase::eraseXmpData(Exiv2::Image* image) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_ && image->xmpData().count() > 0) {
Packit Service 21b5d1
            std::cout << _("Erasing XMP data from the file") << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        image->clearXmpData();                  // Quick fix for bug #612
Packit Service 21b5d1
        image->clearXmpPacket();
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    int Erase::eraseIccProfile(Exiv2::Image* image) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_ && image->iccProfileDefined() ) {
Packit Service 21b5d1
            std::cout << _("Erasing ICC Profile data from the file") << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        image->clearIccProfile();
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Erase::AutoPtr Erase::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Erase* Erase::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new Erase(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Extract::~Extract()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Extract::run(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        try {
Packit Service 21b5d1
            path_ = path;
Packit Service 21b5d1
            int rc = 0;
Packit Service 21b5d1
Packit Service 21b5d1
            bool bStdout = Params::instance().target_ & Params::ctStdInOut ? true : false;
Packit Service 21b5d1
            if (bStdout) {
Packit Service 21b5d1
                _setmode(_fileno(stdout), _O_BINARY);
Packit Service 21b5d1
            }
Packit Service 21b5d1
Packit Service 21b5d1
            if (Params::instance().target_ & Params::ctThumb) {
Packit Service 21b5d1
                rc = writeThumbnail();
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (!rc && Params::instance().target_ & Params::ctPreview) {
Packit Service 21b5d1
                rc = writePreviews();
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (!rc && Params::instance().target_ & Params::ctXmpSidecar) {
Packit Service 21b5d1
                std::string xmpPath = bStdout ? "-" : newFilePath(path_, ".xmp");
Packit Service 21b5d1
                if (dontOverwrite(xmpPath))
Packit Service 21b5d1
                    return 0;
Packit Service 21b5d1
                rc = metacopy(path_, xmpPath, Exiv2::ImageType::xmp, false);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (!rc && Params::instance().target_ & Params::ctIccProfile) {
Packit Service 21b5d1
                std::string iccPath = bStdout ? "-" : newFilePath(path_, ".icc");
Packit Service 21b5d1
                rc = writeIccProfile(iccPath);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (!rc
Packit Service 21b5d1
                && !(Params::instance().target_ & Params::ctXmpSidecar)
Packit Service 21b5d1
                && !(Params::instance().target_ & Params::ctThumb)
Packit Service 21b5d1
                && !(Params::instance().target_ & Params::ctPreview)
Packit Service 21b5d1
                && !(Params::instance().target_ & Params::ctIccProfile)) {
Packit Service 21b5d1
                std::string exvPath = bStdout ? "-" : newFilePath(path_, ".exv");
Packit Service 21b5d1
                if (dontOverwrite(exvPath))
Packit Service 21b5d1
                    return 0;
Packit Service 21b5d1
                rc = metacopy(path_, exvPath, Exiv2::ImageType::exv, false);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            return rc;
Packit Service 21b5d1
        } catch (const Exiv2::AnyError& e) {
Packit Service 21b5d1
            std::cerr << "Exiv2 exception in extract action for file " << path << ":\n" << e << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Extract::writeThumbnail() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path_, true)) {
Packit Service 21b5d1
            std::cerr << path_
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        Exiv2::ExifData& exifData = image->exifData();
Packit Service 21b5d1
        if (exifData.empty()) {
Packit Service 21b5d1
            std::cerr << path_
Packit Service 21b5d1
                      << ": " << _("No Exif data found in the file\n");
Packit Service 21b5d1
            return -3;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        Exiv2::ExifThumb exifThumb(exifData);
Packit Service 21b5d1
        std::string thumbExt = exifThumb.extension();
Packit Service 21b5d1
        if (thumbExt.empty()) {
Packit Service 21b5d1
            std::cerr << path_ << ": " << _("Image does not contain an Exif thumbnail\n");
Packit Service 21b5d1
        }
Packit Service 21b5d1
        else {
Packit Service 21b5d1
            std::string thumb = newFilePath(path_, "-thumb");
Packit Service 21b5d1
            std::string thumbPath = thumb + thumbExt;
Packit Service 21b5d1
            if (dontOverwrite(thumbPath)) return 0;
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                Exiv2::DataBuf buf = exifThumb.copy();
Packit Service 21b5d1
                if (buf.size_ != 0) {
Packit Service 21b5d1
                    std::cout << _("Writing thumbnail") << " (" << exifThumb.mimeType() << ", "
Packit Service 21b5d1
                              << buf.size_ << " " << _("Bytes") << ") " << _("to file") << " "
Packit Service 21b5d1
                              << thumbPath << std::endl;
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
            rc = exifThumb.writeFile(thumb);
Packit Service 21b5d1
            if (rc == 0) {
Packit Service 21b5d1
                std::cerr << path_ << ": " << _("Exif data doesn't contain a thumbnail\n");
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // Extract::writeThumbnail
Packit Service 21b5d1
Packit Service 21b5d1
    int Extract::writePreviews() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path_, true)) {
Packit Service 21b5d1
            std::cerr << path_
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::PreviewManager pvMgr(*image);
Packit Service 21b5d1
        Exiv2::PreviewPropertiesList pvList = pvMgr.getPreviewProperties();
Packit Service 21b5d1
Packit Service 21b5d1
        const Params::PreviewNumbers& numbers = Params::instance().previewNumbers_;
Packit Service 21b5d1
        for (Params::PreviewNumbers::const_iterator n = numbers.begin(); n != numbers.end(); ++n) {
Packit Service 21b5d1
            if (*n == 0) {
Packit Service 21b5d1
                // Write all previews
Packit Service 21b5d1
                for (int num = 0; num < static_cast<int>(pvList.size()); ++num) {
Packit Service 21b5d1
                    writePreviewFile(pvMgr.getPreviewImage(pvList[num]), num + 1);
Packit Service 21b5d1
                }
Packit Service 21b5d1
                break;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (*n > static_cast<int>(pvList.size())) {
Packit Service 21b5d1
                std::cerr << path_ << ": " << _("Image does not have preview")
Packit Service 21b5d1
                          << " " << *n << "\n";
Packit Service 21b5d1
                continue;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            writePreviewFile(pvMgr.getPreviewImage(pvList[*n - 1]), *n);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    } // Extract::writePreviews
Packit Service 21b5d1
Packit Service 21b5d1
    int Extract::writeIccProfile(const std::string& target) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        if (!Exiv2::fileExists(path_, true)) {
Packit Service 21b5d1
            std::cerr << path_
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            rc = -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        bool bStdout = target == "-" ;
Packit Service 21b5d1
Packit Service 21b5d1
        if ( rc == 0 ) {
Packit Service 21b5d1
            Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
Packit Service 21b5d1
            assert(image.get() != 0);
Packit Service 21b5d1
            image->readMetadata();
Packit Service 21b5d1
            if ( !image->iccProfileDefined() ) {
Packit Service 21b5d1
                std::cerr << _("No embedded iccProfile: ") << path_ << std::endl;
Packit Service 21b5d1
                rc = -2;
Packit Service 21b5d1
            } else {
Packit Service 21b5d1
Packit Service 21b5d1
                if ( bStdout ) { // -eC-
Packit Service 21b5d1
                    std::cout.write((const char*)image->iccProfile()->pData_,image->iccProfile()->size_);
Packit Service 21b5d1
                } else {
Packit Service 21b5d1
                    if (Params::instance().verbose_) {
Packit Service 21b5d1
                        std::cout << _("Writing iccProfile: ") << target << std::endl;
Packit Service 21b5d1
                    }
Packit Service 21b5d1
                    Exiv2::FileIo iccFile(target);
Packit Service 21b5d1
                    iccFile.open("wb") ;
Packit Service 21b5d1
                    iccFile.write(image->iccProfile()->pData_,image->iccProfile()->size_);
Packit Service 21b5d1
                    iccFile.close();
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // Extract::writeIccProfile
Packit Service 21b5d1
Packit Service 21b5d1
Packit Service 21b5d1
    void Extract::writePreviewFile(const Exiv2::PreviewImage& pvImg, int num) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::string pvFile = newFilePath(path_, "-preview") + Exiv2::toString(num);
Packit Service 21b5d1
        std::string pvPath = pvFile + pvImg.extension();
Packit Service 21b5d1
        if (dontOverwrite(pvPath)) return;
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("Writing preview") << " " << num << " ("
Packit Service 21b5d1
                      << pvImg.mimeType() << ", ";
Packit Service 21b5d1
            if (pvImg.width() != 0 && pvImg.height() != 0) {
Packit Service 21b5d1
                std::cout << pvImg.width() << "x" << pvImg.height() << " "
Packit Service 21b5d1
                          << _("pixels") << ", ";
Packit Service 21b5d1
            }
Packit Service 21b5d1
            std::cout << pvImg.size() << " " << _("bytes") << ") "
Packit Service 21b5d1
                      << _("to file") << " " << pvPath << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        long rc = pvImg.writeFile(pvFile);
Packit Service 21b5d1
        if (rc == 0) {
Packit Service 21b5d1
            std::cerr << path_ << ": " << _("Image does not have preview")
Packit Service 21b5d1
                      << " " << num << "\n";
Packit Service 21b5d1
        }
Packit Service 21b5d1
    } // Extract::writePreviewFile
Packit Service 21b5d1
Packit Service 21b5d1
    Extract::AutoPtr Extract::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Extract* Extract::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new Extract(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Insert::~Insert()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Insert::run(const std::string& path)
Packit Service 21b5d1
    try {
Packit Service 21b5d1
        // -i{tgt}-  reading from stdin?
Packit Service 21b5d1
        bool          bStdin = (Params::instance().target_ & Params::ctStdInOut)?true:false;
Packit Service 21b5d1
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        Timestamp ts;
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.read(path);
Packit Service 21b5d1
Packit Service 21b5d1
        if (Params::instance().target_ & Params::ctThumb) {
Packit Service 21b5d1
            rc = insertThumbnail(path);
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        if (  rc == 0 && !(Params::instance().target_ & Params::ctXmpRaw)
Packit Service 21b5d1
        && (  Params::instance().target_ & Params::ctExif
Packit Service 21b5d1
           || Params::instance().target_ & Params::ctIptc
Packit Service 21b5d1
           || Params::instance().target_ & Params::ctComment
Packit Service 21b5d1
           || Params::instance().target_ & Params::ctXmp
Packit Service 21b5d1
           )
Packit Service 21b5d1
        ) {
Packit Service 21b5d1
            std::string suffix = Params::instance().suffix_;
Packit Service 21b5d1
            if (suffix.empty()) suffix = ".exv";
Packit Service 21b5d1
            if (Params::instance().target_ & Params::ctXmpSidecar) suffix = ".xmp";
Packit Service 21b5d1
            std::string exvPath = bStdin ? "-" : newFilePath(path, suffix);
Packit Service 21b5d1
            rc = metacopy(exvPath, path, Exiv2::ImageType::none, true);
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        if (0 == rc && (Params::instance().target_ & (Params::ctXmpSidecar|Params::ctXmpRaw)) ) {
Packit Service 21b5d1
            std::string xmpPath = bStdin ? "-" : newFilePath(path,".xmp");
Packit Service 21b5d1
            rc = insertXmpPacket(path,xmpPath);
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        if (0 == rc && Params::instance().target_ & Params::ctIccProfile) {
Packit Service 21b5d1
            std::string iccPath = bStdin ? "-" : newFilePath(path,".icc");
Packit Service 21b5d1
            rc = insertIccProfile(path,iccPath);
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.touch(path);
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    catch(const Exiv2::AnyError& e)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::cerr << "Exiv2 exception in insert action for file " << path
Packit Service 21b5d1
                  << ":\n" << e << "\n";
Packit Service 21b5d1
        return 1;
Packit Service 21b5d1
    } // Insert::run
Packit Service 21b5d1
Packit Service 21b5d1
    int Insert::insertXmpPacket(const std::string& path,const std::string& xmpPath) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        int  rc     = 0;
Packit Service 21b5d1
        bool bStdin = xmpPath == "-" ;
Packit Service 21b5d1
        if ( bStdin ) {
Packit Service 21b5d1
            Exiv2::DataBuf              xmpBlob;
Packit Service 21b5d1
            Params::instance().getStdin(xmpBlob);
Packit Service 21b5d1
            rc   = insertXmpPacket(path,xmpBlob,true);
Packit Service 21b5d1
        } else {
Packit Service 21b5d1
            if (!Exiv2::fileExists(xmpPath, true)) {
Packit Service 21b5d1
                std::cerr << xmpPath
Packit Service 21b5d1
                          << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
                rc = -1;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (rc == 0 && !Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
                std::cerr << path
Packit Service 21b5d1
                          << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
                rc = -1;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if ( rc == 0 ) {
Packit Service 21b5d1
                Exiv2::DataBuf xmpBlob = Exiv2::readFile(xmpPath);
Packit Service 21b5d1
                rc = insertXmpPacket(path,xmpBlob);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
Packit Service 21b5d1
    } // Insert::insertXmpPacket
Packit Service 21b5d1
Packit Service 21b5d1
    int Insert::insertXmpPacket(const std::string& path,const Exiv2::DataBuf& xmpBlob,bool usePacket) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::string xmpPacket;
Packit Service 21b5d1
        for ( long i = 0 ; i < xmpBlob.size_ ; i++ ) {
Packit Service 21b5d1
            xmpPacket += (char) xmpBlob.pData_[i];
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        image->clearXmpData();
Packit Service 21b5d1
        image->setXmpPacket(xmpPacket);
Packit Service 21b5d1
        image->writeXmpFromPacket(usePacket);
Packit Service 21b5d1
        image->writeMetadata();
Packit Service 21b5d1
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Insert::insertIccProfile(const std::string& path,const std::string& iccPath) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        // for path "foo.XXX", do a binary copy of "foo.icc"
Packit Service 21b5d1
        std::string iccProfilePath = newFilePath(path, ".icc");
Packit Service 21b5d1
        if ( iccPath == "-" ) {
Packit Service 21b5d1
            Exiv2::DataBuf              iccProfile ;
Packit Service 21b5d1
            Params::instance().getStdin(iccProfile);
Packit Service 21b5d1
            rc =  insertIccProfile(path,iccProfile);
Packit Service 21b5d1
        } else {
Packit Service 21b5d1
            if (!Exiv2::fileExists(iccProfilePath, true)) {
Packit Service 21b5d1
                std::cerr << iccProfilePath
Packit Service 21b5d1
                          << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
                rc = -1;
Packit Service 21b5d1
            } else {
Packit Service 21b5d1
                Exiv2::DataBuf iccProfile = Exiv2::readFile(iccPath);
Packit Service 21b5d1
                rc = insertIccProfile(path,iccProfile);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // Insert::insertIccProfile
Packit Service 21b5d1
Packit Service 21b5d1
    int Insert::insertIccProfile(const std::string& path,Exiv2::DataBuf& iccProfileBlob) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        // test path exists
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            rc=-1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // read in the metadata
Packit Service 21b5d1
        if ( rc == 0 ) {
Packit Service 21b5d1
            Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
            assert(image.get() != 0);
Packit Service 21b5d1
            image->readMetadata();
Packit Service 21b5d1
            // clear existing profile, assign the blob and rewrite image
Packit Service 21b5d1
            image->clearIccProfile();
Packit Service 21b5d1
            if ( iccProfileBlob.size_ ) {
Packit Service 21b5d1
                image->setIccProfile(iccProfileBlob);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            image->writeMetadata();
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // Insert::insertIccProfile
Packit Service 21b5d1
Packit Service 21b5d1
    int Insert::insertThumbnail(const std::string& path) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::string thumbPath = newFilePath(path, "-thumb.jpg");
Packit Service 21b5d1
        if (!Exiv2::fileExists(thumbPath, true)) {
Packit Service 21b5d1
            std::cerr << thumbPath
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        Exiv2::ExifThumb exifThumb(image->exifData());
Packit Service 21b5d1
        exifThumb.setJpegThumbnail(thumbPath);
Packit Service 21b5d1
        image->writeMetadata();
Packit Service 21b5d1
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    } // Insert::insertThumbnail
Packit Service 21b5d1
Packit Service 21b5d1
    Insert::AutoPtr Insert::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Insert* Insert::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new Insert(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Modify::~Modify()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Modify::run(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
    try {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Timestamp ts;
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.read(path);
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
Packit Service 21b5d1
        int rc = applyCommands(image.get());
Packit Service 21b5d1
Packit Service 21b5d1
        // Save both exif and iptc metadata
Packit Service 21b5d1
        image->writeMetadata();
Packit Service 21b5d1
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.touch(path);
Packit Service 21b5d1
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    catch(const Exiv2::AnyError& e)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::cerr << "Exiv2 exception in modify action for file " << path
Packit Service 21b5d1
                  << ":\n" << e << "\n";
Packit Service 21b5d1
        return 1;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    } // Modify::run
Packit Service 21b5d1
Packit Service 21b5d1
    int Modify::applyCommands(Exiv2::Image* pImage)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!Params::instance().jpegComment_.empty()) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("Setting JPEG comment") << " '"
Packit Service 21b5d1
                          << Params::instance().jpegComment_
Packit Service 21b5d1
                          << "'"
Packit Service 21b5d1
                          << std::endl;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            pImage->setComment(Params::instance().jpegComment_);
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // loop through command table and apply each command
Packit Service 21b5d1
        ModifyCmds& modifyCmds = Params::instance().modifyCmds_;
Packit Service 21b5d1
        ModifyCmds::const_iterator i = modifyCmds.begin();
Packit Service 21b5d1
        ModifyCmds::const_iterator end = modifyCmds.end();
Packit Service 21b5d1
        int rc = 0;
Packit Service 21b5d1
        int ret = 0;
Packit Service 21b5d1
        for (; i != end; ++i) {
Packit Service 21b5d1
            switch (i->cmdId_) {
Packit Service 21b5d1
            case add:
Packit Service 21b5d1
                ret = addMetadatum(pImage, *i);
Packit Service 21b5d1
                if (rc == 0) rc = ret;
Packit Service 21b5d1
                break;
Packit Service 21b5d1
            case set:
Packit Service 21b5d1
                ret = setMetadatum(pImage, *i);
Packit Service 21b5d1
                if (rc == 0) rc = ret;
Packit Service 21b5d1
                break;
Packit Service 21b5d1
            case del:
Packit Service 21b5d1
                delMetadatum(pImage, *i);
Packit Service 21b5d1
                break;
Packit Service 21b5d1
            case reg:
Packit Service 21b5d1
                regNamespace(*i);
Packit Service 21b5d1
                break;
Packit Service 21b5d1
            case invalidCmdId:
Packit Service 21b5d1
                assert(invalidCmdId == i->cmdId_);
Packit Service 21b5d1
                break;
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // Modify::applyCommands
Packit Service 21b5d1
Packit Service 21b5d1
    int Modify::addMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("Add") << " " << modifyCmd.key_ << " \""
Packit Service 21b5d1
                      << modifyCmd.value_ << "\" ("
Packit Service 21b5d1
                      << Exiv2::TypeInfo::typeName(modifyCmd.typeId_)
Packit Service 21b5d1
                      << ")" << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::ExifData& exifData = pImage->exifData();
Packit Service 21b5d1
        Exiv2::IptcData& iptcData = pImage->iptcData();
Packit Service 21b5d1
        Exiv2::XmpData&  xmpData  = pImage->xmpData();
Packit Service 21b5d1
        Exiv2::Value::AutoPtr value = Exiv2::Value::create(modifyCmd.typeId_);
Packit Service 21b5d1
        int rc = value->read(modifyCmd.value_);
Packit Service 21b5d1
        if (0 == rc) {
Packit Service 21b5d1
            if (modifyCmd.metadataId_ == exif) {
Packit Service 21b5d1
                exifData.add(Exiv2::ExifKey(modifyCmd.key_), value.get());
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (modifyCmd.metadataId_ == iptc) {
Packit Service 21b5d1
                iptcData.add(Exiv2::IptcKey(modifyCmd.key_), value.get());
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (modifyCmd.metadataId_ == xmp) {
Packit Service 21b5d1
                xmpData.add(Exiv2::XmpKey(modifyCmd.key_), value.get());
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        else {
Packit Service 21b5d1
            std::cerr << _("Warning") << ": " << modifyCmd.key_ << ": "
Packit Service 21b5d1
                      << _("Failed to read") << " "
Packit Service 21b5d1
                      << Exiv2::TypeInfo::typeName(value->typeId())
Packit Service 21b5d1
                      << " " << _("value")
Packit Service 21b5d1
                      << " \"" << modifyCmd.value_ << "\"\n";
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    // This function looks rather complex because we try to avoid adding an
Packit Service 21b5d1
    // empty metadatum if reading the value fails
Packit Service 21b5d1
    int Modify::setMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("Set") << " " << modifyCmd.key_ << " \""
Packit Service 21b5d1
                      << modifyCmd.value_ << "\" ("
Packit Service 21b5d1
                      << Exiv2::TypeInfo::typeName(modifyCmd.typeId_)
Packit Service 21b5d1
                      << ")" << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::ExifData& exifData = pImage->exifData();
Packit Service 21b5d1
        Exiv2::IptcData& iptcData = pImage->iptcData();
Packit Service 21b5d1
        Exiv2::XmpData&  xmpData  = pImage->xmpData();
Packit Service 21b5d1
        Exiv2::Metadatum* metadatum = 0;
Packit Service 21b5d1
        if (modifyCmd.metadataId_ == exif) {
Packit Service 21b5d1
            Exiv2::ExifData::iterator pos =
Packit Service 21b5d1
                exifData.findKey(Exiv2::ExifKey(modifyCmd.key_));
Packit Service 21b5d1
            if (pos != exifData.end()) {
Packit Service 21b5d1
                metadatum = &(*pos);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (modifyCmd.metadataId_ == iptc) {
Packit Service 21b5d1
            Exiv2::IptcData::iterator pos =
Packit Service 21b5d1
                iptcData.findKey(Exiv2::IptcKey(modifyCmd.key_));
Packit Service 21b5d1
            if (pos != iptcData.end()) {
Packit Service 21b5d1
                metadatum = &(*pos);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (modifyCmd.metadataId_ == xmp) {
Packit Service 21b5d1
            Exiv2::XmpData::iterator pos =
Packit Service 21b5d1
                xmpData.findKey(Exiv2::XmpKey(modifyCmd.key_));
Packit Service 21b5d1
            if (pos != xmpData.end()) {
Packit Service 21b5d1
                metadatum = &(*pos);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        // If a type was explicitly requested, use it; else
Packit Service 21b5d1
        // use the current type of the metadatum, if any;
Packit Service 21b5d1
        // or the default type
Packit Service 21b5d1
        Exiv2::Value::AutoPtr value;
Packit Service 21b5d1
        if (metadatum) {
Packit Service 21b5d1
            value = metadatum->getValue();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (   value.get() == 0
Packit Service 21b5d1
            || (   modifyCmd.explicitType_
Packit Service 21b5d1
                && modifyCmd.typeId_ != value->typeId())) {
Packit Service 21b5d1
            value = Exiv2::Value::create(modifyCmd.typeId_);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        int rc = value->read(modifyCmd.value_);
Packit Service 21b5d1
        if (0 == rc) {
Packit Service 21b5d1
            if (metadatum) {
Packit Service 21b5d1
                metadatum->setValue(value.get());
Packit Service 21b5d1
            }
Packit Service 21b5d1
            else {
Packit Service 21b5d1
                if (modifyCmd.metadataId_ == exif) {
Packit Service 21b5d1
                    exifData.add(Exiv2::ExifKey(modifyCmd.key_), value.get());
Packit Service 21b5d1
                }
Packit Service 21b5d1
                if (modifyCmd.metadataId_ == iptc) {
Packit Service 21b5d1
                    iptcData.add(Exiv2::IptcKey(modifyCmd.key_), value.get());
Packit Service 21b5d1
                }
Packit Service 21b5d1
                if (modifyCmd.metadataId_ == xmp) {
Packit Service 21b5d1
                    xmpData.add(Exiv2::XmpKey(modifyCmd.key_), value.get());
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        else {
Packit Service 21b5d1
            std::cerr << _("Warning") << ": " << modifyCmd.key_ << ": "
Packit Service 21b5d1
                      << _("Failed to read") << " "
Packit Service 21b5d1
                      << Exiv2::TypeInfo::typeName(value->typeId())
Packit Service 21b5d1
                      << " " << _("value")
Packit Service 21b5d1
                      << " \"" << modifyCmd.value_ << "\"\n";
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Modify::delMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("Del") << " " << modifyCmd.key_ << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::ExifData& exifData = pImage->exifData();
Packit Service 21b5d1
        Exiv2::IptcData& iptcData = pImage->iptcData();
Packit Service 21b5d1
        Exiv2::XmpData&  xmpData  = pImage->xmpData();
Packit Service 21b5d1
        if (modifyCmd.metadataId_ == exif) {
Packit Service 21b5d1
            Exiv2::ExifData::iterator pos;
Packit Service 21b5d1
            Exiv2::ExifKey exifKey = Exiv2::ExifKey(modifyCmd.key_);
Packit Service 21b5d1
            while((pos = exifData.findKey(exifKey)) != exifData.end()) {
Packit Service 21b5d1
                exifData.erase(pos);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (modifyCmd.metadataId_ == iptc) {
Packit Service 21b5d1
            Exiv2::IptcData::iterator pos;
Packit Service 21b5d1
            Exiv2::IptcKey iptcKey = Exiv2::IptcKey(modifyCmd.key_);
Packit Service 21b5d1
            while((pos = iptcData.findKey(iptcKey)) != iptcData.end()) {
Packit Service 21b5d1
                iptcData.erase(pos);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (modifyCmd.metadataId_ == xmp) {
Packit Service 21b5d1
            Exiv2::XmpData::iterator pos;
Packit Service 21b5d1
            Exiv2::XmpKey xmpKey = Exiv2::XmpKey(modifyCmd.key_);
Packit Service 21b5d1
            if((pos = xmpData.findKey(xmpKey)) != xmpData.end()) {
Packit Service 21b5d1
                xmpData.eraseFamily(pos);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Modify::regNamespace(const ModifyCmd& modifyCmd)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("Reg ") << modifyCmd.key_ << "=\""
Packit Service 21b5d1
                      << modifyCmd.value_ << "\"" << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::XmpProperties::registerNs(modifyCmd.value_, modifyCmd.key_);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Modify::AutoPtr Modify::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Modify* Modify::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new Modify(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Adjust::~Adjust()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Adjust::run(const std::string& path)
Packit Service 21b5d1
    try {
Packit Service 21b5d1
        adjustment_      = Params::instance().adjustment_;
Packit Service 21b5d1
        yearAdjustment_  = Params::instance().yodAdjust_[Params::yodYear].adjustment_;
Packit Service 21b5d1
        monthAdjustment_ = Params::instance().yodAdjust_[Params::yodMonth].adjustment_;
Packit Service 21b5d1
        dayAdjustment_   = Params::instance().yodAdjust_[Params::yodDay].adjustment_;
Packit Service 21b5d1
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Timestamp ts;
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.read(path);
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        Exiv2::ExifData& exifData = image->exifData();
Packit Service 21b5d1
        if (exifData.empty()) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("No Exif data found in the file\n");
Packit Service 21b5d1
            return -3;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        int rc = adjustDateTime(exifData, "Exif.Image.DateTime", path);
Packit Service 21b5d1
        rc += adjustDateTime(exifData, "Exif.Photo.DateTimeOriginal", path);
Packit Service 21b5d1
        rc += adjustDateTime(exifData, "Exif.Image.DateTimeOriginal", path);
Packit Service 21b5d1
        rc += adjustDateTime(exifData, "Exif.Photo.DateTimeDigitized", path);
Packit Service 21b5d1
Packit Service 21b5d1
        if (rc == 0 ) {
Packit Service 21b5d1
            image->writeMetadata();
Packit Service 21b5d1
            if (Params::instance().preserve_) ts.touch(path);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc?1:0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    catch(const Exiv2::AnyError& e)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::cerr << "Exiv2 exception in adjust action for file " << path
Packit Service 21b5d1
                  << ":\n" << e << "\n";
Packit Service 21b5d1
        return 1;
Packit Service 21b5d1
    } // Adjust::run
Packit Service 21b5d1
Packit Service 21b5d1
    Adjust::AutoPtr Adjust::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Adjust* Adjust::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new Adjust(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Adjust::adjustDateTime(Exiv2::ExifData& exifData,
Packit Service 21b5d1
                               const std::string& key,
Packit Service 21b5d1
                               const std::string& path) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        Exiv2::ExifKey ek(key);
Packit Service 21b5d1
        Exiv2::ExifData::iterator md = exifData.findKey(ek);
Packit Service 21b5d1
        if (md == exifData.end()) {
Packit Service 21b5d1
            // Key not found. That's ok, we do nothing.
Packit Service 21b5d1
            return 0;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        std::string timeStr = md->toString();
Packit Service 21b5d1
        if (timeStr == "" || timeStr[0] == ' ') {
Packit Service 21b5d1
            std::cerr << path << ": " << _("Timestamp of metadatum with key") << " `"
Packit Service 21b5d1
                      << ek << "' " << _("not set\n");
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            bool comma = false;
Packit Service 21b5d1
            std::cout << _("Adjusting") << " `" << ek << "' " << _("by");
Packit Service 21b5d1
            if (yearAdjustment_ != 0) {
Packit Service 21b5d1
                std::cout << (yearAdjustment_ < 0 ? " " : " +") << yearAdjustment_ << " ";
Packit Service 21b5d1
                if (yearAdjustment_ < -1 || yearAdjustment_ > 1) {
Packit Service 21b5d1
                    std::cout << _("years");
Packit Service 21b5d1
                }
Packit Service 21b5d1
                else {
Packit Service 21b5d1
                    std::cout << _("year");
Packit Service 21b5d1
                }
Packit Service 21b5d1
                comma = true;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (monthAdjustment_ != 0) {
Packit Service 21b5d1
                if (comma) std::cout << ",";
Packit Service 21b5d1
                std::cout << (monthAdjustment_ < 0 ? " " : " +") << monthAdjustment_ << " ";
Packit Service 21b5d1
                if (monthAdjustment_ < -1 || monthAdjustment_ > 1) {
Packit Service 21b5d1
                    std::cout << _("months");
Packit Service 21b5d1
                }
Packit Service 21b5d1
                else {
Packit Service 21b5d1
                    std::cout << _("month");
Packit Service 21b5d1
                }
Packit Service 21b5d1
                comma = true;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (dayAdjustment_ != 0) {
Packit Service 21b5d1
                if (comma) std::cout << ",";
Packit Service 21b5d1
                std::cout << (dayAdjustment_ < 0 ? " " : " +") << dayAdjustment_ << " ";
Packit Service 21b5d1
                if (dayAdjustment_ < -1 || dayAdjustment_ > 1) {
Packit Service 21b5d1
                    std::cout << _("days");
Packit Service 21b5d1
                }
Packit Service 21b5d1
                else {
Packit Service 21b5d1
                    std::cout << _("day");
Packit Service 21b5d1
                }
Packit Service 21b5d1
                comma = true;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if (adjustment_ != 0) {
Packit Service 21b5d1
                if (comma) std::cout << ",";
Packit Service 21b5d1
                std::cout << " " << adjustment_ << _("s");
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        struct tm tm;
Packit Service 21b5d1
        if (str2Tm(timeStr, &tm) != 0) {
Packit Service 21b5d1
            if (Params::instance().verbose_) std::cout << std::endl;
Packit Service 21b5d1
            std::cerr << path << ": " << _("Failed to parse timestamp") << " `"
Packit Service 21b5d1
                      << timeStr << "'\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        const long monOverflow = (tm.tm_mon + monthAdjustment_) / 12;
Packit Service 21b5d1
        tm.tm_mon = (tm.tm_mon + monthAdjustment_) % 12;
Packit Service 21b5d1
        tm.tm_year += yearAdjustment_ + monOverflow;
Packit Service 21b5d1
        // Let's not create files with non-4-digit years, we can't read them.
Packit Service 21b5d1
        if (tm.tm_year > 9999 - 1900 || tm.tm_year < 1000 - 1900) {
Packit Service 21b5d1
            if (Params::instance().verbose_) std::cout << std::endl;
Packit Service 21b5d1
            std::cerr << path << ": " << _("Can't adjust timestamp by") << " "
Packit Service 21b5d1
                      << yearAdjustment_ + monOverflow
Packit Service 21b5d1
                      << " " << _("years") << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        time_t time = mktime(&tm;;
Packit Service 21b5d1
        time += adjustment_ + dayAdjustment_ * 86400;
Packit Service 21b5d1
        timeStr = time2Str(time);
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << " " << _("to") << " " << timeStr << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        md->setValue(timeStr);
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    } // Adjust::adjustDateTime
Packit Service 21b5d1
Packit Service 21b5d1
    FixIso::~FixIso()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int FixIso::run(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
    try {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " <<_("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Timestamp ts;
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.read(path);
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        Exiv2::ExifData& exifData = image->exifData();
Packit Service 21b5d1
        if (exifData.empty()) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("No Exif data found in the file\n");
Packit Service 21b5d1
            return -3;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::ExifData::const_iterator md = Exiv2::isoSpeed(exifData);
Packit Service 21b5d1
        if (md != exifData.end()) {
Packit Service 21b5d1
            if (strcmp(md->key().c_str(), "Exif.Photo.ISOSpeedRatings") == 0) {
Packit Service 21b5d1
                if (Params::instance().verbose_) {
Packit Service 21b5d1
                    std::cout << _("Standard Exif ISO tag exists; not modified\n");
Packit Service 21b5d1
                }
Packit Service 21b5d1
                return 0;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            // Copy the proprietary tag to the standard place
Packit Service 21b5d1
            std::ostringstream os;
Packit Service 21b5d1
            md->write(os, &exifData);
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("Setting Exif ISO value to") << " " << os.str() << "\n";
Packit Service 21b5d1
            }
Packit Service 21b5d1
            exifData["Exif.Photo.ISOSpeedRatings"] = os.str();
Packit Service 21b5d1
        }
Packit Service 21b5d1
        image->writeMetadata();
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.touch(path);
Packit Service 21b5d1
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    catch(const Exiv2::AnyError& e)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::cerr << "Exiv2 exception in fixiso action for file " << path
Packit Service 21b5d1
                  << ":\n" << e << "\n";
Packit Service 21b5d1
        return 1;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    } // FixIso::run
Packit Service 21b5d1
Packit Service 21b5d1
    FixIso::AutoPtr FixIso::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    FixIso* FixIso::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new FixIso(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    FixCom::~FixCom()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int FixCom::run(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
    try {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " <<_("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Timestamp ts;
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.read(path);
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->readMetadata();
Packit Service 21b5d1
        Exiv2::ExifData& exifData = image->exifData();
Packit Service 21b5d1
        if (exifData.empty()) {
Packit Service 21b5d1
            std::cerr << path
Packit Service 21b5d1
                      << ": " << _("No Exif data found in the file\n");
Packit Service 21b5d1
            return -3;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::ExifData::iterator pos = exifData.findKey(Exiv2::ExifKey("Exif.Photo.UserComment"));
Packit Service 21b5d1
        if (pos == exifData.end()) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("No Exif user comment found") << "\n";
Packit Service 21b5d1
            }
Packit Service 21b5d1
            return 0;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Value::AutoPtr v = pos->getValue();
Packit Service 21b5d1
        const Exiv2::CommentValue* pcv = dynamic_cast<const Exiv2::CommentValue*>(v.get());
Packit Service 21b5d1
        if (!pcv) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("Found Exif user comment with unexpected value type") << "\n";
Packit Service 21b5d1
            }
Packit Service 21b5d1
            return 0;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::CommentValue::CharsetId csId = pcv->charsetId();
Packit Service 21b5d1
        if (csId != Exiv2::CommentValue::unicode) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("No Exif UNICODE user comment found") << "\n";
Packit Service 21b5d1
            }
Packit Service 21b5d1
            return 0;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        std::string comment = pcv->comment(Params::instance().charset_.c_str());
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("Setting Exif UNICODE user comment to") << " \"" << comment << "\"\n";
Packit Service 21b5d1
        }
Packit Service 21b5d1
        comment = std::string("charset=\"") + Exiv2::CommentValue::CharsetInfo::name(csId) + "\" " + comment;
Packit Service 21b5d1
        // Remove BOM and convert value from source charset to UCS-2, but keep byte order
Packit Service 21b5d1
        pos->setValue(comment);
Packit Service 21b5d1
        image->writeMetadata();
Packit Service 21b5d1
        if (Params::instance().preserve_) ts.touch(path);
Packit Service 21b5d1
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    catch(const Exiv2::AnyError& e)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::cerr << "Exiv2 exception in fixcom action for file " << path
Packit Service 21b5d1
                  << ":\n" << e << "\n";
Packit Service 21b5d1
        return 1;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    } // FixCom::run
Packit Service 21b5d1
Packit Service 21b5d1
    FixCom::AutoPtr FixCom::clone() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return AutoPtr(clone_());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    FixCom* FixCom::clone_() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return new FixCom(*this);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
}                                       // namespace Action
Packit Service 21b5d1
Packit Service 21b5d1
// *****************************************************************************
Packit Service 21b5d1
// local definitions
Packit Service 21b5d1
namespace {
Packit Service 21b5d1
Packit Service 21b5d1
    //! @cond IGNORE
Packit Service 21b5d1
    int Timestamp::read(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        struct stat buf;
Packit Service 21b5d1
        int rc = stat(path.c_str(), &buf;;
Packit Service 21b5d1
        if (0 == rc) {
Packit Service 21b5d1
            actime_  = buf.st_atime;
Packit Service 21b5d1
            modtime_ = buf.st_mtime;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Timestamp::read(struct tm* tm)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        int rc = 1;
Packit Service 21b5d1
        time_t t = mktime(tm); // interpret tm according to current timezone settings
Packit Service 21b5d1
        if (t != (time_t)-1) {
Packit Service 21b5d1
            rc = 0;
Packit Service 21b5d1
            actime_  = t;
Packit Service 21b5d1
            modtime_ = t;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Timestamp::touch(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (0 == actime_) return 1;
Packit Service 21b5d1
        struct utimbuf buf;
Packit Service 21b5d1
        buf.actime = actime_;
Packit Service 21b5d1
        buf.modtime = modtime_;
Packit Service 21b5d1
        return utime(path.c_str(), &buf;;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    //! @endcond
Packit Service 21b5d1
Packit Service 21b5d1
    int str2Tm(const std::string& timeStr, struct tm* tm)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (timeStr.length() == 0 || timeStr[0] == ' ') return 1;
Packit Service 21b5d1
        if (timeStr.length() < 19) return 2;
Packit Service 21b5d1
        if (   timeStr[4]  != ':' || timeStr[7]  != ':' || timeStr[10] != ' '
Packit Service 21b5d1
            || timeStr[13] != ':' || timeStr[16] != ':') return 3;
Packit Service 21b5d1
        if (0 == tm) return 4;
Packit Service 21b5d1
        std::memset(tm, 0x0, sizeof(struct tm));
Packit Service 21b5d1
        tm->tm_isdst = -1;
Packit Service 21b5d1
Packit Service 21b5d1
        long tmp;
Packit Service 21b5d1
        if (!Util::strtol(timeStr.substr(0,4).c_str(), tmp)) return 5;
Packit Service 21b5d1
        tm->tm_year = tmp - 1900;
Packit Service 21b5d1
        if (!Util::strtol(timeStr.substr(5,2).c_str(), tmp)) return 6;
Packit Service 21b5d1
        tm->tm_mon = tmp - 1;
Packit Service 21b5d1
        if (!Util::strtol(timeStr.substr(8,2).c_str(), tmp)) return 7;
Packit Service 21b5d1
        tm->tm_mday = tmp;
Packit Service 21b5d1
        if (!Util::strtol(timeStr.substr(11,2).c_str(), tmp)) return 8;
Packit Service 21b5d1
        tm->tm_hour = tmp;
Packit Service 21b5d1
        if (!Util::strtol(timeStr.substr(14,2).c_str(), tmp)) return 9;
Packit Service 21b5d1
        tm->tm_min = tmp;
Packit Service 21b5d1
        if (!Util::strtol(timeStr.substr(17,2).c_str(), tmp)) return 10;
Packit Service 21b5d1
        tm->tm_sec = tmp;
Packit Service 21b5d1
Packit Service 21b5d1
        // Conversions to set remaining fields of the tm structure
Packit Service 21b5d1
        if (mktime(tm) == (time_t)-1) return 11;
Packit Service 21b5d1
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    } // str2Tm
Packit Service 21b5d1
Packit Service 21b5d1
    std::string time2Str(time_t time)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        struct tm* tm = localtime(&time);
Packit Service 21b5d1
        return tm2Str(tm);
Packit Service 21b5d1
    } // time2Str
Packit Service 21b5d1
Packit Service 21b5d1
    std::string tm2Str(const struct tm* tm)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (0 == tm) return "";
Packit Service 21b5d1
Packit Service 21b5d1
        std::ostringstream os;
Packit Service 21b5d1
        os << std::setfill('0')
Packit Service 21b5d1
           << tm->tm_year + 1900 << ":"
Packit Service 21b5d1
           << std::setw(2) << tm->tm_mon + 1 << ":"
Packit Service 21b5d1
           << std::setw(2) << tm->tm_mday << " "
Packit Service 21b5d1
           << std::setw(2) << tm->tm_hour << ":"
Packit Service 21b5d1
           << std::setw(2) << tm->tm_min << ":"
Packit Service 21b5d1
           << std::setw(2) << tm->tm_sec;
Packit Service 21b5d1
Packit Service 21b5d1
        return os.str();
Packit Service 21b5d1
    } // tm2Str
Packit Service 21b5d1
Packit Service 21b5d1
// use static CS/MUTEX to make temporaryPath() thread safe
Packit Service 21b5d1
#if defined(_MSC_VER) || defined(__MINGW__)
Packit Service 21b5d1
 static CRITICAL_SECTION cs;
Packit Service 21b5d1
#else
Packit Service 21b5d1
 /* Unix/Linux/Cygwin/MacOSX */
Packit Service 21b5d1
 #include <pthread.h>
Packit Service 21b5d1
 /* This is the critical section object (statically allocated). */
Packit Service 21b5d1
 #if defined(__APPLE__)
Packit Service 21b5d1
  #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
Packit Service 21b5d1
    static pthread_mutex_t cs =  PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
Packit Service 21b5d1
   #else
Packit Service 21b5d1
    static pthread_mutex_t cs =  PTHREAD_MUTEX_INITIALIZER;
Packit Service 21b5d1
  #endif
Packit Service 21b5d1
 #else
Packit Service 21b5d1
  #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
Packit Service 21b5d1
    static pthread_mutex_t cs =  PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
Packit Service 21b5d1
   #else
Packit Service 21b5d1
    static pthread_mutex_t cs =  PTHREAD_MUTEX_INITIALIZER;
Packit Service 21b5d1
  #endif
Packit Service 21b5d1
 #endif
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
    static std::string temporaryPath()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        static int  count = 0 ;
Packit Service 21b5d1
Packit Service 21b5d1
#if defined(_MSC_VER) || defined(__MINGW__)
Packit Service 21b5d1
        EnterCriticalSection(&cs);
Packit Service 21b5d1
        char lpTempPathBuffer[MAX_PATH];
Packit Service 21b5d1
        GetTempPath(MAX_PATH,lpTempPathBuffer);
Packit Service 21b5d1
        std::string tmp(lpTempPathBuffer);
Packit Service 21b5d1
        tmp += "\\";
Packit Service 21b5d1
        HANDLE process=0;
Packit Service 21b5d1
        DWORD  pid = ::GetProcessId(process);
Packit Service 21b5d1
#else
Packit Service 21b5d1
        pid_t  pid = ::getpid();
Packit Service 21b5d1
        pthread_mutex_lock( &cs );
Packit Service 21b5d1
        std::string tmp = "/tmp/";
Packit Service 21b5d1
#endif
Packit Service 21b5d1
        char        sCount[12];
Packit Service 21b5d1
        sprintf(sCount,"_%d",++count);
Packit Service 21b5d1
Packit Service 21b5d1
        std::string result = tmp + Exiv2::toString(pid) + sCount ;
Packit Service 21b5d1
        if ( Exiv2::fileExists(result) ) std::remove(result.c_str());
Packit Service 21b5d1
Packit Service 21b5d1
#if defined(_MSC_VER) || defined(__MINGW__)
Packit Service 21b5d1
        LeaveCriticalSection(&cs);
Packit Service 21b5d1
#else
Packit Service 21b5d1
        pthread_mutex_unlock( &cs );
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
        return result;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int metacopy(const std::string& source,
Packit Service 21b5d1
                 const std::string& tgt,
Packit Service 21b5d1
                 int targetType,
Packit Service 21b5d1
                 bool preserve)
Packit Service 21b5d1
    {
Packit Service 21b5d1
#ifdef EXIV2_DEBUG_MESSAGES
Packit Service 21b5d1
        std::cerr << "actions.cpp::metacopy" << " source = " << source << " target = " << tgt << std::endl;
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
        // read the source metadata
Packit Service 21b5d1
        int  rc    = -1   ;
Packit Service 21b5d1
        if (!Exiv2::fileExists(source, true)) {
Packit Service 21b5d1
            std::cerr << source
Packit Service 21b5d1
                      << ": " << _("Failed to open the file\n");
Packit Service 21b5d1
            return rc;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        bool          bStdin  = source == "-";
Packit Service 21b5d1
        bool          bStdout = tgt    == "-";
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::DataBuf stdIn;
Packit Service 21b5d1
        if ( bStdin )  Params::instance().getStdin(stdIn);
Packit Service 21b5d1
        Exiv2::BasicIo::AutoPtr ioStdin = Exiv2::BasicIo::AutoPtr(new Exiv2::MemIo(stdIn.pData_,stdIn.size_));
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::Image::AutoPtr sourceImage = bStdin ? Exiv2::ImageFactory::open(ioStdin) : Exiv2::ImageFactory::open(source);
Packit Service 21b5d1
        assert(sourceImage.get() != 0);
Packit Service 21b5d1
        sourceImage->readMetadata();
Packit Service 21b5d1
Packit Service 21b5d1
        // Apply any modification commands to the source image on-the-fly
Packit Service 21b5d1
        Action::Modify::applyCommands(sourceImage.get());
Packit Service 21b5d1
Packit Service 21b5d1
        // Open or create the target file
Packit Service 21b5d1
        std::string target(bStdout ? temporaryPath() : tgt);
Packit Service 21b5d1
Packit Service 21b5d1
        Exiv2::Image::AutoPtr targetImage;
Packit Service 21b5d1
        if (Exiv2::fileExists(target)) {
Packit Service 21b5d1
            targetImage = Exiv2::ImageFactory::open(target);
Packit Service 21b5d1
            assert(targetImage.get() != 0);
Packit Service 21b5d1
            targetImage->readMetadata();
Packit Service 21b5d1
        } else {
Packit Service 21b5d1
            targetImage = Exiv2::ImageFactory::create(targetType, target);
Packit Service 21b5d1
            assert(targetImage.get() != 0);
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // Copy each type of metadata
Packit Service 21b5d1
        if (   Params::instance().target_ & Params::ctExif
Packit Service 21b5d1
            && !sourceImage->exifData().empty()) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("Writing Exif data from") << " " << source
Packit Service 21b5d1
                          << " " << _("to") << " " << target << std::endl;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if ( preserve ) {
Packit Service 21b5d1
                Exiv2::ExifData::const_iterator end = sourceImage->exifData().end();
Packit Service 21b5d1
                for (Exiv2::ExifData::const_iterator i = sourceImage->exifData().begin(); i != end; ++i) {
Packit Service 21b5d1
                    targetImage->exifData()[i->key()] = i->value();
Packit Service 21b5d1
                }
Packit Service 21b5d1
            } else {
Packit Service 21b5d1
                targetImage->setExifData(sourceImage->exifData());
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (   Params::instance().target_ & Params::ctIptc
Packit Service 21b5d1
            && !sourceImage->iptcData().empty()) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("Writing IPTC data from") << " " << source
Packit Service 21b5d1
                          << " " << _("to") << " " << target << std::endl;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if ( preserve ) {
Packit Service 21b5d1
                Exiv2::IptcData::const_iterator end = sourceImage->iptcData().end();
Packit Service 21b5d1
                for (Exiv2::IptcData::const_iterator i = sourceImage->iptcData().begin(); i != end; ++i) {
Packit Service 21b5d1
                    targetImage->iptcData()[i->key()] = i->value();
Packit Service 21b5d1
                }
Packit Service 21b5d1
            } else {
Packit Service 21b5d1
                targetImage->setIptcData(sourceImage->iptcData());
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (    Params::instance().target_ & (Params::ctXmp|Params::ctXmpRaw)
Packit Service 21b5d1
            && !sourceImage->xmpData().empty()) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("Writing XMP data from") << " " << source
Packit Service 21b5d1
                          << " " << _("to") << " " << target << std::endl;
Packit Service 21b5d1
            }
Packit Service 21b5d1
Packit Service 21b5d1
            // #1148 use Raw XMP packet if there are no XMP modification commands
Packit Service 21b5d1
            int tRawSidecar = Params::ctXmpSidecar | Params::ctXmpRaw; // option -eXX
Packit Service 21b5d1
            // printTarget("in metacopy",Params::instance().target_,true);
Packit Service 21b5d1
            if( Params::instance().modifyCmds_.size() == 0
Packit Service 21b5d1
            && (Params::instance().target_ & tRawSidecar) == tRawSidecar
Packit Service 21b5d1
            ){
Packit Service 21b5d1
                // std::cout << "short cut" << std::endl;
Packit Service 21b5d1
                // http://www.cplusplus.com/doc/tutorial/files/
Packit Service 21b5d1
                std::ofstream os;
Packit Service 21b5d1
                os.open(target.c_str());
Packit Service 21b5d1
                sourceImage->printStructure(os,Exiv2::kpsXMP);
Packit Service 21b5d1
                os.close();
Packit Service 21b5d1
                rc = 0;
Packit Service 21b5d1
            } else if ( preserve ) {
Packit Service 21b5d1
                Exiv2::XmpData::const_iterator end = sourceImage->xmpData().end();
Packit Service 21b5d1
                for (Exiv2::XmpData::const_iterator i = sourceImage->xmpData().begin(); i != end; ++i) {
Packit Service 21b5d1
                    targetImage->xmpData()[i->key()] = i->value();
Packit Service 21b5d1
                }
Packit Service 21b5d1
            } else {
Packit Service 21b5d1
                // std::cout << "long cut" << std::endl;
Packit Service 21b5d1
                targetImage->setXmpData(sourceImage->xmpData());
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (   Params::instance().target_ & Params::ctComment
Packit Service 21b5d1
            && !sourceImage->comment().empty()) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("Writing JPEG comment from") << " " << source
Packit Service 21b5d1
                          << " " << _("to") << " " << tgt << std::endl;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            targetImage->setComment(sourceImage->comment());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if ( rc < 0 ) try {
Packit Service 21b5d1
            targetImage->writeMetadata();
Packit Service 21b5d1
            rc=0;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        catch (const Exiv2::AnyError& e) {
Packit Service 21b5d1
            std::cerr << tgt <<
Packit Service 21b5d1
                ": " << _("Could not write metadata to file") << ": " << e << "\n";
Packit Service 21b5d1
            rc=1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // if we used a temporary target, copy it to stdout
Packit Service 21b5d1
        if ( rc == 0 && bStdout ) {
Packit Service 21b5d1
            FILE* f = ::fopen(target.c_str(),"rb") ;
Packit Service 21b5d1
            _setmode(_fileno(stdout),O_BINARY);
Packit Service 21b5d1
Packit Service 21b5d1
            if (  f ) {
Packit Service 21b5d1
                char buffer[8*1024];
Packit Service 21b5d1
                size_t n = 1 ;
Packit Service 21b5d1
                while ( !feof(f) && n > 0) {
Packit Service 21b5d1
                    n=fread(buffer,1,sizeof buffer,f);
Packit Service 21b5d1
                    fwrite(buffer,1,n,stdout);
Packit Service 21b5d1
                }
Packit Service 21b5d1
                fclose(f);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // delete temporary target
Packit Service 21b5d1
        if ( bStdout ) std::remove(target.c_str());
Packit Service 21b5d1
Packit Service 21b5d1
        return rc;
Packit Service 21b5d1
    } // metacopy
Packit Service 21b5d1
Packit Service 21b5d1
    // Defined outside of the function so that Exiv2::find() can see it
Packit Service 21b5d1
    struct String {
Packit Service 21b5d1
        const char* s_;
Packit Service 21b5d1
        bool operator==(const char* s) const {
Packit Service 21b5d1
            return 0 == strcmp(s_, s);
Packit Service 21b5d1
        }
Packit Service 21b5d1
    };
Packit Service 21b5d1
Packit Service 21b5d1
    int renameFile(std::string& newPath, const struct tm* tm)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::string path = newPath;
Packit Service 21b5d1
        std::string format = Params::instance().format_;
Packit Service 21b5d1
        Util::replace(format, ":basename:",   Util::basename(path, true));
Packit Service 21b5d1
        Util::replace(format, ":dirname:",    Util::basename(Util::dirname(path)));
Packit Service 21b5d1
        Util::replace(format, ":parentname:", Util::basename(Util::dirname(Util::dirname(path))));
Packit Service 21b5d1
Packit Service 21b5d1
        const size_t max = 1024;
Packit Service 21b5d1
        char basename[max];
Packit Service 21b5d1
        std::memset(basename, 0x0, max);
Packit Service 21b5d1
        if (strftime(basename, max, format.c_str(), tm) == 0) {
Packit Service 21b5d1
            std::cerr << _("Filename format yields empty filename for the file") << " "
Packit Service 21b5d1
                      << path << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        newPath =   Util::dirname(path) + EXV_SEPARATOR_STR
Packit Service 21b5d1
                  + basename + Util::suffix(path);
Packit Service 21b5d1
        if (   Util::dirname(newPath)  == Util::dirname(path)
Packit Service 21b5d1
            && Util::basename(newPath) == Util::basename(path)) {
Packit Service 21b5d1
            if (Params::instance().verbose_) {
Packit Service 21b5d1
                std::cout << _("This file already has the correct name") << std::endl;
Packit Service 21b5d1
            }
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        bool go = true;
Packit Service 21b5d1
        int seq = 1;
Packit Service 21b5d1
        std::string s;
Packit Service 21b5d1
        Params::FileExistsPolicy fileExistsPolicy
Packit Service 21b5d1
            = Params::instance().fileExistsPolicy_;
Packit Service 21b5d1
        while (go) {
Packit Service 21b5d1
            if (Exiv2::fileExists(newPath)) {
Packit Service 21b5d1
                switch (fileExistsPolicy) {
Packit Service 21b5d1
                case Params::overwritePolicy:
Packit Service 21b5d1
                    go = false;
Packit Service 21b5d1
                    break;
Packit Service 21b5d1
                case Params::renamePolicy:
Packit Service 21b5d1
                    newPath = Util::dirname(path)
Packit Service 21b5d1
                        + EXV_SEPARATOR_STR + basename
Packit Service 21b5d1
                        + "_" + Exiv2::toString(seq++)
Packit Service 21b5d1
                        + Util::suffix(path);
Packit Service 21b5d1
                    break;
Packit Service 21b5d1
                case Params::askPolicy:
Packit Service 21b5d1
                    std::cout << Params::instance().progname()
Packit Service 21b5d1
                              << ": " << _("File") << " `" << newPath
Packit Service 21b5d1
                              << "' " << _("exists. [O]verwrite, [r]ename or [s]kip?")
Packit Service 21b5d1
                              << " ";
Packit Service 21b5d1
                    std::cin >> s;
Packit Service 21b5d1
                    switch (s[0]) {
Packit Service 21b5d1
                    case 'o':
Packit Service 21b5d1
                    case 'O':
Packit Service 21b5d1
                        go = false;
Packit Service 21b5d1
                        break;
Packit Service 21b5d1
                    case 'r':
Packit Service 21b5d1
                    case 'R':
Packit Service 21b5d1
                        fileExistsPolicy = Params::renamePolicy;
Packit Service 21b5d1
                        newPath = Util::dirname(path)
Packit Service 21b5d1
                            + EXV_SEPARATOR_STR + basename
Packit Service 21b5d1
                            + "_" + Exiv2::toString(seq++)
Packit Service 21b5d1
                            + Util::suffix(path);
Packit Service 21b5d1
                        break;
Packit Service 21b5d1
                    default: // skip
Packit Service 21b5d1
                        return -1;
Packit Service 21b5d1
                        break;
Packit Service 21b5d1
                    }
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
            else {
Packit Service 21b5d1
                go = false;
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        if (Params::instance().verbose_) {
Packit Service 21b5d1
            std::cout << _("Renaming file to") << " " << newPath;
Packit Service 21b5d1
            if (Params::instance().timestamp_) {
Packit Service 21b5d1
                std::cout << ", " << _("updating timestamp");
Packit Service 21b5d1
            }
Packit Service 21b5d1
            std::cout << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        // Workaround for MinGW rename which does not overwrite existing files
Packit Service 21b5d1
        remove(newPath.c_str());
Packit Service 21b5d1
        if (std::rename(path.c_str(), newPath.c_str()) == -1) {
Packit Service 21b5d1
            std::cerr << Params::instance().progname()
Packit Service 21b5d1
                      << ": " << _("Failed to rename") << " "
Packit Service 21b5d1
                      << path << " " << _("to") << " " << newPath << ": "
Packit Service 21b5d1
                      << Exiv2::strError() << "\n";
Packit Service 21b5d1
            return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    } // renameFile
Packit Service 21b5d1
Packit Service 21b5d1
    std::string newFilePath(const std::string& path, const std::string& ext)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::string directory = Params::instance().directory_;
Packit Service 21b5d1
        if (directory.empty()) directory = Util::dirname(path);
Packit Service 21b5d1
        directory   = Exiv2::fileProtocol(path) == Exiv2::pFile
Packit Service 21b5d1
                    ? directory + EXV_SEPARATOR_STR
Packit Service 21b5d1
                    : "" // use current directory for remote files
Packit Service 21b5d1
                    ;
Packit Service 21b5d1
        return directory + Util::basename(path, true) + ext;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int dontOverwrite(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if ( path == "-" ) return 0;
Packit Service 21b5d1
Packit Service 21b5d1
        if (!Params::instance().force_ && Exiv2::fileExists(path)) {
Packit Service 21b5d1
            std::cout << Params::instance().progname()
Packit Service 21b5d1
                      << ": " << _("Overwrite") << " `" << path << "'? ";
Packit Service 21b5d1
            std::string s;
Packit Service 21b5d1
            std::cin >> s;
Packit Service 21b5d1
            if (s[0] != 'y' && s[0] != 'Y') return 1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    std::ostream& operator<<( std::ostream& os, std::pair<std::string, int> strAndWidth)
Packit Service 21b5d1
    {
Packit Service 21b5d1
      const std::string& str( strAndWidth.first);
Packit Service 21b5d1
      size_t minChCount( strAndWidth.second);
Packit Service 21b5d1
      size_t count = mbstowcs( NULL, str.c_str(), 0); // returns 0xFFFFFFFF on error
Packit Service 21b5d1
      if( count < minChCount)
Packit Service 21b5d1
      {
Packit Service 21b5d1
        minChCount += str.size() - count;
Packit Service 21b5d1
      }
Packit Service 21b5d1
      return os << std::setw( minChCount) << str;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int printStructure(std::ostream& out, Exiv2::PrintStructureOption option, const std::string &path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (!Exiv2::fileExists(path, true)) {
Packit Service 21b5d1
            std::cerr << path << ": "
Packit Service 21b5d1
                      << _("Failed to open the file\n");
Packit Service 21b5d1
            return -1;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
Packit Service 21b5d1
        assert(image.get() != 0);
Packit Service 21b5d1
        image->printStructure(out,option);
Packit Service 21b5d1
        return 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
}