Merge branch 'develop' into refactor_remote_operation_to_download_file
authormasensio <masensio@solidgear.es>
Thu, 5 Dec 2013 16:37:40 +0000 (17:37 +0100)
committermasensio <masensio@solidgear.es>
Thu, 5 Dec 2013 16:37:40 +0000 (17:37 +0100)
AndroidManifest.xml
oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedSslSocketFactory.java
oc_framework/src/com/owncloud/android/oc_framework/network/ServerNameIndicator.java [new file with mode: 0644]
res/layout-land/account_setup.xml
res/values-pt-rPT/strings.xml

index bdd792b..205e5ac 100644 (file)
@@ -18,8 +18,8 @@
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  -->
 <manifest package="com.owncloud.android"
-    android:versionCode="105000"
-    android:versionName="1.5.0" xmlns:android="http://schemas.android.com/apk/res/android">
+    android:versionCode="105001"
+    android:versionName="1.5.1" xmlns:android="http://schemas.android.com/apk/res/android">
 
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
         <service
             android:name=".syncadapter.FileSyncService"
             android:exported="true" 
-            android:process=":sync">
+            >
             <intent-filter>
                 <action android:name="android.content.SyncAdapter" />
             </intent-filter>
index e24fa36..775473a 100644 (file)
@@ -24,12 +24,15 @@ import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.SocketAddress;
 import java.net.UnknownHostException;
+//import java.security.Provider;
 import java.security.cert.X509Certificate;
+//import java.util.Enumeration;
 
 import javax.net.SocketFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLHandshakeException;
+//import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSocket;
@@ -39,6 +42,7 @@ import org.apache.commons.httpclient.params.HttpConnectionParams;
 import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
 import org.apache.http.conn.ssl.X509HostnameVerifier;
 
+//import android.os.Build;
 import android.util.Log;
 
 
@@ -84,8 +88,47 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
         return socket;
     }
 
+    /*
+    private void logSslInfo() {
+       if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) {
+               Log.v(TAG, "SUPPORTED SSL PARAMETERS");
+               logSslParameters(mSslContext.getSupportedSSLParameters());
+               Log.v(TAG, "DEFAULT SSL PARAMETERS");
+               logSslParameters(mSslContext.getDefaultSSLParameters());
+               Log.i(TAG, "CURRENT PARAMETERS");
+               Log.i(TAG, "Protocol: " + mSslContext.getProtocol());
+       }
+       Log.i(TAG, "PROVIDER");
+       logSecurityProvider(mSslContext.getProvider());
+       }
     
-    /**
+    private void logSecurityProvider(Provider provider) {
+       Log.i(TAG, "name: " + provider.getName());
+       Log.i(TAG, "version: " + provider.getVersion());
+       Log.i(TAG, "info: " + provider.getInfo());
+       Enumeration<?> keys = provider.propertyNames();
+       String key;
+       while (keys.hasMoreElements()) {
+               key = (String) keys.nextElement();
+               Log.i(TAG, "  property " + key + " : " + provider.getProperty(key));
+       }
+       }
+
+       private void logSslParameters(SSLParameters params) {
+       Log.v(TAG, "Cipher suites: ");
+       String [] elements = params.getCipherSuites();
+       for (int i=0; i<elements.length ; i++) {
+               Log.v(TAG, "  " + elements[i]);
+       }
+       Log.v(TAG, "Protocols: ");
+       elements = params.getProtocols();
+       for (int i=0; i<elements.length ; i++) {
+               Log.v(TAG, "  " + elements[i]);
+       }
+       }
+       */
+
+       /**
      * Attempts to get a new socket connection to the given host within the
      * given time limit.
      * 
@@ -110,6 +153,9 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
             throw new IllegalArgumentException("Parameters may not be null");
         } 
         int timeout = params.getConnectionTimeout();
+        
+        //logSslInfo();
+        
         SocketFactory socketfactory = mSslContext.getSocketFactory();
         Log.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
         Socket socket = socketfactory.createSocket();
@@ -117,12 +163,13 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
         SocketAddress remoteaddr = new InetSocketAddress(host, port);
         socket.setSoTimeout(params.getSoTimeout());
         socket.bind(localaddr);
+        ServerNameIndicator.setServerNameIndication(host, (SSLSocket)socket);
         socket.connect(remoteaddr, timeout);
         verifyPeerIdentity(host, port, socket);
         return socket;
     }
 
-    /**
+       /**
      * @see ProtocolSocketFactory#createSocket(java.lang.String,int)
      */
     public Socket createSocket(String host, int port) throws IOException,
@@ -238,5 +285,5 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
             throw io;
         }
     }
