Browse Source

Merge branch 'develop' into thumbnailOOM

masensio 10 years ago
parent
commit
7eea2ea507
27 changed files with 921 additions and 626 deletions
  1. 2 2
      oc_jb_workaround/AndroidManifest.xml
  2. 1 1
      owncloud-android-library
  3. 1 1
      res/values-en-rGB/strings.xml
  4. 2 2
      res/values-fr/strings.xml
  5. 2 0
      res/values-id/strings.xml
  6. 1 1
      res/values-ja-rJP/strings.xml
  7. 200 44
      res/values-lb/strings.xml
  8. 12 12
      res/values-pt-rPT/strings.xml
  9. 2 0
      res/values-sr-rSP/strings.xml
  10. 20 20
      res/values-sr/strings.xml
  11. 111 28
      src/com/owncloud/android/authentication/AccountUtils.java
  12. 13 9
      src/com/owncloud/android/authentication/AuthenticatorActivity.java
  13. 0 1
      src/com/owncloud/android/datamodel/FileDataStorageManager.java
  14. 1 1
      src/com/owncloud/android/db/ProviderMeta.java
  15. 1 1
      src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java
  16. 2 7
      src/com/owncloud/android/operations/GetServerInfoOperation.java
  17. 233 102
      src/com/owncloud/android/providers/FileContentProvider.java
  18. 0 125
      src/com/owncloud/android/syncadapter/ContactSyncAdapter.java
  19. 0 46
      src/com/owncloud/android/syncadapter/ContactSyncService.java
  20. 30 10
      src/com/owncloud/android/ui/activity/FileActivity.java
  21. 54 193
      src/com/owncloud/android/ui/activity/FileDisplayActivity.java
  22. 1 0
      src/com/owncloud/android/ui/activity/Preferences.java
  23. 14 7
      src/com/owncloud/android/ui/activity/UploadFilesActivity.java
  24. 9 3
      src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java
  25. 104 0
      src/com/owncloud/android/ui/dialog/UploadSourceDialogFragment.java
  26. 16 9
      src/com/owncloud/android/utils/DisplayUtils.java
  27. 89 1
      src/com/owncloud/android/utils/UriUtils.java

+ 2 - 2
oc_jb_workaround/AndroidManifest.xml

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.owncloud.android.workaround.accounts"
-    android:versionCode="0100022"
-    android:versionName="1.0.22" >
+    android:versionCode="0100023"
+    android:versionName="1.0.23" >
 
     <uses-sdk
         android:minSdkVersion="16"

+ 1 - 1
owncloud-android-library

@@ -1 +1 @@
-Subproject commit 9e761387a0b406402684571f28c36c2d6d2b6301
+Subproject commit e73e4a56d3c12d7a2f856ae65b00789b3e0cecb5

+ 1 - 1
res/values-en-rGB/strings.xml

@@ -188,7 +188,7 @@
   <string name="auth_fail_get_user_name">Your server is not returning a correct user id, please contact an administrator
 	</string>
   <string name="auth_can_not_auth_against_server">Cannot authenticate against this server</string>
-  <string name="auth_account_does_not_exist">Account does not exist on the device yet</string>
+  <string name="auth_account_does_not_exist">Account does not exist in the device yet</string>
   <string name="fd_keep_in_sync">Keep file up to date</string>
   <string name="common_rename">Rename</string>
   <string name="common_remove">Remove</string>

+ 2 - 2
res/values-fr/strings.xml

@@ -121,7 +121,7 @@ Téléchargez-le ici : %2$s</string>
   <string name="sync_fail_in_favourites_content">Le contenu de %1$d fichiers n\'a pu être synchronisé (%2$d conflits)</string>
   <string name="sync_foreign_files_forgotten_ticker">Certains fichiers locaux ont été oubliés</string>
   <string name="sync_foreign_files_forgotten_content">%1$d fichiers du dossier %2$s n\'ont pas pu être copiés dans</string>
-  <string name="sync_foreign_files_forgotten_explanation">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.
+  <string name="sync_foreign_files_forgotten_explanation">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
   <string name="prefs_category_instant_uploading">Téléversement immédiat</string>
   <string name="prefs_category_security">Sécurité</string>
   <string name="prefs_instant_video_upload_path_title">Répertoire de téléversement des vidéos</string>
-  <string name="download_folder_failed_content">Le téléchargement du dossier %1$s n\'a pas pu être achevé</string>
+  <string name="download_folder_failed_content">Le téléchargement de %1$s dossier(s) n\'a pas pu être achevé</string>
   <string name="subject_token">%1$s a partagé \"%2$s\" avec vous</string>
   <string name="auth_refresh_button">Actualiser la connexion</string>
   <string name="auth_host_address">Adresse du serveur</string>

+ 2 - 0
res/values-id/strings.xml

@@ -260,6 +260,8 @@
   <string name="share_link_file_error">Terjadi kesalahan saat mencoba membagikan berkas atau folder ini</string>
   <string name="unshare_link_file_no_exist">Tidak dapat menghapus berbagi. Mohon periksa apakah berkas ada</string>
   <string name="unshare_link_file_error">Terjadi kesalahan saat mencoba menghapus berbagi berkas dan folder ini</string>
+  <string name="share_link_password_title">Masukkan sandi</string>
+  <string name="share_link_empty_password">Anda harus memasukkan sandi</string>
   <string name="activity_chooser_send_file_title">Kirim</string>
   <string name="copy_link">Salin tautan</string>
   <string name="clipboard_text_copied">Disalin ke papan klip</string>

+ 1 - 1
res/values-ja-rJP/strings.xml

