Spaces:
Running
Running
//======================================================================== | |
// | |
// pdfseparate.cc | |
// | |
// This file is licensed under the GPLv2 or later | |
// | |
// Copyright (C) 2011, 2012, 2015 Thomas Freitag <[email protected]> | |
// Copyright (C) 2012-2014, 2017, 2018, 2021, 2022 Albert Astals Cid <[email protected]> | |
// Copyright (C) 2013, 2016 Pino Toscano <[email protected]> | |
// Copyright (C) 2013 Daniel Kahn Gillmor <[email protected]> | |
// Copyright (C) 2013 Suzuki Toshiya <[email protected]> | |
// Copyright (C) 2017 Léonard Michelet <[email protected]> | |
// Copyright (C) 2017 Adrian Johnson <[email protected]> | |
// Copyright (C) 2018 Adam Reichold <[email protected]> | |
// Copyright (C) 2019 Oliver Sander <[email protected]> | |
// | |
//======================================================================== | |
static int firstPage = 0; | |
static int lastPage = 0; | |
static bool printVersion = false; | |
static bool printHelp = false; | |
static const ArgDesc argDesc[] = { { "-f", argInt, &firstPage, 0, "first page to extract" }, | |
{ "-l", argInt, &lastPage, 0, "last page to extract" }, | |
{ "-v", argFlag, &printVersion, 0, "print copyright and version info" }, | |
{ "-h", argFlag, &printHelp, 0, "print usage information" }, | |
{ "-help", argFlag, &printHelp, 0, "print usage information" }, | |
{ "--help", argFlag, &printHelp, 0, "print usage information" }, | |
{ "-?", argFlag, &printHelp, 0, "print usage information" }, | |
{} }; | |
static bool extractPages(const char *srcFileName, const char *destFileName) | |
{ | |
char pathName[4096]; | |
PDFDoc *doc = new PDFDoc(std::make_unique<GooString>(srcFileName)); | |
if (!doc->isOk()) { | |
error(errSyntaxError, -1, "Could not extract page(s) from damaged file ('{0:s}')", srcFileName); | |
delete doc; | |
return false; | |
} | |
// destFileName can have multiple %% and one %d | |
// We use auxDestFileName to replace all the valid % appearances | |
// by 'A' (random char that is not %), if at the end of replacing | |
// any of the valid appearances there is still any % around, the | |
// pattern is wrong | |
if (firstPage == 0 && lastPage == 0) { | |
firstPage = 1; | |
lastPage = doc->getNumPages(); | |
} | |
if (lastPage == 0) { | |
lastPage = doc->getNumPages(); | |
} | |
if (firstPage == 0) { | |
firstPage = 1; | |
} | |
if (lastPage < firstPage) { | |
error(errCommandLine, -1, "Wrong page range given: the first page ({0:d}) can not be after the last page ({1:d}).", firstPage, lastPage); | |
delete doc; | |
return false; | |
} | |
bool foundmatch = false; | |
char *auxDestFileName = strdup(destFileName); | |
char *p = strstr(auxDestFileName, "%d"); | |
if (p != nullptr) { | |
foundmatch = true; | |
*p = 'A'; | |
} else { | |
char pattern[6]; | |
for (int i = 2; i < 10; i++) { | |
sprintf(pattern, "%%0%dd", i); | |
p = strstr(auxDestFileName, pattern); | |
if (p != nullptr) { | |
foundmatch = true; | |
*p = 'A'; | |
break; | |
} | |
} | |
} | |
if (!foundmatch && firstPage != lastPage) { | |
error(errSyntaxError, -1, "'{0:s}' must contain '%d' (or any variant respecting printf format) if more than one page should be extracted, in order to print the page number", destFileName); | |
free(auxDestFileName); | |
delete doc; | |
return false; | |
} | |
// at this point auxDestFileName can only contain %% | |
p = strstr(auxDestFileName, "%%"); | |
while (p != nullptr) { | |
*p = 'A'; | |
*(p + 1) = 'A'; | |
p = strstr(p, "%%"); | |
} | |
// at this point any other % is wrong | |
p = strstr(auxDestFileName, "%"); | |
if (p != nullptr) { | |
error(errSyntaxError, -1, "'{0:s}' can only contain one '%d' pattern", destFileName); | |
free(auxDestFileName); | |
delete doc; | |
return false; | |
} | |
free(auxDestFileName); | |
for (int pageNo = firstPage; pageNo <= lastPage; pageNo++) { | |
snprintf(pathName, sizeof(pathName) - 1, destFileName, pageNo); | |
PDFDoc *pagedoc = new PDFDoc(std::make_unique<GooString>(srcFileName)); | |
int errCode = pagedoc->savePageAs(GooString(pathName), pageNo); | |
if (errCode != errNone) { | |
delete doc; | |
delete pagedoc; | |
return false; | |
} | |
delete pagedoc; | |
} | |
delete doc; | |
return true; | |
} | |
static constexpr int kOtherError = 99; | |
int main(int argc, char *argv[]) | |
{ | |
// parse args | |
Win32Console win32console(&argc, &argv); | |
const bool parseOK = parseArgs(argDesc, &argc, argv); | |
if (!parseOK || argc != 3 || printVersion || printHelp) { | |
fprintf(stderr, "pdfseparate version %s\n", PACKAGE_VERSION); | |
fprintf(stderr, "%s\n", popplerCopyright); | |
fprintf(stderr, "%s\n", xpdfCopyright); | |
if (!printVersion) { | |
printUsage("pdfseparate", "<PDF-sourcefile> <PDF-pattern-destfile>", argDesc); | |
} | |
if (printVersion || printHelp) { | |
return 0; | |
} else { | |
return kOtherError; | |
} | |
} | |
globalParams = std::make_unique<GlobalParams>(); | |
const bool extractOK = extractPages(argv[1], argv[2]); | |
return extractOK ? 0 : kOtherError; | |
} | |