1 33 34 package com.internetcds.jdbc.tds; 35 36 import java.sql.*; 37 38 39 abstract public class EscapeProcessor 40 { 41 public static final String cvsVersion = "$Id: EscapeProcessor.java,v 1.1 2006/06/23 10:39:04 sinisa Exp $"; 42 43 String input; 44 45 public EscapeProcessor(String sql) 46 { 47 input = sql; 48 } 50 abstract public String expandDBSpecificFunction(String escapeSequence) 51 throws SQLException; 52 53 60 private static boolean validDigits(String str) 61 { 62 boolean result = true; 63 int i; 64 65 for(i=0, result = true; result && i<str.length(); i++) 66 { 67 result = result && Character.isDigit(str.charAt(i)); 68 } 69 return result; 70 } 72 78 private static int skipWhitespace(String str, int i) 79 { 80 while(i<str.length() && Character.isWhitespace(str.charAt(i))) 81 { 82 i++; 83 } 84 return i; 85 } 87 88 94 private static int skipQuote(String str, int i) 95 { 96 97 if (i<str.length() && (str.charAt(i)=='\'' || str.charAt(i)=='"')) 99 { 100 i++; 104 } 105 return i; 106 } 108 113 private static String getDate(String str) 114 throws SQLException 115 { 116 int i; 117 118 i = 2; 120 121 i = skipWhitespace(str, i); 123 124 i = skipQuote(str, i); 125 126 if (((str.length()-i) < 10) 128 || str.charAt(i+4)!='-' || str.charAt(i+7)!='-') 129 { 130 throw new SQLException("Malformed date"); 131 } 132 133 String year = str.substring(i, i+4); 134 String month = str.substring(i+5, i+5+2); 135 String day = str.substring(i+5+3, i+5+3+2); 136 137 if (!validDigits(year) || !validDigits(month) || !validDigits(day)) 139 { 140 throw new SQLException("Malformed date"); 141 } 142 143 i = i+10; 145 i = skipWhitespace(str, i); 146 i = skipQuote(str, i); 147 i = skipWhitespace(str, i); 148 149 if (i<str.length()) 150 { 151 throw new SQLException("Malformed date"); 152 } 153 154 return "'" + year + month + day + "'"; 155 } 157 158 163 private static String getTime(String str) 164 throws SQLException 165 { 166 int i; 167 168 i = 2; 170 171 i = skipWhitespace(str, i); 173 174 i = skipQuote(str, i); 175 176 if (((str.length()-i) < 8) 178 || str.charAt(i+2)!=':' || str.charAt(i+5)!=':') 179 { 180 throw new SQLException("Malformed time"); 181 } 182 183 String hour = str.substring(i, i+2); 184 String minute = str.substring(i+3, i+3+2); 185 String second = str.substring(i+3+3, i+3+3+2); 186 187 if (!validDigits(hour) || !validDigits(minute) || !validDigits(second)) 189 { 190 throw new SQLException("Malformed time"); 191 } 192 193 i = i+8; 195 i = skipWhitespace(str, i); 196 i = skipQuote(str, i); 197 i = skipWhitespace(str, i); 198 199 if (i<str.length()) 200 { 201 throw new SQLException("Malformed time"); 202 } 203 204 return "'" + hour + ":" + minute + ":" + second + "'"; 205 } 207 208 213 private static String getTimestamp(String str) 214 throws SQLException 215 { 216 int i; 217 218 i = 2; 220 221 i = skipWhitespace(str, i); 223 224 i = skipQuote(str, i); 225 226 if (((str.length()-i) < 19) 228 || str.charAt(i+4)!='-' || str.charAt(i+7)!='-') 229 { 230 throw new SQLException("Malformed date"); 231 } 232 233 String year = str.substring(i, i+4); 234 String month = str.substring(i+5, i+5+2); 235 String day = str.substring(i+5+3, i+5+3+2); 236 237 if (!validDigits(year) || !validDigits(month) || !validDigits(day)) 239 { 240 throw new SQLException("Malformed date"); 241 } 242 243 i = i+10; 245 if (!Character.isWhitespace(str.charAt(i))) 246 { 247 throw new SQLException("Malformed date"); 248 } 249 250 i = skipWhitespace(str, i); 252 253 if (((str.length()-i) < 8) 255 || str.charAt(i+2)!=':' || str.charAt(i+5)!=':') 256 { 257 throw new SQLException("Malformed time"); 258 } 259 String hour = str.substring(i, i+2); 260 String minute = str.substring(i+3, i+3+2); 261 String second = str.substring(i+3+3, i+3+3+2); 262 String fraction = "000"; 263 i = i+8; 264 if (str.length()>i && str.charAt(i)=='.') 265 { 266 fraction = ""; 267 i++; 268 while(str.length()>i && validDigits(str.substring(i,i+1))) 269 { 270 fraction = fraction + str.substring(i,i+1); 271 i++; 272 } 273 if (fraction.length()>3) 274 { 275 fraction = fraction.substring(0,3); 276 } 277 else 278 { 279 while(fraction.length()<3) 280 { 281 fraction = fraction + "0"; 282 } 283 } 284 } 285 286 287 i = skipWhitespace(str, i); 289 i = skipQuote(str, i); 290 i = skipWhitespace(str, i); 291 292 if (i<str.length()) 293 { 294 throw new SQLException("Malformed date"); 295 } 296 297 return ("'" + year + month + day + " " 298 + hour + ":" + minute + ":" + second + "." + fraction + "'"); 299 } 301 302 public String expandEscape(String escapeSequence) 303 throws SQLException 304 { 305 String str = new String (escapeSequence); 306 String result = null; 307 308 str = str.trim(); 310 311 if (str.startsWith("fn ")) 312 { 313 str = str.substring(3); 314 315 result = expandCommonFunction(str); 316 if (result == null) 317 { 318 result = expandDBSpecificFunction(str); 319 } 320 } 321 else if (str.startsWith("call ") 322 || (str.startsWith("?=") 323 && str.substring(2).trim().startsWith("call "))) 324 { 325 throw new SQLException("Not implemented yet"); 326 } 327 else if (str.startsWith("d ")) 328 { 329 result = getDate(str); 330 } 331 else if (str.startsWith("t ")) 332 { 333 result = getTime(str); 334 } 335 else if (str.startsWith("ts ")) 336 { 337 result = getTimestamp(str); 338 } 339 else if (str.startsWith("oj ")) 340 { 341 throw new SQLException("Not implemented yet"); 342 } 343 else 344 { 345 throw new SQLException("Unrecognized escape sequence-\n" + 346 escapeSequence); 347 } 348 349 return result; 350 } 352 353 357 public String expandCommonFunction(String str) 358 { 359 String result = null; 360 361 362 if (str.equalsIgnoreCase("user()")) 363 { 364 result = " user_name() "; 365 } 366 else if (str.equalsIgnoreCase("now()")) 367 { 368 result = " getdate() "; 369 } 370 return result; 371 } 373 374 public String nativeString() 375 throws SQLException 376 { 377 return nativeString(input, '\\'); 378 } 380 private String nativeString(String sql, char escapeCharacter) 381 throws SQLException 382 { 383 String result = ""; 384 385 String escape = ""; 386 int i; 387 388 389 final int normal = 0; 391 392 final int inString = 1; 393 final int inStringWithBackquote = 2; 394 395 final int inEscape = 3; 396 final int inEscapeInString = 4; 397 final int inEscapeInStringWithBackquote = 5; 398 399 int state = normal; 400 char ch; 401 402 403 int escapeStartedAt = -1; 404 i = 0; 405 while(i<sql.length()) 406 { 407 ch = sql.charAt(i); 408 switch(state) 409 { 410 case normal: 411 { 412 if (ch == '{') 413 { 414 escapeStartedAt = i; 415 state = inEscape; 416 escape = ""; 417 } 418 else 419 { 420 result = result + ch; 421 422 if (ch == '\'') state = inString; 423 } 424 break; 425 } 426 case inString: 427 case inStringWithBackquote: 428 { 429 if ((i+1)<sql.length() 430 && ch == escapeCharacter 431 && (sql.charAt(i+1)=='_' 432 || sql.charAt(i+1)=='%')) 433 { 434 i++; 435 ch = sql.charAt(i); 436 result = result + '\\' + ch; 437 } 438 else 439 { 440 result = result + ch; 441 if (state == inStringWithBackquote) 442 { 443 state = inString; 444 } 445 else 446 { 447 if (ch == '\\') state = inStringWithBackquote; 448 if (ch == '\'') state = normal; 449 } 450 } 451 break; 452 } 453 case inEscape: 454 { 455 if (ch == '}') 456 { 457 467 if (escape.startsWith("escape ")) 468 { 469 char c; 470 471 if (i+1!=sql.length()) 473 { 474 throw new SQLException("Malformed statement. " + 475 "escape clause must be at " + 476 "the end of the query"); 477 } 478 479 480 484 c = findEscapeCharacter(sql.substring(escapeStartedAt)); 485 486 result = nativeString(sql.substring(0, escapeStartedAt), 487 c); 488 state = normal; 489 } 490 else 491 { 492 state = normal; 493 result = result + expandEscape(escape); 494 escapeStartedAt = -1; 495 } 496 } 497 else 498 { 499 escape = escape + ch; 500 if (ch == '\'') 501 { 502 state = inEscapeInString; 503 } 504 } 505 break; 506 } 507 case inEscapeInString: 508 case inEscapeInStringWithBackquote: 509 { 510 escape = escape + ch; 511 if (state == inEscapeInStringWithBackquote) 512 { 513 state = inEscapeInString; 514 } 515 else 516 { 517 if (ch == '\\') state = inEscapeInStringWithBackquote; 518 if (ch == '\'') state = inEscape; 519 } 520 break; 521 } 522 default: 523 { 524 throw new SQLException("Internal error. Unknown state in FSM"); 525 } 526 } 527 i++; 528 } 529 530 if (state!=normal && state!=inString) 531 { 532 throw new SQLException("Syntax error in SQL escape syntax"); 533 } 534 return result; 535 } 537 static char findEscapeCharacter(String original_str) 538 throws SQLException 539 { 540 String str = new String (original_str); 541 542 str = str.trim(); 543 if (str.charAt(0)!='{' || str.charAt(str.length()-1)!='}' 544 || str.length()<12) 545 { 546 throw new SQLException("Internal Error"); 547 } 548 549 str = str.substring(1, str.length()-1); 550 str = str.trim(); 551 552 if (! str.startsWith("escape")) 553 { 554 throw new SQLException("Internal Error"); 555 } 556 557 str = str.substring(6); 558 str = str.trim(); 559 if (str.length()!=3 || str.charAt(0)!='\'' || str.charAt(2)!='\'') 560 { 561 throw new SQLException("Malformed escape clause- |" + 562 original_str + "|"); 563 } 564 565 return str.charAt(1); 566 } } 568 | Popular Tags |