1 /* BionicMessage.net Java GroupDAV library V1.0
4 * Created on Friday 23rd May 2008
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 package net
.bionicmessage
.groupdav
;
27 import java
.io
.BufferedInputStream
;
28 import java
.io
.BufferedReader
;
29 import java
.io
.InputStream
;
30 import java
.io
.InputStreamReader
;
31 import java
.io
.UnsupportedEncodingException
;
32 import java
.net
.MalformedURLException
;
33 import java
.net
.Socket
;
35 import java
.util
.Iterator
;
36 import java
.util
.List
;
38 import java
.util
.logging
.Logger
;
39 import javax
.net
.SocketFactory
;
40 import javax
.net
.ssl
.SSLContext
;
41 import javax
.net
.ssl
.TrustManager
;
42 import javax
.net
.ssl
.X509TrustManager
;
50 static SocketFactory ssf
= null;
51 public static // Create a trust manager that does not validate certificate chains
52 TrustManager
[] trustAllCerts
= new TrustManager
[]{
53 new X509TrustManager() {
55 public java
.security
.cert
.X509Certificate
[] getAcceptedIssuers() {
59 public void checkClientTrusted(
60 java
.security
.cert
.X509Certificate
[] certs
, String authType
) {
63 public void checkServerTrusted(
64 java
.security
.cert
.X509Certificate
[] certs
, String authType
) {
69 public static byte[] buildQuery(String method
,
74 throws UnsupportedEncodingException
{
75 StringBuffer buf
= new StringBuffer();
76 buf
.append(method
).append(" ");
77 buf
.append(fullURL
.getPath());
78 buf
.append(" HTTP/1.1\r\n");
80 buf
.append(fullURL
.getHost());
81 if (fullURL
.getPort() != -1) {
82 buf
.append(":").append(fullURL
.getPort());
84 buf
.append("\r\nConnection: close\r\n");
85 buf
.append(parent
.getBase64cache()).append("\r\n");
86 buf
.append("User-Agent: ").append(groupDAV
.USER_AGENT
).append("\r\n");
87 if (headers
!= null) {
88 Iterator headerIt
= headers
.keySet().iterator();
89 while (headerIt
.hasNext()) {
90 String key
= (String
) headerIt
.next();
91 String value
= (String
) headers
.get(key
);
92 buf
.append(key
).append(": ").append(value
);
96 List
<HTTPCookie
> cookies
= parent
.getCookieJar();
97 if (cookies
.size() > 0) {
98 buf
.append("Cookie: ");
99 for (HTTPCookie c
: cookies
) {
100 buf
.append(c
.getCookieString());
104 if ("PUT".equals(method
) || "REPORT".equals(method
) || "PROPFIND".equals(method
)) {
105 buf
.append("Content-Length: ").append(data
.length
);
109 byte[] headers_content
= buf
.toString().getBytes("UTF-8");
110 byte[] fulldata
= new byte[headers_content
.length
+ data
.length
];
111 System
.arraycopy(headers_content
, 0, fulldata
, 0, headers_content
.length
);
112 System
.arraycopy(data
, 0, fulldata
, headers_content
.length
, data
.length
);
116 public static URL
createURL(String path
,
117 URL serverURL
) throws MalformedURLException
{
118 String newPath
= path
;
119 if (path
.startsWith("http://") || path
.startsWith("https://")) {
120 return new URL(path
);
121 } // Don't muck with full URLs
122 // Clean path of: leading slash, etc.
124 if (path
.startsWith("/")) {
125 newPath
= path
.substring(1);
127 newPath
= newPath
.replace("//", "/");
128 return new URL(serverURL
, newPath
);
131 public static Socket
createSocket(URL url
) throws Exception
{
132 int port
= url
.getPort();
133 if (url
.getProtocol().contains("https")) {
139 SSLContext sc
= SSLContext
.getInstance("SSL");
140 sc
.init(null, Common
.trustAllCerts
, new java
.security
.SecureRandom());
141 ssf
= sc
.getSocketFactory();
142 } catch (Exception e
) {
143 System
.err
.println("Error configuration SSL cert manager");
147 return ssf
.createSocket(url
.getHost(), port
);
152 return new Socket(url
.getHost(), port
);
156 public static HTTPInputStream
sendNonKeepAliveRequest(URL srv
,
157 byte[] data
) throws Exception
{
158 int port
= srv
.getPort();
162 Socket st
= createSocket(srv
);
163 st
.getOutputStream().write(data
);
164 HTTPInputStream is
= new HTTPInputStream(st
);
168 public static String
sendNonKeepAliveRequest(
172 Logger l
) throws Exception
{
173 String dbugstring
= new String(by
);
174 String loggableString
= dbugstring
.replace(parent
.getBase64cache(), "Authorization: Basic [removed]");
175 l
.fine("We sent:\r\n" + loggableString
);
177 long time
= new java
.util
.Date().getTime();
178 Socket st
= createSocket(server
);
179 st
.setSoTimeout(15*1000);
180 st
.getOutputStream().write(by
);
181 st
.getOutputStream().flush();
182 InputStream sc
= st
.getInputStream();
183 BufferedInputStream bis
= new BufferedInputStream(sc
);
185 StringBuffer sb
= new StringBuffer();
188 /* In rare-rare cases some non-printable chars have contaminated the
189 * response we get. Here is a good place to get rid of them */
191 // We need to process the message character by chacter instead of byte by byte
192 // or otherwise 2-4 byte characters (many Unicode characters) get stripped away.
193 // To do this, we use the InputStreamReader class to convert byte stream into
194 // an Unicode character stream.
195 BufferedReader charstream
= new BufferedReader(new InputStreamReader(bis
, "UTF-8"));
198 char[] buf
= new char[300];
199 op
= charstream
.read(buf
);
200 if (op
!= 0 && op
!= -1) {
201 for (int i
= 0; i
< op
; i
++) {
203 // Strip bytes which would foul an XML parser, i.e SIF
204 // for Funambol upstream. See
205 // http://cse-mjmcl.cse.bris.ac.uk/blog/2007/02/14/1171465494443.html
209 ((c
>= 0x20) && (c
<= 0xD7FF)) ||
210 ((c
>= 0xE000) && (c
<= 0xFFFD)) ||
211 ((c
>= 0x10000) && (c
<= 0x10FFFF))) {
221 l
.fine(fouls
+ " invalid (XML-wise) characters detected in stream. Is the source/users clean?");
225 long closetime
= new java
.util
.Date().getTime();
226 long rtt
= closetime
- time
;
227 l
.finer("We got:\r\n" + sb
.toString() + "\r\n....in " + rtt
+ "ms");
228 return sb
.toString();