1 | /* |
2 | Copyright (C) 2002-2004 MySQL AB |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of version 2 of the GNU General Public License as |
6 | published by the Free Software Foundation. |
7 | |
8 | There are special exceptions to the terms and conditions of the GPL |
9 | as it is applied to this software. View the full text of the |
10 | exception in file EXCEPTIONS-CONNECTOR-J in the directory of this |
11 | software distribution. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | |
22 | |
23 | |
24 | */ |
25 | package com.mysql.jdbc; |
26 | |
27 | import java.io.ObjectInputStream; |
28 | import java.io.PrintWriter; |
29 | import java.io.StringWriter; |
30 | |
31 | /** |
32 | * Various utility methods for the driver. |
33 | * |
34 | * @author Mark Matthews |
35 | */ |
36 | public class Util { |
37 | // ~ Static fields/initializers |
38 | // --------------------------------------------- |
39 | |
40 | class RandStructcture { |
41 | long maxValue; |
42 | |
43 | double maxValueDbl; |
44 | |
45 | long seed1; |
46 | |
47 | long seed2; |
48 | } |
49 | |
50 | // ~ Methods |
51 | // ---------------------------------------------------------------- |
52 | |
53 | private static Util enclosingInstance = new Util(); |
54 | |
55 | // Right from Monty's code |
56 | static String newCrypt(String password, String seed) { |
57 | byte b; |
58 | double d; |
59 | |
60 | if ((password == null) || (password.length() == 0)) { |
61 | return password; |
62 | } |
63 | |
64 | long[] pw = newHash(seed); |
65 | long[] msg = newHash(password); |
66 | long max = 0x3fffffffL; |
67 | long seed1 = (pw[0] ^ msg[0]) % max; |
68 | long seed2 = (pw[1] ^ msg[1]) % max; |
69 | char[] chars = new char[seed.length()]; |
70 | |
71 | for (int i = 0; i < seed.length(); i++) { |
72 | seed1 = ((seed1 * 3) + seed2) % max; |
73 | seed2 = (seed1 + seed2 + 33) % max; |
74 | d = (double) seed1 / (double) max; |
75 | b = (byte) java.lang.Math.floor((d * 31) + 64); |
76 | chars[i] = (char) b; |
77 | } |
78 | |
79 | seed1 = ((seed1 * 3) + seed2) % max; |
80 | seed2 = (seed1 + seed2 + 33) % max; |
81 | d = (double) seed1 / (double) max; |
82 | b = (byte) java.lang.Math.floor(d * 31); |
83 | |
84 | for (int i = 0; i < seed.length(); i++) { |
85 | chars[i] ^= (char) b; |
86 | } |
87 | |
88 | return new String(chars); |
89 | } |
90 | |
91 | static long[] newHash(String password) { |
92 | long nr = 1345345333L; |
93 | long add = 7; |
94 | long nr2 = 0x12345671L; |
95 | long tmp; |
96 | |
97 | for (int i = 0; i < password.length(); ++i) { |
98 | if ((password.charAt(i) == ' ') || (password.charAt(i) == '\t')) { |
99 | continue; // skip spaces |
100 | } |
101 | |
102 | tmp = (0xff & password.charAt(i)); |
103 | nr ^= ((((nr & 63) + add) * tmp) + (nr << 8)); |
104 | nr2 += ((nr2 << 8) ^ nr); |
105 | add += tmp; |
106 | } |
107 | |
108 | long[] result = new long[2]; |
109 | result[0] = nr & 0x7fffffffL; |
110 | result[1] = nr2 & 0x7fffffffL; |
111 | |
112 | return result; |
113 | } |
114 | |
115 | static String oldCrypt(String password, String seed) { |
116 | long hp; |
117 | long hm; |
118 | long s1; |
119 | long s2; |
120 | long max = 0x01FFFFFF; |
121 | double d; |
122 | byte b; |
123 | |
124 | if ((password == null) || (password.length() == 0)) { |
125 | return password; |
126 | } |
127 | |
128 | hp = oldHash(seed); |
129 | hm = oldHash(password); |
130 | |
131 | long nr = hp ^ hm; |
132 | nr %= max; |
133 | s1 = nr; |
134 | s2 = nr / 2; |
135 | |
136 | char[] chars = new char[seed.length()]; |
137 | |
138 | for (int i = 0; i < seed.length(); i++) { |
139 | s1 = ((s1 * 3) + s2) % max; |
140 | s2 = (s1 + s2 + 33) % max; |
141 | d = (double) s1 / max; |
142 | b = (byte) java.lang.Math.floor((d * 31) + 64); |
143 | chars[i] = (char) b; |
144 | } |
145 | |
146 | return new String(chars); |
147 | } |
148 | |
149 | static long oldHash(String password) { |
150 | long nr = 1345345333; |
151 | long nr2 = 7; |
152 | long tmp; |
153 | |
154 | for (int i = 0; i < password.length(); i++) { |
155 | if ((password.charAt(i) == ' ') || (password.charAt(i) == '\t')) { |
156 | continue; |
157 | } |
158 | |
159 | tmp = password.charAt(i); |
160 | nr ^= ((((nr & 63) + nr2) * tmp) + (nr << 8)); |
161 | nr2 += tmp; |
162 | } |
163 | |
164 | return nr & ((1L << 31) - 1L); |
165 | } |
166 | |
167 | private static RandStructcture randomInit(long seed1, long seed2) { |
168 | RandStructcture randStruct = enclosingInstance.new RandStructcture(); |
169 | |
170 | randStruct.maxValue = 0x3FFFFFFFL; |
171 | randStruct.maxValueDbl = randStruct.maxValue; |
172 | randStruct.seed1 = seed1 % randStruct.maxValue; |
173 | randStruct.seed2 = seed2 % randStruct.maxValue; |
174 | |
175 | return randStruct; |
176 | } |
177 | |
178 | /** |
179 | * Given a ResultSet and an index into the columns of that ResultSet, read |
180 | * binary data from the column which represents a serialized object, and |
181 | * re-create the object. |
182 | * |
183 | * @param resultSet |
184 | * the ResultSet to use. |
185 | * @param index |
186 | * an index into the ResultSet. |
187 | * @return the object if it can be de-serialized |
188 | * @throws Exception |
189 | * if an error occurs |
190 | */ |
191 | public static Object readObject(java.sql.ResultSet resultSet, int index) |
192 | throws Exception { |
193 | ObjectInputStream objIn = new ObjectInputStream(resultSet |
194 | .getBinaryStream(index)); |
195 | Object obj = objIn.readObject(); |
196 | objIn.close(); |
197 | |
198 | return obj; |
199 | } |
200 | |
201 | private static double rnd(RandStructcture randStruct) { |
202 | randStruct.seed1 = ((randStruct.seed1 * 3) + randStruct.seed2) |
203 | % randStruct.maxValue; |
204 | randStruct.seed2 = (randStruct.seed1 + randStruct.seed2 + 33) |
205 | % randStruct.maxValue; |
206 | |
207 | return ((randStruct.seed1) / randStruct.maxValueDbl); |
208 | } |
209 | |
210 | /** |
211 | * DOCUMENT ME! |
212 | * |
213 | * @param message |
214 | * DOCUMENT ME! |
215 | * @param password |
216 | * DOCUMENT ME! |
217 | * |
218 | * @return DOCUMENT ME! |
219 | */ |
220 | public static String scramble(String message, String password) { |
221 | long[] hashPass; |
222 | long[] hashMessage; |
223 | byte[] to = new byte[8]; |
224 | String val = ""; //$NON-NLS-1$ |
225 | |
226 | message = message.substring(0, 8); |
227 | |
228 | if ((password != null) && (password.length() > 0)) { |
229 | hashPass = newHash(password); |
230 | hashMessage = newHash(message); |
231 | |
232 | RandStructcture randStruct = randomInit(hashPass[0] |
233 | ^ hashMessage[0], hashPass[1] ^ hashMessage[1]); |
234 | |
235 | int msgPos = 0; |
236 | int msgLength = message.length(); |
237 | int toPos = 0; |
238 | |
239 | while (msgPos++ < msgLength) { |
240 | to[toPos++] = (byte) (Math.floor(rnd(randStruct) * 31) + 64); |
241 | } |
242 | |
243 | /* Make it harder to break */ |
244 | byte extra = (byte) (Math.floor(rnd(randStruct) * 31)); |
245 | |
246 | for (int i = 0; i < to.length; i++) { |
247 | to[i] ^= extra; |
248 | } |
249 | |
250 | val = new String(to); |
251 | } |
252 | |
253 | return val; |
254 | } |
255 | |
256 | // ~ Inner Classes |
257 | // ---------------------------------------------------------- |
258 | |
259 | /** |
260 | * Converts a nested exception into a nicer message |
261 | * |
262 | * @param ex |
263 | * the exception to expand into a message. |
264 | * |
265 | * @return a message containing the exception, the message (if any), and a |
266 | * stacktrace. |
267 | */ |
268 | public static String stackTraceToString(Throwable ex) { |
269 | StringBuffer traceBuf = new StringBuffer(); |
270 | traceBuf.append(Messages.getString("Util.1")); //$NON-NLS-1$ |
271 | |
272 | if (ex != null) { |
273 | traceBuf.append(ex.getClass().getName()); |
274 | |
275 | String message = ex.getMessage(); |
276 | |
277 | if (message != null) { |
278 | traceBuf.append(Messages.getString("Util.2")); //$NON-NLS-1$ |
279 | traceBuf.append(message); |
280 | } |
281 | |
282 | StringWriter out = new StringWriter(); |
283 | |
284 | PrintWriter printOut = new PrintWriter(out); |
285 | |
286 | ex.printStackTrace(printOut); |
287 | |
288 | traceBuf.append(Messages.getString("Util.3")); //$NON-NLS-1$ |
289 | traceBuf.append(out.toString()); |
290 | } |
291 | |
292 | traceBuf.append(Messages.getString("Util.4")); //$NON-NLS-1$ |
293 | |
294 | return traceBuf.toString(); |
295 | } |
296 | } |