Merge pull request #152 from owncloud/oauth_login

Oauth login and authenticator refactoring
This commit is contained in:
David A. Velasco 2013-05-03 04:38:21 -07:00
commit 52bd01bced
74 changed files with 3312 additions and 2154 deletions

View file

@ -90,7 +90,7 @@
<activity android:name=".ui.activity.PreferencesNewSessionewSession" >
</activity>
<activity android:name="com.owncloud.android.ui.preview.PreviewImageActivity" />
<activity android:name="com.owncloud.android.ui.preview.PreviewImageActivity" />
<activity android:name="com.owncloud.android.ui.preview.PreviewVideoActivity"
android:label="@string/app_name"
@ -98,7 +98,7 @@
</activity>
<service
android:name=".authenticator.AccountAuthenticatorService"
android:name=".authentication.AccountAuthenticatorService"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="android.accounts.AccountAuthenticator" />
@ -130,9 +130,16 @@
</provider>
<activity
android:name=".ui.activity.AuthenticatorActivity"
android:name=".authentication.AuthenticatorActivity"
android:exported="true"
android:theme="@style/Theme.ownCloud.noActionBar" >
android:theme="@style/Theme.ownCloud.noActionBar"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/oauth2_redirect_scheme" />
</intent-filter>
<intent-filter>
<action android:name="com.owncloud.android.workaround.accounts.CREATE" />
<category android:name="android.intent.category.DEFAULT" />
@ -154,21 +161,22 @@
<activity android:name=".ui.activity.LogHistoryActivity"/>
<receiver android:name=".files.InstantUploadBroadcastReceiver">
<intent-filter>
<action android:name="com.android.camera.NEW_PICTURE" />
<data android:mimeType="image/*" />
<receiver android:name=".files.InstantUploadBroadcastReceiver">
<intent-filter>
<action android:name="com.android.camera.NEW_PICTURE" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
<receiver android:name=".files.BootupBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service android:name=".files.services.FileObserverService"/>
</application>
</intent-filter>
</receiver>
<receiver android:name=".files.BootupBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service android:name=".files.services.FileObserverService"/>
</application>
</manifest>

View file

@ -1,186 +1,238 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:oc="http://schemas.android.com/apk/res/com.owncloud.android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusable="true"
android:gravity="center|fill"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="7dp"
android:layout_weight="1"
android:src="@drawable/owncloud_logo" />
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="@+id/host_URL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="@string/auth_host_url"
android:inputType="textNoSuggestions">
<requestFocus />
</EditText>
<ImageView
android:id="@+id/refreshButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:src="@drawable/ic_action_refresh_black"
android:visibility="invisible" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="1" >
<ImageView
android:id="@+id/action_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:src="@android:drawable/stat_notify_sync"
android:visibility="invisible" />
<TextView
android:id="@+id/status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:visibility="invisible" />
</LinearLayout>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="@string/auth_login_details"
android:textAppearance="?android:attr/textAppearanceSmall" />
<EditText
android:id="@+id/account_username"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:ems="10"
android:hint="@string/auth_username"
android:inputType="textNoSuggestions" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="@+id/account_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="@string/auth_password"
android:inputType="textPassword"/>
<ImageView
android:id="@+id/viewPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:src="@android:drawable/ic_menu_view"
android:visibility="invisible" />
</FrameLayout>
</LinearLayout>
</LinearLayout>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
<LinearLayout
android:id="@+id/buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1">
<Button
android:id="@+id/buttonOK"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:enabled="false"
android:onClick="onOkClick"
android:text="@string/setup_btn_connect"
android:textColor="@android:color/black" />
</LinearLayout>
<Button
android:id="@+id/account_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/buttons_layout"
android:layout_centerHorizontal="true"
android:onClick="onRegisterClick"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textColor="#0000FF"
android:background="@android:color/transparent" />
<!-- android:text="@string/app_name @string/auth_register" /-->
</RelativeLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--
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/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:oc="http://schemas.android.com/apk/res/com.owncloud.android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusable="true"
android:gravity="center|fill"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="7dp"
android:layout_weight="1"
android:src="@drawable/owncloud_logo" />
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="@+id/hostUrlInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/auth_host_url"
android:inputType="textNoSuggestions">
<requestFocus />
</EditText>
<ImageView
android:id="@+id/refreshButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:src="@drawable/ic_action_refresh_black"
android:onClick="onRefreshClick"
android:visibility="invisible" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="1" >
<ImageView
android:id="@+id/action_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:src="@android:drawable/stat_notify_sync"
android:visibility="invisible" />
<TextView
android:id="@+id/status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:visibility="invisible" />
</LinearLayout>
<CheckBox
android:id="@+id/oauth_onOff_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:onClick="onCheckClick"
android:text="@string/oauth_check_onoff"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="@string/auth_login_details"
android:textAppearance="?android:attr/textAppearanceSmall" />
<EditText
android:id="@+id/oAuthEntryPoint_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:enabled="false"
android:text="@string/oauth2_url_endpoint_auth"
android:singleLine="true"
android:visibility="gone" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/oAuthEntryPoint_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:enabled="false"
android:text="@string/oauth2_url_endpoint_access"
android:singleLine="true"
android:visibility="gone" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/account_username"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:ems="10"
android:hint="@string/auth_username"
android:inputType="textNoSuggestions" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="@+id/account_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/auth_password"
android:inputType="textPassword"/>
<ImageView
android:id="@+id/viewPasswordButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:src="@android:drawable/ic_menu_view"
android:onClick="onViewPasswordClick"
android:visibility="invisible" />
</FrameLayout>
<TextView
android:id="@+id/auth_status_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/text_placeholder"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:drawableLeft="@android:drawable/stat_notify_sync"
android:drawablePadding="5dip"
android:visibility="invisible"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
<LinearLayout
android:id="@+id/buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1">
<Button
android:id="@+id/buttonOK"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:enabled="false"
android:onClick="onOkClick"
android:text="@string/setup_btn_connect"
android:textColor="@android:color/black" />
</LinearLayout>
<Button
android:id="@+id/account_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/buttons_layout"
android:layout_centerHorizontal="true"
android:onClick="onRegisterClick"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textColor="#0000FF"
android:background="@android:color/transparent" />
<!-- android:text="@string/app_name @string/auth_register" /-->
</RelativeLayout>
</LinearLayout>

View file

@ -1,189 +1,253 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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/>.
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:focusable="true"
android:gravity="center"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_gravity="center"
android:layout_marginBottom="50dip"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:layout_weight="1" >
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:src="@drawable/owncloud_logo" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="@+id/host_URL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/auth_host_url"
android:inputType="textNoSuggestions" >
<requestFocus />
</EditText>
<ImageView
android:id="@+id/refreshButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_refresh_black"
android:layout_gravity="right|center_vertical"
android:visibility="invisible" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="1" >
<ImageView
android:id="@+id/action_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:src="@android:drawable/stat_notify_sync"
android:visibility="invisible" />
<TextView
android:id="@+id/status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:visibility="invisible" />
</LinearLayout>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="@string/auth_login_details"
android:textAppearance="?android:attr/textAppearanceSmall" />
<EditText
android:id="@+id/account_username"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:ems="10"
android:hint="@string/auth_username"
android:inputType="textNoSuggestions" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="@+id/account_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/auth_password"
android:inputType="textPassword"/>
<ImageView
android:id="@+id/viewPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:src="@android:drawable/ic_menu_view"
android:visibility="invisible" />
</FrameLayout>
</LinearLayout>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/buttons_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1">
<Button
android:id="@+id/buttonOK"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:enabled="false"
android:onClick="onOkClick"
android:text="@string/setup_btn_connect"
android:textColor="@android:color/black" />
</LinearLayout>
<Button
android:id="@+id/account_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/buttons_layout"
android:layout_centerHorizontal="true"
android:onClick="onRegisterClick"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textColor="#0000FF"
android:background="@android:color/transparent" />
</RelativeLayout>
</LinearLayout>
</ScrollView>
<?xml version="1.0" encoding="utf-8"?>
<!--
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/>.
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:focusable="true"
android:gravity="center"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_gravity="center"
android:layout_marginBottom="50dip"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:layout_weight="1" >
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:src="@drawable/owncloud_logo" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="@+id/hostUrlInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/auth_host_url"
android:inputType="textNoSuggestions" >
<requestFocus />
</EditText>
<ImageView
android:id="@+id/refreshButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_refresh_black"
android:layout_gravity="right|center_vertical"
android:visibility="invisible" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="1" >
<ImageView
android:id="@+id/action_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:src="@android:drawable/stat_notify_sync"
android:visibility="invisible" />
<TextView
android:id="@+id/status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:visibility="invisible" />
</LinearLayout>
<CheckBox
android:id="@+id/oauth_onOff_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:onClick="onCheckClick"
android:text="@string/oauth_check_onoff"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="@string/auth_login_details"
android:textAppearance="?android:attr/textAppearanceSmall" />
<EditText
android:id="@+id/oAuthEntryPoint_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:text="@string/oauth2_url_endpoint_auth"
android:singleLine="true"
android:visibility="gone" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/oAuthEntryPoint_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:text="@string/oauth2_url_endpoint_access"
android:singleLine="true"
android:visibility="gone" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/account_username"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:ems="10"
android:hint="@string/auth_username"
android:inputType="textNoSuggestions" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<EditText
android:id="@+id/account_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/auth_password"
android:inputType="textPassword"/>
<ImageView
android:id="@+id/viewPasswordButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:src="@android:drawable/ic_menu_view"
android:onClick="onViewPasswordClick"
android:visibility="invisible" />
</FrameLayout>
<TextView
android:id="@+id/auth_status_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/text_placeholder"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:drawableLeft="@android:drawable/stat_notify_sync"
android:drawablePadding="5dip"
android:visibility="invisible"
/>
</LinearLayout>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1">
<Button
android:id="@+id/buttonOK"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:enabled="false"
android:onClick="onOkClick"
android:text="@string/setup_btn_connect"
android:textColor="@android:color/black" />
</LinearLayout>
<Button
android:id="@+id/account_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/buttons_layout"
android:layout_centerHorizontal="true"
android:onClick="onRegisterClick"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textColor="#0000FF"
android:background="@android:color/transparent" />
<Button
android:id="@+id/account_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/buttons_layout"
android:layout_centerHorizontal="true"
android:onClick="onRegisterClick"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textColor="#0000FF"
android:background="@android:color/transparent" />
<!-- android:text="@string/app_name @string/auth_register" /-->
</RelativeLayout>
</LinearLayout>
</ScrollView>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Flag to configure OAuth availability in the app.
3 valid values now: on, off, optional
-->
<string name="oauth2_mode">off</string>
<!-- constants that must be respected by the authorization server; if changed, the app must be rebuild -->
<string name="oauth2_redirect_scheme">owncloud</string>
<string name="oauth2_redirect_uri">owncloud://callback</string>
<!-- values that should be provided by ownCloud server -->
<string name="oauth2_url_endpoint_auth">http://oauth2.authorization.server.org/paht/to/endpoint/for/authorization</string>
<string name="oauth2_url_endpoint_access">http://oauth2.authorization.server.org/paht/to/endporint/for/access/token</string>
<string name="oauth2_scope">owncloud</string>
<string name="oauth2_grant_type">authorization_code</string> <!-- the only one supported right now -->
<string name="oauth2_response_type">code</string> <!-- depends on oauth2_grant_type -->
<!-- values that should be pre-agreed between app and authorization server, but can be loaded without rebuilding the app -->
<string name="oauth2_client_id">com.owncloud.android</string> <!-- preferable that client decides this -->
<string name="oauth2_client_secret"></string> <!-- preferable that client decides this -->
</resources>

View file

@ -118,8 +118,9 @@
<string name="sync_string_contacts">Contacts</string>
<string name="sync_fail_ticker">Synchronization failed</string>
<string name="sync_fail_content">Synchronization of %1$s could not be completed</string>
<string name="sync_conflicts_in_favourites_ticker">Conflicts found</string>
<string name="sync_conflicts_in_favourites_content">%1$d kept-in-sync files could not be sync\'ed</string>
<string name="sync_fail_content_unauthorized">Invalid credentials for %1$s</string>
<string name="sync_conflicts_in_favourites_ticker">Conflicts found</string>
<string name="sync_conflicts_in_favourites_content">%1$d kept-in-sync files could not be sync\'ed</string>
<string name="sync_fail_in_favourites_ticker">Kept-in-sync files failed</string>
<string name="sync_fail_in_favourites_content">Contents of %1$d files could not be sync\'ed (%2$d conflicts)</string>
<string name="sync_foreign_files_forgotten_ticker">Some local files were forgotten</string>
@ -200,9 +201,15 @@
<string name="auth_wrong_connection_title">Couldn\'t establish connection</string>
<string name="auth_secure_connection">Secure connection established</string>
<string name="auth_login_details">Login details</string>
<string name="auth_unauthorized">Invalid login / password</string>
<string name="auth_unauthorized">Invalid credentials</string>
<string name="auth_oauth_error">Unsuccessful authorization</string>
<string name="auth_oauth_error_access_denied">Access denied by authorization server</string>
<string name="auth_not_found">Wrong path given</string>
<string name="auth_internal">Internal server error, code %1$d</string>
<string name="auth_wtf_reenter_URL">Unexpected state; please, enter the server URL again</string>
<string name="auth_expired_oauth_token_toast">Your authorization expired.\nPlease, authorize again</string>
<string name="auth_expired_basic_auth_toast">Your saved credentials are invalid.\nPlease, enter the current credentials</string>
<string name="crashlog_message">Application terminated unexpectedly. Would you like to submit a crash report?</string>
<string name="crashlog_send_report">Send report</string>
<string name="crashlog_dont_send_report">Don\'t send report</string>
@ -229,6 +236,13 @@
<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="oauth_host_url">oAuth2 URL</string>
<string name="oauth_check_onoff">Login with oAuth2.</string>
<string name="oauth_login_connection">Connecting to oAuth2 server…</string>
<string name="oauth_code_validation_message">Please, open a web browser and go to:\n%1$s.\nValidate this code there:\n%2$s</string>
<string name="oauth_connection_url_unavailable">Connection to this URL not available.</string>
<string name="ssl_validator_title">Warning</string>
<string name="ssl_validator_header">The identity of the site could not be verified</string>
<string name="ssl_validator_reason_cert_not_trusted">- The server certificate is not trusted</string>

View file

@ -101,6 +101,10 @@
<item name="android:singleLine">true</item>
</style>
<style name="OAuthDialog" parent="@android:style/Theme.Dialog">
<item name="android:windowNoTitle">false</item>
</style>
<color name="setup_text_hint">#777777</color>
<color name="setup_text_typed">#000000</color>

View file