@@ -303,7 +303,7 @@
   <string name="prefs_category_instant_uploading">自動アップロード</string>
   <string name="prefs_category_security">セキュリティ</string>
   <string name="prefs_instant_video_upload_path_title">動画のアップロードパス</string>
-  <string name="download_folder_failed_content">%1$s フォルダのダウンロードが完了しませんでした</string>
+  <string name="download_folder_failed_content">%1$s フォルダのダウンロードが完了しませんでした</string>
   <string name="subject_token">%1$sがあなたと\"%2$s\"を共有しました</string>
   <string name="auth_refresh_button">再接続中</string>
   <string name="auth_host_address">サーバーアドレス</string>

+ 200 - 44
res/values-lb/strings.xml

@@ -1,96 +1,252 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
+  <string name="about_android">%1$s Android-App</string>
   <string name="about_version">Versioun %1$s</string>
+  <string name="actionbar_sync">Kont opfrëschen</string>
   <string name="actionbar_upload">Eroplueden</string>
-  <string name="actionbar_upload_files">Dateien</string>
+  <string name="actionbar_upload_from_apps">Contenu aus aneren Appen</string>
+  <string name="actionbar_upload_files">Fichieren</string>
   <string name="actionbar_open_with">Opmaachen mat</string>
+  <string name="actionbar_mkdir">Neien Dossier</string>
   <string name="actionbar_settings">Astellungen</string>
   <string name="actionbar_see_details">Detailer</string>
   <string name="actionbar_send_file">Schécken</string>
+  <string name="actionbar_sort">Zortéieren</string>
+  <string name="actionbar_sort_title">Zortéieren no</string>
+  <string-array name="actionbar_sortby">
+    <item>A-Z</item>
+    <item>Nei - Al</item>
+  </string-array>
   <!--TODO re-enable when server-side folder size calculation is available   
     	<item>Biggest - Smallest</item>-->
   <string name="prefs_category_general">Allgemeng</string>
   <string name="prefs_category_more">Méi</string>
-  <string name="prefs_accounts">Accounten</string>
-  <string name="prefs_pincode">App PIN</string>
+  <string name="prefs_accounts">Konten</string>
+  <string name="prefs_manage_accounts">Konte geréieren</string>
+  <string name="prefs_pincode">App-PIN</string>
+  <string name="prefs_pincode_summary">D\'App schützen</string>
+  <string name="prefs_instant_upload">Biller direkt eroplueden</string>
+  <string name="prefs_instant_upload_summary">Biller vum Fotoapparat direkt eroplueden</string>
+  <string name="prefs_instant_video_upload">Videoen direkt eroplueden</string>
+  <string name="prefs_instant_video_upload_summary">Biller vun der Kamera direkt eroplueden</string>
+  <string name="prefs_log_title">Protokoller aktivéieren</string>
+  <string name="prefs_log_summary">Heiduerch gi Problemer protokolléiert</string>
+  <string name="prefs_log_title_history">Protokoll-Historique</string>
+  <string name="prefs_log_summary_history">Hei ginn déi enregistréiert Protokoller ugewisen</string>
+  <string name="prefs_log_delete_history_button">Historique läschen</string>
   <string name="prefs_help">Hëllef</string>
+  <string name="prefs_recommend">Engem Frënd recommendéieren</string>
   <string name="prefs_feedback">Feedback</string>
+  <string name="prefs_imprint">Impressum</string>
+  <string name="auth_check_server">Server kontrolléieren</string>
+  <string name="auth_host_url">Server-Adress https://…</string>
   <string name="auth_username">Benotzernumm</string>
   <string name="auth_password">Passwuert</string>
-  <string name="sync_string_files">Dateien</string>
+  <string name="auth_register">Nei bei %1$s?</string>
+  <string name="sync_string_files">Fichieren</string>
   <string name="setup_btn_connect">Verbannen</string>
   <string name="uploader_btn_upload_text">Eroplueden</string>
+  <string name="uploader_btn_new_folder_text">Neien Dossier</string>
   <string name="uploader_wrn_no_account_title">Keen Account fonnt</string>
   <string name="uploader_wrn_no_account_setup_btn_text">Setup</string>
   <string name="uploader_wrn_no_account_quit_btn_text">Erausgoen</string>
+  <string name="uploader_wrn_no_content_text">Et gouf kee Contenu emfaangen. Näischt do fir eropzelueden.</string>
   <string name="uploader_info_uploading">Eroplueden</string>
-  <string name="file_list_seconds_ago">Sekonnen hir</string>
-  <string name="file_list_empty">Hei ass näischt. Lued eppes rop!</string>
+  <string name="file_list_seconds_ago">Sekonnen hier</string>
+  <string name="file_list_empty">Hei ass näischt. Lued eppes erop!</string>
   <string name="file_list_folder">Dossier</string>
   <string name="file_list_folders">Dossieren</string>
-  <string name="file_list_file">Datei</string>
-  <string name="file_list_files">Dateien</string>
+  <string name="file_list_file">Fichier</string>
+  <string name="file_list_files">Fichieren</string>
   <string name="filedetails_size">Gréisst:</string>
   <string name="filedetails_type">Typ:</string>
   <string name="filedetails_created">Erstallt:</string>
   <string name="filedetails_modified">Geännert:</string>
-  <string name="filedetails_download">Download</string>
+  <string name="filedetails_download">Eroflueden</string>
+  <string name="filedetails_sync_file">Fichier opfrëschen</string>
   <string name="action_share_file">Link deelen</string>
   <string name="common_yes">Jo</string>
   <string name="common_no">Nee</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_upload">Upload ofbriechen</string>
+  <string name="common_cancel_download">Eroflueden ofbriechen</string>
+  <string name="common_cancel_upload">Eroplueden ofbriechen</string>
   <string name="common_cancel">Ofbriechen</string>
