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 | |
27 | static bool doReplace = false; |
28 | static bool printVersion = false; |
29 | static bool printHelp = false; |
30 | |
31 | static 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 | |
39 | static 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 | |
49 | int 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 | |