@ -18,7 +18,7 @@
package com.owncloud.android;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.utils.OwnCloudVersion;
import android.accounts.Account;
@ -31,6 +31,7 @@ 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";
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";
@ -112,8 +113,11 @@ public class AccountUtils {
* @param version version of owncloud
* @return webdav path for given OC version, null if OC version unknown
*/
public static String getWebdavPath(OwnCloudVersion version) {
public static String getWebdavPath(OwnCloudVersion version, boolean supportsOAuth) {
if (version != null) {
if (supportsOAuth) {
return ODAV_PATH;
}
if (version.compareTo(OwnCloudVersion.owncloud_v4) >= 0)
return WEBDAV_PATH_4_0;
if (version.compareTo(OwnCloudVersion.owncloud_v3) >= 0
@ -136,8 +140,9 @@ public class AccountUtils {
AccountManager ama = AccountManager.get(context);
String baseurl = ama.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL);
String strver = ama.getUserData(account, AccountAuthenticator.KEY_OC_VERSION);
boolean supportsOAuth = (ama.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null);
OwnCloudVersion ver = new OwnCloudVersion(strver);
String webdavpath = getWebdavPath(ver);
String webdavpath = getWebdavPath(ver, supportsOAuth);
if (webdavpath == null) return null;
return baseurl + webdavpath;

View file

@ -24,8 +24,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import android.util.Log;
/**
* A helper class for some string operations.
*

View file

@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android;
import java.io.File;
@ -25,12 +26,11 @@ import java.util.List;
import java.util.Stack;
import java.util.Vector;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.accounts.AccountManager;
@ -49,7 +49,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
@ -60,7 +59,6 @@ import android.widget.SimpleAdapter;
import android.widget.Toast;
import com.owncloud.android.R;
import eu.alefzero.webdav.WebdavClient;
/**
* This can be used to upload things to an ownCloud instance.
@ -140,8 +138,8 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
// in API7 < this constatant is defined in
// Settings.ADD_ACCOUNT_SETTINGS
// and Settings.EXTRA_AUTHORITIES
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
intent.putExtra("authorities", new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
intent.putExtra("authorities", new String[] { AccountAuthenticator.AUTHORITY });
startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
} else {
// since in API7 there is no direct call for
@ -357,12 +355,13 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
public void uploadFiles() {
try {
/* 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());
// create last directory in path if necessary
if (mCreateDir) {
wdc.createDirectory(mUploadPath);
}
*/
String[] local = new String[mStreamsToUpload.size()], remote = new String[mStreamsToUpload.size()];

View file

@ -16,33 +16,46 @@
*
*/
package com.owncloud.android.authenticator;
import com.owncloud.android.Log_OC;
import com.owncloud.android.ui.activity.AuthenticatorActivity;
package com.owncloud.android.authentication;
import android.accounts.*;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.owncloud.android.Log_OC;
/**
* Authenticator for ownCloud accounts.
*
* Controller class accessed from the system AccountManager, providing integration of ownCloud accounts with the Android system.
*
* TODO - better separation in operations for OAuth-capable and regular ownCloud accounts.
* TODO - review completeness
*
* @author David A. Velasco
*/
public class AccountAuthenticator extends AbstractAccountAuthenticator {
/**
* Is used by android system to assign accounts to authenticators. Should be
* used by application and all extensions.
*/
public static final String ACCOUNT_TYPE = "owncloud";
public static final String AUTHORITY = "org.owncloud";
public static final String AUTH_TOKEN_TYPE = "org.owncloud";
public static final String AUTH_TOKEN_TYPE_PASSWORD = "owncloud.password";
public static final String AUTH_TOKEN_TYPE_ACCESS_TOKEN = "owncloud.oauth2.access_token";
public static final String AUTH_TOKEN_TYPE_REFRESH_TOKEN = "owncloud.oauth2.refresh_token";
public static final String KEY_AUTH_TOKEN_TYPE = "authTokenType";
public static final String KEY_REQUIRED_FEATURES = "requiredFeatures";
public static final String KEY_LOGIN_OPTIONS = "loginOptions";
public static final String KEY_ACCOUNT = "account";
/**
* 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.authenticator.AuthenticatorActivity.KEY_OC_BASE_URL} and
* {@link com.owncloud.android.authentication.AuthenticatorActivity.KEY_OC_BASE_URL} and
* {@link com.owncloud.android.utils.OwnCloudVersion}
*
* @deprecated
@ -58,8 +71,13 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
* http://server/path or https://owncloud.server
*/
public static final String KEY_OC_BASE_URL = "oc_base_url";
private static final String TAG = "AccountAuthenticator";
/**
* Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
*/
public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
private static final String TAG = AccountAuthenticator.class.getSimpleName();
private Context mContext;
public AccountAuthenticator(Context context) {
@ -86,55 +104,60 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
return e.getFailureBundle();
}
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
intent.putExtra(KEY_REQUIRED_FEATURES, requiredFeatures);
intent.putExtra(KEY_LOGIN_OPTIONS, options);
intent.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_CREATE);
setIntentFlags(intent);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
/**
* {@inheritDoc}
*/
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account, Bundle options) throws NetworkErrorException {
try {
validateAccountType(account.type);
} catch (AuthenticatorException e) {
Log_OC.e(TAG, "Failed to validate account type " + account.type + ": "
+ e.getMessage());
e.printStackTrace();
return e.getFailureBundle();
}
Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
intent.putExtra(KEY_ACCOUNT, account);
intent.putExtra(KEY_LOGIN_OPTIONS, options);
setIntentFlags(intent);
Bundle resultBundle = new Bundle();
resultBundle.putParcelable(AccountManager.KEY_INTENT, intent);
return resultBundle;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response,
String accountType) {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account, Bundle options) throws NetworkErrorException {
try {
validateAccountType(account.type);
} catch (AuthenticatorException e) {
Log_OC.e(TAG, "Failed to validate account type " + account.type + ": "
+ e.getMessage());
e.printStackTrace();
return e.getFailureBundle();
}
Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
intent.putExtra(KEY_ACCOUNT, account);
intent.putExtra(KEY_LOGIN_OPTIONS, options);
setIntentFlags(intent);
Bundle resultBundle = new Bundle();
resultBundle.putParcelable(AccountManager.KEY_INTENT, intent);
return resultBundle;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response,
String accountType) {
return null;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle options)
throws NetworkErrorException {
/// validate parameters
try {
validateAccountType(account.type);
validateAuthTokenType(authTokenType);
@ -144,22 +167,31 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
e.printStackTrace();
return e.getFailureBundle();
}
/// check if required token is stored
final AccountManager am = AccountManager.get(mContext);
final String password = am.getPassword(account);
if (password != null) {
String accessToken;
if (authTokenType.equals(AUTH_TOKEN_TYPE_PASSWORD)) {
accessToken = am.getPassword(account);
} else {
accessToken = am.peekAuthToken(account, authTokenType);
}
if (accessToken != null) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
result.putString(AccountManager.KEY_AUTHTOKEN, password);
result.putString(AccountManager.KEY_AUTHTOKEN, accessToken);
return result;
}
/// if not stored, return Intent to access the AuthenticatorActivity and UPDATE the token for the account
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
intent.putExtra(KEY_LOGIN_OPTIONS, options);
intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
intent.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, account);
intent.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
@ -205,8 +237,6 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
private void setIntentFlags(Intent intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
}
@ -218,65 +248,68 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
}
}
private void validateAuthTokenType(String authTokenType)
throws UnsupportedAuthTokenTypeException {
if (!authTokenType.equals(AUTH_TOKEN_TYPE)) {
throw new UnsupportedAuthTokenTypeException();
}
}
public static class AuthenticatorException extends Exception {
private static final long serialVersionUID = 1L;
private Bundle mFailureBundle;
public AuthenticatorException(int code, String errorMsg) {
mFailureBundle = new Bundle();
mFailureBundle.putInt(AccountManager.KEY_ERROR_CODE, code);
mFailureBundle
.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
}
public Bundle getFailureBundle() {
return mFailureBundle;
}
}
public static class UnsupportedAccountTypeException extends
AuthenticatorException {
private static final long serialVersionUID = 1L;
public UnsupportedAccountTypeException() {
super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"Unsupported account type");
}
}
public static class UnsupportedAuthTokenTypeException extends
AuthenticatorException {
private static final long serialVersionUID = 1L;
public UnsupportedAuthTokenTypeException() {
super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"Unsupported auth token type");
}
}
public static class UnsupportedFeaturesException extends
AuthenticatorException {
public static final long serialVersionUID = 1L;
public UnsupportedFeaturesException() {
super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"Unsupported features");
}
}
public static class AccessDeniedException extends AuthenticatorException {
public AccessDeniedException(int code, String errorMsg) {
super(AccountManager.ERROR_CODE_INVALID_RESPONSE, "Access Denied");
}
private static final long serialVersionUID = 1L;
}
}
private void validateAuthTokenType(String authTokenType)
throws UnsupportedAuthTokenTypeException {
if (!authTokenType.equals(AUTH_TOKEN_TYPE) &&
!authTokenType.equals(AUTH_TOKEN_TYPE_PASSWORD) &&
!authTokenType.equals(AUTH_TOKEN_TYPE_ACCESS_TOKEN) &&
!authTokenType.equals(AUTH_TOKEN_TYPE_REFRESH_TOKEN) ) {
throw new UnsupportedAuthTokenTypeException();
}
}
public static class AuthenticatorException extends Exception {
private static final long serialVersionUID = 1L;
private Bundle mFailureBundle;
public AuthenticatorException(int code, String errorMsg) {
mFailureBundle = new Bundle();
mFailureBundle.putInt(AccountManager.KEY_ERROR_CODE, code);
mFailureBundle
.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
}
public Bundle getFailureBundle() {
return mFailureBundle;
}
}
public static class UnsupportedAccountTypeException extends
AuthenticatorException {
private static final long serialVersionUID = 1L;
public UnsupportedAccountTypeException() {
super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"Unsupported account type");
}
}
public static class UnsupportedAuthTokenTypeException extends
AuthenticatorException {
private static final long serialVersionUID = 1L;
public UnsupportedAuthTokenTypeException() {
super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"Unsupported auth token type");
}
}
public static class UnsupportedFeaturesException extends
AuthenticatorException {
public static final long serialVersionUID = 1L;
public UnsupportedFeaturesException() {
super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"Unsupported features");
}
}
public static class AccessDeniedException extends AuthenticatorException {
public AccessDeniedException(int code, String errorMsg) {
super(AccountManager.ERROR_CODE_INVALID_RESPONSE, "Access Denied");
}
private static final long serialVersionUID = 1L;
}
}

View file

@ -16,7 +16,7 @@
*
*/
package com.owncloud.android.authenticator;
package com.owncloud.android.authentication;
import android.app.Service;
import android.content.Intent;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
/* 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.authentication;
/**
* Constant values for OAuth 2 protocol.
*
* Includes required and optional parameter NAMES used in the 'authorization code' grant type.
*
* @author David A. Velasco
*/
public class OAuth2Constants {
/// Parameters to send to the Authorization Endpoint
public static final String KEY_RESPONSE_TYPE = "response_type";
public static final String KEY_REDIRECT_URI = "redirect_uri";
public static final String KEY_CLIENT_ID = "client_id";
public static final String KEY_SCOPE = "scope";
public static final String KEY_STATE = "state";
/// Additional parameters to send to the Token Endpoint
public static final String KEY_GRANT_TYPE = "grant_type";
public static final String KEY_CODE = "code";
/// Parameters received in an OK response from the Token Endpoint
public static final String KEY_ACCESS_TOKEN = "access_token";
public static final String KEY_TOKEN_TYPE = "token_type";
public static final String KEY_EXPIRES_IN = "expires_in";
public static final String KEY_REFRESH_TOKEN = "refresh_token";
/// Parameters in an ERROR response
public static final String KEY_ERROR = "error";
public static final String KEY_ERROR_DESCRIPTION = "error_description";
public static final String KEY_ERROR_URI = "error_uri";
public static final String VALUE_ERROR_ACCESS_DENIED = "access_denied";
}

View file

@ -1,88 +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.authenticator;
import java.net.URL;
import org.apache.commons.httpclient.HttpStatus;
import com.owncloud.android.R;
import com.owncloud.android.network.OwnCloudClientUtils;
import eu.alefzero.webdav.WebdavClient;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
public class AuthenticationRunnable implements Runnable {
private OnAuthenticationResultListener mListener;
private Handler mHandler;
private URL mUrl;
private String mUsername;
private String mPassword;
private Context mContext;
public AuthenticationRunnable(URL url, String username, String password, Context context) {
mListener = null;
mUrl = url;
mUsername = username;
mPassword = password;
mContext = context;
}
public void setOnAuthenticationResultListener(
OnAuthenticationResultListener listener, Handler handler) {
mListener = listener;
mHandler = handler;
}
@Override
public void run() {
Uri uri;
uri = Uri.parse(mUrl.toString());
WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(uri, mUsername, mPassword, mContext);
int login_result = wdc.tryToLogin();
switch (login_result) {
case HttpStatus.SC_OK:
postResult(true, uri.toString());
break;
case HttpStatus.SC_UNAUTHORIZED:
postResult(false, mContext.getString(R.string.auth_unauthorized));
break;
case HttpStatus.SC_NOT_FOUND:
postResult(false, mContext.getString(R.string.auth_not_found));
break;
default:
postResult(false, String.format(mContext.getString(R.string.auth_internal), login_result));
}
}
private void postResult(final boolean success, final String message) {
if (mHandler != null && mListener != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
mListener.onAuthenticationResult(success, message);
}
});
}
}
}

View file

@ -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.authenticator;
public interface OnAuthenticationResultListener {
public void onAuthenticationResult(boolean success, String message);
}

View file

@ -1,29 +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.authenticator;
public interface OnConnectCheckListener {
enum ResultType {
OK_SSL, OK_NO_SSL, SSL_INIT_ERROR, HOST_NOT_AVAILABLE, TIMEOUT, NO_NETWORK_CONNECTION, INCORRECT_ADDRESS, INSTANCE_NOT_CONFIGURED, FILE_NOT_FOUND, UNKNOWN_ERROR, WRONG_CONNECTION, SSL_UNVERIFIED_SERVER, BAD_OC_VERSION
}
public void onConnectionCheckResult(ResultType type);
}

View file

