vfs: check userland buffers before reading them.
[haiku.git] / src / tools / translation / stxtinfo / stxtinfo.cpp
blobc50ff3a2e8174057f252c9b2ca637bfaf55151af
1 /*****************************************************************************/
2 // stxtinfo
3 // Written by Michael Wilber, OBOS Translation Kit Team
4 //
5 // Version:
6 //
7 // stxtinfo is a command line program for displaying text information about
8 // Be styled text (the format that StyledEdit uses). StyledEdit stores the
9 // styled text information as an attribute of the file and it is this
10 // information that this program is concerned with. This format is outlined
11 // in TranslatorFormats.h.
13 // This program prints out information from the "styles" attribute that
14 // StyledEdit uses. If that information is not available, it attempts
15 // to read the styles information from the contents of the file, assuming
16 // that it is the format that BTranslationUtils::PutStyledText() writes
17 // out.
19 // The intention of this program is to aid with the development and
20 // debugging of the STXTTranslator. It may also be useful for debugging /
21 // testing StyledEdit.
23 // This application and all source files used in its construction, except
24 // where noted, are licensed under the MIT License, and have been written
25 // and are:
27 // Copyright (c) 2003 OpenBeOS Project
29 // Permission is hereby granted, free of charge, to any person obtaining a
30 // copy of this software and associated documentation files (the "Software"),
31 // to deal in the Software without restriction, including without limitation
32 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
33 // and/or sell copies of the Software, and to permit persons to whom the
34 // Software is furnished to do so, subject to the following conditions:
36 // The above copyright notice and this permission notice shall be included
37 // in all copies or substantial portions of the Software.
39 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
40 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
42 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
44 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
45 // DEALINGS IN THE SOFTWARE.
46 /*****************************************************************************/
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ByteOrder.h>
51 #include <File.h>
52 #include <TranslatorFormats.h>
53 #include <Font.h>
54 // for B_UNICODE_UTF8
55 #include <fs_attr.h>
56 // for attr_info
58 #define max(x,y) ((x > y) ? x : y)
59 #define DATA_BUFFER_SIZE 64
61 struct StylesHeader {
62 uint32 magic; // 41 6c 69 21
63 uint32 version; // 0
64 int32 count;
67 struct Style {
68 int32 offset;
69 char family[64];
70 char style[64];
71 float size;
72 float shear; // typically 90.0
73 uint16 face; // typically 0
74 uint8 red;
75 uint8 green;
76 uint8 blue;
77 uint8 alpha; // 255 == opaque
78 uint16 reserved; // 0
81 void
82 PrintStyle(Style &style, int32 i)
84 style.offset = B_BENDIAN_TO_HOST_INT32(style.offset);
85 style.size = B_BENDIAN_TO_HOST_FLOAT(style.size);
86 style.shear = B_BENDIAN_TO_HOST_FLOAT(style.shear);
87 style.face = B_BENDIAN_TO_HOST_INT16(style.face);
88 style.reserved = B_BENDIAN_TO_HOST_INT16(style.reserved);
90 printf("\nStyle %d:\n", static_cast<int>(i + 1));
91 printf("offset: %d\n", static_cast<int>(style.offset));
92 printf("family: %s\n", style.family);
93 printf("style: %s\n", style.style);
94 printf("size: %f\n", style.size);
95 printf("shear: %f (typically 90.0)\n", style.shear);
96 printf("face: %u (typically 0)\n",
97 static_cast<unsigned int>(style.face));
98 printf("RGBA: (%u, %u, %u, %u)\n",
99 static_cast<unsigned int>(style.red),
100 static_cast<unsigned int>(style.blue),
101 static_cast<unsigned int>(style.green),
102 static_cast<unsigned int>(style.alpha));
103 printf("reserved: %u (should be 0)\n",
104 static_cast<unsigned int>(style.reserved));
107 bool
108 PrintStylesAttribute(BFile &file)
110 const char *kAttrName = "styles";
111 attr_info info;
113 if (file.GetAttrInfo(kAttrName, &info) != B_OK)
114 return false;
115 if (info.type != B_RAW_TYPE) {
116 printf("Error: styles attribute is of the wrong type\n");
117 return false;
119 if (info.size < 160) {
120 printf("Error: styles attribute is missing information\n");
121 return false;
124 uint8 *pflatRunArray = new uint8[info.size];
125 if (!pflatRunArray) {
126 printf("Error: Not enough memory available to read styles attribute\n");
127 return false;
130 ssize_t amtread = file.ReadAttr(kAttrName, B_RAW_TYPE, 0,
131 pflatRunArray, info.size);
132 if (amtread != info.size) {
133 printf("Error: Unable to read styles attribute\n");
134 return false;
137 // Check Styles
138 StylesHeader stylesheader;
139 memcpy(&stylesheader, pflatRunArray, sizeof(StylesHeader));
140 if (swap_data(B_UINT32_TYPE, &stylesheader, sizeof(StylesHeader),
141 B_SWAP_BENDIAN_TO_HOST) != B_OK) {
142 printf("Error: Unable to swap byte order of styles header\n");
143 return false;
146 // Print StylesHeader info
147 printf("\"styles\" attribute data:\n\n");
149 printf("magic number: 0x%.8lx ",
150 static_cast<unsigned long>(stylesheader.magic));
151 if (stylesheader.magic == 'Ali!')
152 printf("(valid)\n");
153 else
154 printf("(INVALID, should be 0x%.8lx)\n",
155 static_cast<unsigned long>('Ali!'));
157 printf("version: 0x%.8lx ",
158 static_cast<unsigned long>(stylesheader.version));
159 if (stylesheader.version == 0)
160 printf("(valid)\n");
161 else
162 printf("(INVALID, should be 0x%.8lx)\n", 0UL);
164 printf("number of styles: %d\n",
165 static_cast<int>(stylesheader.count));
167 // Check and Print out each style
168 Style *pstyle = reinterpret_cast<Style *>(pflatRunArray + sizeof(StylesHeader));
169 for (int32 i = 0; i < stylesheader.count; i++)
170 PrintStyle(*(pstyle + i), i);
172 delete[] pflatRunArray;
173 pflatRunArray = NULL;
175 return true;
178 bool
179 PrintStxtInfo(BFile &file)
181 const uint32 kstxtsize = sizeof(TranslatorStyledTextStreamHeader);
182 const uint32 ktxtsize = sizeof(TranslatorStyledTextTextHeader);
183 const uint32 kstylsize = sizeof(TranslatorStyledTextStyleHeader);
184 const uint32 kStyleSize = sizeof(Style);
186 uint8 buffer[max(max(max(kstxtsize, ktxtsize), kstylsize), kStyleSize)];
188 // Check STXT Header
189 status_t nread = 0;
190 nread = file.Read(buffer, kstxtsize);
191 if (nread != static_cast<status_t>(kstxtsize)) {
192 printf("Error: Unable to read stream header\n");
193 return false;
195 TranslatorStyledTextStreamHeader stxtheader;
196 memcpy(&stxtheader, buffer, kstxtsize);
197 if (swap_data(B_UINT32_TYPE, &stxtheader, kstxtsize,
198 B_SWAP_BENDIAN_TO_HOST) != B_OK) {
199 printf("Error: Unable to swap byte order of stream header\n");
200 return false;
203 if (stxtheader.header.magic != B_STYLED_TEXT_FORMAT) {
204 printf("Styled text magic number is incorrect, aborting.\n");
205 return false;
208 // Print Stream Header (STXT)
209 printf("Stream Header (STXT section):\n\n");
211 printf("magic number: 0x%.8lx ", stxtheader.header.magic);
212 if (stxtheader.header.magic == B_STYLED_TEXT_FORMAT)
213 printf("(valid)\n");
214 else
215 printf("(INVALID, should be 0x%.8lx)\n",
216 static_cast<unsigned long>(B_STYLED_TEXT_FORMAT));
218 printf("header size: %u ",
219 static_cast<unsigned int>(stxtheader.header.header_size));
220 if (stxtheader.header.header_size == kstxtsize)
221 printf("(valid)\n");
222 else
223 printf("(INVALID, should be %u)\n",
224 static_cast<unsigned int>(kstxtsize));
226 printf("data size: %u ",
227 static_cast<unsigned int>(stxtheader.header.data_size));
228 if (stxtheader.header.data_size == 0)
229 printf("(valid)\n");
230 else
231 printf("(INVALID, should be 0)\n");
233 printf("version: %d ",
234 static_cast<int>(stxtheader.version));
235 if (stxtheader.version == 100)
236 printf("(valid)\n");
237 else
238 printf("(INVALID, should be 100)\n");
241 // Check the TEXT header
242 TranslatorStyledTextTextHeader txtheader;
243 if (file.Read(buffer, ktxtsize) != static_cast<ssize_t>(ktxtsize)) {
244 printf("Error: Unable to read text header\n");
245 return false;
247 memcpy(&txtheader, buffer, ktxtsize);
248 if (swap_data(B_UINT32_TYPE, &txtheader, ktxtsize,
249 B_SWAP_BENDIAN_TO_HOST) != B_OK) {
250 printf("Error: Unable to swap byte order of text header\n");
251 return false;
254 // Print Text Header (TEXT)
255 printf("\nText Header (TEXT section):\n\n");
257 printf("magic number: 0x%.8lx ", txtheader.header.magic);
258 if (txtheader.header.magic == 'TEXT')
259 printf("(valid)\n");
260 else
261 printf("(INVALID, should be 0x%.8lx)\n",
262 static_cast<unsigned long>('TEXT'));
264 printf("header size: %u ",
265 static_cast<unsigned int>(txtheader.header.header_size));
266 if (stxtheader.header.header_size == ktxtsize)
267 printf("(valid)\n");
268 else
269 printf("(INVALID, should be %u)\n",
270 static_cast<unsigned int>(ktxtsize));
272 printf("data size (bytes of text): %u\n",
273 static_cast<unsigned int>(txtheader.header.data_size));
275 printf("character set: %d ",
276 static_cast<int>(txtheader.charset));
277 if (txtheader.charset == B_UNICODE_UTF8)
278 printf("(valid)\n");
279 else
280 printf("(INVALID, should be %d)\n", B_UNICODE_UTF8);
282 // Skip the text data
283 off_t seekresult, pos;
284 pos = stxtheader.header.header_size +
285 txtheader.header.header_size +
286 txtheader.header.data_size;
287 seekresult = file.Seek(txtheader.header.data_size, SEEK_CUR);
288 if (seekresult < pos) {
289 printf("Error: Unable to seek past text data. " \
290 "Text data could be missing\n");
291 return false;
293 if (seekresult > pos) {
294 printf("Error: File position is beyond expected value\n");
295 return false;
298 // Check the STYL header (not all STXT files have this)
299 ssize_t read = 0;
300 TranslatorStyledTextStyleHeader stylheader;
301 read = file.Read(buffer, kstylsize);
302 if (read != static_cast<ssize_t>(kstylsize) && read != 0) {
303 printf("Error: Unable to read entire style header\n");
304 return false;
307 // If there is no STYL header (and no errors)
308 if (read != static_cast<ssize_t>(kstylsize)) {
309 printf("\nFile contains no Style Header (STYL section)\n");
310 return false;
313 memcpy(&stylheader, buffer, kstylsize);
314 if (swap_data(B_UINT32_TYPE, &stylheader, kstylsize,
315 B_SWAP_BENDIAN_TO_HOST) != B_OK) {
316 printf("Error: Unable to swap byte order of style header\n");
317 return false;
320 // Print Style Header (STYL)
321 printf("\nStyle Header (STYL section):\n\n");
323 printf("magic number: 0x%.8lx ", stylheader.header.magic);
324 if (stylheader.header.magic == 'STYL')
325 printf("(valid)\n");
326 else
327 printf("(INVALID, should be 0x%.8lx)\n",
328 static_cast<unsigned long>('STYL'));
330 printf("header size: %u ",
331 static_cast<unsigned int>(stylheader.header.header_size));
332 if (stylheader.header.header_size == kstylsize)
333 printf("(valid)\n");
334 else
335 printf("(INVALID, should be %u)\n",
336 static_cast<unsigned int>(kstylsize));
338 printf("data size: %u\n",
339 static_cast<unsigned int>(stylheader.header.data_size));
340 printf("apply offset: %u (usually 0)\n",
341 static_cast<unsigned int>(stylheader.apply_offset));
342 printf("apply length: %u (usually the text data size)\n",
343 static_cast<unsigned int>(stylheader.apply_length));
345 // Check Styles
346 StylesHeader stylesheader;
347 read = file.Read(buffer, sizeof(StylesHeader));
348 if (read != sizeof(StylesHeader)) {
349 printf("Error: Unable to read Styles header\n");
350 return false;
352 memcpy(&stylesheader, buffer, sizeof(StylesHeader));
353 if (swap_data(B_UINT32_TYPE, &stylesheader, sizeof(StylesHeader),
354 B_SWAP_BENDIAN_TO_HOST) != B_OK) {
355 printf("Error: Unable to swap byte order of styles header\n");
356 return false;
359 // Print StylesHeader info
360 printf("\nStyles Header (Ali! section):\n\n");
362 printf("magic number: 0x%.8lx ",
363 static_cast<unsigned long>(stylesheader.magic));
364 if (stylesheader.magic == 'Ali!')
365 printf("(valid)\n");
366 else
367 printf("(INVALID, should be 0x%.8lx)\n",
368 static_cast<unsigned long>('Ali!'));
370 printf("version: 0x%.8lx ",
371 static_cast<unsigned long>(stylesheader.version));
372 if (stylesheader.version == 0)
373 printf("(valid)\n");
374 else
375 printf("(INVALID, should be 0x%.8lx)\n", 0UL);
377 printf("number of styles: %d\n",
378 static_cast<int>(stylesheader.count));
380 // Check and Print out each style
381 for (int32 i = 0; i < stylesheader.count; i++) {
382 Style style;
383 read = file.Read(&style, sizeof(Style));
384 if (read != sizeof(Style)) {
385 printf("Error: Unable to read style %d\n",
386 static_cast<int>(i + 1));
387 return false;
390 PrintStyle(style, i);
393 return true;
397 main(int argc, char **argv)
399 printf("\n");
401 if (argc == 2) {
402 BFile file(argv[1], B_READ_ONLY);
403 if (file.InitCheck() != B_OK)
404 printf("Error opening %s\n", argv[1]);
405 else {
406 printf("Be styled text information for: %s\n\n", argv[1]);
407 if (PrintStylesAttribute(file) == false) {
408 printf("Unable to read styles attribute, attempting to read " \
409 "style information from file...\n\n");
410 PrintStxtInfo(file);
414 else {
415 printf("stxtinfo - reports information about a Be styled text file\n");
416 printf("\nUsage:\n");
417 printf("stxtinfo filename.stxt\n");
420 printf("\n");
422 return 0;