1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier * main_u.c
3f5736e95SDavid du Colombier *
4f5736e95SDavid du Colombier * Released under GPL
5f5736e95SDavid du Colombier *
6*25b329d5SDavid du Colombier * Copyright (C) 1998-2004 A.J. van Os
7f5736e95SDavid du Colombier *
8f5736e95SDavid du Colombier * This program is free software; you can redistribute it and/or
9f5736e95SDavid du Colombier * modify it under the terms of the GNU General Public License
10f5736e95SDavid du Colombier * as published by the Free Software Foundation; either version 2
11f5736e95SDavid du Colombier * of the License, or (at your option) any later version.
12f5736e95SDavid du Colombier *
13f5736e95SDavid du Colombier * This program is distributed in the hope that it will be useful,
14f5736e95SDavid du Colombier * but WITHOUT ANY WARRANTY; without even the implied warranty of
15f5736e95SDavid du Colombier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16f5736e95SDavid du Colombier * GNU General Public License for more details.
17f5736e95SDavid du Colombier *
18f5736e95SDavid du Colombier * You should have received a copy of the GNU General Public License
19f5736e95SDavid du Colombier * along with this program; if not, write to the Free Software
20f5736e95SDavid du Colombier * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21f5736e95SDavid du Colombier *
22f5736e95SDavid du Colombier * Description:
23f5736e95SDavid du Colombier * The main program of 'antiword' (Unix version)
24f5736e95SDavid du Colombier */
25f5736e95SDavid du Colombier
26f5736e95SDavid du Colombier #include <stdio.h>
27f5736e95SDavid du Colombier #include <stdlib.h>
28f5736e95SDavid du Colombier #if defined(__dos)
29f5736e95SDavid du Colombier #include <fcntl.h>
30f5736e95SDavid du Colombier #include <io.h>
31f5736e95SDavid du Colombier #endif /* __dos */
32*25b329d5SDavid du Colombier #if defined(__CYGWIN__) || defined(__CYGMING__)
33*25b329d5SDavid du Colombier # ifdef X_LOCALE
34*25b329d5SDavid du Colombier # include <X11/Xlocale.h>
35*25b329d5SDavid du Colombier # else
36f5736e95SDavid du Colombier # include <locale.h>
37*25b329d5SDavid du Colombier # endif
38*25b329d5SDavid du Colombier #else
39*25b329d5SDavid du Colombier #include <locale.h>
40*25b329d5SDavid du Colombier #endif /* __CYGWIN__ || __CYGMING__ */
41*25b329d5SDavid du Colombier #if defined(N_PLAT_NLM)
42*25b329d5SDavid du Colombier #if !defined(_VA_LIST)
43*25b329d5SDavid du Colombier #include "NW-only/nw_os.h"
44*25b329d5SDavid du Colombier #endif /* !_VA_LIST */
45*25b329d5SDavid du Colombier #include "getopt.h"
46*25b329d5SDavid du Colombier #endif /* N_PLAT_NLM */
47f5736e95SDavid du Colombier #include "version.h"
48f5736e95SDavid du Colombier #include "antiword.h"
49f5736e95SDavid du Colombier
50f5736e95SDavid du Colombier /* The name of this program */
51f5736e95SDavid du Colombier static const char *szTask = NULL;
52f5736e95SDavid du Colombier
53f5736e95SDavid du Colombier
54f5736e95SDavid du Colombier static void
vUsage(void)55f5736e95SDavid du Colombier vUsage(void)
56f5736e95SDavid du Colombier {
57f5736e95SDavid du Colombier fprintf(stderr, "\tName: %s\n", szTask);
58f5736e95SDavid du Colombier fprintf(stderr, "\tPurpose: "PURPOSESTRING"\n");
59f5736e95SDavid du Colombier fprintf(stderr, "\tAuthor: "AUTHORSTRING"\n");
60*25b329d5SDavid du Colombier fprintf(stderr, "\tVersion: "VERSIONSTRING);
61*25b329d5SDavid du Colombier #if defined(__dos)
62*25b329d5SDavid du Colombier fprintf(stderr, VERSIONSTRING2);
63*25b329d5SDavid du Colombier #endif /* __dos */
64*25b329d5SDavid du Colombier fprintf(stderr, "\n");
65f5736e95SDavid du Colombier fprintf(stderr, "\tStatus: "STATUSSTRING"\n");
66f5736e95SDavid du Colombier fprintf(stderr,
67f5736e95SDavid du Colombier "\tUsage: %s [switches] wordfile1 [wordfile2 ...]\n", szTask);
68f5736e95SDavid du Colombier fprintf(stderr,
69*25b329d5SDavid du Colombier "\tSwitches: [-f|-t|-a papersize|-p papersize|-x dtd]"
70*25b329d5SDavid du Colombier "[-m mapping][-w #][-i #][-Ls]\n");
71*25b329d5SDavid du Colombier fprintf(stderr, "\t\t-f formatted text output\n");
72f5736e95SDavid du Colombier fprintf(stderr, "\t\t-t text output (default)\n");
73*25b329d5SDavid du Colombier fprintf(stderr, "\t\t-a <paper size name> Adobe PDF output\n");
74f5736e95SDavid du Colombier fprintf(stderr, "\t\t-p <paper size name> PostScript output\n");
75*25b329d5SDavid du Colombier fprintf(stderr, "\t\t paper size like: a4, letter or legal\n");
76f5736e95SDavid du Colombier fprintf(stderr, "\t\t-x <dtd> XML output\n");
77f5736e95SDavid du Colombier fprintf(stderr, "\t\t like: db (DocBook)\n");
78f5736e95SDavid du Colombier fprintf(stderr, "\t\t-m <mapping> character mapping file\n");
79f5736e95SDavid du Colombier fprintf(stderr, "\t\t-w <width> in characters of text output\n");
80f5736e95SDavid du Colombier fprintf(stderr, "\t\t-i <level> image level (PostScript only)\n");
81f5736e95SDavid du Colombier fprintf(stderr, "\t\t-L use landscape mode (PostScript only)\n");
82*25b329d5SDavid du Colombier fprintf(stderr, "\t\t-r Show removed text\n");
83f5736e95SDavid du Colombier fprintf(stderr, "\t\t-s Show hidden (by Word) text\n");
84f5736e95SDavid du Colombier } /* end of vUsage */
85f5736e95SDavid du Colombier
86f5736e95SDavid du Colombier /*
87f5736e95SDavid du Colombier * pStdin2TmpFile - save stdin in a temporary file
88f5736e95SDavid du Colombier *
89f5736e95SDavid du Colombier * returns: the pointer to the temporary file or NULL
90f5736e95SDavid du Colombier */
91f5736e95SDavid du Colombier static FILE *
pStdin2TmpFile(long * lFilesize)92f5736e95SDavid du Colombier pStdin2TmpFile(long *lFilesize)
93f5736e95SDavid du Colombier {
94f5736e95SDavid du Colombier FILE *pTmpFile;
95f5736e95SDavid du Colombier size_t tSize;
96f5736e95SDavid du Colombier BOOL bFailure;
97f5736e95SDavid du Colombier UCHAR aucBytes[BUFSIZ];
98f5736e95SDavid du Colombier
99f5736e95SDavid du Colombier DBG_MSG("pStdin2TmpFile");
100f5736e95SDavid du Colombier
101f5736e95SDavid du Colombier fail(lFilesize == NULL);
102f5736e95SDavid du Colombier
103f5736e95SDavid du Colombier /* Open the temporary file */
104f5736e95SDavid du Colombier pTmpFile = tmpfile();
105f5736e95SDavid du Colombier if (pTmpFile == NULL) {
106f5736e95SDavid du Colombier return NULL;
107f5736e95SDavid du Colombier }
108f5736e95SDavid du Colombier
109f5736e95SDavid du Colombier #if defined(__dos)
110f5736e95SDavid du Colombier /* Stdin must be read as a binary stream */
111f5736e95SDavid du Colombier setmode(fileno(stdin), O_BINARY);
112f5736e95SDavid du Colombier #endif /* __dos */
113f5736e95SDavid du Colombier
114f5736e95SDavid du Colombier /* Copy stdin to the temporary file */
115f5736e95SDavid du Colombier *lFilesize = 0;
116f5736e95SDavid du Colombier bFailure = TRUE;
117f5736e95SDavid du Colombier for (;;) {
118f5736e95SDavid du Colombier tSize = fread(aucBytes, 1, sizeof(aucBytes), stdin);
119f5736e95SDavid du Colombier if (tSize == 0) {
120f5736e95SDavid du Colombier bFailure = feof(stdin) == 0;
121f5736e95SDavid du Colombier break;
122f5736e95SDavid du Colombier }
123f5736e95SDavid du Colombier if (fwrite(aucBytes, 1, tSize, pTmpFile) != tSize) {
124f5736e95SDavid du Colombier bFailure = TRUE;
125f5736e95SDavid du Colombier break;
126f5736e95SDavid du Colombier }
127f5736e95SDavid du Colombier *lFilesize += (long)tSize;
128f5736e95SDavid du Colombier }
129f5736e95SDavid du Colombier
130f5736e95SDavid du Colombier #if defined(__dos)
131f5736e95SDavid du Colombier /* Switch stdin back to a text stream */
132f5736e95SDavid du Colombier setmode(fileno(stdin), O_TEXT);
133f5736e95SDavid du Colombier #endif /* __dos */
134f5736e95SDavid du Colombier
135f5736e95SDavid du Colombier /* Deal with the result of the copy action */
136f5736e95SDavid du Colombier if (bFailure) {
137f5736e95SDavid du Colombier *lFilesize = 0;
138f5736e95SDavid du Colombier (void)fclose(pTmpFile);
139f5736e95SDavid du Colombier return NULL;
140f5736e95SDavid du Colombier }
141f5736e95SDavid du Colombier rewind(pTmpFile);
142f5736e95SDavid du Colombier return pTmpFile;
143f5736e95SDavid du Colombier } /* end of pStdin2TmpFile */
144f5736e95SDavid du Colombier
145f5736e95SDavid du Colombier /*
146f5736e95SDavid du Colombier * bProcessFile - process a single file
147f5736e95SDavid du Colombier *
148f5736e95SDavid du Colombier * returns: TRUE when the given file is a supported Word file, otherwise FALSE
149f5736e95SDavid du Colombier */
150f5736e95SDavid du Colombier static BOOL
bProcessFile(const char * szFilename)151f5736e95SDavid du Colombier bProcessFile(const char *szFilename)
152f5736e95SDavid du Colombier {
153f5736e95SDavid du Colombier FILE *pFile;
154f5736e95SDavid du Colombier diagram_type *pDiag;
155f5736e95SDavid du Colombier long lFilesize;
156f5736e95SDavid du Colombier int iWordVersion;
157f5736e95SDavid du Colombier BOOL bResult;
158f5736e95SDavid du Colombier
159f5736e95SDavid du Colombier fail(szFilename == NULL || szFilename[0] == '\0');
160f5736e95SDavid du Colombier
161f5736e95SDavid du Colombier DBG_MSG(szFilename);
162f5736e95SDavid du Colombier
163f5736e95SDavid du Colombier if (szFilename[0] == '-' && szFilename[1] == '\0') {
164f5736e95SDavid du Colombier pFile = pStdin2TmpFile(&lFilesize);
165f5736e95SDavid du Colombier if (pFile == NULL) {
166f5736e95SDavid du Colombier werr(0, "I can't save the standard input to a file");
167f5736e95SDavid du Colombier return FALSE;
168f5736e95SDavid du Colombier }
169f5736e95SDavid du Colombier } else {
170f5736e95SDavid du Colombier pFile = fopen(szFilename, "rb");
171f5736e95SDavid du Colombier if (pFile == NULL) {
172f5736e95SDavid du Colombier werr(0, "I can't open '%s' for reading", szFilename);
173f5736e95SDavid du Colombier return FALSE;
174f5736e95SDavid du Colombier }
175f5736e95SDavid du Colombier
176f5736e95SDavid du Colombier lFilesize = lGetFilesize(szFilename);
177f5736e95SDavid du Colombier if (lFilesize < 0) {
178f5736e95SDavid du Colombier (void)fclose(pFile);
179f5736e95SDavid du Colombier werr(0, "I can't get the size of '%s'", szFilename);
180f5736e95SDavid du Colombier return FALSE;
181f5736e95SDavid du Colombier }
182f5736e95SDavid du Colombier }
183f5736e95SDavid du Colombier
184f5736e95SDavid du Colombier iWordVersion = iGuessVersionNumber(pFile, lFilesize);
185f5736e95SDavid du Colombier if (iWordVersion < 0 || iWordVersion == 3) {
186f5736e95SDavid du Colombier if (bIsRtfFile(pFile)) {
187f5736e95SDavid du Colombier werr(0, "%s is not a Word Document."
188f5736e95SDavid du Colombier " It is probably a Rich Text Format file",
189f5736e95SDavid du Colombier szFilename);
190f5736e95SDavid du Colombier } if (bIsWordPerfectFile(pFile)) {
191f5736e95SDavid du Colombier werr(0, "%s is not a Word Document."
192f5736e95SDavid du Colombier " It is probably a Word Perfect file",
193f5736e95SDavid du Colombier szFilename);
194f5736e95SDavid du Colombier } else {
195f5736e95SDavid du Colombier #if defined(__dos)
196f5736e95SDavid du Colombier werr(0, "%s is not a Word Document or the filename"
197f5736e95SDavid du Colombier " is not in the 8+3 format.", szFilename);
198f5736e95SDavid du Colombier #else
199f5736e95SDavid du Colombier werr(0, "%s is not a Word Document.", szFilename);
200f5736e95SDavid du Colombier #endif /* __dos */
201f5736e95SDavid du Colombier }
202f5736e95SDavid du Colombier (void)fclose(pFile);
203f5736e95SDavid du Colombier return FALSE;
204f5736e95SDavid du Colombier }
205f5736e95SDavid du Colombier /* Reset any reading done during file testing */
206f5736e95SDavid du Colombier rewind(pFile);
207f5736e95SDavid du Colombier
208f5736e95SDavid du Colombier pDiag = pCreateDiagram(szTask, szFilename);
209f5736e95SDavid du Colombier if (pDiag == NULL) {
210f5736e95SDavid du Colombier (void)fclose(pFile);
211f5736e95SDavid du Colombier return FALSE;
212f5736e95SDavid du Colombier }
213f5736e95SDavid du Colombier
214f5736e95SDavid du Colombier bResult = bWordDecryptor(pFile, lFilesize, pDiag);
215f5736e95SDavid du Colombier vDestroyDiagram(pDiag);
216f5736e95SDavid du Colombier
217f5736e95SDavid du Colombier (void)fclose(pFile);
218f5736e95SDavid du Colombier return bResult;
219f5736e95SDavid du Colombier } /* end of bProcessFile */
220f5736e95SDavid du Colombier
221f5736e95SDavid du Colombier int
main(int argc,char ** argv)222f5736e95SDavid du Colombier main(int argc, char **argv)
223f5736e95SDavid du Colombier {
224f5736e95SDavid du Colombier options_type tOptions;
225f5736e95SDavid du Colombier const char *szWordfile;
226f5736e95SDavid du Colombier int iFirst, iIndex, iGoodCount;
227f5736e95SDavid du Colombier BOOL bUsage, bMultiple, bUseTXT, bUseXML;
228f5736e95SDavid du Colombier
229f5736e95SDavid du Colombier if (argc <= 0) {
230f5736e95SDavid du Colombier return EXIT_FAILURE;
231f5736e95SDavid du Colombier }
232f5736e95SDavid du Colombier
233f5736e95SDavid du Colombier szTask = szBasename(argv[0]);
234f5736e95SDavid du Colombier
235f5736e95SDavid du Colombier if (argc <= 1) {
236f5736e95SDavid du Colombier iFirst = 1;
237f5736e95SDavid du Colombier bUsage = TRUE;
238f5736e95SDavid du Colombier } else {
239f5736e95SDavid du Colombier iFirst = iReadOptions(argc, argv);
240f5736e95SDavid du Colombier bUsage = iFirst <= 0;
241f5736e95SDavid du Colombier }
242f5736e95SDavid du Colombier if (bUsage) {
243f5736e95SDavid du Colombier vUsage();
244f5736e95SDavid du Colombier return iFirst < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
245f5736e95SDavid du Colombier }
246f5736e95SDavid du Colombier
247*25b329d5SDavid du Colombier #if defined(N_PLAT_NLM) && !defined(_VA_LIST)
248*25b329d5SDavid du Colombier nwinit();
249*25b329d5SDavid du Colombier #endif /* N_PLAT_NLM && !_VA_LIST */
250*25b329d5SDavid du Colombier
251f5736e95SDavid du Colombier vGetOptions(&tOptions);
252f5736e95SDavid du Colombier
253*25b329d5SDavid du Colombier #if !defined(__dos)
254*25b329d5SDavid du Colombier if (is_locale_utf8()) {
255f5736e95SDavid du Colombier #if defined(__STDC_ISO_10646__)
256f5736e95SDavid du Colombier /*
257*25b329d5SDavid du Colombier * If the user wants UTF-8 and the envirionment variables
258*25b329d5SDavid du Colombier * support UTF-8, than set the locale accordingly
259f5736e95SDavid du Colombier */
260*25b329d5SDavid du Colombier if (tOptions.eEncoding == encoding_utf_8) {
261f5736e95SDavid du Colombier if (setlocale(LC_CTYPE, "") == NULL) {
262f5736e95SDavid du Colombier werr(1, "Can't set the UTF-8 locale! "
263f5736e95SDavid du Colombier "Check LANG, LC_CTYPE, LC_ALL.");
264f5736e95SDavid du Colombier }
265f5736e95SDavid du Colombier DBG_MSG("The UTF-8 locale has been set");
266*25b329d5SDavid du Colombier } else {
267*25b329d5SDavid du Colombier (void)setlocale(LC_CTYPE, "C");
268f5736e95SDavid du Colombier }
269f5736e95SDavid du Colombier #endif /* __STDC_ISO_10646__ */
270*25b329d5SDavid du Colombier } else {
271*25b329d5SDavid du Colombier if (setlocale(LC_CTYPE, "") == NULL) {
272*25b329d5SDavid du Colombier werr(0, "Can't set the locale! Will use defaults");
273*25b329d5SDavid du Colombier (void)setlocale(LC_CTYPE, "C");
274*25b329d5SDavid du Colombier }
275*25b329d5SDavid du Colombier DBG_MSG("The locale has been set");
276*25b329d5SDavid du Colombier }
277*25b329d5SDavid du Colombier #endif /* !__dos */
278f5736e95SDavid du Colombier
279f5736e95SDavid du Colombier bMultiple = argc - iFirst > 1;
280*25b329d5SDavid du Colombier bUseTXT = tOptions.eConversionType == conversion_text ||
281*25b329d5SDavid du Colombier tOptions.eConversionType == conversion_fmt_text;
282f5736e95SDavid du Colombier bUseXML = tOptions.eConversionType == conversion_xml;
283f5736e95SDavid du Colombier iGoodCount = 0;
284f5736e95SDavid du Colombier
285*25b329d5SDavid du Colombier #if defined(__dos)
286*25b329d5SDavid du Colombier if (tOptions.eConversionType == conversion_pdf) {
287*25b329d5SDavid du Colombier /* PDF must be written as a binary stream */
288*25b329d5SDavid du Colombier setmode(fileno(stdout), O_BINARY);
289*25b329d5SDavid du Colombier }
290*25b329d5SDavid du Colombier #endif /* __dos */
291*25b329d5SDavid du Colombier
292f5736e95SDavid du Colombier if (bUseXML) {
293f5736e95SDavid du Colombier fprintf(stdout,
294f5736e95SDavid du Colombier "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
295f5736e95SDavid du Colombier "<!DOCTYPE %s PUBLIC \"-//OASIS//DTD DocBook XML V4.1.2//EN\"\n"
296f5736e95SDavid du Colombier "\t\"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd\">\n",
297f5736e95SDavid du Colombier bMultiple ? "set" : "book");
298f5736e95SDavid du Colombier if (bMultiple) {
299f5736e95SDavid du Colombier fprintf(stdout, "<set>\n");
300f5736e95SDavid du Colombier }
301f5736e95SDavid du Colombier }
302f5736e95SDavid du Colombier
303f5736e95SDavid du Colombier for (iIndex = iFirst; iIndex < argc; iIndex++) {
304f5736e95SDavid du Colombier if (bMultiple && bUseTXT) {
305f5736e95SDavid du Colombier szWordfile = szBasename(argv[iIndex]);
306f5736e95SDavid du Colombier fprintf(stdout, "::::::::::::::\n");
307f5736e95SDavid du Colombier fprintf(stdout, "%s\n", szWordfile);
308f5736e95SDavid du Colombier fprintf(stdout, "::::::::::::::\n");
309f5736e95SDavid du Colombier }
310f5736e95SDavid du Colombier if (bProcessFile(argv[iIndex])) {
311f5736e95SDavid du Colombier iGoodCount++;
312f5736e95SDavid du Colombier }
313f5736e95SDavid du Colombier }
314f5736e95SDavid du Colombier
315f5736e95SDavid du Colombier if (bMultiple && bUseXML) {
316f5736e95SDavid du Colombier fprintf(stdout, "</set>\n");
317f5736e95SDavid du Colombier }
318f5736e95SDavid du Colombier
319f5736e95SDavid du Colombier DBG_DEC(iGoodCount);
320f5736e95SDavid du Colombier return iGoodCount <= 0 ? EXIT_FAILURE : EXIT_SUCCESS;
321f5736e95SDavid du Colombier } /* end of main */
322