1 /* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * @(#)UUEncoderStream.java 1.3 02/03/27 28 */ 29 30 31 32 package com.sun.xml.internal.messaging.saaj.packaging.mime.util; 33 34 import java.io.*; 35 36 /** 37 * This class implements a UUEncoder. It is implemented as 38 * a FilterOutputStream, so one can just wrap this class around 39 * any output stream and write bytes into this filter. The Encoding 40 * is done as the bytes are written out. 41 * 42 * @author John Mani 43 */ 44 45 public class UUEncoderStream extends FilterOutputStream { 46 private byte[] buffer; // cache of bytes that are yet to be encoded 47 private int bufsize = 0; // size of the cache 48 private boolean wrotePrefix = false; 49 50 protected String name; // name of file 51 protected int mode; // permissions mode 52 53 /** 54 * Create a UUencoder that encodes the specified input stream 55 * @param out the output stream 56 */ 57 public UUEncoderStream(OutputStream out) { 58 this(out, "encoder.buf", 644); 59 } 60 61 /** 62 * Create a UUencoder that encodes the specified input stream 63 * @param out the output stream 64 * @param name Specifies a name for the encoded buffer 65 */ 66 public UUEncoderStream(OutputStream out, String name) { 67 this(out, name, 644); 68 } 69 70 /** 71 * Create a UUencoder that encodes the specified input stream 72 * @param out the output stream 73 * @param name Specifies a name for the encoded buffer 74 * @param mode Specifies permission mode for the encoded buffer 75 */ 76 public UUEncoderStream(OutputStream out, String name, int mode) { 77 super(out); 78 this.name = name; 79 this.mode = mode; 80 buffer = new byte[45]; 81 } 82 83 /** 84 * Set up the buffer name and permission mode. 85 * This method has any effect only if it is invoked before 86 * you start writing into the output stream. 87 * 88 * @param name name to set for the buffer. 89 * @param mode permission mode. 90 */ 91 public void setNameMode(String name, int mode) { 92 this.name = name; 93 this.mode = mode; 94 } 95 96 @Override 97 public void write(byte[] b, int off, int len) throws IOException { 98 for (int i = 0; i < len; i++) 99 write(b[off + i]); 100 } 101 102 @Override 103 public void write(byte[] data) throws IOException { 104 write(data, 0, data.length); 105 } 106 107 @Override 108 public void write(int c) throws IOException { 109 /* buffer up characters till we get a line's worth, then encode 110 * and write them out. Max number of characters allowed per 111 * line is 45. 112 */ 113 buffer[bufsize++] = (byte)c; 114 if (bufsize == 45) { 115 writePrefix(); 116 encode(); 117 bufsize = 0; 118 } 119 } 120 121 @Override 122 public void flush() throws IOException { 123 if (bufsize > 0) { // If there's unencoded characters in the buffer 124 writePrefix(); 125 encode(); // .. encode them 126 } 127 writeSuffix(); 128 out.flush(); 129 } 130 131 @Override 132 public void close() throws IOException { 133 flush(); 134 out.close(); 135 } 136 137 /** 138 * Write out the prefix: "begin <mode> <name>" 139 */ 140 private void writePrefix() throws IOException { 141 if (!wrotePrefix) { 142 PrintStream ps = new PrintStream(out); 143 ps.println("begin " + mode + " " + name); 144 ps.flush(); 145 wrotePrefix = true; 146 } 147 } 148 149 /** 150 * Write a single line containing space and the suffix line 151 * containing the single word "end" (terminated by a newline) 152 */ 153 private void writeSuffix() throws IOException { 154 PrintStream ps = new PrintStream(out); 155 ps.println(" \nend"); 156 ps.flush(); 157 } 158 159 /** 160 * Encode a line. 161 * Start off with the character count, followed by the encoded atoms 162 * and terminate with LF. (or is it CRLF or the local line-terminator ?) 163 * Take three bytes and encodes them into 4 characters 164 * If bufsize if not a multiple of 3, the remaining bytes are filled 165 * with '1'. This insures that the last line won't end in spaces 166 * and potentiallly be truncated. 167 */ 168 private void encode() throws IOException { 169 byte a, b, c; 170 int c1, c2, c3, c4; 171 int i = 0; 172 173 // Start off with the count of characters in the line 174 out.write((bufsize & 0x3f) + ' '); 175 176 while (i < bufsize) { 177 a = buffer[i++]; 178 if (i < bufsize) { 179 b = buffer[i++]; 180 if (i < bufsize) 181 c = buffer[i++]; 182 else // default c to 1 183 c = 1; 184 } 185 else { // default b & c to 1 186 b = 1; 187 c = 1; 188 } 189 190 c1 = (a >>> 2) & 0x3f; 191 c2 = ((a << 4) & 0x30) | ((b >>> 4) & 0xf); 192 c3 = ((b << 2) & 0x3c) | ((c >>> 6) & 0x3); 193 c4 = c & 0x3f; 194 out.write(c1 + ' '); 195 out.write(c2 + ' '); 196 out.write(c3 + ' '); 197 out.write(c4 + ' '); 198 } 199 // Terminate with LF. (should it be CRLF or local line-terminator ?) 200 out.write('\n'); 201 } 202 203 /**** begin TEST program ***** 204 public static void main(String argv[]) throws Exception { 205 FileInputStream infile = new FileInputStream(argv[0]); 206 UUEncoderStream encoder = new UUEncoderStream(System.out); 207 int c; 208 209 while ((c = infile.read()) != -1) 210 encoder.write(c); 211 encoder.close(); 212 } 213 **** end TEST program *****/ 214 }