01: /****************************************************************
02: * Licensed to the Apache Software Foundation (ASF) under one *
03: * or more contributor license agreements. See the NOTICE file *
04: * distributed with this work for additional information *
05: * regarding copyright ownership. The ASF licenses this file *
06: * to you under the Apache License, Version 2.0 (the *
07: * "License"); you may not use this file except in compliance *
08: * with the License. You may obtain a copy of the License at *
09: * *
10: * http://www.apache.org/licenses/LICENSE-2.0 *
11: * *
12: * Unless required by applicable law or agreed to in writing, *
13: * software distributed under the License is distributed on an *
14: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15: * KIND, either express or implied. See the License for the *
16: * specific language governing permissions and limitations *
17: * under the License. *
18: ****************************************************************/package org.apache.james.util;
19:
20: import java.io.FilterInputStream;
21: import java.io.IOException;
22: import java.io.InputStream;
23:
24: /**
25: * Removes the dot-stuffing happening during the NNTP and SMTP message
26: * transfer
27: */
28: public class DotStuffingInputStream extends FilterInputStream {
29: /**
30: * An array to hold the last two bytes read off the stream.
31: * This allows the stream to detect '\r\n' sequences even
32: * when they occur across read boundaries.
33: */
34: protected int last[] = new int[2];
35:
36: public DotStuffingInputStream(InputStream in) {
37: super (in);
38: last[0] = -1;
39: last[1] = -1;
40: }
41:
42: /**
43: * Read through the stream, checking for '\r\n.'
44: *
45: * @return the byte read from the stream
46: */
47: public int read() throws IOException {
48: int b = in.read();
49: if (b == '.' && last[0] == '\r' && last[1] == '\n') {
50: //skip this '.' because it should have been stuffed
51: b = in.read();
52: }
53: last[0] = last[1];
54: last[1] = b;
55: return b;
56: }
57:
58: /**
59: * Read through the stream, checking for '\r\n.'
60: *
61: * @param b the byte array into which the bytes will be read
62: * @param off the offset into the byte array where the bytes will be inserted
63: * @param len the maximum number of bytes to be read off the stream
64: * @return the number of bytes read
65: */
66: public int read(byte[] b, int off, int len) throws IOException {
67: if (b == null) {
68: throw new NullPointerException();
69: } else if ((off < 0) || (off > b.length) || (len < 0)
70: || ((off + len) > b.length) || ((off + len) < 0)) {
71: throw new IndexOutOfBoundsException();
72: } else if (len == 0) {
73: return 0;
74: }
75:
76: int c = read();
77: if (c == -1) {
78: return -1;
79: }
80: b[off] = (byte) c;
81:
82: int i = 1;
83:
84: for (; i < len; i++) {
85: c = read();
86: if (c == -1) {
87: break;
88: }
89: if (b != null) {
90: b[off + i] = (byte) c;
91: }
92: }
93:
94: return i;
95: }
96: }
|