View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.net.telnet;
19  
20  import java.io.IOException;
21  import java.io.OutputStream;
22  
23  /**
24   * Wraps an output stream.
25   * <p>
26   * In binary mode, the only conversion is to double IAC.
27   * <p>
28   * In ASCII mode, if convertCRtoCRLF is true, any CR is converted to CRLF.
29   * IACs are doubled.
30   * <p>
31   ***/
32  
33  
34  final class TelnetOutputStream extends OutputStream
35  {
36      private final TelnetClient __client;
37      // TODO there does not appear to be any way to change this value - should it be a ctor parameter?
38      private final boolean __convertCRtoCRLF = true;
39      private boolean __lastWasCR = false;
40  
41      TelnetOutputStream(TelnetClient client)
42      {
43          __client = client;
44      }
45  
46  
47      /***
48       * Writes a byte to the stream.
49       * <p>
50       * @param ch The byte to write.
51       * @exception IOException If an error occurs while writing to the underlying
52       *            stream.
53       ***/
54      @Override
55      public void write(int ch) throws IOException
56      {
57  
58          synchronized (__client)
59          {
60              ch &= 0xff;
61  
62              if (__client._requestedWont(TelnetOption.BINARY)) // i.e. ASCII
63              {
64                  if (__lastWasCR)
65                  {
66                      if (__convertCRtoCRLF)
67                      {
68                          __client._sendByte('\n');
69                          if (ch == '\n') // i.e. was CRLF anyway
70                          {
71                              __lastWasCR = false;
72                              return ;
73                          }
74                      } // __convertCRtoCRLF
75                      else if (ch != '\n')
76                       {
77                          __client._sendByte('\0'); // RFC854 requires CR NUL for bare CR
78                      }
79                  }
80  
81                  __lastWasCR = false;
82  
83                  switch (ch)
84                  {
85                  case '\r':
86                      __client._sendByte('\r');
87                      __lastWasCR = true;
88                      break;
89                  case TelnetCommand.IAC:
90                      __client._sendByte(TelnetCommand.IAC);
91                      __client._sendByte(TelnetCommand.IAC);
92                      break;
93                  default:
94                      __client._sendByte(ch);
95                      break;
96                  }
97              } // end ASCII
98              else if (ch == TelnetCommand.IAC)
99              {
100                 __client._sendByte(ch);
101                 __client._sendByte(TelnetCommand.IAC);
102             } else {
103                 __client._sendByte(ch);
104             }
105         }
106     }
107 
108 
109     /***
110      * Writes a byte array to the stream.
111      * <p>
112      * @param buffer  The byte array to write.
113      * @exception IOException If an error occurs while writing to the underlying
114      *            stream.
115      ***/
116     @Override
117     public void write(byte buffer[]) throws IOException
118     {
119         write(buffer, 0, buffer.length);
120     }
121 
122 
123     /***
124      * Writes a number of bytes from a byte array to the stream starting from
125      * a given offset.
126      * <p>
127      * @param buffer  The byte array to write.
128      * @param offset  The offset into the array at which to start copying data.
129      * @param length  The number of bytes to write.
130      * @exception IOException If an error occurs while writing to the underlying
131      *            stream.
132      ***/
133     @Override
134     public void write(byte buffer[], int offset, int length) throws IOException
135     {
136         synchronized (__client)
137         {
138             while (length-- > 0) {
139                 write(buffer[offset++]);
140             }
141         }
142     }
143 
144     /*** Flushes the stream. ***/
145     @Override
146     public void flush() throws IOException
147     {
148         __client._flushOutputStream();
149     }
150 
151     /*** Closes the stream. ***/
152     @Override
153     public void close() throws IOException
154     {
155         __client._closeOutputStream();
156     }
157 }