@ -40,7 +40,6 @@ import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.util.Log;
public class FileDataStorageManager implements DataStorageManager {

View file

@ -24,7 +24,6 @@ import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
* Custom database helper for ownCloud

View file

@ -23,7 +23,6 @@ import com.owncloud.android.R;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View file

@ -35,7 +35,6 @@ import android.R;
import android.app.ListActivity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.SimpleAdapter;
public class ExtensionsListActivity extends ListActivity {

View file

@ -24,7 +24,6 @@ import com.owncloud.android.files.services.FileObserverService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class BootupBroadcastReceiver extends BroadcastReceiver {

View file

@ -20,6 +20,11 @@ package com.owncloud.android.files;
import java.io.File;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.db.DbHandler;
import com.owncloud.android.files.services.FileUploader;
import android.accounts.Account;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -32,11 +37,7 @@ import android.preference.PreferenceManager;
import android.provider.MediaStore.Images.Media;
import android.webkit.MimeTypeMap;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.Log_OC;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.db.DbHandler;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.utils.FileStorageUtils;
public class InstantUploadBroadcastReceiver extends BroadcastReceiver {

View file

@ -23,19 +23,16 @@ import java.io.File;
import com.owncloud.android.Log_OC;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.SynchronizeFileOperation;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.ui.activity.ConflictsResolveActivity;
import eu.alefzero.webdav.WebdavClient;
import android.accounts.Account;
import android.content.Context;
import android.content.Intent;
import android.os.FileObserver;
import android.util.Log;
public class OwnCloudFileObserver extends FileObserver {
@ -78,7 +75,6 @@ public class OwnCloudFileObserver extends FileObserver {
mPath);
return;
}
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mOCAccount, mContext);
FileDataStorageManager storageManager = new FileDataStorageManager(mOCAccount, mContext.getContentResolver());
OCFile file = storageManager.getFileByLocalPath(mPath); // a fresh object is needed; many things could have occurred to the file since it was registered to observe
// again, assuming that local files are linked to a remote file AT MOST, SOMETHING TO BE DONE;
@ -89,7 +85,7 @@ public class OwnCloudFileObserver extends FileObserver {
true,
true,
mContext);
RemoteOperationResult result = sfo.execute(wc);
RemoteOperationResult result = sfo.execute(mOCAccount, mContext);
if (result.getCode() == ResultCode.SYNC_CONFLICT) {
// ISSUE 5: if the user is not running the app (this is a service!), this can be very intrusive; a notification should be preferred
Intent i = new Intent(mContext, ConflictsResolveActivity.class);

View file

@ -19,6 +19,7 @@
package com.owncloud.android.files.services;
import java.io.File;
import java.io.IOException;
import java.util.AbstractList;
import java.util.HashMap;
import java.util.Iterator;
@ -27,6 +28,7 @@ import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import eu.alefzero.webdav.OnDatatransferProgressListener;
@ -34,12 +36,14 @@ import eu.alefzero.webdav.OnDatatransferProgressListener;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.DownloadFileOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.ui.activity.FileDetailActivity;
import com.owncloud.android.ui.fragment.FileDetailFragment;
import com.owncloud.android.ui.preview.PreviewImageActivity;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import android.accounts.Account;
import android.accounts.AccountsException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -113,7 +117,6 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
mBinder = new FileDownloaderBinder();
}
/**
* Entry point to add one or several files to the queue of downloads.
*
@ -256,7 +259,6 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
}
/**
* Removes a listener interested in the progress of the download for a concrete file.
*
@ -321,7 +323,6 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
}
}
/**
* Core download method: requests a file to download and stores it.
@ -338,21 +339,28 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
notifyDownloadStart(mCurrentDownload);
/// prepare client object to send the request to the ownCloud server
if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {
mLastAccount = mCurrentDownload.getAccount();
mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
mDownloadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
}
/// perform the download
RemoteOperationResult downloadResult = null;
try {
/// prepare client object to send the request to the ownCloud server
if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {
mLastAccount = mCurrentDownload.getAccount();
mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
mDownloadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
}
/// perform the download
downloadResult = mCurrentDownload.execute(mDownloadClient);
if (downloadResult.isSuccess()) {
saveDownloadedFile();
}
} catch (AccountsException e) {
Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e);
downloadResult = new RemoteOperationResult(e);
} catch (IOException e) {
Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e);
downloadResult = new RemoteOperationResult(e);
} finally {
synchronized(mPendingDownloads) {
mPendingDownloads.remove(downloadKey);
@ -455,23 +463,41 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
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());
finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
Intent showDetailsIntent = null;
if (downloadResult.isSuccess()) {
if (PreviewImageFragment.canBePreviewed(download.getFile())) {
showDetailsIntent = new Intent(this, PreviewImageActivity.class);
} else {
showDetailsIntent = new Intent(this, FileDetailActivity.class);
}
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, download.getFile());
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, download.getAccount());
showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED);
if (needsToUpdateCredentials) {
// let the user update credentials with one click
Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, download.getAccount());
updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
finalNotification.contentIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
finalNotification.setLatestEventInfo( getApplicationContext(),
getString(tickerId),
String.format(getString(contentId), new File(download.getSavePath()).getName()),
finalNotification.contentIntent);
mDownloadClient = null; // grant that future retries on the same account will get the fresh credentials
} else {
// TODO put something smart in showDetailsIntent
showDetailsIntent = new Intent();
Intent showDetailsIntent = null;
if (downloadResult.isSuccess()) {
if (PreviewImageFragment.canBePreviewed(download.getFile())) {
showDetailsIntent = new Intent(this, PreviewImageActivity.class);
} else {
showDetailsIntent = new Intent(this, FileDetailActivity.class);
}
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, download.getFile());
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, download.getAccount());
showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
} else {
// TODO put something smart in showDetailsIntent
showDetailsIntent = new Intent();
}
finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);
finalNotification.setLatestEventInfo(getApplicationContext(), getString(tickerId), String.format(getString(contentId), new File(download.getSavePath()).getName()), finalNotification.contentIntent);
}
finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);
finalNotification.setLatestEventInfo(getApplicationContext(), getString(tickerId), String.format(getString(contentId), new File(download.getSavePath()).getName()), finalNotification.contentIntent);
mNotificationManager.notify(tickerId, finalNotification);
}
}

View file

@ -40,7 +40,6 @@ import android.content.IntentFilter;
import android.database.Cursor;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class FileObserverService extends Service {

View file

@ -1,55 +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.files.services;
import java.io.File;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.content.Context;
import eu.alefzero.webdav.WebdavClient;
public class FileOperation {
Context mContext;
public FileOperation(Context contex){
this.mContext = contex;
}
/**
* Deletes a file from ownCloud - locally and remote.
* @param file The file to delete
* @return True on success, otherwise false
*/
public boolean delete(OCFile file){
Account account = AccountUtils.getCurrentOwnCloudAccount(mContext);
WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(account, mContext);
if(client.deleteFile(file.getRemotePath())){
File localFile = new File(file.getStoragePath());
return localFile.delete();
}
return false;
}
}

View file

@ -19,6 +19,7 @@
package com.owncloud.android.files.services;
import java.io.File;
import java.io.IOException;
import java.util.AbstractList;
import java.util.HashMap;
import java.util.Iterator;
@ -31,8 +32,29 @@ import org.apache.http.HttpStatus;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.operations.ChunkedUploadFileOperation;
import com.owncloud.android.operations.CreateFolderOperation;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.ui.activity.FileDetailActivity;
import com.owncloud.android.ui.fragment.FileDetailFragment;
import com.owncloud.android.utils.OwnCloudVersion;
import eu.alefzero.webdav.OnDatatransferProgressListener;
import eu.alefzero.webdav.WebdavEntry;
import eu.alefzero.webdav.WebdavUtils;
import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountsException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -47,32 +69,17 @@ import android.os.Message;
import android.os.Process;
import android.webkit.MimeTypeMap;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.db.DbHandler;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.ChunkedUploadFileOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.ui.activity.FailedUploadActivity;
import com.owncloud.android.ui.activity.FileDetailActivity;
import com.owncloud.android.ui.activity.InstantUploadActivity;
import com.owncloud.android.ui.fragment.FileDetailFragment;
import com.owncloud.android.ui.preview.PreviewImageActivity;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.OwnCloudVersion;
import eu.alefzero.webdav.OnDatatransferProgressListener;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavEntry;
import eu.alefzero.webdav.WebdavUtils;
public class FileUploader extends Service implements OnDatatransferProgressListener {
@ -490,37 +497,48 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
notifyUploadStart(mCurrentUpload);
// / prepare client object to send requests to the ownCloud server
if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) {
mLastAccount = mCurrentUpload.getAccount();
mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
mUploadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
}
// / create remote folder for instant uploads
if (mCurrentUpload.isRemoteFolderToBeCreated()) {
mUploadClient.createDirectory(FileStorageUtils.getInstantUploadFilePath(this, ""));
// ignoring result fail could just mean that it already exists,
// but local database is not synchronized the upload will be
// tried anyway
}
// / perform the upload
RemoteOperationResult uploadResult = null;
try {
/// prepare client object to send requests to the ownCloud server
if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) {
mLastAccount = mCurrentUpload.getAccount();
mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
mUploadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
}
/// create remote folder for instant uploads
if (mCurrentUpload.isRemoteFolderToBeCreated()) {
RemoteOperation operation = new CreateFolderOperation( FileStorageUtils.getInstantUploadFilePath(this, ""),
mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR).getFileId(), // TODO generalize this : INSTANT_UPLOAD_DIR could not be a child of root
mStorageManager);
operation.execute(mUploadClient); // ignoring result; fail could just mean that it already exists, but local database is not synchronized; the upload will be tried anyway
}
/// perform the upload
uploadResult = mCurrentUpload.execute(mUploadClient);
if (uploadResult.isSuccess()) {
saveUploadedFile();
}
} catch (AccountsException e) {
Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e);
uploadResult = new RemoteOperationResult(e);
} catch (IOException e) {
Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e);
uploadResult = new RemoteOperationResult(e);
} finally {
synchronized (mPendingUploads) {
mPendingUploads.remove(uploadKey);
Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
}
}
// notify result
/// notify result
notifyUploadResult(uploadResult, mCurrentUpload);
sendFinalBroadcast(mCurrentUpload, uploadResult);
@ -775,7 +793,21 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
Notification finalNotification = new Notification(R.drawable.icon,
getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis());
finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
if (uploadResult.getCode() == ResultCode.UNAUTHORIZED) {
// let the user update credentials with one click
Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, upload.getAccount());
updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
finalNotification.contentIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
mUploadClient = null; // grant that future retries on the same account will get the fresh credentials
} else {
// TODO put something smart in the contentIntent below
finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
}
String content = null;
if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL
|| uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) {

View file

@ -26,7 +26,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
public class LocationServiceLauncherReciever extends BroadcastReceiver {

View file

@ -27,7 +27,6 @@ import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import com.owncloud.android.Log_OC;

View file

@ -41,8 +41,6 @@ import org.apache.http.conn.ssl.X509HostnameVerifier;
import com.owncloud.android.Log_OC;
import android.util.Log;
/**
* AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with
* a custom SSLContext and an optional Hostname Verifier.

View file

@ -33,8 +33,6 @@ import javax.net.ssl.X509TrustManager;
import com.owncloud.android.Log_OC;
import android.util.Log;
/**
* @author David A. Velasco
*/

View file

@ -0,0 +1,268 @@
/* 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.network;
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 com.owncloud.android.Log_OC;
/**
* 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 */
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_OC.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_OC.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_OC.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");
}
}

View file

