From: tobiasKaminsky Date: Fri, 21 Nov 2014 16:58:01 +0000 (+0100) Subject: Merge branch 'develop' of git@github.com:owncloud/android.git into X-Git-Tag: oc-android-1.7.0_signed~42^2~17 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/b2158a8673b5a558cbb6e8f754196c9b5d96ede4?hp=462d032625db7668dafb027d5e0915139ac2d64d Merge branch 'develop' of git@github.com:owncloud/android.git into developNew Conflicts: res/values-fr/strings.xml --- diff --git a/owncloud-android-library b/owncloud-android-library index 2799b3e8..5bd0d738 160000 --- a/owncloud-android-library +++ b/owncloud-android-library @@ -1 +1 @@ -Subproject commit 2799b3e853c79e8ebb37051c92dfcc43f8d63788 +Subproject commit 5bd0d7387712ce3f53869294761ac4d8537841cd diff --git a/res/menu/file_select_all.xml b/res/menu/file_select_all.xml deleted file mode 100644 index a8097aae..00000000 --- a/res/menu/file_select_all.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml deleted file mode 100644 index 2cf16ac9..00000000 --- a/res/values-fr/strings.xml +++ /dev/null @@ -1,299 +0,0 @@ - - - %1$s Android App - version %1$s - Actualiser le compte - Téléverser - Contenu d\'autres applications - Fichiers - Ouvrir avec - Nouveau dossier - Paramètres - Détails - Envoyer - Trier - Trier par - - A-Z - Plus récent - Plus ancien - - - Général - Plus - Comptes - Gestion des comptes utilisateur - Utilisation d\'un code de sécurité - Protéger l\'accès aux données manipulées par le client - Téléchargements instantanés d\'images - Téléversement instantané des photos prises par la caméra - Téléchargements instantanés de vidéos - Téléversement instantané des vidéos prises par la caméra - Activer les logs - Utilisé pour enregistrer les problèmes dans les logs - Historique des logs - Cela affiche les logs enregistrés - Supprimer l\'historique - Aide - Recommander à un ami - Commentaires - Empreinte - Mémoriser l\'emplacement de partage - Mémoriser le dernier emplacement d\'upload - Essayez %1$s sur votre smartphone&nbsp;! - J\'aimerais vous inviter à utiliser %1$s sur votre smartphone ! -Téléchargez-le ici&nbsp;: %2$s - Vérifier le serveur - Adresse du serveur https://… - Nom d\'utilisateur - Mot de passe - Nouveau dans %1$s&nbsp;? - Fichiers - Connecter - Téléverser - Sélectionner le dossier d\'envoi&nbsp;: - Aucun compte n\'a été trouvé - Aucun compte %1$s n\'a été trouvé. Veuillez commencer par en configurer un. - Paramètres - Quitter - Rien à envoyer - Aucun contenu reçu. Rien à envoyer. - %1$s n\'est pas autorisé à accéder au contenu partagé - Téléversement - il y a quelques secondes - Il n\'y a rien ici&nbsp;! Envoyez donc quelque chose :) - Chargement… - Aucun fichier n\'est présent dans ce dossier. - Effleurez un fichier pour afficher les informations complémentaires - Taille : - Type : - Créé le : - Modifié le : - Télécharger - Actualiser le fichier - Le fichier a été renommé en %s pendant le téléversement - Partager le lien - Ne plus partager ce lien - Oui - Non - OK - Annuler le téléchargement - Annuler l\'envoi - Annuler - Sauvegarder & Quitter - Erreur - Chargement… - Erreur inconnue - À propos de - Changer de mot de passe - Effacer ce compte - Créer un compte - Téléverser un fichier depuis… - Nom du dossier - Téléversement… - Envoi du fichier %2$s : %1$d%% effectués - Téléversement réussi - Le fichier %1$s a été envoyé avec succès - Échec de l\'envoi - L\'envoi de %1$s a échoué - Le téléversement a échoué, vous devez vous connecter à nouveau - Téléchargement en cours… - Téléchargement en cours de %2$s, %1$d%% effectués - Téléchargement réussi - %1$s a été téléchargé avec succès - Le téléchargement a échoué - Le téléchargement de %1$s a échoué - Pas encore téléchargé - Le téléchargement a échoué, vous devez vous connecter à nouveau - Choisissez un compte - La synchronisation a échoué - Échec de la synchronisation, vous devez vous reconnecter à nouveau - La synchronisation de %1$s ne peut pas être complétée - Mot de passe invalide pour %1$s - Des conflits ont été trouvés - %1$d fichiers à garder synchronisés n\'ont put être synchronisé - La synchronisation des fichiers a échoué - Le contenu de %1$d fichiers n\'a pu être synchronisé (%2$d conflits) - Certains fichiers locaux ont été oubliés - %1$d fichiers du dossier %2$s n\'ont pas pu être copiés dans - Depuis la version 1.3.16, les fichiers envoyé depuis ce périphérique sont copiés dans le dossier local %1$s pour éviter une perte de données lorsqu\'un même fichier est synchronisé avec plusieurs comptes. - -En raison de cette modification, tous les fichiers envoyés avec des versions antérieures de cette application ont été copiés dans le dossier %2$s. Cependant une erreur a empêché l\'achèvement de cette opération pendant la synchronisation du compte. Vous pouvez soit laisser les fichiers tels quels et supprimer le lien vers %3$s, soit déplacer les fichiers dans le dossier %1$s et garder le lien vers %4$s. - -Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxquels ils étaient liés. - Le dossier %1$s n\'existe plus - Tout déplacer - Tous les fichiers ont été déplacés - Certains fichiers n\'ont pu être déplacés - Local&nbsp;: %1$s - Distant : %1$s - Il n\'y a pas assez de place disponible pour copier les fichiers sélectionnés dans le dossier %1$s. Voulez-vous quand même les déplacer ? - Veuillez saisir votre code de sécurité - Veuillez saisir votre code de sécurité - Le code PIN vous sera demandé à chaque lancement de l\'application - Veuillez saisir à nouveau votre code de sécurité - Retirer le code de sécurité - Les deux codes saisis ne concordent pas - Code de sécurité incorrect - Code de sécurité retiré - Code de sécurité enregistré - %1$s lecteur de musique - %1$s (lecture) - %1$s (chargement) - %1$s pourcentage de lecture finie - Fichier média introuvable - Aucun compte n\'a été trouvé - Le fichier n\'est pas dans un compte valide - Le codec de ce média n\'est pas pris en charge - Le fichier média ne peut pas être lu - Le fichier média n\'est pas correctement encodé - Délai dépassé pour la lecture du morceau. - Le fichier média ne peut pas être diffusé - Le fichier média ne peut être joué avec le lecteur standard - Erreur de sécurité à la lecture de %1$s - Erreur de lecture de fichier à la lecture de %1$s - Erreur inattendue à la lecture de %1$s - Bouton de rembobinage - Bouton de lecture ou de pause - Bouton d\'avance rapide - Demande d\'autorisation… - Tentative de connexion… - Pas de connexion réseau - Connexion sécurisée non disponible - Connexion établie - Test de la connexion… - Configuration du serveur erronée - Un compte pour le même utilisateur et serveur existe déjà sur ce périphérique - L\'utilisateur entré ne correspond pas à l\'utilisateur de ce compte - Une erreur inconnue s\'est produite - Impossible de trouver l\'hôte - Aucune instance du serveur n\'a été trouvée - Le serveur met trop longtemps à répondre - Adresse invalide - Échec de l\'initialisation SSL - Impossible de vérifier l\'identité du serveur SSL - La version du serveur n\'est pas reconnue - Impossible d\'établir la connexion - Connexion sécurisée établie - Nom d\'utilisateur ou mot de passe incorrect - Échec d\'autorisation - Accès refusé par le serveur d\'autorisation - État inattendu&nbsp;; veuillez entrer à nouveau l\'URL du serveur - Votre autorisation a expiré. Merci de vous authentifier à nouveau - Veuillez saisir le mot de passe courant - Votre session a expiré. Merci de vous reconnecter - Connexion au serveur d\'authentification… - Le serveur ne prend pas en charge pas cette méthode d\'authentification - %1$s ne prend pas en charge les comptes multiples - Votre serveur a retourné un identifiant d\'utilisateur incorrect. Veuillez prendre contact avec votre administrateur - - Impossible de s\'authentifier sur ce serveur - Maintenir le fichier à jour - Renommer - Supprimer - Voulez-vous vraiment supprimer %1$s&nbsp;? - Voulez-vous vraiment supprimer %1$s et son contenu&nbsp;? - Local seulement - Le contenu local uniquement - Effacer du serveur - Les deux distant et local - Suppression effectuée avec succès - Suppression impossible - Entrez un nouveau nom - La version locale ne peut être renommée, veuillez réessayer avec un nom différent - Renommage impossible - Le fichier distant n\'a pu être vérifié - Le contenu des fichiers est déjà synchronisé - Le dossier n\'a pas pu être créé - Caractères interdits&nbsp;: / \\ &lt; &gt; : " | ? * - Le nom du fichier ne peut pas être vide - Veuillez patienter - Problème inattendu. Veuillez essayer une autre application pour la sélection du fichier - Aucun fichier sélectionné - Envoyer un lien à… - Connexion avec oAuth2 - Connexion au serveur oAuth2… - L\'identité du site ne peut être vérifiée - - Le certificat du serveur n\'est pas sûr - - Le certificat du serveur a expiré - - Le certificat du serveur n\'est pas encore valide - - L\'URL ne correspond pas au nom d\'hôte du certificat - Voulez-vous tout de même faire confiance à ce certificat&nbsp;? - Impossible de sauvegarder le certificat - Détails - Masquer - Délivré à&nbsp;: - Délivré par&nbsp;: - Nom d\'usage&nbsp;: - Organisation&nbsp;: - Unité organisationnelle&nbsp;: - Pays&nbsp;: - Région&nbsp;: - Localisation&nbsp;: - Validité&nbsp;: - De&nbsp;: - À&nbsp;: - Signature&nbsp;: - Algorithme&nbsp;: - Impossible d\'afficher le certificat. - - Aucune information sur l\'erreur - Ceci est un espace réservé - placeholder.txt - Image PNG - 389 Ko - 18/05/2012 12:23 - 12:23:45 - Téléverser les images via une connexion WiFi uniquement - Téléverser les vidéos via une connexion WiFi uniquement - /TéléversementInstantané - Conflit de mise à jour - Le fichier distant %s n\'est pas synchronisé avec le fichier local. En choisissant de continuer, vous remplacerez le contenu de fichier sur le serveur. - Garder les deux versions - Écraser - Ne pas téléverser - Prévisualisation de l\'image - Cette image ne peut pas être affichée - %1$s n\'a pas pu être copié dans le dossier local %2$s - Chemin d\'accès pour le téléversement - Désolé, le partage n\'est pas disponible sur votre serveur. Veuillez contacter votre administrateur. - Impossible de partager. Vérifiez que le fichier est bien présent - Une erreur est survenue lors de la tentative de partage de ce fichier ou répertoire - Impossible de supprimer le partage. Vérifiez que le fichier est bien présent - Une erreur est survenue lors de la tentative d’annulation du partage de ce fichier ou répertoire - Envoyer - Copier le lien - Copié dans le presse-papiers - Erreur critique&nbsp;: impossible de réaliser des opérations - Une erreur s\'est produite pendant la connection au serveur - Une erreur est survenue pendant l\'attente du serveur. L\'opération n\'a pas pu être effectuée. - Une erreur est survenue pendant l\'attente du serveur. L\'opération n\'a pas pu être effectuée. - L\'opération n\'a pas pu être terminée, le serveur n\'est pas disponible. - - Vous ne possédez pas les droits suffisants %s - afin de renommer ce fichier - afin d’effacer ce fichier - afin de partager ce fichier - afin de ne plus partager ce fichier - afin de créer ce fichier - afin d’importer dans ce répertoire - Ce fichier n’est plus disponible sur le serveur - Comptes - Ajouter un compte - La connexion sécurisée est redirigée via une route non-sécurisée. - Journaux - Envoyer l\'historique - Journaux de l\'application Android ownCloud - Chargement des données... - Authentification requise - Mot de passe incorrect - Déplacer - Il n\'y a rien ici. Vous pouvez ajouter un dossier ! - Choisir - Impossible de déplacer. Vérifiez que le fichier existe - Il n\'est pas possible de déplacer un dossier vers un de ses descendants - Le fichier existe déjà dans le dossier de destination - Une erreur est survenue lors de la tentative de déplacement de ce fichier ou dossier - de déplacer ce fichier - Téléchargements instantanés - Sécurité - diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 4da13ba2..072a0850 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -1,6 +1,6 @@ - %1$s Aplicação(ões) Android + %1$s App(s) Android versão %1$s Atualizar conta Enviar @@ -51,15 +51,15 @@ Ligar Enviar Escolha a pasta de envio: - Nenhuma conta encontrada - Não tem nenhuma conta %1$s no seu dispositivo. Configure uma conta. + A conta não foi encontrada + Não tem nenhuma conta %1$s no seu dispositivo. Por favor, configure primeiro uma conta. Configurar Sair - Sem conteúdo para carregar + Sem conteúdo para enviar Não foi recebido nenhum conteúdo. Nada para enviar. O %1$s não está autorizado a aceder aos ficheiro partilhados. A enviar - Minutos atrás + segundos atrás Vazio. Envie alguma coisa! A carregar ... Não existem ficheiros nesta pasta. @@ -215,12 +215,12 @@ Quer confiar neste certificado de qualquer maneira? O certificado não pôde ser guardado Detalhes - Esconder + Ocultar Emitido para: Emitido por: Nome comum. Organização: - Unidade organizaconal. + Unidade organizacional. País: Estado: Localização: @@ -229,33 +229,33 @@ Para: Assinatura: Algoritmo - O certificado não pôde ser mostrado. - - Nenhuma informação acerca do erro + Não foi possível mostrar o certificado. + - Nenhuma informação sobre o erro Isto é uma variável. placeholder.txt Imagem PNG 389 KB - 2012/05/18 12:23 PM + 2012/05/18 12:23 12:23:45 - Enviar fotografias apenas via WiFi - Enviar videos apenas por WiFi - /Upload-Instantâneo - Conflito na actualização + Só enviar as fotografias via wi-fi + Só enviar os vídeos por wi-fi + /Envio Instantâneo + Conflito na atualização O ficheiro remoto %s não está sincronizado com o ficheiro local. Se continuar ira substituir o ficheiro no servidor. - Manter os dois - Sobrepor + Manter ambos + Substituir Não enviar. - Pré-Visualização da imagem + Pré-Visualizar imagem Esta imagem não pode ser mostrada Não foi possível copiar %1$s para a pasta local %2$s - Caminho de Upload + Caminho de \'A Enviar\' Lamentamos mas não é possível partilhar através do seu servidor. Por favor contacte o seu administrador. Não é possivel partilhar. Por favor verifique se o ficheiro existe Ocorreu um erro enquanto tentava partilhar este ficheiro ou pasta Não é possível retirar a partilha. Verifique se o ficheiro existe Ocorreu um erro enquanto retirava a partilha deste ficheiro ou pasta Enviar - Copiar ligação + Copiar hiperligação Copiado para a área de transferência Erro crítico: não é possível executar as operações Ocorreu um erro durante a ligação ao servidos. @@ -263,31 +263,31 @@ Ocorreu um erro durante a ligação ao servidor, não foi possível realizar a operação. A operação não foi concluída, o servidor está inacessível. - Você não tem permissão %s + Não tem permissão %s para renomear este ficheiro - para eliminar este ficheiro + para apagar este ficheiro para partilhar este ficheiro - para eliminar a partilha deste ficheiro + para cancelar a partilha deste ficheiro para criar o ficheiro - para carregar dentro desta pasta + para enviar nesta pasta O ficheiro não está mais disponível no servidor Contas Adicionar conta Ligação segura é redireccionada para um caminho inseguro. - Logs + Registos de Alterações Enviar Histórico - Logs da app ownCloud Android - A carregar os dados... + Registos das alterações da app ownCloud Android + A carregar os dados ... Autenticação necessária - Password errada + Palavra-passe errada Mover Não está aqui nada. Pode adicionar uma pasta! - Escolha - Não é possível mover. Verifique se o ficheiro existe + Escolher + Não é possível mover. Por favor, verifique se o ficheiro existe Não é possível mover esta pasta deste modo O ficheiro já existe na pasta de destino - Um erro ocorreu ao tentar mover este ficheiro ou pasta + Ocorreu um ocorreu quando tentava mover este ficheiro ou pasta para mover este ficheiro - Uploads Instantâneos + Envios Instantâneos Segurança diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index ad2a2cbe..04804402 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -73,6 +73,7 @@ import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.utils.ErrorMessageAdapter; +import com.owncloud.android.utils.UriUtils; @@ -120,6 +121,9 @@ public class FileUploader extends Service implements OnDatatransferProgressListe private NotificationCompat.Builder mNotificationBuilder; private int mLastPercent; + private static final String MIME_TYPE_PDF = "application/pdf"; + private static final String FILE_EXTENSION_PDF = ".pdf"; + public static String getUploadFinishMessage() { return FileUploader.class.getName().toString() + UPLOAD_FINISH_MESSAGE; @@ -646,18 +650,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType, FileDataStorageManager storageManager) { - OCFile newFile = new OCFile(remotePath); - newFile.setStoragePath(localPath); - newFile.setLastSyncDateForProperties(0); - newFile.setLastSyncDateForData(0); - - // size - if (localPath != null && localPath.length() > 0) { - File localFile = new File(localPath); - newFile.setFileLength(localFile.length()); - newFile.setLastSyncDateForData(localFile.lastModified()); - } // don't worry about not assigning size, the problems with localPath - // are checked when the UploadFileOperation instance is created // MIME type if (mimeType == null || mimeType.length() <= 0) { @@ -671,6 +663,25 @@ public class FileUploader extends Service implements OnDatatransferProgressListe if (mimeType == null) { mimeType = "application/octet-stream"; } + + if (isPdfFileFromContentProviderWithoutExtension(localPath, mimeType)){ + remotePath += FILE_EXTENSION_PDF; + } + + OCFile newFile = new OCFile(remotePath); + newFile.setStoragePath(localPath); + newFile.setLastSyncDateForProperties(0); + newFile.setLastSyncDateForData(0); + + // size + if (localPath != null && localPath.length() > 0) { + File localFile = new File(localPath); + newFile.setFileLength(localFile.length()); + newFile.setLastSyncDateForData(localFile.lastModified()); + } // don't worry about not assigning size, the problems with localPath + // are checked when the UploadFileOperation instance is created + + newFile.setMimetype(mimeType); return newFile; @@ -856,4 +867,17 @@ public class FileUploader extends Service implements OnDatatransferProgressListe sendStickyBroadcast(end); } + /** + * Checks if content provider, using the content:// scheme, returns a file with mime-type + * 'application/pdf' but file has not extension + * @param localPath + * @param mimeType + * @return true if is needed to add the pdf file extension to the file + */ + private boolean isPdfFileFromContentProviderWithoutExtension(String localPath, String mimeType) { + return localPath.startsWith(UriUtils.URI_CONTENT_SCHEME) && + mimeType.equals(MIME_TYPE_PDF) && + !localPath.endsWith(FILE_EXTENSION_PDF); + } + } diff --git a/src/com/owncloud/android/operations/UploadFileOperation.java b/src/com/owncloud/android/operations/UploadFileOperation.java index 43fcaa55..1536a604 100644 --- a/src/com/owncloud/android/operations/UploadFileOperation.java +++ b/src/com/owncloud/android/operations/UploadFileOperation.java @@ -31,11 +31,16 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.httpclient.methods.PutMethod; import org.apache.commons.httpclient.methods.RequestEntity; +import android.accounts.Account; +import android.content.Context; +import android.net.Uri; + +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileUploader; -import com.owncloud.android.lib.common.network.ProgressiveDataTransferer; -import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; +import com.owncloud.android.lib.common.network.ProgressiveDataTransferer; import com.owncloud.android.lib.common.operations.OperationCancelledException; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -45,9 +50,7 @@ import com.owncloud.android.lib.resources.files.ChunkedUploadRemoteFileOperation import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation; import com.owncloud.android.utils.FileStorageUtils; - -import android.accounts.Account; -import android.content.Context; +import com.owncloud.android.utils.UriUtils; /** @@ -92,10 +95,9 @@ public class UploadFileOperation extends RemoteOperation { throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation creation"); if (file == null) throw new IllegalArgumentException("Illegal NULL file in UploadFileOperation creation"); - if (file.getStoragePath() == null || file.getStoragePath().length() <= 0 - || !(new File(file.getStoragePath()).exists())) { + if (file.getStoragePath() == null || file.getStoragePath().length() <= 0) { throw new IllegalArgumentException( - "Illegal file in UploadFileOperation; storage path invalid or file not found: " + "Illegal file in UploadFileOperation; storage path invalid: " + file.getStoragePath()); } @@ -218,52 +220,77 @@ public class UploadFileOperation extends RemoteOperation { // copied } else { + String temporalPath = FileStorageUtils.getTemporalPath(mAccount.name) + mFile.getRemotePath(); mFile.setStoragePath(temporalPath); temporalFile = new File(temporalPath); - if (!mOriginalStoragePath.equals(temporalPath)) { // preventing - // weird - // but - // possible - // situation - InputStream in = null; - OutputStream out = null; - try { - File temporalParent = temporalFile.getParentFile(); - temporalParent.mkdirs(); - if (!temporalParent.isDirectory()) { - throw new IOException("Unexpected error: parent directory could not be created"); - } - temporalFile.createNewFile(); - if (!temporalFile.isFile()) { - throw new IOException("Unexpected error: target file could not be created"); - } - in = new FileInputStream(originalFile); + + File temporalParent = temporalFile.getParentFile(); + temporalParent.mkdirs(); + if (!temporalParent.isDirectory()) { + throw new IOException("Unexpected error: parent directory could not be created"); + } + temporalFile.createNewFile(); + if (!temporalFile.isFile()) { + throw new IOException("Unexpected error: target file could not be created"); + } + + InputStream in = null; + OutputStream out = null; + + try { + + // In case document provider schema as 'content://' + if (mOriginalStoragePath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { + + Uri uri = Uri.parse(mOriginalStoragePath); + + in = MainApp.getAppContext().getContentResolver().openInputStream(uri); out = new FileOutputStream(temporalFile); - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - } catch (Exception e) { - result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED); - return result; - - } finally { - try { - if (in != null) - in.close(); - } catch (Exception e) { - Log_OC.d(TAG, "Weird exception while closing input stream for " + mOriginalStoragePath + " (ignoring)", e); + int nRead; + byte[] data = new byte[16384]; + + while ((nRead = in.read(data, 0, data.length)) != -1) { + out.write(data, 0, nRead); } - try { - if (out != null) - out.close(); - } catch (Exception e) { - Log_OC.d(TAG, "Weird exception while closing output stream for " + expectedPath + " (ignoring)", e); + + out.flush(); + + } else { + if (!mOriginalStoragePath.equals(temporalPath)) { // preventing + // weird + // but + // possible + // situation + + in = new FileInputStream(originalFile); + out = new FileOutputStream(temporalFile); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } } } + + } catch (Exception e) { + result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED); + return result; + + } finally { + try { + if (in != null) + in.close(); + } catch (Exception e) { + Log_OC.d(TAG, "Weird exception while closing input stream for " + mOriginalStoragePath + " (ignoring)", e); + } + try { + if (out != null) + out.close(); + } catch (Exception e) { + Log_OC.d(TAG, "Weird exception while closing output stream for " + expectedPath + " (ignoring)", e); + } } } } @@ -417,5 +444,4 @@ public class UploadFileOperation extends RemoteOperation { public void cancel() { mUploadOperation.cancel(); } - } diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index b5d543a4..49259e9f 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -31,6 +31,7 @@ import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; +import android.content.ContentUris; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -41,13 +42,18 @@ import android.content.SyncRequest; import android.content.res.Resources.NotFoundException; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.os.IBinder; import android.preference.PreferenceManager; +import android.provider.DocumentsContract; import android.provider.MediaStore; +import android.provider.OpenableColumns; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; @@ -101,6 +107,7 @@ import com.owncloud.android.ui.preview.PreviewMediaFragment; import com.owncloud.android.ui.preview.PreviewVideoActivity; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.ErrorMessageAdapter; +import com.owncloud.android.utils.UriUtils; /** @@ -151,7 +158,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private String DIALOG_UNTRUSTED_CERT; private OCFile mWaitingToSend; - + @Override protected void onCreate(Bundle savedInstanceState) { Log_OC.d(TAG, "onCreate() start"); @@ -563,6 +570,11 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { builder.setExpedited(true); builder.setManual(true); builder.syncOnce(); + + // Fix bug in Android Lollipop when you click on refresh the whole account + Bundle extras = new Bundle(); + builder.setExtras(extras); + SyncRequest request = builder.build(); ContentResolver.requestSync(request); } @@ -654,8 +666,12 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void requestSimpleUpload(Intent data, int resultCode) { String filepath = null; + String mimeType = null; + + Uri selectedImageUri = data.getData(); + try { - Uri selectedImageUri = data.getData(); + mimeType = getContentResolver().getType(selectedImageUri); String filemanagerstring = selectedImageUri.getPath(); String selectedImagePath = getPath(selectedImageUri); @@ -687,10 +703,34 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } if (!remotepath.endsWith(OCFile.PATH_SEPARATOR)) remotepath += OCFile.PATH_SEPARATOR; - remotepath += new File(filepath).getName(); + + if (filepath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { + + Cursor cursor = MainApp.getAppContext().getContentResolver() + .query(Uri.parse(filepath), null, null, null, null, null); + + try { + if (cursor != null && cursor.moveToFirst()) { + String displayName = cursor.getString( + cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + Log.i(TAG, "Display Name: " + displayName + "; mimeType: " + mimeType); + + displayName.replace(File.separatorChar, '_'); + displayName.replace(File.pathSeparatorChar, '_'); + remotepath += displayName + DisplayUtils.getComposedFileExtension(filepath); + + } + } finally { + cursor.close(); + } + + } else { + remotepath += new File(filepath).getName(); + } i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath); i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath); + i.putExtra(FileUploader.KEY_MIME_TYPE, mimeType); i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); if (resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE) i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE); @@ -866,22 +906,74 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { return dialog; } - /** - * Translates a content URI of an image to a physical path - * on the disk + * Translates a content URI of an content to a physical path on the disk + * * @param uri The URI to resolve - * @return The path to the image or null if it could not be found + * @return The path to the content or null if it could not be found */ public String getPath(Uri uri) { - String[] projection = { MediaStore.Images.Media.DATA }; - Cursor cursor = managedQuery(uri, projection, null, null, null); - if (cursor != null) { - int column_index = cursor - .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); - cursor.moveToFirst(); - return cursor.getString(column_index); - } + final boolean isKitKatOrLater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKatOrLater && DocumentsContract.isDocumentUri(getApplicationContext(), uri)) { + // ExternalStorageProvider + if (UriUtils.isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + } + // DownloadsProvider + else if (UriUtils.isDownloadsDocument(uri)) { + + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), + Long.valueOf(id)); + + return UriUtils.getDataColumn(getApplicationContext(), contentUri, null, null); + } + // MediaProvider + else if (UriUtils.isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[] { split[1] }; + + return UriUtils.getDataColumn(getApplicationContext(), contentUri, selection, selectionArgs); + } + // Documents providers returned as content://... + else if (UriUtils.isContentDocument(uri)) { + return uri.toString(); + } + } + // MediaStore (and general) + else if ("content".equalsIgnoreCase(uri.getScheme())) { + + // Return the remote address + if (UriUtils.isGooglePhotosUri(uri)) + return uri.getLastPathSegment(); + + return UriUtils.getDataColumn(getApplicationContext(), uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } return null; } diff --git a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java index 83e7bc07..09185726 100644 --- a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java +++ b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java @@ -34,9 +34,6 @@ import android.widget.TextView; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.ActionBar.OnNavigationListener; -import com.actionbarsherlock.internal.view.menu.ActionMenuItemView; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; import com.owncloud.android.lib.common.utils.Log_OC; @@ -76,8 +73,6 @@ public class UploadFilesActivity extends FileActivity implements private static final String WAIT_DIALOG_TAG = "WAIT"; private static final String QUERY_TO_MOVE_DIALOG_TAG = "QUERY_TO_MOVE"; - private boolean selectAllToggled = false; - private Menu menu; @Override public void onCreate(Bundle savedInstanceState) { @@ -124,7 +119,6 @@ public class UploadFilesActivity extends FileActivity implements actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); actionBar.setListNavigationCallbacks(mDirectories, this); - // wait dialog if (mCurrentDialog != null) { mCurrentDialog.dismiss(); @@ -133,15 +127,8 @@ public class UploadFilesActivity extends FileActivity implements Log_OC.d(TAG, "onCreate() end"); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu items for use in the action bar - MenuInflater inflater = getSherlock().getMenuInflater(); - inflater.inflate(R.menu.file_select_all, menu); - this.menu = menu; - return true; - } - + + @Override public boolean onOptionsItemSelected(MenuItem item) { boolean retval = true; @@ -152,33 +139,12 @@ public class UploadFilesActivity extends FileActivity implements } break; } - case R.id.actionbar_select_all:{ - if(selectAllToggled){ - toggleOffSelectAll(); - }else{ - toggleOnSelectAll(item); - } - break; - } default: retval = super.onOptionsItemSelected(item); } return retval; } - public void toggleOffSelectAll(MenuItem item){ - selectAllToggled = false; - item.setIcon(android.R.drawable.checkbox_off_background); - mFileListFragment.deselectAll(); - } - public void toggleOffSelectAll(){ - MenuItem item = menu.findItem(R.id.actionbar_select_all); - toggleOffSelectAll(item); - } - public void toggleOnSelectAll(MenuItem item){ - selectAllToggled = true; - item.setIcon(android.R.drawable.checkbox_on_background); - mFileListFragment.selectAll(); - } + @Override public boolean onNavigationItemSelected(int itemPosition, long itemId) { @@ -209,7 +175,6 @@ public class UploadFilesActivity extends FileActivity implements ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(false); } - toggleOffSelectAll(); } @@ -277,11 +242,10 @@ public class UploadFilesActivity extends FileActivity implements * {@inheritDoc} */ @Override - public void onDirectoryClick(File directory) { + public void onDirectoryClick(File directory) { pushDirname(directory); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); - toggleOffSelectAll(); } diff --git a/src/com/owncloud/android/ui/activity/Uploader.java b/src/com/owncloud/android/ui/activity/Uploader.java index 66359f3d..6c8a1320 100644 --- a/src/com/owncloud/android/ui/activity/Uploader.java +++ b/src/com/owncloud/android/ui/activity/Uploader.java @@ -170,7 +170,7 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene case DIALOG_MULTIPLE_ACCOUNT: CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(MainApp.getAccountType()).length]; for (int i = 0; i < ac.length; ++i) { - ac[i] = mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name; + ac[i] = DisplayUtils.convertIdn(mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name, false); } builder.setTitle(R.string.common_choose_account); builder.setItems(ac, new OnClickListener() { diff --git a/src/com/owncloud/android/ui/fragment/LocalFileListFragment.java b/src/com/owncloud/android/ui/fragment/LocalFileListFragment.java index 62b41a3e..c9408b1e 100644 --- a/src/com/owncloud/android/ui/fragment/LocalFileListFragment.java +++ b/src/com/owncloud/android/ui/fragment/LocalFileListFragment.java @@ -98,33 +98,13 @@ public class LocalFileListFragment extends ExtendedListFragment { Log_OC.i(TAG, "onActivityCreated() stop"); } - public void selectAll(){ - int numberOfFiles = mAdapter.getCount(); - for(int i = 0; i < numberOfFiles; i++){ - File file = (File) mAdapter.getItem(i); - if (file != null) { - if (!file.isDirectory()) { - /// Click on a file - getListView().setItemChecked(i, true); - // notify the change to the container Activity - mContainerActivity.onFileClick(file); - } - } - } - } - - public void deselectAll(){ - mAdapter = new LocalFileListAdapter(mContainerActivity.getInitialDirectory(), getActivity()); - setListAdapter(mAdapter); - } /** * Checks the file clicked over. Browses inside if it is a directory. Notifies the container activity in any case. */ @Override public void onItemClick(AdapterView l, View v, int position, long id) { - File file = (File) mAdapter.getItem(position); - + File file = (File) mAdapter.getItem(position); if (file != null) { /// Click on a directory if (file.isDirectory()) { diff --git a/src/com/owncloud/android/utils/DisplayUtils.java b/src/com/owncloud/android/utils/DisplayUtils.java index d8bf88f3..da81f539 100644 --- a/src/com/owncloud/android/utils/DisplayUtils.java +++ b/src/com/owncloud/android/utils/DisplayUtils.java @@ -277,7 +277,24 @@ public class DisplayUtils { return url; } } - + + /** + * Get the file extension if it is on path as type "content://.../DocInfo.doc" + * @param filepath: Content Uri converted to string format + * @return String: fileExtension (type '.pdf'). Empty if no extension + */ + public static String getComposedFileExtension(String filepath) { + String fileExtension = ""; + String fileNameInContentUri = filepath.substring(filepath.lastIndexOf("/")); + + // Check if extension is included in uri + int pos = fileNameInContentUri.lastIndexOf('.'); + if (pos >= 0) { + fileExtension = fileNameInContentUri.substring(pos); + } + return fileExtension; + } + public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution, long transitionResolution, int flags){ CharSequence dateString = ""; @@ -301,6 +318,6 @@ public class DisplayUtils { } } - return dateString.toString().split(",")[0]; + return dateString.toString().split(",")[0]; } } diff --git a/src/com/owncloud/android/utils/UriUtils.java b/src/com/owncloud/android/utils/UriUtils.java new file mode 100644 index 00000000..e66d2c9f --- /dev/null +++ b/src/com/owncloud/android/utils/UriUtils.java @@ -0,0 +1,103 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2014 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 . + * + */ + +package com.owncloud.android.utils; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; + + +/** + * A helper class for some Uri operations. + */ +public class UriUtils { + + public static final String URI_CONTENT_SCHEME = "content://"; + + + /** + * Get the value of the data column for this Uri. This is useful for + * MediaStore Uris, and other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @param selection (Optional) Filter used in the query. + * @param selectionArgs (Optional) Selection arguments used in the query. + * @return The value of the _data column, which is typically a file path. + */ + public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { column }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + if (cursor != null && cursor.moveToFirst()) { + + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } finally { + if (cursor != null) + cursor.close(); + } + return null; + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + */ + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + */ + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + */ + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is Google Photos. + */ + public static boolean isGooglePhotosUri(Uri uri) { + return "com.google.android.apps.photos.content".equals(uri.getAuthority()); + } + + /** + * + * @param uri The Uri to check. + * @return Whether the Uri is from a content provider as kind "content://..." + */ + public static boolean isContentDocument(Uri uri) { + return uri.toString().startsWith(URI_CONTENT_SCHEME); + } +} diff --git a/tests/.classpath b/tests/.classpath index 26d8fe48..9b141f6f 100644 --- a/tests/.classpath +++ b/tests/.classpath @@ -1,10 +1,10 @@ + + - -