]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/server/Utf8HttpWriter.java
Merge "Update notes about password security"
[gigi.git] / lib / jetty / org / eclipse / jetty / server / Utf8HttpWriter.java
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22
23 /** OutputWriter.
24  * A writer that can wrap a {@link HttpOutput} stream and provide
25  * character encodings.
26  *
27  * The UTF-8 encoding is done by this class and no additional
28  * buffers or Writers are used.
29  * The UTF-8 code was inspired by http://javolution.org
30  */
31 public class Utf8HttpWriter extends HttpWriter
32 {
33     int _surrogate=0;
34
35     /* ------------------------------------------------------------ */
36     public Utf8HttpWriter(HttpOutput out)
37     {
38         super(out);
39     }
40
41     /* ------------------------------------------------------------ */
42     @Override
43     public void write (char[] s,int offset, int length) throws IOException
44     {
45         HttpOutput out = _out;
46         if (length==0 && out.isAllContentWritten())
47         {
48             close();
49             return;
50         }
51         
52         while (length > 0)
53         {
54             _bytes.reset();
55             int chars = length>MAX_OUTPUT_CHARS?MAX_OUTPUT_CHARS:length;
56
57             byte[] buffer=_bytes.getBuf();
58             int bytes=_bytes.getCount();
59
60             if (bytes+chars>buffer.length)
61                 chars=buffer.length-bytes;
62
63             for (int i = 0; i < chars; i++)
64             {
65                 int code = s[offset+i];
66
67                 // Do we already have a surrogate?
68                 if(_surrogate==0)
69                 {
70                     // No - is this char code a surrogate?
71                     if(Character.isHighSurrogate((char)code))
72                     {
73                         _surrogate=code; // UCS-?
74                         continue;
75                     }
76                 }
77                 // else handle a low surrogate
78                 else if(Character.isLowSurrogate((char)code))
79                 {
80                     code = Character.toCodePoint((char)_surrogate, (char)code); // UCS-4
81                 }
82                 // else UCS-2
83                 else
84                 {
85                     code=_surrogate; // UCS-2
86                     _surrogate=0; // USED
87                     i--;
88                 }
89
90                 if ((code & 0xffffff80) == 0)
91                 {
92                     // 1b
93                     if (bytes>=buffer.length)
94                     {
95                         chars=i;
96                         break;
97                     }
98                     buffer[bytes++]=(byte)(code);
99                 }
100                 else
101                 {
102                     if((code&0xfffff800)==0)
103                     {
104                         // 2b
105                         if (bytes+2>buffer.length)
106                         {
107                             chars=i;
108                             break;
109                         }
110                         buffer[bytes++]=(byte)(0xc0|(code>>6));
111                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
112                     }
113                     else if((code&0xffff0000)==0)
114                     {
115                         // 3b
116                         if (bytes+3>buffer.length)
117                         {
118                             chars=i;
119                             break;
120                         }
121                         buffer[bytes++]=(byte)(0xe0|(code>>12));
122                         buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
123                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
124                     }
125                     else if((code&0xff200000)==0)
126                     {
127                         // 4b
128                         if (bytes+4>buffer.length)
129                         {
130                             chars=i;
131                             break;
132                         }
133                         buffer[bytes++]=(byte)(0xf0|(code>>18));
134                         buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
135                         buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
136                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
137                     }
138                     else if((code&0xf4000000)==0)
139                     {
140                         // 5b
141                         if (bytes+5>buffer.length)
142                         {
143                             chars=i;
144                             break;
145                         }
146                         buffer[bytes++]=(byte)(0xf8|(code>>24));
147                         buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
148                         buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
149                         buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
150                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
151                     }
152                     else if((code&0x80000000)==0)
153                     {
154                         // 6b
155                         if (bytes+6>buffer.length)
156                         {
157                             chars=i;
158                             break;
159                         }
160                         buffer[bytes++]=(byte)(0xfc|(code>>30));
161                         buffer[bytes++]=(byte)(0x80|((code>>24)&0x3f));
162                         buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
163                         buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
164                         buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
165                         buffer[bytes++]=(byte)(0x80|(code&0x3f));
166                     }
167                     else
168                     {
169                         buffer[bytes++]=(byte)('?');
170                     }
171
172                     _surrogate=0; // USED
173
174                     if (bytes==buffer.length)
175                     {
176                         chars=i+1;
177                         break;
178                     }
179                 }
180             }
181             _bytes.setCount(bytes);
182
183             _bytes.writeTo(out);
184             length-=chars;
185             offset+=chars;
186         }
187     }
188 }