001// Copyright (C) 1999-2001 by Jason Hunter <jhunter_AT_acm_DOT_org>. 002// All rights reserved. Use of this class is limited. 003// Please see the LICENSE for more information. 004 005package com.oreilly.servlet.multipart; 006 007import java.io.OutputStream; 008import java.io.FilterOutputStream; 009import java.io.IOException; 010 011/** 012 * A <code>MacBinaryDecoderOutput</code> filters MacBinary files to normal 013 * files on the fly; optimized for speed more than readability. 014 * 015 * @author Jason Hunter 016 */ 017public class MacBinaryDecoderOutputStream extends FilterOutputStream { 018 private int bytesFiltered = 0; 019 private int dataForkLength = 0; 020 021 public MacBinaryDecoderOutputStream(OutputStream out) { 022 super(out); 023 } 024 025 public void write(int b) throws IOException { 026 // Bytes 83 through 86 are a long representing the data fork length 027 // Check <= 86 first to short circuit early in the common case 028 if (bytesFiltered <= 86 && bytesFiltered >= 83) { 029 int leftShift = (86 - bytesFiltered) * 8; 030 dataForkLength = dataForkLength | (b & 0xff) << leftShift; 031 } 032 033 // Bytes 128 up to (128 + dataForkLength - 1) are the data fork 034 else if (bytesFiltered < (128 + dataForkLength) && bytesFiltered >= 128) { 035 out.write(b); 036 } 037 038 bytesFiltered++; 039 } 040 041 public void write(byte b[]) throws IOException { 042 write(b, 0, b.length); 043 } 044 045 public void write(byte b[], int off, int len) throws IOException { 046 // If the write is for content past the end of the data fork, ignore 047 if (bytesFiltered >= (128 + dataForkLength)) { 048 bytesFiltered += len; 049 } 050 // If the write is entirely within the data fork, write it directly 051 else if (bytesFiltered >= 128 && 052 (bytesFiltered + len) <= (128 + dataForkLength)) { 053 out.write(b, off, len); 054 bytesFiltered += len; 055 } 056 // Otherwise, do the write a byte at a time to get the logic above 057 else { 058 for (int i = 0 ; i < len ; i++) { 059 write(b[off + i]); 060 } 061 } 062 } 063}