📄 cmsrequesthttpservlet.java
字号:
* @return Enumeration of parameter names.
*/
public Enumeration getParameterNames() {
String type = m_req.getHeader("content-type");
if((type != null) && type.startsWith("multipart/form-data")) {
// add all parameters extreacted in the multipart handling
return m_parameters.keys();
}
else {
// add all parameters from the original request
return m_req.getParameterNames();
}
}
/**
* Returns all parameter values of a parameter key.
*
* @return Aarray of String containing the parameter values.
*/
public String[] getParameterValues(String key) {
return m_req.getParameterValues(key);
}
/**
* This funtion returns the name of the requested resource.
* <P>
* For a http request, the name of the resource is extracted as follows:
* <CODE>http://{servername}/{servletpath}/{path to the cms resource}</CODE>
* In the following example:
* <CODE>http://my.work.server/servlet/opencms/system/def/explorer</CODE>
* the requested resource is <CODE>/system/def/explorer</CODE>.
* </P>
*
* @return The path to the requested resource.
*/
public String getRequestedResource() {
return m_req.getPathInfo();
}
/**
* A utility method that reads a single part of the multipart request
* that represents a file. Unlike the method name it does NOT saves the file to disk.
* The name is from the original O'Reilly implmentaton.
* <p>
* A subclass can override this method for a better optimized or
* differently behaved implementation.
*
* @param in The stream from which to read the file.
* @param boundary The boundary signifying the end of this part.
* @exception IOException If there's a problem reading or parsing the request.
*/
private byte[] readAndSaveFile(CmsMultipartInputStreamHandler in, String boundary) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(8 * 1024);
byte[] boundaryBytes = boundary.getBytes();
int[] lookaheadBuf = new int[boundary.length() + 3];
int[] newLineBuf = {
-1, -1
};
int matches = 0;
int matchingByte = new Byte(boundaryBytes[matches]).intValue();
/*
File parts of multipart request should not be read line by line.
Since some servlet environments touch and change the new line
character(s) when calling the ServletInputStream's <code>readLine</code>
this may cause problems with binary file uploads.
We decided to read this parts byte by byte here.
*/
int read = in.read();
while(read > -1) {
if(read == matchingByte) {
// read byte is matching the next byte of the boundary
// we should not write to the output stream here.
lookaheadBuf[matches] = read;
matches++;
if(matches == boundary.length()) {
// The end of the Boundary has been reached.
// Now snip the following line feed.
read = in.read();
if(newLineBuf[1] == read) {
// New line contains ONE single character.
// Write the last byte of the buffer to the output stream.
out.write(newLineBuf[0]);
}
else {
// new line contains TWO characters, possibly "\r\n"
// The bytes in the buffer are not part of the file.
// We even have to read one more byte.
in.read();
}
break;
}
matchingByte = new Byte(boundaryBytes[matches]).intValue();
}
else {
// read byte does not match the next byte of the boundary
// write the first buffer byte to the output stream
if(newLineBuf[0] != -1) {
out.write(newLineBuf[0]);
}
if(matches == 0) {
// this may be the most propably case.
newLineBuf[0] = newLineBuf[1];
}
else {
// we have started to read the boundary.
// Unfortunately, this was NOT the real boundary.
// Fall back to normal read mode.
// write the complete buffer to the output stream
if(newLineBuf[1] != -1) {
out.write(newLineBuf[1]);
}
for(int i = 0;i < matches;i++) {
out.write(lookaheadBuf[i]);
}
// reset boundary matching counter
matches = 0;
matchingByte = new Byte(boundaryBytes[matches]).intValue();
// clear buffer
newLineBuf[0] = -1;
}
// put the last byte read into the buffer.
// it may be part of a line feed.
newLineBuf[1] = read;
}
read = in.read();
}
out.flush();
return out.toByteArray();
}
/**
* A utility method that reads an individual part. Dispatches to
* readParameter() and readAndSaveFile() to do the actual work.
* <p>
* The single files are stored in a hashtable (seperated in filename and contents)
* for later addition to a CmsFile Object
* <p> A subclass can override this method for a better optimized or
* differently behaved implementation.
*
* @param in The stream from which to read the part
* @param boundary The boundary separating parts
* @return A flag indicating whether this is the last part
* @exception IOException If there's a problem reading or parsing the
* request
*
* @see readParameter
* @see readAndSaveFile
*/
private boolean readNextPart(CmsMultipartInputStreamHandler in, String boundary) throws IOException {
// Read the first line, should look like this:
// content-disposition: form-data; name="field1"; filename="file1.txt"
String line = in.readLine();
if(line == null || line.equals("")) {
// No parts left, we're done
return true;
}
// Parse the content-disposition line
String[] dispInfo = extractDispositionInfo(line);
// String disposition = dispInfo[0];
String name = dispInfo[1];
String filename = dispInfo[2];
// Now onto the next line. This will either be empty
// or contain a Content-Type and then an empty line.
line = in.readLine();
if(line == null) {
// No parts left, we're done
return true;
}
// Get the content type, or null if none specified
String contentType = extractContentType(line);
if(contentType != null) {
// Eat the empty line
line = in.readLine();
if(line == null || line.length() > 0) { // line should be empty
throw new IOException("Malformed line after content type: " + line);
}
}
else {
// Assume a default content type
contentType = "application/octet-stream";
}
// Now, finally, we read the content (end after reading the boundary)
if(filename == null) {
// This is a parameter
String value = readParameter(in, boundary);
m_parameters.put(name, value);
}
else {
// This is a file
byte[] value = readAndSaveFile(in, boundary);
filecounter++;
// stroe the filecontent
m_files.put(filename, value);
// store the name of the file to the parameters
m_parameters.put(name, filename);
}
// there's more to read
return false;
}
/**
* A utility method that reads a single part of the multipart request
* that represents a parameter. A subclass can override this method
* for a better optimized or differently behaved implementation.
*
* @param in The stream from which to read the parameter information
* @param boundary The boundary signifying the end of this part
* @return The parameter value
* @exception IOException If there's a problem reading or parsing the
* request
*/
private String readParameter(CmsMultipartInputStreamHandler in, String boundary) throws IOException {
StringBuffer sbuf = new StringBuffer();
String line;
while((line = in.readLine()) != null) {
if(line.startsWith(boundary)) {
break;
}
// add the \r\n in case there are many lines
sbuf.append(line + "\r\n");
}
if(sbuf.length() == 0) {
// nothing read
return null;
}
// cut off the last line's \r\n
sbuf.setLength(sbuf.length() - 2);
// no URL decoding needed
return sbuf.toString();
}
/**
* This method actually parses the request. A subclass
* can override this method for a better optimized or differently
* behaved implementation.
*
* @exception IOException If the uploaded content is larger than
* <tt>maxSize</tt> or there's a problem parsing the request.
*/
private void readRequest() throws IOException {
// Check the content type to make sure it's "multipart/form-data"
String type = m_req.getContentType();
if(type == null || !type.toLowerCase().startsWith("multipart/form-data")) {
throw new IOException(C_REQUEST_NOMULTIPART);
}
int length = m_req.getContentLength();
// Get the boundary string; it's included in the content type.
// Should look something like "------------------------12012133613061"
String boundary = extractBoundary(type);
if(boundary == null) {
throw new IOException(C_REQUEST_NOBOUNDARY);
}
// Construct the special input stream we'll read from
CmsMultipartInputStreamHandler in = new CmsMultipartInputStreamHandler(m_req.getInputStream(), boundary, length);
// Read the first line, should be the first boundary
String line = in.readLine();
if(line == null) {
throw new IOException(C_REQUEST_PROMATUREEND);
}
// Verify that the line is the boundary
if(!line.startsWith(boundary)) {
throw new IOException(C_REQUEST_NOBOUNDARY);
}
// Now that we're just beyond the first boundary, loop over each part
boolean done = false;
while(!done) {
done = readNextPart(in, boundary);
}
// Unfortunately some servlet environmets cannot handle multipart
// requests AND URL parameters at the same time, we have to manage
// the URL params ourself here. So try to read th URL parameters:
String queryString = m_req.getQueryString();
if(queryString != null) {
StringTokenizer st = new StringTokenizer(m_req.getQueryString(), "&");
while(st.hasMoreTokens()) {
// Loop through all parameters
String currToken = st.nextToken();
if(currToken != null && !"".equals(currToken)) {
// look for the "=" character to divide parameter name and value
int idx = currToken.indexOf("=");
if(idx > -1) {
String key = currToken.substring(0, idx);
String value = (idx < (currToken.length() - 1)) ? currToken.substring(idx + 1) : "";
m_parameters.put(key, value);
}
}
}
}
}
/**
* Returns the part of the Url that descibes the Web-Application.
*
* E.g: http://www.myserver.com/opencms/engine/index.html returns
* http://www.myserver.com/opencms
*/
public String getWebAppUrl() {
return m_webAppUrl;
}
/**
* Gets the part of the Url that describes the current servlet of this
* Web-Application.
*/
public String getServletUrl(){
return m_servletUrl;
}
/**
* Methods to get the data from the original request.
*/
public String getServerName(){
return m_serverName;
}
/**
* Methods to get the data from the original request.
*/
public int getServerPort(){
return m_serverPort;
}
/**
* Methods to get the data from the original request.
*/
public String getScheme(){
return m_scheme;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -