| 1 33 34 35 36 package com.internetcds.jdbc.tds; 37 38 import java.net.Socket ; 39 import java.util.Vector ; 40 import java.lang.Thread ; 41 import java.util.StringTokenizer ; 42 import java.sql.*; 43 import com.internetcds.jdbc.tds.TdsComm; 44 import com.internetcds.util.Logger; 45 import java.math.BigInteger ; 46 import java.math.BigDecimal ; 47 import java.util.Calendar ; 48 import java.util.Properties ; 49 import java.util.TimeZone ; 50 import java.util.Locale ; 51 52 53 54 60 class TimeoutHandler extends Thread  61 { 62 public static final String cvsVersion = "$Id: Tds.java,v 1.1 2006/06/23 10:39:30 sinisa Exp $"; 63 64 java.sql.Statement stmt; 65 int timeout; 66 67 68 public TimeoutHandler( 69 java.sql.Statement stmt_, 70 int timeout_) 71 { 72 stmt = stmt_; 73 timeout = timeout_; 74 } 75 76 77 public void run() 78 { 79 try 80 { 81 sleep(timeout * 1000); 82 stmt.cancel(); 83 } 84 catch(SQLException e) 85 { 86 } 88 catch(java.lang.InterruptedException e) 89 { 90 } 92 } 93 } 94 95 96 97 105 public class Tds implements TdsDefinitions 106 { 107 public static final String cvsVersion = "$Id: Tds.java,v 1.1 2006/06/23 10:39:30 sinisa Exp $"; 108 109 110 static boolean ignoreNotImplemented = false; 118 119 120 Socket sock = null; 121 TdsComm comm = null; 122 123 String databaseProductName; 124 String databaseProductVersion; 125 126 java.sql.Connection connection; 127 String host; 128 int serverType = -1; int port; String database; 131 String user; 132 String password; 133 String appName; 134 String serverName; 135 String progName; 136 byte progMajorVersion; 137 byte progMinorVersion; 138 139 boolean haveProcNameTable = false; 140 String procNameGeneratorName = null; 141 String procNameTableName = null; 142 143 String initialSettings = null; 144 145 private Properties initialProps = null; 146 private EncodingHelper encoder = null; 147 private String charset = null; 148 149 private boolean moreResults = false; 152 private boolean moreResults2 = true; 156 157 CancelController cancelController = null; 158 159 SqlMessage lastServerMessage = null; 160 161 private int tdsVer = Tds.TDS42; 163 164 private boolean showWarnings = false; 166 167 private int zoneOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET); 169 170 public Tds( 171 java.sql.Connection connection_, 172 Properties props_, 173 String initialSettings) 174 throws java.io.IOException , java.net.UnknownHostException , 175 java.sql.SQLException , com.internetcds.jdbc.tds.TdsException 176 { 177 connection = (java.sql.Connection )connection_; 178 initialProps = props_; 179 180 host = props_.getProperty("HOST"); 181 serverType = Integer.parseInt(props_.getProperty("SERVERTYPE")); 182 port = Integer.parseInt(props_.getProperty("PORT")); 183 database = props_.getProperty("DBNAME"); 184 user = props_.getProperty("user"); 185 password = props_.getProperty("password"); 186 appName = props_.getProperty("APPNAME", "jdbclib"); 187 serverName = props_.getProperty("SERVERNAME", host); 188 progName = props_.getProperty("PROGNAME", "java_app"); 189 progMajorVersion = (byte)DriverVersion.getDriverMajorVersion(); 190 progMinorVersion = (byte)DriverVersion.getDriverMinorVersion(); 191 String verString = props_.getProperty("TDS", "7.0"); 193 194 197 198 tdsVer = TDS42; 199 if (verString.equals("5.0")) 200 { 201 tdsVer = Tds.TDS50; 202 } 203 else if (verString.equals("7.0")) 204 { 205 tdsVer = Tds.TDS70; 206 } 207 if (System.getProperty("TDS_SHOW_WARNINGS") != null 209 || 210 props_.getProperty("TDS_SHOW_WARNINGS") != null) 211 { 212 showWarnings = true; 213 } 214 215 cancelController = new CancelController(); 216 217 sock = new Socket (host, port); 219 sock.setTcpNoDelay(true); 220 comm = new TdsComm(sock, tdsVer); 221 222 setCharset(props_.getProperty("CHARSET")); 223 224 if (logon()) 225 { 226 } 228 else 229 { 230 throw new SQLException("Logon failed. " + lastServerMessage); 231 } 232 } 233 234 private void setCharset(String charset) 235 { 236 try 237 { 238 Logger.println("Trying to change charset to " + charset); 239 } 240 catch(java.io.IOException e) 241 { 242 } 244 245 if (charset == null || charset.length() > 30) 246 { 247 charset = "iso_1"; 248 } 249 250 if (!charset.equals(this.charset)) 251 { 252 encoder = EncodingHelper.getHelper(charset); 253 if (encoder == null) 254 { 255 charset = "iso_1"; 256 encoder = EncodingHelper.getHelper(charset); 257 } 258 this.charset = charset; 259 } 260 } 261 262 EncodingHelper getEncoder() { 263 return encoder; 264 } 265 266 public void close() 267 { 268 comm.close(); 269 try 270 { 271 sock.close(); 272 } 273 catch(java.io.IOException e) 274 { 275 } 277 } 278 279 static private int toUInt(byte b) 280 { 281 int result = ((int)b) & 0x00ff; 282 return result; 283 } 284 285 public String toString() 286 { 287 return "" 288 + database + ", " 289 + sock.getLocalAddress() + ":" + sock.getLocalPort() 290 + " -> " + sock.getInetAddress() + ":" + sock.getPort(); 291 } 292 293 294 301 static public String toNativeSql(String input, int serverType) 302 throws SQLException 303 { 304 EscapeProcessor escape; 305 if (serverType==TdsDefinitions.SYBASE) 306 { 307 escape = new SybaseEscapeProcessor(input); 308 } 309 else 310 { 311 escape = new MSSqlServerEscapeProcessor(input); 312 } 313 314 return escape.nativeString(); 315 } 316 317 318 328 public static byte cvtJdbcTypeToNativeType(int jdbcType) 329 throws TdsNotImplemented 330 { 331 byte result = 0; 333 switch(jdbcType) 334 { 335 case java.sql.Types.CHAR: 336 { 339 result = SYBCHAR; 340 break; 341 } 342 case java.sql.Types.VARCHAR: 345 case java.sql.Types.LONGVARCHAR: 346 { 347 result = SYBVARCHAR; 348 break; 349 } 350 case java.sql.Types.DECIMAL: 353 { 354 result = SYBFLT8; 355 break; 356 } 357 case java.sql.Types.INTEGER: 358 case java.sql.Types.SMALLINT: 359 case java.sql.Types.BIGINT: 360 { 361 result = SYBINT4; 362 break; 363 } 364 case java.sql.Types.REAL: 365 case java.sql.Types.DOUBLE: 366 { 367 result = SYBFLT8; 368 break; 369 } 370 case java.sql.Types.DATE: 371 case java.sql.Types.TIMESTAMP: 372 case java.sql.Types.TIME: 373 { 374 result = SYBDATETIMN; 375 break; 376 } 377 case java.sql.Types.VARBINARY: 378 case java.sql.Types.LONGVARBINARY: 379 { 380 result = SYBIMAGE; 381 break; 382 } 383 case java.sql.Types.BIT: 385 { 386 result = SYBBIT; 387 break; 388 } 389 default: 390 { 391 throw new TdsNotImplemented("cvtJdbcTypeToNativeType (" 392 + TdsUtil.javaSqlTypeToString(jdbcType) + ")"); 393 } 394 } 395 396 return result; 397 } 398 399 400 411 public static int cvtNativeTypeToJdbcType(int nativeType, 412 int size) 413 throws TdsException 414 { 415 416 418 int result = java.sql.Types.OTHER; 419 switch(nativeType) 420 { 421 case SYBBINARY: result = java.sql.Types.BINARY; break; 423 case SYBBIT: result = java.sql.Types.BIT; break; 424 case SYBBITN: result = java.sql.Types.BIT; break; 425 case SYBCHAR: result = java.sql.Types.CHAR; break; 426 case SYBNCHAR: result = java.sql.Types.CHAR; break; 427 case SYBDATETIME4: result = java.sql.Types.TIMESTAMP; break; 428 case SYBDATETIME: result = java.sql.Types.TIMESTAMP; break; 429 case SYBDATETIMN: result = java.sql.Types.TIMESTAMP; break; 430 case SYBDECIMAL: result = java.sql.Types.DECIMAL; break; 431 case SYBNUMERIC: result = java.sql.Types.NUMERIC; break; 432 case SYBFLT8: result = java.sql.Types.DOUBLE; break; 433 case SYBFLTN: result = java.sql.Types.DOUBLE; break; 434 case SYBINT1: result = java.sql.Types.TINYINT; break; 435 case SYBINT2: result = java.sql.Types.SMALLINT; break; 436 case SYBINT4: result = java.sql.Types.INTEGER; break; 437 case SYBINTN: 438 { 439 switch (size) 440 { 441 case 1: result = java.sql.Types.TINYINT; break; 442 case 2: result = java.sql.Types.SMALLINT; break; 443 case 4: result = java.sql.Types.INTEGER; break; 444 default: throw new TdsException("Bad size of SYBINTN"); 445 } 446 break; 447 } 448 case SYBSMALLMONEY: result = java.sql.Types.NUMERIC; break; 450 case SYBMONEY4: result = java.sql.Types.NUMERIC; break; 451 case SYBMONEY: result = java.sql.Types.NUMERIC; break; 452 case SYBMONEYN: result = java.sql.Types.NUMERIC; break; 453 case SYBREAL: result = java.sql.Types.REAL; break; 455 case SYBTEXT: result = java.sql.Types.LONGVARCHAR; break; 456 case SYBNTEXT: result = java.sql.Types.LONGVARCHAR; break; 457 case SYBIMAGE: result = java.sql.Types.VARBINARY; break; 458 case SYBVARBINARY: result = java.sql.Types.VARBINARY; break; 459 case SYBVARCHAR: result = java.sql.Types.VARCHAR; break; 460 case SYBNVARCHAR: result = java.sql.Types.VARCHAR; break; 461 default: throw new TdsException("Unknown native data type " 463 + Integer.toHexString( 464 nativeType&0xff)); 465 } 466 return result; 467 } 468 469 470 475 public int getServerType() 476 { 477 return serverType; 478 } 479 480 481 487 private String getClientName() 488 { 489 String tmp; 491 try 492 { 493 tmp = java.net.InetAddress.getLocalHost().getHostName(); 494 } 495 catch(java.net.UnknownHostException e) 496 { 497 tmp = ""; 498 } 499 StringTokenizer st = new StringTokenizer (tmp, "."); 500 501 502 503 if (!st.hasMoreTokens()) 504 { 505 return "JOHNDOE"; 507 } 508 509 tmp = st.nextToken(); 511 if (tmp.length()==0) 512 { 513 return "JANEDOE"; 516 } 517 else if (Character.isDigit(tmp.charAt(0))) 518 { 519 return "BABYDOE"; 523 } 524 else 525 { 526 return tmp.toUpperCase(); 530 } 531 } 532 533 534 608 private boolean logon() 609 throws java.sql.SQLException , 610 TdsUnknownPacketSubType, java.io.IOException , 611 com.internetcds.jdbc.tds.TdsException 612 { 613 boolean isOkay = true; 614 byte pad = (byte) 0; 615 byte[] empty = new byte[0]; 616 617 if (tdsVer == Tds.TDS70) 619 send70Login(); 620 else { 621 622 comm.startPacket(TdsComm.LOGON); 623 624 byte[] tmp = encoder.getBytes(getClientName()); 627 comm.appendBytes(tmp, 30, pad); 628 comm.appendByte((byte)(tmp.length < 30 ? tmp.length : 30)); 629 630 tmp = encoder.getBytes(user); 632 comm.appendBytes(tmp, 30, pad); 633 comm.appendByte((byte)(tmp.length < 30 ? tmp.length : 30)); 634 635 tmp = encoder.getBytes(password); 637 comm.appendBytes(tmp, 30, pad); 638 comm.appendByte((byte)(tmp.length < 30 ? tmp.length : 30)); 639 640 tmp = encoder.getBytes("00000116"); 642 comm.appendBytes(tmp, 8, pad); 643 644 comm.appendBytes(empty, (30-14), pad); 646 647 comm.appendByte((byte)0x0); 649 comm.appendByte((byte)0xA0); 650 comm.appendByte((byte)0x24); 651 comm.appendByte((byte)0xCC); 652 comm.appendByte((byte)0x50); 653 comm.appendByte((byte)0x12); 654 655 comm.appendByte((byte)8); 657 658 comm.appendByte((byte)3); 660 661 comm.appendByte((byte)1); 663 664 comm.appendByte((byte)6); 666 667 comm.appendByte((byte)10); 669 670 comm.appendByte((byte)9); 672 673 comm.appendByte((byte)1); 675 676 comm.appendByte((byte)1); 678 679 comm.appendByte((byte)0); 681 682 comm.appendByte((byte)0); 684 685 comm.appendBytes(empty, 7, pad); 687 688 tmp = encoder.getBytes(appName); 690 comm.appendBytes(tmp, 30, pad); 691 comm.appendByte((byte)(tmp.length < 30 ? tmp.length : 30)); 692 693 tmp = encoder.getBytes(serverName); 695 comm.appendBytes(tmp, 30, pad); 696 comm.appendByte((byte)(tmp.length < 30 ? tmp.length : 30)); 697 698 comm.appendBytes(empty, 2, pad); 700 tmp = encoder.getBytes(password); 701 comm.appendBytes(tmp, 253, pad); 702 comm.appendByte((byte)(tmp.length < 253 ? tmp.length+2 : 253+2)); 703 704 comm.appendByte((byte)4); 706 comm.appendByte((byte)2); 707 comm.appendByte((byte)0); 708 comm.appendByte((byte)0); 709 710 tmp = encoder.getBytes(progName); 712 comm.appendBytes(tmp, 10, pad); 713 comm.appendByte((byte)(tmp.length < 10 ? tmp.length : 10)); 714 715 comm.appendByte((byte) 6); comm.appendByte((byte) 0); comm.appendByte((byte) 0); 719 comm.appendByte((byte) 0); 720 721 comm.appendByte((byte)0); 723 724 comm.appendByte((byte)0x0D); 726 727 comm.appendByte((byte)0x11); 729 730 tmp = encoder.getBytes("us_english"); 732 comm.appendBytes(tmp, 30, pad); 733 comm.appendByte((byte)(tmp.length < 30 ? tmp.length : 30)); 734 735 comm.appendByte((byte)1); 737 738 comm.appendShort((short)0); 740 741 comm.appendBytes(empty, 8, pad); 743 744 comm.appendShort((short)0); 746 747 comm.appendByte((byte)0); 749 750 tmp = encoder.getBytes(charset); 752 comm.appendBytes(tmp, 30, pad); 753 comm.appendByte((byte)(tmp.length < 30 ? tmp.length : 30)); 754 755 comm.appendByte((byte)1); 757 758 tmp = encoder.getBytes("512"); 760 comm.appendBytes(tmp, 6, pad); 761 comm.appendByte((byte)3); 762 763 comm.appendBytes(empty, 8, pad); 765 766 moreResults2=true; } 768 769 comm.sendPacket(); 770 771 PacketResult result; 773 774 while (! ((result = processSubPacket()) instanceof PacketEndTokenResult)) 775 { 776 if (result instanceof PacketErrorResult) 777 { 778 isOkay = false; 779 } 780 } 782 783 784 if (isOkay) 785 { 786 isOkay = changeSettings(database, initialSettings); 788 } 789 790 return isOkay; 793 } 794 795 796 804 private void send70Login() throws java.io.IOException { 805 806 byte[] magic1 = {(byte)0006, (byte)0203, (byte)0362, (byte)0370, 807 (byte)0377, (byte)0000, (byte)0000, (byte)0000, 808 (byte)0000, (byte)0340, (byte)0003, (byte)0000, 809 (byte)0000, (byte)0210, (byte)0377, (byte)0377, 810 (byte)0377, (byte)0066, (byte)0004, (byte)0000, 811 (byte)0000}; 812 byte[] magic2 = {(byte)0000, (byte)0100, (byte)0063, (byte)0232, 813 (byte)0153, (byte)0120}; 814 byte[] magic3 = encoder.getBytes("NTLMSSP"); 815 String libName = "DB-Library"; 816 byte pad = (byte)0; 817 byte[] empty = new byte[0]; 818 String appName = "CDR"; 819 short len = (short)(86 + 2 * (user.length() + 820 password.length() + 821 appName.length() + 822 serverName.length() + 823 libName.length())); 824 short packSize = (short)(len + 48); 825 comm.startPacket(TdsComm.LOGON70); 826 comm.appendTdsShort(packSize); 827 comm.appendBytes(empty, 5, pad); 828 comm.appendByte((byte)0x70); 829 comm.appendBytes(empty, 7, pad); 830 comm.appendBytes(magic1, 21, pad); 831 832 short curPos = 86; 834 835 comm.appendTdsShort(curPos); 837 comm.appendTdsShort((short)0); 838 839 comm.appendTdsShort(curPos); 841 comm.appendTdsShort((short)user.length()); 842 curPos += user.length() * 2; 843 844 comm.appendTdsShort(curPos); 846 comm.appendTdsShort((short)password.length()); 847 curPos += password.length() * 2; 848 849 comm.appendTdsShort(curPos); 851 comm.appendTdsShort((short)appName.length()); 852 curPos += appName.length() * 2; 853 854 comm.appendTdsShort(curPos); 856 comm.appendTdsShort((short)serverName.length()); 857 curPos += serverName.length() * 2; 858 859 comm.appendTdsShort((short)0); 861 comm.appendTdsShort((short)0); 862 863 comm.appendTdsShort(curPos); 865 comm.appendTdsShort((short)libName.length()); 866 curPos += libName.length() * 2; 867 868 comm.appendTdsShort(curPos); 870 comm.appendTdsShort((short)0); 871 comm.appendTdsShort(curPos); 872 comm.appendTdsShort((short)0); 873 874 comm.appendBytes(magic2, 6, pad); 876 comm.appendTdsShort(len); 877 comm.appendTdsShort((short)0x30); 878 comm.appendTdsShort(packSize); 879 comm.appendTdsShort((short)0); 880 881 String scrambledPw = tds7CryptPass(password); 883 comm.appendChars(user); 884 comm.appendChars(scrambledPw); 885 comm.appendChars(appName); 886 comm.appendChars(serverName); 887 comm.appendChars(libName); 888 889 comm.appendBytes(magic3, 7, pad); 891 comm.appendByte((byte)0); 892 comm.appendByte((byte)1); 893 comm.appendBytes(empty, 3, pad); 894 comm.appendByte((byte)6); 895 comm.appendByte((byte)130); 896 comm.appendBytes(empty, 22, pad); 897 comm.appendByte((byte)48); 898 comm.appendBytes(empty, 7, pad); 899 comm.appendByte((byte)48); 900 comm.appendBytes(empty, 3, pad); 901 } 902 903 906 private static String tds7CryptPass(String pw) { 907 int xormask = 0x5A5A; 908 int len = pw.length(); 909 char[] chars = new char[len]; 910 for (int i = 0; i < len; ++i) { 911 int c = (int)(pw.charAt(i)) ^ xormask; 912 int m1 = (c >> 4) & 0x0F0F; 913 int m2 = (c << 4) & 0xF0F0; 914 chars[i] = (char)(m1 | m2); 915 } 916 return new String (chars); 917 } 918 919 925 synchronized public boolean changeSettings( 926 String database, 927 String settings) 928 |