-  <string name="common_save_exit">Späicher &amp; géi raus</string>
-  <string name="common_error">Fehler</string>
-  <string name="common_error_unknown">Et ass en onbekannte Fehler opgetrueden</string>
+  <string name="common_save_exit">Späicheren an Zoumaachen</string>
+  <string name="common_error">Feeler</string>
+  <string name="common_error_unknown">Onbekannte Feeler</string>
   <string name="about_title">Iwwer</string>
   <string name="change_password">Passwuert änneren</string>
-  <string name="delete_account">Account läschen</string>
-  <string name="create_account">Account erstellen</string>
-  <string name="uploader_info_dirname">Dossiers Numm:</string>
-  <string name="uploader_upload_in_progress_ticker">Gett eropgelueden ...</string>
-  <string name="uploader_upload_succeeded_ticker">Eroplueden färdeg</string>
-  <string name="uploader_upload_failed_ticker">Eroplueden huet net geklappt</string>
-  <string name="downloader_download_failed_ticker">Eroflueden huet net geklappt</string>
-  <string name="common_choose_account">Wiel en Account aus</string>
-  <string name="foreign_files_move">Alles bewegen</string>
-  <string name="pincode_enter_pin_code">Gëff w.e.g. däin App PIN an</string>
-  <string name="pincode_configure_your_pin">Gëff däin App PIN an</string>
-  <string name="pincode_reenter_your_pincode">Gëff däin App PIN w.e.g. nei an</string>
-  <string name="pincode_remove_your_pincode">Huel däin App PIN raus</string>
-  <string name="pincode_wrong">Ongültegen App PIN</string>
-  <string name="pincode_removed">App PIN geläscht</string>
-  <string name="pincode_stored">App PIN gespaichert</string>
-  <string name="auth_no_net_conn_title">Keng Netzwierk Verbindung</string>
-  <string name="auth_nossl_plain_ok_title">Keng geséchert Verbindung verfügbar.</string>
-  <string name="auth_connection_established">Verbindung hiergestallt</string>
-  <string name="auth_not_configured_title">Ongülteg Server Konfiguratioun</string>
-  <string name="auth_unknown_error_title">Et ass en onbekannte Fehler opgetrueden!</string>
-  <string name="auth_incorrect_path_title">Server Instanz net fonnt</string>
-  <string name="common_rename">Ëm-benennen</string>
+  <string name="delete_account">Kont läschen</string>
+  <string name="create_account">Kont uleeën</string>
+  <string name="uploader_info_dirname">Dossiersnumm:</string>
+  <string name="uploader_upload_in_progress_ticker">Lueden erop ...</string>
+  <string name="uploader_upload_succeeded_ticker">Eroplueden ofgeschloss</string>
+  <string name="uploader_upload_succeeded_content_single">%1$s gouf erfollegräich eropgelueden</string>
+  <string name="uploader_upload_failed_ticker">Eropluede feelgeschloen</string>
+  <string name="uploader_upload_failed_content_single">Eropluede vun %1$s konnt net ofgeschloss ginn</string>
+  <string name="uploader_upload_failed_credentials_error">Eropluede feelgeschloen, du muss dech nei aloggen</string>
+  <string name="downloader_download_in_progress_ticker">Lueden erof …</string>
+  <string name="downloader_download_succeeded_ticker">Eroflueden ofgeschloss</string>
+  <string name="downloader_download_succeeded_content">%1$s gouf erfollegräich erofgelueden</string>
+  <string name="downloader_download_failed_ticker">Erofluede feelgeschloen</string>
+  <string name="downloader_download_failed_content">Erofluede vun %1$s konnt net ofgeschloss ginn</string>
+  <string name="downloader_not_downloaded_yet">Nach net erofgelueden</string>
+  <string name="downloader_download_failed_credentials_error">Erofluede feelgeschloen, du muss dech nei aloggen</string>
+  <string name="common_choose_account">Kont auswielen</string>
+  <string name="sync_fail_ticker">Synchroniséierung feelgeschloen</string>
+  <string name="sync_fail_ticker_unauthorized">Synchroniséierung feelgeschloen, du muss dech nei aloggen</string>
+  <string name="sync_fail_content">Synchroniséierung vun %1$s konnt net ofgeschloss ginn</string>
+  <string name="sync_fail_content_unauthorized">Ongëltegt Passwuert fir %1$s</string>
+  <string name="sync_conflicts_in_favourites_ticker">Konflikter fonnt</string>
+  <string name="sync_foreign_files_forgotten_ticker">Verschidde lokal Fichiere goufe vergiess</string>
+  <string name="sync_current_folder_was_removed">Den Dossier %1$s existéiert net méi</string>
+  <string name="foreign_files_move">All réckelen</string>
+  <string name="foreign_files_success">All d\'Fichiere goufe geréckelt</string>
+  <string name="foreign_files_fail">Verschidde Fichiere konnten net geréckelt ginn</string>
+  <string name="foreign_files_local_text">Lokal: %1$s</string>
+  <string name="foreign_files_remote_text">Um Server: %1$s</string>
+  <string name="pincode_enter_pin_code">Gëff w.e.g. däin App-PIN an</string>
+  <string name="pincode_configure_your_pin">Gëff däin App-PIN an</string>
+  <string name="pincode_configure_your_pin_explanation">De PIN gëtt all Kéier gefrot wann d\'App gestart gëtt</string>
+  <string name="pincode_reenter_your_pincode">App-PIN nei aginn</string>
+  <string name="pincode_remove_your_pincode">App-PIN läschen</string>
+  <string name="pincode_mismatch">D\'App-PINe sinn net déi selwescht</string>
+  <string name="pincode_wrong">Ongëltegen App-PIN</string>
+  <string name="pincode_removed">App-PIN geläscht</string>
+  <string name="pincode_stored">App-PIN gespäichert</string>
+  <string name="media_notif_ticker">%1$s Musek-Programm</string>
+  <string name="media_state_playing">%1$s (spillt of)</string>
+  <string name="media_state_loading">%1$s (lued)</string>
+  <string name="media_event_done">%1$s Ofspillen ofgeschloss</string>
+  <string name="media_err_nothing_to_play">Kee Mediefichier fonnt</string>
+  <string name="media_err_no_account">Kee Kont uginn</string>
+  <string name="media_err_not_in_owncloud">Fichier net an engem gëltege Kont</string>
+  <string name="media_err_unsupported">Medie-Codec net ënnerstëtzt</string>
+  <string name="media_err_io">Mediefichier konnt net gelies ginn</string>
+  <string name="media_err_malformed">Mediefichier net korrekt encodéiert</string>
+  <string name="media_err_timeout">Zäit ofgelaf beim Versuch de Fichier ofzespillen</string>
+  <string name="media_err_invalid_progressive_playback">Mediefichier konnt net gestreamt ginn</string>
+  <string name="media_err_unknown">Mediefichier konnt net mam Standard-Medieprogramm ofgespillt ginn</string>
+  <string name="media_err_security_ex">Sécherheetsfeeler beim Ofspille vun %1$s</string>
+  <string name="media_rewind_description">Zréckspull-Knäppchen</string>
+  <string name="media_play_pause_description">Ofspill- oder Paus-Knäppchen</string>
+  <string name="auth_no_net_conn_title">Keng Netzwierkconnectioun</string>
+  <string name="auth_nossl_plain_ok_title">Keng geséchert Connectioun disponibel.</string>
+  <string name="auth_connection_established">Connectioun hiergestallt</string>
+  <string name="auth_testing_connection">Testen d\'Connectioun</string>
+  <string name="auth_not_configured_title">Ongëlteg Server-Konfiguratioun</string>
+  <string name="auth_unknown_error_title">Et ass en onbekannte Feeler opgetrueden!</string>
+  <string name="auth_unknown_host_title">Server konnt net fonnt ginn</string>
+  <string name="auth_incorrect_path_title">Server-Instanz net fonnt</string>
+  <string name="auth_timeout_title">De Server huet ze laang gebraucht fir ze äntweren</string>
+  <string name="auth_incorrect_address_title">Ongëlteg URL</string>
+  <string name="auth_ssl_general_error_title">SSL-Initialiséierung feelgeschloen</string>
+  <string name="auth_ssl_unverified_server_title">Konnt d\'Identitéit vum SSL-Server net verifizéieren</string>
+  <string name="auth_bad_oc_version_title">Onbekannte Server-Versioun</string>
+  <string name="auth_wrong_connection_title">Konnt d\'Connectioun net hierstellen</string>
+  <string name="auth_secure_connection">Sécher Connectioun hiergestallt</string>
+  <string name="auth_unauthorized">Falsche Benotzernumm oder falscht Passwuert</string>
+  <string name="auth_oauth_error">Authoriséierung net erfollegräich</string>
+  <string name="auth_oauth_error_access_denied">Accès duerch den Authoriséierungsserver verweigert</string>
+  <string name="auth_expired_basic_auth_toast">Gëff w.e.g. däin aktuellt Passwuert an</string>
+  <string name="auth_expired_saml_sso_token_toast">Deng Sessioun ass ofgelaf. Connectéier dech nei w.e.g.</string>
+  <string name="auth_unsupported_auth_method">De Server ënnerstëtzt dës Authentifizéierungsmethod net</string>
+  <string name="fd_keep_in_sync">Fichier aktuell halen</string>
+  <string name="common_rename">Ëmbenennen</string>
   <string name="common_remove">Läschen</string>
