1 13 package org.jahia.services.jef; 14 15 import org.jahia.exceptions.JahiaException; 16 17 import javax.crypto.Cipher; 18 import javax.crypto.SecretKeyFactory; 19 import javax.crypto.spec.DESKeySpec; 20 import java.io.*; 21 import java.security.Key ; 22 import java.security.Security ; 23 import java.util.Enumeration ; 24 import java.util.Hashtable ; 25 import java.util.StringTokenizer ; 26 import java.util.zip.CRC32 ; 27 28 29 35 class JefFile { 36 private static org.apache.log4j.Logger logger = 37 org.apache.log4j.Logger.getLogger (JecFile.class); 38 39 40 private String filePath = ""; 41 42 43 private Hashtable keys = new Hashtable (); 44 45 46 private Hashtable files = new Hashtable (); 47 48 private static final String CHAR_ENC = "UTF-16"; 49 50 private final String MSG_INTERNAL_ERROR = "JefFile internal error"; 51 52 53 65 public JefFile (String path) 66 throws IOException, InvalidJefFileException, JahiaException { 67 68 readFile (path); 69 70 } 71 72 73 79 public final Hashtable getKeys () { 80 return keys; 81 } 82 83 91 public final String getKey (String name) { 92 return (String ) keys.get (name); 93 } 94 95 96 102 public final Hashtable getFiles () { 103 return files; 104 } 105 106 107 113 public final Enumeration getFilenames () { 114 return files.keys (); 115 } 116 117 118 127 public final boolean extractFile (String filename, String dest) { 128 129 boolean result = true; 130 131 if (filename == null || dest == null) { 132 return false; 133 } 134 135 byte[] aFile = (byte[]) files.get (filename); 136 137 if (aFile == null) { 138 return false; 139 } 140 141 File f = new File (dest); 142 143 try { 145 146 FileOutputStream fos = new FileOutputStream (dest); 147 148 fos.write (aFile); 149 150 fos.flush (); 152 fos.close (); 153 } catch (FileNotFoundException ex) { 154 System.out.println ("ERROR : Could not create the encrypted file"); 155 result = false; 156 } catch (SecurityException ex) { 157 System.out.println ("ERROR : No security permissions to create the file."); 158 result = false; 159 } catch (IOException ex) { 160 System.out.println ("ERROR : I/O error."); 161 result = false; 162 } 163 164 return result; 165 } 166 167 168 176 public final boolean extractFiles (String dest) { 177 178 boolean result = true; 179 180 if (dest == null) { 181 return false; 182 } 183 184 185 File f = new File (dest); 186 if (!f.isDirectory () || !f.canWrite ()) { 187 return false; 188 } 189 190 192 Enumeration filenames = getFilenames (); 193 String filename = null; 194 195 197 while (filenames.hasMoreElements ()) { 198 199 filename = (String ) filenames.nextElement (); 200 201 if (!extractFile (filename, dest + File.separator + filename)) { 202 return false; 203 } 204 } 205 206 return result; 207 } 208 209 210 216 public final boolean extractFiles () { 217 218 219 boolean result = true; 220 221 File f = new File (filePath); 222 if (!f.isFile ()) { 223 return false; 224 } 225 226 return extractFiles (f.getParentFile ().getAbsolutePath ()); 227 228 } 229 230 231 242 private static String [] getTokens (String str, String sep) { 243 if (str == null) { 244 return null; 245 } 246 247 StringTokenizer st = new StringTokenizer (str, sep); 248 String [] result = new String [st.countTokens ()]; 249 int count = 0; 250 while (st.hasMoreTokens ()) { 251 result[count] = st.nextToken (); 252 count++; 253 } 254 255 return result; 256 } 257 258 259 267 private static Hashtable parseKeys (String keysString) 268 throws InvalidJefFileException { 269 270 Hashtable keys = new Hashtable (); 271 272 if (keysString == null || keysString.trim ().equals ("")) { 273 throw new InvalidJefFileException ("invalid keys values"); 274 } 275 276 278 String k = ""; 279 String val = ""; 280 281 String [] tokens = getTokens (keysString, ","); 282 for (int i = 0; i < tokens.length; i++) { 283 if ((tokens[i].indexOf ("=") == -1) || tokens[i].indexOf ("=") == (tokens[i].length () - 1)) { 284 throw new InvalidJefFileException ("invalid keys values"); 285 } 286 k = tokens[i].substring (0, tokens[i].indexOf ("=")); 287 val = tokens[i].substring (tokens[i].indexOf ("=") + 1, tokens[i].length ()); 288 keys.put (k.trim (), val.trim ()); 290 } 291 292 return keys; 293 } 294 295 296 297 303 private final void readFile (String path) 304 throws IOException, InvalidJefFileException, JahiaException { 305 306 307 FileInputStream fstream = null; 308 DataInputStream stream = null; 309 ByteArrayOutputStream bos = null; 310 ByteArrayInputStream byteStream = null; 311 312 try { 313 314 File srcFile = new File (path); 316 317 if (!srcFile.exists () || !srcFile.canRead ()) { 318 logger.debug ("cannot access file " + path); 319 throw new JahiaException (MSG_INTERNAL_ERROR, "cannot access file " + path, 320 JefFileConstants.IO_ERROR, JahiaException.ERROR_SEVERITY); 321 322 } 323 324 325 filePath = path; 326 327 boolean securityErr = false; 328 boolean tryAgain = true; 329 boolean goSleep = false; 330 long fLength = 0; 331 332 long storedChecksum = 0; 333 long streamChecksum = -1; 334 335 byte[] bytes = null; 336 byte[] data = null; 337 338 while (tryAgain) { 341 securityErr = false; 342 fLength = srcFile.length (); 343 goSleep = false; 344 345 try { 346 347 fstream = new FileInputStream (srcFile); 348 stream = new DataInputStream (fstream); 349 350 int streamSize = (new Long (srcFile.length () - 16)).intValue (); 353 bos = new ByteArrayOutputStream (); 354 byte[] buff = null; 355 int crcOffset = stream.readInt (); 356 357 359 buff = new byte[crcOffset]; 360 stream.read (buff, 0, crcOffset); 361 bos.write (buff); 362 363 364 Security.addProvider ( 366 new com.sun.crypto.provider.SunJCE ()); 367 368 int keyLength = stream.readInt (); 370 byte[] keyAsBytes = new byte[keyLength]; 371 stream.read (keyAsBytes); 372 373 DESKeySpec keySpec = new DESKeySpec (keyAsBytes); 374 375 Key myKey = SecretKeyFactory.getInstance ("DES").generateSecret (keySpec); 376 keyAsBytes = myKey.getEncoded (); 377 379 Cipher decCipher = Cipher.getInstance ("DES"); 380 381 382 decCipher.init (Cipher.DECRYPT_MODE, myKey); 383 384 385 storedChecksum = stream.readLong (); 386 389 buff = new byte[streamSize - (crcOffset + keyLength)]; 390 stream.read (buff, 0, buff.length); 391 bos.write (buff); 392 buff = null; 393 394 bytes = bos.toByteArray (); 395 396 fstream.close (); 398 stream = null; 399 fstream = null; 400 srcFile = null; 401 bos.close (); 402 bos = null; 403 404 405 CRC32 crc = new CRC32 (); 407 crc.update (bytes); 408 409 streamChecksum = crc.getValue (); 410 413 415 byte[] decryptedBytes = decCipher.doFinal (bytes); 416 417 bytes = null; 418 419 421 422 if (srcFile == null) { 423 srcFile = new File (path); 424 } 425 426 if (fLength == srcFile.length ()) { 427 if ((streamChecksum != storedChecksum)) { 428 logger.debug (" checksum not match "); 429 throw new InvalidJefFileException (); 430 } 431 432 byteStream = new ByteArrayInputStream (decryptedBytes); 433 stream = new DataInputStream (byteStream); 434 int offset = 0; 435 int totalOffset = offset; 436 437 439 440 offset = stream.readShort (); 442 totalOffset += offset; 443 444 446 byte[] chars = new byte[offset]; 447 448 if (offset > 0) { 449 stream.read (chars, 0, offset); 450 String keysString = new String (chars, CHAR_ENC); 451 keys = parseKeys (keysString); 453 } else { 454 } 456 457 data = new byte[decryptedBytes.length - (totalOffset + 2)]; 459 460 stream.read (data, 0, data.length); 461 462 464 byteStream = new ByteArrayInputStream (data); 466 stream = new DataInputStream (byteStream); 467 468 int nbBytes = data.length; 469 int nbBytesRead = 0; 470 offset = 0; 471 String fileName = ""; 472 Long fSize = null; 473 byte[] aFile = null; 474 475 while (nbBytesRead < nbBytes) { 476 477 offset = stream.readShort (); 479 nbBytesRead += 2; 480 chars = new byte[offset]; 481 nbBytesRead += offset; 482 483 stream.read (chars, 0, offset); 484 fileName = new String (chars, CHAR_ENC); 485 487 fSize = new Long (stream.readLong ()); 489 490 492 aFile = new byte[fSize.intValue ()]; 493 494 nbBytesRead += 8; 495 496 stream.read (aFile, 0, fSize.intValue ()); 497 nbBytesRead += fSize.intValue (); 498 499 files.put (fileName, aFile); 500 aFile = null; 501 502 } 504 505 if (fLength == srcFile.length ()) { 506 tryAgain = false; 507 } 508 } else { 509 goSleep = true; 510 } 511 bytes = null; 512 data = null; 513 514 } catch (java.security.InvalidKeyException ike) { 515 securityErr = true; 516 logger.error (" exception occured " + ike.getMessage ()); 517 ike.printStackTrace (); 518 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception" 519 + ike.getMessage (), 520 JefFileConstants.JAVA_SECURITY_ERROR, 521 JahiaException.ERROR_SEVERITY); 522 } catch (java.security.NoSuchAlgorithmException nae) { 523 securityErr = true; 524 logger.error (" exception occured " + nae.getMessage ()); 525 nae.printStackTrace (); 526 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception" 527 + nae.getMessage (), 528 JefFileConstants.JAVA_SECURITY_ERROR, 529 JahiaException.ERROR_SEVERITY); 530 } catch (java.security.spec.InvalidKeySpecException iks) { 531 securityErr = true; 532 logger.error (" exception occured " + iks.getMessage ()); 533 iks.printStackTrace (); 534 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception" 535 + iks.getMessage (), 536 JefFileConstants.JAVA_SECURITY_ERROR, 537 JahiaException.ERROR_SEVERITY); 538 } catch (javax.crypto.NoSuchPaddingException npe) { 539 securityErr = true; 540 logger.error (" exception occured " + npe.getMessage ()); 541 npe.printStackTrace (); 542 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception" 543 + npe.getMessage (), 544 JefFileConstants.JAVA_SECURITY_ERROR, 545 JahiaException.ERROR_SEVERITY); 546 } catch (javax.crypto.IllegalBlockSizeException ibse) { 547 securityErr = true; 548 logger.error (" exception occured " + ibse.getMessage ()); 549 ibse.printStackTrace (); 550 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception" 551 + ibse.getMessage (), 552 JefFileConstants.JAVA_SECURITY_ERROR, 553 JahiaException.ERROR_SEVERITY); 554 } catch (javax.crypto.BadPaddingException bpe) { 555 securityErr = true; 556 logger.error (" exception occured " + bpe.getMessage ()); 557 bpe.printStackTrace (); 558 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception" 559 + bpe.getMessage (), 560 JefFileConstants.JAVA_SECURITY_ERROR, 561 JahiaException.ERROR_SEVERITY); 562 } catch (java.lang.ExceptionInInitializerError eiie) { 563 securityErr = true; 564 logger.error (" exception occured " + eiie.getMessage ()); 565 eiie.printStackTrace (); 566 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , java.lang.ExceptionInInitializerError " 567 + eiie.getMessage (), 568 JefFileConstants.JAVA_SECURITY_ERROR, 569 JahiaException.ERROR_SEVERITY); 570 } catch (IOException ioe) { 571 logger.error (" exception occured " + ioe.getMessage ()); 572 ioe.printStackTrace (); 573 if (srcFile.isFile () && srcFile.canRead () && (fLength == srcFile.length ())) { 574 File tmpFile = new File (srcFile.getAbsolutePath () + "_error"); 575 srcFile.renameTo (tmpFile); 576 tryAgain = false; 577 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , IOException " 578 + ioe.getMessage (), 579 JefFileConstants.IO_ERROR, JahiaException.ERROR_SEVERITY); 580 } else { 581 goSleep = true; 582 } 583 } catch (Throwable t) { 584 logger.error (" exception occured " + t.getMessage ()); 585 t.printStackTrace (); 586 if (srcFile.isFile () && srcFile.canRead () && (fLength == srcFile.length ())) { 587 tryAgain = false; 590 throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , Unknown Exception ", 591 JefFileConstants.UNKNOWN_ERROR, JahiaException.ERROR_SEVERITY); 592 } else { 593 goSleep = true; 594 } 595 } 596 597 if (goSleep) { 598 try { 599 Thread.sleep (500); 602 while (fLength < srcFile.length ()) { 603 fLength = srcFile.length (); 604 Thread.sleep (500); 606 } 607 } catch (Throwable tr) { 608 logger.error (tr.getMessage ()); 609 } 610 } 611 } 612 613 } finally { 614 615 616 if (byteStream != null) { 617 byteStream.close (); 618 } 619 byteStream = null; 620 621 622 if (stream != null) { 623 stream.close (); 624 } 625 stream = null; 626 627 628 if (fstream != null) { 629 fstream.close (); 630 } 631 fstream = null; 632 633 634 if (bos != null) { 635 bos.close (); 636 } 637 bos = null; 638 639 } 640 641 } 642 643 } 644 645 | Popular Tags |