@ -0,0 +1,97 @@
/* 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.network;
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;
}
}

View file

@ -37,19 +37,24 @@ import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.Log_OC;
import eu.alefzero.webdav.WebdavClient;
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.util.Log;
import android.os.Bundle;
public class OwnCloudClientUtils {
final private static String TAG = "OwnCloudClientFactory";
final private static String TAG = OwnCloudClientUtils.class.getSimpleName();
/** Default timeout for waiting data from the server */
public static final int DEFAULT_DATA_TIMEOUT = 60000;
@ -70,46 +75,61 @@ public class OwnCloudClientUtils {
/**
* Creates a WebdavClient setup for an ownCloud account
*
* @param account The ownCloud account
* @param context The application context
* @return A WebdavClient object ready to be used
*/
public static WebdavClient createOwnCloudClient (Account account, Context context) {
Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(context, account));
WebdavClient client = createOwnCloudClient(uri, context);
String username = account.name.substring(0, account.name.lastIndexOf('@'));
String password = AccountManager.get(context).getPassword(account);
//String password = am.blockingGetAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE, true);
client.setCredentials(username, password);
return client;
}
/**
* Creates a WebdavClient to try a new account before saving it
* Do not call this method from the main thread.
*
* @param uri URL to the ownCloud server
* @param username User name
* @param password User password
* @param context Android context where the WebdavClient is being created.
* @return A WebdavClient object ready to be used
* @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.
*/
public static WebdavClient createOwnCloudClient(Uri uri, String username, String password, Context context) {
Log_OC.d(TAG, "Creating WebdavClient for " + username + "@" + uri);
public static WebdavClient createOwnCloudClient (Account account, Context appContext) throws OperationCanceledException, AuthenticatorException, IOException {
//Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
WebdavClient client = createOwnCloudClient(uri, appContext);
AccountManager am = AccountManager.get(appContext);
if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) { // TODO avoid a call to getUserData here
String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, false);
client.setBearerCredentials(accessToken); // TODO not assume that the access token is a bearer token
WebdavClient client = createOwnCloudClient(uri, context);
client.setCredentials(username, password);
} else {
String username = account.name.substring(0, account.name.lastIndexOf('@'));
//String password = am.getPassword(account);
String password = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, false);
client.setBasicCredentials(username, password);
}
return client;
}
public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException {
Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
WebdavClient client = createOwnCloudClient(uri, appContext);
AccountManager am = AccountManager.get(appContext);
if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) { // TODO avoid a call to getUserData here
AccountManagerFuture<Bundle> future = am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, null, currentActivity, null, null);
Bundle result = future.getResult();
String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
//String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, false);
if (accessToken == null) throw new AuthenticatorException("WTF!");
client.setBearerCredentials(accessToken); // TODO not assume that the access token is a bearer token
} else {
String username = account.name.substring(0, account.name.lastIndexOf('@'));
//String password = am.getPassword(account);
//String password = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, false);
AccountManagerFuture<Bundle> future = am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, 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.
*
@ -118,7 +138,7 @@ public class OwnCloudClientUtils {
* @return A WebdavClient object ready to be used
*/
public static WebdavClient createOwnCloudClient(Uri uri, Context context) {
Log_OC.d(TAG, "Creating WebdavClient for " + uri);
//Log_OC.d(TAG, "Creating WebdavClient for " + uri);
//allowSelfsignedCertificates(true);
try {
@ -244,4 +264,5 @@ public class OwnCloudClientUtils {
return mConnManager;
}
}

View file

@ -32,7 +32,6 @@ import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.network.ProgressiveDataTransferer;
import android.accounts.Account;
import android.util.Log;
import eu.alefzero.webdav.ChunkFromFileChannelRequestEntity;
import eu.alefzero.webdav.WebdavClient;

View file

@ -0,0 +1,94 @@
/* 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.jackrabbit.webdav.client.methods.MkColMethod;
import com.owncloud.android.Log_OC;
import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
/**
* Remote operation performing the creation of a new folder in the ownCloud server.
*
* @author David A. Velasco
*/
public class CreateFolderOperation extends RemoteOperation {
private static final String TAG = CreateFolderOperation.class.getSimpleName();
private static final int READ_TIMEOUT = 10000;
private static final int CONNECTION_TIMEOUT = 5000;
protected String mRemotePath;
protected long mParentDirId;
protected DataStorageManager mStorageManager;
/**
* Constructor
*
* @param remoetPath Full path to the new directory to create in the remote server.
* @param parentDirId Local database id for the parent folder.
* @param storageManager Reference to the local database corresponding to the account where the file is contained.
*/
public CreateFolderOperation(String remotePath, long parentDirId, DataStorageManager storageManager) {
mRemotePath = remotePath;
mParentDirId = parentDirId;
mStorageManager = storageManager;
}
/**
* Performs the remove operation
*
* @param client Client object to communicate with the remote ownCloud server.
*/
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
MkColMethod mkcol = null;
try {
mkcol = new MkColMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
int status = client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);
if (mkcol.succeeded()) {
// Save new directory in local database
OCFile newDir = new OCFile(mRemotePath);
newDir.setMimetype("DIR");
newDir.setParentId(mParentDirId);
mStorageManager.saveFile(newDir);
}
result = new RemoteOperationResult(mkcol.succeeded(), status);
Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
client.exhaustResponse(mkcol.getResponseBodyAsStream());
} catch (Exception e) {
result = new RemoteOperationResult(e);
Log_OC.e(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage(), e);
} finally {
if (mkcol != null)
mkcol.releaseConnection();
}
return result;
}
}

View file

@ -42,7 +42,6 @@ import eu.alefzero.webdav.OnDatatransferProgressListener;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
import android.accounts.Account;
import android.util.Log;
import android.webkit.MimeTypeMap;
/**

View file

@ -0,0 +1,94 @@
/* 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.Log_OC;
import eu.alefzero.webdav.WebdavClient;
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() + 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);
Log_OC.d(TAG, "Existence check for " + client.getBaseUri() + 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() + 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();
}
}

View file

@ -0,0 +1,174 @@
package com.owncloud.android.operations;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import com.owncloud.android.Log_OC;
import com.owncloud.android.authentication.OAuth2Constants;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import eu.alefzero.webdav.WebdavClient;
public class OAuth2GetAccessToken extends RemoteOperation {
private static final String TAG = OAuth2GetAccessToken.class.getSimpleName();
private String mClientId;
private String mRedirectUri;
private String mGrantType;
private String mOAuth2AuthorizationResponse;
private Map<String, String> mOAuth2ParsedAuthorizationResponse;
private Map<String, String> mResultTokenMap;
public OAuth2GetAccessToken(String clientId, String redirectUri, String grantType, String oAuth2AuthorizationResponse) {
mClientId = clientId;
mRedirectUri = redirectUri;
mGrantType = grantType;
mOAuth2AuthorizationResponse = oAuth2AuthorizationResponse;
mOAuth2ParsedAuthorizationResponse = new HashMap<String, String>();
mResultTokenMap = null;
}
public Map<String, String> getOauth2AutorizationResponse() {
return mOAuth2ParsedAuthorizationResponse;
}
public Map<String, String> getResultTokenMap() {
return mResultTokenMap;
}
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
PostMethod postMethod = null;
try {
parseAuthorizationResponse();
if (mOAuth2ParsedAuthorizationResponse.keySet().contains(OAuth2Constants.KEY_ERROR)) {
if (OAuth2Constants.VALUE_ERROR_ACCESS_DENIED.equals(mOAuth2ParsedAuthorizationResponse.get(OAuth2Constants.KEY_ERROR))) {
result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR_ACCESS_DENIED);
} else {
result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR);
}
}
if (result == null) {
NameValuePair[] nameValuePairs = new NameValuePair[4];
nameValuePairs[0] = new NameValuePair(OAuth2Constants.KEY_GRANT_TYPE, mGrantType);
nameValuePairs[1] = new NameValuePair(OAuth2Constants.KEY_CODE, mOAuth2ParsedAuthorizationResponse.get(OAuth2Constants.KEY_CODE));
nameValuePairs[2] = new NameValuePair(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri);
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.setRequestBody(nameValuePairs);
int status = client.executeMethod(postMethod);
String response = postMethod.getResponseBodyAsString();
if (response != null && response.length() > 0) {
JSONObject tokenJson = new JSONObject(response);
parseAccessTokenResult(tokenJson);
if (mResultTokenMap.get(OAuth2Constants.KEY_ERROR) != null || mResultTokenMap.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR);
} else {
result = new RemoteOperationResult(true, status);
}
} else {
client.exhaustResponse(postMethod.getResponseBodyAsStream());
result = new RemoteOperationResult(false, status);
}
}
} catch (Exception e) {
result = new RemoteOperationResult(e);
} finally {
if (postMethod != null)
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());
} 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());
} 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"));
} else {
Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage());
}
}
return result;
}
private void parseAuthorizationResponse() {
String[] pairs = mOAuth2AuthorizationResponse.split("&");
int i = 0;
String key = "";
String value = "";
StringBuilder sb = new StringBuilder();
while (pairs.length > i) {
int j = 0;
String[] part = pairs[i].split("=");
while (part.length > j) {
String p = part[j];
if (j == 0) {
key = p;
sb.append(key + " = ");
} else if (j == 1) {
value = p;
mOAuth2ParsedAuthorizationResponse.put(key, value);
sb.append(value + "\n");
}
Log_OC.v(TAG, "[" + i + "," + j + "] = " + p);
j++;
}
i++;
}
}
private void parseAccessTokenResult (JSONObject tokenJson) throws JSONException {
mResultTokenMap = new HashMap<String, String>();
if (tokenJson.has(OAuth2Constants.KEY_ACCESS_TOKEN)) {
mResultTokenMap.put(OAuth2Constants.KEY_ACCESS_TOKEN, tokenJson.getString(OAuth2Constants.KEY_ACCESS_TOKEN));
}
if (tokenJson.has(OAuth2Constants.KEY_TOKEN_TYPE)) {
mResultTokenMap.put(OAuth2Constants.KEY_TOKEN_TYPE, tokenJson.getString(OAuth2Constants.KEY_TOKEN_TYPE));
}
if (tokenJson.has(OAuth2Constants.KEY_EXPIRES_IN)) {
mResultTokenMap.put(OAuth2Constants.KEY_EXPIRES_IN, tokenJson.getString(OAuth2Constants.KEY_EXPIRES_IN));
}
if (tokenJson.has(OAuth2Constants.KEY_REFRESH_TOKEN)) {
mResultTokenMap.put(OAuth2Constants.KEY_REFRESH_TOKEN, tokenJson.getString(OAuth2Constants.KEY_REFRESH_TOKEN));
}
if (tokenJson.has(OAuth2Constants.KEY_SCOPE)) {
mResultTokenMap.put(OAuth2Constants.KEY_SCOPE, tokenJson.getString(OAuth2Constants.KEY_SCOPE));
}
if (tokenJson.has(OAuth2Constants.KEY_ERROR)) {
mResultTokenMap.put(OAuth2Constants.KEY_ERROR, tokenJson.getString(OAuth2Constants.KEY_ERROR));
}
if (tokenJson.has(OAuth2Constants.KEY_ERROR_DESCRIPTION)) {
mResultTokenMap.put(OAuth2Constants.KEY_ERROR_DESCRIPTION, tokenJson.getString(OAuth2Constants.KEY_ERROR_DESCRIPTION));
}
if (tokenJson.has(OAuth2Constants.KEY_ERROR_URI)) {
mResultTokenMap.put(OAuth2Constants.KEY_ERROR_URI, tokenJson.getString(OAuth2Constants.KEY_ERROR_URI));
}
}
}

View file

@ -30,21 +30,20 @@ import eu.alefzero.webdav.WebdavClient;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.util.Log;
public class ConnectionCheckOperation extends RemoteOperation {
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 = ConnectionCheckOperation.class.getSimpleName();
private static final String TAG = OwnCloudServerCheckOperation.class.getSimpleName();
private String mUrl;
private RemoteOperationResult mLatestResult;
private Context mContext;
private OwnCloudVersion mOCVersion;
public ConnectionCheckOperation(String url, Context context) {
public OwnCloudServerCheckOperation(String url, Context context) {
mUrl = url;
mContext = context;
mOCVersion = null;

View file

@ -16,6 +16,21 @@
*/
package com.owncloud.android.operations;
import java.io.IOException;
import org.apache.commons.httpclient.Credentials;
import com.owncloud.android.Log_OC;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.network.BearerCredentials;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.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 eu.alefzero.webdav.WebdavClient;
@ -29,7 +44,15 @@ import eu.alefzero.webdav.WebdavClient;
*/
public abstract class RemoteOperation implements Runnable {
/** Object to interact with the ownCloud server */
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 */
@ -38,16 +61,49 @@ public abstract class RemoteOperation implements Runnable {
/** 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 = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
} catch (Exception e) {
Log_OC.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.
*/
@ -59,6 +115,43 @@ public abstract class RemoteOperation implements Runnable {
}
/**
* 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
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;
}
/**
* Asynchronously executes the remote operation
*
@ -115,20 +208,74 @@ public abstract class RemoteOperation implements Runnable {
* 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() {
final RemoteOperationResult result = execute(mClient);
RemoteOperationResult result = null;
boolean repeat = false;
do {
try{
if (mClient == null) {
if (mAccount != null && mContext != null) {
if (mCallerActivity != null) {
mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext, mCallerActivity);
} else {
mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
}
} else {
throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
}
}
} catch (IOException e) {
Log_OC.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_OC.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) {
/// fail due to lack of authorization in an operation performed in foreground
AccountManager am = AccountManager.get(mContext);
Credentials cred = mClient.getCredentials();
if (cred instanceof BearerCredentials) {
am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken());
} 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, result);
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;
}
}

View file

@ -32,8 +32,6 @@ import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.jackrabbit.webdav.DavException;
import android.util.Log;
import com.owncloud.android.Log_OC;
import com.owncloud.android.network.CertificateCombinedException;
@ -49,10 +47,37 @@ public class RemoteOperationResult implements Serializable {
/** Generated - should be refreshed every time the class changes!! */
private static final long serialVersionUID = -7805531062432602444L;
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, SYNC_CONFLICT, LOCAL_STORAGE_FULL, LOCAL_STORAGE_NOT_MOVED, LOCAL_STORAGE_NOT_COPIED, QUOTA_EXCEEDED
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
}
private boolean mSuccess = false;

View file

@ -20,8 +20,6 @@ package com.owncloud.android.operations;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
import android.util.Log;
import com.owncloud.android.Log_OC;
import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.OCFile;

View file

@ -24,7 +24,6 @@ import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
//import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
import android.accounts.Account;
import android.util.Log;
import com.owncloud.android.Log_OC;
import com.owncloud.android.datamodel.DataStorageManager;
@ -42,7 +41,7 @@ import eu.alefzero.webdav.WebdavUtils;
*/
public class RenameFileOperation extends RemoteOperation {
private static final String TAG = RemoveFileOperation.class.getSimpleName();
private static final String TAG = RenameFileOperation.class.getSimpleName();
private static final int RENAME_READ_TIMEOUT = 10000;
private static final int RENAME_CONNECTION_TIMEOUT = 5000;

View file

@ -25,7 +25,6 @@ import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import android.accounts.Account;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.owncloud.android.Log_OC;
import com.owncloud.android.datamodel.DataStorageManager;

View file

@ -34,7 +34,6 @@ import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import android.accounts.Account;
import android.content.Context;
import android.util.Log;
import com.owncloud.android.Log_OC;
import com.owncloud.android.datamodel.DataStorageManager;

View file

@ -25,11 +25,10 @@ import org.json.JSONObject;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.util.Log;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.Log_OC;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.utils.OwnCloudVersion;

View file

@ -37,7 +37,6 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
/**
* The ContentProvider for the ownCloud App.

View file

@ -142,7 +142,7 @@ public abstract class AbstractOwnCloudSyncAdapter extends
return null;
}
protected void initClientForCurrentAccount() throws UnknownHostException {
protected void initClientForCurrentAccount() throws OperationCanceledException, AuthenticatorException, IOException {
if (AccountUtils.constructFullURLForAccount(getContext(), account) == null) {
throw new UnknownHostException();
}

View file

@ -25,7 +25,7 @@ import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.authentication.AccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountManager;

View file

@ -19,7 +19,6 @@
package com.owncloud.android.syncadapter;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -29,6 +28,7 @@ import org.apache.jackrabbit.webdav.DavException;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
@ -38,6 +38,7 @@ import com.owncloud.android.operations.UpdateOCVersionOperation;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
import android.accounts.Account;
import android.accounts.AccountsException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -47,13 +48,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.os.Bundle;
import android.util.Log;
/**
* SyncAdapter implementation for syncing sample SyncAdapter contacts to the
* platform ContactOperations provider.
*
* @author Bartek Przybylski
* @author David A. Velasco
*/
public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
@ -103,8 +104,13 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
this.setStorageManager(new FileDataStorageManager(account, getContentProvider()));
try {
this.initClientForCurrentAccount();
} catch (UnknownHostException e) {
/// the account is unknown for the Synchronization Manager. unreachable for this context; don't try this again
} catch (IOException e) {
/// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
mSyncResult.tooManyRetries = true;
notifyFailedSynchronization();
return;
} catch (AccountsException e) {
/// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
mSyncResult.tooManyRetries = true;
notifyFailedSynchronization();
return;
@ -147,7 +153,6 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
}
}
/**
* Called by system SyncManager when a synchronization is required to be cancelled.
@ -173,7 +178,6 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
mLastFailedResult = result;
}
}
/**
@ -292,12 +296,28 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
private void notifyFailedSynchronization() {
Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
// TODO put something smart in the contentIntent below
boolean needsToUpdateCredentials = (mLastFailedResult != null && mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED);
// TODO put something smart in the contentIntent below for all the possible errors
notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
notification.setLatestEventInfo(getContext().getApplicationContext(),
getContext().getString(R.string.sync_fail_ticker),
String.format(getContext().getString(R.string.sync_fail_content), getAccount().name),
notification.contentIntent);
if (needsToUpdateCredentials) {
// let the user update credentials with one click
Intent updateAccountCredentials = new Intent(getContext(), AuthenticatorActivity.class);
updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, getAccount());
updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
notification.contentIntent = PendingIntent.getActivity(getContext(), (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
notification.setLatestEventInfo(getContext().getApplicationContext(),
getContext().getString(R.string.sync_fail_ticker),
String.format(getContext().getString(R.string.sync_fail_content_unauthorized), getAccount().name),
notification.contentIntent);
} else {
notification.setLatestEventInfo(getContext().getApplicationContext(),
getContext().getString(R.string.sync_fail_ticker),
String.format(getContext().getString(R.string.sync_fail_content), getAccount().name),
notification.contentIntent);
}
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_ticker, notification);
}
@ -331,7 +351,6 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_conflicts_in_favourites_ticker, notification);
}
}
/**
* Notifies the user about local copies of files out of the ownCloud local directory that were 'forgotten' because

View file

@ -32,7 +32,6 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.ContextMenu;
import android.view.View;
import android.view.ViewGroup;
@ -49,8 +48,8 @@ import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.Log_OC;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.R;
@ -95,10 +94,10 @@ public class AccountSelectActivity extends SherlockListActivity implements
/// the account set as default changed since this activity was created
// trigger synchronization
ContentResolver.cancelSync(null, AccountAuthenticator.AUTH_TOKEN_TYPE);
ContentResolver.cancelSync(null, AccountAuthenticator.AUTHORITY);
Bundle bundle = new Bundle();
bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
ContentResolver.requestSync(AccountUtils.getCurrentOwnCloudAccount(this), AccountAuthenticator.AUTH_TOKEN_TYPE, bundle);
ContentResolver.requestSync(AccountUtils.getCurrentOwnCloudAccount(this), AccountAuthenticator.AUTHORITY, bundle);
// restart the main activity
Intent i = new Intent(this, FileDisplayActivity.class);
@ -136,7 +135,7 @@ public class AccountSelectActivity extends SherlockListActivity implements
Intent intent = new Intent(
android.provider.Settings.ACTION_ADD_ACCOUNT);
intent.putExtra("authorities",
new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
new String[] { AccountAuthenticator.AUTHORITY });
startActivity(intent);
return true;
}

View file

@ -1,609 +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.ui.activity;
import java.net.MalformedURLException;
import java.net.URL;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.Log_OC;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.authenticator.AuthenticationRunnable;
import com.owncloud.android.authenticator.OnAuthenticationResultListener;
import com.owncloud.android.authenticator.OnConnectCheckListener;
import com.owncloud.android.ui.dialog.SslValidatorDialog;
import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.ConnectionCheckOperation;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import com.owncloud.android.R;
import eu.alefzero.webdav.WebdavClient;
/**
* This Activity is used to add an ownCloud account to the App
*
* @author Bartek Przybylski
*
*/
public class AuthenticatorActivity extends AccountAuthenticatorActivity
implements OnAuthenticationResultListener, OnConnectCheckListener, OnRemoteOperationListener, OnSslValidatorListener,
OnFocusChangeListener, OnClickListener {
private static final int DIALOG_LOGIN_PROGRESS = 0;
private static final int DIALOG_SSL_VALIDATOR = 1;
private static final int DIALOG_CERT_NOT_SAVED = 2;
private static final String TAG = "AuthActivity";
private Thread mAuthThread;
private AuthenticationRunnable mAuthRunnable;
//private ConnectionCheckerRunnable mConnChkRunnable = null;
private ConnectionCheckOperation mConnChkRunnable;
private final Handler mHandler = new Handler();
private String mBaseUrl;
private static final String STATUS_TEXT = "STATUS_TEXT";
private static final String STATUS_ICON = "STATUS_ICON";
private static final String STATUS_CORRECT = "STATUS_CORRECT";
private static final String IS_SSL_CONN = "IS_SSL_CONN";
private int mStatusText, mStatusIcon;
private boolean mStatusCorrect, mIsSslConn;
private RemoteOperationResult mLastSslUntrustedServerResult;
public static final String PARAM_USERNAME = "param_Username";
public static final String PARAM_HOSTNAME = "param_Hostname";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.account_setup);
ImageView iv = (ImageView) findViewById(R.id.refreshButton);
ImageView iv2 = (ImageView) findViewById(R.id.viewPassword);
TextView tv = (TextView) findViewById(R.id.host_URL);
TextView tv2 = (TextView) findViewById(R.id.account_password);
if (savedInstanceState != null) {
mStatusIcon = savedInstanceState.getInt(STATUS_ICON);
mStatusText = savedInstanceState.getInt(STATUS_TEXT);
mStatusCorrect = savedInstanceState.getBoolean(STATUS_CORRECT);
mIsSslConn = savedInstanceState.getBoolean(IS_SSL_CONN);
setResultIconAndText(mStatusIcon, mStatusText);
findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
if (!mStatusCorrect)
iv.setVisibility(View.VISIBLE);
else
iv.setVisibility(View.INVISIBLE);
} else {
mStatusText = mStatusIcon = 0;
mStatusCorrect = false;
mIsSslConn = false;
}
iv.setOnClickListener(this);
iv2.setOnClickListener(this);
tv.setOnFocusChangeListener(this);
tv2.setOnFocusChangeListener(this);
Button b = (Button) findViewById(R.id.account_register);
if (b != null) {
b.setText(String.format(getString(R.string.auth_register), getString(R.string.app_name)));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(STATUS_ICON, mStatusIcon);
outState.putInt(STATUS_TEXT, mStatusText);
outState.putBoolean(STATUS_CORRECT, mStatusCorrect);
super.onSaveInstanceState(outState);
}
@Override
protected Dialog onCreateDialog(int id) {
Dialog dialog = null;
switch (id) {
case DIALOG_LOGIN_PROGRESS: {
ProgressDialog working_dialog = new ProgressDialog(this);
working_dialog.setMessage(getResources().getString(
R.string.auth_trying_to_login));
working_dialog.setIndeterminate(true);
working_dialog.setCancelable(true);
working_dialog
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
Log_OC.i(TAG, "Login canceled");
if (mAuthThread != null) {
mAuthThread.interrupt();
finish();
}
}
});
dialog = working_dialog;
break;
}
case DIALOG_SSL_VALIDATOR: {
dialog = SslValidatorDialog.newInstance(this, mLastSslUntrustedServerResult, this);
break;
}
case DIALOG_CERT_NOT_SAVED: {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved));
builder.setCancelable(false);
builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
};
});
dialog = builder.create();
break;
}
default:
Log_OC.e(TAG, "Incorrect dialog called with id = " + id);
}
return dialog;
}
@Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
switch (id) {
case DIALOG_LOGIN_PROGRESS:
case DIALOG_CERT_NOT_SAVED:
break;
case DIALOG_SSL_VALIDATOR: {
((SslValidatorDialog)dialog).updateResult(mLastSslUntrustedServerResult);
break;
}
default:
Log_OC.e(TAG, "Incorrect dialog called with id = " + id);
}
}
public void onAuthenticationResult(boolean success, String message) {
if (success) {
TextView username_text = (TextView) findViewById(R.id.account_username), password_text = (TextView) findViewById(R.id.account_password);
URL url;
try {
url = new URL(message);
} catch (MalformedURLException e) {
// should never happen
Log_OC.e(getClass().getName(), "Malformed URL: " + message);
return;
}
String username = username_text.getText().toString().trim();
String accountName = username + "@" + url.getHost();
if (url.getPort() >= 0) {
accountName += ":" + url.getPort();
}
Account account = new Account(accountName,
AccountAuthenticator.ACCOUNT_TYPE);
AccountManager accManager = AccountManager.get(this);
accManager.addAccountExplicitly(account, password_text.getText()
.toString(), null);
// Add this account as default in the preferences, if there is none
// already
Account defaultAccount = AccountUtils
.getCurrentOwnCloudAccount(this);
if (defaultAccount == null) {
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(this).edit();
editor.putString("select_oc_account", accountName);
editor.commit();
}
final Intent intent = new Intent();
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE,
AccountAuthenticator.ACCOUNT_TYPE);
intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
intent.putExtra(AccountManager.KEY_AUTHTOKEN,
AccountAuthenticator.ACCOUNT_TYPE);
intent.putExtra(AccountManager.KEY_USERDATA, username);
accManager.setUserData(account,
AccountAuthenticator.KEY_OC_VERSION, mConnChkRunnable
.getDiscoveredVersion().toString());
accManager.setUserData(account,
AccountAuthenticator.KEY_OC_BASE_URL, mBaseUrl);
setAccountAuthenticatorResult(intent.getExtras());
setResult(RESULT_OK, intent);
Bundle bundle = new Bundle();
bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
//getContentResolver().startSync(ProviderTableMeta.CONTENT_URI,
// bundle);
ContentResolver.requestSync(account, "org.owncloud", bundle);
/*
* if
* (mConnChkRunnable.getDiscoveredVersion().compareTo(OwnCloudVersion
* .owncloud_v2) >= 0) { Intent i = new Intent(this,
* ExtensionsAvailableActivity.class); startActivity(i); }
*/
finish();
} else {
try {
dismissDialog(DIALOG_LOGIN_PROGRESS);
} catch (IllegalArgumentException e) {
// NOTHING TO DO ; can't find out what situation that leads to the exception in this code, but user logs signal that it happens
}
TextView tv = (TextView) findViewById(R.id.account_username);
tv.setError(message + " "); // the extra spaces are a workaround for an ugly bug:
// 1. insert wrong credentials and connect
// 2. put the focus on the user name field with using hardware controls (don't touch the screen); the error is shown UNDER the field
// 3. touch the user name field; the software keyboard appears; the error popup is moved OVER the field and SHRINKED in width, losing the last word
// Seen, at least, in Android 2.x devices
}
}
public void onCancelClick(View view) {
setResult(RESULT_CANCELED);
finish();
}
public void onOkClick(View view) {
String prefix = "";
String url = ((TextView) findViewById(R.id.host_URL)).getText()
.toString().trim();
if (mIsSslConn) {
prefix = "https://";
} else {
prefix = "http://";
}
if (url.toLowerCase().startsWith("http://")
|| url.toLowerCase().startsWith("https://")) {
prefix = "";
}
continueConnection(prefix);
}
public void onRegisterClick(View view) {
Intent register = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_account_register)));
setResult(RESULT_CANCELED);
startActivity(register);
}
private void continueConnection(String prefix) {
String url = ((TextView) findViewById(R.id.host_URL)).getText()
.toString().trim();
String username = ((TextView) findViewById(R.id.account_username))
.getText().toString();
String password = ((TextView) findViewById(R.id.account_password))
.getText().toString();
if (url.endsWith("/"))
url = url.substring(0, url.length() - 1);
URL uri = null;
String webdav_path = AccountUtils.getWebdavPath(mConnChkRunnable
.getDiscoveredVersion());
if (webdav_path == null) {
onAuthenticationResult(false, getString(R.string.auth_bad_oc_version_title));
return;
}
try {
mBaseUrl = prefix + url;
String url_str = prefix + url + webdav_path;
uri = new URL(url_str);
} catch (MalformedURLException e) {
// should never happen
onAuthenticationResult(false, getString(R.string.auth_incorrect_address_title));
return;
}
showDialog(DIALOG_LOGIN_PROGRESS);
mAuthRunnable = new AuthenticationRunnable(uri, username, password, this);
mAuthRunnable.setOnAuthenticationResultListener(this, mHandler);
mAuthThread = new Thread(mAuthRunnable);
mAuthThread.start();
}
@Override
public void onConnectionCheckResult(ResultType type) {
mStatusText = mStatusIcon = 0;
mStatusCorrect = false;
String t_url = ((TextView) findViewById(R.id.host_URL)).getText()
.toString().trim().toLowerCase();
switch (type) {
case OK_SSL:
mIsSslConn = true;
mStatusIcon = android.R.drawable.ic_secure;
mStatusText = R.string.auth_secure_connection;
mStatusCorrect = true;
break;
case OK_NO_SSL:
mIsSslConn = false;
mStatusCorrect = true;
if (t_url.startsWith("http://") ) {
mStatusText = R.string.auth_connection_established;
mStatusIcon = R.drawable.ic_ok;
} else {
mStatusText = R.string.auth_nossl_plain_ok_title;
mStatusIcon = android.R.drawable.ic_partial_secure;
}
break;
case BAD_OC_VERSION:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_bad_oc_version_title;
break;
case WRONG_CONNECTION:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_wrong_connection_title;
break;
case TIMEOUT:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_timeout_title;
break;
case INCORRECT_ADDRESS:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_incorrect_address_title;
break;
case SSL_UNVERIFIED_SERVER:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_ssl_unverified_server_title;
break;
case SSL_INIT_ERROR:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_ssl_general_error_title;
break;
case HOST_NOT_AVAILABLE:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_unknown_host_title;
break;
case NO_NETWORK_CONNECTION:
mStatusIcon = R.drawable.no_network;
mStatusText = R.string.auth_no_net_conn_title;
break;
case INSTANCE_NOT_CONFIGURED:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_not_configured_title;
break;
case UNKNOWN_ERROR:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_unknown_error_title;
break;
case FILE_NOT_FOUND:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_incorrect_path_title;
break;
default:
Log_OC.e(TAG, "Incorrect connection checker result type: " + type);
}
setResultIconAndText(mStatusIcon, mStatusText);
if (!mStatusCorrect)
findViewById(R.id.refreshButton).setVisibility(View.VISIBLE);
else
findViewById(R.id.refreshButton).setVisibility(View.INVISIBLE);
findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
}
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (view.getId() == R.id.host_URL) {
if (!hasFocus) {
TextView tv = ((TextView) findViewById(R.id.host_URL));
String uri = tv.getText().toString().trim();
if (uri.length() != 0) {
setResultIconAndText(R.drawable.progress_small,
R.string.auth_testing_connection);
//mConnChkRunnable = new ConnectionCheckerRunnable(uri, this);
mConnChkRunnable = new ConnectionCheckOperation(uri, this);
//mConnChkRunnable.setListener(this, mHandler);
//mAuthThread = new Thread(mConnChkRunnable);
//mAuthThread.start();
WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(uri), this);
mAuthThread = mConnChkRunnable.execute(client, this, mHandler);
} else {
findViewById(R.id.refreshButton).setVisibility(
View.INVISIBLE);
setResultIconAndText(0, 0);
}
} else {
// avoids that the 'connect' button can be clicked if the test was previously passed
findViewById(R.id.buttonOK).setEnabled(false);
}
} else if (view.getId() == R.id.account_password) {
ImageView iv = (ImageView) findViewById(R.id.viewPassword);
if (hasFocus) {
iv.setVisibility(View.VISIBLE);
} else {
TextView v = (TextView) findViewById(R.id.account_password);
int input_type = InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_VARIATION_PASSWORD;
v.setInputType(input_type);
iv.setVisibility(View.INVISIBLE);
}
}
}
private void setResultIconAndText(int drawable_id, int text_id) {
ImageView iv = (ImageView) findViewById(R.id.action_indicator);
TextView tv = (TextView) findViewById(R.id.status_text);
if (drawable_id == 0 && text_id == 0) {
iv.setVisibility(View.INVISIBLE);
tv.setVisibility(View.INVISIBLE);
} else {
iv.setImageResource(drawable_id);
tv.setText(text_id);
iv.setVisibility(View.VISIBLE);
tv.setVisibility(View.VISIBLE);
}
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.refreshButton) {
onFocusChange(findViewById(R.id.host_URL), false);
} else if (v.getId() == R.id.viewPassword) {
EditText view = (EditText) findViewById(R.id.account_password);
int selectionStart = view.getSelectionStart();
int selectionEnd = view.getSelectionEnd();
int input_type = view.getInputType();
if ((input_type & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
input_type = InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_VARIATION_PASSWORD;
} else {
input_type = InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
}
view.setInputType(input_type);
view.setSelection(selectionStart, selectionEnd);
}
}
@Override
public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
if (operation.equals(mConnChkRunnable)) {
mStatusText = mStatusIcon = 0;
mStatusCorrect = false;
String t_url = ((TextView) findViewById(R.id.host_URL)).getText()
.toString().trim().toLowerCase();
switch (result.getCode()) {
case OK_SSL:
mIsSslConn = true;
mStatusIcon = android.R.drawable.ic_secure;
mStatusText = R.string.auth_secure_connection;
mStatusCorrect = true;
break;
case OK_NO_SSL:
case OK:
mIsSslConn = false;
mStatusCorrect = true;
if (t_url.startsWith("http://") ) {
mStatusText = R.string.auth_connection_established;
mStatusIcon = R.drawable.ic_ok;
} else {
mStatusText = R.string.auth_nossl_plain_ok_title;
mStatusIcon = android.R.drawable.ic_partial_secure;
}
break;
case BAD_OC_VERSION:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_bad_oc_version_title;
break;
case WRONG_CONNECTION:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_wrong_connection_title;
break;
case TIMEOUT:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_timeout_title;
break;
case INCORRECT_ADDRESS:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_incorrect_address_title;
break;
case SSL_RECOVERABLE_PEER_UNVERIFIED:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_ssl_unverified_server_title;
mLastSslUntrustedServerResult = result;
showDialog(DIALOG_SSL_VALIDATOR);
break;
case SSL_ERROR:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_ssl_general_error_title;
break;
case HOST_NOT_AVAILABLE:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_unknown_host_title;
break;
case NO_NETWORK_CONNECTION:
mStatusIcon = R.drawable.no_network;
mStatusText = R.string.auth_no_net_conn_title;
break;
case INSTANCE_NOT_CONFIGURED:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_not_configured_title;
break;
case FILE_NOT_FOUND:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_incorrect_path_title;
break;
case UNHANDLED_HTTP_CODE:
case UNKNOWN_ERROR:
mStatusIcon = R.drawable.common_error;
mStatusText = R.string.auth_unknown_error_title;
break;
default:
Log_OC.e(TAG, "Incorrect connection checker result type: " + result.getHttpCode());
}
setResultIconAndText(mStatusIcon, mStatusText);
if (!mStatusCorrect)
findViewById(R.id.refreshButton).setVisibility(View.VISIBLE);
else
findViewById(R.id.refreshButton).setVisibility(View.INVISIBLE);
findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
}
}
public void onSavedCertificate() {
mAuthThread = mConnChkRunnable.retry(this, mHandler);
}
@Override
public void onFailedSavingCertificate() {
showDialog(DIALOG_CERT_NOT_SAVED);
}
}