-  <string name="confirmation_remove_local">Nemmen Lokal</string>
+  <string name="confirmation_remove_alert">Wëlls du %1$s wierklech läschen?</string>
+  <string name="confirmation_remove_folder_alert">Wëlls du %1$s an de ganzen Inhalt wierklech läschen?</string>
+  <string name="confirmation_remove_local">Nemme lokal</string>
+  <string name="confirmation_remove_folder_local">Nëmme lokal Inhalter</string>
   <string name="confirmation_remove_remote">Vum Server läschen</string>
+  <string name="confirmation_remove_remote_and_local">Um Server a lokal</string>
+  <string name="remove_success_msg">Erfollegräich geläscht</string>
+  <string name="remove_fail_msg">Läsche feelgeschloen</string>
+  <string name="rename_dialog_title">Gëff en neien Numm an</string>
+  <string name="sync_file_nothing_to_do_msg">Fichiersinhalter scho synchroniséiert</string>
+  <string name="create_dir_fail_msg">Dossier konnt net ugeluecht ginn</string>
+  <string name="filename_empty">De Fichiersnumm kann net eidel sinn</string>
+  <string name="wait_a_moment">Waart ee Moment</string>
+  <string name="filedisplay_no_file_selected">Kee Fichier selektionéiert</string>
+  <string name="activity_chooser_title">Link schécken un …</string>
+  <string name="oauth_check_onoff">Mat oAuth2 aloggen</string>
+  <string name="ssl_validator_reason_cert_expired">- D\'Server-Zerfitikat ass ofgelaf</string>
+  <string name="ssl_validator_reason_cert_not_yet_valid">- D\'Validitéitsdate vum Server-Zertifikat leien an der Zukunft</string>
+  <string name="ssl_validator_reason_hostname_not_verified">- D\'URL stëmmt net mam Servernumm am Zertifikat iwwereneen</string>
+  <string name="ssl_validator_question">Wëlls du dësem Zertifikat trotzdeem vertrauen?</string>
+  <string name="ssl_validator_not_saved">Den Zertifikat konnt net gespäichert ginn</string>
   <string name="ssl_validator_btn_details_see">Detailer</string>
   <string name="ssl_validator_btn_details_hide">Verstoppen</string>
