From: masensio Date: Tue, 5 May 2015 08:31:46 +0000 (+0200) Subject: Merge branch 'develop' into thumbnailOOM X-Git-Tag: test~6^2^2~8 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/7eea2ea507b41edb242cc1a2fe9eae1a9c03d280?hp=6b0af8296009bc8b89bc98a8ec8b3afd7815ed8e Merge branch 'develop' into thumbnailOOM --- diff --git a/oc_jb_workaround/AndroidManifest.xml b/oc_jb_workaround/AndroidManifest.xml index c08002c4..65fc3648 100644 --- a/oc_jb_workaround/AndroidManifest.xml +++ b/oc_jb_workaround/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="0100023" + android:versionName="1.0.23" > Your server is not returning a correct user id, please contact an administrator Cannot authenticate against this server - Account does not exist on the device yet + Account does not exist in the device yet Keep file up to date Rename Remove diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index e673ba2f..029da740 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -121,7 +121,7 @@ Téléchargez-le ici : %2$s 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és 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. + Depuis la version 1.3.16, les fichiers envoyés depuis cet appareil 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. @@ -306,7 +306,7 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq Téléversement immédiat Sécurité Répertoire de téléversement des vidéos - Le téléchargement du dossier %1$s n\'a pas pu être achevé + Le téléchargement de %1$s dossier(s) n\'a pas pu être achevé %1$s a partagé \"%2$s\" avec vous Actualiser la connexion Adresse du serveur diff --git a/res/values-id/strings.xml b/res/values-id/strings.xml index c25cd831..ebb6be7e 100644 --- a/res/values-id/strings.xml +++ b/res/values-id/strings.xml @@ -260,6 +260,8 @@ Terjadi kesalahan saat mencoba membagikan berkas atau folder ini Tidak dapat menghapus berbagi. Mohon periksa apakah berkas ada Terjadi kesalahan saat mencoba menghapus berbagi berkas dan folder ini + Masukkan sandi + Anda harus memasukkan sandi Kirim Salin tautan Disalin ke papan klip diff --git a/res/values-ja-rJP/strings.xml b/res/values-ja-rJP/strings.xml index 430b55d7..77e26fa0 100644 --- a/res/values-ja-rJP/strings.xml +++ b/res/values-ja-rJP/strings.xml @@ -303,7 +303,7 @@ 自動アップロード セキュリティ 動画のアップロードパス - %1$s のフォルダのダウンロードが完了しませんでした。 + %1$s フォルダーのダウンロードが完了しませんでした %1$sがあなたと\"%2$s\"を共有しました 再接続中 サーバーアドレス diff --git a/res/values-lb/strings.xml b/res/values-lb/strings.xml index 8518d696..71280e81 100644 --- a/res/values-lb/strings.xml +++ b/res/values-lb/strings.xml @@ -1,96 +1,252 @@ + %1$s Android-App Versioun %1$s + Kont opfrëschen Eroplueden - Dateien + Contenu aus aneren Appen + Fichieren Opmaachen mat + Neien Dossier Astellungen Detailer Schécken + Zortéieren + Zortéieren no + + A-Z + Nei - Al + Allgemeng Méi - Accounten - App PIN + Konten + Konte geréieren + App-PIN + D\'App schützen + Biller direkt eroplueden + Biller vum Fotoapparat direkt eroplueden + Videoen direkt eroplueden + Biller vun der Kamera direkt eroplueden + Protokoller aktivéieren + Heiduerch gi Problemer protokolléiert + Protokoll-Historique + Hei ginn déi enregistréiert Protokoller ugewisen + Historique läschen Hëllef + Engem Frënd recommendéieren Feedback + Impressum + Server kontrolléieren + Server-Adress https://… Benotzernumm Passwuert - Dateien + Nei bei %1$s? + Fichieren Verbannen Eroplueden + Neien Dossier Keen Account fonnt Setup Erausgoen + Et gouf kee Contenu emfaangen. Näischt do fir eropzelueden. Eroplueden - Sekonnen hir - Hei ass näischt. Lued eppes rop! + Sekonnen hier + Hei ass näischt. Lued eppes erop! Dossier Dossieren - Datei - Dateien + Fichier + Fichieren Gréisst: Typ: Erstallt: Geännert: - Download + Eroflueden + Fichier opfrëschen Link deelen Jo Nee OK - Upload ofbriechen + Eroflueden ofbriechen + Eroplueden ofbriechen Ofbriechen - Späicher & géi raus - Fehler - Et ass en onbekannte Fehler opgetrueden + Späicheren an Zoumaachen + Feeler + Onbekannte Feeler Iwwer Passwuert änneren - Account läschen - Account erstellen - Dossiers Numm: - Gett eropgelueden ... - Eroplueden färdeg - Eroplueden huet net geklappt - Eroflueden huet net geklappt - Wiel en Account aus - Alles bewegen - Gëff w.e.g. däin App PIN an - Gëff däin App PIN an - Gëff däin App PIN w.e.g. nei an - Huel däin App PIN raus - Ongültegen App PIN - App PIN geläscht - App PIN gespaichert - Keng Netzwierk Verbindung - Keng geséchert Verbindung verfügbar. - Verbindung hiergestallt - Ongülteg Server Konfiguratioun - Et ass en onbekannte Fehler opgetrueden! - Server Instanz net fonnt - Ëm-benennen + Kont läschen + Kont uleeën + Dossiersnumm: + Lueden erop ... + Eroplueden ofgeschloss + %1$s gouf erfollegräich eropgelueden + Eropluede feelgeschloen + Eropluede vun %1$s konnt net ofgeschloss ginn + Eropluede feelgeschloen, du muss dech nei aloggen + Lueden erof … + Eroflueden ofgeschloss + %1$s gouf erfollegräich erofgelueden + Erofluede feelgeschloen + Erofluede vun %1$s konnt net ofgeschloss ginn + Nach net erofgelueden + Erofluede feelgeschloen, du muss dech nei aloggen + Kont auswielen + Synchroniséierung feelgeschloen + Synchroniséierung feelgeschloen, du muss dech nei aloggen + Synchroniséierung vun %1$s konnt net ofgeschloss ginn + Ongëltegt Passwuert fir %1$s + Konflikter fonnt + Verschidde lokal Fichiere goufe vergiess + Den Dossier %1$s existéiert net méi + All réckelen + All d\'Fichiere goufe geréckelt + Verschidde Fichiere konnten net geréckelt ginn + Lokal: %1$s + Um Server: %1$s + Gëff w.e.g. däin App-PIN an + Gëff däin App-PIN an + De PIN gëtt all Kéier gefrot wann d\'App gestart gëtt + App-PIN nei aginn + App-PIN läschen + D\'App-PINe sinn net déi selwescht + Ongëltegen App-PIN + App-PIN geläscht + App-PIN gespäichert + %1$s Musek-Programm + %1$s (spillt of) + %1$s (lued) + %1$s Ofspillen ofgeschloss + Kee Mediefichier fonnt + Kee Kont uginn + Fichier net an engem gëltege Kont + Medie-Codec net ënnerstëtzt + Mediefichier konnt net gelies ginn + Mediefichier net korrekt encodéiert + Zäit ofgelaf beim Versuch de Fichier ofzespillen + Mediefichier konnt net gestreamt ginn + Mediefichier konnt net mam Standard-Medieprogramm ofgespillt ginn + Sécherheetsfeeler beim Ofspille vun %1$s + Zréckspull-Knäppchen + Ofspill- oder Paus-Knäppchen + Keng Netzwierkconnectioun + Keng geséchert Connectioun disponibel. + Connectioun hiergestallt + Testen d\'Connectioun + Ongëlteg Server-Konfiguratioun + Et ass en onbekannte Feeler opgetrueden! + Server konnt net fonnt ginn + Server-Instanz net fonnt + De Server huet ze laang gebraucht fir ze äntweren + Ongëlteg URL + SSL-Initialiséierung feelgeschloen + Konnt d\'Identitéit vum SSL-Server net verifizéieren + Onbekannte Server-Versioun + Konnt d\'Connectioun net hierstellen + Sécher Connectioun hiergestallt + Falsche Benotzernumm oder falscht Passwuert + Authoriséierung net erfollegräich + Accès duerch den Authoriséierungsserver verweigert + Gëff w.e.g. däin aktuellt Passwuert an + Deng Sessioun ass ofgelaf. Connectéier dech nei w.e.g. + De Server ënnerstëtzt dës Authentifizéierungsmethod net + Fichier aktuell halen + Ëmbenennen Läschen - Nemmen Lokal + Wëlls du %1$s wierklech läschen? + Wëlls du %1$s an de ganzen Inhalt wierklech läschen? + Nemme lokal + Nëmme lokal Inhalter Vum Server läschen + Um Server a lokal + Erfollegräich geläscht + Läsche feelgeschloen + Gëff en neien Numm an + Fichiersinhalter scho synchroniséiert + Dossier konnt net ugeluecht ginn + De Fichiersnumm kann net eidel sinn + Waart ee Moment + Kee Fichier selektionéiert + Link schécken un … + Mat oAuth2 aloggen + - D\'Server-Zerfitikat ass ofgelaf + - D\'Validitéitsdate vum Server-Zertifikat leien an der Zukunft + - D\'URL stëmmt net mam Servernumm am Zertifikat iwwereneen + Wëlls du dësem Zertifikat trotzdeem vertrauen? + Den Zertifikat konnt net gespäichert ginn Detailer Verstoppen + Ausgestallt un: + Ausgestallt vun: + Allgemengen Numm: + Organisatioun: + Organisatiounseenheet: Land: Staat: Uert: - Gültegkeet: + Gëltegkeet: Vun: - Fir: + Un: Signatur: - PNG Bild - 389 KB - 2012/05/18 12:23 + Algorithmus: + Den Zertifikat konnt net ugewise ginn. + - Keng Informatioun iwwer de Feeler + Dëst ass e Plazhaler + plazhaler.txt + PNG-Bild + 389kB + 18.05.2012 12:23 12:23:45 Béid halen Iwwerschreiwen Net eroplueden + Biller-Virschau + Dëst Bild kann net ugewise ginn + %1$s konnt net an de lokalen Dossier %2$s kopéiert ginn + Pad fir d\'Eroplueden + E Passwuert aginn + Du muss e Passwuert aginn Schécken + Link kopéieren + An d\'Tëschenoflag kopéiert + Kritesche Feeler: D\'Operatioune konnten net ausgeféiert ginn + Bei der Connectioun mam Server ass e Feeler opgetrueden. + Beim Waarden op de Server ass e Feeler opgetrueden, d\'Operatioun konnt net duerchgeféiert ginn + Beim Waarden op de Server ass e Feeler opgetrueden, d\'Operatioun konnt net duerchgeféiert ginn + D\'Operatioun konnt net ofgeschloss ginn, de Server ass net disponibel - Accounten + Du hues keng Berechtegung %s + fir dëse Fichier ëmzebenennen + fir dëse Fichier ze läschen + fir dëse Fichier ze deelen + fir dëse Fichier net méi ze deelen + fir dëse Fichier unzeleeën + fir an dësen Dossier eropzelueden + De Fichier ass net méi um Server disponibel + Konten + Kont dobäisetzen + Sécher Connectioun gëtt op eng onsécher Route ëmgeleet. + Protokoller + Historique schécken + Keng App fonnt fir d\'Protokoller ze schécken. Installéier eng Mail-App! + Protokoller vun der %1$s-Android-App + Date gi gelueden… + Authentifizéierung néideg + Falscht Passwuert + Réckelen + Hei ass näischt. Setz en Dossier dobäi! Auswielen - Server Adress + Konnt net réckelen. Kontrolléier w.e.g. ob de Fichier existéiert + Et ass net méiglech, en Dossier an en Ënnerdossier vu sech selwer ze réckelen + De Fichier existéiert schonn am Zildossier + Beim Réckele vun dësem Fichier oder Dossier ass e Feeler opgetrueden + fir dëse Fichier ze réckelen + Direkt eropgeluede Fichieren + Sécherheet + Pad fir d\'Eropluede vun de Videoen + D\'Erofluede vum %1$s-Dossier konnt net ofgeschloss ginn + %1$s huet \"%2$s\" mat dir gedeelt + Connectioun opfrëschen + Server-Adress diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 94cad43c..d0f407cc 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -77,7 +77,7 @@ Atualizar ficheiro O ficheiro foi renomeado para %1$s durante o envio. Partilhar a hiperligação - Deixar de partilhar a hiperligação + Cancelar partilha da hiperligação Sim Não ACEITAR @@ -100,7 +100,7 @@ %1$s foi enviado com sucesso Não foi possível enviar Não foi possível concluir o envio de %1$s. - Falha no carregamento, é necessário fazer novo login + Falha no envio, precisa de reiniciar a sessão A transferir... %1$d%% A transferir %2$s Transferência bem sucedida @@ -111,13 +111,13 @@ Não foi possível transferir, tem de iniciar a sessão novamente Escolha a conta Falhou a sincronização - Falhou a sincronização, necessita fazer um novo login - Não foi possível sincronizar %1$s + Falhou a sincronização, precisa de reiniciar a sessão + Não foi possível concluir a sincronização de %1$s Senha inválida para %1$s Foram encontrados conflitos Não foi possível sincronizar o ficheiro %1$d Falhou a operação de manter os ficheiros sincronizados - Não foi possível sincronizar o conteúdo de %1$d ficheiros (%2$d conflictos) + Não foi possível sincronizar o conteúdo de %1$d ficheiros (%2$d conflitos) Alguns ficheiros locais ficaram esquecidos Nao foi possivel copiar os ficheiros %1$d da pasta %2$s para Tal como na versão 1.3.16, os ficheiros que foram enviados deste dispositivo são copiados para a pasta local %1$s para prevenir perda de dados quando um ficheiro é partilhado com várias contas.\n\nDevido a esta alteração, todos os ficheiros das versões anteriores foram copiados para a pasta %2$s. No entanto, um erro impediu a conclusão deste 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 ficheiro(s) locais e remotos em %5$s que foram ligados. @@ -137,18 +137,18 @@ CÓDIGO da App Incorreto CÓDIGOS da App removido CÓDIGO da App guardado - %1$s leitor de música + %1$s reprodutor de música %1$s (a reproduzir) %1$s (a carregar) - %1$s leitura terminada - Não foi encontrado nenhum ficheiro de média - Não foi fornecida conta + %1$s reprodução terminada + Não foi encontrado nenhum ficheiro de multimédia + Não foi indicada uma conta O ficheiro não está numa conta válida Codec de multimédia não suportado Não foi possível ler o ficheiro de multimédia - Ficheiro erradamente codificado (codec) - O tempo de espera para jogar expirou - O ficheiro não pode ser reproduzido (streaming) + O ficheiro de multimédia não foi codificado corretamente + Tempo expirado enquanto tentava jogar + O ficheiro de multimédia não pôde ser transmitido O ficheiro não pode ser reproduzido com o leitor de média de origem Erro de segurança a tentar reproduzir o ficheiro %1$s Erro de input a tentar reproduzir %1$s diff --git a/res/values-sr-rSP/strings.xml b/res/values-sr-rSP/strings.xml index bee87c7b..f35d65aa 100644 --- a/res/values-sr-rSP/strings.xml +++ b/res/values-sr-rSP/strings.xml @@ -33,6 +33,7 @@ Otkaži Greška Nepoznata greška + O programu Izmeni lozinku Ukloni nalog Novi nalog @@ -62,6 +63,7 @@ Potpis: Zadrži oboje Pošalji + Kopirano u klipbord Nalozi Izaberi diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 0e41c261..08b79dd4 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -4,14 +4,14 @@ верзија %1$s Освежи налог Отпреми - Садржај из других апликација - Фајлови + садржај из других апликација + фајлове Отвори помоћу Нова фасцикла Поставке Детаљи Пошаљи - Разврстај + Разврставање Разврставање A-Z @@ -20,30 +20,30 @@ Опште - Више + Остало Налози Управљање налозима ПИБ апликације - Заштитите програм - Тренутно отпремање фотографија - Тренутно отпремај фотографије сликане камером - Тренутно отпремање видеа - Тренутно отпремај видео снимљен камером + заштитите програм + Отпремање фотографија + тренутно отпремај фотографије сликане камером + Отпремање видеа + тренутно отпремај видео снимљен камером Укључи бележење - Ово се користи за бележење проблема + користи се за бележење проблема Историјат бележења - Ово приказује сачуване записнике + приказује сачуване записнике Обриши историјат Помоћ Препоручи пријатељу Ваше мишљење Жиг Упамти локацију дељења - Памти последњу локацију отпремања дељења + памти последњу локацију отпремања дељења Пробајте %1$s на вашем телефону! Предлажем вам да пробате %1$s на вашем телефону!\nПреузмите овде: %2$s Провери сервер - Адреса сервера https://… + адреса сервера https://… Корисничко име Лозинка Нов вам је %1$s? @@ -58,16 +58,16 @@ Напусти Нема садржаја за отпремање Садржај није примљен. Нема шта да се отпреми. - %1$s није дозвољен приступ дељеном садржају + Апликацији %1$s није дозвољен приступ дељеном садржају Отпремање пре пар секунди Овде нема ничег. Отпремите нешто! Учитавам Нема фајлова у овој фасцикли. фасцикла - фасцикле + фасцикли фајл - фајлови + фајлова Тапните на фајл ради приказа додатних информација. Величина: Врста: @@ -95,14 +95,14 @@ Отпреми из… Назив фасцикле Отпремам… - %1$d%% oтпрема %2$s + %1$d%% oтпремам %2$s Отпремање је успело %1$s је успешно отпремљен Отпремање није успело Не могу да довршим отпремање %1$s Отпремање неуспешно. Поново се пријавите. Преузимам… - %1$d%% Преузимам %2$s + %1$d%% преузимам %2$s Преузимање успешно %1$s је успешно преузет Преузимање није успело @@ -128,9 +128,9 @@ Локално: %1$s Удаљено: %1$s Нема довољно простора да би се изабрани фајлови копирали у фасциклу %1$s. Желите ли да их преместите? - Унесите ПИБ апликације + Унесите ПИБ за апликацију Унесите ПИБ за апликацију - Са сваким покретањем апликације мораћете да унесете ПИБ + Приликом сваког покретања апликације мораћете да унесете ПИБ Унесите ПИБ поново Уклоните ПИБ апликације Бројеви се не поклапају diff --git a/src/com/owncloud/android/authentication/AccountUtils.java b/src/com/owncloud/android/authentication/AccountUtils.java index bd3a8e79..1e67aa67 100644 --- a/src/com/owncloud/android/authentication/AccountUtils.java +++ b/src/com/owncloud/android/authentication/AccountUtils.java @@ -24,24 +24,28 @@ import java.util.Locale; import com.owncloud.android.MainApp; import com.owncloud.android.lib.common.accounts.AccountTypeUtils; +import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; +import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OwnCloudVersion; import android.accounts.Account; import android.accounts.AccountManager; import android.content.Context; import android.content.SharedPreferences; +import android.net.Uri; import android.preference.PreferenceManager; public class AccountUtils { - public static final String WEBDAV_PATH_1_2 = "/webdav/owncloud.php"; - public static final String WEBDAV_PATH_2_0 = "/files/webdav.php"; - public static final String WEBDAV_PATH_4_0 = "/remote.php/webdav"; + + private static final String TAG = AccountUtils.class.getSimpleName(); + + public static final String WEBDAV_PATH_4_0_AND_LATER = "/remote.php/webdav"; private static final String ODAV_PATH = "/remote.php/odav"; private static final String SAML_SSO_PATH = "/remote.php/webdav"; - public static final String CARDDAV_PATH_2_0 = "/apps/contacts/carddav.php"; - public static final String CARDDAV_PATH_4_0 = "/remote/carddav.php"; public static final String STATUS_PATH = "/status.php"; + public static final int ACCOUNT_VERSION = 1; + /** * Can be used to get the currently selected ownCloud {@link Account} in the * application preferences. @@ -105,19 +109,6 @@ public class AccountUtils { } - /** - * Checks, whether or not there are any ownCloud accounts setup. - * - * @return true, if there is at least one account. - */ - public static boolean accountsAreSetup(Context context) { - AccountManager accMan = AccountManager.get(context); - Account[] accounts = accMan - .getAccountsByType(MainApp.getAccountType()); - return accounts.length > 0; - } - - public static boolean setCurrentOwnCloudAccount(Context context, String accountName) { boolean result = false; if (accountName != null) { @@ -145,8 +136,10 @@ public class AccountUtils { * according to its version and the authorization method used. * * @param version Version of ownCloud server. - * @param authTokenType Authorization token type, matching some of the AUTH_TOKEN_TYPE_* constants in {@link AccountAuthenticator}. - * @return WebDAV path for given OC version and authorization method, null if OC version is unknown. + * @param authTokenType Authorization token type, matching some of the AUTH_TOKEN_TYPE_* constants in + * {@link AccountAuthenticator}. + * @return WebDAV path for given OC version and authorization method, null if OC version + * is unknown; versions prior to ownCloud 4 are not supported anymore */ public static String getWebdavPath(OwnCloudVersion version, String authTokenType) { if (version != null) { @@ -156,15 +149,105 @@ public class AccountUtils { if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(authTokenType)) { return SAML_SSO_PATH; } - if (version.compareTo(OwnCloudVersion.owncloud_v4) >= 0) - return WEBDAV_PATH_4_0; - if (version.compareTo(OwnCloudVersion.owncloud_v3) >= 0 - || version.compareTo(OwnCloudVersion.owncloud_v2) >= 0) - return WEBDAV_PATH_2_0; - if (version.compareTo(OwnCloudVersion.owncloud_v1) >= 0) - return WEBDAV_PATH_1_2; + return WEBDAV_PATH_4_0_AND_LATER; } return null; } - + + + /** + * Update the accounts in AccountManager to meet the current version of accounts expected by the app, if needed. + * + * Introduced to handle a change in the structure of stored account names needed to allow different OC servers + * in the same domain, but not in the same path. + * + * @param context Used to access the AccountManager. + */ + public static void updateAccountVersion(Context context) { + Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(context); + AccountManager accountMgr = AccountManager.get(context); + + if ( currentAccount != null ) { + String currentAccountVersion = accountMgr.getUserData(currentAccount, Constants.KEY_OC_ACCOUNT_VERSION); + + if (currentAccountVersion == null) { + Log_OC.i(TAG, "Upgrading accounts to account version #" + ACCOUNT_VERSION); + Account[] ocAccounts = accountMgr.getAccountsByType(MainApp.getAccountType()); + String serverUrl, username, newAccountName, password; + Account newAccount; + for (Account account : ocAccounts) { + // build new account name + serverUrl = accountMgr.getUserData(account, Constants.KEY_OC_BASE_URL); + username = account.name.substring(0, account.name.lastIndexOf('@')); + newAccountName = com.owncloud.android.lib.common.accounts.AccountUtils. + buildAccountName(Uri.parse(serverUrl), username); + + // migrate to a new account, if needed + if (!newAccountName.equals(account.name)) { + Log_OC.d(TAG, "Upgrading " + account.name + " to " + newAccountName); + + // create the new account + newAccount = new Account(newAccountName, MainApp.getAccountType()); + password = accountMgr.getPassword(account); + accountMgr.addAccountExplicitly(newAccount, (password != null) ? password : "", null); + + // copy base URL + accountMgr.setUserData(newAccount, Constants.KEY_OC_BASE_URL, serverUrl); + + // copy server version + accountMgr.setUserData( + newAccount, + Constants.KEY_OC_VERSION, + accountMgr.getUserData(account, Constants.KEY_OC_VERSION) + ); + + // copy cookies + accountMgr.setUserData( + newAccount, + Constants.KEY_COOKIES, + accountMgr.getUserData(account, Constants.KEY_COOKIES) + ); + + // copy type of authentication + String isSamlStr = accountMgr.getUserData(account, Constants.KEY_SUPPORTS_SAML_WEB_SSO); + boolean isSaml = "TRUE".equals(isSamlStr); + if (isSaml) { + accountMgr.setUserData(newAccount, Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); + } + + String isOauthStr = accountMgr.getUserData(account, Constants.KEY_SUPPORTS_OAUTH2); + boolean isOAuth = "TRUE".equals(isOauthStr); + if (isOAuth) { + accountMgr.setUserData(newAccount, Constants.KEY_SUPPORTS_OAUTH2, "TRUE"); + } + /* TODO - study if it's possible to run this method in a background thread to copy the authToken + if (isOAuth || isSaml) { + accountMgr.setAuthToken(newAccount, mAuthTokenType, mAuthToken); + } + */ + + // don't forget the account saved in preferences as the current one + if (currentAccount != null && currentAccount.name.equals(account.name)) { + AccountUtils.setCurrentOwnCloudAccount(context, newAccountName); + } + + // remove the old account + accountMgr.removeAccount(account, null, null); // will assume it succeeds, not a big deal otherwise + + } else { + // servers which base URL is in the root of their domain need no change + Log_OC.d(TAG, account.name + " needs no upgrade "); + newAccount = account; + } + + // at least, upgrade account version + Log_OC.d(TAG, "Setting version " + ACCOUNT_VERSION + " to " + newAccountName); + accountMgr.setUserData(newAccount, Constants.KEY_OC_ACCOUNT_VERSION, Integer.toString(ACCOUNT_VERSION)); + + } + } + } + } + + } diff --git a/src/com/owncloud/android/authentication/AuthenticatorActivity.java b/src/com/owncloud/android/authentication/AuthenticatorActivity.java index 1e4e8b4f..713851ba 100644 --- a/src/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/src/com/owncloud/android/authentication/AuthenticatorActivity.java @@ -380,7 +380,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity findViewById(R.id.hostUrlFrame).setVisibility(View.GONE); mRefreshButton = findViewById(R.id.centeredRefreshButton); } - showRefreshButton(mServerIsChecked && !mServerIsValid && + showRefreshButton(mServerIsChecked && !mServerIsValid && mWaitingForOpId > Integer.MAX_VALUE); mServerStatusView = (TextView) findViewById(R.id.server_status_text); showServerStatus(); @@ -773,10 +773,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity mOkButton.setEnabled(false); mServerInfo = new GetServerInfoOperation.ServerInfo(); showRefreshButton(false); - + if (uri.length() != 0) { // Handle internationalized domain names uri = DisplayUtils.convertIdn(uri, true); + mServerStatusText = R.string.auth_testing_connection; mServerStatusIcon = R.drawable.progress_small; showServerStatus(); @@ -1119,13 +1120,9 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity // TODO remove, if possible private String trimUrlWebdav(String url){ - if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0.length()); - } else if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_2_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_2_0.length()); - } else if (url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_1_2)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_1_2.length()); - } + if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0_AND_LATER)){ + url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0_AND_LATER.length()); + } return (url != null ? url : ""); } @@ -1487,6 +1484,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity ); } + // include account version with the new account + mAccountMgr.setUserData( + mAccount, + Constants.KEY_OC_ACCOUNT_VERSION, + Integer.toString(AccountUtils.ACCOUNT_VERSION) + ); + /// add the new account as default in preferences, if there is none already Account defaultAccount = AccountUtils.getCurrentOwnCloudAccount(this); if (defaultAccount == null) { diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index a197e080..c32dbbce 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -168,7 +168,6 @@ public class FileDataStorageManager { return ret; } - public boolean saveFile(OCFile file) { boolean overriden = false; ContentValues cv = new ContentValues(); diff --git a/src/com/owncloud/android/db/ProviderMeta.java b/src/com/owncloud/android/db/ProviderMeta.java index 1f789d14..25e8fbd1 100644 --- a/src/com/owncloud/android/db/ProviderMeta.java +++ b/src/com/owncloud/android/db/ProviderMeta.java @@ -31,7 +31,7 @@ import com.owncloud.android.MainApp; public class ProviderMeta { public static final String DB_NAME = "filelist"; - public static final int DB_VERSION = 9; + public static final int DB_VERSION = 10; private ProviderMeta() { } diff --git a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java index b52c36d9..47f7127b 100644 --- a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java +++ b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java @@ -89,7 +89,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { Account account = AccountUtils.getCurrentOwnCloudAccount(context); if (account == null) { - Log_OC.w(TAG, "No owncloud account found for instant upload, aborting"); + Log_OC.w(TAG, "No ownCloud account found for instant upload, aborting"); return; } diff --git a/src/com/owncloud/android/operations/GetServerInfoOperation.java b/src/com/owncloud/android/operations/GetServerInfoOperation.java index 8e911000..1b4b7a9b 100644 --- a/src/com/owncloud/android/operations/GetServerInfoOperation.java +++ b/src/com/owncloud/android/operations/GetServerInfoOperation.java @@ -23,7 +23,6 @@ package com.owncloud.android.operations; import java.util.ArrayList; -import com.owncloud.android.MainApp; import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -118,12 +117,8 @@ public class GetServerInfoOperation extends RemoteOperation { if (url.endsWith("/")) { url = url.substring(0, url.length() - 1); } - if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0.length()); - } else if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_2_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_2_0.length()); - } else if (url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_1_2)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_1_2.length()); + if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0_AND_LATER)){ + url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0_AND_LATER.length()); } } return url; diff --git a/src/com/owncloud/android/providers/FileContentProvider.java b/src/com/owncloud/android/providers/FileContentProvider.java index 737c6646..a4e50cec 100644 --- a/src/com/owncloud/android/providers/FileContentProvider.java +++ b/src/com/owncloud/android/providers/FileContentProvider.java @@ -22,15 +22,23 @@ package com.owncloud.android.providers; +import java.io.File; +import java.security.Provider; import java.util.ArrayList; import java.util.HashMap; +import com.owncloud.android.MainApp; import com.owncloud.android.R; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.db.ProviderMeta; import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; +import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.utils.FileStorageUtils; +import android.accounts.Account; +import android.accounts.AccountManager; import android.content.ContentProvider; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; @@ -85,7 +93,7 @@ public class FileContentProvider extends ContentProvider { ProviderTableMeta.FILE_KEEP_IN_SYNC); mFileProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, ProviderTableMeta.FILE_ACCOUNT_OWNER); - mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG, + mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG, ProviderTableMeta.FILE_ETAG); mFileProjectionMap.put(ProviderTableMeta.FILE_SHARE_BY_LINK, ProviderTableMeta.FILE_SHARE_BY_LINK); @@ -107,7 +115,7 @@ public class FileContentProvider extends ContentProvider { private static final int SHARES = 4; private static final String TAG = FileContentProvider.class.getSimpleName(); - + // Projection for ocshares table private static HashMap mOCSharesProjectionMap; static { @@ -142,9 +150,9 @@ public class FileContentProvider extends ContentProvider { mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, ProviderTableMeta.OCSHARES_ACCOUNT_OWNER); } - + private UriMatcher mUriMatcher; - + @Override public int delete(Uri uri, String where, String[] whereArgs) { //Log_OC.d(TAG, "Deleting " + uri + " at provider " + this); @@ -160,7 +168,7 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(uri, null); return count; } - + private int delete(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) { int count = 0; switch (mUriMatcher.match(uri)) { @@ -199,7 +207,6 @@ public class FileContentProvider extends ContentProvider { if (children != null && children.moveToFirst()) { long childId; boolean isDir; - //String remotePath; while (!children.isAfterLast()) { childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID)); isDir = "DIR".equals(children.getString( @@ -208,16 +215,16 @@ public class FileContentProvider extends ContentProvider { //remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH)); if (isDir) { count += delete( - db, - ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), - null, + db, + ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), + null, null ); } else { count += delete( - db, + db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), - null, + null, null ); } @@ -281,7 +288,7 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(newUri, null); return newUri; } - + private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) { switch (mUriMatcher.match(uri)){ case ROOT_DIRECTORY: @@ -289,19 +296,19 @@ public class FileContentProvider extends ContentProvider { String remotePath = values.getAsString(ProviderTableMeta.FILE_PATH); String accountName = values.getAsString(ProviderTableMeta.FILE_ACCOUNT_OWNER); String[] projection = new String[] { - ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, - ProviderTableMeta.FILE_ACCOUNT_OWNER + ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, + ProviderTableMeta.FILE_ACCOUNT_OWNER }; - String where = ProviderTableMeta.FILE_PATH + "=? AND " + + String where = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; String[] whereArgs = new String[] {remotePath, accountName}; Cursor doubleCheck = query(db, uri, projection, where, whereArgs, null); - // ugly patch; serious refactorization is needed to reduce work in + // ugly patch; serious refactorization is needed to reduce work in // FileDataStorageManager and bring it to FileContentProvider - if (doubleCheck == null || !doubleCheck.moveToFirst()) { + if (doubleCheck == null || !doubleCheck.moveToFirst()) { long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values); if (rowId > 0) { - Uri insertedFileUri = + Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId); return insertedFileUri; } else { @@ -310,33 +317,33 @@ public class FileContentProvider extends ContentProvider { } else { // file is already inserted; race condition, let's avoid a duplicated entry Uri insertedFileUri = ContentUris.withAppendedId( - ProviderTableMeta.CONTENT_URI_FILE, + ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)) ); doubleCheck.close(); return insertedFileUri; } - + case SHARES: String path = values.getAsString(ProviderTableMeta.OCSHARES_PATH); String accountNameShare= values.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER); String[] projectionShare = new String[] { - ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, - ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER }; - String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + + String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; String[] whereArgsShare = new String[] {path, accountNameShare}; Uri insertedShareUri = null; - Cursor doubleCheckShare = + Cursor doubleCheckShare = query(db, uri, projectionShare, whereShare, whereArgsShare, null); - // ugly patch; serious refactorization is needed to reduce work in + // ugly patch; serious refactorization is needed to reduce work in // FileDataStorageManager and bring it to FileContentProvider - if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { + if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values); if (rowId >0) { - insertedShareUri = + insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId); } else { throw new SQLException("ERROR " + uri); @@ -345,7 +352,7 @@ public class FileContentProvider extends ContentProvider { } else { // file is already inserted; race condition, let's avoid a duplicated entry insertedShareUri = ContentUris.withAppendedId( - ProviderTableMeta.CONTENT_URI_SHARE, + ProviderTableMeta.CONTENT_URI_SHARE, doubleCheckShare.getLong( doubleCheckShare.getColumnIndex(ProviderTableMeta._ID) ) @@ -354,37 +361,37 @@ public class FileContentProvider extends ContentProvider { } updateFilesTableAccordingToShareInsertion(db, uri, values); return insertedShareUri; - + default: throw new IllegalArgumentException("Unknown uri id: " + uri); } - + } - + private void updateFilesTableAccordingToShareInsertion( SQLiteDatabase db, Uri uri, ContentValues shareValues ) { ContentValues fileValues = new ContentValues(); fileValues.put( - ProviderTableMeta.FILE_SHARE_BY_LINK, - ShareType.PUBLIC_LINK.getValue() == - shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)? 1 : 0 + ProviderTableMeta.FILE_SHARE_BY_LINK, + ShareType.PUBLIC_LINK.getValue() == + shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE) ? 1 : 0 ); - String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + + String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; String[] whereArgsShare = new String[] { - shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH), + shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH), shareValues.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER) }; db.update(ProviderTableMeta.FILE_TABLE_NAME, fileValues, whereShare, whereArgsShare); } - + @Override public boolean onCreate() { mDbHelper = new DataBaseHelper(getContext()); - + String authority = getContext().getResources().getString(R.string.authority); mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); mUriMatcher.addURI(authority, null, ROOT_DIRECTORY); @@ -394,20 +401,20 @@ public class FileContentProvider extends ContentProvider { mUriMatcher.addURI(authority, "dir/#", DIRECTORY); mUriMatcher.addURI(authority, "shares/", SHARES); mUriMatcher.addURI(authority, "shares/#", SHARES); - + return true; } - + @Override public Cursor query( - Uri uri, - String[] projection, - String selection, - String[] selectionArgs, + Uri uri, + String[] projection, + String selection, + String[] selectionArgs, String sortOrder ) { - + Cursor result = null; SQLiteDatabase db = mDbHelper.getReadableDatabase(); db.beginTransaction(); @@ -419,16 +426,16 @@ public class FileContentProvider extends ContentProvider { } return result; } - + private Cursor query( - SQLiteDatabase db, - Uri uri, - String[] projection, - String selection, - String[] selectionArgs, + SQLiteDatabase db, + Uri uri, + String[] projection, + String selection, + String[] selectionArgs, String sortOrder ) { - + SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder(); sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME); @@ -448,7 +455,7 @@ public class FileContentProvider extends ContentProvider { + uri.getPathSegments().get(1)); } break; - case SHARES: + case SHARES: sqlQuery.setTables(ProviderTableMeta.OCSHARES_TABLE_NAME); sqlQuery.setProjectionMap(mOCSharesProjectionMap); if (uri.getPathSegments().size() > 1) { @@ -481,7 +488,7 @@ public class FileContentProvider extends ContentProvider { @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - + int count = 0; SQLiteDatabase db = mDbHelper.getWritableDatabase(); db.beginTransaction(); @@ -494,14 +501,14 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(uri, null); return count; } - - + + private int update( - SQLiteDatabase db, - Uri uri, - ContentValues values, - String selection, + SQLiteDatabase db, + Uri uri, + ContentValues values, + String selection, String[] selectionArgs ) { switch (mUriMatcher.match(uri)) { @@ -516,14 +523,14 @@ public class FileContentProvider extends ContentProvider { ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs ); } - } + } - /* + /* private int updateFolderSize(SQLiteDatabase db, String folderId) { int count = 0; String [] whereArgs = new String[] { folderId }; - - // read current size saved for the folder + + // read current size saved for the folder long folderSize = 0; long folderParentId = -1; Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId); @@ -535,7 +542,7 @@ public class FileContentProvider extends ContentProvider { folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));; } folderCursor.close(); - + // read and sum sizes of children long childrenSize = 0; Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId); @@ -549,14 +556,14 @@ public class FileContentProvider extends ContentProvider { } } childrenCursor.close(); - + // update if needed if (folderSize != childrenSize) { Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize); ContentValues cv = new ContentValues(); cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize); count = db.update(ProviderTableMeta.FILE_TABLE_NAME, cv, folderWhere, whereArgs); - + // propagate update until root if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) { Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId); @@ -570,15 +577,15 @@ public class FileContentProvider extends ContentProvider { return count; } */ - + @Override - public ContentProviderResult[] applyBatch (ArrayList operations) + public ContentProviderResult[] applyBatch (ArrayList operations) throws OperationApplicationException { - Log_OC.d("FileContentProvider", "applying batch in provider " + this + + Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" ); ContentProviderResult[] results = new ContentProviderResult[operations.size()]; int i=0; - + SQLiteDatabase db = mDbHelper.getWritableDatabase(); db.beginTransaction(); // it's supposed that transactions can be nested try { @@ -621,7 +628,7 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER, " - + ProviderTableMeta.FILE_ETAG + " TEXT, " + + ProviderTableMeta.FILE_ETAG + " TEXT, " + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER, " + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT, " + ProviderTableMeta.FILE_PERMISSIONS + " TEXT null," @@ -629,7 +636,7 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER," //boolean + ProviderTableMeta.FILE_IS_DOWNLOADING + " INTEGER);" //boolean ); - + // Create table ocshares db.execSQL("CREATE TABLE " + ProviderTableMeta.OCSHARES_TABLE_NAME + "(" + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, " @@ -645,14 +652,14 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME + " TEXT, " + ProviderTableMeta.OCSHARES_IS_DIRECTORY + " INTEGER, " // boolean + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, " - + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log_OC.i("SQL", "Entering in onUpgrade"); - boolean upgraded = false; + boolean upgraded = false; if (oldVersion == 1 && newVersion >= 2) { Log_OC.i("SQL", "Entering in the #1 ADD in onUpgrade"); db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + @@ -665,15 +672,15 @@ public class FileContentProvider extends ContentProvider { db.beginTransaction(); try { db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + - " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + + " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER " + " DEFAULT 0"); - + // assume there are not local changes pending to upload - db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + - " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " - + System.currentTimeMillis() + + db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + + " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + + System.currentTimeMillis() + " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -684,15 +691,15 @@ public class FileContentProvider extends ContentProvider { Log_OC.i("SQL", "Entering in the #3 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + - " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + - " INTEGER " + " DEFAULT 0"); - - db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + + " INTEGER " + " DEFAULT 0"); + + db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + " SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED + " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -700,17 +707,17 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); - + if (oldVersion < 5 && newVersion >= 5) { Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_ETAG + " TEXT " + " DEFAULT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -718,7 +725,7 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 6 && newVersion >= 6) { @@ -728,7 +735,7 @@ public class FileContentProvider extends ContentProvider { db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER " + " DEFAULT 0"); - + db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT " + " DEFAULT NULL"); @@ -741,15 +748,15 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.OCSHARES_SHARE_TYPE + " INTEGER, " + ProviderTableMeta.OCSHARES_SHARE_WITH + " TEXT, " + ProviderTableMeta.OCSHARES_PATH + " TEXT, " - + ProviderTableMeta.OCSHARES_PERMISSIONS+ " INTEGER, " + + ProviderTableMeta.OCSHARES_PERMISSIONS + " INTEGER, " + ProviderTableMeta.OCSHARES_SHARED_DATE + " INTEGER, " + ProviderTableMeta.OCSHARES_EXPIRATION_DATE + " INTEGER, " + ProviderTableMeta.OCSHARES_TOKEN + " TEXT, " + ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME + " TEXT, " + ProviderTableMeta.OCSHARES_IS_DIRECTORY + " INTEGER, " // boolean + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, " - + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," - + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" ); + + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );"); upgraded = true; db.setTransactionSuccessful(); @@ -758,21 +765,21 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 7 && newVersion >= 7) { Log_OC.i("SQL", "Entering in the #7 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_PERMISSIONS + " TEXT " + " DEFAULT NULL"); - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_REMOTE_ID + " TEXT " + " DEFAULT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -780,14 +787,14 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 8 && newVersion >= 8) { Log_OC.i("SQL", "Entering in the #8 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER " + " DEFAULT 0"); @@ -818,7 +825,131 @@ public class FileContentProvider extends ContentProvider { if (!upgraded) Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); + + if (oldVersion < 10 && newVersion >= 10) { + Log_OC.i("SQL", "Entering in the #10 ADD in onUpgrade"); + updateAccountName(db); + upgraded = true; + } + if (!upgraded) + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + ", newVersion == " + newVersion); + } + } + + + /** + * Version 10 of database does not modify its scheme. It coincides with the upgrade of the ownCloud account names + * structure to include in it the path to the server instance. Updating the account names and path to local files + * in the files table is a must to keep the existing account working and the database clean. + * + * See {@link com.owncloud.android.authentication.AccountUtils#updateAccountVersion(android.content.Context)} + * + * @param db Database where table of files is included. + */ + private void updateAccountName(SQLiteDatabase db){ + Log_OC.d("SQL", "THREAD: "+ Thread.currentThread().getName()); + AccountManager ama = AccountManager.get(getContext()); + try { + // get accounts from AccountManager ; we can't be sure if accounts in it are updated or not although + // we know the update was previously done in {link @FileActivity#onCreate} because the changes through + // AccountManager are not synchronous + Account[] accounts = AccountManager.get(getContext()).getAccountsByType( + MainApp.getAccountType()); + String serverUrl, username, oldAccountName, newAccountName; + for (Account account : accounts) { + // build both old and new account name + serverUrl = ama.getUserData(account, AccountUtils.Constants.KEY_OC_BASE_URL); + username = account.name.substring(0, account.name.lastIndexOf('@')); + oldAccountName = AccountUtils.buildAccountNameOld(Uri.parse(serverUrl), username); + newAccountName = AccountUtils.buildAccountName(Uri.parse(serverUrl), username); + + // update values in database + db.beginTransaction(); + try { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, newAccountName); + int num = db.update(ProviderTableMeta.FILE_TABLE_NAME, + cv, + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", + new String[]{oldAccountName}); + + Log_OC.d("SQL", "Updated account in database: old name == " + oldAccountName + + ", new name == " + newAccountName + " (" + num + " rows updated )"); + + // update path for downloaded files + updateDownloadedFiles(db, newAccountName, oldAccountName); + + db.setTransactionSuccessful(); + + } catch (SQLException e) { + Log_OC.e(TAG, "SQL Exception upgrading account names or paths in database", e); + } finally { + db.endTransaction(); + } + } + } catch (Exception e) { + Log_OC.e(TAG, "Exception upgrading account names or paths in database", e); + } + } + + + /** + * Rename the local ownCloud folder of one account to match the a rename of the account itself. Updates the + * table of files in database so that the paths to the local files keep being the same. + * + * @param db Database where table of files is included. + * @param newAccountName New name for the target OC account. + * @param oldAccountName Old name of the target OC account. + */ + private void updateDownloadedFiles(SQLiteDatabase db, String newAccountName, + String oldAccountName) { + + String whereClause = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"; + + Cursor c = db.query(ProviderTableMeta.FILE_TABLE_NAME, + null, + whereClause, + new String[] { newAccountName }, + null, null, null); + + try { + if (c.moveToFirst()) { + // create storage path + String oldAccountPath = FileStorageUtils.getSavePath(oldAccountName); + String newAccountPath = FileStorageUtils.getSavePath(newAccountName); + + // move files + File oldAccountFolder = new File(oldAccountPath); + File newAccountFolder = new File(newAccountPath); + oldAccountFolder.renameTo(newAccountFolder); + + // update database + do { + // Update database + String oldPath = c.getString( + c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)); + OCFile file = new OCFile( + c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH))); + String newPath = FileStorageUtils.getDefaultSavePathFor(newAccountName, file); + + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, newPath); + db.update(ProviderTableMeta.FILE_TABLE_NAME, + cv, + ProviderTableMeta.FILE_STORAGE_PATH + "=?", + new String[]{oldPath}); + + Log_OC.v("SQL", "Updated path of downloaded file: old file name == " + oldPath + + ", new file name == " + newPath); + + } while (c.moveToNext()); + } + } finally { + c.close(); } + } } diff --git a/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java b/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java deleted file mode 100644 index d3ab06c1..00000000 --- a/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java +++ /dev/null @@ -1,125 +0,0 @@ -/** - * ownCloud Android client application - * - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2015 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.syncadapter; - -import java.io.FileInputStream; -import java.io.IOException; - -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.ByteArrayEntity; - -import com.owncloud.android.authentication.AccountUtils; -import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; - - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; -import android.content.ContentProviderClient; -import android.content.Context; -import android.content.SyncResult; -import android.content.res.AssetFileDescriptor; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.provider.ContactsContract; - -public class ContactSyncAdapter extends AbstractOwnCloudSyncAdapter { - private String mAddrBookUri; - - public ContactSyncAdapter(Context context, boolean autoInitialize) { - super(context, autoInitialize); - mAddrBookUri = null; - } - - @Override - public void onPerformSync(Account account, Bundle extras, String authority, - ContentProviderClient provider, SyncResult syncResult) { - setAccount(account); - setContentProviderClient(provider); - Cursor c = getLocalContacts(false); - if (c.moveToFirst()) { - do { - String lookup = c.getString(c - .getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); - String a = getAddressBookUri(); - String uri = a + lookup + ".vcf"; - FileInputStream f; - try { - f = getContactVcard(lookup); - HttpPut query = new HttpPut(uri); - byte[] b = new byte[f.available()]; - f.read(b); - query.setEntity(new ByteArrayEntity(b)); - fireRawRequest(query); - } catch (IOException e) { - e.printStackTrace(); - return; - } catch (OperationCanceledException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (AuthenticatorException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } while (c.moveToNext()); - // } while (c.moveToNext()); - } - - } - - private String getAddressBookUri() { - if (mAddrBookUri != null) - return mAddrBookUri; - - AccountManager am = getAccountManager(); - @SuppressWarnings("deprecation") - String uri = am.getUserData(getAccount(), - Constants.KEY_OC_URL).replace( - AccountUtils.WEBDAV_PATH_2_0, AccountUtils.CARDDAV_PATH_2_0); - uri += "/addressbooks/" - + getAccount().name.substring(0, - getAccount().name.lastIndexOf('@')) + "/default/"; - mAddrBookUri = uri; - return uri; - } - - private FileInputStream getContactVcard(String lookupKey) - throws IOException { - Uri uri = Uri.withAppendedPath( - ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey); - AssetFileDescriptor fd = getContext().getContentResolver() - .openAssetFileDescriptor(uri, "r"); - return fd.createInputStream(); - } - - private Cursor getLocalContacts(boolean include_hidden_contacts) { - return getContext().getContentResolver().query( - ContactsContract.Contacts.CONTENT_URI, - new String[] { ContactsContract.Contacts._ID, - ContactsContract.Contacts.LOOKUP_KEY }, - ContactsContract.Contacts.IN_VISIBLE_GROUP + " = ?", - new String[] { (include_hidden_contacts ? "0" : "1") }, - ContactsContract.Contacts._ID + " DESC"); - } - -} diff --git a/src/com/owncloud/android/syncadapter/ContactSyncService.java b/src/com/owncloud/android/syncadapter/ContactSyncService.java deleted file mode 100644 index d907bb49..00000000 --- a/src/com/owncloud/android/syncadapter/ContactSyncService.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * ownCloud Android client application - * - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2015 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.syncadapter; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -public class ContactSyncService extends Service { - private static final Object syncAdapterLock = new Object(); - private static AbstractOwnCloudSyncAdapter mSyncAdapter = null; - - @Override - public void onCreate() { - synchronized (syncAdapterLock) { - if (mSyncAdapter == null) { - mSyncAdapter = new ContactSyncAdapter(getApplicationContext(), - true); - } - } - } - - @Override - public IBinder onBind(Intent arg0) { - return mSyncAdapter.getSyncAdapterBinder(); - } - -} diff --git a/src/com/owncloud/android/ui/activity/FileActivity.java b/src/com/owncloud/android/ui/activity/FileActivity.java index a566ccdb..373603e6 100644 --- a/src/com/owncloud/android/ui/activity/FileActivity.java +++ b/src/com/owncloud/android/ui/activity/FileActivity.java @@ -61,7 +61,6 @@ import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.services.OperationsService; import com.owncloud.android.services.OperationsService.OperationsServiceBinder; -import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.LoadingDialog; import com.owncloud.android.ui.dialog.SharePasswordDialogFragment; import com.owncloud.android.utils.ErrorMessageAdapter; @@ -137,9 +136,8 @@ public class FileActivity extends SherlockFragmentActivity super.onCreate(savedInstanceState); mHandler = new Handler(); mFileOperationsHelper = new FileOperationsHelper(this); - Account account; + Account account = null; if(savedInstanceState != null) { - account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT); mFile = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE); mFromNotification = savedInstanceState.getBoolean(FileActivity.EXTRA_FROM_NOTIFICATION); mFileOperationsHelper.setOpIdWaitingFor( @@ -152,6 +150,8 @@ public class FileActivity extends SherlockFragmentActivity mFromNotification = getIntent().getBooleanExtra(FileActivity.EXTRA_FROM_NOTIFICATION, false); } + AccountUtils.updateAccountVersion(this); // best place, before any access to AccountManager or database + setAccount(account, savedInstanceState != null); mOperationsServiceConnection = new OperationsServiceConnection(); @@ -168,7 +168,16 @@ public class FileActivity extends SherlockFragmentActivity } - + @Override + protected void onNewIntent (Intent intent) { + Log_OC.v(TAG, "onNewIntent() start"); + Account current = AccountUtils.getCurrentOwnCloudAccount(this); + if (current != null && mAccount != null && !mAccount.name.equals(current.name)) { + mAccount = current; + } + Log_OC.v(TAG, "onNewIntent() stop"); + } + /** * Since ownCloud {@link Account}s can be managed from the system setting menu, * the existence of the {@link Account} associated to the instance must be checked @@ -176,46 +185,54 @@ public class FileActivity extends SherlockFragmentActivity */ @Override protected void onRestart() { + Log_OC.v(TAG, "onRestart() start"); super.onRestart(); - boolean validAccount = (mAccount != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), mAccount.name)); + boolean validAccount = (mAccount != null && AccountUtils.exists(mAccount, this)); if (!validAccount) { swapToDefaultAccount(); } + Log_OC.v(TAG, "onRestart() end"); } @Override protected void onStart() { + Log_OC.v(TAG, "onStart() start"); super.onStart(); if (mAccountWasSet) { onAccountSet(mAccountWasRestored); } + Log_OC.v(TAG, "onStart() end"); } @Override protected void onResume() { + Log_OC.v(TAG, "onResume() start"); super.onResume(); if (mOperationsServiceBinder != null) { doOnResumeAndBound(); } - + Log_OC.v(TAG, "onResume() end"); } @Override protected void onPause() { - + Log_OC.v(TAG, "onPause() start"); + if (mOperationsServiceBinder != null) { mOperationsServiceBinder.removeOperationListener(this); } super.onPause(); + Log_OC.v(TAG, "onPause() end"); } @Override protected void onDestroy() { + Log_OC.v(TAG, "onDestroy() start"); if (mOperationsServiceConnection != null) { unbindService(mOperationsServiceConnection); mOperationsServiceBinder = null; @@ -230,6 +247,7 @@ public class FileActivity extends SherlockFragmentActivity } super.onDestroy(); + Log_OC.v(TAG, "onDestroy() end"); } @@ -245,7 +263,8 @@ public class FileActivity extends SherlockFragmentActivity */ protected void setAccount(Account account, boolean savedAccount) { Account oldAccount = mAccount; - boolean validAccount = (account != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account.name)); + boolean validAccount = + (account != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account.name)); if (validAccount) { mAccount = account; mAccountWasSet = true; @@ -305,7 +324,6 @@ public class FileActivity extends SherlockFragmentActivity protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(FileActivity.EXTRA_FILE, mFile); - outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount); outState.putBoolean(FileActivity.EXTRA_FROM_NOTIFICATION, mFromNotification); outState.putLong(KEY_WAITING_FOR_OP_ID, mFileOperationsHelper.getOpIdWaitingFor()); outState.putBoolean(KEY_TRY_SHARE_AGAIN, mTryShareAgain); @@ -546,7 +564,9 @@ public class FileActivity extends SherlockFragmentActivity } } - private void onSynchronizeFolderOperationFinish(SynchronizeFolderOperation operation, RemoteOperationResult result) { + private void onSynchronizeFolderOperationFinish( + SynchronizeFolderOperation operation, RemoteOperationResult result + ) { if (!result.isSuccess() && result.getCode() != ResultCode.CANCELLED){ Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), Toast.LENGTH_LONG); diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 3ea6822b..83a49024 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -29,12 +29,9 @@ import android.accounts.AccountManager; import android.accounts.AuthenticatorException; import android.annotation.TargetApi; import android.app.AlertDialog; -import android.app.Dialog; -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; @@ -47,16 +44,12 @@ 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; @@ -97,9 +90,11 @@ import com.owncloud.android.operations.RefreshFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.syncadapter.FileSyncAdapter; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; +import com.owncloud.android.ui.dialog.UploadSourceDialogFragment; import com.owncloud.android.ui.fragment.FileDetailFragment; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.ui.fragment.OCFileListFragment; @@ -136,14 +131,10 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS"; private static final String KEY_WAITING_TO_SEND = "WAITING_TO_SEND"; - public static final int DIALOG_SHORT_WAIT = 0; - private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1; - private static final int DIALOG_CERT_NOT_SAVED = 2; - public static final String ACTION_DETAILS = "com.owncloud.android.ui.activity.action.DETAILS"; - private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; - private static final int ACTION_SELECT_MULTIPLE_FILES = 2; + public static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; + public static final int ACTION_SELECT_MULTIPLE_FILES = 2; public static final int ACTION_MOVE_FILES = 3; private static final String TAG = FileDisplayActivity.class.getSimpleName(); @@ -155,8 +146,12 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private boolean mSyncInProgress = false; - private String DIALOG_UNTRUSTED_CERT; - + private static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT"; + private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER"; + private static String DIALOG_UPLOAD_SOURCE = "DIALOG_UPLOAD_SOURCE"; + private static String DIALOG_CERT_NOT_SAVED = "DIALOG_CERT_NOT_SAVED"; + + private OCFile mWaitingToSend; @Override @@ -214,13 +209,17 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override protected void onStart() { + Log_OC.d(TAG, "onStart() start"); super.onStart(); getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId()); + Log_OC.d(TAG, "onStart() end"); } @Override protected void onDestroy() { + Log_OC.d(TAG, "onDestroy() start"); super.onDestroy(); + Log_OC.d(TAG, "onDestroy() end"); } /** @@ -478,9 +477,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { boolean retval = true; switch (item.getItemId()) { case R.id.action_create_dir: { - CreateFolderDialogFragment dialog = - CreateFolderDialogFragment.newInstance(getCurrentDir()); - dialog.show(getSupportFragmentManager(), "createdirdialog"); + CreateFolderDialogFragment dialog = CreateFolderDialogFragment.newInstance(getCurrentDir()); + dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER); break; } case R.id.action_sync_account: { @@ -488,7 +486,9 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { break; } case R.id.action_upload: { - showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE); + UploadSourceDialogFragment dialog = UploadSourceDialogFragment.newInstance(getAccount()); + dialog.show(getSupportFragmentManager(), DIALOG_UPLOAD_SOURCE); + break; } case R.id.action_settings: { @@ -608,8 +608,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { * */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) { //getClipData is only supported on api level 16+, Jelly Bean @@ -638,7 +638,11 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { }, DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS ); + + } else { + super.onActivityResult(requestCode, resultCode, data); } + } private void requestMultipleUpload(Intent data, int resultCode) { @@ -675,7 +679,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void requestSimpleUpload(Intent data, int resultCode) { - String filepath = null; + String filePath = null; String mimeType = null; Uri selectedImageUri = data.getData(); @@ -683,67 +687,60 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { try { mimeType = getContentResolver().getType(selectedImageUri); - String filemanagerstring = selectedImageUri.getPath(); - String selectedImagePath = getPath(selectedImageUri); + String fileManagerString = selectedImageUri.getPath(); + String selectedImagePath = UriUtils.getLocalPath(selectedImageUri, this); if (selectedImagePath != null) - filepath = selectedImagePath; + filePath = selectedImagePath; else - filepath = filemanagerstring; + filePath = fileManagerString; } catch (Exception e) { Log_OC.e(TAG, "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e); - e.printStackTrace(); } finally { - if (filepath == null) { + if (filePath == null) { Log_OC.e(TAG, "Couldn't resolve path to file"); - Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG); + Toast t = Toast.makeText( + this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG + ); t.show(); return; } } Intent i = new Intent(this, FileUploader.class); - i.putExtra(FileUploader.KEY_ACCOUNT, - getAccount()); - String remotepath = new String(); - for (int j = mDirectories.getCount() - 2; j >= 0; --j) { - remotepath += OCFile.PATH_SEPARATOR + mDirectories.getItem(j); - } - if (!remotepath.endsWith(OCFile.PATH_SEPARATOR)) - remotepath += OCFile.PATH_SEPARATOR; - - if (filepath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { - - Cursor cursor = MainApp.getAppContext().getContentResolver() - .query(Uri.parse(filepath), null, null, null, null, null); + i.putExtra(FileUploader.KEY_ACCOUNT, getAccount()); + OCFile currentDir = getCurrentDir(); + String remotePath = (currentDir != null) ? currentDir.getRemotePath() : OCFile.ROOT_PATH; + if (filePath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { + Cursor cursor = getContentResolver().query(Uri.parse(filePath), 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); + String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + Log_OC.v(TAG, "Display Name: " + displayName ); displayName.replace(File.separatorChar, '_'); displayName.replace(File.pathSeparatorChar, '_'); - remotepath += displayName + DisplayUtils.getComposedFileExtension(filepath); + remotePath += displayName + DisplayUtils.getComposedFileExtension(filePath); } + // and what happens in case of error?; wrong target name for the upload } finally { cursor.close(); } } else { - remotepath += new File(filepath).getName(); + remotePath += new File(filePath).getName(); } - i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath); - i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath); + 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); + i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE); startService(i); } @@ -798,9 +795,9 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override protected void onResume() { - super.onResume(); Log_OC.d(TAG, "onResume() start"); - + super.onResume(); + // refresh list of files refreshListOfFilesFragment(); @@ -847,148 +844,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } - Log_OC.d(TAG, "onPause() end"); super.onPause(); - } - - - @Override - protected Dialog onCreateDialog(int id) { - Dialog dialog = null; - AlertDialog.Builder builder; - switch (id) { - case DIALOG_SHORT_WAIT: { - ProgressDialog working_dialog = new ProgressDialog(this); - working_dialog.setMessage(getResources().getString( - R.string.wait_a_moment)); - working_dialog.setIndeterminate(true); - working_dialog.setCancelable(false); - dialog = working_dialog; - break; - } - case DIALOG_CHOOSE_UPLOAD_SOURCE: { - - - String[] allTheItems = { getString(R.string.actionbar_upload_files), - getString(R.string.actionbar_upload_from_apps) }; - - builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.actionbar_upload); - builder.setItems(allTheItems, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - if (item == 0) { - // if (!mDualPane) { - Intent action = new Intent(FileDisplayActivity.this, UploadFilesActivity.class); - action.putExtra(UploadFilesActivity.EXTRA_ACCOUNT, FileDisplayActivity.this.getAccount()); - startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES); - // } else { - // TODO create and handle new fragment - // LocalFileListFragment - // } - } else if (item == 1) { - Intent action = new Intent(Intent.ACTION_GET_CONTENT); - action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); - //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); - } - startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)), - ACTION_SELECT_CONTENT_FROM_APPS); - } - } - }); - dialog = builder.create(); - break; - } - case DIALOG_CERT_NOT_SAVED: { - builder = new AlertDialog.Builder(this); - builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved)); - builder.setCancelable(false); - builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - }; - }); - dialog = builder.create(); - break; - } - default: - dialog = null; - } - - return dialog; - } - - /** - * 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 content or null if it could not be found - */ - public String getPath(Uri uri) { - 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; + Log_OC.d(TAG, "onPause() end"); } /** @@ -1492,7 +1349,10 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override public void onFailedSavingCertificate() { - showDialog(DIALOG_CERT_NOT_SAVED); + ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance( + R.string.ssl_validator_not_saved, new String[]{}, R.string.common_ok, -1, -1 + ); + dialog.show(getSupportFragmentManager(), DIALOG_CERT_NOT_SAVED); } @Override @@ -1932,4 +1792,5 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void sortByName(boolean ascending){ getListOfFilesFragment().sortByName(ascending); } + } diff --git a/src/com/owncloud/android/ui/activity/Preferences.java b/src/com/owncloud/android/ui/activity/Preferences.java index 5585024d..70ca9dee 100644 --- a/src/com/owncloud/android/ui/activity/Preferences.java +++ b/src/com/owncloud/android/ui/activity/Preferences.java @@ -616,6 +616,7 @@ public class Preferences extends SherlockPreferenceActivity FileDisplayActivity.class ); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(i); } else { finish(); diff --git a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java index 7563ea66..fce4ddce 100644 --- a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java +++ b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java @@ -64,11 +64,13 @@ public class UploadFilesActivity extends FileActivity implements private Account mAccountOnCreation; private DialogFragment mCurrentDialog; - public static final String EXTRA_CHOSEN_FILES = UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CHOSEN_FILES"; + public static final String EXTRA_CHOSEN_FILES = + UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CHOSEN_FILES"; public static final int RESULT_OK_AND_MOVE = RESULT_FIRST_USER; - private static final String KEY_DIRECTORY_PATH = UploadFilesActivity.class.getCanonicalName() + ".KEY_DIRECTORY_PATH"; + private static final String KEY_DIRECTORY_PATH = + UploadFilesActivity.class.getCanonicalName() + ".KEY_DIRECTORY_PATH"; private static final String TAG = "UploadFilesActivity"; private static final String WAIT_DIALOG_TAG = "WAIT"; private static final String QUERY_TO_MOVE_DIALOG_TAG = "QUERY_TO_MOVE"; @@ -180,7 +182,8 @@ public class UploadFilesActivity extends FileActivity implements @Override protected void onSaveInstanceState(Bundle outState) { - // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved + // responsibility of restore is preferred in onCreate() before than in + // onRestoreInstanceState when there are Fragments involved Log_OC.d(TAG, "onSaveInstanceState() start"); super.onSaveInstanceState(outState); outState.putString(UploadFilesActivity.KEY_DIRECTORY_PATH, mCurrentDir.getAbsolutePath()); @@ -317,7 +320,7 @@ public class UploadFilesActivity extends FileActivity implements File localFile = new File(localPath); total += localFile.length(); } - return (FileStorageUtils.getUsableSpace(mAccountOnCreation.name) >= total); + return (new Boolean(FileStorageUtils.getUsableSpace(mAccountOnCreation.name) >= total)); } /** @@ -341,9 +344,12 @@ public class UploadFilesActivity extends FileActivity implements finish(); } else { - // show a dialog to query the user if wants to move the selected files to the ownCloud folder instead of copying + // show a dialog to query the user if wants to move the selected files + // to the ownCloud folder instead of copying String[] args = {getString(R.string.app_name)}; - ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance(R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1, R.string.common_no); + ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance( + R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1, R.string.common_no + ); dialog.setOnConfirmationListener(UploadFilesActivity.this); dialog.show(getSupportFragmentManager(), QUERY_TO_MOVE_DIALOG_TAG); } @@ -354,7 +360,8 @@ public class UploadFilesActivity extends FileActivity implements public void onConfirmation(String callerTag) { Log_OC.d(TAG, "Positive button in dialog was clicked; dialog tag is " + callerTag); if (callerTag.equals(QUERY_TO_MOVE_DIALOG_TAG)) { - // return the list of selected files to the caller activity (success), signaling that they should be moved to the ownCloud folder, instead of copied + // return the list of selected files to the caller activity (success), + // signaling that they should be moved to the ownCloud folder, instead of copied Intent data = new Intent(); data.putExtra(EXTRA_CHOSEN_FILES, mFileListFragment.getCheckedFilePaths()); setResult(RESULT_OK_AND_MOVE, data); diff --git a/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java b/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java index 29ed3908..48aabe5c 100644 --- a/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java +++ b/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java @@ -93,7 +93,9 @@ public class ConfirmationDialogFragment extends SherlockDialogFragment { builder.setPositiveButton(posBtn, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - mListener.onConfirmation(getTag()); + if (mListener != null) { + mListener.onConfirmation(getTag()); + } dialog.dismiss(); } }); @@ -101,7 +103,9 @@ public class ConfirmationDialogFragment extends SherlockDialogFragment { builder.setNeutralButton(neuBtn, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - mListener.onNeutral(getTag()); + if (mListener != null) { + mListener.onNeutral(getTag()); + } dialog.dismiss(); } }); @@ -110,7 +114,9 @@ public class ConfirmationDialogFragment extends SherlockDialogFragment { new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mListener.onCancel(getTag()); + if (mListener != null) { + mListener.onCancel(getTag()); + } dialog.dismiss(); } }); diff --git a/src/com/owncloud/android/ui/dialog/UploadSourceDialogFragment.java b/src/com/owncloud/android/ui/dialog/UploadSourceDialogFragment.java new file mode 100644 index 00000000..2f6eeadf --- /dev/null +++ b/src/com/owncloud/android/ui/dialog/UploadSourceDialogFragment.java @@ -0,0 +1,104 @@ +/** + * ownCloud Android client application + * + * @author David A. Velasco + * Copyright (C) 2015 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.ui.dialog; + +import android.accounts.Account; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockDialogFragment; +import com.owncloud.android.R; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.ui.activity.FileActivity; +import com.owncloud.android.ui.activity.UploadFilesActivity; + + +/** + * Dialog showing two options to allow the user upload files from the filesystem or from other apps. + * + * Assumes that its parent activity extends {@link FileActivity} + */ +public class UploadSourceDialogFragment extends SherlockDialogFragment { + + private final static String TAG = UploadSourceDialogFragment.class.getSimpleName(); + private final static String ARG_ACCOUNT = UploadSourceDialogFragment.class.getSimpleName() + ".ARG_ACCOUNT"; + + public static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; + public static final int ACTION_SELECT_MULTIPLE_FILES = 2; + + public static UploadSourceDialogFragment newInstance(Account account) { + UploadSourceDialogFragment f = new UploadSourceDialogFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_ACCOUNT, account); + f.setArguments(args); + return f; + } + + public UploadSourceDialogFragment() { + super(); + Log_OC.v(TAG, "constructor"); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + String[] allTheItems = { + getString(R.string.actionbar_upload_files), + getString(R.string.actionbar_upload_from_apps) + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(getSherlockActivity()); + builder.setTitle(R.string.actionbar_upload); + builder.setItems(allTheItems, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + if (item == 0) { + Intent action = new Intent(getSherlockActivity(), UploadFilesActivity.class); + action.putExtra( + UploadFilesActivity.EXTRA_ACCOUNT, + ((FileActivity)getSherlockActivity()).getAccount() + ); + //startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES); // this flow seems broken; + // Actionbarsherlock, maybe? + getSherlockActivity().startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES); + + } else if (item == 1) { + Intent action = new Intent(Intent.ACTION_GET_CONTENT); + action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); + //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + } + //startActivityForResult( // this flow seems broken; + // Actionbarsherlock, maybe? + getSherlockActivity().startActivityForResult( + Intent.createChooser(action, getString(R.string.upload_chooser_title)), + ACTION_SELECT_CONTENT_FROM_APPS + ); + } + } + }); + return builder.create(); + } + +} diff --git a/src/com/owncloud/android/utils/DisplayUtils.java b/src/com/owncloud/android/utils/DisplayUtils.java index 905f60b2..91dfc47c 100644 --- a/src/com/owncloud/android/utils/DisplayUtils.java +++ b/src/com/owncloud/android/utils/DisplayUtils.java @@ -257,26 +257,33 @@ public class DisplayUtils { */ @TargetApi(Build.VERSION_CODES.GINGERBREAD) public static String convertIdn(String url, boolean toASCII) { - + + String urlNoDots = url; + String dots=""; + while (urlNoDots.startsWith(".")) { + urlNoDots = url.substring(1); + dots = dots + "."; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { // Find host name after '//' or '@' int hostStart = 0; - if (url.indexOf("//") != -1) { + if (urlNoDots.indexOf("//") != -1) { hostStart = url.indexOf("//") + "//".length(); } else if (url.indexOf("@") != -1) { hostStart = url.indexOf("@") + "@".length(); } - + int hostEnd = url.substring(hostStart).indexOf("/"); // Handle URL which doesn't have a path (path is implicitly '/') - hostEnd = (hostEnd == -1 ? url.length() : hostStart + hostEnd); - - String host = url.substring(hostStart, hostEnd); + hostEnd = (hostEnd == -1 ? urlNoDots.length() : hostStart + hostEnd); + + String host = urlNoDots.substring(hostStart, hostEnd); host = (toASCII ? IDN.toASCII(host) : IDN.toUnicode(host)); - - return url.substring(0, hostStart) + host + url.substring(hostEnd); + + return dots + urlNoDots.substring(0, hostStart) + host + urlNoDots.substring(hostEnd); } else { - return url; + return dots + url; } } diff --git a/src/com/owncloud/android/utils/UriUtils.java b/src/com/owncloud/android/utils/UriUtils.java index 8070e360..2972ee55 100644 --- a/src/com/owncloud/android/utils/UriUtils.java +++ b/src/com/owncloud/android/utils/UriUtils.java @@ -19,16 +19,30 @@ package com.owncloud.android.utils; +import android.annotation.TargetApi; +import android.content.ContentUris; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; +import android.provider.OpenableColumns; + +import com.owncloud.android.MainApp; +import com.owncloud.android.lib.common.utils.Log_OC; + +import java.io.File; /** * A helper class for some Uri operations. */ public class UriUtils { - + + public static final String TAG = UriUtils.class.getSimpleName(); + public static final String URI_CONTENT_SCHEME = "content://"; @@ -102,4 +116,78 @@ public class UriUtils { public static boolean isContentDocument(Uri uri) { return uri.toString().startsWith(URI_CONTENT_SCHEME); } + + + /** + * Translates a content:// URI referred to a local file file to a path on the local filesystem + * + * @param uri The URI to resolve + * @return The path in the file system to the content or null if it could not be found (not a file) + */ + @TargetApi(Build.VERSION_CODES.KITKAT) + public static String getLocalPath(Uri uri, Context context) { + final boolean isKitKatOrLater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKatOrLater && DocumentsContract.isDocumentUri(context, 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(context, 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(context, 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(context, uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + return null; + } + }