View file

@ -28,7 +28,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;

View file

@ -1,3 +1,20 @@
/* 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.ui.activity;
import android.app.Activity;
@ -14,18 +31,7 @@ import com.owncloud.android.R;
*
* The entry-point for this activity is the 'Failed upload Notification"
*
*
* @author andomaex / Matthias Baumann
*
* 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 3 of the License. (at
* your option) any later version.
*
* 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 de/
*/
public class FailedUploadActivity extends Activity {

View file

@ -31,7 +31,6 @@ import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;

View file

@ -23,7 +23,6 @@ import java.io.File;
import android.accounts.Account;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@ -35,8 +34,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageInfo;
import android.content.res.Resources.NotFoundException;
import android.database.Cursor;
import android.net.Uri;
@ -47,11 +44,9 @@ import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@ -65,7 +60,7 @@ import com.actionbarsherlock.view.Window;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
@ -74,7 +69,7 @@ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileObserverService;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.CreateFolderOperation;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
@ -83,7 +78,6 @@ import com.owncloud.android.operations.RenameFileOperation;
import com.owncloud.android.operations.SynchronizeFileOperation;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.syncadapter.FileSyncService;
import com.owncloud.android.ui.dialog.ChangelogDialog;
import com.owncloud.android.ui.dialog.EditNameDialog;
import com.owncloud.android.ui.dialog.SslValidatorDialog;
import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
@ -95,8 +89,6 @@ import com.owncloud.android.ui.preview.PreviewImageActivity;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.ui.preview.PreviewMediaFragment;
import eu.alefzero.webdav.WebdavClient;
/**
* Displays, what files the user has available in his ownCloud.
*
@ -126,13 +118,10 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
private boolean mBackFromCreatingFirstAccount;
private static final int DIALOG_SETUP_ACCOUNT = 0;
private static final int DIALOG_CREATE_DIR = 1;
public static final int DIALOG_SHORT_WAIT = 3;
private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 4;
private static final int DIALOG_SSL_VALIDATOR = 5;
private static final int DIALOG_CERT_NOT_SAVED = 6;
private static final String DIALOG_CHANGELOG_TAG = "DIALOG_CHANGELOG";
public static final int DIALOG_SHORT_WAIT = 1;
private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 2;
private static final int DIALOG_SSL_VALIDATOR = 3;
private static final int DIALOG_CERT_NOT_SAVED = 4;
private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
private static final int ACTION_SELECT_MULTIPLE_FILES = 2;
@ -147,6 +136,8 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
Log_OC.d(getClass().toString(), "onCreate() start");
super.onCreate(savedInstanceState);
mHandler = new Handler();
/// Load of parameters from received intent
Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
if (account != null && AccountUtils.setCurrentOwnCloudAccount(this, account.name)) {
@ -233,46 +224,18 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
setSupportProgressBarIndeterminateVisibility(false); // always AFTER setContentView(...) ; to workaround bug in its implementation
// show changelog, if needed
//showChangeLog();
mBackFromCreatingFirstAccount = false;
Log_OC.d(getClass().toString(), "onCreate() end");
}
/**
* Shows a dialog with the change log of the current version after each app update
*
* TODO make it permanent; by now, only to advice the workaround app for 4.1.x
*/
private void showChangeLog() {
if (android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.JELLY_BEAN) {
final String KEY_VERSION = "version";
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
int currentVersionNumber = 0;
int savedVersionNumber = sharedPref.getInt(KEY_VERSION, 0);
try {
PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0);
currentVersionNumber = pi.versionCode;
} catch (Exception e) {}
if (currentVersionNumber > savedVersionNumber) {
ChangelogDialog.newInstance(true).show(getSupportFragmentManager(), DIALOG_CHANGELOG_TAG);
Editor editor = sharedPref.edit();
editor.putInt(KEY_VERSION, currentVersionNumber);
editor.commit();
}
}
}
/**
* Launches the account creation activity. To use when no ownCloud account is available
*/
private void createFirstAccount() {
Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
intent.putExtra(android.provider.Settings.EXTRA_AUTHORITIES, new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
intent.putExtra(android.provider.Settings.EXTRA_AUTHORITIES, new String[] { AccountAuthenticator.AUTHORITY });
startActivity(intent); // the new activity won't be created until this.onStart() and this.onResume() are finished;
}
@ -386,12 +349,12 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
}
private void startSynchronization() {
ContentResolver.cancelSync(null, AccountAuthenticator.AUTH_TOKEN_TYPE); // cancel the current synchronizations of any ownCloud account
ContentResolver.cancelSync(null, AccountAuthenticator.AUTHORITY); // cancel the current synchronizations of any ownCloud account
Bundle bundle = new Bundle();
bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
ContentResolver.requestSync(
AccountUtils.getCurrentOwnCloudAccount(this),
AccountAuthenticator.AUTH_TOKEN_TYPE, bundle);
AccountAuthenticator.AUTHORITY, bundle);
}
@ -545,7 +508,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
outState.putParcelable(FileDetailActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
Log_OC.d(getClass().toString(), "onSaveInstanceState() end");
}
@Override
protected void onResume() {
@ -651,53 +613,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
dialog = builder.create();
break;
}
case DIALOG_CREATE_DIR: {
builder = new Builder(this);
final EditText dirNameInput = new EditText(getBaseContext());
builder.setView(dirNameInput);
builder.setTitle(R.string.uploader_info_dirname);
int typed_color = getResources().getColor(R.color.setup_text_typed);
dirNameInput.setTextColor(typed_color);
builder.setPositiveButton(android.R.string.ok,
new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String directoryName = dirNameInput.getText().toString();
if (directoryName.trim().length() == 0) {
dialog.cancel();
return;
}
// Figure out the path where the dir needs to be created
String path;
if (mCurrentDir == null) {
// this is just a patch; we should ensure that mCurrentDir never is null
if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
mStorageManager.saveFile(file);
}
mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
}
path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
// Create directory
path += directoryName + OCFile.PATH_SEPARATOR;
Thread thread = new Thread(new DirectoryCreator(path, AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
thread.start();
dialog.dismiss();
showDialog(DIALOG_SHORT_WAIT);
}
});
builder.setNegativeButton(R.string.common_cancel,
new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog = builder.create();
break;
}
case DIALOG_SHORT_WAIT: {
ProgressDialog working_dialog = new ProgressDialog(this);
working_dialog.setMessage(getResources().getString(
@ -818,57 +733,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
return !mDirectories.isEmpty();
}
private class DirectoryCreator implements Runnable {
private String mTargetPath;
private Account mAccount;
private Handler mHandler;
public DirectoryCreator(String targetPath, Account account, Handler handler) {
mTargetPath = targetPath;
mAccount = account;
mHandler = handler;
}
@Override
public void run() {
WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
boolean created = wdc.createDirectory(mTargetPath);
if (created) {
mHandler.post(new Runnable() {
@Override
public void run() {
dismissDialog(DIALOG_SHORT_WAIT);
// Save new directory in local database
OCFile newDir = new OCFile(mTargetPath);
newDir.setMimetype("DIR");
newDir.setParentId(mCurrentDir.getFileId());
mStorageManager.saveFile(newDir);
// Display the new folder right away
mFileList.listDirectory();
}
});
} else {
mHandler.post(new Runnable() {
@Override
public void run() {
dismissDialog(DIALOG_SHORT_WAIT);
try {
Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG);
msg.show();
} catch (NotFoundException e) {
Log_OC.e(TAG, "Error while trying to show fail message ", e);
}
}
});
}
}
}
// Custom array adapter to override text colors
private class CustomArrayAdapter<T> extends ArrayAdapter<T> {
@ -1283,6 +1147,9 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
} else if (operation instanceof SynchronizeFileOperation) {
onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);
} else if (operation instanceof CreateFolderOperation) {
onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
}
}
@ -1322,6 +1189,30 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
}
}
/**
* Updates the view associated to the activity after the finish of an operation trying create a new folder
*
* @param operation Creation operation performed.
* @param result Result of the creation.
*/
private void onCreateFolderOperationFinish(CreateFolderOperation operation, RemoteOperationResult result) {
if (result.isSuccess()) {
dismissDialog(DIALOG_SHORT_WAIT);
mFileList.listDirectory();
} else {
dismissDialog(DIALOG_SHORT_WAIT);
try {
Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG);
msg.show();
} catch (NotFoundException e) {
Log_OC.e(TAG, "Error while trying to show fail message " , e);
}
}
}
/**
* Updates the view associated to the activity after the finish of an operation trying to rename a
* file.
@ -1430,7 +1321,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
//dialog.dismiss();
if (dialog.getResult()) {
String newDirectoryName = dialog.getNewFilename().trim();
Log.d(TAG, "'create directory' dialog dismissed with new name " + newDirectoryName);
Log_OC.d(TAG, "'create directory' dialog dismissed with new name " + newDirectoryName);
if (newDirectoryName.length() > 0) {
String path;
if (mCurrentDir == null) {
@ -1445,14 +1336,19 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
// Create directory
path += newDirectoryName + OCFile.PATH_SEPARATOR;
Thread thread = new Thread(new DirectoryCreator(path, AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
thread.start();
RemoteOperation operation = new CreateFolderOperation(path, mCurrentDir.getFileId(), mStorageManager);
operation.execute( AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this),
FileDisplayActivity.this,
FileDisplayActivity.this,
mHandler,
FileDisplayActivity.this);
showDialog(DIALOG_SHORT_WAIT);
}
}
}
private void requestForDownload() {
Account account = AccountUtils.getCurrentOwnCloudAccount(this);
if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {

View file

@ -2,8 +2,8 @@
* 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 as published by
* the Free Software Foundation, either version 3 of the License.
* 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
@ -26,7 +26,6 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.View;
@ -59,16 +58,6 @@ import com.owncloud.android.utils.FileStorageUtils;
* sub-menu underneath the 'Upload' menu-item
*
* @author andomaex / Matthias Baumann
*
* 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 3 of the License. (at
* your option) any later version.
*
* 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 de/
*/
public class InstantUploadActivity extends Activity {
@ -363,7 +352,7 @@ public class InstantUploadActivity extends Activity {
@Override
public boolean onLongClick(View v) {
Log.d(LOG_TAG, message);
Log_OC.d(LOG_TAG, message);
Toast toast = Toast.makeText(InstantUploadActivity.this, getString(R.string.failed_upload_retry_text)
+ message, Toast.LENGTH_LONG);
toast.show();

View file

@ -17,7 +17,7 @@
package com.owncloud.android.ui.activity;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.ui.adapter.LandingScreenAdapter;
import android.accounts.Account;
@ -112,9 +112,9 @@ public class LandingActivity extends SherlockFragmentActivity implements
dialog.dismiss();
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
intent.putExtra("authorities",
new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
new String[] { AccountAuthenticator.AUTHORITY });
startActivity(intent);
break;
case DialogInterface.BUTTON_NEGATIVE:

View file

@ -25,7 +25,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;

View file

@ -31,7 +31,6 @@ import javax.security.auth.x500.X500Principal;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;

View file

@ -22,7 +22,6 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import com.actionbarsherlock.app.SherlockDialogFragment;
import com.owncloud.android.Log_OC;

View file

@ -19,24 +19,8 @@ package com.owncloud.android.ui.fragment;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import org.json.JSONObject;
import android.accounts.Account;
import android.accounts.AccountManager;
//import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@ -47,7 +31,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@ -60,42 +43,15 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Point;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.DisplayUtils;
import com.owncloud.android.Log_OC;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
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.network.OwnCloudClientUtils;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
@ -108,15 +64,12 @@ import com.owncloud.android.ui.activity.FileDetailActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.dialog.EditNameDialog;
import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.utils.OwnCloudVersion;
import com.owncloud.android.R;
import eu.alefzero.webdav.OnDatatransferProgressListener;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
/**
* This Fragment is used to display the details about a file.
*
@ -163,7 +116,6 @@ public class FileDetailFragment extends SherlockFragment implements
mProgressListener = null;
}
/**
* Creates a details fragment.
*
@ -289,57 +241,58 @@ public class FileDetailFragment extends SherlockFragment implements
}
@Override
public View getView() {
return super.getView() == null ? mView : super.getView();
}
@Override
public View getView() {
return super.getView() == null ? mView : super.getView();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.fdDownloadBtn: {
FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
downloaderBinder.cancel(mAccount, mFile);
if (mFile.isDown()) {
setButtonsForDown();
} else {
setButtonsForRemote();
}
} else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {
uploaderBinder.cancel(mAccount, mFile);
if (!mFile.fileExists()) {
// TODO make something better
if (getActivity() instanceof FileDisplayActivity) {
// double pane
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FTAG); // empty FileDetailFragment
transaction.commit();
mContainerActivity.onFileStateChanged();
} else {
getActivity().finish();
}
} else if (mFile.isDown()) {
setButtonsForDown();
} else {
setButtonsForRemote();
}
} else {
mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
mLastRemoteOperation.execute(wc, this, mHandler);
// update ui
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
}
break;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.fdDownloadBtn: {
FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
downloaderBinder.cancel(mAccount, mFile);
if (mFile.isDown()) {
setButtonsForDown();
} else {
setButtonsForRemote();
}
} else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {
uploaderBinder.cancel(mAccount, mFile);
if (!mFile.fileExists()) {
// TODO make something better
if (getActivity() instanceof FileDisplayActivity) {
// double pane
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FTAG); // empty FileDetailFragment
transaction.commit();
mContainerActivity.onFileStateChanged();
} else {
getActivity().finish();
}
} else if (mFile.isDown()) {
setButtonsForDown();
} else {
setButtonsForRemote();
}
} else {
mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
// update ui
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
setButtonsForTransferring(); // disable button immediately, although the synchronization does not result in a file transference
}
break;
}
case R.id.fdKeepInSync: {
CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);
mFile.setKeepInSync(cb.isChecked());
@ -389,13 +342,8 @@ public class FileDetailFragment extends SherlockFragment implements
Log_OC.e(TAG, "Incorrect view clicked!");
}
/* else if (v.getId() == R.id.fdShareBtn) {
Thread t = new Thread(new ShareRunnable(mFile.getRemotePath()));
t.start();
}*/
}
}
/**
* Opens mFile.
*/
@ -410,7 +358,7 @@ public class FileDetailFragment extends SherlockFragment implements
startActivity(i);
} catch (Throwable t) {
Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
boolean toastIt = true;
String mimeType = "";
try {
@ -429,13 +377,13 @@ public class FileDetailFragment extends SherlockFragment implements
}
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
} catch (Throwable th) {
Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
} finally {
if (toastIt) {
@ -446,7 +394,6 @@ public class FileDetailFragment extends SherlockFragment implements
}
}
@Override
public void onConfirmation(String callerTag) {
if (callerTag.equals(FTAG_CONFIRMATION)) {
@ -454,8 +401,7 @@ public class FileDetailFragment extends SherlockFragment implements
mLastRemoteOperation = new RemoveFileOperation( mFile,
true,
mStorageManager);
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
mLastRemoteOperation.execute(wc, this, mHandler);
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
@ -476,7 +422,7 @@ public class FileDetailFragment extends SherlockFragment implements
@Override
public void onCancel(String callerTag) {
Log.d(TAG, "REMOVAL CANCELED");
Log_OC.d(TAG, "REMOVAL CANCELED");
}
@ -567,7 +513,6 @@ public class FileDetailFragment extends SherlockFragment implements
getView().invalidate();
}
/**
* Checks if the fragment is ready to show details of a OCFile
*
@ -769,120 +714,15 @@ public class FileDetailFragment extends SherlockFragment implements
}
// this is a temporary class for sharing purposes, it need to be replaced in transfer service
@SuppressWarnings("unused")
private class ShareRunnable implements Runnable {
private String mPath;
public ShareRunnable(String path) {
mPath = path;
}
public void run() {
AccountManager am = AccountManager.get(getActivity());
Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(account, AccountAuthenticator.KEY_OC_VERSION));
String url = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + AccountUtils.getWebdavPath(ocv);
Log.d("share", "sharing for version " + ocv.toString());
if (ocv.compareTo(new OwnCloudVersion(0x040000)) >= 0) {
String APPS_PATH = "/apps/files_sharing/";
String SHARE_PATH = "ajax/share.php";
String SHARED_PATH = "/apps/files_sharing/get.php?token=";
final String WEBDAV_SCRIPT = "webdav.php";
final String WEBDAV_FILES_LOCATION = "/files/";
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getActivity().getApplicationContext());
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setMaxConnectionsPerHost(wc.getHostConfiguration(), 5);
//wc.getParams().setParameter("http.protocol.single-cookie-header", true);
//wc.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
PostMethod post = new PostMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + APPS_PATH + SHARE_PATH);
post.addRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8" );
post.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
Log.d("share", mPath+"");
formparams.add(new BasicNameValuePair("sources",mPath));
formparams.add(new BasicNameValuePair("uid_shared_with", "public"));
formparams.add(new BasicNameValuePair("permissions", "0"));
post.setRequestEntity(new StringRequestEntity(URLEncodedUtils.format(formparams, HTTP.UTF_8)));
int status;
try {
PropFindMethod find = new PropFindMethod(url+"/");
find.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
Log.d("sharer", ""+ url+"/");
for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {
Log.d("sharer-h", a.getName() + ":"+a.getValue());
}
int status2 = wc.executeMethod(find);
Log.d("sharer", "propstatus "+status2);
GetMethod get = new GetMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + "/");
get.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
status2 = wc.executeMethod(get);
Log.d("sharer", "getstatus "+status2);
Log.d("sharer", "" + get.getResponseBodyAsString());
for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {
Log.d("sharer", a.getName() + ":"+a.getValue());
}
status = wc.executeMethod(post);
for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {
Log.d("sharer-h", a.getName() + ":"+a.getValue());
}
for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {
Log.d("sharer", a.getName() + ":"+a.getValue());
}
String resp = post.getResponseBodyAsString();
Log.d("share", ""+post.getURI().toString());
Log.d("share", "returned status " + status);
Log.d("share", " " +resp);
if(status != HttpStatus.SC_OK ||resp == null || resp.equals("") || resp.startsWith("false")) {
return;
}
JSONObject jsonObject = new JSONObject (resp);
String jsonStatus = jsonObject.getString("status");
if(!jsonStatus.equals("success")) throw new Exception("Error while sharing file status != success");
String token = jsonObject.getString("data");
String uri = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + SHARED_PATH + token;
Log.d("Actions:shareFile ok", "url: " + uri);
} catch (Exception e) {
e.printStackTrace();
}
} else if (ocv.compareTo(new OwnCloudVersion(0x030000)) >= 0) {
}
}
}
public void onDismiss(EditNameDialog dialog) {
if (dialog.getResult()) {
String newFilename = dialog.getNewFilename();
Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename);
mLastRemoteOperation = new RenameFileOperation( mFile,
mAccount,
newFilename,
new FileDataStorageManager(mAccount, getActivity().getContentResolver()));
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
mLastRemoteOperation.execute(wc, this, mHandler);
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
}
@ -998,7 +838,7 @@ public class FileDetailFragment extends SherlockFragment implements
}
}
public void listenForTransferProgress() {
if (mProgressListener != null) {
if (mContainerActivity.getFileDownloaderBinder() != null) {
@ -1057,4 +897,110 @@ public class FileDetailFragment extends SherlockFragment implements
};
}
/*
// this is a temporary class for sharing purposes, it need to be replaced in transfer service
@SuppressWarnings("unused")
private class ShareRunnable implements Runnable {
private String mPath;
public ShareRunnable(String path) {
mPath = path;
}
public void run() {
AccountManager am = AccountManager.get(getActivity());
Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(account, AccountAuthenticator.KEY_OC_VERSION));
String url = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + AccountUtils.getWebdavPath(ocv);
Log_OC.d("share", "sharing for version " + ocv.toString());
if (ocv.compareTo(new OwnCloudVersion(0x040000)) >= 0) {
String APPS_PATH = "/apps/files_sharing/";
String SHARE_PATH = "ajax/share.php";
String SHARED_PATH = "/apps/files_sharing/get.php?token=";
final String WEBDAV_SCRIPT = "webdav.php";
final String WEBDAV_FILES_LOCATION = "/files/";
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getActivity().getApplicationContext());
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setMaxConnectionsPerHost(wc.getHostConfiguration(), 5);
//wc.getParams().setParameter("http.protocol.single-cookie-header", true);
//wc.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
PostMethod post = new PostMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + APPS_PATH + SHARE_PATH);
post.addRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8" );
post.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
Log_OC.d("share", mPath+"");
formparams.add(new BasicNameValuePair("sources",mPath));
formparams.add(new BasicNameValuePair("uid_shared_with", "public"));
formparams.add(new BasicNameValuePair("permissions", "0"));
post.setRequestEntity(new StringRequestEntity(URLEncodedUtils.format(formparams, HTTP.UTF_8)));
int status;
try {
PropFindMethod find = new PropFindMethod(url+"/");
find.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
Log_OC.d("sharer", ""+ url+"/");
for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {
Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
}
int status2 = wc.executeMethod(find);
Log_OC.d("sharer", "propstatus "+status2);
GetMethod get = new GetMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + "/");
get.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
status2 = wc.executeMethod(get);
Log_OC.d("sharer", "getstatus "+status2);
Log_OC.d("sharer", "" + get.getResponseBodyAsString());
for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {
Log_OC.d("sharer", a.getName() + ":"+a.getValue());
}
status = wc.executeMethod(post);
for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {
Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
}
for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {
Log_OC.d("sharer", a.getName() + ":"+a.getValue());
}
String resp = post.getResponseBodyAsString();
Log_OC.d("share", ""+post.getURI().toString());
Log_OC.d("share", "returned status " + status);
Log_OC.d("share", " " +resp);
if(status != HttpStatus.SC_OK ||resp == null || resp.equals("") || resp.startsWith("false")) {
return;
}
JSONObject jsonObject = new JSONObject (resp);
String jsonStatus = jsonObject.getString("status");
if(!jsonStatus.equals("success")) throw new Exception("Error while sharing file status != success");
String token = jsonObject.getString("data");
String uri = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + SHARED_PATH + token;
Log_OC.d("Actions:shareFile ok", "url: " + uri);
} catch (Exception e) {
e.printStackTrace();
}
} else if (ocv.compareTo(new OwnCloudVersion(0x030000)) >= 0) {
}
}
}
*/
}

