1 //========================================================================
2 //
3 // pdfattach.cc
4 //
5 // This file is licensed under the GPLv2 or later
6 //
7 // Copyright (C) 2019-2021 Albert Astals Cid <aacid@kde.org>
8 // Copyright (C) 2019 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 "Win32Console.h"
25
26 static bool doReplace = false;
27 static bool printVersion = false;
28 static bool printHelp = false;
29
30 static const ArgDesc argDesc[] = { { "-replace", argFlag, &doReplace, 0, "replace embedded file with same name (if it exists)" },
31 { "-v", argFlag, &printVersion, 0, "print copyright and version info" },
32 { "-h", argFlag, &printHelp, 0, "print usage information" },
33 { "-help", argFlag, &printHelp, 0, "print usage information" },
34 { "--help", argFlag, &printHelp, 0, "print usage information" },
35 { "-?", argFlag, &printHelp, 0, "print usage information" },
36 {} };
37
fileExists(const char * filePath)38 static bool fileExists(const char *filePath)
39 {
40 FILE *f = openFile(filePath, "r");
41 if (f != nullptr) {
42 fclose(f);
43 return true;
44 }
45 return false;
46 }
47
main(int argc,char * argv[])48 int main(int argc, char *argv[])
49 {
50 Win32Console win32Console(&argc, &argv);
51
52 // parse args
53 const bool ok = parseArgs(argDesc, &argc, argv);
54 if (!ok || argc != 4 || printVersion || printHelp) {
55 fprintf(stderr, "pdfattach version %s\n", PACKAGE_VERSION);
56 fprintf(stderr, "%s\n", popplerCopyright);
57 fprintf(stderr, "%s\n", xpdfCopyright);
58 if (!printVersion) {
59 printUsage("pdfattach", "<input-PDF-file> <file-to-attach> <output-PDF-file>", argDesc);
60 }
61 return 99;
62 }
63 const GooString pdfFileName(argv[1]);
64 const std::string attachFilePath(argv[2]);
65
66 // init GlobalParams
67 globalParams = std::make_unique<GlobalParams>();
68
69 // open PDF file
70 std::unique_ptr<PDFDoc> doc(PDFDocFactory().createPDFDoc(pdfFileName, nullptr, nullptr));
71
72 if (!doc->isOk()) {
73 fprintf(stderr, "Couldn't open %s\n", pdfFileName.c_str());
74 return 1;
75 }
76
77 std::unique_ptr<GooFile> attachFile(GooFile::open(attachFilePath));
78 if (!attachFile) {
79 fprintf(stderr, "Couldn't open %s\n", attachFilePath.c_str());
80 return 2;
81 }
82
83 if (fileExists(argv[3])) {
84 fprintf(stderr, "File %s already exists.\n", argv[3]);
85 return 3;
86 }
87
88 const std::string attachFileName = gbasename(attachFilePath.c_str());
89
90 if (!doReplace && doc->getCatalog()->hasEmbeddedFile(attachFileName)) {
91 fprintf(stderr, "There is already an embedded file named %s.\n", attachFileName.c_str());
92 return 4;
93 }
94
95 doc->getCatalog()->addEmbeddedFile(attachFile.get(), attachFileName);
96
97 const GooString outputPdfFilePath(argv[3]);
98 const int saveResult = doc->saveAs(&outputPdfFilePath);
99 if (saveResult != errNone) {
100 fprintf(stderr, "Couldn't save the file properly.\n");
101 return 5;
102 }
103
104 return 0;
105 }
106