+  <string name="ssl_validator_label_subject">Ausgestallt un:</string>
+  <string name="ssl_validator_label_issuer">Ausgestallt vun:</string>
+  <string name="ssl_validator_label_CN">Allgemengen Numm:</string>
+  <string name="ssl_validator_label_O">Organisatioun:</string>
+  <string name="ssl_validator_label_OU">Organisatiounseenheet:</string>
   <string name="ssl_validator_label_C">Land:</string>
   <string name="ssl_validator_label_ST">Staat:</string>
   <string name="ssl_validator_label_L">Uert:</string>
-  <string name="ssl_validator_label_validity">Gültegkeet:</string>
+  <string name="ssl_validator_label_validity">Gëltegkeet:</string>
   <string name="ssl_validator_label_validity_from">Vun:</string>
-  <string name="ssl_validator_label_validity_to">Fir:</string>
+  <string name="ssl_validator_label_validity_to">Un:</string>
   <string name="ssl_validator_label_signature">Signatur:</string>
-  <string name="placeholder_filetype">PNG Bild</string>
-  <string name="placeholder_filesize">389 KB</string>
-  <string name="placeholder_timestamp">2012/05/18 12:23</string>
+  <string name="ssl_validator_label_signature_algorithm">Algorithmus:</string>
+  <string name="ssl_validator_null_cert">Den Zertifikat konnt net ugewise ginn.</string>
+  <string name="ssl_validator_no_info_about_error">- Keng Informatioun iwwer de Feeler</string>
+  <string name="placeholder_sentence">Dëst ass e Plazhaler</string>
+  <string name="placeholder_filename">plazhaler.txt</string>
+  <string name="placeholder_filetype">PNG-Bild</string>
+  <string name="placeholder_filesize">389kB</string>
+  <string name="placeholder_timestamp">18.05.2012 12:23</string>
   <string name="placeholder_media_time">12:23:45</string>
   <string name="conflict_keep_both">Béid halen</string>
   <string name="conflict_overwrite">Iwwerschreiwen</string>
   <string name="conflict_dont_upload">Net eroplueden</string>
+  <string name="preview_image_description">Biller-Virschau</string>
+  <string name="preview_image_error_unknown_format">Dëst Bild kann net ugewise ginn</string>
+  <string name="error__upload__local_file_not_copied">%1$s konnt net an de lokalen Dossier %2$s kopéiert ginn</string>
+  <string name="prefs_instant_upload_path_title">Pad fir d\'Eroplueden</string>
+  <string name="share_link_password_title">E Passwuert aginn</string>
+  <string name="share_link_empty_password">Du muss e Passwuert aginn</string>
   <string name="activity_chooser_send_file_title">Schécken</string>
+  <string name="copy_link">Link kopéieren</string>
+  <string name="clipboard_text_copied">An d\'Tëschenoflag kopéiert</string>
+  <string name="error_cant_bind_to_operations_service">Kritesche Feeler: D\'Operatioune konnten net ausgeféiert ginn</string>
+  <string name="network_error_socket_exception">Bei der Connectioun mam Server ass e Feeler opgetrueden.</string>
+  <string name="network_error_socket_timeout_exception">Beim Waarden op de Server ass e Feeler opgetrueden, d\'Operatioun konnt net duerchgeféiert ginn</string>
+  <string name="network_error_connect_timeout_exception">Beim Waarden op de Server ass e Feeler opgetrueden, d\'Operatioun konnt net duerchgeféiert ginn</string>
+  <string name="network_host_not_available">D\'Operatioun konnt net ofgeschloss ginn, de Server ass net disponibel</string>
   <string name="empty"></string>
-  <string name="prefs_category_accounts">Accounten</string>
+  <string name="forbidden_permissions">Du hues keng Berechtegung %s</string>
+  <string name="forbidden_permissions_rename">fir dëse Fichier ëmzebenennen</string>
+  <string name="forbidden_permissions_delete">fir dëse Fichier ze läschen</string>
+  <string name="share_link_forbidden_permissions">fir dëse Fichier ze deelen</string>
+  <string name="unshare_link_forbidden_permissions">fir dëse Fichier net méi ze deelen</string>
+  <string name="forbidden_permissions_create">fir dëse Fichier unzeleeën</string>
+  <string name="uploader_upload_forbidden_permissions">fir an dësen Dossier eropzelueden</string>
+  <string name="downloader_download_file_not_found">De Fichier ass net méi um Server disponibel</string>
+  <string name="prefs_category_accounts">Konten</string>
+  <string name="prefs_add_account">Kont dobäisetzen</string>
+  <string name="auth_redirect_non_secure_connection_title">Sécher Connectioun gëtt op eng onsécher Route ëmgeleet.</string>
+  <string name="actionbar_logger">Protokoller</string>
+  <string name="log_send_history_button">Historique schécken</string>
+  <string name="log_send_no_mail_app">Keng App fonnt fir d\'Protokoller ze schécken. Installéier eng Mail-App!</string>
+  <string name="log_send_mail_subject">Protokoller vun der %1$s-Android-App</string>
+  <string name="log_progress_dialog_text">Date gi gelueden…</string>
+  <string name="saml_authentication_required_text">Authentifizéierung néideg</string>
+  <string name="saml_authentication_wrong_pass">Falscht Passwuert</string>
+  <string name="actionbar_move">Réckelen</string>
+  <string name="file_list_empty_moving">Hei ass näischt. Setz en Dossier dobäi!</string>
   <string name="folder_picker_choose_button_text">Auswielen</string>
-  <string name="auth_host_address">Server Adress</string>
+  <string name="move_file_not_found">Konnt net réckelen. Kontrolléier w.e.g. ob de Fichier existéiert</string>
+  <string name="move_file_invalid_into_descendent">Et ass net méiglech, en Dossier an en Ënnerdossier vu sech selwer ze réckelen</string>
+  <string name="move_file_invalid_overwrite">De Fichier existéiert schonn am Zildossier</string>
+  <string name="move_file_error">Beim Réckele vun dësem Fichier oder Dossier ass e Feeler opgetrueden</string>
+  <string name="forbidden_permissions_move">fir dëse Fichier ze réckelen</string>
+  <string name="prefs_category_instant_uploading">Direkt eropgeluede Fichieren</string>
+  <string name="prefs_category_security">Sécherheet</string>
+  <string name="prefs_instant_video_upload_path_title">Pad fir d\'Eropluede vun de Videoen</string>
+  <string name="download_folder_failed_content">D\'Erofluede vum %1$s-Dossier konnt net ofgeschloss ginn</string>
+  <string name="subject_token">%1$s huet \"%2$s\" mat dir gedeelt</string>
+  <string name="auth_refresh_button">Connectioun opfrëschen</string>
+  <string name="auth_host_address">Server-Adress</string>
 </resources>

+ 12 - 12
res/values-pt-rPT/strings.xml

@@ -77,7 +77,7 @@
   <string name="filedetails_sync_file">Atualizar ficheiro</string>
   <string name="filedetails_renamed_in_upload_msg">O ficheiro foi renomeado para %1$s durante o envio.</string>
   <string name="action_share_file">Partilhar a hiperligação</string>
-  <string name="action_unshare_file">Deixar de partilhar a hiperligação</string>
+  <string name="action_unshare_file">Cancelar partilha da hiperligação</string>
   <string name="common_yes">Sim</string>
   <string name="common_no">Não</string>
   <string name="common_ok">ACEITAR</string>
@@ -100,7 +100,7 @@
   <string name="uploader_upload_succeeded_content_single">%1$s foi enviado com sucesso</string>
   <string name="uploader_upload_failed_ticker">Não foi possível enviar</string>
   <string name="uploader_upload_failed_content_single">Não foi possível concluir o envio de %1$s.</string>
-  <string name="uploader_upload_failed_credentials_error">Falha no carregamento, é necessário fazer novo login</string>
+  <string name="uploader_upload_failed_credentials_error">Falha no envio, precisa de reiniciar a sessão</string>
   <string name="downloader_download_in_progress_ticker">A transferir...</string>
   <string name="downloader_download_in_progress_content">%1$d%% A transferir %2$s</string>
   <string name="downloader_download_succeeded_ticker">Transferência bem sucedida</string>
@@ -111,13 +111,13 @@
   <string name="downloader_download_failed_credentials_error">Não foi possível transferir, tem de iniciar a sessão novamente</string>
   <string name="common_choose_account">Escolha a conta</string>
   <string name="sync_fail_ticker">Falhou a sincronização</string>
-  <string name="sync_fail_ticker_unauthorized">Falhou a sincronização, necessita fazer um novo login</string>
-  <string name="sync_fail_content">Não foi possível sincronizar %1$s</string>
+  <string name="sync_fail_ticker_unauthorized">Falhou a sincronização, precisa de reiniciar a sessão</string>
+  <string name="sync_fail_content">Não foi possível concluir a sincronização de %1$s</string>
   <string name="sync_fail_content_unauthorized">Senha inválida para %1$s</string>
   <string name="sync_conflicts_in_favourites_ticker">Foram encontrados conflitos</string>
   <string name="sync_conflicts_in_favourites_content">Não foi possível sincronizar o ficheiro %1$d</string>
   <string name="sync_fail_in_favourites_ticker">Falhou a operação de manter os ficheiros sincronizados</string>
-  <string name="sync_fail_in_favourites_content">Não foi possível sincronizar  o conteúdo de %1$d ficheiros  (%2$d conflictos)</string>
+  <string name="sync_fail_in_favourites_content">Não foi possível sincronizar  o conteúdo de %1$d ficheiros  (%2$d conflitos)</string>
   <string name="sync_foreign_files_forgotten_ticker">Alguns ficheiros locais ficaram esquecidos</string>
   <string name="sync_foreign_files_forgotten_content">Nao foi possivel copiar os ficheiros %1$d da pasta %2$s para</string>
   <string name="sync_foreign_files_forgotten_explanation">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.</string>
@@ -137,18 +137,18 @@
   <string name="pincode_wrong">CÓDIGO da App Incorreto</string>
   <string name="pincode_removed">CÓDIGOS da App removido</string>
   <string name="pincode_stored">CÓDIGO da App guardado</string>
-  <string name="media_notif_ticker">%1$s leitor de música</string>
+  <string name="media_notif_ticker">%1$s reprodutor de música</string>
   <string name="media_state_playing">%1$s (a reproduzir)</string>
   <string name="media_state_loading">%1$s (a carregar)</string>
-  <string name="media_event_done">%1$s leitura terminada</string>
-  <string name="media_err_nothing_to_play">Não foi encontrado nenhum ficheiro de média</string>
-  <string name="media_err_no_account">Não foi fornecida conta</string>
+  <string name="media_event_done">%1$s reprodução terminada</string>
+  <string name="media_err_nothing_to_play">Não foi encontrado nenhum ficheiro de multimédia</string>
+  <string name="media_err_no_account">Não foi indicada uma conta</string>
   <string name="media_err_not_in_owncloud">O ficheiro não está numa conta válida</string>
   <string name="media_err_unsupported">Codec de multimédia não suportado</string>
   <string name="media_err_io">Não foi possível ler o ficheiro de multimédia</string>