View file

@ -25,7 +25,6 @@ import com.owncloud.android.ui.adapter.LocalFileListAdapter;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;

View file

@ -28,7 +28,6 @@ import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoveFileOperation;
@ -42,7 +41,6 @@ import com.owncloud.android.ui.dialog.EditNameDialog;
import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
import android.accounts.Account;
@ -52,7 +50,6 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
@ -317,8 +314,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
case R.id.action_download_file: {
Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, false, getSherlockActivity());
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getSherlockActivity().getApplicationContext());
operation.execute(wc, mContainerActivity, mHandler);
operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
getSherlockActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
return true;
}
@ -484,8 +480,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
AccountUtils.getCurrentOwnCloudAccount(getActivity()),
newFilename,
mContainerActivity.getStorageManager());
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
operation.execute(wc, mContainerActivity, mHandler);
operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
}
}
@ -498,8 +493,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
RemoteOperation operation = new RemoveFileOperation( mTargetFile,
true,
mContainerActivity.getStorageManager());
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
operation.execute(wc, mContainerActivity, mHandler);
operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
}

View file

@ -3,8 +3,8 @@
* 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 as published by
* the Free Software Foundation, either version 3 of the License.
* 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
@ -23,7 +23,6 @@ import android.accounts.Account;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@ -38,6 +37,7 @@ import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import eu.alefzero.webdav.OnDatatransferProgressListener;
@ -239,7 +239,7 @@ public class FileDownloadFragment extends SherlockFragment implements OnClickLis
break;
}
default:
Log.e(TAG, "Incorrect view clicked!");
Log_OC.e(TAG, "Incorrect view clicked!");
}
}