-
+    
 }
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/ServerNameIndicator.java b/oc_framework/src/com/owncloud/android/oc_framework/network/ServerNameIndicator.java
new file mode 100644 (file)
index 0000000..1a20697
--- /dev/null
@@ -0,0 +1,144 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.oc_framework.network;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.net.ssl.SSLSocket;
+
+import android.util.Log;
+
+
+/**
+ * Enables the support of Server Name Indication if existing 
+ * in the underlying network implementation.
+ * 
+ * Build as a singleton.
+ * 
+ * @author David A. Velasco
+ */
+public class ServerNameIndicator {
+       
+       private static final String TAG = ServerNameIndicator.class.getSimpleName();
+       
+       private static final AtomicReference<ServerNameIndicator> mSingleInstance = new AtomicReference<ServerNameIndicator>();
+       
+       private static final String METHOD_NAME = "setHostname";
+       
+       private final WeakReference<Class<?>> mSSLSocketClassRef;
+       private final WeakReference<Method> mSetHostnameMethodRef;
+       
+       
+       /**
+        * Private constructor, class is a singleton.
+        * 
+        * @param sslSocketClass                Underlying implementation class of {@link SSLSocket} used to connect with the server. 
+        * @param setHostnameMethod             Name of the method to call to enable the SNI support.
+        */
+       private ServerNameIndicator(Class<?> sslSocketClass, Method setHostnameMethod) {
+               mSSLSocketClassRef = new WeakReference<Class<?>>(sslSocketClass);
+               mSetHostnameMethodRef = (setHostnameMethod == null) ? null : new WeakReference<Method>(setHostnameMethod);
+       }
+       
+       
+       /**
+        * Calls the {@code #setHostname(String)} method of the underlying implementation 
+        * of {@link SSLSocket} if exists.
+        * 
+        * Creates and initializes the single instance of the class when needed
+        *
+        * @param hostname              The name of the server host of interest.
+        * @param sslSocket     Client socket to connect with the server.
+        */
+       public static void setServerNameIndication(String hostname, SSLSocket sslSocket) {
+               final Method setHostnameMethod = getMethod(sslSocket);
+               if (setHostnameMethod != null) {
+                       try {
+                               setHostnameMethod.invoke(sslSocket, hostname);
+                               Log.i(TAG, "SNI done, hostname: " + hostname);
+                               
+                       } catch (IllegalArgumentException e) {
+                               Log.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
+                               
+                       } catch (IllegalAccessException e) {
+                               Log.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
+                               
+                       } catch (InvocationTargetException e) {
+                               Log.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
+                       }
+               } else {
+                       Log.i(TAG, "SNI not supported");
+               }
+       }
+
+       
+       /**
+        * Gets the method to invoke trying to minimize the effective 
+        * application of reflection.
+        * 
+        * @param       sslSocket               Instance of the SSL socket to use in connection with server.
+        * @return                                      Method to call to indicate the server name of interest to the server.
+        */
+       private static Method getMethod(SSLSocket sslSocket) {
+               final Class<?> sslSocketClass = sslSocket.getClass();
+               final ServerNameIndicator instance = mSingleInstance.get();
+               if (instance == null) {
+                       return initFrom(sslSocketClass);
+                       
+               } else if (instance.mSSLSocketClassRef.get() != sslSocketClass) {
+                       // the underlying class changed
+                       return initFrom(sslSocketClass);
+                               
+               } else if (instance.mSetHostnameMethodRef == null) {
+                       // SNI not supported
+                       return null;
+                               
+               } else {
+                       final Method cachedSetHostnameMethod = instance.mSetHostnameMethodRef.get();
+                       return (cachedSetHostnameMethod == null) ? initFrom(sslSocketClass) : cachedSetHostnameMethod;
+               }
+       }
+
+
+       /**
+        * Singleton initializer.
+        * 
+        * Uses reflection to extract and 'cache' the method to invoke to indicate the desited host name to the server side.
+        *  
+        * @param       sslSocketClass          Underlying class providing the implementation of {@link SSLSocket}.
+        * @return                                              Method to call to indicate the server name of interest to the server.
+        */
+       private static Method initFrom(Class<?> sslSocketClass) {
+        Log.i(TAG, "SSLSocket implementation: " + sslSocketClass.getCanonicalName());
+               Method setHostnameMethod = null;
+               try {
+                       setHostnameMethod = sslSocketClass.getMethod(METHOD_NAME, String.class);
+               } catch (SecurityException e) {
+                       Log.e(TAG, "Could not access to SSLSocket#setHostname(String) method ", e);
+                       
+               } catch (NoSuchMethodException e) {
+                       Log.i(TAG, "Could not find SSLSocket#setHostname(String) method - SNI not supported");
+               }
+               mSingleInstance.set(new ServerNameIndicator(sslSocketClass, setHostnameMethod));
+               return setHostnameMethod;
+       }
+
+}
index 1025bcf..4eea9b3 100644 (file)
@@ -27,7 +27,7 @@
     <LinearLayout\r
         android:layout_width="match_parent"\r
         android:layout_height="wrap_content"\r