-  <string name="media_err_malformed">Ficheiro erradamente codificado (codec)</string>
-  <string name="media_err_timeout">O tempo de espera para jogar expirou</string>
-  <string name="media_err_invalid_progressive_playback">O ficheiro não pode ser reproduzido (streaming)</string>
+  <string name="media_err_malformed">O ficheiro de multimédia não foi codificado corretamente</string>
+  <string name="media_err_timeout">Tempo expirado enquanto tentava jogar</string>
+  <string name="media_err_invalid_progressive_playback">O ficheiro de multimédia não pôde ser transmitido</string>
   <string name="media_err_unknown">O ficheiro não pode ser reproduzido com o leitor de média de origem</string>
   <string name="media_err_security_ex">Erro de segurança a tentar reproduzir o ficheiro %1$s</string>
   <string name="media_err_io_ex">Erro de input a tentar reproduzir %1$s</string>

+ 2 - 0
res/values-sr-rSP/strings.xml

@@ -33,6 +33,7 @@
   <string name="common_cancel">Otkaži</string>
   <string name="common_error">Greška</string>
   <string name="common_error_unknown">Nepoznata greška</string>
+  <string name="about_title">O programu</string>
   <string name="change_password">Izmeni lozinku</string>
   <string name="delete_account">Ukloni nalog</string>
   <string name="create_account">Novi nalog</string>
@@ -62,6 +63,7 @@
   <string name="ssl_validator_label_signature">Potpis:</string>
   <string name="conflict_keep_both">Zadrži oboje</string>
   <string name="activity_chooser_send_file_title">Pošalji</string>
+  <string name="clipboard_text_copied">Kopirano u klipbord</string>
   <string name="empty"></string>
   <string name="prefs_category_accounts">Nalozi</string>
   <string name="folder_picker_choose_button_text">Izaberi</string>

+ 20 - 20
res/values-sr/strings.xml

@@ -4,14 +4,14 @@
   <string name="about_version">верзија %1$s</string>
   <string name="actionbar_sync">Освежи налог</string>
   <string name="actionbar_upload">Отпреми</string>
-  <string name="actionbar_upload_from_apps">Садржај из других апликација</string>
-  <string name="actionbar_upload_files">Фајлови</string>
+  <string name="actionbar_upload_from_apps">садржај из других апликација</string>
+  <string name="actionbar_upload_files">фајлове</string>
   <string name="actionbar_open_with">Отвори помоћу</string>
   <string name="actionbar_mkdir">Нова фасцикла</string>
   <string name="actionbar_settings">Поставке</string>
   <string name="actionbar_see_details">Детаљи</string>
   <string name="actionbar_send_file">Пошаљи</string>
-  <string name="actionbar_sort">Разврстај</string>
+  <string name="actionbar_sort">Разврставање</string>
   <string name="actionbar_sort_title">Разврставање</string>
   <string-array name="actionbar_sortby">
     <item>A-Z</item>
@@ -20,30 +20,30 @@
   <!--TODO re-enable when server-side folder size calculation is available   
     	<item>Biggest - Smallest</item>-->
   <string name="prefs_category_general">Опште</string>
-  <string name="prefs_category_more">Више</string>
+  <string name="prefs_category_more">Остало</string>
   <string name="prefs_accounts">Налози</string>
   <string name="prefs_manage_accounts">Управљање налозима</string>
   <string name="prefs_pincode">ПИБ апликације</string>
-  <string name="prefs_pincode_summary">Заштитите програм</string>
-  <string name="prefs_instant_upload">Тренутно отпремање фотографија</string>
-  <string name="prefs_instant_upload_summary">Тренутно отпремај фотографије сликане камером</string>
-  <string name="prefs_instant_video_upload">Тренутно отпремање видеа</string>
-  <string name="prefs_instant_video_upload_summary">Тренутно отпремај видео снимљен камером</string>
+  <string name="prefs_pincode_summary">заштитите програм</string>
+  <string name="prefs_instant_upload">Отпремање фотографија</string>
+  <string name="prefs_instant_upload_summary">тренутно отпремај фотографије сликане камером</string>
+  <string name="prefs_instant_video_upload">Отпремање видеа</string>
+  <string name="prefs_instant_video_upload_summary">тренутно отпремај видео снимљен камером</string>
   <string name="prefs_log_title">Укључи бележење</string>
-  <string name="prefs_log_summary">Ово се користи за бележење проблема</string>
+  <string name="prefs_log_summary">користи се за бележење проблема</string>
   <string name="prefs_log_title_history">Историјат бележења</string>
-  <string name="prefs_log_summary_history">Ово приказује сачуване записнике</string>
+  <string name="prefs_log_summary_history">приказује сачуване записнике</string>
   <string name="prefs_log_delete_history_button">Обриши историјат</string>
   <string name="prefs_help">Помоћ</string>
   <string name="prefs_recommend">Препоручи пријатељу</string>
   <string name="prefs_feedback">Ваше мишљење</string>
   <string name="prefs_imprint">Жиг</string>
   <string name="prefs_remember_last_share_location">Упамти локацију дељења</string>
-  <string name="prefs_remember_last_upload_location_summary">Памти последњу локацију отпремања дељења</string>
+  <string name="prefs_remember_last_upload_location_summary">памти последњу локацију отпремања дељења</string>
   <string name="recommend_subject">Пробајте %1$s на вашем телефону!</string>
   <string name="recommend_text">Предлажем вам да пробате %1$s на вашем телефону!\nПреузмите овде: %2$s</string>
   <string name="auth_check_server">Провери сервер</string>