View file

@ -16,8 +16,6 @@
*/
package com.owncloud.android.ui.preview;
import org.apache.commons.httpclient.methods.PostMethod;
import android.accounts.Account;
import android.app.Dialog;
import android.app.ProgressDialog;
@ -29,9 +27,7 @@ import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
@ -52,6 +48,7 @@ import com.owncloud.android.ui.fragment.FileDetailFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
/**
@ -170,12 +167,12 @@ public class PreviewImageActivity extends SherlockFragmentActivity implements Fi
mDownloaderBinder = (FileDownloaderBinder) service;
if (mRequestWaitingForBinder) {
mRequestWaitingForBinder = false;
Log.d(TAG, "Simulating reselection of current page after connection of download binder");
Log_OC.d(TAG, "Simulating reselection of current page after connection of download binder");
onPageSelected(mViewPager.getCurrentItem());
}
} else if (component.equals(new ComponentName(PreviewImageActivity.this, FileUploader.class))) {
Log.d(TAG, "Upload service connected");
Log_OC.d(TAG, "Upload service connected");
mUploaderBinder = (FileUploaderBinder) service;
} else {
return;
@ -186,10 +183,10 @@ public class PreviewImageActivity extends SherlockFragmentActivity implements Fi
@Override
public void onServiceDisconnected(ComponentName component) {
if (component.equals(new ComponentName(PreviewImageActivity.this, FileDownloader.class))) {
Log.d(TAG, "Download service suddenly disconnected");
Log_OC.d(TAG, "Download service suddenly disconnected");
mDownloaderBinder = null;
} else if (component.equals(new ComponentName(PreviewImageActivity.this, FileUploader.class))) {
Log.d(TAG, "Upload service suddenly disconnected");
Log_OC.d(TAG, "Upload service suddenly disconnected");
mUploaderBinder = null;
}
}
@ -328,7 +325,7 @@ public class PreviewImageActivity extends SherlockFragmentActivity implements Fi
private void requestForDownload(OCFile file) {
if (mDownloaderBinder == null) {
Log.d(TAG, "requestForDownload called without binder to download service");
Log_OC.d(TAG, "requestForDownload called without binder to download service");
} else if (!mDownloaderBinder.isDownloading(mAccount, file)) {
Intent i = new Intent(this, FileDownloader.class);
@ -413,7 +410,7 @@ public class PreviewImageActivity extends SherlockFragmentActivity implements Fi
mPreviewImagePagerAdapter.notifyDataSetChanged(); // will trigger the creation of new fragments
} else {
Log.d(TAG, "Download finished, but the fragment is offscreen");
Log_OC.d(TAG, "Download finished, but the fragment is offscreen");
}
}

View file

@ -36,7 +36,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
@ -54,7 +53,6 @@ import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
@ -62,8 +60,8 @@ import com.owncloud.android.operations.RemoveFileOperation;
import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
@ -339,7 +337,7 @@ public class PreviewImageFragment extends SherlockFragment implements FileFrag
startActivity(i);
} catch (Throwable t) {
Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
boolean toastIt = true;
String mimeType = "";
try {
@ -358,13 +356,13 @@ public class PreviewImageFragment extends SherlockFragment implements FileFrag
}
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
} catch (Throwable th) {
Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
} finally {
if (toastIt) {
@ -404,8 +402,7 @@ public class PreviewImageFragment extends SherlockFragment implements FileFrag
mLastRemoteOperation = new RemoveFileOperation( mFile, // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters
true,
mStorageManager);
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
mLastRemoteOperation.execute(wc, this, mHandler);
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
getActivity().showDialog(PreviewImageActivity.DIALOG_SHORT_WAIT);
}
@ -557,24 +554,24 @@ public class PreviewImageFragment extends SherlockFragment implements FileFrag
// really load the bitmap
options.inJustDecodeBounds = false; // the next decodeFile call will be real
result = BitmapFactory.decodeFile(storagePath, options);
//Log.d(TAG, "Image loaded - width: " + options.outWidth + ", loaded height: " + options.outHeight);
//Log_OC.d(TAG, "Image loaded - width: " + options.outWidth + ", loaded height: " + options.outHeight);
if (result == null) {
mErrorMessageId = R.string.preview_image_error_unknown_format;
Log.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
Log_OC.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
}
} catch (OutOfMemoryError e) {
mErrorMessageId = R.string.preview_image_error_unknown_format;
Log.e(TAG, "Out of memory occured for file " + storagePath, e);
Log_OC.e(TAG, "Out of memory occured for file " + storagePath, e);
} catch (NoSuchFieldError e) {
mErrorMessageId = R.string.common_error_unknown;
Log.e(TAG, "Error from access to unexisting field despite protection; file " + storagePath, e);
Log_OC.e(TAG, "Error from access to unexisting field despite protection; file " + storagePath, e);
} catch (Throwable t) {
mErrorMessageId = R.string.common_error_unknown;
Log.e(TAG, "Unexpected error loading " + mFile.getStoragePath(), t);
Log_OC.e(TAG, "Unexpected error loading " + mFile.getStoragePath(), t);
}
return result;

View file

@ -16,7 +16,6 @@
*/
package com.owncloud.android.ui.preview;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -24,16 +23,9 @@ import java.util.Set;
import java.util.Vector;
import android.accounts.Account;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.owncloud.android.datamodel.DataStorageManager;

