/*
 * RSAEncrypt.java
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.studio.client.common.crypto;

import org.rstudio.core.client.CommandWithArg;
import org.rstudio.core.client.ExternalJavaScriptLoader;
import org.rstudio.core.client.ExternalJavaScriptLoader.Callback;
import org.rstudio.studio.client.application.Desktop;
import org.rstudio.studio.client.server.ServerError;
import org.rstudio.studio.client.server.ServerRequestCallback;

public class RSAEncrypt
{
   public interface ResponseCallback
   {
      void onSuccess(String encryptedData);
      void onFailure(ServerError error);
   }
   
   
   public static void encrypt_ServerOnly(
         final CryptoServerOperations server,
         final String input,
         final ResponseCallback callback)
   {
      if (Desktop.isDesktop())
      {
         // Don't encrypt for desktop, Windows can't decrypt it.
         callback.onSuccess(input);
         return;
      }

      loader_.addCallback(new Callback()
      {
         @Override
         public void onLoaded()
         { 
            server.getPublicKey(new ServerRequestCallback<PublicKeyInfo>()
            {
               @Override
               public void onResponseReceived(PublicKeyInfo response)
               {
   
                  callback.onSuccess(encrypt(input,
                                             response.getExponent(),
                                             response.getModulo()));
               }
   
               @Override
               public void onError(ServerError error)
               {
                  callback.onFailure(error);
               }
            });
         }
      });
   }
   
   public static void encrypt_ServerOnly(final PublicKeyInfo publicKeyInfo,
                                         final String input,
                                         final CommandWithArg<String> callback)
   {
      if (Desktop.isDesktop())
      {
         // Don't encrypt for desktop, Windows can't decrypt it.
         callback.execute(input);
         return;
      }

      loader_.addCallback(new Callback()
      {
         @Override
         public void onLoaded()
         { 
            callback.execute(encrypt(input, 
                                     publicKeyInfo.getExponent(),
                                     publicKeyInfo.getModulo()));
           
         }
      });
   }
   
  
   private static native String encrypt(String value,
                                        String exponent,
                                        String modulo) /*-{
      return $wnd.encrypt(value, exponent, modulo);
   }-*/;

   private static final ExternalJavaScriptLoader loader_ =
         new ExternalJavaScriptLoader("js/encrypt.min.js");
}

@@ -1451,32 +1451,170 @@
  return;%0A      %7D
+%0A      %0A      if (input == null)%0A      %7B%0A         // fallback case for null input (see case 4375)%0A         callback.onSuccess(%22%22);%0A      %7D
 %0A%0A      loader_.
@@ -2709,32 +2709,162 @@
 eturn;%0A      %7D%0A%0A
+      if (input == null)%0A      %7B%0A         // fallback case for null input (see case 4375)%0A         callback.execute(%22%22);%0A      %7D%0A%0A
       loader_.ad

shell encryption: encrypt null input as empty