1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2 /* libstaroffice
3 * Version: MPL 2.0 / LGPLv2+
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 2.0 (the "License"); you may not use this file except in compliance with
7 * the License or as specified alternatively below. You may obtain a copy of
8 * the License at http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * Major Contributor(s):
16 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
17 * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
18 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
19 * Copyright (C) 2006, 2007 Andrew Ziem
20 * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
21 *
22 *
23 * All Rights Reserved.
24 *
25 * For minor contributions see the git repository.
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
29 * in which case the provisions of the LGPLv2+ are applicable
30 * instead of those above.
31 */
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include <unistd.h>
36 
37 #include <librevenge/librevenge.h>
38 #include <librevenge-generators/librevenge-generators.h>
39 #include <librevenge-stream/librevenge-stream.h>
40 
41 #include <libstaroffice/libstaroffice.hxx>
42 
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46 
47 #ifndef VERSION
48 #define VERSION "UNKNOWN VERSION"
49 #endif
50 
51 #define TOOLNAME "sd2text"
52 
printUsage()53 static int printUsage()
54 {
55   printf("`" TOOLNAME "' converts StarOffice documents to plain text.\n");
56   printf("\n");
57   printf("Usage: " TOOLNAME " [OPTION] INPUT\n");
58   printf("\n");
59   printf("Options:\n");
60   printf("\t-i                show document metadata instead of the text\n");
61   printf("\t-h                show this help message\n");
62   printf("\t-o OUTPUT         write ouput to OUTPUT\n");
63   printf("\t-p PASSWORD       set password to open the file\n");
64   printf("\t-v                show version information\n");
65   printf("\n");
66   printf("Report bugs to <https://github.com/fosnola/libstaroffice/issues>.\n");
67   return 0;
68 }
69 
printVersion()70 static int printVersion()
71 {
72   printf("%s %s\n", TOOLNAME, VERSION);
73   return 0;
74 }
75 
main(int argc,char * argv[])76 int main(int argc, char *argv[])
77 {
78   if (argc < 2)
79     return printUsage();
80 
81   char const *output = nullptr;
82   char const *password=nullptr;
83   bool isInfo = false;
84   bool printHelp=false;
85   int ch;
86 
87   while ((ch = getopt(argc, argv, "hio:p:v")) != -1) {
88     switch (ch) {
89     case 'i':
90       isInfo=true;
91       break;
92     case 'o':
93       output=optarg;
94       break;
95     case 'p':
96       password=optarg;
97       break;
98     case 'v':
99       printVersion();
100       return 0;
101     default:
102     case 'h':
103       printHelp = true;
104       break;
105     }
106   }
107 
108   if (argc != 1+optind || printHelp) {
109     printUsage();
110     return -1;
111   }
112   librevenge::RVNGFileStream input(argv[optind]);
113 
114   STOFFDocument::Kind kind;
115   auto confidence = STOFFDocument::STOFF_C_NONE;
116   try {
117     confidence=STOFFDocument::isFileFormatSupported(&input, kind);
118   }
119   catch (...) {
120     confidence = STOFFDocument::STOFF_C_NONE;
121   }
122 
123   if (confidence != STOFFDocument::STOFF_C_EXCELLENT && confidence != STOFFDocument::STOFF_C_SUPPORTED_ENCRYPTION) {
124     printf("ERROR: Unsupported file format!\n");
125     return 1;
126   }
127 
128   librevenge::RVNGString document;
129   librevenge::RVNGStringVector pages;
130   bool useStringVector=false;
131   auto error = STOFFDocument::STOFF_R_OK;
132   try {
133     if (kind == STOFFDocument::STOFF_K_DRAW || kind == STOFFDocument::STOFF_K_GRAPHIC) {
134       if (isInfo) {
135         printf("ERROR: can not print info concerning a graphic document!\n");
136         return 1;
137       }
138       librevenge::RVNGTextDrawingGenerator documentGenerator(pages);
139       error=STOFFDocument::parse(&input, &documentGenerator, password);
140       if (error == STOFFDocument::STOFF_R_OK && !pages.size()) {
141         printf("ERROR: find no graphics!\n");
142         return 1;
143       }
144       useStringVector=true;
145     }
146     else if (kind == STOFFDocument::STOFF_K_SPREADSHEET || kind == STOFFDocument::STOFF_K_DATABASE) {
147       librevenge::RVNGTextSpreadsheetGenerator documentGenerator(pages, isInfo);
148       error=STOFFDocument::parse(&input, &documentGenerator, password);
149       if (error == STOFFDocument::STOFF_R_OK && !pages.size()) {
150         printf("ERROR: find no sheets!\n");
151         return 1;
152       }
153       useStringVector=true;
154     }
155     else if (kind == STOFFDocument::STOFF_K_PRESENTATION) {
156       if (isInfo) {
157         printf("ERROR: can not print info concerning a presentation document!\n");
158         return 1;
159       }
160       librevenge::RVNGTextPresentationGenerator documentGenerator(pages);
161       error=STOFFDocument::parse(&input, &documentGenerator, password);
162       if (error == STOFFDocument::STOFF_R_OK && !pages.size()) {
163         printf("ERROR: find no slides!\n");
164         return 1;
165       }
166       useStringVector=true;
167     }
168     else {
169       librevenge::RVNGTextTextGenerator documentGenerator(document, isInfo);
170       error=STOFFDocument::parse(&input, &documentGenerator, password);
171     }
172   }
173   catch (STOFFDocument::Result const &err) {
174     error=err;
175   }
176   catch (...) {
177     error = STOFFDocument::STOFF_R_UNKNOWN_ERROR;
178   }
179 
180   if (error == STOFFDocument::STOFF_R_FILE_ACCESS_ERROR)
181     fprintf(stderr, "ERROR: File Exception!\n");
182   else if (error == STOFFDocument::STOFF_R_PARSE_ERROR)
183     fprintf(stderr, "ERROR: Parse Exception!\n");
184   else if (error == STOFFDocument::STOFF_R_OLE_ERROR)
185     fprintf(stderr, "ERROR: File is an OLE document!\n");
186   else if (error == STOFFDocument::STOFF_R_PASSWORD_MISSMATCH_ERROR)
187     fprintf(stderr, "ERROR: Bad password!\n");
188   else if (error != STOFFDocument::STOFF_R_OK)
189     fprintf(stderr, "ERROR: Unknown Error!\n");
190 
191   if (error != STOFFDocument::STOFF_R_OK)
192     return 1;
193 
194   if (!output) {
195     if (!useStringVector)
196       printf("%s", document.cstr());
197     else {
198       for (unsigned i=0; i < pages.size(); ++i)
199         printf("%s\n", pages[i].cstr());
200     }
201   }
202   else {
203     FILE *out=fopen(output, "wb");
204     if (!out) {
205       fprintf(stderr, "ERROR: can not open file %s!\n", output);
206       return 1;
207     }
208     if (!useStringVector)
209       fprintf(out, "%s", document.cstr());
210     else {
211       for (unsigned i=0; i < pages.size(); ++i)
212         fprintf(out, "%s\n", pages[i].cstr());
213     }
214     fclose(out);
215   }
216 
217   return 0;
218 }
219 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
220