View file

@ -39,7 +39,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@ -59,7 +58,6 @@ 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.network.OwnCloudClientUtils;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
@ -70,8 +68,8 @@ import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
import com.owncloud.android.ui.fragment.FileDetailFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
/**
@ -354,7 +352,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
*/
@Override
public void onPrepared(MediaPlayer vp) {
Log.e(TAG, "onPrepared");
Log_OC.e(TAG, "onPrepared");
mVideoPreview.seekTo(mSavedPlaybackPosition);
if (mAutoplay) {
mVideoPreview.start();
@ -373,7 +371,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
*/
@Override
public void onCompletion(MediaPlayer mp) {
Log.e(TAG, "completed");
Log_OC.e(TAG, "completed");
if (mp != null) {
mVideoPreview.seekTo(0);
// next lines are necessary to work around undesired video loops
@ -428,7 +426,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
super.onStop();
if (mMediaServiceConnection != null) {
Log.d(TAG, "Unbinding from MediaService ...");
Log_OC.d(TAG, "Unbinding from MediaService ...");
if (mMediaServiceBinder != null && mMediaController != null) {
mMediaServiceBinder.unregisterMediaController(mMediaController);
}
@ -471,7 +469,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
private void playAudio() {
if (!mMediaServiceBinder.isPlaying(mFile)) {
Log.d(TAG, "starting playback of " + mFile.getStoragePath());
Log_OC.d(TAG, "starting playback of " + mFile.getStoragePath());
mMediaServiceBinder.start(mAccount, mFile, mAutoplay, mSavedPlaybackPosition);
} else {
@ -484,7 +482,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
private void bindMediaService() {
Log.d(TAG, "Binding to MediaService...");
Log_OC.d(TAG, "Binding to MediaService...");
if (mMediaServiceConnection == null) {
mMediaServiceConnection = new MediaServiceConnection();
}
@ -501,16 +499,16 @@ public class PreviewMediaFragment extends SherlockFragment implements
@Override
public void onServiceConnected(ComponentName component, IBinder service) {
if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
Log.d(TAG, "Media service connected");
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.d(TAG, "Successfully bound to MediaService, MediaController ready");
Log_OC.d(TAG, "Successfully bound to MediaService, MediaController ready");
} else {
Log.e(TAG, "Unexpected response from MediaService while binding");
Log_OC.e(TAG, "Unexpected response from MediaService while binding");
}
}
}
@ -527,7 +525,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
@Override
public void onServiceDisconnected(ComponentName component) {
if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
Log.e(TAG, "Media service suddenly disconnected");
Log_OC.e(TAG, "Media service suddenly disconnected");
if (mMediaController != null) {
mMediaController.setMediaPlayer(null);
} else {
@ -559,7 +557,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
startActivity(i);
} catch (Throwable t) {
Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
boolean toastIt = true;
String mimeType = "";
try {
@ -578,13 +576,13 @@ public class PreviewMediaFragment extends SherlockFragment implements
}
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
} catch (Throwable th) {
Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
} finally {
if (toastIt) {
@ -624,8 +622,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
mLastRemoteOperation = new RemoveFileOperation( mFile, // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters
true,
mStorageManager);
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
mLastRemoteOperation.execute(wc, this, mHandler);
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);

View file

@ -28,12 +28,12 @@ import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.MediaController;
import android.widget.VideoView;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.media.MediaService;
@ -84,7 +84,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "ACTIVITY\t\tonCreate");
Log_OC.e(TAG, "ACTIVITY\t\tonCreate");
setContentView(R.layout.video_layout);
@ -143,7 +143,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e(TAG, "ACTIVITY\t\tonSaveInstanceState");
Log_OC.e(TAG, "ACTIVITY\t\tonSaveInstanceState");
outState.putParcelable(PreviewVideoActivity.EXTRA_FILE, mFile);
outState.putParcelable(PreviewVideoActivity.EXTRA_ACCOUNT, mAccount);
outState.putInt(PreviewVideoActivity.EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
@ -153,7 +153,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
@Override
public void onBackPressed() {
Log.e(TAG, "ACTIVTIY\t\tonBackPressed");
Log_OC.e(TAG, "ACTIVTIY\t\tonBackPressed");
Intent i = new Intent();
i.putExtra(EXTRA_AUTOPLAY, mVideoPlayer.isPlaying());
i.putExtra(EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
@ -165,33 +165,33 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
@Override
public void onResume() {
super.onResume();
Log.e(TAG, "ACTIVTIY\t\tonResume");
Log_OC.e(TAG, "ACTIVTIY\t\tonResume");
}
@Override
public void onStart() {
super.onStart();
Log.e(TAG, "ACTIVTIY\t\tonStart");
Log_OC.e(TAG, "ACTIVTIY\t\tonStart");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "ACTIVITY\t\tonDestroy");
Log_OC.e(TAG, "ACTIVITY\t\tonDestroy");
}
@Override
public void onStop() {
super.onStop();
Log.e(TAG, "ACTIVTIY\t\tonStop");
Log_OC.e(TAG, "ACTIVTIY\t\tonStop");
}
@Override
public void onPause() {
super.onPause();
Log.e(TAG, "ACTIVTIY\t\tonPause");
Log_OC.e(TAG, "ACTIVTIY\t\tonPause");
}
@ -204,7 +204,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
*/
@Override
public void onPrepared(MediaPlayer mp) {
Log.e(TAG, "ACTIVITY\t\tonPrepare");
Log_OC.e(TAG, "ACTIVITY\t\tonPrepare");
mVideoPlayer.seekTo(mSavedPlaybackPosition);
if (mAutoplay) {
mVideoPlayer.start();
@ -235,7 +235,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
*/
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
Log_OC.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
if (mMediaController != null) {
mMediaController.hide();

View file

@ -24,7 +24,6 @@ import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile;

View file

@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package eu.alefzero.webdav;
import java.io.BufferedInputStream;
@ -22,14 +23,20 @@ import java.io.File;
import java.io.FileOutputStream;
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.HostConfiguration;
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.HttpState;
import org.apache.commons.httpclient.HttpVersion;
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.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
@ -39,12 +46,13 @@ import org.apache.http.HttpStatus;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.jackrabbit.webdav.client.methods.DavMethod;
import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
import com.owncloud.android.Log_OC;
import com.owncloud.android.network.BearerAuthScheme;
import com.owncloud.android.network.BearerCredentials;
import android.net.Uri;
import android.util.Log;
public class WebdavClient extends HttpClient {
private Uri mUri;
@ -65,176 +73,32 @@ public class WebdavClient extends HttpClient {
getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
}
public void setCredentials(String username, String password) {
getParams().setAuthenticationPreemptive(true);
getState().setCredentials(AuthScope.ANY,
getCredentials(username, password));
}
private Credentials getCredentials(String username, String password) {
if (mCredentials == null)
mCredentials = new UsernamePasswordCredentials(username, password);
return mCredentials;
}
/**
* Downloads a file in remoteFilepath to the local targetPath.
*
* @param remoteFilepath Path to the file in the remote server, URL DECODED.
* @param targetFile Local path to save the downloaded file.
* @return 'True' when the file is successfully downloaded.
*/
public boolean downloadFile(String remoteFilePath, File targetFile) {
boolean ret = false;
GetMethod get = new GetMethod(mUri.toString() + WebdavUtils.encodePath(remoteFilePath));
try {
int status = executeMethod(get);
if (status == HttpStatus.SC_OK) {
targetFile.createNewFile();
BufferedInputStream bis = new BufferedInputStream(
get.getResponseBodyAsStream());
FileOutputStream fos = new FileOutputStream(targetFile);
byte[] bytes = new byte[4096];
int readResult;
while ((readResult = bis.read(bytes)) != -1) {
if (mDataTransferListener != null)
mDataTransferListener.onTransferProgress(readResult);
fos.write(bytes, 0, readResult);
}
fos.close();
ret = true;
} else {
exhaustResponse(get.getResponseBodyAsStream());
}
Log_OC.e(TAG, "Download of " + remoteFilePath + " to " + targetFile + " finished with HTTP status " + status + (!ret?"(FAIL)":""));
} catch (Exception e) {
logException(e, "dowloading " + remoteFilePath);
} finally {
if (!ret && targetFile.exists()) {
targetFile.delete();
}
get.releaseConnection(); // let the connection available for other methods
}
return ret;
}
/**
* Deletes a remote file via webdav
* @param remoteFilePath Remote file path of the file to delete, in URL DECODED format.
* @return
*/
public boolean deleteFile(String remoteFilePath) {
boolean ret = false;
DavMethod delete = new DeleteMethod(mUri.toString() + WebdavUtils.encodePath(remoteFilePath));
try {
int status = executeMethod(delete);
ret = (status == HttpStatus.SC_OK || status == HttpStatus.SC_ACCEPTED || status == HttpStatus.SC_NO_CONTENT);
exhaustResponse(delete.getResponseBodyAsStream());
Log_OC.e(TAG, "DELETE of " + remoteFilePath + " finished with HTTP status " + status + (!ret?"(FAIL)":""));
} catch (Exception e) {
logException(e, "deleting " + remoteFilePath);
} finally {
delete.releaseConnection(); // let the connection available for other methods
}
return ret;
}
public void setDataTransferProgressListener(OnDatatransferProgressListener listener) {
mDataTransferListener = listener;
}
/**
* Creates or update a file in the remote server with the contents of a local file.
*
* @param localFile Path to the local file to upload.
* @param remoteTarget Remote path to the file to create or update, URL DECODED
* @param contentType MIME type of the file.
* @return Status HTTP code returned by the server.
* @throws IOException When a transport error that could not be recovered occurred while uploading the file to the server.
* @throws HttpException When a violation of the HTTP protocol occurred.
*/
public int putFile(String localFile, String remoteTarget, String contentType) throws HttpException, IOException {
int status = -1;
PutMethod put = new PutMethod(mUri.toString() + WebdavUtils.encodePath(remoteTarget));
public void setBearerCredentials(String accessToken) {
AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
try {
File f = new File(localFile);
FileRequestEntity entity = new FileRequestEntity(f, contentType);
entity.addDatatransferProgressListener(mDataTransferListener);
put.setRequestEntity(entity);
status = executeMethod(put);
exhaustResponse(put.getResponseBodyAsStream());
} finally {
put.releaseConnection(); // let the connection available for other methods
}
return status;
}
/**
* Tries to log in to the current URI, with the current credentials
*
* @return A {@link HttpStatus}-Code of the result. SC_OK is good.
*/
public int tryToLogin() {
int status = 0;
HeadMethod head = new HeadMethod(mUri.toString());
try {
status = executeMethod(head);
boolean result = status == HttpStatus.SC_OK;
Log_OC.d(TAG, "HEAD for " + mUri + " finished with HTTP status " + status + (!result?"(FAIL)":""));
exhaustResponse(head.getResponseBodyAsStream());
} catch (Exception e) {
logException(e, "trying to login at " + mUri.toString());
} finally {
head.releaseConnection();
}
return status;
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);
}
/**
* Creates a remote directory with the received path.
*
* @param path Path of the directory to create, URL DECODED
* @return 'True' when the directory is successfully created
*/
public boolean createDirectory(String path) {
boolean result = false;
int status = -1;
MkColMethod mkcol = new MkColMethod(mUri.toString() + WebdavUtils.encodePath(path));
try {
Log_OC.d(TAG, "Creating directory " + path);
status = executeMethod(mkcol);
Log_OC.d(TAG, "Status returned: " + status);
result = mkcol.succeeded();
Log_OC.d(TAG, "MKCOL to " + path + " finished with HTTP status " + status + (!result?"(FAIL)":""));
exhaustResponse(mkcol.getResponseBodyAsStream());
} catch (Exception e) {
logException(e, "creating directory " + path);
} finally {
mkcol.releaseConnection(); // let the connection available for other methods
}
return result;
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);
}
/**
* 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
*/
@ -250,7 +114,7 @@ public class WebdavClient extends HttpClient {
head.releaseConnection(); // let the connection available for other methods
}
}
/**
* Requests the received method with the received timeout (milliseconds).
*
@ -299,25 +163,6 @@ public class WebdavClient extends HttpClient {
}
}
/**
* Logs an exception triggered in a HTTP request.
*
* @param e Caught exception.
* @param doing Suffix to add at the end of the logged message.
*/
private void logException(Exception e, String doing) {
if (e instanceof HttpException) {
Log_OC.e(TAG, "HTTP violation while " + doing, e);
} else if (e instanceof IOException) {
Log_OC.e(TAG, "Unrecovered transport exception while " + doing, e);
} else {
Log_OC.e(TAG, "Unexpected exception while " + doing, e);
}
}
/**
* Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client.
*/
@ -338,4 +183,8 @@ public class WebdavClient extends HttpClient {
return mUri;
}
public final Credentials getCredentials() {
return mCredentials;
}
}

View file

@ -26,7 +26,6 @@ import org.apache.jackrabbit.webdav.property.DavPropertySet;
import com.owncloud.android.Log_OC;
import android.net.Uri;
import android.util.Log;
public class WebdavEntry {
private String mName, mPath, mUri, mContentType;