1//========================================================================
2//
3// pdfattach.cc
4//
5// This file is licensed under the GPLv2 or later
6//
7// Copyright (C) 2019-2022 Albert Astals Cid <aacid@kde.org>
8// Copyright (C) 2019, 2023 Oliver Sander <oliver.sander@tu-dresden.de>
9//
10// To see a description of the changes please see the Changelog file that
11// came with your tarball or type make ChangeLog if you are building from git
12//
13//========================================================================
14
15#include "config.h"
16#include <poppler-config.h>
17#include "gbasename.h"
18#include "parseargs.h"
19#include "GlobalParams.h"
20#include "PDFDoc.h"
21#include "PDFDocFactory.h"
22#include "Error.h"
23#include "ErrorCodes.h"
24#include "UTF.h"
25#include "Win32Console.h"
26
27static bool doReplace = false;
28static bool printVersion = false;
29static bool printHelp = false;
30
31static const ArgDesc argDesc[] = { { .arg: "-replace", .kind: argFlag, .val: &doReplace, .size: 0, .usage: "replace embedded file with same name (if it exists)" },
32 { .arg: "-v", .kind: argFlag, .val: &printVersion, .size: 0, .usage: "print copyright and version info" },
33 { .arg: "-h", .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" },
34 { .arg: "-help", .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" },
35 { .arg: "--help", .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" },
36 { .arg: "-?", .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" },
37 {} };
38
39static bool fileExists(const char *filePath)
40{
41 FILE *f = openFile(path: filePath, mode: "r");
42 if (f != nullptr) {
43 fclose(stream: f);
44 return true;
45 }
46 return false;
47}
48
49int main(int argc, char *argv[])
50{
51 Win32Console win32Console(&argc, &argv);
52
53 // parse args
54 const bool ok = parseArgs(args: argDesc, argc: &argc, argv);
55 if (!ok || argc != 4 || printVersion || printHelp) {
56 fprintf(stderr, format: "pdfattach version %s\n", PACKAGE_VERSION);
57 fprintf(stderr, format: "%s\n", popplerCopyright);
58 fprintf(stderr, format: "%s\n", xpdfCopyright);
59 if (!printVersion) {
60 printUsage(program: "pdfattach", otherArgs: "<input-PDF-file> <file-to-attach> <output-PDF-file>", args: argDesc);
61 }
62 return 99;
63 }
64 const GooString pdfFileName(argv[1]);
65 const std::string attachFilePath(argv[2]);
66
67 // init GlobalParams
68 globalParams = std::make_unique<GlobalParams>();
69
70 // open PDF file
71 std::unique_ptr<PDFDoc> doc(PDFDocFactory().createPDFDoc(uri: pdfFileName, ownerPassword: {}, userPassword: {}));
72
73 if (!doc->isOk()) {
74 fprintf(stderr, format: "Couldn't open %s\n", pdfFileName.c_str());
75 return 1;
76 }
77
78 std::unique_ptr<GooFile> attachFile(GooFile::open(fileName: attachFilePath));
79 if (!attachFile) {
80 fprintf(stderr, format: "Couldn't open %s\n", attachFilePath.c_str());
81 return 2;
82 }
83
84 if (fileExists(filePath: argv[3])) {
85 fprintf(stderr, format: "File %s already exists.\n", argv[3]);
86 return 3;
87 }
88
89 const std::string attachFileName = utf8ToUtf16WithBom(utf8: gbasename(filename: attachFilePath.c_str()));
90
91 if (!doReplace && doc->getCatalog()->hasEmbeddedFile(fileName: attachFileName)) {
92 fprintf(stderr, format: "There is already an embedded file named %s.\n", attachFileName.c_str());
93 return 4;
94 }
95
96 doc->getCatalog()->addEmbeddedFile(file: attachFile.get(), fileName: attachFileName);
97
98 const GooString outputPdfFilePath(argv[3]);
99 const int saveResult = doc->saveAs(name: outputPdfFilePath);
100 if (saveResult != errNone) {
101 fprintf(stderr, format: "Couldn't save the file properly.\n");
102 return 5;
103 }
104
105 return 0;
106}
107

source code of poppler/utils/pdfattach.cc