mirror of
https://github.com/simon987/antiword.git
synced 2025-04-10 13:06:41 +00:00
322 lines
8.0 KiB
C
322 lines
8.0 KiB
C
/*
|
|
* main_u.c
|
|
*
|
|
* Released under GPL
|
|
*
|
|
* Copyright (C) 1998-2004 A.J. van Os
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* Description:
|
|
* The main program of 'antiword' (Unix version)
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#if defined(__dos)
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
#endif /* __dos */
|
|
#if defined(__CYGWIN__) || defined(__CYGMING__)
|
|
# ifdef X_LOCALE
|
|
# include <X11/Xlocale.h>
|
|
# else
|
|
# include <locale.h>
|
|
# endif
|
|
#else
|
|
#include <locale.h>
|
|
#endif /* __CYGWIN__ || __CYGMING__ */
|
|
#if defined(N_PLAT_NLM)
|
|
#if !defined(_VA_LIST)
|
|
#include "NW-only/nw_os.h"
|
|
#endif /* !_VA_LIST */
|
|
#include "getopt.h"
|
|
#endif /* N_PLAT_NLM */
|
|
#include "version.h"
|
|
#include "antiword.h"
|
|
|
|
/* The name of this program */
|
|
static const char *szTask = NULL;
|
|
|
|
|
|
static void
|
|
vUsage(void)
|
|
{
|
|
fprintf(stderr, "\tName: %s\n", szTask);
|
|
fprintf(stderr, "\tPurpose: "PURPOSESTRING"\n");
|
|
fprintf(stderr, "\tAuthor: "AUTHORSTRING"\n");
|
|
fprintf(stderr, "\tVersion: "VERSIONSTRING);
|
|
#if defined(__dos)
|
|
fprintf(stderr, VERSIONSTRING2);
|
|
#endif /* __dos */
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "\tStatus: "STATUSSTRING"\n");
|
|
fprintf(stderr,
|
|
"\tUsage: %s [switches] wordfile1 [wordfile2 ...]\n", szTask);
|
|
fprintf(stderr,
|
|
"\tSwitches: [-f|-t|-a papersize|-p papersize|-x dtd]"
|
|
"[-m mapping][-w #][-i #][-Ls]\n");
|
|
fprintf(stderr, "\t\t-f formatted text output\n");
|
|
fprintf(stderr, "\t\t-t text output (default)\n");
|
|
fprintf(stderr, "\t\t-a <paper size name> Adobe PDF output\n");
|
|
fprintf(stderr, "\t\t-p <paper size name> PostScript output\n");
|
|
fprintf(stderr, "\t\t paper size like: a4, letter or legal\n");
|
|
fprintf(stderr, "\t\t-x <dtd> XML output\n");
|
|
fprintf(stderr, "\t\t like: db (DocBook)\n");
|
|
fprintf(stderr, "\t\t-m <mapping> character mapping file\n");
|
|
fprintf(stderr, "\t\t-w <width> in characters of text output\n");
|
|
fprintf(stderr, "\t\t-i <level> image level (PostScript only)\n");
|
|
fprintf(stderr, "\t\t-L use landscape mode (PostScript only)\n");
|
|
fprintf(stderr, "\t\t-r Show removed text\n");
|
|
fprintf(stderr, "\t\t-s Show hidden (by Word) text\n");
|
|
} /* end of vUsage */
|
|
|
|
/*
|
|
* pStdin2TmpFile - save stdin in a temporary file
|
|
*
|
|
* returns: the pointer to the temporary file or NULL
|
|
*/
|
|
static FILE *
|
|
pStdin2TmpFile(long *lFilesize)
|
|
{
|
|
FILE *pTmpFile;
|
|
size_t tSize;
|
|
BOOL bFailure;
|
|
UCHAR aucBytes[BUFSIZ];
|
|
|
|
DBG_MSG("pStdin2TmpFile");
|
|
|
|
fail(lFilesize == NULL);
|
|
|
|
/* Open the temporary file */
|
|
pTmpFile = tmpfile();
|
|
if (pTmpFile == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
#if defined(__dos)
|
|
/* Stdin must be read as a binary stream */
|
|
setmode(fileno(stdin), O_BINARY);
|
|
#endif /* __dos */
|
|
|
|
/* Copy stdin to the temporary file */
|
|
*lFilesize = 0;
|
|
bFailure = TRUE;
|
|
for (;;) {
|
|
tSize = fread(aucBytes, 1, sizeof(aucBytes), stdin);
|
|
if (tSize == 0) {
|
|
bFailure = feof(stdin) == 0;
|
|
break;
|
|
}
|
|
if (fwrite(aucBytes, 1, tSize, pTmpFile) != tSize) {
|
|
bFailure = TRUE;
|
|
break;
|
|
}
|
|
*lFilesize += (long)tSize;
|
|
}
|
|
|
|
#if defined(__dos)
|
|
/* Switch stdin back to a text stream */
|
|
setmode(fileno(stdin), O_TEXT);
|
|
#endif /* __dos */
|
|
|
|
/* Deal with the result of the copy action */
|
|
if (bFailure) {
|
|
*lFilesize = 0;
|
|
(void)fclose(pTmpFile);
|
|
return NULL;
|
|
}
|
|
rewind(pTmpFile);
|
|
return pTmpFile;
|
|
} /* end of pStdin2TmpFile */
|
|
|
|
/*
|
|
* bProcessFile - process a single file
|
|
*
|
|
* returns: TRUE when the given file is a supported Word file, otherwise FALSE
|
|
*/
|
|
static BOOL
|
|
bProcessFile(const char *szFilename)
|
|
{
|
|
FILE *pFile;
|
|
diagram_type *pDiag;
|
|
long lFilesize;
|
|
int iWordVersion;
|
|
BOOL bResult;
|
|
|
|
fail(szFilename == NULL || szFilename[0] == '\0');
|
|
|
|
DBG_MSG(szFilename);
|
|
|
|
if (szFilename[0] == '-' && szFilename[1] == '\0') {
|
|
pFile = pStdin2TmpFile(&lFilesize);
|
|
if (pFile == NULL) {
|
|
werr(0, "I can't save the standard input to a file");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
pFile = fopen(szFilename, "rb");
|
|
if (pFile == NULL) {
|
|
werr(0, "I can't open '%s' for reading", szFilename);
|
|
return FALSE;
|
|
}
|
|
|
|
lFilesize = lGetFilesize(szFilename);
|
|
if (lFilesize < 0) {
|
|
(void)fclose(pFile);
|
|
werr(0, "I can't get the size of '%s'", szFilename);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
iWordVersion = iGuessVersionNumber(pFile, lFilesize);
|
|
if (iWordVersion < 0 || iWordVersion == 3) {
|
|
if (bIsRtfFile(pFile)) {
|
|
werr(0, "%s is not a Word Document."
|
|
" It is probably a Rich Text Format file",
|
|
szFilename);
|
|
} if (bIsWordPerfectFile(pFile)) {
|
|
werr(0, "%s is not a Word Document."
|
|
" It is probably a Word Perfect file",
|
|
szFilename);
|
|
} else {
|
|
#if defined(__dos)
|
|
werr(0, "%s is not a Word Document or the filename"
|
|
" is not in the 8+3 format.", szFilename);
|
|
#else
|
|
werr(0, "%s is not a Word Document.", szFilename);
|
|
#endif /* __dos */
|
|
}
|
|
(void)fclose(pFile);
|
|
return FALSE;
|
|
}
|
|
/* Reset any reading done during file testing */
|
|
rewind(pFile);
|
|
|
|
pDiag = pCreateDiagram(szTask, szFilename);
|
|
if (pDiag == NULL) {
|
|
(void)fclose(pFile);
|
|
return FALSE;
|
|
}
|
|
|
|
bResult = bWordDecryptor(pFile, lFilesize, pDiag);
|
|
vDestroyDiagram(pDiag);
|
|
|
|
(void)fclose(pFile);
|
|
return bResult;
|
|
} /* end of bProcessFile */
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
options_type tOptions;
|
|
const char *szWordfile;
|
|
int iFirst, iIndex, iGoodCount;
|
|
BOOL bUsage, bMultiple, bUseTXT, bUseXML;
|
|
|
|
if (argc <= 0) {
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
szTask = szBasename(argv[0]);
|
|
|
|
if (argc <= 1) {
|
|
iFirst = 1;
|
|
bUsage = TRUE;
|
|
} else {
|
|
iFirst = iReadOptions(argc, argv);
|
|
bUsage = iFirst <= 0;
|
|
}
|
|
if (bUsage) {
|
|
vUsage();
|
|
return iFirst < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
}
|
|
|
|
#if defined(N_PLAT_NLM) && !defined(_VA_LIST)
|
|
nwinit();
|
|
#endif /* N_PLAT_NLM && !_VA_LIST */
|
|
|
|
vGetOptions(&tOptions);
|
|
|
|
#if !defined(__dos)
|
|
if (is_locale_utf8()) {
|
|
#if defined(__STDC_ISO_10646__)
|
|
/*
|
|
* If the user wants UTF-8 and the envirionment variables
|
|
* support UTF-8, than set the locale accordingly
|
|
*/
|
|
if (tOptions.eEncoding == encoding_utf_8) {
|
|
if (setlocale(LC_CTYPE, "") == NULL) {
|
|
werr(1, "Can't set the UTF-8 locale! "
|
|
"Check LANG, LC_CTYPE, LC_ALL.");
|
|
}
|
|
DBG_MSG("The UTF-8 locale has been set");
|
|
} else {
|
|
(void)setlocale(LC_CTYPE, "C");
|
|
}
|
|
#endif /* __STDC_ISO_10646__ */
|
|
} else {
|
|
if (setlocale(LC_CTYPE, "") == NULL) {
|
|
werr(0, "Can't set the locale! Will use defaults");
|
|
(void)setlocale(LC_CTYPE, "C");
|
|
}
|
|
DBG_MSG("The locale has been set");
|
|
}
|
|
#endif /* !__dos */
|
|
|
|
bMultiple = argc - iFirst > 1;
|
|
bUseTXT = tOptions.eConversionType == conversion_text ||
|
|
tOptions.eConversionType == conversion_fmt_text;
|
|
bUseXML = tOptions.eConversionType == conversion_xml;
|
|
iGoodCount = 0;
|
|
|
|
#if defined(__dos)
|
|
if (tOptions.eConversionType == conversion_pdf) {
|
|
/* PDF must be written as a binary stream */
|
|
setmode(fileno(stdout), O_BINARY);
|
|
}
|
|
#endif /* __dos */
|
|
|
|
if (bUseXML) {
|
|
fprintf(stdout,
|
|
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
|
"<!DOCTYPE %s PUBLIC \"-//OASIS//DTD DocBook XML V4.1.2//EN\"\n"
|
|
"\t\"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd\">\n",
|
|
bMultiple ? "set" : "book");
|
|
if (bMultiple) {
|
|
fprintf(stdout, "<set>\n");
|
|
}
|
|
}
|
|
|
|
for (iIndex = iFirst; iIndex < argc; iIndex++) {
|
|
if (bMultiple && bUseTXT) {
|
|
szWordfile = szBasename(argv[iIndex]);
|
|
fprintf(stdout, "::::::::::::::\n");
|
|
fprintf(stdout, "%s\n", szWordfile);
|
|
fprintf(stdout, "::::::::::::::\n");
|
|
}
|
|
if (bProcessFile(argv[iIndex])) {
|
|
iGoodCount++;
|
|
}
|
|
}
|
|
|
|
if (bMultiple && bUseXML) {
|
|
fprintf(stdout, "</set>\n");
|
|
}
|
|
|
|
DBG_DEC(iGoodCount);
|
|
return iGoodCount <= 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
} /* end of main */
|