View Javadoc
1 /* Reattore HTTP Server 2 3 Copyright (C) 2002 Michael Hope <michaelh@juju.net.nz> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 $Id: HeaderParser.java,v 1.6 2003/02/22 04:29:52 michaelh Exp $ 20 */ 21 22 package juju.reattore.protocol.http.impl; 23 24 import java.io.IOException; 25 26 import org.apache.commons.logging.*; 27 28 import juju.reattore.io.impl.*; 29 import juju.reattore.io.ByteSource; 30 import juju.reattore.protocol.http.ParseException; 31 import juju.reattore.util.CharUtil; 32 33 /*** HTTP header parser. 34 */ 35 public class HeaderParser { 36 37 private static Log log = LogFactory.getLog(HeaderParser.class); 38 39 private static final int SOL = 0; 40 private static final int IN_NAME = 1; 41 private static final int PRE_VALUE_WS = 2; 42 private static final int IN_VALUE = 3; 43 private static final int IN_FOLDING = 4; 44 private static final int IN_RESET = 5; 45 46 private int state = IN_RESET; 47 48 private StringBuffer name; 49 private StringBuffer value; 50 51 private Callback callback; 52 53 /*** Called when a header has been parsed. Register using 54 #setCallback 55 */ 56 public interface Callback { 57 /*** Called when a header has been parsed 58 59 @param name The header name 60 @param value The header value 61 */ 62 void onHeader(String name, String value); 63 } 64 65 /*** Sets what to call when a header has been parsed. 66 67 @param callback The class to call, or null to disable. 68 */ 69 public void setCallback(Callback callback) { 70 this.callback = callback; 71 } 72 73 private void addHeader() { 74 if (callback != null) { 75 callback.onHeader(name.toString(), value.toString().trim()); 76 } 77 78 name = new StringBuffer(); 79 value = new StringBuffer(); 80 } 81 82 /*** Resets back to a clean state. 83 */ 84 public void reset() { 85 name = new StringBuffer(); 86 value = new StringBuffer(); 87 state = SOL; 88 } 89 90 /*** Parse HTTP headers. 91 92 @param in Source to parse from 93 @return false means more parsing needed 94 @throws ParseException if an error occurs while parsing. 95 @throws IOException on error. 96 97 @todo Minor: Pull out parsing into character classes. 98 */ 99 public boolean add(PushbackByteSource in) 100 throws ParseException, IOException { 101 102 int got; 103 104 if (state == IN_RESET) { 105 reset(); 106 } 107 108 while ((got = in.get()) != PushbackByteSource.EOF) { 109 110 switch (state) { 111 case SOL: 112 switch (got) { 113 /* Could be the last line or the start of a new header */ 114 case '\r': 115 got = in.get(); 116 if (got == '\n') { 117 /* Is the end of the headers */ 118 state = IN_RESET; 119 return true; 120 } 121 else if (got == PushbackByteSource.EOF) { 122 /* We don't really know until the next read */ 123 in.pushback('\r'); 124 return false; 125 } 126 else { 127 in.pushback(got); 128 } 129 break; 130 default: 131 in.pushback(got); 132 state = IN_NAME; 133 break; 134 } 135 break; 136 case IN_NAME: 137 switch (got) { 138 case ':': 139 /* End of the name */ 140 state = PRE_VALUE_WS; 141 break; 142 default: 143 name.append((char)got); 144 break; 145 } 146 break; 147 case PRE_VALUE_WS: 148 switch (got) { 149 case ' ': 150 case '\t': 151 /* Keep reading */ 152 break; 153 default: 154 in.pushback(got); 155 state = IN_VALUE; 156 break; 157 } 158 break; 159 case IN_VALUE: 160 switch (got) { 161 case '\r': 162 if ((got = in.get()) == '\n') { 163 state = IN_FOLDING; 164 } 165 else if (got == PushbackByteSource.EOF) { 166 in.pushback('\r'); 167 return false; 168 } 169 else { 170 in.pushback(got); 171 } 172 break; 173 default: 174 value.append((char)got); 175 break; 176 } 177 break; 178 case IN_FOLDING: 179 switch (got) { 180 case ' ': 181 case '\t': 182 /* Is folded - keep reading */ 183 state = IN_VALUE; 184 break; 185 default: 186 addHeader(); 187 188 in.pushback(got); 189 state = SOL; 190 } 191 break; 192 default: 193 assert false; 194 state = SOL; 195 break; 196 } 197 } 198 199 return false; 200 } 201 } 202

This page was automatically generated by Maven