-        android:layout_above="@id/buttonOK"\r
+        android:layout_above="@+id/bottom_block"\r
         android:layout_alignParentTop="true"\r
         android:orientation="horizontal" >\r
         \r
                                                           \r
        </LinearLayout>\r
        \r
-       <Button\r
-           android:id="@id/buttonOK"\r
-           android:layout_width="match_parent"\r
-           android:layout_height="wrap_content"\r
-           android:layout_above="@+id/welcome_link"\r
-           android:layout_centerHorizontal="true"\r
-           android:enabled="false"\r
-           android:onClick="onOkClick"\r
-           android:text="@string/setup_btn_connect" />\r
-\r
-       <Button\r
-           android:id="@id/welcome_link"\r
-           android:layout_width="wrap_content"\r
-           android:layout_height="wrap_content"\r
-           android:layout_alignParentBottom="true"\r
-           android:layout_centerHorizontal="true"\r
-           android:background="@android:color/transparent"\r
-           android:onClick="onRegisterClick"\r
-           android:paddingBottom="5dp"\r
-           android:paddingTop="5dp"\r
-           android:text="@string/auth_register"\r
-           android:textColor="#0000FF"/>\r
-       \r
+    <LinearLayout\r
+        android:id="@id/bottom_block"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+               android:layout_alignParentBottom="true"\r
+        android:orientation="vertical" >\r
+        \r
+               <Button\r
+                   android:id="@+id/buttonOK"\r
+                   android:layout_width="match_parent"\r
+                   android:layout_height="wrap_content"\r
+                   android:layout_gravity="center_horizontal"\r
+                   android:enabled="false"\r
+                   android:onClick="onOkClick"\r
+                   android:text="@string/setup_btn_connect" />\r
+               \r
+               <Button\r
+                   android:id="@+id/welcome_link"\r
+                   android:layout_width="wrap_content"\r
+                   android:layout_height="wrap_content"\r
+                   android:layout_gravity="center_horizontal"\r
+                   android:background="@android:color/transparent"\r
+                   android:onClick="onRegisterClick"\r
+                   android:paddingBottom="5dp"\r
+                   android:paddingTop="5dp"\r
+                   android:text="@string/auth_register"\r
+                   android:textColor="#0000FF"/>\r
+       </LinearLayout>\r
+               \r
 </RelativeLayout>\r
index 6121f6d..f082b52 100644 (file)
   <string name="prefs_log_summary_history">Isto mostra os registos guardados</string>
   <string name="prefs_log_delete_history_button">Eliminar Histórico</string>
   <string name="prefs_help">Ajuda</string>
+  <string name="prefs_recommend">Recomendar a um amigo</string>
   <string name="prefs_feedback">Resposta</string>
   <string name="prefs_imprint">Imprint</string>
+  <string name="recommend_subject">Experimente %1$s no seu smartphone!</string>
+  <string name="recommend_text">Quero convidá-lo para experimentar %1$s no seu smartphone!\nDescarregue aqui: %2$s</string>
   <string name="auth_check_server">Verificar Servidor</string>
   <string name="auth_host_url">Endereço do servidor</string>
   <string name="auth_username">Nome de Utilizador</string>
@@ -92,6 +95,7 @@
   <string name="sync_foreign_files_forgotten_ticker">Alguns ficheiros locais ficaram esquecidos</string>
   <string name="sync_foreign_files_forgotten_content">%1$d ficheiros da directoria %2$s não foram copiados</string>
   <string name="sync_foreign_files_forgotten_explanation">Com a versão 1.3.16, os ficheiros que foram enviados deste dispositivo foram copiados para a pasta local %1$s para prevenir perda de dados quando um ficheiro está partilhado com várias contas.\nDevido a esta alteração, todos os ficheiros e as suas versões foram copiados para a pasta %2$s. Contudo, um erro não deixou concluír este processo durante a sincronização da conta. Pode deixar o ficheiro(s) como está(ão) e remover o link para %3$s, ou mover o(s) ficheiro(s)  para a pasta %1$s e guardar o link para %4$s.\n\nEm baixo está(ão) listados o(s) ficheiro(s) locais e remotos em %5$s que foram ligados.</string>
