CryptCodecProvider.java

  1. /*
  2. Copyright (c) 2010 Vladimir Berezniker

  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at

  6.     http://www.apache.org/licenses/LICENSE-2.0

  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */

  13. package com.healthmarketscience.jackcess.crypt;

  14. import java.io.IOException;
  15. import java.nio.charset.Charset;
  16. import java.util.function.Supplier;

  17. import com.healthmarketscience.jackcess.crypt.impl.JetCryptCodecHandler;
  18. import com.healthmarketscience.jackcess.crypt.impl.MSISAMCryptCodecHandler;
  19. import com.healthmarketscience.jackcess.crypt.impl.OfficeCryptCodecHandler;
  20. import com.healthmarketscience.jackcess.impl.CodecHandler;
  21. import com.healthmarketscience.jackcess.impl.CodecProvider;
  22. import com.healthmarketscience.jackcess.impl.DefaultCodecProvider;
  23. import com.healthmarketscience.jackcess.impl.JetFormat;
  24. import com.healthmarketscience.jackcess.impl.PageChannel;


  25. /**
  26.  * Implementation of CodecProvider with support for some forms of Microsoft
  27.  * Access and Microsoft Money file encryption.
  28.  * <p>
  29.  * Note, not all "encrypted" access databases actually require passwords in
  30.  * order to be opened.  Many older forms of access "encryption" ("obfuscation"
  31.  * would be a better term) include the keys within the access file itself.  If
  32.  * required, a password can be provided in one of two ways:
  33.  * <ul>
  34.  * <li>If a {@link PasswordCallback} or {@link Supplier} has been provided
  35.  *     (via the constructor or {@link #setPasswordCallback}), then
  36.  *     {@link PasswordCallback#getPassword} will be invoked to retrieve the
  37.  *     necessary password</li>
  38.  * <li>If no password callback has been configured, then {@link #getPassword}
  39.  *     will be invoked directly on the CryptCodecProvider (which will return
  40.  *     the password configured via the constructor or {@link
  41.  *     #setPassword})</li>
  42.  * </ul>
  43.  *
  44.  * @author Vladimir Berezniker
  45.  */
  46. public class CryptCodecProvider implements CodecProvider, PasswordCallback
  47. {
  48.   private String _password;
  49.   private Supplier<String> _callback;

  50.   public CryptCodecProvider() {
  51.     this(null, null);
  52.   }

  53.   public CryptCodecProvider(String password) {
  54.     this(password, null);
  55.   }

  56.   public CryptCodecProvider(PasswordCallback callback) {
  57.     this(null, callback);
  58.   }

  59.   public CryptCodecProvider(Supplier<String> callback) {
  60.     this(null, callback);
  61.   }

  62.   protected CryptCodecProvider(String password, Supplier<String> callback) {
  63.     _password = password;
  64.     _callback = callback;
  65.   }

  66.   @Override
  67.   public String getPassword() {
  68.     return _password;
  69.   }

  70.   public CryptCodecProvider setPassword(String newPassword) {
  71.     _password = newPassword;
  72.     return this;
  73.   }

  74.   public PasswordCallback getPasswordCallback() {
  75.     return (PasswordCallback)getPasswordSupplier();
  76.   }

  77.   public Supplier<String> getPasswordSupplier() {
  78.     return _callback;
  79.   }

  80.   public CryptCodecProvider setPasswordCallback(PasswordCallback newCallback) {
  81.     return setPasswordSupplier(newCallback);
  82.   }

  83.   public CryptCodecProvider setPasswordSupplier(Supplier<String> newCallback) {
  84.     _callback = newCallback;
  85.     return this;
  86.   }

  87.   @Override
  88.   public CodecHandler createHandler(PageChannel channel, Charset charset)
  89.     throws IOException
  90.   {
  91.     // determine from where to retrieve the password
  92.     Supplier<String> callback = getPasswordSupplier();
  93.     if(callback == null) {
  94.       callback = this;
  95.     }

  96.     JetFormat format = channel.getFormat();
  97.     switch(format.CODEC_TYPE) {
  98.     case NONE:
  99.       // no encoding, all good
  100.       return DefaultCodecProvider.DUMMY_HANDLER;

  101.     case JET:
  102.       return JetCryptCodecHandler.create(channel);

  103.     case MSISAM:
  104.       return MSISAMCryptCodecHandler.create(callback, channel, charset);

  105.     case OFFICE:
  106.       return OfficeCryptCodecHandler.create(callback, channel, charset);

  107.     default:
  108.       throw new RuntimeException("Unknown codec type " + format.CODEC_TYPE);
  109.     }
  110.   }
  111. }