Logo Search packages:      
Sourcecode: qpdf version File versions  Download package

pdf-mod-info.cc

// Author: Vitaliy Pavlyuk

#include <qpdf/QPDF.hh>
#include <qpdf/QPDFWriter.hh>
#include <qpdf/QPDFObjectHandle.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/QTC.hh>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

static char const* version = "1.1";
static char const* whoami = 0;

void usage()
{
    std::cerr
      << "Usage: " << whoami
      << " -in in_file [-out out_file] [-key key [-val val]?]+\n"
      << "Modifies/Adds/Removes PDF /Info entries in the in_file\n"
      << "and stores the result in out_file\n"
      << "Special mode: " << whoami << " --dump file\n"
      << "dumps all /Info entries to stdout\n";
    exit(2);
}

void dumpInfoDict(QPDF& pdf,
              std::ostream& os = std::cout,
              std::string const& sep = ":\t")
{
    QPDFObjectHandle trailer = pdf.getTrailer();
    if (trailer.hasKey("/Info"))
    {
      QPDFObjectHandle info = trailer.getKey("/Info");
      std::set<std::string> keys = info.getKeys();
      for (std::set<std::string>::const_iterator it = keys.begin();
           keys.end() != it; ++it)
      {
          QPDFObjectHandle elt = info.getKey(*it);
          std::string val;
          if (false) {}
          else if (elt.isString())
          {
            val = elt.getStringValue();
          }
          else if (elt.isName())
          {
            val = elt.getName();
          }
          else // according to PDF Spec 1.5, shouldn't happen
          {
            val = elt.unparseResolved();
          }
          os << it->substr(1) << sep << val << std::endl; // skip '/'
      }
    }
}

void pdfDumpInfoDict(char const* fname)
{
    try
    {
      QPDF pdf;
      pdf.processFile(fname);
      dumpInfoDict(pdf);
    }
    catch (std::exception& e)
    {
      std::cerr << e.what() << std::endl;
      exit(2);
    }
}

int main(int argc, char* argv[])
{

    bool static_id = false;
    std::map<std::string, std::string> Keys;

    if ((whoami = strrchr(argv[0], '/')) == NULL)
    {
      whoami = argv[0];
    }
    else
    {
      ++whoami;
    }
    // For libtool's sake....
    if (strncmp(whoami, "lt-", 3) == 0)
    {
      whoami += 3;
    }

    if ((argc == 2) && (! strcmp(argv[1], "--version")) )
    {
      std::cout << whoami << " version " << version << std::endl;
      exit(0);
    }
    if ((argc == 4) && (! strcmp(argv[1], "--dump")) &&
      (strcmp(argv[2], "-in") == 0) )
    {
      QTC::TC("examples", "pdf-mod-info --dump");
      pdfDumpInfoDict(argv[3]);
      exit(0);
    }

    char* fl_in = 0;
    char* fl_out = 0;
    char* cur_key = 0;

    for (int i = 1; i < argc; ++i)
    {
      if ((! strcmp(argv[i], "-in")) && (++i < argc))
      {
          fl_in = argv[i];
      }
      else if ((! strcmp(argv[i], "-out")) && (++i < argc))
      {
          fl_out = argv[i];
      }
      else if (! strcmp(argv[i], "--static-id")) // don't document
      {
          static_id = true; // this should be used in test suites only
      }
      else if ((! strcmp(argv[i], "-key")) && (++i < argc))
      {
          QTC::TC("examples", "pdf-mod-info -key");
          cur_key = argv[i];
          Keys[cur_key] = "";
      }
      else if ((! strcmp(argv[i], "-val")) && (++i < argc))
      {
          if (cur_key == 0)
          {
            QTC::TC("examples", "pdf-mod-info usage wrong val");
            usage();
          }
          QTC::TC("examples", "pdf-mod-info -val");
          Keys[cur_key] = argv[i];
          cur_key = 0;
      }
      else
      {
          QTC::TC("examples", "pdf-mod-info usage junk");
          usage();
      }
    }
    if (! fl_in)
    {
      QTC::TC("examples", "pdf-mod-info no in file");
      usage();
    }
    if (! fl_out)
    {
      QTC::TC("examples", "pdf-mod-info in-place");
      fl_out = fl_in;
    }
    if (Keys.size() == 0)
    {
      QTC::TC("examples", "pdf-mod-info no keys");
      usage();
    }

    try
    {
      QPDF file;
      file.processFile(fl_in);

      QPDFObjectHandle filetrailer = file.getTrailer();
      QPDFObjectHandle fileinfo;

      for (std::map<std::string, std::string>::const_iterator it =
             Keys.begin(); Keys.end() != it; ++it)
      {
          if (! fileinfo.isInitialized())
          {
            if (filetrailer.hasKey("/Info"))
            {
                QTC::TC("examples", "pdf-mod-info has info");
                fileinfo = filetrailer.getKey("/Info");
            }
            else
            {
                QTC::TC("examples", "pdf-mod-info file no info");
                std::map<std::string, QPDFObjectHandle> vacant;
                fileinfo = fileinfo.newDictionary(vacant);
                filetrailer.replaceKey("/Info", fileinfo);
            }
          }
          if (it->second == "")
          {
            fileinfo.removeKey(it->first);
          }
          else
          {
            QPDFObjectHandle elt = fileinfo.newString(it->second);
            elt.makeDirect();
            fileinfo.replaceKey(it->first, elt);
          }
      }
      std::string fl_tmp = fl_out;
      fl_tmp += ".tmp";
      QPDFWriter w(file, fl_tmp.c_str());
      w.setStreamDataMode(QPDFWriter::s_preserve);
      w.setLinearization(true);
      w.setStaticID(static_id);
      w.write();
      QUtil::os_wrapper("rename " + fl_tmp + " " + std::string(fl_out),
                    rename(fl_tmp.c_str(), fl_out));
    }
    catch (std::exception& e)
    {
      std::cerr << e.what() << std::endl;
      exit(2);
    }

    return 0;
}

Generated by  Doxygen 1.6.0   Back to index