001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.war.webdav;
034:
035: import org.apache.commons.codec.binary.Base64;
036:
037: import javax.servlet.Servlet;
038: import javax.servlet.ServletConfig;
039: import javax.servlet.ServletException;
040: import javax.servlet.http.Cookie;
041: import javax.servlet.http.HttpServletRequest;
042: import javax.servlet.http.HttpServletResponse;
043: import javax.xml.parsers.DocumentBuilder;
044: import javax.xml.parsers.DocumentBuilderFactory;
045: import javax.xml.parsers.ParserConfigurationException;
046: import java.io.ByteArrayOutputStream;
047: import java.io.IOException;
048: import java.io.InputStream;
049: import java.io.OutputStream;
050:
051: public abstract class FxWebDavServlet extends FxWebDavServletBase
052: implements Servlet {
053:
054: private static final String RE_AUTH = "@AUTH_RE@";
055: private static String PREFIX = null;
056: private static FxDavContext dc = null;
057:
058: /**
059: * Tries to LOG a user in for webdav access.
060: * <p/>
061: * This function has to be fast since some dav clients are calling the login with every request,
062: * therefor caching is recommended.
063: *
064: * @param request the request
065: * @param username the username
066: * @param password the password
067: * @return true if the login was successfull
068: */
069: protected abstract boolean login(HttpServletRequest request,
070: String username, String password);
071:
072: /**
073: * Chcks if a webdav user is currently logged in.
074: *
075: * @param request the request
076: * @return true if a user is currently logged in an may access webdav
077: */
078: protected abstract boolean isLoggedIn(HttpServletRequest request);
079:
080: /**
081: * Returns the dav context that should be used.
082: *
083: * @return the dav context
084: */
085: protected static FxDavContext getDavContext() {
086: return dc;
087: }
088:
089: public void init(ServletConfig servletConfig)
090: throws ServletException {
091: super .init(servletConfig);
092: try {
093: String className = getInitParameter("FxDavContext");
094: Class cdc = Class.forName(className);
095: dc = ((FxDavContext) cdc.newInstance()).getSingleton();
096: } catch (Exception exc) {
097: String error = "Failed to initialize the webdav context: "
098: + exc.getMessage();
099: if (debug > 0)
100: System.err.println(error);
101: throw new ServletException(error);
102: }
103: }
104:
105: /**
106: * The service methode.
107: *
108: * @param req the request
109: * @param response the response
110: * @throws ServletException if a error occurs
111: * @throws IOException if a IO error occurs
112: */
113: public void service(HttpServletRequest req,
114: HttpServletResponse response) throws ServletException,
115: IOException {
116:
117: if (debug > 0)
118: System.out.println("WebDAVCall debug level: " + debug);
119:
120: // Initialize the href prefix upon the first call
121: if (PREFIX == null) {
122: PREFIX = ((req.getContextPath() == null) ? "" : req
123: .getContextPath())
124: + ((req.getServletPath() == null) ? "" : req
125: .getServletPath());
126: }
127: // TODO: gnome nautilus looses ssl session every few seconds and reauthorizes itself,
128: // this means we need some kind of userticket caching.
129:
130: // Security
131: final String AUTH = req.getHeader("Authorization");
132: if (AUTH != null && AUTH.length() > 0) {
133: String enc = AUTH.substring(6);
134: String dec = new String(Base64.decodeBase64(enc
135: .getBytes("UTF-8")), "UTF-8");
136: int idx = dec.indexOf(":");
137: String uid = dec.substring(0, idx);
138: String pwd = dec.substring(idx + 1);
139: if (!login(req, uid, pwd)) {
140: sendAuthRequest(req, response);
141: return;
142: }
143: response.addCookie(new Cookie("flexive-webdav", "true"));
144: } else if (!isLoggedIn(req) /*&& req.isSecure()*/) {
145: sendAuthRequest(req, response);
146: return;
147: }
148:
149: // All okay, service the request
150: super .service(req, response);
151: }
152:
153: /**
154: * Helper function to send the authenticate request.
155: *
156: * @param request the request
157: * @param response the repsonse
158: */
159: private void sendAuthRequest(HttpServletRequest request,
160: HttpServletResponse response) {
161: request.getSession().removeAttribute(RE_AUTH);
162: response.addHeader("WWW-Authenticate",
163: "BASIC realm=\"[fleXive] powered WebDav\"");
164: response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
165: }
166:
167: /**
168: * Return JAXP document builder instance.
169: *
170: * @return the JAXP document builder instance
171: * @throws ServletException
172: */
173: protected static DocumentBuilder getDocumentbuilder()
174: throws ServletException {
175: DocumentBuilder documentBuilder;
176: DocumentBuilderFactory documentBuilderFactory;
177: try {
178: documentBuilderFactory = DocumentBuilderFactory
179: .newInstance();
180: documentBuilderFactory.setNamespaceAware(true);
181: documentBuilder = documentBuilderFactory
182: .newDocumentBuilder();
183: } catch (ParserConfigurationException e) {
184: throw new ServletException(
185: "Unable to get the document builder: "
186: + e.getMessage());
187: }
188: return documentBuilder;
189: }
190:
191: /**
192: * Rewrites the url.
193: *
194: * @param path the path to process
195: * @return the final url
196: */
197: protected static String rewriteUrl(String path) {
198: path = PREFIX + (path.startsWith("/") ? "" : "/") + path;
199: if (path.endsWith("/")) {
200: path = path.substring(1, path.length() - 1);
201: }
202: if (path.charAt(0) != '/') {
203: path = "/" + path;
204: }
205: return FxWebDavServletBase.rewriteUrl(path);
206: }
207:
208: /**
209: * Converts the input stream to a string.
210: *
211: * @param re the request
212: * @return the input stream as string
213: */
214: protected static String inputStreamToString(HttpServletRequest re) {
215: InputStream is = null;
216: OutputStream os = null;
217: try {
218: byte[] buffer = new byte[4096];
219: is = re.getInputStream();
220: os = new ByteArrayOutputStream();
221: while (true) {
222: int read = is.read(buffer);
223: if (read == -1) {
224: break;
225: }
226: os.write(buffer, 0, read);
227: }
228: return os.toString();
229: } catch (Exception exc) {
230: return "";
231: } finally {
232: if (is != null)
233: try {
234: is.close();
235: } catch (Exception e) {/*ignore*/
236: }
237: if (os != null)
238: try {
239: os.close();
240: } catch (Exception e) {/*ignore*/
241: }
242: }
243: }
244: }
|