-  <string name="auth_host_url">Адреса сервера https://…</string>
+  <string name="auth_host_url">адреса сервера https://…</string>
   <string name="auth_username">Корисничко име</string>
   <string name="auth_password">Лозинка</string>
   <string name="auth_register">Нов вам је %1$s?</string>
@@ -58,16 +58,16 @@
   <string name="uploader_wrn_no_account_quit_btn_text">Напусти</string>
   <string name="uploader_wrn_no_content_title">Нема садржаја за отпремање</string>
   <string name="uploader_wrn_no_content_text">Садржај није примљен. Нема шта да се отпреми.</string>
-  <string name="uploader_error_forbidden_content">%1$s није дозвољен приступ дељеном садржају</string>
+  <string name="uploader_error_forbidden_content">Апликацији %1$s није дозвољен приступ дељеном садржају</string>
   <string name="uploader_info_uploading">Отпремање</string>
   <string name="file_list_seconds_ago">пре пар секунди</string>
   <string name="file_list_empty">Овде нема ничег. Отпремите нешто!</string>
   <string name="file_list_loading">Учитавам</string>
   <string name="local_file_list_empty">Нема фајлова у овој фасцикли.</string>
   <string name="file_list_folder">фасцикла</string>
-  <string name="file_list_folders">фасцикле</string>
+  <string name="file_list_folders">фасцикли</string>
   <string name="file_list_file">фајл</string>
-  <string name="file_list_files">фајлови</string>
+  <string name="file_list_files">фајлова</string>
   <string name="filedetails_select_file">Тапните на фајл ради приказа додатних информација.</string>
   <string name="filedetails_size">Величина:</string>
   <string name="filedetails_type">Врста:</string>
@@ -95,14 +95,14 @@
   <string name="upload_chooser_title">Отпреми из…</string>
   <string name="uploader_info_dirname">Назив фасцикле</string>
   <string name="uploader_upload_in_progress_ticker">Отпремам…</string>
-  <string name="uploader_upload_in_progress_content">%1$d%% oтпрема %2$s</string>
+  <string name="uploader_upload_in_progress_content">%1$d%% oтпремам %2$s</string>
   <string name="uploader_upload_succeeded_ticker">Отпремање је успело</string>
   <string name="uploader_upload_succeeded_content_single">%1$s је успешно отпремљен</string>
   <string name="uploader_upload_failed_ticker">Отпремање није успело</string>
   <string name="uploader_upload_failed_content_single">Не могу да довршим отпремање %1$s</string>
   <string name="uploader_upload_failed_credentials_error">Отпремање неуспешно. Поново се пријавите.</string>
   <string name="downloader_download_in_progress_ticker">Преузимам…</string>
-  <string name="downloader_download_in_progress_content">%1$d%% Преузимам %2$s</string>
+  <string name="downloader_download_in_progress_content">%1$d%% преузимам %2$s</string>
   <string name="downloader_download_succeeded_ticker">Преузимање успешно</string>
   <string name="downloader_download_succeeded_content">%1$s је успешно преузет</string>
   <string name="downloader_download_failed_ticker">Преузимање није успело</string>
@@ -128,9 +128,9 @@
   <string name="foreign_files_local_text">Локално: %1$s</string>
   <string name="foreign_files_remote_text">Удаљено: %1$s</string>
   <string name="upload_query_move_foreign_files">Нема довољно простора да би се изабрани фајлови копирали у фасциклу %1$s. Желите ли да их преместите? </string>
-  <string name="pincode_enter_pin_code">Унесите ПИБ апликације</string>
+  <string name="pincode_enter_pin_code">Унесите ПИБ за апликацију</string>
   <string name="pincode_configure_your_pin">Унесите ПИБ за апликацију</string>
-  <string name="pincode_configure_your_pin_explanation">Са сваким покретањем апликације мораћете да унесете ПИБ</string>
+  <string name="pincode_configure_your_pin_explanation">Приликом сваког покретања апликације мораћете да унесете ПИБ</string>
   <string name="pincode_reenter_your_pincode">Унесите ПИБ поново</string>
   <string name="pincode_remove_your_pincode">Уклоните ПИБ апликације</string>
   <string name="pincode_mismatch">Бројеви се не поклапају</string>

+ 111 - 28
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));
+
+                }
+            }
+        }
+    }
+
+
 }

+ 13 - 9
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) {

+ 0 - 1
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();

+ 1 - 1
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() {
     }

+ 1 - 1
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;
         }
 

+ 2 - 7
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;

+ 233 - 102
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<String, String> 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<ContentProviderOperation> operations) 
+    public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> 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();
         }
+
     }
 
 }

+ 0 - 125
src/com/owncloud/android/syncadapter/ContactSyncAdapter.java

@@ -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 <http://www.gnu.org/licenses/>.
- *
- */
-
-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");
-    }
-
-}

+ 0 - 46
src/com/owncloud/android/syncadapter/ContactSyncService.java

@@ -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 <http://www.gnu.org/licenses/>.
- *
- */
-
-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();
-    }
-
-}

+ 30 - 10
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);

+ 54 - 193
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);
     }
+
 }

+ 1 - 0
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();

+ 14 - 7
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);

+ 9 - 3
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();
                         }
                     });

+ 104 - 0
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 <http://www.gnu.org/licenses/>.
+ *
+ */
+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();
+    }
+
+}

+ 16 - 9
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;
         }
     }
 

+ 89 - 1
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;
+    }
+
 }