1 16 17 22 package org.apache.poi.hssf.dev; 23 24 import org.apache.poi.hssf.record.*; 25 import org.apache.poi.poifs.filesystem.POIFSFileSystem; 26 import org.apache.poi.util.HexDump; 27 import org.apache.poi.util.LittleEndian; 28 29 import java.io.FileInputStream ; 30 import java.io.IOException ; 31 import java.io.InputStream ; 32 import java.util.ArrayList ; 33 34 41 42 public class BiffViewer { 43 String filename; 44 private boolean dump; 45 46 47 52 53 public BiffViewer(String [] args) { 54 if (args.length > 0) { 55 filename = args[0]; 56 } else { 57 System.out.println("BIFFVIEWER REQUIRES A FILENAME***"); 58 } 59 } 60 61 62 65 66 public void run() { 67 try { 68 POIFSFileSystem fs = 69 new POIFSFileSystem(new FileInputStream (filename)); 70 InputStream stream = 71 fs.createDocumentInputStream("Workbook"); 72 createRecords(stream, dump); 73 } catch (Exception e) { 74 e.printStackTrace(); 75 } 76 } 77 78 79 89 90 public static Record[] createRecords(InputStream in, boolean dump) 91 throws RecordFormatException { 92 ArrayList records = new ArrayList (); 93 int loc = 0; 95 96 RecordDetails activeRecord = null; 97 98 try { 99 short rectype = 0; 101 102 do { 103 rectype = LittleEndian.readShort(in); 104 int startloc = loc; 105 loc += 2; 106 if (rectype != 0) { 107 short recsize = LittleEndian.readShort(in); 108 109 loc += 2; 110 byte[] data = new byte[(int) recsize]; 111 112 in.read(data); 113 loc += recsize; 114 Record record = createRecord(rectype, recsize, data ); 115 if (record.getSid() != ContinueRecord.sid) 116 { 117 records.add(record); 118 if (activeRecord != null) 119 activeRecord.dump(); 120 activeRecord = new RecordDetails(rectype, recsize, startloc, data, record); 121 } 122 else 123 { 124 activeRecord.getRecord().processContinueRecord(data); 125 } 126 if (dump) { 127 dumpRaw(rectype, recsize, data); 128 } 129 } 130 } while (rectype != 0); 131 132 activeRecord.dump(); 133 134 } catch (IOException e) { 135 throw new RecordFormatException("Error reading bytes"); 136 } 137 Record[] retval = new Record[records.size()]; 138 139 retval = (Record[]) records.toArray(retval); 140 return retval; 141 } 142 143 private static void dumpNormal(Record record, int startloc, short rectype, short recsize) 144 { 145 System.out.println("Offset 0x" + Integer.toHexString(startloc) + " (" + startloc + ")"); 146 System.out.println( "recordid = 0x" + Integer.toHexString( rectype ) + ", size = " + recsize ); 147 System.out.println( record.toString() ); 148 149 } 150 151 private static void dumpContinueRecord(Record last_record, boolean dump, byte[] data) throws IOException { 152 if (last_record == null) { 153 throw new RecordFormatException( 154 "First record is a ContinueRecord??"); 155 } 156 if (dump) { 157 System.out.println( 158 "-----PRECONTINUED LAST RECORD WOULD SERIALIZE LIKE:"); 159 byte[] lr = last_record.serialize(); 160 161 if (lr != null) { 162 HexDump.dump(last_record.serialize(), 163 0, System.out, 0); 164 } 165 System.out.println(); 166 System.out.println( 167 "-----PRECONTINUED----------------------------------"); 168 } 169 last_record.processContinueRecord(data); 170 if (dump) { 171 System.out.println( 172 "-----CONTINUED LAST RECORD WOULD SERIALIZE LIKE:"); 173 HexDump.dump(last_record.serialize(), 0, 174 System.out, 0); 175 System.out.println(); 176 System.out.println( 177 "-----CONTINUED----------------------------------"); 178 } 179 } 180 181 182 private static void dumpUnknownRecord(byte[] data) throws IOException { 183 System.out.println( 185 "-----UNKNOWN----------------------------------"); 186 if (data.length > 0) { 187 HexDump.dump(data, 0, System.out, 0); 188 } else { 189 System.out.print("**NO RECORD DATA**"); 190 } 191 System.out.println(); 192 System.out.println( 193 "-----UNKNOWN----------------------------------"); 194 } 195 196 197 private static void dumpRaw( short rectype, short recsize, byte[] data ) throws IOException 198 { 199 System.out.println("============================================"); 202 System.out.print( "rectype = 0x" 203 + Integer.toHexString( rectype ) ); 204 System.out.println( ", recsize = 0x" 205 + Integer.toHexString( recsize ) ); 206 System.out.println( 207 "-BEGIN DUMP---------------------------------" ); 208 if ( data.length > 0 ) 209 { 210 HexDump.dump( data, 0, System.out, 0 ); 211 } 212 else 213 { 214 System.out.println( "**NO RECORD DATA**" ); 215 } 216 System.out.println( 218 "-END DUMP-----------------------------------" ); 219 } 220 221 222 227 private static Record createRecord( short rectype, short size, 228 byte[] data ) 229 { 230 Record retval = null; 231 232 switch ( rectype ) 233 { 234 235 case ChartRecord.sid: 236 retval = new ChartRecord( rectype, size, data ); 237 break; 238 case ChartFormatRecord.sid: 239 retval = new ChartFormatRecord( rectype, size, data ); 240 break; 241 case SeriesRecord.sid: 242 retval = new SeriesRecord( rectype, size, data ); 243 break; 244 case BeginRecord.sid: 245 retval = new BeginRecord( rectype, size, data ); 246 break; 247 case EndRecord.sid: 248 retval = new EndRecord( rectype, size, data ); 249 break; 250 case BOFRecord.sid: 251 retval = new BOFRecord( rectype, size, data ); 252 break; 253 case InterfaceHdrRecord.sid: 254 retval = new InterfaceHdrRecord( rectype, size, data ); 255 break; 256 case MMSRecord.sid: 257 retval = new MMSRecord( rectype, size, data ); 258 break; 259 case InterfaceEndRecord.sid: 260 retval = new InterfaceEndRecord( rectype, size, data ); 261 break; 262 case WriteAccessRecord.sid: 263 retval = new WriteAccessRecord( rectype, size, data ); 264 break; 265 case CodepageRecord.sid: 266 retval = new CodepageRecord( rectype, size, data ); 267 break; 268 case DSFRecord.sid: 269 retval = new DSFRecord( rectype, size, data ); 270 break; 271 case TabIdRecord.sid: 272 retval = new TabIdRecord( rectype, size, data ); 273 break; 274 case FnGroupCountRecord.sid: 275 retval = new FnGroupCountRecord( rectype, size, data ); 276 break; 277 case WindowProtectRecord.sid: 278 retval = new WindowProtectRecord( rectype, size, data ); 279 break; 280 case ProtectRecord.sid: 281 retval = new ProtectRecord( rectype, size, data ); 282 break; 283 case PasswordRecord.sid: 284 retval = new PasswordRecord( rectype, size, data ); 285 break; 286 case ProtectionRev4Record.sid: 287 retval = new ProtectionRev4Record( rectype, size, data ); 288 break; 289 case PasswordRev4Record.sid: 290 retval = new PasswordRev4Record( rectype, size, data ); 291 break; 292 case WindowOneRecord.sid: 293 retval = new WindowOneRecord( rectype, size, data ); 294 break; 295 case BackupRecord.sid: 296 retval = new BackupRecord( rectype, size, data ); 297 break; 298 case HideObjRecord.sid: 299 retval = new HideObjRecord( rectype, size, data ); 300 break; 301 case DateWindow1904Record.sid: 302 retval = new DateWindow1904Record( rectype, size, data ); 303 break; 304 case PrecisionRecord.sid: 305 retval = new PrecisionRecord( rectype, size, data ); 306 break; 307 case RefreshAllRecord.sid: 308 retval = new RefreshAllRecord( rectype, size, data ); 309 break; 310 case BookBoolRecord.sid: 311 retval = new BookBoolRecord( rectype, size, data ); 312 break; 313 case FontRecord.sid: 314 retval = new FontRecord( rectype, size, data ); 315 break; 316 case FormatRecord.sid: 317 retval = new FormatRecord( rectype, size, data ); 318 break; 319 case ExtendedFormatRecord.sid: 320 retval = new ExtendedFormatRecord( rectype, size, data ); 321 break; 322 case StyleRecord.sid: 323 retval = new StyleRecord( rectype, size, data ); 324 break; 325 case UseSelFSRecord.sid: 326 retval = new UseSelFSRecord( rectype, size, data ); 327 break; 328 case BoundSheetRecord.sid: 329 retval = new BoundSheetRecord( rectype, size, data ); 330 break; 331 case CountryRecord.sid: 332 retval = new CountryRecord( rectype, size, data ); 333 break; 334 case SSTRecord.sid: 335 retval = new SSTRecord( rectype, size, data ); 336 break; 337 case ExtSSTRecord.sid: 338 retval = new ExtSSTRecord( rectype, size, data ); 339 break; 340 case EOFRecord.sid: 341 retval = new EOFRecord( rectype, size, data ); 342 break; 343 case IndexRecord.sid: 344 retval = new IndexRecord( rectype, size, data ); 345 break; 346 case CalcModeRecord.sid: 347 retval = new CalcModeRecord( rectype, size, data ); 348 break; 349 case CalcCountRecord.sid: 350 retval = new CalcCountRecord( rectype, size, data ); 351 break; 352 case RefModeRecord.sid: 353 retval = new RefModeRecord( rectype, size, data ); 354 break; 355 case IterationRecord.sid: 356 retval = new IterationRecord( rectype, size, data ); 357 break; 358 case DeltaRecord.sid: 359 retval = new DeltaRecord( rectype, size, data ); 360 break; 361 case SaveRecalcRecord.sid: 362 retval = new SaveRecalcRecord( rectype, size, data ); 363 break; 364 case PrintHeadersRecord.sid: 365 retval = new PrintHeadersRecord( rectype, size, data ); 366 break; 367 case PrintGridlinesRecord.sid: 368 retval = new PrintGridlinesRecord( rectype, size, data ); 369 break; 370 case GridsetRecord.sid: 371 retval = new GridsetRecord( rectype, size, data ); 372 break; 373 case DrawingGroupRecord.sid: 374 retval = new DrawingGroupRecord( rectype, size, data ); 375 break; 376 case DrawingRecordForBiffViewer.sid: 377 retval = new DrawingRecordForBiffViewer( rectype, size, data ); 378 break; 379 case DrawingSelectionRecord.sid: 380 retval = new DrawingSelectionRecord( rectype, size, data ); 381 break; 382 case GutsRecord.sid: 383 retval = new GutsRecord( rectype, size, data ); 384 break; 385 case DefaultRowHeightRecord.sid: 386 retval = new DefaultRowHeightRecord( rectype, size, data ); 387 break; 388 case WSBoolRecord.sid: 389 retval = new WSBoolRecord( rectype, size, data ); 390 break; 391 case HeaderRecord.sid: 392 retval = new HeaderRecord( rectype, size, data ); 393 break; 394 case FooterRecord.sid: 395 retval = new FooterRecord( rectype, size, data ); 396 break; 397 case HCenterRecord.sid: 398 retval = new HCenterRecord( rectype, size, data ); 399 break; 400 case VCenterRecord.sid: 401 retval = new VCenterRecord( rectype, size, data ); 402 break; 403 case PrintSetupRecord.sid: 404 retval = new PrintSetupRecord( rectype, size, data ); 405 break; 406 case DefaultColWidthRecord.sid: 407 retval = new DefaultColWidthRecord( rectype, size, data ); 408 break; 409 case DimensionsRecord.sid: 410 retval = new DimensionsRecord( rectype, size, data ); 411 break; 412 case RowRecord.sid: 413 retval = new RowRecord( rectype, size, data ); 414 break; 415 case LabelSSTRecord.sid: 416 retval = new LabelSSTRecord( rectype, size, data ); 417 break; 418 case RKRecord.sid: 419 retval = new RKRecord( rectype, size, data ); 420 break; 421 case NumberRecord.sid: 422 retval = new NumberRecord( rectype, size, data ); 423 break; 424 case DBCellRecord.sid: 425 retval = new DBCellRecord( rectype, size, data ); 426 break; 427 case WindowTwoRecord.sid: 428 retval = new WindowTwoRecord( rectype, size, data ); 429 break; 430 case SelectionRecord.sid: 431 retval = new SelectionRecord( rectype, size, data ); 432 break; 433 case ContinueRecord.sid: 434 retval = new ContinueRecord( rectype, size, data ); 435 break; 436 case LabelRecord.sid: 437 retval = new LabelRecord( rectype, size, data ); 438 break; 439 case MulRKRecord.sid: 440 retval = new MulRKRecord( rectype, size, data ); 441 break; 442 case MulBlankRecord.sid: 443 retval = new MulBlankRecord( rectype, size, data ); 444 break; 445 case BlankRecord.sid: 446 retval = new BlankRecord( rectype, size, data ); 447 break; 448 case BoolErrRecord.sid: 449 retval = new BoolErrRecord( rectype, size, data ); 450 break; 451 case ColumnInfoRecord.sid: 452 retval = new ColumnInfoRecord( rectype, size, data ); 453 break; 454 case MergeCellsRecord.sid: 455 retval = new MergeCellsRecord( rectype, size, data ); 456 break; 457 case AreaRecord.sid: 458 retval = new AreaRecord( rectype, size, data ); 459 break; 460 case DataFormatRecord.sid: 461 retval = new DataFormatRecord( rectype, size, data ); 462 break; 463 case BarRecord.sid: 464 retval = new BarRecord( rectype, size, data ); 465 break; 466 case DatRecord.sid: 467 retval = new DatRecord( rectype, size, data ); 468 break; 469 case PlotGrowthRecord.sid: 470 retval = new PlotGrowthRecord( rectype, size, data ); 471 break; 472 case UnitsRecord.sid: 473 retval = new UnitsRecord( rectype, size, data ); 474 break; 475 case FrameRecord.sid: 476 retval = new FrameRecord( rectype, size, data ); 477 break; 478 case ValueRangeRecord.sid: 479 retval = new ValueRangeRecord( rectype, size, data ); 480 break; 481 case SeriesListRecord.sid: 482 retval = new SeriesListRecord( rectype, size, data ); 483 break; 484 case FontBasisRecord.sid: 485 retval = new FontBasisRecord( rectype, size, data ); 486 break; 487 case FontIndexRecord.sid: 488 retval = new FontIndexRecord( rectype, size, data ); 489 break; 490 case LineFormatRecord.sid: 491 retval = new LineFormatRecord( rectype, size, data ); 492 break; 493 case AreaFormatRecord.sid: 494 retval = new AreaFormatRecord( rectype, size, data ); 495 break; 496 case LinkedDataRecord.sid: 497 retval = new LinkedDataRecord( rectype, size, data ); 498 break; 499 case FormulaRecord.sid: 500 retval = new FormulaRecord( rectype, size, data ); 501 break; 502 case SheetPropertiesRecord.sid: 503 retval = new SheetPropertiesRecord( rectype, size, data ); 504 break; 505 case DefaultDataLabelTextPropertiesRecord.sid: 506 retval = new DefaultDataLabelTextPropertiesRecord( rectype, size, data ); 507 break; 508 case TextRecord.sid: 509 retval = new TextRecord( rectype, size, data ); 510 break; 511 case AxisParentRecord.sid: 512 retval = new AxisParentRecord( rectype, size, data ); 513 break; 514 case AxisLineFormatRecord.sid: 515 retval = new AxisLineFormatRecord( rectype, size, data ); 516 break; 517 case SupBookRecord.sid: 518 retval = new SupBookRecord( rectype, size, data ); 519 break; 520 case ExternSheetRecord.sid: 521 retval = new ExternSheetRecord( rectype, size, data ); 522 break; 523 case SCLRecord.sid: 524 retval = new SCLRecord( rectype, size, data ); 525 break; 526 case SeriesToChartGroupRecord.sid: 527 retval = new SeriesToChartGroupRecord( rectype, size, data ); 528 break; 529 case AxisUsedRecord.sid: 530 retval = new AxisUsedRecord( rectype, size, data ); 531 break; 532 case AxisRecord.sid: 533 retval = new AxisRecord( rectype, size, data ); 534 break; 535 case CategorySeriesAxisRecord.sid: 536 retval = new CategorySeriesAxisRecord( rectype, size, data ); 537 break; 538 case AxisOptionsRecord.sid: 539 retval = new AxisOptionsRecord( rectype, size, data ); 540 break; 541 case TickRecord.sid: 542 retval = new TickRecord( rectype, size, data ); 543 break; 544 case SeriesTextRecord.sid: 545 retval = new SeriesTextRecord( rectype, size, data ); 546 break; 547 case ObjectLinkRecord.sid: 548 retval = new ObjectLinkRecord( rectype, size, data ); 549 break; 550 case PlotAreaRecord.sid: 551 retval = new PlotAreaRecord( rectype, size, data ); 552 break; 553 case SeriesIndexRecord.sid: 554 retval = new SeriesIndexRecord( rectype, size, data ); 555 break; 556 case LegendRecord.sid: 557 retval = new LegendRecord( rectype, size, data ); 558 break; 559 case LeftMarginRecord.sid: 560 retval = new LeftMarginRecord( rectype, size, data ); 561 break; 562 case RightMarginRecord.sid: 563 retval = new RightMarginRecord( rectype, size, data ); 564 break; 565 case TopMarginRecord.sid: 566 retval = new TopMarginRecord( rectype, size, data ); 567 break; 568 case BottomMarginRecord.sid: 569 retval = new BottomMarginRecord( rectype, size, data ); 570 break; 571 case PaletteRecord.sid: 572 retval = new PaletteRecord( rectype, size, data ); 573 break; 574 case StringRecord.sid: 575 retval = new StringRecord( rectype, size, data ); 576 break; 577 case NameRecord.sid: 578 retval = new NameRecord( rectype, size, data ); 579 break; 580 case PaneRecord.sid: 581 retval = new PaneRecord( rectype, size, data ); 582 break; 583 case SharedFormulaRecord.sid: 584 retval = new SharedFormulaRecord( rectype, size, data); 585 break; 586 case ObjRecord.sid: 587 retval = new ObjRecord( rectype, size, data); 588 break; 589 case TextObjectRecord.sid: 590 retval = new TextObjectRecord( rectype, size, data); 591 break; 592 case HorizontalPageBreakRecord.sid: 593 retval = new HorizontalPageBreakRecord( rectype, size, data); 594 break; 595 case VerticalPageBreakRecord.sid: 596 retval = new VerticalPageBreakRecord( rectype, size, data); 597 break; 598 default: 599 retval = new UnknownRecord( rectype, size, data ); 600 } 601 return retval; 602 } 603 604 605 610 611 public void setDump(boolean dump) { 612 this.dump = dump; 613 } 614 615 616 631 public static void main(String [] args) { 632 try { 633 BiffViewer viewer = new BiffViewer(args); 634 635 if ((args.length > 1) && args[1].equals("on")) { 636 viewer.setDump(true); 637 } 638 if ((args.length > 1) && args[1].equals("bfd")) { 639 POIFSFileSystem fs = 640 new POIFSFileSystem(new FileInputStream (args[0])); 641 InputStream stream = 642 fs.createDocumentInputStream("Workbook"); 643 int size = stream.available(); 644 byte[] data = new byte[size]; 645 646 stream.read(data); 647 HexDump.dump(data, 0, System.out, 0); 648 } else { 649 viewer.run(); 650 } 651 } catch (Exception e) { 652 e.printStackTrace(); 653 } 654 } 655 656 static class RecordDetails 657 { 658 short rectype, recsize; 659 int startloc; 660 byte[] data; 661 Record record; 662 663 public RecordDetails( short rectype, short recsize, int startloc, byte[] data, Record record ) 664 { 665 this.rectype = rectype; 666 this.recsize = recsize; 667 this.startloc = startloc; 668 this.data = data; 669 this.record = record; 670 } 671 672 public short getRectype() 673 { 674 return rectype; 675 } 676 677 public short getRecsize() 678 { 679 return recsize; 680 } 681 682 public byte[] getData() 683 { 684 return data; 685 } 686 687 public Record getRecord() 688 { 689 return record; 690 } 691 692 public void dump() throws IOException 693 { 694 if (record instanceof UnknownRecord) 695 dumpUnknownRecord(data); 696 else 697 dumpNormal(record, startloc, rectype, recsize); 698 } 699 } 700 701 } 702 703 | Popular Tags |