Merge pull request #311 from tobiasKaminsky/develop
authormasensio <masensio@solidgear.es>
Fri, 14 Feb 2014 13:59:24 +0000 (14:59 +0100)
committermasensio <masensio@solidgear.es>
Fri, 14 Feb 2014 13:59:24 +0000 (14:59 +0100)
Added support for sharing files:

253 files changed:
.gitmodules
AndroidManifest.xml
SETUP.md
libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar [deleted file]
oc_framework-test-project/.classpath [deleted file]
oc_framework-test-project/.project [deleted file]
oc_framework-test-project/.settings/org.eclipse.jdt.core.prefs [deleted file]
oc_framework-test-project/AndroidManifest.xml [deleted file]
oc_framework-test-project/ic_launcher-web.png [deleted file]
oc_framework-test-project/libs/android-support-v4.jar [deleted file]
oc_framework-test-project/oc_framework-test-test/.classpath [deleted file]
oc_framework-test-project/oc_framework-test-test/.project [deleted file]
oc_framework-test-project/oc_framework-test-test/.settings/org.eclipse.jdt.core.prefs [deleted file]
oc_framework-test-project/oc_framework-test-test/AndroidManifest.xml [deleted file]
oc_framework-test-project/oc_framework-test-test/project.properties [deleted file]
oc_framework-test-project/oc_framework-test-test/res/drawable-hdpi/ic_launcher.png [deleted file]
oc_framework-test-project/oc_framework-test-test/res/drawable-ldpi/ic_launcher.png [deleted file]
oc_framework-test-project/oc_framework-test-test/res/drawable-mdpi/ic_launcher.png [deleted file]
oc_framework-test-project/oc_framework-test-test/res/drawable-xhdpi/ic_launcher.png [deleted file]
oc_framework-test-project/oc_framework-test-test/res/values/strings.xml [deleted file]
oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java [deleted file]
oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/RenameFileTest.java [deleted file]
oc_framework-test-project/project.properties [deleted file]
oc_framework-test-project/res/drawable-hdpi/ic_launcher.png [deleted file]
oc_framework-test-project/res/drawable-mdpi/ic_launcher.png [deleted file]
oc_framework-test-project/res/drawable-xhdpi/ic_launcher.png [deleted file]
oc_framework-test-project/res/drawable-xxhdpi/ic_launcher.png [deleted file]
oc_framework-test-project/res/layout/activity_test.xml [deleted file]
oc_framework-test-project/res/menu/test.xml [deleted file]
oc_framework-test-project/res/values-sw600dp/dimens.xml [deleted file]
oc_framework-test-project/res/values-sw720dp-land/dimens.xml [deleted file]
oc_framework-test-project/res/values-v11/styles.xml [deleted file]
oc_framework-test-project/res/values-v14/styles.xml [deleted file]
oc_framework-test-project/res/values/dimens.xml [deleted file]
oc_framework-test-project/res/values/strings.xml [deleted file]
oc_framework-test-project/res/values/styles.xml [deleted file]
oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java [deleted file]
oc_framework/.classpath [deleted file]
oc_framework/.project [deleted file]
oc_framework/.settings/org.eclipse.jdt.core.prefs [deleted file]
oc_framework/AndroidManifest.xml [deleted file]
oc_framework/build.xml [deleted file]
oc_framework/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar [deleted file]
oc_framework/project.properties [deleted file]
oc_framework/res/values/empty.xml [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountTypeUtils.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountUtils.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/accounts/OwnCloudAccount.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedSslSocketFactory.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedX509TrustManager.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/BearerAuthScheme.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/BearerCredentials.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/CertificateCombinedException.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/NetworkUtils.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/ProgressiveDataTransferer.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/ChunkFromFileChannelRequestEntity.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/FileRequestEntity.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OnDatatransferProgressListener.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OwnCloudClientFactory.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavClient.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavEntry.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavUtils.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/operations/OnRemoteOperationListener.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/operations/OperationCancelledException.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperation.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/operations/remote/CreateRemoteFolderOperation.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/operations/remote/RenameRemoteFileOperation.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java [deleted file]
oc_framework/src/com/owncloud/android/oc_framework/utils/OwnCloudVersion.java [deleted file]
oc_jb_workaround/AndroidManifest.xml
oc_jb_workaround/res/drawable-xhdpi/main_app_icon.png [deleted file]
oc_jb_workaround/res/drawable-xhdpi/workaround_app_icon.png [deleted file]
owncloud-android-library [new submodule]
pom.xml
project.properties
res/drawable-hdpi/sharedlink.png [new file with mode: 0644]
res/drawable-hdpi/winter_holidays_icon.png [new file with mode: 0644]
res/drawable-ldpi/winter_holidays_icon.png [new file with mode: 0644]
res/drawable-mdpi/sharedlink.png [new file with mode: 0644]
res/drawable-mdpi/winter_holidays_icon.png [new file with mode: 0644]
res/drawable-xhdpi/icon.png [new file with mode: 0644]
res/drawable-xhdpi/sharedlink.png [new file with mode: 0644]
res/layout-land/account_setup.xml
res/layout-v11/activity_row.xml [new file with mode: 0644]
res/layout/activity_row.xml [new file with mode: 0644]
res/layout/list_item.xml
res/menu/file_actions_menu.xml
res/values-ak/strings.xml [new file with mode: 0644]
res/values-ar/strings.xml
res/values-az/strings.xml [new file with mode: 0644]
res/values-be/strings.xml
res/values-bg-rBG/strings.xml
res/values-bn-rBD/strings.xml
res/values-ca/strings.xml
res/values-cs-rCZ/strings.xml
res/values-da/strings.xml
res/values-de-rCH/strings.xml
res/values-de-rDE/strings.xml
res/values-de/strings.xml
res/values-el/strings.xml
res/values-en-rGB/strings.xml
res/values-eo/strings.xml
res/values-es-rAR/strings.xml
res/values-es-rCL/strings.xml [new file with mode: 0644]
res/values-es-rMX/strings.xml
res/values-es/strings.xml
res/values-et-rEE/strings.xml
res/values-eu-rES/strings.xml [new file with mode: 0644]
res/values-eu/strings.xml
res/values-fa/strings.xml
res/values-fi-rFI/strings.xml
res/values-fr-rCA/strings.xml [new file with mode: 0644]
res/values-fr/strings.xml
res/values-gl/strings.xml
res/values-he/strings.xml
res/values-hu-rHU/strings.xml
res/values-ia/strings.xml
res/values-id/strings.xml
res/values-is/strings.xml
res/values-it/strings.xml
res/values-ja-rJP/strings.xml
res/values-ka-rGE/strings.xml
res/values-ko/strings.xml
res/values-ku-rIQ/strings.xml
res/values-lb/strings.xml
res/values-lt-rLT/strings.xml
res/values-lv/strings.xml
res/values-mk/strings.xml
res/values-ml/strings.xml [new file with mode: 0644]
res/values-mn/strings.xml [new file with mode: 0644]
res/values-ms-rMY/strings.xml
res/values-nb-rNO/strings.xml
res/values-nl/strings.xml
res/values-nn-rNO/strings.xml
res/values-pa/strings.xml
res/values-pl/strings.xml
res/values-pt-rBR/strings.xml
res/values-pt-rPT/strings.xml
res/values-ro/strings.xml
res/values-ru-rRU/strings.xml
res/values-ru/strings.xml
res/values-si-rLK/strings.xml
res/values-sk-rSK/strings.xml
res/values-sk/strings.xml
res/values-sl/strings.xml
res/values-sq/strings.xml
res/values-sr-rSP/strings.xml
res/values-sr/strings.xml
res/values-su/strings.xml [new file with mode: 0644]
res/values-sv/strings.xml
res/values-ta-rLK/strings.xml
res/values-te/strings.xml
res/values-th-rTH/strings.xml
res/values-tr/strings.xml
res/values-ug/strings.xml
res/values-uk/strings.xml
res/values-ur/strings.xml [new file with mode: 0644]
res/values-vi/strings.xml
res/values-zh-rCN/strings.xml
res/values-zh-rTW/strings.xml
res/values/setup.xml
res/values/strings.xml
setup_env.bat
setup_env.sh
src/com/owncloud/android/authentication/AccountAuthenticator.java
src/com/owncloud/android/authentication/AccountUtils.java
src/com/owncloud/android/authentication/AuthenticatorActivity.java
src/com/owncloud/android/authentication/SsoWebViewClient.java
src/com/owncloud/android/datamodel/FileDataStorageManager.java
src/com/owncloud/android/datamodel/OCFile.java
src/com/owncloud/android/db/ProviderMeta.java
src/com/owncloud/android/files/FileHandler.java [deleted file]
src/com/owncloud/android/files/FileOperationsHelper.java [new file with mode: 0644]
src/com/owncloud/android/files/OwnCloudFileObserver.java
src/com/owncloud/android/files/managers/OCNotificationManager.java
src/com/owncloud/android/files/services/FileDownloader.java
src/com/owncloud/android/files/services/FileUploader.java
src/com/owncloud/android/operations/ChunkedUploadFileOperation.java [deleted file]
src/com/owncloud/android/operations/CreateFolderOperation.java
src/com/owncloud/android/operations/CreateShareOperation.java [new file with mode: 0644]
src/com/owncloud/android/operations/DownloadFileOperation.java
src/com/owncloud/android/operations/ExistenceCheckOperation.java [deleted file]
src/com/owncloud/android/operations/GetSharesForFileOperation.java [new file with mode: 0644]
src/com/owncloud/android/operations/GetSharesOperation.java [new file with mode: 0644]
src/com/owncloud/android/operations/OAuth2GetAccessToken.java
src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java [deleted file]
src/com/owncloud/android/operations/RemoveFileOperation.java
src/com/owncloud/android/operations/RenameFileOperation.java
src/com/owncloud/android/operations/SynchronizeFileOperation.java
src/com/owncloud/android/operations/SynchronizeFolderOperation.java
src/com/owncloud/android/operations/UnshareLinkOperation.java [new file with mode: 0644]
src/com/owncloud/android/operations/UpdateOCVersionOperation.java
src/com/owncloud/android/operations/UploadFileOperation.java
src/com/owncloud/android/operations/common/SyncOperation.java [new file with mode: 0644]
src/com/owncloud/android/providers/FileContentProvider.java
src/com/owncloud/android/services/OperationsService.java [new file with mode: 0644]
src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java
src/com/owncloud/android/syncadapter/ContactSyncAdapter.java
src/com/owncloud/android/syncadapter/FileSyncAdapter.java
src/com/owncloud/android/syncadapter/FileSyncService.java
src/com/owncloud/android/ui/activity/AccountSelectActivity.java
src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java
src/com/owncloud/android/ui/activity/FileActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/GenericExplanationActivity.java
src/com/owncloud/android/ui/activity/HookActivity.java [new file with mode: 0644]
src/com/owncloud/android/ui/activity/LogHistoryActivity.java
src/com/owncloud/android/ui/activity/PinCodeActivity.java
src/com/owncloud/android/ui/activity/Preferences.java
src/com/owncloud/android/ui/activity/UploadFilesActivity.java
src/com/owncloud/android/ui/activity/Uploader.java
src/com/owncloud/android/ui/adapter/FileListListAdapter.java
src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
src/com/owncloud/android/ui/dialog/ActivityChooserDialog.java [new file with mode: 0644]
src/com/owncloud/android/ui/dialog/ChangelogDialog.java
src/com/owncloud/android/ui/dialog/ConflictsResolveDialog.java
src/com/owncloud/android/ui/dialog/EditNameDialog.java
src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java
src/com/owncloud/android/ui/dialog/SslValidatorDialog.java
src/com/owncloud/android/ui/fragment/FileDetailFragment.java
src/com/owncloud/android/ui/fragment/FileFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/com/owncloud/android/ui/preview/FileDownloadFragment.java
src/com/owncloud/android/ui/preview/PreviewImageActivity.java
src/com/owncloud/android/ui/preview/PreviewImageFragment.java
src/com/owncloud/android/ui/preview/PreviewMediaFragment.java
src/com/owncloud/android/ui/preview/PreviewVideoActivity.java
src/com/owncloud/android/utils/DisplayUtils.java
src/com/owncloud/android/utils/FileStorageUtils.java
tests/src/com/owncloud/android/test/AccountUtilsTest.java
third_party/transifex-client/.gitignore [deleted file]
third_party/transifex-client/DEVELOPMENT.rst [deleted file]
third_party/transifex-client/LICENSE [deleted file]
third_party/transifex-client/MANIFEST.in [deleted file]
third_party/transifex-client/README.rst [deleted file]
third_party/transifex-client/setup.py [deleted file]
third_party/transifex-client/tests/__init__.py [deleted file]
third_party/transifex-client/tests/test_processors.py [deleted file]
third_party/transifex-client/tests/test_project.py [deleted file]
third_party/transifex-client/tx [deleted file]
third_party/transifex-client/txclib/__init__.py [deleted file]
third_party/transifex-client/txclib/commands.py [deleted file]
third_party/transifex-client/txclib/config.py [deleted file]
third_party/transifex-client/txclib/exceptions.py [deleted file]
third_party/transifex-client/txclib/http_utils.py [deleted file]
third_party/transifex-client/txclib/log.py [deleted file]
third_party/transifex-client/txclib/parsers.py [deleted file]
third_party/transifex-client/txclib/processors.py [deleted file]
third_party/transifex-client/txclib/project.py [deleted file]
third_party/transifex-client/txclib/urls.py [deleted file]
third_party/transifex-client/txclib/utils.py [deleted file]
third_party/transifex-client/txclib/web.py [deleted file]

index b41da32..12d15b6 100644 (file)
@@ -1,3 +1,6 @@
 [submodule "actionbarsherlock"]
        path = actionbarsherlock
        url = git://github.com/JakeWharton/ActionBarSherlock.git
+[submodule "owncloud-android-library"]
+       path = owncloud-android-library
+       url = git@github.com:owncloud/android-library.git
index bdd792b..465dec8 100644 (file)
@@ -18,8 +18,8 @@
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  -->
 <manifest package="com.owncloud.android"
-    android:versionCode="105000"
-    android:versionName="1.5.0" xmlns:android="http://schemas.android.com/apk/res/android">
+    android:versionCode="105003"
+    android:versionName="1.5.3" xmlns:android="http://schemas.android.com/apk/res/android">
 
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
@@ -54,7 +54,6 @@
             >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
                 <category android:name="android.intent.category.DEFAULT" >
                 </category>
 
-                <data android:mimeType="*/*" >
+                <data android:mimeType="*/*" android:scheme="content">
                 </data>
-            </intent-filter>
+
+                <data android:mimeType="*/*" android:scheme="file">
+                </data>
+                </intent-filter>
         </activity>
         <activity
             android:name=".ui.activity.Preferences"
         <service
             android:name=".syncadapter.FileSyncService"
             android:exported="true" 
-            android:process=":sync">
+            >
             <intent-filter>
                 <action android:name="android.content.SyncAdapter" />
             </intent-filter>
             </intent-filter>
         </activity>
 
+        <service android:name=".services.OperationsService" />
         <service android:name=".files.services.FileDownloader" />
         <service android:name=".files.services.FileUploader" />
         <service android:name=".media.MediaService" />
index 6470157..12db83d 100644 (file)
--- a/SETUP.md
+++ b/SETUP.md
@@ -25,15 +25,19 @@ NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in
 
 ### 3. Building with console/maven:
 
-NOTE: You must have mvn in your environment path
+NOTE: You must have mvn (version >= 3.1.1) in your environment path. Current Android 'platforms-tools' need to be installed.
 
-* Download/install Android plugin for Maven, then build ownCloud with mvn:
-* "cd .."
-* "git clone https://github.com/mosabua/maven-android-sdk-deployer.git"
-* "cd maven-android-sdk-deployer"
-* "mvn -pl com.simpligility.android.sdk-deployer:android-17 -am install"
-* "cd ../android"
-* Now you can create APK using "mvn package"
+Download/install Android plugin for Maven, install owncloud-android-library, then build ownCloud with mvn:
+
+* cd ..
+* git clone https://github.com/mosabua/maven-android-sdk-deployer.git
+* cd maven-android-sdk-deployer
+* mvn -pl com.simpligility.android.sdk-deployer:android-19 -am install
+* cd ../android/owncloud-android-library
+* mvn install
+* cd ..
+
+Now you can create ownCloud APK using "mvn package"
 
 ### 4. Building with Eclipse:
 
@@ -44,15 +48,15 @@ NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in
 * Clean project and compile.
 * If any error appear, check the project properties; in the 'Android' section, API Level should be greater or equal than 14.
 * Make sure android/actionbarsherlock/library/bin/library.jar was created.
-* Create a new "Android Project from Existing Code". Choose android/oc_framework/library as root.
+* Create a new "Android Project from Existing Code". Choose android/owncloud-android-library as root.
 * Clean project and compile.
 * If any error appear, check the project properties; in the 'Android' section, API Level should be 19 or greater.
-* Make sure android/oc_framework/bin/classes.jar was created.  
+* Make sure android/owncloud-android-library/bin/classes.jar was created.  
 * Import ownCloud Android project.
 * Clean project and compile.
-* If any error appears, check the project properties; in the 'Android' section:
+* If any error appears, check the project properties of owncloud-android project; in the 'Android' section:
   - API Level should be 19 or greater.
-  - Two library projects should appear referred in the bottom square: actionbarsherlock/library and oc_framework. Add them if needed. 
+  - Two library projects should appear referred in the bottom square: actionbarsherlock/library and owncloud-android-library. Add them if needed. 
 * After those actions you should be good to go. HAVE FUN!
 
 NOTE: Even though API level is set to 19, APK also runs on older devices because in AndroidManifest.xml minSdkVersion is set to 8.
@@ -68,6 +72,16 @@ NOTE: You must sign the [Contributor Agreement][1] before your changes can be ac
 * Again, click "Edit" and set "compare:develop"
 * Enter description and send pull request.
 
+### 6. Create another pull request:
+
+To make sure your new pull request does not contain commits which are already contained in previous PRs, create a new branch which is a clone of upstream/develop.
+
+* git fetch upstream
+* git checkout -b my_new_develop_branch upstream/develop
+* If you want to rename that branch later: "git checkout -b my_new_develop_branch_with_new_name"
+* Push branch to server: "git push -u origin name_of_local_develop_branch"
+* Use Github to issue PR
+
 
 [0]: https://github.com/owncloud/android/blob/master/CONTRIBUTING.md
 [1]: http://owncloud.org/about/contributor-agreement/
diff --git a/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar b/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar
deleted file mode 100755 (executable)
index 2dd374f..0000000
Binary files a/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar and /dev/null differ
diff --git a/oc_framework-test-project/.classpath b/oc_framework-test-project/.classpath
deleted file mode 100644 (file)
index 394360f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
-       <classpathentry exported="true" kind="lib" path="/oc_framework/bin/oc_framework.jar" sourcepath="/oc_framework"/>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="gen"/>
-       <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/oc_framework-test-project/.project b/oc_framework-test-project/.project
deleted file mode 100644 (file)
index 8c7df64..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-       <name>oc_framework-test-project</name>
-       <comment></comment>
-       <projects>
-       </projects>
-       <buildSpec>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.jdt.core.javabuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-       </buildSpec>
-       <natures>
-               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
-               <nature>org.eclipse.jdt.core.javanature</nature>
-       </natures>
-</projectDescription>
diff --git a/oc_framework-test-project/.settings/org.eclipse.jdt.core.prefs b/oc_framework-test-project/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644 (file)
index b080d2d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.source=1.6
diff --git a/oc_framework-test-project/AndroidManifest.xml b/oc_framework-test-project/AndroidManifest.xml
deleted file mode 100644 (file)
index c913bf0..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.owncloud.android.oc_framework_test_project"
-    android:versionCode="1"
-    android:versionName="1.0" >
-    
-    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
-    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
-    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
-    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
-    <uses-permission android:name="android.permission.INTERNET"/>
-        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    
-    <uses-sdk
-        android:minSdkVersion="8"
-        android:targetSdkVersion="19" />
-
-    <application
-        android:allowBackup="true"
-        android:icon="@drawable/ic_launcher"
-        android:label="@string/app_name"
-        android:theme="@style/AppTheme" >
-        <activity
-            android:name="com.owncloud.android.oc_framework_test_project.TestActivity"
-            android:label="@string/app_name" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-
-</manifest>
diff --git a/oc_framework-test-project/ic_launcher-web.png b/oc_framework-test-project/ic_launcher-web.png
deleted file mode 100644 (file)
index a18cbb4..0000000
Binary files a/oc_framework-test-project/ic_launcher-web.png and /dev/null differ
diff --git a/oc_framework-test-project/libs/android-support-v4.jar b/oc_framework-test-project/libs/android-support-v4.jar
deleted file mode 100644 (file)
index feaf44f..0000000
Binary files a/oc_framework-test-project/libs/android-support-v4.jar and /dev/null differ
diff --git a/oc_framework-test-project/oc_framework-test-test/.classpath b/oc_framework-test-project/oc_framework-test-test/.classpath
deleted file mode 100644 (file)
index 6c54c1c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/oc_framework-test-project"/>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="gen"/>
-       <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/oc_framework-test-project/oc_framework-test-test/.project b/oc_framework-test-project/oc_framework-test-test/.project
deleted file mode 100644 (file)
index c490827..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-       <name>oc_framework-test</name>
-       <comment></comment>
-       <projects>
-               <project>oc_framework-test-project</project>
-       </projects>
-       <buildSpec>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.jdt.core.javabuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-       </buildSpec>
-       <natures>
-               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
-               <nature>org.eclipse.jdt.core.javanature</nature>
-       </natures>
-</projectDescription>
diff --git a/oc_framework-test-project/oc_framework-test-test/.settings/org.eclipse.jdt.core.prefs b/oc_framework-test-project/oc_framework-test-test/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644 (file)
index b080d2d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.source=1.6
diff --git a/oc_framework-test-project/oc_framework-test-test/AndroidManifest.xml b/oc_framework-test-project/oc_framework-test-test/AndroidManifest.xml
deleted file mode 100644 (file)
index 294f271..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.owncloud.android.oc_framework_test_project.test"
-    android:versionCode="1"
-    android:versionName="1.0" >
-
-    <uses-sdk android:minSdkVersion="8" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation
-        android:name="android.test.InstrumentationTestRunner"
-        android:label="Tests for com.owncloud.android.oc_framework_test_project"
-        android:targetPackage="com.owncloud.android.oc_framework_test_project" />
-
-</manifest>
\ No newline at end of file
diff --git a/oc_framework-test-project/oc_framework-test-test/project.properties b/oc_framework-test-project/oc_framework-test-test/project.properties
deleted file mode 100644 (file)
index 4ab1256..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-19
diff --git a/oc_framework-test-project/oc_framework-test-test/res/drawable-hdpi/ic_launcher.png b/oc_framework-test-project/oc_framework-test-test/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644 (file)
index 96a442e..0000000
Binary files a/oc_framework-test-project/oc_framework-test-test/res/drawable-hdpi/ic_launcher.png and /dev/null differ
diff --git a/oc_framework-test-project/oc_framework-test-test/res/drawable-ldpi/ic_launcher.png b/oc_framework-test-project/oc_framework-test-test/res/drawable-ldpi/ic_launcher.png
deleted file mode 100644 (file)
index 9923872..0000000
Binary files a/oc_framework-test-project/oc_framework-test-test/res/drawable-ldpi/ic_launcher.png and /dev/null differ
diff --git a/oc_framework-test-project/oc_framework-test-test/res/drawable-mdpi/ic_launcher.png b/oc_framework-test-project/oc_framework-test-test/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644 (file)
index 359047d..0000000
Binary files a/oc_framework-test-project/oc_framework-test-test/res/drawable-mdpi/ic_launcher.png and /dev/null differ
diff --git a/oc_framework-test-project/oc_framework-test-test/res/drawable-xhdpi/ic_launcher.png b/oc_framework-test-project/oc_framework-test-test/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644 (file)
index 71c6d76..0000000
Binary files a/oc_framework-test-project/oc_framework-test-test/res/drawable-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/oc_framework-test-project/oc_framework-test-test/res/values/strings.xml b/oc_framework-test-project/oc_framework-test-test/res/values/strings.xml
deleted file mode 100644 (file)
index 657f31d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <string name="app_name">Oc_framework-testTest</string>
-
-</resources>
diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java
deleted file mode 100644 (file)
index 8414502..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.owncloud.android.oc_framework_test_project.test;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.oc_framework_test_project.TestActivity;
-
-import android.test.ActivityInstrumentationTestCase2;
-
-/**
- * Class to test Create Folder Operation
- * @author masensio
- *
- */
-public class CreateFolderTest extends ActivityInstrumentationTestCase2<TestActivity> {
-
-       private TestActivity mActivity;
-       private String mCurrentDate;
-       
-       public CreateFolderTest() {
-           super(TestActivity.class);
-          
-               SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
-               mCurrentDate = sdf.format(new Date());
-       }
-       
-       @Override
-         protected void setUp() throws Exception {
-           super.setUp();
-           setActivityInitialTouchMode(false);
-           mActivity = getActivity();
-       }
-       
-       /**
-        * Test Create Folder
-        */
-       public void testCreateFolder() {
-
-               String remotePath = "/testCreateFolder" + mCurrentDate;
-               boolean createFullPath = true;
-               
-               RemoteOperationResult result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.isSuccess() || result.getCode() == ResultCode.TIMEOUT);
-               
-               // Create Subfolder
-               remotePath = "/testCreateFolder" + mCurrentDate + "/" + "testCreateFolder" + mCurrentDate;
-               createFullPath = true;
-               
-               result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.isSuccess() || result.getCode() == ResultCode.TIMEOUT);
-       }
-       
-       
-       /**
-        * Test to Create Folder with special characters: /  \  < >  :  "  |  ?  *
-        */
-       public void testCreateFolderSpecialCharacters() {               
-               boolean createFullPath = true;
-               
-               String remotePath = "/testSpecialCharacters_\\" + mCurrentDate;
-               RemoteOperationResult result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               remotePath = "/testSpecialCharacters_<" + mCurrentDate;         
-               result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               remotePath = "/testSpecialCharacters_>" + mCurrentDate;         
-               result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               remotePath = "/testSpecialCharacters_:" + mCurrentDate;         
-               result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               remotePath = "/testSpecialCharacters_\"" + mCurrentDate;                
-               result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               remotePath = "/testSpecialCharacters_|" + mCurrentDate;         
-               result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               remotePath = "/testSpecialCharacters_?" + mCurrentDate;         
-               result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               remotePath = "/testSpecialCharacters_*" + mCurrentDate;         
-               result =  mActivity.createFolder(remotePath, createFullPath);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-       }
-
-
-}
diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/RenameFileTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/RenameFileTest.java
deleted file mode 100644 (file)
index fe30550..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-package com.owncloud.android.oc_framework_test_project.test;
-
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.oc_framework_test_project.TestActivity;
-
-import android.test.ActivityInstrumentationTestCase2;
-
-public class RenameFileTest extends ActivityInstrumentationTestCase2<TestActivity> {
-
-       /* Folder data to rename. This folder must exist on the account */
-       private final String mOldFolderName = "folderToRename";
-       private final String mOldFolderPath = "/folderToRename";
-       private final String mNewFolderName = "renamedFolder"; 
-       private final String mNewFolderPath = "/renamedFolder";
-       
-       /* File data to rename. This file must exist on the account */
-       private final String mOldFileName = "fileToRename.png";
-       private final String mOldFilePath = "/fileToRename.png";
-       private final String mNewFileName = "renamedFile";
-       private final String mFileExtension = ".png";
-       private final String mNewFilePath ="/renamedFile.png";
-       
-       
-       private TestActivity mActivity;
-       
-       public RenameFileTest() {
-           super(TestActivity.class);
-          
-       }
-       
-       @Override
-         protected void setUp() throws Exception {
-           super.setUp();
-           setActivityInitialTouchMode(false);
-           mActivity = getActivity();
-       }
-       
-       /**
-        * Test Rename Folder
-        */
-       public void testRenameFolder() {
-
-               RemoteOperationResult result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName, true);
-               assertTrue(result.isSuccess());
-       }
-       
-       /**
-        * Test Rename Folder with forbidden characters : \  < >  :  "  |  ?  *
-        */
-       public void testRenameFolderForbiddenChars() {
-               
-               RemoteOperationResult result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName + "\\", true);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName + "<", true);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName + ">", true);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName + ":", true);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName + "\"", true);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName + "|", true);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName + "?", true);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFolderName, mOldFolderPath, 
-                               mNewFolderName + "*", true);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-       }
-       
-       /**
-        * Test Rename File
-        */
-       public void testRenameFile() {
-               RemoteOperationResult result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + mFileExtension, false);
-               assertTrue(result.isSuccess());
-       }
-       
-       
-       /**
-        * Test Rename Folder with forbidden characters: \  < >  :  "  |  ?  *
-        */
-       public void testRenameFileForbiddenChars() {            
-               RemoteOperationResult result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + "\\" + mFileExtension, false);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + "<" + mFileExtension, false);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + ">" + mFileExtension, false);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + ":" + mFileExtension, false);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + "\"" + mFileExtension, false);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + "|" + mFileExtension, false);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + "?" + mFileExtension, false);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-               result = mActivity.renameFile(mOldFileName, mOldFilePath, 
-                               mNewFileName + "*" + mFileExtension, false);
-               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
-               
-       }
-       
-       
-       /**
-        * Restore initial conditions
-        */
-       public void testRestoreInitialConditions() {
-               RemoteOperationResult result = mActivity.renameFile(mNewFolderName, mNewFolderPath, mOldFolderName, true);
-               assertTrue(result.isSuccess());
-               
-               result = mActivity.renameFile(mNewFileName + mFileExtension, mNewFilePath, mOldFileName, false);
-               assertTrue(result.isSuccess());
-       }
-       
-}
diff --git a/oc_framework-test-project/project.properties b/oc_framework-test-project/project.properties
deleted file mode 100644 (file)
index 153d36b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-19
-android.library.reference.1=../oc_framework
diff --git a/oc_framework-test-project/res/drawable-hdpi/ic_launcher.png b/oc_framework-test-project/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644 (file)
index 288b665..0000000
Binary files a/oc_framework-test-project/res/drawable-hdpi/ic_launcher.png and /dev/null differ
diff --git a/oc_framework-test-project/res/drawable-mdpi/ic_launcher.png b/oc_framework-test-project/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644 (file)
index 6ae570b..0000000
Binary files a/oc_framework-test-project/res/drawable-mdpi/ic_launcher.png and /dev/null differ
diff --git a/oc_framework-test-project/res/drawable-xhdpi/ic_launcher.png b/oc_framework-test-project/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644 (file)
index d4fb7cd..0000000
Binary files a/oc_framework-test-project/res/drawable-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/oc_framework-test-project/res/drawable-xxhdpi/ic_launcher.png b/oc_framework-test-project/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100644 (file)
index 85a6081..0000000
Binary files a/oc_framework-test-project/res/drawable-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/oc_framework-test-project/res/layout/activity_test.xml b/oc_framework-test-project/res/layout/activity_test.xml
deleted file mode 100644 (file)
index 42c4fbd..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:paddingBottom="@dimen/activity_vertical_margin"
-    android:paddingLeft="@dimen/activity_horizontal_margin"
-    android:paddingRight="@dimen/activity_horizontal_margin"
-    android:paddingTop="@dimen/activity_vertical_margin"
-    tools:context=".TestActivity" >
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/hello_world" />
-
-</RelativeLayout>
diff --git a/oc_framework-test-project/res/menu/test.xml b/oc_framework-test-project/res/menu/test.xml
deleted file mode 100644 (file)
index c002028..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <item
-        android:id="@+id/action_settings"
-        android:orderInCategory="100"
-        android:showAsAction="never"
-        android:title="@string/action_settings"/>
-
-</menu>
diff --git a/oc_framework-test-project/res/values-sw600dp/dimens.xml b/oc_framework-test-project/res/values-sw600dp/dimens.xml
deleted file mode 100644 (file)
index 44f01db..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<resources>
-
-    <!--
-         Customize dimensions originally defined in res/values/dimens.xml (such as
-         screen margins) for sw600dp devices (e.g. 7" tablets) here.
-    -->
-
-</resources>
diff --git a/oc_framework-test-project/res/values-sw720dp-land/dimens.xml b/oc_framework-test-project/res/values-sw720dp-land/dimens.xml
deleted file mode 100644 (file)
index 61e3fa8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<resources>
-
-    <!--
-         Customize dimensions originally defined in res/values/dimens.xml (such as
-         screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
-    -->
-    <dimen name="activity_horizontal_margin">128dp</dimen>
-
-</resources>
diff --git a/oc_framework-test-project/res/values-v11/styles.xml b/oc_framework-test-project/res/values-v11/styles.xml
deleted file mode 100644 (file)
index 3c02242..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<resources>
-
-    <!--
-        Base application theme for API 11+. This theme completely replaces
-        AppBaseTheme from res/values/styles.xml on API 11+ devices.
-    -->
-    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
-        <!-- API 11 theme customizations can go here. -->
-    </style>
-
-</resources>
diff --git a/oc_framework-test-project/res/values-v14/styles.xml b/oc_framework-test-project/res/values-v14/styles.xml
deleted file mode 100644 (file)
index a91fd03..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<resources>
-
-    <!--
-        Base application theme for API 14+. This theme completely replaces
-        AppBaseTheme from BOTH res/values/styles.xml and
-        res/values-v11/styles.xml on API 14+ devices.
-    -->
-    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
-        <!-- API 14 theme customizations can go here. -->
-    </style>
-
-</resources>
diff --git a/oc_framework-test-project/res/values/dimens.xml b/oc_framework-test-project/res/values/dimens.xml
deleted file mode 100644 (file)
index 55c1e59..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<resources>
-
-    <!-- Default screen margins, per the Android Design guidelines. -->
-    <dimen name="activity_horizontal_margin">16dp</dimen>
-    <dimen name="activity_vertical_margin">16dp</dimen>
-
-</resources>
diff --git a/oc_framework-test-project/res/values/strings.xml b/oc_framework-test-project/res/values/strings.xml
deleted file mode 100644 (file)
index 3a21cff..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <string name="app_name">oc_framework-test-project</string>
-    <string name="action_settings">Settings</string>
-    <string name="hello_world">Hello world!</string>
-    <string name="test_account_not_found">The test account %1$s could not be found in the device</string>
-
-</resources>
diff --git a/oc_framework-test-project/res/values/styles.xml b/oc_framework-test-project/res/values/styles.xml
deleted file mode 100644 (file)
index 6ce89c7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<resources>
-
-    <!--
-        Base application theme, dependent on API level. This theme is replaced
-        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-    -->
-    <style name="AppBaseTheme" parent="android:Theme.Light">
-        <!--
-            Theme customizations available in newer API levels can go in
-            res/values-vXX/styles.xml, while customizations related to
-            backward-compatibility can go here.
-        -->
-    </style>
-
-    <!-- Application theme. -->
-    <style name="AppTheme" parent="AppBaseTheme">
-        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
-    </style>
-
-</resources>
diff --git a/oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java b/oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java
deleted file mode 100644 (file)
index 7687bb2..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.owncloud.android.oc_framework_test_project;
-
-import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.remote.CreateRemoteFolderOperation;
-import com.owncloud.android.oc_framework.operations.remote.RenameRemoteFileOperation;
-
-import android.net.Uri;
-import android.os.Bundle;
-import android.app.Activity;
-import android.view.Menu;
-
-/**
- * Activity to test OC framework
- * @author masensio
- * @author David A. Velasco
- */
-public class TestActivity extends Activity {
-       
-       // This account must exists on the simulator / device
-       private static final String mServerUri = "https://beta.owncloud.com/owncloud/remote.php/webdav";
-       private static final String mUser = "testandroid";
-       private static final String mPass = "testandroid";
-       
-       //private Account mAccount = null;
-       private WebdavClient mClient;
-       
-       @Override
-       protected void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-               setContentView(R.layout.activity_test);
-       Uri uri = Uri.parse(mServerUri);
-       mClient = OwnCloudClientFactory.createOwnCloudClient(uri ,getApplicationContext(), true);
-       mClient.setBasicCredentials(mUser, mPass);
-       }
-
-       @Override
-       public boolean onCreateOptionsMenu(Menu menu) {
-               // Inflate the menu; this adds items to the action bar if it is present.
-               getMenuInflater().inflate(R.menu.test, menu);
-               return true;
-       }
-
-       /**
-        * Access to the library method to Create a Folder
-        * @param remotePath
-        * @param createFullPath
-        * 
-        * @return
-        */
-       public RemoteOperationResult createFolder(String remotePath, boolean createFullPath) {
-               
-               CreateRemoteFolderOperation createOperation = new CreateRemoteFolderOperation(remotePath, createFullPath);
-               RemoteOperationResult result =  createOperation.execute(mClient);
-               
-               return result;
-       }
-       
-       /**
-        * Access to the library method to Rename a File or Folder
-        * @param oldName                       Old name of the file.
-     * @param oldRemotePath            Old remote path of the file. For folders it starts and ends by "/"
-     * @param newName                  New name to set as the name of file.
-     * @param isFolder                 'true' for folder and 'false' for files
-     * 
-     * @return
-     */
-
-       public RemoteOperationResult renameFile(String oldName, String oldRemotePath, String newName, boolean isFolder) {
-               
-               RenameRemoteFileOperation renameOperation = new RenameRemoteFileOperation(oldName, oldRemotePath, newName, isFolder);
-               RemoteOperationResult result = renameOperation.execute(mClient);
-               
-               return result;
-       }
-       
-}
diff --git a/oc_framework/.classpath b/oc_framework/.classpath
deleted file mode 100644 (file)
index 5176974..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
-       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="gen"/>
-       <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/oc_framework/.project b/oc_framework/.project
deleted file mode 100644 (file)
index 18812a0..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-       <name>oc_framework</name>
-       <comment></comment>
-       <projects>
-       </projects>
-       <buildSpec>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.jdt.core.javabuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-       </buildSpec>
-       <natures>
-               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
-               <nature>org.eclipse.jdt.core.javanature</nature>
-       </natures>
-</projectDescription>
diff --git a/oc_framework/.settings/org.eclipse.jdt.core.prefs b/oc_framework/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644 (file)
index b080d2d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.source=1.6
diff --git a/oc_framework/AndroidManifest.xml b/oc_framework/AndroidManifest.xml
deleted file mode 100644 (file)
index 836b4a0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.owncloud.android.oc_framework"
-    android:versionCode="1"
-    android:versionName="1.0" >
-
-    <uses-sdk
-        android:minSdkVersion="8"
-        android:targetSdkVersion="19" />
-
-</manifest>
diff --git a/oc_framework/build.xml b/oc_framework/build.xml
deleted file mode 100644 (file)
index 6b112f4..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="ownCloudFramework" default="help">
-
-    <!-- The local.properties file is created and updated by the 'android' tool.
-         It contains the path to the SDK. It should *NOT* be checked into
-         Version Control Systems. -->
-    <property file="local.properties" />
-
-    <!-- The ant.properties file can be created by you. It is only edited by the
-         'android' tool to add properties to it.
-         This is the place to change some Ant specific build properties.
-         Here are some properties you may want to change/update:
-
-         source.dir
-             The name of the source directory. Default is 'src'.
-         out.dir
-             The name of the output directory. Default is 'bin'.
-
-         For other overridable properties, look at the beginning of the rules
-         files in the SDK, at tools/ant/build.xml
-
-         Properties related to the SDK location or the project target should
-         be updated using the 'android' tool with the 'update' action.
-
-         This file is an integral part of the build system for your
-         application and should be checked into Version Control Systems.
-
-         -->
-    <property file="ant.properties" />
-
-    <!-- if sdk.dir was not set from one of the property file, then
-         get it from the ANDROID_HOME env var.
-         This must be done before we load project.properties since
-         the proguard config can use sdk.dir -->
-    <property environment="env" />
-    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
-        <isset property="env.ANDROID_HOME" />
-    </condition>
-
-    <!-- The project.properties file is created and updated by the 'android'
-         tool, as well as ADT.
-
-         This contains project specific properties such as project target, and library
-         dependencies. Lower level build properties are stored in ant.properties
-         (or in .classpath for Eclipse projects).
-
-         This file is an integral part of the build system for your
-         application and should be checked into Version Control Systems. -->
-    <loadproperties srcFile="project.properties" />
-
-    <!-- quick check on sdk.dir -->
-    <fail
-            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
-            unless="sdk.dir"
-    />
-
-    <!--
-        Import per project custom build rules if present at the root of the project.
-        This is the place to put custom intermediary targets such as:
-            -pre-build
-            -pre-compile
-            -post-compile (This is typically used for code obfuscation.
-                           Compiled code location: ${out.classes.absolute.dir}
-                           If this is not done in place, override ${out.dex.input.absolute.dir})
-            -post-package
-            -post-build
-            -pre-clean
-    -->
-    <import file="custom_rules.xml" optional="true" />
-
-    <!-- Import the actual build file.
-
-         To customize existing targets, there are two options:
-         - Customize only one target:
-             - copy/paste the target into this file, *before* the
-               <import> task.
-             - customize it to your needs.
-         - Customize the whole content of build.xml
-             - copy/paste the content of the rules files (minus the top node)
-               into this file, replacing the <import> task.
-             - customize to your needs.
-
-         ***********************
-         ****** IMPORTANT ******
-         ***********************
-         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
-         in order to avoid having your file be overridden by tools such as "android update project"
-    -->
-    <!-- version-tag: 1 -->
-    <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
diff --git a/oc_framework/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar b/oc_framework/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar
deleted file mode 100644 (file)
index 2dd374f..0000000
Binary files a/oc_framework/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar and /dev/null differ
diff --git a/oc_framework/project.properties b/oc_framework/project.properties
deleted file mode 100644 (file)
index 91d2b02..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-19
-android.library=true
diff --git a/oc_framework/res/values/empty.xml b/oc_framework/res/values/empty.xml
deleted file mode 100644 (file)
index 42eba3c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources/>
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountTypeUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountTypeUtils.java
deleted file mode 100644 (file)
index 2c9db68..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012  Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.accounts;
-
-/**
- * @author masensio
- * @author David A. Velasco
- */
-public class AccountTypeUtils {
-
-    public static String getAuthTokenTypePass(String accountType) {
-        return accountType + ".password";
-    }
-    
-    public static String getAuthTokenTypeAccessToken(String accountType) {
-        return accountType  + ".oauth2.access_token";
-    }
-    
-    public static String getAuthTokenTypeRefreshToken(String accountType) {
-        return accountType  + ".oauth2.refresh_token";
-    }
-    
-    public static String getAuthTokenTypeSamlSessionCookie(String accountType) {
-        return accountType  +  ".saml.web_sso.session_cookie";
-    }
-    
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountUtils.java
deleted file mode 100644 (file)
index 810f3eb..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012  Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.accounts;
-
-import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountsException;
-import android.content.Context;
-
-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 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";
-
-    /**
-     * 
-     * @param version version of owncloud
-     * @return webdav path for given OC version, null if OC version unknown
-     */
-    public static String getWebdavPath(OwnCloudVersion version, boolean supportsOAuth, boolean supportsSamlSso) {
-        if (version != null) {
-            if (supportsOAuth) {
-                return ODAV_PATH;
-            }
-            if (supportsSamlSso) {
-                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 null;
-    }
-    
-//    /**
-//     * Returns the proper URL path to access the WebDAV interface of an ownCloud server,
-//     * 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.
-//     */
-//    public static String getWebdavPath(OwnCloudVersion version, String authTokenType) {
-//        if (version != null) {
-//            if (MainApp.getAuthTokenTypeAccessToken().equals(authTokenType)) {
-//                return ODAV_PATH;
-//            }
-//            if (MainApp.getAuthTokenTypeSamlSessionCookie().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 null;
-//    }
-    
-    /**
-     * Constructs full url to host and webdav resource basing on host version
-     * @param context
-     * @param account
-     * @return url or null on failure
-     * @throws AccountNotFoundException     When 'account' is unknown for the AccountManager
-     */
-    public static String constructFullURLForAccount(Context context, Account account) throws AccountNotFoundException {
-        AccountManager ama = AccountManager.get(context);
-        String baseurl = ama.getUserData(account, OwnCloudAccount.Constants.KEY_OC_BASE_URL);
-        String strver  = ama.getUserData(account, OwnCloudAccount.Constants.KEY_OC_VERSION);
-        boolean supportsOAuth = (ama.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2) != null);
-        boolean supportsSamlSso = (ama.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null);
-        OwnCloudVersion ver = new OwnCloudVersion(strver);
-        String webdavpath = getWebdavPath(ver, supportsOAuth, supportsSamlSso);
-
-        if (baseurl == null || webdavpath == null) 
-            throw new AccountNotFoundException(account, "Account not found", null);
-        
-        return baseurl + webdavpath;
-    }
-    
-    
-    public static class AccountNotFoundException extends AccountsException {
-        
-        /** Generated - should be refreshed every time the class changes!! */
-        private static final long serialVersionUID = -9013287181793186830L;
-        
-        private Account mFailedAccount; 
-                
-        public AccountNotFoundException(Account failedAccount, String message, Throwable cause) {
-            super(message, cause);
-            mFailedAccount = failedAccount;
-        }
-        
-        public Account getFailedAccount() {
-            return mFailedAccount;
-        }
-    }
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/accounts/OwnCloudAccount.java b/oc_framework/src/com/owncloud/android/oc_framework/accounts/OwnCloudAccount.java
deleted file mode 100644 (file)
index 73fdb65..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.accounts;
-
-import android.accounts.Account;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Account with extra information specific for ownCloud accounts.
- * 
- * TODO integrate in the main app
- * 
- * @author David A. Velasco
- */
-public class OwnCloudAccount extends Account {
-
-       public static class Constants {
-           /**
-            * Value under this key should handle path to webdav php script. Will be
-            * removed and usage should be replaced by combining
-            * {@link com.owncloud.android.authentication.AuthenticatorActivity.KEY_OC_BASE_URL} and
-            * {@link com.owncloud.android.oc_framework.utils.utils.OwnCloudVersion}
-            * 
-            * @deprecated
-            */
-           public static final String KEY_OC_URL = "oc_url";
-           /**
-            * Version should be 3 numbers separated by dot so it can be parsed by
-            * {@link com.owncloud.android.oc_framework.utils.utils.OwnCloudVersion}
-            */
-           public static final String KEY_OC_VERSION = "oc_version";
-           /**
-            * Base url should point to owncloud installation without trailing / ie:
-            * http://server/path or https://owncloud.server
-            */
-           public static final String KEY_OC_BASE_URL = "oc_base_url";
-           /**
-            * Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
-            */
-           public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
-           /**
-            * Flag signaling if the ownCloud server can be accessed with session cookies from SAML-based web single-sign-on.
-            */
-           public static final String KEY_SUPPORTS_SAML_WEB_SSO = "oc_supports_saml_web_sso";
-       }
-       
-       private String mAuthTokenType;
-
-       public OwnCloudAccount(String name, String type, String authTokenType) {
-               super(name, type);
-               // TODO validate authTokentype as supported
-               mAuthTokenType = authTokenType;
-       }
-       
-    /**
-     * Reconstruct from parcel
-     * 
-     * @param source The source parcel
-     */
-       public OwnCloudAccount(Parcel source) {
-               super(source);
-        mAuthTokenType = source.readString();
-       }
-       
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-       super.writeToParcel(dest, flags);
-        dest.writeString(mAuthTokenType);
-    }
-       
-       
-       public String getAuthTokenType() {
-               return mAuthTokenType;
-       }
-
-       
-    public static final Parcelable.Creator<OwnCloudAccount> CREATOR = new Parcelable.Creator<OwnCloudAccount>() {
-        @Override
-        public OwnCloudAccount createFromParcel(Parcel source) {
-            return new OwnCloudAccount(source);
-        }
-
-        @Override
-        public OwnCloudAccount [] newArray(int size) {
-            return new OwnCloudAccount[size];
-        }
-    };
-       
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedSslSocketFactory.java b/oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedSslSocketFactory.java
deleted file mode 100644 (file)
index e24fa36..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.network;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.UnknownHostException;
-import java.security.cert.X509Certificate;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-
-import org.apache.commons.httpclient.ConnectTimeoutException;
-import org.apache.commons.httpclient.params.HttpConnectionParams;
-import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-
-import android.util.Log;
-
-
-
-/**
- * AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with 
- * a custom SSLContext and an optional Hostname Verifier.
- * 
- * @author David A. Velasco
- */
-
-public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
-
-    private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName();
-    
-    private SSLContext mSslContext = null;
-    private AdvancedX509TrustManager mTrustManager = null;
-    private X509HostnameVerifier mHostnameVerifier = null;
-
-    public SSLContext getSslContext() {
-        return mSslContext;
-    }
-    
-    /**
-     * Constructor for AdvancedSSLProtocolSocketFactory.
-     */
-    public AdvancedSslSocketFactory(SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier) {
-        if (sslContext == null)
-            throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext");
-        if (trustManager == null)
-            throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null Trust Manager");
-        mSslContext = sslContext;
-        mTrustManager = trustManager;
-        mHostnameVerifier = hostnameVerifier;
-    }
-
-    /**
-     * @see ProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
-     */
-    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
-        Socket socket = mSslContext.getSocketFactory().createSocket(host, port, clientHost, clientPort);
-        verifyPeerIdentity(host, port, socket);
-        return socket;
-    }
-
-    
-    /**
-     * Attempts to get a new socket connection to the given host within the
-     * given time limit.
-     * 
-     * @param host the host name/IP
-     * @param port the port on the host
-     * @param clientHost the local host name/IP to bind the socket to
-     * @param clientPort the port on the local machine
-     * @param params {@link HttpConnectionParams Http connection parameters}
-     * 
-     * @return Socket a new socket
-     * 
-     * @throws IOException if an I/O error occurs while creating the socket
-     * @throws UnknownHostException if the IP address of the host cannot be
-     *             determined
-     */
-    public Socket createSocket(final String host, final int port,
-            final InetAddress localAddress, final int localPort,
-            final HttpConnectionParams params) throws IOException,
-            UnknownHostException, ConnectTimeoutException {
-        Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
-        if (params == null) {
-            throw new IllegalArgumentException("Parameters may not be null");
-        } 
-        int timeout = params.getConnectionTimeout();
-        SocketFactory socketfactory = mSslContext.getSocketFactory();
-        Log.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
-        Socket socket = socketfactory.createSocket();
-        SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
-        SocketAddress remoteaddr = new InetSocketAddress(host, port);
-        socket.setSoTimeout(params.getSoTimeout());
-        socket.bind(localaddr);
-        socket.connect(remoteaddr, timeout);
-        verifyPeerIdentity(host, port, socket);
-        return socket;
-    }
-
-    /**
-     * @see ProtocolSocketFactory#createSocket(java.lang.String,int)
-     */
-    public Socket createSocket(String host, int port) throws IOException,
-            UnknownHostException {
-       Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
-        Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
-        verifyPeerIdentity(host, port, socket);
-        return socket; 
-    }
-
-    public boolean equals(Object obj) {
-        return ((obj != null) && obj.getClass().equals(
-                AdvancedSslSocketFactory.class));
-    }
-
-    public int hashCode() {
-        return AdvancedSslSocketFactory.class.hashCode();
-    }
-
-
-    public X509HostnameVerifier getHostNameVerifier() {
-        return mHostnameVerifier;
-    }
-    
-    
-    public void setHostNameVerifier(X509HostnameVerifier hostnameVerifier) {
-        mHostnameVerifier = hostnameVerifier;
-    }
-    
-    /**
-     * Verifies the identity of the server. 
-     * 
-     * The server certificate is verified first.
-     * 
-     * Then, the host name is compared with the content of the server certificate using the current host name verifier, if any.
-     * @param socket
-     */
-    private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException {
-        try {
-            CertificateCombinedException failInHandshake = null;
-            /// 1. VERIFY THE SERVER CERTIFICATE through the registered TrustManager (that should be an instance of AdvancedX509TrustManager) 
-            try {
-                SSLSocket sock = (SSLSocket) socket;    // a new SSLSession instance is created as a "side effect" 
-                sock.startHandshake();
-                
-            } catch (RuntimeException e) {
-                
-                if (e instanceof CertificateCombinedException) {
-                    failInHandshake = (CertificateCombinedException) e;
-                } else {
-                    Throwable cause = e.getCause();
-                    Throwable previousCause = null;
-                    while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
-                        previousCause = cause;
-                        cause = cause.getCause();
-                    }
-                    if (cause != null && cause instanceof CertificateCombinedException) {
-                        failInHandshake = (CertificateCombinedException)cause;
-                    }
-                }
-                if (failInHandshake == null) {
-                    throw e;
-                }
-                failInHandshake.setHostInUrl(host);
-                
-            }
-            
-            /// 2. VERIFY HOSTNAME
-            SSLSession newSession = null;
-            boolean verifiedHostname = true;
-            if (mHostnameVerifier != null) {
-                if (failInHandshake != null) {
-                    /// 2.1 : a new SSLSession instance was NOT created in the handshake
-                    X509Certificate serverCert = failInHandshake.getServerCertificate();
-                    try {
-                        mHostnameVerifier.verify(host, serverCert);
-                    } catch (SSLException e) {
-                        verifiedHostname = false;
-                    }
-                
-                } else {
-                    /// 2.2 : a new SSLSession instance was created in the handshake
-                    newSession = ((SSLSocket)socket).getSession();
-                    if (!mTrustManager.isKnownServer((X509Certificate)(newSession.getPeerCertificates()[0]))) {
-                        verifiedHostname = mHostnameVerifier.verify(host, newSession); 
-                    }
-                }
-            }
-
-            /// 3. Combine the exceptions to throw, if any
-            if (!verifiedHostname) {
-                SSLPeerUnverifiedException pue = new SSLPeerUnverifiedException("Names in the server certificate do not match to " + host + " in the URL");
-                if (failInHandshake == null) {
-                    failInHandshake = new CertificateCombinedException((X509Certificate) newSession.getPeerCertificates()[0]);
-                    failInHandshake.setHostInUrl(host);
-                }
-                failInHandshake.setSslPeerUnverifiedException(pue);
-                pue.initCause(failInHandshake);
-                throw pue;
-                
-            } else if (failInHandshake != null) {
-                SSLHandshakeException hse = new SSLHandshakeException("Server certificate could not be verified");
-                hse.initCause(failInHandshake);
-                throw hse;
-            }
-            
-        } catch (IOException io) {        
-            try {
-                socket.close();
-            } catch (Exception x) {
-                // NOTHING - irrelevant exception for the caller 
-            }
-            throw io;
-        }
-    }
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedX509TrustManager.java b/oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedX509TrustManager.java
deleted file mode 100644 (file)
index 4bad3ef..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.network;
-
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertStoreException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-import android.util.Log;
-
-
-
-/**
- * @author David A. Velasco
- */
-public class AdvancedX509TrustManager implements X509TrustManager {
-    
-    private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
-
-    private X509TrustManager mStandardTrustManager = null;
-    private KeyStore mKnownServersKeyStore;
-
-    /**
-     * Constructor for AdvancedX509TrustManager
-     * 
-     * @param  knownServersCertStore    Local certificates store with server certificates explicitly trusted by the user.
-     * @throws CertStoreException       When no default X509TrustManager instance was found in the system.
-     */
-    public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
-            throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
-        super();
-        TrustManagerFactory factory = TrustManagerFactory
-                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
-        factory.init((KeyStore)null);
-        mStandardTrustManager = findX509TrustManager(factory);
-
-        mKnownServersKeyStore = knownServersKeyStore;
-    }
-    
-    
-    /**
-     * Locates the first X509TrustManager provided by a given TrustManagerFactory
-     * @param factory               TrustManagerFactory to inspect in the search for a X509TrustManager
-     * @return                      The first X509TrustManager found in factory.
-     * @throws CertStoreException   When no X509TrustManager instance was found in factory
-     */
-    private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
-        TrustManager tms[] = factory.getTrustManagers();
-        for (int i = 0; i < tms.length; i++) {
-            if (tms[i] instanceof X509TrustManager) {
-                return (X509TrustManager) tms[i];
-            }
-        }
-        return null;
-    }
-    
-
-    /**
-     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
-     *      String authType)
-     */
-    public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
-        mStandardTrustManager.checkClientTrusted(certificates, authType);
-    }
-
-    
-    /**
-     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
-     *      String authType)
-     */
-    public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
-        if (!isKnownServer(certificates[0])) {
-               CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
-               try {
-                       certificates[0].checkValidity();
-               } catch (CertificateExpiredException c) {
-                       result.setCertificateExpiredException(c);
-                       
-               } catch (CertificateNotYetValidException c) {
-                result.setCertificateNotYetException(c);
-               }
-               
-               try {
-                   mStandardTrustManager.checkServerTrusted(certificates, authType);
-               } catch (CertificateException c) {
-                Throwable cause = c.getCause();
-                Throwable previousCause = null;
-                while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) {     // getCause() is not funny
-                    previousCause = cause;
-                    cause = cause.getCause();
-                }
-                if (cause != null && cause instanceof CertPathValidatorException) {
-                       result.setCertPathValidatorException((CertPathValidatorException)cause);
-                } else {
-                       result.setOtherCertificateException(c);
-                }
-               }
-               
-               if (result.isException())
-                       throw result;
-
-        }
-    }
-    
-    
-    /**
-     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
-     */
-    public X509Certificate[] getAcceptedIssuers() {
-        return mStandardTrustManager.getAcceptedIssuers();
-    }
-
-    
-    public boolean isKnownServer(X509Certificate cert) {
-        try {
-            return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
-        } catch (KeyStoreException e) {
-            Log.d(TAG, "Fail while checking certificate in the known-servers store");
-            return false;
-        }
-    }
-    
-}
\ No newline at end of file
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/BearerAuthScheme.java b/oc_framework/src/com/owncloud/android/oc_framework/network/BearerAuthScheme.java
deleted file mode 100644 (file)
index 37698d6..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-package com.owncloud.android.oc_framework.network;
-/* ownCloud Android client application
- *   Copyright (C) 2012  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/>.
- *
- */
-
-
-
-import java.util.Map;
-
-import org.apache.commons.httpclient.Credentials;
-import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.auth.AuthChallengeParser;
-import org.apache.commons.httpclient.auth.AuthScheme;
-import org.apache.commons.httpclient.auth.AuthenticationException;
-import org.apache.commons.httpclient.auth.InvalidCredentialsException;
-import org.apache.commons.httpclient.auth.MalformedChallengeException;
-
-import android.util.Log;
-
-
-
-/**
- * Bearer authentication scheme as defined in RFC 6750.
- * 
- * @author David A. Velasco
- */
-
-public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
-    
-    private static final String TAG = BearerAuthScheme.class.getSimpleName();
-
-    public static final String AUTH_POLICY = "Bearer";
-    
-    /** Whether the bearer authentication process is complete */
-    private boolean mComplete;
-    
-    /** Authentication parameter map */
-    @SuppressWarnings("rawtypes")
-       private Map mParams = null;
-    
-    
-    /**
-     * Default constructor for the bearer authentication scheme.
-     */
-    public BearerAuthScheme() {
-        mComplete = false;
-    }
-
-    /**
-     * Constructor for the basic authentication scheme.
-     * 
-     * @param   challenge                       Authentication challenge
-     * 
-     * @throws  MalformedChallengeException     Thrown if the authentication challenge is malformed
-     * 
-     * @deprecated Use parameterless constructor and {@link AuthScheme#processChallenge(String)} method
-     */
-    public BearerAuthScheme(final String challenge) throws MalformedChallengeException {
-        processChallenge(challenge);
-        mComplete = true;
-    }
-
-    /**
-     * Returns textual designation of the bearer authentication scheme.
-     * 
-     * @return "Bearer"
-     */
-    public String getSchemeName() {
-        return "bearer";
-    }
-
-    /**
-     * Processes the Bearer challenge.
-     *  
-     * @param   challenge                   The challenge string
-     * 
-     * @throws MalformedChallengeException  Thrown if the authentication challenge is malformed
-     */
-    public void processChallenge(String challenge) throws MalformedChallengeException {
-        String s = AuthChallengeParser.extractScheme(challenge);
-        if (!s.equalsIgnoreCase(getSchemeName())) {
-            throw new MalformedChallengeException(
-              "Invalid " + getSchemeName() + " challenge: " + challenge); 
-        }
-        mParams = AuthChallengeParser.extractParams(challenge);
-        mComplete = true;
-    }
-
-    /**
-     * Tests if the Bearer authentication process has been completed.
-     * 
-     * @return 'true' if Bearer authorization has been processed, 'false' otherwise.
-     */
-    public boolean isComplete() {
-        return this.mComplete;
-    }
-
-    /**
-     * Produces bearer authorization string for the given set of 
-     * {@link Credentials}.
-     * 
-     * @param   credentials                     The set of credentials to be used for authentication
-     * @param   method                          Method name is ignored by the bearer authentication scheme
-     * @param   uri                             URI is ignored by the bearer authentication scheme
-     * @throws  InvalidCredentialsException     If authentication credentials are not valid or not applicable 
-     *                                          for this authentication scheme
-     * @throws  AuthenticationException         If authorization string cannot be generated due to an authentication failure
-     * @return  A bearer authorization string
-     * 
-     * @deprecated Use {@link #authenticate(Credentials, HttpMethod)}
-     */
-    public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException {
-        Log.d(TAG, "enter BearerScheme.authenticate(Credentials, String, String)");
-
-        BearerCredentials bearer = null;
-        try {
-            bearer = (BearerCredentials) credentials;
-        } catch (ClassCastException e) {
-            throw new InvalidCredentialsException(
-             "Credentials cannot be used for bearer authentication: " 
-              + credentials.getClass().getName());
-        }
-        return BearerAuthScheme.authenticate(bearer);
-    }
-
-    
-    /**
-     * Returns 'false'. Bearer authentication scheme is request based.
-     * 
-     * @return 'false'.
-     */
-    public boolean isConnectionBased() {
-        return false;    
-    }
-
-    /**
-     * Produces bearer authorization string for the given set of {@link Credentials}.
-     * 
-     * @param   credentials                     The set of credentials to be used for authentication
-     * @param   method                          The method being authenticated
-     * @throws  InvalidCredentialsException     If authentication credentials are not valid or not applicable for this authentication 
-     *                                          scheme.
-     * @throws AuthenticationException         If authorization string cannot be generated due to an authentication failure.
-     * 
-     * @return a basic authorization string
-     */
-    public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException {
-        Log.d(TAG, "enter BearerScheme.authenticate(Credentials, HttpMethod)");
-
-        if (method == null) {
-            throw new IllegalArgumentException("Method may not be null");
-        }
-        BearerCredentials bearer = null;
-        try {
-            bearer = (BearerCredentials) credentials;
-        } catch (ClassCastException e) {
-            throw new InvalidCredentialsException(
-                    "Credentials cannot be used for bearer authentication: " 
-                    + credentials.getClass().getName());
-        }
-        return BearerAuthScheme.authenticate(
-            bearer, 
-            method.getParams().getCredentialCharset());
-    }
-    
-    /**
-     * @deprecated Use {@link #authenticate(BearerCredentials, String)}
-     * 
-     * Returns a bearer Authorization header value for the given 
-     * {@link BearerCredentials}.
-     * 
-     * @param   credentials     The credentials to encode.
-     * 
-     * @return                  A bearer authorization string
-     */
-    public static String authenticate(BearerCredentials credentials) {
-        return authenticate(credentials, "ISO-8859-1");
-    }
-
-    /**
-     * Returns a bearer Authorization header value for the given 
-     * {@link BearerCredentials} and charset.
-     * 
-     * @param   credentials         The credentials to encode.
-     * @param   charset             The charset to use for encoding the credentials
-     * 
-     * @return                      A bearer authorization string
-     * 
-     * @since 3.0
-     */
-    public static String authenticate(BearerCredentials credentials, String charset) {
-        Log.d(TAG, "enter BearerAuthScheme.authenticate(BearerCredentials, String)");
-
-        if (credentials == null) {
-            throw new IllegalArgumentException("Credentials may not be null"); 
-        }
-        if (charset == null || charset.length() == 0) {
-            throw new IllegalArgumentException("charset may not be null or empty");
-        }
-        StringBuffer buffer = new StringBuffer();
-        buffer.append(credentials.getAccessToken());
-        
-        //return "Bearer " + EncodingUtil.getAsciiString(EncodingUtil.getBytes(buffer.toString(), charset));
-        return "Bearer " + buffer.toString();
-    }
-
-    /**
-     * Returns a String identifying the authentication challenge.  This is
-     * used, in combination with the host and port to determine if
-     * authorization has already been attempted or not.  Schemes which
-     * require multiple requests to complete the authentication should
-     * return a different value for each stage in the request.
-     * 
-     * Additionally, the ID should take into account any changes to the
-     * authentication challenge and return a different value when appropriate.
-     * For example when the realm changes in basic authentication it should be
-     * considered a different authentication attempt and a different value should
-     * be returned.
-     * 
-     * This method simply returns the realm for the challenge.
-     * 
-     * @return String       a String identifying the authentication challenge.
-     * 
-     * @deprecated no longer used
-     */
-    @Override
-    public String getID() {
-        return getRealm();
-    }
-
-    /**
-     * Returns authentication parameter with the given name, if available.
-     * 
-     * @param   name    The name of the parameter to be returned
-     * 
-     * @return          The parameter with the given name
-     */
-    @Override
-    public String getParameter(String name) {
-        if (name == null) {
-            throw new IllegalArgumentException("Parameter name may not be null"); 
-        }
-        if (mParams == null) {
-            return null;
-        }
-        return (String) mParams.get(name.toLowerCase());
-    }
-
-    /**
-     * Returns authentication realm. The realm may not be null.
-     * 
-     * @return  The authentication realm
-     */
-    @Override
-    public String getRealm() {
-        return getParameter("realm");
-    }
-    
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/BearerCredentials.java b/oc_framework/src/com/owncloud/android/oc_framework/network/BearerCredentials.java
deleted file mode 100644 (file)
index 5b18e62..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-package com.owncloud.android.oc_framework.network;
-/* ownCloud Android client application
- *   Copyright (C) 2012  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/>.
- *
- */
-
-
-
-import org.apache.commons.httpclient.Credentials;
-import org.apache.commons.httpclient.util.LangUtils;
-
-/**
- * Bearer token {@link Credentials}
- *
- * @author David A. Velasco
- */
-public class BearerCredentials implements Credentials {
-
-    
-    private String mAccessToken;
-    
-    
-    /**
-     * The constructor with the bearer token
-     *
-     * @param token     The bearer token
-     */
-    public BearerCredentials(String token) {
-        /*if (token == null) {
-            throw new IllegalArgumentException("Bearer token may not be null");            
-        }*/
-        mAccessToken = (token == null) ? "" : token;
-    }
-
-
-    /**
-     * Returns the access token
-     *
-     * @return      The access token
-     */
-    public String getAccessToken() {
-        return mAccessToken;
-    }
-
-
-    /**
-     * Get this object string.
-     *
-     * @return  The access token
-     */
-    public String toString() {
-        return mAccessToken;
-    }
-
-    /**
-     * Does a hash of the access token.
-     *
-     * @return The hash code of the access token
-     */
-    public int hashCode() {
-        int hash = LangUtils.HASH_SEED;
-        hash = LangUtils.hashCode(hash, mAccessToken);
-        return hash;
-    }
-
-    /**
-     * These credentials are assumed equal if accessToken is the same.
-     *
-     * @param   o   The other object to compare with.
-     *
-     * @return      'True' if the object is equivalent.
-     */
-    public boolean equals(Object o) {
-        if (o == null) return false;
-        if (this == o) return true;
-        if (this.getClass().equals(o.getClass())) {
-            BearerCredentials that = (BearerCredentials) o;
-            if (LangUtils.equals(mAccessToken, that.mAccessToken)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
-
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/CertificateCombinedException.java b/oc_framework/src/com/owncloud/android/oc_framework/network/CertificateCombinedException.java
deleted file mode 100644 (file)
index 1b262bc..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-package com.owncloud.android.oc_framework.network;
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
-
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.SSLPeerUnverifiedException;
-
-/**
- * Exception joining all the problems that {@link AdvancedX509TrustManager} can find in
- * a certificate chain for a server.
- * 
- * This was initially created as an extension of CertificateException, but some
- * implementations of the SSL socket layer in existing devices are REPLACING the CertificateException
- * instances thrown by {@link javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], String)}
- * with SSLPeerUnverifiedException FORGETTING THE CAUSING EXCEPTION instead of wrapping it. 
- * 
- * Due to this, extending RuntimeException is necessary to get that the CertificateCombinedException 
- * instance reaches {@link AdvancedSslSocketFactory#verifyPeerIdentity}.
- * 
- * BE CAREFUL. As a RuntimeException extensions, Java compilers do not require to handle it
- * in client methods. Be sure to use it only when you know exactly where it will go.
- * 
- * @author David A. Velasco
- */
-public class CertificateCombinedException extends RuntimeException {
-
-    /** Generated - to refresh every time the class changes */
-    private static final long serialVersionUID = -8875782030758554999L;
-    
-    private X509Certificate mServerCert = null;
-    private String mHostInUrl;
-
-    private CertificateExpiredException mCertificateExpiredException = null;
-    private CertificateNotYetValidException mCertificateNotYetValidException = null;
-    private CertPathValidatorException mCertPathValidatorException = null;
-    private CertificateException mOtherCertificateException = null;
-    private SSLPeerUnverifiedException mSslPeerUnverifiedException = null;
-    
-    public CertificateCombinedException(X509Certificate x509Certificate) {
-        mServerCert = x509Certificate;
-    }
-
-    public X509Certificate getServerCertificate() {
-        return mServerCert;
-    }
-
-    public String getHostInUrl() {
-        return mHostInUrl;
-    }
-
-    public void setHostInUrl(String host) {
-        mHostInUrl = host;
-    }
-
-    public CertificateExpiredException getCertificateExpiredException() {
-        return mCertificateExpiredException;
-    }
-
-    public void setCertificateExpiredException(CertificateExpiredException c) {
-        mCertificateExpiredException  = c;
-    }
-
-    public CertificateNotYetValidException getCertificateNotYetValidException() {
-        return mCertificateNotYetValidException;
-    }
-
-    public void setCertificateNotYetException(CertificateNotYetValidException c) {
-        mCertificateNotYetValidException = c;
-    }
-
-    public CertPathValidatorException getCertPathValidatorException() {
-        return mCertPathValidatorException;
-    }
-
-    public void setCertPathValidatorException(CertPathValidatorException c) {
-        mCertPathValidatorException = c;
-    }
-
-    public CertificateException getOtherCertificateException() {
-        return mOtherCertificateException;
-    }
-
-    public void setOtherCertificateException(CertificateException c) {
-        mOtherCertificateException = c;
-    }
-
-    public SSLPeerUnverifiedException getSslPeerUnverifiedException() {
-        return mSslPeerUnverifiedException ; 
-    }
-
-    public void setSslPeerUnverifiedException(SSLPeerUnverifiedException s) {
-        mSslPeerUnverifiedException = s;
-    }
-
-    public boolean isException() {
-        return (mCertificateExpiredException != null ||
-                mCertificateNotYetValidException != null ||
-                mCertPathValidatorException != null ||
-                mOtherCertificateException != null ||
-                mSslPeerUnverifiedException != null);
-    }
-
-    public boolean isRecoverable() {
-        return (mCertificateExpiredException != null ||
-                mCertificateNotYetValidException != null ||
-                mCertPathValidatorException != null ||
-                mSslPeerUnverifiedException != null);
-    }
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/NetworkUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/network/NetworkUtils.java
deleted file mode 100644 (file)
index ac2e015..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-package com.owncloud.android.oc_framework.network;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-
-import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
-import org.apache.commons.httpclient.protocol.Protocol;
-import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-
-import android.content.Context;
-import android.util.Log;
-
-public class NetworkUtils {
-    
-    final private static String TAG = NetworkUtils.class.getSimpleName();
-    
-    /** Default timeout for waiting data from the server */
-    public static final int DEFAULT_DATA_TIMEOUT = 60000;
-    
-    /** Default timeout for establishing a connection */
-    public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
-
-    /** Connection manager for all the WebdavClients */
-    private static MultiThreadedHttpConnectionManager mConnManager = null;
-    
-    private static Protocol mDefaultHttpsProtocol = null;
-
-    private static AdvancedSslSocketFactory mAdvancedSslSocketFactory = null;
-
-    private static X509HostnameVerifier mHostnameVerifier = null;
-    
-    
-    /**
-     * Registers or unregisters the proper components for advanced SSL handling.
-     * @throws IOException 
-     */
-    public static void registerAdvancedSslContext(boolean register, Context context) throws GeneralSecurityException, IOException {
-        Protocol pr = null;
-        try {
-            pr = Protocol.getProtocol("https");
-            if (pr != null && mDefaultHttpsProtocol == null) {
-                mDefaultHttpsProtocol = pr;
-            }
-        } catch (IllegalStateException e) {
-            // nothing to do here; really
-        }
-        boolean isRegistered = (pr != null && pr.getSocketFactory() instanceof AdvancedSslSocketFactory);
-        if (register && !isRegistered) {
-            Protocol.registerProtocol("https", new Protocol("https", getAdvancedSslSocketFactory(context), 443));
-            
-        } else if (!register && isRegistered) {
-            if (mDefaultHttpsProtocol != null) {
-                Protocol.registerProtocol("https", mDefaultHttpsProtocol);
-            }
-        }
-    }
-    
-    public static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context context) throws GeneralSecurityException, IOException {
-        if (mAdvancedSslSocketFactory  == null) {
-            KeyStore trustStore = getKnownServersStore(context);
-            AdvancedX509TrustManager trustMgr = new AdvancedX509TrustManager(trustStore);
-            TrustManager[] tms = new TrustManager[] { trustMgr };
-                
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.init(null, tms, null);
-                    
-            mHostnameVerifier = new BrowserCompatHostnameVerifier();
-            mAdvancedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, trustMgr, mHostnameVerifier);
-        }
-        return mAdvancedSslSocketFactory;
-    }
-
-
-    private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
-    
-    private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
-
-    private static KeyStore mKnownServersStore = null;
-    
-    /**
-     * Returns the local store of reliable server certificates, explicitly accepted by the user.
-     * 
-     * Returns a KeyStore instance with empty content if the local store was never created.
-     * 
-     * Loads the store from the storage environment if needed.
-     * 
-     * @param context                       Android context where the operation is being performed.
-     * @return                              KeyStore instance with explicitly-accepted server certificates. 
-     * @throws KeyStoreException            When the KeyStore instance could not be created.
-     * @throws IOException                  When an existing local trust store could not be loaded.
-     * @throws NoSuchAlgorithmException     When the existing local trust store was saved with an unsupported algorithm.
-     * @throws CertificateException         When an exception occurred while loading the certificates from the local trust store.
-     */
-    private static KeyStore getKnownServersStore(Context context) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
-        if (mKnownServersStore == null) {
-            //mKnownServersStore = KeyStore.getInstance("BKS");
-            mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
-            File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
-            Log.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
-            if (localTrustStoreFile.exists()) {
-                InputStream in = new FileInputStream(localTrustStoreFile);
-                try {
-                    mKnownServersStore.load(in, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
-                } finally {
-                    in.close();
-                }
-            } else {
-                mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray()); // necessary to initialize an empty KeyStore instance
-            }
-        }
-        return mKnownServersStore;
-    }
-    
-    
-    public static void addCertToKnownServersStore(Certificate cert, Context context) throws  KeyStoreException, NoSuchAlgorithmException, 
-                                                                                            CertificateException, IOException {
-        KeyStore knownServers = getKnownServersStore(context);
-        knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
-        FileOutputStream fos = null;
-        try {
-            fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE);
-            knownServers.store(fos, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
-        } finally {
-            fos.close();
-        }
-    }
-    
-    
-    static public MultiThreadedHttpConnectionManager getMultiThreadedConnManager() {
-        if (mConnManager == null) {
-            mConnManager = new MultiThreadedHttpConnectionManager();
-            mConnManager.getParams().setDefaultMaxConnectionsPerHost(5);
-            mConnManager.getParams().setMaxTotalConnections(5);
-        }
-        return mConnManager;
-    }
-
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/ProgressiveDataTransferer.java b/oc_framework/src/com/owncloud/android/oc_framework/network/ProgressiveDataTransferer.java
deleted file mode 100644 (file)
index 3a21d5f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.owncloud.android.oc_framework.network;
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
-
-import java.util.Collection;
-
-import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
-
-
-public interface ProgressiveDataTransferer {
-
-    public void addDatatransferProgressListener (OnDatatransferProgressListener listener);
-    
-    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners);
-
-    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener);
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/ChunkFromFileChannelRequestEntity.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/ChunkFromFileChannelRequestEntity.java
deleted file mode 100644 (file)
index 6a4200d..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.network.webdav;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.commons.httpclient.methods.RequestEntity;
-
-import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
-
-import android.util.Log;
-
-
-/**
- * A RequestEntity that represents a PIECE of a file.
- * 
- * @author David A. Velasco
- */
-public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
-
-    private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
-    
-    //private final File mFile;
-    private final FileChannel mChannel;
-    private final String mContentType;
-    private final long mChunkSize;
-    private final File mFile;
-    private long mOffset;
-    private long mTransferred;
-    Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
-    private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
-
-    public ChunkFromFileChannelRequestEntity(final FileChannel channel, final String contentType, long chunkSize, final File file) {
-        super();
-        if (channel == null) {
-            throw new IllegalArgumentException("File may not be null");
-        }
-        if (chunkSize <= 0) {
-            throw new IllegalArgumentException("Chunk size must be greater than zero");
-        }
-        mChannel = channel;
-        mContentType = contentType;
-        mChunkSize = chunkSize;
-        mFile = file;
-        mOffset = 0;
-        mTransferred = 0;
-    }
-    
-    public void setOffset(long offset) {
-        mOffset = offset;
-    }
-    
-    public long getContentLength() {
-        try {
-            return Math.min(mChunkSize, mChannel.size() - mChannel.position());
-        } catch (IOException e) {
-            return mChunkSize;
-        }
-    }
-
-    public String getContentType() {
-        return mContentType;
-    }
-
-    public boolean isRepeatable() {
-        return true;
-    }
-    
-    @Override
-    public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.add(listener);
-        }
-    }
-    
-    @Override
-    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.addAll(listeners);
-        }
-    }
-    
-    @Override
-    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.remove(listener);
-        }
-    }
-    
-    
-    public void writeRequest(final OutputStream out) throws IOException {
-        int readCount = 0;
-        Iterator<OnDatatransferProgressListener> it = null;
-        
-       try {
-            mChannel.position(mOffset);
-            long size = mFile.length();
-            if (size == 0) size = -1;
-            long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
-            while (mChannel.position() < maxCount) {
-                readCount = mChannel.read(mBuffer);
-                out.write(mBuffer.array(), 0, readCount);
-                mBuffer.clear();
-                if (mTransferred < maxCount) {  // condition to avoid accumulate progress for repeated chunks
-                    mTransferred += readCount;
-                }
-                synchronized (mDataTransferListeners) {
-                    it = mDataTransferListeners.iterator();
-                    while (it.hasNext()) {
-                        it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
-                    }
-                }
-            }
-            
-        } catch (IOException io) {
-            Log.e(TAG, io.getMessage());
-            throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
-            
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/FileRequestEntity.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/FileRequestEntity.java
deleted file mode 100644 (file)
index 3f066f9..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.network.webdav;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.commons.httpclient.methods.RequestEntity;
-
-import android.util.Log;
-
-import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
-
-
-/**
- * A RequestEntity that represents a File.
- * 
- */
-public class FileRequestEntity implements RequestEntity, ProgressiveDataTransferer {
-
-    final File mFile;
-    final String mContentType;
-    Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
-
-    public FileRequestEntity(final File file, final String contentType) {
-        super();
-        this.mFile = file;
-        this.mContentType = contentType;
-        if (file == null) {
-            throw new IllegalArgumentException("File may not be null");
-        }
-    }
-    
-    @Override
-    public long getContentLength() {
-        return mFile.length();
-    }
-
-    @Override
-    public String getContentType() {
-        return mContentType;
-    }
-
-    @Override
-    public boolean isRepeatable() {
-        return true;
-    }
-
-    @Override
-    public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.add(listener);
-        }
-    }
-    
-    @Override
-    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.addAll(listeners);
-        }
-    }
-    
-    @Override
-    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.remove(listener);
-        }
-    }
-    
-    
-    @Override
-    public void writeRequest(final OutputStream out) throws IOException {
-        //byte[] tmp = new byte[4096];
-        ByteBuffer tmp = ByteBuffer.allocate(4096);
-        int readResult = 0;
-        
-        // TODO(bprzybylski): each mem allocation can throw OutOfMemoryError we need to handle it
-        //                    globally in some fashionable manner
-        RandomAccessFile raf = new RandomAccessFile(mFile, "r");
-        FileChannel channel = raf.getChannel();
-        Iterator<OnDatatransferProgressListener> it = null;
-        long transferred = 0;
-        long size = mFile.length();
-        if (size == 0) size = -1;
-        try {
-            while ((readResult = channel.read(tmp)) >= 0) {
-                out.write(tmp.array(), 0, readResult);
-                tmp.clear();
-                transferred += readResult;
-                synchronized (mDataTransferListeners) {
-                    it = mDataTransferListeners.iterator();
-                    while (it.hasNext()) {
-                        it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
-                    }
-                }
-            }
-            
-        } catch (IOException io) {
-            Log.e("FileRequestException", io.getMessage());
-            throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
-            
-        } finally {
-            channel.close();
-            raf.close();
-        }
-    }
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OnDatatransferProgressListener.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OnDatatransferProgressListener.java
deleted file mode 100644 (file)
index 06f32b5..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.network.webdav;
-
-public interface OnDatatransferProgressListener {
-    public void onTransferProgress(long progressRate);
-    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName);
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OwnCloudClientFactory.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OwnCloudClientFactory.java
deleted file mode 100644 (file)
index 5c41edb..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-package com.owncloud.android.oc_framework.network.webdav;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-
-import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;
-import com.owncloud.android.oc_framework.accounts.AccountUtils;
-import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
-import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
-import com.owncloud.android.oc_framework.network.NetworkUtils;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
-import android.app.Activity;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-
-public class OwnCloudClientFactory {
-    
-    final private static String TAG = OwnCloudClientFactory.class.getSimpleName();
-    
-    /** Default timeout for waiting data from the server */
-    public static final int DEFAULT_DATA_TIMEOUT = 60000;
-    
-    /** Default timeout for establishing a connection */
-    public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
-
-    
-    /**
-     * Creates a WebdavClient setup for an ownCloud account
-     * 
-     * Do not call this method from the main thread.
-     * 
-     * @param account                       The ownCloud account
-     * @param appContext                    Android application context
-     * @return                              A WebdavClient object ready to be used
-     * @throws AuthenticatorException       If the authenticator failed to get the authorization token for the account.
-     * @throws OperationCanceledException   If the authenticator operation was cancelled while getting the authorization token for the account. 
-     * @throws IOException                  If there was some I/O error while getting the authorization token for the account.
-     * @throws AccountNotFoundException     If 'account' is unknown for the AccountManager
-     */
-    public static WebdavClient createOwnCloudClient (Account account, Context appContext) throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {
-        //Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
-       
-        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
-        AccountManager am = AccountManager.get(appContext);
-        boolean isOauth2 = am.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2) != null;   // TODO avoid calling to getUserData here
-        boolean isSamlSso = am.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null;
-        WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso);
-        if (isOauth2) {    
-            String accessToken = am.blockingGetAuthToken(account, AccountTypeUtils.getAuthTokenTypeAccessToken(account.type), false);
-            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
-        
-        } else if (isSamlSso) {    // TODO avoid a call to getUserData here
-            String accessToken = am.blockingGetAuthToken(account, AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type), false);
-            client.setSsoSessionCookie(accessToken);
-            
-        } else {
-            String username = account.name.substring(0, account.name.lastIndexOf('@'));
-            //String password = am.getPassword(account);
-            String password = am.blockingGetAuthToken(account, AccountTypeUtils.getAuthTokenTypePass(account.type), false);
-            client.setBasicCredentials(username, password);
-        }
-        
-        return client;
-    }
-    
-    
-    public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {
-        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
-        AccountManager am = AccountManager.get(appContext);
-        boolean isOauth2 = am.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2) != null;   // TODO avoid calling to getUserData here
-        boolean isSamlSso = am.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null;
-        WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso);
-        
-        if (isOauth2) {    // TODO avoid a call to getUserData here
-            AccountManagerFuture<Bundle> future =  am.getAuthToken(account,  AccountTypeUtils.getAuthTokenTypeAccessToken(account.type), null, currentActivity, null, null);
-            Bundle result = future.getResult();
-            String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
-            if (accessToken == null) throw new AuthenticatorException("WTF!");
-            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
-
-        } else if (isSamlSso) {    // TODO avoid a call to getUserData here
-            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type), null, currentActivity, null, null);
-            Bundle result = future.getResult();
-            String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
-            if (accessToken == null) throw new AuthenticatorException("WTF!");
-            client.setSsoSessionCookie(accessToken);
-
-        } else {
-            String username = account.name.substring(0, account.name.lastIndexOf('@'));
-            //String password = am.getPassword(account);
-            //String password = am.blockingGetAuthToken(account, MainApp.getAuthTokenTypePass(), false);
-            AccountManagerFuture<Bundle> future =  am.getAuthToken(account,  AccountTypeUtils.getAuthTokenTypePass(account.type), null, currentActivity, null, null);
-            Bundle result = future.getResult();
-            String password = result.getString(AccountManager.KEY_AUTHTOKEN);
-            client.setBasicCredentials(username, password);
-        }
-        
-        return client;
-    }
-    
-    /**
-     * Creates a WebdavClient to access a URL and sets the desired parameters for ownCloud client connections.
-     * 
-     * @param uri       URL to the ownCloud server
-     * @param context   Android context where the WebdavClient is being created.
-     * @return          A WebdavClient object ready to be used
-     */
-    public static WebdavClient createOwnCloudClient(Uri uri, Context context, boolean followRedirects) {
-        try {
-            NetworkUtils.registerAdvancedSslContext(true, context);
-        }  catch (GeneralSecurityException e) {
-            Log.e(TAG, "Advanced SSL Context could not be loaded. Default SSL management in the system will be used for HTTPS connections", e);
-            
-        } catch (IOException e) {
-            Log.e(TAG, "The local server truststore could not be read. Default SSL management in the system will be used for HTTPS connections", e);
-        }
-        
-        WebdavClient client = new WebdavClient(NetworkUtils.getMultiThreadedConnManager());
-        
-        client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
-        client.setBaseUri(uri);
-        client.setFollowRedirects(followRedirects);
-        
-        return client;
-    }
-    
-    
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavClient.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavClient.java
deleted file mode 100644 (file)
index 543374c..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2011  Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.network.webdav;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.httpclient.Credentials;
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpConnectionManager;
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.HttpMethodBase;
-import org.apache.commons.httpclient.HttpVersion;
-import org.apache.commons.httpclient.URI;
-import org.apache.commons.httpclient.UsernamePasswordCredentials;
-import org.apache.commons.httpclient.auth.AuthPolicy;
-import org.apache.commons.httpclient.auth.AuthScope;
-import org.apache.commons.httpclient.cookie.CookiePolicy;
-import org.apache.commons.httpclient.methods.HeadMethod;
-import org.apache.commons.httpclient.params.HttpMethodParams;
-import org.apache.http.HttpStatus;
-import org.apache.http.params.CoreProtocolPNames;
-
-import com.owncloud.android.oc_framework.network.BearerAuthScheme;
-import com.owncloud.android.oc_framework.network.BearerCredentials;
-
-import android.net.Uri;
-import android.util.Log;
-
-public class WebdavClient extends HttpClient {
-    private static final int MAX_REDIRECTIONS_COUNT = 3;
-    
-    private Uri mUri;
-    private Credentials mCredentials;
-    private boolean mFollowRedirects;
-    private String mSsoSessionCookie;
-    final private static String TAG = WebdavClient.class.getSimpleName();
-    public static final String USER_AGENT = "Android-ownCloud";
-    
-    static private byte[] sExhaustBuffer = new byte[1024];
-    
-    /**
-     * Constructor
-     */
-    public WebdavClient(HttpConnectionManager connectionMgr) {
-        super(connectionMgr);
-        Log.d(TAG, "Creating WebdavClient");
-        getParams().setParameter(HttpMethodParams.USER_AGENT, USER_AGENT);
-        getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
-        mFollowRedirects = true;
-        mSsoSessionCookie = null;
-    }
-
-    public void setBearerCredentials(String accessToken) {
-        AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
-        
-        List<String> authPrefs = new ArrayList<String>(1);
-        authPrefs.add(BearerAuthScheme.AUTH_POLICY);
-        getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);        
-        
-        mCredentials = new BearerCredentials(accessToken);
-        getState().setCredentials(AuthScope.ANY, mCredentials);
-        mSsoSessionCookie = null;
-    }
-
-    public void setBasicCredentials(String username, String password) {
-        List<String> authPrefs = new ArrayList<String>(1);
-        authPrefs.add(AuthPolicy.BASIC);
-        getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);        
-        
-        getParams().setAuthenticationPreemptive(true);
-        mCredentials = new UsernamePasswordCredentials(username, password);
-        getState().setCredentials(AuthScope.ANY, mCredentials);
-        mSsoSessionCookie = null;
-    }
-    
-    public void setSsoSessionCookie(String accessToken) {
-        getParams().setAuthenticationPreemptive(false);
-        getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
-        mSsoSessionCookie = accessToken;
-        mCredentials = null;
-    }
-    
-    
-    /**
-     * Check if a file exists in the OC server
-     * 
-     * TODO replace with ExistenceOperation
-     * 
-     * @return              'true' if the file exists; 'false' it doesn't exist
-     * @throws  Exception   When the existence could not be determined
-     */
-    public boolean existsFile(String path) throws IOException, HttpException {
-        HeadMethod head = new HeadMethod(mUri.toString() + WebdavUtils.encodePath(path));
-        try {
-            int status = executeMethod(head);
-            Log.d(TAG, "HEAD to " + path + " finished with HTTP status " + status + ((status != HttpStatus.SC_OK)?"(FAIL)":""));
-            exhaustResponse(head.getResponseBodyAsStream());
-            return (status == HttpStatus.SC_OK);
-            
-        } finally {
-            head.releaseConnection();    // let the connection available for other methods
-        }
-    }
-    
-    /**
-     * Requests the received method with the received timeout (milliseconds).
-     * 
-     * Executes the method through the inherited HttpClient.executedMethod(method).
-     * 
-     * Sets the socket and connection timeouts only for the method received.
-     * 
-     * The timeouts are both in milliseconds; 0 means 'infinite'; < 0 means 'do not change the default'
-     * 
-     * @param method            HTTP method request.
-     * @param readTimeout       Timeout to set for data reception
-     * @param conntionTimout    Timeout to set for connection establishment
-     */
-    public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws HttpException, IOException {
-        int oldSoTimeout = getParams().getSoTimeout();
-        int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();
-        try {
-            if (readTimeout >= 0) { 
-                method.getParams().setSoTimeout(readTimeout);   // this should be enough...
-                getParams().setSoTimeout(readTimeout);          // ... but this looks like necessary for HTTPS
-            }
-            if (connectionTimeout >= 0) {
-                getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
-            }
-            return executeMethod(method);
-        } finally {
-            getParams().setSoTimeout(oldSoTimeout);
-            getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);
-        }
-    }
-    
-    
-    @Override
-    public int executeMethod(HttpMethod method) throws IOException, HttpException {
-        boolean customRedirectionNeeded = false;
-        try {
-            method.setFollowRedirects(mFollowRedirects);
-        } catch (Exception e) {
-            //if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used if needed");
-            customRedirectionNeeded = mFollowRedirects;
-        }
-        if (mSsoSessionCookie != null && mSsoSessionCookie.length() > 0) {
-            method.setRequestHeader("Cookie", mSsoSessionCookie);
-        }
-        int status = super.executeMethod(method);
-        int redirectionsCount = 0;
-        while (customRedirectionNeeded &&
-                redirectionsCount < MAX_REDIRECTIONS_COUNT &&
-                (   status == HttpStatus.SC_MOVED_PERMANENTLY || 
-                    status == HttpStatus.SC_MOVED_TEMPORARILY ||
-                    status == HttpStatus.SC_TEMPORARY_REDIRECT)
-                ) {
-            
-            Header location = method.getResponseHeader("Location");
-            if (location != null) {
-                Log.d(TAG,  "Location to redirect: " + location.getValue());
-                method.setURI(new URI(location.getValue(), true));
-                status = super.executeMethod(method);
-                redirectionsCount++;
-                
-            } else {
-                Log.d(TAG,  "No location to redirect!");
-                status = HttpStatus.SC_NOT_FOUND;
-            }
-        }
-        
-        return status;
-    }
-
-
-    /**
-     * Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation.
-     * 
-     * @param responseBodyAsStream      InputStream with the HTTP response to exhaust.
-     */
-    public void exhaustResponse(InputStream responseBodyAsStream) {
-        if (responseBodyAsStream != null) {
-            try {
-                while (responseBodyAsStream.read(sExhaustBuffer) >= 0);
-                responseBodyAsStream.close();
-            
-            } catch (IOException io) {
-                Log.e(TAG, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED", io);
-            }
-        }
-    }
-
-    /**
-     * Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client.
-     */
-    public void setDefaultTimeouts(int defaultDataTimeout, int defaultConnectionTimeout) {
-            getParams().setSoTimeout(defaultDataTimeout);
-            getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout);
-    }
-
-    /**
-     * Sets the base URI for the helper methods that receive paths as parameters, instead of full URLs
-     * @param uri
-     */
-    public void setBaseUri(Uri uri) {
-        mUri = uri;
-    }
-
-    public Uri getBaseUri() {
-        return mUri;
-    }
-
-    public final Credentials getCredentials() {
-        return mCredentials;
-    }
-    
-    public final String getSsoSessionCookie() {
-        return mSsoSessionCookie;
-    }
-
-    public void setFollowRedirects(boolean followRedirects) {
-        mFollowRedirects = followRedirects;
-    }
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavEntry.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavEntry.java
deleted file mode 100644 (file)
index 3bcfa36..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012  ownCloud
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-package com.owncloud.android.oc_framework.network.webdav;
-
-import java.util.Date;
-
-import org.apache.jackrabbit.webdav.MultiStatusResponse;
-import org.apache.jackrabbit.webdav.property.DavProperty;
-import org.apache.jackrabbit.webdav.property.DavPropertyName;
-import org.apache.jackrabbit.webdav.property.DavPropertySet;
-
-
-
-import android.net.Uri;
-import android.util.Log;
-
-public class WebdavEntry {
-    private String mName, mPath, mUri, mContentType, mEtag;
-    private long mContentLength, mCreateTimestamp, mModifiedTimestamp;
-
-    public WebdavEntry(MultiStatusResponse ms, String splitElement) {
-        resetData();
-        if (ms.getStatus().length != 0) {
-            mUri = ms.getHref();
-
-            mPath = mUri.split(splitElement, 2)[1];
-
-            int status = ms.getStatus()[0].getStatusCode();
-            DavPropertySet propSet = ms.getProperties(status);
-            @SuppressWarnings("rawtypes")
-            DavProperty prop = propSet.get(DavPropertyName.DISPLAYNAME);
-            if (prop != null) {
-                mName = (String) prop.getName().toString();
-                mName = mName.substring(1, mName.length()-1);
-            }
-            else {
-                String[] tmp = mPath.split("/");
-                if (tmp.length > 0)
-                    mName = tmp[tmp.length - 1];
-            }
-
-            // use unknown mimetype as default behavior
-            mContentType = "application/octet-stream";
-            prop = propSet.get(DavPropertyName.GETCONTENTTYPE);
-            if (prop != null) {
-                mContentType = (String) prop.getValue();
-                // dvelasco: some builds of ownCloud server 4.0.x added a trailing ';' to the MIME type ; if looks fixed, but let's be cautious
-                if (mContentType.indexOf(";") >= 0) {
-                    mContentType = mContentType.substring(0, mContentType.indexOf(";"));
-                }
-            }
-            
-            // check if it's a folder in the standard way: see RFC2518 12.2 . RFC4918 14.3 
-            prop = propSet.get(DavPropertyName.RESOURCETYPE);
-            if (prop!= null) {
-                Object value = prop.getValue();
-                if (value != null) {
-                    mContentType = "DIR";   // a specific attribute would be better, but this is enough; unless while we have no reason to distinguish MIME types for folders
-                }
-            }
-
-            prop = propSet.get(DavPropertyName.GETCONTENTLENGTH);
-            if (prop != null)
-                mContentLength = Long.parseLong((String) prop.getValue());
-
-            prop = propSet.get(DavPropertyName.GETLASTMODIFIED);
-            if (prop != null) {
-                Date d = WebdavUtils
-                        .parseResponseDate((String) prop.getValue());
-                mModifiedTimestamp = (d != null) ? d.getTime() : 0;
-            }
-
-            prop = propSet.get(DavPropertyName.CREATIONDATE);
-            if (prop != null) {
-                Date d = WebdavUtils
-                        .parseResponseDate((String) prop.getValue());
-                mCreateTimestamp = (d != null) ? d.getTime() : 0;
-            }
-            
-            prop = propSet.get(DavPropertyName.GETETAG);
-            if (prop != null) {
-                mEtag = (String) prop.getValue();
-                mEtag = mEtag.substring(1, mEtag.length()-1);
-            }
-
-        } else {
-            Log.e("WebdavEntry",
-                    "General fuckup, no status for webdav response");
-        }
-    }
-
-    public String path() {
-        return mPath;
-    }
-    
-    public String decodedPath() {
-        return Uri.decode(mPath);
-    }
-
-    public String name() {
-        return mName;
-    }
-
-    public boolean isDirectory() {
-        return mContentType.equals("DIR");
-    }
-
-    public String contentType() {
-        return mContentType;
-    }
-
-    public String uri() {
-        return mUri;
-    }
-
-    public long contentLength() {
-        return mContentLength;
-    }
-
-    public long createTimestamp() {
-        return mCreateTimestamp;
-    }
-
-    public long modifiedTimestamp() {
-        return mModifiedTimestamp;
-    }
-    
-    public String etag() {
-        return mEtag;
-    }
-
-    private void resetData() {
-        mName = mUri = mContentType = null;
-        mContentLength = mCreateTimestamp = mModifiedTimestamp = 0;
-    }
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavUtils.java
deleted file mode 100644 (file)
index f5681de..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012  Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.network.webdav;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-import android.net.Uri;
-
-public class WebdavUtils {
-    public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat(
-            "dd.MM.yyyy hh:mm");
-    private static final SimpleDateFormat DATETIME_FORMATS[] = {
-            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US),
-            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
-            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US),
-            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US),
-            new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US),
-            new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
-            new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
-
-    public static String prepareXmlForPropFind() {
-        String ret = "<?xml version=\"1.0\" ?><D:propfind xmlns:D=\"DAV:\"><D:allprop/></D:propfind>";
-        return ret;
-    }
-
-    public static String prepareXmlForPatch() {
-        return "<?xml version=\"1.0\" ?><D:propertyupdate xmlns:D=\"DAV:\"></D:propertyupdate>";
-    }
-
-    public static Date parseResponseDate(String date) {
-        Date returnDate = null;
-        for (int i = 0; i < DATETIME_FORMATS.length; ++i) {
-            try {
-                returnDate = DATETIME_FORMATS[i].parse(date);
-                return returnDate;
-            } catch (ParseException e) {
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Encodes a path according to URI RFC 2396. 
-     * 
-     * If the received path doesn't start with "/", the method adds it.
-     * 
-     * @param remoteFilePath    Path
-     * @return                  Encoded path according to RFC 2396, always starting with "/"
-     */
-    public static String encodePath(String remoteFilePath) {
-        String encodedPath = Uri.encode(remoteFilePath, "/");
-        if (!encodedPath.startsWith("/"))
-            encodedPath = "/" + encodedPath;
-        return encodedPath;
-    }
-    
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/OnRemoteOperationListener.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/OnRemoteOperationListener.java
deleted file mode 100644 (file)
index a81d401..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.operations;
-
-public interface OnRemoteOperationListener {
-
-       void onRemoteOperationFinish(RemoteOperation caller, RemoteOperationResult result);
-       
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/OperationCancelledException.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/OperationCancelledException.java
deleted file mode 100644 (file)
index d5fd378..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.operations;
-
-public class OperationCancelledException extends Exception {
-
-    /**
-     * Generated serial version - to avoid Java warning
-     */
-    private static final long serialVersionUID = -6350981497740424983L;
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperation.java
deleted file mode 100644 (file)
index e18ae53..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-package com.owncloud.android.oc_framework.operations;
-
-import java.io.IOException;
-
-import org.apache.commons.httpclient.Credentials;
-
-import com.owncloud.android.oc_framework.network.BearerCredentials;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-
-
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountsException;
-import android.app.Activity;
-import android.content.Context;
-import android.os.Handler;
-import android.util.Log;
-
-
-/**
- * Operation which execution involves one or several interactions with an ownCloud server.
- * 
- * Provides methods to execute the operation both synchronously or asynchronously.
- * 
- * @author David A. Velasco 
- */
-public abstract class RemoteOperation implements Runnable {
-       
-    private static final String TAG = RemoteOperation.class.getSimpleName();
-
-    /** ownCloud account in the remote ownCloud server to operate */
-    private Account mAccount = null;
-    
-    /** Android Application context */
-    private Context mContext = null;
-    
-       /** Object to interact with the remote server */
-       private WebdavClient mClient = null;
-       
-       /** Callback object to notify about the execution of the remote operation */
-       private OnRemoteOperationListener mListener = null;
-       
-       /** Handler to the thread where mListener methods will be called */
-       private Handler mListenerHandler = null;
-
-       /** Activity */
-    private Activity mCallerActivity;
-
-       
-       /**
-        *  Abstract method to implement the operation in derived classes.
-        */
-       protected abstract RemoteOperationResult run(WebdavClient client); 
-       
-
-    /**
-     * Synchronously executes the remote operation on the received ownCloud account.
-     * 
-     * Do not call this method from the main thread.
-     * 
-     * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}. 
-     * 
-     * @param account   ownCloud account in remote ownCloud server to reach during the execution of the operation.
-     * @param context   Android context for the component calling the method.
-     * @return          Result of the operation.
-     */
-    public final RemoteOperationResult execute(Account account, Context context) {
-        if (account == null)
-            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
-        if (context == null)
-            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
-        mAccount = account;
-        mContext = context.getApplicationContext();
-        try {
-            mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext);
-        } catch (Exception e) {
-            Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
-            return new RemoteOperationResult(e);
-        }
-        return run(mClient);
-    }
-    
-       
-       /**
-        * Synchronously executes the remote operation
-        * 
-     * Do not call this method from the main thread.
-     * 
-        * @param client        Client object to reach an ownCloud server during the execution of the operation.
-        * @return                      Result of the operation.
-        */
-       public final RemoteOperationResult execute(WebdavClient client) {
-               if (client == null)
-                       throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
-               mClient = client;
-               return run(client);
-       }
-
-       
-    /**
-     * Asynchronously executes the remote operation
-     * 
-     * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}. 
-     * 
-     * @param account           ownCloud account in remote ownCloud server to reach during the execution of the operation.
-     * @param context           Android context for the component calling the method.
-     * @param listener          Listener to be notified about the execution of the operation.
-     * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
-     * @return                  Thread were the remote operation is executed.
-     */
-    public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) {
-        if (account == null)
-            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
-        if (context == null)
-            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
-        mAccount = account;
-        mContext = context.getApplicationContext();
-        mCallerActivity = callerActivity;
-        mClient = null;     // the client instance will be created from mAccount and mContext in the runnerThread to create below
-        
-        mListener = listener;
-        
-        mListenerHandler = listenerHandler;
-        
-        Thread runnerThread = new Thread(this);
-        runnerThread.start();
-        return runnerThread;
-    }
-
-    
-       /**
-        * Asynchronously executes the remote operation
-        * 
-        * @param client                        Client object to reach an ownCloud server during the execution of the operation.
-        * @param listener                      Listener to be notified about the execution of the operation.
-        * @param listenerHandler       Handler associated to the thread where the methods of the listener objects must be called.
-        * @return                                      Thread were the remote operation is executed.
-        */
-       public final Thread execute(WebdavClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
-               if (client == null) {
-                       throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
-               }
-               mClient = client;
-               
-               if (listener == null) {
-                       throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
-               }
-               mListener = listener;
-               
-               if (listenerHandler == null) {
-                       throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
-               }
-               mListenerHandler = listenerHandler;
-               
-               Thread runnerThread = new Thread(this);
-               runnerThread.start();
-               return runnerThread;
-       }
-       
-    /**
-     * Synchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient)}
-     * 
-     * @param listener          Listener to be notified about the execution of the operation.
-     * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
-     * @return                  Thread were the remote operation is executed.
-     */
-    public final RemoteOperationResult retry() {
-        return execute(mClient);
-    }
-    
-    /**
-     * Asynchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}
-     * 
-     * @param listener          Listener to be notified about the execution of the operation.
-     * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
-     * @return                  Thread were the remote operation is executed.
-     */
-    public final Thread retry(OnRemoteOperationListener listener, Handler listenerHandler) {
-        return execute(mClient, listener, listenerHandler);
-    }
-       
-       
-       /**
-        * Asynchronous execution of the operation 
-        * started by {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}, 
-        * and result posting.
-        * 
-        * TODO refactor && clean the code; now it's a mess
-        */
-    @Override
-    public final void run() {
-        RemoteOperationResult result = null;
-        boolean repeat = false;
-        do {
-            try{
-                if (mClient == null) {
-                    if (mAccount != null && mContext != null) {
-                        if (mCallerActivity != null) {
-                            mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext, mCallerActivity);
-                        } else {
-                            mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext);
-                        }
-                    } else {
-                        throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
-                    }
-                }
-            
-            } catch (IOException e) {
-                Log.e(TAG, "Error while trying to access to " + mAccount.name, new AccountsException("I/O exception while trying to authorize the account", e));
-                result = new RemoteOperationResult(e);
-            
-            } catch (AccountsException e) {
-                Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
-                result = new RemoteOperationResult(e);
-            }
-       
-            if (result == null)
-                result = run(mClient);
-        
-            repeat = false;
-            if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() &&
-//                    (result.getCode() == ResultCode.UNAUTHORIZED || (result.isTemporalRedirection() && result.isIdPRedirection()))) {
-                    (result.getCode() == ResultCode.UNAUTHORIZED || result.isIdPRedirection())) {
-                /// possible fail due to lack of authorization in an operation performed in foreground
-                Credentials cred = mClient.getCredentials();
-                String ssoSessionCookie = mClient.getSsoSessionCookie();
-                if (cred != null || ssoSessionCookie != null) {
-                    /// confirmed : unauthorized operation
-                    AccountManager am = AccountManager.get(mContext);
-                    boolean bearerAuthorization = (cred != null && cred instanceof BearerCredentials);
-                    boolean samlBasedSsoAuthorization = (cred == null && ssoSessionCookie != null);
-                    if (bearerAuthorization) {
-                        am.invalidateAuthToken(mAccount.type, ((BearerCredentials)cred).getAccessToken());
-                    } else if (samlBasedSsoAuthorization ) {
-                        am.invalidateAuthToken(mAccount.type, ssoSessionCookie);
-                    } else {
-                        am.clearPassword(mAccount);
-                    }
-                    mClient = null;
-                    repeat = true;  // when repeated, the creation of a new OwnCloudClient after erasing the saved credentials will trigger the login activity
-                    result = null;
-                }
-            }
-        } while (repeat);
-        
-        final RemoteOperationResult resultToSend = result;
-        if (mListenerHandler != null && mListener != null) {
-               mListenerHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
-                }
-            });
-        }
-    }
-
-
-    /**
-     * Returns the current client instance to access the remote server.
-     * 
-     * @return      Current client instance to access the remote server.
-     */
-    public final WebdavClient getClient() {
-        return mClient;
-    }
-
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java
deleted file mode 100644 (file)
index f26988c..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.operations;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.net.MalformedURLException;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import javax.net.ssl.SSLException;
-
-import org.apache.commons.httpclient.ConnectTimeoutException;
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.jackrabbit.webdav.DavException;
-
-import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
-import com.owncloud.android.oc_framework.network.CertificateCombinedException;
-
-import android.accounts.Account;
-import android.accounts.AccountsException;
-import android.util.Log;
-
-
-/**
- * The result of a remote operation required to an ownCloud server.
- * 
- * Provides a common classification of remote operation results for all the
- * application.
- * 
- * @author David A. Velasco
- */
-public class RemoteOperationResult implements Serializable {
-
-    /** Generated - should be refreshed every time the class changes!! */
-    private static final long serialVersionUID = -4415103901492836870L;
-    
-
-    
-    private static final String TAG = "RemoteOperationResult";
-    
-    public enum ResultCode { 
-        OK,
-        OK_SSL,
-        OK_NO_SSL,
-        UNHANDLED_HTTP_CODE,
-        UNAUTHORIZED,        
-        FILE_NOT_FOUND, 
-        INSTANCE_NOT_CONFIGURED, 
-        UNKNOWN_ERROR, 
-        WRONG_CONNECTION,  
-        TIMEOUT, 
-        INCORRECT_ADDRESS, 
-        HOST_NOT_AVAILABLE, 
-        NO_NETWORK_CONNECTION, 
-        SSL_ERROR,
-        SSL_RECOVERABLE_PEER_UNVERIFIED,
-        BAD_OC_VERSION,
-        CANCELLED, 
-        INVALID_LOCAL_FILE_NAME, 
-        INVALID_OVERWRITE,
-        CONFLICT, 
-        OAUTH2_ERROR,
-        SYNC_CONFLICT,
-        LOCAL_STORAGE_FULL, 
-        LOCAL_STORAGE_NOT_MOVED, 
-        LOCAL_STORAGE_NOT_COPIED, 
-        OAUTH2_ERROR_ACCESS_DENIED,
-        QUOTA_EXCEEDED, 
-        ACCOUNT_NOT_FOUND, 
-        ACCOUNT_EXCEPTION, 
-        ACCOUNT_NOT_NEW, 
-        ACCOUNT_NOT_THE_SAME,
-        INVALID_CHARACTER_IN_NAME
-    }
-
-    private boolean mSuccess = false;
-    private int mHttpCode = -1;
-    private Exception mException = null;
-    private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
-    private String mRedirectedLocation;
-
-    public RemoteOperationResult(ResultCode code) {
-        mCode = code;
-        mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
-    }
-
-    private RemoteOperationResult(boolean success, int httpCode) {
-        mSuccess = success;
-        mHttpCode = httpCode;
-
-        if (success) {
-            mCode = ResultCode.OK;
-
-        } else if (httpCode > 0) {
-            switch (httpCode) {
-            case HttpStatus.SC_UNAUTHORIZED:
-                mCode = ResultCode.UNAUTHORIZED;
-                break;
-            case HttpStatus.SC_NOT_FOUND:
-                mCode = ResultCode.FILE_NOT_FOUND;
-                break;
-            case HttpStatus.SC_INTERNAL_SERVER_ERROR:
-                mCode = ResultCode.INSTANCE_NOT_CONFIGURED;
-                break;
-            case HttpStatus.SC_CONFLICT:
-                mCode = ResultCode.CONFLICT;
-                break;
-            case HttpStatus.SC_INSUFFICIENT_STORAGE:
-                mCode = ResultCode.QUOTA_EXCEEDED;
-                break;
-            default:
-                mCode = ResultCode.UNHANDLED_HTTP_CODE;
-                Log.d(TAG, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + httpCode);
-            }
-        }
-    }
-    
-    public RemoteOperationResult(boolean success, int httpCode, Header[] headers) {
-        this(success, httpCode);
-        if (headers != null) {
-            Header current;
-            for (int i=0; i<headers.length; i++) {
-                current = headers[i];
-                if ("Location".equals(current.getName())) {
-                    mRedirectedLocation = current.getValue();
-                    break;
-                }
-            }
-        }
-    }    
-
-    public RemoteOperationResult(Exception e) {
-        mException = e;
-
-        if (e instanceof OperationCancelledException) {
-            mCode = ResultCode.CANCELLED;
-
-        } else if (e instanceof SocketException) {
-            mCode = ResultCode.WRONG_CONNECTION;
-
-        } else if (e instanceof SocketTimeoutException) {
-            mCode = ResultCode.TIMEOUT;
-
-        } else if (e instanceof ConnectTimeoutException) {
-            mCode = ResultCode.TIMEOUT;
-
-        } else if (e instanceof MalformedURLException) {
-            mCode = ResultCode.INCORRECT_ADDRESS;
-
-        } else if (e instanceof UnknownHostException) {
-            mCode = ResultCode.HOST_NOT_AVAILABLE;
-
-        } else if (e instanceof AccountNotFoundException) {
-            mCode = ResultCode.ACCOUNT_NOT_FOUND;
-            
-        } else if (e instanceof AccountsException) {
-            mCode = ResultCode.ACCOUNT_EXCEPTION;
-            
-        } else if (e instanceof SSLException || e instanceof RuntimeException) {
-            CertificateCombinedException se = getCertificateCombinedException(e);
-            if (se != null) {
-                mException = se;
-                if (se.isRecoverable()) {
-                    mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
-                }
-            } else if (e instanceof RuntimeException) {
-                mCode = ResultCode.HOST_NOT_AVAILABLE;
-
-            } else {
-                mCode = ResultCode.SSL_ERROR;
-            }
-
-        } else {
-            mCode = ResultCode.UNKNOWN_ERROR;
-        }
-
-    }
-
-    public boolean isSuccess() {
-        return mSuccess;
-    }
-
-    public boolean isCancelled() {
-        return mCode == ResultCode.CANCELLED;
-    }
-
-    public int getHttpCode() {
-        return mHttpCode;
-    }
-
-    public ResultCode getCode() {
-        return mCode;
-    }
-
-    public Exception getException() {
-        return mException;
-    }
-
-    public boolean isSslRecoverableException() {
-        return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
-    }
-
-    private CertificateCombinedException getCertificateCombinedException(Exception e) {
-        CertificateCombinedException result = null;
-        if (e instanceof CertificateCombinedException) {
-            return (CertificateCombinedException) e;
-        }
-        Throwable cause = mException.getCause();
-        Throwable previousCause = null;
-        while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
-            previousCause = cause;
-            cause = cause.getCause();
-        }
-        if (cause != null && cause instanceof CertificateCombinedException) {
-            result = (CertificateCombinedException) cause;
-        }
-        return result;
-    }
-
-    public String getLogMessage() {
-
-        if (mException != null) {
-            if (mException instanceof OperationCancelledException) {
-                return "Operation cancelled by the caller";
-
-            } else if (mException instanceof SocketException) {
-                return "Socket exception";
-
-            } else if (mException instanceof SocketTimeoutException) {
-                return "Socket timeout exception";
-
-            } else if (mException instanceof ConnectTimeoutException) {
-                return "Connect timeout exception";
-
-            } else if (mException instanceof MalformedURLException) {
-                return "Malformed URL exception";
-
-            } else if (mException instanceof UnknownHostException) {
-                return "Unknown host exception";
-
-            } else if (mException instanceof CertificateCombinedException) {
-                if (((CertificateCombinedException) mException).isRecoverable())
-                    return "SSL recoverable exception";
-                else
-                    return "SSL exception";
-
-            } else if (mException instanceof SSLException) {
-                return "SSL exception";
-
-            } else if (mException instanceof DavException) {
-                return "Unexpected WebDAV exception";
-
-            } else if (mException instanceof HttpException) {
-                return "HTTP violation";
-
-            } else if (mException instanceof IOException) {
-                return "Unrecovered transport exception";
-
-            } else if (mException instanceof AccountNotFoundException) {
-                Account failedAccount = ((AccountNotFoundException)mException).getFailedAccount();
-                return mException.getMessage() + " (" + (failedAccount != null ? failedAccount.name : "NULL") + ")";
-                
-            } else if (mException instanceof AccountsException) {
-                return "Exception while using account";
-                
-            } else {
-                return "Unexpected exception";
-            }
-        }
-
-        if (mCode == ResultCode.INSTANCE_NOT_CONFIGURED) {
-            return "The ownCloud server is not configured!";
-
-        } else if (mCode == ResultCode.NO_NETWORK_CONNECTION) {
-            return "No network connection";
-
-        } else if (mCode == ResultCode.BAD_OC_VERSION) {
-            return "No valid ownCloud version was found at the server";
-
-        } else if (mCode == ResultCode.LOCAL_STORAGE_FULL) {
-            return "Local storage full";
-
-        } else if (mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED) {
-            return "Error while moving file to final directory";
-
-        } else if (mCode == ResultCode.ACCOUNT_NOT_NEW) {
-            return "Account already existing when creating a new one";
-
-        } else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) {
-            return "Authenticated with a different account than the one updating";
-        } else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) {
-               return "The file name contains an forbidden character";
-        }
-
-        return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")";
-
-    }
-
-    public boolean isServerFail() {
-        return (mHttpCode >= HttpStatus.SC_INTERNAL_SERVER_ERROR);
-    }
-
-    public boolean isException() {
-        return (mException != null);
-    }
-
-    public boolean isTemporalRedirection() {
-        return (mHttpCode == 302 || mHttpCode == 307);
-    }
-
-    public String getRedirectedLocation() {
-        return mRedirectedLocation;
-    }
-    
-    public boolean isIdPRedirection() {
-        return (mRedirectedLocation != null &&
-                (mRedirectedLocation.toUpperCase().contains("SAML") || 
-                mRedirectedLocation.toLowerCase().contains("wayf")));
-    }
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/CreateRemoteFolderOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/CreateRemoteFolderOperation.java
deleted file mode 100644 (file)
index 0974d08..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-package com.owncloud.android.oc_framework.operations.remote;
-
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
-
-import android.util.Log;
-
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.oc_framework.utils.FileUtils;
-
-
-
-/**
- * Remote operation performing the creation of a new folder in the ownCloud server.
- * 
- * @author David A. Velasco 
- * @author masensio
- *
- */
-public class CreateRemoteFolderOperation extends RemoteOperation {
-    
-    private static final String TAG = CreateRemoteFolderOperation.class.getSimpleName();
-
-    private static final int READ_TIMEOUT = 10000;
-    private static final int CONNECTION_TIMEOUT = 5000;
-    
-
-    protected String mRemotePath;
-    protected boolean mCreateFullPath;
-    
-    /**
-     * Constructor
-     * 
-     * @param remotePath            Full path to the new directory to create in the remote server.
-     * @param createFullPath        'True' means that all the ancestor folders should be created if don't exist yet.
-     */
-    public CreateRemoteFolderOperation(String remotePath, boolean createFullPath) {
-        mRemotePath = remotePath;
-        mCreateFullPath = createFullPath;
-    }
-
-    /**
-     * Performs the operation
-     * 
-     * @param   client      Client object to communicate with the remote ownCloud server.
-     */
-    @Override
-    protected RemoteOperationResult run(WebdavClient client) {
-        RemoteOperationResult result = null;
-        MkColMethod mkcol = null;
-        
-        boolean noInvalidChars = FileUtils.isValidPath(mRemotePath);
-        if (noInvalidChars) {
-               try {
-                       mkcol = new MkColMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
-                       int status =  client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);
-                       if (!mkcol.succeeded() && mkcol.getStatusCode() == HttpStatus.SC_CONFLICT && mCreateFullPath) {
-                               result = createParentFolder(FileUtils.getParentPath(mRemotePath), client);
-                               status = client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);    // second (and last) try
-                       }
-
-                       result = new RemoteOperationResult(mkcol.succeeded(), status, mkcol.getResponseHeaders());
-                       Log.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
-                       client.exhaustResponse(mkcol.getResponseBodyAsStream());
-
-               } catch (Exception e) {
-                       result = new RemoteOperationResult(e);
-                       Log.e(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage(), e);
-
-               } finally {
-                       if (mkcol != null)
-                               mkcol.releaseConnection();
-               }
-        } else {
-               result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
-        }
-        
-        return result;
-    }
-
-    
-    private RemoteOperationResult createParentFolder(String parentPath, WebdavClient client) {
-        RemoteOperation operation = new CreateRemoteFolderOperation(parentPath,
-                                                                mCreateFullPath);
-        return operation.execute(client);
-    }
-    
-   
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/RenameRemoteFileOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/RenameRemoteFileOperation.java
deleted file mode 100644 (file)
index ad6fffc..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-package com.owncloud.android.oc_framework.operations.remote;
-
-import java.io.File;
-
-import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
-
-import android.util.Log;
-
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.oc_framework.utils.FileUtils;
-
-
-/**
- * Remote operation performing the rename of a remote file or folder in the ownCloud server.
- * 
- * @author David A. Velasco
- * @author masensio
- */
-public class RenameRemoteFileOperation extends RemoteOperation {
-
-       private static final String TAG = RenameRemoteFileOperation.class.getSimpleName();
-
-       private static final int RENAME_READ_TIMEOUT = 10000;
-       private static final int RENAME_CONNECTION_TIMEOUT = 5000;
-
-    private String mOldName;
-    private String mOldRemotePath;
-    private String mNewName;
-    private String mNewRemotePath;
-    
-    
-    /**
-     * Constructor
-     * 
-     * @param oldName                  Old name of the file.
-     * @param oldRemotePath            Old remote path of the file. 
-     * @param newName                  New name to set as the name of file.
-     * @param isFolder                 'true' for folder and 'false' for files
-     */
-       public RenameRemoteFileOperation(String oldName, String oldRemotePath, String newName, boolean isFolder) {
-               mOldName = oldName;
-               mOldRemotePath = oldRemotePath;
-               mNewName = newName;
-               
-        String parent = (new File(mOldRemotePath)).getParent();
-        parent = (parent.endsWith(FileUtils.PATH_SEPARATOR)) ? parent : parent + FileUtils.PATH_SEPARATOR; 
-        mNewRemotePath =  parent + mNewName;
-        if (isFolder) {
-            mNewRemotePath += FileUtils.PATH_SEPARATOR;
-        }
-       }
-
-        /**
-     * Performs the rename operation.
-     * 
-     * @param   client      Client object to communicate with the remote ownCloud server.
-     */
-       @Override
-       protected RemoteOperationResult run(WebdavClient client) {
-               RemoteOperationResult result = null;
-               
-               LocalMoveMethod move = null;
-        
-        boolean noInvalidChars = FileUtils.isValidPath(mNewRemotePath);
-        
-        if (noInvalidChars) {
-        try {
-               
-            if (mNewName.equals(mOldName)) {
-                return new RemoteOperationResult(ResultCode.OK);
-            }
-        
-            
-            // check if a file with the new name already exists
-            if (client.existsFile(mNewRemotePath)) {
-               return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
-            }
-            
-            move = new LocalMoveMethod( client.getBaseUri() + WebdavUtils.encodePath(mOldRemotePath),
-                       client.getBaseUri() + WebdavUtils.encodePath(mNewRemotePath));
-            int status = client.executeMethod(move, RENAME_READ_TIMEOUT, RENAME_CONNECTION_TIMEOUT);
-            
-            move.getResponseBodyAsString(); // exhaust response, although not interesting
-            result = new RemoteOperationResult(move.succeeded(), status, move.getResponseHeaders());
-            Log.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " + result.getLogMessage());
-            
-        } catch (Exception e) {
-            result = new RemoteOperationResult(e);
-            Log.e(TAG, "Rename " + mOldRemotePath + " to " + ((mNewRemotePath==null) ? mNewName : mNewRemotePath) + ": " + result.getLogMessage(), e);
-            
-        } finally {
-            if (move != null)
-                move.releaseConnection();
-        }
-        } else {
-               result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
-        }
-               
-        return result;
-       }
-       
-       /**
-        * Move operation
-        * 
-        */
-    private class LocalMoveMethod extends DavMethodBase {
-
-        public LocalMoveMethod(String uri, String dest) {
-            super(uri);
-            addRequestHeader(new org.apache.commons.httpclient.Header("Destination", dest));
-        }
-
-        @Override
-        public String getName() {
-            return "MOVE";
-        }
-
-        @Override
-        protected boolean isSuccess(int status) {
-            return status == 201 || status == 204;
-        }
-            
-    }
-
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java
deleted file mode 100644 (file)
index 8fb01dc..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.owncloud.android.oc_framework.utils;
-
-import java.io.File;
-
-import android.util.Log;
-
-public class FileUtils {
-
-       public static final String PATH_SEPARATOR = "/";
-
-
-       public static String getParentPath(String remotePath) {
-               String parentPath = new File(remotePath).getParent();
-               parentPath = parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR;
-               return parentPath;
-       }
-       
-       /**
-        * Validate the fileName to detect if contains any forbidden character: / , \ , < , > , : , " , | , ? , *
-        * @param fileName
-        * @return
-        */
-       public static boolean isValidName(String fileName) {
-               boolean result = true;
-               
-               Log.d("FileUtils", "fileName =======" + fileName);
-               if (fileName.contains(PATH_SEPARATOR) ||
-                               fileName.contains("\\") || fileName.contains("<") || fileName.contains(">") ||
-                               fileName.contains(":") || fileName.contains("\"") || fileName.contains("|") || 
-                               fileName.contains("?") || fileName.contains("*")) {
-                       result = false;
-               }
-               return result;
-       }
-       
-       /**
-        * Validate the path to detect if contains any forbidden character: \ , < , > , : , " , | , ? , *
-        * @param path
-        * @return
-        */
-       public static boolean isValidPath(String path) {
-               boolean result = true;
-               
-               Log.d("FileUtils", "path ....... " + path);
-               if (path.contains("\\") || path.contains("<") || path.contains(">") ||
-                               path.contains(":") || path.contains("\"") || path.contains("|") || 
-                               path.contains("?") || path.contains("*")) {
-                       result = false;
-               }
-               return result;
-       }
-}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/utils/OwnCloudVersion.java b/oc_framework/src/com/owncloud/android/oc_framework/utils/OwnCloudVersion.java
deleted file mode 100644 (file)
index 5a9df4d..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012  Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.oc_framework.utils;
-
-public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
-    public static final OwnCloudVersion owncloud_v1 = new OwnCloudVersion(
-            0x010000);
-    public static final OwnCloudVersion owncloud_v2 = new OwnCloudVersion(
-            0x020000);
-    public static final OwnCloudVersion owncloud_v3 = new OwnCloudVersion(
-            0x030000);
-    public static final OwnCloudVersion owncloud_v4 = new OwnCloudVersion(
-            0x040000);
-    public static final OwnCloudVersion owncloud_v4_5 = new OwnCloudVersion(
-            0x040500);
-
-    // format is in version
-    // 0xAABBCC
-    // for version AA.BB.CC
-    // ie version 2.0.3 will be stored as 0x030003
-    private int mVersion;
-    private boolean mIsValid;
-
-    public OwnCloudVersion(int version) {
-        mVersion = version;
-        mIsValid = true;
-    }
-
-    public OwnCloudVersion(String version) {
-        mVersion = 0;
-        mIsValid = false;
-        parseVersionString(version);
-    }
-
-    public String toString() {
-        return ((mVersion >> 16) % 256) + "." + ((mVersion >> 8) % 256) + "."
-                + ((mVersion) % 256);
-    }
-
-    public boolean isVersionValid() {
-        return mIsValid;
-    }
-
-    @Override
-    public int compareTo(OwnCloudVersion another) {
-        return another.mVersion == mVersion ? 0
-                : another.mVersion < mVersion ? 1 : -1;
-    }
-
-    private void parseVersionString(String version) {
-        try {
-            String[] nums = version.split("\\.");
-            if (nums.length > 0) {
-                mVersion += Integer.parseInt(nums[0]);
-            }
-            mVersion = mVersion << 8;
-            if (nums.length > 1) {
-                mVersion += Integer.parseInt(nums[1]);
-            }
-            mVersion = mVersion << 8;
-            if (nums.length > 2) {
-                mVersion += Integer.parseInt(nums[2]);
-            }
-            mIsValid = true;
-        } catch (Exception e) {
-            mIsValid = false;
-        }
-    }
-}
index 1b12fb4..ea25105 100644 (file)
@@ -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="0100010"
-    android:versionName="1.0.10" >
+    android:versionCode="0100012"
+    android:versionName="1.0.12" >
 
     <uses-sdk
         android:minSdkVersion="16"
diff --git a/oc_jb_workaround/res/drawable-xhdpi/main_app_icon.png b/oc_jb_workaround/res/drawable-xhdpi/main_app_icon.png
deleted file mode 100644 (file)
index e388c7b..0000000
Binary files a/oc_jb_workaround/res/drawable-xhdpi/main_app_icon.png and /dev/null differ
diff --git a/oc_jb_workaround/res/drawable-xhdpi/workaround_app_icon.png b/oc_jb_workaround/res/drawable-xhdpi/workaround_app_icon.png
deleted file mode 100644 (file)
index 7daeea4..0000000
Binary files a/oc_jb_workaround/res/drawable-xhdpi/workaround_app_icon.png and /dev/null differ
diff --git a/owncloud-android-library b/owncloud-android-library
new file mode 160000 (submodule)
index 0000000..6992df8
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 6992df89b04c3c35bf906c3f810fa05daad7b43f
diff --git a/pom.xml b/pom.xml
index a55a77a..15bd0b6 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -5,13 +5,17 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.owncloud.android</groupId>
     <artifactId>owncloud</artifactId>
-    <version>1.3.21-SNAPSHOT</version>
+    <version>${owncloud.version}</version>
     <packaging>apk</packaging>
     <name>Owncloud Android</name>
 
     <properties>
+        <owncloud.version>1.5.1-SNAPSHOT</owncloud.version>
         <java-version>1.6</java-version>
-        <google.android-version>4.2.2_r2</google.android-version>
+        <!-- Given by maven-android-sdk-deployer -->
+        <google.android-version>4.4.2_r2</google.android-version>
+        <!-- Usually the latest Android API -->
+        <google.android-api>19</google.android-api>
         <actionbarsherlock-version>4.2.0</actionbarsherlock-version>
     </properties>
 
@@ -22,7 +26,7 @@
         <developerConnection>scm:git:git@github.com:owncloud/android.git</developerConnection>
         <url>https://github.com/owncloud/android</url>
     </scm>
-
+    
     <dependencies>
 
         <dependency>
             <type>apklib</type>
         </dependency>
 
+        <!-- MUST BE INSTALLED FIRST: cd owncloud-android-library; mvn install -->
         <dependency>
-            <groupId>org.apache.jackrabbit</groupId>
-            <artifactId>jackrabbit-webdav</artifactId>
-            <version>2.5.2</version>
-        </dependency>
+         <groupId>com.owncloud.android</groupId>
+         <artifactId>owncloud-android-library</artifactId>
+         <version>${owncloud.version}</version>
+      </dependency>
 
     </dependencies>
 
             <plugin>
                 <groupId>com.jayway.maven.plugins.android.generation2</groupId>
                 <artifactId>android-maven-plugin</artifactId>
-                <version>3.5.0</version>
+                <version>3.8.0</version>
                 <configuration>
                     <sdk>
-                        <!-- platform or api level (api level 4 = platform 1.6)-->
                         <path>${env.ANDROID_HOME}</path>
-                        <platform>17</platform>
+                        <platform>${google.android-api}</platform>
                     </sdk>
                 </configuration>
                 <extensions>true</extensions>
index dbd0f5e..28edd99 100644 (file)
@@ -10,4 +10,4 @@
 # Project target.
 target=android-19
 android.library.reference.1=actionbarsherlock/library
-android.library.reference.2=oc_framework
+android.library.reference.2=owncloud-android-library
diff --git a/res/drawable-hdpi/sharedlink.png b/res/drawable-hdpi/sharedlink.png
new file mode 100644 (file)
index 0000000..222172a
Binary files /dev/null and b/res/drawable-hdpi/sharedlink.png differ
diff --git a/res/drawable-hdpi/winter_holidays_icon.png b/res/drawable-hdpi/winter_holidays_icon.png
new file mode 100644 (file)
index 0000000..c1764b6
Binary files /dev/null and b/res/drawable-hdpi/winter_holidays_icon.png differ
diff --git a/res/drawable-ldpi/winter_holidays_icon.png b/res/drawable-ldpi/winter_holidays_icon.png
new file mode 100644 (file)
index 0000000..9261d32
Binary files /dev/null and b/res/drawable-ldpi/winter_holidays_icon.png differ
diff --git a/res/drawable-mdpi/sharedlink.png b/res/drawable-mdpi/sharedlink.png
new file mode 100644 (file)
index 0000000..8300eac
Binary files /dev/null and b/res/drawable-mdpi/sharedlink.png differ
diff --git a/res/drawable-mdpi/winter_holidays_icon.png b/res/drawable-mdpi/winter_holidays_icon.png
new file mode 100644 (file)
index 0000000..b0226dc
Binary files /dev/null and b/res/drawable-mdpi/winter_holidays_icon.png differ
diff --git a/res/drawable-xhdpi/icon.png b/res/drawable-xhdpi/icon.png
new file mode 100644 (file)
index 0000000..041efc6
Binary files /dev/null and b/res/drawable-xhdpi/icon.png differ
diff --git a/res/drawable-xhdpi/sharedlink.png b/res/drawable-xhdpi/sharedlink.png
new file mode 100644 (file)
index 0000000..3879663
Binary files /dev/null and b/res/drawable-xhdpi/sharedlink.png differ
index 1025bcf..4eea9b3 100644 (file)
@@ -27,7 +27,7 @@
     <LinearLayout\r
         android:layout_width="match_parent"\r
         android:layout_height="wrap_content"\r
-        android:layout_above="@id/buttonOK"\r
+        android:layout_above="@+id/bottom_block"\r
         android:layout_alignParentTop="true"\r
         android:orientation="horizontal" >\r
         \r
                                                           \r
        </LinearLayout>\r
        \r
-       <Button\r
-           android:id="@id/buttonOK"\r
-           android:layout_width="match_parent"\r
-           android:layout_height="wrap_content"\r
-           android:layout_above="@+id/welcome_link"\r
-           android:layout_centerHorizontal="true"\r
-           android:enabled="false"\r
-           android:onClick="onOkClick"\r
-           android:text="@string/setup_btn_connect" />\r
-\r
-       <Button\r
-           android:id="@id/welcome_link"\r
-           android:layout_width="wrap_content"\r
-           android:layout_height="wrap_content"\r
-           android:layout_alignParentBottom="true"\r
-           android:layout_centerHorizontal="true"\r
-           android:background="@android:color/transparent"\r
-           android:onClick="onRegisterClick"\r
-           android:paddingBottom="5dp"\r
-           android:paddingTop="5dp"\r
-           android:text="@string/auth_register"\r
-           android:textColor="#0000FF"/>\r
-       \r
+    <LinearLayout\r
+        android:id="@id/bottom_block"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+               android:layout_alignParentBottom="true"\r
+        android:orientation="vertical" >\r
+        \r
+               <Button\r
+                   android:id="@+id/buttonOK"\r
+                   android:layout_width="match_parent"\r
+                   android:layout_height="wrap_content"\r
+                   android:layout_gravity="center_horizontal"\r
+                   android:enabled="false"\r
+                   android:onClick="onOkClick"\r
+                   android:text="@string/setup_btn_connect" />\r
+               \r
+               <Button\r
+                   android:id="@+id/welcome_link"\r
+                   android:layout_width="wrap_content"\r
+                   android:layout_height="wrap_content"\r
+                   android:layout_gravity="center_horizontal"\r
+                   android:background="@android:color/transparent"\r
+                   android:onClick="onRegisterClick"\r
+                   android:paddingBottom="5dp"\r
+                   android:paddingTop="5dp"\r
+                   android:text="@string/auth_register"\r
+                   android:textColor="#0000FF"/>\r
+       </LinearLayout>\r
+               \r
 </RelativeLayout>\r
diff --git a/res/layout-v11/activity_row.xml b/res/layout-v11/activity_row.xml
new file mode 100644 (file)
index 0000000..95c7dfc
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+
+  Copyright (C) 2012-2014 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
+                       android:id="@+id/list_item"
+                               android:layout_width="match_parent"
+                               android:layout_height="48dp"
+                               android:paddingStart="16dip"
+                               android:paddingEnd="16dip"
+                               android:paddingRight="16dip"
+                               android:paddingLeft="16dip"
+                               android:minWidth="196dip"
+                               android:background="?android:attr/activatedBackgroundIndicator"
+                       android:orientation="vertical" >
+
+       <LinearLayout
+               android:layout_width="wrap_content"
+               android:layout_height="match_parent"
+               android:duplicateParentState="true" >
+
+               <ImageView
+                       android:id="@+id/icon"
+                       android:layout_width="40dip"
+                       android:layout_height="40dip"
+                       android:layout_gravity="center_vertical"
+                       android:layout_marginEnd="8dip"
+                       android:layout_marginRight="8dip"
+                       android:duplicateParentState="true" />
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+            android:duplicateParentState="true"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal" />
+
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/activity_row.xml b/res/layout/activity_row.xml
new file mode 100644 (file)
index 0000000..b917600
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+
+  Copyright (C) 2012-2014 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
+                       android:id="@+id/list_item"
+                               android:layout_width="match_parent"
+                               android:layout_height="48dp"
+                               android:paddingRight="16dip"
+                               android:paddingLeft="16dip"
+                               android:minWidth="196dip"
+                       android:orientation="vertical" >
+
+       <LinearLayout
+               android:layout_width="wrap_content"
+               android:layout_height="match_parent"
+               android:duplicateParentState="true" >
+
+               <ImageView
+                       android:id="@+id/icon"
+                       android:layout_width="40dip"
+                       android:layout_height="40dip"
+                       android:layout_gravity="center_vertical"
+                       android:layout_marginRight="8dip"
+                       android:duplicateParentState="true" />
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:duplicateParentState="true"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal" />
+
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
index ea73832..abe0e7f 100644 (file)
             android:src="@drawable/ic_favorite" />\r
         \r
     </FrameLayout>\r
-\r\r\r\r
+\r
     <LinearLayout\r
         android:layout_width="0dp"\r
         android:layout_height="match_parent"\r
         android:layout_weight="1"\r
         android:gravity="center_vertical"\r
         android:orientation="vertical" >\r
-\r\r
+\r
         <TextView\r
             android:id="@+id/Filename"\r
             android:layout_width="wrap_content"\r
         </LinearLayout>\r
 \r
     </LinearLayout>\r
-\r\r\r\r
+\r
+    <ImageView\r
+        android:id="@+id/shareIcon"\r
+        android:layout_width="wrap_content"\r
+        android:layout_height="wrap_content"\r
+        android:layout_gravity="center_vertical"\r
+        android:layout_marginLeft="4dp"\r
+        android:layout_marginRight="4dp"\r
+        android:src="@drawable/sharedlink" />\r
+\r
     <ImageView\r
         android:id="@+id/custom_checkbox"\r
         android:layout_width="wrap_content"\r
index c292dff..0572206 100644 (file)
@@ -19,7 +19,9 @@
 -->
 <menu  xmlns:android="http://schemas.android.com/apk/res/android">
     
-       <item   android:id="@+id/action_open_file_with"                 android:title="@string/actionbar_open_with"                     android:icon="@android:drawable/ic_menu_edit"                                   android:orderInCategory="1" />
+       <item   android:id="@+id/action_share_file"                             android:title="@string/action_share_file"                       android:icon="@android:drawable/ic_menu_share"                                  android:orderInCategory="1" />
+       <item   android:id="@+id/action_unshare_file"               android:title="@string/action_unshare_file"                 android:icon="@android:drawable/ic_menu_share"                                  android:orderInCategory="1" />
+    <item      android:id="@+id/action_open_file_with"                 android:title="@string/actionbar_open_with"                     android:icon="@android:drawable/ic_menu_edit"                                   android:orderInCategory="1" /> 
        <item   android:id="@+id/action_download_file"                  android:title="@string/filedetails_download"            android:icon="@drawable/ic_action_download"                                             android:orderInCategory="1" />
     <item      android:id="@+id/action_sync_file"                              android:title="@string/filedetails_sync_file"           android:icon="@drawable/ic_action_refresh"                                              android:orderInCategory="1" />
        <item   android:id="@+id/action_cancel_download"                android:title="@string/common_cancel_download"          android:icon="@android:drawable/ic_menu_close_clear_cancel"             android:orderInCategory="1" />
diff --git a/res/values-ak/strings.xml b/res/values-ak/strings.xml
new file mode 100644 (file)
index 0000000..c757504
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
index cbda0e7..499d68a 100644 (file)
@@ -7,12 +7,12 @@
   <string name="actionbar_upload_files">الملفات</string>
   <string name="actionbar_mkdir">إنشاء دليل</string>
   <string name="actionbar_settings">تعديلات</string>
+  <string name="actionbar_see_details">تفاصيل</string>
   <string name="prefs_category_general">عام</string>
   <string name="prefs_category_more">المزيد</string>
   <string name="prefs_accounts">حسابات</string>
   <string name="prefs_help">المساعدة</string>
   <string name="prefs_imprint">الدمغة.</string>
-  <string name="auth_host_url">عنوان الخادم</string>
   <string name="auth_username">إسم المستخدم</string>
   <string name="auth_password">كلمات السر</string>
   <string name="auth_register">جديد لـ %1$s ؟</string>
   <string name="filedetails_type">النوع</string>
   <string name="filedetails_modified">عُدل</string>
   <string name="filedetails_download">انزال</string>
+  <string name="filedetails_sync_file">تحديث ملف</string>
   <string name="filedetails_renamed_in_upload_msg">تم تغيير اسم الملف إلى  %1$s أثناء الرفع</string>
   <string name="common_yes">نعم</string>
   <string name="common_no">لا</string>
   <string name="common_ok">تم</string>
+  <string name="common_cancel_download">إلغاء تحميل</string>
   <string name="common_cancel_upload">إلغاء رفع الملفات</string>
   <string name="common_cancel">الغاء</string>
   <string name="common_error">خطأ</string>
+  <string name="common_loading">تحميل ...</string>
   <string name="common_error_unknown">حدث خطأ غير معروف. </string>
   <string name="about_title">حول</string>
   <string name="change_password">عدل كلمة السر</string>
   <string name="delete_account">حذف الحساب</string>
   <string name="create_account">حساب جديد</string>
   <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%% رفع %2$s</string>
   <string name="uploader_upload_succeeded_ticker">تم الرفع بنجاح</string>
@@ -56,6 +60,7 @@
   <string name="downloader_download_succeeded_content">تم تحميل %1$s  بنجاح </string>
   <string name="downloader_download_failed_ticker">فشل التحميل</string>
   <string name="downloader_download_failed_content"> تحميل %1$s قد لا يكون كاملاَ</string>
+  <string name="downloader_not_downloaded_yet">لم يتم تحميلها بعد</string>
   <string name="common_choose_account">اختر حساب</string>
   <string name="sync_fail_content">تعذر إكمال التزامن لـ %1$s  </string>
   <string name="sync_fail_content_unauthorized">كلمة السر غير صالحة لـ %1$s</string>
   <string name="common_remove">الغى</string>
   <string name="confirmation_remove_alert">هل تود حقاَ إزالة %1$s ؟ </string>
   <string name="confirmation_remove_folder_alert">هل ترغب في إزالة %1$s و جهات الاتصال التابعة له؟ </string>
+  <string name="confirmation_remove_folder_local">المحتويات المحلية فقط</string>
   <string name="confirmation_remove_remote">حذف من الخادم</string>
   <string name="remove_success_msg">يتم الحذف بنجاح</string>
   <string name="remove_fail_msg">لقد فشل الحذف</string>
+  <string name="rename_dialog_title">أدخل اسما جديدا</string>
   <string name="wait_a_moment">فضلاً, انتظر</string>
   <string name="filedisplay_no_file_selected">لم يتم اختيار أي ملف</string>
+  <string name="ssl_validator_btn_details_see">تفاصيل</string>
+  <string name="ssl_validator_btn_details_hide">إخفاء</string>
+  <string name="ssl_validator_label_CN">الاسم الشائع:</string>
+  <string name="ssl_validator_label_O">منظمة:</string>
+  <string name="ssl_validator_label_OU">الوحدة التنظيمية:</string>
+  <string name="ssl_validator_label_C">البلد:</string>
+  <string name="ssl_validator_label_L">المكان:</string>
+  <string name="ssl_validator_label_validity_from">من:</string>
+  <string name="ssl_validator_label_validity_to">إلى:</string>
+  <string name="ssl_validator_label_signature">التوقيع:</string>
+  <string name="ssl_validator_label_signature_algorithm">الخوارزمية:</string>
+  <string name="placeholder_filesize">389 KB</string>
+  <string name="placeholder_media_time">12:23:45</string>
+  <string name="preview_image_description">معاينة الصورة</string>
+  <string name="preview_image_error_unknown_format">هذه الصورة لا يمكن أن تظهر</string>
+  <string name="failed_upload_all_cb">تحديد الكل</string>
 </resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
new file mode 100644 (file)
index 0000000..c757504
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
index c757504..8be4885 100644 (file)
@@ -1,2 +1,7 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<resources/>
+<resources>
+  <string name="actionbar_settings">Налады</string>
+  <string name="common_yes">Так</string>
+  <string name="common_no">Не</string>
+  <string name="common_error">Памылка</string>
+</resources>
index c84d705..335b1b4 100644 (file)
@@ -10,7 +10,6 @@
   <string name="prefs_accounts">Профили</string>
   <string name="prefs_instant_upload_summary">Своевременно качване на снимки направени с камерата</string>
   <string name="prefs_help">Помощ</string>
-  <string name="auth_host_url">Адрес на сървъра</string>
   <string name="auth_username">Потребител</string>
   <string name="auth_password">Парола</string>
   <string name="sync_string_files">Файлове</string>
index a9080e6..2454ad3 100644 (file)
@@ -8,7 +8,6 @@
   <string name="prefs_category_more">বেশী</string>
   <string name="prefs_accounts">একাউন্ট</string>
   <string name="prefs_help">সহায়িকা</string>
-  <string name="auth_host_url">সার্ভার ঠিকানা</string>
   <string name="auth_username">ব্যবহারকারি</string>
   <string name="auth_password">কূটশব্দ</string>
   <string name="sync_string_files">ফাইল</string>
index f093cd2..c29514d 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Proveu %1$s a un telèfon avançat!</string>
   <string name="recommend_text">Vull convidar-te a usar l\'aplicació %1$s al teu telèfon avançat!\nBaixa\'l aquí: %2$s</string>
   <string name="auth_check_server">Comprova el servidor</string>
-  <string name="auth_host_url">Adreça del servidor</string>
+  <string name="auth_host_url">Adreça del servidor https://…</string>
   <string name="auth_username">Nom d\'usuari</string>
   <string name="auth_password">Contrasenya</string>
   <string name="auth_register">Nou a %1$s?</string>
@@ -55,6 +55,7 @@
   <string name="filedetails_download">Baixa</string>
   <string name="filedetails_sync_file">Actualitza el fitxer</string>
   <string name="filedetails_renamed_in_upload_msg">L\'arxiu s\'ha canviat de nom a %1$s durant la càrrega</string>
+  <string name="action_share_file">Enllaç de compartició</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">D\'acord</string>
   <string name="sync_file_fail_msg">L\'arxiu remot no ha pogut ser comprovat</string>
   <string name="sync_file_nothing_to_do_msg">Contingut de l\'arxiu ja sincronitzat</string>
   <string name="create_dir_fail_msg">La carpeta no s\'ha pogut crear</string>
+  <string name="filename_forbidden_characters">Caràcters no permesos: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Espereu</string>
   <string name="filedisplay_unexpected_bad_get_content">S\'ha produït un problema inesperat; proveu una altra aplicació per seleccionar el fitxer</string>
   <string name="filedisplay_no_file_selected">No heu seleccionat cap fitxer</string>
   <string name="preview_image_description">Visualització prèvia d\'imatge</string>
   <string name="preview_image_error_unknown_format">Auquesta imatge no es pot mostrar</string>
   <string name="error__upload__local_file_not_copied">%1$s no s\'ha pogut copiar a la carpeta local %2$s</string>
+  <string name="actionbar_failed_instant_upload">La pujada instantània ha fallat</string>
   <string name="failed_upload_headline_text">Fallada de pujades instantànies</string>
   <string name="failed_upload_headline_hint">Resum de totes les pujades instantànies que han fallat</string>
   <string name="failed_upload_all_cb">selecciona-ho tot</string>
index df2dd56..03bc06a 100644 (file)
   <string name="prefs_log_summary_history">Zobrazuje zaznamenané logy</string>
   <string name="prefs_log_delete_history_button">Smazat historii</string>
   <string name="prefs_help">Nápověda</string>
+  <string name="prefs_recommend">Doporučit příteli</string>
   <string name="prefs_feedback">Odezva</string>
   <string name="prefs_imprint">Imprint</string>
+  <string name="recommend_subject">Zkuste %1$s na vašem smartphonu!</string>
+  <string name="recommend_text">Chtěl bych vás pozvat k používání %1$s na vašem smartphonu.\nKe stažení zde:  %2$s</string>
   <string name="auth_check_server">Zkontrolovat server</string>
-  <string name="auth_host_url">Adresa serveru</string>
+  <string name="auth_host_url">Adresa serveru https://...</string>
   <string name="auth_username">Uživatelské jméno</string>
   <string name="auth_password">Heslo</string>
   <string name="auth_register">Nováček s %1$s?</string>
@@ -52,6 +55,8 @@
   <string name="filedetails_download">Stáhnout</string>
   <string name="filedetails_sync_file">Obnovit soubor</string>
   <string name="filedetails_renamed_in_upload_msg">Soubor byl v průběhu odesílání přejmenován na %1$s</string>
+  <string name="action_share_file">Sdílet odkaz</string>
+  <string name="action_unshare_file">Zrušit sdílení odkazu</string>
   <string name="common_yes">Ano</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">OK</string>
@@ -92,6 +97,7 @@
   <string name="sync_foreign_files_forgotten_ticker">Některé místní soubory byly zapomenuty</string>
   <string name="sync_foreign_files_forgotten_content">%1$d souborů z adresáře %2$s nelze zkopírovat do</string>
   <string name="sync_foreign_files_forgotten_explanation">Od verze 1.3.16 jsou soubory odeslané z tohoto zařízení, pro ochranu proti ztrátě dat při synchronizaci z více účtů, nahrány do místní složky %1$s.\n\nVšechny soubory odeslané předchozími verzemi byly kvůli této změně přesunuty do složky %2$s. Bohužel chyba zabránila dokončení této operace při synchronizaci účtu. Můžete nyní ponechat soubory ve stávajícím stavu a smazat odkaz na %3$s nebo přesunout soubory do adresáře %1$s a zachovat odkazy na %4$s.\n\nNásleduje seznam místních souborů a jejich odkazů na vzdálené soubory v %5$s.</string>
+  <string name="sync_current_folder_was_removed">Složka %1$s již neexistuje</string>
   <string name="foreign_files_move">Přesunout vše</string>
   <string name="foreign_files_success">Všechny soubory byly přesunuty</string>
   <string name="foreign_files_fail">Některé soubory nebylo možno přesunout</string>
   <string name="media_err_unsupported">Nepodporovaný kodek</string>
   <string name="media_err_io">Multimediální soubor nelze přečíst</string>
   <string name="media_err_malformed">Multimediální soubor není správně kódován</string>
+  <string name="media_err_timeout">Vypršel čas při pokusu o přehrání</string>
   <string name="media_err_invalid_progressive_playback">Multimediální soubor nelze proudově odesílat</string>
   <string name="media_err_unknown">Multimediální soubor nemůže být přehrán s výchozím přehrávačem</string>
   <string name="media_err_security_ex">Chyba zabezpečení při pokusu o přehrání %1$s</string>
   <string name="auth_connection_established">Spojení navázáno</string>
   <string name="auth_testing_connection">Zkouším spojení...</string>
   <string name="auth_not_configured_title">Neplatné nastavení serveru</string>
+  <string name="auth_account_not_new">Účet pro stejného uživatele a server již v zařízení existuje</string>
+  <string name="auth_account_not_the_same">Zadaný uživatel neodpovídá uživateli tohoto účtu</string>
   <string name="auth_unknown_error_title">Nastala neznámá chyba</string>
   <string name="auth_unknown_host_title">Nelze najít hostitele</string>
   <string name="auth_incorrect_path_title">Instance serveru nenalezena</string>
   <string name="auth_timeout_title">Serveru trvalo příliš dlouho odpovědět</string>
   <string name="auth_incorrect_address_title">Neplatné URL</string>
   <string name="auth_ssl_general_error_title">Inicializace SSL selhala</string>
+  <string name="auth_ssl_unverified_server_title">Nemohu ověřit SSL identitu serveru</string>
   <string name="auth_bad_oc_version_title">Nerozpoznaná verze serveru</string>
   <string name="auth_wrong_connection_title">Nemohu navázat spojení</string>
   <string name="auth_secure_connection">Zabezpečené spojení navázáno</string>
   <string name="auth_oauth_error">Neúspěšné přihlášení</string>
   <string name="auth_oauth_error_access_denied">Přístup zamítnut autorizačním serverem</string>
   <string name="auth_wtf_reenter_URL">Neočekávaný stav; prosím vložte znovu URL adresu serveru</string>
+  <string name="auth_expired_oauth_token_toast">Vaše přihlášení vypršelo. Přihlašte se, prosím, znovu</string>
   <string name="auth_expired_basic_auth_toast">Zadejte prosím aktuální heslo</string>
+  <string name="auth_expired_saml_sso_token_toast">Vaše přihlášení vypršelo. Přihlašte se, prosím, znovu</string>
+  <string name="auth_connecting_auth_server">Připojuji se k přihlašovacímu serveru...</string>
+  <string name="auth_unsupported_auth_method">Server nepodporuje tuto přihlašovací metodu</string>
+  <string name="auth_unsupported_multiaccount">%1$s nepodporuje více účtů</string>
   <string name="fd_keep_in_sync">Udržovat soubor aktuální</string>
   <string name="common_rename">Přejmenovat</string>
   <string name="common_remove">Odstranit</string>
   <string name="sync_file_fail_msg">Vzdálený soubor nemohl být zkontrolován</string>
   <string name="sync_file_nothing_to_do_msg">Obsah souboru je již synchronizován</string>
   <string name="create_dir_fail_msg">Adresář nelze vytvořit</string>
+  <string name="filename_forbidden_characters">Zakázané znaky: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Počkejte chvíli</string>
   <string name="filedisplay_unexpected_bad_get_content">Neočekávaný problém - zkuste zvolit soubor jinou aplikací</string>
   <string name="filedisplay_no_file_selected">Žádný soubor nebyl vybrán</string>
+  <string name="activity_chooser_title">Odeslat odkaz ...</string>
+  <string name="oauth_check_onoff">Přihlásit se s oAuth2</string>
   <string name="oauth_login_connection">Připojuji se k oAuth2 serveru...</string>
   <string name="ssl_validator_header">Identitu stránky nelze ověřit</string>
   <string name="ssl_validator_reason_cert_not_trusted">- Certifikát serveru je nedůvěryhodný</string>
   <string name="preview_image_description">Náhled obrázku</string>
   <string name="preview_image_error_unknown_format">Obrázek nemůže být zobrazen</string>
   <string name="error__upload__local_file_not_copied">%1$s nelze zkopírovat do místního adresáře %2$s</string>
+  <string name="actionbar_failed_instant_upload">Selhalo Okamžité odeslání</string>
   <string name="failed_upload_headline_text">Selhaná okamžitá odeslání</string>
   <string name="failed_upload_headline_hint">Souhrn všech selhaných okamžitých odeslání</string>
   <string name="failed_upload_all_cb">vybrat vše</string>
   <string name="failed_upload_retry_do_nothing_text">nic nedělat nejste připojeni pro okamžité odeslání</string>
   <string name="failed_upload_failure_text">Chybová zpráva:</string>
   <string name="failed_upload_quota_exceeded_text">Zkontrolujte prosím nastavení vašeho serveru, možná jste překročili kvótu.</string>
+  <string name="share_link_no_support_share_api">Je nám líto, ale sdílení není na vašem serveru povoleno. Kontaktujte vašeho administrátora.</string>
+  <string name="share_link_file_no_exist">Nepodařilo se sdílet tento soubor či složku. Ujistěte se, že existuje.</string>
+  <string name="share_link_file_error">Při pokusu o sdílení tohoto souboru či složky nastala chyba</string>
+  <string name="unshare_link_file_error">Při pokusu o zrušení sdílení tohoto souboru či složky nastala chyba</string>
 </resources>
index 85489a1..71a7bff 100644 (file)
   <string name="prefs_log_summary_history">Dette viser de optagne logger</string>
   <string name="prefs_log_delete_history_button">Slet Historik</string>
   <string name="prefs_help">Hjælp</string>
+  <string name="prefs_recommend">Anbefal til en ven</string>
+  <string name="prefs_feedback">Feedback</string>
   <string name="prefs_imprint">Imprint</string>
+  <string name="recommend_subject">Prøv %1$s på din smartphone!</string>
+  <string name="recommend_text">Jeg ønsker at invitere dig til at bruge %1$s på din smartphone!\nHent den her: %2$s</string>
   <string name="auth_check_server">Check Server</string>
-  <string name="auth_host_url">Serveradresse</string>
+  <string name="auth_host_url">Server addresse https://…</string>
   <string name="auth_username">Brugernavn</string>
   <string name="auth_password">Kodeord</string>
   <string name="auth_register">Uvant med %1$s</string>
@@ -51,6 +55,8 @@
   <string name="filedetails_download">Hent</string>
   <string name="filedetails_sync_file">Opdater fil</string>
   <string name="filedetails_renamed_in_upload_msg">Filen blev omdøbt til %1$s under upload</string>
+  <string name="action_share_file">Del link</string>
+  <string name="action_unshare_file">Ophæv deling</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nej</string>
   <string name="common_ok">OK</string>
@@ -91,6 +97,7 @@
   <string name="sync_foreign_files_forgotten_ticker">Visse lokale filer blev glemt</string>
   <string name="sync_foreign_files_forgotten_content">%1$d filer ud af %2$s mappe kunne ikke kopieres ind i</string>
   <string name="sync_foreign_files_forgotten_explanation">Fra version 1.3.16 bliver filer uploadet fra denne enhed kopieret til mappen %1$s for at forhindre datatab når en enkelt fil synkroniseres med flere konti.\n\nPå grund af denne ændring blev alle filer uploadet i tidligere versioner af denne app kopieret til mappen %2$s. Imidlertid forhindrede en fejl færdiggørelsen af denne operation under konto-synkronisering. Du kan enten lade filerne være som de er og fjerne linket til %3$s eller flytte filerne til mappen %1$s og beholde linket til %4$s.\n\nHerunder er en liste med de lokale filer og de eksterne filer i %5$s, som de var knyttet til.</string>
+  <string name="sync_current_folder_was_removed">Mappen %1$s eksistere ikke længere</string>
   <string name="foreign_files_move">Flyt alle</string>
   <string name="foreign_files_success">Alle filer blev flyttet</string>
   <string name="foreign_files_fail">Visse filer kunne ikke flyttes</string>
   <string name="media_err_unsupported">Ikke-understøttet medie codec</string>
   <string name="media_err_io">Mediefilen kunne ikke læses</string>
   <string name="media_err_malformed">Mediefilen er ikke korrekt kodet</string>
+  <string name="media_err_timeout">Tiden udløb under forsøg på at afspille</string>
   <string name="media_err_invalid_progressive_playback">Mediefilen kan ikke streames</string>
   <string name="media_err_unknown">Mediefil kan ikke afspilles med tilgængelige medieafspiller</string>
   <string name="media_err_security_ex">Sikkerhedsfejl ved forsøg på afspilning af </string>
   <string name="auth_connection_established">Forbindelse oprettet</string>
   <string name="auth_testing_connection">Afprøver forbindelse ...</string>
   <string name="auth_not_configured_title">Misdannet server konfiguration</string>
+  <string name="auth_account_not_new">En konto for den samme bruger og server eksisterer allerede på enheden</string>
+  <string name="auth_account_not_the_same">Den indtastede bruger passer ikke til brugeren for denne konto</string>
   <string name="auth_unknown_error_title">Ukendt fejl opstod!</string>
   <string name="auth_unknown_host_title">Kunne ikke finde host</string>
   <string name="auth_incorrect_path_title">Server instans blev ikke fundet</string>
   <string name="auth_timeout_title">Serveren var for længe om at svare</string>
   <string name="auth_incorrect_address_title">Deform URL</string>
   <string name="auth_ssl_general_error_title">SSL initialisering fejlede</string>
+  <string name="auth_ssl_unverified_server_title">Kunne ikke bekræfte SSl-serverens identitet</string>
   <string name="auth_bad_oc_version_title">Ikke genkendt server version</string>
   <string name="auth_wrong_connection_title">Ikke ikke oprette forbindelse</string>
   <string name="auth_secure_connection">Sikker forbindelse oprettet</string>
   <string name="auth_oauth_error">Mislykket godkendelse</string>
   <string name="auth_oauth_error_access_denied">Adgang afvist af autorisationsserver</string>
   <string name="auth_wtf_reenter_URL">Uventet tilstand; angiv server-URL\'en igen</string>
+  <string name="auth_expired_oauth_token_toast">Din godkendelse udløb. Gentag godkendelse</string>
   <string name="auth_expired_basic_auth_toast">Indtast venligst dit nuværende kodeord</string>
+  <string name="auth_expired_saml_sso_token_toast">Din session udløb. Forbind venligst igen</string>
+  <string name="auth_connecting_auth_server">Forbinder til godkendelsesserver ...</string>
+  <string name="auth_unsupported_auth_method">Serveren understøtter ikke denne godkendelsesmetode</string>
+  <string name="auth_unsupported_multiaccount">%1$s understøtter ikke multiple konti</string>
   <string name="fd_keep_in_sync">Hold fil opdateret</string>
   <string name="common_rename">Omdøb</string>
   <string name="common_remove">Fjern</string>
   <string name="sync_file_fail_msg">Ekstern fil kunne ikke kontrolleres</string>
   <string name="sync_file_nothing_to_do_msg">Filindholdet allerede synkroniseret</string>
   <string name="create_dir_fail_msg">Mappe kunne ikke oprettes</string>
+  <string name="filename_forbidden_characters">Ugyldige tegn: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Vent et øjeblik</string>
   <string name="filedisplay_unexpected_bad_get_content">Uforventet problem; prøv venligst anden applikation til at vælge filen</string>
   <string name="filedisplay_no_file_selected">Ingen fil blev valgt</string>
+  <string name="activity_chooser_title">Send link til ...</string>
+  <string name="oauth_check_onoff">Log på med oAuth2</string>
   <string name="oauth_login_connection">Forbinder til oAuth2 server...</string>
   <string name="ssl_validator_header">Sidens identitet kunne ikke verificeres</string>
   <string name="ssl_validator_reason_cert_not_trusted">- Serverens certifikat er ikke troværdigt</string>
   <string name="preview_image_description">Billede preview</string>
   <string name="preview_image_error_unknown_format">Dette billede kan ikke vises</string>
   <string name="error__upload__local_file_not_copied">%1$s kunne ikke kopieres til %2$s lokale mappe</string>
+  <string name="actionbar_failed_instant_upload">Fejlede Umiddelbar upload</string>
   <string name="failed_upload_headline_text">Øjeblikkelige uploads mislykkedes</string>
   <string name="failed_upload_headline_hint">Sammenfatning af alle mislykkede øjeblikkelige uploads</string>
   <string name="failed_upload_all_cb">Vælg alle</string>
   <string name="failed_upload_retry_do_nothing_text">gør intet, du er ikke online til øjeblikkelig upload</string>
   <string name="failed_upload_failure_text">Fejlmeddelelse</string>
   <string name="failed_upload_quota_exceeded_text">Tjek din serverkonfiguration, måske er din kvota overskredet.</string>
+  <string name="share_link_no_support_share_api">Beklager, deling er ikke slået til på din server. Kontakt venligst din administrator.</string>
+  <string name="share_link_file_no_exist">Kan ikke dele denne fil eller mappe. Find venligst ud af om den eksisterer</string>
+  <string name="share_link_file_error">Der opstod en fejl ved deling af denne fil eller mappe</string>
+  <string name="unshare_link_file_error">Der opstod en fejl ved stopning af deling af denne mappe.</string>
 </resources>
index 619fca8..c5d7ce4 100644 (file)
@@ -28,7 +28,6 @@
   <string name="prefs_feedback">Rückmeldungen</string>
   <string name="prefs_imprint">Impressum</string>
   <string name="auth_check_server">Server überprüfen</string>
-  <string name="auth_host_url">Adresse des Servers</string>
   <string name="auth_username">Benutzername</string>
   <string name="auth_password">Passwort</string>
   <string name="auth_register">Ist %1$s neu für Sie?</string>
index 22cd02f..97a67e9 100644 (file)
@@ -31,7 +31,7 @@
   <string name="recommend_subject">Probieren Sie %1$s auf Ihrem Smartphone!</string>
   <string name="recommend_text">Ich möchte Sie zum Benutzen von %1$s auf Ihrem Smartphone einladen!\nLaden Sie es hier herunter: %2$s</string>
   <string name="auth_check_server">Server überprüfen</string>
-  <string name="auth_host_url">Adresse des Servers</string>
+  <string name="auth_host_url">Server-Adresse https://…</string>
   <string name="auth_username">Benutzername</string>
   <string name="auth_password">Passwort</string>
   <string name="auth_register">Ist %1$s neu für Sie?</string>
@@ -56,6 +56,8 @@
   <string name="filedetails_download">Herunterladen</string>
   <string name="filedetails_sync_file">Datei aktualisieren</string>
   <string name="filedetails_renamed_in_upload_msg">Datei wurde wärend des Uploads zu %1$s umbenannt</string>
+  <string name="action_share_file">Link teilen</string>
+  <string name="action_unshare_file">Link nicht mehr freigeben</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nein</string>
   <string name="common_ok">OK</string>
   <string name="sync_file_fail_msg">Die entfernte Datei konnte nicht überprüft werden</string>
   <string name="sync_file_nothing_to_do_msg">Dateiinhalte bereits synchronisiert</string>
   <string name="create_dir_fail_msg">Das Verzeichnis konnte nicht erstellt werden.</string>
+  <string name="filename_forbidden_characters">Verbotene Zeichen: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Bitte warten Sie einen Moment.</string>
   <string name="filedisplay_unexpected_bad_get_content">Ein unerwartetes Problem ist aufgetreten. Bitte versuchen Sie, die Datei in einer anderen App zu öffnen.</string>
   <string name="filedisplay_no_file_selected">Es wurde keine Datei ausgewählt.</string>
+  <string name="activity_chooser_title">Link senden an ...</string>
   <string name="oauth_check_onoff">Anmelden mit oAuth2</string>
   <string name="oauth_login_connection">Verbinde mit dem oAuth2-Server…</string>
   <string name="ssl_validator_header">Die Identität der Website konnte nicht überprüft werden</string>
   <string name="preview_image_description">Bildvorschau</string>
   <string name="preview_image_error_unknown_format">Dieses Bild kann nicht angezeigt werden</string>
   <string name="error__upload__local_file_not_copied">%1$s konnte nicht in den lokalen %2$s Ordner kopiert werden</string>
+  <string name="actionbar_failed_instant_upload">Sofort-Upload fehlgeschlagen</string>
   <string name="failed_upload_headline_text">Sofortige Uploads fehlgeschlagen</string>
   <string name="failed_upload_headline_hint">Zusammenfassung aller fehlgeschlagenen Uploads</string>
   <string name="failed_upload_all_cb">Alle auswählen</string>
   <string name="failed_upload_retry_do_nothing_text">Nicht durchgeführt - Nicht online für sofortigen Upload</string>
   <string name="failed_upload_failure_text">Fehlermeldung:</string>
   <string name="failed_upload_quota_exceeded_text">Bitte überprüfen Sie Ihre Serverkonfiguration. Vielleicht ist Ihr Nutzungslimit überschritten.</string>
+  <string name="share_link_no_support_share_api">Entschuldigung, Freigaben sind auf Ihrem Server nicht aktiviert. Bitte kontaktieren Sie Ihren Administrator.</string>
+  <string name="share_link_file_no_exist">Die Freigabe der Datei oder des Ordners ist nicht möglich. Bitte stellen Sie sicher, dass diese existiert.</string>
+  <string name="share_link_file_error">Es ist ein Fehler beim Freigeben der Datei oder des Ordners aufgetreten.</string>
+  <string name="unshare_link_file_error">Es ist ein Fehler beim Entfernen der Freigabe für diese Datei oder den Ordner aufgetreten.</string>
 </resources>
index 5fbc442..06f49d4 100644 (file)
@@ -29,9 +29,9 @@
   <string name="prefs_feedback">Rückmeldungen</string>
   <string name="prefs_imprint">Impressum</string>
   <string name="recommend_subject">Probiere %1$s auf Deinem Smartphone!</string>
-  <string name="recommend_text">Ich möchte Dich zum Benutzen von %1$s auf Deinem Smartphone einladen!\nLade es hier herunter: %2$s</string>
+  <string name="recommend_text">Ich möchte Dich zu %1$s für Dein Smartphone einladen!\nLade es hier herunter: %2$s</string>
   <string name="auth_check_server">Überprüfe den Server</string>
-  <string name="auth_host_url">Adresse des Servers</string>
+  <string name="auth_host_url">Server-Adresse https://…</string>
   <string name="auth_username">Benutzername</string>
   <string name="auth_password">Passwort</string>
   <string name="auth_register">Ist %1$s neu für dich?</string>
@@ -56,6 +56,8 @@
   <string name="filedetails_download">Herunterladen</string>
   <string name="filedetails_sync_file">Datei aktualisieren</string>
   <string name="filedetails_renamed_in_upload_msg">Datei wurde wärend des Uploads zu %1$s umbenannt</string>
+  <string name="action_share_file">Link Teilen</string>
+  <string name="action_unshare_file">Link nicht mehr freigeben</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nein</string>
   <string name="common_ok">OK</string>
@@ -95,7 +97,7 @@
   <string name="sync_fail_in_favourites_content">Inhalte von %1$d konnte nicht synchronisiert werden (%2$d Konflikte)</string>
   <string name="sync_foreign_files_forgotten_ticker">Einige lokale Dateien wurden vergessen</string>
   <string name="sync_foreign_files_forgotten_content">%1$d Dateien aus dem Verzeichnis %2$s konnten nicht kopiert werden nach</string>
-  <string name="sync_foreign_files_forgotten_explanation">\"Mit Version 1.3.16 werden Dateien die von diesem Gerät aus hochgeladen werden in den lokalen Ordner %1$s kopiert um Datenverlust zu vermeiden, wenn eine einzelne Datei mit mehreren Accounts synchronisiert wird.\n\nInfolge dieser Änderung wurden alle Dateien, die mit vorherigen Versionen dieser App hochgeladen wurden, in den Ordner %2$s verschoben. Jedoch ist während der Account-Synchronisation ein Fehler aufgetreten, der das Abschließen dieses Vorgangs verhindert. Du kannst die Datei(en) entweder wie sie sind belassen und den Link zu %3$s entfernen oder die Datei(en) in den %1$s Ordner verschieben und  den Link zu %4$s beibehalten.\n\nUnten befindet sich eine Liste der lokalen Datei(en) und der mit ihnen verbundenen Remote-Datei(en) in %5$s.</string>
+  <string name="sync_foreign_files_forgotten_explanation">\"Mit Version 1.3.16 werden Dateien die von diesem Gerät aus hochgeladen werden in den lokalen Ordner %1$s kopiert, um Datenverlust zu vermeiden, wenn eine einzelne Datei mit mehreren Accounts synchronisiert wird.\n\nInfolge dieser Änderung wurden alle Dateien, die mit vorherigen Versionen dieser App hochgeladen wurden, in den Ordner %2$s verschoben. Jedoch ist während der Account-Synchronisation ein Fehler aufgetreten, der das Abschließen dieses Vorgangs verhindert. Du kannst die Datei(en) entweder wie sie sind belassen und den Link zu %3$s entfernen, oder die Datei(en) in den %1$s Ordner verschieben, und  den Link zu %4$s beibehalten.\n\nUnten befindet sich eine Liste der lokalen Datei(en) und der mit ihnen verbundenen Remote-Datei(en) in %5$s.</string>
   <string name="sync_current_folder_was_removed">Das Verzeichnis %1$s existiert nicht mehr</string>
   <string name="foreign_files_move">Verschiebe alle</string>
   <string name="foreign_files_success">Alle Dateien wurden verschoben</string>
   <string name="auth_oauth_error">Autorisierung nicht erfolgreich</string>
   <string name="auth_oauth_error_access_denied">Zugriff durch den Autorisierungsserver abgelehnt</string>
   <string name="auth_wtf_reenter_URL">Unerwarteter Zustand; bitte gib die URL des Servers nochmals ein</string>
-  <string name="auth_expired_oauth_token_toast">Ihre Autorisierung ist abgelaufen. Bitte Autorisierung nochmals durchführen</string>
+  <string name="auth_expired_oauth_token_toast">Deine Autorisierung ist abgelaufen. Bitte Autorisierung nochmals durchführen</string>
   <string name="auth_expired_basic_auth_toast">Bitte gib dein aktuelles Passwort ein</string>
-  <string name="auth_expired_saml_sso_token_toast">Ihre Sitzung ist abgelaufen. Bitte Anmeldung nochmals durchführen</string>
+  <string name="auth_expired_saml_sso_token_toast">Deine Sitzung ist abgelaufen. Bitte Anmeldung nochmals durchführen</string>
   <string name="auth_connecting_auth_server">Verbinde mit dem Authentifizierung-Server…</string>
   <string name="auth_unsupported_auth_method">Der Server unterstützt diese Authentifizierung-Methode nicht</string>
   <string name="auth_unsupported_multiaccount">%1$s unterstützt nicht mehrere Benutzerkonten</string>
   <string name="sync_file_fail_msg">Die entfernte Datei konnte nicht überprüft werden</string>
   <string name="sync_file_nothing_to_do_msg">Dateiinhalte bereits synchronisiert</string>
   <string name="create_dir_fail_msg">Das Verzeichnis konnte nicht erstellt werden.</string>
+  <string name="filename_forbidden_characters">Verbotene Zeichen: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Bitte warte einen Moment.</string>
   <string name="filedisplay_unexpected_bad_get_content">Ein unerwartetes Problem ist aufgetreten. Bitte versuche, die Datei in einer anderen App zu öffnen</string>
   <string name="filedisplay_no_file_selected">Es wurde keine Datei ausgewählt.</string>
+  <string name="activity_chooser_title">Link senden an ...</string>
   <string name="oauth_check_onoff">Anmelden mit oAuth2</string>
   <string name="oauth_login_connection">Verbinde mit dem oAuth2-Server.</string>
   <string name="ssl_validator_header">Die Identität der Website konnte nicht überprüft werden</string>
   <string name="preview_image_description">Bildvorschau</string>
   <string name="preview_image_error_unknown_format">Dieses Bild kann nicht angezeigt werden</string>
   <string name="error__upload__local_file_not_copied">%1$s konnte nicht in den lokalen %2$s Ordner kopiert werden</string>
+  <string name="actionbar_failed_instant_upload">Sofort-Upload fehlgeschlagen</string>
   <string name="failed_upload_headline_text">SofortUpload fehlgeschlagen</string>
   <string name="failed_upload_headline_hint">Übersicht aller fehlgeschlagenen SofortUploads</string>
   <string name="failed_upload_all_cb">Alles auswählen</string>
   <string name="failed_upload_retry_do_nothing_text">Nicht durchgeführt - Nicht online für sofortigen Upload</string>
   <string name="failed_upload_failure_text">Fehlermeldung:</string>
   <string name="failed_upload_quota_exceeded_text">Bitte überprüfe Deine Servereinstellungen. Eventuell ist Dein Nutzungslimit überschritten.</string>
+  <string name="share_link_no_support_share_api">Entschuldigung, Freigaben sind auf Deinem Server nicht aktiviert. Bitte kontaktiere Deinen Administrator.</string>
+  <string name="share_link_file_no_exist">Die Freigabe der Datei oder des Ordners ist nicht möglich. Bitte stelle sicher, dass diese existiert.</string>
+  <string name="share_link_file_error">Es ist ein Fehler beim Freigeben der Datei oder des Ordners aufgetreten.</string>
+  <string name="unshare_link_file_error">Es ist ein Fehler beim Entfernen der Freigabe für diese Datei oder den Ordner aufgetreten.</string>
 </resources>
index 0837a49..da7c29d 100644 (file)
@@ -2,6 +2,7 @@
 <resources>
   <string name="about_android">%1$s Εφαρμογή για Android</string>
   <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="prefs_pincode_summary">Προστατέψτε την εφαρμογή</string>
   <string name="prefs_instant_upload">Ενεργοποιήστε την άμεση μεταφόρτωση</string>
   <string name="prefs_instant_upload_summary">Άμεση μεταφόρτωση των φωτογραφιών που τραβάει η φωτογρ. μηχανή</string>
+  <string name="prefs_log_title">Ενεργοποίηση Καταγραφής Ιστορικού</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_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="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">Διεύθυνση εξυπηρέτη</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>
   <string name="sync_string_files">Αρχεία</string>
   <string name="setup_btn_connect">Σύνδεση</string>
   <string name="uploader_btn_upload_text">Μεταφόρτωση</string>
@@ -46,6 +55,8 @@
   <string name="filedetails_download">Λήψη</string>
   <string name="filedetails_sync_file">Ανανέωση αρχείου</string>
   <string name="filedetails_renamed_in_upload_msg">Το αρχείο μετονομάστηκε σε %1$s κατά την μεταφόρτωση</string>
+  <string name="action_share_file">Διαμοιρασμός συνδέσμου</string>
+  <string name="action_unshare_file">Ακύρωση διαμοιρασμού συνδέσμου</string>
   <string name="common_yes">Ναι</string>
   <string name="common_no">Όχι</string>
   <string name="common_ok">ΟΚ</string>
@@ -74,6 +85,7 @@
   <string name="downloader_download_succeeded_content">%1$s αρχεία λήφθηκαν με επιτυχία</string>
   <string name="downloader_download_failed_ticker">Το κατέβασμα απέτυχε</string>
   <string name="downloader_download_failed_content">Η λήψη του %1$s δεν μπόρεσε να ολοκληρωθεί με επιτυχία</string>
+  <string name="downloader_not_downloaded_yet">Δεν έχει κατέβει ακόμα</string>
   <string name="common_choose_account">Επιλογή λογαριασμού</string>
   <string name="sync_fail_ticker">Ο συγχρονισμός απέτυχε</string>
   <string name="sync_fail_content">Ο συγχρονισμός του %1$s  δεν μπόρεσε να ολοκληρωθεί</string>
@@ -84,6 +96,8 @@
   <string name="sync_fail_in_favourites_content">Τα περιεχόμενα των %1$d αρχείων δεν μπόρεσαν να συγχρονιστούν (%2$d διενέξεις)</string>
   <string name="sync_foreign_files_forgotten_ticker">Ορισμένα τοπικά αρχεία ξεχάστηκαν</string>
   <string name="sync_foreign_files_forgotten_content">%1$d αρχεια απο τον %2$s χωρο αποθηκευσης δεν μπορουν να αντιγραφθουν σε</string>
+  <string name="sync_foreign_files_forgotten_explanation">Από την έκδοση 1.3.16 και μετά, αρχεία που μεταφορτώνονται από αυτήν τη συσκευή αντιγράφονται στον τοπικό φάκελο %1$s για να αποτραπεί η απώλεια δεδομένων όταν ένα αρχείο είναι συγχρονισμένο με πολλαπλούς λογαριασμούς.\nΛόγω αυτής της αλλαγής, όλα τα αρχεία που μεταφορτώθηκαν με προηγούμενες εκδόσεις αυτής της εφαρμογής αντιγράφηκαν στο φάκελο %2$s. Ωστόσο, ένα σφάλμα εμπόδισε την ολοκλήρωση αυτής της επιχείρησης κατά το συγχρονισμό του λογαριασμού. Μπορείτε είτε να αφήσετε τα αρχεία όπως είναι και να καταργήσετε τη σύνδεση με%3$s ή να μετακινήσετε τα αρχεία στον κατάλογο %1$s και να διατηρήσετε τη σύνδεση με %4$s.\n\nΑπαριθμημένα πιο κάτω είναι το(α) τοπικό(ά) αρχείο(α) και το(α) απομακρυσμένο(α) αρχείο(α) στο %5$s με το(α) οποίο(α) συνδέονταν.</string>
+  <string name="sync_current_folder_was_removed">Ο φάκελος %1$s δεν υπάρχει πια</string>
   <string name="foreign_files_move">Μετακινηση ολων</string>
   <string name="foreign_files_success">Ολα τα αρχεια μετακινηθηκαν</string>
   <string name="foreign_files_fail">Μερικα αρχεια δεν μπορεσαν να μετακινηθουν</string>
   <string name="pincode_wrong">Εσφαλμένο PIN της εφαρμογής</string>
   <string name="pincode_removed">Αφαιρέθηκε το PIN της εφαρμογής</string>
   <string name="pincode_stored">Το PIN της εφαρμογής αποθηκεύτηκε</string>
+  <string name="media_notif_ticker">%1$s αναπαραγωγή μουσικής</string>
+  <string name="media_state_playing">%1$s (αναπαραγωγή)</string>
+  <string name="media_state_loading">%1$s (φόρτωση)</string>
+  <string name="media_event_done">%1$s αναπαραγωγή τελείωσε</string>
   <string name="media_err_nothing_to_play">Δεν βρέθηκε αρχείο πολυμέσων</string>
   <string name="media_err_no_account">Δεν δόθηκε λογαριασμός</string>
+  <string name="media_err_not_in_owncloud">Το αρχείο δεν βρίσκεται σε έγκυρο λογαριασμό</string>
+  <string name="media_err_unsupported">Αυτή η μορφή κωδικοποιήσης πολυμέσων δεν υποστηρίζεται</string>
   <string name="media_err_io">Το αρχείο πολυμέσων δεν μπόρεσε να διαβαστεί</string>
   <string name="media_err_malformed">Το αρχείο πολυμέσων δεν είναι σωστά κοδικοποιημένο</string>
+  <string name="media_err_timeout">Λήξη χρόνου κατά την προσπάθεια αναπαραγωγής</string>
+  <string name="media_err_invalid_progressive_playback">Το αρχείο πολυμέσων δεν μπορεί να μεταδοθεί</string>
+  <string name="media_err_unknown">Το αρχείο πολυμέσων δεν μπορεί να αναπαραχθεί με την παρεχόμενη εφαρμογή αναπαραγωγής πολυμέσων</string>
+  <string name="media_err_security_ex">Σφάλμα ασφαλείας κατά την προσπάθεια αναπαραγωγής του %1$s</string>
+  <string name="media_err_io_ex">Σφάλμα εισόδου κατά την προσπάθεια αναπαραγωγής του %1$s</string>
+  <string name="media_err_unexpected">Απροσδόκτο σφάλμα κατά την προσπάθεια αναπαραγωγής του %1$s</string>
+  <string name="media_rewind_description">Κουμπί επαναφοράς</string>
   <string name="media_play_pause_description">Κουμπί αναπαραγωγής ή παύσης</string>
+  <string name="media_forward_description">Κουμπί προώθησης</string>
   <string name="auth_trying_to_login">Προσπάθεια σύνδεσης...</string>
   <string name="auth_no_net_conn_title">Δεν υπάρχει σύνδεση στο δίκτυο</string>
   <string name="auth_nossl_plain_ok_title">Μη διαθέσιμη ασφαλής σύνδεση.</string>
   <string name="auth_connection_established">Επετεύχθη σύνδεση</string>
   <string name="auth_testing_connection">Έλεγχος σύνδεσης...</string>
   <string name="auth_not_configured_title">Λανθασμένες ρυθμίσεις </string>
+  <string name="auth_account_not_new">Ένας λογαριασμός για τον ίδιο χρήστη και διακομιστή υπάρχει ήδη στη συσκευή</string>
+  <string name="auth_account_not_the_same">Ο χρήστης που εισάγατε δεν ταιριάζει με το χρήστη αυτού του λογαριασμού</string>
   <string name="auth_unknown_error_title">Παρουσιάστηκε άγνωστο σφάλμα</string>
   <string name="auth_unknown_host_title">Δεν βρέθηκε υπολογιστής</string>
   <string name="auth_incorrect_path_title">Δεν βρέθηκε στιγμιότυπο server σας</string>
   <string name="auth_timeout_title">Ο εξυπηρετητής αργεί πολύ να απαντήσει</string>
   <string name="auth_incorrect_address_title">Κακώς διατυπωμένο URL</string>
   <string name="auth_ssl_general_error_title">Η αρχικοποίηση του SLL απέτυχε</string>
+  <string name="auth_ssl_unverified_server_title">Αδυναμία επιβεβαίωσης την ταυτότητα SSL του διακομιστή</string>
   <string name="auth_bad_oc_version_title">Μη αναγνωρίσιμη έκδοση διακομιστή server σας</string>
   <string name="auth_wrong_connection_title">Δεν ήταν δυνατή η σύνδεση</string>
   <string name="auth_secure_connection">Επιτεύχθηκε ασφαλής σύνδεση</string>
   <string name="auth_unauthorized">Λάθος όνομα χρήστη ή κωδικός</string>
   <string name="auth_oauth_error">Η πιστοποίηση απέτυχε</string>
+  <string name="auth_oauth_error_access_denied">Ο διακομιστής πιστοποίησης αρνήθηκε την πρόσβαση</string>
+  <string name="auth_wtf_reenter_URL">Απρόοπτη κατάσταση - παρακαλώ εισάγετε τη διεύθυνση URL του διακομιστή ξανά</string>
+  <string name="auth_expired_oauth_token_toast">Η εξουσιοδότησή σας έληξε. Παρακαλώ εξουσιοδοτείστε ξανά</string>
   <string name="auth_expired_basic_auth_toast">Παρακαλώ είσάγετε τον τρέχοντα κωδικό</string>
+  <string name="auth_expired_saml_sso_token_toast">Η συνεδρία σας έληξε. Παρακαλώ συνδεθείτε ξανά</string>
+  <string name="auth_connecting_auth_server">Σύνδεση με το διακομιστή πιστοποίησης σε εξέλιξη...</string>
+  <string name="auth_unsupported_auth_method">Ο διακομιστής δεν υποστηρίζει αυτή τη μέθοδο πιστοποίησης</string>
+  <string name="auth_unsupported_multiaccount">Ο %1$s  δεν υποστηρίζει πολλαπλούς λογαριασμούς</string>
   <string name="fd_keep_in_sync">Διατήρηση αρχείου ενημερωμένo</string>
   <string name="common_rename">Μετονομασία</string>
   <string name="common_remove">Αφαίρεση</string>
   <string name="sync_file_fail_msg">Αδυναμία ελέγχου του απομακρυσμένου αρχείου</string>
   <string name="sync_file_nothing_to_do_msg">Τα περιεχόμενα του αρχείου έχουν ήδη συγχρονιστεί</string>
   <string name="create_dir_fail_msg">Ο κατάλογος δεν ήταν δυνατόν να δημιουργηθεί</string>
+  <string name="filename_forbidden_characters">Μη-επιτρεπόμενοι χαρακτήρες: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Παρακαλούμε περιμένετε</string>
   <string name="filedisplay_unexpected_bad_get_content">Απροσδόκητο σφάλμα, δοκιμάστε με άλλη εφαρμογή</string>
   <string name="filedisplay_no_file_selected">Δεν επιλέχθηκαν αρχεία </string>
+  <string name="activity_chooser_title">Αποστολή συνδέσμου σε ...</string>
+  <string name="oauth_check_onoff">Σύνδεση με oAuth2</string>
+  <string name="oauth_login_connection">Σύνδεση με το διακομιστή oAuth2 σε εξέλιξη...</string>
   <string name="ssl_validator_header">Η ταυτότητα της σελίδας δεν μπορεί να εγκριθεί</string>
   <string name="ssl_validator_reason_cert_not_trusted">- Το πιστοποιητικό του διακομιστή δεν είναι αξιόπιστο</string>
   <string name="ssl_validator_reason_cert_expired">- Το πιστοποιητικό του διακομιστή έχει λήξει</string>
   <string name="preview_image_description">Προεπισκόπηση εικόνας</string>
   <string name="preview_image_error_unknown_format">Αυτή η εικόνε δεν μπόρεσε να προβληθεί</string>
   <string name="error__upload__local_file_not_copied">%1$s δεν μπορεσε να αντιγραφθεί στον %2$s τοπικο καταλόγο </string>
+  <string name="actionbar_failed_instant_upload">Αποτυχημένη στιγμιαία φόρτωση</string>
+  <string name="failed_upload_headline_text">Αποτυχημένες στιγμιαίες φορτώσεις</string>
+  <string name="failed_upload_headline_hint">Σύνοψη όλων των αποτυχημένων φορτώσεων</string>
   <string name="failed_upload_all_cb">επιλογή όλων</string>
+  <string name="failed_upload_headline_retryall_btn">επανάληψη για όλα τα επιλεγμένα</string>
+  <string name="failed_upload_headline_delete_all_btn">διαγραφή όλων των επιλεγμένων από τη λίστα προς μεταφόρτωση</string>
+  <string name="failed_upload_retry_text">επανάληψη προσπάθειας μεταφόρτωσης της εικόνας:</string>
   <string name="failed_upload_load_more_images">Φόρτωση περισσότερων εικόνων</string>
   <string name="failed_upload_failure_text">Μήνυμα Αποτυχίας:</string>
+  <string name="failed_upload_quota_exceeded_text">Παρακαλώ ελέγξτε τις ρυθμίσεις του διακομιστή σας, ίσως έχετε υπερβεί τη διαθέσιμη μερίδα σας.</string>
+  <string name="share_link_no_support_share_api">Λυπάμαι, ο διαμοιρασμός δεν είναι ενεργοποιημένος στο διακομιστή σας. Παρακαλώ επικοινωνήστε με το διαχειριστή σας.</string>
+  <string name="share_link_file_no_exist">Αδυναμία διαμοιρασμού αυτού του αρχείου ή φακέλου. Παρακαλώ βεβαιωθείτε ότι υπάρχει</string>
+  <string name="share_link_file_error">Ένα σφάλμα προέκυψε κατά την προσπάθεια διαμοιρασμού αυτού του αρχείου ή φακέλου</string>
+  <string name="unshare_link_file_error">Ένα σφάλμα προέκυψε κατά τη διάρκεια ακύρωσης διαμοιρασμού αυτού του αρχείου ή φακέλου</string>
 </resources>
index e47efd9..4ec67dd 100644 (file)
@@ -31,7 +31,7 @@
   <string name="recommend_subject">Try %1$s on your smartphone!</string>
   <string name="recommend_text">I want to invite you to use %1$s on your smartphone!\nDownload here: %2$s</string>
   <string name="auth_check_server">Check Server</string>
-  <string name="auth_host_url">Server address</string>
+  <string name="auth_host_url">Server address https://…</string>
   <string name="auth_username">Username</string>
   <string name="auth_password">Password</string>
   <string name="auth_register">New to %1$s?</string>
@@ -56,6 +56,8 @@
   <string name="filedetails_download">Download</string>
   <string name="filedetails_sync_file">Refresh file</string>
   <string name="filedetails_renamed_in_upload_msg">File was renamed to %1$s during upload</string>
+  <string name="action_share_file">Share link</string>
+  <string name="action_unshare_file">Unshare link</string>
   <string name="common_yes">Yes</string>
   <string name="common_no">No</string>
   <string name="common_ok">OK</string>
   <string name="wait_a_moment">Wait a moment</string>
   <string name="filedisplay_unexpected_bad_get_content">Unexpected problem; please select the file from a different app</string>
   <string name="filedisplay_no_file_selected">No file was selected</string>
+  <string name="activity_chooser_title">Send link to …</string>
   <string name="oauth_check_onoff">Log in with oAuth2</string>
   <string name="oauth_login_connection">Connecting to oAuth2 server…</string>
   <string name="ssl_validator_header">The identity of the site could not be verified</string>
   <string name="failed_upload_retry_do_nothing_text">do nothing you are not online for instant upload</string>
   <string name="failed_upload_failure_text">Failure Message: </string>
   <string name="failed_upload_quota_exceeded_text">Please check your server configuration, perhaps your quota is exceeded.</string>
+  <string name="share_link_no_support_share_api">Sorry, sharing is not enabled on your server. Please contact your administrator.</string>
+  <string name="share_link_file_no_exist">Unable to share this file or folder. Please, make sure it exists</string>
+  <string name="share_link_file_error">An error occurred while trying to share this file or folder</string>
+  <string name="unshare_link_file_error">An error occurred while trying to unshare this file or folder</string>
 </resources>
index debd294..cf19b74 100644 (file)
@@ -15,7 +15,6 @@
   <string name="prefs_instant_upload">Kapabligi tujan alŝuton</string>
   <string name="prefs_instant_upload_summary">Tuje alŝuti fotojn faritajn per fotilo</string>
   <string name="prefs_help">Helpo</string>
-  <string name="auth_host_url">Servila adreso</string>
   <string name="auth_username">Uzantonomo</string>
   <string name="auth_password">Pasvorto</string>
   <string name="sync_string_files">Dosieroj</string>
@@ -36,6 +35,7 @@
   <string name="filedetails_modified">Modifita je:</string>
   <string name="filedetails_download">Elŝuti</string>
   <string name="filedetails_renamed_in_upload_msg">La dosiero alinomiĝis al %1$s dum alŝuto</string>
+  <string name="action_share_file">Konhavigi ligilon</string>
   <string name="common_yes">Jes</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Akcepti</string>
index f9196dd..4bc8c76 100644 (file)
   <string name="prefs_log_summary_history">Esto muestra los registros grabados</string>
   <string name="prefs_log_delete_history_button">Eliminar Historial</string>
   <string name="prefs_help">Ayuda</string>
+  <string name="prefs_recommend">Recomendar a un amigo</string>
   <string name="prefs_feedback">Sugerencias</string>
   <string name="prefs_imprint">Imprint</string>
+  <string name="recommend_subject">¡Intento %1$s en tu teléfono inteligente!</string>
+  <string name="recommend_text">¡Quisiera invitarte a usar %1$s en tu smartphone!\nDescárgalo aquí: %2$s</string>
   <string name="auth_check_server">Verificar Servidor</string>
-  <string name="auth_host_url">Dirección del servidor</string>
+  <string name="auth_host_url">Dirección del servidor https://...</string>
   <string name="auth_username">Nombre de usuario</string>
   <string name="auth_password">Contraseña</string>
   <string name="auth_register">¿Sos nuevo para %1$s?</string>
@@ -52,6 +55,7 @@
   <string name="filedetails_download">Descargar</string>
   <string name="filedetails_sync_file">Actualizar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado como %1$s durante la subida</string>
+  <string name="action_share_file">Compartir vínculo</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">Aceptar</string>
@@ -92,6 +96,7 @@
   <string name="sync_foreign_files_forgotten_ticker">Algunos archivos locales fueron olvidados</string>
   <string name="sync_foreign_files_forgotten_content">%1$d archivos del directorio %2$s no pudieron ser copiados en</string>
   <string name="sync_foreign_files_forgotten_explanation">Desde la versión 1.3.16, los archivos subidos desde este dispositivo se copian a un directorio local %1$s para prevenir la pérdida de datos cuando un único archivo es sincronizado con múltiples cuentas. \n\nDebido a este cambio, todos los archivos subidos en versiones previas de esta aplicación fueron copiados al directorio %2$s. No obstante, debido a un error, esta operación no pudo ser completada durante la sincronización de la cuenta. Podés dejar los archivos así y borrar el enlace a %3$s, o podés mover el/los archivos al directorio %1$s y conservar el enlace a %4$s. \n\nAbajo, encontrás la lista con los enlaces a los archivos locales y remotos en %5$s a los que están enlazados.</string>
+  <string name="sync_current_folder_was_removed">El directorio %1$s ya no existe</string>
   <string name="foreign_files_move">Mover todos</string>
   <string name="foreign_files_success">Todos los archivos fueron movidos</string>
   <string name="foreign_files_fail">Algunos archivos no pudieron ser movidos</string>
   <string name="media_err_unsupported">Codec no soportado</string>
   <string name="media_err_io">El archivo de medios no pudo ser leído </string>
   <string name="media_err_malformed">Archivo no está correctamente codificado</string>
+  <string name="media_err_timeout">Tiempo expirado mientras se intentaba reproducir</string>
   <string name="media_err_invalid_progressive_playback">Archivo de medios no puede ser transmitido</string>
   <string name="media_err_unknown">El archivo de medios no se puede reproducir con el reproductor de medios por defecto </string>
   <string name="media_err_security_ex">Error de seguridad al intentar reproducir %1$s</string>
   <string name="auth_connection_established">Conexión establecida</string>
   <string name="auth_testing_connection">Probando conexión...</string>
   <string name="auth_not_configured_title">Configuración de servidor en formato incorrecto</string>
+  <string name="auth_account_not_new">Una cuenta para el mismo usuario y servidor ya existe en el dispositivo</string>
+  <string name="auth_account_not_the_same">El usuario ingresado no concuerda con el usuario de esta cuenta</string>
   <string name="auth_unknown_error_title">¡Ocurrió un error desconocido!</string>
   <string name="auth_unknown_host_title">No fue posible encontrar la dirección</string>
   <string name="auth_incorrect_path_title">Instancia de servidor no encontrada</string>
   <string name="auth_timeout_title">El servidor tardó demasiado en responder</string>
   <string name="auth_incorrect_address_title">URL no válida</string>
   <string name="auth_ssl_general_error_title">Error al inicializar el SSL</string>
+  <string name="auth_ssl_unverified_server_title">No se ha podido verifica la identidad SSL del servidor</string>
   <string name="auth_bad_oc_version_title">No es posible reconocer la versión del servidor</string>
   <string name="auth_wrong_connection_title">No fue posible establecer la conexión</string>
   <string name="auth_secure_connection">Conexión segura establecida</string>
   <string name="auth_oauth_error">Autorización no satisfactoria</string>
   <string name="auth_oauth_error_access_denied">Acceso denegado por el servidor de autorización</string>
   <string name="auth_wtf_reenter_URL">Estado inesperado; por favor, introducí la URL del servidor de nuevo</string>
+  <string name="auth_expired_oauth_token_toast">Tu autorización ha expirado. Por favor, obtenga una nueva autorización</string>
   <string name="auth_expired_basic_auth_toast">Por favor, ingresá tu contraseña actual</string>
+  <string name="auth_expired_saml_sso_token_toast">Su sesión ha expirado. Por favor, conéctese de nuevo</string>
+  <string name="auth_connecting_auth_server">Conectando al servidor de autenticación...</string>
+  <string name="auth_unsupported_auth_method">El servidor no soporta este método de autenticación</string>
+  <string name="auth_unsupported_multiaccount">%1$s no soporta múltiples cuentas</string>
   <string name="fd_keep_in_sync">Mantener el archivo actualizado</string>
   <string name="common_rename">Renombrar</string>
   <string name="common_remove">Borrar</string>
   <string name="sync_file_fail_msg">No pudo comprobarse el archivo remoto</string>
   <string name="sync_file_nothing_to_do_msg">Ya está sincronizado</string>
   <string name="create_dir_fail_msg">No fue posible crear el directorio</string>
+  <string name="filename_forbidden_characters">Caracteres prohibidos: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Esperá un momento</string>
   <string name="filedisplay_unexpected_bad_get_content">Problema inesperado; por favor, intentá con otra aplicación para abrir el archivo</string>
   <string name="filedisplay_no_file_selected">No se seleccionó ningún archivo</string>
+  <string name="oauth_check_onoff">Iniciando sesión con oAuth2</string>
   <string name="oauth_login_connection">Conectando al servidor oAuth2...</string>
   <string name="ssl_validator_header">La identidad del sitio no pudo ser verificada</string>
   <string name="ssl_validator_reason_cert_not_trusted">- El certificado del servidor no es confiable</string>
   <string name="preview_image_description">Previsualización de imagen</string>
   <string name="preview_image_error_unknown_format">No se puede mostrar la imagen</string>
   <string name="error__upload__local_file_not_copied">%1$s no pudo ser copiado al directorio local %2$s</string>
+  <string name="actionbar_failed_instant_upload">Falló InstantUpload</string>
   <string name="failed_upload_headline_text">Error en Cargas instantánea </string>
   <string name="failed_upload_headline_hint">Resumen de todas las cargas instantáneas con error</string>
   <string name="failed_upload_all_cb">Seleccionar todos</string>
diff --git a/res/values-es-rCL/strings.xml b/res/values-es-rCL/strings.xml
new file mode 100644 (file)
index 0000000..a6b3cbb
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+  <string name="actionbar_upload">Subir</string>
+  <string name="actionbar_upload_files">Archivos</string>
+  <string name="actionbar_mkdir">Crear directorio</string>
+  <string name="actionbar_settings">Configuración</string>
+  <string name="prefs_category_general">General</string>
+  <string name="prefs_accounts">Cuentas</string>
+  <string name="auth_username">Usuario</string>
+  <string name="auth_password">Clave</string>
+  <string name="sync_string_files">Archivos</string>
+  <string name="setup_btn_connect">Conectar</string>
+  <string name="uploader_btn_upload_text">Subir</string>
+  <string name="uploader_wrn_no_account_title">No se encuentra la cuenta</string>
+  <string name="uploader_info_uploading">Subiendo</string>
+  <string name="filedetails_select_file">Seleccione un archivo para desplegar información adicional.</string>
+  <string name="filedetails_size">Tamaño:</string>
+  <string name="filedetails_type">Tipo:</string>
+  <string name="filedetails_created">Creado:</string>
+  <string name="filedetails_modified">Modificado:</string>
+  <string name="filedetails_download">Descargar</string>
+  <string name="common_yes">Si</string>
+  <string name="common_no">No</string>
+  <string name="common_ok">OK</string>
+  <string name="common_cancel">Cancelar</string>
+  <string name="common_error">Error</string>
+  <string name="uploader_info_dirname">Nombre del directorio</string>
+  <string name="common_choose_account">Elija una cuenta</string>
+  <string name="pincode_enter_pin_code">Por favor, ingreses su PIN de aplicación</string>
+  <string name="pincode_configure_your_pin">Ingrese su PIN de aplicación</string>
+  <string name="pincode_reenter_your_pincode">Por favor, reingrese su PIN de aplicación</string>
+</resources>
index c757504..b674cea 100644 (file)
@@ -1,2 +1,234 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<resources/>
+<resources>
+  <string name="about_android">App Android %1$s</string>
+  <string name="about_version">versión %1$s</string>
+  <string name="actionbar_sync">Actualizar cuenta</string>
+  <string name="actionbar_upload">Subir archivo</string>
+  <string name="actionbar_upload_from_apps">Contenido de otras aplicaciones</string>
+  <string name="actionbar_upload_files">Archivos</string>
+  <string name="actionbar_open_with">Abrir con</string>
+  <string name="actionbar_mkdir">Crear directorio</string>
+  <string name="actionbar_settings">Ajustes</string>
+  <string name="actionbar_see_details">Detalles</string>
+  <string name="prefs_category_general">General</string>
+  <string name="prefs_category_more">Más</string>
+  <string name="prefs_accounts">Cuentas</string>
+  <string name="prefs_manage_accounts">Gestionar cuentas</string>
+  <string name="prefs_pincode">PIN de aplicación </string>
+  <string name="prefs_pincode_summary">Proteja su cliente</string>
+  <string name="prefs_instant_upload">Habilita la subida instantánea</string>
+  <string name="prefs_instant_upload_summary">Subir instantáneamente las fotos tomadas por la cámara</string>
+  <string name="prefs_log_title">Habilitar registro</string>
+  <string name="prefs_log_summary">Esto es usado para registrar problemas</string>
+  <string name="prefs_log_title_history">Historia del Registro</string>
+  <string name="prefs_log_summary_history">Esto muestra los registros grabados</string>
+  <string name="prefs_log_delete_history_button">Eliminar Historial</string>
+  <string name="prefs_help">Ayuda</string>
+  <string name="prefs_recommend">Recomendar a un amigo</string>
+  <string name="prefs_feedback">Mensajes de retroalimentación</string>
+  <string name="prefs_imprint">Imprint</string>
+  <string name="recommend_subject">Prueba  %1$s en tu smarthphone!</string>
+  <string name="recommend_text">Quiero invitarte a usar %1$s en tu smarthphone!⏎\nDescargalo aquí: %2$s</string>
+  <string name="auth_check_server">Compruebe el servidor.</string>
+  <string name="auth_host_url">Dirección del servidor https://…</string>
+  <string name="auth_username">Nombre de usuario</string>
+  <string name="auth_password">Contraseña</string>
+  <string name="auth_register">New to %1$s?</string>
+  <string name="sync_string_files">Archivos</string>
+  <string name="setup_btn_connect">Conectar</string>
+  <string name="uploader_btn_upload_text">Subir</string>
+  <string name="uploader_top_message">Escoja el directorio de carga:</string>
+  <string name="uploader_wrn_no_account_title">No se encontraron cuentas</string>
+  <string name="uploader_wrn_no_account_text">No hay cuentas de %1$s en tu dispositivo. Por favor configura una cuenta primero.</string>
+  <string name="uploader_wrn_no_account_setup_btn_text">Configuración</string>
+  <string name="uploader_wrn_no_account_quit_btn_text">Salir</string>
+  <string name="uploader_wrn_no_content_title">No hay contenido para subir</string>
+  <string name="uploader_wrn_no_content_text">Ningún contenido ha sido recibido. No hay nada que subir.</string>
+  <string name="uploader_error_forbidden_content">%1$s no está autorizado para acceder al contenido compartido</string>
+  <string name="uploader_info_uploading">Enviando</string>
+  <string name="file_list_empty">No hay archivos en esta carpeta.\nPuedes añadir nuevos archivos con la opción \"Subir\" del menú.</string>
+  <string name="filedetails_select_file">Pulsa sobre un archivo para mostrar información adicional.</string>
+  <string name="filedetails_size">Tamaño:</string>
+  <string name="filedetails_type">Tipo:</string>
+  <string name="filedetails_created">Creado:</string>
+  <string name="filedetails_modified">Modificado:</string>
+  <string name="filedetails_download">Descargar</string>
+  <string name="filedetails_sync_file">Actualizar archivo</string>
+  <string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado como %1$s durante la subida</string>
+  <string name="action_share_file">Enlace compartido</string>
+  <string name="common_yes">Sí</string>
+  <string name="common_no">No</string>
+  <string name="common_ok">Aceptar</string>
+  <string name="common_cancel_download">Cancelar descarga</string>
+  <string name="common_cancel_upload">Cancelar subida</string>
+  <string name="common_cancel">Cancelar</string>
+  <string name="common_save_exit">Guardar &amp; Salir</string>
+  <string name="common_error">Error</string>
+  <string name="common_loading">Cargando ...</string>
+  <string name="common_error_unknown">Error desconocido</string>
+  <string name="about_title">Acerca de</string>
+  <string name="change_password">Cambiar contraseña</string>
+  <string name="delete_account">Eliminar cuenta</string>
+  <string name="create_account">Crear cuenta</string>
+  <string name="upload_chooser_title">Subir</string>
+  <string name="uploader_info_dirname">Nombre de directorio</string>
+  <string name="uploader_upload_in_progress_ticker">Subiendo...</string>
+  <string name="uploader_upload_in_progress_content">%1$d%% Subiendo %2$s</string>
+  <string name="uploader_upload_succeeded_ticker">Subido con éxito</string>
+  <string name="uploader_upload_succeeded_content_single">%1$s se ha subido con éxito</string>
+  <string name="uploader_upload_failed_ticker">Error en la subida</string>
+  <string name="uploader_upload_failed_content_single">La subida de %1$s no se pudo completar</string>
+  <string name="downloader_download_in_progress_ticker">Descargando ...</string>
+  <string name="downloader_download_in_progress_content">%1$s Descargada de %2$s</string>
+  <string name="downloader_download_succeeded_ticker">Descarga completa</string>
+  <string name="downloader_download_succeeded_content">%1$s se ha descargado con éxito</string>
+  <string name="downloader_download_failed_ticker">Falló la descarga</string>
+  <string name="downloader_download_failed_content">La descarga de %1$s no se pudo completar</string>
+  <string name="downloader_not_downloaded_yet">No descargado</string>
+  <string name="common_choose_account">Elige una cuenta</string>
+  <string name="sync_fail_ticker">Falló la sincronización</string>
+  <string name="sync_fail_content">La sincronización de %1$s s no se pudo completar</string>
+  <string name="sync_fail_content_unauthorized">Contraseña no válida para %1$s</string>
+  <string name="sync_conflicts_in_favourites_ticker">Se encontraron conflictos</string>
+  <string name="sync_conflicts_in_favourites_content">Falló la sincronización de contenidos de %1$d archivos</string>
+  <string name="sync_fail_in_favourites_ticker">Fallos en la sincronización de contenidos</string>
+  <string name="sync_fail_in_favourites_content">Los contenidos de %1$d archivos no fueron sincronizados (%2$d conflictos)</string>
+  <string name="sync_foreign_files_forgotten_ticker">Algunos archivos locales se han perdido</string>
+  <string name="sync_foreign_files_forgotten_content">%1$d archivos de %2$s no han podido ser copiados</string>
+  <string name="sync_foreign_files_forgotten_explanation">Como versión 1.3.16, los archivos subidos desde este dispositivo son copiados a un archivo %1$s local para prevenir perdida de datos cuando un simple archivo es sincronizado con multiples cuentas.\n\nDebido a este cambio, todos los archivos subidos en versiones previas de esta aplicación han sido copiados a la carpeta %2$s. No obtante, un error previno el completado de esta operación durante la sincronización de cuenta. Debería dejar el o los archivos así y eliminar el enlace a %3$s o mover el o los archivos al %1$s directorio y conservar el enlace a %4$s.\n\nListado abajo tiene los enlaces a los archivos locales y archivos remotos en %5$s </string>
+  <string name="sync_current_folder_was_removed">La carpeta local %1$s no existe.</string>
+  <string name="foreign_files_move">Mover todo</string>
+  <string name="foreign_files_success">Todos los archivos fueron movidos</string>
+  <string name="foreign_files_fail">Algunos archivos no han podido ser movidos</string>
+  <string name="foreign_files_local_text">Local: %1$s</string>
+  <string name="foreign_files_remote_text">Remoto: %1$s</string>
+  <string name="upload_query_move_foreign_files">No hay suficiente espacio para copiar los archivos seleccionados en la carpeta %1$s. ¿Quiere moverlos en lugar de copiarlos?</string>
+  <string name="pincode_enter_pin_code">Por favor, inserta tu PIN de aplicación</string>
+  <string name="pincode_configure_your_pin">Introduzca un PIN para la aplicación</string>
+  <string name="pincode_configure_your_pin_explanation">Se solicitará el PIN cada vez que se inicie la aplicación</string>
+  <string name="pincode_reenter_your_pincode">Repita el PIN para la aplicación, por favor</string>
+  <string name="pincode_remove_your_pincode">Borre su PIN de aplicación</string>
+  <string name="pincode_mismatch">Los PIN introducidos no son iguales</string>
+  <string name="pincode_wrong">PIN de aplicación incorrecto</string>
+  <string name="pincode_removed">PIN de aplicación borrado</string>
+  <string name="pincode_stored">PIN de aplicación guardado</string>
+  <string name="media_notif_ticker">Reproductor de música %1$s</string>
+  <string name="media_state_playing">%1$s (reproduciendo)</string>
+  <string name="media_state_loading">%1$s (cargando)</string>
+  <string name="media_event_done">%1$s reproducción finalizada</string>
+  <string name="media_err_nothing_to_play">No se encuentra archivo de medio</string>
+  <string name="media_err_no_account">No se ha proporcionado cuenta</string>
+  <string name="media_err_not_in_owncloud">El archivo no esta en una cuenta valida </string>
+  <string name="media_err_unsupported">Codec No Soportado</string>
+  <string name="media_err_io">El archivo de medios no pudo ser leído </string>
+  <string name="media_err_malformed">Archivo no codificado correctamente</string>
+  <string name="media_err_timeout">Tiempo de espera agotado en el intento de reproducción</string>
+  <string name="media_err_invalid_progressive_playback">Archivo de medio no puede ser transmitido</string>
+  <string name="media_err_unknown">El archivo de medios no se puede reproducir con el reproductor de medios por defecto </string>
+  <string name="media_err_security_ex">Error de seguridad al intentar reproducir %1$s</string>
+  <string name="media_err_io_ex">Error de entrada al intentar reproducir %1$s</string>
+  <string name="media_err_unexpected">Error inesperado intentando reproducir %1$s</string>
+  <string name="media_rewind_description">Botón Rebobinado</string>
+  <string name="media_play_pause_description">Botón de reproducción o pausa </string>
+  <string name="media_forward_description">Botón avance rápido</string>
+  <string name="auth_trying_to_login">Intentado iniciar sesión...</string>
+  <string name="auth_no_net_conn_title">Sin conexión de red</string>
+  <string name="auth_nossl_plain_ok_title">Conexión segura no disponible.</string>
+  <string name="auth_connection_established">Conexión establecida</string>
+  <string name="auth_testing_connection">Probando conexión...</string>
+  <string name="auth_not_configured_title">Configuración de servidor en formato incorrecto</string>
+  <string name="auth_account_not_new">Una cuenta para el mismo usuario y servidor ya existen en el dispositivo</string>
+  <string name="auth_account_not_the_same">El usuario introducido no concuerda con el usuario de esta cuenta</string>
+  <string name="auth_unknown_error_title">Ocurrió un error desconocido</string>
+  <string name="auth_unknown_host_title">No se pudo encontrar la dirección</string>
+  <string name="auth_incorrect_path_title">Instancia de servidor no encontrada</string>
+  <string name="auth_timeout_title">El servidor ha tardado demasiado en responder</string>
+  <string name="auth_incorrect_address_title">URL no válida</string>
+  <string name="auth_ssl_general_error_title">Falló la inicialización SSL</string>
+  <string name="auth_ssl_unverified_server_title">No fue posible verificar la identidad del servidor SLL</string>
+  <string name="auth_bad_oc_version_title">No se reconoce  la versión del servidor </string>
+  <string name="auth_wrong_connection_title">No se ha podido establecer la conexión</string>
+  <string name="auth_secure_connection">Conexión segura establecida</string>
+  <string name="auth_unauthorized">Nombre de usuario o contraseña incorrecta</string>
+  <string name="auth_oauth_error">Autorización no satisfactoria</string>
+  <string name="auth_oauth_error_access_denied">Acceso denegado por servidor de autorización</string>
+  <string name="auth_wtf_reenter_URL">Estado inesperado; por favor, introduzca la URL del servidor de nuevo</string>
+  <string name="auth_expired_oauth_token_toast">Su autorización ha expirado. Por favor, autorice de nuevo</string>
+  <string name="auth_expired_basic_auth_toast">Por favor, introduzca la contraseña actual.</string>
+  <string name="auth_expired_saml_sso_token_toast">Su sesión ha expirado. Favor de conectarse de nuevo</string>
+  <string name="auth_connecting_auth_server">Conectando al servidor de autenticación...</string>
+  <string name="auth_unsupported_auth_method">El servidor no soporta este método de autenticación</string>
+  <string name="auth_unsupported_multiaccount">%1$s no soporta cuentas múltiples</string>
+  <string name="fd_keep_in_sync">Mantener el archivo actualizado</string>
+  <string name="common_rename">Renombrar</string>
+  <string name="common_remove">Borrar</string>
+  <string name="confirmation_remove_alert">¿Está seguro que desea borrar %1$s ?</string>
+  <string name="confirmation_remove_folder_alert">¿Desea elimiar %1$s y sus descendientes?</string>
+  <string name="confirmation_remove_local">Sólo local</string>
+  <string name="confirmation_remove_folder_local">Sólo archivos locales</string>
+  <string name="confirmation_remove_remote">Eliminar del servidor</string>
+  <string name="confirmation_remove_remote_and_local">Tanto remoto como local</string>
+  <string name="remove_success_msg">Borrado correctamente</string>
+  <string name="remove_fail_msg">El borrado no pudo ser completado</string>
+  <string name="rename_dialog_title">Introduzca un nombre nuevo</string>
+  <string name="rename_local_fail_msg">No se pudo cambiar el nombre de la copia local, trata con un nombre differente</string>
+  <string name="rename_server_fail_msg">No se pudo cambiar el nombre</string>
+  <string name="sync_file_fail_msg">No pudo comprobarse el archivo remoto</string>
+  <string name="sync_file_nothing_to_do_msg">Ya está sincronizado</string>
+  <string name="create_dir_fail_msg">El directorio no pudo ser creado</string>
+  <string name="filename_forbidden_characters">Carácteres ilegales: / \\ &lt; &gt; : \" | ? *</string>
+  <string name="wait_a_moment">Espere un momento</string>
+  <string name="filedisplay_unexpected_bad_get_content">Problema inesperado; por favor, prueba otra app para seleccionar el archivo</string>
+  <string name="filedisplay_no_file_selected">No fué seleccionado ningún archivo</string>
+  <string name="oauth_check_onoff">Ingresar con oAuth2</string>
+  <string name="oauth_login_connection">Conectando al servidor oAuth2...</string>
+  <string name="ssl_validator_header">La identidad del sitio no puede ser verificada</string>
+  <string name="ssl_validator_reason_cert_not_trusted">- El certificado del servidor no es de confianza</string>
+  <string name="ssl_validator_reason_cert_expired">- El certificado del servidor expiró</string>
+  <string name="ssl_validator_reason_cert_not_yet_valid">- El certificado del servidor es demasiado reciente</string>
+  <string name="ssl_validator_reason_hostname_not_verified">- La URL no coincide con el nombre de dominio del certificado</string>
+  <string name="ssl_validator_question">¿Confías de todas formas en este certificado?</string>
+  <string name="ssl_validator_not_saved">El certificado no pudo ser guardado</string>
+  <string name="ssl_validator_btn_details_see">Detalles</string>
+  <string name="ssl_validator_btn_details_hide">Ocultar</string>
+  <string name="ssl_validator_label_subject">Emitido para:</string>
+  <string name="ssl_validator_label_issuer">Emitido por:</string>
+  <string name="ssl_validator_label_CN">Nombre común:</string>
+  <string name="ssl_validator_label_O">Organización:</string>
+  <string name="ssl_validator_label_OU">Unidad organizativa</string>
+  <string name="ssl_validator_label_C">Pais:</string>
+  <string name="ssl_validator_label_ST">Estado:</string>
+  <string name="ssl_validator_label_L">Ubicación:</string>
+  <string name="ssl_validator_label_validity">Validez:</string>
+  <string name="ssl_validator_label_validity_from">De:</string>
+  <string name="ssl_validator_label_validity_to">A:</string>
+  <string name="ssl_validator_label_signature">Firma:</string>
+  <string name="ssl_validator_label_signature_algorithm">Algoritmo:</string>
+  <string name="placeholder_sentence">Esto es un marcador de posición</string>
+  <string name="placeholder_filename">marcadordeposición.txt</string>
+  <string name="placeholder_filetype">Imagen PNG</string>
+  <string name="placeholder_filesize">389 KB</string>
+  <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
+  <string name="placeholder_media_time">12:23:45</string>
+  <string name="instant_upload_on_wifi">Subir imágenes sólo via WiFi</string>
+  <string name="instant_upload_path">/SubidasInstantáneas</string>
+  <string name="conflict_title">Conflicto en la actualización</string>
+  <string name="conflict_message">El archivo remoto %s no está sincronizado con el archivo local. Si continúa, se reemplazará el contenido del archivo en el servidor.</string>
+  <string name="conflict_keep_both">Mantener ambas</string>
+  <string name="conflict_overwrite">Sobrescribir</string>
+  <string name="conflict_dont_upload">No subir</string>
+  <string name="preview_image_description">Previsualización de imagen</string>
+  <string name="preview_image_error_unknown_format">No se puede mostrar la imagen</string>
+  <string name="error__upload__local_file_not_copied">%1$s no puede ser copiado al %2$s directorio local </string>
+  <string name="actionbar_failed_instant_upload">Carga instantánea fallida</string>
+  <string name="failed_upload_headline_text">Cargas instantáneas fallidas</string>
+  <string name="failed_upload_headline_hint">Resumen de todas las cargas instantáneas fallidas</string>
+  <string name="failed_upload_all_cb">Seleccionar todos</string>
+  <string name="failed_upload_headline_retryall_btn">Reintentar todos los seleccionados</string>
+  <string name="failed_upload_headline_delete_all_btn">Eliminar todo de la cola de subida</string>
+  <string name="failed_upload_retry_text">Reintentar subida de imagen:</string>
+  <string name="failed_upload_load_more_images">Cargar mas imágenes</string>
+  <string name="failed_upload_retry_do_nothing_text">No hacer nada no está conectado para subida instantánea</string>
+  <string name="failed_upload_failure_text">Mensaje de error:</string>
+  <string name="failed_upload_quota_exceeded_text">Por favor revise su configuración de servidor, posiblemente su cuota se haya excedido.</string>
+</resources>
index e7eff34..1e19c56 100644 (file)
@@ -1,14 +1,14 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
-  <string name="about_android">App Android %1$s</string>
+  <string name="about_android">%1$s para Android</string>
   <string name="about_version">versión %1$s</string>
   <string name="actionbar_sync">Actualizar cuenta</string>
-  <string name="actionbar_upload">Subir archivo</string>
+  <string name="actionbar_upload">Subir</string>
   <string name="actionbar_upload_from_apps">Contenido de otras aplicaciones</string>
   <string name="actionbar_upload_files">Archivos</string>
   <string name="actionbar_open_with">Abrir con</string>
   <string name="actionbar_mkdir">Crear directorio</string>
-  <string name="actionbar_settings">Ajustes</string>
+  <string name="actionbar_settings">Configuración</string>
   <string name="actionbar_see_details">Detalles</string>
   <string name="prefs_category_general">General</string>
   <string name="prefs_category_more">Más</string>
@@ -16,7 +16,7 @@
   <string name="prefs_manage_accounts">Gestionar cuentas</string>
   <string name="prefs_pincode">PIN de aplicación </string>
   <string name="prefs_pincode_summary">Proteja su cliente</string>
-  <string name="prefs_instant_upload">Habilita la subida instantánea</string>
+  <string name="prefs_instant_upload">Activar la subida instantánea</string>
   <string name="prefs_instant_upload_summary">Subir instantáneamente las fotos tomadas por la cámara</string>
   <string name="prefs_log_title">Habilitar registro</string>
   <string name="prefs_log_summary">Esto es usado para registrar problemas</string>
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Prueba  %1$s en tu smarthphone!</string>
   <string name="recommend_text">Quiero invitarte a usar %1$s en tu smarthphone!⏎\nDescargalo aquí: %2$s</string>
   <string name="auth_check_server">Compruebe el servidor.</string>
-  <string name="auth_host_url">Dirección del servidor</string>
+  <string name="auth_host_url">Dirección del servidor https://…</string>
   <string name="auth_username">Nombre de usuario</string>
   <string name="auth_password">Contraseña</string>
   <string name="auth_register">New to %1$s?</string>
   <string name="setup_btn_connect">Conectar</string>
   <string name="uploader_btn_upload_text">Subir</string>
   <string name="uploader_top_message">Escoja el directorio de carga:</string>
-  <string name="uploader_wrn_no_account_title">No se encontraron cuentas</string>
+  <string name="uploader_wrn_no_account_title">No se encontró la cuenta</string>
   <string name="uploader_wrn_no_account_text">No hay cuentas de %1$s en tu dispositivo. Por favor configura una cuenta primero.</string>
   <string name="uploader_wrn_no_account_setup_btn_text">Configuración</string>
   <string name="uploader_wrn_no_account_quit_btn_text">Salir</string>
   <string name="uploader_wrn_no_content_title">No hay contenido para subir</string>
   <string name="uploader_wrn_no_content_text">Ningún contenido ha sido recibido. No hay nada que subir.</string>
   <string name="uploader_error_forbidden_content">%1$s no está autorizado para acceder al contenido compartido</string>
-  <string name="uploader_info_uploading">Enviando</string>
+  <string name="uploader_info_uploading">Subiendo...</string>
   <string name="file_list_empty">No hay archivos en esta carpeta.\nPuedes añadir nuevos archivos con la opción \"Subir\" del menú.</string>
   <string name="filedetails_select_file">Pulsa sobre un archivo para mostrar información adicional.</string>
   <string name="filedetails_size">Tamaño:</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">Descargar</string>
   <string name="filedetails_sync_file">Actualizar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El fichero fue renombrado como %1$s durante la subida</string>
+  <string name="action_share_file">Enlace compartido</string>
+  <string name="action_unshare_file">Ya no compartir enlace</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">Aceptar</string>
@@ -78,7 +80,7 @@
   <string name="uploader_upload_failed_ticker">Error en la subida</string>
   <string name="uploader_upload_failed_content_single">La subida de %1$s no se pudo completar</string>
   <string name="downloader_download_in_progress_ticker">Descargando ...</string>
-  <string name="downloader_download_in_progress_content">%1$s Descargada de %2$s</string>
+  <string name="downloader_download_in_progress_content">%1$d%% Descargado de %2$s</string>
   <string name="downloader_download_succeeded_ticker">Descarga completa</string>
   <string name="downloader_download_succeeded_content">%1$s se ha descargado con éxito</string>
   <string name="downloader_download_failed_ticker">Falló la descarga</string>
   <string name="filename_forbidden_characters">Carácteres ilegales: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Espere un momento</string>
   <string name="filedisplay_unexpected_bad_get_content">Problema inesperado; por favor, prueba otra app para seleccionar el archivo</string>
-  <string name="filedisplay_no_file_selected">No fué seleccionado ningún archivo</string>
+  <string name="filedisplay_no_file_selected">No hay ficheros seleccionados.</string>
+  <string name="activity_chooser_title">Enviar enlace a...</string>
   <string name="oauth_check_onoff">Ingresar con oAuth2</string>
   <string name="oauth_login_connection">Conectando al servidor oAuth2...</string>
   <string name="ssl_validator_header">La identidad del sitio no puede ser verificada</string>
   <string name="placeholder_filesize">389 KB</string>
   <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
   <string name="placeholder_media_time">12:23:45</string>
-  <string name="instant_upload_on_wifi">Subir imágenes sólo via WiFi</string>
+  <string name="instant_upload_on_wifi">Subir imágenes sólo cuando hay WiFi</string>
   <string name="instant_upload_path">/SubidasInstantáneas</string>
   <string name="conflict_title">Conflicto en la actualización</string>
   <string name="conflict_message">El archivo remoto %s no está sincronizado con el archivo local. Si continúa, se reemplazará el contenido del archivo en el servidor.</string>
   <string name="preview_image_description">Previsualización de imagen</string>
   <string name="preview_image_error_unknown_format">No se puede mostrar la imagen</string>
   <string name="error__upload__local_file_not_copied">%1$s no puede ser copiado al %2$s directorio local </string>
+  <string name="actionbar_failed_instant_upload">Carga instantánea fallida</string>
   <string name="failed_upload_headline_text">Cargas instantáneas fallidas</string>
   <string name="failed_upload_headline_hint">Resumen de todas las cargas instantáneas fallidas</string>
   <string name="failed_upload_all_cb">Seleccionar todos</string>
   <string name="failed_upload_retry_do_nothing_text">No hacer nada no está conectado para subida instantánea</string>
   <string name="failed_upload_failure_text">Mensaje de error:</string>
   <string name="failed_upload_quota_exceeded_text">Por favor revise su configuración de servidor, posiblemente su cuota se haya excedido.</string>
+  <string name="share_link_no_support_share_api">Compartir archivos no está activado en su servidor. Sírvase contactar a su administrador de sistema.</string>
+  <string name="share_link_file_no_exist">No es posible compartir este archivo o carpeta. Asegúrese de que existe.</string>
+  <string name="share_link_file_error">Ocurrió un error al tratar de compartir este archivo o carpeta</string>
+  <string name="unshare_link_file_error">Ocurrió un error al tratar de ya no compartir este archivo o carpeta</string>
 </resources>
index 41a7c31..eba9663 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Proovi oma nutitelefonil rakendust %1$s!</string>
   <string name="recommend_text">Soovin sind kutsuda kasutama oma nutitelefonil rakendust %1$s!\nLae alla siit: %2$s</string>
   <string name="auth_check_server">Kontrolli serverit</string>
-  <string name="auth_host_url">Serveri aadress</string>
+  <string name="auth_host_url">Serveri aadress https://...</string>
   <string name="auth_username">Kasutajanimi</string>
   <string name="auth_password">Parool</string>
   <string name="auth_register">Uus %1$s kasutaja?</string>
@@ -55,6 +55,7 @@
   <string name="filedetails_download">Lae alla</string>
   <string name="filedetails_sync_file">Värskenda faili</string>
   <string name="filedetails_renamed_in_upload_msg">Fail nimetati üleslaadimise käigus ümber %1$ </string>
+  <string name="action_share_file">Jaga linki</string>
   <string name="common_yes">Jah</string>
   <string name="common_no">Ei</string>
   <string name="common_ok">OK</string>
   <string name="sync_file_fail_msg">Mujaloleva faili kontrollimine ebaõnnestus</string>
   <string name="sync_file_nothing_to_do_msg">Faili sisu on juba sünkroniseeritud</string>
   <string name="create_dir_fail_msg">Kausta loomine ebaõnnestus</string>
+  <string name="filename_forbidden_characters">Keelatud sümbolid:  / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Oota hetk</string>
   <string name="filedisplay_unexpected_bad_get_content">Ootamatu tõrge ; palun kasuta faili valimiseks mõnda teist rakendust</string>
   <string name="filedisplay_no_file_selected">Ühtegi faili pole valitud</string>
+  <string name="activity_chooser_title">Saada link</string>
   <string name="oauth_check_onoff">Logi sisse oAuth2-ga</string>
   <string name="oauth_login_connection">oAuth2 serveriga ühendumine...</string>
   <string name="ssl_validator_header">Saidi identiteeti ei suudetud kinnitada</string>
   <string name="preview_image_description">Pildi eelvaade</string>
   <string name="preview_image_error_unknown_format">Seda pilti ei saa näidata</string>
   <string name="error__upload__local_file_not_copied">%1$s ei suudetud kopeerida kohalikku kataloogi failina %2$s</string>
+  <string name="actionbar_failed_instant_upload">Ebaõnnestunud kohene üleslaadimine</string>
   <string name="failed_upload_headline_text">Ebaõnnestunud kohesed üleslaadimised</string>
   <string name="failed_upload_headline_hint">Kõikide ebaõnnestunud üleslaadimiste kokkuvõte</string>
   <string name="failed_upload_all_cb">vali kõik</string>
   <string name="failed_upload_retry_do_nothing_text">ära tee midagi, sa pole võrku ühendatud koheseks üleslaadimiseks</string>
   <string name="failed_upload_failure_text">Veateade:</string>
   <string name="failed_upload_quota_exceeded_text">Palun kontrolli oma serveri seadeid, võib-olla on mahulimiit ületatud.</string>
+  <string name="share_link_file_error">Faili või kausta jagamisel esines viga</string>
+  <string name="unshare_link_file_error">Faili või kausta jagamise tühistamisel esines viga</string>
 </resources>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
new file mode 100644 (file)
index 0000000..64bd780
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+  <string name="filedetails_download">Deskargatu</string>
+  <string name="common_cancel">Ezeztatu</string>
+</resources>
index 221b0b8..6f476d9 100644 (file)
   <string name="prefs_log_summary_history">Honek gordetako erregistroak bistaratzen ditu.</string>
   <string name="prefs_log_delete_history_button">Ezabatu historia</string>
   <string name="prefs_help">Laguntza</string>
+  <string name="prefs_recommend">Lagun bati aholkatu</string>
+  <string name="prefs_feedback">Oharrak</string>
   <string name="prefs_imprint">Imprint</string>
+  <string name="recommend_subject">Probatu %1$s zure telefono adimentsuan!</string>
+  <string name="recommend_text">Nik %1$s zure telefono adimentsuan erabitzera gonbidatu nahi zaitut!\nDeskargatu hemen: %2$s</string>
   <string name="auth_check_server">Egiaztatu zerbitzaria</string>
-  <string name="auth_host_url">Zerbitzariaren helbidea</string>
+  <string name="auth_host_url">Zerbitzariaren helbidea https://</string>
   <string name="auth_username">Erabiltzaile izena</string>
   <string name="auth_password">Pasahitza</string>
   <string name="auth_register">Berria %1$s-n?</string>
@@ -51,6 +55,7 @@
   <string name="filedetails_download">Deskargatu</string>
   <string name="filedetails_sync_file">Freskatu fitxaegia</string>
   <string name="filedetails_renamed_in_upload_msg">Fitxategiaren izena %1$sra aldatu da igotzean</string>
+  <string name="action_share_file">Elkarbanatu lotura</string>
   <string name="common_yes">Bai</string>
   <string name="common_no">Ez</string>
   <string name="common_ok">Ados</string>
@@ -90,6 +95,8 @@
   <string name="sync_fail_in_favourites_content">%1$d fitxategien edukiak ezin dira sinkronizatu (%2$d gatazka)</string>
   <string name="sync_foreign_files_forgotten_ticker">Bertako fitxategi batzuk ahaztu dira</string>
   <string name="sync_foreign_files_forgotten_content">%2$s karpetako %1$d fitxategi ezin dira dira kopiatu</string>
+  <string name="sync_foreign_files_forgotten_explanation">1.3.16 bertsioan, gailu honetatik igotzen diren fitxategiak bertako %1$s karpetara mugitzen dira datu galera ekiditzeko fitxategi bat kontu ezberdinekin sinkronizatzen denean.\n\nAldaketa hau dela eta, programa honen aurreko bertsioetan igotako fitxategi guztiak %2$s karpetara kopiatu dira. Hala ere, errore batek hau burutzea ekidin du kontuaren sinkronizazioa egiten ari zen bitartean. Orain fitxategiak dauden bezala utz ditzakezu eta %3$s rako lotura ezabatu, edo fitxategiak %1$s karpetara mugi ditzakezu eta %4$srako lotura mantendu.\n\nBehean bertako fitxategien zerrenda eta %5$s era lotuta zeuden urruneko fitxategiena.</string>
+  <string name="sync_current_folder_was_removed">%1$s karpeta dagoeneko ez da existitzen</string>
   <string name="foreign_files_move">Mugitu denak</string>
   <string name="foreign_files_success">Fitxategi guztiak mugitu dira</string>
   <string name="foreign_files_fail">Fitxategi batzuk ezin dira mugitu</string>
   <string name="media_err_unsupported">Onartzen ez de euskarri kodeka</string>
   <string name="media_err_io">Euskarri fitxategia ezin da bihurtu</string>
   <string name="media_err_malformed">Euskarri fitxategia ezin da kodetu</string>
+  <string name="media_err_timeout">Erreproduzitzen saiatzean denbora iraungitu da</string>
   <string name="media_err_invalid_progressive_playback">Euskarri fitxategia ezin da jariotu</string>
   <string name="media_err_unknown">Euskarri fitxategia ezin erreproduzitu stock euskarri erreproduzigailuarekin</string>
   <string name="media_err_security_ex">Segurtasun errorea %1$s erreproduzitzen saiatzean</string>
   <string name="auth_connection_established">Konexioa ezarri da</string>
   <string name="auth_testing_connection">Konexioa probatzen...</string>
   <string name="auth_not_configured_title">gaizki egindako server konfigurazioa</string>
+  <string name="auth_account_not_new">Erabiltzaile eta zerbitzari hauendako dagoeneko kontu bat  existitzen da gailu honetan</string>
+  <string name="auth_account_not_the_same">Sartutako erabiltzaileak ez du bat egiten kontu honetako erabiltzailearekin</string>
   <string name="auth_unknown_error_title">Errore ezezagun bat gertatu da</string>
   <string name="auth_unknown_host_title">Ezin izan da hostalaria aurkitu</string>
   <string name="auth_incorrect_path_title">ez da serveren instalaziorik aurkitu</string>
   <string name="auth_timeout_title">Zerbitzariak denbora asko hartu du erantzuteko</string>
   <string name="auth_incorrect_address_title">Gaizki sortutako URLa</string>
   <string name="auth_ssl_general_error_title">SSL abiaratzeak huts egin du</string>
+  <string name="auth_ssl_unverified_server_title">Ezin izan da SSL zerbitzariaren identitaea egiaztatu</string>
   <string name="auth_bad_oc_version_title">server zerbitzari bertsio ezezaguna</string>
   <string name="auth_wrong_connection_title">Ezin izan da konexioa egin</string>
   <string name="auth_secure_connection">Konexio segurua ezarri da</string>
   <string name="auth_oauth_error">Baimena ez da lortu</string>
   <string name="auth_oauth_error_access_denied">Sarrera autorizazio zerbitzariak ukatua</string>
   <string name="auth_wtf_reenter_URL">Egoera esperogabea, mesedez idatzi berriz zerbitzari URLa</string>
+  <string name="auth_expired_oauth_token_toast">Zure baimena iraungitu da.\nMesedez, baimendu berriz</string>
   <string name="auth_expired_basic_auth_toast">Mesedez, sartu oraingo pasahitza</string>
+  <string name="auth_expired_saml_sso_token_toast">Zure saioa iraungitu da. Mesdez konektatu berriro</string>
+  <string name="auth_connecting_auth_server">Konektatzen autentikazio zerbitzarira...</string>
+  <string name="auth_unsupported_auth_method">Zerbitzariak ez du autentikazio metodo hau onartzen</string>
+  <string name="auth_unsupported_multiaccount">%1$s ez du kontu anitzak onartzen</string>
   <string name="fd_keep_in_sync">Mantendu fitxategia eguneratuta</string>
   <string name="common_rename">Berrizendatu</string>
   <string name="common_remove">Ezabatu</string>
   <string name="sync_file_fail_msg">Urruneko fitxategia ezin izan da arakatu</string>
   <string name="sync_file_nothing_to_do_msg">Fitxategi edukiak dagoeneko sinkronizaturik</string>
   <string name="create_dir_fail_msg">Karpeta ezin da sortu</string>
+  <string name="filename_forbidden_characters">Debekatutako karaktereak: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Itxaron momentu bat</string>
   <string name="filedisplay_unexpected_bad_get_content">Ezusteko arazoa; mesedez, saiatu beste app batekin fitxategia hautatzeko</string>
   <string name="filedisplay_no_file_selected">Ez da fitxategirik hautatu</string>
+  <string name="oauth_check_onoff">Saioa hasi oAuth2-rekin</string>
   <string name="oauth_login_connection">Konektatzen oAuth2 zerbitzarira...</string>
   <string name="ssl_validator_header">Lekuaren identitatea ezin da egiaztatu</string>
   <string name="ssl_validator_reason_cert_not_trusted">- Zerbitzariaren ziurtagiria ez da fidagarria</string>
   <string name="preview_image_description">Irudi aurreikuspena</string>
   <string name="preview_image_error_unknown_format">Ezin da irudi hau erakutsi</string>
   <string name="error__upload__local_file_not_copied">%1$s ezin da %2$s bertako karpetara kopiatu</string>
+  <string name="actionbar_failed_instant_upload">UnekoIgoerak huts egin du</string>
   <string name="failed_upload_headline_text">Uneko igoerek huts egin dute</string>
   <string name="failed_upload_headline_hint">Huts egindako igoeren laburpena</string>
   <string name="failed_upload_all_cb">Hautatu dena</string>
index 15690cc..d37ecfe 100644 (file)
@@ -26,7 +26,6 @@
   <string name="prefs_help">راه‌نما</string>
   <string name="prefs_feedback">باز خورد</string>
   <string name="prefs_imprint">مهر زدن</string>
-  <string name="auth_host_url">آدرس سرور</string>
   <string name="auth_username">نام کاربری</string>
   <string name="auth_password">رمز عبور</string>
   <string name="sync_string_files">پرونده‌ها</string>
index d2f780b..e81641d 100644 (file)
@@ -27,7 +27,7 @@
   <string name="recommend_subject">Kokeile %1$sia älypuhelimellasi!</string>
   <string name="recommend_text">Ota %1$s käyttöösi älypuhelimessa!\nLataa tästä: %2$s</string>
   <string name="auth_check_server">Tarkista palvelin</string>
-  <string name="auth_host_url">Palvelimen osoite</string>
+  <string name="auth_host_url">Palvelinosoite https://…</string>
   <string name="auth_username">Käyttäjätunnus</string>
   <string name="auth_password">Salasana</string>
   <string name="auth_register">Onko %1$s uusi tuttavuus sinulle?</string>
@@ -52,6 +52,7 @@
   <string name="filedetails_download">Lataa</string>
   <string name="filedetails_sync_file">Päivitä tiedosto</string>
   <string name="filedetails_renamed_in_upload_msg">Tiedoston nimeksi muutettiin %1$s siirron yhteydessä</string>
+  <string name="action_share_file">Jaa linkki</string>
   <string name="common_yes">Kyllä</string>
   <string name="common_no">Ei</string>
   <string name="common_ok">OK</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
new file mode 100644 (file)
index 0000000..c757504
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
index 65f0723..7588229 100644 (file)
@@ -3,7 +3,7 @@
   <string name="about_android">%1$s Android App</string>
   <string name="about_version">version %1$s</string>
   <string name="actionbar_sync">Actualiser le compte</string>
-  <string name="actionbar_upload">Téléverser</string>
+  <string name="actionbar_upload">Charger</string>
   <string name="actionbar_upload_from_apps">Contenu d\'une autre application</string>
   <string name="actionbar_upload_files">Fichiers</string>
   <string name="actionbar_open_with">Ouvrir avec</string>
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Essayez %1$s sur votre smartphone !</string>
   <string name="recommend_text">J\'aimerais vous inviter à utiliser %1$s sur votre smartphone !\nTéléchargez-le ici : %2$s</string>
   <string name="auth_check_server">Vérifier le serveur</string>
-  <string name="auth_host_url">Adresse du serveur</string>
+  <string name="auth_host_url">Adresse du serveur https://...</string>
   <string name="auth_username">Nom d\'utilisateur</string>
   <string name="auth_password">Mot de passe</string>
   <string name="auth_register">Nouveau dans %1$s ?</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">Télécharger</string>
   <string name="filedetails_sync_file">Actualiser le fichier</string>
   <string name="filedetails_renamed_in_upload_msg">Le fichier a été renommé en %s pendant le téléversement</string>
+  <string name="action_share_file">Partager le lien</string>
+  <string name="action_unshare_file">Ne plus partager ce lien</string>
   <string name="common_yes">Oui</string>
   <string name="common_no">Non</string>
   <string name="common_ok">OK</string>
   <string name="sync_file_fail_msg">Le fichier distant n\'a pu être vérifié</string>
   <string name="sync_file_nothing_to_do_msg">Le contenu des fichiers est déjà synchronisé</string>
   <string name="create_dir_fail_msg">Création du répertoire impossible</string>
+  <string name="filename_forbidden_characters">Caractères interdits : / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Veuillez patienter</string>
   <string name="filedisplay_unexpected_bad_get_content">Problème inattendu ; veuillez essayer une autre app pour la sélection du fichier</string>
   <string name="filedisplay_no_file_selected">Aucun fichier sélectionné</string>
+  <string name="activity_chooser_title">Envoyer un lien à…</string>
   <string name="oauth_check_onoff">Connexion avec aAuth2.</string>
   <string name="oauth_login_connection">Connexion au serveur aAuth2...</string>
   <string name="ssl_validator_header">L\'identité du site ne peut être vérifiée</string>
   <string name="preview_image_description">Prévisualisation de l\'image</string>
   <string name="preview_image_error_unknown_format">Cette image ne peut pas être affichée</string>
   <string name="error__upload__local_file_not_copied">%1$s n\'a pas pu être copié vers le dossier local suivant %2$s</string>
+  <string name="actionbar_failed_instant_upload">Échec du téléversement instantané</string>
   <string name="failed_upload_headline_text">Téléchargements instantanés échoués</string>
   <string name="failed_upload_headline_hint">Résumé de tous les téléchargements instantanés échoués</string>
   <string name="failed_upload_all_cb">Tous sélectionner</string>
   <string name="failed_upload_retry_do_nothing_text">Ne rien faire vous n\'êtes pas connecté pour le téléchargement instantané</string>
   <string name="failed_upload_failure_text">Message d\'échec:</string>
   <string name="failed_upload_quota_exceeded_text">Veuillez vérifier la configuration de votre serveur, peut-être que votre quota est dépassé.</string>
+  <string name="share_link_no_support_share_api">Désolé, la fonctionnalité de partage n’est pas activée sur ce serveur. Veuillez contacter votre administrateur.</string>
+  <string name="share_link_file_no_exist">Impossible de partager ce fichier ou répertoire. Vérifiez qu’il est bien présent</string>
+  <string name="share_link_file_error">Une erreur est survenue lors de la tentative de partage de ce fichier ou répertoire</string>
+  <string name="unshare_link_file_error">Une erreur est survenue lors de la tentative d’annulation du partage de ce fichier ou répertoire</string>
 </resources>
index 2c223c3..8820c20 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Tente %1$s no seu teléfono intelixente!</string>
   <string name="recommend_text">Quero convidalo a empregar %1$s no seu teléfono intelixente!⏎\nDescárgueo de aquí:%2$s</string>
   <string name="auth_check_server">Comprobar o servidor</string>
-  <string name="auth_host_url">Enderezo do servidor</string>
+  <string name="auth_host_url">Enderezo do servidor https://…</string>
   <string name="auth_username">Nome de usuario</string>
   <string name="auth_password">Contrasinal</string>
   <string name="auth_register">Novo en %1$s?</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">Descargar</string>
   <string name="filedetails_sync_file">Actualizar o ficheiro</string>
   <string name="filedetails_renamed_in_upload_msg">O ficheiro foi renomeado a %1$s durante o envío</string>
+  <string name="action_share_file">Ligazón para compartir</string>
+  <string name="action_unshare_file">Deixar de compartir a ligazón</string>
   <string name="common_yes">Si</string>
   <string name="common_no">Non</string>
   <string name="common_ok">Aceptar</string>
   <string name="sync_file_fail_msg">Non foi posíbel comprobar o ficheiro remoto</string>
   <string name="sync_file_nothing_to_do_msg">Os contidos do ficheiro xa están sincronizados</string>
   <string name="create_dir_fail_msg">Non foi posíbel crear o directorio</string>
+  <string name="filename_forbidden_characters">Caracteres non permitidos: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Agarde un chisco</string>
   <string name="filedisplay_unexpected_bad_get_content">Produciuse un erro non agardado. Seleccione o ficheiro con outro aplicativo diferente</string>
   <string name="filedisplay_no_file_selected">Non se escolleu ningún ficheiro</string>
+  <string name="activity_chooser_title">Enviar a ligazón a ...</string>
   <string name="oauth_check_onoff">Acceder con oAuth2</string>
   <string name="oauth_login_connection">Conectando co servidor oAuth2…</string>
   <string name="ssl_validator_header">Non foi posíbel verificar a identidade do sitio</string>
   <string name="preview_image_description">Vista previa da imaxe</string>
   <string name="preview_image_error_unknown_format">Esta imaxe non pode ser amosada</string>
   <string name="error__upload__local_file_not_copied">Non foi posíbel copiar %1$s no directorio local %2$s</string>
+  <string name="actionbar_failed_instant_upload">produciuse un fallo de EnvíoInstantáneo</string>
   <string name="failed_upload_headline_text">Envíos instantáneos fallados</string>
   <string name="failed_upload_headline_hint">Resumo de todos os envíos instantáneos fallados</string>
   <string name="failed_upload_all_cb">seleccionar todo</string>
   <string name="failed_upload_retry_do_nothing_text">non facer nada que non estea en liña para o envío instantáneo</string>
   <string name="failed_upload_failure_text">Mensaxe de fallo:</string>
   <string name="failed_upload_quota_exceeded_text">Comprobe a configuración do seu servidor. é probábel que xa excedera a cota.</string>
+  <string name="share_link_no_support_share_api">O seu servidor non ten activada a opción de compartir. Póñase en contacto co administrador.</string>
+  <string name="share_link_file_no_exist">Non foi posíbel compartir este ficheiro ou cartafol. Asegurese de que existe.</string>
+  <string name="share_link_file_error">Produciuse un erro ao tentar compartir este ficheiro ou cartafol.</string>
+  <string name="unshare_link_file_error">Produciuse un erro ao tentar deixar de compartir este ficheiro ou cartafol</string>
 </resources>
index 71c8b9d..36de5a7 100644 (file)
@@ -15,7 +15,6 @@
   <string name="prefs_instant_upload">הפעלת העלאות מהירות</string>
   <string name="prefs_instant_upload_summary">העלאה מהירה של תמונות שמצולמות במצלמה שלך</string>
   <string name="prefs_help">עזרה</string>
-  <string name="auth_host_url">כתובת שרת</string>
   <string name="auth_username">שם משתמש</string>
   <string name="auth_password">ססמה</string>
   <string name="sync_string_files">קבצים</string>
index dc76079..b341bb8 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Próbálja ki %1$s-t az okostelefonján!</string>
   <string name="recommend_text">Kérem próbálja ki %1$s-t az okostelefonján!\nInnen tölthető le: %2$s</string>
   <string name="auth_check_server">Szerver állapot ellenörzés</string>
-  <string name="auth_host_url">A kiszolgáló címe</string>
+  <string name="auth_host_url">Kiszolgáló címe https://...</string>
   <string name="auth_username">Felhasználói név</string>
   <string name="auth_password">Jelszó</string>
   <string name="auth_register">Új vagy a %1$s területen?</string>
@@ -55,6 +55,7 @@
   <string name="filedetails_download">Letöltés</string>
   <string name="filedetails_sync_file">File frissítése</string>
   <string name="filedetails_renamed_in_upload_msg">A feltöltés során az állmányt erre neveztük át: %1$s</string>
+  <string name="action_share_file">Megosztás hivatkozással</string>
   <string name="common_yes">Igen</string>
   <string name="common_no">Nem</string>
   <string name="common_ok">OK</string>
   <string name="sync_file_fail_msg">A távoli fájl nem volt ellenőrizhető</string>
   <string name="sync_file_nothing_to_do_msg">Az állományok már szinkonizálva vannak</string>
   <string name="create_dir_fail_msg">A mappa nem hozható létre</string>
+  <string name="filename_forbidden_characters">Nem megendedett karakterek: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Egy pillanat...</string>
   <string name="filedisplay_unexpected_bad_get_content">Váratlan hiba; válassza ki a fájlt más programból</string>
   <string name="filedisplay_no_file_selected">Egy fájl sincs kiválasztva</string>
   <string name="preview_image_description">Előnézeti kép</string>
   <string name="preview_image_error_unknown_format">Ez a kép nem jelenik meg</string>
   <string name="error__upload__local_file_not_copied">%1$s-t nem sikerült átmásolni ide: %2$s </string>
+  <string name="actionbar_failed_instant_upload">Sikertelen azonnali feltöltés\"</string>
   <string name="failed_upload_headline_text">Sikertelen Azonnali feltöltés</string>
   <string name="failed_upload_headline_hint">Összefoglaló az összes sikertelen instant feltöltésről</string>
   <string name="failed_upload_all_cb">Összes kijelölése</string>
index 5db09aa..ecfaa30 100644 (file)
@@ -3,6 +3,7 @@
   <string name="actionbar_upload">Incargar</string>
   <string name="actionbar_upload_files">Files</string>
   <string name="actionbar_settings">Configurationes</string>
+  <string name="prefs_category_general">General</string>
   <string name="prefs_category_more">Plus</string>
   <string name="prefs_help">Adjuta</string>
   <string name="auth_username">Nomine de usator</string>
index 3eb4ccb..e190c5c 100644 (file)
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
+  <string name="about_android">%1$s Apl Android</string>
+  <string name="about_version">versi %1$s</string>
+  <string name="actionbar_sync">Segarkan akun</string>
   <string name="actionbar_upload">Unggah</string>
+  <string name="actionbar_upload_from_apps">Konten dari apl lain</string>
   <string name="actionbar_upload_files">Berkas</string>
+  <string name="actionbar_open_with">Bukan dengan</string>
+  <string name="actionbar_mkdir">Buat folder</string>
   <string name="actionbar_settings">pengaturan</string>
+  <string name="actionbar_see_details">Rincian</string>
   <string name="prefs_category_general">umum</string>
   <string name="prefs_category_more">Lainnya</string>
+  <string name="prefs_accounts">Akun</string>
+  <string name="prefs_manage_accounts">Kelola Akun</string>
+  <string name="prefs_pincode">PIN Apl</string>
+  <string name="prefs_pincode_summary">Lindungi klien Anda</string>
+  <string name="prefs_instant_upload">Aktifkan unggah instan</string>
+  <string name="prefs_instant_upload_summary">Unggah langsung foto yang diambil oleh kamera</string>
+  <string name="prefs_log_title">Aktifkan Pencatatan</string>
+  <string name="prefs_log_summary">Ini digunakan untuk mencatat masalah</string>
+  <string name="prefs_log_title_history">Riwayat Catatan</string>
+  <string name="prefs_log_summary_history">Ini menampilkan catatan yang disimpan</string>
+  <string name="prefs_log_delete_history_button">Riwayat Hapus</string>
   <string name="prefs_help">Bantuan</string>
+  <string name="prefs_recommend">Rekomendasikan ke teman</string>
+  <string name="prefs_feedback">Umpan balik</string>
   <string name="prefs_imprint">Imprint</string>
-  <string name="auth_host_url">alamat server</string>
-  <string name="auth_username">nama pengguna</string>
-  <string name="auth_password">kata kunci</string>
+  <string name="recommend_subject">Coba %1$s pada smartphone Anda!</string>
+  <string name="recommend_text">Saya mengundang Anda untuk menggunakan %1$s pada smartphone Anda!\nUnduh di sini: %2$s</string>
+  <string name="auth_check_server">Periksa Server</string>
+  <string name="auth_host_url">Alamat server https://…</string>
+  <string name="auth_username">Nama Pengguna</string>
+  <string name="auth_password">Sandi</string>
+  <string name="auth_register">Baru di %1$s?</string>
   <string name="sync_string_files">Berkas</string>
+  <string name="setup_btn_connect">Sambungkan</string>
   <string name="uploader_btn_upload_text">Unggah</string>
+  <string name="uploader_top_message">Pilih folder unggah</string>
+  <string name="uploader_wrn_no_account_title">Tidak ada akun yang ditemukan</string>
+  <string name="uploader_wrn_no_account_text">Belum ada akun %1$s pada perangkat Anda. Silahkan buat akun terlebih dahulu.</string>
+  <string name="uploader_wrn_no_account_setup_btn_text">Pengaturan</string>
   <string name="uploader_wrn_no_account_quit_btn_text">Keluar</string>
-  <string name="filedetails_download">unduh</string>
+  <string name="uploader_wrn_no_content_title">Tidak ada konten untuk diunggah</string>
+  <string name="uploader_wrn_no_content_text">Tidak ada konten yang diterima. Tidak ada yang diunggah</string>
+  <string name="uploader_error_forbidden_content">%1$s tidak diizinkan mengakses konten berbagi</string>
+  <string name="uploader_info_uploading">Mengunggah</string>
+  <string name="file_list_empty">Tidak ada berkas dalam folder ini.\nBerkas baru dapat ditambahkan dengan opsi menu \"Unggah\".</string>
+  <string name="filedetails_select_file">Sentuh pada berkas untuk menampilkan informasi tambahan</string>
+  <string name="filedetails_size">Ukuran:</string>
+  <string name="filedetails_type">Tipe:</string>
+  <string name="filedetails_created">Dibuat:</string>
+  <string name="filedetails_modified">Diubah:</string>
+  <string name="filedetails_download">Unduh</string>
+  <string name="filedetails_sync_file">Segarkan berkas</string>
+  <string name="filedetails_renamed_in_upload_msg">Berkas diubah namanya menjadi %1$s saat pengunggahan</string>
+  <string name="action_share_file">Bagikan tautan</string>
   <string name="common_yes">Ya</string>
   <string name="common_no">Tidak</string>
   <string name="common_ok">Oke</string>
+  <string name="common_cancel_download">Batal mengunduh</string>
   <string name="common_cancel_upload">Batal mengunggah</string>
-  <string name="common_cancel">batal</string>
-  <string name="common_error">kesalahan</string>
+  <string name="common_cancel">Batal</string>
+  <string name="common_save_exit">Simpan &amp; Keluar</string>
+  <string name="common_error">Kesalahan</string>
+  <string name="common_loading">Memuat ...</string>
+  <string name="common_error_unknown">Galat tidak diketahui</string>
+  <string name="about_title">Tentang</string>
   <string name="change_password">Ubah sandi</string>
+  <string name="delete_account">Hapus akun</string>
+  <string name="create_account">Buat akun</string>
+  <string name="upload_chooser_title">Unggah dari...</string>
+  <string name="uploader_info_dirname">Nama folder</string>
+  <string name="uploader_upload_in_progress_ticker">Mengungggah...</string>
+  <string name="uploader_upload_in_progress_content">%1$d%% Mengunggah %2$s</string>
+  <string name="uploader_upload_succeeded_ticker">Berhasil mengunggah</string>
+  <string name="uploader_upload_succeeded_content_single">%1$s berhasil diunggah</string>
+  <string name="uploader_upload_failed_ticker">Gagal mengunggah</string>
+  <string name="uploader_upload_failed_content_single">Unggah %1$s tidak selesai</string>
+  <string name="downloader_download_in_progress_ticker">Mengunduh...</string>
+  <string name="downloader_download_in_progress_content">%1$d%% Mengunduh %2$s</string>
+  <string name="downloader_download_succeeded_ticker">Berhasil mengunduh</string>
+  <string name="downloader_download_succeeded_content">%1$s berhasil diunduh</string>
+  <string name="downloader_download_failed_ticker">Gagal Mengunduh</string>
+  <string name="downloader_download_failed_content">Mengunduh %1$s tidak selesai</string>
+  <string name="downloader_not_downloaded_yet">Belum diunduh</string>
+  <string name="common_choose_account">Pilih akun</string>
+  <string name="sync_fail_ticker">Sinkronisasi gagal</string>
+  <string name="sync_fail_content">Sinkronisasi %1$s tidak selesai</string>
+  <string name="sync_fail_content_unauthorized">Sandi salah untuk %1$s</string>
+  <string name="sync_conflicts_in_favourites_ticker">Konflik ditemukan</string>
+  <string name="sync_fail_in_favourites_content">Konten berkas %1$d tidak dapat disinkronasikan (%2$d konflik)</string>
+  <string name="sync_foreign_files_forgotten_ticker">Beberapa berkas lokal terlupakan</string>
+  <string name="sync_foreign_files_forgotten_content">%1$d berkas dari direktori %2$s tidak dapat disalin ke</string>
+  <string name="sync_current_folder_was_removed">Folder %1$s tidak ada lagi</string>
+  <string name="foreign_files_move">Pindahkan semua</string>
+  <string name="foreign_files_success">Semua berkas sudah dipindahkan</string>
+  <string name="foreign_files_fail">Beberapa berkas tidak dapat dipindahkan</string>
+  <string name="foreign_files_local_text">Lokal: %1$s</string>
+  <string name="foreign_files_remote_text">Jauh: %1$s</string>
+  <string name="pincode_enter_pin_code">Silakan masukkan PIN Apl</string>
+  <string name="pincode_configure_your_pin">Masukkan PIN Apl</string>
+  <string name="pincode_configure_your_pin_explanation">PIN akan selalu diminta setiap kali apl dijalankan</string>
+  <string name="pincode_reenter_your_pincode">Silakan masukkan ulang PIN Apl</string>
+  <string name="pincode_remove_your_pincode">Hapus PIN Apl</string>
+  <string name="pincode_mismatch">PIN Apl tidak sama</string>
+  <string name="pincode_wrong">PIN Apl salah</string>
+  <string name="pincode_removed">PIN Apl dihapus</string>
+  <string name="pincode_stored">PIN Apl disimpan</string>
+  <string name="media_notif_ticker">Pemutar musik %1$s</string>
+  <string name="media_state_playing">%1$s (dimainkan)</string>
+  <string name="media_state_loading">%1$s (sedang dimuat)</string>
+  <string name="media_err_nothing_to_play">Tidak ditemukan berkas media</string>
+  <string name="media_err_no_account">Tidak ada akun yang diberikan</string>
+  <string name="media_err_not_in_owncloud">Brkas tidak didalam akun yang sah</string>
+  <string name="media_err_unsupported">Kodek media tidak didukung</string>
+  <string name="media_err_io">Berkas media tidak dapat dibaca</string>
+  <string name="media_err_malformed">Berkas media tidak di enkode dengan benar</string>
+  <string name="media_err_timeout">Waktu habis saat mencoba untuk main</string>
+  <string name="media_err_invalid_progressive_playback">Berkas media tidak bisa dialirkan</string>
+  <string name="media_err_unknown">Berkas media tidak dapat dimainkan dengan pemutar media</string>
+  <string name="media_err_security_ex">Kesalahan keamanan saat mencoba memutar %1$s</string>
+  <string name="media_err_io_ex">Kesalahan masukkan saat mencoba memutar %1$s</string>
+  <string name="media_err_unexpected">Kesalahan tak terduga saat mencoba memutar %1$s</string>
+  <string name="media_rewind_description">Tombol mundur</string>
+  <string name="media_play_pause_description">Tombol main dan jeda</string>
+  <string name="media_forward_description">Tombol maju</string>
+  <string name="auth_trying_to_login">Mencoba untuk masuk...</string>
+  <string name="auth_no_net_conn_title">Tidak ada koneksi internet</string>
+  <string name="auth_nossl_plain_ok_title">Sambungan aman tidak tersedia</string>
+  <string name="auth_connection_established">Sambungan dibuat</string>
+  <string name="auth_testing_connection">Pengetesan koneksi ...</string>
+  <string name="auth_not_configured_title">Konfigurasi server cacat</string>
+  <string name="auth_account_not_new">Akun untuk pengguna dan server yang sama sudah ada dalam perangkat</string>
+  <string name="auth_account_not_the_same">Pengguna yang dimasukkan tidak cocok dengan pengguna akun ini</string>
+  <string name="auth_unknown_error_title">Terjadi kesalahan yang tidak diketahui!</string>
+  <string name="auth_unknown_host_title">Tidak menemukan host</string>
+  <string name="auth_incorrect_path_title">Instansi server tidak ditemukan</string>
+  <string name="auth_timeout_title">Server terlalu lama merespon</string>
+  <string name="auth_incorrect_address_title">Format URL salah</string>
+  <string name="auth_ssl_general_error_title">Menginisiasi SSL gagal</string>
+  <string name="auth_ssl_unverified_server_title">Tidak dapat memverifikasi identitas server SSL</string>
+  <string name="auth_bad_oc_version_title">Versi server tidak dikenal</string>
+  <string name="auth_wrong_connection_title">Tidak dapat membuat koneksi</string>
+  <string name="auth_secure_connection">Sambungan aman dibuat</string>
+  <string name="auth_unauthorized">Nama pengguna dan sandi salah</string>
+  <string name="auth_oauth_error">Otorisasi tidak berhasil</string>
+  <string name="auth_oauth_error_access_denied">Akses ditolak oleh server otorisasi</string>
+  <string name="auth_wtf_reenter_URL">Keadaan tak terduga, silahkan masukkan URL server yang lagi</string>
+  <string name="auth_expired_oauth_token_toast">Otorisasi Anda telah berakhir. Silakan mengotorisasi lagi</string>
+  <string name="auth_expired_basic_auth_toast">Silakan mesukkan sandi saat ini</string>
+  <string name="auth_expired_saml_sso_token_toast">Sesi Anda telah berakhir. Silakan masuk kembali</string>
+  <string name="auth_connecting_auth_server">Menyambungkan ke server otentikasi...</string>
+  <string name="auth_unsupported_auth_method">Server tidak mendukung medote otentikasi ini</string>
+  <string name="auth_unsupported_multiaccount">%1$s tidak mendukung banyak akun </string>
+  <string name="fd_keep_in_sync">Biarkan berkas tetap terbaru</string>
   <string name="common_rename">Ubah nama</string>
-  <string name="common_remove">hilangkan</string>
-  <string name="ssl_validator_btn_details_hide">sembunyikan</string>
+  <string name="common_remove">Hapus</string>
+  <string name="confirmation_remove_alert">Apakah Anda yakin ingin menghapus %1$s ?</string>
+  <string name="confirmation_remove_folder_alert">Apakah Anda benar-benar ingin menghapus %1$s beserta isinya?</string>
+  <string name="confirmation_remove_local">Lokal saja</string>
+  <string name="confirmation_remove_folder_local">Konten lokal saja</string>
+  <string name="confirmation_remove_remote">Hapus dari server</string>
+  <string name="confirmation_remove_remote_and_local">Jarak jauh dan lokal</string>
+  <string name="remove_success_msg">Penghapusan berhasil</string>
+  <string name="remove_fail_msg">Penghapusan gagal</string>
+  <string name="rename_dialog_title">Masukkan nama baru</string>
+  <string name="rename_local_fail_msg">Salinan lokal tidak dapat diubah nama, coba dengan nama yang berbeda</string>
+  <string name="rename_server_fail_msg">Mengubah nama tidak selesai</string>
+  <string name="sync_file_fail_msg">Berkas jauh tidak dapat diperiksa</string>
+  <string name="sync_file_nothing_to_do_msg">Isi berkas sudah diselaraskan</string>
+  <string name="create_dir_fail_msg">Folder tidak dapat dibuat</string>
+  <string name="filename_forbidden_characters">Karakter yang dilarang: / \\ &lt; &gt; : \" | ? *</string>
+  <string name="wait_a_moment">Tunggu sejenak</string>
+  <string name="filedisplay_unexpected_bad_get_content">Masalah tidak terduga, silahkan pilih berkas dari apl yang berbeda</string>
+  <string name="filedisplay_no_file_selected">Tidak ada berkas yang terpilih</string>
+  <string name="oauth_check_onoff">Masuk dengan oAuth2</string>
+  <string name="oauth_login_connection">Menyambungkan ke server oAuth2...</string>
+  <string name="ssl_validator_header">Identitas situs tidak dapat diverfikasi</string>
+  <string name="ssl_validator_reason_cert_not_trusted">- Sertifikat server tidak terpercaya</string>
+  <string name="ssl_validator_reason_cert_expired">- Sertifikat server kadaluarsa</string>
+  <string name="ssl_validator_reason_cert_not_yet_valid">- Tanggal sertifikat server yang valid adalah di masa depan</string>
+  <string name="ssl_validator_reason_hostname_not_verified">- URL tidak cocok dengan nama host dalam sertifikat</string>
+  <string name="ssl_validator_question">Apakah Anda percaya dengan sertifikat ini?</string>
+  <string name="ssl_validator_not_saved">Sertifikat tidak dapat disimpan</string>
+  <string name="ssl_validator_btn_details_see">Rincian</string>
+  <string name="ssl_validator_btn_details_hide">Sembunyikan</string>
+  <string name="ssl_validator_label_subject">Diterbitkan untuk:</string>
+  <string name="ssl_validator_label_issuer">Diterbitkan oleh:</string>
+  <string name="ssl_validator_label_CN">Nama panggilan:</string>
+  <string name="ssl_validator_label_O">Organisasi:</string>
+  <string name="ssl_validator_label_OU">Unit Organisasi:</string>
+  <string name="ssl_validator_label_C">Negara:</string>
+  <string name="ssl_validator_label_ST">Negara bagian:</string>
+  <string name="ssl_validator_label_L">Lokasi:</string>
+  <string name="ssl_validator_label_validity">Masa berlaku:</string>
+  <string name="ssl_validator_label_validity_from">Dari:</string>
+  <string name="ssl_validator_label_validity_to">Untuk:</string>
+  <string name="ssl_validator_label_signature">Tanda tangan:</string>
+  <string name="ssl_validator_label_signature_algorithm">Algoritma:</string>
+  <string name="placeholder_sentence">Ini adalah placeholder</string>
+  <string name="placeholder_filename">placeholder.txt</string>
+  <string name="placeholder_filetype">Gambar PNG</string>
+  <string name="placeholder_filesize">389 KB</string>
+  <string name="placeholder_timestamp">18/05/2012 12:23 PM</string>
+  <string name="placeholder_media_time">12:23:45</string>
+  <string name="instant_upload_on_wifi">Hanya unggah gambar via WiFi</string>
+  <string name="instant_upload_path">/UnggahInstan</string>
+  <string name="conflict_title">Perbarui benturan</string>
+  <string name="conflict_message">Berkas jauh %s tidak sinkron dengan berkas lokal. Melanjutkan akan menggantikan konten berkas di server.</string>
+  <string name="conflict_keep_both">Biarkan keduannya</string>
+  <string name="conflict_overwrite">Timpa</string>
+  <string name="conflict_dont_upload">Jangan mengunggah</string>
+  <string name="preview_image_description">Pratilik gambar</string>
+  <string name="preview_image_error_unknown_format">Gambar ini tidak dapat ditampilkan</string>
+  <string name="error__upload__local_file_not_copied">%1$s tidak dapat disalin ke direktori lokal %2$s</string>
+  <string name="actionbar_failed_instant_upload">UnggahInsatan Gagal</string>
+  <string name="failed_upload_headline_text">Unggahan instan gagal</string>
+  <string name="failed_upload_headline_hint">Ringkasan dari semua unggahan instan yang gagal</string>
+  <string name="failed_upload_all_cb">pilih semua</string>
+  <string name="failed_upload_headline_retryall_btn">Ulangi semua yang terpilih</string>
+  <string name="failed_upload_headline_delete_all_btn">hapus semua yang terpilih dari antrian unggahan</string>
+  <string name="failed_upload_retry_text">ulangi unggah gambar:</string>
+  <string name="failed_upload_load_more_images">Muat Gambar selengkapnya</string>
+  <string name="failed_upload_retry_do_nothing_text">Tidak melakukan apapun, Anda tidak sedang online</string>
+  <string name="failed_upload_failure_text">Pesan Kegagalan:</string>
+  <string name="failed_upload_quota_exceeded_text">Silakan periksa konfigurasi server Anda, kemungkinan kuota terlampaui.</string>
 </resources>
index 6a2f987..e7d228b 100644 (file)
@@ -5,7 +5,6 @@
   <string name="actionbar_settings">Stillingar</string>
   <string name="prefs_category_more">Meira</string>
   <string name="prefs_help">Hjálp</string>
-  <string name="auth_host_url">Host nafn netþjóns</string>
   <string name="auth_username">Notendanafn</string>
   <string name="auth_password">Lykilorð</string>
   <string name="sync_string_files">Skrár</string>
index 58bdc13..578ea5f 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Prova %1$s sul tuo smartphone!</string>
   <string name="recommend_text">Vorrei invitarti ad usare %1$s sul tuo smartphone!⏎\nScarica qui: %2$s</string>
   <string name="auth_check_server">Verifica server</string>
-  <string name="auth_host_url">Indirizzo del server</string>
+  <string name="auth_host_url">Indirizzo server https://...</string>
   <string name="auth_username">Nome utente</string>
   <string name="auth_password">Password</string>
   <string name="auth_register">Prima volta su %1$s?</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">Scarica</string>
   <string name="filedetails_sync_file">Aggiorna file</string>
   <string name="filedetails_renamed_in_upload_msg">Il file è stato rinominato in %1$s durante il caricamento</string>
+  <string name="action_share_file">Condividi collegamento</string>
+  <string name="action_unshare_file">Rimuovi condivisione collegamento</string>
   <string name="common_yes">Sì</string>
   <string name="common_no">No</string>
   <string name="common_ok">OK</string>
   <string name="sync_file_fail_msg">Il file remoto non può essere controllato</string>
   <string name="sync_file_nothing_to_do_msg">Contenuti del file già sincronizzati</string>
   <string name="create_dir_fail_msg">La cartella non può essere creata</string>
+  <string name="filename_forbidden_characters">Caratteri proibiti: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Attendi</string>
   <string name="filedisplay_unexpected_bad_get_content">Problema inatteso; prova un\'altra applicazione per selezionare il file</string>
   <string name="filedisplay_no_file_selected">Non è stato selezionato alcun file</string>
+  <string name="activity_chooser_title">Invia collegamento a...</string>
   <string name="oauth_check_onoff">Accesso con oAuth2.</string>
   <string name="oauth_login_connection">Connessione al server oAuth2 in corso...</string>
   <string name="ssl_validator_header">L\'identità del sito non può essere verificata</string>
   <string name="preview_image_description">Anteprima dell\'immagine</string>
   <string name="preview_image_error_unknown_format">Questa immagine non può essere mostrata</string>
   <string name="error__upload__local_file_not_copied">%1$s non può essere copiato nella cartella locale %2$s</string>
+  <string name="actionbar_failed_instant_upload">Caricamento istantaneo non riuscito</string>
   <string name="failed_upload_headline_text">Caricamenti istantanei non riusciti</string>
   <string name="failed_upload_headline_hint">Riepilogo dei caricamenti istantanei non riusciti</string>
   <string name="failed_upload_all_cb">seleziona tutto</string>
   <string name="failed_upload_retry_do_nothing_text">non fare niente, non sei collegato per i caricamenti istantanei</string>
   <string name="failed_upload_failure_text">Messaggio d\'errore:</string>
   <string name="failed_upload_quota_exceeded_text">Controlla la configurazione del server, forse hai superato la tua quota.</string>
+  <string name="share_link_no_support_share_api">Spiacenti, la condivisione non è abilitata sul server. Contatta il tuo amministratore.</string>
+  <string name="share_link_file_no_exist">Impossibile condividere il file o la cartella. Assicurati che esista.</string>
+  <string name="share_link_file_error">Si è verificato un errore durante il tentativo di condivisione del file o della cartella</string>
+  <string name="unshare_link_file_error">Si è verificato un errore durante il tentativo di rimuovere la condivisione del file o della cartella</string>
 </resources>
index 64da276..2c19547 100644 (file)
@@ -18,9 +18,9 @@
   <string name="prefs_pincode_summary">クライアントを保護する</string>
   <string name="prefs_instant_upload">自動アップロードを有効</string>
   <string name="prefs_instant_upload_summary">カメラで撮影した画像を自動アップロード</string>
-  <string name="prefs_log_title">記録を有効化</string>
-  <string name="prefs_log_summary">これは問題を記録するのにつかわれます。</string>
-  <string name="prefs_log_title_history">記録している履歴</string>
+  <string name="prefs_log_title">ログを有効にする</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_delete_history_button">履歴を削除</string>
   <string name="prefs_help">ヘルプ</string>
@@ -30,7 +30,7 @@
   <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">ã\82µã\83¼ã\83\90ã\82¢ã\83\89ã\83¬ã\82¹</string>
+  <string name="auth_host_url">ã\82µã\83¼ã\83\90ã\83¼ã\82¢ã\83\89ã\83¬ã\82¹ https://â\80¦</string>
   <string name="auth_username">ユーザー名</string>
   <string name="auth_password">パスワード</string>
   <string name="auth_register">%1$sは初めてですか?</string>
@@ -46,7 +46,7 @@
   <string name="uploader_wrn_no_content_text">コンテンツを受信しませんでした。アップロードするものはありません。</string>
   <string name="uploader_error_forbidden_content">%1$sで共有コンテンツへのアクセスが許可されていません。</string>
   <string name="uploader_info_uploading">アップロード中</string>
-  <string name="file_list_empty">このフォルダにはファイルがありません。\n\"アップロード\" メニューで新しいファイルを追加することができます。</string>
+  <string name="file_list_empty">ã\81\93ã\81®ã\83\95ã\82©ã\83«ã\83\80ã\83¼ã\81«ã\81¯ã\83\95ã\82¡ã\82¤ã\83«ã\81\8cã\81\82ã\82\8aã\81¾ã\81\9bã\82\93ã\80\82\n\"ã\82¢ã\83\83ã\83\97ã\83­ã\83¼ã\83\89\" ã\83¡ã\83\8bã\83¥ã\83¼ã\81§æ\96°ã\81\97ã\81\84ã\83\95ã\82¡ã\82¤ã\83«ã\82\92追å\8a ã\81\99ã\82\8bã\81\93ã\81¨ã\81\8cã\81§ã\81\8dã\81¾ã\81\99ã\80\82</string>
   <string name="filedetails_select_file">ファイルをタップすると追加情報が表示されます。</string>
   <string name="filedetails_size">サイズ:</string>
   <string name="filedetails_type">タイプ:</string>
@@ -55,6 +55,7 @@
   <string name="filedetails_download">ダウンロード</string>
   <string name="filedetails_sync_file">ファイルを同期</string>
   <string name="filedetails_renamed_in_upload_msg">アップロード中にファイル名を %1$s に変更しました</string>
+  <string name="action_share_file">URLで共有</string>
   <string name="common_yes">はい</string>
   <string name="common_no">いいえ</string>
   <string name="common_ok">OK</string>
   <string name="sync_conflicts_in_favourites_content">%1$d 同期ファイルを同期できませんでした</string>
   <string name="sync_fail_in_favourites_ticker">ファイルの同期に失敗しました</string>
   <string name="sync_fail_in_favourites_content">%1$d ファイルのコンテンツを同期できませんでした(%2$d の競合)</string>
-  <string name="sync_foreign_files_forgotten_ticker">いくつかのローカルファイルが忘れられています</string>
+  <string name="sync_foreign_files_forgotten_ticker">一部のローカルファイルが忘れられています</string>
   <string name="sync_foreign_files_forgotten_content">%2$s ディレクトリ内の %1$d ファイルはコピーすることができませんでした</string>
-  <string name="sync_foreign_files_forgotten_explanation">\"ã\83\90ã\83¼ã\82¸ã\83§ã\83³ 1.3.16ã\81\8bã\82\89ã\80\81ã\81\93ã\81®ã\83\87ã\83\90ã\82¤ã\82¹ã\81\8bã\82\89ã\82¢ã\83\83ã\83\97ã\83­ã\83¼ã\83\89ã\81\95ã\82\8cã\81\9fã\83\95ã\82¡ã\82¤ã\83«ã\81¯ã\80\81å\8d\98ç\8b¬ã\81®ã\83\95ã\82¡ã\82¤ã\83«ã\81\8cè¤\87æ\95°ã\81®ã\82¢ã\82«ã\82¦ã\83³ã\83\88ã\81¨å\90\8cæ\9c\9fã\81\95ã\82\8cã\82\8bæ\99\82ã\81«ã\83\87ã\83¼ã\82¿ã\81®æ\90\8d失ã\82\92é\98²ã\81\90ã\81\9fã\82\81ã\80\81ã\83­ã\83¼ã\82«ã\83«ã\81®%1$sã\81®ã\83\95ã\82©ã\83«ã\83\80ã\81«ã\82³ã\83\94ã\83¼ã\81\95ã\82\8cã\81¾ã\81\99ã\80\82\n\nã\81\93ã\81®å¤\89æ\9b´ã\81«ã\82\88ã\82\8aã\80\81ã\81\93ã\81®ã\82¢ã\83\97ã\83ªã\81®ä»¥å\89\8dã\81®ã\83\90ã\83¼ã\82¸ã\83§ã\83³ã\81§ã\82¢ã\83\83ã\83\97ã\83­ã\83¼ã\83\89ã\81\95ã\82\8cã\81\9fã\81\99ã\81¹ã\81¦ã\81®ã\83\95ã\82¡ã\82¤ã\83«ã\81\8c%2$s ã\83\95ã\82©ã\83«ã\83\80にコピーされます。ただし、アカウント同期の際に、エラーがこの操作の完了を阻止しました。このままファイルを残し、%3$sへのリンクを削除するか、あるいは%1$s ディレクトリのファイルを移動し、%4$sへのリンクを維持することができます。\n\n以下にローカルのファイルと、それにリンクしていた%5$sのリモートファイルがリストされています</string>
-  <string name="sync_current_folder_was_removed">フォルダ %1$s はもう存在しません</string>
+  <string name="sync_foreign_files_forgotten_explanation">\"ã\83\90ã\83¼ã\82¸ã\83§ã\83³ 1.3.16ã\81\8bã\82\89ã\80\81ã\81\93ã\81®ã\83\87ã\83\90ã\82¤ã\82¹ã\81\8bã\82\89ã\82¢ã\83\83ã\83\97ã\83­ã\83¼ã\83\89ã\81\95ã\82\8cã\81\9fã\83\95ã\82¡ã\82¤ã\83«ã\81¯ã\80\81å\8d\98ç\8b¬ã\81®ã\83\95ã\82¡ã\82¤ã\83«ã\81\8cè¤\87æ\95°ã\81®ã\82¢ã\82«ã\82¦ã\83³ã\83\88ã\81¨å\90\8cæ\9c\9fã\81\95ã\82\8cã\82\8bæ\99\82ã\81«ã\83\87ã\83¼ã\82¿ã\81®æ\90\8d失ã\82\92é\98²ã\81\90ã\81\9fã\82\81ã\80\81ã\83­ã\83¼ã\82«ã\83«ã\81®%1$sã\81®ã\83\95ã\82©ã\83«ã\83\80ã\83¼ã\81«ã\82³ã\83\94ã\83¼ã\81\95ã\82\8cã\81¾ã\81\99ã\80\82\n\nã\81\93ã\81®å¤\89æ\9b´ã\81«ã\82\88ã\82\8aã\80\81ã\81\93ã\81®ã\82¢ã\83\97ã\83ªã\81®ä»¥å\89\8dã\81®ã\83\90ã\83¼ã\82¸ã\83§ã\83³ã\81§ã\82¢ã\83\83ã\83\97ã\83­ã\83¼ã\83\89ã\81\95ã\82\8cã\81\9fã\81\99ã\81¹ã\81¦ã\81®ã\83\95ã\82¡ã\82¤ã\83«ã\81\8c%2$s ã\83\95ã\82©ã\83«ã\83\80ã\83¼にコピーされます。ただし、アカウント同期の際に、エラーがこの操作の完了を阻止しました。このままファイルを残し、%3$sへのリンクを削除するか、あるいは%1$s ディレクトリのファイルを移動し、%4$sへのリンクを維持することができます。\n\n以下にローカルのファイルと、それにリンクしていた%5$sのリモートファイルがリストされています</string>
+  <string name="sync_current_folder_was_removed">フォルダ %1$s はもう存在しません</string>
   <string name="foreign_files_move">全て移動</string>
   <string name="foreign_files_success">全てのファイルは移動されました</string>
-  <string name="foreign_files_fail">いくつかのファイルは移動出来ませんでした</string>
+  <string name="foreign_files_fail">一部のファイルは移動できませんでした</string>
   <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 ã\83\95ã\82©ã\83«ã\83\80ã\81«é\81¸æ\8a\9eã\81\95ã\82\8cã\81\9fã\83\95ã\82¡ã\82¤ã\83«ã\82\92ã\82³ã\83\94ã\83¼ã\81\99ã\82\8bã\81®ã\81«å\8d\81å\88\86ã\81ªã\82¹ã\83\9aã\83¼ã\82¹がありません。コピーする代わりに、それらを移動させますか?</string>
+  <string name="upload_query_move_foreign_files">%1$s ã\83\95ã\82©ã\83«ã\83\80ã\83¼ã\81«é\81¸æ\8a\9eã\81\95ã\82\8cã\81\9fã\83\95ã\82¡ã\82¤ã\83«ã\82\92ã\82³ã\83\94ã\83¼ã\81\99ã\82\8bã\81®ã\81«å\8d\81å\88\86ã\81ªç©ºã\81\8dé \98å\9f\9fがありません。コピーする代わりに、それらを移動させますか?</string>
   <string name="pincode_enter_pin_code">アプリのパスワードを入力してください</string>
   <string name="pincode_configure_your_pin">アプリのパスワードを入力してください</string>
   <string name="pincode_configure_your_pin_explanation">アプリ開始時に毎回PINが要求されます。</string>
   <string name="media_err_malformed">メディアファイルが正確にエンコードされていません</string>
   <string name="media_err_timeout">再生中にタイムアウトが発生しました</string>
   <string name="media_err_invalid_progressive_playback">メディアファイルをストリーミングできません</string>
-  <string name="media_err_unknown">メディアファイルをStock Media Playerでプレイ出来ません</string>
-  <string name="media_err_security_ex">プレイに際してセキュリティエラー %1$s</string>
-  <string name="media_err_io_ex">プレイに際して入力エラー %1$s</string>
-  <string name="media_err_unexpected">プレイに際して予期しないエラー %1$s</string>
+  <string name="media_err_unknown">メディアファイルをStock Media Playerで再生できません</string>
+  <string name="media_err_security_ex">再生時にセキュリティエラー %1$s</string>
+  <string name="media_err_io_ex">再生時に入力エラー %1$s</string>
+  <string name="media_err_unexpected">再生時に予期しないエラー %1$s</string>
   <string name="media_rewind_description">巻き戻しボタン</string>
-  <string name="media_play_pause_description">プレイ/ポーズボタン</string>
+  <string name="media_play_pause_description">再生/一時停止ボタン</string>
   <string name="media_forward_description">早送りボタン</string>
   <string name="auth_trying_to_login">ログイン中...</string>
   <string name="auth_no_net_conn_title">ネットワークに接続されていません</string>
   <string name="auth_nossl_plain_ok_title">暗号化通信が利用できません。</string>
   <string name="auth_connection_established">接続が確立しました</string>
   <string name="auth_testing_connection">接続をテスト中...</string>
-  <string name="auth_not_configured_title">サーバーの間違った設定</string>
-  <string name="auth_account_not_new">å\90\8cã\81\98ã\83¦ã\83¼ã\82¶ã\81¨ã\82µã\83¼ã\83\90のアカウントがデバイス上にすでに存在します</string>
-  <string name="auth_account_not_the_same">å\85¥å\8a\9bã\81\95ã\82\8cã\81\9fã\83¦ã\83¼ã\82¶ã\81¯ã\81\93ã\81®ã\82¢ã\82«ã\82¦ã\83³ã\83\88ã\81®ã\83¦ã\83¼ã\82と一致しません</string>
+  <string name="auth_not_configured_title">サーバー設定が間違っています</string>
+  <string name="auth_account_not_new">å\90\8cã\81\98ã\83¦ã\83¼ã\82¶ã\83¼ã\81¨ã\82µã\83¼ã\83\90ã\83¼のアカウントがデバイス上にすでに存在します</string>
+  <string name="auth_account_not_the_same">å\85¥å\8a\9bã\81\95ã\82\8cã\81\9fã\83¦ã\83¼ã\82¶ã\83¼ã\81¯ã\81\93ã\81®ã\82¢ã\82«ã\82¦ã\83³ã\83\88ã\81®ã\83¦ã\83¼ã\82¶ã\83¼と一致しません</string>
   <string name="auth_unknown_error_title">不明なエラーに発生しました</string>
   <string name="auth_unknown_host_title">ホストが見つかりませんでした</string>
-  <string name="auth_incorrect_path_title">ã\81®ã\82¤ã\83³ã\82¹ã\82¿ã\83³ã\82¹ã\81\8cè¦\8bã\81¤ã\81\8bã\82\8aã\81¾ã\81\9bã\82\93ã\81§ã\81\97ã\81\9f</string>
-  <string name="auth_timeout_title">サーバーからの反応がありません</string>
+  <string name="auth_incorrect_path_title">ã\82µã\83¼ã\83\90ã\83¼ã\81®ã\82¤ã\83³ã\82¹ã\82¿ã\83³ã\82¹ã\81\8cè¦\8bã\81¤ã\81\8bã\82\8aã\81¾ã\81\9bã\82\93</string>
+  <string name="auth_timeout_title">サーバーからの反応がありません</string>
   <string name="auth_incorrect_address_title">不明なURL形式</string>
   <string name="auth_ssl_general_error_title">SSLの初期化に失敗しました</string>
-  <string name="auth_ssl_unverified_server_title">SSL サーバ識別子を確認できませんでした</string>
-  <string name="auth_bad_oc_version_title">認識出来ないサーバのバージョンです</string>
+  <string name="auth_ssl_unverified_server_title">SSLサーバー識別子を確認できませんでした</string>
+  <string name="auth_bad_oc_version_title">認識できないサーバーのバージョンです</string>
   <string name="auth_wrong_connection_title">接続を確立できませんでした</string>
   <string name="auth_secure_connection">暗号化通信を確立しました</string>
   <string name="auth_unauthorized">間違ったユーザー名もしくはパスワード</string>
   <string name="auth_expired_oauth_token_toast">認証情報は有効期限切れです。再度認証を行ってください。</string>
   <string name="auth_expired_basic_auth_toast">現在のパスワードを入力してください</string>
   <string name="auth_expired_saml_sso_token_toast">セッションの有効期限切れです。再度接続してください。</string>
-  <string name="auth_connecting_auth_server">認証サーバに接続中 ...</string>
-  <string name="auth_unsupported_auth_method">サーバはこの認証方式をサポートしていません</string>
+  <string name="auth_connecting_auth_server">èª\8d証ã\82µã\83¼ã\83\90ã\83¼ã\81«æ\8e¥ç¶\9a中 ...</string>
+  <string name="auth_unsupported_auth_method">ã\82µã\83¼ã\83\90ã\83¼ã\81¯ã\81\93ã\81®èª\8d証æ\96¹å¼\8fã\82\92ã\82µã\83\9dã\83¼ã\83\88ã\81\97ã\81¦ã\81\84ã\81¾ã\81\9bã\82\93</string>
   <string name="auth_unsupported_multiaccount">%1$s は複数アカウントをサポートしていません</string>
   <string name="fd_keep_in_sync">ファイルを最新に保つ</string>
   <string name="common_rename">名前を変更</string>
   <string name="confirmation_remove_folder_alert">本当に %1$s およびそのコンテンツを削除してもよろしいですか?</string>
   <string name="confirmation_remove_local">ローカルのみ</string>
   <string name="confirmation_remove_folder_local">ローカルコンテンツのみ</string>
-  <string name="confirmation_remove_remote">サーバから削除</string>
+  <string name="confirmation_remove_remote">ã\82µã\83¼ã\83\90ã\83¼ã\81\8bã\82\89å\89\8aé\99¤</string>
   <string name="confirmation_remove_remote_and_local">リモートとローカルの両方</string>
   <string name="remove_success_msg">削除に成功しました</string>
   <string name="remove_fail_msg">削除を完了できませんでした</string>
   <string name="sync_file_fail_msg">リモートファイルをチェックできませんでした</string>
   <string name="sync_file_nothing_to_do_msg">ファイルコンテンツはすでに同期されています</string>
   <string name="create_dir_fail_msg">ディレクトリを作成できませんでした</string>
+  <string name="filename_forbidden_characters">使用できない文字: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">しばらくお待ちください</string>
   <string name="filedisplay_unexpected_bad_get_content">予期せぬ問題;他のアプリでファイルを選択してみてください。</string>
   <string name="filedisplay_no_file_selected">ファイルは選択されていません</string>
-  <string name="oauth_check_onoff">oAuth2 でログイン</string>
+  <string name="oauth_check_onoff">oAuth2でログイン</string>
   <string name="oauth_login_connection">oAuth2サーバーに接続中...</string>
   <string name="ssl_validator_header">サイトの識別子を確認できませんでした</string>
-  <string name="ssl_validator_reason_cert_not_trusted">- サーバ証明書は信頼されていません</string>
-  <string name="ssl_validator_reason_cert_expired">- サーバ証明書は有効期限切れです</string>
-  <string name="ssl_validator_reason_cert_not_yet_valid">- サーバ証明書は若すぎます</string>
+  <string name="ssl_validator_reason_cert_not_trusted">- サーバ証明書は信頼されていません</string>
+  <string name="ssl_validator_reason_cert_expired">- サーバ証明書は有効期限切れです</string>
+  <string name="ssl_validator_reason_cert_not_yet_valid">- サーバー証明書の有効期限は未来のものです</string>
   <string name="ssl_validator_reason_hostname_not_verified">- URLは証明書内のホスト名と一致しません</string>
   <string name="ssl_validator_question">この証明書を信頼してもよろしいですか?</string>
   <string name="ssl_validator_not_saved">証明書は保存できませんでした</string>
   <string name="placeholder_media_time">12:23:45</string>
   <string name="instant_upload_on_wifi">WiFi経由でのみ写真をアップロード</string>
   <string name="instant_upload_path">/InstantUpload</string>
-  <string name="conflict_title">æ\9b´æ\96°ã\81®競合</string>
-  <string name="conflict_message">リモートファイル %s はローカルファイルと同期していません。続行すると、サーバ上のファイルを置き換えます。</string>
+  <string name="conflict_title">æ\9b´æ\96°ã\81\8c競合</string>
+  <string name="conflict_message">リモートファイル %s はローカルファイルと同期していません。続行すると、サーバ上のファイルを置き換えます。</string>
   <string name="conflict_keep_both">両方を保持</string>
   <string name="conflict_overwrite">上書き</string>
   <string name="conflict_dont_upload">アップロードしない</string>
   <string name="preview_image_description">イメージプレビュー</string>
   <string name="preview_image_error_unknown_format">この画像は表示できません</string>
-  <string name="error__upload__local_file_not_copied">%1$s は %2$s ローカルディレクトリにコピー出来ませんでした</string>
+  <string name="error__upload__local_file_not_copied">%1$s は %2$s ローカルディレクトリにコピーできませんでした</string>
+  <string name="actionbar_failed_instant_upload">インスタントアップロードに失敗</string>
   <string name="failed_upload_headline_text">インスタントアップロードに失敗</string>
   <string name="failed_upload_headline_hint">全ての失敗したインスタントアップロードの要約</string>
   <string name="failed_upload_all_cb">すべて選択</string>
   <string name="failed_upload_load_more_images">更に画像を読み込む</string>
   <string name="failed_upload_retry_do_nothing_text">オンラインでなく、インスタントアップロードのために何もしません</string>
   <string name="failed_upload_failure_text">失敗メッセージ:</string>
-  <string name="failed_upload_quota_exceeded_text">サーバーの設定を確認してください。許容を超過している可能性があります。</string>
+  <string name="failed_upload_quota_exceeded_text">サーバー設定を確認してください。クォータサイズを超えている可能性があります。</string>
 </resources>
index 56a17fa..0ff4bee 100644 (file)
@@ -16,7 +16,6 @@
   <string name="prefs_help">დახმარება</string>
   <string name="prefs_feedback">უკუკავშირი</string>
   <string name="prefs_imprint">ბეჭედი</string>
-  <string name="auth_host_url">სერვერის მისამართი</string>
   <string name="auth_username">მომხმარებლის სახელი</string>
   <string name="auth_password">პაროლი</string>
   <string name="sync_string_files">ფაილები</string>
index 26d42b8..112c57f 100644 (file)
@@ -28,8 +28,9 @@
   <string name="prefs_feedback">피드백</string>
   <string name="prefs_imprint">임프린트</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">서버 주소</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>
@@ -54,6 +55,7 @@
   <string name="filedetails_download">다운로드</string>
   <string name="filedetails_sync_file">파일 새로고침</string>
   <string name="filedetails_renamed_in_upload_msg">업로드 중 파일 이름을 %1$s(으)로 변경하였습니다</string>
+  <string name="action_share_file">링크 공유</string>
   <string name="common_yes">예</string>
   <string name="common_no">아니요</string>
   <string name="common_ok">확인</string>
   <string name="media_err_unsupported">지원하지 않는 미디어 코덱</string>
   <string name="media_err_io">미디어 파일을 읽을수 </string>
   <string name="media_err_malformed">미디어 파일이 제대로 인코드 되지 않았습니다</string>
+  <string name="media_err_timeout">재생 시도 중 시간이 초과됨</string>
   <string name="media_err_invalid_progressive_playback">미디어 파일을 스트리밍 할수 없습니다</string>
   <string name="media_err_unknown">내장된 미디어 플레이어에서는 이 미디어 파일을 재생할수 없습니다</string>
   <string name="media_err_security_ex">%1$s 를 재생하는 중에 보안오류가 발생함</string>
   <string name="auth_connection_established">연결됨</string>
   <string name="auth_testing_connection">연결 테스트 중...</string>
   <string name="auth_not_configured_title">서버 설정이 잘못됨</string>
+  <string name="auth_account_not_new">같은 사용자와 서버에 대한 계정이 이미 존재합니다</string>
+  <string name="auth_account_not_the_same">입력된 사용자가 이 계정의 사용자와 일치하지 않음</string>
   <string name="auth_unknown_error_title">알 수 없는 오류가 발생하였습니다!</string>
   <string name="auth_unknown_host_title">호스트를 찾을 수 없음</string>
   <string name="auth_incorrect_path_title">서버 인스턴스를 찾을 수 없음</string>
   <string name="sync_file_fail_msg">원격 파일을 확인할 수 없었습니다</string>
   <string name="sync_file_nothing_to_do_msg">파일 내용이 이미 동기화되었습니다</string>
   <string name="create_dir_fail_msg">디렉터리를 만들 수 없었습니다</string>
+  <string name="filename_forbidden_characters">사용할수 없는 문자들: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">잠시 기다려 주십시오</string>
   <string name="filedisplay_unexpected_bad_get_content">예상하지 못한 오류입니다. 다른 앱에서 파일을 선택하십시오</string>
   <string name="filedisplay_no_file_selected">선택한 파일 없음</string>
   <string name="ssl_validator_label_signature_algorithm">알고리즘:</string>
   <string name="placeholder_sentence">이것은 플레이스홀더입니다</string>
   <string name="placeholder_filename">placeholder.txt</string>
-  <string name="placeholder_filetype">PNG í\8c\8cì\9d¼</string>
+  <string name="placeholder_filetype">PNG ê·¸ë¦¼</string>
   <string name="placeholder_filesize">389 KB</string>
   <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
   <string name="placeholder_media_time">12:23:45</string>
   <string name="preview_image_description">그림 미리보기</string>
   <string name="preview_image_error_unknown_format">이 그림을 볼수 없습니다</string>
   <string name="error__upload__local_file_not_copied">%1$s를 %2$s 로컬 디렉토리로 복사하지 못했습니다.</string>
+  <string name="actionbar_failed_instant_upload">자동 업로드가 실패했습니다</string>
   <string name="failed_upload_headline_text">자동 업로드 실패함</string>
   <string name="failed_upload_headline_hint">실패된 자동 업로드 전체 요약</string>
   <string name="failed_upload_all_cb">전체 선택</string>
   <string name="failed_upload_headline_delete_all_btn">선택된 업로드 큐 전체 삭제</string>
   <string name="failed_upload_retry_text">이미지 업로드 재시도:</string>
   <string name="failed_upload_load_more_images">더 많은 사진 불러오기</string>
+  <string name="failed_upload_retry_do_nothing_text">현재 온라인이 아니셔서 자동 업로드를 할수 없습니다</string>
   <string name="failed_upload_failure_text">실패 메시지:</string>
   <string name="failed_upload_quota_exceeded_text">서버 설정을 확인해주세요, 아마 업로드 제한을 초과하셨을겁니다.</string>
 </resources>
index c40ddc5..09c1c8c 100644 (file)
@@ -1,12 +1,30 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
   <string name="actionbar_upload">بارکردن</string>
+  <string name="actionbar_upload_files">په‌ڕگەکان</string>
+  <string name="actionbar_mkdir">درووستکردنى بوخچە</string>
   <string name="actionbar_settings">ده‌ستكاری</string>
+  <string name="prefs_category_general">گشتی</string>
+  <string name="prefs_accounts">هەژمارەکان</string>
   <string name="prefs_help">یارمەتی</string>
-  <string name="auth_host_url">ناونیشانی ڕاژه</string>
   <string name="auth_username">ناوی به‌کارهێنه‌ر</string>
   <string name="auth_password">وشەی تێپەربو</string>
+  <string name="sync_string_files">په‌ڕگەکان</string>
+  <string name="setup_btn_connect">بەستنەوە</string>
   <string name="uploader_btn_upload_text">بارکردن</string>
+  <string name="uploader_wrn_no_account_title">هیچ هەژمارێک نه‌دۆزرایه‌وه‌</string>
+  <string name="uploader_wrn_no_account_setup_btn_text">جێگیرکردن</string>
+  <string name="uploader_wrn_no_account_quit_btn_text">دەرچوون</string>
+  <string name="uploader_info_uploading">بارکردن</string>
+  <string name="filedetails_size">قەبارە:</string>
+  <string name="filedetails_type">جۆر:</string>
+  <string name="filedetails_created">درووستبووە:</string>
+  <string name="filedetails_modified">گۆردراو:</string>
   <string name="filedetails_download">داگرتن</string>
+  <string name="common_yes">بەڵێ</string>
+  <string name="common_no">نەخێر</string>
+  <string name="common_ok">باشە</string>
+  <string name="common_cancel">لابردن</string>
+  <string name="common_save_exit">پاشکەوتکردن &amp; دەرچوون</string>
   <string name="common_error">هه‌ڵه</string>
 </resources>
index f7a0fe6..7b6579d 100644 (file)
@@ -13,7 +13,6 @@
   <string name="prefs_pincode">App PIN</string>
   <string name="prefs_help">Hëllef</string>
   <string name="prefs_feedback">Feedback</string>
-  <string name="auth_host_url">Server Adress</string>
   <string name="auth_username">Benotzernumm</string>
   <string name="auth_password">Passwuert</string>
   <string name="sync_string_files">Dateien</string>
@@ -28,6 +27,7 @@
   <string name="filedetails_created">Erstallt:</string>
   <string name="filedetails_modified">Geännert:</string>
   <string name="filedetails_download">Download</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>
index ad28304..063cc84 100644 (file)
@@ -30,7 +30,6 @@
   <string name="recommend_subject">Išbandykite %1$s savo išmaniajame telefone!</string>
   <string name="recommend_text">Siūlau pabandyti %1$s savo išmaniajame telefone!\nParsisiųskite štai čia: %2$s</string>
   <string name="auth_check_server">Patikrinti Serverį</string>
-  <string name="auth_host_url">Serverio adresas</string>
   <string name="auth_username">Prisijungimo vardas</string>
   <string name="auth_password">Slaptažodis</string>
   <string name="sync_string_files">Failai</string>
@@ -54,6 +53,7 @@
   <string name="filedetails_download">Atsisiųsti</string>
   <string name="filedetails_sync_file">Atnaujinti failą</string>
   <string name="filedetails_renamed_in_upload_msg">Įkėlimo metu failas buvo pervadintas į %1$s</string>
+  <string name="action_share_file">Dalintis nuoroda</string>
   <string name="common_yes">Taip</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Gerai</string>
index 37eb6b9..e52b10f 100644 (file)
@@ -14,7 +14,6 @@
   <string name="prefs_instant_upload">Aktivēt tūlītējo augšupielādēšanu</string>
   <string name="prefs_instant_upload_summary">Nekavējoties augšupielādēt kameras uzņemtos attēlus</string>
   <string name="prefs_help">Palīdzība</string>
-  <string name="auth_host_url">Servera adrese</string>
   <string name="auth_username">Lietotājvārds</string>
   <string name="auth_password">Parole</string>
   <string name="sync_string_files">Datnes</string>
index 720e4da..10fa36a 100644 (file)
@@ -16,7 +16,6 @@
   <string name="prefs_help">Помош</string>
   <string name="prefs_recommend">Препорачај на пријател</string>
   <string name="prefs_feedback">Повратен одговор</string>
-  <string name="auth_host_url">Адреса на сервер</string>
   <string name="auth_username">Корисничко име</string>
   <string name="auth_password">Лозинка</string>
   <string name="sync_string_files">Датотеки</string>
@@ -30,6 +29,7 @@
   <string name="filedetails_created">Создадено:</string>
   <string name="filedetails_modified">Изменето:</string>
   <string name="filedetails_download">Преземање</string>
+  <string name="action_share_file">Сподели ја врската</string>
   <string name="common_yes">Да</string>
   <string name="common_no">Не</string>
   <string name="common_ok">Во ред</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
new file mode 100644 (file)
index 0000000..c757504
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
new file mode 100644 (file)
index 0000000..c757504
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
index b2b8fdf..0ca0b78 100644 (file)
@@ -9,7 +9,6 @@
   <string name="prefs_accounts">Akaun</string>
   <string name="prefs_pincode">PIN App</string>
   <string name="prefs_help">Bantuan</string>
-  <string name="auth_host_url">Alamat pelayan</string>
   <string name="auth_username">Nama pengguna</string>
   <string name="auth_password">Kata laluan</string>
   <string name="sync_string_files">Fail-fail</string>
index f7c70fd..b1d1899 100644 (file)
@@ -1,33 +1,61 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
+  <string name="about_android">%1$s Andriod app</string>
+  <string name="about_version">versjon %1$s</string>
+  <string name="actionbar_sync">Oppdater konto</string>
   <string name="actionbar_upload">Last opp</string>
   <string name="actionbar_upload_from_apps">Innhold fra andre applikasjoner</string>
   <string name="actionbar_upload_files">Filer</string>
+  <string name="actionbar_open_with">Åpne med</string>
   <string name="actionbar_mkdir">Opprett katalog</string>
   <string name="actionbar_settings">Innstillinger</string>
+  <string name="actionbar_see_details">Detaljer</string>
   <string name="prefs_category_general">Generelt</string>
   <string name="prefs_category_more">Mer</string>
   <string name="prefs_accounts">Kontoer</string>
+  <string name="prefs_manage_accounts">Håndter kontoer</string>
+  <string name="prefs_pincode">PIN kode</string>
+  <string name="prefs_pincode_summary">Beskytt klienten din</string>
+  <string name="prefs_instant_upload">Aktiver direkte opplastinger</string>
   <string name="prefs_instant_upload_summary">Last opp bilder tatt med kamera øyeblikkelig</string>
+  <string name="prefs_log_title">Aktiver loggføring</string>
+  <string name="prefs_log_summary">Denne er brukt til å loggføre problemer</string>
+  <string name="prefs_log_title_history">Loggføringshistorikk</string>
+  <string name="prefs_log_summary_history">Denne viser de lagrede loggene</string>
+  <string name="prefs_log_delete_history_button">Slett historikk</string>
   <string name="prefs_help">Hjelp</string>
-  <string name="auth_host_url">Server-adresse</string>
+  <string name="prefs_recommend">Anbefal til en venn</string>
+  <string name="prefs_feedback">Tilbakemelding</string>
+  <string name="prefs_imprint">Avtrykk</string>
+  <string name="recommend_subject">Prøv %1$s på smarttelefonen din!</string>
+  <string name="recommend_text">Jeg vil gjerne invitere deg til å bruke %1$s på smarttelefonen din!\nLast ned her: %2$s</string>
+  <string name="auth_check_server">Sjekk server</string>
+  <string name="auth_host_url">Serveradresse https://...</string>
   <string name="auth_username">Brukernavn</string>
   <string name="auth_password">Passord</string>
+  <string name="auth_register">Ny med %1$s?</string>
   <string name="sync_string_files">Filer</string>
   <string name="setup_btn_connect">Koble til</string>
   <string name="uploader_btn_upload_text">Last opp</string>
+  <string name="uploader_top_message">Velg opplastingsmappe:</string>
   <string name="uploader_wrn_no_account_title">Ingen konto funnet</string>
+  <string name="uploader_wrn_no_account_text">Det finnes ingen %1$s kontoer for din enhent. For å bruker denne appen må du først opprette en.</string>
   <string name="uploader_wrn_no_account_setup_btn_text">Oppsett</string>
   <string name="uploader_wrn_no_account_quit_btn_text">Avslutt</string>
   <string name="uploader_wrn_no_content_title">Intet innhold å laste opp</string>
   <string name="uploader_wrn_no_content_text">Intet innhold ble mottatt. Intet å laste opp.</string>
+  <string name="uploader_error_forbidden_content">%1$s har ikke tilgang til det delte innholdet</string>
   <string name="uploader_info_uploading">Laster opp</string>
+  <string name="file_list_empty">Det finnes ikke filer i mappen.\nNye filer kan legges til med \"last opp\" i menyen.</string>
   <string name="filedetails_select_file">Trykk på en fil for å vise ekstra informasjon.</string>
   <string name="filedetails_size">Størrelse:</string>
   <string name="filedetails_type">Type:</string>
   <string name="filedetails_created">Opprettet:</string>
   <string name="filedetails_modified">Endret:</string>
   <string name="filedetails_download">Last ned</string>
+  <string name="filedetails_sync_file">Oppdater fil</string>
+  <string name="filedetails_renamed_in_upload_msg">Filnavnet ble endret til  %1$s under opplasting</string>
+  <string name="action_share_file">Del lenke</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nei</string>
   <string name="common_ok">OK</string>
@@ -36,6 +64,8 @@
   <string name="common_cancel">Avbryt</string>
   <string name="common_save_exit">Lagre og avslutt</string>
   <string name="common_error">Feil</string>
+  <string name="common_loading">Laster...</string>
+  <string name="common_error_unknown">Ukjent feil</string>
   <string name="about_title">Om</string>
   <string name="change_password">Endre passord</string>
   <string name="delete_account">Slett konto</string>
   <string name="uploader_upload_in_progress_ticker">Laster opp...</string>
   <string name="uploader_upload_in_progress_content">%1$d%% Laster opp %2$s</string>
   <string name="uploader_upload_succeeded_ticker">Opplasting fullført</string>
+  <string name="uploader_upload_succeeded_content_single">%1$s ble lastet opp</string>
   <string name="uploader_upload_failed_ticker">Opplasting feilet</string>
   <string name="uploader_upload_failed_content_single">Opplasting av %1$s kunne ikke fullføres</string>
   <string name="downloader_download_in_progress_ticker">Laster ned...</string>
   <string name="downloader_download_in_progress_content">%1$d%% Laster ned %2$s</string>
   <string name="downloader_download_succeeded_ticker">Nedlasting fullført</string>
+  <string name="downloader_download_succeeded_content">%1$s ble lastet ned</string>
   <string name="downloader_download_failed_ticker">Nedlasting feilet</string>
   <string name="downloader_download_failed_content">Nedlasting av %1$s kunne ikke fullføres</string>
+  <string name="downloader_not_downloaded_yet">Ikke lastet ned enda</string>
   <string name="common_choose_account">Velg konto</string>
   <string name="sync_fail_ticker">Synkronisering feilet</string>
   <string name="sync_fail_content">Synkronisering av %1$s kunne ikke fullføres</string>
+  <string name="sync_fail_content_unauthorized">Ugyldig passord for %1$s</string>
   <string name="sync_conflicts_in_favourites_ticker">Konflikter funnet</string>
+  <string name="sync_conflicts_in_favourites_content">%1$d hold-i-synk filer kunne ikke synkroniseres</string>
+  <string name="sync_fail_in_favourites_ticker">Hold i synk filer mislyktes</string>
+  <string name="sync_fail_in_favourites_content">Contents of %1$d files could not be sync\'ed (%2$d conflicts)\nInnhold av %1$d filer kunne ikke synkroniseres (%2$d konflikter)</string>
+  <string name="sync_foreign_files_forgotten_ticker">Noen lokale filer ble glemt</string>
+  <string name="sync_foreign_files_forgotten_content">%1$d filer av %2$s mappen kunne ikke kopieres til</string>
+  <string name="sync_foreign_files_forgotten_explanation">Fra versjon 1.3.16 blir filer lastet opp fra denne enheten kopiert til den lokale %1$s mappen for å forhindre tap av data når én fil blir synkronisert over flere kontoer.\n\nPå grunn av denne forandringern ble alle filer lastet opp i tidligere versjoner av denne appen kopiert til %2$s mappen. Imidlertid ble fullføring av denne operasjonen forhindet av en feil, under kontosynkronisering. Du kan enten la filen(e) være som de er, og fjerne koblinken til  %3$s, eller flytte filen(e) til %1$s mappe, og opprettholde koblingen til %4$s.\n\nListet under er de lokale filen(e), og de eksterne filen(e) i %5$s de var kolet til.</string>
+  <string name="sync_current_folder_was_removed">Mappen %1$s finnes ikke lengere</string>
+  <string name="foreign_files_move">Flytt alle</string>
+  <string name="foreign_files_success">Alle filer ble flyttet</string>
+  <string name="foreign_files_fail">Noen filer kunne ikke fjernes</string>
+  <string name="foreign_files_local_text">Lokal: %1$s</string>
+  <string name="foreign_files_remote_text">Ekstern: %1$s</string>
+  <string name="upload_query_move_foreign_files">Det er ikke nok plass til å kopiere de valgte filene til %1$s mappe. Vil du flytte dem i stedet?</string>
   <string name="pincode_enter_pin_code">Vennligst tast inn din App-PIN</string>
+  <string name="pincode_configure_your_pin">Skriv inn din PIN kode</string>
+  <string name="pincode_configure_your_pin_explanation">PIN koden vil bli ettersourt hver gang appen starter</string>
+  <string name="pincode_reenter_your_pincode">Vennligst tast inn din PIN kode på nytt</string>
+  <string name="pincode_remove_your_pincode">Fjern din PIN kode</string>
+  <string name="pincode_mismatch">PIN kodene du tastet er ulike</string>
+  <string name="pincode_wrong">Feil PIN kode</string>
+  <string name="pincode_removed">PIN kode fjernet</string>
+  <string name="pincode_stored">PIN kode lagret</string>
+  <string name="media_notif_ticker">%1$s musikkspiller</string>
+  <string name="media_state_playing">%1$s (spiller)</string>
+  <string name="media_state_loading">%1$s (laster)</string>
+  <string name="media_event_done">%1$s avspilling avsluttet</string>
+  <string name="media_err_nothing_to_play">Ingen mediafil funnet</string>
+  <string name="media_err_no_account">Ingen konto angitt</string>
+  <string name="media_err_not_in_owncloud">Filen er ikke i en gyldig konto</string>
+  <string name="media_err_unsupported">Mediakodek er ikke støttet</string>
+  <string name="media_err_io">Mediafilen kunne ikke leses</string>
+  <string name="media_err_malformed">Mediafilen er ikke riktig kodet</string>
+  <string name="media_err_timeout">Tidsavbrudd under avspillingsforsøk</string>
+  <string name="media_err_invalid_progressive_playback">Mediafilen kan ikke strømmes</string>
+  <string name="media_err_unknown">Mediafilen kan ikke spilles med standard mediaspiller</string>
+  <string name="media_err_security_ex">Sikkerhetsfeil under avspilling av %1$s</string>
+  <string name="media_err_io_ex">Inputfeil under avspilling av %1$s</string>
+  <string name="media_err_unexpected">Uforventet feil under avspilling av %1$s</string>
+  <string name="media_rewind_description">Spol tilbake</string>
+  <string name="media_play_pause_description">Spill eller pause</string>
+  <string name="media_forward_description">Spol fremover</string>
   <string name="auth_trying_to_login">Prøver å logge inn...</string>
   <string name="auth_no_net_conn_title">Ingen nettverkstilkobling</string>
   <string name="auth_nossl_plain_ok_title">Sikker tilkobling ikke tilgjengelig.</string>
   <string name="auth_connection_established">Tilkobling opprettet</string>
   <string name="auth_testing_connection">Tester tilgang...</string>
+  <string name="auth_not_configured_title">Feil i server konfigurasjon</string>
+  <string name="auth_account_not_new">En konto for samme bruker og server finnes allerede på enheten</string>
+  <string name="auth_account_not_the_same">Den innskrevne brukeren matcher ikke brukeren av denne kontoen</string>
   <string name="auth_unknown_error_title">Ukjent feil oppstod!</string>
   <string name="auth_unknown_host_title">Fant ikke tjener</string>
+  <string name="auth_incorrect_path_title">Finner ikke server instans</string>
   <string name="auth_timeout_title">Serveren brukte for lang tid på å svare</string>
   <string name="auth_incorrect_address_title">Feil formatert URL</string>
   <string name="auth_ssl_general_error_title">Oppstart av SSL feilet</string>
+  <string name="auth_ssl_unverified_server_title">Kunne ikke verifisere SSL-serverens identitet</string>
+  <string name="auth_bad_oc_version_title">Ukjent server versjon</string>
   <string name="auth_wrong_connection_title">Klarte ikke å opprette tilkobling</string>
   <string name="auth_secure_connection">Sikker tilkobling opprettet</string>
+  <string name="auth_unauthorized">Feil brukernavn eller passord</string>
+  <string name="auth_oauth_error">Mislykket autorisasjon</string>
+  <string name="auth_oauth_error_access_denied">Tilgang nektet av autorisasjonsserver</string>
+  <string name="auth_wtf_reenter_URL">Uforventet tilstand; vennligst skriv inn serveradressen en gang til</string>
+  <string name="auth_expired_oauth_token_toast">Autorisasjonen din har gått ut. Vennligt autoriser igjen</string>
+  <string name="auth_expired_basic_auth_toast">Vennligst skriv inn gjeldende passord</string>
+  <string name="auth_expired_saml_sso_token_toast">Sesjonen din har gått ut. Vennligst koble til igjen</string>
+  <string name="auth_connecting_auth_server">Kobler til autorisasjonsserver...</string>
+  <string name="auth_unsupported_auth_method">Serveren støtter ikke denne autorisasjonsmetoden</string>
+  <string name="auth_unsupported_multiaccount">%1$s støtter ikke flere kontoer</string>
   <string name="fd_keep_in_sync">Hold filen oppdatert</string>
   <string name="common_rename">Endre navn</string>
   <string name="common_remove">Fjern</string>
   <string name="confirmation_remove_alert">Er du sikker på at du vil fjerne %1$s ?</string>
+  <string name="confirmation_remove_folder_alert">Vil du virkelig fjerne %1$s og dens innhold?</string>
   <string name="confirmation_remove_local">Kun lokalt</string>
+  <string name="confirmation_remove_folder_local">Kun lokalt innhold</string>
   <string name="confirmation_remove_remote">Fjern fra server</string>
+  <string name="confirmation_remove_remote_and_local">Ekstern og lokal</string>
+  <string name="remove_success_msg">Fjerning var vellykket</string>
+  <string name="remove_fail_msg">Fjerning mislyktes</string>
+  <string name="rename_dialog_title">Skriv inn et nytt navn</string>
+  <string name="rename_local_fail_msg">Lokal kopi kunne ikke endre navn; prøv et annet navn</string>
   <string name="rename_server_fail_msg">Klarte ikke å endre navn</string>
+  <string name="sync_file_fail_msg">Eksterne filer kunne ikke sjekkes</string>
+  <string name="sync_file_nothing_to_do_msg">filinnhold er allerede synkronisert</string>
   <string name="create_dir_fail_msg">Mappe kunne ikke opprettes</string>
+  <string name="filename_forbidden_characters">Forbudte tegn: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Vent et øyeblikk</string>
+  <string name="filedisplay_unexpected_bad_get_content">Uforventet problem; vennligst velg filen fra en annen applikasjon</string>
   <string name="filedisplay_no_file_selected">Ingen fil ble valgt</string>
+  <string name="oauth_check_onoff">Logg inn med oAuth2</string>
+  <string name="oauth_login_connection">Kobler til oAuth2 server...</string>
   <string name="ssl_validator_header">Identiteten til siden kunne ikke verifiseres</string>
   <string name="ssl_validator_reason_cert_not_trusted">- Serverens sertifikat er ikke til å stole på</string>
   <string name="ssl_validator_reason_cert_expired">- Serverens sertifikat er utløpt</string>
+  <string name="ssl_validator_reason_cert_not_yet_valid">- Server-sertifikatets gyldige datoer er i fremtiden</string>
+  <string name="ssl_validator_reason_hostname_not_verified">- Nettadressen samsvarer ikke med vertsnavnet i sertifikatet</string>
+  <string name="ssl_validator_question">Vil du stole på dette sertifikatet likevel?</string>
+  <string name="ssl_validator_not_saved">Sertifikatet kunne ikke lagres</string>
   <string name="ssl_validator_btn_details_see">Detaljer</string>
   <string name="ssl_validator_btn_details_hide">Skjul</string>
+  <string name="ssl_validator_label_subject">Utstedt til:</string>
+  <string name="ssl_validator_label_issuer">Utstedt av:</string>
+  <string name="ssl_validator_label_CN">Vanlig navn:</string>
+  <string name="ssl_validator_label_O">Organisasjon:</string>
+  <string name="ssl_validator_label_OU">Organisasjonsenhet:</string>
   <string name="ssl_validator_label_C">Land:</string>
+  <string name="ssl_validator_label_ST">Stat:</string>
+  <string name="ssl_validator_label_L">Sted:</string>
+  <string name="ssl_validator_label_validity">Gyldighet:</string>
   <string name="ssl_validator_label_validity_from">Fra:</string>
   <string name="ssl_validator_label_validity_to">Til:</string>
   <string name="ssl_validator_label_signature">Signatur:</string>
+  <string name="ssl_validator_label_signature_algorithm">Algoritme:</string>
+  <string name="placeholder_sentence">Dette er en plassholder</string>
+  <string name="placeholder_filename">placeholder.txt</string>
+  <string name="placeholder_filetype">PNG bilde</string>
+  <string name="placeholder_filesize">389 KB</string>
+  <string name="placeholder_timestamp">18.05.2012 12:23</string>
+  <string name="placeholder_media_time">12:23:45</string>
+  <string name="instant_upload_on_wifi">Kun last opp bilder via WiFi</string>
+  <string name="instant_upload_path">/Direkteopplasting</string>
+  <string name="conflict_title">Oppdateringskonflikt</string>
+  <string name="conflict_message">Ekstern fil %s er ikke synkronisert med lokal fil. Hvis du fortsetter vil det erstatte innhold på serveren.</string>
   <string name="conflict_keep_both">Behold begge</string>
+  <string name="conflict_overwrite">Overskriv</string>
+  <string name="conflict_dont_upload">Ikke last opp</string>
+  <string name="preview_image_description">Bildeforhåndsvisning</string>
+  <string name="preview_image_error_unknown_format">Dette bildet kan ikke vises</string>
+  <string name="error__upload__local_file_not_copied">%1$s kunne ikke kopieres til %2$s lokale mapper</string>
+  <string name="actionbar_failed_instant_upload">Misslyktes direkteopplasting</string>
+  <string name="failed_upload_headline_text">Mislykket direkteopplastinger</string>
+  <string name="failed_upload_headline_hint">Oppsumering av alle mislykkede direkteopplastinger</string>
+  <string name="failed_upload_all_cb">velg alle</string>
+  <string name="failed_upload_headline_retryall_btn">forsøk alle valgte på nytt</string>
+  <string name="failed_upload_headline_delete_all_btn">slett alle valgte fra opplastingskø</string>
+  <string name="failed_upload_retry_text">forsøk å laste opp bildet på nytt:</string>
+  <string name="failed_upload_load_more_images">Last flere bilder</string>
+  <string name="failed_upload_retry_do_nothing_text">ikke gjør noe når du ikke er online for direkteopplasting</string>
+  <string name="failed_upload_failure_text">Feilmelding:</string>
+  <string name="failed_upload_quota_exceeded_text">Vennligst sjekk serverkonfigurasjon, kanskje kvoten din er brukt opp.</string>
 </resources>
index 98c947e..4cfbceb 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Probeer %1$s op uw smartphone!</string>
   <string name="recommend_text">Uitnodiging om %1$s op uw smartphone uit te proberen!\nDownload hier: %2$s</string>
   <string name="auth_check_server">Controleer server</string>
-  <string name="auth_host_url">Server adres</string>
+  <string name="auth_host_url">Serveradres https://…</string>
   <string name="auth_username">Gebruikersnaam</string>
   <string name="auth_password">Wachtwoord</string>
   <string name="auth_register">Nieuw bij %1$s?</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">Download</string>
   <string name="filedetails_sync_file">Bestand verversen</string>
   <string name="filedetails_renamed_in_upload_msg">Bestand was hernoemt naar %1$s tijdens het uploaden</string>
+  <string name="action_share_file">Deel link</string>
+  <string name="action_unshare_file">Link niet meer delen</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nee</string>
   <string name="common_ok">OK</string>
   <string name="sync_file_fail_msg">Extern bestand kon niet worden gecontroleerd</string>
   <string name="sync_file_nothing_to_do_msg">Bestandsinhoud is al gesynchroniseerd</string>
   <string name="create_dir_fail_msg">Map kon niet worden aangemaakt</string>
+  <string name="filename_forbidden_characters">Verboden tekens: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Even geduld</string>
   <string name="filedisplay_unexpected_bad_get_content">Onverwacht probleem; probeer een andere app om het bestand te selecteren</string>
   <string name="filedisplay_no_file_selected">Er werd geen bestand geselecteerd</string>
+  <string name="activity_chooser_title">Verstuur link naar ...</string>
   <string name="oauth_check_onoff">Inloggen met oAuth2</string>
   <string name="oauth_login_connection">Verbinden met oAuth2-server.</string>
   <string name="ssl_validator_header">De identiteit van de site kan niet worden gecontroleerd</string>
   <string name="preview_image_description">Afbeelding voorbeeld</string>
   <string name="preview_image_error_unknown_format">Deze afbeelding kan niet weergegeven worden</string>
   <string name="error__upload__local_file_not_copied">%1$s kon niet worden gekopieerd naar de %2$s lokale map</string>
+  <string name="actionbar_failed_instant_upload">Mislukt InstantUpload</string>
   <string name="failed_upload_headline_text">Mislukte directe uploads</string>
   <string name="failed_upload_headline_hint">Samenvatting van alle mislukte directe uploads</string>
   <string name="failed_upload_all_cb">alles selecteren</string>
   <string name="failed_upload_retry_do_nothing_text">doe niks, u bent niet online voor directe upload</string>
   <string name="failed_upload_failure_text">Mislukkings Bericht:</string>
   <string name="failed_upload_quota_exceeded_text">Controleer uw server instellingen, misschien is uw quota overschreden.</string>
+  <string name="share_link_no_support_share_api">Sorry, delen is niet mogelijk op uw server. Neem contact op met uw beheerder.</string>
+  <string name="share_link_file_no_exist">Kan dit bestand of deze map niet delen. Controleer of dit object wel bestaat.</string>
+  <string name="share_link_file_error">Er trad een fout op bij uw poging dit bestand of deze map te delen</string>
+  <string name="unshare_link_file_error">Er trad een fout op bij uw poging het delen van dit bestand of deze map te beëindigen</string>
 </resources>
index 12eba28..0d76c8e 100644 (file)
@@ -11,7 +11,6 @@
   <string name="prefs_instant_upload_summary">Last opp kamerabilete med ein gong du tek dei</string>
   <string name="prefs_help">Hjelp</string>
   <string name="prefs_imprint">Impressum</string>
-  <string name="auth_host_url">Tenaradresse</string>
   <string name="auth_username">Brukarnamn</string>
   <string name="auth_password">Passord</string>
   <string name="sync_string_files">Filer</string>
index 7d9f60a..d3a2836 100644 (file)
@@ -15,7 +15,6 @@
   <string name="prefs_log_title">ਲਾਗ ਰੱਖਣਾ ਚਾਲੂ</string>
   <string name="prefs_log_title_history">ਲਾਗ ਰੱਖਣ ਅਤੀਤ</string>
   <string name="prefs_log_delete_history_button">ਅਤੀਤ ਹਟਆਓ</string>
-  <string name="auth_host_url">ਸਰਵਰ ਐਡਰੈਸ</string>
   <string name="auth_username">ਯੂਜ਼ਰ-ਨਾਂ</string>
   <string name="auth_password">ਪਾਸਵਰ</string>
   <string name="auth_register">%1$s ਲਈ ਨਵੇਂ ਹੋ?</string>
index 6dd15a0..3d0e63d 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Wypróbuj %1$s na swoim smartphonie!</string>
   <string name="recommend_text">Chcę was zaprosić do korzystania z %1$ s na twoim smartfonie!\nPobierz tutaj: %2$s</string>
   <string name="auth_check_server">Sprawdź serwer</string>
-  <string name="auth_host_url">Adres Serwera</string>
+  <string name="auth_host_url">Adres serwera https://...</string>
   <string name="auth_username">Nazwa użytkownika</string>
   <string name="auth_password">Hasło</string>
   <string name="auth_register">Nowe %1$s?</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">Pobierz</string>
   <string name="filedetails_sync_file">Odśwież plik</string>
   <string name="filedetails_renamed_in_upload_msg">Podczas wysyłania nazwa pliku została zmieniona na %1$s</string>
+  <string name="action_share_file">Udostępnij link</string>
+  <string name="action_unshare_file">Anuluj udostępnianie</string>
   <string name="common_yes">Tak</string>
   <string name="common_no">Nie</string>
   <string name="common_ok">OK</string>
   <string name="sync_file_fail_msg">Nie można sprawdzić zdalnego pliku</string>
   <string name="sync_file_nothing_to_do_msg">Zawartość pliku została już synchronizowana</string>
   <string name="create_dir_fail_msg">Nie można utworzyć katalogu</string>
+  <string name="filename_forbidden_characters">Znaki zabronione: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Poczekaj chwilę</string>
   <string name="filedisplay_unexpected_bad_get_content">Nieoczekiwany problem; spróbuj wybrać plik z innej aplikacji</string>
   <string name="filedisplay_no_file_selected">Nie wybrano żadnych plików</string>
+  <string name="activity_chooser_title">Wyślij link do ...</string>
   <string name="oauth_check_onoff">Loguj przez oAuth2</string>
   <string name="oauth_login_connection">Łączenie z serwerem oAuth2...</string>
   <string name="ssl_validator_header">Nie można zweryfikować tożsamości strony</string>
   <string name="preview_image_description">Podgląd</string>
   <string name="preview_image_error_unknown_format">Obraz nie może zostać wyświetlony</string>
   <string name="error__upload__local_file_not_copied">%1$s nie może zostać skopiowany do lokalnego %2$s katalogu</string>
+  <string name="actionbar_failed_instant_upload">InstantUpload nie powiódł się</string>
   <string name="failed_upload_headline_text">Błąd automatycznego przesyłania</string>
   <string name="failed_upload_headline_hint">Podsumowanie wszystkich nieudanych transferów</string>
   <string name="failed_upload_all_cb">zaznacz wszystkie</string>
   <string name="failed_upload_retry_do_nothing_text">nic nie rób, ponieważ nie jesteś online, nie możesz przesyłać plików</string>
   <string name="failed_upload_failure_text">Komunikat błędu:</string>
   <string name="failed_upload_quota_exceeded_text">Proszę sprawdź ustawienia serwera, możliwe że przekroczyłes limit wielkości pliku</string>
+  <string name="share_link_no_support_share_api">Przepraszamy, udostępnianie jest wyłączone na twoim serwerze. Skontaktuj się z twoim administratorem.</string>
+  <string name="share_link_file_no_exist">Brak możliwości udostępnienia tego pliku lub folderu. Upewnij się, że istnieje.</string>
+  <string name="share_link_file_error">Wystąpił błąd podczas udostępniania tego pliku lub folderu.</string>
+  <string name="unshare_link_file_error">Wystąpił błąd podczas anulowania udostępniania tego pliku lub folderu.</string>
 </resources>
index c43a22b..93d654d 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Tentar %1$s em seu smartfone!</string>
   <string name="recommend_text">Gostaria de lhe convidar para usar %1$s em seu smartfone!\nBaixe aqui: %2$s</string>
   <string name="auth_check_server">Verificar Servidor</string>
-  <string name="auth_host_url">Endereço do servidor</string>
+  <string name="auth_host_url">Endereço do servidor https://...</string>
   <string name="auth_username">Nome de usuário</string>
   <string name="auth_password">Senha</string>
   <string name="auth_register">Novo para %1$s?</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">Download</string>
   <string name="filedetails_sync_file">Atualizar arquivo</string>
   <string name="filedetails_renamed_in_upload_msg">Arquivo foi renomeado para %1$s durante o upload</string>
+  <string name="action_share_file">Compartilher link</string>
+  <string name="action_unshare_file">Descompartilhar o link</string>
   <string name="common_yes">Sim</string>
   <string name="common_no">Não</string>
   <string name="common_ok">OK</string>
   <string name="wait_a_moment">Aguarde um momento</string>
   <string name="filedisplay_unexpected_bad_get_content">Problema inesperado; por favor, tente selecionar o arquivo com outro app</string>
   <string name="filedisplay_no_file_selected">Nenhum arquivo foi selecionado</string>
+  <string name="activity_chooser_title">Enviar o link para</string>
   <string name="oauth_check_onoff">Login com oAuth2</string>
   <string name="oauth_login_connection">Conectando-se a oAuth2 servidor ...</string>
   <string name="ssl_validator_header">A identidade do site não pode ser verificada</string>
   <string name="failed_upload_retry_do_nothing_text">não fazer nada voce não está conectado para envio instantâneo </string>
   <string name="failed_upload_failure_text">Mensagem de Falha:</string>
   <string name="failed_upload_quota_exceeded_text">Por favor verifique a configuração do servidor, talvez a sua cota esteja vencida.</string>
+  <string name="share_link_no_support_share_api">Desculpe, compartilhamento não está habilitado para seu servidor. Por favor faça contato com o seu administrador.</string>
+  <string name="share_link_file_no_exist">Incapaz de compartilhar esse arquivo ou pasta. Por favor, certifique-se que existe</string>
+  <string name="share_link_file_error">Ocorreu um erro durante a tentativa de compartilhar esse arquivo ou pasta</string>
+  <string name="unshare_link_file_error">Ocorreu um erro ao tentar descompartilhar este arquivo ou pasta</string>
 </resources>
index 6121f6d..0005cb4 100644 (file)
   <string name="prefs_log_summary_history">Isto mostra os registos guardados</string>
   <string name="prefs_log_delete_history_button">Eliminar Histórico</string>
   <string name="prefs_help">Ajuda</string>
+  <string name="prefs_recommend">Recomendar a um amigo</string>
   <string name="prefs_feedback">Resposta</string>
   <string name="prefs_imprint">Imprint</string>
+  <string name="recommend_subject">Experimente %1$s no seu smartphone!</string>
+  <string name="recommend_text">Quero convidá-lo para experimentar %1$s no seu smartphone!\nDescarregue aqui: %2$s</string>
   <string name="auth_check_server">Verificar Servidor</string>
-  <string name="auth_host_url">Endereço do servidor</string>
+  <string name="auth_host_url">Endereço do servidor https://..</string>
   <string name="auth_username">Nome de Utilizador</string>
   <string name="auth_password">Palavra-passe</string>
   <string name="auth_register">Novo em %1$s?</string>
@@ -52,6 +55,7 @@
   <string name="filedetails_download">Descarregar</string>
   <string name="filedetails_sync_file">Atualizar ficheiro</string>
   <string name="filedetails_renamed_in_upload_msg">O nome do ficheiro foi alterado para %1$s durante o envio.</string>
+  <string name="action_share_file">Partilhar o link</string>
   <string name="common_yes">Sim</string>
   <string name="common_no">Não</string>
   <string name="common_ok">OK</string>
@@ -92,6 +96,7 @@
   <string name="sync_foreign_files_forgotten_ticker">Alguns ficheiros locais ficaram esquecidos</string>
   <string name="sync_foreign_files_forgotten_content">%1$d ficheiros da directoria %2$s não foram copiados</string>
   <string name="sync_foreign_files_forgotten_explanation">Com a versão 1.3.16, os ficheiros que foram enviados deste dispositivo foram copiados para a pasta local %1$s para prevenir perda de dados quando um ficheiro está partilhado com várias contas.\nDevido a esta alteração, todos os ficheiros e as suas versões foram copiados para a pasta %2$s. Contudo, um erro não deixou concluír este processo durante a sincronização da conta. Pode deixar o ficheiro(s) como está(ão) e remover o link para %3$s, ou mover o(s) ficheiro(s)  para a pasta %1$s e guardar o link para %4$s.\n\nEm baixo está(ão) listados o(s) ficheiro(s) locais e remotos em %5$s que foram ligados.</string>
+  <string name="sync_current_folder_was_removed">A pasta %1$s já não existe</string>
   <string name="foreign_files_move">Mover Todos</string>
   <string name="foreign_files_success">Todos os ficheiros foram movidos</string>
   <string name="foreign_files_fail">Não foi possível mover alguns ficheiros</string>
   <string name="media_err_unsupported">Codec de média não suportado</string>
   <string name="media_err_io">Não foi possível reproduzir o ficheiro</string>
   <string name="media_err_malformed">Ficheiro erradamente codificado (codec)</string>
+  <string name="media_err_timeout">O tempo de espera para jogar expirou</string>
   <string name="media_err_invalid_progressive_playback">O ficheiro não pode ser reproduzido (streaming)</string>
   <string name="media_err_unknown">O ficheiro não pode ser reproduzido com o leitor de média de origem</string>
   <string name="media_err_security_ex">Erro de segurança a tentar reproduzir o ficheiro %1$s</string>
   <string name="auth_connection_established">Ligação estabelecida</string>
   <string name="auth_testing_connection">A testar a ligação...</string>
   <string name="auth_not_configured_title">Configuração do servidor incorrecta.</string>
+  <string name="auth_account_not_new">Uma conta para este utilizador e servidor já existe no dispositivo</string>
+  <string name="auth_account_not_the_same">O utilizador que escreveu não coincide com o nome de utilizador desta conta</string>
   <string name="auth_unknown_error_title">Ocorreu um erro desconhecido!</string>
   <string name="auth_unknown_host_title">Não é possível encontrar o servidor</string>
   <string name="auth_incorrect_path_title">Instância servidor não encontrada</string>
   <string name="auth_timeout_title">O servidor levou demasiado tempo a responder</string>
   <string name="auth_incorrect_address_title">URL errado</string>
   <string name="auth_ssl_general_error_title">Inicialização de SSL falhou</string>
+  <string name="auth_ssl_unverified_server_title">Não foi possível verificar a identidade SSL do servidor</string>
   <string name="auth_bad_oc_version_title">Versão do servidor não reconhecida</string>
   <string name="auth_wrong_connection_title">Não consegue estabelecer ligação</string>
   <string name="auth_secure_connection">Ligação segura estabelecida</string>
   <string name="auth_oauth_error">autorização mal sucedida</string>
   <string name="auth_oauth_error_access_denied">Acesso negado pelo servidor</string>
   <string name="auth_wtf_reenter_URL">Estado inesperado, por favor, digite a URL do servidor novamente</string>
+  <string name="auth_expired_oauth_token_toast">O prazo da sua autorização expirou. Por favor renove-a</string>
   <string name="auth_expired_basic_auth_toast">Por favor, introduza a password actual</string>
+  <string name="auth_expired_saml_sso_token_toast">A sua sessão expirou. Por favor autentique-se de novo</string>
+  <string name="auth_connecting_auth_server">A verificar a sua autenticação no servidor...</string>
+  <string name="auth_unsupported_auth_method">O servidor não suporta este método de autenticação</string>
+  <string name="auth_unsupported_multiaccount">%1$s não suporta contas múltiplas</string>
   <string name="fd_keep_in_sync">manter ficheiro actualizado</string>
   <string name="common_rename">Renomear</string>
   <string name="common_remove">Remover</string>
   <string name="sync_file_fail_msg">Não foi possível verificar o ficheiro remoto</string>
   <string name="sync_file_nothing_to_do_msg">O conteúdo do ficheiro já foi sincronizado</string>
   <string name="create_dir_fail_msg">Não foi possível criar a pasta</string>
+  <string name="filename_forbidden_characters">Caracteres não permitidos: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Aguarde um momento</string>
   <string name="filedisplay_unexpected_bad_get_content">Erro inesperado. Por favor tente outra aplicação para seleccionar o ficheiro.</string>
   <string name="filedisplay_no_file_selected">Não selecionou nenhum ficheiro</string>
+  <string name="oauth_check_onoff">Autenticar-se com oAuth2</string>
   <string name="oauth_login_connection">A ligar ao servidor oAuth2</string>
   <string name="ssl_validator_header">Não foi possível verificar a identidade do site.</string>
   <string name="ssl_validator_reason_cert_not_trusted">- O certificado do servidor não é de confiança</string>
   <string name="preview_image_description">Pré-Visualização da imagem</string>
   <string name="preview_image_error_unknown_format">Esta imagem não pode ser mostrada</string>
   <string name="error__upload__local_file_not_copied">Não foi possível copiar %1$s para a pasta local %2$s</string>
+  <string name="actionbar_failed_instant_upload">O envio rápido falhou</string>
   <string name="failed_upload_headline_text">Falharam os Uploads-Instantâneos</string>
   <string name="failed_upload_headline_hint">Sumário dos Uploads-Instantâneos falhados</string>
   <string name="failed_upload_all_cb">Seleccionar Todos</string>
index a35bbdc..0569277 100644 (file)
@@ -11,7 +11,6 @@
   <string name="prefs_manage_accounts">Administrare conturi</string>
   <string name="prefs_instant_upload">Activează încărcarea instant</string>
   <string name="prefs_help">Ajutor</string>
-  <string name="auth_host_url">Adresa server-ului</string>
   <string name="auth_username">Nume utilizator</string>
   <string name="auth_password">Parolă</string>
   <string name="sync_string_files">Fișiere</string>
index b7d3c62..6675918 100644 (file)
@@ -16,7 +16,6 @@
   <string name="prefs_instant_upload">Включить немедленную загрузку</string>
   <string name="prefs_instant_upload_summary">Мгновенно загрузить фотографии, сделанные камерой</string>
   <string name="prefs_help">Помощь</string>
-  <string name="auth_host_url">URL</string>
   <string name="auth_username">Имя пользователя</string>
   <string name="auth_password">Пароль</string>
   <string name="auth_register">Я новичок в %1$s</string>
index ccc1699..1964f73 100644 (file)
@@ -1,52 +1,52 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
-  <string name="about_android">%1$s Ð\9fÑ\80иложение Ð\90ндÑ\80оид</string>
+  <string name="about_android">%1$s Ð\9fÑ\80иложение Ð´Ð»Ñ\8f Ð\90ндÑ\80оида</string>
   <string name="about_version">Версия %1$s</string>
   <string name="actionbar_sync">Обновить учетную запись</string>
-  <string name="actionbar_upload">Ð\97агÑ\80Ñ\83зка</string>
-  <string name="actionbar_upload_from_apps">СодеÑ\80жимое Ð¾Ñ\82 других приложений</string>
+  <string name="actionbar_upload">Ð\97агÑ\80Ñ\83зиÑ\82Ñ\8c</string>
+  <string name="actionbar_upload_from_apps">СодеÑ\80жимое Ð¸Ð· других приложений</string>
   <string name="actionbar_upload_files">Файлы</string>
   <string name="actionbar_open_with">Открыть с помощью</string>
-  <string name="actionbar_mkdir">СоздаÑ\82Ñ\8c Ð´Ð¸Ñ\80екÑ\82оÑ\80иÑ\8e</string>
+  <string name="actionbar_mkdir">СоздаÑ\82Ñ\8c ÐºÐ°Ñ\82алог</string>
   <string name="actionbar_settings">Настройки</string>
-  <string name="actionbar_see_details">Ð\94еÑ\82али</string>
-  <string name="prefs_category_general">Ð\93лавные</string>
+  <string name="actionbar_see_details">Ð\9fодÑ\80обно</string>
+  <string name="prefs_category_general">Ð\9eÑ\81новные</string>
   <string name="prefs_category_more">Больше</string>
-  <string name="prefs_accounts">Ð\90ккаÑ\83нÑ\82Ñ\8b</string>
-  <string name="prefs_manage_accounts">Управление аккаунтами</string>
+  <string name="prefs_accounts">УÑ\87Ñ\91Ñ\82нÑ\8bе Ð·Ð°Ð¿Ð¸Ñ\81и</string>
+  <string name="prefs_manage_accounts">Управление учётными записями</string>
   <string name="prefs_pincode">App PIN</string>
-  <string name="prefs_pincode_summary">Защитить ваш клиент применение</string>
-  <string name="prefs_instant_upload">Включить моментальную загрузку</string>
-  <string name="prefs_instant_upload_summary">Ð\9cоменÑ\82алÑ\8cно загружать фотографии, полученные с камеры</string>
-  <string name="prefs_log_title">Ð\92клÑ\8eÑ\87иÑ\82Ñ\8c Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8c Ð¶Ñ\83Ñ\80нала</string>
-  <string name="prefs_log_summary">ЭÑ\82о Ð¸Ñ\81полÑ\8cзÑ\83еÑ\82Ñ\81Ñ\8f Ð´Ð»Ñ\8f  Ñ\80егиÑ\81Ñ\82Ñ\80аÑ\86ии Ð¿Ñ\80облем</string>
-  <string name="prefs_log_title_history">Ð\97апиÑ\81Ñ\8bваÑ\82Ñ\8c Ð¸Ñ\81Ñ\82оÑ\80иÑ\8e</string>
-  <string name="prefs_log_summary_history">Ð\97деÑ\81Ñ\8c Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ñ\8b Ð¶Ñ\83Ñ\80налÑ\8b</string>
-  <string name="prefs_log_delete_history_button">Удалить историю</string>
+  <string name="prefs_pincode_summary">Защитить ваш клиент</string>
+  <string name="prefs_instant_upload">Включить режим немедленной загрузки</string>
+  <string name="prefs_instant_upload_summary">Ð\9dемедленно загружать фотографии, полученные с камеры</string>
+  <string name="prefs_log_title">Ð\92клÑ\8eÑ\87иÑ\82Ñ\8c Ð¶Ñ\83Ñ\80налиÑ\80ование</string>
+  <string name="prefs_log_summary">Ð\98Ñ\81полÑ\8cзÑ\83еÑ\82Ñ\81Ñ\8f Ð´Ð»Ñ\8f Ñ\80егиÑ\81Ñ\82Ñ\80аÑ\86ии Ð¾Ñ\88ибок</string>
+  <string name="prefs_log_title_history">Ð\96Ñ\83Ñ\80нал</string>
+  <string name="prefs_log_summary_history">Ð\97деÑ\81Ñ\8c Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ñ\8b Ð·Ð°Ð¿Ð¸Ñ\81и Ð² Ð¶Ñ\83Ñ\80нал</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="recommend_subject">Попробуйте %1$s на вашем смартфоне!</string>
-  <string name="recommend_text">ХоÑ\87Ñ\83 Ð¿Ñ\80едложиÑ\82Ñ\8c Ð²Ð°Ð¼ Ð¿Ð¾Ð»Ñ\8cзоваÑ\82Ñ\8cÑ\81Ñ\8f %1$s Ð½Ð° Ð²Ð°Ñ\88ем Ñ\81маÑ\80Ñ\82Ñ\84оне!\nÐ\94лÑ\8f Ð·Ð°Ð³Ñ\80Ñ\83зки: %2$s</string>
+  <string name="recommend_text">ХоÑ\87Ñ\83 Ð¿Ñ\80едложиÑ\82Ñ\8c Ð²Ð°Ð¼ Ð¿Ð¾Ð»Ñ\8cзоваÑ\82Ñ\8cÑ\81Ñ\8f %1$s Ð½Ð° Ð²Ð°Ñ\88ем Ñ\81маÑ\80Ñ\82Ñ\84оне!\nСкаÑ\87аÑ\82Ñ\8c: %2$s</string>
   <string name="auth_check_server">Проверить сервер</string>
-  <string name="auth_host_url">Адрес сервера</string>
-  <string name="auth_username">Ð\9fолÑ\8cзоваÑ\82елÑ\8c</string>
+  <string name="auth_host_url">Адрес сервера https://...</string>
+  <string name="auth_username">Ð\98мÑ\8f Ð¿Ð¾Ð»Ñ\8cзоваÑ\82елÑ\8f</string>
   <string name="auth_password">Пароль</string>
-  <string name="auth_register">Ð\92пеÑ\80вÑ\8bе с %1$s?</string>
+  <string name="auth_register">Ð\9dезнакомÑ\8b с %1$s?</string>
   <string name="sync_string_files">Файлы</string>
   <string name="setup_btn_connect">Соединить</string>
-  <string name="uploader_btn_upload_text">Ð\97агÑ\80Ñ\83зка</string>
-  <string name="uploader_top_message">Ð\92Ñ\8bбÑ\80аÑ\82Ñ\8c Ð¼ÐµÑ\81Ñ\82о Ð´Ð»Ñ\8f Ð·Ð°Ð³Ñ\80Ñ\83зки:</string>
-  <string name="uploader_wrn_no_account_title">Ð\90ккаÑ\83нÑ\82Ñ\8b Ð½Ðµ Ð½Ð°Ð¹Ð´ÐµÐ½Ñ\8b</string>
-  <string name="uploader_wrn_no_account_text">На вашем устройстве нет аккаунтов %1$s. Настройте сначала аккаунт.</string>
+  <string name="uploader_btn_upload_text">Ð\97агÑ\80Ñ\83зиÑ\82Ñ\8c</string>
+  <string name="uploader_top_message">Ð\92Ñ\8bбÑ\80аÑ\82Ñ\8c ÐºÐ°Ñ\82алог Ð´Ð»Ñ\8f Ð·Ð°Ð³Ñ\80Ñ\83зок:</string>
+  <string name="uploader_wrn_no_account_title">УÑ\87Ñ\91Ñ\82наÑ\8f Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8c Ð½Ðµ Ð½Ð°Ð¹Ð´ÐµÐ½Ð°</string>
+  <string name="uploader_wrn_no_account_text">На вашем устройстве нет учётных записей %1$s. Сначала нужно настроить учётную запись.</string>
   <string name="uploader_wrn_no_account_setup_btn_text">Установка</string>
   <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">Ð\9aонÑ\82енÑ\82 Ð½Ðµ Ð¿Ð¾Ð»Ñ\83Ñ\87ен. Нечего загружать.</string>
+  <string name="uploader_wrn_no_content_text">СодеÑ\80жимое Ð½Ðµ Ð¿Ð¾Ð»Ñ\83Ñ\87ено. Нечего загружать.</string>
   <string name="uploader_error_forbidden_content">%1$s не имеет доступа к опубликованным данным</string>
   <string name="uploader_info_uploading">Загрузка</string>
-  <string name="file_list_empty">Ð\92 Ñ\8dÑ\82ой Ð¿Ð°Ð¿Ðºе нет файлов.\nНовые файлы могут быть добавлены с помощью пункта меню \"Загрузить\".</string>
+  <string name="file_list_empty">Ð\92 Ñ\8dÑ\82ом ÐºÐ°Ñ\82алоге нет файлов.\nНовые файлы могут быть добавлены с помощью пункта меню \"Загрузить\".</string>
   <string name="filedetails_select_file">Нажмите на файл для отображения дополнительной информации.</string>
   <string name="filedetails_size">Размер:</string>
   <string name="filedetails_type">Тип:</string>
   <string name="filedetails_download">Скачать</string>
   <string name="filedetails_sync_file">Обновить файл</string>
   <string name="filedetails_renamed_in_upload_msg">Файл был переименован в %1$s во время загрузки</string>
+  <string name="action_share_file">Поделиться ссылкой</string>
+  <string name="action_unshare_file">Удалить ссылку</string>
   <string name="common_yes">Да</string>
   <string name="common_no">Нет</string>
   <string name="common_ok">ОК</string>
   <string name="common_cancel_download">Отменить скачивание</string>
-  <string name="common_cancel_upload">Ð\9eÑ\82мена Ð·Ð°Ð³Ñ\80Ñ\83зки</string>
+  <string name="common_cancel_upload">Ð\9eÑ\82мениÑ\82Ñ\8c Ð·Ð°Ð³Ñ\80Ñ\83зкÑ\83</string>
   <string name="common_cancel">Отмена</string>
   <string name="common_save_exit">Сохранить &amp; Выйти</string>
   <string name="common_error">Ошибка</string>
-  <string name="common_loading">Ð\97агÑ\80Ñ\83жаеÑ\82Ñ\81Ñ\8f...</string>
+  <string name="common_loading">Ð\98дÑ\91Ñ\82 Ð·Ð°Ð³Ñ\80Ñ\83зка...</string>
   <string name="common_error_unknown">Неизвестная ошибка</string>
   <string name="about_title">О программе</string>
   <string name="change_password">Сменить пароль</string>
-  <string name="delete_account">Удалить аккаунт</string>
-  <string name="create_account">Создать аккаунт</string>
+  <string name="delete_account">Удалить учётную запись</string>
+  <string name="create_account">Создать учётную запись</string>
   <string name="upload_chooser_title">Загрузить из...</string>
-  <string name="uploader_info_dirname">Ð\98мÑ\8f Ð´Ð¸Ñ\80екÑ\82оÑ\80ии</string>
+  <string name="uploader_info_dirname">Ð\98мÑ\8f ÐºÐ°Ñ\82алога</string>
   <string name="uploader_upload_in_progress_ticker">Загрузка...</string>
   <string name="uploader_upload_in_progress_content">%1$d%% загрузки %2$s</string>
-  <string name="uploader_upload_succeeded_ticker">Ð\97агÑ\80Ñ\83зка Ð¿Ñ\80оÑ\88ла Ñ\83Ñ\81пеÑ\88но</string>
+  <string name="uploader_upload_succeeded_ticker">Ð\97агÑ\80Ñ\83зка Ð·Ð°Ð²ÐµÑ\80Ñ\88ена</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="downloader_download_in_progress_ticker">Скачивание...</string>
   <string name="downloader_download_in_progress_content">%1$d%% скачивания %2$s</string>
-  <string name="downloader_download_succeeded_ticker">СкаÑ\87ивание Ð¿Ñ\80оÑ\88ло Ñ\83Ñ\81пеÑ\88но</string>
+  <string name="downloader_download_succeeded_ticker">СкаÑ\87ивание Ð·Ð°Ð²ÐµÑ\80Ñ\88ено</string>
   <string name="downloader_download_succeeded_content">%1$s успешно скачан</string>
-  <string name="downloader_download_failed_ticker">СкаÑ\87ивание Ð½Ðµ Ñ\83далась</string>
+  <string name="downloader_download_failed_ticker">СкаÑ\87ивание Ð½Ðµ Ñ\83далось</string>
   <string name="downloader_download_failed_content">Скачивание %1$s не может быть завершено</string>
-  <string name="downloader_not_downloaded_yet">Ещё не загружено</string>
-  <string name="common_choose_account">Выберите аккаунт</string>
+  <string name="downloader_not_downloaded_yet">Ещё не скачано</string>
+  <string name="common_choose_account">Выберите учётную запись</string>
   <string name="sync_fail_ticker">Синхронизация прошла неудачно</string>
   <string name="sync_fail_content">Синхронизация %1$s не может быть завершена</string>
   <string name="sync_fail_content_unauthorized">Неверный пароль для %1$s</string>
   <string name="sync_conflicts_in_favourites_ticker">Обнаружены конфликты</string>
-  <string name="sync_conflicts_in_favourites_content">%1$d файлы, которые должны быть синхронизированными не могут синхронизироваться</string>
+  <string name="sync_conflicts_in_favourites_content">%1$d файлы не могут быть синхронизированы</string>
   <string name="sync_fail_in_favourites_ticker">Не удалось синхронизировать файлы</string>
-  <string name="sync_fail_in_favourites_content">СодеÑ\80жание %1$d Ñ\84айла(ов) Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ñ\81инÑ\85Ñ\80онизиÑ\80овано (%2$d ÐºÐ¾Ð½Ñ\84ликÑ\82а(ов))</string>
+  <string name="sync_fail_in_favourites_content">СодеÑ\80жимое %1$d Ñ\84айлов Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ñ\81инÑ\85Ñ\80онизиÑ\80овано (конÑ\84ликÑ\82ов: %2$d)</string>
   <string name="sync_foreign_files_forgotten_ticker">Несколько локальных файлов были забыты</string>
-  <string name="sync_foreign_files_forgotten_content">%1$d файлы из %2$s папки не могут быть скопированы в</string>
-  <string name="sync_foreign_files_forgotten_explanation">файлы, загруженные с этого устройства, скопированы в локальную папку %1$s для предотвращения потери данных, когда отдельный файл синхронизируется с нескольких учётных записей. По причине этого изменения, все файлы, загруженные в предыдущих версиях этого приложения, были скопированы в папку %2$s. Однако, ошибка помешала завершению этой операции при синхронизации учётной записи. Вы можете либо оставить файлы как есть, или переместить их в папку %1$s и сохранить ссылку в %4$s. \nВ списке указаны локальные файлы, привязанные к файлам на сервере в папке %5$s.</string>
+  <string name="sync_foreign_files_forgotten_content">%1$d файлов из %2$s папок не могут быть скопированы в</string>
+  <string name="sync_foreign_files_forgotten_explanation">Начиная с версии 1.3.16 файлы, загруженные с этого устройства, скопированы в локальный каталог %1$s для предотвращения потери данных, когда один и тот же файл синхронизируется с нескольких учётных записей.\n\nПо причине этого изменения, все файлы, загруженные в предыдущих версиях этого приложения, были скопированы в каталог %2$s. Однако, ошибка помешала завершению этой операции при синхронизации учётной записи. Вы можете либо оставить файлы как есть и удалить ссылку на %3$s, или переместить файлы в каталог %1$s и сохранить ссылку на %4$s.\n\nНиже перечислены локальные файлы и те удалённые файлы в %5$s, с которыми они связаны.</string>
   <string name="sync_current_folder_was_removed">Каталог %1$s больше не существует</string>
   <string name="foreign_files_move">Переместить всё</string>
   <string name="foreign_files_success">Все файлы были перемещены</string>
   <string name="foreign_files_fail">Некоторые файлы не могут быть перемещены</string>
   <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">Ð\9eÑ\82Ñ\81Ñ\83Ñ\82Ñ\81Ñ\82вÑ\83еÑ\82 Ð´Ð¾Ñ\81Ñ\82аÑ\82оÑ\87ное ÐºÐ¾Ð»Ð¸Ñ\87еÑ\81Ñ\82во Ð¼ÐµÑ\81Ñ\82а Ð´Ð»Ñ\8f ÐºÐ¾Ð¿Ð¸Ñ\80ованиÑ\8f Ð²Ñ\8bделеннÑ\8bÑ\85 Ñ\84айлов Ð² Ð¿Ð°Ð¿ÐºÑ\83 %1$s. Ð¥Ð¾Ñ\82иÑ\82е Ð»Ð¸ Ð\92Ñ\8b Ð¿ереместить их в другое место?</string>
+  <string name="upload_query_move_foreign_files">Ð\9dедоÑ\81Ñ\82аÑ\82оÑ\87но Ð¼ÐµÑ\81Ñ\82а Ð´Ð»Ñ\8f ÐºÐ¾Ð¿Ð¸Ñ\80ованиÑ\8f Ð²Ñ\8bделеннÑ\8bÑ\85 Ñ\84айлов Ð² ÐºÐ°Ñ\82алог %1$s. Ð\9fереместить их в другое место?</string>
   <string name="pincode_enter_pin_code">Вставьте PIN вашего приложения</string>
-  <string name="pincode_configure_your_pin">Введите  App PIN</string>
-  <string name="pincode_configure_your_pin_explanation">ПИН-код будет запрашиваться каждый раз, когда вы запускаете приложение.</string>
-  <string name="pincode_reenter_your_pincode">Повторите App PIN</string>
+  <string name="pincode_configure_your_pin">Введите App PIN</string>
+  <string name="pincode_configure_your_pin_explanation">PIN-код будет запрашиваться при каждом запуске приложения.</string>
+  <string name="pincode_reenter_your_pincode">Повторите ввод App PIN</string>
   <string name="pincode_remove_your_pincode">Удалить App PIN</string>
-  <string name="pincode_mismatch">Ð\94ва App PIN не совпадают</string>
+  <string name="pincode_mismatch">Ð\92ведÑ\91ннÑ\8bе App PIN не совпадают</string>
   <string name="pincode_wrong">Неверный App PIN</string>
   <string name="pincode_removed">App PIN удалён</string>
   <string name="pincode_stored">App PIN сохранён</string>
-  <string name="media_notif_ticker">%1$s Ð¼Ñ\83зÑ\8bкалÑ\8cнÑ\8bй Ð¿Ñ\80оигÑ\80Ñ\8bваÑ\82елÑ\8c</string>
+  <string name="media_notif_ticker">%1$s Ð°Ñ\83диоплееÑ\80</string>
   <string name="media_state_playing">%1$s (проигрывается)</string>
   <string name="media_state_loading">%1$s (загружается)</string>
   <string name="media_event_done">%1$s воспроизведение завершено</string>
-  <string name="media_err_nothing_to_play">Ð\9dе Ð½Ð°Ð¹Ð´ÐµÐ½ Ð¼ÐµÐ´Ð¸Ð°-Ñ\84айл</string>
-  <string name="media_err_no_account">Ð\9dе Ð½Ð°Ñ\81Ñ\82Ñ\80оена Ñ\83Ñ\87Ñ\91Ñ\82наÑ\8f Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8c</string>
+  <string name="media_err_nothing_to_play">Ð\9cедиаÑ\84айлов Ð½Ðµ Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾</string>
+  <string name="media_err_no_account">УÑ\87Ñ\91Ñ\82наÑ\8f Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8c Ð½Ðµ Ð½Ð°Ñ\81Ñ\82Ñ\80оена</string>
   <string name="media_err_not_in_owncloud">Файл в неверной учётной записи</string>
   <string name="media_err_unsupported">Неподдерживаемый кодек</string>
-  <string name="media_err_io">Файл не может быть прочитан</string>
-  <string name="media_err_malformed">Файл </string>
-  <string name="media_err_timeout">Тайм Ð°Ñ\83Ñ\82 Ð¿Ñ\80и Ð²Ð¾Ñ\81пÑ\80оизведении</string>
-  <string name="media_err_invalid_progressive_playback">Ð\9dевозможно Ð²Ð¾Ñ\81пÑ\80оизвеÑ\81Ñ\82и Ñ\84айл ÐºÐ°Ðº Ð¿Ð¾Ñ\82ок</string>
-  <string name="media_err_unknown">Файл Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ð¿Ñ\80оигÑ\80ан  стандартным плеером</string>
+  <string name="media_err_io">Ð\9cедиаÑ\84айл не может быть прочитан</string>
+  <string name="media_err_malformed">Ð\9cедиаÑ\84айл Ð½ÐµÐºÐ¾Ñ\80Ñ\80екÑ\82но Ð·Ð°ÐºÐ¾Ð´Ð¸Ñ\80ован</string>
+  <string name="media_err_timeout">Ð\92Ñ\80емÑ\8f Ð¿Ð¾Ð¿Ñ\8bÑ\82ок Ð²Ð¾Ñ\81пÑ\80оизведениÑ\8f Ð²Ñ\8bÑ\88ло</string>
+  <string name="media_err_invalid_progressive_playback">Ð\9dевозможно Ð¾Ñ\80ганизоваÑ\82Ñ\8c Ð¿Ð¾Ñ\82оковÑ\83Ñ\8e Ð¿ÐµÑ\80едаÑ\87Ñ\83 Ð¼ÐµÐ´Ð¸Ð°Ñ\84айла</string>
+  <string name="media_err_unknown">Ð\9cедиаÑ\84айл Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ð¿Ñ\80оигÑ\80ан стандартным плеером</string>
   <string name="media_err_security_ex">Ошибка безопасности при воспроизведении %1$s</string>
   <string name="media_err_io_ex">Ошибка ввода при воспроизведении %1$s</string>
   <string name="media_err_unexpected">Неожиданная ошибка при воспроизведении %1$s</string>
   <string name="auth_nossl_plain_ok_title">Защищённое соединение недоступно.</string>
   <string name="auth_connection_established">Соединение установлено</string>
   <string name="auth_testing_connection">Тестирование соединения...</string>
-  <string name="auth_not_configured_title">Ð\9dевеÑ\80наÑ\8f ÐºÐ¾Ð½Ñ\84игÑ\83Ñ\80аÑ\86иÑ\8f Ñ\81еÑ\80веÑ\80</string>
-  <string name="auth_account_not_new">Учётная запись для такого пользователя и сервера уже существует на устройстве</string>
-  <string name="auth_account_not_the_same">Введённый пользователь не соответсвует пользователю учётной записи</string>
+  <string name="auth_not_configured_title">Ð\9aонÑ\84игÑ\83Ñ\80аÑ\86иÑ\8f Ñ\81еÑ\80веÑ\80а Ð·Ð°Ð´Ð°Ð½Ð° Ð½ÐµÐ²ÐµÑ\80но</string>
+  <string name="auth_account_not_new">Учётная запись такого пользователя и сервера уже существует на устройстве</string>
+  <string name="auth_account_not_the_same">Введённый пользователь не соответствует этой учётной записи</string>
   <string name="auth_unknown_error_title">Произошла неизвестная ошибка!</string>
   <string name="auth_unknown_host_title">Невозможно найти сервер</string>
-  <string name="auth_incorrect_path_title">ЭкземплÑ\8fÑ\80 Ñ\81ервер не найден</string>
+  <string name="auth_incorrect_path_title">Сервер не найден</string>
   <string name="auth_timeout_title">Сервер слишком долго не отвечает</string>
   <string name="auth_incorrect_address_title">Неверный URL</string>
   <string name="auth_ssl_general_error_title">Ошибка инициализации SSL</string>
-  <string name="auth_ssl_unverified_server_title">Невозможно проверить сертификат SSL сервера</string>
+  <string name="auth_ssl_unverified_server_title">Невозможно проверить SSL-сертификат сервера</string>
   <string name="auth_bad_oc_version_title">Неизвестная версия сервера</string>
   <string name="auth_wrong_connection_title">Невозможно установить соединение</string>
   <string name="auth_secure_connection">Защищённое соединение установлено</string>
   <string name="auth_unauthorized">Неверное имя пользователя или пароль</string>
   <string name="auth_oauth_error">Ошибка авторизации</string>
-  <string name="auth_oauth_error_access_denied">Сервер отказал в доступе</string>
-  <string name="auth_wtf_reenter_URL">Ð\9dеожиданнÑ\8bй Ð¾Ñ\82веÑ\82; Ð¿Ð¾Ð¶Ð°Ð»Ñ\83йÑ\81Ñ\82а, Ð²Ð²ÐµÐ´Ð¸Ñ\82е Ð°Ð´Ñ\80еÑ\81 Ñ\81еÑ\80веÑ\80а ÐµÑ\89Ñ\91 Ñ\80аз</string>
-  <string name="auth_expired_oauth_token_toast">Ваша авторизация истекла. Пожалуйста, авторизуйтесь снова</string>
+  <string name="auth_oauth_error_access_denied">СеÑ\80веÑ\80 Ð°Ð²Ñ\82оÑ\80изаÑ\86ии Ð¾Ñ\82казал Ð² Ð´Ð¾Ñ\81Ñ\82Ñ\83пе</string>
+  <string name="auth_wtf_reenter_URL">Неожиданный ответ; введите адрес сервера ещё раз</string>
+  <string name="auth_expired_oauth_token_toast">Время авторизации истекло. Пожалуйста, авторизуйтесь снова</string>
   <string name="auth_expired_basic_auth_toast">Пожалуйста, введите пароль</string>
-  <string name="auth_expired_saml_sso_token_toast">Ваша сессия истекла. Пожалуйста, подключитесь снова</string>
+  <string name="auth_expired_saml_sso_token_toast">Время сессии истекло. Пожалуйста, подключитесь снова</string>
   <string name="auth_connecting_auth_server">Подключение к серверу аутентификации...</string>
   <string name="auth_unsupported_auth_method">Сервер не поддерживает выбранный метод аутентификации</string>
-  <string name="auth_unsupported_multiaccount">%1$s не поддерживает множественные учётные записи</string>
+  <string name="auth_unsupported_multiaccount">%1$s не поддерживает сразу несколько учётных записей</string>
   <string name="fd_keep_in_sync">Обновлять файл</string>
   <string name="common_rename">Переименовать</string>
   <string name="common_remove">Удалить</string>
-  <string name="confirmation_remove_alert">Ð\92Ñ\8b Ð² Ñ\81амом Ð´ÐµÐ»Ðµ хотите удалить %1$s ?</string>
-  <string name="confirmation_remove_folder_alert">Вы действительно хотите удалить %1$s  и его содержимое ?</string>
+  <string name="confirmation_remove_alert">Ð\92Ñ\8b Ð´ÐµÐ¹Ñ\81Ñ\82виÑ\82елÑ\8cно хотите удалить %1$s ?</string>
+  <string name="confirmation_remove_folder_alert">Вы действительно хотите удалить %1$s и его содержимое?</string>
   <string name="confirmation_remove_local">Только локально</string>
   <string name="confirmation_remove_folder_local">Только локальные данные</string>
   <string name="confirmation_remove_remote">Удалить с сервера</string>
-  <string name="confirmation_remove_remote_and_local">Ð\98 Ñ\83далённо и локально</string>
-  <string name="remove_success_msg">Успешное удаление</string>
-  <string name="remove_fail_msg">Удаление Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ð·Ð°Ð²ÐµÑ\80Ñ\88ено</string>
+  <string name="confirmation_remove_remote_and_local">Удалённо и локально</string>
+  <string name="remove_success_msg">Удаление завершено</string>
+  <string name="remove_fail_msg">Ð\9eÑ\88ибка Ñ\83далениÑ\8f</string>
   <string name="rename_dialog_title">Введите новое имя</string>
   <string name="rename_local_fail_msg">Локальная копия не может быть переименована; попробуйте другое имя</string>
   <string name="rename_server_fail_msg">Переименование не может быть завершено</string>
   <string name="sync_file_fail_msg">Удаленный файл не может быть проверен</string>
   <string name="sync_file_nothing_to_do_msg">Содержимое файла уже синхронизировано</string>
-  <string name="create_dir_fail_msg">Ð\94иÑ\80екÑ\82оÑ\80иÑ\8f Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ñ\81оздана</string>
-  <string name="filename_forbidden_characters">Ð\97апÑ\80еÑ\89Ñ\91нные символы: / \\ &lt; &gt; : \" | ? *</string>
+  <string name="create_dir_fail_msg">Ð\9aаÑ\82алог Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ñ\81оздан</string>
+  <string name="filename_forbidden_characters">Ð\9dедопÑ\83Ñ\81Ñ\82имые символы: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Подождите немного</string>
-  <string name="filedisplay_unexpected_bad_get_content">Ð\9dеизвеÑ\81Ñ\82наÑ\8f Ð¾Ñ\88ибка; Ð¿Ð¾Ð¿Ñ\80обÑ\83йÑ\82е Ð´Ñ\80Ñ\83гое Ð¿Ñ\80иложение Ð´Ð»Ñ\8f Ð²Ñ\8bбоÑ\80а Ñ\84айла</string>
+  <string name="filedisplay_unexpected_bad_get_content">Ð\9dеизвеÑ\81Ñ\82наÑ\8f Ð¾Ñ\88ибка; Ð²Ñ\8bбеÑ\80иÑ\82е Ñ\8dÑ\82оÑ\82 Ñ\84айл Ð¸Ð· Ð´Ñ\80Ñ\83гого Ð¿Ñ\80иложениÑ\8f</string>
   <string name="filedisplay_no_file_selected">Файлы не выбраны</string>
-  <string name="oauth_check_onoff">Подключать через oAuth2</string>
+  <string name="activity_chooser_title">Отправить ссылку...</string>
+  <string name="oauth_check_onoff">Войти через oAuth2</string>
   <string name="oauth_login_connection">Подключение к серверу oAuth2...</string>
   <string name="ssl_validator_header">Подлинность сайта не может быть проверена</string>
   <string name="ssl_validator_reason_cert_not_trusted">- Сертификат сервера не является доверенным</string>
   <string name="ssl_validator_reason_cert_expired">- Срок действия сертификата сервера истёк</string>
-  <string name="ssl_validator_reason_cert_not_yet_valid">- Сертификат сервера слишком новый</string>
-  <string name="ssl_validator_reason_hostname_not_verified">- Адрес не совпадает с именем в сертификате</string>
-  <string name="ssl_validator_question">Ð\92Ñ\81е-Ñ\80авно Ð´Ð¾Ð²ÐµÑ\80Ñ\8fÑ\82Ñ\8c Ð´Ð°Ð½Ð½Ð¾Ð¼Ñ\83 Ñ\81еÑ\80Ñ\82иÑ\84икаÑ\82Ñ\83?</string>
+  <string name="ssl_validator_reason_cert_not_yet_valid">- Срок действия сертификата сервера ещё не начался</string>
+  <string name="ssl_validator_reason_hostname_not_verified">- URL не совпадает с именем сервера в сертификате</string>
+  <string name="ssl_validator_question">Ð\92Ñ\8b Ñ\85оÑ\82иÑ\82е Ð´Ð¾Ð²ÐµÑ\80Ñ\8fÑ\82Ñ\8c Ð´Ð°Ð½Ð½Ð¾Ð¼Ñ\83 Ñ\81еÑ\80Ñ\82иÑ\84икаÑ\82Ñ\83 Ð² Ð»Ñ\8eбом Ñ\81лÑ\83Ñ\87ае?</string>
   <string name="ssl_validator_not_saved">Сертификат не может быть сохранён</string>
-  <string name="ssl_validator_btn_details_see">Ð\94еÑ\82али</string>
-  <string name="ssl_validator_btn_details_hide">СпÑ\80Ñ\8fÑ\82ать</string>
-  <string name="ssl_validator_label_subject">Ð\92Ñ\8bдано Ð´Ð»Ñ\8f:</string>
-  <string name="ssl_validator_label_issuer">Ð\92Ñ\8bдан:</string>
+  <string name="ssl_validator_btn_details_see">Ð\9fодÑ\80обно</string>
+  <string name="ssl_validator_btn_details_hide">СкÑ\80Ñ\8bть</string>
+  <string name="ssl_validator_label_subject">Ð\9aомÑ\83 Ð²Ñ\8bдано:</string>
+  <string name="ssl_validator_label_issuer">Ð\9aем Ð²Ñ\8bдано:</string>
   <string name="ssl_validator_label_CN">Имя:</string>
   <string name="ssl_validator_label_O">Организация:</string>
   <string name="ssl_validator_label_OU">Организационное подразделение:</string>
   <string name="ssl_validator_label_C">Страна:</string>
-  <string name="ssl_validator_label_ST">СÑ\82аÑ\82Ñ\83Ñ\81:</string>
+  <string name="ssl_validator_label_ST">ШÑ\82аÑ\82:</string>
   <string name="ssl_validator_label_L">Местонахождение:</string>
   <string name="ssl_validator_label_validity">Срок действия:</string>
-  <string name="ssl_validator_label_validity_from">Ð\9eÑ\82:</string>
-  <string name="ssl_validator_label_validity_to">Ð\94о:</string>
+  <string name="ssl_validator_label_validity_from">Ð\98з:</string>
+  <string name="ssl_validator_label_validity_to">Ð\92:</string>
   <string name="ssl_validator_label_signature">Подпись:</string>
   <string name="ssl_validator_label_signature_algorithm">Алгоритм:</string>
   <string name="placeholder_sentence">Это заполнитель</string>
   <string name="placeholder_filename">placeholder.txt</string>
   <string name="placeholder_filetype">Изображение PNG</string>
-  <string name="placeholder_filesize">389 KB</string>
+  <string name="placeholder_filesize">389 КБ</string>
   <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
   <string name="placeholder_media_time">12:23:45</string>
-  <string name="instant_upload_on_wifi">Загружать изображения только через WiFi</string>
+  <string name="instant_upload_on_wifi">Загружать изображения только через Wi-Fi</string>
   <string name="instant_upload_path">/InstantUpload</string>
   <string name="conflict_title">Конфликт обновления</string>
-  <string name="conflict_message">УдаленнÑ\8bй Ñ\84айл %s Ð½Ðµ Ñ\81инÑ\85Ñ\80онизиÑ\80ован Ñ\81 Ð»Ð¾ÐºÐ°Ð»Ñ\8cнÑ\8bм. Ð\97авеÑ\80Ñ\88ение Ð¿Ñ\80иведеÑ\82 Ðº Ð·Ð°Ð¼ÐµÐ½Ðµ Ñ\81одеÑ\80жаниÑ\8f файла на сервере.</string>
-  <string name="conflict_keep_both">Ð\9eÑ\81Ñ\82авить оба</string>
+  <string name="conflict_message">УдаленнÑ\8bй Ñ\84айл %s Ð½Ðµ Ñ\81инÑ\85Ñ\80онизиÑ\80ован Ñ\81 Ð»Ð¾ÐºÐ°Ð»Ñ\8cнÑ\8bм. Ð\9fÑ\80одолжение Ð¿Ñ\80иведеÑ\82 Ðº Ð·Ð°Ð¼ÐµÐ½Ðµ Ñ\81одеÑ\80жимого файла на сервере.</string>
+  <string name="conflict_keep_both">СоÑ\85Ñ\80анить оба</string>
   <string name="conflict_overwrite">Заменить</string>
   <string name="conflict_dont_upload">Не загружать</string>
   <string name="preview_image_description">Предпросмотр</string>
-  <string name="preview_image_error_unknown_format">ЭÑ\82о Ð¸Ð·Ð¾Ð±Ñ\80ажение Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ð¾Ñ\82обÑ\80ажено</string>
-  <string name="error__upload__local_file_not_copied">%1$s не может быть скопирован в %2$s локальною папку</string>
-  <string name="actionbar_failed_instant_upload">Ð\91Ñ\8bÑ\81Ñ\82Ñ\80аÑ\8f Ð·Ð°Ð³Ñ\80Ñ\83зка Ð½Ðµ Ñ\83далаÑ\81Ñ\8c</string>
-  <string name="failed_upload_headline_text">Ð\91Ñ\8bÑ\81Ñ\82Ñ\80Ñ\8bе Ð·Ð°Ð³Ñ\80Ñ\83зки Ð½Ðµ Ñ\83далиÑ\81Ñ\8c</string>
-  <string name="failed_upload_headline_hint">СпиÑ\81ок Ð²Ñ\81еÑ\85 Ð½ÐµÑ\83даÑ\87нÑ\8bÑ\85 Ð·Ð°Ð³Ñ\80Ñ\83зок</string>
+  <string name="preview_image_error_unknown_format">ЭÑ\82о Ð¸Ð·Ð¾Ð±Ñ\80ажение Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ð¿Ð¾ÐºÐ°Ð·Ð°но</string>
+  <string name="error__upload__local_file_not_copied">%1$s не может быть скопирован в локальный каталог %2$s</string>
+  <string name="actionbar_failed_instant_upload">Сбой Ð½ÐµÐ¼ÐµÐ´Ð»ÐµÐ½Ð½Ð¾Ð¹ Ð·Ð°Ð³Ñ\80Ñ\83зки</string>
+  <string name="failed_upload_headline_text">Сбой Ð½ÐµÐ¼ÐµÐ´Ð»ÐµÐ½Ð½Ð¾Ð¹ Ð·Ð°Ð³Ñ\80Ñ\83зки</string>
+  <string name="failed_upload_headline_hint">Сводка Ð¿Ð¾ Ð²Ñ\81ем Ñ\81бойнÑ\8bм Ð½ÐµÐ¼ÐµÐ´Ð»ÐµÐ½Ð½Ñ\8bм Ð·Ð°Ð³Ñ\80Ñ\83зкам</string>
   <string name="failed_upload_all_cb">Выбрать всё</string>
   <string name="failed_upload_headline_retryall_btn">Ещё раз попробовать всё выделенное</string>
-  <string name="failed_upload_headline_delete_all_btn">УдалиÑ\82Ñ\8c Ð²Ñ\81Ñ\91| Ð²Ñ\8bбÑ\80анное Ð¸Ð· Ð¾Ñ\87еÑ\80еди Ð·Ð°Ð³Ñ\80Ñ\83зки</string>
-  <string name="failed_upload_retry_text">Ð\9fопÑ\80обоваÑ\82Ñ\8c ÐµÑ\89Ñ\91 Ñ\80аз Ð·Ð°Ð³Ñ\80Ñ\83зиÑ\82Ñ\8c Ð¸Ð·Ð¾Ð±Ñ\80ажение</string>
+  <string name="failed_upload_headline_delete_all_btn">Удалить выбранное из очереди загрузки</string>
+  <string name="failed_upload_retry_text">попÑ\80обоваÑ\82Ñ\8c ÐµÑ\89Ñ\91 Ñ\80аз Ð·Ð°Ð³Ñ\80Ñ\83зиÑ\82Ñ\8c Ð¸Ð·Ð¾Ð±Ñ\80ажение:</string>
   <string name="failed_upload_load_more_images">Загрузить больше картинок</string>
-  <string name="failed_upload_retry_do_nothing_text">Ничего не делать, если не в сети</string>
-  <string name="failed_upload_failure_text">Сообщение об ошибке</string>
-  <string name="failed_upload_quota_exceeded_text">Проверьте настройки сервера, возможно ваш лимит превышен</string>
+  <string name="failed_upload_retry_do_nothing_text">Ничего не делать, если нет подключения к сети</string>
+  <string name="failed_upload_failure_text">Сообщение об ошибке:</string>
+  <string name="failed_upload_quota_exceeded_text">Проверьте настройки сервера, возможно ваш лимит исчерпан</string>
+  <string name="share_link_no_support_share_api">Механизм общего доступа не включен на вашем сервере. Свяжитесь с администратором.</string>
+  <string name="share_link_file_no_exist">Невозможно предоставить доступ к этому файлу или каталогу. Убедитесь, что он существует</string>
+  <string name="share_link_file_error">Ошибка предоставления общего доступа к этому файлу или каталогу</string>
+  <string name="unshare_link_file_error">Ошибка удаления общего доступа к этому файлу или каталогу</string>
 </resources>
index 59a8531..7f0cf88 100644 (file)
@@ -12,7 +12,6 @@
   <string name="prefs_instant_upload">ක්‍ෂණික උඩුගත කිරීම් සක්‍රිය කරන්න</string>
   <string name="prefs_instant_upload_summary">කැමරාවෙන් ගත් රූප ක්‍ෂණිකව උඩුගත කරන්න</string>
   <string name="prefs_help">උදව්</string>
-  <string name="auth_host_url">සේවාදායකයේ ලිපිනය</string>
   <string name="auth_username">පරිශීලක නම</string>
   <string name="auth_password">මුර පදය</string>
   <string name="sync_string_files">ගොනු</string>
index b598dfc..0b17370 100644 (file)
@@ -28,8 +28,9 @@
   <string name="prefs_feedback">Spätná väzba</string>
   <string name="prefs_imprint">Podmienky používania</string>
   <string name="recommend_subject">Skúste %1$s na vašom telefóne!</string>
+  <string name="recommend_text">Chcem vás pozvať na používanie %1$s na vašom smartphone!\nNa stiahnutie tu: %2$s</string>
   <string name="auth_check_server">Skontrolovať Server</string>
-  <string name="auth_host_url">Adresa servera</string>
+  <string name="auth_host_url">Adresa servera https://...</string>
   <string name="auth_username">Používateľské meno</string>
   <string name="auth_password">Heslo</string>
   <string name="auth_register">Ste nový v %1$s?</string>
@@ -54,6 +55,7 @@
   <string name="filedetails_download">Stiahnuť</string>
   <string name="filedetails_sync_file">Obnoviť súbor</string>
   <string name="filedetails_renamed_in_upload_msg">Súbor bol premenovaný na %1$s počas nahrávania</string>
+  <string name="action_share_file">Zdieľať linku</string>
   <string name="common_yes">Áno</string>
   <string name="common_no">Nie</string>
   <string name="common_ok">OK</string>
@@ -94,6 +96,7 @@
   <string name="sync_foreign_files_forgotten_ticker">Niektoré lokálne súbory boli zabudnuté</string>
   <string name="sync_foreign_files_forgotten_content">%1$d súborov z priečinka %2$s nemožno skopírovať do</string>
   <string name="sync_foreign_files_forgotten_explanation">Od verzie 1.3.16 sú súbory nahrané z tohoto zariadenia, skopírovné do lokálneho priečinka %1$s, aby sa zabránilo strate dát, keď je jeden súbor synchronizovný s viacerými účtami.\n\nPre túto zmenu, všetky súbory nahraté v predchádzajúcich verziách tejto aplikácie boli skopírované do priečinka %2$s. Je nám to ľúto, chyba zabránila dokončeniu tejto operácie počas synchronizácie účtu. Súbor(y) môžete ponechať v súčasnom stave a zmazať odkaz na %3$s, alebo presunúť súbor(y) do priečinka %1$s a zachovať odkaz na %4$s.\n\nĎalej lokálny súbor(y) a vzdialený súbor(y) sú spojené v priečinku %5$s.</string>
+  <string name="sync_current_folder_was_removed">Priečinok %1$s už existuje</string>
   <string name="foreign_files_move">Premiestniť všetko</string>
   <string name="foreign_files_success">Všetky súbory boli premiestnené</string>
   <string name="foreign_files_fail">Niektoré súbory nebolo možné premiestniť</string>
   <string name="sync_file_fail_msg">Vzdialený súbor nemohol byť prekontrolovaný</string>
   <string name="sync_file_nothing_to_do_msg">Obsah súboru je zosynchronizovaný</string>
   <string name="create_dir_fail_msg">Priečinok nie je možné vytvoriť</string>
+  <string name="filename_forbidden_characters">Zakázané znaky: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Počkať chvíľu</string>
   <string name="filedisplay_unexpected_bad_get_content">Neočakávaný problém; skúste vybrať súbor inou aplikáciou</string>
   <string name="filedisplay_no_file_selected">Nebol vybraný súbor</string>
+  <string name="oauth_check_onoff">Prihlásiť sa z oAuth2</string>
   <string name="oauth_login_connection">Pripájam sa na oAuth2 server…</string>
   <string name="ssl_validator_header">Identitu stránky nemožno overiť</string>
   <string name="ssl_validator_reason_cert_not_trusted">- Certifikát servera nie je overený</string>
   <string name="preview_image_description">Ukážka obrazu</string>
   <string name="preview_image_error_unknown_format">Obraz nemôže byť zobrazený</string>
   <string name="error__upload__local_file_not_copied">%1$s nemožno skopírovať do lokálneho priečinka %2$s</string>
+  <string name="actionbar_failed_instant_upload">Okamžité odoslanie zlyhalo</string>
   <string name="failed_upload_headline_text">Zlyhané instantné nahratia</string>
   <string name="failed_upload_headline_hint">Zhrnutie všetkých zlyhaných nahratí</string>
   <string name="failed_upload_all_cb">vybrať všetko</string>
index c757504..1eb12a4 100644 (file)
@@ -1,2 +1,7 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<resources/>
+<resources>
+  <string name="actionbar_settings">Nastavenia</string>
+  <string name="prefs_category_general">Všeobecné</string>
+  <string name="filedetails_download">Stiahnuť</string>
+  <string name="common_cancel">Zrušiť</string>
+</resources>
index 362a5fb..d61395a 100644 (file)
@@ -30,7 +30,7 @@
   <string name="recommend_subject">Preizkusi %1$s na pametnem telefonu!</string>
   <string name="recommend_text">Želim ti predstaviti program %1$s za pametni telefon!\nPrejmeš ga lahko na: %2$s</string>
   <string name="auth_check_server">Preveri strežnik</string>
-  <string name="auth_host_url">Naslov strežnika</string>
+  <string name="auth_host_url">Naslov strežnika https://…</string>
   <string name="auth_username">Uporabniško ime</string>
   <string name="auth_password">Geslo</string>
   <string name="auth_register">Ali ste novi uporabnik sistema %1$s?</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">Prejmi</string>
   <string name="filedetails_sync_file">Osveži datoteko</string>
   <string name="filedetails_renamed_in_upload_msg">Datoteka je bila med nalaganjem preimenovana v %1$s</string>
+  <string name="action_share_file">Povezava za souporabo</string>
+  <string name="action_unshare_file">Odstrani možnost souporabe</string>
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">V redu</string>
@@ -94,6 +96,7 @@
   <string name="sync_fail_in_favourites_content">Vsebine %1$d datotek ni bilo mogoče uskladiti (zaznanih je %2$d sporov)</string>
   <string name="sync_foreign_files_forgotten_ticker">Nekatere krajevne datoteke so spregledane</string>
   <string name="sync_foreign_files_forgotten_content">Skupno %1$d datotek iz mape %2$s ni mogoče kopirati v</string>
+  <string name="sync_foreign_files_forgotten_explanation">Od različice 1.3.16 dalje so datoteke, poslane iz te naprave, kopirane v krajevno mapo %1$s. S tem je preprečena izguba podatkov, kadar poteka usklajevanje ene datoteke z več računi.\n\nZaradi te spremembe so vse datoteke, poslane pred namestitvijo te različice programa, kopirane v mapo %2$s. Med usklajevanjem računov je prišlo do napake, ki je preprečila končanje tega opravila. Datoteke lahko pustite nespremenjene in odstranite povezavo do %3$s ali jih premaknete v mapo %1$s in ohranite povezavo do %4$s.\n\nNavedene so krajevne in oddaljene datoteke in mesto %5$s, kje so bile povezane.</string>
   <string name="sync_current_folder_was_removed">Mapa %1$s ne obstaja več</string>
   <string name="foreign_files_move">Premakni vse</string>
   <string name="foreign_files_success">Vse datoteke so uspešno premaknjene na novo mesto</string>
   <string name="media_err_security_ex">Prišlo je do varnostne napake med predvajanjem %1$s</string>
   <string name="media_err_io_ex">Prišlo je do napake vhoda med predvajanjem %1$s</string>
   <string name="media_err_unexpected">Prišlo je do nepričakovane napake med predvajanjem %1$s</string>
+  <string name="media_rewind_description">Vrni nazaj</string>
   <string name="media_play_pause_description">Gumb za predvajanje in premor</string>
   <string name="media_forward_description">Gumb za hitro predvajanje naprej</string>
   <string name="auth_trying_to_login">Poskus prijave …</string>
   <string name="auth_testing_connection">Preizkušanje povezave ...</string>
   <string name="auth_not_configured_title">Napačno oblikovane nastavitve strežnika</string>
   <string name="auth_account_not_new">Na napravi račun za istega uporabnika in strežnik že obstaja</string>
+  <string name="auth_account_not_the_same">Vpisan uporabnik ni lastnik tega računa</string>
   <string name="auth_unknown_error_title">Prišlo je do neznane napake!</string>
   <string name="auth_unknown_host_title">Gostitelja ni mogoče najti</string>
   <string name="auth_incorrect_path_title">Primerka strežnika ni mogoče najti</string>
   <string name="auth_expired_basic_auth_toast">Vnesite trenutno geslo</string>
   <string name="auth_expired_saml_sso_token_toast">Seja je potekla. Ponovno je treba vzpostaviti povezavo.</string>
   <string name="auth_connecting_auth_server">Poteka povezovanje z overitvenim strežnikom ...</string>
+  <string name="auth_unsupported_auth_method">Strežnik ne podpira tega načina overitve</string>
   <string name="auth_unsupported_multiaccount">%1$s ne omogoča podpore več računom</string>
   <string name="fd_keep_in_sync">Datoteka naj bo posodobljena</string>
   <string name="common_rename">Preimenuj</string>
   <string name="wait_a_moment">Počakajte trenutek ...</string>
   <string name="filedisplay_unexpected_bad_get_content">Prišlo je do nepričakovane napake. Poskusite datoteko izbrati z drugim programom.</string>
   <string name="filedisplay_no_file_selected">Ni izbranih datotek</string>
+  <string name="activity_chooser_title">Pošlji povezavo ...</string>
   <string name="oauth_check_onoff">Prijava  z oAuth2</string>
   <string name="oauth_login_connection">Poteka povezovanje s strežnikom oAuth2 ...</string>
   <string name="ssl_validator_header">Istovetnosti strani ni mogoče preveriti</string>
   <string name="preview_image_description">Predogled slike</string>
   <string name="preview_image_error_unknown_format">Te slike ni mogoče prikazati</string>
   <string name="error__upload__local_file_not_copied">Datoteke %1$s ni mogoče kopirati v krajevno mapo %2$s.</string>
+  <string name="actionbar_failed_instant_upload">Spodletelo takojšnje pošiljanje</string>
+  <string name="failed_upload_headline_text">Spodletela takojšnja pošiljanja</string>
+  <string name="failed_upload_headline_hint">Povzetek vseh spodletelih takojšnjih pošiljanj</string>
   <string name="failed_upload_all_cb">izberi vse</string>
   <string name="failed_upload_headline_retryall_btn">vse izbrane poskusi znova</string>
+  <string name="failed_upload_headline_delete_all_btn">izbriši izbrane iz vrste za pošiljanje</string>
+  <string name="failed_upload_retry_text">poskusi poslati sliko:</string>
   <string name="failed_upload_load_more_images">Naloži več slik</string>
+  <string name="failed_upload_retry_do_nothing_text">ne pošlji takoj, saj je povezava v omrežje ni dejavna</string>
   <string name="failed_upload_failure_text">Sporočilo o napaki:</string>
   <string name="failed_upload_quota_exceeded_text">Preverite nastavitve strežnika. Morda je presežena vrednost količinske omejitve.</string>
+  <string name="share_link_file_no_exist">Ni mogoče omogočiti souporabe te datoteke ali mape. Prepričajte se, da obstaja ...</string>
+  <string name="share_link_file_error">Prišlo je do napake med poskusom omogočanja souporabe te datoteke ali mape</string>
+  <string name="unshare_link_file_error">Prišlo je do napake med poskusom odstranjevanja souporabe te datoteke ali mape</string>
 </resources>
index 03b08ac..c460e82 100644 (file)
@@ -2,21 +2,53 @@
 <resources>
   <string name="actionbar_upload">Ngarko</string>
   <string name="actionbar_upload_files">Skedarët</string>
+  <string name="actionbar_mkdir">Krijo kartelë</string>
   <string name="actionbar_settings">Parametrat</string>
   <string name="prefs_category_general">Përgjithshme</string>
   <string name="prefs_category_more">Më tepër</string>
+  <string name="prefs_accounts">Llogarit</string>
   <string name="prefs_help">Ndihmë</string>
+  <string name="prefs_imprint">Stampoj</string>
   <string name="auth_username">Përdoruesi</string>
   <string name="auth_password">Kodi</string>
   <string name="sync_string_files">Skedarët</string>
+  <string name="setup_btn_connect">Lidhu</string>
   <string name="uploader_btn_upload_text">Ngarko</string>
+  <string name="uploader_wrn_no_account_title">Nuk u gjend asnjë llogari</string>
+  <string name="uploader_wrn_no_account_text">Nuk ka %1$s llogari në pajisjen tuaj. Ju lutemi të krijojnë një llogari të parë.</string>
+  <string name="uploader_wrn_no_account_setup_btn_text">Ndërto</string>
+  <string name="uploader_wrn_no_account_quit_btn_text">Dil</string>
+  <string name="uploader_info_uploading">Ngarko</string>
+  <string name="filedetails_select_file">Trokitje e lehtë në një dokument për të shfaqur informacion shtesë.</string>
+  <string name="filedetails_size">Dimensioni:</string>
+  <string name="filedetails_type">Tipi:</string>
+  <string name="filedetails_created">Krijuar:</string>
+  <string name="filedetails_modified">Modifikuar:</string>
   <string name="filedetails_download">Shkarko</string>
   <string name="common_yes">Po</string>
   <string name="common_no">Jo</string>
+  <string name="common_ok">Ok</string>
   <string name="common_cancel_upload">Anulo ngarkimin</string>
   <string name="common_cancel">Anulo</string>
   <string name="common_error">Veprim i gabuar</string>
+  <string name="common_error_unknown">Gabim panjohur</string>
+  <string name="about_title">Rreth</string>
   <string name="change_password">Ndrysho fjalëkalimin</string>
+  <string name="delete_account">Fshi llogarin</string>
+  <string name="create_account">Krijo llogari</string>
+  <string name="upload_chooser_title">Ngarko nga...</string>
+  <string name="uploader_upload_in_progress_ticker">Ngarkim...</string>
+  <string name="uploader_upload_in_progress_content">%1$d%% Ngarkim %2$s</string>
+  <string name="uploader_upload_succeeded_ticker">Ngarkimi me sukses.</string>
+  <string name="uploader_upload_succeeded_content_single">%1$s u ngarkua me sukses</string>
   <string name="uploader_upload_failed_ticker">Ngarkimi dështoi</string>
+  <string name="uploader_upload_failed_content_single">Ngarkimi i %1$s nuk mund te behej</string>
+  <string name="downloader_download_in_progress_ticker">Shkarkimi...</string>
+  <string name="downloader_download_in_progress_content">%1$d%% Shkarkimi %2$s</string>
+  <string name="downloader_download_succeeded_ticker">Shkarkimi me sukses</string>
+  <string name="downloader_download_succeeded_content">%1$s u shkarkua me sukses</string>
+  <string name="downloader_download_failed_ticker">Shkarkimi dështoj</string>
+  <string name="auth_secure_connection">Lidhja e Sigurt vendos</string>
   <string name="common_rename">Riemërto</string>
+  <string name="common_remove">Hiq</string>
 </resources>
index 663c462..eefd16d 100644 (file)
@@ -2,16 +2,52 @@
 <resources>
   <string name="actionbar_upload">Pošalji</string>
   <string name="actionbar_upload_files">Fajlovi</string>
+  <string name="actionbar_mkdir">Novi folder</string>
   <string name="actionbar_settings">Podešavanja</string>
+  <string name="actionbar_see_details">Detaljnije</string>
+  <string name="prefs_category_general">Opšte</string>
+  <string name="prefs_accounts">Nalozi</string>
+  <string name="prefs_manage_accounts">Upravljaj nalozima</string>
   <string name="prefs_help">Pomoć</string>
   <string name="auth_username">Korisničko ime</string>
   <string name="auth_password">Lozinka</string>
   <string name="sync_string_files">Fajlovi</string>
   <string name="uploader_btn_upload_text">Pošalji</string>
+  <string name="uploader_wrn_no_account_title">Nalog nije nađen</string>
+  <string name="uploader_info_uploading">Šalje se</string>
+  <string name="filedetails_size">Veličina:</string>
+  <string name="filedetails_type">Tip:</string>
   <string name="filedetails_download">Preuzmi</string>
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_cancel">Otkaži</string>
   <string name="common_error">Greška</string>
   <string name="change_password">Izmeni lozinku</string>
+  <string name="delete_account">Ukloni nalog</string>
+  <string name="create_account">Novi nalog</string>
+  <string name="uploader_upload_in_progress_ticker">Otpremanje...</string>
+  <string name="uploader_upload_succeeded_ticker">Uspešno otpremljeno</string>
+  <string name="uploader_upload_failed_ticker">Otpremanje nije uspelo</string>
+  <string name="downloader_download_in_progress_ticker">Preuzimanje...</string>
+  <string name="downloader_download_succeeded_ticker">Uspešno preuzeto</string>
+  <string name="downloader_download_failed_ticker">Preuzimanje nije uspelo</string>
+  <string name="common_choose_account">Odaberite nalog</string>
+  <string name="auth_no_net_conn_title">Nema konekcije</string>
+  <string name="auth_nossl_plain_ok_title">Sigurna konekcija nije dostupna.</string>
+  <string name="auth_connection_established">Konekcija uspostavljena</string>
+  <string name="common_rename">Preimenij</string>
+  <string name="common_remove">Ukloni</string>
+  <string name="confirmation_remove_alert">Da li želite da uklonite %1$s ?</string>
+  <string name="remove_success_msg">Uklanjanje je uspelo</string>
+  <string name="remove_fail_msg">Uklanjanje nije uspelo</string>
+  <string name="wait_a_moment">Molim pričekajte</string>
+  <string name="ssl_validator_btn_details_see">Detaljnije</string>
+  <string name="ssl_validator_btn_details_hide">Sakrij</string>
+  <string name="ssl_validator_label_O">Organizacija:</string>
+  <string name="ssl_validator_label_C">Država:</string>
+  <string name="ssl_validator_label_L">Lokacija:</string>
+  <string name="ssl_validator_label_validity_from">Od:</string>
+  <string name="ssl_validator_label_validity_to">Za:</string>
+  <string name="ssl_validator_label_signature">Potpis:</string>
+  <string name="conflict_keep_both">Zadrži oboje</string>
 </resources>
index 446a6ee..83ce42d 100644 (file)
@@ -10,7 +10,6 @@
   <string name="prefs_accounts">Налози</string>
   <string name="prefs_instant_upload_summary">Тренутно отпремај фотографије сликане камером</string>
   <string name="prefs_help">Помоћ</string>
-  <string name="auth_host_url">Адреса сервера</string>
   <string name="auth_username">Корисничко име</string>
   <string name="auth_password">Лозинка</string>
   <string name="sync_string_files">Фајлови</string>
diff --git a/res/values-su/strings.xml b/res/values-su/strings.xml
new file mode 100644 (file)
index 0000000..c757504
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
index f527133..79c9887 100644 (file)
@@ -30,7 +30,6 @@
   <string name="recommend_subject">Försök %1$s på din smarttelefon!</string>
   <string name="recommend_text">Jag vill bjuda in dig till att anända %1$s på din smarttelefon!\nLadda ner här: %2$s</string>
   <string name="auth_check_server">Kontrollera Server</string>
-  <string name="auth_host_url">Serveradress</string>
   <string name="auth_username">Användarnamn</string>
   <string name="auth_password">Lösenord</string>
   <string name="auth_register">Ny på %1$s?</string>
@@ -55,6 +54,7 @@
   <string name="filedetails_download">Ladda ner</string>
   <string name="filedetails_sync_file">Ladda om fil</string>
   <string name="filedetails_renamed_in_upload_msg">Filen bytte namn till %1$s under uppladdningen</string>
+  <string name="action_share_file">Dela länk</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nej</string>
   <string name="common_ok">OK</string>
   <string name="sync_file_fail_msg">Fjärrfilen kunde inte kontrolleras</string>
   <string name="sync_file_nothing_to_do_msg">Filinnehåll redan synkroniserat</string>
   <string name="create_dir_fail_msg">Mapp kunde inte skapas</string>
+  <string name="filename_forbidden_characters">Förbjudna tecken är: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Var god vänta</string>
   <string name="filedisplay_unexpected_bad_get_content">Oväntat problem; prova annat program för aktuell fil</string>
   <string name="filedisplay_no_file_selected">Ingen fil vald</string>
   <string name="preview_image_description">Förhandsvisa bild</string>
   <string name="preview_image_error_unknown_format">Denna bild kan inte visas</string>
   <string name="error__upload__local_file_not_copied">%1$s kunde inte kopieras till %2$s lokal mapp</string>
+  <string name="actionbar_failed_instant_upload">Fel vid direktuppladdning\"</string>
   <string name="failed_upload_headline_text">Misslyckades vid direktuppladdning</string>
   <string name="failed_upload_headline_hint">Sammanfattning av alla misslyckade uppladdningar</string>
   <string name="failed_upload_all_cb">välj alla</string>
index 9b888c4..2f1f51c 100644 (file)
@@ -15,7 +15,6 @@
   <string name="prefs_instant_upload">உடனடி பதிவேற்றலை இயலுமைப்படுத்துக</string>
   <string name="prefs_instant_upload_summary">கமராவினால் எடுக்கப்பட்ட படங்கள் உடனடியாக பதிவேற்றப்பட்டன</string>
   <string name="prefs_help">உதவி</string>
-  <string name="auth_host_url">சேவையக முகவரி</string>
   <string name="auth_username">பயனாளர் பெயர்</string>
   <string name="auth_password">கடவுச்சொல்</string>
   <string name="sync_string_files">கோப்புகள்</string>
index b827eda..ca33f4e 100644 (file)
@@ -3,7 +3,6 @@
   <string name="actionbar_settings">అమరికలు</string>
   <string name="prefs_category_more">మరిన్ని</string>
   <string name="prefs_help">సహాయం</string>
-  <string name="auth_host_url">సేవకి చిరునామా</string>
   <string name="auth_username">వాడుకరి పేరు</string>
   <string name="auth_password">సంకేతపదం</string>
   <string name="common_yes">అవును</string>
index 521ad4a..77451fa 100644 (file)
@@ -15,7 +15,6 @@
   <string name="prefs_instant_upload">เปิดใช้งานระบบอัพโหลดได้ทันที</string>
   <string name="prefs_instant_upload_summary">อัพโหลดรูปภาพจากกล้องขึ้นไปทันที</string>
   <string name="prefs_help">ช่วยเหลือ</string>
-  <string name="auth_host_url">ที่อยู่เซิร์ฟเวอร์</string>
   <string name="auth_username">ชื่อผู้ใช้</string>
   <string name="auth_password">รหัสผ่าน</string>
   <string name="sync_string_files">ไฟล์</string>
index 954b941..0e920b4 100644 (file)
@@ -3,11 +3,11 @@
   <string name="about_android">%1$s Android Uygulaması</string>
   <string name="about_version">sürüm %1$s</string>
   <string name="actionbar_sync">Hesabı yenile</string>
-  <string name="actionbar_upload">Dosya yükle</string>
+  <string name="actionbar_upload">Yükle</string>
   <string name="actionbar_upload_from_apps">Diğer uygulamalardan içerik</string>
   <string name="actionbar_upload_files">Dosyalar</string>
   <string name="actionbar_open_with">ile aç</string>
-  <string name="actionbar_mkdir">Klasör oluştur</string>
+  <string name="actionbar_mkdir">Dizin oluştur</string>
   <string name="actionbar_settings">Ayarlar</string>
   <string name="actionbar_see_details">Detaylar</string>
   <string name="prefs_category_general">Genel</string>
@@ -30,7 +30,7 @@
   <string name="recommend_subject">%1$s uygulamasını akıllı telefonunda dene!</string>
   <string name="recommend_text">Sana, akıllı telefonunda kullanmak üzere %1$s daveti yapıyorum!\nBuradan indirebilirsin: %2$s</string>
   <string name="auth_check_server">Sunucuyu kontrol et</string>
-  <string name="auth_host_url">Sunucu Adresi</string>
+  <string name="auth_host_url">Sunucu Adresi https://…</string>
   <string name="auth_username">Kullanıcı Adi:</string>
   <string name="auth_password">Şifre:</string>
   <string name="auth_register">%1$s senin için yeni mi?</string>
@@ -38,8 +38,8 @@
   <string name="setup_btn_connect">Bağlan</string>
   <string name="uploader_btn_upload_text">Yükle</string>
   <string name="uploader_top_message">Yükleme dizinini seçiniz:</string>
-  <string name="uploader_wrn_no_account_title">Hesap bulunamadi</string>
-  <string name="uploader_wrn_no_account_text">Cihazınızda %1$s hesabı bulunmamaktadır. Lütfen öncelikle bir hesap ayarı giriniz.</string>
+  <string name="uploader_wrn_no_account_title">Hesap bulunamadı</string>
+  <string name="uploader_wrn_no_account_text">Cihazınızda %1$s hesabı bulunmamaktadır. Lütfen öncelikle bir hesap ayarlayın.</string>
   <string name="uploader_wrn_no_account_setup_btn_text">Kurulum</string>
   <string name="uploader_wrn_no_account_quit_btn_text">Çıkış</string>
   <string name="uploader_wrn_no_content_title">Yüklenecek içerik yok</string>
@@ -47,7 +47,7 @@
   <string name="uploader_error_forbidden_content">%1$s, paylaşılan içeriğe erişim izni vermiyor</string>
   <string name="uploader_info_uploading">Yükleniyor</string>
   <string name="file_list_empty">Klasörde dosya yok. Yeni dosyalar yükle\'ye tıklayarak eklenebilir.</string>
-  <string name="filedetails_select_file">Ek bilgileri görmek için dosyaya tıklayınız.</string>
+  <string name="filedetails_select_file">Ek bilgileri görmek için dosyaya dokunun.</string>
   <string name="filedetails_size">Boyut:</string>
   <string name="filedetails_type">Tür:</string>
   <string name="filedetails_created">Oluşturulma:</string>
@@ -55,6 +55,8 @@
   <string name="filedetails_download">İndir</string>
   <string name="filedetails_sync_file">Dosyayı yenile</string>
   <string name="filedetails_renamed_in_upload_msg">Dosya adı, yükleme sırasında %1$s olarak değiştirildi</string>
+  <string name="action_share_file">Paylaşma bağlantısı</string>
+  <string name="action_unshare_file">Bağlantı paylaşımını kaldır</string>
   <string name="common_yes">Evet</string>
   <string name="common_no">Hayır</string>
   <string name="common_ok">OK</string>
   <string name="downloader_not_downloaded_yet">Henüz indirilemedi</string>
   <string name="common_choose_account">Hesap seçiniz</string>
   <string name="sync_fail_ticker">Eşitleme başarısız</string>
-  <string name="sync_fail_content">%1$s Senkronizasyonu tamamlanamadı</string>
+  <string name="sync_fail_content">%1$s eşitlemesi tamamlanamadı</string>
   <string name="sync_fail_content_unauthorized">%1$s için geçersiz parola</string>
   <string name="sync_conflicts_in_favourites_ticker">Çakışma bulundu</string>
-  <string name="sync_conflicts_in_favourites_content">%1$d korumalı senkronizasyon dosyası, senkronize edilemedi</string>
-  <string name="sync_fail_in_favourites_ticker">Korunan dosya senkronizasyonu başarısız</string>
-  <string name="sync_fail_in_favourites_content">%1$d dosya  senkronize edilemedi  (%2$d hata)</string>
+  <string name="sync_conflicts_in_favourites_content">%1$d korumalı eşitleme dosyası, eşitlenemedi</string>
+  <string name="sync_fail_in_favourites_ticker">Korunan dosya eşitlemesi başarısız</string>
+  <string name="sync_fail_in_favourites_content">%1$d dosya eşitlenemedi (%2$d çakışma)</string>
   <string name="sync_foreign_files_forgotten_ticker">Bazı yerel dosyalar unutuldu</string>
-  <string name="sync_foreign_files_forgotten_content">%1$d dosyalar  %2$s dizinine kopyalanamadı</string>
+  <string name="sync_foreign_files_forgotten_content">%1$d dosya %2$s dizinine kopyalanamadı</string>
   <string name="sync_foreign_files_forgotten_explanation">1.3.16 sürümünden sonra, bu aygıttan yüklenen dosyalar bir dosya birden fazla hesapla eşitlendiğinde veri kaybının önlenebilmesi için %1$s yerel klasörüne kopyalanır.\n\nBu değişiklikten dolayı, bu uygulamanın yüklenmiş tüm önceki sürümündeki dosyalar %2$s klasörüne kopyalandı. Ancak hesap eşitlenmesi sırasında bu işlemin tamamlanmasını engelleyen bir hata oluştu. Dosyayı/dosyaları olduğu gibi bırakabilir ve %3$s bağlantısını kaldırabilirsiniz veya dosyayı/dosyaları %1$s dizinine taşıyıp %4$s bağlantılarını koruyabilirsiniz.\n\nAşağıda listelenenler yerel dosyalar ve bağlı oldukları %5$s içerisindeki uzak dosyalardır.</string>
   <string name="sync_current_folder_was_removed">%1$s klasörü artık mevcut değil.</string>
   <string name="foreign_files_move">Tümünü taşı</string>
   <string name="media_err_security_ex">%1$s oynatılmaya çalışılırken güvenlik hatası oluştu</string>
   <string name="media_err_io_ex">%1$s oynatılmaya çalışılırken girdi hatası oluştu</string>
   <string name="media_err_unexpected">%1$s oynatılmaya çalışılırken beklenmeyen bir hata oluştu</string>
-  <string name="media_rewind_description">Başa sar butonu</string>
-  <string name="media_play_pause_description">Oynat veya duraklat butonu</string>
-  <string name="media_forward_description">Hızlı ileri butonu</string>
+  <string name="media_rewind_description">Başa sar düğmesi</string>
+  <string name="media_play_pause_description">Oynat veya duraklat düğmesi</string>
+  <string name="media_forward_description">Hızlı ileri düğmesi</string>
   <string name="auth_trying_to_login">Giriş için deneniyor</string>
   <string name="auth_no_net_conn_title">Ağ bağlantısı yok</string>
   <string name="auth_nossl_plain_ok_title">Günvenli bağlantı mevcut değil.</string>
   <string name="auth_account_not_the_same">Girilen kullanıcı bu hesabın kullanıcısı ile eşleşmiyor</string>
   <string name="auth_unknown_error_title">Bilinmeyen hata oluştu.</string>
   <string name="auth_unknown_host_title">Anabilgisayar bulunamadı</string>
-  <string name="auth_incorrect_path_title">sunucu servisi bulunamadı.</string>
+  <string name="auth_incorrect_path_title">Sunucu örneği bulunamadı.</string>
   <string name="auth_timeout_title">Sunucu çok geç cevap veriyor</string>
   <string name="auth_incorrect_address_title">Hatalı biçimlendirilmiş URL</string>
   <string name="auth_ssl_general_error_title">SSL başlatılmasında hata</string>
   <string name="rename_local_fail_msg">Yerel kopya adlandırılamaz; farklı bir ad deneyin</string>
   <string name="rename_server_fail_msg">Yeniden  adlandırılma tamamlanmadı</string>
   <string name="sync_file_fail_msg">Dosya teslim edilemedi</string>
-  <string name="sync_file_nothing_to_do_msg">Dosyalar başarıyla senkronize edildi</string>
+  <string name="sync_file_nothing_to_do_msg">Dosya içerikleri zaten eşitlenmiş</string>
   <string name="create_dir_fail_msg">Dizin oluşturulamadı</string>
   <string name="filename_forbidden_characters">Yasaklı karakterler: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Bir süre bekleyin</string>
   <string name="filedisplay_unexpected_bad_get_content">Beklenmeyen problem ; lütfen, dosya seçmek için diğer uygulamayı deneyin</string>
   <string name="filedisplay_no_file_selected">Hiçbir dosya seçilmedi</string>
+  <string name="activity_chooser_title">Bağlantıyı gönder ...</string>
   <string name="oauth_check_onoff">oAuth2 ile oturum aç</string>
   <string name="oauth_login_connection">oAuth2 sunucusuna bağlanılıyor…</string>
   <string name="ssl_validator_header">Bu sitenin sertifikası doğrulanamadı</string>
   <string name="instant_upload_on_wifi">Resimleri sadece WiFi bağlantısında yükle</string>
   <string name="instant_upload_path">/AnındaYükle</string>
   <string name="conflict_title">Çakışmayı güncelle</string>
-  <string name="conflict_message">Uzaktaki %s dosyası, yerel dosya ile senkronize edilemedi.  işleme devam etmek sunucudaki dosyanın içeriğini değiştirecektir.</string>
+  <string name="conflict_message">Uzaktaki %s dosyası, yerel dosya ile eşitlenemedi. İşleme devam etmek sunucudaki dosyanın içeriğini değiştirecektir.</string>
   <string name="conflict_keep_both">İkisini de koru</string>
   <string name="conflict_overwrite">Üzerine yaz</string>
   <string name="conflict_dont_upload">Yükleme</string>
   <string name="failed_upload_retry_do_nothing_text">anında yükleme için çevrimiçi değilsiniz, bir şey yapma</string>
   <string name="failed_upload_failure_text">Hata Mesajı:</string>
   <string name="failed_upload_quota_exceeded_text">Sunucu yapılandırmanızı kontrol edin. Kotanızı aşmış olabilirsiniz.</string>
+  <string name="share_link_no_support_share_api">Üzgünüz, paylaşım sunucunuzda etkin değil. Lütfen yöneticinizle iletişime geçin.</string>
+  <string name="share_link_file_no_exist">Bu dosya veya klasör paylaşılamıyor. Lütfen mevcut olup olmadığını denetleyin</string>
+  <string name="share_link_file_error">Bu dosya veya klasörü paylaşmaya çalışılırken bir hata oluştu</string>
+  <string name="unshare_link_file_error">Bu dosya veya klasör paylaşımı kaldırılmaya çalışılırken bir hata oluştu</string>
 </resources>
index 41798ce..16a441a 100644 (file)
@@ -9,7 +9,6 @@
   <string name="prefs_accounts">ھېساباتلار</string>
   <string name="prefs_help">ياردەم</string>
   <string name="prefs_feedback">قايتۇرما ئىنكاس</string>
-  <string name="auth_host_url">مۇلازىمېتىر ئادرىسى</string>
   <string name="auth_username">ئىشلەتكۈچى ئاتى</string>
   <string name="auth_password">ئىم</string>
   <string name="sync_string_files">ھۆججەتلەر</string>
index 749321e..d0f4dfd 100644 (file)
@@ -17,7 +17,6 @@
   <string name="prefs_help">Допомога</string>
   <string name="prefs_feedback">Зворотній зв\'язок</string>
   <string name="prefs_imprint">Відбиток</string>
-  <string name="auth_host_url">Адреса сервера</string>
   <string name="auth_username">Ім\'я користувача</string>
   <string name="auth_password">Пароль</string>
   <string name="sync_string_files">Файли</string>
@@ -39,6 +38,7 @@
   <string name="filedetails_modified">Змінено:</string>
   <string name="filedetails_download">Завантажити</string>
   <string name="filedetails_renamed_in_upload_msg">Файл був переіменований в %1$s протягом вивантаження</string>
+  <string name="action_share_file">Опублікувати посилання</string>
   <string name="common_yes">Так</string>
   <string name="common_no">Ні</string>
   <string name="common_ok">OK</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
new file mode 100644 (file)
index 0000000..c757504
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
index d5f060b..0f1c0ee 100644 (file)
   <string name="prefs_log_summary_history">Hiển thị các nhật trình đã được ghi nhận lại</string>
   <string name="prefs_log_delete_history_button">Xóa lịch sử</string>
   <string name="prefs_help">Giúp đỡ</string>
+  <string name="prefs_recommend">Giới thiệu đến bạn bè</string>
+  <string name="prefs_feedback">Phản hồi</string>
+  <string name="prefs_imprint">Đánh dấu</string>
+  <string name="recommend_subject">Thử %1$s trên smartphone của bạn!</string>
+  <string name="recommend_text">Tôi muốn mời bạn sử dụng %1$s trên smartphone của bạn!\nTải về tại đây: %2$s</string>
   <string name="auth_check_server">Kiểm tra máy chủ</string>
-  <string name="auth_host_url">Địa chỉ máy chủ</string>
+  <string name="auth_host_url">Địa chỉ máy chủ https://…</string>
   <string name="auth_username">Tên người dùng</string>
   <string name="auth_password">Mật khẩu</string>
   <string name="auth_register">Lần đầu mới đến %1$s?</string>
@@ -41,7 +46,7 @@
   <string name="uploader_wrn_no_content_text">Không có nội dung được nhận. Không có gì để tải lên.</string>
   <string name="uploader_error_forbidden_content">%1$s không cho phép truy cập vào các nội dung chia sẻ</string>
   <string name="uploader_info_uploading">Đang tải lên</string>
-  <string name="file_list_empty">Không có các tập tin trong thư mục này ⏎ tập tin mới có thể được thêm vào với tùy chọn trình đơn \"Tải lên\".</string>
+  <string name="file_list_empty">Không có tập tin trong thư mục này. tập tin mới có thể được thêm vào với tùy chọn \"Tải lên\".</string>
   <string name="filedetails_select_file">Tap vào một tập tin để hiển thị thêm thông tin</string>
   <string name="filedetails_size">Kích thước:</string>
   <string name="filedetails_type">Loại:</string>
@@ -50,6 +55,7 @@
   <string name="filedetails_download">Tải về</string>
   <string name="filedetails_sync_file">Cập nhật lại tập tin</string>
   <string name="filedetails_renamed_in_upload_msg">Tập tin đã bị đổi tên thành %1$s trong quá trình tải lên</string>
+  <string name="action_share_file">Chia sẻ liên kết</string>
   <string name="common_yes">Yes</string>
   <string name="common_no">Không</string>
   <string name="common_ok">Chấp nhận</string>
@@ -89,6 +95,8 @@
   <string name="sync_fail_in_favourites_content">Nội dung tập tin %1$d không thể đồng bộ (%2$d xung đột)</string>
   <string name="sync_foreign_files_forgotten_ticker">Một số tập tin cục bộ bị quên</string>
   <string name="sync_foreign_files_forgotten_content">Các tập tin %1$d ở ngoài thư mục %2$s không thể được chép vào</string>
+  <string name="sync_foreign_files_forgotten_explanation">\"Từ phiên bản 1.3.16, các tập tin tải lên từ thiết bị này được chép vào thư mục cục bộ %1$s để đề phòng mất dữ liệu khi một tập tin được đồng bộ với nhiều tài khoản.\n\nDo thay đổi này, tất cả các tập tin được tải lên ở phiên bản trước của ứng dụng này được chép vào thư mục %2$s. Tuy nhiên, đã có lỗi ngăn cản việc này trong lúc đồng bộ tài khoản. Bạn có thể để (các) tập tin như vậy và xóa liên kết đến %3$s, hoặc di chuyển (các) tập tin vào thư mục %1$s và giữ lại liên kết tới %4$s.\n\nDanh sách bên dưới là (các) tập tin cục bộ và (các) tập tin ở xa trong %5$s mà chúng được liên kết tới.</string>
+  <string name="sync_current_folder_was_removed">Thư mục %1$s không còn tồn tại</string>
   <string name="foreign_files_move">Di chuyển tất cả</string>
   <string name="foreign_files_success">Tất cả tập tin đã được chuyển đi</string>
   <string name="foreign_files_fail">Một vài tập tin không thể chuyển đi</string>
   <string name="media_err_unsupported">Codec của media không được hỗ trợ</string>
   <string name="media_err_io">Không thể đọc dữ liệu từ tập tin media</string>
   <string name="media_err_malformed">Tập tin media không được mã hóa đúng quy định</string>
+  <string name="media_err_timeout">Tạm ngừng trong khi đang cố gắng chạy</string>
   <string name="media_err_invalid_progressive_playback">Không thể phân luồng dữ liệu tập tin media</string>
   <string name="media_err_unknown">Tập tin media không thể được phát với trình phát media của stock</string>
   <string name="media_err_security_ex">Lỗi bảo mật khi cố phát %1$s</string>
   <string name="auth_connection_established">Kết nối đã thiết lập</string>
   <string name="auth_testing_connection">Đang kiểm tra kết nối...</string>
   <string name="auth_not_configured_title">Thay đổi cấu hình máy chủ </string>
+  <string name="auth_account_not_new">Một tài khoản với cùng tên người dùng và máy chủ đã tồn tại trong thiết bị</string>
+  <string name="auth_account_not_the_same">Tên người dùng đã nhập không đúng với tên người dùng của tài khoản này</string>
   <string name="auth_unknown_error_title">Không xác định được lỗi!</string>
   <string name="auth_unknown_host_title">Không thể tìm thấy máy chủ</string>
   <string name="auth_incorrect_path_title">Phiên bản máy chủ không tìm thấy</string>
   <string name="auth_timeout_title">Máy chủ đã quá dài để đáp ứng</string>
   <string name="auth_incorrect_address_title">Thay đổi URL</string>
   <string name="auth_ssl_general_error_title">SSL khởi tạo thất bại</string>
+  <string name="auth_ssl_unverified_server_title">không thể xác minh danh tính của máy chủ SSL</string>
   <string name="auth_bad_oc_version_title">Không chấp nhận phiên bản máy chủ</string>
   <string name="auth_wrong_connection_title">Không thể thiết lập kết nối</string>
   <string name="auth_secure_connection">Kết nối an toàn đã được thiết lập</string>
   <string name="auth_oauth_error">Xác nhận không thành công</string>
   <string name="auth_oauth_error_access_denied">Từ chối truy cập vì xác nhận từ phía máy chủ</string>
   <string name="auth_wtf_reenter_URL">Trạng thái không rõ, vui lòng điền lại đường dẫn liên kết một lần nữa</string>
+  <string name="auth_expired_oauth_token_toast">Hạn xác nhận của bạn đã hết. Vui lòng, xác nhận lại</string>
   <string name="auth_expired_basic_auth_toast">Vui lòng điền vào mật khẩu hiện tại của bạn</string>
+  <string name="auth_expired_saml_sso_token_toast">Phiên làm việc của bạn đã kết thúc. Vui lòng kết nối lại</string>
+  <string name="auth_connecting_auth_server">Đang kết nối đến máy chủ xác thực...</string>
+  <string name="auth_unsupported_auth_method">Máy chủ không hổ trợ phương thức xác thực này</string>
+  <string name="auth_unsupported_multiaccount">%1$s  không hỗ trợ nhiều tài khoản</string>
   <string name="fd_keep_in_sync">Giữ tập tin cập nhật</string>
   <string name="common_rename">Sửa tên</string>
   <string name="common_remove">Xóa</string>
   <string name="sync_file_fail_msg">Tập tin từ xa không được kiểm tra</string>
   <string name="sync_file_nothing_to_do_msg">Nội dung tập tin đã đồng bộ</string>
   <string name="create_dir_fail_msg">Thư mục không thể được tạo</string>
+  <string name="filename_forbidden_characters">Những kí tự không được dùng: / \\ &lt; &gt; : \" | ? *</string>
   <string name="wait_a_moment">Chờ một lúc</string>
   <string name="filedisplay_unexpected_bad_get_content">Vấn đề bất ngờ ; hãy thử ứng dụng khác để chọn tập tin</string>
   <string name="filedisplay_no_file_selected">Không có tập tin nào được chọn</string>
+  <string name="oauth_check_onoff">Đăng nhập bằng oAuth2.</string>
   <string name="oauth_login_connection">Đang kết nối đến máy chủ oAuth2...</string>
   <string name="ssl_validator_header">Không thể xác minh danh tính của site</string>
   <string name="ssl_validator_reason_cert_not_trusted">Chứng chỉ này không đáng tin cậy</string>
   <string name="preview_image_description">Xem trước hình ảnh</string>
   <string name="preview_image_error_unknown_format">Không thể hiển thị hình ảnh</string>
   <string name="error__upload__local_file_not_copied">%1$s không thể sao chép vào %2$s thư mục cục bộ</string>
+  <string name="actionbar_failed_instant_upload">Tải lên nhanh bị lỗi</string>
   <string name="failed_upload_headline_text">Tải lên nhanh bị lỗi</string>
   <string name="failed_upload_headline_hint">Tóm tắt tất cả các tải lên nhanh bị lỗi</string>
   <string name="failed_upload_all_cb">chọn tất cả</string>
index 366d2e3..3b4f8eb 100644 (file)
@@ -1,5 +1,6 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
+  <string name="about_android">%1$s 安卓应用</string>
   <string name="about_version">版本:%1$s</string>
   <string name="actionbar_sync">刷新帐户</string>
   <string name="actionbar_upload">上传</string>
   <string name="prefs_instant_upload">开启即时上传</string>
   <string name="prefs_instant_upload_summary">即时上传相机拍摄的照片</string>
   <string name="prefs_log_title">开启日志</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_delete_history_button">删除历史</string>
   <string name="prefs_help">帮助</string>
   <string name="prefs_feedback">反馈</string>
   <string name="prefs_imprint">版本说明</string>
   <string name="auth_check_server">检查服务器</string>
-  <string name="auth_host_url">服务器地址</string>
   <string name="auth_username">用户名</string>
   <string name="auth_password">密码</string>
+  <string name="auth_register">新增到 %1$s?</string>
   <string name="sync_string_files">文件</string>
   <string name="setup_btn_connect">连接</string>
   <string name="uploader_btn_upload_text">上传</string>
   <string name="filedetails_created">创建于:</string>
   <string name="filedetails_modified">已修改:</string>
   <string name="filedetails_download">下载</string>
+  <string name="filedetails_sync_file">刷新文件</string>
   <string name="filedetails_renamed_in_upload_msg">上传过程中文件被更名为了 %1$s</string>
+  <string name="action_share_file">分享链接</string>
+  <string name="action_unshare_file">取消共享链接</string>
   <string name="common_yes">是</string>
   <string name="common_no">否</string>
   <string name="common_ok">OK</string>
   <string name="auth_wrong_connection_title">无法建立连接</string>
   <string name="auth_secure_connection">加密连接已建立</string>
   <string name="auth_unauthorized">用户名或密码错误!</string>
+  <string name="auth_oauth_error">认证不成功</string>
+  <string name="auth_oauth_error_access_denied">访问被认证服务器拒绝</string>
+  <string name="auth_wtf_reenter_URL">意外状态;请再次输入服务器的地址</string>
   <string name="auth_expired_basic_auth_toast">请输入当前密码:</string>
   <string name="fd_keep_in_sync">保证文件更新</string>
   <string name="common_rename">重命名</string>
   <string name="wait_a_moment">请稍候</string>
   <string name="filedisplay_unexpected_bad_get_content">未知问题;请试试用其他程序选择此文件</string>
   <string name="filedisplay_no_file_selected">未选择文件。</string>
+  <string name="activity_chooser_title">发送链接给 …</string>
+  <string name="oauth_login_connection">连接oAuth2 服务器...</string>
   <string name="ssl_validator_header">站点身份无法验证</string>
   <string name="ssl_validator_reason_cert_not_trusted">不受信任的服务器证书</string>
   <string name="ssl_validator_reason_cert_expired">服务器证书过期</string>
   <string name="failed_upload_retry_do_nothing_text">不在线时不开启即时上传</string>
   <string name="failed_upload_failure_text">失败消息</string>
   <string name="failed_upload_quota_exceeded_text">请检查服务器设置。可能走出配额。</string>
+  <string name="share_link_no_support_share_api">对不起,共享服务功能未开启,请联系管理员</string>
+  <string name="share_link_file_no_exist">无法共享该文件或目录,请确定该文件或目录存在</string>
+  <string name="share_link_file_error">共享文件或目录出错</string>
+  <string name="unshare_link_file_error">解除文件或目录共享时出错</string>
 </resources>
index 2b14a23..51fd70b 100644 (file)
@@ -27,7 +27,6 @@
   <string name="prefs_feedback">反饋</string>
   <string name="prefs_imprint">法律聲明</string>
   <string name="auth_check_server">檢查伺服器</string>
-  <string name="auth_host_url">伺服器位址</string>
   <string name="auth_username">使用者名稱</string>
   <string name="auth_password">密碼</string>
   <string name="auth_register">新增到 %1$s?</string>
@@ -52,6 +51,7 @@
   <string name="filedetails_download">下載</string>
   <string name="filedetails_sync_file">更新檔案列表</string>
   <string name="filedetails_renamed_in_upload_msg">檔案名稱在上傳時已被更改為 %1$s</string>
+  <string name="action_share_file">分享連結</string>
   <string name="common_yes">是</string>
   <string name="common_no">否</string>
   <string name="common_ok">好</string>
index 226b618..2e07ae4 100644 (file)
@@ -8,12 +8,14 @@
     <string name ="db_name">ownCloud</string>
     <string name ="data_folder">owncloud</string>
     <string name ="log_name">Owncloud_</string>
+    <string name ="default_display_name_for_root_folder">/</string>
     
     <!-- URLs and flags related -->
     <string name="server_url"></string>
     <bool name="show_server_url_input">true</bool>
     <bool name="show_welcome_link">true</bool>
        <string name="welcome_link_url">"https://owncloud.com/mobile/new"</string>
+       <string name="share_api_link"></string>
     
     <!-- Flags to setup the authentication methods available in the app -->
     <string name="auth_method_oauth2">off</string>
index 61d0448..6c392b2 100644 (file)
@@ -34,7 +34,7 @@
        <string name="recommend_text">"I want to invite you to use %1$s on your smartphone!\nDownload here: %2$s"</string>  
 
     <string name="auth_check_server">Check Server</string>
-    <string name="auth_host_url">Server address</string>
+    <string name="auth_host_url">Server address https://…</string>
     <string name="auth_username">Username</string>
     <string name="auth_password">Password</string>
     <string name="auth_register">New to %1$s?</string>
@@ -59,6 +59,8 @@
     <string name="filedetails_download">Download</string>
     <string name="filedetails_sync_file">Refresh file</string>
     <string name="filedetails_renamed_in_upload_msg">File was renamed to %1$s during upload</string>
+    <string name="action_share_file">Share link</string>
+    <string name="action_unshare_file">Unshare link</string>
     <string name="common_yes">Yes</string>
     <string name="common_no">No</string>
     <string name="common_ok">OK</string>
     <string name="wait_a_moment">Wait a moment</string>
     <string name="filedisplay_unexpected_bad_get_content">"Unexpected problem ; please select the file from a different app"</string>
     <string name="filedisplay_no_file_selected">No file was selected</string>
+    <string name="activity_chooser_title">Send link to &#8230;</string>
     
     <string name="oauth_check_onoff">Login with oAuth2</string> 
     <string name="oauth_login_connection">Connecting to oAuth2 server…</string>    
     <string name="failed_upload_retry_do_nothing_text">do nothing you are not online for instant upload</string>
        <string name="failed_upload_failure_text">Failure Message: </string>
        <string name="failed_upload_quota_exceeded_text">Please check your server configuration,maybe your quota is exceeded.</string>
+       
+       <string name="share_link_no_support_share_api">Sorry, sharing is not enabled on your server. Please contact your administrator.</string>
+       <string name="share_link_file_no_exist">Unable to share this file or folder. Please, make sure it exists</string>
+       <string name="share_link_file_error">An error occurred while trying to share this file or folder</string>
+       <string name="unshare_link_file_no_exist">Unable to unshare this file or folder. It does not exist.</string>
+       <string name="unshare_link_file_error">An error occurred while trying to unshare this file or folder</string>
 </resources>
index d5b78c9..dc44a12 100644 (file)
@@ -1,7 +1,7 @@
 call git submodule init
 call git submodule update
 call android.bat update project -p actionbarsherlock\library -n ActionBarSherlock
-call android.bat update project -p oc_framework -n ownCloudFramework
+call android.bat update lib-project -p owncloud-android-library
 call android.bat update project -p .
 call android.bat update project -p oc_jb_workaround
 copy /Y third_party\android-support-library\android-support-v4.jar actionbarsherlock\library\libs\android-support-v4.jar
index b13fe81..e604752 100755 (executable)
@@ -3,7 +3,7 @@
 git submodule init
 git submodule update
 android update project -p actionbarsherlock/library -n ActionBarSherlock
-android update project -p oc_framework -n ownCloudFramework
+android update lib-project -p owncloud-android-library
 android update project -p .
 android update project -p oc_jb_workaround
 cp third_party/android-support-library/android-support-v4.jar actionbarsherlock/library/libs/android-support-v4.jar 
index 78a8575..49a9355 100644 (file)
@@ -28,7 +28,7 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.widget.Toast;
 
-import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;
+import com.owncloud.android.lib.accounts.AccountTypeUtils;
 import com.owncloud.android.utils.Log_OC;
 
 
index 33c7e6a..5f0441c 100644 (file)
@@ -19,8 +19,8 @@
 package com.owncloud.android.authentication;\r
 \r
 import com.owncloud.android.MainApp;\r
-import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;\r
-import com.owncloud.android.oc_framework.utils.OwnCloudVersion;\r
+import com.owncloud.android.lib.accounts.AccountTypeUtils;\r
+import com.owncloud.android.lib.utils.OwnCloudVersion;\r
 \r
 import android.accounts.Account;\r
 import android.accounts.AccountManager;\r
index 85f4914..3a817d6 100644 (file)
@@ -36,6 +36,7 @@ import android.support.v4.app.Fragment;
 import android.text.Editable;\r
 import android.text.InputType;\r
 import android.text.TextWatcher;\r
+import android.util.Log;\r
 import android.view.KeyEvent;\r
 import android.view.MotionEvent;\r
 import android.view.View;\r
@@ -53,22 +54,25 @@ import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.owncloud.android.MainApp;\r
 import com.owncloud.android.R;\r
 import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener;\r
-import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;\r
-import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;\r
-import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;\r
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;\r
-import com.owncloud.android.operations.ExistenceCheckOperation;\r
+import com.owncloud.android.lib.accounts.AccountTypeUtils;\r
+import com.owncloud.android.lib.accounts.OwnCloudAccount;\r
+import com.owncloud.android.lib.network.OwnCloudClientFactory;\r
+import com.owncloud.android.lib.network.OwnCloudClient;\r
 import com.owncloud.android.operations.OAuth2GetAccessToken;\r
-import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;\r
-import com.owncloud.android.operations.OwnCloudServerCheckOperation;\r
-import com.owncloud.android.oc_framework.operations.RemoteOperation;\r
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;\r
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;\r
+
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;\r
+import com.owncloud.android.lib.operations.remote.OwnCloudServerCheckOperation;\r
+import com.owncloud.android.lib.operations.common.RemoteOperation;\r
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;\r
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;\r
+import com.owncloud.android.lib.operations.remote.ExistenceCheckRemoteOperation;\r
+import com.owncloud.android.lib.operations.remote.GetUserNameRemoteOperation;\r
+
 import com.owncloud.android.ui.dialog.SamlWebViewDialog;\r
 import com.owncloud.android.ui.dialog.SslValidatorDialog;\r
 import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;\r
 import com.owncloud.android.utils.Log_OC;\r
-import com.owncloud.android.oc_framework.utils.OwnCloudVersion;\r
+import com.owncloud.android.lib.utils.OwnCloudVersion;\r
 \r
 /**\r
  * This Activity is used to add an ownCloud account to the App\r
@@ -102,8 +106,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     private static final String KEY_AUTH_STATUS_TEXT = "AUTH_STATUS_TEXT";\r
     private static final String KEY_AUTH_STATUS_ICON = "AUTH_STATUS_ICON";\r
     private static final String KEY_REFRESH_BUTTON_ENABLED = "KEY_REFRESH_BUTTON_ENABLED";\r
-    \r
-    private static final String KEY_OC_USERNAME_EQUALS = "oc_username=";\r
+    private static final String KEY_IS_SHARED_SUPPORTED = "KEY_IS_SHARE_SUPPORTED";\r
 \r
     private static final String AUTH_ON = "on";\r
     private static final String AUTH_OFF = "off";\r
@@ -121,6 +124,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     \r
     private String mHostBaseUrl;\r
     private OwnCloudVersion mDiscoveredVersion;\r
+    private boolean mIsSharedSupported;\r
 \r
     private String mAuthMessageText;\r
     private int mAuthMessageVisibility, mServerStatusText, mServerStatusIcon;\r
@@ -131,7 +135,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     private final Handler mHandler = new Handler();\r
     private Thread mOperationThread;\r
     private OwnCloudServerCheckOperation mOcServerChkOperation;\r
-    private ExistenceCheckOperation mAuthCheckOperation;\r
+    private ExistenceCheckRemoteOperation mAuthCheckOperation;\r
     private RemoteOperationResult mLastSslUntrustedServerResult;\r
 \r
     private Uri mNewCapturedUriFromOAuth2Redirection;\r
@@ -231,6 +235,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mServerIsChecked = false;\r
             mIsSslConn = false;\r
             mAuthStatusText = mAuthStatusIcon = 0;\r
+            mIsSharedSupported = false;\r
 \r
             /// retrieve extras from intent\r
             mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT);\r
@@ -243,6 +248,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
                 mHostUrlInput.setText(mHostBaseUrl);\r
                 String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@'));\r
                 mUsernameInput.setText(userName);\r
+                mIsSharedSupported = Boolean.getBoolean(mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_SHARE_API));\r
+                \r
             }\r
             initAuthorizationMethod();  // checks intent and setup.xml to determine mCurrentAuthorizationMethod\r
             mJustCreated = true;\r
@@ -269,6 +276,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             \r
             /// server data\r
             String ocVersion = savedInstanceState.getString(KEY_OC_VERSION);\r
+            mIsSharedSupported = savedInstanceState.getBoolean(KEY_IS_SHARED_SUPPORTED, false);\r
             if (ocVersion != null) {\r
                 mDiscoveredVersion = new OwnCloudVersion(ocVersion);\r
             }\r
@@ -448,6 +456,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             outState.putString(KEY_OC_VERSION, mDiscoveredVersion.toString());\r
         }\r
         outState.putString(KEY_HOST_URL_TEXT, mHostBaseUrl);\r
+        outState.putBoolean(KEY_IS_SHARED_SUPPORTED, mIsSharedSupported);\r
 \r
         /// account data, if updating\r
         if (mAccount != null) {\r
@@ -525,8 +534,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
                 getString(R.string.oauth2_redirect_uri),       \r
                 getString(R.string.oauth2_grant_type),\r
                 queryParameters);\r
-        //WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(getString(R.string.oauth2_url_endpoint_access)), getApplicationContext());\r
-        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mOAuthTokenEndpointText.getText().toString().trim()), getApplicationContext(), true);\r
+        //OwnCloudClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(getString(R.string.oauth2_url_endpoint_access)), getApplicationContext());\r
+        OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mOAuthTokenEndpointText.getText().toString().trim()), getApplicationContext(), true);\r
         operation.execute(client, this, mHandler);\r
     }\r
 \r
@@ -582,6 +591,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         \r
         mServerIsValid = false;\r
         mServerIsChecked = false;\r
+        mIsSharedSupported = false;\r
         mOkButton.setEnabled(false);\r
         mDiscoveredVersion = null;\r
         hideRefreshButton();\r
@@ -590,7 +600,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mServerStatusIcon = R.drawable.progress_small;\r
             showServerStatus();\r
             mOcServerChkOperation = new  OwnCloudServerCheckOperation(uri, this);\r
-            WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(uri), this, true);\r
+            OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(uri), this, true);\r
             mOperationThread = mOcServerChkOperation.execute(client, this, mHandler);\r
         } else {\r
             mServerStatusText = 0;\r
@@ -716,8 +726,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         showDialog(DIALOG_LOGIN_PROGRESS);\r
 \r
         /// test credentials accessing the root folder\r
-        mAuthCheckOperation = new  ExistenceCheckOperation("", this, false);\r
-        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
+        mAuthCheckOperation = new  ExistenceCheckRemoteOperation("", this, false);\r
+        OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
         client.setBasicCredentials(username, password);\r
         mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);\r
     }\r
@@ -765,8 +775,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion, mAuthTokenType);\r
 \r
         /// test credentials accessing the root folder\r
-        mAuthCheckOperation = new  ExistenceCheckOperation("", this, false);\r
-        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, false);\r
+        mAuthCheckOperation = new  ExistenceCheckRemoteOperation("", this, false);\r
+        OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, false);\r
         mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);\r
       \r
     }\r
@@ -785,17 +795,52 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         } else if (operation instanceof OAuth2GetAccessToken) {\r
             onGetOAuthAccessTokenFinish((OAuth2GetAccessToken)operation, result);\r
 \r
-        } else if (operation instanceof ExistenceCheckOperation)  {\r
+        } else if (operation instanceof ExistenceCheckRemoteOperation)  {\r
             if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                 onSamlBasedFederatedSingleSignOnAuthorizationStart(operation, result);\r
                 \r
             } else {\r
-                onAuthorizationCheckFinish((ExistenceCheckOperation)operation, result);\r
+                onAuthorizationCheckFinish((ExistenceCheckRemoteOperation)operation, result);\r
             }\r
+        } else if (operation instanceof GetUserNameRemoteOperation) {\r
+            onGetUserNameFinish((GetUserNameRemoteOperation) operation, result);\r
+             \r
         }\r
+        \r
     }\r
-    \r
-    \r
+\r
+    private void onGetUserNameFinish(GetUserNameRemoteOperation operation, RemoteOperationResult result) {\r
+        if (result.isSuccess()) {\r
+            boolean success = false;\r
+            String username = operation.getUserName();\r
+            \r
+            if ( mAction == ACTION_CREATE) {\r
+                mUsernameInput.setText(username);\r
+                success = createAccount();\r
+            } else {\r
+                \r
+                if (!mUsernameInput.getText().toString().equals(username)) {\r
+                    // fail - not a new account, but an existing one; disallow\r
+                    result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME); \r
+                    updateAuthStatusIconAndText(result);\r
+                    showAuthStatus();\r
+                    Log_OC.d(TAG, result.getLogMessage());\r
+                } else {\r
+                  updateToken();\r
+                  success = true;\r
+                }\r
+            }\r
+            \r
+            if (success)\r
+                finish();\r
+        } else {\r
+            updateAuthStatusIconAndText(result);\r
+            showAuthStatus();\r
+            Log_OC.e(TAG, "Access to user name failed: " + result.getLogMessage());\r
+        }\r
+        \r
+    }\r
+\r
     private void onSamlBasedFederatedSingleSignOnAuthorizationStart(RemoteOperation operation, RemoteOperationResult result) {\r
         try {\r
             dismissDialog(DIALOG_LOGIN_PROGRESS);\r
@@ -860,6 +905,9 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
 \r
             /// allow or not the user try to access the server\r
             mOkButton.setEnabled(mServerIsValid);\r
+            \r
+            /// retrieve if is supported the Share API\r
+            mIsSharedSupported = operation.isSharedSupported();\r
 \r
         }   // else nothing ; only the last check operation is considered; \r
         // multiple can be triggered if the user amends a URL before a previous check can be triggered\r
@@ -1084,8 +1132,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             /// time to test the retrieved access token on the ownCloud server\r
             mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);\r
             Log_OC.d(TAG, "Got ACCESS TOKEN: " + mAuthToken);\r
-            mAuthCheckOperation = new ExistenceCheckOperation("", this, false);\r
-            WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
+            mAuthCheckOperation = new ExistenceCheckRemoteOperation("", this, false);\r
+            OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
             client.setBearerCredentials(mAuthToken);\r
             mAuthCheckOperation.execute(client, this, mHandler);\r
 \r
@@ -1105,7 +1153,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
      * @param operation     Access check performed.\r
      * @param result        Result of the operation.\r
      */\r
-    private void onAuthorizationCheckFinish(ExistenceCheckOperation operation, RemoteOperationResult result) {\r
+    private void onAuthorizationCheckFinish(ExistenceCheckRemoteOperation operation, RemoteOperationResult result) {\r
         try {\r
             dismissDialog(DIALOG_LOGIN_PROGRESS);\r
         } catch (IllegalArgumentException e) {\r
@@ -1120,7 +1168,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
                 success = createAccount();\r
 \r
             } else {\r
-                success = updateToken();\r
+                updateToken();\r
+                success = true;\r
             }\r
 \r
             if (success) {\r
@@ -1166,7 +1215,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
      * Sets the proper response to get that the Account Authenticator that started this activity saves \r
      * a new authorization token for mAccount.\r
      */\r
-    private boolean updateToken() {\r
+    private void updateToken() {\r
         Bundle response = new Bundle();\r
         response.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);\r
         response.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type);\r
@@ -1177,16 +1226,6 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);\r
             \r
         } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
-            String username = getUserNameForSamlSso();\r
-            if (!mUsernameInput.getText().toString().equals(username)) {\r
-                // fail - not a new account, but an existing one; disallow\r
-                RemoteOperationResult result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME); \r
-                updateAuthStatusIconAndText(result);\r
-                showAuthStatus();\r
-                Log_OC.d(TAG, result.getLogMessage());\r
-                \r
-                return false;\r
-            }\r
             \r
             response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);\r
             // the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention\r
@@ -1198,7 +1237,6 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         }\r
         setAccountAuthenticatorResult(response);\r
         \r
-        return true;\r
     }\r
 \r
 \r
@@ -1216,10 +1254,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
 \r
         Uri uri = Uri.parse(mHostBaseUrl);\r
         String username = mUsernameInput.getText().toString().trim();\r
-        if (isSaml) {\r
-            username = getUserNameForSamlSso();\r
-            \r
-        } else if (isOAuth) {\r
+        if (isOAuth) {\r
             username = "OAuth_user" + (new java.util.Random(System.currentTimeMillis())).nextLong();\r
         }            \r
         String accountName = username + "@" + uri.getHost();\r
@@ -1266,6 +1301,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             /// add user data to the new account; TODO probably can be done in the last parameter addAccountExplicitly, or in KEY_USERDATA\r
             mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_VERSION,    mDiscoveredVersion.toString());\r
             mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_BASE_URL,   mHostBaseUrl);\r
+            mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_SHARE_API, Boolean.toString(mIsSharedSupported));\r
             if (isSaml) {\r
                 mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); \r
             } else if (isOAuth) {\r
@@ -1279,20 +1315,6 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         }\r
     }\r
 \r
-    \r
-    private String getUserNameForSamlSso() {\r
-        if (mAuthToken != null) {\r
-            String [] cookies = mAuthToken.split(";");\r
-            for (int i=0; i<cookies.length; i++) {\r
-                if (cookies[i].startsWith(KEY_OC_USERNAME_EQUALS )) {\r
-                    String value = Uri.decode(cookies[i].substring(KEY_OC_USERNAME_EQUALS.length()));\r
-                    return value;\r
-                }\r
-            }\r
-        }\r
-        return "";\r
-    }\r
-\r
 \r
     /**\r
      * {@inheritDoc}\r
@@ -1588,21 +1610,16 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     }\r
 \r
 \r
-    public void onSamlDialogSuccess(String sessionCookie){\r
+    public void onSamlDialogSuccess(String sessionCookie) {\r
         mAuthToken = sessionCookie;\r
         \r
         if (sessionCookie != null && sessionCookie.length() > 0) {\r
             mAuthToken = sessionCookie;\r
-            boolean success = false;\r
-            if (mAction == ACTION_CREATE) {\r
-                success = createAccount();\r
-        \r
-            } else {\r
-                success = updateToken();\r
-            }\r
-            if (success) {\r
-                finish();\r
-            }\r
+\r
+            GetUserNameRemoteOperation getUserOperation = new GetUserNameRemoteOperation();            \r
+            OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl), getApplicationContext(), true);\r
+            client.setSsoSessionCookie(mAuthToken);\r
+            getUserOperation.execute(client, this, mHandler);\r
         }\r
 \r
             \r
@@ -1652,4 +1669,5 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         }\r
         return super.onTouchEvent(event);\r
     }\r
+    \r
 }\r
index 8d80e9b..442ec73 100644 (file)
@@ -21,12 +21,16 @@ import java.lang.ref.WeakReference;
 
 import com.owncloud.android.utils.Log_OC;
 
-
 import android.graphics.Bitmap;
+import android.net.http.SslError;
 import android.os.Handler;
 import android.os.Message;
+import android.view.KeyEvent;
 import android.view.View;
 import android.webkit.CookieManager;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebResourceResponse;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 
@@ -107,7 +111,7 @@ public class SsoWebViewClient extends WebViewClient {
             view.setVisibility(View.GONE);
             CookieManager cookieManager = CookieManager.getInstance();
             final String cookies = cookieManager.getCookie(url);
-            //Log_OC.d(TAG, "Cookies: " + cookies);
+            Log_OC.d(TAG, "Cookies: " + cookies);
             if (mListenerHandler != null && mListenerRef != null) {
                 // this is good idea because onPageFinished is not running in the UI thread
                 mListenerHandler.post(new Runnable() {
@@ -115,16 +119,16 @@ public class SsoWebViewClient extends WebViewClient {
                     public void run() {
                         SsoWebViewClientListener listener = mListenerRef.get();
                         if (listener != null) {
+                               // Send Cookies to the listener
                             listener.onSsoFinished(cookies);
                         }
                     }
                 });
             }
-        }
-
+        } 
     }
     
-    /*
+    
     @Override
     public void doUpdateVisitedHistory (WebView view, String url, boolean isReload) {
         Log_OC.d(TAG, "doUpdateVisitedHistory : " + url);
@@ -133,6 +137,7 @@ public class SsoWebViewClient extends WebViewClient {
     @Override
     public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) {
         Log_OC.d(TAG, "onReceivedSslError : " + error);
+        handler.proceed();
     }
     
     @Override
@@ -172,5 +177,5 @@ public class SsoWebViewClient extends WebViewClient {
         Log_OC.d(TAG, "shouldOverrideKeyEvent : " + event);
         return false;
     }
-    */
+
 }
index fb55e93..f886e16 100644 (file)
@@ -27,6 +27,9 @@ import java.util.Vector;
 
 import com.owncloud.android.MainApp;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
+import com.owncloud.android.lib.operations.common.OCShare;
+import com.owncloud.android.lib.operations.common.ShareType;
+import com.owncloud.android.lib.utils.FileUtils;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.Log_OC;
 
@@ -181,7 +184,9 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
         cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
-
+        cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
+        
         boolean sameRemotePath = fileExists(file.getRemotePath());
         if (sameRemotePath ||
                 fileExists(file.getFileId())        ) {           // for renamed files; no more delete and create
@@ -278,6 +283,8 @@ public class FileDataStorageManager {
             cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
             cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
             cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
+            cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
+            cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
 
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {
@@ -333,6 +340,9 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
         cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.keepInSync() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
+        cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, folder.isShareByLink() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
+        
         operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
                 withValues(cv).
                 withSelection(  ProviderTableMeta._ID + "=?", 
@@ -434,7 +444,7 @@ public class FileDataStorageManager {
                     }
                     updateFolderSize(file.getParentId());
                 }
-                if (removeLocalCopy && file.isDown()) {
+                if (removeLocalCopy && file.isDown() && file.getStoragePath() != null) {
                     boolean success = new File(file.getStoragePath()).delete();
                     if (!removeDBData && success) {
                         // maybe unnecessary, but should be checked TODO remove if unnecessary
@@ -663,6 +673,32 @@ public class FileDataStorageManager {
         }
         return c;
     }
+    
+    private Cursor getShareCursorForValue(String key, String value) {
+        Cursor c = null;
+        if (getContentResolver() != null) {
+            c = getContentResolver()
+                    .query(ProviderTableMeta.CONTENT_URI_SHARE,
+                            null,
+                            key + "=? AND "
+                                    + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
+                                    + "=?",
+                                    new String[] { value, mAccount.name }, null);
+        } else {
+            try {
+                c = getContentProviderClient().query(
+                        ProviderTableMeta.CONTENT_URI_SHARE,
+                        null,
+                        key + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
+                        + "=?", new String[] { value, mAccount.name },
+                        null);
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
+                c = null;
+            }
+        }
+        return c;
+    }
 
     private OCFile createFileInstance(Cursor c) {
         OCFile file = null;
@@ -701,9 +737,543 @@ public class FileDataStorageManager {
             file.setKeepInSync(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
             file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
+            file.setShareByLink(c.getInt(
+                    c.getColumnIndex(ProviderTableMeta.FILE_SHARE_BY_LINK)) == 1 ? true : false);
+            file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK)));
                     
         }
         return file;
     }
+    
+    /**
+     * Returns if the file/folder is shared by link or not
+     * @param path  Path of the file/folder
+     * @return
+     */
+    public boolean isShareByLink(String path) {
+        Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
+        OCFile file = null;
+        if (c.moveToFirst()) {
+            file = createFileInstance(c);
+        }
+        c.close();
+        return file.isShareByLink();
+    }
+    
+    /**
+     * Returns the public link of the file/folder
+     * @param path  Path of the file/folder
+     * @return
+     */
+    public String getPublicLink(String path) {
+        Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
+        OCFile file = null;
+        if (c.moveToFirst()) {
+            file = createFileInstance(c);
+        }
+        c.close();
+        return file.getPublicLink();
+    }
+    
+    
+    // Methods for Shares
+    public boolean saveShare(OCShare share) {
+        boolean overriden = false;
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
+        cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
+        cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
+        cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
+        cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
+        cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
+        cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
+        cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
+        cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
+        cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
+        cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
+        cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
+        cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
+        cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
+        
+        if (shareExists(share.getIdRemoteShared())) {           // for renamed files; no more delete and create
+
+            overriden = true;
+            if (getContentResolver() != null) {
+                getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv,
+                        ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
+                        new String[] { String.valueOf(share.getIdRemoteShared()) });
+            } else {
+                try {
+                    getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_SHARE,
+                            cv, ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
+                            new String[] { String.valueOf(share.getIdRemoteShared()) });
+                } catch (RemoteException e) {
+                    Log_OC.e(TAG,
+                            "Fail to insert insert file to database "
+                                    + e.getMessage());
+                }
+            }
+        } else {
+            Uri result_uri = null;
+            if (getContentResolver() != null) {
+                result_uri = getContentResolver().insert(
+                        ProviderTableMeta.CONTENT_URI_SHARE, cv);
+            } else {
+                try {
+                    result_uri = getContentProviderClient().insert(
+                            ProviderTableMeta.CONTENT_URI_SHARE, cv);
+                } catch (RemoteException e) {
+                    Log_OC.e(TAG,
+                            "Fail to insert insert file to database "
+                                    + e.getMessage());
+                }
+            }
+            if (result_uri != null) {
+                long new_id = Long.parseLong(result_uri.getPathSegments()
+                        .get(1));
+                share.setId(new_id);
+            }            
+        }
+
+        return overriden;
+    }
+
+    private OCShare getShareById(long id) {
+        Cursor c = getShareCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
+        OCShare share = null;
+        if (c.moveToFirst()) {
+            share = createShareInstance(c);
+        }
+        c.close();
+        return share;
+    }
+
+    private OCShare getShareByRemoteId(long remoteId) {
+        Cursor c = getShareCursorForValue(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId));
+        OCShare share = null;
+        if (c.moveToFirst()) {
+            share = createShareInstance(c);
+        }
+        c.close();
+        return share;
+    }
+
+    public OCShare getShareByPath(String path) {
+        Cursor c = getShareCursorForValue(ProviderTableMeta.OCSHARES_PATH, path);
+        OCShare share = null;
+        if (c.moveToFirst()) {
+            share = createShareInstance(c);
+        }
+        c.close();
+        return share;
+    }
+    
+    private OCShare createShareInstance(Cursor c) {
+        OCShare share = null;
+        if (c != null) {
+            share = new OCShare(c.getString(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_PATH)));
+            share.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
+            share.setFileSource(c.getLong(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_ITEM_SOURCE)));
+            share.setShareType(ShareType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_TYPE))));
+            share.setPermissions(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_PERMISSIONS)));
+            share.setSharedDate(c.getLong(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_SHARED_DATE)));
+            share.setExpirationDate(c.getLong(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_EXPIRATION_DATE)));
+            share.setToken(c.getString(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_TOKEN)));
+            share.setSharedWithDisplayName(c.getString(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME)));
+            share.setIsFolder(c.getInt(
+                    c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1 ? true : false);
+            share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
+            share.setIdRemoteShared(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)));
+                    
+        }
+        return share;
+    }
 
+    private boolean shareExists(String cmp_key, String value) {
+        Cursor c;
+        if (getContentResolver() != null) {
+            c = getContentResolver()
+                    .query(ProviderTableMeta.CONTENT_URI_SHARE,
+                            null,
+                            cmp_key + "=? AND "
+                                    + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
+                                    + "=?",
+                                    new String[] { value, mAccount.name }, null);
+        } else {
+            try {
+                c = getContentProviderClient().query(
+                        ProviderTableMeta.CONTENT_URI_SHARE,
+                        null,
+                        cmp_key + "=? AND "
+                                + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?",
+                                new String[] { value, mAccount.name }, null);
+            } catch (RemoteException e) {
+                Log_OC.e(TAG,
+                        "Couldn't determine file existance, assuming non existance: "
+                                + e.getMessage());
+                return false;
+            }
+        }
+        boolean retval = c.moveToFirst();
+        c.close();
+        return retval;
+    }
+    
+    private boolean shareExists(long remoteId) {
+        return shareExists(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId));
+    }
+
+    private void cleanSharedFiles() {
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
+        cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
+        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
+        String [] whereArgs = new String[]{mAccount.name};
+        
+        if (getContentResolver() != null) {
+            getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+
+        } else {
+            try {
+                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+                
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Exception in cleanSharedFiles" + e.getMessage());
+            }
+        }
+    }
+
+    private void cleanSharedFilesInFolder(OCFile folder) {
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
+        cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
+        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PARENT + "=?";
+        String [] whereArgs = new String[] { mAccount.name , String.valueOf(folder.getFileId()) };
+        
+        if (getContentResolver() != null) {
+            getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+
+        } else {
+            try {
+                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+                
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Exception in cleanSharedFilesInFolder " + e.getMessage());
+            }
+        }
+    }
+
+    private void cleanShares() {
+        String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
+        String [] whereArgs = new String[]{mAccount.name};
+        
+        if (getContentResolver() != null) {
+            getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
+
+        } else {
+            try {
+                getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
+                
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage());
+            }
+        }
+    }
+    
+    public void saveShares(Collection<OCShare> shares) {
+        cleanShares();
+        if (shares != null) {
+            ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(shares.size());
+
+            // prepare operations to insert or update files to save in the given folder
+            for (OCShare share : shares) {
+                ContentValues cv = new ContentValues();
+                cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
+                cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
+                cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
+                cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
+                cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
+                cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
+                cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
+                cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
+                cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
+                cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
+                cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
+                cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
+                cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
+                cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
+
+                if (shareExists(share.getIdRemoteShared())) {
+                    // updating an existing file
+                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
+                            withValues(cv).
+                            withSelection(  ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", 
+                                    new String[] { String.valueOf(share.getIdRemoteShared()) })
+                                    .build());
+
+                } else {
+                    // adding a new file
+                    operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build());
+                }
+            }
+            
+            // apply operations in batch
+            if (operations.size() > 0) {
+                @SuppressWarnings("unused")
+                ContentProviderResult[] results = null;
+                Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
+                try {
+                    if (getContentResolver() != null) {
+                        results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+    
+                    } else {
+                        results = getContentProviderClient().applyBatch(operations);
+                    }
+    
+                } catch (OperationApplicationException e) {
+                    Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
+    
+                } catch (RemoteException e) {
+                    Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
+                }
+            }
+        }
+        
+    }
+    
+    public void updateSharedFiles(Collection<OCFile> sharedFiles) {
+        cleanSharedFiles();
+        
+        if (sharedFiles != null) {
+            ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(sharedFiles.size());
+
+            // prepare operations to insert or update files to save in the given folder
+            for (OCFile file : sharedFiles) {
+                ContentValues cv = new ContentValues();
+                cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
+                cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
+                cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
+                cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
+                cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
+                cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
+                cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
+                cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
+                if (!file.isFolder()) {
+                    cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+                }
+                cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
+                cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
+                cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
+                cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
+                cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
+                cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
+                cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
+
+                boolean existsByPath = fileExists(file.getRemotePath());
+                if (existsByPath || fileExists(file.getFileId())) {
+                    // updating an existing file
+                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
+                            withValues(cv).
+                            withSelection(  ProviderTableMeta._ID + "=?", 
+                                    new String[] { String.valueOf(file.getFileId()) })
+                                    .build());
+
+                } else {
+                    // adding a new file
+                    operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
+                }
+            }
+            
+            // apply operations in batch
+            if (operations.size() > 0) {
+                @SuppressWarnings("unused")
+                ContentProviderResult[] results = null;
+                Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
+                try {
+                    if (getContentResolver() != null) {
+                        results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+    
+                    } else {
+                        results = getContentProviderClient().applyBatch(operations);
+                    }
+    
+                } catch (OperationApplicationException e) {
+                    Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
+    
+                } catch (RemoteException e) {
+                    Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
+                }
+            }
+        }
+        
+    } 
+    
+    public void removeShare(OCShare share){
+        Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE;
+        String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+        String [] whereArgs = new String[]{mAccount.name, share.getPath()};
+        if (getContentProviderClient() != null) {
+            try {
+                getContentProviderClient().delete(share_uri, where, whereArgs);
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        } else {
+            getContentResolver().delete(share_uri, where, whereArgs); 
+        }
+    }
+    
+    public void saveSharesDB(ArrayList<OCShare> shares) {
+        saveShares(shares);
+
+        ArrayList<OCFile> sharedFiles = new ArrayList<OCFile>();
+
+        for (OCShare share : shares) {
+            // Get the path
+            String path = share.getPath();
+            if (share.isFolder()) {
+                path = path + FileUtils.PATH_SEPARATOR;
+            }           
+
+            // Update OCFile with data from share: ShareByLink  ¿and publicLink?
+            OCFile file = getFileByPath(path);
+            if (file != null) {
+                if (share.getShareType().equals(ShareType.PUBLIC_LINK)) {
+                    file.setShareByLink(true);
+                    sharedFiles.add(file);
+                }
+            } 
+        }
+        
+        updateSharedFiles(sharedFiles);
+    }
+
+    
+    public void saveSharesInFolder(ArrayList<OCShare> shares, OCFile folder) {
+        cleanSharedFilesInFolder(folder);
+        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
+        operations = prepareRemoveSharesInFolder(folder, operations);
+        
+        if (shares != null) {
+            // prepare operations to insert or update files to save in the given folder
+            for (OCShare share : shares) {
+                ContentValues cv = new ContentValues();
+                cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
+                cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource());
+                cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue());
+                cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith());
+                cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath());
+                cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions());
+                cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
+                cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
+                cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
+                cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
+                cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
+                cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
+                cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
+                cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
+
+                /*
+                if (shareExists(share.getIdRemoteShared())) {
+                    // updating an existing share resource
+                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
+                            withValues(cv).
+                            withSelection(  ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", 
+                                    new String[] { String.valueOf(share.getIdRemoteShared()) })
+                                    .build());
+
+                } else {
+                */
+                // adding a new share resource
+                operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build());
+                //}
+            }
+        }
+            
+        // apply operations in batch
+        if (operations.size() > 0) {
+            @SuppressWarnings("unused")
+            ContentProviderResult[] results = null;
+            Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
+            try {
+                if (getContentResolver() != null) {
+                    results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+
+                } else {
+                    results = getContentProviderClient().applyBatch(operations);
+                }
+
+            } catch (OperationApplicationException e) {
+                Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
+
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
+            }
+        }
+        //}
+        
+    }
+
+    private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(OCFile folder, ArrayList<ContentProviderOperation> preparedOperations) {
+        if (folder != null) {
+            String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
+            String [] whereArgs = new String[]{ "", mAccount.name };
+            
+            Vector<OCFile> files = getFolderContent(folder);
+            
+            for (OCFile file : files) {
+                whereArgs[0] = file.getRemotePath();
+                preparedOperations.add(ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE)
+                        .withSelection(where, whereArgs)
+                        .build());
+            }
+        }
+        return preparedOperations;
+        
+        /*
+        if (operations.size() > 0) {
+            try {
+                if (getContentResolver() != null) {
+                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+
+                } else {
+                    getContentProviderClient().applyBatch(operations);
+                }
+
+            } catch (OperationApplicationException e) {
+                Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
+
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
+            }
+        }            
+        */
+            
+            /*
+            if (getContentResolver() != null) {
+                
+                getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, 
+                                            where,
+                                            whereArgs);
+            } else {
+                try {
+                    getContentProviderClient().delete(  ProviderTableMeta.CONTENT_URI_SHARE, 
+                                                        where,
+                                                        whereArgs);
+
+                } catch (RemoteException e) {
+                    Log_OC.e(TAG, "Exception deleting shares in a folder " + e.getMessage());
+                }
+            }
+            */
+        //}
+    }
 }
index a6e6a54..82c341c 100644 (file)
@@ -61,6 +61,9 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
     private boolean mKeepInSync;
 
     private String mEtag;
+    
+    private boolean mShareByLink;
+    private String mPublicLink;
 
 
     /**
@@ -99,6 +102,8 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mLastSyncDateForProperties = source.readLong();
         mLastSyncDateForData = source.readLong();
         mEtag = source.readString();
+        mShareByLink = source.readInt() == 1;
+        mPublicLink = source.readString();
     }
 
     @Override
@@ -117,6 +122,8 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         dest.writeLong(mLastSyncDateForProperties);
         dest.writeLong(mLastSyncDateForData);
         dest.writeString(mEtag);
+        dest.writeInt(mShareByLink ? 1 : 0);
+        dest.writeString(mPublicLink);
     }
     
     /**
@@ -325,6 +332,8 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mKeepInSync = false;
         mNeedsUpdating = false;
         mEtag = null;
+        mShareByLink = false;
+        mPublicLink = null;
     }
 
     /**
@@ -445,7 +454,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
 
     @Override
     public String toString() {
-        String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, parentId=%s, keepInSinc=%s etag=%s]";
+        String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, parentId=%s, keepInSync=%s etag=%s]";
         asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(), mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mKeepInSync), mEtag);
         return asString;
     }
@@ -458,6 +467,23 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         this.mEtag = etag;
     }
     
+    
+    public boolean isShareByLink() {
+        return mShareByLink;
+    }
+
+    public void setShareByLink(boolean shareByLink) {
+        this.mShareByLink = shareByLink;
+    }
+
+    public String getPublicLink() {
+        return mPublicLink;
+    }
+
+    public void setPublicLink(String publicLink) {
+        this.mPublicLink = publicLink;
+    }
+
     public long getLocalModificationTimestamp() {
         if (mLocalPath != null && mLocalPath.length() > 0) {
             File f = new File(mLocalPath);
index 8701ebd..2101a68 100644 (file)
@@ -30,28 +30,28 @@ import android.provider.BaseColumns;
  */\r
 public class ProviderMeta {\r
 \r
-    /* These constants are now in MainApp\r
-        public static final String AUTHORITY_FILES = "org.owncloud";\r
-        public static final String DB_FILE = "owncloud.db";\r
-    */\r
     public static final String DB_NAME = "filelist";\r
-    public static final int DB_VERSION = 5;\r
+    public static final int DB_VERSION = 6;\r
 \r
     private ProviderMeta() {\r
     }\r
 \r
     static public class ProviderTableMeta implements BaseColumns {\r
-        public static final String DB_NAME = "filelist";\r
+        public static final String FILE_TABLE_NAME = "filelist";\r
+        public static final String OCSHARES_TABLE_NAME = "ocshares";\r
         public static final Uri CONTENT_URI = Uri.parse("content://"\r
                 + MainApp.getAuthority() + "/");\r
         public static final Uri CONTENT_URI_FILE = Uri.parse("content://"\r
                 + MainApp.getAuthority() + "/file");\r
         public static final Uri CONTENT_URI_DIR = Uri.parse("content://"\r
                 + MainApp.getAuthority() + "/dir");\r
+        public static final Uri CONTENT_URI_SHARE = Uri.parse("content://"\r
+                + MainApp.getAuthority() + "/shares");\r
 \r
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.owncloud.file";\r
         public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.owncloud.file";\r
 \r
+        // Columns of filelist table\r
         public static final String FILE_PARENT = "parent";\r
         public static final String FILE_NAME = "filename";\r
         public static final String FILE_CREATION = "created";\r
@@ -66,9 +66,31 @@ public class ProviderMeta {
         public static final String FILE_LAST_SYNC_DATE_FOR_DATA = "last_sync_date_for_data";\r
         public static final String FILE_KEEP_IN_SYNC = "keep_in_sync";\r
         public static final String FILE_ETAG = "etag";\r
+        public static final String FILE_SHARE_BY_LINK = "share_by_link";\r
+        public static final String FILE_PUBLIC_LINK = "public_link";\r
 \r
-        public static final String DEFAULT_SORT_ORDER = FILE_NAME\r
+        public static final String FILE_DEFAULT_SORT_ORDER = FILE_NAME\r
                 + " collate nocase asc";\r
+        \r
+        // Columns of ocshares table\r
+        public static final String OCSHARES_FILE_SOURCE = "file_source";\r
+        public static final String OCSHARES_ITEM_SOURCE = "item_source";\r
+        public static final String OCSHARES_SHARE_TYPE = "share_type";\r
+        public static final String OCSHARES_SHARE_WITH = "shate_with";\r
+        public static final String OCSHARES_PATH = "path";\r
+        public static final String OCSHARES_PERMISSIONS = "permissions";\r
+        public static final String OCSHARES_SHARED_DATE = "shared_date";\r
+        public static final String OCSHARES_EXPIRATION_DATE = "expiration_date";\r
+        public static final String OCSHARES_TOKEN = "token";\r
+        public static final String OCSHARES_SHARE_WITH_DISPLAY_NAME = "shared_with_display_name";\r
+        public static final String OCSHARES_IS_DIRECTORY = "is_directory";\r
+        public static final String OCSHARES_USER_ID = "user_id";\r
+        public static final String OCSHARES_ID_REMOTE_SHARED = "id_remote_shared";\r
+        public static final String OCSHARES_ACCOUNT_OWNER = "owner_share";\r
+        \r
+        public static final String OCSHARES_DEFAULT_SORT_ORDER = OCSHARES_FILE_SOURCE \r
+                + " collate nocase asc";\r
+        \r
 \r
     }\r
 }\r
diff --git a/src/com/owncloud/android/files/FileHandler.java b/src/com/owncloud/android/files/FileHandler.java
deleted file mode 100644 (file)
index 2eb754d..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.files;
-
-import com.owncloud.android.datamodel.OCFile;
-
-public interface FileHandler {
-
-    /**
-     * TODO
-     */
-    public void openFile(OCFile file);
-
-    
-}
diff --git a/src/com/owncloud/android/files/FileOperationsHelper.java b/src/com/owncloud/android/files/FileOperationsHelper.java
new file mode 100644 (file)
index 0000000..4b37a3b
--- /dev/null
@@ -0,0 +1,163 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.files;
+
+import org.apache.http.protocol.HTTP;
+
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.v4.app.DialogFragment;
+import android.webkit.MimeTypeMap;
+import android.widget.Toast;
+
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.accounts.OwnCloudAccount;
+import com.owncloud.android.lib.network.webdav.WebdavUtils;
+import com.owncloud.android.services.OperationsService;
+import com.owncloud.android.ui.activity.FileActivity;
+import com.owncloud.android.ui.dialog.ActivityChooserDialog;
+import com.owncloud.android.utils.Log_OC;
+
+/**
+ * 
+ * @author masensio
+ * @author David A. Velasco
+ */
+public class FileOperationsHelper {
+
+    private static final String TAG = FileOperationsHelper.class.getName();
+    
+    private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG"; 
+
+    
+    public void openFile(OCFile file, FileActivity callerActivity) {
+        if (file != null) {
+            String storagePath = file.getStoragePath();
+            String encodedStoragePath = WebdavUtils.encodePath(storagePath);
+            
+            Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
+            intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype());
+            intentForSavedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+            
+            Intent intentForGuessedMimeType = null;
+            if (storagePath.lastIndexOf('.') >= 0) {
+                String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
+                if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
+                    intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
+                    intentForGuessedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), guessedMimeType);
+                    intentForGuessedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+                }
+            }
+            
+            Intent chooserIntent = null;
+            if (intentForGuessedMimeType != null) {
+                chooserIntent = Intent.createChooser(intentForGuessedMimeType, callerActivity.getString(R.string.actionbar_open_with));
+            } else {
+                chooserIntent = Intent.createChooser(intentForSavedMimeType, callerActivity.getString(R.string.actionbar_open_with));
+            }
+            
+            callerActivity.startActivity(chooserIntent);
+            
+        } else {
+            Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
+        }
+    }
+    
+
+    public void shareFileWithLink(OCFile file, FileActivity callerActivity) {
+        
+        if (isSharedSupported(callerActivity)) {
+            if (file != null) {
+                String link = "https://fake.url";
+                Intent intent = createShareWithLinkIntent(link);
+                String[] packagesToExclude = new String[] { callerActivity.getPackageName() };
+                DialogFragment chooserDialog = ActivityChooserDialog.newInstance(intent, packagesToExclude, file);
+                chooserDialog.show(callerActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
+                
+            } else {
+                Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
+            }
+            
+        } else {
+            // Show a Message
+            Toast t = Toast.makeText(callerActivity, callerActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG);
+            t.show();
+        }
+    }
+    
+    
+    public void shareFileWithLinkToApp(OCFile file, Intent sendIntent, FileActivity callerActivity) {
+        
+        if (file != null) {
+            callerActivity.showLoadingDialog();
+            
+            Intent service = new Intent(callerActivity, OperationsService.class);
+            service.setAction(OperationsService.ACTION_CREATE_SHARE);
+            service.putExtra(OperationsService.EXTRA_ACCOUNT, callerActivity.getAccount());
+            service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+            service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent);
+            callerActivity.startService(service);
+            
+        } else {
+            Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
+        }
+    }
+    
+    
+    private Intent createShareWithLinkIntent(String link) {
+        Intent intentToShareLink = new Intent(Intent.ACTION_SEND);
+        intentToShareLink.putExtra(Intent.EXTRA_TEXT, link);
+        intentToShareLink.setType(HTTP.PLAIN_TEXT_TYPE);
+        return intentToShareLink; 
+    }
+    
+    
+    /**
+     *  @return 'True' if the server supports the Share API
+     */
+    public boolean isSharedSupported(FileActivity callerActivity) {
+        if (callerActivity.getAccount() != null) {
+            AccountManager accountManager = AccountManager.get(callerActivity);
+            return Boolean.parseBoolean(accountManager.getUserData(callerActivity.getAccount(), OwnCloudAccount.Constants.KEY_SUPPORTS_SHARE_API));
+        }
+        return false;
+    }
+
+    
+    public void unshareFileWithLink(OCFile file, FileActivity callerActivity) {
+        
+        if (isSharedSupported(callerActivity)) {
+            // Unshare the file
+            Intent service = new Intent(callerActivity, OperationsService.class);
+            service.setAction(OperationsService.ACTION_UNSHARE);
+            service.putExtra(OperationsService.EXTRA_ACCOUNT, callerActivity.getAccount());
+            service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+            callerActivity.startService(service);
+            
+            callerActivity.showLoadingDialog();
+            
+        } else {
+            // Show a Message
+            Toast t = Toast.makeText(callerActivity, callerActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG);
+            t.show();
+            
+        }
+    }
+}
index 68c97e4..ade4c61 100644 (file)
@@ -22,9 +22,9 @@ import java.io.File;
 
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
 import com.owncloud.android.operations.SynchronizeFileOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
 import com.owncloud.android.ui.activity.ConflictsResolveActivity;
 import com.owncloud.android.utils.Log_OC;
 
index 11a8c37..47fb491 100644 (file)
@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import com.owncloud.android.R;
+import com.owncloud.android.utils.DisplayUtils;
 
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -101,7 +102,7 @@ public class OCNotificationManager {
         
         switch (type) {
             case NOTIFICATION_SIMPLE:
-                notification = new Notification(R.drawable.icon, data.getText(), System.currentTimeMillis());
+                notification = new Notification(DisplayUtils.getSeasonalIconId(), data.getText(), System.currentTimeMillis());
                 break;
             case NOTIFICATION_PROGRESS:
                 notification = new Notification();
@@ -139,7 +140,7 @@ public class OCNotificationManager {
                                                               false);
                 return true;
             case NOTIFICATION_SIMPLE:
-                pair.mNotificaiton = new Notification(R.drawable.icon,
+                pair.mNotificaiton = new Notification(DisplayUtils.getSeasonalIconId(),
                                                       data.getText(), System.currentTimeMillis());
                 mNM.notify(notification_id, pair.mNotificaiton);
                 return true;
index 232a042..67bd796 100644 (file)
@@ -33,16 +33,18 @@ import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 
-import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
-import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.lib.network.OnDatatransferProgressListener;
+import com.owncloud.android.lib.network.OwnCloudClientFactory;
+import com.owncloud.android.lib.network.OwnCloudClient;
 import com.owncloud.android.operations.DownloadFileOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.utils.FileUtils;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
@@ -78,7 +80,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
     private Looper mServiceLooper;
     private ServiceHandler mServiceHandler;
     private IBinder mBinder;
-    private WebdavClient mDownloadClient = null;
+    private OwnCloudClient mDownloadClient = null;
     private Account mLastAccount = null;
     private FileDataStorageManager mStorageManager;
     
@@ -281,13 +283,6 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
             }
         }
 
-
-        @Override
-        public void onTransferProgress(long progressRate) {
-            // old way, should not be in use any more
-        }
-
-
         @Override
         public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,
                 String fileName) {
@@ -387,7 +382,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
      * Updates the OC File after a successful download.
      */
     private void saveDownloadedFile() {
-        OCFile file = mCurrentDownload.getFile();
+        OCFile file = mStorageManager.getFileById(mCurrentDownload.getFile().getFileId());
         long syncDate = System.currentTimeMillis();
         file.setLastSyncDateForProperties(syncDate);
         file.setLastSyncDateForData(syncDate);
@@ -409,12 +404,12 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
     private void notifyDownloadStart(DownloadFileOperation download) {
         /// create status notification with a progress bar
         mLastPercent = 0;
-        mNotification = new Notification(R.drawable.icon, getString(R.string.downloader_download_in_progress_ticker), System.currentTimeMillis());
+        mNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(R.string.downloader_download_in_progress_ticker), System.currentTimeMillis());
         mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
         mNotification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.progressbar_layout);
         mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, download.getSize() < 0);
         mNotification.contentView.setTextViewText(R.id.status_text, String.format(getString(R.string.downloader_download_in_progress_content), 0, new File(download.getSavePath()).getName()));
-        mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon);
+        mNotification.contentView.setImageViewResource(R.id.status_icon, DisplayUtils.getSeasonalIconId());
         
         /// includes a pending intent in the notification showing the details view of the file
         Intent showDetailsIntent = null;
@@ -436,28 +431,20 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
      * Callback method to update the progress bar in the status notification.
      */
     @Override
-    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName) {
+    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filePath) {
         int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
         if (percent != mLastPercent) {
-          mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, totalToTransfer < 0);
-          String text = String.format(getString(R.string.downloader_download_in_progress_content), percent, fileName);
-          mNotification.contentView.setTextViewText(R.id.status_text, text);
-          mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);
+            mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, totalToTransfer < 0);
+            String fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1);
+            String text = String.format(getString(R.string.downloader_download_in_progress_content), percent, fileName);
+            mNotification.contentView.setTextViewText(R.id.status_text, text);
+            mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);
         }
         mLastPercent = percent;
     }
     
     
     /**
-     * Callback method to update the progress bar in the status notification (old version)
-     */
-    @Override
-    public void onTransferProgress(long progressRate) {
-        // NOTHING TO DO HERE ANYMORE
-    }
-    
-
-    /**
      * Updates the status notification with the result of a download operation.
      * 
      * @param downloadResult    Result of the download operation.
@@ -468,7 +455,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
         if (!downloadResult.isCancelled()) {
             int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : R.string.downloader_download_failed_ticker;
             int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content;
-            Notification finalNotification = new Notification(R.drawable.icon, getString(tickerId), System.currentTimeMillis());
+            Notification finalNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(tickerId), System.currentTimeMillis());
             finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
             boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
                                                 // (downloadResult.isTemporalRedirection() && downloadResult.isIdPRedirection()
index 61f6179..e9a4637 100644 (file)
@@ -28,36 +28,32 @@ import java.util.Vector;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import org.apache.http.HttpStatus;
-import org.apache.jackrabbit.webdav.DavConstants;
-import org.apache.jackrabbit.webdav.MultiStatus;
-import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
-
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.db.DbHandler;
-import com.owncloud.android.operations.ChunkedUploadFileOperation;
 import com.owncloud.android.operations.CreateFolderOperation;
-import com.owncloud.android.operations.ExistenceCheckOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteFile;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
 import com.owncloud.android.operations.UploadFileOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
-import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
-import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
-import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.remote.ExistenceCheckRemoteOperation;
+import com.owncloud.android.lib.operations.remote.ReadRemoteFileOperation;
+import com.owncloud.android.lib.utils.FileUtils;
+import com.owncloud.android.lib.utils.OwnCloudVersion;
+import com.owncloud.android.lib.network.OnDatatransferProgressListener;
+import com.owncloud.android.lib.accounts.OwnCloudAccount;
+import com.owncloud.android.lib.network.OwnCloudClientFactory;
+import com.owncloud.android.lib.network.OwnCloudClient;
 import com.owncloud.android.ui.activity.FailedUploadActivity;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.activity.InstantUploadActivity;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
@@ -113,7 +109,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
     private Looper mServiceLooper;
     private ServiceHandler mServiceHandler;
     private IBinder mBinder;
-    private WebdavClient mUploadClient = null;
+    private OwnCloudClient mUploadClient = null;
     private Account mLastAccount = null;
     private FileDataStorageManager mStorageManager;
 
@@ -251,7 +247,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                 files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i], ((mimeTypes != null) ? mimeTypes[i]
                         : (String) null), storageManager);
                 if (files[i] == null) {
-                    // TODO @andomaex add failure Notiification
+                    // TODO @andomaex add failure Notification
                     return Service.START_NOT_STICKY;
                 }
             }
@@ -265,12 +261,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
         try {
             for (int i = 0; i < files.length; i++) {
                 uploadKey = buildRemoteName(account, files[i].getRemotePath());
-                if (chunked) {
-                    newUpload = new ChunkedUploadFileOperation(account, files[i], isInstant, forceOverwrite,
-                            localAction);
-                } else {
-                    newUpload = new UploadFileOperation(account, files[i], isInstant, forceOverwrite, localAction);
-                }
+                newUpload = new UploadFileOperation(account, files[i], chunked, isInstant, forceOverwrite, localAction, 
+                        getApplicationContext());
                 if (isInstant) {
                     newUpload.setRemoteFolderToBeCreated();
                 }
@@ -426,12 +418,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
 
 
         @Override
-        public void onTransferProgress(long progressRate) {
-            // old way, should not be in use any more
-        }
-
-
-        @Override
         public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,
                 String fileName) {
             String key = buildRemoteName(mCurrentUpload.getAccount(), mCurrentUpload.getFile());
@@ -559,7 +545,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
      *  @return  An {@link OCFile} instance corresponding to the folder where the file will be uploaded.
      */
     private RemoteOperationResult grantFolderExistence(String pathToGrant) {
-        RemoteOperation operation = new ExistenceCheckOperation(pathToGrant, this, false);
+        RemoteOperation operation = new ExistenceCheckRemoteOperation(pathToGrant, this, false);
         RemoteOperationResult result = operation.execute(mUploadClient);
         if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && mCurrentUpload.isRemoteFolderToBeCreated()) {
             operation = new CreateFolderOperation( pathToGrant,
@@ -611,43 +597,21 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
      */
     private void saveUploadedFile() {
         OCFile file = mCurrentUpload.getFile();
+        if (file.fileExists()) {
+            file = mStorageManager.getFileById(file.getFileId());
+        }
         long syncDate = System.currentTimeMillis();
         file.setLastSyncDateForData(syncDate);
 
-        // / new PROPFIND to keep data consistent with server in theory, should
-        // return the same we already have
-        PropFindMethod propfind = null;
-        RemoteOperationResult result = null;
-        try {
-            propfind = new PropFindMethod(mUploadClient.getBaseUri() + WebdavUtils.encodePath(mCurrentUpload.getRemotePath()),
-                    DavConstants.PROPFIND_ALL_PROP,
-                    DavConstants.DEPTH_0);
-            int status = mUploadClient.executeMethod(propfind);
-            boolean isMultiStatus = (status == HttpStatus.SC_MULTI_STATUS);
-            if (isMultiStatus) {
-                MultiStatus resp = propfind.getResponseBodyAsMultiStatus();
-                WebdavEntry we = new WebdavEntry(resp.getResponses()[0], mUploadClient.getBaseUri().getPath());
-                updateOCFile(file, we);
-                file.setLastSyncDateForProperties(syncDate);
-
-            } else {
-                mUploadClient.exhaustResponse(propfind.getResponseBodyAsStream());
-            }
-
-            result = new RemoteOperationResult(isMultiStatus, status, propfind.getResponseHeaders());
-            Log_OC.i(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": "
-                    + result.getLogMessage());
-
-        } catch (Exception e) {
-            result = new RemoteOperationResult(e);
-            Log_OC.e(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": "
-                    + result.getLogMessage(), e);
-
-        } finally {
-            if (propfind != null)
-                propfind.releaseConnection();
+        // new PROPFIND to keep data consistent with server 
+        // in theory, should return the same we already have
+        ReadRemoteFileOperation operation = new ReadRemoteFileOperation(mCurrentUpload.getRemotePath());
+        RemoteOperationResult result = operation.execute(mUploadClient);
+        if (result.isSuccess()) {
+            updateOCFile(file, (RemoteFile) result.getData().get(0));
+            file.setLastSyncDateForProperties(syncDate);
         }
-
+        
         // / maybe this would be better as part of UploadFileOperation... or
         // maybe all this method
         if (mCurrentUpload.wasRenamed()) {
@@ -664,13 +628,13 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
         mStorageManager.saveFile(file);
     }
 
-    private void updateOCFile(OCFile file, WebdavEntry we) {
-        file.setCreationTimestamp(we.createTimestamp());
-        file.setFileLength(we.contentLength());
-        file.setMimetype(we.contentType());
-        file.setModificationTimestamp(we.modifiedTimestamp());
-        file.setModificationTimestampAtLastSyncForData(we.modifiedTimestamp());
-        // file.setEtag(mCurrentUpload.getEtag());    // TODO Etag, where available
+    private void updateOCFile(OCFile file, RemoteFile remoteFile) {
+        file.setCreationTimestamp(remoteFile.getCreationTimestamp());
+        file.setFileLength(remoteFile.getLength());
+        file.setMimetype(remoteFile.getMimeType());
+        file.setModificationTimestamp(remoteFile.getModifiedTimestamp());
+        file.setModificationTimestampAtLastSyncForData(remoteFile.getModifiedTimestamp());
+        // file.setEtag(remoteFile.getEtag());    // TODO Etag, where available
     }
 
     private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType,
@@ -714,7 +678,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
     private void notifyUploadStart(UploadFileOperation upload) {
         // / create status notification with a progress bar
         mLastPercent = 0;
-        mNotification = new Notification(R.drawable.icon, getString(R.string.uploader_upload_in_progress_ticker),
+        mNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(R.string.uploader_upload_in_progress_ticker),
                 System.currentTimeMillis());
         mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
         mDefaultNotificationContentView = mNotification.contentView;
@@ -723,7 +687,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
         mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, false);
         mNotification.contentView.setTextViewText(R.id.status_text,
                 String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName()));
-        mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon);
+        mNotification.contentView.setImageViewResource(R.id.status_icon, DisplayUtils.getSeasonalIconId());
         
         /// includes a pending intent in the notification showing the details view of the file
         Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class);
@@ -740,10 +704,11 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
      * Callback method to update the progress bar in the status notification
      */
     @Override
-    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName) {
+    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filePath) {
         int percent = (int) (100.0 * ((double) totalTransferredSoFar) / ((double) totalToTransfer));
         if (percent != mLastPercent) {
             mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, false);
+            String fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1);
             String text = String.format(getString(R.string.uploader_upload_in_progress_content), percent, fileName);
             mNotification.contentView.setTextViewText(R.id.status_text, text);
             mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotification);
@@ -752,15 +717,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
     }
 
     /**
-     * Callback method to update the progress bar in the status notification
-     * (old version)
-     */
-    @Override
-    public void onTransferProgress(long progressRate) {
-        // NOTHING TO DO HERE ANYMORE
-    }
-
-    /**
      * Updates the status notification with the result of an upload operation.
      * 
      * @param uploadResult Result of the upload operation.
@@ -791,6 +747,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             }
             showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, upload.getFile());
             showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount());
+            showDetailsIntent.putExtra(FileActivity.EXTRA_FROM_NOTIFICATION, true);
             showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
             mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
                     (int) System.currentTimeMillis(), showDetailsIntent, 0);
@@ -810,7 +767,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
 
             // / fail -> explicit failure notification
             mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
-            Notification finalNotification = new Notification(R.drawable.icon,
+            Notification finalNotification = new Notification(DisplayUtils.getSeasonalIconId(),
                     getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis());
             finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
             String content = null;
diff --git a/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java b/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java
deleted file mode 100644 (file)
index fd8a5a6..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.operations;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileChannel;
-import java.util.Random;
-
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.methods.PutMethod;
-
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
-import com.owncloud.android.oc_framework.network.webdav.ChunkFromFileChannelRequestEntity;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.utils.Log_OC;
-
-
-import android.accounts.Account;
-
-
-public class ChunkedUploadFileOperation extends UploadFileOperation {
-    
-    private static final long CHUNK_SIZE = 1024000;
-    private static final String OC_CHUNKED_HEADER = "OC-Chunked";
-    private static final String TAG = ChunkedUploadFileOperation.class.getSimpleName();
-
-    public ChunkedUploadFileOperation(  Account account,
-                                        OCFile file,
-                                        boolean isInstant, 
-                                        boolean forceOverwrite,
-                                        int localBehaviour) {
-        
-        super(account, file, isInstant, forceOverwrite, localBehaviour);
-    }
-
-    @Override
-    protected int uploadFile(WebdavClient client) throws HttpException, IOException {
-        int status = -1;
-
-        FileChannel channel = null;
-        RandomAccessFile raf = null;
-        try {
-            File file = new File(getStoragePath());
-            raf = new RandomAccessFile(file, "r");
-            channel = raf.getChannel();
-            mEntity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file);
-            ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners());
-            long offset = 0;
-            String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(getRemotePath()) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
-            long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
-            for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
-                if (mPutMethod != null) {
-                    mPutMethod.releaseConnection();    // let the connection available for other methods
-                }
-                mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
-                mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
-                ((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset);
-                mPutMethod.setRequestEntity(mEntity);
-                status = client.executeMethod(mPutMethod);
-                client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
-                Log_OC.d(TAG, "Upload of " + getStoragePath() + " to " + getRemotePath() + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status);
-                if (!isSuccess(status))
-                    break;
-            }
-            
-        } finally {
-            if (channel != null)
-                channel.close();
-            if (raf != null)
-                raf.close();
-            if (mPutMethod != null)
-                mPutMethod.releaseConnection();    // let the connection available for other methods
-        }
-        return status;
-    }
-
-}
index 1cf1f84..9ba118e 100644 (file)
@@ -19,11 +19,11 @@ package com.owncloud.android.operations;
 
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.operations.remote.CreateRemoteFolderOperation;
-import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.remote.CreateRemoteFolderOperation;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.Log_OC;
 
@@ -58,7 +58,7 @@ public class CreateFolderOperation extends RemoteOperation implements OnRemoteOp
 
 
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
+    protected RemoteOperationResult run(OwnCloudClient client) {
         CreateRemoteFolderOperation operation = new CreateRemoteFolderOperation(mRemotePath, mCreateFullPath);
         RemoteOperationResult result =  operation.execute(client);
         
diff --git a/src/com/owncloud/android/operations/CreateShareOperation.java b/src/com/owncloud/android/operations/CreateShareOperation.java
new file mode 100644 (file)
index 0000000..7b64653
--- /dev/null
@@ -0,0 +1,127 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.operations;
+
+/**
+ * Creates a new share from a given file
+ * 
+ * @author masensio
+ *
+ */
+
+import android.content.Intent;
+
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.OCShare;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.ShareType;
+import com.owncloud.android.lib.operations.remote.CreateShareRemoteOperation;
+import com.owncloud.android.lib.utils.FileUtils;
+import com.owncloud.android.operations.common.SyncOperation;
+import com.owncloud.android.utils.Log_OC;
+
+public class CreateShareOperation extends SyncOperation {
+
+    private static final String TAG = CreateShareOperation.class.getSimpleName();
+
+    protected FileDataStorageManager mStorageManager;
+
+    private String mPath;
+    private ShareType mShareType;
+    private String mShareWith;
+    private boolean mPublicUpload;
+    private String mPassword;
+    private int mPermissions;
+    private Intent mSendIntent;
+
+    /**
+     * Constructor
+     * @param path          Full path of the file/folder being shared. Mandatory argument
+     * @param shareType     \910\92 = user, \911\92 = group, \913\92 = Public link. Mandatory argument
+     * @param shareWith     User/group ID with who the file should be shared.  This is mandatory for shareType of 0 or 1
+     * @param publicUpload  If \91false\92 (default) public cannot upload to a public shared folder. 
+     *                      If \91true\92 public can upload to a shared folder. Only available for public link shares
+     * @param password      Password to protect a public link share. Only available for public link shares
+     * @param permissions   1 - Read only \96 Default for \93public\94 shares
+     *                      2 - Update
+     *                      4 - Create
+     *                      8 - Delete
+     *                      16- Re-share
+     *                      31- All above \96 Default for \93private\94 shares
+     *                      For user or group shares.
+     *                      To obtain combinations, add the desired values together.  
+     *                      For instance, for \93Re-Share\94\93delete\94\93read\94\93update\94, add 16+8+2+1 = 27.
+     */
+    public CreateShareOperation(String path, ShareType shareType, String shareWith, boolean publicUpload, 
+            String password, int permissions, Intent sendIntent) {
+
+        mPath = path;
+        mShareType = shareType;
+        mShareWith = shareWith;
+        mPublicUpload = publicUpload;
+        mPassword = password;
+        mPermissions = permissions;
+        mSendIntent = sendIntent;
+    }
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+        CreateShareRemoteOperation operation = new CreateShareRemoteOperation(mPath, mShareType, mShareWith, mPublicUpload, mPassword, mPermissions);
+        RemoteOperationResult result = operation.execute(client);
+
+        if (result.isSuccess()) {
+
+            if (result.getData().size() > 0) {
+                OCShare share = (OCShare) result.getData().get(0);
+
+                // Update DB with the response
+                share.setPath(mPath);
+                if (mPath.endsWith(FileUtils.PATH_SEPARATOR)) {
+                    share.setIsFolder(true);
+                } else {
+                    share.setIsFolder(false);
+                }
+                share.setPermissions(mPermissions);
+                
+                getStorageManager().saveShare(share);
+                
+                // Update OCFile with data from share: ShareByLink  and publicLink
+                OCFile file = getStorageManager().getFileByPath(mPath);
+                if (file!=null) {
+                    mSendIntent.putExtra(Intent.EXTRA_TEXT, share.getShareLink());
+                    file.setPublicLink(share.getShareLink());
+                    file.setShareByLink(true);
+                    getStorageManager().saveFile(file);
+                    Log_OC.d(TAG, "Public Link = " + file.getPublicLink());
+
+                }
+            }
+        }
+
+
+        return result;
+    }
+    
+    
+    public Intent getSendIntent() {
+        return mSendIntent;
+    }
+
+}
index eb45d4b..04011c1 100644 (file)
 
 package com.owncloud.android.operations;
 
-import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.methods.GetMethod;
-import org.apache.http.HttpStatus;
 
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.oc_framework.operations.OperationCancelledException;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.lib.network.OnDatatransferProgressListener;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.remote.DownloadRemoteFileOperation;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.Log_OC;
 
@@ -46,9 +35,10 @@ import android.accounts.Account;
 import android.webkit.MimeTypeMap;
 
 /**
- * Remote operation performing the download of a file to an ownCloud server
+ * Remote mDownloadOperation performing the download of a file to an ownCloud server
  * 
  * @author David A. Velasco
+ * @author masensio
  */
 public class DownloadFileOperation extends RemoteOperation {
     
@@ -57,9 +47,9 @@ public class DownloadFileOperation extends RemoteOperation {
     private Account mAccount;
     private OCFile mFile;
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
-    private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
     private long mModificationTimestamp = 0;
-    private GetMethod mGet;
+    
+    private DownloadRemoteFileOperation mDownloadOperation;
 
     
     public DownloadFileOperation(Account account, OCFile file) {
@@ -70,6 +60,7 @@ public class DownloadFileOperation extends RemoteOperation {
         
         mAccount = account;
         mFile = file;
+        
     }
 
 
@@ -93,6 +84,10 @@ public class DownloadFileOperation extends RemoteOperation {
         return FileStorageUtils.getTemporalPath(mAccount.name) + mFile.getRemotePath();
     }
     
+    public String getTmpFolder() {
+        return FileStorageUtils.getTemporalPath(mAccount.name);
+    }
+    
     public String getRemotePath() {
         return mFile.getRemotePath();
     }
@@ -121,22 +116,9 @@ public class DownloadFileOperation extends RemoteOperation {
     public long getModificationTimestamp() {
         return (mModificationTimestamp > 0) ? mModificationTimestamp : mFile.getModificationTimestamp();
     }
-    
-    
-    public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.add(listener);
-        }
-    }
-    
-    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.remove(listener);
-        }
-    }
 
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
+    protected RemoteOperationResult run(OwnCloudClient client) {
         RemoteOperationResult result = null;
         File newFile = null;
         boolean moved = true;
@@ -144,93 +126,46 @@ public class DownloadFileOperation extends RemoteOperation {
         /// download will be performed to a temporal file, then moved to the final location
         File tmpFile = new File(getTmpPath());
         
+        String tmpFolder =  getTmpFolder();
+        
         /// perform the download
-        try {
-            tmpFile.getParentFile().mkdirs();
-            int status = downloadFile(client, tmpFile);
-            if (isSuccess(status)) {
-                newFile = new File(getSavePath());
-                newFile.getParentFile().mkdirs();
-                moved = tmpFile.renameTo(newFile);
-            }
+        mDownloadOperation = new DownloadRemoteFileOperation(mFile.getRemotePath(), tmpFolder);
+        Iterator<OnDatatransferProgressListener> listener = mDataTransferListeners.iterator();
+        while (listener.hasNext()) {
+            mDownloadOperation.addDatatransferProgressListener(listener.next());
+        }
+        result = mDownloadOperation.execute(client);
+        
+        if (result.isSuccess()) {
+            mModificationTimestamp = mDownloadOperation.getModificationTimestamp();
+            newFile = new File(getSavePath());
+            newFile.getParentFile().mkdirs();
+            moved = tmpFile.renameTo(newFile);
+        
             if (!moved)
                 result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED);
-            else
-                result = new RemoteOperationResult(isSuccess(status), status, (mGet != null ? mGet.getResponseHeaders() : null));
-            Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage());
-            
-        } catch (Exception e) {
-            result = new RemoteOperationResult(e);
-            Log_OC.e(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage(), e);
         }
+        Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage());
+        
         
         return result;
     }
 
-    
-    public boolean isSuccess(int status) {
-        return (status == HttpStatus.SC_OK);
+    public void cancel() {
+        mDownloadOperation.cancel();
     }
-    
-    
-    protected int downloadFile(WebdavClient client, File targetFile) throws HttpException, IOException, OperationCancelledException {
-        int status = -1;
-        boolean savedFile = false;
-        mGet = new GetMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath()));
-        Iterator<OnDatatransferProgressListener> it = null;
-        
-        FileOutputStream fos = null;
-        try {
-            status = client.executeMethod(mGet);
-            if (isSuccess(status)) {
-                targetFile.createNewFile();
-                BufferedInputStream bis = new BufferedInputStream(mGet.getResponseBodyAsStream());
-                fos = new FileOutputStream(targetFile);
-                long transferred = 0;
 
-                byte[] bytes = new byte[4096];
-                int readResult = 0;
-                while ((readResult = bis.read(bytes)) != -1) {
-                    synchronized(mCancellationRequested) {
-                        if (mCancellationRequested.get()) {
-                            mGet.abort();
-                            throw new OperationCancelledException();
-                        }
-                    }
-                    fos.write(bytes, 0, readResult);
-                    transferred += readResult;
-                    synchronized (mDataTransferListeners) {
-                        it = mDataTransferListeners.iterator();
-                        while (it.hasNext()) {
-                            it.next().onTransferProgress(readResult, transferred, mFile.getFileLength(), targetFile.getName());
-                        }
-                    }
-                }
-                savedFile = true;
-                Header modificationTime = mGet.getResponseHeader("Last-Modified");
-                if (modificationTime != null) {
-                    Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue());
-                    mModificationTimestamp = (d != null) ? d.getTime() : 0;
-                }
-                
-            } else {
-                client.exhaustResponse(mGet.getResponseBodyAsStream());
-            }
-                
-        } finally {
-            if (fos != null) fos.close();
-            if (!savedFile && targetFile.exists()) {
-                targetFile.delete();
-            }
-            mGet.releaseConnection();    // let the connection available for other methods
+
+    public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
+        synchronized (mDataTransferListeners) {
+            mDataTransferListeners.add(listener);
         }
-        return status;
     }
-
     
-    public void cancel() {
-        mCancellationRequested.set(true);   // atomic set; there is no need of synchronizing it
+    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+        synchronized (mDataTransferListeners) {
+            mDataTransferListeners.remove(listener);
+        }
     }
-
-
+    
 }
diff --git a/src/com/owncloud/android/operations/ExistenceCheckOperation.java b/src/com/owncloud/android/operations/ExistenceCheckOperation.java
deleted file mode 100644 (file)
index d92190c..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012 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.operations;
-
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.methods.HeadMethod;
-
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.utils.Log_OC;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-
-/**
- * Operation to check the existence or absence of a path in a remote server.
- * 
- * @author David A. Velasco
- */
-public class ExistenceCheckOperation extends RemoteOperation {
-    
-    /** Maximum time to wait for a response from the server in MILLISECONDs.  */
-    public static final int TIMEOUT = 10000;
-    
-    private static final String TAG = ExistenceCheckOperation.class.getSimpleName();
-    
-    private String mPath;
-    private Context mContext;
-    private boolean mSuccessIfAbsent;
-
-    
-    /**
-     * Full constructor. Success of the operation will depend upon the value of successIfAbsent.
-     * 
-     * @param path              Path to append to the URL owned by the client instance.
-     * @param context           Android application context.
-     * @param successIfAbsent   When 'true', the operation finishes in success if the path does NOT exist in the remote server (HTTP 404).
-     */
-    public ExistenceCheckOperation(String path, Context context, boolean successIfAbsent) {
-        mPath = (path != null) ? path : "";
-        mContext = context;
-        mSuccessIfAbsent = successIfAbsent;
-    }
-    
-
-       @Override
-       protected RemoteOperationResult run(WebdavClient client) {
-        if (!isOnline()) {
-            return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION);
-        }
-        RemoteOperationResult result = null;
-        HeadMethod head = null;
-        try {
-            head = new HeadMethod(client.getBaseUri() + WebdavUtils.encodePath(mPath));
-            int status = client.executeMethod(head, TIMEOUT, TIMEOUT);
-            client.exhaustResponse(head.getResponseBodyAsStream());
-            boolean success = (status == HttpStatus.SC_OK && !mSuccessIfAbsent) || (status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent);
-            result = new RemoteOperationResult(success, status, head.getResponseHeaders());
-            Log_OC.d(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + "finished with HTTP status " + status + (!success?"(FAIL)":""));
-            
-        } catch (Exception e) {
-            result = new RemoteOperationResult(e);
-            Log_OC.e(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " + result.getLogMessage(), result.getException());
-            
-        } finally {
-            if (head != null)
-                head.releaseConnection();
-        }
-        return result;
-       }
-
-    private boolean isOnline() {
-        ConnectivityManager cm = (ConnectivityManager) mContext
-                .getSystemService(Context.CONNECTIVITY_SERVICE);
-        return cm != null && cm.getActiveNetworkInfo() != null
-                && cm.getActiveNetworkInfo().isConnectedOrConnecting();
-    }
-
-
-}
diff --git a/src/com/owncloud/android/operations/GetSharesForFileOperation.java b/src/com/owncloud/android/operations/GetSharesForFileOperation.java
new file mode 100644 (file)
index 0000000..fd2dab7
--- /dev/null
@@ -0,0 +1,79 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+package com.owncloud.android.operations;
+
+import java.util.ArrayList;
+
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.OCShare;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.remote.GetSharesForFileRemoteOperation;
+import com.owncloud.android.operations.common.SyncOperation;
+import com.owncloud.android.utils.Log_OC;
+
+/**
+ * Provide a list shares for a specific file.  
+ * 
+ * @author masensio
+ *
+ */
+public class GetSharesForFileOperation extends SyncOperation {
+    
+    private static final String TAG = GetSharesForFileOperation.class.getSimpleName();
+    
+    private String mPath;
+    private boolean mReshares;
+    private boolean mSubfiles;
+
+    /**
+     * Constructor
+     * 
+     * @param path      Path to file or folder
+     * @param reshares  If set to \91false\92 (default), only shares from the current user are returned
+     *                  If set to \91true\92, all shares from the given file are returned
+     * @param subfiles  If set to \91false\92 (default), lists only the folder being shared
+     *                  If set to \91true\92, all shared files within the folder are returned.
+     */
+    public GetSharesForFileOperation(String path, boolean reshares, boolean subfiles) {
+        mPath = path;
+        mReshares = reshares;
+        mSubfiles = subfiles;
+    }
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+        GetSharesForFileRemoteOperation operation = new GetSharesForFileRemoteOperation(mPath, mReshares, mSubfiles);
+        RemoteOperationResult result = operation.execute(client);
+
+        if (result.isSuccess()) {
+
+            // Update DB with the response
+            Log_OC.d(TAG, "File = " + mPath + " Share list size  " + result.getData().size());
+            ArrayList<OCShare> shares = new ArrayList<OCShare>();
+            for(Object obj: result.getData()) {
+                shares.add((OCShare) obj);
+            }
+
+            getStorageManager().saveSharesDB(shares);
+        }
+
+        return result;
+    }
+
+}
diff --git a/src/com/owncloud/android/operations/GetSharesOperation.java b/src/com/owncloud/android/operations/GetSharesOperation.java
new file mode 100644 (file)
index 0000000..eb22159
--- /dev/null
@@ -0,0 +1,61 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.operations;
+
+import java.util.ArrayList;
+
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.OCShare;
+import com.owncloud.android.lib.operations.remote.GetRemoteSharesOperation;
+import com.owncloud.android.operations.common.SyncOperation;
+import com.owncloud.android.utils.Log_OC;
+
+/**
+ * Access to remote operation to get the share files/folders
+ * Save the data in Database
+ * 
+ * @author masensio
+ * @author David A. Velasco
+ */
+
+public class GetSharesOperation extends SyncOperation {
+
+    private static final String TAG = GetSharesOperation.class.getSimpleName();
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+        GetRemoteSharesOperation operation = new GetRemoteSharesOperation();
+        RemoteOperationResult result = operation.execute(client);
+
+        if (result.isSuccess()) {
+
+            // Update DB with the response
+            Log_OC.d(TAG, "Share list size = " + result.getData().size());
+            ArrayList<OCShare> shares = new ArrayList<OCShare>();
+            for(Object obj: result.getData()) {
+                shares.add((OCShare) obj);
+            }
+
+            getStorageManager().saveSharesDB(shares);
+        }
+
+        return result;
+    }
+
+}
index d392645..45238ba 100644 (file)
@@ -9,10 +9,10 @@ import org.json.JSONException;
 import org.json.JSONObject;
 
 import com.owncloud.android.authentication.OAuth2Constants;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
 import com.owncloud.android.utils.Log_OC;
 
 
@@ -48,7 +48,7 @@ public class OAuth2GetAccessToken extends RemoteOperation {
     }
     
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
+    protected RemoteOperationResult run(OwnCloudClient client) {
         RemoteOperationResult result = null;
         PostMethod postMethod = null;
         
@@ -70,7 +70,7 @@ public class OAuth2GetAccessToken extends RemoteOperation {
                 nameValuePairs[3] = new NameValuePair(OAuth2Constants.KEY_CLIENT_ID, mClientId);
                 //nameValuePairs[4] = new NameValuePair(OAuth2Constants.KEY_SCOPE, mOAuth2ParsedAuthorizationResponse.get(OAuth2Constants.KEY_SCOPE));         
                 
-                postMethod = new PostMethod(client.getBaseUri().toString());
+                postMethod = new PostMethod(client.getWebdavUri().toString());
                 postMethod.setRequestBody(nameValuePairs);
                 int status = client.executeMethod(postMethod);
                 
@@ -99,16 +99,16 @@ public class OAuth2GetAccessToken extends RemoteOperation {
                 postMethod.releaseConnection();    // let the connection available for other methods
             
             if (result.isSuccess()) {
-                Log_OC.i(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage());
+                Log_OC.i(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getWebdavUri() + ": " + result.getLogMessage());
             
             } else if (result.getException() != null) {
-                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage(), result.getException());
+                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getWebdavUri() + ": " + result.getLogMessage(), result.getException());
                 
             } else if (result.getCode() == ResultCode.OAUTH2_ERROR) {
-                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + ((mResultTokenMap != null) ? mResultTokenMap.get(OAuth2Constants.KEY_ERROR) : "NULL"));
+                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getWebdavUri() + ": " + ((mResultTokenMap != null) ? mResultTokenMap.get(OAuth2Constants.KEY_ERROR) : "NULL"));
                     
             } else {
-                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage());
+                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getWebdavUri() + ": " + result.getLogMessage());
             }
         }
         
diff --git a/src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java b/src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java
deleted file mode 100644 (file)
index 8209685..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.operations;
-
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.methods.GetMethod;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
-import com.owncloud.android.utils.Log_OC;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.Uri;
-
-public class OwnCloudServerCheckOperation extends RemoteOperation {
-    
-    /** Maximum time to wait for a response from the server when the connection is being tested, in MILLISECONDs.  */
-    public static final int TRY_CONNECTION_TIMEOUT = 5000;
-    
-    private static final String TAG = OwnCloudServerCheckOperation.class.getSimpleName();
-    
-    private String mUrl;
-    private RemoteOperationResult mLatestResult;
-    private Context mContext;
-    private OwnCloudVersion mOCVersion;
-
-    public OwnCloudServerCheckOperation(String url, Context context) {
-        mUrl = url;
-        mContext = context;
-        mOCVersion = null;
-    }
-    
-    public OwnCloudVersion getDiscoveredVersion() {
-        return mOCVersion;
-    }
-
-    private boolean tryConnection(WebdavClient wc, String urlSt) {
-        boolean retval = false;
-        GetMethod get = null;
-        try {
-            get = new GetMethod(urlSt);
-            int status = wc.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT);
-            String response = get.getResponseBodyAsString();
-            if (status == HttpStatus.SC_OK) {
-                JSONObject json = new JSONObject(response);
-                if (!json.getBoolean("installed")) {
-                    mLatestResult = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
-                } else {
-                    mOCVersion = new OwnCloudVersion(json.getString("version"));
-                    if (!mOCVersion.isVersionValid()) {
-                        mLatestResult = new RemoteOperationResult(RemoteOperationResult.ResultCode.BAD_OC_VERSION);
-                        
-                    } else {
-                        mLatestResult = new RemoteOperationResult(urlSt.startsWith("https://") ? 
-                                                                    RemoteOperationResult.ResultCode.OK_SSL : 
-                                                                    RemoteOperationResult.ResultCode.OK_NO_SSL
-                            );
-
-                        retval = true;
-                    }
-                }
-                
-            } else {
-                mLatestResult = new RemoteOperationResult(false, status, get.getResponseHeaders());
-            }
-
-        } catch (JSONException e) {
-            mLatestResult = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
-            
-        } catch (Exception e) {
-            mLatestResult = new RemoteOperationResult(e);
-            
-        } finally {
-            if (get != null)
-                get.releaseConnection();
-        }
-        
-        if (mLatestResult.isSuccess()) {
-            Log_OC.i(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage());
-            
-        } else if (mLatestResult.getException() != null) {
-            Log_OC.e(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage(), mLatestResult.getException());
-            
-        } else {
-            Log_OC.e(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage());
-        }
-
-        return retval;
-    }
-
-    private boolean isOnline() {
-        ConnectivityManager cm = (ConnectivityManager) mContext
-                .getSystemService(Context.CONNECTIVITY_SERVICE);
-        return cm != null && cm.getActiveNetworkInfo() != null
-                && cm.getActiveNetworkInfo().isConnectedOrConnecting();
-    }
-
-       @Override
-       protected RemoteOperationResult run(WebdavClient client) {
-        if (!isOnline()) {
-               return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION);
-        }
-        if (mUrl.startsWith("http://") || mUrl.startsWith("https://")) {
-            tryConnection(client, mUrl + AccountUtils.STATUS_PATH);
-            
-        } else {
-            client.setBaseUri(Uri.parse("https://" + mUrl + AccountUtils.STATUS_PATH));
-            boolean httpsSuccess = tryConnection(client, "https://" + mUrl + AccountUtils.STATUS_PATH); 
-            if (!httpsSuccess && !mLatestResult.isSslRecoverableException()) {
-                Log_OC.d(TAG, "establishing secure connection failed, trying non secure connection");
-                client.setBaseUri(Uri.parse("http://" + mUrl + AccountUtils.STATUS_PATH));
-                tryConnection(client, "http://" + mUrl + AccountUtils.STATUS_PATH);
-            }
-        }
-        return mLatestResult;
-       }
-       
-}
index 34926af..5cd668c 100644 (file)
 
 package com.owncloud.android.operations;
 
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
-
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.utils.Log_OC;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.remote.RemoveRemoteFileOperation;
 
 
 /**
@@ -36,10 +33,7 @@ import com.owncloud.android.utils.Log_OC;
  */
 public class RemoveFileOperation extends RemoteOperation {
     
-    private static final String TAG = RemoveFileOperation.class.getSimpleName();
-
-    private static final int REMOVE_READ_TIMEOUT = 10000;
-    private static final int REMOVE_CONNECTION_TIMEOUT = 5000;
+    // private static final String TAG = RemoveFileOperation.class.getSimpleName();
     
     OCFile mFileToRemove;
     boolean mDeleteLocalCopy;
@@ -69,34 +63,22 @@ public class RemoveFileOperation extends RemoteOperation {
         return mFileToRemove;
     }
     
-    
     /**
      * Performs the remove operation
      * 
      * @param   client      Client object to communicate with the remote ownCloud server.
      */
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
+    protected RemoteOperationResult run(OwnCloudClient client) {
         RemoteOperationResult result = null;
-        DeleteMethod delete = null;
-        try {
-            delete = new DeleteMethod(client.getBaseUri() + WebdavUtils.encodePath(mFileToRemove.getRemotePath()));
-            int status = client.executeMethod(delete, REMOVE_READ_TIMEOUT, REMOVE_CONNECTION_TIMEOUT);
-            if (delete.succeeded() || status == HttpStatus.SC_NOT_FOUND) {
-                mDataStorageManager.removeFile(mFileToRemove, true, mDeleteLocalCopy);
-            }
-            delete.getResponseBodyAsString();   // exhaust the response, although not interesting
-            result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status, delete.getResponseHeaders());
-            Log_OC.i(TAG, "Remove " + mFileToRemove.getRemotePath() + ": " + result.getLogMessage());
-            
-        } catch (Exception e) {
-            result = new RemoteOperationResult(e);
-            Log_OC.e(TAG, "Remove " + mFileToRemove.getRemotePath() + ": " + result.getLogMessage(), e);
-            
-        } finally {
-            if (delete != null)
-                delete.releaseConnection();
+        
+        RemoveRemoteFileOperation operation = new RemoveRemoteFileOperation(mFileToRemove.getRemotePath());
+        result = operation.execute(client);
+        
+        if (result.isSuccess() || result.getCode() == ResultCode.FILE_NOT_FOUND) {
+            mDataStorageManager.removeFile(mFileToRemove, true, mDeleteLocalCopy);
         }
+        
         return result;
     }
     
index 9aa573a..d77020c 100644 (file)
@@ -20,14 +20,13 @@ package com.owncloud.android.operations;
 import java.io.File;
 import java.io.IOException;
 
-import org.apache.commons.httpclient.HttpException;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.oc_framework.operations.remote.RenameRemoteFileOperation;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.remote.RenameRemoteFileOperation;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.Log_OC;
 
@@ -78,7 +77,7 @@ public class RenameFileOperation extends RemoteOperation {
      * @param   client      Client object to communicate with the remote ownCloud server.
      */
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
+    protected RemoteOperationResult run(OwnCloudClient client) {
         RemoteOperationResult result = null;
         
         // check if the new name is valid in the local file system
index f087aa5..2b94885 100644 (file)
 
 package com.owncloud.android.operations;
 
-import org.apache.http.HttpStatus;
-import org.apache.jackrabbit.webdav.DavConstants;
-import org.apache.jackrabbit.webdav.MultiStatus;
-import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
-
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.RemoteFile;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.remote.ReadRemoteFileOperation;
+import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.content.Context;
 import android.content.Intent;
 
+/**
+ * Remote operation performing the read of remote file in the ownCloud server.
+ * 
+ * @author David A. Velasco
+ * @author masensio
+ */
 
 public class SynchronizeFileOperation extends RemoteOperation {
 
     private String TAG = SynchronizeFileOperation.class.getSimpleName();
-    private static final int SYNC_READ_TIMEOUT = 10000;
-    private static final int SYNC_CONNECTION_TIMEOUT = 5000;
     
     private OCFile mLocalFile;
     private OCFile mServerFile;
@@ -73,104 +73,84 @@ public class SynchronizeFileOperation extends RemoteOperation {
 
 
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
-        
-        PropFindMethod propfind = null;
+    protected RemoteOperationResult run(OwnCloudClient client) {
+
         RemoteOperationResult result = null;
         mTransferWasRequested = false;
-        try {
-            if (!mLocalFile.isDown()) {
-                /// easy decision
-                requestForDownload(mLocalFile);
-                result = new RemoteOperationResult(ResultCode.OK);
-                
-            } else {
-                /// local copy in the device -> need to think a bit more before do anything
-                
-                if (mServerFile == null) {
-                    /// take the duty of check the server for the current state of the file there
-                    propfind = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mLocalFile.getRemotePath()),
-                            DavConstants.PROPFIND_ALL_PROP,
-                            DavConstants.DEPTH_0);
-                    int status = client.executeMethod(propfind, SYNC_READ_TIMEOUT, SYNC_CONNECTION_TIMEOUT);
-                    boolean isMultiStatus = status == HttpStatus.SC_MULTI_STATUS;
-                    if (isMultiStatus) {
-                        MultiStatus resp = propfind.getResponseBodyAsMultiStatus();
-                        WebdavEntry we = new WebdavEntry(resp.getResponses()[0],
-                                               client.getBaseUri().getPath());
-                        mServerFile = fillOCFile(we);
-                        mServerFile.setLastSyncDateForProperties(System.currentTimeMillis());
-                        
-                    } else {
-                        client.exhaustResponse(propfind.getResponseBodyAsStream());
-                        result = new RemoteOperationResult(false, status, propfind.getResponseHeaders());
-                    }
+        if (!mLocalFile.isDown()) {
+            /// easy decision
+            requestForDownload(mLocalFile);
+            result = new RemoteOperationResult(ResultCode.OK);
+
+        } else {
+            /// local copy in the device -> need to think a bit more before do anything
+
+            if (mServerFile == null) {
+                String remotePath = mLocalFile.getRemotePath();
+                ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath);
+                result = operation.execute(client);
+                if (result.isSuccess()){
+                    mServerFile = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0));
+                    mServerFile.setLastSyncDateForProperties(System.currentTimeMillis());
                 }
-                
-                if (result == null) {   // true if the server was not checked. nothing was wrong with the remote request
-              
-                    /// check changes in server and local file
-                    boolean serverChanged = false;
-                    /* time for eTag is coming, but not yet
+            }
+
+            if (mServerFile != null) {   
+
+                /// check changes in server and local file
+                boolean serverChanged = false;
+                /* time for eTag is coming, but not yet
                     if (mServerFile.getEtag() != null) {
                         serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag()));   // TODO could this be dangerous when the user upgrades the server from non-tagged to tagged?
                     } else { */
-                        // server without etags
-                        serverChanged = (mServerFile.getModificationTimestamp() > mLocalFile.getModificationTimestampAtLastSyncForData());
-                    //}
-                    boolean localChanged = (mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData());
-                        // TODO this will be always true after the app is upgraded to database version 2; will result in unnecessary uploads
-              
-                    /// decide action to perform depending upon changes
-                    //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) {
-                    if (localChanged && serverChanged) {
-                        result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
-                  
-                    } else if (localChanged) {
-                        if (mSyncFileContents) {
-                            requestForUpload(mLocalFile);
-                            // the local update of file properties will be done by the FileUploader service when the upload finishes
-                        } else {
-                            // NOTHING TO DO HERE: updating the properties of the file in the server without uploading the contents would be stupid; 
-                            // So, an instance of SynchronizeFileOperation created with syncFileContents == false is completely useless when we suspect
-                            // that an upload is necessary (for instance, in FileObserverService).
-                        }
-                        result = new RemoteOperationResult(ResultCode.OK);
-                  
-                    } else if (serverChanged) {
-                        if (mSyncFileContents) {
-                            requestForDownload(mLocalFile); // local, not server; we won't to keep the value of keepInSync!
-                            // the update of local data will be done later by the FileUploader service when the upload finishes
-                        } else {
-                            // TODO CHECK: is this really useful in some point in the code?
-                            mServerFile.setKeepInSync(mLocalFile.keepInSync());
-                            mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData());
-                            mServerFile.setStoragePath(mLocalFile.getStoragePath());
-                            mServerFile.setParentId(mLocalFile.getParentId());
-                            mStorageManager.saveFile(mServerFile);
-                            
-                        }
-                        result = new RemoteOperationResult(ResultCode.OK);
-              
+                // server without etags
+                serverChanged = (mServerFile.getModificationTimestamp() != mLocalFile.getModificationTimestampAtLastSyncForData());
+                //}
+                boolean localChanged = (mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData());
+                // TODO this will be always true after the app is upgraded to database version 2; will result in unnecessary uploads
+
+                /// decide action to perform depending upon changes
+                //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) {
+                if (localChanged && serverChanged) {
+                    result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
+
+                } else if (localChanged) {
+                    if (mSyncFileContents) {
+                        requestForUpload(mLocalFile);
+                        // the local update of file properties will be done by the FileUploader service when the upload finishes
                     } else {
-                        // nothing changed, nothing to do
-                        result = new RemoteOperationResult(ResultCode.OK);
+                        // NOTHING TO DO HERE: updating the properties of the file in the server without uploading the contents would be stupid; 
+                        // So, an instance of SynchronizeFileOperation created with syncFileContents == false is completely useless when we suspect
+                        // that an upload is necessary (for instance, in FileObserverService).
                     }
-              
-                } 
-          
-            }
-            
-            Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage());
-          
-        } catch (Exception e) {
-            result = new RemoteOperationResult(e);
-            Log_OC.e(TAG, "Synchronizing " + mAccount.name + ", file " + (mLocalFile != null ? mLocalFile.getRemotePath() : "NULL") + ": " + result.getLogMessage(), result.getException());
-
-        } finally {
-            if (propfind != null)
-                propfind.releaseConnection();
+                    result = new RemoteOperationResult(ResultCode.OK);
+
+                } else if (serverChanged) {
+                    if (mSyncFileContents) {
+                        requestForDownload(mLocalFile); // local, not server; we won't to keep the value of keepInSync!
+                        // the update of local data will be done later by the FileUploader service when the upload finishes
+                    } else {
+                        // TODO CHECK: is this really useful in some point in the code?
+                        mServerFile.setKeepInSync(mLocalFile.keepInSync());
+                        mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData());
+                        mServerFile.setStoragePath(mLocalFile.getStoragePath());
+                        mServerFile.setParentId(mLocalFile.getParentId());
+                        mStorageManager.saveFile(mServerFile);
+
+                    }
+                    result = new RemoteOperationResult(ResultCode.OK);
+
+                } else {
+                    // nothing changed, nothing to do
+                    result = new RemoteOperationResult(ResultCode.OK);
+                }
+
+            } 
+
         }
+
+        Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage());
+
         return result;
     }
 
@@ -207,24 +187,6 @@ public class SynchronizeFileOperation extends RemoteOperation {
     }
 
 
-    /**
-     * Creates and populates a new {@link OCFile} object with the data read from the server.
-     * 
-     * @param we        WebDAV entry read from the server for a WebDAV resource (remote file or folder).
-     * @return          New OCFile instance representing the remote resource described by we.
-     */
-    private OCFile fillOCFile(WebdavEntry we) {
-        OCFile file = new OCFile(we.decodedPath());
-        file.setCreationTimestamp(we.createTimestamp());
-        file.setFileLength(we.contentLength());
-        file.setMimetype(we.contentType());
-        file.setModificationTimestamp(we.modifiedTimestamp());
-        file.setEtag(we.etag());
-        
-        return file;
-    }
-
-
     public boolean transferWasRequested() {
         return mTransferWasRequested;
     }
index 780fd42..11ce41e 100644 (file)
@@ -23,29 +23,30 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
 import org.apache.http.HttpStatus;
-import org.apache.jackrabbit.webdav.DavConstants;
-import org.apache.jackrabbit.webdav.MultiStatus;
-import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
-
 import android.accounts.Account;
 import android.content.Context;
 import android.content.Intent;
+//import android.support.v4.content.LocalBroadcastManager;
 
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.syncadapter.FileSyncService;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.OCShare;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.remote.GetSharesForFileRemoteOperation;
+import com.owncloud.android.lib.operations.remote.ReadRemoteFileOperation;
+import com.owncloud.android.lib.operations.remote.ReadRemoteFolderOperation;
+import com.owncloud.android.lib.operations.common.RemoteFile;
+import com.owncloud.android.syncadapter.FileSyncAdapter;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.Log_OC;
 
@@ -66,6 +67,8 @@ public class SynchronizeFolderOperation extends RemoteOperation {
 
     private static final String TAG = SynchronizeFolderOperation.class.getSimpleName();
 
+    public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED  = SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED";
+    public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED    = SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED";
     
     /** Time stamp for the synchronization process in progress */
     private long mCurrentSyncTime;
@@ -97,9 +100,12 @@ public class SynchronizeFolderOperation extends RemoteOperation {
     /** 'True' means that this operation is part of a full account synchronization */ 
     private boolean mSyncFullAccount;
 
+    /** 'True' means that Share resources bound to the files into the folder should be refreshed also */
+    private boolean mRefreshShares;
+    
     /** 'True' means that the remote folder changed from last synchronization and should be fetched */
     private boolean mRemoteFolderChanged;
-    
+
     
     /**
      * Creates a new instance of {@link SynchronizeFolderOperation}.
@@ -116,12 +122,14 @@ public class SynchronizeFolderOperation extends RemoteOperation {
     public SynchronizeFolderOperation(  OCFile folder, 
                                         long currentSyncTime, 
                                         boolean syncFullAccount,
+                                        boolean refreshShares,
                                         FileDataStorageManager dataStorageManager, 
                                         Account account, 
                                         Context context ) {
         mLocalFolder = folder;
         mCurrentSyncTime = currentSyncTime;
         mSyncFullAccount = syncFullAccount;
+        mRefreshShares = refreshShares;
         mStorageManager = dataStorageManager;
         mAccount = account;
         mContext = context;
@@ -157,7 +165,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
      * {@inheritDoc}
      */
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
+    protected RemoteOperationResult run(OwnCloudClient client) {
         RemoteOperationResult result = null;
         mFailsInFavouritesFound = 0;
         mConflictsFound = 0;
@@ -174,126 +182,81 @@ public class SynchronizeFolderOperation extends RemoteOperation {
         }
         
         if (!mSyncFullAccount) {            
-            sendStickyBroadcast(false, mLocalFolder.getRemotePath(), result);
+            sendLocalBroadcast(EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result);
         }
-
+        
+        if (result.isSuccess() && mRefreshShares) {
+            RemoteOperationResult shareResult = refreshSharesForFolder(client);
+            if (shareResult.getCode() != ResultCode.FILE_NOT_FOUND) {
+                result = shareResult;
+            } // else , keep the previous result ; being conservative for servers where Sharing API is supported, but disabled
+        }
+        
+        if (!mSyncFullAccount) {            
+            sendLocalBroadcast(EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result);
+        }
+        
         return result;
         
     }
 
-
-    private RemoteOperationResult checkForChanges(WebdavClient client) {
+    private RemoteOperationResult checkForChanges(OwnCloudClient client) {
         mRemoteFolderChanged = false;
         RemoteOperationResult result = null;
         String remotePath = null;
-        PropFindMethod query = null;
-        
-        try {
-            remotePath = mLocalFolder.getRemotePath();
-            Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath);
-
-            // remote request 
-            query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(remotePath),
-                    DavConstants.PROPFIND_ALL_PROP,
-                    DavConstants.DEPTH_0);
-            int status = client.executeMethod(query);
-
-            // check and process response
-            if (isMultiStatus(status)) {
-                // parse data from remote folder 
-                WebdavEntry we = new WebdavEntry(query.getResponseBodyAsMultiStatus().getResponses()[0], client.getBaseUri().getPath());
-                OCFile remoteFolder = fillOCFile(we);
-                
-                // check if remote and local folder are different
-                mRemoteFolderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag()));
-                
-                result = new RemoteOperationResult(ResultCode.OK);
-                
-            } else {
-                // check failed
-                client.exhaustResponse(query.getResponseBodyAsStream());
-                if (status == HttpStatus.SC_NOT_FOUND) {
-                    removeLocalFolder();
-                }
-                result = new RemoteOperationResult(false, status, query.getResponseHeaders());
-            }
 
-        } catch (Exception e) {
-            result = new RemoteOperationResult(e);
+        remotePath = mLocalFolder.getRemotePath();
+        Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath);
+        
+        // remote request 
+        ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath);
+        result = operation.execute(client);
+        if (result.isSuccess()){
+            OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0));
             
-
-        } finally {
-            if (query != null)
-                query.releaseConnection();  // let the connection available for other methods
-            if (result.isSuccess()) {
-                Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + (mRemoteFolderChanged ? "changed" : "not changed"));
+            // check if remote and local folder are different
+            mRemoteFolderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag()));
+          
+            result = new RemoteOperationResult(ResultCode.OK);
+        
+            Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + (mRemoteFolderChanged ? "changed" : "not changed"));
+            
+        } else {
+            // check failed
+            if (result.getCode() == ResultCode.FILE_NOT_FOUND) {
+                removeLocalFolder();
+            }
+            if (result.isException()) {
+                Log_OC.e(TAG, "Checked " + mAccount.name + remotePath  + " : " + result.getLogMessage(), result.getException());
             } else {
-                if (result.isException()) {
-                    Log_OC.e(TAG, "Checked " + mAccount.name + remotePath  + " : " + result.getLogMessage(), result.getException());
-                } else {
-                    Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + result.getLogMessage());
-                }
+                Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + result.getLogMessage());
             }
-            
         }
+        
         return result;
     }
 
 
-    private RemoteOperationResult fetchAndSyncRemoteFolder(WebdavClient client) {
-        RemoteOperationResult result = null;
-        String remotePath = null;
-        PropFindMethod query = null;
-        try {
-            remotePath = mLocalFolder.getRemotePath();
-            Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath);
-
-            // remote request 
-            query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(remotePath),
-                    DavConstants.PROPFIND_ALL_PROP,
-                    DavConstants.DEPTH_1);
-            int status = client.executeMethod(query);
-
-            // check and process response
-            if (isMultiStatus(status)) {
-                synchronizeData(query.getResponseBodyAsMultiStatus(), client);
-                if (mConflictsFound > 0  || mFailsInFavouritesFound > 0) { 
-                    result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);   // should be different result, but will do the job
-                } else {
-                    result = new RemoteOperationResult(true, status, query.getResponseHeaders());
-                }
-                
-            } else {
-                // synchronization failed
-                client.exhaustResponse(query.getResponseBodyAsStream());
-                if (status == HttpStatus.SC_NOT_FOUND) {
-                    removeLocalFolder();
-                }
-                result = new RemoteOperationResult(false, status, query.getResponseHeaders());
-            }
-
-        } catch (Exception e) {
-            result = new RemoteOperationResult(e);
-            
-
-        } finally {
-            if (query != null)
-                query.releaseConnection();  // let the connection available for other methods
-            if (result.isSuccess()) {
-                Log_OC.i(TAG, "Synchronized " + mAccount.name + remotePath + ": " + result.getLogMessage());
-            } else {
-                if (result.isException()) {
-                    Log_OC.e(TAG, "Synchronized " + mAccount.name + remotePath  + ": " + result.getLogMessage(), result.getException());
-                } else {
-                    Log_OC.e(TAG, "Synchronized " + mAccount.name + remotePath + ": " + result.getLogMessage());
-                }
+    private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) {
+        String remotePath = mLocalFolder.getRemotePath();
+        ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(remotePath);
+        RemoteOperationResult result = operation.execute(client);
+        Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath);
+        
+        if (result.isSuccess()) {
+            synchronizeData(result.getData(), client);
+            if (mConflictsFound > 0  || mFailsInFavouritesFound > 0) { 
+                result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);   // should be different result, but will do the job
             }
-            
+        } else {
+            if (result.getCode() == ResultCode.FILE_NOT_FOUND)
+                removeLocalFolder();
         }
+        
         return result;
     }
 
-
+    
     private void removeLocalFolder() {
         if (mStorageManager.fileExists(mLocalFolder.getFileId())) {
             String currentSavePath = FileStorageUtils.getSavePath(mAccount.name);
@@ -307,26 +270,25 @@ public class SynchronizeFolderOperation extends RemoteOperation {
      *  with the current data in the local database.
      *  
      *  Grants that mChildren is updated with fresh data after execution.
-     * 
-     *  @param dataInServer     Full response got from the server with the data of the target 
-     *                          folder and its direct children.
+     *  
+     *  @param folderAndFiles   Remote folder and children files in Folder 
+     *  
      *  @param client           Client instance to the remote server where the data were 
      *                          retrieved.  
      *  @return                 'True' when any change was made in the local data, 'false' otherwise.
      */
-    private void synchronizeData(MultiStatus dataInServer, WebdavClient client) {
+    private void synchronizeData(ArrayList<Object> folderAndFiles, OwnCloudClient client) {
         // get 'fresh data' from the database
         mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath());
         
         // parse data from remote folder 
-        WebdavEntry we = new WebdavEntry(dataInServer.getResponses()[0], client.getBaseUri().getPath());
-        OCFile remoteFolder = fillOCFile(we);
+        OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0));
         remoteFolder.setParentId(mLocalFolder.getParentId());
         remoteFolder.setFileId(mLocalFolder.getFileId());
         
         Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " changed - starting update of local data ");
         
-        List<OCFile> updatedFiles = new Vector<OCFile>(dataInServer.getResponses().length - 1);
+        List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
         List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
 
         // get current data about local contents of the folder to synchronize
@@ -338,10 +300,9 @@ public class SynchronizeFolderOperation extends RemoteOperation {
         
         // loop to update every child
         OCFile remoteFile = null, localFile = null;
-        for (int i = 1; i < dataInServer.getResponses().length; ++i) {
+        for (int i=1; i<folderAndFiles.size(); i++) {
             /// new OCFile instance with the data from the server
-            we = new WebdavEntry(dataInServer.getResponses()[i], client.getBaseUri().getPath());                        
-            remoteFile = fillOCFile(we);
+            remoteFile = fillOCFile((RemoteFile)folderAndFiles.get(i));
             remoteFile.setParentId(mLocalFolder.getFileId());
 
             /// retrieve local data for the read file 
@@ -390,13 +351,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
         // request for the synchronization of file contents AFTER saving current remote properties
         startContentSynchronizations(filesToSyncContents, client);
 
-        // removal of obsolete files
-        //removeObsoleteFiles();
-       
-        // must be done AFTER saving all the children information, so that eTag is not updated in the database in case of unexpected exceptions
-        //mStorageManager.saveFile(remoteFolder);
         mChildren = updatedFiles;
-        
     }
 
     /**
@@ -408,7 +363,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
      * @param filesToSyncContents       Synchronization operations to execute.
      * @param client                    Interface to the remote ownCloud server.
      */
-    private void startContentSynchronizations(List<SynchronizeFileOperation> filesToSyncContents, WebdavClient client) {
+    private void startContentSynchronizations(List<SynchronizeFileOperation> filesToSyncContents, OwnCloudClient client) {
         RemoteOperationResult contentsResult = null;
         for (SynchronizeFileOperation op: filesToSyncContents) {
             contentsResult = op.execute(client);   // returns without waiting for upload or download finishes
@@ -432,20 +387,19 @@ public class SynchronizeFolderOperation extends RemoteOperation {
         return (status == HttpStatus.SC_MULTI_STATUS); 
     }
 
-
     /**
      * Creates and populates a new {@link OCFile} object with the data read from the server.
      * 
-     * @param we        WebDAV entry read from the server for a WebDAV resource (remote file or folder).
+     * @param remote    remote file read from the server (remote file or folder).
      * @return          New OCFile instance representing the remote resource described by we.
      */
-    private OCFile fillOCFile(WebdavEntry we) {
-        OCFile file = new OCFile(we.decodedPath());
-        file.setCreationTimestamp(we.createTimestamp());
-        file.setFileLength(we.contentLength());
-        file.setMimetype(we.contentType());
-        file.setModificationTimestamp(we.modifiedTimestamp());
-        file.setEtag(we.etag());
+    private OCFile fillOCFile(RemoteFile remote) {
+        OCFile file = new OCFile(remote.getRemotePath());
+        file.setCreationTimestamp(remote.getCreationTimestamp());
+        file.setFileLength(remote.getLength());
+        file.setMimetype(remote.getMimeType());
+        file.setModificationTimestamp(remote.getModifiedTimestamp());
+        file.setEtag(remote.getEtag());
         return file;
     }
     
@@ -512,6 +466,27 @@ public class SynchronizeFolderOperation extends RemoteOperation {
             }
         }
     }
+    
+    
+    private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) {
+        RemoteOperationResult result = null;
+        
+        // remote request 
+        GetSharesForFileRemoteOperation operation = new GetSharesForFileRemoteOperation(mLocalFolder.getRemotePath(), false, true);
+        result = operation.execute(client);
+        
+        if (result.isSuccess()) {
+            // update local database
+            ArrayList<OCShare> shares = new ArrayList<OCShare>();
+            for(Object obj: result.getData()) {
+                shares.add((OCShare) obj);
+            }
+            mStorageManager.saveSharesInFolder(shares, mLocalFolder);
+        }
+
+        return result;
+    }
+    
 
     /**
      * Scans the default location for saving local copies of files searching for
@@ -534,20 +509,20 @@ public class SynchronizeFolderOperation extends RemoteOperation {
     /**
      * Sends a message to any application component interested in the progress of the synchronization.
      * 
-     * @param inProgress        'True' when the synchronization progress is not finished.
+     * @param event
      * @param dirRemotePath     Remote path of a folder that was just synchronized (with or without success)
+     * @param result
      */
-    private void sendStickyBroadcast(boolean inProgress, String dirRemotePath, RemoteOperationResult result) {
-        Intent i = new Intent(FileSyncService.getSyncMessage());
-        i.putExtra(FileSyncService.IN_PROGRESS, inProgress);
-        i.putExtra(FileSyncService.ACCOUNT_NAME, mAccount.name);
+    private void sendLocalBroadcast(String event, String dirRemotePath, RemoteOperationResult result) {
+        Log_OC.d(TAG, "Send broadcast " + event);
+        Intent intent = new Intent(event);
+        intent.putExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME, mAccount.name);
         if (dirRemotePath != null) {
-            i.putExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH, dirRemotePath);
-        }
-        if (result != null) {
-            i.putExtra(FileSyncService.SYNC_RESULT, result);
+            intent.putExtra(FileSyncAdapter.EXTRA_FOLDER_PATH, dirRemotePath);
         }
-        mContext.sendStickyBroadcast(i);
+        intent.putExtra(FileSyncAdapter.EXTRA_RESULT, result);
+        mContext.sendStickyBroadcast(intent);
+        //LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
     }
 
 
diff --git a/src/com/owncloud/android/operations/UnshareLinkOperation.java b/src/com/owncloud/android/operations/UnshareLinkOperation.java
new file mode 100644 (file)
index 0000000..d4f9c37
--- /dev/null
@@ -0,0 +1,93 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.operations;
+
+import android.content.Context;
+
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.OCShare;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.remote.ExistenceCheckRemoteOperation;
+import com.owncloud.android.lib.operations.remote.RemoveRemoteShareOperation;
+import com.owncloud.android.operations.common.SyncOperation;
+import com.owncloud.android.utils.Log_OC;
+
+/**
+ * Unshare file/folder
+ * Save the data in Database
+ * 
+ * @author masensio
+ */
+public class UnshareLinkOperation extends SyncOperation {
+
+    private static final String TAG = UnshareLinkOperation.class.getSimpleName();
+    
+    private String mRemotePath;
+    private Context mContext;
+    
+    
+    public UnshareLinkOperation(String remotePath, Context context) {
+        mRemotePath = remotePath;
+        mContext = context;
+    }
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+        RemoteOperationResult result  = null;
+        
+        // Get Share for a file
+        OCShare share = getStorageManager().getShareByPath(mRemotePath);
+        
+        if (share != null) {
+            RemoveRemoteShareOperation operation = new RemoveRemoteShareOperation((int) share.getIdRemoteShared());
+            result = operation.execute(client);
+
+            if (result.isSuccess() || result.getCode() == ResultCode.SHARE_NOT_FOUND) {
+                Log_OC.d(TAG, "Share id = " + share.getIdRemoteShared() + " deleted");
+
+                OCFile file = getStorageManager().getFileByPath(mRemotePath);
+                file.setShareByLink(false);
+                file.setPublicLink("");
+                getStorageManager().saveFile(file);
+                getStorageManager().removeShare(share);
+                
+                if (result.getCode() == ResultCode.SHARE_NOT_FOUND) {
+                    if (existsFile(client, file.getRemotePath())) {
+                        result = new RemoteOperationResult(ResultCode.OK);
+                    } else {
+                        getStorageManager().removeFile(file, true, true);
+                    }
+                }
+            } 
+                
+        } else {
+            result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND);
+        }
+
+        return result;
+    }
+    
+    private boolean existsFile(OwnCloudClient client, String remotePath){
+        ExistenceCheckRemoteOperation existsOperation = new ExistenceCheckRemoteOperation(remotePath, mContext, false);
+        RemoteOperationResult result = existsOperation.execute(client);
+        return result.isSuccess();
+    }
+
+}
index 7e33060..a047f11 100644 (file)
@@ -23,12 +23,12 @@ import org.json.JSONException;
 import org.json.JSONObject;
 
 import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
+import com.owncloud.android.lib.accounts.OwnCloudAccount;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.utils.OwnCloudVersion;
 import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
@@ -56,7 +56,7 @@ public class UpdateOCVersionOperation extends RemoteOperation {
     
     
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
+    protected RemoteOperationResult run(OwnCloudClient client) {
         AccountManager accountMngr = AccountManager.get(mContext); 
         String statUrl = accountMngr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_BASE_URL);
         statUrl += AccountUtils.STATUS_PATH;
@@ -90,15 +90,15 @@ public class UpdateOCVersionOperation extends RemoteOperation {
                     result = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
                 }
             }
-            Log_OC.i(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage());
+            Log_OC.i(TAG, "Check for update of ownCloud server version at " + client.getWebdavUri() + ": " + result.getLogMessage());
             
         } catch (JSONException e) {
             result = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
-            Log_OC.e(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage(), e);
+            Log_OC.e(TAG, "Check for update of ownCloud server version at " + client.getWebdavUri() + ": " + result.getLogMessage(), e);
                 
         } catch (Exception e) {
             result = new RemoteOperationResult(e);
-            Log_OC.e(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage(), e);
+            Log_OC.e(TAG, "Check for update of ownCloud server version at " + client.getWebdavUri() + ": " + result.getLogMessage(), e);
             
         } finally {
             if (get != null) 
index 80a3463..faa8154 100644 (file)
@@ -24,29 +24,30 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.methods.PutMethod;
 import org.apache.commons.httpclient.methods.RequestEntity;
-import org.apache.http.HttpStatus;
 
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
-import com.owncloud.android.oc_framework.network.webdav.FileRequestEntity;
-import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.oc_framework.operations.OperationCancelledException;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.network.ProgressiveDataTransferer;
+import com.owncloud.android.lib.network.OnDatatransferProgressListener;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.OperationCancelledException;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.remote.ChunkedUploadRemoteFileOperation;
+import com.owncloud.android.lib.operations.remote.ExistenceCheckRemoteOperation;
+import com.owncloud.android.lib.operations.remote.UploadRemoteFileOperation;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
+import android.content.Context;
 
 
 /**
@@ -62,6 +63,7 @@ public class UploadFileOperation extends RemoteOperation {
     private OCFile mFile;
     private OCFile mOldFile;
     private String mRemotePath = null;
+    private boolean mChunked = false;
     private boolean mIsInstant = false;
     private boolean mRemoteFolderToBeCreated = false;
     private boolean mForceOverwrite = false;
@@ -72,15 +74,20 @@ public class UploadFileOperation extends RemoteOperation {
     PutMethod mPutMethod = null;
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
+    private Context mContext;
+    
+    private UploadRemoteFileOperation mUploadOperation;
 
     protected RequestEntity mEntity = null;
 
     
     public UploadFileOperation( Account account,
                                 OCFile file,
+                                boolean chunked,
                                 boolean isInstant, 
                                 boolean forceOverwrite,
-                                int localBehaviour) {
+                                int localBehaviour, 
+                                Context context) {
         if (account == null)
             throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation creation");
         if (file == null)
@@ -95,11 +102,13 @@ public class UploadFileOperation extends RemoteOperation {
         mAccount = account;
         mFile = file;
         mRemotePath = file.getRemotePath();
+        mChunked = chunked;
         mIsInstant = isInstant;
         mForceOverwrite = forceOverwrite;
         mLocalBehaviour = localBehaviour;
         mOriginalStoragePath = mFile.getStoragePath();
         mOriginalFileName = mFile.getFileName();
+        mContext = context;
     }
 
     public Account getAccount() {
@@ -177,7 +186,7 @@ public class UploadFileOperation extends RemoteOperation {
     }
 
     @Override
-    protected RemoteOperationResult run(WebdavClient client) {
+    protected RemoteOperationResult run(OwnCloudClient client) {
         RemoteOperationResult result = null;
         boolean localCopyPassed = false, nameCheckPassed = false;
         File temporalFile = null, originalFile = new File(mOriginalStoragePath), expectedFile = null;
@@ -199,7 +208,7 @@ public class UploadFileOperation extends RemoteOperation {
                                                                                                 // !!!
             expectedFile = new File(expectedPath);
 
-            // check location of local file; if not the expected, copy to a
+            // check location of local file; if not the expected, copy to a
             // temporal file before upload (if COPY is the expected behaviour)
             if (!mOriginalStoragePath.equals(expectedPath) && mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY) {
 
@@ -260,19 +269,23 @@ public class UploadFileOperation extends RemoteOperation {
             }
             localCopyPassed = true;
 
-            // / perform the upload
-            synchronized (mCancellationRequested) {
-                if (mCancellationRequested.get()) {
-                    throw new OperationCancelledException();
-                } else {
-                    mPutMethod = new PutMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath()));
-                }
+            /// perform the upload
+            if ( mChunked && (new File(mFile.getStoragePath())).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) {
+                mUploadOperation = new ChunkedUploadRemoteFileOperation(mFile.getStoragePath(), mFile.getRemotePath(), 
+                        mFile.getMimetype());
+            } else {
+                mUploadOperation = new UploadRemoteFileOperation(mFile.getStoragePath(), mFile.getRemotePath(), 
+                        mFile.getMimetype());
+            }
+            Iterator <OnDatatransferProgressListener> listener = mDataTransferListeners.iterator();
+            while (listener.hasNext()) {
+                mUploadOperation.addDatatransferProgressListener(listener.next());
             }
-            int status = uploadFile(client);
+            result = mUploadOperation.execute(client);
 
-            // / move local temporal file or original file to its corresponding
+            /// move local temporal file or original file to its corresponding
             // location in the ownCloud local folder
-            if (isSuccess(status)) {
+            if (result.isSuccess()) {
                 if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) {
                     mFile.setStoragePath(null);
 
@@ -305,8 +318,6 @@ public class UploadFileOperation extends RemoteOperation {
                 }
             }
 
-            result = new RemoteOperationResult(isSuccess(status), status, (mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
-
         } catch (Exception e) {
             // TODO something cleaner with cancellations
             if (mCancellationRequested.get()) {
@@ -358,29 +369,6 @@ public class UploadFileOperation extends RemoteOperation {
         mFile = newFile;
     }
 
-    public boolean isSuccess(int status) {
-        return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT));
-    }
-
-    protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException {
-        int status = -1;
-        try {
-            File f = new File(mFile.getStoragePath());
-            mEntity  = new FileRequestEntity(f, getMimeType());
-            synchronized (mDataTransferListeners) {
-                ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
-            }
-            mPutMethod.setRequestEntity(mEntity);
-            status = client.executeMethod(mPutMethod);
-            client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
-
-        } finally {
-            mPutMethod.releaseConnection(); // let the connection available for
-                                            // other methods
-        }
-        return status;
-    }
-
     /**
      * Checks if remotePath does not exist in the server and returns it, or adds
      * a suffix to it in order to avoid the server file is overwritten.
@@ -388,8 +376,8 @@ public class UploadFileOperation extends RemoteOperation {
      * @param string
      * @return
      */
-    private String getAvailableRemotePath(WebdavClient wc, String remotePath) throws Exception {
-        boolean check = wc.existsFile(remotePath);
+    private String getAvailableRemotePath(OwnCloudClient wc, String remotePath) throws Exception {
+        boolean check = existsFile(wc, remotePath);
         if (!check) {
             return remotePath;
         }
@@ -404,10 +392,12 @@ public class UploadFileOperation extends RemoteOperation {
         int count = 2;
         do {
             suffix = " (" + count + ")";
-            if (pos >= 0)
-                check = wc.existsFile(remotePath + suffix + "." + extension);
-            else
-                check = wc.existsFile(remotePath + suffix);
+            if (pos >= 0) {
+                check = existsFile(wc, remotePath + suffix + "." + extension);
+            }
+            else {
+                check = existsFile(wc, remotePath + suffix);
+            }
             count++;
         } while (check);
 
@@ -418,12 +408,14 @@ public class UploadFileOperation extends RemoteOperation {
         }
     }
 
+    private boolean existsFile(OwnCloudClient client, String remotePath){
+        ExistenceCheckRemoteOperation existsOperation = new ExistenceCheckRemoteOperation(remotePath, mContext, false);
+        RemoteOperationResult result = existsOperation.execute(client);
+        return result.isSuccess();
+    }
+    
     public void cancel() {
-        synchronized (mCancellationRequested) {
-            mCancellationRequested.set(true);
-            if (mPutMethod != null)
-                mPutMethod.abort();
-        }
+        mUploadOperation.cancel();
     }
 
 }
diff --git a/src/com/owncloud/android/operations/common/SyncOperation.java b/src/com/owncloud/android/operations/common/SyncOperation.java
new file mode 100644 (file)
index 0000000..7a8e356
--- /dev/null
@@ -0,0 +1,129 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.operations.common;
+
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Handler;
+
+
+/**
+ * Operation which execution involves both interactions with an ownCloud server and
+ * with local data in the device.
+ * 
+ * Provides methods to execute the operation both synchronously or asynchronously.
+ * 
+ * @author David A. Velasco 
+ */
+public abstract class SyncOperation extends RemoteOperation {
+       
+    //private static final String TAG = SyncOperation.class.getSimpleName();
+
+    private FileDataStorageManager mStorageManager;
+    
+    public FileDataStorageManager getStorageManager() {
+        return mStorageManager;
+    }
+       
+
+    /**
+     * Synchronously executes the operation on the received ownCloud account.
+     * 
+     * Do not call this method from the main thread.
+     * 
+     * This method should be used whenever an ownCloud account is available, instead of {@link #execute(OwnCloudClient)}. 
+     * 
+     * @param account   ownCloud account in remote ownCloud server to reach during the execution of the operation.
+     * @param context   Android context for the component calling the method.
+     * @return          Result of the operation.
+     */
+    public RemoteOperationResult execute(FileDataStorageManager storageManager, Context context) {
+        if (storageManager == null) {
+            throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager");
+        }
+        if (storageManager.getAccount() == null) {
+            throw new IllegalArgumentException("Trying to execute a sync operation with a storage manager for a NULL account");
+        }
+        mStorageManager = storageManager;
+        return super.execute(mStorageManager.getAccount(), context);
+    }
+    
+       
+       /**
+        * Synchronously executes the remote operation
+        * 
+     * Do not call this method from the main thread.
+     * 
+        * @param client        Client object to reach an ownCloud server during the execution of the operation.
+        * @return                      Result of the operation.
+        */
+       public RemoteOperationResult execute(OwnCloudClient client, FileDataStorageManager storageManager) {
+        if (storageManager == null)
+            throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager");
+        mStorageManager = storageManager;
+               return super.execute(client);
+       }
+
+       
+    /**
+     * Asynchronously executes the remote operation
+     * 
+     * This method should be used whenever an ownCloud account is available, instead of {@link #execute(OwnCloudClient)}. 
+     * 
+     * @param account           ownCloud account in remote ownCloud server to reach during the execution of the operation.
+     * @param context           Android context for the component calling the method.
+     * @param listener          Listener to be notified about the execution of the operation.
+     * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
+     * @return                  Thread were the remote operation is executed.
+     */
+    public Thread execute(FileDataStorageManager storageManager, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) {
+        if (storageManager == null) {
+            throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager");
+        }
+        if (storageManager.getAccount() == null) {
+            throw new IllegalArgumentException("Trying to execute a sync operation with a storage manager for a NULL account");
+        }
+        mStorageManager = storageManager;
+        return super.execute(storageManager.getAccount(), context, listener, listenerHandler, callerActivity);
+    }
+
+    
+       /**
+        * Asynchronously executes the remote operation
+        * 
+        * @param client                        Client object to reach an ownCloud server during the execution of the operation.
+        * @param listener                      Listener to be notified about the execution of the operation.
+        * @param listenerHandler       Handler associated to the thread where the methods of the listener objects must be called.
+        * @return                                      Thread were the remote operation is executed.
+        */
+       public Thread execute(OwnCloudClient client, FileDataStorageManager storageManager, OnRemoteOperationListener listener, Handler listenerHandler) {
+        if (storageManager == null) {
+            throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager");
+        }
+        mStorageManager = storageManager;
+        return super.execute(client, listener, listenerHandler);
+       }
+
+       
+}
index 9e7cd3f..36c0353 100644 (file)
@@ -25,6 +25,7 @@ import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.db.ProviderMeta;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
+import com.owncloud.android.lib.operations.common.ShareType;
 import com.owncloud.android.utils.Log_OC;
 
 
@@ -56,44 +57,85 @@ public class FileContentProvider extends ContentProvider {
 
     private DataBaseHelper mDbHelper;
 
-    private static HashMap<String, String> mProjectionMap;
+    // Projection for filelist table
+    private static HashMap<String, String> mFileProjectionMap;
     static {
-        mProjectionMap = new HashMap<String, String>();
-        mProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
-        mProjectionMap.put(ProviderTableMeta.FILE_PARENT,
+        mFileProjectionMap = new HashMap<String, String>();
+        mFileProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
+        mFileProjectionMap.put(ProviderTableMeta.FILE_PARENT,
                 ProviderTableMeta.FILE_PARENT);
-        mProjectionMap.put(ProviderTableMeta.FILE_PATH,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_PATH,
                 ProviderTableMeta.FILE_PATH);
-        mProjectionMap.put(ProviderTableMeta.FILE_NAME,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_NAME,
                 ProviderTableMeta.FILE_NAME);
-        mProjectionMap.put(ProviderTableMeta.FILE_CREATION,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_CREATION,
                 ProviderTableMeta.FILE_CREATION);
-        mProjectionMap.put(ProviderTableMeta.FILE_MODIFIED,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_MODIFIED,
                 ProviderTableMeta.FILE_MODIFIED);
-        mProjectionMap.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
                 ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA);
-        mProjectionMap.put(ProviderTableMeta.FILE_CONTENT_LENGTH,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_CONTENT_LENGTH,
                 ProviderTableMeta.FILE_CONTENT_LENGTH);
-        mProjectionMap.put(ProviderTableMeta.FILE_CONTENT_TYPE,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_CONTENT_TYPE,
                 ProviderTableMeta.FILE_CONTENT_TYPE);
-        mProjectionMap.put(ProviderTableMeta.FILE_STORAGE_PATH,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_STORAGE_PATH,
                 ProviderTableMeta.FILE_STORAGE_PATH);
-        mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE,
                 ProviderTableMeta.FILE_LAST_SYNC_DATE);
-        mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
                 ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA);
-        mProjectionMap.put(ProviderTableMeta.FILE_KEEP_IN_SYNC,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_KEEP_IN_SYNC,
                 ProviderTableMeta.FILE_KEEP_IN_SYNC);
-        mProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
+        mFileProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
                 ProviderTableMeta.FILE_ACCOUNT_OWNER);
-        mProjectionMap.put(ProviderTableMeta.FILE_ETAG, 
+        mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG, 
                 ProviderTableMeta.FILE_ETAG);
+        mFileProjectionMap.put(ProviderTableMeta.FILE_SHARE_BY_LINK,
+                ProviderTableMeta.FILE_SHARE_BY_LINK);
+        mFileProjectionMap.put(ProviderTableMeta.FILE_PUBLIC_LINK,
+                ProviderTableMeta.FILE_PUBLIC_LINK);
     }
 
     private static final int SINGLE_FILE = 1;
     private static final int DIRECTORY = 2;
     private static final int ROOT_DIRECTORY = 3;
-
+    private static final int SHARES = 4;
+    
+    // Projection for ocshares table
+    private static HashMap<String, String> mOCSharesProjectionMap;
+    static {
+        mOCSharesProjectionMap = new HashMap<String, String>();
+        mOCSharesProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_FILE_SOURCE,
+                ProviderTableMeta.OCSHARES_FILE_SOURCE);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE,
+                ProviderTableMeta.OCSHARES_ITEM_SOURCE);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_TYPE,
+                ProviderTableMeta.OCSHARES_SHARE_TYPE);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_WITH,
+                ProviderTableMeta.OCSHARES_SHARE_WITH);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_PATH,
+                ProviderTableMeta.OCSHARES_PATH);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_PERMISSIONS,
+                ProviderTableMeta.OCSHARES_PERMISSIONS);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARED_DATE,
+                ProviderTableMeta.OCSHARES_SHARED_DATE);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE,
+                ProviderTableMeta.OCSHARES_EXPIRATION_DATE);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_TOKEN,
+                ProviderTableMeta.OCSHARES_TOKEN);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
+                ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY,
+                ProviderTableMeta.OCSHARES_IS_DIRECTORY);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_USER_ID,
+                ProviderTableMeta.OCSHARES_USER_ID);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED,
+                ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED);
+        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER,
+                ProviderTableMeta.OCSHARES_ACCOUNT_OWNER);
+    }
+    
     private UriMatcher mUriMatcher;
     
     @Override
@@ -112,7 +154,6 @@ public class FileContentProvider extends ContentProvider {
         return count;
     }
     
-    
     private int delete(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) {
         int count = 0;
         switch (mUriMatcher.match(uri)) {
@@ -124,7 +165,7 @@ public class FileContentProvider extends ContentProvider {
             }
             Log_OC.d(TAG, "Removing FILE " + remotePath);
             */
-            count = db.delete(ProviderTableMeta.DB_NAME,
+            count = db.delete(ProviderTableMeta.FILE_TABLE_NAME,
                     ProviderTableMeta._ID
                             + "="
                             + uri.getPathSegments().get(1)
@@ -168,7 +209,7 @@ public class FileContentProvider extends ContentProvider {
             }
             Log_OC.d(TAG, "Removing DIRECTORY " + folderName + " (or maybe not) ");
             */
-            count += db.delete(ProviderTableMeta.DB_NAME,
+            count += db.delete(ProviderTableMeta.FILE_TABLE_NAME,
                     ProviderTableMeta._ID
                     + "="
                     + uri.getPathSegments().get(1)
@@ -181,7 +222,10 @@ public class FileContentProvider extends ContentProvider {
             break;
         case ROOT_DIRECTORY:
             //Log_OC.d(TAG, "Removing ROOT!");
-            count = db.delete(ProviderTableMeta.DB_NAME, where, whereArgs);
+            count = db.delete(ProviderTableMeta.FILE_TABLE_NAME, where, whereArgs);
+            break;
+        case SHARES:
+            count = db.delete(ProviderTableMeta.OCSHARES_TABLE_NAME, where, whereArgs);
             break;
         default:
             //Log_OC.e(TAG, "Unknown uri " + uri);
@@ -191,6 +235,7 @@ public class FileContentProvider extends ContentProvider {
     }
     
 
+    // TODO: switch(uri)
     @Override
     public String getType(Uri uri) {
         switch (mUriMatcher.match(uri)) {
@@ -221,37 +266,77 @@ public class FileContentProvider extends ContentProvider {
     }
     
     private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) {
-        if (mUriMatcher.match(uri) != SINGLE_FILE &&
-                mUriMatcher.match(uri) != ROOT_DIRECTORY) {
-            //Log_OC.e(TAG, "Inserting invalid URI: " + uri);
-            throw new IllegalArgumentException("Unknown uri id: " + uri);
-        }
+        switch (mUriMatcher.match(uri)){
+        case ROOT_DIRECTORY:
+        case SINGLE_FILE:
+            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 };
+            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);
+            if (doubleCheck == null || !doubleCheck.moveToFirst()) {    // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider 
+                long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values);
+                if (rowId > 0) {
+                    Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
+                    //Log_OC.d(TAG, "Inserted " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
+                    return insertedFileUri;
+                } else {
+                    //Log_OC.d(TAG, "Error while inserting " + values.getAsString(ProviderTableMeta.FILE_PATH)  + " at provider " + this);
+                    throw new SQLException("ERROR " + uri);
+                }
+            } else {
+                // file is already inserted; race condition, let's avoid a duplicated entry
+                Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)));
+                doubleCheck.close();
 
-        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 };
-        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);
-        if (doubleCheck == null || !doubleCheck.moveToFirst()) {    // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider 
-            long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
-            if (rowId > 0) {
-                Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
-                //Log_OC.d(TAG, "Inserted " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
                 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 };
+            String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
+            String[] whereArgsShare = new String[] {path, accountNameShare};
+            Uri insertedShareUri = null;
+            Cursor doubleCheckShare = query(db, uri, projectionShare, whereShare, whereArgsShare, null);
+            if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) {    // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider 
+                long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values);
+                if (rowId >0) {
+                    insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId);
+                } else {
+                    throw new SQLException("ERROR " + uri);
+
+                }
             } else {
-                //Log_OC.d(TAG, "Error while inserting " + values.getAsString(ProviderTableMeta.FILE_PATH)  + " at provider " + this);
-                throw new SQLException("ERROR " + uri);
+                // file is already inserted; race condition, let's avoid a duplicated entry
+                insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, doubleCheckShare.getLong(doubleCheckShare.getColumnIndex(ProviderTableMeta._ID)));
+                doubleCheckShare.close();
             }
-        } else {
-            // file is already inserted; race condition, let's avoid a duplicated entry
-            Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)));
-            doubleCheck.close();
-            return insertedFileUri;
+            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);
+        String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
+        String[] whereArgsShare = new String[] {
+                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());
@@ -263,6 +348,8 @@ public class FileContentProvider extends ContentProvider {
         mUriMatcher.addURI(authority, "file/#", SINGLE_FILE);
         mUriMatcher.addURI(authority, "dir/", DIRECTORY);
         mUriMatcher.addURI(authority, "dir/#", DIRECTORY);
+        mUriMatcher.addURI(authority, "shares/", SHARES);
+        mUriMatcher.addURI(authority, "shares/#", SHARES);
         
         return true;
     }
@@ -285,8 +372,8 @@ public class FileContentProvider extends ContentProvider {
     private Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
         SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
 
-        sqlQuery.setTables(ProviderTableMeta.DB_NAME);
-        sqlQuery.setProjectionMap(mProjectionMap);
+        sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME);
+        sqlQuery.setProjectionMap(mFileProjectionMap);
 
         switch (mUriMatcher.match(uri)) {
         case ROOT_DIRECTORY:
@@ -302,13 +389,26 @@ public class FileContentProvider extends ContentProvider {
                         + uri.getPathSegments().get(1));
             }
             break;
+        case SHARES: 
+            sqlQuery.setTables(ProviderTableMeta.OCSHARES_TABLE_NAME);
+            sqlQuery.setProjectionMap(mOCSharesProjectionMap);
+            if (uri.getPathSegments().size() > 1) {
+                sqlQuery.appendWhere(ProviderTableMeta._ID + "="
+                        + uri.getPathSegments().get(1));
+            }
+            break;
         default:
             throw new IllegalArgumentException("Unknown uri id: " + uri);
         }
 
         String order;
         if (TextUtils.isEmpty(sortOrder)) {
-            order = ProviderTableMeta.DEFAULT_SORT_ORDER;
+            if (mUriMatcher.match(uri) == SHARES) {
+                order = ProviderTableMeta.OCSHARES_DEFAULT_SORT_ORDER;
+            } else {
+
+                order = ProviderTableMeta.FILE_DEFAULT_SORT_ORDER;
+            }
         } else {
             order = sortOrder;
         }
@@ -338,12 +438,15 @@ public class FileContentProvider extends ContentProvider {
     }
     
     
+
     private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs) {
         switch (mUriMatcher.match(uri)) {
             case DIRECTORY:
                 return updateFolderSize(db, selectionArgs[0]);
+            case SHARES:
+                return db.update(ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs);
             default:
-                return db.update(ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
+                return db.update(ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs);
         }
     }    
 
@@ -384,7 +487,7 @@ public class FileContentProvider extends ContentProvider {
             Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize);
             ContentValues cv = new ContentValues();
             cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize);
-            count = db.update(ProviderTableMeta.DB_NAME, cv, folderWhere, whereArgs);
+            count = db.update(ProviderTableMeta.FILE_TABLE_NAME, cv, folderWhere, whereArgs);
             
             // propagate update until root
             if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) {
@@ -433,7 +536,7 @@ public class FileContentProvider extends ContentProvider {
         public void onCreate(SQLiteDatabase db) {
             // files table
             Log_OC.i("SQL", "Entering in onCreate");
-            db.execSQL("CREATE TABLE " + ProviderTableMeta.DB_NAME + "("
+            db.execSQL("CREATE TABLE " + ProviderTableMeta.FILE_TABLE_NAME + "("
                     + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
                     + ProviderTableMeta.FILE_NAME + " TEXT, "
                     + ProviderTableMeta.FILE_PATH + " TEXT, "
@@ -448,8 +551,28 @@ 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 );"
                     );
+            
+            // Create table ocshares
+            db.execSQL("CREATE TABLE " + ProviderTableMeta.OCSHARES_TABLE_NAME + "("
+                    + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
+                    + ProviderTableMeta.OCSHARES_FILE_SOURCE + " INTEGER, "
+                    + ProviderTableMeta.OCSHARES_ITEM_SOURCE + " INTEGER, "
+                    + ProviderTableMeta.OCSHARES_SHARE_TYPE + " INTEGER, "
+                    + ProviderTableMeta.OCSHARES_SHARE_WITH + " TEXT, "
+                    + ProviderTableMeta.OCSHARES_PATH + " TEXT, "
+                    + 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 );" );
         }
 
         @Override
@@ -458,7 +581,7 @@ public class FileContentProvider extends ContentProvider {
             boolean upgraded = false; 
             if (oldVersion == 1 && newVersion >= 2) {
                 Log_OC.i("SQL", "Entering in the #1 ADD in onUpgrade");
-                db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
+                db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
                            " ADD COLUMN " + ProviderTableMeta.FILE_KEEP_IN_SYNC  + " INTEGER " +
                            " DEFAULT 0");
                 upgraded = true;
@@ -467,12 +590,12 @@ public class FileContentProvider extends ContentProvider {
                 Log_OC.i("SQL", "Entering in the #2 ADD in onUpgrade");
                 db.beginTransaction();
                 try {
-                    db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
+                    db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
                                " 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.DB_NAME + 
+                    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");
                  
@@ -486,11 +609,11 @@ public class FileContentProvider extends ContentProvider {
                 Log_OC.i("SQL", "Entering in the #3 ADD in onUpgrade");
                 db.beginTransaction();
                 try {
-                    db .execSQL("ALTER TABLE " + ProviderTableMeta.DB_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.DB_NAME + 
+                    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");
                 
@@ -507,7 +630,7 @@ public class FileContentProvider extends ContentProvider {
                 Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade");
                 db.beginTransaction();
                 try {
-                    db .execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
+                    db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
                             " ADD COLUMN " + ProviderTableMeta.FILE_ETAG + " TEXT " +
                             " DEFAULT NULL");
                     
@@ -519,6 +642,45 @@ public class FileContentProvider extends ContentProvider {
             }
             if (!upgraded)
                 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
+            
+            if (oldVersion < 6 && newVersion >= 6) {
+                Log_OC.i("SQL", "Entering in the #5 ADD in onUpgrade");
+                db.beginTransaction();
+                try {
+                    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");
+                    
+                    // Create table ocshares
+                    db.execSQL("CREATE TABLE " + ProviderTableMeta.OCSHARES_TABLE_NAME + "("
+                            + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
+                            + ProviderTableMeta.OCSHARES_FILE_SOURCE + " INTEGER, "
+                            + ProviderTableMeta.OCSHARES_ITEM_SOURCE + " INTEGER, "
+                            + ProviderTableMeta.OCSHARES_SHARE_TYPE + " INTEGER, "
+                            + ProviderTableMeta.OCSHARES_SHARE_WITH + " TEXT, "
+                            + ProviderTableMeta.OCSHARES_PATH + " TEXT, "
+                            + 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 );" );
+                    
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            if (!upgraded)
+                Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
         }
     }
 
diff --git a/src/com/owncloud/android/services/OperationsService.java b/src/com/owncloud/android/services/OperationsService.java
new file mode 100644 (file)
index 0000000..200d7a3
--- /dev/null
@@ -0,0 +1,404 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.services;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import com.owncloud.android.datamodel.FileDataStorageManager;
+
+import com.owncloud.android.lib.network.OwnCloudClientFactory;
+import com.owncloud.android.lib.network.OwnCloudClient;
+import com.owncloud.android.operations.CreateShareOperation;
+import com.owncloud.android.operations.UnshareLinkOperation;
+import com.owncloud.android.operations.common.SyncOperation;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.ShareType;
+import com.owncloud.android.utils.Log_OC;
+
+import android.accounts.Account;
+import android.accounts.AccountsException;
+import android.app.Service;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+//import android.support.v4.content.LocalBroadcastManager;
+import android.util.Pair;
+
+public class OperationsService extends Service {
+    
+    private static final String TAG = OperationsService.class.getSimpleName();
+    
+    public static final String EXTRA_ACCOUNT = "ACCOUNT";
+    public static final String EXTRA_SERVER_URL = "SERVER_URL";
+    public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
+    public static final String EXTRA_SEND_INTENT = "SEND_INTENT";
+    public static final String EXTRA_RESULT = "RESULT";
+    
+    public static final String ACTION_CREATE_SHARE = "CREATE_SHARE";
+    public static final String ACTION_UNSHARE = "UNSHARE";
+    
+    public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + ".OPERATION_ADDED";
+    public static final String ACTION_OPERATION_FINISHED = OperationsService.class.getName() + ".OPERATION_FINISHED";
+
+    private ConcurrentLinkedQueue<Pair<Target, RemoteOperation>> mPendingOperations = new ConcurrentLinkedQueue<Pair<Target, RemoteOperation>>();
+    
+    private static class Target {
+        public Uri mServerUrl = null;
+        public Account mAccount = null;
+        public Target(Account account, Uri serverUrl) {
+            mAccount = account;
+            mServerUrl = serverUrl;
+        }
+    }
+
+    private Looper mServiceLooper;
+    private ServiceHandler mServiceHandler;
+    private OperationsServiceBinder mBinder;
+    private OwnCloudClient mOwnCloudClient = null;
+    private Target mLastTarget = null;
+    private FileDataStorageManager mStorageManager;
+    private RemoteOperation mCurrentOperation = null;
+    
+    
+    /**
+     * Service initialization
+     */
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        HandlerThread thread = new HandlerThread("Operations service thread", Process.THREAD_PRIORITY_BACKGROUND);
+        thread.start();
+        mServiceLooper = thread.getLooper();
+        mServiceHandler = new ServiceHandler(mServiceLooper, this);
+        mBinder = new OperationsServiceBinder();
+    }
+
+    /**
+     * Entry point to add a new operation to the queue of operations.
+     * 
+     * New operations are added calling to startService(), resulting in a call to this method. 
+     * This ensures the service will keep on working although the caller activity goes away.
+     * 
+     * IMPORTANT: the only operations performed here right now is {@link GetSharedFilesOperation}. The class
+     * is taking advantage of it due to time constraints.
+     */
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (!intent.hasExtra(EXTRA_ACCOUNT) && !intent.hasExtra(EXTRA_SERVER_URL)) {
+            Log_OC.e(TAG, "Not enough information provided in intent");
+            return START_NOT_STICKY;
+        }
+        try {
+            Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
+            String serverUrl = intent.getStringExtra(EXTRA_SERVER_URL);
+            
+            Target target = new Target(account, (serverUrl == null) ? null : Uri.parse(serverUrl));
+            RemoteOperation operation = null;
+            
+            String action = intent.getAction();
+            if (action.equals(ACTION_CREATE_SHARE)) {  // Create Share
+                String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
+                Intent sendIntent = intent.getParcelableExtra(EXTRA_SEND_INTENT);
+                if (remotePath.length() > 0) {
+                    operation = new CreateShareOperation(remotePath, ShareType.PUBLIC_LINK, 
+                            "", false, "", 1, sendIntent);
+                }
+            } else if (action.equals(ACTION_UNSHARE)) {  // Unshare file
+                String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
+                if (remotePath.length() > 0) {
+                    operation = new UnshareLinkOperation(remotePath, this.getApplicationContext());
+                }
+            } else {
+                // nothing we are going to handle
+                return START_NOT_STICKY;
+            }
+            
+            mPendingOperations.add(new Pair<Target , RemoteOperation>(target, operation));
+            //sendBroadcastNewOperation(target, operation);
+            
+            Message msg = mServiceHandler.obtainMessage();
+            msg.arg1 = startId;
+            mServiceHandler.sendMessage(msg);
+            
+        } catch (IllegalArgumentException e) {
+            Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage());
+            return START_NOT_STICKY;
+        }
+        
+        return START_NOT_STICKY;
+    }
+
+    
+    /**
+     * Provides a binder object that clients can use to perform actions on the queue of operations, 
+     * except the addition of new operations. 
+     */
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    
+    /**
+     * Called when ALL the bound clients were unbound.
+     */
+    @Override
+    public boolean onUnbind(Intent intent) {
+        //((OperationsServiceBinder)mBinder).clearListeners();
+        return false;   // not accepting rebinding (default behaviour)
+    }
+
+    
+    /**
+     *  Binder to let client components to perform actions on the queue of operations.
+     * 
+     *  It provides by itself the available operations.
+     */
+    public class OperationsServiceBinder extends Binder /* implements OnRemoteOperationListener */ {
+        
+        /** 
+         * Map of listeners that will be reported about the end of operations from a {@link OperationsServiceBinder} instance 
+         */
+        private Map<OnRemoteOperationListener, Handler> mBoundListeners = new HashMap<OnRemoteOperationListener, Handler>();
+        
+        /**
+         * Cancels an operation
+         *
+         * TODO
+         */
+        public void cancel() {
+            // TODO
+        }
+        
+        
+        public void clearListeners() {
+            
+            mBoundListeners.clear();
+        }
+
+        
+        /**
+         * Adds a listener interested in being reported about the end of operations.
+         * 
+         * @param listener          Object to notify about the end of operations.    
+         * @param callbackHandler   {@link Handler} to access the listener without breaking Android threading protection.
+         */
+        public void addOperationListener (OnRemoteOperationListener listener, Handler callbackHandler) {
+            mBoundListeners.put(listener, callbackHandler);
+        }
+        
+        
+        /**
+         * Removes a listener from the list of objects interested in the being reported about the end of operations.
+         * 
+         * @param listener      Object to notify about progress of transfer.    
+         */
+        public void removeOperationListener (OnRemoteOperationListener listener) {
+            mBoundListeners.remove(listener);
+        }
+
+
+        /**
+         * TODO - IMPORTANT: update implementation when more operations are moved into the service 
+         * 
+         * @return  'True' when an operation that enforces the user to wait for completion is in process.
+         */
+        public boolean isPerformingBlockingOperation() {
+            return (!mPendingOperations.isEmpty());
+        }
+
+    }
+    
+    
+    /** 
+     * Operations worker. Performs the pending operations in the order they were requested. 
+     * 
+     * Created with the Looper of a new thread, started in {@link OperationsService#onCreate()}. 
+     */
+    private static class ServiceHandler extends Handler {
+        // don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak
+        OperationsService mService;
+        public ServiceHandler(Looper looper, OperationsService service) {
+            super(looper);
+            if (service == null) {
+                throw new IllegalArgumentException("Received invalid NULL in parameter 'service'");
+            }
+            mService = service;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            mService.nextOperation();
+            mService.stopSelf(msg.arg1);
+        }
+    }
+    
+
+    /**
+     * Performs the next operation in the queue
+     */
+    private void nextOperation() {
+        
+        Pair<Target, RemoteOperation> next = null;
+        synchronized(mPendingOperations) {
+            next = mPendingOperations.peek();
+        }
+        
+        if (next != null) {
+            
+            mCurrentOperation = next.second;
+            RemoteOperationResult result = null;
+            try {
+                /// prepare client object to send the request to the ownCloud server
+                if (mLastTarget == null || !mLastTarget.equals(next.first)) {
+                    mLastTarget = next.first;
+                    if (mLastTarget.mAccount != null) {
+                        mOwnCloudClient = OwnCloudClientFactory.createOwnCloudClient(mLastTarget.mAccount, getApplicationContext());
+                        mStorageManager = new FileDataStorageManager(mLastTarget.mAccount, getContentResolver());
+                    } else {
+                        mOwnCloudClient = OwnCloudClientFactory.createOwnCloudClient(mLastTarget.mServerUrl, getApplicationContext(), true);    // this is not good enough
+                        mStorageManager = null;
+                    }
+                }
+
+                /// perform the operation
+                if (mCurrentOperation instanceof SyncOperation) {
+                    result = ((SyncOperation)mCurrentOperation).execute(mOwnCloudClient, mStorageManager);
+                } else {
+                    result = mCurrentOperation.execute(mOwnCloudClient);
+                }
+            
+            } catch (AccountsException e) {
+                if (mLastTarget.mAccount == null) {
+                    Log_OC.e(TAG, "Error while trying to get autorization for a NULL account", e);
+                } else {
+                    Log_OC.e(TAG, "Error while trying to get autorization for " + mLastTarget.mAccount.name, e);
+                }
+                result = new RemoteOperationResult(e);
+                
+            } catch (IOException e) {
+                if (mLastTarget.mAccount == null) {
+                    Log_OC.e(TAG, "Error while trying to get autorization for a NULL account", e);
+                } else {
+                    Log_OC.e(TAG, "Error while trying to get autorization for " + mLastTarget.mAccount.name, e);
+                }
+                result = new RemoteOperationResult(e);
+            } catch (Exception e) {
+                if (mLastTarget.mAccount == null) {
+                    Log_OC.e(TAG, "Unexpected error for a NULL account", e);
+                } else {
+                    Log_OC.e(TAG, "Unexpected error for " + mLastTarget.mAccount.name, e);
+                }
+                result = new RemoteOperationResult(e);
+            
+            } finally {
+                synchronized(mPendingOperations) {
+                    mPendingOperations.poll();
+                }
+            }
+            
+            //sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result);
+            callbackOperationListeners(mLastTarget, mCurrentOperation, result);
+        }
+    }
+
+
+    /**
+     * Sends a broadcast when a new operation is added to the queue.
+     * 
+     * Local broadcasts are only delivered to activities in the same process, but can't be done sticky :\
+     * 
+     * @param target            Account or URL pointing to an OC server.
+     * @param operation         Added operation.
+     */
+    private void sendBroadcastNewOperation(Target target, RemoteOperation operation) {
+        Intent intent = new Intent(ACTION_OPERATION_ADDED);
+        if (target.mAccount != null) {
+            intent.putExtra(EXTRA_ACCOUNT, target.mAccount);    
+        } else {
+            intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl);    
+        }
+        //LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
+        //lbm.sendBroadcast(intent);
+        sendStickyBroadcast(intent);
+    }
+
+    
+    // TODO - maybe add a notification for real start of operations
+    
+    /**
+     * Sends a LOCAL broadcast when an operations finishes in order to the interested activities can update their view
+     * 
+     * Local broadcasts are only delivered to activities in the same process.
+     * 
+     * @param target            Account or URL pointing to an OC server.
+     * @param operation         Finished operation.
+     * @param result            Result of the operation.
+     */
+    private void sendBroadcastOperationFinished(Target target, RemoteOperation operation, RemoteOperationResult result) {
+        Intent intent = new Intent(ACTION_OPERATION_FINISHED);
+        intent.putExtra(EXTRA_RESULT, result);
+        if (target.mAccount != null) {
+            intent.putExtra(EXTRA_ACCOUNT, target.mAccount);    
+        } else {
+            intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl);    
+        }
+        //LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
+        //lbm.sendBroadcast(intent);
+        sendStickyBroadcast(intent);
+    }
+
+    
+    /**
+     * Notifies the currently subscribed listeners about the end of an operation.
+     * 
+     * @param target            Account or URL pointing to an OC server.
+     * @param operation         Finished operation.
+     * @param result            Result of the operation.
+     */
+    private void callbackOperationListeners(Target target, final RemoteOperation operation, final RemoteOperationResult result) {
+        Iterator<OnRemoteOperationListener> listeners = mBinder.mBoundListeners.keySet().iterator();
+        while (listeners.hasNext()) {
+            final OnRemoteOperationListener listener = listeners.next();
+            final Handler handler = mBinder.mBoundListeners.get(listener);
+            if (handler != null) { 
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        listener.onRemoteOperationFinish(operation, result);
+                    }
+                });
+            }
+        }
+            
+    }
+    
+
+}
index 74d2686..6dcf531 100644 (file)
@@ -25,10 +25,10 @@ import org.apache.http.HttpResponse;
 import org.apache.http.client.ClientProtocolException;\r
 \r
 import com.owncloud.android.datamodel.FileDataStorageManager;\r
-import com.owncloud.android.oc_framework.accounts.AccountUtils;\r
-import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;\r
-import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;\r
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;\r
+import com.owncloud.android.lib.accounts.AccountUtils;\r
+import com.owncloud.android.lib.accounts.AccountUtils.AccountNotFoundException;\r
+import com.owncloud.android.lib.network.OwnCloudClientFactory;\r
+import com.owncloud.android.lib.network.OwnCloudClient;\r
 \r
 \r
 import android.accounts.Account;\r
@@ -56,7 +56,7 @@ public abstract class AbstractOwnCloudSyncAdapter extends
     private ContentProviderClient mContentProviderClient;\r
     private FileDataStorageManager mStoreManager;\r
 \r
-    private WebdavClient mClient = null;\r
+    private OwnCloudClient mClient = null;\r
 \r
     public AbstractOwnCloudSyncAdapter(Context context, boolean autoInitialize) {\r
         super(context, autoInitialize);\r
@@ -105,7 +105,7 @@ public abstract class AbstractOwnCloudSyncAdapter extends
         mClient = OwnCloudClientFactory.createOwnCloudClient(account, getContext());\r
     }\r
     \r
-    protected WebdavClient getClient() {\r
+    protected OwnCloudClient getClient() {\r
         return mClient;\r
     }\r
     \r
index 9bf5d83..f80824f 100644 (file)
@@ -24,9 +24,8 @@ import java.io.IOException;
 import org.apache.http.client.methods.HttpPut;
 import org.apache.http.entity.ByteArrayEntity;
 
-import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
+import com.owncloud.android.lib.accounts.OwnCloudAccount;
 
 
 import android.accounts.Account;
index f0bc870..6b2ea73 100644 (file)
@@ -26,20 +26,22 @@ import java.util.Map;
 
 import org.apache.jackrabbit.webdav.DavException;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.lib.accounts.OwnCloudAccount;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
 import com.owncloud.android.operations.SynchronizeFolderOperation;
 import com.owncloud.android.operations.UpdateOCVersionOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
 import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.Log_OC;
 
 
 import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.accounts.AccountsException;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -51,6 +53,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.SyncResult;
 import android.os.Bundle;
+//import android.support.v4.content.LocalBroadcastManager;
 
 /**
  * Implementation of {@link AbstractThreadedSyncAdapter} responsible for synchronizing 
@@ -69,6 +72,16 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
     private static final int MAX_FAILED_RESULTS = 3; 
     
     
+    public static final String EVENT_FULL_SYNC_START = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_START";
+    public static final String EVENT_FULL_SYNC_END = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_END";
+    public static final String EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED";
+    public static final String EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED";
+    
+    public static final String EXTRA_ACCOUNT_NAME = FileSyncAdapter.class.getName() + ".EXTRA_ACCOUNT_NAME";
+    public static final String EXTRA_FOLDER_PATH = FileSyncAdapter.class.getName() + ".EXTRA_FOLDER_PATH";
+    public static final String EXTRA_RESULT = FileSyncAdapter.class.getName() + ".EXTRA_RESULT";
+    
+    
     /** Time stamp for the current synchronization process, used to distinguish fresh data */
     private long mCurrentSyncTime;
     
@@ -95,6 +108,9 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
 
     /** {@link SyncResult} instance to return to the system when the synchronization finish */
     private SyncResult mSyncResult;
+
+    /** 'True' means that the server supports the share API */
+    private boolean mIsSharedSupported;
     
     
     /**
@@ -139,6 +155,10 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         this.setAccount(account);
         this.setContentProviderClient(providerClient);
         this.setStorageManager(new FileDataStorageManager(account, providerClient));
+        
+        AccountManager accountManager = getAccountManager();
+        mIsSharedSupported = Boolean.parseBoolean(accountManager.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_SHARE_API));
+
         try {
             this.initClientForCurrentAccount();
         } catch (IOException e) {
@@ -154,7 +174,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         }
         
         Log_OC.d(TAG, "Synchronization of ownCloud account " + account.name + " starting");
-        sendStickyBroadcast(true, null, null);  // message to signal the start of the synchronization to the UI
+        sendLocalBroadcast(EVENT_FULL_SYNC_START, null, null);  // message to signal the start of the synchronization to the UI
         
         try {
             updateOCVersion();
@@ -184,7 +204,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             if (mForgottenLocalFiles.size() > 0) {
                 notifyForgottenLocalFiles();
             }
-            sendStickyBroadcast(false, null, mLastFailedResult);        // message to signal the end to the UI
+            sendLocalBroadcast(EVENT_FULL_SYNC_END, null, mLastFailedResult);   // message to signal the end to the UI
         }
         
     }
@@ -243,13 +263,13 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         DataStorageManager dataStorageManager, 
         Account account, 
         Context context ) {
-            
         }
         */
         // folder synchronization
         SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation(  folder, 
                                                                                     mCurrentSyncTime, 
                                                                                     true,
+                                                                                    mIsSharedSupported,
                                                                                     getStorageManager(), 
                                                                                     getAccount(), 
                                                                                     getContext()
@@ -258,7 +278,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         
         
         // synchronized folder -> notice to UI - ALWAYS, although !result.isSuccess
-        sendStickyBroadcast(true, folder.getRemotePath(), null);
+        sendLocalBroadcast(EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED, folder.getRemotePath(), result);
         
         // check the result of synchronizing the folder
         if (result.isSuccess() || result.getCode() == ResultCode.SYNC_CONFLICT) {
@@ -322,8 +342,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
     private void fetchChildren(OCFile parent, List<OCFile> files, boolean parentEtagChanged) {
         int i;
         OCFile newFile = null;
-        String etag = null;
-        boolean syncDown = false;
+        //String etag = null;
+        //boolean syncDown = false;
         for (i=0; i < files.size() && !mCancellation; i++) {
             newFile = files.get(i);
             if (newFile.isFolder()) {
@@ -332,9 +352,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
                 syncDown = (parentEtagChanged || etag == null || etag.length() == 0);
                 if(syncDown) { */
                     synchronizeFolder(newFile);
-                    // update the size of the parent folder again after recursive synchronization 
-                    //getStorageManager().updateFolderSize(parent.getFileId());  
-                    sendStickyBroadcast(true, parent.getRemotePath(), null);        // notify again to refresh size in UI
+                    sendLocalBroadcast(EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED, parent.getRemotePath(), null);
                 //}
             }
         }
@@ -346,20 +364,22 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
     /**
      * Sends a message to any application component interested in the progress of the synchronization.
      * 
-     * @param inProgress        'True' when the synchronization progress is not finished.
-     * @param dirRemotePath     Remote path of a folder that was just synchronized (with or without success)
+     * @param event             Event in the process of synchronization to be notified.   
+     * @param dirRemotePath     Remote path of the folder target of the event occurred.
+     * @param result            Result of an individual {@ SynchronizeFolderOperation}, if completed; may be null.
      */
-    private void sendStickyBroadcast(boolean inProgress, String dirRemotePath, RemoteOperationResult result) {
-        Intent i = new Intent(FileSyncService.getSyncMessage());
-        i.putExtra(FileSyncService.IN_PROGRESS, inProgress);
-        i.putExtra(FileSyncService.ACCOUNT_NAME, getAccount().name);
+    private void sendLocalBroadcast(String event, String dirRemotePath, RemoteOperationResult result) {
+        Log_OC.d(TAG, "Send broadcast " + event);
+        Intent intent = new Intent(event);
+        intent.putExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME, getAccount().name);
         if (dirRemotePath != null) {
-            i.putExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH, dirRemotePath);
+            intent.putExtra(FileSyncAdapter.EXTRA_FOLDER_PATH, dirRemotePath);
         }
         if (result != null) {
-            i.putExtra(FileSyncService.SYNC_RESULT, result);
+            intent.putExtra(FileSyncAdapter.EXTRA_RESULT, result);
         }
-        getContext().sendStickyBroadcast(i);
+        getContext().sendStickyBroadcast(intent);
+        //LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
     }
 
     
@@ -368,7 +388,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
      * Notifies the user about a failed synchronization through the status notification bar 
      */
     private void notifyFailedSynchronization() {
-        Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
+        Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
         notification.flags |= Notification.FLAG_AUTO_CANCEL;
         boolean needsToUpdateCredentials = (mLastFailedResult != null && 
                                              (  mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
@@ -410,7 +430,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
      */
     private void notifyFailsInFavourites() {
         if (mFailedResultsCounter > 0) {
-            Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_in_favourites_ticker), System.currentTimeMillis());
+            Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_fail_in_favourites_ticker), System.currentTimeMillis());
             notification.flags |= Notification.FLAG_AUTO_CANCEL;
             // TODO put something smart in the contentIntent below
             notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
@@ -421,7 +441,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_in_favourites_ticker, notification);
             
         } else {
-            Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_conflicts_in_favourites_ticker), System.currentTimeMillis());
+            Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_conflicts_in_favourites_ticker), System.currentTimeMillis());
             notification.flags |= Notification.FLAG_AUTO_CANCEL;
             // TODO put something smart in the contentIntent below
             notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
@@ -443,7 +463,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
      * We won't consider a synchronization as failed when foreign files can not be copied to the ownCloud local directory.
      */
     private void notifyForgottenLocalFiles() {
-        Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_foreign_files_forgotten_ticker), System.currentTimeMillis());
+        Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_foreign_files_forgotten_ticker), System.currentTimeMillis());
         notification.flags |= Notification.FLAG_AUTO_CANCEL;
 
         /// includes a pending intent in the notification showing a more detailed explanation
index 1e1e11f..5da8c24 100644 (file)
@@ -17,8 +17,6 @@
  */\r
 package com.owncloud.android.syncadapter;\r
 \r
-import com.owncloud.android.utils.Log_OC;\r
-\r
 import android.app.Service;\r
 import android.content.Intent;\r
 import android.os.IBinder;\r
@@ -33,20 +31,11 @@ import android.os.IBinder;
  */\r
 public class FileSyncService extends Service {\r
     \r
-    private static final String SYNC_MESSAGE = "ACCOUNT_SYNC";\r
-    public static final String SYNC_FOLDER_REMOTE_PATH = "SYNC_FOLDER_REMOTE_PATH";\r
-    public static final String IN_PROGRESS = "SYNC_IN_PROGRESS";\r
-    public static final String ACCOUNT_NAME = "ACCOUNT_NAME";\r
-    public static final String SYNC_RESULT = "SYNC_RESULT";\r
-\r
     // Storage for an instance of the sync adapter\r
     private static FileSyncAdapter sSyncAdapter = null;\r
     // Object to use as a thread-safe lock\r
     private static final Object sSyncAdapterLock = new Object();\r
     \r
-    public static String getSyncMessage(){\r
-        return FileSyncService.class.getName().toString() + SYNC_MESSAGE;\r
-    }\r
     /*\r
      * {@inheritDoc}\r
      */\r
index b1ff845..9f8bcfd 100644 (file)
@@ -27,7 +27,6 @@ import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.AccountManagerCallback;
 import android.accounts.AccountManagerFuture;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
@@ -49,7 +48,8 @@ import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
+import com.owncloud.android.lib.accounts.OwnCloudAccount;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
@@ -75,9 +75,10 @@ public class AccountSelectActivity extends SherlockListActivity implements
             mPreviousAccount = AccountUtils.getCurrentOwnCloudAccount(this);
         }
         
-        ActionBar action_bar = getSupportActionBar();
-        action_bar.setDisplayShowTitleEnabled(true);
-        action_bar.setDisplayHomeAsUpEnabled(false);
+        ActionBar actionBar = getSupportActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
+        actionBar.setDisplayShowTitleEnabled(true);
+        actionBar.setDisplayHomeAsUpEnabled(false);
     }
 
     @Override
index 2d13a66..fbbc5df 100644 (file)
 
 package com.owncloud.android.ui.activity;
 
-import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.actionbarsherlock.app.ActionBar;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog.OnConflictDecisionMadeListener;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.Log_OC;
 
 import android.content.Intent;
@@ -43,10 +44,12 @@ public class ConflictsResolveActivity extends FileActivity implements OnConflict
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        ActionBar actionBar = getSupportActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
     }
 
     @Override
-    public void ConflictDecisionMade(Decision decision) {
+    public void conflictDecisionMade(Decision decision) {
         Intent i = new Intent(getApplicationContext(), FileUploader.class);
         
         switch (decision) {
@@ -73,6 +76,7 @@ public class ConflictsResolveActivity extends FileActivity implements OnConflict
 
     @Override
     protected void onAccountSet(boolean stateWasRecovered) {
+        super.onAccountSet(stateWasRecovered);
         if (getAccount() != null) {
             OCFile file = getFile();
             if (getFile() == null) {
@@ -80,8 +84,7 @@ public class ConflictsResolveActivity extends FileActivity implements OnConflict
                 finish();
             } else {
                 /// Check whether the 'main' OCFile handled by the Activity is contained in the current Account
-                FileDataStorageManager storageManager = new FileDataStorageManager(getAccount(), getContentResolver());
-                file = storageManager.getFileByPath(file.getRemotePath());   // file = null if not in the current Account
+                file = getStorageManager().getFileByPath(file.getRemotePath());   // file = null if not in the current Account
                 if (file != null) {
                     setFile(file);
                     ConflictsResolveDialog d = ConflictsResolveDialog.newInstance(file.getRemotePath(), this);
@@ -94,7 +97,6 @@ public class ConflictsResolveActivity extends FileActivity implements OnConflict
             }
             
         } else {
-            Log_OC.wtf(TAG, "onAccountChanged was called with NULL account associated!");
             finish();
         }
         
index 59b4443..dc3ad0d 100644 (file)
@@ -23,17 +23,35 @@ import android.accounts.AccountManager;
 import android.accounts.AccountManagerCallback;
 import android.accounts.AccountManagerFuture;
 import android.accounts.OperationCanceledException;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
-import android.net.Uri;
+import android.content.ServiceConnection;
 import android.os.Bundle;
-import android.webkit.MimeTypeMap;
+import android.os.Handler;
+import android.os.IBinder;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.widget.Toast;
 
 import com.actionbarsherlock.app.SherlockFragmentActivity;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.files.FileOperationsHelper;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.operations.CreateShareOperation;
+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.LoadingDialog;
 import com.owncloud.android.utils.Log_OC;
 
 
@@ -42,13 +60,16 @@ import com.owncloud.android.utils.Log_OC;
  * 
  * @author David A. Velasco
  */
-public abstract class FileActivity extends SherlockFragmentActivity {
+public class FileActivity extends SherlockFragmentActivity implements OnRemoteOperationListener {
 
     public static final String EXTRA_FILE = "com.owncloud.android.ui.activity.FILE";
     public static final String EXTRA_ACCOUNT = "com.owncloud.android.ui.activity.ACCOUNT";
     public static final String EXTRA_WAITING_TO_PREVIEW = "com.owncloud.android.ui.activity.WAITING_TO_PREVIEW";
+    public static final String EXTRA_FROM_NOTIFICATION= "com.owncloud.android.ui.activity.FROM_NOTIFICATION";
+    
+    public static final String TAG = FileActivity.class.getSimpleName();
     
-    public static final String TAG = FileActivity.class.getSimpleName(); 
+    private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
     
     
     /** OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located. */
@@ -65,6 +86,21 @@ public abstract class FileActivity extends SherlockFragmentActivity {
     
     /** Flag to signal when the value of mAccount was restored from a saved state */ 
     private boolean mAccountWasRestored;
+    
+    /** Flag to signal if the activity is launched by a notification */
+    private boolean mFromNotification;
+    
+    /** Messages handler associated to the main thread and the life cycle of the activity */
+    private Handler mHandler;
+    
+    /** Access point to the cached database for the current ownCloud {@link Account} */
+    private FileDataStorageManager mStorageManager = null;
+    
+    private FileOperationsHelper mFileOperationsHelper;
+    
+    private ServiceConnection mOperationsServiceConnection = null;
+    
+    private OperationsServiceBinder mOperationsServiceBinder = null;
 
     
     /**
@@ -77,17 +113,23 @@ public abstract class FileActivity extends SherlockFragmentActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
+        mHandler = new Handler();
+        mFileOperationsHelper = new FileOperationsHelper();
         Account account;
         if(savedInstanceState != null) {
             account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
             mFile = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE);
+            mFromNotification = savedInstanceState.getBoolean(FileActivity.EXTRA_FROM_NOTIFICATION);
         } else {
             account = getIntent().getParcelableExtra(FileActivity.EXTRA_ACCOUNT);
             mFile = getIntent().getParcelableExtra(FileActivity.EXTRA_FILE);
+            mFromNotification = getIntent().getBooleanExtra(FileActivity.EXTRA_FROM_NOTIFICATION, false);
         }
 
         setAccount(account, savedInstanceState != null);
+        
+        mOperationsServiceConnection = new OperationsServiceConnection();
+        bindService(new Intent(this, OperationsService.class), mOperationsServiceConnection, Context.BIND_AUTO_CREATE);
     }
 
     
@@ -103,7 +145,6 @@ public abstract class FileActivity extends SherlockFragmentActivity {
         if (!validAccount) {
             swapToDefaultAccount();
         }
-        
     }
 
     
@@ -113,6 +154,28 @@ public abstract class FileActivity extends SherlockFragmentActivity {
         if (mAccountWasSet) {
             onAccountSet(mAccountWasRestored);
         }
+        if (mOperationsServiceBinder != null) {
+            mOperationsServiceBinder.addOperationListener(FileActivity.this, mHandler);
+        }
+    }
+    
+    
+    @Override 
+    protected void onStop() {
+        super.onStop();
+        if (mOperationsServiceBinder != null) {
+            mOperationsServiceBinder.removeOperationListener(this);
+        }
+    }
+    
+    
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mOperationsServiceConnection != null) {
+            unbindService(mOperationsServiceConnection);
+            mOperationsServiceBinder = null;
+        }
     }
     
     
@@ -191,6 +254,7 @@ public abstract class FileActivity extends SherlockFragmentActivity {
         super.onSaveInstanceState(outState);
         outState.putParcelable(FileActivity.EXTRA_FILE, mFile);
         outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount);
+        outState.putBoolean(FileActivity.EXTRA_FROM_NOTIFICATION, mFromNotification);
     }
     
     
@@ -223,6 +287,12 @@ public abstract class FileActivity extends SherlockFragmentActivity {
         return mAccount;
     }
 
+    /**
+     * @return Value of mFromNotification: True if the Activity is launched by a notification
+     */
+    public boolean fromNotification() {
+        return mFromNotification;
+    }
     
     /**
      * @return  'True' when the Activity is finishing to enforce the setup of a new account.
@@ -279,41 +349,149 @@ public abstract class FileActivity extends SherlockFragmentActivity {
      * 
      *  Child classes must grant that state depending on the {@link Account} is updated.
      */
-    protected abstract void onAccountSet(boolean stateWasRecovered);
+    protected void onAccountSet(boolean stateWasRecovered) {
+        if (getAccount() != null) {
+            mStorageManager = new FileDataStorageManager(getAccount(), getContentResolver());
+            
+        } else {
+            Log_OC.wtf(TAG, "onAccountChanged was called with NULL account associated!");
+        }
+    }
+
+
+    public FileDataStorageManager getStorageManager() {
+        return mStorageManager;
+    }
+
+
+    public OnRemoteOperationListener getRemoteOperationListener() {
+        return this;
+    }
+
+
+    public Handler getHandler() {
+        return mHandler;
+    }
     
+    public FileOperationsHelper getFileOperationsHelper() {
+        return mFileOperationsHelper;
+    }
     
+    /**
+     * 
+     * @param operation     Removal operation performed.
+     * @param result        Result of the removal.
+     */
+    @Override
+    public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+        Log_OC.d(TAG, "Received result of operation in FileActivity - common behaviour for all the FileActivities ");
+        if (operation instanceof CreateShareOperation) {
+            onCreateShareOperationFinish((CreateShareOperation) operation, result);
+            
+        } else if (operation instanceof UnshareLinkOperation) {
+            onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result);
+        
+        } 
+    }
 
-    public void openFile(OCFile file) {
-        if (file != null) {
-            String storagePath = file.getStoragePath();
-            String encodedStoragePath = WebdavUtils.encodePath(storagePath);
+    private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) {
+        dismissLoadingDialog();
+        if (result.isSuccess()) {
+            updateFileFromDB();
             
-            Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
-            intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype());
-            intentForSavedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+            Intent sendIntent = operation.getSendIntent();
+            startActivity(sendIntent);
             
-            Intent intentForGuessedMimeType = null;
-            if (storagePath.lastIndexOf('.') >= 0) {
-                String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
-                if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
-                    intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
-                    intentForGuessedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), guessedMimeType);
-                    intentForGuessedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-                }
-            }
+        } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND)  {        // Error --> SHARE_NOT_FOUND
+                Toast t = Toast.makeText(this, getString(R.string.share_link_file_no_exist), Toast.LENGTH_LONG);
+                t.show();
+        } else {    // Generic error
+            // Show a Message, operation finished without success
+            Toast t = Toast.makeText(this, getString(R.string.share_link_file_error), Toast.LENGTH_LONG);
+            t.show();
+        }
+    }
+    
+    
+    private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) {
+        dismissLoadingDialog();
+        
+        if (result.isSuccess()){
+            updateFileFromDB();
             
-            Intent chooserIntent = null;
-            if (intentForGuessedMimeType != null) {
-                chooserIntent = Intent.createChooser(intentForGuessedMimeType, getString(R.string.actionbar_open_with));
+        } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND)  {        // Error --> SHARE_NOT_FOUND
+            Toast t = Toast.makeText(this, getString(R.string.unshare_link_file_no_exist), Toast.LENGTH_LONG);
+            t.show();
+        } else {    // Generic error
+            // Show a Message, operation finished without success
+            Toast t = Toast.makeText(this, getString(R.string.unshare_link_file_error), Toast.LENGTH_LONG);
+            t.show();
+        }
+        
+    }
+    
+    
+    private void updateFileFromDB(){
+      OCFile file = getStorageManager().getFileByPath(getFile().getRemotePath());
+      if (file != null) {
+          setFile(file);
+      }
+    }
+    
+    /**
+     * Show loading dialog 
+     */
+    public void showLoadingDialog() {
+        // Construct dialog
+        LoadingDialog loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment));
+        FragmentManager fm = getSupportFragmentManager();
+        FragmentTransaction ft = fm.beginTransaction();
+        loading.show(ft, DIALOG_WAIT_TAG);
+        
+    }
+
+    
+    /**
+     * Dismiss loading dialog
+     */
+    public void dismissLoadingDialog(){
+        Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
+        if (frag != null) {
+            LoadingDialog loading = (LoadingDialog) frag;
+            loading.dismiss();
+        }
+    }
+
+    
+    /** 
+     * Implements callback methods for service binding. Passed as a parameter to { 
+     */
+    private class OperationsServiceConnection implements ServiceConnection {
+
+        @Override
+        public void onServiceConnected(ComponentName component, IBinder service) {
+            if (component.equals(new ComponentName(FileActivity.this, OperationsService.class))) {
+                Log_OC.d(TAG, "Operations service connected");
+                mOperationsServiceBinder = (OperationsServiceBinder) service;
+                mOperationsServiceBinder.addOperationListener(FileActivity.this, mHandler);
+                if (!mOperationsServiceBinder.isPerformingBlockingOperation()) {
+                    dismissLoadingDialog();
+                }
+
             } else {
-                chooserIntent = Intent.createChooser(intentForSavedMimeType, getString(R.string.actionbar_open_with));
+                return;
             }
-            
-            startActivity(chooserIntent);
-            
-        } else {
-            Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
         }
-    }
+        
+
+        @Override
+        public void onServiceDisconnected(ComponentName component) {
+            if (component.equals(new ComponentName(FileActivity.this, OperationsService.class))) {
+                Log_OC.d(TAG, "Operations service disconnected");
+                mOperationsServiceBinder = null;
+                // TODO whatever could be waiting for the service is unbound
+            }
+        }
+    };    
     
 }
index 0bf8207..e696352 100644 (file)
@@ -38,13 +38,12 @@ import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.IBinder;
 import android.preference.PreferenceManager;
 import android.provider.MediaStore;
 import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
+//import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -60,7 +59,6 @@ import com.actionbarsherlock.view.MenuItem;
 import com.actionbarsherlock.view.Window;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
-import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileObserverService;
@@ -68,26 +66,30 @@ import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.operations.CreateFolderOperation;
-import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.operations.CreateShareOperation;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.SynchronizeFolderOperation;
-import com.owncloud.android.syncadapter.FileSyncService;
+import com.owncloud.android.operations.UnshareLinkOperation;
+import com.owncloud.android.services.OperationsService;
+import com.owncloud.android.syncadapter.FileSyncAdapter;
 import com.owncloud.android.ui.dialog.EditNameDialog;
 import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
-import com.owncloud.android.ui.dialog.LoadingDialog;
 import com.owncloud.android.ui.dialog.SslValidatorDialog;
 import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
 import com.owncloud.android.ui.fragment.FileDetailFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
 import com.owncloud.android.ui.fragment.OCFileListFragment;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
+import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.ui.preview.PreviewVideoActivity;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.Log_OC;
 
 
@@ -98,17 +100,15 @@ import com.owncloud.android.utils.Log_OC;
  * @author David A. Velasco
  */
 
-public class FileDisplayActivity extends FileActivity implements
-OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslValidatorListener, OnRemoteOperationListener, EditNameDialogListener {
+public class FileDisplayActivity extends HookActivity implements
+OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslValidatorListener, EditNameDialogListener {
 
     private ArrayAdapter<String> mDirectories;
 
-    /** Access point to the cached database for the current ownCloud {@link Account} */
-    private FileDataStorageManager mStorageManager = null;
-
     private SyncBroadcastReceiver mSyncBroadcastReceiver;
     private UploadFinishReceiver mUploadFinishReceiver;
     private DownloadFinishReceiver mDownloadFinishReceiver;
+    //private OperationsServiceReceiver mOperationsServiceReceiver;
     private FileDownloaderBinder mDownloaderBinder = null;
     private FileUploaderBinder mUploaderBinder = null;
     private ServiceConnection mDownloadConnection = null, mUploadConnection = null;
@@ -120,14 +120,13 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
 
     private static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
     private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS";
+    private static final String KEY_REFRESH_SHARES_IN_PROGRESS = "SHARES_IN_PROGRESS";
 
     public static final int DIALOG_SHORT_WAIT = 0;
     private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1;
     private static final int DIALOG_SSL_VALIDATOR = 2;
     private static final int DIALOG_CERT_NOT_SAVED = 3;
     
-    private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
-
     public static final String ACTION_DETAILS = "com.owncloud.android.ui.activity.action.DETAILS";
 
     private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
@@ -139,9 +138,9 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
     private static final String TAG_SECOND_FRAGMENT = "SECOND_FRAGMENT";
 
     private OCFile mWaitingToPreview;
-    private Handler mHandler;
     
     private boolean mSyncInProgress = false;
+    //private boolean mRefreshSharesInProgress = false;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -150,8 +149,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
 
         super.onCreate(savedInstanceState); // this calls onAccountChanged() when ownCloud Account is valid
 
-        mHandler = new Handler();
-        
         /// bindings to transference services
         mUploadConnection = new ListServiceConnection(); 
         mDownloadConnection = new ListServiceConnection();
@@ -161,6 +158,8 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         // PIN CODE request ;  best location is to decide, let's try this first
         if (getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN) && savedInstanceState == null) {
             requestPinCode();
+        } else if (getIntent().getAction() == null && savedInstanceState == null) {
+            requestPinCode();
         }
 
         /// file observer
@@ -172,10 +171,12 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         if(savedInstanceState != null) {
             mWaitingToPreview = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW);
             mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS);
+            //mRefreshSharesInProgress = savedInstanceState.getBoolean(KEY_REFRESH_SHARES_IN_PROGRESS);
            
         } else {
             mWaitingToPreview = null;
             mSyncInProgress = false;
+            //mRefreshSharesInProgress = false;
         }        
 
         /// USER INTERFACE
@@ -187,18 +188,27 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         mRightFragmentContainer = findViewById(R.id.right_fragment_container);
         if (savedInstanceState == null) {
             createMinFragments();
+        } else {
+            Log_OC.d(TAG, "Init the secondFragment again");
+            if (mDualPane) {
+                initFragmentsWithFile();                
+            }
         }
 
         // Action bar setup
         mDirectories = new CustomArrayAdapter<String>(this, R.layout.sherlock_spinner_dropdown_item);
         getSupportActionBar().setHomeButtonEnabled(true);       // mandatory since Android ICS, according to the official documentation
-        setSupportProgressBarIndeterminateVisibility(mSyncInProgress);    // always AFTER setContentView(...) ; to work around bug in its implementation        
-        
-        
+        setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/);    // always AFTER setContentView(...) ; to work around bug in its implementation
         
         Log_OC.d(TAG, "onCreate() end");
     }
-
+    
+    @Override
+    protected void onStart() {
+        super.onStart();
+        getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId());
+        refeshListOfFilesFragment();
+    }
 
     @Override
     protected void onDestroy() {
@@ -215,9 +225,8 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
      */ 
     @Override
     protected void onAccountSet(boolean stateWasRecovered) {
+        super.onAccountSet(stateWasRecovered);
         if (getAccount() != null) {
-            mStorageManager = new FileDataStorageManager(getAccount(), getContentResolver());
-
             /// Check whether the 'main' OCFile handled by the Activity is contained in the current Account
             OCFile file = getFile();
             // get parent from path
@@ -227,18 +236,19 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
                     // upload in progress - right now, files are not inserted in the local cache until the upload is successful
                     // get parent from path
                     parentPath = file.getRemotePath().substring(0, file.getRemotePath().lastIndexOf(file.getFileName()));
-                    if (mStorageManager.getFileByPath(parentPath) ==  null)
+                    if (getStorageManager().getFileByPath(parentPath) ==  null)
                         file = null; // not able to know the directory where the file is uploading
                 } else {
-                    file = mStorageManager.getFileByPath(file.getRemotePath());   // currentDir = null if not in the current Account
+                    file = getStorageManager().getFileByPath(file.getRemotePath());   // currentDir = null if not in the current Account
                 }
             }
             if (file == null) {
                 // fall back to root folder
-                file = mStorageManager.getFileByPath(OCFile.ROOT_PATH);  // never returns null
+                file = getStorageManager().getFileByPath(OCFile.ROOT_PATH);  // never returns null
             }
             setFile(file);
             setNavigationListWithFolder(file);
+            
             if (!stateWasRecovered) {
                 Log_OC.e(TAG, "Initializing Fragments in onAccountChanged..");
                 initFragmentsWithFile();
@@ -250,10 +260,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
                 updateFragmentsVisibility(!file.isFolder());
                 updateNavigationElementsInActionBar(file.isFolder() ? null : file);
             }
-            
-            
-        } else {
-            Log_OC.wtf(TAG, "onAccountChanged was called with NULL account associated!");
         }
     }
 
@@ -266,10 +272,9 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
             if (fileIt.isFolder()) {
                 mDirectories.add(fileIt.getFileName());
             }
-            //fileIt = mStorageManager.getFileById(fileIt.getParentId());
             // get parent from path
             parentPath = fileIt.getRemotePath().substring(0, fileIt.getRemotePath().lastIndexOf(fileIt.getFileName()));
-            fileIt = mStorageManager.getFileByPath(parentPath);
+            fileIt = getStorageManager().getFileByPath(parentPath);
         }
         mDirectories.add(OCFile.PATH_SEPARATOR);
     }
@@ -281,7 +286,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         transaction.add(R.id.left_fragment_container, listOfFiles, TAG_LIST_OF_FILES);
         transaction.commit();
     }
-
+    
     private void initFragmentsWithFile() {
         if (getAccount() != null && getFile() != null) {
             /// First fragment
@@ -431,12 +436,12 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
                 boolean detailsFragmentChanged = false;
                 if (waitedPreview) {
                     if (success) {
-                        mWaitingToPreview = mStorageManager.getFileById(mWaitingToPreview.getFileId());   // update the file from database, for the local storage path
+                        mWaitingToPreview = getStorageManager().getFileById(mWaitingToPreview.getFileId());   // update the file from database, for the local storage path
                         if (PreviewMediaFragment.canBePreviewed(mWaitingToPreview)) {
                             startMediaPreview(mWaitingToPreview, 0, true);
                             detailsFragmentChanged = true;
                         } else {
-                            openFile(mWaitingToPreview);
+                            getFileOperationsHelper().openFile(mWaitingToPreview, this);
                         }
                     }
                     mWaitingToPreview = null;
@@ -448,7 +453,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         }
     }
 
-
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         MenuInflater inflater = getSherlock().getMenuInflater();
@@ -527,7 +531,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
                 targetPath = mDirectories.getItem(i) + OCFile.PATH_SEPARATOR + targetPath; 
             }
             targetPath = OCFile.PATH_SEPARATOR + targetPath;
-            OCFile targetFolder = mStorageManager.getFileByPath(targetPath);
+            OCFile targetFolder = getStorageManager().getFileByPath(targetPath);
             if (targetFolder != null) {
                 browseTo(targetFolder);
             }
@@ -535,7 +539,8 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
             // the next operation triggers a new call to this method, but it's necessary to 
             // ensure that the name exposed in the action bar is the current directory when the 
             // user selected it in the navigation list
-            getSupportActionBar().setSelectedNavigationItem(0);
+            if (getSupportActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_LIST  && itemPosition != 0) 
+                getSupportActionBar().setSelectedNavigationItem(0);
         }
         return true;
     }
@@ -661,6 +666,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         super.onSaveInstanceState(outState);
         outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
         outState.putBoolean(FileDisplayActivity.KEY_SYNC_IN_PROGRESS, mSyncInProgress);
+        //outState.putBoolean(FileDisplayActivity.KEY_REFRESH_SHARES_IN_PROGRESS, mRefreshSharesInProgress);
 
         Log_OC.d(TAG, "onSaveInstanceState() end");
     }
@@ -673,9 +679,15 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         Log_OC.e(TAG, "onResume() start");
 
         // Listen for sync messages
-        IntentFilter syncIntentFilter = new IntentFilter(FileSyncService.getSyncMessage());
+        IntentFilter syncIntentFilter = new IntentFilter(FileSyncAdapter.EVENT_FULL_SYNC_START);
+        syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_END);
+        syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED);
+        syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED);
+        syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED);
+        syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED);
         mSyncBroadcastReceiver = new SyncBroadcastReceiver();
         registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
+        //LocalBroadcastManager.getInstance(this).registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
 
         // Listen for upload messages
         IntentFilter uploadIntentFilter = new IntentFilter(FileUploader.getUploadFinishMessage());
@@ -687,6 +699,14 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         downloadIntentFilter.addAction(FileDownloader.getDownloadFinishMessage());
         mDownloadFinishReceiver = new DownloadFinishReceiver();
         registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
+        
+        // Listen for messages from the OperationsService
+        /*
+        IntentFilter operationsIntentFilter = new IntentFilter(OperationsService.ACTION_OPERATION_ADDED);
+        operationsIntentFilter.addAction(OperationsService.ACTION_OPERATION_FINISHED);
+        mOperationsServiceReceiver = new OperationsServiceReceiver();
+        LocalBroadcastManager.getInstance(this).registerReceiver(mOperationsServiceReceiver, operationsIntentFilter);
+        */
     
         Log_OC.d(TAG, "onResume() end");
     }
@@ -698,6 +718,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         Log_OC.e(TAG, "onPause() start");
         if (mSyncBroadcastReceiver != null) {
             unregisterReceiver(mSyncBroadcastReceiver);
+            //LocalBroadcastManager.getInstance(this).unregisterReceiver(mSyncBroadcastReceiver);
             mSyncBroadcastReceiver = null;
         }
         if (mUploadFinishReceiver != null) {
@@ -708,7 +729,12 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
             unregisterReceiver(mDownloadFinishReceiver);
             mDownloadFinishReceiver = null;
         }
-
+        /*
+        if (mOperationsServiceReceiver != null) {
+            LocalBroadcastManager.getInstance(this).unregisterReceiver(mOperationsServiceReceiver);
+            mOperationsServiceReceiver = null;
+        }
+        */
         Log_OC.d(TAG, "onPause() end");
     }
 
@@ -805,30 +831,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
 
 
     /**
-     * Show loading dialog 
-     */
-    public void showLoadingDialog() {
-        // Construct dialog
-        LoadingDialog loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment));
-        FragmentManager fm = getSupportFragmentManager();
-        FragmentTransaction ft = fm.beginTransaction();
-        loading.show(ft, DIALOG_WAIT_TAG);
-        
-    }
-    
-    /**
-     * Dismiss loading dialog
-     */
-    public void dismissLoadingDialog(){
-        Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
-      if (frag != null) {
-          LoadingDialog loading = (LoadingDialog) frag;
-            loading.dismiss();
-        }
-    }
-    
-    
-    /**
      * Translates a content URI of an image to a physical path
      * on the disk
      * @param uri The URI to resolve
@@ -880,6 +882,8 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
 
             ((TextView) v).setTextColor(getResources().getColorStateList(
                     android.R.color.white));
+            
+            fixRoot((TextView) v );
             return v;
         }
 
@@ -890,9 +894,16 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
             ((TextView) v).setTextColor(getResources().getColorStateList(
                     android.R.color.white));
 
+            fixRoot((TextView) v );
             return v;
         }
 
+        private void fixRoot(TextView v) {
+            if (v.getText().equals(OCFile.PATH_SEPARATOR)) {
+                v.setText(R.string.default_display_name_for_root_folder);
+            }
+        }
+
     }
 
     private class SyncBroadcastReceiver extends BroadcastReceiver {
@@ -902,47 +913,65 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
          */
         @Override
         public void onReceive(Context context, Intent intent) {
-            boolean inProgress = intent.getBooleanExtra(FileSyncService.IN_PROGRESS, false);
-            String accountName = intent.getStringExtra(FileSyncService.ACCOUNT_NAME);
-            RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
-
-            if (getAccount() != null && accountName.equals(getAccount().name)
-                    && mStorageManager != null
-                    ) {  
-
-                String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH); 
-
-                OCFile currentFile = (getFile() == null) ? null : mStorageManager.getFileByPath(getFile().getRemotePath());
-                OCFile currentDir = (getCurrentDir() == null) ? null : mStorageManager.getFileByPath(getCurrentDir().getRemotePath());
-
-                if (currentDir == null) {
-                    // current folder was removed from the server 
-                    Toast.makeText( FileDisplayActivity.this, 
-                                    String.format(getString(R.string.sync_current_folder_was_removed), mDirectories.getItem(0)), 
-                                    Toast.LENGTH_LONG)
-                        .show();
-                    browseToRoot();
+            String event = intent.getAction();
+            Log_OC.d(TAG, "Received broadcast " + event);
+            String accountName = intent.getStringExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME);
+            String synchFolderRemotePath = intent.getStringExtra(FileSyncAdapter.EXTRA_FOLDER_PATH); 
+            RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncAdapter.EXTRA_RESULT);
+            boolean sameAccount = (getAccount() != null && accountName.equals(getAccount().name) && getStorageManager() != null); 
+
+            if (sameAccount) {
+                
+                if (FileSyncAdapter.EVENT_FULL_SYNC_START.equals(event)) {
+                    mSyncInProgress = true;
                     
                 } else {
-                    if (currentFile == null && !getFile().isFolder()) {
-                        // currently selected file was removed in the server, and now we know it
-                        cleanSecondFragment();
-                        currentFile = currentDir;
-                    }
-                
-                    if (synchFolderRemotePath != null && currentDir.getRemotePath().equals(synchFolderRemotePath)) {
-                        OCFileListFragment fileListFragment = getListOfFilesFragment();
-                        if (fileListFragment != null) {
-                            fileListFragment.listDirectory(currentDir);
+                    OCFile currentFile = (getFile() == null) ? null : getStorageManager().getFileByPath(getFile().getRemotePath());
+                    OCFile currentDir = (getCurrentDir() == null) ? null : getStorageManager().getFileByPath(getCurrentDir().getRemotePath());
+
+                    if (currentDir == null) {
+                        // current folder was removed from the server 
+                        Toast.makeText( FileDisplayActivity.this, 
+                                        String.format(getString(R.string.sync_current_folder_was_removed), mDirectories.getItem(0)), 
+                                        Toast.LENGTH_LONG)
+                            .show();
+                        browseToRoot();
+                        
+                    } else {
+                        if (currentFile == null && !getFile().isFolder()) {
+                            // currently selected file was removed in the server, and now we know it
+                            cleanSecondFragment();
+                            currentFile = currentDir;
                         }
+                    
+                        if (synchFolderRemotePath != null && currentDir.getRemotePath().equals(synchFolderRemotePath)) {
+                            OCFileListFragment fileListFragment = getListOfFilesFragment();
+                            if (fileListFragment != null) {
+                                fileListFragment.listDirectory(currentDir);
+                            }
+                        }
+                        setFile(currentFile);
+                    }
+                    
+                    mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
+                            
+                    /*
+                    if (synchResult != null && 
+                        synchResult.isSuccess() &&
+                            (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SYNCED.equals(event) || 
+                                FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED.equals(event)
+                            ) &&
+                            !mRefreshSharesInProgress &&
+                            getFileOperationsHelper().isSharedSupported(FileDisplayActivity.this)
+                        ) {
+                        startGetShares();
                     }
-                    setFile(currentFile);
+                    */
+                    
                 }
-                
-                setSupportProgressBarIndeterminateVisibility(inProgress);
                 removeStickyBroadcast(intent);
-                mSyncInProgress = inProgress;
-
+                Log_OC.d(TAG, "Setting progress visibility to " + mSyncInProgress);
+                setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/);
             }
             
             if (synchResult != null) {
@@ -1007,16 +1036,45 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
             return (accountName != null && getAccount() != null && accountName.equals(getAccount().name));
         }
     }
-
-
+    
+    
     /**
-     * {@inheritDoc}
+     * Class waiting for broadcast events from the {@link OperationsService}.
+     * 
+     * Updates the list of files when a get for shares is finished; at this moment the refresh of shares is the only
+     * operation performed in {@link OperationsService}.
+     * 
+     * In the future will handle the progress or finalization of all the operations performed in {@link OperationsService}, 
+     * probably all the operations associated to the app model. 
      */
-    @Override
-    public FileDataStorageManager getStorageManager() {
-        return mStorageManager;
-    }
+    private class OperationsServiceReceiver extends BroadcastReceiver {
 
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (OperationsService.ACTION_OPERATION_ADDED.equals(intent.getAction())) {
+                
+            } else if (OperationsService.ACTION_OPERATION_FINISHED.equals(intent.getAction())) {
+                //mRefreshSharesInProgress = false;
+                
+                Account account = intent.getParcelableExtra(OperationsService.EXTRA_ACCOUNT);
+                RemoteOperationResult getSharesResult = (RemoteOperationResult)intent.getSerializableExtra(OperationsService.EXTRA_RESULT);
+                if (getAccount() != null && account.name.equals(getAccount().name)
+                        && getStorageManager() != null
+                        ) {
+                    refeshListOfFilesFragment();
+                }
+                if ((getSharesResult != null) &&
+                        RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED.equals(getSharesResult.getCode())) {
+                    mLastSslUntrustedServerResult = getSharesResult;
+                    showDialog(DIALOG_SSL_VALIDATOR); 
+                }
+
+                //setSupportProgressBarIndeterminateVisibility(mRefreshSharesInProgress || mSyncInProgress);
+            }
+            
+        }
+            
+    }
 
     public void browseToRoot() {
         OCFileListFragment listOfFiles = getListOfFilesFragment(); 
@@ -1024,7 +1082,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
             while (mDirectories.getCount() > 1) {
                 popDirname();
             }
-            OCFile root = mStorageManager.getFileByPath(OCFile.ROOT_PATH);
+            OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
             listOfFiles.listDirectory(root);
             setFile(listOfFiles.getCurrentFile());
             startSyncFolderOperation(root);
@@ -1137,9 +1195,13 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         if (chosenFile == null || mDualPane) {
             // only list of files - set for browsing through folders
             OCFile currentDir = getCurrentDir();
-            actionBar.setDisplayHomeAsUpEnabled(currentDir != null && currentDir.getParentId() != 0);
-            actionBar.setDisplayShowTitleEnabled(false);
-            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+            boolean noRoot = (currentDir != null && currentDir.getParentId() != 0);
+            actionBar.setDisplayHomeAsUpEnabled(noRoot);
+            actionBar.setDisplayShowTitleEnabled(!noRoot); 
+            if (!noRoot) {
+                actionBar.setTitle(getString(R.string.default_display_name_for_root_folder));
+            }
+            actionBar.setNavigationMode(!noRoot ? ActionBar.NAVIGATION_MODE_STANDARD : ActionBar.NAVIGATION_MODE_LIST);
             actionBar.setListNavigationCallbacks(mDirectories, this);   // assuming mDirectories is updated
 
         } else {
@@ -1151,19 +1213,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
     }
 
 
-//    private void updateDisplayHomeAtSync(){
-//        ActionBar actionBar = getSupportActionBar();
-//        OCFile currentDir = getCurrentDir();
-//        if (currentDir.getParentId() != DataStorageManager.ROOT_PARENT_ID) {
-//            actionBar.setHomeButtonEnabled(!mSyncInProgress);
-//            actionBar.setDisplayHomeAsUpEnabled(!mSyncInProgress);
-//        }
-//        else {
-//            actionBar.setHomeButtonEnabled(true);
-//            actionBar.setDisplayHomeAsUpEnabled(false);
-//        }
-//    }
-//    
     /**
      * {@inheritDoc}
      */
@@ -1273,6 +1322,8 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
      */
     @Override
     public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+        super.onRemoteOperationFinish(operation, result);
+        
         if (operation instanceof RemoveFileOperation) {
             onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
 
@@ -1285,10 +1336,52 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         } else if (operation instanceof CreateFolderOperation) {
             onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
             
+        } else if (operation instanceof CreateShareOperation) {
+            onCreateShareOperationFinish((CreateShareOperation) operation, result);
+            
+        } else if (operation instanceof UnshareLinkOperation) {
+            onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result);
+        
         } 
+        
     }
 
+    
+    private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) {
+        if (result.isSuccess()) {
+            refreshShowDetails();
+            refeshListOfFilesFragment();
+        }
+    }
 
+    
+    private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) {
+        if (result.isSuccess()) {
+            refreshShowDetails();
+            refeshListOfFilesFragment();
+        } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND) {
+            cleanSecondFragment();
+            refeshListOfFilesFragment();
+        }
+    }
+    
+    private void refreshShowDetails() {
+        FileFragment details = getSecondFragment();
+        if (details != null) {
+            OCFile file = details.getFile();
+            if (file != null) {
+                file = getStorageManager().getFileByPath(file.getRemotePath()); 
+                if (details instanceof PreviewMediaFragment) {
+                    // Refresh  OCFile of the fragment
+                    ((PreviewMediaFragment) details).updateFile(file);
+                } else {
+                    showDetails(file);
+                } 
+            }
+            invalidateOptionsMenu();
+        } 
+    }
+    
     /**
      * Updates the view associated to the activity after the finish of an operation trying to remove a 
      * file. 
@@ -1307,7 +1400,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
             if (second != null && removedFile.equals(second.getFile())) {
                 cleanSecondFragment();
             }
-            if (mStorageManager.getFileById(removedFile.getParentId()).equals(getCurrentDir())) {
+            if (getStorageManager().getFileById(removedFile.getParentId()).equals(getCurrentDir())) {
                 refeshListOfFilesFragment();
             }
 
@@ -1366,7 +1459,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
                     ((FileDetailFragment) details).updateFileDetails(renamedFile, getAccount());
                 }
             }
-            if (mStorageManager.getFileById(renamedFile.getParentId()).equals(getCurrentDir())) {
+            if (getStorageManager().getFileById(renamedFile.getParentId()).equals(getCurrentDir())) {
                 refeshListOfFilesFragment();
             }
 
@@ -1442,11 +1535,11 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
 
                 // Create directory
                 path += newDirectoryName + OCFile.PATH_SEPARATOR;
-                RemoteOperation operation = new CreateFolderOperation(path, false, mStorageManager);
+                RemoteOperation operation = new CreateFolderOperation(path, false, getStorageManager());
                 operation.execute(  getAccount(), 
                         FileDisplayActivity.this, 
                         FileDisplayActivity.this, 
-                        mHandler,
+                        getHandler(),
                         FileDisplayActivity.this);
 
                 showLoadingDialog();
@@ -1471,9 +1564,9 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         if (file != null) {
             if (file.isFolder()) {
                 return file;
-            } else if (mStorageManager != null) {
+            } else if (getStorageManager() != null) {
                 String parentPath = file.getRemotePath().substring(0, file.getRemotePath().lastIndexOf(file.getFileName()));
-                return mStorageManager.getFileByPath(parentPath);
+                return getStorageManager().getFileByPath(parentPath);
             }
         }
         return null;
@@ -1488,6 +1581,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder,  
                                                                         currentSyncTime, 
                                                                         false,
+                                                                        getFileOperationsHelper().isSharedSupported(this),
                                                                         getStorageManager(), 
                                                                         getAccount(), 
                                                                         getApplicationContext()
@@ -1497,16 +1591,15 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
         setSupportProgressBarIndeterminateVisibility(true);
     }
 
-    
-//    public void enableDisableViewGroup(ViewGroup viewGroup, boolean enabled) {
-//        int childCount = viewGroup.getChildCount();
-//        for (int i = 0; i < childCount; i++) {
-//          View view = viewGroup.getChildAt(i);
-//          view.setEnabled(enabled);
-//          view.setClickable(!enabled);
-//          if (view instanceof ViewGroup) {
-//            enableDisableViewGroup((ViewGroup) view, enabled);
-//          }
-//        }
-//      }
+    /*
+    private void startGetShares() {
+        // Get shared files/folders
+        Intent intent = new Intent(this, OperationsService.class);
+        intent.putExtra(OperationsService.EXTRA_ACCOUNT, getAccount());
+        startService(intent);
+        
+        mRefreshSharesInProgress = true;
+    }
+    */
+
 }
index b971c40..901434e 100644 (file)
@@ -30,8 +30,10 @@ import android.widget.ListAdapter;
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.actionbarsherlock.app.ActionBar;
 import com.actionbarsherlock.app.SherlockFragmentActivity;
 import com.owncloud.android.R;
+import com.owncloud.android.utils.DisplayUtils;
 
 
 /**
@@ -74,6 +76,9 @@ public class GenericExplanationActivity  extends SherlockFragmentActivity {
         } else {
             listView.setVisibility(View.GONE);
         }
+        
+        ActionBar actionBar = getSupportActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
     }
     
     public class ExplanationListAdapterView extends ArrayAdapter<String> {
diff --git a/src/com/owncloud/android/ui/activity/HookActivity.java b/src/com/owncloud/android/ui/activity/HookActivity.java
new file mode 100644 (file)
index 0000000..54d65b1
--- /dev/null
@@ -0,0 +1,24 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.activity;
+
+public abstract class HookActivity extends FileActivity {
+
+    private static final String TAG = HookActivity.class.getName();
+    
+}
index e879cc7..ca454d4 100644 (file)
@@ -34,6 +34,7 @@ import com.actionbarsherlock.app.SherlockPreferenceActivity;
 import com.actionbarsherlock.view.MenuItem;
 import com.owncloud.android.R;
 import com.owncloud.android.ui.adapter.LogListAdapter;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FileStorageUtils;
 
 
@@ -50,6 +51,7 @@ public class LogHistoryActivity extends SherlockPreferenceActivity implements On
         setContentView(R.layout.log_send_file);
         setTitle("Log History");
         ActionBar actionBar = getSherlock().getActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
         actionBar.setDisplayHomeAsUpEnabled(true);
         ListView listView = (ListView) findViewById(android.R.id.list);
         Button deleteHistoryButton = (Button) findViewById(R.id.deleteLogHistoryButton);
index c962fb2..39b973d 100644 (file)
@@ -18,8 +18,10 @@ package com.owncloud.android.ui.activity;
 
 import java.util.Arrays;
 
+import com.actionbarsherlock.app.ActionBar;
 import com.actionbarsherlock.app.SherlockFragmentActivity;
 import com.owncloud.android.R;
+import com.owncloud.android.utils.DisplayUtils;
 
 import android.app.AlertDialog;
 import android.content.DialogInterface;
@@ -44,23 +46,23 @@ public class PinCodeActivity extends SherlockFragmentActivity {
     public final static String EXTRA_ACTIVITY = "com.owncloud.android.ui.activity.PinCodeActivity.ACTIVITY";
     public final static String EXTRA_NEW_STATE = "com.owncloud.android.ui.activity.PinCodeActivity.NEW_STATE";
     
-    Button bCancel;
-    TextView mPinHdr;
-    TextView mPinHdrExplanation;
-    EditText mText1;
-    EditText mText2;
-    EditText mText3;
-    EditText mText4;
+    private Button mBCancel;
+    private TextView mPinHdr;
+    private TextView mPinHdrExplanation;
+    private EditText mText1;
+    private EditText mText2;
+    private EditText mText3;
+    private EditText mText4;
     
-    String [] tempText ={"","","",""};
+    private String [] mTempText ={"","","",""};
     
-    String activity;
+    private String mActivity;
     
-    boolean confirmingPinCode = false;
-    boolean pinCodeChecked = false;
-    boolean newPasswordEntered = false;
-    boolean bChange = true; // to control that only one blocks jump
-    int tCounter ; // Count the number of attempts an user could introduce the PIN code
+    private boolean mConfirmingPinCode = false;
+    private boolean mPinCodeChecked = false;
+    private boolean mNewPasswordEntered = false;
+    private boolean mBChange = true; // to control that only one blocks jump
+    //private int mTCounter ; // Count the number of attempts an user could introduce the PIN code
 
     
     protected void onCreate(Bundle savedInstanceState) {
@@ -68,9 +70,9 @@ public class PinCodeActivity extends SherlockFragmentActivity {
         setContentView(R.layout.pincodelock); 
         
         Intent intent = getIntent();
-        activity = intent.getStringExtra(EXTRA_ACTIVITY);
+        mActivity = intent.getStringExtra(EXTRA_ACTIVITY);
      
-        bCancel = (Button) findViewById(R.id.cancel);
+        mBCancel = (Button) findViewById(R.id.cancel);
         mPinHdr = (TextView) findViewById(R.id.pinHdr);
         mPinHdrExplanation = (TextView) findViewById(R.id.pinHdrExpl);
         mText1 = (EditText) findViewById(R.id.txt1);
@@ -88,23 +90,23 @@ public class PinCodeActivity extends SherlockFragmentActivity {
         // In a previous version settings is allow from start
         if ( (appPrefs.getString("PrefPinCode1", null) == null ) ){
             setChangePincodeView(true);
-            pinCodeChecked = true; 
-            newPasswordEntered = true;
+            mPinCodeChecked = true; 
+            mNewPasswordEntered = true;
             
         }else{ 
             
             if (appPrefs.getBoolean("set_pincode", false)){
                // pincode activated
-               if (activity.equals("preferences")){
+               if (mActivity.equals("preferences")){
                 // PIN has been activated yet
                  mPinHdr.setText(R.string.pincode_configure_your_pin);
                  mPinHdrExplanation.setVisibility(View.VISIBLE);
-                 pinCodeChecked = true ; // No need to check it 
+                 mPinCodeChecked = true ; // No need to check it 
                  setChangePincodeView(true);
                }else{
                 // PIN active
-                 bCancel.setVisibility(View.INVISIBLE);
-                 bCancel.setVisibility(View.GONE);
+                 mBCancel.setVisibility(View.INVISIBLE);
+                 mBCancel.setVisibility(View.GONE);
                  mPinHdr.setText(R.string.pincode_enter_pin_code);
                  mPinHdrExplanation.setVisibility(View.INVISIBLE);
                  setChangePincodeView(false);
@@ -114,28 +116,29 @@ public class PinCodeActivity extends SherlockFragmentActivity {
             // pincode removal
               mPinHdr.setText(R.string.pincode_remove_your_pincode);
               mPinHdrExplanation.setVisibility(View.INVISIBLE);
-              pinCodeChecked = false;
+              mPinCodeChecked = false;
               setChangePincodeView(true); 
            }
            
         }
         setTextListeners();
         
-        
+        ActionBar actionBar = getSupportActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
     }
     
 
      
     protected void setInitVars(){
-        confirmingPinCode = false;
-        pinCodeChecked = false;
-        newPasswordEntered = false;
+        mConfirmingPinCode = false;
+        mPinCodeChecked = false;
+        mNewPasswordEntered = false;
 
     }
     
     protected void setInitView(){
-        bCancel.setVisibility(View.INVISIBLE);
-        bCancel.setVisibility(View.GONE);
+        mBCancel.setVisibility(View.INVISIBLE);
+        mBCancel.setVisibility(View.GONE);
         mPinHdr.setText(R.string.pincode_enter_pin_code);
         mPinHdrExplanation.setVisibility(View.INVISIBLE);
     }
@@ -144,8 +147,8 @@ public class PinCodeActivity extends SherlockFragmentActivity {
     protected void setChangePincodeView(boolean state){
        
         if(state){
-        bCancel.setVisibility(View.VISIBLE);
-        bCancel.setOnClickListener(new OnClickListener() {
+        mBCancel.setVisibility(View.VISIBLE);
+        mBCancel.setOnClickListener(new OnClickListener() {
         @Override
         public void onClick(View v) {
             
@@ -192,8 +195,8 @@ public class PinCodeActivity extends SherlockFragmentActivity {
             @Override
             public void afterTextChanged(Editable s) {
                 if (s.length() > 0) {
-                    if (!confirmingPinCode){
-                       tempText[0] = mText1.getText().toString();
+                    if (!mConfirmingPinCode){
+                       mTempText[0] = mText1.getText().toString();
                        
                     }
                     mText2.requestFocus();
@@ -221,8 +224,8 @@ public class PinCodeActivity extends SherlockFragmentActivity {
             @Override
             public void afterTextChanged(Editable s) {
                 if (s.length() > 0) {
-                    if (!confirmingPinCode){
-                        tempText[1] = mText2.getText().toString();
+                    if (!mConfirmingPinCode){
+                        mTempText[1] = mText2.getText().toString();
                     }
                     
                     mText3.requestFocus();
@@ -234,16 +237,16 @@ public class PinCodeActivity extends SherlockFragmentActivity {
 
             @Override
             public boolean onKey(View v, int keyCode, KeyEvent event) {
-                if (keyCode == KeyEvent.KEYCODE_DEL && bChange) {
+                if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) {
 
                     mText1.setText("");
                     mText1.requestFocus();
-                    if (!confirmingPinCode)
-                       tempText[0] = "";
-                    bChange= false;
+                    if (!mConfirmingPinCode)
+                       mTempText[0] = "";
+                    mBChange= false;
                 
-                }else if(!bChange){
-                    bChange=true;
+                }else if(!mBChange){
+                    mBChange=true;
                     
                 }
                 return false;
@@ -285,8 +288,8 @@ public class PinCodeActivity extends SherlockFragmentActivity {
             @Override
             public void afterTextChanged(Editable s) {
                 if (s.length() > 0) {
-                    if (!confirmingPinCode){
-                        tempText[2] = mText3.getText().toString();
+                    if (!mConfirmingPinCode){
+                        mTempText[2] = mText3.getText().toString();
                     }
                     mText4.requestFocus();
                 }
@@ -297,15 +300,15 @@ public class PinCodeActivity extends SherlockFragmentActivity {
 
             @Override
             public boolean onKey(View v, int keyCode, KeyEvent event) {
-                if (keyCode == KeyEvent.KEYCODE_DEL && bChange) {
+                if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) {
                     mText2.requestFocus();
-                    if (!confirmingPinCode)
-                        tempText[1] = "";
+                    if (!mConfirmingPinCode)
+                        mTempText[1] = "";
                     mText2.setText("");
-                    bChange= false;
+                    mBChange= false;
                     
-                }else if(!bChange){
-                    bChange=true;                        
+                }else if(!mBChange){
+                    mBChange=true;                        
                     
                 }
                 return false;
@@ -353,18 +356,19 @@ public class PinCodeActivity extends SherlockFragmentActivity {
             public void afterTextChanged(Editable s) {
                 if (s.length() > 0) {
                     
-                    if (!confirmingPinCode){
-                       tempText[3] = mText4.getText().toString();
+                    if (!mConfirmingPinCode){
+                       mTempText[3] = mText4.getText().toString();
                     }
                     mText1.requestFocus();
 
-                    if (!pinCodeChecked){
-                        pinCodeChecked = checkPincode();
+                    if (!mPinCodeChecked){
+                        mPinCodeChecked = checkPincode();
                     }
                     
-                    if (pinCodeChecked && activity.equals("FileDisplayActivity")){
+                    if (mPinCodeChecked && 
+                            ( mActivity.equals("FileDisplayActivity") || mActivity.equals("PreviewImageActivity") ) ){
                         finish();
-                    } else if (pinCodeChecked){
+                    } else if (mPinCodeChecked){
                         
                         Intent intent = getIntent();
                         String newState = intent.getStringExtra(EXTRA_NEW_STATE);
@@ -380,7 +384,7 @@ public class PinCodeActivity extends SherlockFragmentActivity {
                             
                         }else{
                         
-                            if (!confirmingPinCode){
+                            if (!mConfirmingPinCode){
                                 pinCodeChangeRequest();
                              
                             } else {
@@ -400,15 +404,15 @@ public class PinCodeActivity extends SherlockFragmentActivity {
 
             @Override
             public boolean onKey(View v, int keyCode, KeyEvent event) {
-                if (keyCode == KeyEvent.KEYCODE_DEL && bChange) {
+                if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) {
                     mText3.requestFocus();
-                    if (!confirmingPinCode)
-                        tempText[2]="";
+                    if (!mConfirmingPinCode)
+                        mTempText[2]="";
                     mText3.setText("");
-                    bChange= false;
+                    mBChange= false;
                     
-                }else if(!bChange){
-                    bChange=true;    
+                }else if(!mBChange){
+                    mBChange=true;    
                 }
                 return false;
             }
@@ -453,7 +457,7 @@ public class PinCodeActivity extends SherlockFragmentActivity {
         clearBoxes(); 
         mPinHdr.setText(R.string.pincode_reenter_your_pincode); 
         mPinHdrExplanation.setVisibility(View.INVISIBLE);        
-        confirmingPinCode =true;
+        mConfirmingPinCode =true;
         
     }
     
@@ -469,16 +473,16 @@ public class PinCodeActivity extends SherlockFragmentActivity {
         String pText3 = appPrefs.getString("PrefPinCode3", null);
         String pText4 = appPrefs.getString("PrefPinCode4", null);
 
-        if ( tempText[0].equals(pText1) && 
-             tempText[1].equals(pText2) &&
-             tempText[2].equals(pText3) &&
-             tempText[3].equals(pText4) ) {
+        if ( mTempText[0].equals(pText1) && 
+             mTempText[1].equals(pText2) &&
+             mTempText[2].equals(pText3) &&
+             mTempText[3].equals(pText4) ) {
             
             return true;
         
         
         }else {
-            Arrays.fill(tempText, null);
+            Arrays.fill(mTempText, null);
             AlertDialog aDialog = new AlertDialog.Builder(this).create();
             CharSequence errorSeq = getString(R.string.common_error);
             aDialog.setTitle(errorSeq);
@@ -497,8 +501,8 @@ public class PinCodeActivity extends SherlockFragmentActivity {
             clearBoxes(); 
             mPinHdr.setText(R.string.pincode_enter_pin_code);
             mPinHdrExplanation.setVisibility(View.INVISIBLE);
-            newPasswordEntered = true;
-            confirmingPinCode = false;
+            mNewPasswordEntered = true;
+            mConfirmingPinCode = false;
             
         }
      
@@ -508,23 +512,23 @@ public class PinCodeActivity extends SherlockFragmentActivity {
     
     protected void confirmPincode(){
         
-        confirmingPinCode = false;
+        mConfirmingPinCode = false;
         
         String rText1 = mText1.getText().toString();
         String rText2 = mText2.getText().toString();
         String rText3 = mText3.getText().toString();
         String rText4 = mText4.getText().toString();
         
-        if ( tempText[0].equals(rText1) && 
-             tempText[1].equals(rText2) &&
-             tempText[2].equals(rText3) &&
-             tempText[3].equals(rText4) ) {
+        if ( mTempText[0].equals(rText1) && 
+             mTempText[1].equals(rText2) &&
+             mTempText[2].equals(rText3) &&
+             mTempText[3].equals(rText4) ) {
                         
             savePincodeAndExit();
             
         } else {
             
-            Arrays.fill(tempText, null);
+            Arrays.fill(mTempText, null);
             AlertDialog aDialog = new AlertDialog.Builder(this).create();
             CharSequence errorSeq = getString(R.string.common_error);
             aDialog.setTitle(errorSeq);
@@ -581,10 +585,10 @@ public class PinCodeActivity extends SherlockFragmentActivity {
         SharedPreferences.Editor appPrefs = PreferenceManager
                 .getDefaultSharedPreferences(getApplicationContext()).edit();
         
-        appPrefs.putString("PrefPinCode1", tempText[0]);
-        appPrefs.putString("PrefPinCode2",tempText[1]);
-        appPrefs.putString("PrefPinCode3", tempText[2]);
-        appPrefs.putString("PrefPinCode4", tempText[3]);
+        appPrefs.putString("PrefPinCode1", mTempText[0]);
+        appPrefs.putString("PrefPinCode2",mTempText[1]);
+        appPrefs.putString("PrefPinCode3", mTempText[2]);
+        appPrefs.putString("PrefPinCode4", mTempText[3]);
         appPrefs.putBoolean("set_pincode",true);
         appPrefs.commit();
         
@@ -609,7 +613,7 @@ public class PinCodeActivity extends SherlockFragmentActivity {
     public boolean onKeyDown(int keyCode, KeyEvent event){
         if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount()== 0){
             
-            if (activity.equals("preferences")){
+            if (mActivity.equals("preferences")){
                 SharedPreferences.Editor appPrefsE = PreferenceManager
             
                     .getDefaultSharedPreferences(getApplicationContext()).edit();
index 678dad6..3ebb432 100644 (file)
@@ -17,8 +17,7 @@
  */
 package com.owncloud.android.ui.activity;
 
-import java.util.Vector;
-
+import android.accounts.Account;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.PackageInfo;
@@ -37,9 +36,10 @@ import com.actionbarsherlock.app.SherlockPreferenceActivity;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuItem;
 import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.db.DbHandler;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.Log_OC;
-import com.owncloud.android.utils.OwnCloudSession;
 
 
 /**
@@ -51,15 +51,11 @@ import com.owncloud.android.utils.OwnCloudSession;
 public class Preferences extends SherlockPreferenceActivity {
     
     private static final String TAG = "OwnCloudPreferences";
-    private final int mNewSession = 47;
-    private final int mEditSession = 48;
     private DbHandler mDbHandler;
-    private Vector<OwnCloudSession> mSessions;
     private CheckBoxPreference pCode;
     //private CheckBoxPreference pLogging;
     //private Preference pLoggingHistory;
     private Preference pAboutApp;
-    private int mSelectedMenuItem;
 
 
     @SuppressWarnings("deprecation")
@@ -67,10 +63,10 @@ public class Preferences extends SherlockPreferenceActivity {
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mDbHandler = new DbHandler(getBaseContext());
-        mSessions = new Vector<OwnCloudSession>();
         addPreferencesFromResource(R.xml.preferences);
         //populateAccountList();
         ActionBar actionBar = getSherlock().getActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
         actionBar.setDisplayHomeAsUpEnabled(true);
         
         Preference p = findPreference("manage_account");
@@ -137,18 +133,19 @@ public class Preferences extends SherlockPreferenceActivity {
 
                         Intent intent = new Intent(Intent.ACTION_SENDTO); 
                         intent.setType("text/plain");
-                        //Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(Preferences.this);
+                        intent.setData(Uri.parse(getString(R.string.mail_recommend))); 
+                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
+                        
                         String appName = getString(R.string.app_name);
-                        //String username = currentAccount.name.substring(0, currentAccount.name.lastIndexOf('@')); 
-                        //String recommendSubject = String.format(getString(R.string.recommend_subject), username, appName);
+                        String downloadUrl = getString(R.string.url_app_download);
+                        Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(Preferences.this);
+                        String username = currentAccount.name.substring(0, currentAccount.name.lastIndexOf('@'));
+                        
                         String recommendSubject = String.format(getString(R.string.recommend_subject), appName);
+                        String recommendText = String.format(getString(R.string.recommend_text), appName, downloadUrl, username);
+                        
                         intent.putExtra(Intent.EXTRA_SUBJECT, recommendSubject);
-                        //String recommendText = String.format(getString(R.string.recommend_text), getString(R.string.app_name), username);
-                        String recommendText = String.format(getString(R.string.recommend_text), getString(R.string.app_name), getString(R.string.url_app_download));
                         intent.putExtra(Intent.EXTRA_TEXT, recommendText);
-
-                        intent.setData(Uri.parse(getString(R.string.mail_recommend))); 
-                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
                         startActivity(intent);
 
 
index 7c941e8..8b4a41d 100644 (file)
@@ -40,6 +40,7 @@ import com.owncloud.android.ui.dialog.IndeterminateProgressDialog;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
 import com.owncloud.android.ui.fragment.LocalFileListFragment;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.Log_OC;
 
@@ -111,6 +112,7 @@ public class UploadFilesActivity extends FileActivity implements
             
         // Action bar setup
         ActionBar actionBar = getSupportActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
         actionBar.setHomeButtonEnabled(true);   // mandatory since Android ICS, according to the official documentation
         actionBar.setDisplayHomeAsUpEnabled(mCurrentDir != null && mCurrentDir.getName() != null);
         actionBar.setDisplayShowTitleEnabled(false);
@@ -378,6 +380,7 @@ public class UploadFilesActivity extends FileActivity implements
 
     @Override
     protected void onAccountSet(boolean stateWasRecovered) {
+        super.onAccountSet(stateWasRecovered);
         if (getAccount() != null) {
             if (!mAccountOnCreation.equals(getAccount())) {
                 setResult(RESULT_CANCELED);
@@ -385,7 +388,6 @@ public class UploadFilesActivity extends FileActivity implements
             }
             
         } else {
-            Log_OC.wtf(TAG, "onAccountChanged was called with NULL account associated!");
             setResult(RESULT_CANCELED);
             finish();
         }
index 08e2d21..07e6e95 100644 (file)
@@ -28,9 +28,6 @@ import java.util.Vector;
 
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
-import com.owncloud.android.R.id;
-import com.owncloud.android.R.layout;
-import com.owncloud.android.R.string;
 import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
@@ -332,13 +329,13 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
 
     public void uploadFiles() {
         try {
-            //WebdavClient webdav = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
+            //OwnCloudClient webdav = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
 
             ArrayList<String> local = new ArrayList<String>();
             ArrayList<String> remote = new ArrayList<String>();
             
             /* TODO - mCreateDir can never be true at this moment; we will replace wdc.createDirectory by CreateFolderOperation when that is fixed 
-            WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
+            OwnCloudClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
             // create last directory in path if necessary
             if (mCreateDir) {
                 wdc.createDirectory(mUploadPath);
index 841a5d0..f31ca14 100644 (file)
@@ -1,6 +1,6 @@
 /* ownCloud Android client application\r
  *   Copyright (C) 2011  Bartek Przybylski\r
- *   Copyright (C) 2012-2013 ownCloud Inc.\r
+ *   Copyright (C) 2012-2014 ownCloud Inc.\r
  *\r
  *   This program is free software: you can redistribute it and/or modify\r
  *   it under the terms of the GNU General Public License version 2,\r
@@ -165,8 +165,15 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
                 lastModV.setVisibility(View.VISIBLE);\r
                 lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.getModificationTimestamp()));\r
-               checkBoxV.setVisibility(View.GONE);\r
-               view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
+                checkBoxV.setVisibility(View.GONE);\r
+                view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
+            }\r
+            \r
+            ImageView shareIconV = (ImageView) view.findViewById(R.id.shareIcon);\r
+            if (file.isShareByLink()) {\r
+                shareIconV.setVisibility(View.VISIBLE);\r
+            } else {\r
+                shareIconV.setVisibility(View.INVISIBLE);\r
             }\r
         }\r
 \r
index 7cd2c2a..5686874 100644 (file)
@@ -1,6 +1,6 @@
 /* ownCloud Android client application
  *   Copyright (C) 2011  Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
+ *   Copyright (C) 2012-2014 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -135,6 +135,8 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
             
             view.findViewById(R.id.imageView2).setVisibility(View.INVISIBLE);   // not GONE; the alignment changes; ugly way to keep it
             view.findViewById(R.id.imageView3).setVisibility(View.GONE);
+            
+            view.findViewById(R.id.shareIcon).setVisibility(View.GONE);
         }
 
         return view;
diff --git a/src/com/owncloud/android/ui/dialog/ActivityChooserDialog.java b/src/com/owncloud/android/ui/dialog/ActivityChooserDialog.java
new file mode 100644 (file)
index 0000000..dc15f69
--- /dev/null
@@ -0,0 +1,151 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.dialog;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.actionbarsherlock.app.SherlockDialogFragment;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.FileOperationsHelper;
+import com.owncloud.android.ui.activity.FileActivity;
+import com.owncloud.android.utils.Log_OC;
+
+/**
+ * Dialog showing a list activities able to resolve a given Intent, 
+ * filtering out the activities matching give package names.
+ * 
+ * @author David A. Velasco
+ */
+public class ActivityChooserDialog  extends SherlockDialogFragment {
+    
+    private final static String TAG =  ActivityChooserDialog.class.getSimpleName();
+    private final static String ARG_INTENT =  ActivityChooserDialog.class.getSimpleName() + ".ARG_INTENT";
+    private final static String ARG_PACKAGES_TO_EXCLUDE =  ActivityChooserDialog.class.getSimpleName() + ".ARG_PACKAGES_TO_EXCLUDE";
+    private final static String ARG_FILE_TO_SHARE = ActivityChooserDialog.class.getSimpleName() + ".FILE_TO_SHARE";
+    
+    private ActivityAdapter mAdapter;
+    private OCFile mFile;
+    private Intent mIntent;
+    
+    public static ActivityChooserDialog newInstance(Intent intent, String[] packagesToExclude, OCFile fileToShare) {
+        ActivityChooserDialog f = new ActivityChooserDialog();
+        Bundle args = new Bundle();
+        args.putParcelable(ARG_INTENT, intent);
+        args.putStringArray(ARG_PACKAGES_TO_EXCLUDE, packagesToExclude);
+        args.putParcelable(ARG_FILE_TO_SHARE, fileToShare);
+        f.setArguments(args);
+        return f;
+    }
+    
+    public ActivityChooserDialog() {
+        super();
+        Log_OC.d(TAG, "constructor");
+    }
+    
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        mIntent = getArguments().getParcelable(ARG_INTENT);
+        String[] packagesToExclude = getArguments().getStringArray(ARG_PACKAGES_TO_EXCLUDE);
+        List<String> packagesToExcludeList = Arrays.asList(packagesToExclude != null ? packagesToExclude : new String[0]);
+        mFile = getArguments().getParcelable(ARG_FILE_TO_SHARE);
+        
+        PackageManager pm= getSherlockActivity().getPackageManager();
+        List<ResolveInfo> activities = pm.queryIntentActivities(mIntent, PackageManager.MATCH_DEFAULT_ONLY);
+        Iterator<ResolveInfo> it = activities.iterator();
+        ResolveInfo resolveInfo;
+        while (it.hasNext()) {
+            resolveInfo = it.next();
+            if (packagesToExcludeList.contains(resolveInfo.activityInfo.packageName.toLowerCase())) {
+                it.remove();
+            }
+        }
+        Collections.sort(activities, new ResolveInfo.DisplayNameComparator(pm)); 
+        mAdapter = new ActivityAdapter(getSherlockActivity(), pm, activities);
+        
+        return new AlertDialog.Builder(getSherlockActivity())
+                   .setTitle(R.string.activity_chooser_title)
+                   .setAdapter(mAdapter, new DialogInterface.OnClickListener() {
+                           @Override
+                           public void onClick(DialogInterface dialog, int which) {
+                               // Add the information of the chosen activity to the intent to send 
+                               ResolveInfo chosen = mAdapter.getItem(which);
+                               ActivityInfo actInfo = chosen.activityInfo;
+                               ComponentName name=new ComponentName(actInfo.applicationInfo.packageName, actInfo.name);
+                               mIntent.setComponent(name);                               
+                               
+                               // Create a new share resource
+                               FileOperationsHelper foh = new FileOperationsHelper();
+                               foh.shareFileWithLinkToApp(mFile, mIntent, (FileActivity)getSherlockActivity()); 
+                           }
+                       })
+                   .create();
+    }
+
+    
+    class ActivityAdapter extends ArrayAdapter<ResolveInfo> {
+        
+        private PackageManager mPackageManager;
+        
+        ActivityAdapter(Context context, PackageManager pm, List<ResolveInfo> apps) {
+            super(context, R.layout.activity_row, apps);
+            this.mPackageManager = pm;
+        }
+        
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = newView(parent);
+            }
+            bindView(position, convertView);
+            return convertView;
+        }
+        
+        private View newView(ViewGroup parent) {
+            return(((LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.activity_row, parent, false));
+        }
+        
+        private void bindView(int position, View row) {
+            TextView label = (TextView) row.findViewById(R.id.title);
+            label.setText(getItem(position).loadLabel(mPackageManager));
+            ImageView icon = (ImageView) row.findViewById(R.id.icon);
+            icon.setImageDrawable(getItem(position).loadIcon(mPackageManager));
+        }
+    }
+    
+}
index 676bea5..eef9d09 100644 (file)
@@ -25,6 +25,7 @@ import android.webkit.WebView;
 
 import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.owncloud.android.R;
+import com.owncloud.android.utils.DisplayUtils;
 
 
 /**
@@ -63,7 +64,7 @@ public class ChangelogDialog extends SherlockDialogFragment {
         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         
         Dialog dialog = builder.setView(webview)
-                                .setIcon(R.drawable.icon)
+                                .setIcon(DisplayUtils.getSeasonalIconId())
                                 //.setTitle(R.string.whats_new)
                                 .setPositiveButton(R.string.common_ok,
                                         new DialogInterface.OnClickListener() {
index 1998fcb..91cfbfd 100644 (file)
@@ -28,6 +28,7 @@ import android.support.v4.app.FragmentTransaction;
 import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.actionbarsherlock.app.SherlockFragmentActivity;
 import com.owncloud.android.R;
+import com.owncloud.android.utils.DisplayUtils;
 
 
 /**
@@ -59,7 +60,7 @@ public class ConflictsResolveDialog extends SherlockDialogFragment {
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         String remotepath = getArguments().getString("remotepath");
         return new AlertDialog.Builder(getSherlockActivity())
-                   .setIcon(R.drawable.icon)
+                   .setIcon(DisplayUtils.getSeasonalIconId())
                    .setTitle(R.string.conflict_title)
                    .setMessage(String.format(getString(R.string.conflict_message), remotepath))
                    .setPositiveButton(R.string.conflict_overwrite,
@@ -68,7 +69,7 @@ public class ConflictsResolveDialog extends SherlockDialogFragment {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (mListener != null)
-                                   mListener.ConflictDecisionMade(Decision.OVERWRITE);
+                                   mListener.conflictDecisionMade(Decision.OVERWRITE);
                            }
                        })
                    .setNeutralButton(R.string.conflict_keep_both,
@@ -76,7 +77,7 @@ public class ConflictsResolveDialog extends SherlockDialogFragment {
                             @Override
                             public void onClick(DialogInterface dialog, int which) {
                                 if (mListener != null)
-                                    mListener.ConflictDecisionMade(Decision.KEEP_BOTH);
+                                    mListener.conflictDecisionMade(Decision.KEEP_BOTH);
                             }
                         })
                    .setNegativeButton(R.string.conflict_dont_upload,
@@ -84,7 +85,7 @@ public class ConflictsResolveDialog extends SherlockDialogFragment {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (mListener != null)
-                                   mListener.ConflictDecisionMade(Decision.CANCEL);
+                                   mListener.conflictDecisionMade(Decision.CANCEL);
                            }
                    })
                    .create();
@@ -112,10 +113,10 @@ public class ConflictsResolveDialog extends SherlockDialogFragment {
     
     @Override
     public void onCancel(DialogInterface dialog) {
-        mListener.ConflictDecisionMade(Decision.CANCEL);
+        mListener.conflictDecisionMade(Decision.CANCEL);
     }
     
     public interface OnConflictDecisionMadeListener {
-        public void ConflictDecisionMade(Decision decision);
+        public void conflictDecisionMade(Decision decision);
     }
 }
index 862715f..14a74c5 100644 (file)
@@ -31,7 +31,7 @@ import android.widget.Toast;
 
 import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.owncloud.android.R;
-import com.owncloud.android.oc_framework.utils.FileUtils;
+import com.owncloud.android.lib.utils.FileUtils;
 
 
 /**
index 91c607e..a90a7ad 100644 (file)
@@ -38,7 +38,7 @@ import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.SsoWebViewClient;
 import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener;
-import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.lib.network.OwnCloudClient;
 import com.owncloud.android.utils.Log_OC;
 
 
@@ -181,7 +181,7 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
         webSettings.setBuiltInZoomControls(true);
         webSettings.setLoadWithOverviewMode(false);
         webSettings.setSavePassword(false);
-        webSettings.setUserAgentString(WebdavClient.USER_AGENT);
+        webSettings.setUserAgentString(OwnCloudClient.USER_AGENT);
         webSettings.setSaveFormData(false);
         
         return rootView;
index a50ecc9..dd4046b 100644 (file)
@@ -39,9 +39,9 @@ import android.view.Window;
 import android.widget.Button;
 import android.widget.TextView;
 
-import com.owncloud.android.oc_framework.network.CertificateCombinedException;
-import com.owncloud.android.oc_framework.network.NetworkUtils;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.lib.network.CertificateCombinedException;
+import com.owncloud.android.lib.network.NetworkUtils;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
 import com.owncloud.android.utils.Log_OC;
 
 /**
index ea0f814..fb5b6a9 100644 (file)
@@ -50,11 +50,11 @@ import com.owncloud.android.files.services.FileObserverService;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
-import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.network.OnDatatransferProgressListener;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
@@ -186,6 +186,10 @@ public class FileDetailFragment extends FileFragment implements
         super.onActivityCreated(savedInstanceState);
         if (mAccount != null) {
             mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
+            OCFile file = mStorageManager.getFileByPath(getFile().getRemotePath());
+            if (file != null) {
+                setFile(file);
+            }
         }
     }
         
@@ -310,7 +314,14 @@ public class FileDetailFragment extends FileFragment implements
             toHide.add(R.id.action_remove_file);
             
         }
-
+        
+        // Options shareLink
+        if (!file.isShareByLink()) {
+            toHide.add(R.id.action_unshare_file);
+        } else {
+            toShow.add(R.id.action_unshare_file);
+        }
+        
         MenuItem item = null;
         for (int i : toHide) {
             item = menu.findItem(i);
@@ -335,8 +346,19 @@ public class FileDetailFragment extends FileFragment implements
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
+            case R.id.action_share_file: {
+                FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity();
+                activity.getFileOperationsHelper().shareFileWithLink(getFile(), activity);
+                return true;
+            }
+            case R.id.action_unshare_file: {
+                FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity();
+                activity.getFileOperationsHelper().unshareFileWithLink(getFile(), activity);
+                return true;
+            }
             case R.id.action_open_file_with: {
-                mContainerActivity.openFile(getFile());
+                FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity();
+                activity.getFileOperationsHelper().openFile(getFile(), activity);
                 return true;
             }
             case R.id.action_remove_file: {
@@ -358,7 +380,7 @@ public class FileDetailFragment extends FileFragment implements
                 return false;
         }
     }
-    
+
     @Override
     public void onClick(View v) {
         switch (v.getId()) {
@@ -399,7 +421,6 @@ public class FileDetailFragment extends FileFragment implements
         }
     }
 
-
     private void removeFile() {
         OCFile file = getFile();
         ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
@@ -473,12 +494,10 @@ public class FileDetailFragment extends FileFragment implements
     
     @Override
     public void onNeutral(String callerTag) {
-        File f = null;
         OCFile file = getFile();
-        if (file.isDown() && (f = new File(file.getStoragePath())).exists()) {
-            f.delete();
+        mStorageManager.removeFile(file, false, true);    // TODO perform in background task / new thread
+        if (file.getStoragePath() != null) {
             file.setStoragePath(null);
-            mStorageManager.saveFile(file);
             updateFileDetails(file, mAccount);
         }
     }
@@ -906,11 +925,6 @@ public class FileDetailFragment extends FileFragment implements
         }
         
         @Override
-        public void onTransferProgress(long progressRate) {
-            // old method, nothing here
-        };
-
-        @Override
         public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
             int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
             if (percent != mLastPercent) {
index b6c6574..2f1a49b 100644 (file)
@@ -21,7 +21,6 @@ import android.support.v4.app.Fragment;
 
 import com.actionbarsherlock.app.SherlockFragment;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.FileHandler;
 import com.owncloud.android.ui.activity.TransferServiceGetter;
 
 
@@ -73,7 +72,7 @@ public class FileFragment extends SherlockFragment {
      * 
      * @author David A. Velasco
      */
-    public interface ContainerActivity extends TransferServiceGetter, FileHandler {
+    public interface ContainerActivity extends TransferServiceGetter {
 
         /**
          * Callback method invoked when the detail fragment wants to notice its container 
@@ -95,8 +94,7 @@ public class FileFragment extends SherlockFragment {
          * @param file      File to show details
          */
         public void showDetails(OCFile file);
-        
-        
+
     }
     
 }
index 6da24cd..5780e58 100644 (file)
@@ -25,11 +25,10 @@ import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.FileHandler;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
@@ -184,8 +183,8 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName
                         // media preview
                         mContainerActivity.startMediaPreview(file, 0, true);
                     } else {
-                        // open with
-                        mContainerActivity.openFile(file);
+                        FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity();
+                        activity.getFileOperationsHelper().openFile(file, activity);
                     }
                     
                 } else {
@@ -260,6 +259,11 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName
                 toHide.add(R.id.action_cancel_upload);
             }
         }
+        
+        // Options shareLink
+        if (!targetFile.isShareByLink()) {
+            toHide.add(R.id.action_unshare_file);
+        }
 
         for (int i : toHide) {
             item = menu.findItem(i);
@@ -285,7 +289,17 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName
     public boolean onContextItemSelected (MenuItem item) {
         AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();        
         mTargetFile = (OCFile) mAdapter.getItem(info.position);
-        switch (item.getItemId()) {
+        switch (item.getItemId()) {                
+            case R.id.action_share_file: {
+                FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity();
+                activity.getFileOperationsHelper().shareFileWithLink(mTargetFile, activity);
+                return true;
+            }
+            case R.id.action_unshare_file: {
+                FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity();
+                activity.getFileOperationsHelper().unshareFileWithLink(mTargetFile, activity);
+                return true;
+            }
             case R.id.action_rename_file: {
                 String fileName = mTargetFile.getFileName();
                 int extensionStart = mTargetFile.isFolder() ? -1 : fileName.lastIndexOf(".");
@@ -359,7 +373,7 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName
                 return super.onContextItemSelected(item); 
         }
     }
-    
+
 
     /**
      * Use this to query the {@link OCFile} that is currently
@@ -420,7 +434,7 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName
      * 
      * @author David A. Velasco
      */
-    public interface ContainerActivity extends TransferServiceGetter, OnRemoteOperationListener, FileHandler {
+    public interface ContainerActivity extends TransferServiceGetter, OnRemoteOperationListener {
 
         /**
          * Callback method invoked when a the user browsed into a different folder through the list of files
@@ -428,7 +442,7 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName
          * @param file
          */
         public void onBrowsedDownTo(OCFile folder);
-        
+
         public void startDownloadForPreview(OCFile file);
 
         public void startMediaPreview(OCFile file, int i, boolean b);
index c18f84b..8ca2be3 100644 (file)
@@ -37,7 +37,7 @@ import android.widget.ImageButton;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
+import com.owncloud.android.lib.network.OnDatatransferProgressListener;
 
 
 /**
@@ -353,11 +353,6 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene
         }
         
         @Override
-        public void onTransferProgress(long progressRate) {
-            // old method, nothing here
-        };
-
-        @Override
         public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
             int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
             if (percent != mLastPercent) {
index fde70df..548a27b 100644 (file)
@@ -22,8 +22,10 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.preference.PreferenceManager;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
@@ -43,10 +45,18 @@ import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode;
+import com.owncloud.android.operations.CreateShareOperation;
+import com.owncloud.android.operations.UnshareLinkOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
+import com.owncloud.android.ui.activity.PinCodeActivity;
 import com.owncloud.android.ui.dialog.LoadingDialog;
 import com.owncloud.android.ui.fragment.FileFragment;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.Log_OC;
 
 
@@ -55,7 +65,7 @@ import com.owncloud.android.utils.Log_OC;
  *  
  *  @author David A. Velasco
  */
-public class PreviewImageActivity extends FileActivity implements FileFragment.ContainerActivity, ViewPager.OnPageChangeListener, OnTouchListener {
+public class PreviewImageActivity extends FileActivity implements FileFragment.ContainerActivity, ViewPager.OnPageChangeListener, OnTouchListener , OnRemoteOperationListener{
     
     public static final int DIALOG_SHORT_WAIT = 0;
 
@@ -66,8 +76,6 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C
     
     private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
     
-    private FileDataStorageManager mStorageManager;
-    
     private ViewPager mViewPager; 
     private PreviewImagePagerAdapter mPreviewImagePagerAdapter;    
     
@@ -90,9 +98,15 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C
         setContentView(R.layout.preview_image_activity);
         
         ActionBar actionBar = getSupportActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
         actionBar.setDisplayHomeAsUpEnabled(true);
         actionBar.hide();
         
+        // PIN CODE request
+        if (getIntent().getExtras() != null && savedInstanceState == null && fromNotification()) {
+            requestPinCode();
+        }         
+        
         mFullScreen = true;
         if (savedInstanceState != null) {
             mRequestWaitingForBinder = savedInstanceState.getBoolean(KEY_WAITING_FOR_BINDER);
@@ -105,13 +119,12 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C
     private void initViewPager() {
         // get parent from path
         String parentPath = getFile().getRemotePath().substring(0, getFile().getRemotePath().lastIndexOf(getFile().getFileName()));
-        OCFile parentFolder = mStorageManager.getFileByPath(parentPath);
-        //OCFile parentFolder = mStorageManager.getFileById(getFile().getParentId());
+        OCFile parentFolder = getStorageManager().getFileByPath(parentPath);
         if (parentFolder == null) {
             // should not be necessary
-            parentFolder = mStorageManager.getFileByPath(OCFile.ROOT_PATH);
+            parentFolder = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
         }
-        mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(), parentFolder, getAccount(), mStorageManager);
+        mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(), parentFolder, getAccount(), getStorageManager());
         mViewPager = (ViewPager) findViewById(R.id.fragmentPager);
         int position = mPreviewImagePagerAdapter.getFilePosition(getFile());
         position = (position >= 0) ? position : 0;
@@ -140,7 +153,43 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C
         outState.putBoolean(KEY_WAITING_FOR_BINDER, mRequestWaitingForBinder);    
     }
 
-
+    @Override
+    public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+        super.onRemoteOperationFinish(operation, result);
+        
+        if (operation instanceof CreateShareOperation) {
+            onCreateShareOperationFinish((CreateShareOperation) operation, result);
+            
+        } else if (operation instanceof UnshareLinkOperation) {
+            onUnshareLinkOperationFinish((UnshareLinkOperation) operation, result);
+            
+        }
+    }
+    
+    
+    private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) {
+        if (result.isSuccess()) {
+            OCFile file = getStorageManager().getFileByPath(getFile().getRemotePath());
+            if (file != null) {
+                setFile(file);
+            }
+            invalidateOptionsMenu();
+        } else if  (result.getCode() == ResultCode.SHARE_NOT_FOUND) {
+            backToDisplayActivity();
+        }
+            
+    }
+    
+    private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) {
+        if (result.isSuccess()) {
+            OCFile file = getStorageManager().getFileByPath(getFile().getRemotePath());
+            if (file != null) {
+                setFile(file);
+            }
+            invalidateOptionsMenu();
+        }
+    }
+    
     /** Defines callbacks for service binding, passed to bindService() */
     private class PreviewImageServiceConnection implements ServiceConnection {
 
@@ -375,7 +424,7 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C
             if (getAccount().name.equals(accountName) && 
                     downloadedRemotePath != null) {
 
-                OCFile file = mStorageManager.getFileByPath(downloadedRemotePath);
+                OCFile file = getStorageManager().getFileByPath(downloadedRemotePath);
                 int position = mPreviewImagePagerAdapter.getFilePosition(file);
                 boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
                 //boolean isOffscreen =  Math.abs((mViewPager.getCurrentItem() - position)) <= mViewPager.getOffscreenPageLimit();
@@ -423,6 +472,7 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C
 
     @Override
     protected void onAccountSet(boolean stateWasRecovered) {
+        super.onAccountSet(stateWasRecovered);
         if (getAccount() != null) {
             OCFile file = getFile();
             /// Validate handled file  (first image to preview)
@@ -432,15 +482,14 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C
             if (!file.isImage()) {
                 throw new IllegalArgumentException("Non-image file passed as argument");
             }
-            mStorageManager = new FileDataStorageManager(getAccount(), getContentResolver());            
             
             // Update file according to DB file, if it is possible
             if (file.getFileId() > FileDataStorageManager.ROOT_PARENT_ID)            
-                file = mStorageManager.getFileById(file.getFileId());
+                file = getStorageManager().getFileById(file.getFileId());
             
             if (file != null) {
                 /// Refresh the activity according to the Account and OCFile set
-                setFile(file);  // reset after getting it fresh from mStorageManager
+                setFile(file);  // reset after getting it fresh from storageManager
                 getSupportActionBar().setTitle(getFile().getFileName());
                 //if (!stateWasRecovered) {
                     initViewPager();
@@ -450,11 +499,22 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C
                 // handled file not in the current Account
                 finish();
             }
-            
-        } else {
-            Log_OC.wtf(TAG, "onAccountChanged was called with NULL account associated!");
         }
     }
     
     
+    /**
+     * Launch an intent to request the PIN code to the user before letting him use the app
+     */
+    private void requestPinCode() {
+        boolean pinStart = false;
+        SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+        pinStart = appPrefs.getBoolean("set_pincode", false);
+        if (pinStart) {
+            Intent i = new Intent(getApplicationContext(), PinCodeActivity.class);
+            i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "PreviewImageActivity");
+            startActivity(i);
+        }
+    }
+
 }
index 022120b..88f40b8 100644 (file)
@@ -16,7 +16,6 @@
  */
 package com.owncloud.android.ui.preview;
 
-import java.io.File;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
@@ -53,11 +52,12 @@ import com.actionbarsherlock.view.MenuItem;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.lib.network.webdav.WebdavUtils;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
 import com.owncloud.android.operations.RemoveFileOperation;
+import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
 import com.owncloud.android.utils.Log_OC;
@@ -176,8 +176,22 @@ public class PreviewImageFragment extends FileFragment implements   OnRemoteOper
         mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
         if (savedInstanceState != null) {
             if (!mIgnoreFirstSavedState) {
-                setFile((OCFile)savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE));
+                OCFile file = (OCFile)savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE);
                 mAccount = savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_ACCOUNT);
+                
+                // Update the file
+                if (mAccount!= null) {
+                    mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
+                    OCFile updatedFile = mStorageManager.getFileByPath(file.getRemotePath());
+                    if (updatedFile != null) {
+                        setFile(updatedFile);
+                    } else {
+                        setFile(file);
+                    }
+                } else {
+                    setFile(file);
+                }
+
             } else {
                 mIgnoreFirstSavedState = false;
             }
@@ -230,6 +244,11 @@ public class PreviewImageFragment extends FileFragment implements   OnRemoteOper
         toHide.add(R.id.action_cancel_upload);
         toHide.add(R.id.action_download_file);
         toHide.add(R.id.action_rename_file);    // by now
+        
+        // Options shareLink
+        if (!getFile().isShareByLink()) {
+            toHide.add(R.id.action_unshare_file);
+        }
 
         for (int i : toHide) {
             item = menu.findItem(i);
@@ -241,6 +260,27 @@ public class PreviewImageFragment extends FileFragment implements   OnRemoteOper
         
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        
+        MenuItem item = menu.findItem(R.id.action_unshare_file);
+        // Options shareLink
+        OCFile file = ((FileActivity) getSherlockActivity()).getFile();
+        if (!file.isShareByLink()) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        } else {
+            item.setVisible(true);
+            item.setEnabled(true);
+        }
+            
+    }
+
+    
     
     /**
      * {@inheritDoc}
@@ -248,6 +288,16 @@ public class PreviewImageFragment extends FileFragment implements   OnRemoteOper
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
+            case R.id.action_share_file: {
+                FileActivity act = (FileActivity)getSherlockActivity();
+                act.getFileOperationsHelper().shareFileWithLink(getFile(), act);
+                return true;
+            }
+            case R.id.action_unshare_file: {
+                FileActivity act = (FileActivity)getSherlockActivity();
+                act.getFileOperationsHelper().unshareFileWithLink(getFile(), act);
+                return true;
+            }
             case R.id.action_open_file_with: {
                 openFile();
                 return true;
@@ -279,6 +329,7 @@ public class PreviewImageFragment extends FileFragment implements   OnRemoteOper
     }
 
     
+
     private void seeDetails() {
         ((FileFragment.ContainerActivity)getActivity()).showDetails(getFile());        
     }
@@ -400,15 +451,9 @@ public class PreviewImageFragment extends FileFragment implements   OnRemoteOper
      */
     @Override
     public void onNeutral(String callerTag) {
-        // TODO this code should be made in a secondary thread,
         OCFile file = getFile();
-        if (file.isDown()) {   // checks it is still there
-            File f = new File(file.getStoragePath());
-            f.delete();
-            file.setStoragePath(null);
-            mStorageManager.saveFile(file);
-            finish();
-        }
+        mStorageManager.removeFile(file, false, true);    // TODO perform in background task / new thread
+        finish();
     }
     
     /**
index 0cce76a..4c52280 100644 (file)
@@ -16,7 +16,6 @@
  */
 package com.owncloud.android.ui.preview;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -58,10 +57,10 @@ import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.media.MediaControlView;
 import com.owncloud.android.media.MediaService;
 import com.owncloud.android.media.MediaServiceBinder;
-import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
-import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
-import com.owncloud.android.oc_framework.operations.RemoteOperation;
-import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.lib.network.webdav.WebdavUtils;
+import com.owncloud.android.lib.operations.common.OnRemoteOperationListener;
+import com.owncloud.android.lib.operations.common.RemoteOperation;
+import com.owncloud.android.lib.operations.common.RemoteOperationResult;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
@@ -290,7 +289,12 @@ public class PreviewMediaFragment extends FileFragment implements
         toHide.add(R.id.action_download_file);
         toHide.add(R.id.action_sync_file);
         toHide.add(R.id.action_rename_file);    // by now
-
+        
+        // Options shareLink
+        if (!getFile().isShareByLink()) {
+            toHide.add(R.id.action_unshare_file);
+        }
+        
         for (int i : toHide) {
             item = menu.findItem(i);
             if (item != null) {
@@ -301,6 +305,25 @@ public class PreviewMediaFragment extends FileFragment implements
         
     }
 
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        
+        MenuItem item = menu.findItem(R.id.action_unshare_file);
+        // Options shareLink
+        if (!getFile().isShareByLink()) {            
+            item.setVisible(false);
+            item.setEnabled(false);
+        } else {
+            item.setVisible(true);
+            item.setEnabled(true);
+        }
+    }
+    
     
     /**
      * {@inheritDoc}
@@ -308,6 +331,14 @@ public class PreviewMediaFragment extends FileFragment implements
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
+            case R.id.action_share_file: {
+                shareFileWithLink();
+                return true;
+            }
+            case R.id.action_unshare_file: {
+                unshareFileWithLink();
+                return true;
+            }
             case R.id.action_open_file_with: {
                 openFile();
                 return true;
@@ -325,8 +356,31 @@ public class PreviewMediaFragment extends FileFragment implements
                 return false;
         }
     }
+    
+
 
+    /**
+     * Update the file of the fragment with file value
+     * @param file
+     */
+    public void updateFile(OCFile file){
+        setFile(file);
+    }
+    
+    private void unshareFileWithLink() {
+        stopPreview(false);
+        FileActivity activity = (FileActivity)((FileFragment.ContainerActivity)getActivity());
+        activity.getFileOperationsHelper().unshareFileWithLink(getFile(), activity);
+    }
     
+    private void shareFileWithLink() {
+        stopPreview(false);
+        FileActivity activity = (FileActivity)((FileFragment.ContainerActivity)getActivity());
+        activity.getFileOperationsHelper().shareFileWithLink(getFile(), activity);
+        
+    }
+
+
     private void seeDetails() {
         stopPreview(false);
         ((FileFragment.ContainerActivity)getActivity()).showDetails(getFile());        
@@ -534,17 +588,19 @@ public class PreviewMediaFragment extends FileFragment implements
 
         @Override
         public void onServiceConnected(ComponentName component, IBinder service) {
-            if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
-                Log_OC.d(TAG, "Media service connected");
-                mMediaServiceBinder = (MediaServiceBinder) service;
-                if (mMediaServiceBinder != null) {
-                    prepareMediaController();
-                    playAudio();    // do not wait for the touch of nobody to play audio
-                    
-                    Log_OC.d(TAG, "Successfully bound to MediaService, MediaController ready");
-                    
-                } else {
-                    Log_OC.e(TAG, "Unexpected response from MediaService while binding");
+            if (getActivity() != null) {
+                if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
+                    Log_OC.d(TAG, "Media service connected");
+                    mMediaServiceBinder = (MediaServiceBinder) service;
+                    if (mMediaServiceBinder != null) {
+                        prepareMediaController();
+                        playAudio();    // do not wait for the touch of nobody to play audio
+
+                        Log_OC.d(TAG, "Successfully bound to MediaService, MediaController ready");
+
+                    } else {
+                        Log_OC.e(TAG, "Unexpected response from MediaService while binding");
+                    }
                 }
             }
         }
@@ -672,16 +728,10 @@ public class PreviewMediaFragment extends FileFragment implements
      */
     @Override
     public void onNeutral(String callerTag) {
-        // TODO this code should be made in a secondary thread,
         OCFile file = getFile();
-        if (file.isDown()) {   // checks it is still there
-            stopPreview(true);
-            File f = new File(file.getStoragePath());
-            f.delete();
-            file.setStoragePath(null);
-            mStorageManager.saveFile(file);
-            finish();
-        }
+        stopPreview(true);
+        mStorageManager.removeFile(file, false, true);    // TODO perform in background task / new thread
+        finish();
     }
     
     /**
index 59d9655..5e5999b 100644 (file)
@@ -18,7 +18,6 @@
 package com.owncloud.android.ui.preview;
 
 import com.owncloud.android.R;
-import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.media.MediaService;
 import com.owncloud.android.ui.activity.FileActivity;
@@ -37,8 +36,8 @@ import android.os.Bundle;
 import android.widget.MediaController;
 import android.widget.VideoView;
 
-import com.owncloud.android.oc_framework.accounts.AccountUtils;
-import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
+import com.owncloud.android.lib.accounts.AccountUtils;
+import com.owncloud.android.lib.accounts.AccountUtils.AccountNotFoundException;
 
 /**
  *  Activity implementing a basic video player.
@@ -60,8 +59,6 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
     
     private static final String TAG = PreviewVideoActivity.class.getSimpleName();
 
-    private FileDataStorageManager mStorageManager;
-    
     private int mSavedPlaybackPosition;         // in the unit time handled by MediaPlayer.getCurrentPosition()
     private boolean mAutoplay;                  // when 'true', the playback starts immediately with the activity
     private VideoView mVideoPlayer;             // view to play the file; both performs and show the playback
@@ -194,6 +191,7 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
     
     @Override
     protected void onAccountSet(boolean stateWasRecovered) {
+        super.onAccountSet(stateWasRecovered);
         if (getAccount() != null) {
             OCFile file = getFile();
             /// Validate handled file  (first image to preview)
@@ -203,8 +201,7 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
             if (!file.isVideo()) {
                 throw new IllegalArgumentException("Non-video file passed as argument");
             }
-            mStorageManager = new FileDataStorageManager(getAccount(), getContentResolver());
-            file = mStorageManager.getFileById(file.getFileId()); 
+            file = getStorageManager().getFileById(file.getFileId()); 
             if (file != null) {
                 if (file.isDown()) {
                     mVideoPlayer.setVideoPath(file.getStoragePath());
@@ -230,7 +227,6 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
                 finish();
             }
         } else {
-            Log_OC.wtf(TAG, "onAccountChanged was called with NULL account associated!");
             finish();
         }
    }
index e4bdd99..680107b 100644 (file)
 package com.owncloud.android.utils;\r
 \r
 import java.util.Arrays;\r
+import java.util.Calendar;\r
 import java.util.Date;\r
 import java.util.HashMap;\r
 import java.util.HashSet;\r
 import java.util.Set;\r
 \r
 import com.owncloud.android.R;\r
-import com.owncloud.android.R.drawable;\r
 \r
 /**\r
  * A helper class for some string operations.\r
@@ -190,4 +190,13 @@ public class DisplayUtils {
         Date date = new Date(milliseconds);\r
         return date.toLocaleString();\r
     }\r
+    \r
+    \r
+    public static int getSeasonalIconId() {\r
+        if (Calendar.getInstance().get(Calendar.DAY_OF_YEAR) >= 354) {\r
+            return R.drawable.winter_holidays_icon;\r
+        } else {\r
+            return R.drawable.icon;\r
+        }\r
+    }\r
 }\r
index 2520644..639caef 100644 (file)
@@ -22,6 +22,7 @@ import java.io.File;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.operations.common.RemoteFile;
 
 import android.annotation.SuppressLint;
 import android.content.Context;
@@ -82,5 +83,38 @@ public class FileStorageUtils {
         parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
         return parentPath;
     }
+    
+    /**
+     * Creates and populates a new {@link OCFile} object with the data read from the server.
+     * 
+     * @param remote    remote file read from the server (remote file or folder).
+     * @return          New OCFile instance representing the remote resource described by we.
+     */
+    public static OCFile fillOCFile(RemoteFile remote) {
+        OCFile file = new OCFile(remote.getRemotePath());
+        file.setCreationTimestamp(remote.getCreationTimestamp());
+        file.setFileLength(remote.getLength());
+        file.setMimetype(remote.getMimeType());
+        file.setModificationTimestamp(remote.getModifiedTimestamp());
+        file.setEtag(remote.getEtag());
+        
+        return file;
+    }
+    
+    /**
+     * Creates and populates a new {@link RemoteFile} object with the data read from an {@link OCFile}.
+     * 
+     * @param oCFile    OCFile 
+     * @return          New RemoteFile instance representing the resource described by ocFile.
+     */
+    public static RemoteFile fillRemoteFile(OCFile ocFile){
+        RemoteFile file = new RemoteFile(ocFile.getRemotePath());
+        file.setCreationTimestamp(ocFile.getCreationTimestamp());
+        file.setLength(ocFile.getFileLength());
+        file.setMimeType(ocFile.getMimetype());
+        file.setModifiedTimestamp(ocFile.getModificationTimestamp());
+        file.setEtag(ocFile.getEtag());
+        return file;
+    }
   
 }
\ No newline at end of file
index 1524d3b..150034b 100644 (file)
 
 package com.owncloud.android.test;
 
+import com.owncloud.android.lib.accounts.AccountUtils;
+import com.owncloud.android.lib.utils.OwnCloudVersion;
+
 import android.test.AndroidTestCase;
 
-import com.owncloud.android.oc_framework.accounts.AccountUtils;
-import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
 
 public class AccountUtilsTest extends AndroidTestCase {
     
diff --git a/third_party/transifex-client/.gitignore b/third_party/transifex-client/.gitignore
deleted file mode 100644 (file)
index 72bd50c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-.tx
-*pyc
-*pyo
-*~
-*egg-info*
diff --git a/third_party/transifex-client/DEVELOPMENT.rst b/third_party/transifex-client/DEVELOPMENT.rst
deleted file mode 100644 (file)
index 992e518..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Releasing
-=========
-
-To create a new release:
-
-1. Update local rep and update the version in ``setup.py``::
-
-    $ hg pull -u
-    $ vim setup.py
-
-2. Test::
-
-    $ python setup.py clean sdist
-    $ cd dist
-    $ tar zxf ...
-    $ cd transifex-client
-    ...test
-
-3. Package and upload on PyPI::
-
-    $ python setup.py clean sdist bdist_egg upload
diff --git a/third_party/transifex-client/LICENSE b/third_party/transifex-client/LICENSE
deleted file mode 100644 (file)
index db860a3..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software
-    interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Program does not specify a
-version number of this License, you may choose any version ever
-published by the Free Software Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these
-terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-  
-    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, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
diff --git a/third_party/transifex-client/MANIFEST.in b/third_party/transifex-client/MANIFEST.in
deleted file mode 100644 (file)
index 83126ac..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-include tx
-
-# Docs
-include LICENSE README.rst
-recursive-include docs *
-
diff --git a/third_party/transifex-client/README.rst b/third_party/transifex-client/README.rst
deleted file mode 100644 (file)
index bb88750..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-
-=============================
- Transifex Command-Line Tool
-=============================
-
-The Transifex Command-line Client is a command line tool that enables
-you to easily manage your translations within a project without the need
-of an elaborate UI system.
-
-You can use the command line client to easily create new resources, map
-locale files to translations and synchronize your Transifex project with
-your local repository and vice verca. Translators and localization
-managers can also use it to handle large volumes of translation files
-easily and without much hassle.
-
-Check the full documentation at
-http://help.transifex.com/user-guide/client/
-
-
-Installing
-==========
-
-You can install the latest version of transifex-client running ``pip
-install transifex-client`` or ``easy_install transifex-client``
-You can also install the `in-development version`_ of transifex-client
-with ``pip install transifex-client==dev`` or ``easy_install
-transifex-client==dev``.
-
-.. _in-development version: http://code.transifex.com/transifex-client/
-
diff --git a/third_party/transifex-client/setup.py b/third_party/transifex-client/setup.py
deleted file mode 100755 (executable)
index 626303d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import os
-import glob
-from codecs import BOM
-
-from setuptools import setup, find_packages
-from setuptools.command.build_py import build_py as _build_py
-
-from txclib import get_version
-
-readme_file = open(u'README.rst')
-long_description = readme_file.read()
-readme_file.close()
-if long_description.startswith(BOM):
-    long_description = long_description.lstrip(BOM)
-long_description = long_description.decode('utf-8')
-
-package_data = {
-    '': ['LICENSE', 'README.rst'],
-}
-
-scripts = ['tx']
-
-install_requires = []
-try:
-    import json
-except ImportError:
-    install_requires.append('simplejson')
-
-setup(
-    name="transifex-client",
-    version=get_version(),
-    scripts=scripts,
-    description="A command line interface for Transifex",
-    long_description=long_description,
-    author="Transifex",
-    author_email="info@transifex.com",
-    url="https://www.transifex.com",
-    license="GPLv2",
-    dependency_links = [
-    ],
-    setup_requires = [
-    ],
-    install_requires = install_requires,
-    tests_require = ["mock", ],
-    data_files=[
-    ],
-    test_suite="tests",
-    zip_safe=False,
-    packages=['txclib', ],
-    include_package_data=True,
-    package_data = package_data,
-    keywords = ('translation', 'localization', 'internationalization',),
-)
diff --git a/third_party/transifex-client/tests/__init__.py b/third_party/transifex-client/tests/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/third_party/transifex-client/tests/test_processors.py b/third_party/transifex-client/tests/test_processors.py
deleted file mode 100644 (file)
index dd7d7d9..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Unit tests for processor functions.
-"""
-
-import unittest
-from urlparse import urlparse
-from txclib.processors import hostname_tld_migration, hostname_ssl_migration
-
-
-class TestHostname(unittest.TestCase):
-    """Test for hostname processors."""
-
-    def test_tld_migration_needed(self):
-        """
-        Test the tld migration of Transifex, when needed.
-        """
-        hostnames = [
-            'http://transifex.net', 'http://www.transifex.net',
-            'https://fedora.transifex.net',
-        ]
-        for h in hostnames:
-            hostname = hostname_tld_migration(h)
-            self.assertTrue(hostname.endswith('com'))
-        orig_hostname = 'http://www.transifex.net/path/'
-        hostname = hostname_tld_migration(orig_hostname)
-        self.assertEqual(hostname, orig_hostname.replace('net', 'com', 1))
-
-    def test_tld_migration_needed(self):
-        """
-        Test that unneeded tld migrations are detected correctly.
-        """
-        hostnames = [
-            'https://www.transifex.com', 'http://fedora.transifex.com',
-            'http://www.example.net/path/'
-        ]
-        for h in hostnames:
-            hostname = hostname_tld_migration(h)
-            self.assertEqual(hostname, h)
-
-    def test_no_scheme_specified(self):
-        """
-        Test that, if no scheme has been specified, the https one will be used.
-        """
-        hostname = '//transifex.net'
-        hostname = hostname_ssl_migration(hostname)
-        self.assertTrue(hostname.startswith('https://'))
-
-    def test_http_replacement(self):
-        """Test the replacement of http with https."""
-        hostnames = [
-            'http://transifex.com', 'http://transifex.net/http/',
-            'http://www.transifex.com/path/'
-        ]
-        for h in hostnames:
-            hostname = hostname_ssl_migration(h)
-            self.assertEqual(hostname[:8], 'https://')
-            self.assertEqual(hostname[7:], h[6:])
-
-    def test_no_http_replacement_needed(self):
-        """Test that http will not be replaces with https, when not needed."""
-        for h in ['http://example.com', 'http://example.com/http/']:
-            hostname = hostname_ssl_migration(h)
-            self.assertEqual(hostname, hostname)
diff --git a/third_party/transifex-client/tests/test_project.py b/third_party/transifex-client/tests/test_project.py
deleted file mode 100644 (file)
index 3b42121..0000000
+++ /dev/null
@@ -1,531 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-import unittest
-import contextlib
-import itertools
-try:
-    import json
-except ImportError:
-    import simplejson as json
-from mock import Mock, patch
-
-from txclib.project import Project
-from txclib.config import Flipdict
-
-
-class TestProject(unittest.TestCase):
-
-    def test_extract_fields(self):
-        """Test the functions that extract a field from a stats object."""
-        stats = {
-            'completed': '80%',
-            'last_update': '00:00',
-            'foo': 'bar',
-        }
-        self.assertEqual(
-            stats['completed'], '%s%%' % Project._extract_completed(stats)
-        )
-        self.assertEqual(stats['last_update'], Project._extract_updated(stats))
-
-    def test_specifying_resources(self):
-        """Test the various ways to specify resources in a project."""
-        p = Project(init=False)
-        resources = [
-            'proj1.res1',
-            'proj2.res2',
-            'transifex.txn',
-            'transifex.txo',
-        ]
-        with patch.object(p, 'get_resource_list') as mock:
-            mock.return_value = resources
-            cmd_args = [
-                'proj1.res1', '*1*', 'transifex*', '*r*',
-                '*o', 'transifex.tx?', 'transifex.txn',
-            ]
-            results = [
-                ['proj1.res1', ],
-                ['proj1.res1', ],
-                ['transifex.txn', 'transifex.txo', ],
-                ['proj1.res1', 'proj2.res2', 'transifex.txn', 'transifex.txo', ],
-                ['transifex.txo', ],
-                ['transifex.txn', 'transifex.txo', ],
-                ['transifex.txn', ],
-                [],
-            ]
-
-            for i, arg in enumerate(cmd_args):
-                resources = [arg]
-                self.assertEqual(p.get_chosen_resources(resources), results[i])
-
-            # wrong argument
-            resources = ['*trasnifex*', ]
-            self.assertRaises(Exception, p.get_chosen_resources, resources)
-
-
-class TestProjectMinimumPercent(unittest.TestCase):
-    """Test the minimum-perc option."""
-
-    def setUp(self):
-        super(TestProjectMinimumPercent, self).setUp()
-        self.p = Project(init=False)
-        self.p.minimum_perc = None
-        self.p.resource = "resource"
-
-    def test_cmd_option(self):
-        """Test command-line option."""
-        self.p.minimum_perc = 20
-        results = itertools.cycle([80, 90 ])
-        def side_effect(*args):
-            return results.next()
-
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.side_effect = side_effect
-            self.assertFalse(self.p._satisfies_min_translated({'completed': '12%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '20%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '30%'}))
-
-    def test_global_only(self):
-        """Test only global option."""
-        results = itertools.cycle([80, None ])
-        def side_effect(*args):
-            return results.next()
-
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.side_effect = side_effect
-            self.assertFalse(self.p._satisfies_min_translated({'completed': '70%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '80%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
-
-    def test_local_lower_than_global(self):
-        """Test the case where the local option is lower than the global."""
-        results = itertools.cycle([80, 70 ])
-        def side_effect(*args):
-            return results.next()
-
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.side_effect = side_effect
-            self.assertFalse(self.p._satisfies_min_translated({'completed': '60%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '70%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '80%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
-
-    def test_local_higher_than_global(self):
-        """Test the case where the local option is lower than the global."""
-        results = itertools.cycle([60, 70 ])
-        def side_effect(*args):
-            return results.next()
-
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.side_effect = side_effect
-            self.assertFalse(self.p._satisfies_min_translated({'completed': '60%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '70%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '80%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
-
-    def test_local_only(self):
-        """Test the case where the local option is lower than the global."""
-        results = itertools.cycle([None, 70 ])
-        def side_effect(*args):
-            return results.next()
-
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.side_effect = side_effect
-            self.assertFalse(self.p._satisfies_min_translated({'completed': '60%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '70%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '80%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
-
-    def test_no_option(self):
-        """"Test the case there is nothing defined."""
-        results = itertools.cycle([None, None ])
-        def side_effect(*args):
-            return results.next()
-
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.side_effect = side_effect
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '0%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '10%'}))
-            self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
-
-
-class TestProjectFilters(unittest.TestCase):
-    """Test filters used to decide whether to push/pull a translation or not."""
-
-    def setUp(self):
-        super(TestProjectFilters, self).setUp()
-        self.p = Project(init=False)
-        self.p.minimum_perc = None
-        self.p.resource = "resource"
-        self.stats = {
-            'en': {
-                'completed': '100%', 'last_update': '2011-11-01 15:00:00',
-            }, 'el': {
-                'completed': '60%', 'last_update': '2011-11-01 15:00:00',
-            }, 'pt': {
-                'completed': '70%', 'last_update': '2011-11-01 15:00:00',
-            },
-        }
-        self.langs = self.stats.keys()
-
-    def test_add_translation(self):
-        """Test filters for adding translations.
-
-        We do not test here for minimum percentages.
-        """
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.return_value = None
-            should_add = self.p._should_add_translation
-            for force in [True, False]:
-                for lang in self.langs:
-                    self.assertTrue(should_add(lang, self.stats, force))
-
-            # unknown language
-            self.assertFalse(should_add('es', self.stats))
-
-    def test_update_translation(self):
-        """Test filters for updating a translation.
-
-        We do not test here for minimum percentages.
-        """
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.return_value = None
-
-            should_update = self.p._should_update_translation
-            force = True
-            for lang in self.langs:
-                self.assertTrue(should_update(lang, self.stats, 'foo', force))
-
-            force = False       # reminder
-            local_file = 'foo'
-
-            # unknown language
-            self.assertFalse(should_update('es', self.stats, local_file))
-
-            # no local file
-            with patch.object(self.p, "_get_time_of_local_file") as time_mock:
-                time_mock.return_value = None
-                with patch.object(self.p, "get_full_path") as path_mock:
-                    path_mock.return_value = "foo"
-                    for lang in self.langs:
-                        self.assertTrue(
-                            should_update(lang, self.stats, local_file)
-                        )
-
-            # older local files
-            local_times = [self.p._generate_timestamp('2011-11-01 14:00:59')]
-            results = itertools.cycle(local_times)
-            def side_effect(*args):
-                return results.next()
-
-            with patch.object(self.p, "_get_time_of_local_file") as time_mock:
-                time_mock.side_effect = side_effect
-                with patch.object(self.p, "get_full_path") as path_mock:
-                    path_mock.return_value = "foo"
-                    for lang in self.langs:
-                        self.assertTrue(
-                            should_update(lang, self.stats, local_file)
-                        )
-
-            # newer local files
-            local_times = [self.p._generate_timestamp('2011-11-01 15:01:59')]
-            results = itertools.cycle(local_times)
-            def side_effect(*args):
-                return results.next()
-
-            with patch.object(self.p, "_get_time_of_local_file") as time_mock:
-                time_mock.side_effect = side_effect
-                with patch.object(self.p, "get_full_path") as path_mock:
-                    path_mock.return_value = "foo"
-                    for lang in self.langs:
-                        self.assertFalse(
-                            should_update(lang, self.stats, local_file)
-                        )
-
-    def test_push_translation(self):
-        """Test filters for pushing a translation file."""
-        with patch.object(self.p, "get_resource_option") as mock:
-            mock.return_value = None
-
-            local_file = 'foo'
-            should_push = self.p._should_push_translation
-            force = True
-            for lang in self.langs:
-                self.assertTrue(should_push(lang, self.stats, local_file, force))
-
-            force = False       # reminder
-
-            # unknown language
-            self.assertTrue(should_push('es', self.stats, local_file))
-
-            # older local files
-            local_times = [self.p._generate_timestamp('2011-11-01 14:00:59')]
-            results = itertools.cycle(local_times)
-            def side_effect(*args):
-                return results.next()
-
-            with patch.object(self.p, "_get_time_of_local_file") as time_mock:
-                time_mock.side_effect = side_effect
-                with patch.object(self.p, "get_full_path") as path_mock:
-                    path_mock.return_value = "foo"
-                    for lang in self.langs:
-                        self.assertFalse(
-                            should_push(lang, self.stats, local_file)
-                        )
-
-            # newer local files
-            local_times = [self.p._generate_timestamp('2011-11-01 15:01:59')]
-            results = itertools.cycle(local_times)
-            def side_effect(*args):
-                return results.next()
-
-            with patch.object(self.p, "_get_time_of_local_file") as time_mock:
-                time_mock.side_effect = side_effect
-                with patch.object(self.p, "get_full_path") as path_mock:
-                    path_mock.return_value = "foo"
-                    for lang in self.langs:
-                        self.assertTrue(
-                            should_push(lang, self.stats, local_file)
-                        )
-
-
-class TestProjectPull(unittest.TestCase):
-    """Test bits & pieces of the pull method."""
-
-    def setUp(self):
-        super(TestProjectPull, self).setUp()
-        self.p = Project(init=False)
-        self.p.minimum_perc = None
-        self.p.resource = "resource"
-        self.p.host = 'foo'
-        self.p.project_slug = 'foo'
-        self.p.resource_slug = 'foo'
-        self.stats = {
-            'en': {
-                'completed': '100%', 'last_update': '2011-11-01 15:00:00',
-            }, 'el': {
-                'completed': '60%', 'last_update': '2011-11-01 15:00:00',
-            }, 'pt': {
-                'completed': '70%', 'last_update': '2011-11-01 15:00:00',
-            },
-        }
-        self.langs = self.stats.keys()
-        self.files = dict(zip(self.langs, itertools.repeat(None)))
-        self.details = {'available_languages': []}
-        for lang in self.langs:
-            self.details['available_languages'].append({'code': lang})
-        self.slang = 'en'
-        self.lang_map = Flipdict()
-
-    def test_new_translations(self):
-        """Test finding new transaltions to add."""
-        with patch.object(self.p, 'do_url_request') as resource_mock:
-            resource_mock.return_value = json.dumps(self.details)
-            files_keys = self.langs
-            new_trans = self.p._new_translations_to_add
-            for force in [True, False]:
-                res = new_trans(
-                    self.files, self.slang, self.lang_map, self.stats, force
-                )
-                self.assertEquals(res, set([]))
-
-            with patch.object(self.p, '_should_add_translation') as filter_mock:
-                filter_mock.return_value = True
-                for force in [True, False]:
-                    res = new_trans(
-                        {'el': None}, self.slang, self.lang_map, self.stats, force
-                    )
-                    self.assertEquals(res, set(['pt']))
-                for force in [True, False]:
-                    res = new_trans(
-                        {}, self.slang, self.lang_map, self.stats, force
-                    )
-                    self.assertEquals(res, set(['el', 'pt']))
-
-                files = {}
-                files['pt_PT'] = None
-                lang_map = {'pt': 'pt_PT'}
-                for force in [True, False]:
-                    res = new_trans(
-                        files, self.slang, lang_map, self.stats, force
-                    )
-                    self.assertEquals(res, set(['el']))
-
-    def test_languages_to_pull_empty_initial_list(self):
-        """Test determining the languages to pull, when the initial
-        list is empty.
-        """
-        languages = []
-        force = False
-
-        res = self.p._languages_to_pull(
-            languages, self.files, self.lang_map, self.stats, force
-        )
-        existing = res[0]
-        new = res[1]
-        self.assertEquals(existing, set(['el', 'en', 'pt']))
-        self.assertFalse(new)
-
-        del self.files['el']
-        self.files['el-gr'] = None
-        self.lang_map['el'] = 'el-gr'
-        res = self.p._languages_to_pull(
-            languages, self.files, self.lang_map, self.stats, force
-        )
-        existing = res[0]
-        new = res[1]
-        self.assertEquals(existing, set(['el', 'en', 'pt']))
-        self.assertFalse(new)
-
-    def test_languages_to_pull_with_initial_list(self):
-        """Test determining the languages to pull, then there is a
-        language selection from the user.
-        """
-        languages = ['el', 'en']
-        self.lang_map['el'] = 'el-gr'
-        del self.files['el']
-        self.files['el-gr'] = None
-        force = False
-
-        with patch.object(self.p, '_should_add_translation') as mock:
-            mock.return_value = True
-            res = self.p._languages_to_pull(
-                languages, self.files, self.lang_map, self.stats, force
-            )
-            existing = res[0]
-            new = res[1]
-            self.assertEquals(existing, set(['en', 'el-gr', ]))
-            self.assertFalse(new)
-
-            mock.return_value = False
-            res = self.p._languages_to_pull(
-                languages, self.files, self.lang_map, self.stats, force
-            )
-            existing = res[0]
-            new = res[1]
-            self.assertEquals(existing, set(['en', 'el-gr', ]))
-            self.assertFalse(new)
-
-            del self.files['el-gr']
-            mock.return_value = True
-            res = self.p._languages_to_pull(
-                languages, self.files, self.lang_map, self.stats, force
-            )
-            existing = res[0]
-            new = res[1]
-            self.assertEquals(existing, set(['en', ]))
-            self.assertEquals(new, set(['el', ]))
-
-            mock.return_value = False
-            res = self.p._languages_to_pull(
-                languages, self.files, self.lang_map, self.stats, force
-            )
-            existing = res[0]
-            new = res[1]
-            self.assertEquals(existing, set(['en', ]))
-            self.assertEquals(new, set([]))
-
-    def test_in_combination_with_force_option(self):
-        """Test the minumum-perc option along with -f."""
-        with patch.object(self.p, 'get_resource_option') as mock:
-            mock.return_value = 70
-
-            res = self.p._should_download('de', self.stats, None, False)
-            self.assertEquals(res, False)
-            res = self.p._should_download('el', self.stats, None, False)
-            self.assertEquals(res, False)
-            res = self.p._should_download('el', self.stats, None, True)
-            self.assertEquals(res, False)
-            res = self.p._should_download('en', self.stats, None, False)
-            self.assertEquals(res, True)
-            res = self.p._should_download('en', self.stats, None, True)
-            self.assertEquals(res, True)
-
-            with patch.object(self.p, '_remote_is_newer') as local_file_mock:
-                local_file_mock = False
-                res = self.p._should_download('pt', self.stats, None, False)
-                self.assertEquals(res, True)
-                res = self.p._should_download('pt', self.stats, None, True)
-                self.assertEquals(res, True)
-
-
-class TestFormats(unittest.TestCase):
-    """Tests for the supported formats."""
-
-    def setUp(self):
-        self.p = Project(init=False)
-
-    def test_extensions(self):
-        """Test returning the correct extension for a format."""
-        sample_formats = {
-            'PO': {'file-extensions': '.po, .pot'},
-            'QT': {'file-extensions': '.ts'},
-        }
-        extensions = ['.po', '.ts', '', ]
-        with patch.object(self.p, "do_url_request") as mock:
-            mock.return_value = json.dumps(sample_formats)
-            for (type_, ext) in zip(['PO', 'QT', 'NONE', ], extensions):
-                extension = self.p._extension_for(type_)
-                self.assertEquals(extension, ext)
-
-
-class TestOptions(unittest.TestCase):
-    """Test the methods related to parsing the configuration file."""
-
-    def setUp(self):
-        self.p = Project(init=False)
-
-    def test_get_option(self):
-        """Test _get_option method."""
-        with contextlib.nested(
-            patch.object(self.p, 'get_resource_option'),
-            patch.object(self.p, 'config', create=True)
-        ) as (rmock, cmock):
-            rmock.return_value = 'resource'
-            cmock.has_option.return_value = 'main'
-            cmock.get.return_value = 'main'
-            self.assertEqual(self.p._get_option(None, None), 'resource')
-            rmock.return_value = None
-            cmock.has_option.return_value = 'main'
-            cmock.get.return_value = 'main'
-            self.assertEqual(self.p._get_option(None, None), 'main')
-            cmock.has_option.return_value = None
-            self.assertIs(self.p._get_option(None, None), None)
-
-
-class TestConfigurationOptions(unittest.TestCase):
-    """Test the various configuration options."""
-
-    def test_i18n_type(self):
-        p = Project(init=False)
-        type_string = 'type'
-        i18n_type = 'PO'
-        with patch.object(p, 'config', create=True) as config_mock:
-            p.set_i18n_type([], i18n_type)
-            calls = config_mock.method_calls
-            self.assertEquals('set', calls[0][0])
-            self.assertEquals('main', calls[0][1][0])
-            p.set_i18n_type(['transifex.txo'], 'PO')
-            calls = config_mock.method_calls
-            self.assertEquals('set', calls[0][0])
-            p.set_i18n_type(['transifex.txo', 'transifex.txn'], 'PO')
-            calls = config_mock.method_calls
-            self.assertEquals('set', calls[0][0])
-            self.assertEquals('set', calls[1][0])
-
-
-class TestStats(unittest.TestCase):
-    """Test the access to the stats objects."""
-
-    def setUp(self):
-        self.stats = Mock()
-        self.stats.__getitem__ = Mock()
-        self.stats.__getitem__.return_value = '12%'
-
-    def test_field_used_per_mode(self):
-        """Test the fields used for each mode."""
-        Project._extract_completed(self.stats, 'translate')
-        self.stats.__getitem__.assert_called_with('completed')
-        Project._extract_completed(self.stats, 'reviewed')
-        self.stats.__getitem__.assert_called_with('reviewed_percentage')
-
diff --git a/third_party/transifex-client/tx b/third_party/transifex-client/tx
deleted file mode 100755 (executable)
index dfb4a4c..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from optparse import OptionParser, OptionValueError
-import os
-import sys
-
-from txclib import utils
-from txclib import get_version
-from txclib.log import set_log_level, logger
-
-reload(sys) # WTF? Otherwise setdefaultencoding doesn't work
-
-# This block ensures that ^C interrupts are handled quietly.
-try:
-    import signal
-
-    def exithandler(signum,frame):
-        signal.signal(signal.SIGINT, signal.SIG_IGN)
-        signal.signal(signal.SIGTERM, signal.SIG_IGN)
-        sys.exit(1)
-
-    signal.signal(signal.SIGINT, exithandler)
-    signal.signal(signal.SIGTERM, exithandler)
-    if hasattr(signal, 'SIGPIPE'):
-        signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-
-except KeyboardInterrupt:
-    sys.exit(1)
-
-# When we open file with f = codecs.open we specifi FROM what encoding to read
-# This sets the encoding for the strings which are created with f.read()
-sys.setdefaultencoding('utf-8')
-
-
-def main(argv):
-    """
-    Here we parse the flags (short, long) and we instantiate the classes.
-    """
-    usage = "usage: %prog [options] command [cmd_options]"
-    description = "This is the Transifex command line client which"\
-               " allows you to manage your translations locally and sync"\
-               " them with the master Transifex server.\nIf you'd like to"\
-               " check the available commands issue `%prog help` or if you"\
-               " just want help with a specific command issue `%prog help"\
-               " command`"
-
-    parser = OptionParser(
-        usage=usage, version=get_version(), description=description
-    )
-    parser.disable_interspersed_args()
-    parser.add_option(
-        "-d", "--debug", action="store_true", dest="debug",
-        default=False, help=("enable debug messages")
-    )
-    parser.add_option(
-        "-q", "--quiet", action="store_true", dest="quiet",
-        default=False, help="don't print status messages to stdout"
-    )
-    parser.add_option(
-        "-r", "--root", action="store", dest="root_dir", type="string",
-        default=None, help="change root directory (default is cwd)"
-    )
-    parser.add_option(
-        "--traceback", action="store_true", dest="trace", default=False,
-        help="print full traceback on exceptions"
-    )
-    parser.add_option(
-        "--disable-colors", action="store_true", dest="color_disable",
-        default=(os.name == 'nt' or not sys.stdout.isatty()),
-        help="disable colors in the output of commands"
-    )
-    (options, args) = parser.parse_args()
-
-    if len(args) < 1:
-        parser.error("No command was given")
-
-    utils.DISABLE_COLORS = options.color_disable
-
-    # set log level
-    if options.quiet:
-        set_log_level('WARNING')
-    elif options.debug:
-        set_log_level('DEBUG')
-
-    # find .tx
-    path_to_tx = options.root_dir or utils.find_dot_tx()
-
-
-    cmd = args[0]
-    try:
-        utils.exec_command(cmd, args[1:], path_to_tx)
-    except utils.UnknownCommandError:
-        logger.error("tx: Command %s not found" % cmd)
-    except SystemExit:
-        sys.exit()
-    except:
-        import traceback
-        if options.trace:
-            traceback.print_exc()
-        else:
-            formatted_lines = traceback.format_exc().splitlines()
-            logger.error(formatted_lines[-1])
-        sys.exit(1)
-
-# Run baby :) ... run
-if __name__ == "__main__":
-    # sys.argv[0] is the name of the script that we’re running.
-    main(sys.argv[1:])
diff --git a/third_party/transifex-client/txclib/__init__.py b/third_party/transifex-client/txclib/__init__.py
deleted file mode 100644 (file)
index 814773c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Copyright (C) 2010 by Indifex (www.indifex.com), see AUTHORS.
-License: BSD, see LICENSE for details.
-
-For further information visit http://code.indifex.com/transifex-client
-"""
-
-
-VERSION = (0, 9, 0, 'devel')
-
-def get_version():
-    version = '%s.%s' % (VERSION[0], VERSION[1])
-    if VERSION[2]:
-        version = '%s.%s' % (version, VERSION[2])
-    if VERSION[3] != 'final':
-        version = '%s %s' % (version, VERSION[3])
-    return version
diff --git a/third_party/transifex-client/txclib/commands.py b/third_party/transifex-client/txclib/commands.py
deleted file mode 100644 (file)
index 282287f..0000000
+++ /dev/null
@@ -1,576 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-In this file we have all the top level commands for the transifex client.
-Since we're using a way to automatically list them and execute them, when
-adding code to this file you must take care of the following:
- * Added functions must begin with 'cmd_' followed by the actual name of the
-   command being used in the command line (eg cmd_init)
- * The description for each function that we display to the user is read from
-   the func_doc attribute which reads the doc string. So, when adding
-   docstring to a new function make sure you add an oneliner which is
-   descriptive and is meant to be seen by the user.
- * When including libraries, it's best if you include modules instead of
-   functions because that way our function resolution will work faster and the
-   chances of overlapping are minimal
- * All functions should use the OptionParser and should have a usage and
-   descripition field.
-"""
-import os
-import re, shutil
-import sys
-from optparse import OptionParser, OptionGroup
-import ConfigParser
-
-
-from txclib import utils, project
-from txclib.utils import parse_json, compile_json, relpath
-from txclib.config import OrderedRawConfigParser
-from txclib.exceptions import UnInitializedError
-from txclib.parsers import delete_parser, help_parser, parse_csv_option, \
-        status_parser, pull_parser, set_parser, push_parser, init_parser
-from txclib.log import logger
-
-
-def cmd_init(argv, path_to_tx):
-    "Initialize a new transifex project."
-    parser = init_parser()
-    (options, args) = parser.parse_args(argv)
-    if len(args) > 1:
-        parser.error("Too many arguments were provided. Aborting...")
-    if args:
-        path_to_tx = args[0]
-    else:
-        path_to_tx = os.getcwd()
-
-    if os.path.isdir(os.path.join(path_to_tx,".tx")):
-        logger.info("tx: There is already a tx folder!")
-        reinit = raw_input("Do you want to delete it and reinit the project? [y/N]: ")
-        while (reinit != 'y' and reinit != 'Y' and reinit != 'N' and reinit != 'n' and reinit != ''):
-            reinit = raw_input("Do you want to delete it and reinit the project? [y/N]: ")
-        if not reinit or reinit in ['N', 'n', 'NO', 'no', 'No']:
-            return
-        # Clean the old settings
-        # FIXME: take a backup
-        else:
-            rm_dir = os.path.join(path_to_tx, ".tx")
-            shutil.rmtree(rm_dir)
-
-    logger.info("Creating .tx folder...")
-    os.mkdir(os.path.join(path_to_tx,".tx"))
-
-    # Handle the credentials through transifexrc
-    home = os.path.expanduser("~")
-    txrc = os.path.join(home, ".transifexrc")
-    config = OrderedRawConfigParser()
-
-    default_transifex = "https://www.transifex.com"
-    transifex_host = options.host or raw_input("Transifex instance [%s]: " % default_transifex)
-
-    if not transifex_host:
-        transifex_host = default_transifex
-    if not transifex_host.startswith(('http://', 'https://')):
-        transifex_host = 'https://' + transifex_host
-
-    config_file = os.path.join(path_to_tx, ".tx", "config")
-    if not os.path.exists(config_file):
-        # The path to the config file (.tx/config)
-        logger.info("Creating skeleton...")
-        config = OrderedRawConfigParser()
-        config.add_section('main')
-        config.set('main', 'host', transifex_host)
-        # Touch the file if it doesn't exist
-        logger.info("Creating config file...")
-        fh = open(config_file, 'w')
-        config.write(fh)
-        fh.close()
-
-    prj = project.Project(path_to_tx)
-    prj.getset_host_credentials(transifex_host, user=options.user,
-        password=options.password)
-    prj.save()
-    logger.info("Done.")
-
-
-def cmd_set(argv, path_to_tx):
-    "Add local or remote files under transifex"
-    parser = set_parser()
-    (options, args) = parser.parse_args(argv)
-
-    # Implement options/args checks
-    # TODO !!!!!!!
-    if options.local:
-        try:
-            expression = args[0]
-        except IndexError:
-            parser.error("Please specify an expression.")
-        if not options.resource:
-            parser.error("Please specify a resource")
-        if not options.source_language:
-            parser.error("Please specify a source language.")
-        if not '<lang>' in expression:
-            parser.error("The expression you have provided is not valid.")
-        if not utils.valid_slug(options.resource):
-            parser.error("Invalid resource slug. The format is <project_slug>"\
-                ".<resource_slug> and the valid characters include [_-\w].")
-        _auto_local(path_to_tx, options.resource,
-            source_language=options.source_language,
-            expression = expression, source_file=options.source_file,
-            execute=options.execute, regex=False)
-        if options.execute:
-            _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx)
-            _set_mode(options.resource, options.mode, path_to_tx)
-            _set_type(options.resource, options.i18n_type, path_to_tx)
-        return
-
-    if options.remote:
-        try:
-            url = args[0]
-        except IndexError:
-            parser.error("Please specify an remote url")
-        _auto_remote(path_to_tx, url)
-        _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx)
-        _set_mode(options.resource, options.mode, path_to_tx)
-        return
-
-    if options.is_source:
-        resource = options.resource
-        if not resource:
-            parser.error("You must specify a resource name with the"
-                " -r|--resource flag.")
-
-        lang = options.language
-        if not lang:
-            parser.error("Please specify a source language.")
-
-        if len(args) != 1:
-            parser.error("Please specify a file.")
-
-        if not utils.valid_slug(resource):
-            parser.error("Invalid resource slug. The format is <project_slug>"\
-                ".<resource_slug> and the valid characters include [_-\w].")
-
-        file = args[0]
-        # Calculate relative path
-        path_to_file = relpath(file, path_to_tx)
-        _set_source_file(path_to_tx, resource, options.language, path_to_file)
-    elif options.resource or options.language:
-        resource = options.resource
-        lang = options.language
-
-        if len(args) != 1:
-            parser.error("Please specify a file")
-
-        # Calculate relative path
-        path_to_file = relpath(args[0], path_to_tx)
-
-        try:
-            _go_to_dir(path_to_tx)
-        except UnInitializedError, e:
-            utils.logger.error(e)
-            return
-
-        if not utils.valid_slug(resource):
-            parser.error("Invalid resource slug. The format is <project_slug>"\
-                ".<resource_slug> and the valid characters include [_-\w].")
-        _set_translation(path_to_tx, resource, lang, path_to_file)
-
-    _set_mode(options.resource, options.mode, path_to_tx)
-    _set_type(options.resource, options.i18n_type, path_to_tx)
-    _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx)
-
-    logger.info("Done.")
-    return
-
-
-def _auto_local(path_to_tx, resource, source_language, expression, execute=False,
-                source_file=None, regex=False):
-    """Auto configure local project."""
-    # The path everything will be relative to
-    curpath = os.path.abspath(os.curdir)
-
-    # Force expr to be a valid regex expr (escaped) but keep <lang> intact
-    expr_re = utils.regex_from_filefilter(expression, curpath)
-    expr_rec = re.compile(expr_re)
-
-    if not execute:
-        logger.info("Only printing the commands which will be run if the "
-                  "--execute switch is specified.")
-
-    # First, let's construct a dictionary of all matching files.
-    # Note: Only the last matching file of a language will be stored.
-    translation_files = {}
-    for root, dirs, files in os.walk(curpath):
-        for f in files:
-            f_path = os.path.abspath(os.path.join(root, f))
-            match = expr_rec.match(f_path)
-            if match:
-                lang = match.group(1)
-                f_path = os.path.abspath(f_path)
-                if lang == source_language and not source_file:
-                    source_file = f_path
-                else:
-                    translation_files[lang] = f_path
-
-    if not source_file:
-        raise Exception("Could not find a source language file. Please run"
-            " set --source manually and then re-run this command or provide"
-            " the source file with the -s flag.")
-    if execute:
-        logger.info("Updating source for resource %s ( %s -> %s )." % (resource,
-            source_language, relpath(source_file, path_to_tx)))
-        _set_source_file(path_to_tx, resource, source_language,
-            relpath(source_file, path_to_tx))
-    else:
-        logger.info('\ntx set --source -r %(res)s -l %(lang)s %(file)s\n' % {
-            'res': resource,
-            'lang': source_language,
-            'file': relpath(source_file, curpath)})
-
-    prj = project.Project(path_to_tx)
-    root_dir = os.path.abspath(path_to_tx)
-
-    if execute:
-        try:
-            prj.config.get("%s" % resource, "source_file")
-        except ConfigParser.NoSectionError:
-            raise Exception("No resource with slug \"%s\" was found.\nRun 'tx set --auto"
-                "-local -r %s \"expression\"' to do the initial configuration." % resource)
-
-    # Now let's handle the translation files.
-    if execute:
-        logger.info("Updating file expression for resource %s ( %s )." % (resource,
-            expression))
-        # Eval file_filter relative to root dir
-        file_filter = relpath(os.path.join(curpath, expression),
-            path_to_tx)
-        prj.config.set("%s" % resource, "file_filter", file_filter)
-    else:
-        for (lang, f_path) in sorted(translation_files.items()):
-            logger.info('tx set -r %(res)s -l %(lang)s %(file)s' % {
-                'res': resource,
-                'lang': lang,
-                'file': relpath(f_path, curpath)})
-
-    if execute:
-        prj.save()
-
-
-def _auto_remote(path_to_tx, url):
-    """
-    Initialize a remote release/project/resource to the current directory.
-    """
-    logger.info("Auto configuring local project from remote URL...")
-
-    type, vars = utils.parse_tx_url(url)
-    prj = project.Project(path_to_tx)
-    username, password = prj.getset_host_credentials(vars['hostname'])
-
-    if type == 'project':
-        logger.info("Getting details for project %s" % vars['project'])
-        proj_info = utils.get_details('project_details',
-            username, password,
-            hostname = vars['hostname'], project = vars['project'])
-        resources = [ '.'.join([vars['project'], r['slug']]) for r in proj_info['resources'] ]
-        logger.info("%s resources found. Configuring..." % len(resources))
-    elif type == 'release':
-        logger.info("Getting details for release %s" % vars['release'])
-        rel_info = utils.get_details('release_details',
-            username, password, hostname = vars['hostname'],
-            project = vars['project'], release = vars['release'])
-        resources = []
-        for r in rel_info['resources']:
-            if r.has_key('project'):
-                resources.append('.'.join([r['project']['slug'], r['slug']]))
-            else:
-                resources.append('.'.join([vars['project'], r['slug']]))
-        logger.info("%s resources found. Configuring..." % len(resources))
-    elif type == 'resource':
-        logger.info("Getting details for resource %s" % vars['resource'])
-        resources = [ '.'.join([vars['project'], vars['resource']]) ]
-    else:
-        raise("Url '%s' is not recognized." % url)
-
-    for resource in resources:
-        logger.info("Configuring resource %s." % resource)
-        proj, res = resource.split('.')
-        res_info = utils.get_details('resource_details',
-             username, password, hostname = vars['hostname'],
-             project = proj, resource=res)
-        try:
-            source_lang = res_info['source_language_code']
-            i18n_type = res_info['i18n_type']
-        except KeyError:
-            raise Exception("Remote server seems to be running an unsupported version"
-                " of Transifex. Either update your server software of fallback"
-                " to a previous version of transifex-client.")
-        prj.set_remote_resource(
-            resource=resource,
-            host = vars['hostname'],
-            source_lang = source_lang,
-            i18n_type = i18n_type)
-
-    prj.save()
-
-
-def cmd_push(argv, path_to_tx):
-    "Push local files to remote server"
-    parser = push_parser()
-    (options, args) = parser.parse_args(argv)
-    force_creation = options.force_creation
-    languages = parse_csv_option(options.languages)
-    resources = parse_csv_option(options.resources)
-    skip = options.skip_errors
-    prj = project.Project(path_to_tx)
-    if not (options.push_source or options.push_translations):
-        parser.error("You need to specify at least one of the -s|--source,"
-            " -t|--translations flags with the push command.")
-
-    prj.push(
-        force=force_creation, resources=resources, languages=languages,
-        skip=skip, source=options.push_source,
-        translations=options.push_translations,
-        no_interactive=options.no_interactive
-    )
-    logger.info("Done.")
-
-
-def cmd_pull(argv, path_to_tx):
-    "Pull files from remote server to local repository"
-    parser = pull_parser()
-    (options, args) = parser.parse_args(argv)
-    if options.fetchall and options.languages:
-        parser.error("You can't user a language filter along with the"\
-            " -a|--all option")
-    languages = parse_csv_option(options.languages)
-    resources = parse_csv_option(options.resources)
-    skip = options.skip_errors
-    minimum_perc = options.minimum_perc or None
-
-    try:
-        _go_to_dir(path_to_tx)
-    except UnInitializedError, e:
-        utils.logger.error(e)
-        return
-
-    # instantiate the project.Project
-    prj = project.Project(path_to_tx)
-    prj.pull(
-        languages=languages, resources=resources, overwrite=options.overwrite,
-        fetchall=options.fetchall, fetchsource=options.fetchsource,
-        force=options.force, skip=skip, minimum_perc=minimum_perc,
-        mode=options.mode
-    )
-    logger.info("Done.")
-
-
-def _set_source_file(path_to_tx, resource, lang, path_to_file):
-    """Reusable method to set source file."""
-    proj, res = resource.split('.')
-    if not proj or not res:
-        raise Exception("\"%s.%s\" is not a valid resource identifier. It should"
-            " be in the following format project_slug.resource_slug." %
-            (proj, res))
-    if not lang:
-        raise Exception("You haven't specified a source language.")
-
-    try:
-        _go_to_dir(path_to_tx)
-    except UnInitializedError, e:
-        utils.logger.error(e)
-        return
-
-    if not os.path.exists(path_to_file):
-        raise Exception("tx: File ( %s ) does not exist." %
-            os.path.join(path_to_tx, path_to_file))
-
-    # instantiate the project.Project
-    prj = project.Project(path_to_tx)
-    root_dir = os.path.abspath(path_to_tx)
-
-    if root_dir not in os.path.normpath(os.path.abspath(path_to_file)):
-        raise Exception("File must be under the project root directory.")
-
-    logger.info("Setting source file for resource %s.%s ( %s -> %s )." % (
-        proj, res, lang, path_to_file))
-
-    path_to_file = relpath(path_to_file, root_dir)
-
-    prj = project.Project(path_to_tx)
-
-    # FIXME: Check also if the path to source file already exists.
-    try:
-        try:
-            prj.config.get("%s.%s" % (proj, res), "source_file")
-        except ConfigParser.NoSectionError:
-            prj.config.add_section("%s.%s" % (proj, res))
-        except ConfigParser.NoOptionError:
-            pass
-    finally:
-        prj.config.set("%s.%s" % (proj, res), "source_file",
-           path_to_file)
-        prj.config.set("%s.%s" % (proj, res), "source_lang",
-            lang)
-
-    prj.save()
-
-
-def _set_translation(path_to_tx, resource, lang, path_to_file):
-    """Reusable method to set translation file."""
-
-    proj, res = resource.split('.')
-    if not project or not resource:
-        raise Exception("\"%s\" is not a valid resource identifier. It should"
-            " be in the following format project_slug.resource_slug." %
-            resource)
-
-    try:
-        _go_to_dir(path_to_tx)
-    except UnInitializedError, e:
-        utils.logger.error(e)
-        return
-
-    # Warn the user if the file doesn't exist
-    if not os.path.exists(path_to_file):
-        logger.info("Warning: File '%s' doesn't exist." % path_to_file)
-
-    # instantiate the project.Project
-    prj = project.Project(path_to_tx)
-    root_dir = os.path.abspath(path_to_tx)
-
-    if root_dir not in os.path.normpath(os.path.abspath(path_to_file)):
-        raise Exception("File must be under the project root directory.")
-
-    if lang ==  prj.config.get("%s.%s" % (proj, res), "source_lang"):
-        raise Exception("tx: You cannot set translation file for the source language."
-            " Source languages contain the strings which will be translated!")
-
-    logger.info("Updating translations for resource %s ( %s -> %s )." % (resource,
-        lang, path_to_file))
-    path_to_file = relpath(path_to_file, root_dir)
-    prj.config.set("%s.%s" % (proj, res), "trans.%s" % lang,
-        path_to_file)
-
-    prj.save()
-
-
-def cmd_status(argv, path_to_tx):
-    "Print status of current project"
-    parser = status_parser()
-    (options, args) = parser.parse_args(argv)
-    resources = parse_csv_option(options.resources)
-    prj = project.Project(path_to_tx)
-    resources = prj.get_chosen_resources(resources)
-    resources_num = len(resources)
-    for idx, res in enumerate(resources):
-        p, r = res.split('.')
-        logger.info("%s -> %s (%s of %s)" % (p, r, idx + 1, resources_num))
-        logger.info("Translation Files:")
-        slang = prj.get_resource_option(res, 'source_lang')
-        sfile = prj.get_resource_option(res, 'source_file') or "N/A"
-        lang_map = prj.get_resource_lang_mapping(res)
-        logger.info(" - %s: %s (%s)" % (utils.color_text(slang, "RED"),
-            sfile, utils.color_text("source", "YELLOW")))
-        files = prj.get_resource_files(res)
-        fkeys = files.keys()
-        fkeys.sort()
-        for lang in fkeys:
-            local_lang = lang
-            if lang in lang_map.values():
-                local_lang = lang_map.flip[lang]
-            logger.info(" - %s: %s" % (utils.color_text(local_lang, "RED"),
-                files[lang]))
-        logger.info("")
-
-
-def cmd_help(argv, path_to_tx):
-    """List all available commands"""
-    parser = help_parser()
-    (options, args) = parser.parse_args(argv)
-    if len(args) > 1:
-        parser.error("Multiple arguments received. Exiting...")
-
-    # Get all commands
-    fns = utils.discover_commands()
-
-    # Print help for specific command
-    if len(args) == 1:
-        try:
-            fns[argv[0]](['--help'], path_to_tx)
-        except KeyError:
-            utils.logger.error("Command %s not found" % argv[0])
-    # or print summary of all commands
-
-    # the code below will only be executed if the KeyError exception is thrown
-    # becuase in all other cases the function called with --help will exit
-    # instead of return here
-    keys = fns.keys()
-    keys.sort()
-
-    logger.info("Transifex command line client.\n")
-    logger.info("Available commands are:")
-    for key in keys:
-        logger.info("  %-15s\t%s" % (key, fns[key].func_doc))
-    logger.info("\nFor more information run %s command --help" % sys.argv[0])
-
-
-def cmd_delete(argv, path_to_tx):
-    "Delete an accessible resource or translation in a remote server."
-    parser = delete_parser()
-    (options, args) = parser.parse_args(argv)
-    languages = parse_csv_option(options.languages)
-    resources = parse_csv_option(options.resources)
-    skip = options.skip_errors
-    force = options.force_delete
-    prj = project.Project(path_to_tx)
-    prj.delete(resources, languages, skip, force)
-    logger.info("Done.")
-
-
-def _go_to_dir(path):
-    """Change the current working directory to the directory specified as
-    argument.
-
-    Args:
-        path: The path to chdor to.
-    Raises:
-        UnInitializedError, in case the directory has not been initialized.
-    """
-    if path is None:
-        raise UnInitializedError(
-            "Directory has not been initialzied. "
-            "Did you forget to run 'tx init' first?"
-        )
-    os.chdir(path)
-
-
-def _set_minimum_perc(resource, value, path_to_tx):
-    """Set the minimum percentage in the .tx/config file."""
-    args = (resource, 'minimum_perc', value, path_to_tx, 'set_min_perc')
-    _set_project_option(*args)
-
-
-def _set_mode(resource, value, path_to_tx):
-    """Set the mode in the .tx/config file."""
-    args = (resource, 'mode', value, path_to_tx, 'set_default_mode')
-    _set_project_option(*args)
-
-
-def _set_type(resource, value, path_to_tx):
-    """Set the i18n type in the .tx/config file."""
-    args = (resource, 'type', value, path_to_tx, 'set_i18n_type')
-    _set_project_option(*args)
-
-
-def _set_project_option(resource, name, value, path_to_tx, func_name):
-    """Save the option to the project config file."""
-    if value is None:
-        return
-    if not resource:
-        logger.debug("Setting the %s for all resources." % name)
-        resources = []
-    else:
-        logger.debug("Setting the %s for resource %s." % (name, resource))
-        resources = [resource, ]
-    prj = project.Project(path_to_tx)
-    getattr(prj, func_name)(resources, value)
-    prj.save()
diff --git a/third_party/transifex-client/txclib/config.py b/third_party/transifex-client/txclib/config.py
deleted file mode 100644 (file)
index a9d055f..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-import ConfigParser
-
-
-class OrderedRawConfigParser( ConfigParser.RawConfigParser ):
-    """
-    Overload standard Class ConfigParser.RawConfigParser
-    """
-    def write(self, fp):
-        """Write an .ini-format representation of the configuration state."""
-        if self._defaults:
-            fp.write("[%s]\n" % DEFAULTSECT)
-            for key in sorted( self._defaults ):
-                fp.write( "%s = %s\n" % (key, str( self._defaults[ key ]
-                    ).replace('\n', '\n\t')) )
-            fp.write("\n")
-        for section in self._sections:
-            fp.write("[%s]\n" % section)
-            for key in sorted( self._sections[section] ):
-                if key != "__name__":
-                    fp.write("%s = %s\n" %
-                        (key, str( self._sections[section][ key ]
-                        ).replace('\n', '\n\t')))
-            fp.write("\n")
-
-    optionxform = str
-
-
-_NOTFOUND = object()
-
-
-class Flipdict(dict):
-    """An injective (one-to-one) python dict.  Ensures that each key maps
-    to a unique value, and each value maps back to that same key.
-
-    Code mostly taken from here:
-    http://code.activestate.com/recipes/576968-flipdict-python-dict-that-also-maintains-a-one-to-/
-    """
-
-    def __init__(self, *args, **kw):
-        self._flip = dict.__new__(self.__class__)
-        setattr(self._flip, "_flip", self)
-        for key, val in dict(*args, **kw).iteritems():
-            self[key] = val
-
-    @property
-    def flip(self):
-        """The inverse mapping."""
-        return self._flip
-
-    def __repr__(self):
-        return "%s(%r)" % (self.__class__.__name__, dict(self))
-
-    __str__ = __repr__
-
-    def copy(self):
-        return self.__class__(self)
-
-    @classmethod
-    def fromkeys(cls, keys, value=None):
-        return cls(dict.fromkeys(keys, value))
-
-    def __setitem__(self, key, val):
-        k = self._flip.get(val, _NOTFOUND)
-        if not (k is _NOTFOUND or k==key):
-            raise KeyError('(key,val) would erase mapping for value %r' % val)
-
-        v = self.get(key, _NOTFOUND)
-        if v is not _NOTFOUND:
-            dict.__delitem__(self._flip, v)
-
-        dict.__setitem__(self,       key, val)
-        dict.__setitem__(self._flip, val, key)
-
-    def setdefault(self, key, default = None):
-        # Copied from python's UserDict.DictMixin code.
-        try:
-            return self[key]
-        except KeyError:
-            self[key] = default
-            return default
-
-    def update(self, other = None, **kwargs):
-        # Copied from python's UserDict.DictMixin code.
-        # Make progressively weaker assumptions about "other"
-        if other is None:
-            pass
-        elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
-            for k, v in other.iteritems():
-                self[k] = v
-        elif hasattr(other, 'keys'):
-            for k in other.keys():
-                self[k] = other[k]
-        else:
-            for k, v in other:
-                self[k] = v
-        if kwargs:
-            self.update(kwargs)
-
-    def __delitem__(self, key):
-        val = dict.pop(self, key)
-        dict.__delitem__(self._flip, val)
-
-    def pop(self, key, *args):
-        val = dict.pop(self, key, *args)
-        dict.__delitem__(self._flip, val)
-        return val
-
-    def popitem(self):
-        key, val = dict.popitem(self)
-        dict.__delitem__(self._flip, val)
-        return key, val
-
-    def clear(self):
-        dict.clear(self)
-        dict.clear(self._flip)
diff --git a/third_party/transifex-client/txclib/exceptions.py b/third_party/transifex-client/txclib/exceptions.py
deleted file mode 100644 (file)
index 8766a01..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Exception classes for the tx client.
-"""
-
-
-class UnInitializedError(Exception):
-    """The project directory has not been initialized."""
-
-
-class UnknownCommandError(Exception):
-    """The provided command is not supported."""
diff --git a/third_party/transifex-client/txclib/http_utils.py b/third_party/transifex-client/txclib/http_utils.py
deleted file mode 100644 (file)
index 3243149..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-HTTP-related utility functions.
-"""
-
-from __future__ import with_statement
-import gzip
-try:
-    import cStringIO as StringIO
-except ImportError:
-    import StringIO
-
-
-def _gzip_decode(gzip_data):
-    """
-    Unzip gzipped data and return them.
-
-    :param gzip_data: Gzipped data.
-    :returns: The actual data.
-    """
-    try:
-        gzip_data = StringIO.StringIO(gzip_data)
-        gzip_file = gzip.GzipFile(fileobj=gzip_data)
-        data = gzip_file.read()
-        return data
-    finally:
-        gzip_data.close()
-
-
-def http_response(response):
-    """
-    Return the response of a HTTP request.
-
-    If the response has been gzipped, gunzip it first.
-
-    :param response: The raw response of a HTTP request.
-    :returns: A response suitable to be used by clients.
-    """
-    metadata = response.info()
-    data = response.read()
-    response.close()
-    if metadata.get('content-encoding') == 'gzip':
-        return _gzip_decode(data)
-    else:
-        return data
diff --git a/third_party/transifex-client/txclib/log.py b/third_party/transifex-client/txclib/log.py
deleted file mode 100644 (file)
index 9baf322..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Add logging capabilities to tx-client.
-"""
-
-import sys
-import logging
-
-_logger = logging.getLogger('txclib')
-_logger.setLevel(logging.INFO)
-
-_formatter = logging.Formatter('%(message)s')
-
-_error_handler = logging.StreamHandler(sys.stderr)
-_error_handler.setLevel(logging.ERROR)
-_error_handler.setFormatter(_formatter)
-_logger.addHandler(_error_handler)
-
-_msg_handler = logging.StreamHandler(sys.stdout)
-_msg_handler.setLevel(logging.DEBUG)
-_msg_handler.setFormatter(_formatter)
-_msg_filter = logging.Filter()
-_msg_filter.filter = lambda r: r.levelno < logging.ERROR
-_msg_handler.addFilter(_msg_filter)
-_logger.addHandler(_msg_handler)
-
-logger = _logger
-
-
-def set_log_level(level):
-    """Set the level for the logger.
-
-    Args:
-        level: A string among DEBUG, INFO, WARNING, ERROR, CRITICAL.
-    """
-    logger.setLevel(getattr(logging, level))
diff --git a/third_party/transifex-client/txclib/parsers.py b/third_party/transifex-client/txclib/parsers.py
deleted file mode 100644 (file)
index fd3237d..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from optparse import OptionParser, OptionGroup
-
-
-class EpilogParser(OptionParser):
-    def format_epilog(self, formatter):
-        return self.epilog
-
-
-def delete_parser():
-    """Return the command-line parser for the delete command."""
-    usage = "usage: %prog [tx_options] delete OPTION [OPTIONS]"
-    description = (
-        "This command deletes translations for a resource in the remote server."
-    )
-    epilog = (
-        "\nExamples:\n"
-        " To delete a translation:\n  "
-        "$ tx delete -r project.resource -l <lang_code>\n\n"
-        " To delete a resource:\n  $ tx delete -r project.resource\n"
-    )
-    parser = EpilogParser(usage=usage, description=description, epilog=epilog)
-    parser.add_option(
-        "-r", "--resource", action="store", dest="resources", default=None,
-        help="Specify the resource you want to delete (defaults to all)"
-    )
-    parser.add_option(
-        "-l","--language", action="store", dest="languages",
-        default=None, help="Specify the translation you want to delete"
-    )
-    parser.add_option(
-        "--skip", action="store_true", dest="skip_errors", default=False,
-        help="Don't stop on errors."
-    )
-    parser.add_option(
-        "-f","--force", action="store_true", dest="force_delete",
-        default=False, help="Delete an entity forcefully."
-    )
-    return parser
-
-
-def help_parser():
-    """Return the command-line parser for the help command."""
-    usage="usage: %prog help command"
-    description="Lists all available commands in the transifex command"\
-        " client. If a command is specified, the help page of the specific"\
-        " command is displayed instead."
-
-    parser = OptionParser(usage=usage, description=description)
-    return parser
-
-
-def init_parser():
-    """Return the command-line parser for the init command."""
-    usage="usage: %prog [tx_options] init <path>"
-    description="This command initializes a new project for use with"\
-        " transifex. It is recommended to execute this command in the"\
-        " top level directory of your project so that you can include"\
-        " all files under it in transifex. If no path is provided, the"\
-        " current working dir will be used."
-    parser = OptionParser(usage=usage, description=description)
-    parser.add_option("--host", action="store", dest="host",
-        default=None, help="Specify a default Transifex host.")
-    parser.add_option("--user", action="store", dest="user",
-        default=None, help="Specify username for Transifex server.")
-    parser.add_option("--pass", action="store", dest="password",
-        default=None, help="Specify password for Transifex server.")
-    return parser
-
-
-def pull_parser():
-    """Return the command-line parser for the pull command."""
-    usage="usage: %prog [tx_options] pull [options]"
-    description="This command pulls all outstanding changes from the remote"\
-        " Transifex server to the local repository. By default, only the"\
-        " files that are watched by Transifex will be updated but if you"\
-        " want to fetch the translations for new languages as well, use the"\
-        " -a|--all option. (Note: new translations are saved in the .tx folder"\
-        " and require the user to manually rename them and add then in "\
-        " transifex using the set_translation command)."
-    parser = OptionParser(usage=usage,description=description)
-    parser.add_option("-l","--language", action="store", dest="languages",
-        default=[], help="Specify which translations you want to pull"
-        " (defaults to all)")
-    parser.add_option("-r","--resource", action="store", dest="resources",
-        default=[], help="Specify the resource for which you want to pull"
-        " the translations (defaults to all)")
-    parser.add_option("-a","--all", action="store_true", dest="fetchall",
-        default=False, help="Fetch all translation files from server (even new"
-        " ones)")
-    parser.add_option("-s","--source", action="store_true", dest="fetchsource",
-        default=False, help="Force the fetching of the source file (default:"
-        " False)")
-    parser.add_option("-f","--force", action="store_true", dest="force",
-        default=False, help="Force download of translations files.")
-    parser.add_option("--skip", action="store_true", dest="skip_errors",
-        default=False, help="Don't stop on errors. Useful when pushing many"
-        " files concurrently.")
-    parser.add_option("--disable-overwrite", action="store_false",
-        dest="overwrite", default=True,
-        help="By default transifex will fetch new translations files and"\
-            " replace existing ones. Use this flag if you want to disable"\
-            " this feature")
-    parser.add_option("--minimum-perc", action="store", type="int",
-        dest="minimum_perc", default=0,
-        help="Specify the minimum acceptable percentage of a translation "
-             "in order to download it.")
-    parser.add_option(
-        "--mode", action="store", dest="mode", help=(
-            "Specify the mode of the translation file to pull (e.g. "
-            "'reviewed'). See http://bit.ly/txcmod1 for available values."
-        )
-    )
-    return parser
-
-
-def push_parser():
-    """Return the command-line parser for the push command."""
-    usage="usage: %prog [tx_options] push [options]"
-    description="This command pushes all local files that have been added to"\
-        " Transifex to the remote server. All new translations are merged"\
-        " with existing ones and if a language doesn't exists then it gets"\
-        " created. If you want to push the source file as well (either"\
-        " because this is your first time running the client or because"\
-        " you just have updated with new entries), use the -f|--force option."\
-        " By default, this command will push all files which are watched by"\
-        " Transifex but you can filter this per resource or/and language."
-    parser = OptionParser(usage=usage, description=description)
-    parser.add_option("-l","--language", action="store", dest="languages",
-        default=None, help="Specify which translations you want to push"
-        " (defaults to all)")
-    parser.add_option("-r","--resource", action="store", dest="resources",
-        default=None, help="Specify the resource for which you want to push"
-        " the translations (defaults to all)")
-    parser.add_option("-f","--force", action="store_true", dest="force_creation",
-        default=False, help="Push source files without checking modification"
-        " times.")
-    parser.add_option("--skip", action="store_true", dest="skip_errors",
-        default=False, help="Don't stop on errors. Useful when pushing many"
-        " files concurrently.")
-    parser.add_option("-s", "--source", action="store_true", dest="push_source",
-        default=False, help="Push the source file to the server.")
-
-    parser.add_option("-t", "--translations", action="store_true", dest="push_translations",
-        default=False, help="Push the translation files to the server")
-    parser.add_option("--no-interactive", action="store_true", dest="no_interactive",
-        default=False, help="Don't require user input when forcing a push.")
-    return parser
-
-
-def set_parser():
-    """Return the command-line parser for the set command."""
-    usage="usage: %prog [tx_options] set [options] [args]"
-    description="This command can be used to create a mapping between files"\
-        " and projects either using local files or using files from a remote"\
-        " Transifex server."
-    epilog="\nExamples:\n"\
-        " To set the source file:\n  $ tx set -r project.resource --source -l en <file>\n\n"\
-        " To set a single translation file:\n  $ tx set -r project.resource -l de <file>\n\n"\
-        " To automatically detect and assign the source files and translations:\n"\
-        "  $ tx set --auto-local -r project.resource 'expr' --source-lang en\n\n"\
-        " To set a specific file as a source and auto detect translations:\n"\
-        "  $ tx set --auto-local -r project.resource 'expr' --source-lang en"\
-        " --source-file <file>\n\n"\
-        " To set a remote release/resource/project:\n"\
-        "  $ tx set --auto-remote <transifex-url>\n"
-    parser = EpilogParser(usage=usage, description=description, epilog=epilog)
-    parser.add_option("--auto-local", action="store_true", dest="local",
-        default=False, help="Used when auto configuring local project.")
-    parser.add_option("--auto-remote", action="store_true", dest="remote",
-        default=False, help="Used when adding remote files from Transifex"
-        " server.")
-    parser.add_option("-r","--resource", action="store", dest="resource",
-        default=None, help="Specify the slug of the resource that you're"
-            " setting up (This must be in the following format:"
-            " `project_slug.resource_slug`).")
-    parser.add_option(
-        "--source", action="store_true", dest="is_source", default=False,
-        help=(
-            "Specify that the given file is a source file "
-            "[doesn't work with the --auto-* commands]."
-        )
-    )
-    parser.add_option("-l","--language", action="store", dest="language",
-        default=None, help="Specify which translations you want to pull"
-        " [doesn't work with the --auto-* commands].")
-    parser.add_option("-t", "--type", action="store", dest="i18n_type",
-        help=(
-            "Specify the i18n type of the resource(s). This is only needed, if "
-            "the resource(s) does not exist yet in Transifex. For a list of "
-            "available i18n types, see "
-            "http://help.transifex.com/features/formats.html"
-        )
-    )
-    parser.add_option("--minimum-perc", action="store", dest="minimum_perc",
-        help=(
-            "Specify the minimum acceptable percentage of a translation "
-            "in order to download it."
-        )
-    )
-    parser.add_option(
-        "--mode", action="store", dest="mode", help=(
-            "Specify the mode of the translation file to pull (e.g. "
-            "'reviewed'). See http://help.transifex.com/features/client/"
-            "index.html#defining-the-mode-of-the-translated-file for the"
-            "available values."
-        )
-    )
-    group = OptionGroup(parser, "Extended options", "These options can only be"
-        " used with the --auto-local command.")
-    group.add_option("-s","--source-language", action="store",
-        dest="source_language",
-        default=None, help="Specify the source language of a resource"
-        " [requires --auto-local].")
-    group.add_option("-f","--source-file", action="store", dest="source_file",
-        default=None, help="Specify the source file of a resource [requires"
-        " --auto-local].")
-    group.add_option("--execute", action="store_true", dest="execute",
-        default=False, help="Execute commands [requires --auto-local].")
-    parser.add_option_group(group)
-    return parser
-
-
-def status_parser():
-    """Return the command-line parser for the status command."""
-    usage="usage: %prog [tx_options] status [options]"
-    description="Prints the status of the current project by reading the"\
-        " data in the configuration file."
-    parser = OptionParser(usage=usage,description=description)
-    parser.add_option("-r","--resource", action="store", dest="resources",
-        default=[], help="Specify resources")
-    return parser
-
-
-def parse_csv_option(option):
-    """Return a list out of the comma-separated option or an empty list."""
-    if option:
-        return option.split(',')
-    else:
-        return []
diff --git a/third_party/transifex-client/txclib/processors.py b/third_party/transifex-client/txclib/processors.py
deleted file mode 100644 (file)
index dc3a73f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Module for API-related calls.
-"""
-
-import urlparse
-
-
-def hostname_tld_migration(hostname):
-    """
-    Migrate transifex.net to transifex.com.
-
-    :param hostname: The hostname to migrate (if needed).
-    :returns: A hostname with the transifex.com domain (if needed).
-    """
-    parts = urlparse.urlparse(hostname)
-    if parts.hostname.endswith('transifex.net'):
-        hostname = hostname.replace('transifex.net', 'transifex.com', 1)
-    return hostname
-
-
-def hostname_ssl_migration(hostname):
-    """
-    Migrate Transifex hostnames to use HTTPS.
-
-    :param hostname: The hostname to migrate (if needed).
-    :returns: A https hostname (if needed).
-    """
-    parts = urlparse.urlparse(hostname)
-    is_transifex = (
-        parts.hostname[-14:-3] == '.transifex.' or
-        parts.hostname == 'transifex.net' or
-        parts.hostname == 'transifex.com'
-    )
-    is_https = parts.scheme == 'https'
-    if is_transifex and not is_https:
-        if not parts.scheme:
-            hostname = 'https:' + hostname
-        else:
-            hostname = hostname.replace(parts.scheme, 'https', 1)
-    return hostname
-
-
-def visit_hostname(hostname):
-    """
-    Have a chance to visit a hostname before actually using it.
-
-    :param hostname: The original hostname.
-    :returns: The hostname with the necessary changes.
-    """
-    for processor in [hostname_ssl_migration, hostname_tld_migration, ]:
-        hostname = processor(hostname)
-    return hostname
diff --git a/third_party/transifex-client/txclib/project.py b/third_party/transifex-client/txclib/project.py
deleted file mode 100644 (file)
index 88bb46b..0000000
+++ /dev/null
@@ -1,1233 +0,0 @@
-# -*- coding: utf-8 -*-
-import base64
-import copy
-import getpass
-import os
-import re
-import fnmatch
-import urllib2
-import datetime, time
-import ConfigParser
-
-from txclib.web import *
-from txclib.utils import *
-from txclib.urls import API_URLS
-from txclib.config import OrderedRawConfigParser, Flipdict
-from txclib.log import logger
-from txclib.http_utils import http_response
-from txclib.processors import visit_hostname
-
-
-class ProjectNotInit(Exception):
-    pass
-
-
-class Project(object):
-    """
-    Represents an association between the local and remote project instances.
-    """
-
-    def __init__(self, path_to_tx=None, init=True):
-        """
-        Initialize the Project attributes.
-        """
-        if init:
-            self._init(path_to_tx)
-
-    def _init(self, path_to_tx=None):
-        instructions = "Run 'tx init' to initialize your project first!"
-        try:
-            self.root = self._get_tx_dir_path(path_to_tx)
-            self.config_file = self._get_config_file_path(self.root)
-            self.config = self._read_config_file(self.config_file)
-            self.txrc_file = self._get_transifex_file()
-            self.txrc = self._get_transifex_config(self.txrc_file)
-        except ProjectNotInit, e:
-            logger.error('\n'.join([unicode(e), instructions]))
-            raise
-
-    def _get_config_file_path(self, root_path):
-        """Check the .tx/config file exists."""
-        config_file = os.path.join(root_path, ".tx", "config")
-        logger.debug("Config file is %s" % config_file)
-        if not os.path.exists(config_file):
-            msg = "Cannot find the config file (.tx/config)!"
-            raise ProjectNotInit(msg)
-        return config_file
-
-    def _get_tx_dir_path(self, path_to_tx):
-        """Check the .tx directory exists."""
-        root_path = path_to_tx or find_dot_tx()
-        logger.debug("Path to tx is %s." % root_path)
-        if not root_path:
-            msg = "Cannot find any .tx directory!"
-            raise ProjectNotInit(msg)
-        return root_path
-
-    def _read_config_file(self, config_file):
-        """Parse the config file and return its contents."""
-        config = OrderedRawConfigParser()
-        try:
-            config.read(config_file)
-        except Exception, err:
-            msg = "Cannot open/parse .tx/config file: %s" % err
-            raise ProjectNotInit(msg)
-        return config
-
-    def _get_transifex_config(self, txrc_file):
-        """Read the configuration from the .transifexrc file."""
-        txrc = OrderedRawConfigParser()
-        try:
-            txrc.read(txrc_file)
-        except Exception, e:
-            msg = "Cannot read global configuration file: %s" % e
-            raise ProjectNotInit(msg)
-        self._migrate_txrc_file(txrc)
-        return txrc
-
-    def _migrate_txrc_file(self, txrc):
-        """Migrate the txrc file, if needed."""
-        for section in txrc.sections():
-            orig_hostname = txrc.get(section, 'hostname')
-            hostname = visit_hostname(orig_hostname)
-            if hostname != orig_hostname:
-                msg = "Hostname %s should be changed to %s."
-                logger.info(msg % (orig_hostname, hostname))
-                if (sys.stdin.isatty() and sys.stdout.isatty() and
-                    confirm('Change it now? ', default=True)):
-                    txrc.set(section, 'hostname', hostname)
-                    msg = 'Hostname changed'
-                    logger.info(msg)
-                else:
-                    hostname = orig_hostname
-            self._save_txrc_file(txrc)
-        return txrc
-
-    def _get_transifex_file(self, directory=None):
-        """Fetch the path of the .transifexrc file.
-
-        It is in the home directory ofthe user by default.
-        """
-        if directory is None:
-            directory = os.path.expanduser('~')
-        txrc_file = os.path.join(directory, ".transifexrc")
-        logger.debug(".transifexrc file is at %s" % directory)
-        if not os.path.exists(txrc_file):
-            msg = "No authentication data found."
-            logger.info(msg)
-            mask = os.umask(077)
-            open(txrc_file, 'w').close()
-            os.umask(mask)
-        return txrc_file
-
-    def validate_config(self):
-        """
-        To ensure the json structure is correctly formed.
-        """
-        pass
-
-    def getset_host_credentials(self, host, user=None, password=None):
-        """
-        Read .transifexrc and report user,pass for a specific host else ask the
-        user for input.
-        """
-        try:
-            username = self.txrc.get(host, 'username')
-            passwd = self.txrc.get(host, 'password')
-        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
-            logger.info("No entry found for host %s. Creating..." % host)
-            username = user or raw_input("Please enter your transifex username: ")
-            while (not username):
-                username = raw_input("Please enter your transifex username: ")
-            passwd = password
-            while (not passwd):
-                passwd = getpass.getpass()
-
-            logger.info("Updating %s file..." % self.txrc_file)
-            self.txrc.add_section(host)
-            self.txrc.set(host, 'username', username)
-            self.txrc.set(host, 'password', passwd)
-            self.txrc.set(host, 'token', '')
-            self.txrc.set(host, 'hostname', host)
-
-        return username, passwd
-
-    def set_remote_resource(self, resource, source_lang, i18n_type, host,
-            file_filter="translations<sep>%(proj)s.%(res)s<sep><lang>.%(extension)s"):
-        """
-        Method to handle the add/conf of a remote resource.
-        """
-        if not self.config.has_section(resource):
-            self.config.add_section(resource)
-
-        p_slug, r_slug = resource.split('.')
-        file_filter = file_filter.replace("<sep>", r"%s" % os.path.sep)
-        self.url_info = {
-            'host': host,
-            'project': p_slug,
-            'resource': r_slug
-        }
-        extension = self._extension_for(i18n_type)[1:]
-
-        self.config.set(resource, 'source_lang', source_lang)
-        self.config.set(
-            resource, 'file_filter',
-            file_filter % {'proj': p_slug, 'res': r_slug, 'extension': extension}
-        )
-        if host != self.config.get('main', 'host'):
-            self.config.set(resource, 'host', host)
-
-    def get_resource_host(self, resource):
-        """
-        Returns the host that the resource is configured to use. If there is no
-        such option we return the default one
-        """
-        if self.config.has_option(resource, 'host'):
-            return self.config.get(resource, 'host')
-        return self.config.get('main', 'host')
-
-    def get_resource_lang_mapping(self, resource):
-        """
-        Get language mappings for a specific resource.
-        """
-        lang_map = Flipdict()
-        try:
-            args = self.config.get("main", "lang_map")
-            for arg in args.replace(' ', '').split(','):
-                k,v = arg.split(":")
-                lang_map.update({k:v})
-        except ConfigParser.NoOptionError:
-            pass
-        except (ValueError, KeyError):
-            raise Exception("Your lang map configuration is not correct.")
-
-        if self.config.has_section(resource):
-            res_lang_map = Flipdict()
-            try:
-                args = self.config.get(resource, "lang_map")
-                for arg in args.replace(' ', '').split(','):
-                    k,v = arg.split(":")
-                    res_lang_map.update({k:v})
-            except ConfigParser.NoOptionError:
-                pass
-            except (ValueError, KeyError):
-                raise Exception("Your lang map configuration is not correct.")
-
-        # merge the lang maps and return result
-        lang_map.update(res_lang_map)
-
-        return lang_map
-
-
-    def get_resource_files(self, resource):
-        """
-        Get a dict for all files assigned to a resource. First we calculate the
-        files matching the file expression and then we apply all translation
-        excpetions. The resulting dict will be in this format:
-
-        { 'en': 'path/foo/en/bar.po', 'de': 'path/foo/de/bar.po', 'es': 'path/exceptions/es.po'}
-
-        NOTE: All paths are relative to the root of the project
-        """
-        tr_files = {}
-        if self.config.has_section(resource):
-            try:
-                file_filter = self.config.get(resource, "file_filter")
-            except ConfigParser.NoOptionError:
-                file_filter = "$^"
-            source_lang = self.config.get(resource, "source_lang")
-            source_file = self.get_resource_option(resource, 'source_file') or None
-            expr_re = regex_from_filefilter(file_filter, self.root)
-            expr_rec = re.compile(expr_re)
-            for root, dirs, files in os.walk(self.root):
-                for f in files:
-                    f_path = os.path.abspath(os.path.join(root, f))
-                    match = expr_rec.match(f_path)
-                    if match:
-                        lang = match.group(1)
-                        if lang != source_lang:
-                            f_path = relpath(f_path, self.root)
-                            if f_path != source_file:
-                                tr_files.update({lang: f_path})
-
-            for (name, value) in self.config.items(resource):
-                if name.startswith("trans."):
-                    lang = name.split('.')[1]
-                    # delete language which has same file
-                    if value in tr_files.values():
-                        keys = []
-                        for k, v in tr_files.iteritems():
-                            if v == value:
-                                keys.append(k)
-                        if len(keys) == 1:
-                            del tr_files[keys[0]]
-                        else:
-                            raise Exception("Your configuration seems wrong."\
-                                " You have multiple languages pointing to"\
-                                " the same file.")
-                    # Add language with correct file
-                    tr_files.update({lang:value})
-
-            return tr_files
-
-        return None
-
-    def get_resource_option(self, resource, option):
-        """
-        Return the requested option for a specific resource
-
-        If there is no such option, we return None
-        """
-
-        if self.config.has_section(resource):
-            if self.config.has_option(resource, option):
-                return self.config.get(resource, option)
-        return None
-
-    def get_resource_list(self, project=None):
-        """
-        Parse config file and return tuples with the following format
-
-        [ (project_slug, resource_slug), (..., ...)]
-        """
-
-        resource_list= []
-        for r in self.config.sections():
-            if r == 'main':
-                continue
-            p_slug, r_slug = r.split('.', 1)
-            if project and p_slug != project:
-                continue
-            resource_list.append(r)
-
-        return resource_list
-
-    def save(self):
-        """
-        Store the config dictionary in the .tx/config file of the project.
-        """
-        self._save_tx_config()
-        self._save_txrc_file()
-
-    def _save_tx_config(self, config=None):
-        """Save the local config file."""
-        if config is None:
-            config = self.config
-        fh = open(self.config_file,"w")
-        config.write(fh)
-        fh.close()
-
-    def _save_txrc_file(self, txrc=None):
-        """Save the .transifexrc file."""
-        if txrc is None:
-            txrc = self.txrc
-        mask = os.umask(077)
-        fh = open(self.txrc_file, 'w')
-        txrc.write(fh)
-        fh.close()
-        os.umask(mask)
-
-    def get_full_path(self, relpath):
-        if relpath[0] == "/":
-            return relpath
-        else:
-            return os.path.join(self.root, relpath)
-
-    def pull(self, languages=[], resources=[], overwrite=True, fetchall=False,
-        fetchsource=False, force=False, skip=False, minimum_perc=0, mode=None):
-        """Pull all translations file from transifex server."""
-        self.minimum_perc = minimum_perc
-        resource_list = self.get_chosen_resources(resources)
-
-        if mode == 'reviewed':
-            url = 'pull_reviewed_file'
-        elif mode == 'translator':
-            url = 'pull_translator_file'
-        elif mode == 'developer':
-            url = 'pull_developer_file'
-        else:
-            url = 'pull_file'
-
-        for resource in resource_list:
-            logger.debug("Handling resource %s" % resource)
-            self.resource = resource
-            project_slug, resource_slug = resource.split('.')
-            files = self.get_resource_files(resource)
-            slang = self.get_resource_option(resource, 'source_lang')
-            sfile = self.get_resource_option(resource, 'source_file')
-            lang_map = self.get_resource_lang_mapping(resource)
-            host = self.get_resource_host(resource)
-            logger.debug("Language mapping is: %s" % lang_map)
-            if mode is None:
-                mode = self._get_option(resource, 'mode')
-            self.url_info = {
-                'host': host,
-                'project': project_slug,
-                'resource': resource_slug
-            }
-            logger.debug("URL data are: %s" % self.url_info)
-
-            stats = self._get_stats_for_resource()
-
-
-            try:
-                file_filter = self.config.get(resource, 'file_filter')
-            except ConfigParser.NoOptionError:
-                file_filter = None
-
-            # Pull source file
-            pull_languages = set([])
-            new_translations = set([])
-
-            if fetchall:
-                new_translations = self._new_translations_to_add(
-                    files, slang, lang_map, stats, force
-                )
-                if new_translations:
-                    msg = "New translations found for the following languages: %s"
-                    logger.info(msg % ', '.join(new_translations))
-
-            existing, new = self._languages_to_pull(
-                languages, files, lang_map, stats, force
-            )
-            pull_languages |= existing
-            new_translations |= new
-            logger.debug("Adding to new translations: %s" % new)
-
-            if fetchsource:
-                if sfile and slang not in pull_languages:
-                    pull_languages.add(slang)
-                elif slang not in new_translations:
-                    new_translations.add(slang)
-
-            if pull_languages:
-                logger.debug("Pulling languages for: %s" % pull_languages)
-                msg = "Pulling translations for resource %s (source: %s)"
-                logger.info(msg % (resource, sfile))
-
-            for lang in pull_languages:
-                local_lang = lang
-                if lang in lang_map.values():
-                    remote_lang = lang_map.flip[lang]
-                else:
-                    remote_lang = lang
-                if languages and lang not in pull_languages:
-                    logger.debug("Skipping language %s" % lang)
-                    continue
-                if lang != slang:
-                    local_file = files.get(lang, None) or files[lang_map[lang]]
-                else:
-                    local_file = sfile
-                logger.debug("Using file %s" % local_file)
-
-                kwargs = {
-                    'lang': remote_lang,
-                    'stats': stats,
-                    'local_file': local_file,
-                    'force': force,
-                    'mode': mode,
-                }
-                if not self._should_update_translation(**kwargs):
-                    msg = "Skipping '%s' translation (file: %s)."
-                    logger.info(
-                        msg % (color_text(remote_lang, "RED"), local_file)
-                    )
-                    continue
-
-                if not overwrite:
-                    local_file = ("%s.new" % local_file)
-                logger.warning(
-                    " -> %s: %s" % (color_text(remote_lang, "RED"), local_file)
-                )
-                try:
-                    r = self.do_url_request(url, language=remote_lang)
-                except Exception,e:
-                    if not skip:
-                        raise e
-                    else:
-                        logger.error(e)
-                        continue
-                base_dir = os.path.split(local_file)[0]
-                mkdir_p(base_dir)
-                fd = open(local_file, 'wb')
-                fd.write(r)
-                fd.close()
-
-            if new_translations:
-                msg = "Pulling new translations for resource %s (source: %s)"
-                logger.info(msg % (resource, sfile))
-                for lang in new_translations:
-                    if lang in lang_map.keys():
-                        local_lang = lang_map[lang]
-                    else:
-                        local_lang = lang
-                    remote_lang = lang
-                    if file_filter:
-                        local_file = relpath(os.path.join(self.root,
-                            file_filter.replace('<lang>', local_lang)), os.curdir)
-                    else:
-                        trans_dir = os.path.join(self.root, ".tx", resource)
-                        if not os.path.exists(trans_dir):
-                            os.mkdir(trans_dir)
-                        local_file = relpath(os.path.join(trans_dir, '%s_translation' %
-                            local_lang, os.curdir))
-
-                    if lang != slang:
-                        satisfies_min = self._satisfies_min_translated(
-                            stats[remote_lang], mode
-                        )
-                        if not satisfies_min:
-                            msg = "Skipping language %s due to used options."
-                            logger.info(msg % lang)
-                            continue
-                    logger.warning(
-                        " -> %s: %s" % (color_text(remote_lang, "RED"), local_file)
-                    )
-                    r = self.do_url_request(url, language=remote_lang)
-
-                    base_dir = os.path.split(local_file)[0]
-                    mkdir_p(base_dir)
-                    fd = open(local_file, 'wb')
-                    fd.write(r)
-                    fd.close()
-
-    def push(self, source=False, translations=False, force=False, resources=[], languages=[],
-        skip=False, no_interactive=False):
-        """
-        Push all the resources
-        """
-        resource_list = self.get_chosen_resources(resources)
-        self.skip = skip
-        self.force = force
-        for resource in resource_list:
-            push_languages = []
-            project_slug, resource_slug = resource.split('.')
-            files = self.get_resource_files(resource)
-            slang = self.get_resource_option(resource, 'source_lang')
-            sfile = self.get_resource_option(resource, 'source_file')
-            lang_map = self.get_resource_lang_mapping(resource)
-            host = self.get_resource_host(resource)
-            logger.debug("Language mapping is: %s" % lang_map)
-            logger.debug("Using host %s" % host)
-            self.url_info = {
-                'host': host,
-                'project': project_slug,
-                'resource': resource_slug
-            }
-
-            logger.info("Pushing translations for resource %s:" % resource)
-
-            stats = self._get_stats_for_resource()
-
-            if force and not no_interactive:
-                answer = raw_input("Warning: By using --force, the uploaded"
-                    " files will overwrite remote translations, even if they"
-                    " are newer than your uploaded files.\nAre you sure you"
-                    " want to continue? [y/N] ")
-
-                if not answer in ["", 'Y', 'y', "yes", 'YES']:
-                    return
-
-            if source:
-                if sfile == None:
-                    logger.error("You don't seem to have a proper source file"
-                        " mapping for resource %s. Try without the --source"
-                        " option or set a source file first and then try again." %
-                        resource)
-                    continue
-                # Push source file
-                try:
-                    logger.warning("Pushing source file (%s)" % sfile)
-                    if not self._resource_exists(stats):
-                        logger.info("Resource does not exist.  Creating...")
-                        fileinfo = "%s;%s" % (resource_slug, slang)
-                        filename = self.get_full_path(sfile)
-                        self._create_resource(resource, project_slug, fileinfo, filename)
-                    self.do_url_request(
-                        'push_source', multipart=True, method="PUT",
-                        files=[(
-                                "%s;%s" % (resource_slug, slang)
-                                , self.get_full_path(sfile)
-                        )],
-                    )
-                except Exception, e:
-                    if not skip:
-                        raise
-                    else:
-                        logger.error(e)
-            else:
-                try:
-                    self.do_url_request('resource_details')
-                except Exception, e:
-                    code = getattr(e, 'code', None)
-                    if code == 404:
-                        msg = "Resource %s doesn't exist on the server."
-                        logger.error(msg % resource)
-                        continue
-
-            if translations:
-                # Check if given language codes exist
-                if not languages:
-                    push_languages = files.keys()
-                else:
-                    push_languages = []
-                    f_langs = files.keys()
-                    for l in languages:
-                        if l in lang_map.keys():
-                            l = lang_map[l]
-                        push_languages.append(l)
-                        if l not in f_langs:
-                            msg = "Warning: No mapping found for language code '%s'."
-                            logger.error(msg % color_text(l,"RED"))
-                logger.debug("Languages to push are %s" % push_languages)
-
-                # Push translation files one by one
-                for lang in push_languages:
-                    local_lang = lang
-                    if lang in lang_map.values():
-                        remote_lang = lang_map.flip[lang]
-                    else:
-                        remote_lang = lang
-
-                    local_file = files[local_lang]
-
-                    kwargs = {
-                        'lang': remote_lang,
-                        'stats': stats,
-                        'local_file': local_file,
-                        'force': force,
-                    }
-                    if not self._should_push_translation(**kwargs):
-                        msg = "Skipping '%s' translation (file: %s)."
-                        logger.info(msg % (color_text(lang, "RED"), local_file))
-                        continue
-
-                    msg = "Pushing '%s' translations (file: %s)"
-                    logger.warning(
-                         msg % (color_text(remote_lang, "RED"), local_file)
-                    )
-                    try:
-                        self.do_url_request(
-                            'push_translation', multipart=True, method='PUT',
-                            files=[(
-                                    "%s;%s" % (resource_slug, remote_lang),
-                                    self.get_full_path(local_file)
-                            )], language=remote_lang
-                        )
-                        logger.debug("Translation %s pushed." % remote_lang)
-                    except Exception, e:
-                        if not skip:
-                            raise e
-                        else:
-                            logger.error(e)
-
-    def delete(self, resources=[], languages=[], skip=False, force=False):
-        """Delete translations."""
-        resource_list = self.get_chosen_resources(resources)
-        self.skip = skip
-        self.force = force
-
-        if not languages:
-            delete_func = self._delete_resource
-        else:
-            delete_func = self._delete_translations
-
-        for resource in resource_list:
-            project_slug, resource_slug = resource.split('.')
-            host = self.get_resource_host(resource)
-            self.url_info = {
-                'host': host,
-                'project': project_slug,
-                'resource': resource_slug
-            }
-            logger.debug("URL data are: %s" % self.url_info)
-            project_details = parse_json(
-                self.do_url_request('project_details', project=self)
-            )
-            teams = project_details['teams']
-            stats = self._get_stats_for_resource()
-            delete_func(project_details, resource, stats, languages)
-
-    def _delete_resource(self, project_details, resource, stats, *args):
-        """Delete a resource from Transifex."""
-        project_slug, resource_slug = resource.split('.')
-        project_resource_slugs = [
-            r['slug'] for r in project_details['resources']
-        ]
-        logger.info("Deleting resource %s:" % resource)
-        if resource_slug not in project_resource_slugs:
-            if not self.skip:
-                msg = "Skipping: %s : Resource does not exist."
-                logger.info(msg % resource)
-            return
-        if not self.force:
-            slang = self.get_resource_option(resource, 'source_lang')
-            for language in stats:
-                if language == slang:
-                    continue
-                if int(stats[language]['translated_entities']) > 0:
-                    msg = (
-                        "Skipping: %s : Unable to delete resource because it "
-                        "has a not empty %s translation.\nPlease use -f or "
-                        "--force option to delete this resource."
-                    )
-                    logger.info(msg % (resource, language))
-                    return
-        try:
-            self.do_url_request('delete_resource', method="DELETE")
-            self.config.remove_section(resource)
-            self.save()
-            msg = "Deleted resource %s of project %s."
-            logger.info(msg % (resource_slug, project_slug))
-        except Exception, e:
-            msg = "Unable to delete resource %s of project %s."
-            logger.error(msg % (resource_slug, project_slug))
-            if not self.skip:
-                raise
-
-    def _delete_translations(self, project_details, resource, stats, languages):
-        """Delete the specified translations for the specified resource."""
-        logger.info("Deleting translations from resource %s:" % resource)
-        for language in languages:
-            self._delete_translation(project_details, resource, stats, language)
-
-    def _delete_translation(self, project_details, resource, stats, language):
-        """Delete a specific translation from the specified resource."""
-        project_slug, resource_slug = resource.split('.')
-        if language not in stats:
-            if not self.skip:
-                msg = "Skipping %s: Translation does not exist."
-                logger.warning(msg % (language))
-            return
-        if not self.force:
-            teams = project_details['teams']
-            if language in teams:
-                msg = (
-                    "Skipping %s: Unable to delete translation because it is "
-                    "associated with a team.\nPlease use -f or --force option "
-                    "to delete this translation."
-                )
-                logger.warning(msg % language)
-                return
-            if int(stats[language]['translated_entities']) > 0:
-                msg = (
-                    "Skipping %s: Unable to delete translation because it "
-                    "is not empty.\nPlease use -f or --force option to delete "
-                    "this translation."
-                )
-                logger.warning(msg % language)
-                return
-        try:
-            self.do_url_request(
-                'delete_translation', language=language, method="DELETE"
-            )
-            msg = "Deleted language %s from resource %s of project %s."
-            logger.info(msg % (language, resource_slug, project_slug))
-        except Exception, e:
-            msg = "Unable to delete translation %s"
-            logger.error(msg % language)
-            if not self.skip:
-                raise
-
-    def do_url_request(self, api_call, multipart=False, data=None,
-                       files=[], encoding=None, method="GET", **kwargs):
-        """
-        Issues a url request.
-        """
-        # Read the credentials from the config file (.transifexrc)
-        host = self.url_info['host']
-        try:
-            username = self.txrc.get(host, 'username')
-            passwd = self.txrc.get(host, 'password')
-            token = self.txrc.get(host, 'token')
-            hostname = self.txrc.get(host, 'hostname')
-        except ConfigParser.NoSectionError:
-            raise Exception("No user credentials found for host %s. Edit"
-                " ~/.transifexrc and add the appropriate info in there." %
-                host)
-
-        # Create the Url
-        kwargs['hostname'] = hostname
-        kwargs.update(self.url_info)
-        url = (API_URLS[api_call] % kwargs).encode('UTF-8')
-        logger.debug(url)
-
-        opener = None
-        headers = None
-        req = None
-
-        if multipart:
-            opener = urllib2.build_opener(MultipartPostHandler)
-            for info,filename in files:
-                data = { "resource" : info.split(';')[0],
-                         "language" : info.split(';')[1],
-                         "uploaded_file" :  open(filename,'rb') }
-
-            urllib2.install_opener(opener)
-            req = RequestWithMethod(url=url, data=data, method=method)
-        else:
-            req = RequestWithMethod(url=url, data=data, method=method)
-            if encoding:
-                req.add_header("Content-Type",encoding)
-
-        base64string = base64.encodestring('%s:%s' % (username, passwd))[:-1]
-        authheader = "Basic %s" % base64string
-        req.add_header("Authorization", authheader)
-        req.add_header("Accept-Encoding", "gzip,deflate")
-        req.add_header("User-Agent", user_agent_identifier())
-
-        try:
-            response = urllib2.urlopen(req, timeout=300)
-            return http_response(response)
-        except urllib2.HTTPError, e:
-            if e.code in [401, 403, 404]:
-                raise e
-            elif 200 <= e.code < 300:
-                return None
-            else:
-                # For other requests, we should print the message as well
-                raise Exception("Remote server replied: %s" % e.read())
-        except urllib2.URLError, e:
-            error = e.args[0]
-            raise Exception("Remote server replied: %s" % error[1])
-
-
-    def _should_update_translation(self, lang, stats, local_file, force=False,
-                                   mode=None):
-        """Whether a translation should be udpated from Transifex.
-
-        We use the following criteria for that:
-        - If user requested to force the download.
-        - If language exists in Transifex.
-        - If the local file is older than the Transifex's file.
-        - If the user requested a x% completion.
-
-        Args:
-            lang: The language code to check.
-            stats: The (global) statistics object.
-            local_file: The local translation file.
-            force: A boolean flag.
-            mode: The mode for the translation.
-        Returns:
-            True or False.
-        """
-        return self._should_download(lang, stats, local_file, force)
-
-    def _should_add_translation(self, lang, stats, force=False, mode=None):
-        """Whether a translation should be added from Transifex.
-
-        We use the following criteria for that:
-        - If user requested to force the download.
-        - If language exists in Transifex.
-        - If the user requested a x% completion.
-
-        Args:
-            lang: The language code to check.
-            stats: The (global) statistics object.
-            force: A boolean flag.
-            mode: The mode for the translation.
-        Returns:
-            True or False.
-        """
-        return self._should_download(lang, stats, None, force)
-
-    def _should_download(self, lang, stats, local_file=None, force=False,
-                         mode=None):
-        """Return whether a translation should be downloaded.
-
-        If local_file is None, skip the timestamps check (the file does
-        not exist locally).
-        """
-        try:
-            lang_stats = stats[lang]
-        except KeyError, e:
-            logger.debug("No lang %s in statistics" % lang)
-            return False
-
-        satisfies_min = self._satisfies_min_translated(lang_stats, mode)
-        if not satisfies_min:
-            return False
-
-        if force:
-            logger.debug("Downloading translation due to -f")
-            return True
-
-        if local_file is not None:
-            remote_update = self._extract_updated(lang_stats)
-            if not self._remote_is_newer(remote_update, local_file):
-                logger.debug("Local is newer than remote for lang %s" % lang)
-                return False
-        return True
-
-    def _should_push_translation(self, lang, stats, local_file, force=False):
-        """Return whether a local translation file should be
-        pushed to Trasnifex.
-
-        We use the following criteria for that:
-        - If user requested to force the upload.
-        - If language exists in Transifex.
-        - If local file is younger than the remote file.
-
-        Args:
-            lang: The language code to check.
-            stats: The (global) statistics object.
-            local_file: The local translation file.
-            force: A boolean flag.
-        Returns:
-            True or False.
-        """
-        if force:
-            logger.debug("Push translation due to -f.")
-            return True
-        try:
-            lang_stats = stats[lang]
-        except KeyError, e:
-            logger.debug("Language %s does not exist in Transifex." % lang)
-            return True
-        if local_file is not None:
-            remote_update = self._extract_updated(lang_stats)
-            if self._remote_is_newer(remote_update, local_file):
-                msg  = "Remote translation is newer than local file for lang %s"
-                logger.debug(msg % lang)
-                return False
-        return True
-
-    def _generate_timestamp(self, update_datetime):
-        """Generate a UNIX timestamp from the argument.
-
-        Args:
-            update_datetime: The datetime in the format used by Transifex.
-        Returns:
-            A float, representing the timestamp that corresponds to the
-            argument.
-        """
-        time_format = "%Y-%m-%d %H:%M:%S"
-        return time.mktime(
-            datetime.datetime(
-                *time.strptime(update_datetime, time_format)[0:5]
-            ).utctimetuple()
-        )
-
-    def _get_time_of_local_file(self, path):
-        """Get the modified time of the path_.
-
-        Args:
-            path: The path we want the mtime for.
-        Returns:
-            The time as a timestamp or None, if the file does not exist
-        """
-        if not os.path.exists(path):
-            return None
-        return time.mktime(time.gmtime(os.path.getmtime(path)))
-
-    def _satisfies_min_translated(self, stats, mode=None):
-        """Check whether a translation fulfills the filter used for
-        minimum translated percentage.
-
-        Args:
-            perc: The current translation percentage.
-        Returns:
-            True or False
-        """
-        cur = self._extract_completed(stats, mode)
-        option_name = 'minimum_perc'
-        if self.minimum_perc is not None:
-            minimum_percent = self.minimum_perc
-        else:
-            global_minimum = int(
-                self.get_resource_option('main', option_name) or 0
-            )
-            resource_minimum = int(
-                self.get_resource_option(
-                    self.resource, option_name
-                ) or global_minimum
-            )
-            minimum_percent = resource_minimum
-        return cur >= minimum_percent
-
-    def _remote_is_newer(self, remote_updated, local_file):
-        """Check whether the remote translation is newer that the local file.
-
-        Args:
-            remote_updated: The date and time the translation was last
-                updated remotely.
-            local_file: The local file.
-        Returns:
-            True or False.
-        """
-        if remote_updated is None:
-            logger.debug("No remote time")
-            return False
-        remote_time = self._generate_timestamp(remote_updated)
-        local_time = self._get_time_of_local_file(
-            self.get_full_path(local_file)
-        )
-        logger.debug(
-            "Remote time is %s and local %s" % (remote_time, local_time)
-        )
-        if local_time is not None and remote_time < local_time:
-            return False
-        return True
-
-    @classmethod
-    def _extract_completed(cls, stats, mode=None):
-        """Extract the information for the translated percentage from the stats.
-
-        Args:
-            stats: The stats object for a language as returned by Transifex.
-            mode: The mode of translations requested.
-        Returns:
-            The percentage of translation as integer.
-        """
-        if mode == 'reviewed':
-            key = 'reviewed_percentage'
-        else:
-            key = 'completed'
-        try:
-            return int(stats[key][:-1])
-        except KeyError, e:
-            return 0
-
-    @classmethod
-    def _extract_updated(cls, stats):
-        """Extract the  information for the last update of a translation.
-
-        Args:
-            stats: The stats object for a language as returned by Transifex.
-        Returns:
-            The last update field.
-        """
-        try:
-            return stats['last_update']
-        except KeyError, e:
-            return None
-
-    def _new_translations_to_add(self, files, slang, lang_map,
-                                 stats, force=False):
-        """Return a list of translations which are new to the
-        local installation.
-        """
-        new_translations = []
-        timestamp = time.time()
-        langs = stats.keys()
-        logger.debug("Available languages are: %s" % langs)
-
-        for lang in langs:
-            lang_exists = lang in files.keys()
-            lang_is_source = lang == slang
-            mapped_lang_exists = (
-                lang in lang_map and lang_map[lang] in files.keys()
-            )
-            if lang_exists or lang_is_source or mapped_lang_exists:
-                continue
-            if self._should_add_translation(lang, stats, force):
-                new_translations.append(lang)
-        return set(new_translations)
-
-    def _get_stats_for_resource(self):
-        """Get the statistics information for a resource."""
-        try:
-            r = self.do_url_request('resource_stats')
-            logger.debug("Statistics response is %s" % r)
-            stats = parse_json(r)
-        except urllib2.HTTPError, e:
-            logger.debug("Resource not found: %s" % e)
-            stats = {}
-        except Exception,e:
-            logger.debug("Network error: %s" % e)
-            raise
-        return stats
-
-    def get_chosen_resources(self, resources):
-        """Get the resources the user selected.
-
-        Support wildcards in the resources specified by the user.
-
-        Args:
-            resources: A list of resources as specified in command-line or
-                an empty list.
-        Returns:
-            A list of resources.
-        """
-        configured_resources = self.get_resource_list()
-        if not resources:
-            return configured_resources
-
-        selected_resources = []
-        for resource in resources:
-            found = False
-            for full_name in configured_resources:
-                if fnmatch.fnmatch(full_name, resource):
-                    selected_resources.append(full_name)
-                    found = True
-            if not found:
-                msg = "Specified resource '%s' does not exist."
-                raise Exception(msg % resource)
-        logger.debug("Operating on resources: %s" % selected_resources)
-        return selected_resources
-
-    def _languages_to_pull(self, languages, files, lang_map, stats, force):
-        """Get a set of langauges to pull.
-
-        Args:
-            languages: A list of languages the user selected in cmd.
-            files: A dictionary of current local translation files.
-        Returns:
-            A tuple of a set of existing languages and new translations.
-        """
-        if not languages:
-            pull_languages = set([])
-            pull_languages |= set(files.keys())
-            mapped_files = []
-            for lang in pull_languages:
-                if lang in lang_map.flip:
-                    mapped_files.append(lang_map.flip[lang])
-            pull_languages -= set(lang_map.flip.keys())
-            pull_languages |= set(mapped_files)
-            return (pull_languages, set([]))
-        else:
-            pull_languages = []
-            new_translations = []
-            f_langs = files.keys()
-            for l in languages:
-                if l not in f_langs and not (l in lang_map and lang_map[l] in f_langs):
-                    if self._should_add_translation(l, stats, force):
-                        new_translations.append(l)
-                else:
-                    if l in lang_map.keys():
-                        l = lang_map[l]
-                    pull_languages.append(l)
-            return (set(pull_languages), set(new_translations))
-
-    def _extension_for(self, i18n_type):
-        """Return the extension used for the specified type."""
-        try:
-            res = parse_json(self.do_url_request('formats'))
-            return res[i18n_type]['file-extensions'].split(',')[0]
-        except Exception,e:
-            logger.error(e)
-            return ''
-
-    def _resource_exists(self, stats):
-        """Check if resource exists.
-
-        Args:
-            stats: The statistics dict as returned by Tx.
-        Returns:
-            True, if the resource exists in the server.
-        """
-        return bool(stats)
-
-    def _create_resource(self, resource, pslug, fileinfo, filename, **kwargs):
-        """Create a resource.
-
-        Args:
-            resource: The full resource name.
-            pslug: The slug of the project.
-            fileinfo: The information of the resource.
-            filename: The name of the file.
-        Raises:
-            URLError, in case of a problem.
-        """
-        multipart = True
-        method = "POST"
-        api_call = 'create_resource'
-
-        host = self.url_info['host']
-        try:
-            username = self.txrc.get(host, 'username')
-            passwd = self.txrc.get(host, 'password')
-            token = self.txrc.get(host, 'token')
-            hostname = self.txrc.get(host, 'hostname')
-        except ConfigParser.NoSectionError:
-            raise Exception("No user credentials found for host %s. Edit"
-                " ~/.transifexrc and add the appropriate info in there." %
-                host)
-
-        # Create the Url
-        kwargs['hostname'] = hostname
-        kwargs.update(self.url_info)
-        kwargs['project'] = pslug
-        url = (API_URLS[api_call] % kwargs).encode('UTF-8')
-
-        opener = None
-        headers = None
-        req = None
-
-        i18n_type = self._get_option(resource, 'type')
-        if i18n_type is None:
-            logger.error(
-                "Please define the resource type in .tx/config (eg. type = PO)."
-                " More info: http://bit.ly/txcl-rt"
-            )
-
-        opener = urllib2.build_opener(MultipartPostHandler)
-        data = {
-            "slug": fileinfo.split(';')[0],
-            "name": fileinfo.split(';')[0],
-            "uploaded_file":  open(filename,'rb'),
-            "i18n_type": i18n_type
-        }
-        urllib2.install_opener(opener)
-        req = RequestWithMethod(url=url, data=data, method=method)
-
-        base64string = base64.encodestring('%s:%s' % (username, passwd))[:-1]
-        authheader = "Basic %s" % base64string
-        req.add_header("Authorization", authheader)
-
-        try:
-            fh = urllib2.urlopen(req)
-        except urllib2.HTTPError, e:
-            if e.code in [401, 403, 404]:
-                raise e
-            else:
-                # For other requests, we should print the message as well
-                raise Exception("Remote server replied: %s" % e.read())
-        except urllib2.URLError, e:
-            error = e.args[0]
-            raise Exception("Remote server replied: %s" % error[1])
-
-        raw = fh.read()
-        fh.close()
-        return raw
-
-    def _get_option(self, resource, option):
-        """Get the value for the option in the config file.
-
-        If the option is not in the resource section, look for it in
-        the project.
-
-        Args:
-            resource: The resource name.
-            option: The option the value of which we are interested in.
-        Returns:
-            The option value or None, if it does not exist.
-        """
-        value = self.get_resource_option(resource, option)
-        if value is None:
-            if self.config.has_option('main', option):
-                return self.config.get('main', option)
-        return value
-
-    def set_i18n_type(self, resources, i18n_type):
-        """Set the type for the specified resources."""
-        self._set_resource_option(resources, key='type', value=i18n_type)
-
-    def set_min_perc(self, resources, perc):
-        """Set the minimum percentage for the resources."""
-        self._set_resource_option(resources, key='minimum_perc', value=perc)
-
-    def set_default_mode(self, resources, mode):
-        """Set the default mode for the specified resources."""
-        self._set_resource_option(resources, key='mode', value=mode)
-
-    def _set_resource_option(self, resources, key, value):
-        """Set options in the config file.
-
-        If resources is empty. set the option globally.
-        """
-        if not resources:
-            self.config.set('main', key, value)
-            return
-        for r in resources:
-            self.config.set(r, key, value)
diff --git a/third_party/transifex-client/txclib/urls.py b/third_party/transifex-client/txclib/urls.py
deleted file mode 100644 (file)
index 0bb74fd..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# These are the Transifex API urls
-
-API_URLS = {
-    'get_resources': '%(hostname)s/api/2/project/%(project)s/resources/',
-    'project_details': '%(hostname)s/api/2/project/%(project)s/?details',
-    'resource_details': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/',
-    'release_details': '%(hostname)s/api/2/project/%(project)s/release/%(release)s/',
-    'pull_file': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/?file',
-    'pull_reviewed_file': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/?file&mode=reviewed',
-    'pull_translator_file': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/?file&mode=translated',
-    'pull_developer_file': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/?file&mode=default',
-    'resource_stats': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/stats/',
-    'create_resource': '%(hostname)s/api/2/project/%(project)s/resources/',
-    'push_source': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/content/',
-    'push_translation': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/',
-    'delete_translation': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/',
-    'formats': '%(hostname)s/api/2/formats/',
-    'delete_resource': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/',
-}
-
-
diff --git a/third_party/transifex-client/txclib/utils.py b/third_party/transifex-client/txclib/utils.py
deleted file mode 100644 (file)
index 318bee9..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-import os, sys, re, errno
-try:
-    from json import loads as parse_json, dumps as compile_json
-except ImportError:
-    from simplejson import loads as parse_json, dumps as compile_json
-import urllib2 # This should go and instead use do_url_request everywhere
-
-from urls import API_URLS
-from txclib.log import logger
-from txclib.exceptions import UnknownCommandError
-
-
-def find_dot_tx(path = os.path.curdir, previous = None):
-    """
-    Return the path where .tx folder is found.
-
-    The 'path' should be a DIRECTORY.
-    This process is functioning recursively from the current directory to each
-    one of the ancestors dirs.
-    """
-    path = os.path.abspath(path)
-    if path == previous:
-        return None
-    joined = os.path.join(path, ".tx")
-    if os.path.isdir(joined):
-        return path
-    else:
-        return find_dot_tx(os.path.dirname(path), path)
-
-
-#################################################
-# Parse file filter expressions and create regex
-
-def regex_from_filefilter(file_filter, root_path = os.path.curdir):
-    """
-    Create proper regex from <lang> expression
-    """
-    # Force expr to be a valid regex expr (escaped) but keep <lang> intact
-    expr_re = re.escape(os.path.join(root_path, file_filter))
-    expr_re = expr_re.replace("\\<lang\\>", '<lang>').replace(
-        '<lang>', '([^%(sep)s]+)' % { 'sep': re.escape(os.path.sep)})
-
-    return "^%s$" % expr_re
-
-
-TX_URLS = {
-    'resource': '(?P<hostname>https?://(\w|\.|:|-)+)/projects/p/(?P<project>(\w|-)+)/resource/(?P<resource>(\w|-)+)/?$',
-    'release': '(?P<hostname>https?://(\w|\.|:|-)+)/projects/p/(?P<project>(\w|-)+)/r/(?P<release>(\w|-)+)/?$',
-    'project': '(?P<hostname>https?://(\w|\.|:|-)+)/projects/p/(?P<project>(\w|-)+)/?$',
-}
-
-
-def parse_tx_url(url):
-    """
-    Try to match given url to any of the valid url patterns specified in
-    TX_URLS. If not match is found, we raise exception
-    """
-    for type in TX_URLS.keys():
-        pattern = TX_URLS[type]
-        m = re.match(pattern, url)
-        if m:
-            return type, m.groupdict()
-
-    raise Exception("tx: Malformed url given. Please refer to our docs: http://bit.ly/txautor")
-
-
-def get_details(api_call, username, password, *args, **kwargs):
-    """
-    Get the tx project info through the API.
-
-    This function can also be used to check the existence of a project.
-    """
-    import base64
-    url = (API_URLS[api_call] % (kwargs)).encode('UTF-8')
-
-    req = urllib2.Request(url=url)
-    base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
-    authheader = "Basic %s" % base64string
-    req.add_header("Authorization", authheader)
-
-    try:
-        fh = urllib2.urlopen(req)
-        raw = fh.read()
-        fh.close()
-        remote_project = parse_json(raw)
-    except urllib2.HTTPError, e:
-        if e.code in [401, 403, 404]:
-            raise e
-        else:
-            # For other requests, we should print the message as well
-            raise Exception("Remote server replied: %s" % e.read())
-    except urllib2.URLError, e:
-        error = e.args[0]
-        raise Exception("Remote server replied: %s" % error[1])
-
-    return remote_project
-
-
-def valid_slug(slug):
-    """
-    Check if a slug contains only valid characters.
-
-    Valid chars include [-_\w]
-    """
-    try:
-        a, b = slug.split('.')
-    except ValueError:
-        return False
-    else:
-        if re.match("^[A-Za-z0-9_-]*$", a) and re.match("^[A-Za-z0-9_-]*$", b):
-            return True
-        return False
-
-
-def discover_commands():
-    """
-    Inspect commands.py and find all available commands
-    """
-    import inspect
-    from txclib import commands
-
-    command_table = {}
-    fns = inspect.getmembers(commands, inspect.isfunction)
-
-    for name, fn in fns:
-        if name.startswith("cmd_"):
-            command_table.update({
-                name.split("cmd_")[1]:fn
-            })
-
-    return command_table
-
-
-def exec_command(command, *args, **kwargs):
-    """
-    Execute given command
-    """
-    commands = discover_commands()
-    try:
-        cmd_fn = commands[command]
-    except KeyError:
-        raise UnknownCommandError
-    cmd_fn(*args,**kwargs)
-
-
-def mkdir_p(path):
-    try:
-        if path:
-            os.makedirs(path)
-    except OSError, exc: # Python >2.5
-        if exc.errno == errno.EEXIST:
-            pass
-        else:
-            raise
-
-
-def confirm(prompt='Continue?', default=True):
-    """
-    Prompt the user for a Yes/No answer.
-
-    Args:
-        prompt: The text displayed to the user ([Y/n] will be appended)
-        default: If the default value will be yes or no
-    """
-    valid_yes = ['Y', 'y', 'Yes', 'yes', ]
-    valid_no = ['N', 'n', 'No', 'no', ]
-    if default:
-        prompt = prompt + '[Y/n]'
-        valid_yes.append('')
-    else:
-        prompt = prompt + '[y/N]'
-        valid_no.append('')
-
-    ans = raw_input(prompt)
-    while (ans not in valid_yes and ans not in valid_no):
-        ans = raw_input(prompt)
-
-    return ans in valid_yes
-
-
-# Stuff for command line colored output
-
-COLORS = [
-    'BLACK', 'RED', 'GREEN', 'YELLOW',
-    'BLUE', 'MAGENTA', 'CYAN', 'WHITE'
-]
-
-DISABLE_COLORS = False
-
-
-def color_text(text, color_name, bold=False):
-    """
-    This command can be used to colorify command line output. If the shell
-    doesn't support this or the --disable-colors options has been set, it just
-    returns the plain text.
-
-    Usage:
-        print "%s" % color_text("This text is red", "RED")
-    """
-    if color_name in COLORS and not DISABLE_COLORS:
-        return '\033[%s;%sm%s\033[0m' % (
-            int(bold), COLORS.index(color_name) + 30, text)
-    else:
-        return text
-
-
-##############################################
-# relpath implementation taken from Python 2.7
-
-if not hasattr(os.path, 'relpath'):
-    if os.path is sys.modules.get('ntpath'):
-        def relpath(path, start=os.path.curdir):
-            """Return a relative version of a path"""
-
-            if not path:
-                raise ValueError("no path specified")
-            start_list = os.path.abspath(start).split(os.path.sep)
-            path_list = os.path.abspath(path).split(os.path.sep)
-            if start_list[0].lower() != path_list[0].lower():
-                unc_path, rest = os.path.splitunc(path)
-                unc_start, rest = os.path.splitunc(start)
-                if bool(unc_path) ^ bool(unc_start):
-                    raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
-                                                                        % (path, start))
-                else:
-                    raise ValueError("path is on drive %s, start on drive %s"
-                                                        % (path_list[0], start_list[0]))
-            # Work out how much of the filepath is shared by start and path.
-            for i in range(min(len(start_list), len(path_list))):
-                if start_list[i].lower() != path_list[i].lower():
-                    break
-            else:
-                i += 1
-
-            rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
-            if not rel_list:
-                return os.path.curdir
-            return os.path.join(*rel_list)
-
-    else:
-        # default to posixpath definition
-        def relpath(path, start=os.path.curdir):
-            """Return a relative version of a path"""
-
-            if not path:
-                raise ValueError("no path specified")
-
-            start_list = os.path.abspath(start).split(os.path.sep)
-            path_list = os.path.abspath(path).split(os.path.sep)
-
-            # Work out how much of the filepath is shared by start and path.
-            i = len(os.path.commonprefix([start_list, path_list]))
-
-            rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
-            if not rel_list:
-                return os.path.curdir
-            return os.path.join(*rel_list)
-else:
-    from os.path import relpath
diff --git a/third_party/transifex-client/txclib/web.py b/third_party/transifex-client/txclib/web.py
deleted file mode 100644 (file)
index a3cb3f0..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-# -*- coding: utf-8 -*-
-import urllib2
-import itertools, mimetools, mimetypes
-import platform
-from txclib import get_version
-
-# Helper class to enable urllib2 to handle PUT/DELETE requests as well
-class RequestWithMethod(urllib2.Request):
-    """Workaround for using DELETE with urllib2"""
-    def __init__(self, url, method, data=None, headers={},
-        origin_req_host=None, unverifiable=False):
-        self._method = method
-        urllib2.Request.__init__(self, url, data=data, headers=headers,
-                 origin_req_host=None, unverifiable=False)
-
-    def get_method(self):
-        return self._method
-
-import urllib
-import os, stat
-from cStringIO import StringIO
-
-class Callable:
-    def __init__(self, anycallable):
-        self.__call__ = anycallable
-
-# Controls how sequences are uncoded. If true, elements may be given multiple
-# values by assigning a sequence.
-doseq = 1
-
-class MultipartPostHandler(urllib2.BaseHandler):
-    handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first
-
-    def http_request(self, request):
-        data = request.get_data()
-        if data is not None and type(data) != str:
-            v_files = []
-            v_vars = []
-            try:
-                 for(key, value) in data.items():
-                     if type(value) == file:
-                         v_files.append((key, value))
-                     else:
-                         v_vars.append((key, value))
-            except TypeError:
-                systype, value, traceback = sys.exc_info()
-                raise TypeError, "not a valid non-string sequence or mapping object", traceback
-
-            if len(v_files) == 0:
-                data = urllib.urlencode(v_vars, doseq)
-            else:
-                boundary, data = self.multipart_encode(v_vars, v_files)
-
-                contenttype = 'multipart/form-data; boundary=%s' % boundary
-                if(request.has_header('Content-Type')
-                   and request.get_header('Content-Type').find('multipart/form-data') != 0):
-                    print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
-                request.add_unredirected_header('Content-Type', contenttype)
-
-            request.add_data(data)
-
-        return request
-
-    def multipart_encode(vars, files, boundary = None, buf = None):
-        if boundary is None:
-            boundary = mimetools.choose_boundary()
-        if buf is None:
-            buf = StringIO()
-        for(key, value) in vars:
-            buf.write('--%s\r\n' % boundary)
-            buf.write('Content-Disposition: form-data; name="%s"' % key)
-            buf.write('\r\n\r\n' + value + '\r\n')
-        for(key, fd) in files:
-            file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
-            filename = fd.name.split('/')[-1]
-            contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
-            buf.write('--%s\r\n' % boundary)
-            buf.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename))
-            buf.write('Content-Type: %s\r\n' % contenttype)
-            # buffer += 'Content-Length: %s\r\n' % file_size
-            fd.seek(0)
-            buf.write('\r\n' + fd.read() + '\r\n')
-        buf.write('--' + boundary + '--\r\n\r\n')
-        buf = buf.getvalue()
-        return boundary, buf
-    multipart_encode = Callable(multipart_encode)
-
-    https_request = http_request
-
-
-def user_agent_identifier():
-    """Return the user agent for the client."""
-    client_info = (get_version(), platform.system(), platform.machine())
-    return "txclient/%s (%s %s)" % client_info