mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Add CLI support for working with attachments
This commit is contained in:
parent
1f4771cd0d
commit
832d792e4e
@ -1,3 +1,9 @@
|
||||
2021-02-10 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Add new command-line arguments for operating on attachments:
|
||||
--list-attachments, --add-attachment, --remove-attachment,
|
||||
--copy-attachments-from. See --help and manual for details.
|
||||
|
||||
2021-02-09 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Add methods to QUtil for working with PDF timestamp strings:
|
||||
|
@ -1801,6 +1801,181 @@ outfile.pdf</option>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="ref.attachments">
|
||||
<title>Embedded Files/Attachments Options</title>
|
||||
<para>
|
||||
Starting with qpdf 10.2, you can work with file attachments in PDF
|
||||
files from the command line. The following options are available:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>--list-attachments</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Show the “key” and stream number for embedded
|
||||
files. With <option>--verbose</option>, additional
|
||||
information, including preferred file name, description,
|
||||
dates, and more are also displayed. The key is usually but not
|
||||
always equal to the file name, and is needed by some of the
|
||||
other options.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--show-attachment=<replaceable>key</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Write the contents of the specified attachment to standard
|
||||
output as binary data. The key should match one of the keys
|
||||
shown by <option>--list-attachments</option>. If specified
|
||||
multiple times, only the last attachment will be shown.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--add-attachment <replaceable>file</replaceable> <replaceable>options</replaceable> --</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Add or replace an attachment with the contents of
|
||||
<replaceable>file</replaceable>. This may be specified more
|
||||
than once. The following additional options may appear before
|
||||
the <literal>--</literal> that ends this option:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>--key=<replaceable>key</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The key to use to register the attachment in the embedded
|
||||
files table. Defaults to the last path element of
|
||||
<replaceable>file</replaceable>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--filename=<replaceable>name</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The file name to be used for the attachment. This is what is usually
|
||||
displayed to the user and is the name most graphical PDF
|
||||
viewers will use when saving a file. It defaults to the
|
||||
last path element of <replaceable>file</replaceable>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--creationdate=<replaceable>date</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The attachment's creation date in PDF format; defaults to
|
||||
the current time. The date format is explained below.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--moddate=<replaceable>date</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The attachment's modification date in PDF format; defaults
|
||||
to the current time. The date format is explained below.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--mimetype=<replaceable>type/subtype</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The mime type for the attachment, e.g.
|
||||
<literal>text/plain</literal> or
|
||||
<literal>application/pdf</literal>. Note that the mimetype
|
||||
appears in a field called <literal>/Subtype</literal> in
|
||||
the PDF but actually includes the full type and subtype of
|
||||
the mime type.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--description=<replaceable>"text"</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Descriptive text for the attachment, displayed by some PDF
|
||||
viewers.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--replace</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Indicates that any existing attachment with the same key
|
||||
should be replaced by the new attachment. Otherwise,
|
||||
<command>qpdf</command> gives an error if an attachment
|
||||
with that key is already present.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--remove-attachment=<replaceable>key</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Remove the specified attachment. This doesn't only remove the
|
||||
attachment from the embedded files table but also clears out
|
||||
the file specification. That means that any potential internal
|
||||
links to the attachment will be broken. This option may be
|
||||
specified multiple times. Run with <option>--verbose</option>
|
||||
to see status of the removal.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--copy-attachments-from <replaceable>file</replaceable> <replaceable>options</replaceable> --</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Copy attachments from another file. This may be specified more
|
||||
than once. The following additional options may appear before
|
||||
the <literal>--</literal> that ends this option:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>--password=<replaceable>password</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If required, the password needed to open
|
||||
<replaceable>file</replaceable>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--prefix=<replaceable>prefix</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Only required if the file from which attachments are being
|
||||
copied has attachments with keys that conflict with
|
||||
attachments already in the file. In this case, the
|
||||
specified prefix will be prepended to each key. This
|
||||
affects only the key in the embedded files table, not the
|
||||
file name. The PDF specification doesn't preclude multiple
|
||||
attachments having the same file name.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
When a date is required, the date should conform to the PDF date
|
||||
format specification, which is
|
||||
<literal>D:</literal><replaceable>yyyymmddhhmmss<z></replaceable>,
|
||||
where <replaceable><z></replaceable> is either
|
||||
<literal>Z</literal> for UTC or a timezone offset in the form
|
||||
<replaceable>-hh'mm'</replaceable> or
|
||||
<replaceable>+hh'mm'</replaceable>. Examples:
|
||||
<literal>D:20210207161528-05'00'</literal>,
|
||||
<literal>D:20210207211528Z</literal>.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="ref.advanced-parsing">
|
||||
<title>Advanced Parsing Options</title>
|
||||
<para>
|
||||
@ -4911,6 +5086,13 @@ print "\n";
|
||||
CLI Enhancements
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Add new command line options for listing, saving, adding,
|
||||
removing, and and copying file attachments. See <xref
|
||||
linkend="ref.attachments"/> for details.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The option
|
||||
|
504
qpdf/qpdf.cc
504
qpdf/qpdf.cc
@ -26,6 +26,7 @@
|
||||
#include <qpdf/QPDFExc.hh>
|
||||
#include <qpdf/QPDFSystemError.hh>
|
||||
#include <qpdf/QPDFCryptoProvider.hh>
|
||||
#include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
|
||||
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QIntC.hh>
|
||||
@ -95,6 +96,31 @@ struct UnderOverlay
|
||||
std::vector<int> repeat_pagenos;
|
||||
};
|
||||
|
||||
struct AddAttachment
|
||||
{
|
||||
AddAttachment() :
|
||||
replace(false)
|
||||
{
|
||||
}
|
||||
|
||||
std::string path;
|
||||
std::string key;
|
||||
std::string filename;
|
||||
std::string creationdate;
|
||||
std::string moddate;
|
||||
std::string mimetype;
|
||||
std::string description;
|
||||
bool replace;
|
||||
};
|
||||
|
||||
struct CopyAttachmentFrom
|
||||
{
|
||||
std::string path;
|
||||
std::string password;
|
||||
std::string prefix;
|
||||
};
|
||||
|
||||
|
||||
enum remove_unref_e { re_auto, re_yes, re_no };
|
||||
|
||||
struct Options
|
||||
@ -177,6 +203,7 @@ struct Options
|
||||
show_page_images(false),
|
||||
collate(false),
|
||||
flatten_rotation(false),
|
||||
list_attachments(false),
|
||||
json(false),
|
||||
check(false),
|
||||
optimize_images(false),
|
||||
@ -282,6 +309,11 @@ struct Options
|
||||
bool show_page_images;
|
||||
bool collate;
|
||||
bool flatten_rotation;
|
||||
bool list_attachments;
|
||||
std::string attachment_to_show;
|
||||
std::list<std::string> attachments_to_remove;
|
||||
std::list<AddAttachment> attachments_to_add;
|
||||
std::list<CopyAttachmentFrom> attachments_to_copy;
|
||||
bool json;
|
||||
std::set<std::string> json_keys;
|
||||
std::set<std::string> json_objects;
|
||||
@ -758,6 +790,11 @@ class ArgParser
|
||||
void argRotate(char* parameter);
|
||||
void argCollate();
|
||||
void argFlattenRotation();
|
||||
void argListAttachments();
|
||||
void argShowAttachment(char* parameter);
|
||||
void argRemoveAttachment(char* parameter);
|
||||
void argAddAttachment();
|
||||
void argCopyAttachments();
|
||||
void argStreamData(char* parameter);
|
||||
void argCompressStreams(char* parameter);
|
||||
void argRecompressFlate();
|
||||
@ -838,6 +875,19 @@ class ArgParser
|
||||
void argReplaceInput();
|
||||
void argIsEncrypted();
|
||||
void argRequiresPassword();
|
||||
void argAApositional(char* arg);
|
||||
void argAAKey(char* parameter);
|
||||
void argAAFilename(char* parameter);
|
||||
void argAACreationDate(char* parameter);
|
||||
void argAAModDate(char* parameter);
|
||||
void argAAMimeType(char* parameter);
|
||||
void argAADescription(char* parameter);
|
||||
void argAAReplace();
|
||||
void argEndAddAttachment();
|
||||
void argCApositional(char* arg);
|
||||
void argCAprefix(char* parameter);
|
||||
void argCApassword(char* parameter);
|
||||
void argEndCopyAttachments();
|
||||
|
||||
void usage(std::string const& message);
|
||||
void checkCompletion();
|
||||
@ -874,6 +924,8 @@ class ArgParser
|
||||
std::map<std::string, OptionEntry> encrypt128_option_table;
|
||||
std::map<std::string, OptionEntry> encrypt256_option_table;
|
||||
std::map<std::string, OptionEntry> under_overlay_option_table;
|
||||
std::map<std::string, OptionEntry> add_attachment_option_table;
|
||||
std::map<std::string, OptionEntry> copy_attachments_option_table;
|
||||
std::vector<PointerHolder<char> > new_argv;
|
||||
std::vector<PointerHolder<char> > bash_argv;
|
||||
PointerHolder<char*> argv_ph;
|
||||
@ -982,6 +1034,13 @@ ArgParser::initOptionTable()
|
||||
{"compress", "preserve", "uncompress", 0};
|
||||
(*t)["collate"] = oe_bare(&ArgParser::argCollate);
|
||||
(*t)["flatten-rotation"] = oe_bare(&ArgParser::argFlattenRotation);
|
||||
(*t)["list-attachments"] = oe_bare(&ArgParser::argListAttachments);
|
||||
(*t)["show-attachment"] = oe_requiredParameter(
|
||||
&ArgParser::argShowAttachment, "attachment-key");
|
||||
(*t)["remove-attachment"] = oe_requiredParameter(
|
||||
&ArgParser::argRemoveAttachment, "attachment-key");
|
||||
(*t)["add-attachment"] = oe_bare(&ArgParser::argAddAttachment);
|
||||
(*t)["copy-attachments-from"] = oe_bare(&ArgParser::argCopyAttachments);
|
||||
(*t)["stream-data"] = oe_requiredChoices(
|
||||
&ArgParser::argStreamData, stream_data_choices);
|
||||
(*t)["compress-streams"] = oe_requiredChoices(
|
||||
@ -1129,6 +1188,31 @@ ArgParser::initOptionTable()
|
||||
(*t)["password"] = oe_requiredParameter(
|
||||
&ArgParser::argUOpassword, "password");
|
||||
(*t)["--"] = oe_bare(&ArgParser::argEndUnderOverlay);
|
||||
|
||||
t = &this->add_attachment_option_table;
|
||||
(*t)[""] = oe_positional(&ArgParser::argAApositional);
|
||||
(*t)["key"] = oe_requiredParameter(
|
||||
&ArgParser::argAAKey, "attachment-key");
|
||||
(*t)["filename"] = oe_requiredParameter(
|
||||
&ArgParser::argAAFilename, "filename");
|
||||
(*t)["creationdate"] = oe_requiredParameter(
|
||||
&ArgParser::argAACreationDate, "creation-date");
|
||||
(*t)["moddate"] = oe_requiredParameter(
|
||||
&ArgParser::argAAModDate, "modification-date");
|
||||
(*t)["mimetype"] = oe_requiredParameter(
|
||||
&ArgParser::argAAMimeType, "mime/type");
|
||||
(*t)["description"] = oe_requiredParameter(
|
||||
&ArgParser::argAADescription, "description");
|
||||
(*t)["replace"] = oe_bare(&ArgParser::argAAReplace);
|
||||
(*t)["--"] = oe_bare(&ArgParser::argEndAddAttachment);
|
||||
|
||||
t = &this->copy_attachments_option_table;
|
||||
(*t)[""] = oe_positional(&ArgParser::argCApositional);
|
||||
(*t)["prefix"] = oe_requiredParameter(
|
||||
&ArgParser::argCAprefix, "prefix");
|
||||
(*t)["password"] = oe_requiredParameter(
|
||||
&ArgParser::argCApassword, "password");
|
||||
(*t)["--"] = oe_bare(&ArgParser::argEndCopyAttachments);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1361,7 +1445,6 @@ ArgParser::argHelp()
|
||||
<< " --allow-insecure allow the owner password to be empty when the\n"
|
||||
<< " user password is not empty\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< " print-opt may be:\n"
|
||||
<< "\n"
|
||||
<< " full allow full printing\n"
|
||||
@ -1487,6 +1570,55 @@ ArgParser::argHelp()
|
||||
<< " any \"from\" pages have been exhausted\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Embedded Files/Attachments Options\n"
|
||||
<< "----------------------------------\n"
|
||||
<< "\n"
|
||||
<< "These options can be used to work with embedded files, also known as\n"
|
||||
<< "attachments.\n"
|
||||
<< "\n"
|
||||
<< "--list-attachments show key and stream number for embedded files;\n"
|
||||
<< " combine with --verbose for more detailed information\n"
|
||||
<< "--show-attachment=key write the contents of the specified attachment to\n"
|
||||
<< " standard output as binary data\n"
|
||||
<< "--add-attachment file options --\n"
|
||||
<< " add or replace an attachment\n"
|
||||
<< "--remove-attachment=key remove the specified attachment; repeatable\n"
|
||||
<< "--copy-attachments-from file options --\n"
|
||||
<< " copy attachments from another file\n"
|
||||
<< "\n"
|
||||
<< "The \"key\" option is the unique name under which the attachment is registered\n"
|
||||
<< "within the PDF file. You can get this using the --list-attachments option. This\n"
|
||||
<< "is usually the same as the filename, but it doesn't have to be.\n"
|
||||
<< "\n"
|
||||
<< "Options for adding attachments:\n"
|
||||
<< "\n"
|
||||
<< " file path to the file to attach\n"
|
||||
<< " --key=key the name of this in the embedded files table;\n"
|
||||
<< " defaults to the last path element of file\n"
|
||||
<< " --filename=name the file name of the attachment; this is what is\n"
|
||||
<< " usually displayed to the user; defaults to the\n"
|
||||
<< " last path element of file\n"
|
||||
<< " --creationdate=date creation date in PDF format; defaults to the\n"
|
||||
<< " current time\n"
|
||||
<< " --moddate=date modification date in PDF format; defaults to the\n"
|
||||
<< " current time\n"
|
||||
<< " --mimetype=type/subtype mime type of attachment (e.g. application/pdf)\n"
|
||||
<< " --description=\"text\" attachment description\n"
|
||||
<< " --replace replace any existing attachment with the same key\n"
|
||||
<< "\n"
|
||||
<< "Options for copying attachments:\n"
|
||||
<< "\n"
|
||||
<< " file file whose attachments should be copied\n"
|
||||
<< " --password=password password to open the other file, if needed\n"
|
||||
<< " --prefix=prefix a prefix to insert in front of each key;\n"
|
||||
<< " required if needed to ensure each attachment\n"
|
||||
<< " has a unique key\n"
|
||||
<< "\n"
|
||||
<< "Date format: D:yyyymmddhhmmss<z> where <z> is either Z for UTC or a timezone\n"
|
||||
<< "offset in the form -hh'mm' or +hh'mm'.\n"
|
||||
<< "Examples: D:20210207161528-05'00', D:20210207211528Z\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "Advanced Parsing Options\n"
|
||||
<< "------------------------\n"
|
||||
<< "\n"
|
||||
@ -1960,6 +2092,40 @@ ArgParser::argFlattenRotation()
|
||||
o.flatten_rotation = true;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argListAttachments()
|
||||
{
|
||||
o.list_attachments = true;
|
||||
o.require_outfile = false;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argShowAttachment(char* parameter)
|
||||
{
|
||||
o.attachment_to_show = parameter;
|
||||
o.require_outfile = false;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argRemoveAttachment(char* parameter)
|
||||
{
|
||||
o.attachments_to_remove.push_back(parameter);
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAddAttachment()
|
||||
{
|
||||
this->option_table = &(this->add_attachment_option_table);
|
||||
o.attachments_to_add.push_back(AddAttachment());
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argCopyAttachments()
|
||||
{
|
||||
this->option_table = &(this->copy_attachments_option_table);
|
||||
o.attachments_to_copy.push_back(CopyAttachmentFrom());
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argStreamData(char* parameter)
|
||||
{
|
||||
@ -2617,6 +2783,134 @@ ArgParser::argRequiresPassword()
|
||||
o.require_outfile = false;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAApositional(char* arg)
|
||||
{
|
||||
o.attachments_to_add.back().path = arg;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAAKey(char* parameter)
|
||||
{
|
||||
o.attachments_to_add.back().key = parameter;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAAFilename(char* parameter)
|
||||
{
|
||||
o.attachments_to_add.back().filename = parameter;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAACreationDate(char* parameter)
|
||||
{
|
||||
if (! QUtil::pdf_time_to_qpdf_time(parameter))
|
||||
{
|
||||
usage(std::string(parameter) + " is not a valid PDF timestamp");
|
||||
}
|
||||
o.attachments_to_add.back().creationdate = parameter;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAAModDate(char* parameter)
|
||||
{
|
||||
if (! QUtil::pdf_time_to_qpdf_time(parameter))
|
||||
{
|
||||
usage(std::string(parameter) + " is not a valid PDF timestamp");
|
||||
}
|
||||
o.attachments_to_add.back().moddate = parameter;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAAMimeType(char* parameter)
|
||||
{
|
||||
if (strchr(parameter, '/') == nullptr)
|
||||
{
|
||||
usage("mime type should be specified as type/subtype");
|
||||
}
|
||||
o.attachments_to_add.back().mimetype = parameter;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAADescription(char* parameter)
|
||||
{
|
||||
o.attachments_to_add.back().description = parameter;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argAAReplace()
|
||||
{
|
||||
o.attachments_to_add.back().replace = true;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argEndAddAttachment()
|
||||
{
|
||||
static std::string now = QUtil::qpdf_time_to_pdf_time(
|
||||
QUtil::get_current_qpdf_time());
|
||||
this->option_table = &(this->main_option_table);
|
||||
auto& cur = o.attachments_to_add.back();
|
||||
if (cur.path.empty())
|
||||
{
|
||||
usage("add attachment: no path specified");
|
||||
}
|
||||
std::string last_element = cur.path;
|
||||
size_t pathsep = cur.path.find_last_of("/\\");
|
||||
if (pathsep != std::string::npos)
|
||||
{
|
||||
last_element = cur.path.substr(pathsep + 1);
|
||||
if (last_element.empty())
|
||||
{
|
||||
usage("path for --add-attachment may not end"
|
||||
" with a path separator");
|
||||
}
|
||||
}
|
||||
if (cur.filename.empty())
|
||||
{
|
||||
cur.filename = last_element;
|
||||
}
|
||||
if (cur.key.empty())
|
||||
{
|
||||
cur.key = last_element;
|
||||
}
|
||||
if (cur.creationdate.empty())
|
||||
{
|
||||
cur.creationdate = now;
|
||||
}
|
||||
if (cur.moddate.empty())
|
||||
{
|
||||
cur.moddate = now;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argCApositional(char* arg)
|
||||
{
|
||||
o.attachments_to_copy.back().path = arg;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argCAprefix(char* parameter)
|
||||
{
|
||||
o.attachments_to_copy.back().prefix = parameter;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argCApassword(char* parameter)
|
||||
{
|
||||
o.attachments_to_copy.back().password = parameter;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argEndCopyAttachments()
|
||||
{
|
||||
this->option_table = &(this->main_option_table);
|
||||
if (o.attachments_to_copy.back().path.empty())
|
||||
{
|
||||
usage("copy attachments: no path specified");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::handleArgFileArguments()
|
||||
{
|
||||
@ -3768,6 +4062,66 @@ static void do_show_pages(QPDF& pdf, Options& o)
|
||||
}
|
||||
}
|
||||
|
||||
static void do_list_attachments(QPDF& pdf, Options& o)
|
||||
{
|
||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||
if (efdh.hasEmbeddedFiles())
|
||||
{
|
||||
for (auto const& i: efdh.getEmbeddedFiles())
|
||||
{
|
||||
std::string const& key = i.first;
|
||||
auto efoh = i.second;
|
||||
std::cout << key << " -> "
|
||||
<< efoh->getEmbeddedFileStream().getObjGen()
|
||||
<< std::endl;
|
||||
if (o.verbose)
|
||||
{
|
||||
auto desc = efoh->getDescription();
|
||||
if (! desc.empty())
|
||||
{
|
||||
std::cout << " description: " << desc << std::endl;
|
||||
}
|
||||
std::cout << " preferred name: " << efoh->getFilename()
|
||||
<< std::endl;
|
||||
std::cout << " all names:" << std::endl;
|
||||
for (auto const& i2: efoh->getFilenames())
|
||||
{
|
||||
std::cout << " " << i2.first << " -> " << i2.second
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << " all data streams:" << std::endl;
|
||||
for (auto i2: QPDFDictItems(efoh->getEmbeddedFileStreams()))
|
||||
{
|
||||
std::cout << " " << i2.first << " -> "
|
||||
<< i2.second.getObjGen()
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << o.infilename << " has no embedded files" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_show_attachment(QPDF& pdf, Options& o, int& exit_code)
|
||||
{
|
||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||
auto fs = efdh.getEmbeddedFile(o.attachment_to_show);
|
||||
if (! fs)
|
||||
{
|
||||
std::cerr << whoami << ": attachment " << o.attachment_to_show
|
||||
<< " not found" << std::endl;
|
||||
exit_code = EXIT_ERROR;
|
||||
return;
|
||||
}
|
||||
auto efs = fs->getEmbeddedFileStream();
|
||||
QUtil::binary_stdout();
|
||||
Pl_StdioFile out("stdout", stdout);
|
||||
efs.pipeStreamData(&out, 0, qpdf_dl_all);
|
||||
}
|
||||
|
||||
static std::set<QPDFObjGen>
|
||||
get_wanted_json_objects(Options& o)
|
||||
{
|
||||
@ -4354,6 +4708,14 @@ static void do_inspection(QPDF& pdf, Options& o)
|
||||
{
|
||||
do_show_pages(pdf, o);
|
||||
}
|
||||
if (o.list_attachments)
|
||||
{
|
||||
do_list_attachments(pdf, o);
|
||||
}
|
||||
if (! o.attachment_to_show.empty())
|
||||
{
|
||||
do_show_attachment(pdf, o, exit_code);
|
||||
}
|
||||
if ((! pdf.getWarnings().empty()) && (exit_code != EXIT_ERROR))
|
||||
{
|
||||
std::cerr << whoami
|
||||
@ -4858,7 +5220,106 @@ static void handle_under_overlay(QPDF& pdf, Options& o)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_transformations(QPDF& pdf, Options& o)
|
||||
static void maybe_set_pagemode(QPDF& pdf, std::string const& pagemode)
|
||||
{
|
||||
auto root = pdf.getRoot();
|
||||
if (root.getKey("/PageMode").isNull())
|
||||
{
|
||||
root.replaceKey("/PageMode", QPDFObjectHandle::newName(pagemode));
|
||||
}
|
||||
}
|
||||
|
||||
static void add_attachments(QPDF& pdf, Options& o, int& exit_code)
|
||||
{
|
||||
maybe_set_pagemode(pdf, "/UseAttachments");
|
||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||
for (auto const& to_add: o.attachments_to_add)
|
||||
{
|
||||
if ((! to_add.replace) && efdh.getEmbeddedFile(to_add.key))
|
||||
{
|
||||
std::cerr << whoami << ": " << pdf.getFilename()
|
||||
<< " already has an attachment with key = "
|
||||
<< to_add.key << "; use --replace to replace"
|
||||
<< " or --key to specificy a different key"
|
||||
<< std::endl;
|
||||
exit_code = EXIT_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto fs = QPDFFileSpecObjectHelper::createFileSpec(
|
||||
pdf, to_add.filename, to_add.path);
|
||||
if (! to_add.description.empty())
|
||||
{
|
||||
fs.setDescription(to_add.description);
|
||||
}
|
||||
auto efs = QPDFEFStreamObjectHelper(fs.getEmbeddedFileStream());
|
||||
efs.setCreationDate(to_add.creationdate)
|
||||
.setModDate(to_add.moddate);
|
||||
if (! to_add.mimetype.empty())
|
||||
{
|
||||
efs.setSubtype(to_add.mimetype);
|
||||
}
|
||||
|
||||
efdh.replaceEmbeddedFile(to_add.key, fs);
|
||||
if (o.verbose)
|
||||
{
|
||||
std::cout << whoami << ": attached " << to_add.path
|
||||
<< " as " << to_add.filename
|
||||
<< " with key " << to_add.key << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_attachments(QPDF& pdf, Options& o, int& exit_code)
|
||||
{
|
||||
maybe_set_pagemode(pdf, "/UseAttachments");
|
||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||
for (auto const& to_copy: o.attachments_to_copy)
|
||||
{
|
||||
auto other = process_file(
|
||||
to_copy.path.c_str(), to_copy.password.c_str(), o);
|
||||
QPDFEmbeddedFileDocumentHelper other_efdh(*other);
|
||||
auto other_attachments = other_efdh.getEmbeddedFiles();
|
||||
for (auto const& iter: other_attachments)
|
||||
{
|
||||
if (o.verbose)
|
||||
{
|
||||
std::cout << whoami << ": copying attachments from "
|
||||
<< to_copy.path << std::endl;
|
||||
}
|
||||
std::string new_key = to_copy.prefix + iter.first;
|
||||
if (efdh.getEmbeddedFile(new_key))
|
||||
{
|
||||
exit_code = EXIT_ERROR;
|
||||
std::cerr << whoami << to_copy.path << " and "
|
||||
<< pdf.getFilename()
|
||||
<< " both have attachments with key " << new_key
|
||||
<< "; use --prefix with --copy-attachments-from"
|
||||
<< " or manually copy individual attachments"
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto new_fs_oh = pdf.copyForeignObject(
|
||||
iter.second->getObjectHandle());
|
||||
efdh.replaceEmbeddedFile(
|
||||
new_key, QPDFFileSpecObjectHelper(new_fs_oh));
|
||||
if (o.verbose)
|
||||
{
|
||||
std::cout << " " << iter.first << " -> " << new_key
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((other->anyWarnings()) && (exit_code == 0))
|
||||
{
|
||||
exit_code = EXIT_WARNING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_transformations(QPDF& pdf, Options& o, int& exit_code)
|
||||
{
|
||||
QPDFPageDocumentHelper dh(pdf);
|
||||
if (o.externalize_inline_images)
|
||||
@ -4935,6 +5396,35 @@ static void handle_transformations(QPDF& pdf, Options& o)
|
||||
{
|
||||
pdf.getRoot().removeKey("/PageLabels");
|
||||
}
|
||||
if (! o.attachments_to_remove.empty())
|
||||
{
|
||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||
for (auto const& key: o.attachments_to_remove)
|
||||
{
|
||||
if (efdh.removeEmbeddedFile(key))
|
||||
{
|
||||
if (o.verbose)
|
||||
{
|
||||
std::cout << whoami <<
|
||||
": removed attachment " << key << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << whoami <<
|
||||
": attachment " << key << " not found" << std::endl;
|
||||
exit_code = EXIT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! o.attachments_to_add.empty())
|
||||
{
|
||||
add_attachments(pdf, o, exit_code);
|
||||
}
|
||||
if (! o.attachments_to_copy.empty())
|
||||
{
|
||||
copy_attachments(pdf, o, exit_code);
|
||||
}
|
||||
}
|
||||
|
||||
static bool should_remove_unreferenced_resources(QPDF& pdf, Options& o)
|
||||
@ -5854,6 +6344,7 @@ int realmain(int argc, char* argv[])
|
||||
Options o;
|
||||
ArgParser ap(argc, argv, o);
|
||||
|
||||
int exit_code = 0;
|
||||
try
|
||||
{
|
||||
ap.parseOptions();
|
||||
@ -5906,7 +6397,7 @@ int realmain(int argc, char* argv[])
|
||||
handle_rotations(pdf, o);
|
||||
}
|
||||
handle_under_overlay(pdf, o);
|
||||
handle_transformations(pdf, o);
|
||||
handle_transformations(pdf, o, exit_code);
|
||||
|
||||
if ((o.outfilename == 0) && (! o.replace_input))
|
||||
{
|
||||
@ -5929,7 +6420,10 @@ int realmain(int argc, char* argv[])
|
||||
<< std::endl;
|
||||
}
|
||||
// Still return with warning code even if warnings were suppressed.
|
||||
return EXIT_WARNING;
|
||||
if (exit_code == 0)
|
||||
{
|
||||
exit_code = EXIT_WARNING;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
@ -5938,7 +6432,7 @@ int realmain(int argc, char* argv[])
|
||||
return EXIT_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS_WMAIN
|
||||
|
@ -523,7 +523,7 @@ $td->runtest("page operations on form xobject",
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- File Attachments ---");
|
||||
$n_tests += 4;
|
||||
$n_tests += 33;
|
||||
|
||||
open(F, ">auto-txt") or die;
|
||||
print F "from file";
|
||||
@ -532,16 +532,183 @@ $td->runtest("attachments",
|
||||
{$td->COMMAND => "test_driver 76 minimal.pdf auto-txt"},
|
||||
{$td->FILE => "test76.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("show attachment",
|
||||
{$td->COMMAND => "qpdf --show-attachment=att1 a.pdf"},
|
||||
{$td->STRING => "from file", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "test76.pdf"});
|
||||
$td->runtest("attachments",
|
||||
$td->runtest("list attachments",
|
||||
{$td->COMMAND => "qpdf --list-attachments a.pdf"},
|
||||
{$td->FILE => "test76-list.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("list attachments verbose",
|
||||
{$td->COMMAND => "qpdf --list-attachments --verbose a.pdf"},
|
||||
{$td->FILE => "test76-list-verbose.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("remove attachment (test_driver)",
|
||||
{$td->COMMAND => "test_driver 77 test76.pdf"},
|
||||
{$td->STRING => "test 77 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "test77.pdf"});
|
||||
$td->runtest("remove attachment (cli)",
|
||||
{$td->COMMAND => "qpdf --remove-attachment=att2 test76.pdf" .
|
||||
" --static-id --qdf --verbose b.pdf"},
|
||||
{$td->FILE => "remove-attachment.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "b.pdf"},
|
||||
{$td->FILE => "test77.pdf"});
|
||||
$td->runtest("show missing attachment",
|
||||
{$td->COMMAND => "qpdf --show-attachment=att2 b.pdf"},
|
||||
{$td->STRING => "qpdf: attachment att2 not found\n",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("remove missing attachment",
|
||||
{$td->COMMAND => "qpdf --remove-attachment=att2 b.pdf c.pdf"},
|
||||
{$td->STRING => "qpdf: attachment att2 not found\n",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("add attachment: bad creation date",
|
||||
{$td->COMMAND => "qpdf minimal.pdf a.pdf" .
|
||||
" --add-attachment auto-txt --creationdate=potato --"},
|
||||
{$td->REGEXP => ".*potato is not a valid PDF timestamp.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("add attachment: bad mod date",
|
||||
{$td->COMMAND => "qpdf minimal.pdf a.pdf" .
|
||||
" --add-attachment auto-txt --moddate=potato --"},
|
||||
{$td->REGEXP => ".*potato is not a valid PDF timestamp.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("add attachment: bad mod date",
|
||||
{$td->COMMAND => "qpdf minimal.pdf a.pdf" .
|
||||
" --add-attachment auto-txt --mimetype=potato --"},
|
||||
{$td->REGEXP =>
|
||||
".*mime type should be specified as type/subtype.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("add attachment: trailing slash",
|
||||
{$td->COMMAND => "qpdf minimal.pdf a.pdf" .
|
||||
" --add-attachment auto-txt/ --"},
|
||||
{$td->REGEXP => ".*may not end with a path separator.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("add attachment: trailing slash",
|
||||
{$td->COMMAND => "qpdf minimal.pdf a.pdf" .
|
||||
" --add-attachment --"},
|
||||
{$td->REGEXP => ".*add attachment: no path specified.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
foreach my $i (qw(1 2 3))
|
||||
{
|
||||
open(F, ">auto-$i") or die;
|
||||
print F "attachment $i";
|
||||
close(F);
|
||||
}
|
||||
my @dates = ("--creationdate=D:20210210091359-05'00'",
|
||||
"--moddate=D:20210210141359Z");
|
||||
$td->runtest("add attachments",
|
||||
{$td->COMMAND =>
|
||||
[qw(qpdf minimal.pdf a.pdf --no-original-object-ids),
|
||||
qw(--verbose --static-id --qdf),
|
||||
qw(--add-attachment ./auto-1), @dates,
|
||||
qw(--mimetype=text/plain --),
|
||||
qw(--add-attachment ./auto-2 --key=auto-Two), @dates, '--',
|
||||
qw(--add-attachment ./auto-3 --filename=auto-Three.txt),
|
||||
@dates, '--description=two words', '--']},
|
||||
{$td->FILE => "add-attachments-1.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("list attachments",
|
||||
{$td->COMMAND => "qpdf --list-attachments a.pdf --verbose"},
|
||||
{$td->FILE => "list-attachments-1.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "add-attachments-1.pdf"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("add attachments: duplicate",
|
||||
{$td->COMMAND =>
|
||||
"qpdf a.pdf b.pdf --verbose --add-attachment ./auto-1 --"},
|
||||
{$td->FILE => "add-attachments-duplicate.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("add attachments: replace",
|
||||
{$td->COMMAND =>
|
||||
[qw(qpdf a.pdf b.pdf --no-original-object-ids),
|
||||
qw(--verbose --static-id --qdf),
|
||||
qw(--add-attachment ./auto-2 --key=auto-1 --replace),
|
||||
@dates, '--']},
|
||||
{$td->FILE => "add-attachments-2.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("list attachments",
|
||||
{$td->COMMAND => "qpdf --list-attachments b.pdf --verbose"},
|
||||
{$td->FILE => "list-attachments-3.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "b.pdf"},
|
||||
{$td->FILE => "add-attachments-2.pdf"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("copy attachments",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --verbose --no-original-object-ids" .
|
||||
" --static-id --qdf minimal.pdf b.pdf" .
|
||||
" --copy-attachments-from a.pdf --"},
|
||||
{$td->FILE => "copy-attachments-1.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("list attachments",
|
||||
{$td->COMMAND => "qpdf --list-attachments b.pdf --verbose"},
|
||||
{$td->FILE => "list-attachments-1.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "b.pdf"},
|
||||
{$td->FILE => "add-attachments-1.pdf"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("copy attachments: duplicate",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --verbose --no-original-object-ids" .
|
||||
" --static-id --qdf a.pdf c.pdf" .
|
||||
" --copy-attachments-from b.pdf --"},
|
||||
{$td->FILE => "copy-attachments-duplicate.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("copy attachments: prefix",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --verbose --no-original-object-ids" .
|
||||
" --static-id --qdf a.pdf c.pdf" .
|
||||
" --copy-attachments-from b.pdf --prefix=1- --"},
|
||||
{$td->FILE => "copy-attachments-2.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("list attachments",
|
||||
{$td->COMMAND => "qpdf --list-attachments c.pdf --verbose"},
|
||||
{$td->FILE => "list-attachments-2.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "c.pdf"},
|
||||
{$td->FILE => "copy-attachments-2.pdf"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("add attachments: current date",
|
||||
{$td->COMMAND =>
|
||||
[qw(qpdf minimal.pdf a.pdf --encrypt u o 256 --),
|
||||
qw(--verbose --add-attachment ./auto-1 --)]},
|
||||
{$td->FILE => "add-attachments-3.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("list attachments",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --password=u --list-attachments a.pdf --verbose"},
|
||||
{$td->FILE => "list-attachments-4.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
# The object to show here is the one in list-attachments-4.out
|
||||
$td->runtest("check dates",
|
||||
{$td->COMMAND => "qpdf --show-object=6 a.pdf --password=u"},
|
||||
{$td->REGEXP => ".*CreationDate \\(D:\\d+.*ModDate \\(D:\\d+.*",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
|
4
qpdf/qtest/qpdf/add-attachments-1.out
Normal file
4
qpdf/qtest/qpdf/add-attachments-1.out
Normal file
@ -0,0 +1,4 @@
|
||||
qpdf: attached ./auto-1 as auto-1 with key auto-1
|
||||
qpdf: attached ./auto-2 as auto-2 with key auto-Two
|
||||
qpdf: attached ./auto-3 as auto-Three.txt with key auto-3
|
||||
qpdf: wrote file a.pdf
|
223
qpdf/qtest/qpdf/add-attachments-1.pdf
Normal file
223
qpdf/qtest/qpdf/add-attachments-1.pdf
Normal file
@ -0,0 +1,223 @@
|
||||
%PDF-1.3
|
||||
%¿÷¢þ
|
||||
%QDF-1.0
|
||||
|
||||
1 0 obj
|
||||
<<
|
||||
/Names <<
|
||||
/EmbeddedFiles 2 0 R
|
||||
>>
|
||||
/PageMode /UseAttachments
|
||||
/Pages 3 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<<
|
||||
/Names [
|
||||
(auto-1)
|
||||
4 0 R
|
||||
(auto-3)
|
||||
5 0 R
|
||||
(auto-Two)
|
||||
6 0 R
|
||||
]
|
||||
>>
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
7 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<<
|
||||
/EF <<
|
||||
/F 8 0 R
|
||||
/UF 8 0 R
|
||||
>>
|
||||
/F (auto-1)
|
||||
/Type /Filespec
|
||||
/UF (auto-1)
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<<
|
||||
/Desc (two words)
|
||||
/EF <<
|
||||
/F 10 0 R
|
||||
/UF 10 0 R
|
||||
>>
|
||||
/F (auto-Three.txt)
|
||||
/Type /Filespec
|
||||
/UF (auto-Three.txt)
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<<
|
||||
/EF <<
|
||||
/F 12 0 R
|
||||
/UF 12 0 R
|
||||
>>
|
||||
/F (auto-2)
|
||||
/Type /Filespec
|
||||
/UF (auto-2)
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
7 0 obj
|
||||
<<
|
||||
/Contents 14 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
612
|
||||
792
|
||||
]
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 16 0 R
|
||||
>>
|
||||
/ProcSet 17 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <a857d18d3fc23ad412122ef040733331>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
/Subtype /text#2fplain
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 9 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 1
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
9 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <d6c7ac7cf295ae133fea186cfd068dab>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 11 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 3
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
11 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
12 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <9f991a5669c47a94f9350f53e3953e57>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 13 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 2
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
13 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
%% Contents for page 1
|
||||
14 0 obj
|
||||
<<
|
||||
/Length 15 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Potato) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
15 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
16 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
/Name /F1
|
||||
/Subtype /Type1
|
||||
/Type /Font
|
||||
>>
|
||||
endobj
|
||||
|
||||
17 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
]
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 18
|
||||
0000000000 65535 f
|
||||
0000000025 00000 n
|
||||
0000000149 00000 n
|
||||
0000000257 00000 n
|
||||
0000000329 00000 n
|
||||
0000000439 00000 n
|
||||
0000000587 00000 n
|
||||
0000000709 00000 n
|
||||
0000000904 00000 n
|
||||
0000001199 00000 n
|
||||
0000001218 00000 n
|
||||
0000001488 00000 n
|
||||
0000001508 00000 n
|
||||
0000001778 00000 n
|
||||
0000001821 00000 n
|
||||
0000001922 00000 n
|
||||
0000001942 00000 n
|
||||
0000002061 00000 n
|
||||
trailer <<
|
||||
/Root 1 0 R
|
||||
/Size 18
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
2097
|
||||
%%EOF
|
2
qpdf/qtest/qpdf/add-attachments-2.out
Normal file
2
qpdf/qtest/qpdf/add-attachments-2.out
Normal file
@ -0,0 +1,2 @@
|
||||
qpdf: attached ./auto-2 as auto-2 with key auto-1
|
||||
qpdf: wrote file b.pdf
|
222
qpdf/qtest/qpdf/add-attachments-2.pdf
Normal file
222
qpdf/qtest/qpdf/add-attachments-2.pdf
Normal file
@ -0,0 +1,222 @@
|
||||
%PDF-1.3
|
||||
%¿÷¢þ
|
||||
%QDF-1.0
|
||||
|
||||
1 0 obj
|
||||
<<
|
||||
/Names <<
|
||||
/EmbeddedFiles 2 0 R
|
||||
>>
|
||||
/PageMode /UseAttachments
|
||||
/Pages 3 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<<
|
||||
/Names [
|
||||
(auto-1)
|
||||
4 0 R
|
||||
(auto-3)
|
||||
5 0 R
|
||||
(auto-Two)
|
||||
6 0 R
|
||||
]
|
||||
>>
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
7 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<<
|
||||
/EF <<
|
||||
/F 8 0 R
|
||||
/UF 8 0 R
|
||||
>>
|
||||
/F (auto-2)
|
||||
/Type /Filespec
|
||||
/UF (auto-2)
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<<
|
||||
/Desc (two words)
|
||||
/EF <<
|
||||
/F 10 0 R
|
||||
/UF 10 0 R
|
||||
>>
|
||||
/F (auto-Three.txt)
|
||||
/Type /Filespec
|
||||
/UF (auto-Three.txt)
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<<
|
||||
/EF <<
|
||||
/F 12 0 R
|
||||
/UF 12 0 R
|
||||
>>
|
||||
/F (auto-2)
|
||||
/Type /Filespec
|
||||
/UF (auto-2)
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
7 0 obj
|
||||
<<
|
||||
/Contents 14 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
612
|
||||
792
|
||||
]
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 16 0 R
|
||||
>>
|
||||
/ProcSet 17 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <9f991a5669c47a94f9350f53e3953e57>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 9 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 2
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
9 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <d6c7ac7cf295ae133fea186cfd068dab>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 11 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 3
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
11 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
12 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <9f991a5669c47a94f9350f53e3953e57>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 13 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 2
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
13 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
%% Contents for page 1
|
||||
14 0 obj
|
||||
<<
|
||||
/Length 15 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Potato) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
15 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
16 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
/Name /F1
|
||||
/Subtype /Type1
|
||||
/Type /Font
|
||||
>>
|
||||
endobj
|
||||
|
||||
17 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
]
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 18
|
||||
0000000000 65535 f
|
||||
0000000025 00000 n
|
||||
0000000149 00000 n
|
||||
0000000257 00000 n
|
||||
0000000329 00000 n
|
||||
0000000439 00000 n
|
||||
0000000587 00000 n
|
||||
0000000709 00000 n
|
||||
0000000904 00000 n
|
||||
0000001172 00000 n
|
||||
0000001191 00000 n
|
||||
0000001461 00000 n
|
||||
0000001481 00000 n
|
||||
0000001751 00000 n
|
||||
0000001794 00000 n
|
||||
0000001895 00000 n
|
||||
0000001915 00000 n
|
||||
0000002034 00000 n
|
||||
trailer <<
|
||||
/Root 1 0 R
|
||||
/Size 18
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
2070
|
||||
%%EOF
|
2
qpdf/qtest/qpdf/add-attachments-3.out
Normal file
2
qpdf/qtest/qpdf/add-attachments-3.out
Normal file
@ -0,0 +1,2 @@
|
||||
qpdf: attached ./auto-1 as auto-1 with key auto-1
|
||||
qpdf: wrote file a.pdf
|
2
qpdf/qtest/qpdf/add-attachments-duplicate.out
Normal file
2
qpdf/qtest/qpdf/add-attachments-duplicate.out
Normal file
@ -0,0 +1,2 @@
|
||||
qpdf: a.pdf already has an attachment with key = auto-1; use --replace to replace or --key to specificy a different key
|
||||
qpdf: wrote file b.pdf
|
7
qpdf/qtest/qpdf/copy-attachments-1.out
Normal file
7
qpdf/qtest/qpdf/copy-attachments-1.out
Normal file
@ -0,0 +1,7 @@
|
||||
qpdf: copying attachments from a.pdf
|
||||
auto-1 -> auto-1
|
||||
qpdf: copying attachments from a.pdf
|
||||
auto-3 -> auto-3
|
||||
qpdf: copying attachments from a.pdf
|
||||
auto-Two -> auto-Two
|
||||
qpdf: wrote file b.pdf
|
7
qpdf/qtest/qpdf/copy-attachments-2.out
Normal file
7
qpdf/qtest/qpdf/copy-attachments-2.out
Normal file
@ -0,0 +1,7 @@
|
||||
qpdf: copying attachments from b.pdf
|
||||
auto-1 -> 1-auto-1
|
||||
qpdf: copying attachments from b.pdf
|
||||
auto-3 -> 1-auto-3
|
||||
qpdf: copying attachments from b.pdf
|
||||
auto-Two -> 1-auto-Two
|
||||
qpdf: wrote file c.pdf
|
339
qpdf/qtest/qpdf/copy-attachments-2.pdf
Normal file
339
qpdf/qtest/qpdf/copy-attachments-2.pdf
Normal file
@ -0,0 +1,339 @@
|
||||
%PDF-1.3
|
||||
%¿÷¢þ
|
||||
%QDF-1.0
|
||||
|
||||
1 0 obj
|
||||
<<
|
||||
/Names <<
|
||||
/EmbeddedFiles 2 0 R
|
||||
>>
|
||||
/PageMode /UseAttachments
|
||||
/Pages 3 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<<
|
||||
/Names [
|
||||
(1-auto-1)
|
||||
4 0 R
|
||||
(1-auto-3)
|
||||
5 0 R
|
||||
(1-auto-Two)
|
||||
6 0 R
|
||||
(auto-1)
|
||||
7 0 R
|
||||
(auto-3)
|
||||
8 0 R
|
||||
(auto-Two)
|
||||
9 0 R
|
||||
]
|
||||
>>
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
10 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<<
|
||||
/EF <<
|
||||
/F 11 0 R
|
||||
/UF 11 0 R
|
||||
>>
|
||||
/F (auto-1)
|
||||
/Type /Filespec
|
||||
/UF (auto-1)
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<<
|
||||
/Desc (two words)
|
||||
/EF <<
|
||||
/F 13 0 R
|
||||
/UF 13 0 R
|
||||
>>
|
||||
/F (auto-Three.txt)
|
||||
/Type /Filespec
|
||||
/UF (auto-Three.txt)
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<<
|
||||
/EF <<
|
||||
/F 15 0 R
|
||||
/UF 15 0 R
|
||||
>>
|
||||
/F (auto-2)
|
||||
/Type /Filespec
|
||||
/UF (auto-2)
|
||||
>>
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
<<
|
||||
/EF <<
|
||||
/F 17 0 R
|
||||
/UF 17 0 R
|
||||
>>
|
||||
/F (auto-1)
|
||||
/Type /Filespec
|
||||
/UF (auto-1)
|
||||
>>
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<<
|
||||
/Desc (two words)
|
||||
/EF <<
|
||||
/F 19 0 R
|
||||
/UF 19 0 R
|
||||
>>
|
||||
/F (auto-Three.txt)
|
||||
/Type /Filespec
|
||||
/UF (auto-Three.txt)
|
||||
>>
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
<<
|
||||
/EF <<
|
||||
/F 21 0 R
|
||||
/UF 21 0 R
|
||||
>>
|
||||
/F (auto-2)
|
||||
/Type /Filespec
|
||||
/UF (auto-2)
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
10 0 obj
|
||||
<<
|
||||
/Contents 23 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
612
|
||||
792
|
||||
]
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 25 0 R
|
||||
>>
|
||||
/ProcSet 26 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
|
||||
11 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <a857d18d3fc23ad412122ef040733331>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
/Subtype /text#2fplain
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 12 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 1
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
12 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
13 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <d6c7ac7cf295ae133fea186cfd068dab>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 14 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 3
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
14 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
15 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <9f991a5669c47a94f9350f53e3953e57>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 16 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 2
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
16 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
17 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <a857d18d3fc23ad412122ef040733331>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
/Subtype /text#2fplain
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 18 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 1
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
18 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
19 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <d6c7ac7cf295ae133fea186cfd068dab>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 20 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 3
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
20 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
21 0 obj
|
||||
<<
|
||||
/Params <<
|
||||
/CheckSum <9f991a5669c47a94f9350f53e3953e57>
|
||||
/CreationDate (D:20210210091359-05'00')
|
||||
/ModDate (D:20210210141359Z)
|
||||
/Size 12
|
||||
>>
|
||||
/Type /EmbeddedFile
|
||||
/Length 22 0 R
|
||||
>>
|
||||
stream
|
||||
attachment 2
|
||||
endstream
|
||||
endobj
|
||||
|
||||
%QDF: ignore_newline
|
||||
22 0 obj
|
||||
12
|
||||
endobj
|
||||
|
||||
%% Contents for page 1
|
||||
23 0 obj
|
||||
<<
|
||||
/Length 24 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Potato) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
24 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
25 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
/Name /F1
|
||||
/Subtype /Type1
|
||||
/Type /Font
|
||||
>>
|
||||
endobj
|
||||
|
||||
26 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
]
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 27
|
||||
0000000000 65535 f
|
||||
0000000025 00000 n
|
||||
0000000149 00000 n
|
||||
0000000334 00000 n
|
||||
0000000407 00000 n
|
||||
0000000519 00000 n
|
||||
0000000667 00000 n
|
||||
0000000779 00000 n
|
||||
0000000891 00000 n
|
||||
0000001039 00000 n
|
||||
0000001161 00000 n
|
||||
0000001357 00000 n
|
||||
0000001654 00000 n
|
||||
0000001674 00000 n
|
||||
0000001944 00000 n
|
||||
0000001964 00000 n
|
||||
0000002234 00000 n
|
||||
0000002254 00000 n
|
||||
0000002551 00000 n
|
||||
0000002571 00000 n
|
||||
0000002841 00000 n
|
||||
0000002861 00000 n
|
||||
0000003131 00000 n
|
||||
0000003174 00000 n
|
||||
0000003275 00000 n
|
||||
0000003295 00000 n
|
||||
0000003414 00000 n
|
||||
trailer <<
|
||||
/Root 1 0 R
|
||||
/Size 27
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
3450
|
||||
%%EOF
|
7
qpdf/qtest/qpdf/copy-attachments-duplicate.out
Normal file
7
qpdf/qtest/qpdf/copy-attachments-duplicate.out
Normal file
@ -0,0 +1,7 @@
|
||||
qpdf: copying attachments from b.pdf
|
||||
qpdfb.pdf and a.pdf both have attachments with key auto-1; use --prefix with --copy-attachments-from or manually copy individual attachments
|
||||
qpdf: copying attachments from b.pdf
|
||||
qpdfb.pdf and a.pdf both have attachments with key auto-3; use --prefix with --copy-attachments-from or manually copy individual attachments
|
||||
qpdf: copying attachments from b.pdf
|
||||
qpdfb.pdf and a.pdf both have attachments with key auto-Two; use --prefix with --copy-attachments-from or manually copy individual attachments
|
||||
qpdf: wrote file c.pdf
|
25
qpdf/qtest/qpdf/list-attachments-1.out
Normal file
25
qpdf/qtest/qpdf/list-attachments-1.out
Normal file
@ -0,0 +1,25 @@
|
||||
auto-1 -> 8,0
|
||||
preferred name: auto-1
|
||||
all names:
|
||||
/F -> auto-1
|
||||
/UF -> auto-1
|
||||
all data streams:
|
||||
/F -> 8,0
|
||||
/UF -> 8,0
|
||||
auto-3 -> 10,0
|
||||
description: two words
|
||||
preferred name: auto-Three.txt
|
||||
all names:
|
||||
/F -> auto-Three.txt
|
||||
/UF -> auto-Three.txt
|
||||
all data streams:
|
||||
/F -> 10,0
|
||||
/UF -> 10,0
|
||||
auto-Two -> 12,0
|
||||
preferred name: auto-2
|
||||
all names:
|
||||
/F -> auto-2
|
||||
/UF -> auto-2
|
||||
all data streams:
|
||||
/F -> 12,0
|
||||
/UF -> 12,0
|
50
qpdf/qtest/qpdf/list-attachments-2.out
Normal file
50
qpdf/qtest/qpdf/list-attachments-2.out
Normal file
@ -0,0 +1,50 @@
|
||||
1-auto-1 -> 11,0
|
||||
preferred name: auto-1
|
||||
all names:
|
||||
/F -> auto-1
|
||||
/UF -> auto-1
|
||||
all data streams:
|
||||
/F -> 11,0
|
||||
/UF -> 11,0
|
||||
1-auto-3 -> 13,0
|
||||
description: two words
|
||||
preferred name: auto-Three.txt
|
||||
all names:
|
||||
/F -> auto-Three.txt
|
||||
/UF -> auto-Three.txt
|
||||
all data streams:
|
||||
/F -> 13,0
|
||||
/UF -> 13,0
|
||||
1-auto-Two -> 15,0
|
||||
preferred name: auto-2
|
||||
all names:
|
||||
/F -> auto-2
|
||||
/UF -> auto-2
|
||||
all data streams:
|
||||
/F -> 15,0
|
||||
/UF -> 15,0
|
||||
auto-1 -> 17,0
|
||||
preferred name: auto-1
|
||||
all names:
|
||||
/F -> auto-1
|
||||
/UF -> auto-1
|
||||
all data streams:
|
||||
/F -> 17,0
|
||||
/UF -> 17,0
|
||||
auto-3 -> 19,0
|
||||
description: two words
|
||||
preferred name: auto-Three.txt
|
||||
all names:
|
||||
/F -> auto-Three.txt
|
||||
/UF -> auto-Three.txt
|
||||
all data streams:
|
||||
/F -> 19,0
|
||||
/UF -> 19,0
|
||||
auto-Two -> 21,0
|
||||
preferred name: auto-2
|
||||
all names:
|
||||
/F -> auto-2
|
||||
/UF -> auto-2
|
||||
all data streams:
|
||||
/F -> 21,0
|
||||
/UF -> 21,0
|
25
qpdf/qtest/qpdf/list-attachments-3.out
Normal file
25
qpdf/qtest/qpdf/list-attachments-3.out
Normal file
@ -0,0 +1,25 @@
|
||||
auto-1 -> 8,0
|
||||
preferred name: auto-2
|
||||
all names:
|
||||
/F -> auto-2
|
||||
/UF -> auto-2
|
||||
all data streams:
|
||||
/F -> 8,0
|
||||
/UF -> 8,0
|
||||
auto-3 -> 10,0
|
||||
description: two words
|
||||
preferred name: auto-Three.txt
|
||||
all names:
|
||||
/F -> auto-Three.txt
|
||||
/UF -> auto-Three.txt
|
||||
all data streams:
|
||||
/F -> 10,0
|
||||
/UF -> 10,0
|
||||
auto-Two -> 12,0
|
||||
preferred name: auto-2
|
||||
all names:
|
||||
/F -> auto-2
|
||||
/UF -> auto-2
|
||||
all data streams:
|
||||
/F -> 12,0
|
||||
/UF -> 12,0
|
8
qpdf/qtest/qpdf/list-attachments-4.out
Normal file
8
qpdf/qtest/qpdf/list-attachments-4.out
Normal file
@ -0,0 +1,8 @@
|
||||
auto-1 -> 6,0
|
||||
preferred name: auto-1
|
||||
all names:
|
||||
/F -> auto-1
|
||||
/UF -> auto-1
|
||||
all data streams:
|
||||
/F -> 6,0
|
||||
/UF -> 6,0
|
2
qpdf/qtest/qpdf/remove-attachment.out
Normal file
2
qpdf/qtest/qpdf/remove-attachment.out
Normal file
@ -0,0 +1,2 @@
|
||||
qpdf: removed attachment att2
|
||||
qpdf: wrote file b.pdf
|
25
qpdf/qtest/qpdf/test76-list-verbose.out
Normal file
25
qpdf/qtest/qpdf/test76-list-verbose.out
Normal file
@ -0,0 +1,25 @@
|
||||
att1 -> 8,0
|
||||
description: some text
|
||||
preferred name: att1.txt
|
||||
all names:
|
||||
/F -> att1.txt
|
||||
/UF -> att1.txt
|
||||
all data streams:
|
||||
/F -> 8,0
|
||||
/UF -> 8,0
|
||||
att2 -> 10,0
|
||||
preferred name: att2.txt
|
||||
all names:
|
||||
/F -> att2.txt
|
||||
/UF -> att2.txt
|
||||
all data streams:
|
||||
/F -> 10,0
|
||||
/UF -> 10,0
|
||||
att3 -> 12,0
|
||||
preferred name: π.txt
|
||||
all names:
|
||||
/F -> att3.txt
|
||||
/UF -> π.txt
|
||||
all data streams:
|
||||
/F -> 12,0
|
||||
/UF -> 12,0
|
3
qpdf/qtest/qpdf/test76-list.out
Normal file
3
qpdf/qtest/qpdf/test76-list.out
Normal file
@ -0,0 +1,3 @@
|
||||
att1 -> 8,0
|
||||
att2 -> 10,0
|
||||
att3 -> 12,0
|
Loading…
Reference in New Issue
Block a user