+  <string name="sync_current_folder_was_removed">A pasta %1$s já não existe</string>
   <string name="foreign_files_move">Mover Todos</string>
   <string name="foreign_files_success">Todos os ficheiros foram movidos</string>
   <string name="foreign_files_fail">Não foi possível mover alguns ficheiros</string>
   <string name="media_err_unsupported">Codec de média não suportado</string>
   <string name="media_err_io">Não foi possível reproduzir o ficheiro</string>
   <string name="media_err_malformed">Ficheiro erradamente codificado (codec)</string>
+  <string name="media_err_timeout">O tempo de espera para jogar expirou</string>
   <string name="media_err_invalid_progressive_playback">O ficheiro não pode ser reproduzido (streaming)</string>
   <string name="media_err_unknown">O ficheiro não pode ser reproduzido com o leitor de média de origem</string>
   <string name="media_err_security_ex">Erro de segurança a tentar reproduzir o ficheiro %1$s</string>
   <string name="auth_connection_established">Ligação estabelecida</string>
   <string name="auth_testing_connection">A testar a ligação...</string>
   <string name="auth_not_configured_title">Configuração do servidor incorrecta.</string>
+  <string name="auth_account_not_new">Uma conta para este utilizador e servidor já existe no dispositivo</string>
+  <string name="auth_account_not_the_same">O utilizador que escreveu não coincide com o nome de utilizador desta conta</string>
   <string name="auth_unknown_error_title">Ocorreu um erro desconhecido!</string>
   <string name="auth_unknown_host_title">Não é possível encontrar o servidor</string>
   <string name="auth_incorrect_path_title">Instância servidor não encontrada</string>
   <string name="auth_timeout_title">O servidor levou demasiado tempo a responder</string>
   <string name="auth_incorrect_address_title">URL errado</string>
   <string name="auth_ssl_general_error_title">Inicialização de SSL falhou</string>
+  <string name="auth_ssl_unverified_server_title">Não foi possível verificar a identidade SSL do servidor</string>
   <string name="auth_bad_oc_version_title">Versão do servidor não reconhecida</string>
   <string name="auth_wrong_connection_title">Não consegue estabelecer ligação</string>
   <string name="auth_secure_connection">Ligação segura estabelecida</string>
   <string name="auth_oauth_error">autorização mal sucedida</string>
   <string name="auth_oauth_error_access_denied">Acesso negado pelo servidor</string>
   <string name="auth_wtf_reenter_URL">Estado inesperado, por favor, digite a URL do servidor novamente</string>
+  <string name="auth_expired_oauth_token_toast">O prazo da sua autorização expirou. Por favor renove-a</string>
   <string name="auth_expired_basic_auth_toast">Por favor, introduza a password actual</string>
+  <string name="auth_expired_saml_sso_token_toast">A sua sessão expirou. Por favor autentique-se de novo</string>
+  <string name="auth_connecting_auth_server">A verificar a sua autenticação no servidor...</string>
+  <string name="auth_unsupported_auth_method">O servidor não suporta este método de autenticação</string>
+  <string name="auth_unsupported_multiaccount">%1$s não suporta contas múltiplas</string>
   <string name="fd_keep_in_sync">manter ficheiro actualizado</string>
   <string name="common_rename">Renomear</string>
   <string name="common_remove">Remover</string>
   <string name="sync_file_fail_msg">Não foi possível verificar o ficheiro remoto</string>
   <string name="sync_file_nothing_to_do_msg">O conteúdo do ficheiro já foi sincronizado</string>
   <string name="create_dir_fail_msg">Não foi possível criar a pasta</string>
+  <string name="filename_forbidden_characters">Caracteres não permitidos: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Aguarde um momento</string>
   <string name="filedisplay_unexpected_bad_get_content">Erro inesperado. Por favor tente outra aplicação para seleccionar o ficheiro.</string>
   <string name="filedisplay_no_file_selected">Não selecionou nenhum ficheiro</string>
+  <string name="oauth_check_onoff">Autenticar-se com oAuth2</string>
   <string name="oauth_login_connection">A ligar ao servidor oAuth2</string>
   <string name="ssl_validator_header">Não foi possível verificar a identidade do site.</string>
   <string name="ssl_validator_reason_cert_not_trusted">- O certificado do servidor não é de confiança</string>
   <string name="preview_image_description">Pré-Visualização da imagem</string>
   <string name="preview_image_error_unknown_format">Esta imagem não pode ser mostrada</string>
   <string name="error__upload__local_file_not_copied">Não foi possível copiar %1$s para a pasta local %2$s</string>
+  <string name="actionbar_failed_instant_upload">O envio rápido falhou</string>
   <string name="failed_upload_headline_text">Falharam os Uploads-Instantâneos</string>
   <string name="failed_upload_headline_hint">Sumário dos Uploads-Instantâneos falhados</string>
   <string name="failed_upload_all_cb">Seleccionar Todos</string>