From: David A. Velasco Date: Tue, 17 Jul 2012 10:59:15 +0000 (+0200) Subject: OCFile stores again decoded remote paths; WebdavUtils.encode(...) added; fixed space... X-Git-Tag: oc-android-1.4.3~270 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/c6b553f635c7cbb4f21d41a6fa82e204447c16cf?ds=inline OCFile stores again decoded remote paths; WebdavUtils.encode(...) added; fixed space conversion in paths in multiple uploads; CLEAN THE APPLICATION CACHE AFTER INSTALLING --- diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 53c014c9..a547234a 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -18,7 +18,7 @@ --> + android:versionName="0.1.161B" xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/src/eu/alefzero/owncloud/Uploader.java b/src/eu/alefzero/owncloud/Uploader.java index fcb22a2a..354b007b 100644 --- a/src/eu/alefzero/owncloud/Uploader.java +++ b/src/eu/alefzero/owncloud/Uploader.java @@ -166,7 +166,7 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro null, null, null); mCursor.moveToFirst(); pathToUpload = mCursor.getString(mCursor.getColumnIndex(ProviderTableMeta.FILE_PATH)) - + mCursor.getString(mCursor.getColumnIndex(ProviderTableMeta.FILE_NAME)).replace(" ", "%20"); + + mCursor.getString(mCursor.getColumnIndex(ProviderTableMeta.FILE_NAME)).replace(" ", "%20"); // TODO don't make this ; use WebdavUtils.encode in the right moment } a a = new a(pathToUpload, dirName); builder.setPositiveButton(R.string.common_ok, a); @@ -251,10 +251,9 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro // click on button switch (v.getId()) { case R.id.uploader_choose_folder: - mUploadPath = "/"; + mUploadPath = ""; // first element in mParents is root dir, represented by ""; init mUploadPath with "/" results in a "//" prefix for (String p : mParents) - mUploadPath += p + "/"; - mUploadPath = Uri.encode(mUploadPath, "/"); + mUploadPath += p + OCFile.PATH_SEPARATOR; Log.d(TAG, "Uploading file to dir " + mUploadPath); uploadFiles(); @@ -393,11 +392,11 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro final String display_name = c.getString(c.getColumnIndex(Media.DISPLAY_NAME)), data = c.getString(c.getColumnIndex(Media.DATA)); local[i] = data; - remote[i] = mUploadPath + Uri.encode(display_name); + remote[i] = mUploadPath + display_name; } else if (uri.getScheme().equals("file")) { final File file = new File(Uri.decode(uri.toString()).replace(uri.getScheme() + "://", "")); local[i] = file.getAbsolutePath(); - remote[i] = mUploadPath + Uri.encode(file.getName()); + remote[i] = mUploadPath + file.getName(); } } diff --git a/src/eu/alefzero/owncloud/datamodel/FileDataStorageManager.java b/src/eu/alefzero/owncloud/datamodel/FileDataStorageManager.java index e1b62ef7..c732f59b 100644 --- a/src/eu/alefzero/owncloud/datamodel/FileDataStorageManager.java +++ b/src/eu/alefzero/owncloud/datamodel/FileDataStorageManager.java @@ -378,7 +378,7 @@ public class FileDataStorageManager implements DataStorageManager { if (file.getStoragePath() == null) { // try to find existing file and bind it with current account File sdCard = Environment.getExternalStorageDirectory(); - File f = new File(sdCard.getAbsolutePath() + "/owncloud/" + mAccount.name + file.getURLDecodedRemotePath()); + File f = new File(sdCard.getAbsolutePath() + "/owncloud/" + mAccount.name + file.getRemotePath()); if (f.exists()) file.setStoragePath(f.getAbsolutePath()); } diff --git a/src/eu/alefzero/owncloud/datamodel/OCFile.java b/src/eu/alefzero/owncloud/datamodel/OCFile.java index ce9c03b5..5cd54f64 100644 --- a/src/eu/alefzero/owncloud/datamodel/OCFile.java +++ b/src/eu/alefzero/owncloud/datamodel/OCFile.java @@ -40,6 +40,8 @@ public class OCFile implements Parcelable, Comparable { } }; + public static final String PATH_SEPARATOR = "/"; + private long mId; private long mParentId; private long mLength; @@ -53,24 +55,19 @@ public class OCFile implements Parcelable, Comparable { private boolean mKeepInSync; /** - * Create new {@link OCFile} with given path + * Create new {@link OCFile} with given path. + * + * The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'. * - * @param path The remote path of the file - * @throws MalformedURLException + * @param path The remote path of the file. */ public OCFile(String path) { resetData(); mNeedsUpdating = false; - /// dvelasco: the encoding / decoding problem should be completely translated to WebdavClient & WebdavEntry, but at this moment we are in a little hurry - if (path != null && path.length() > 0) { - try { - new URL("http://silly.test.com:8888" + path); - } catch (MalformedURLException e) { - throw new RuntimeException("Trying to create a OCFile with a non valid remote path: " + path , e); - } - } else throw new RuntimeException("Trying to create a OCFile with a non valid remote path: " + path); - // save encoded paths have a problem: normalization; this is a quick&dirty fix to avoid duplications - mRemotePath = Uri.encode(Uri.decode(path), "/"); + if (path == null || path.length() <= 0 || !path.startsWith(PATH_SEPARATOR)) { + throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path); + } + mRemotePath = path; } /** @@ -126,15 +123,6 @@ public class OCFile implements Parcelable, Comparable { } /** - * Returns the remote path of the file on ownCloud - * - * @return The remote path to the file - */ - public String getURLDecodedRemotePath() { - return Uri.decode(mRemotePath); - } - - /** * Can be used to check, whether or not this file exists in the database * already * @@ -222,7 +210,7 @@ public class OCFile implements Parcelable, Comparable { * @return The name of the file */ public String getFileName() { - File f = new File(getURLDecodedRemotePath()); + File f = new File(getRemotePath()); return f.getName().length() == 0 ? "/" : f.getName(); } diff --git a/src/eu/alefzero/owncloud/files/services/FileUploader.java b/src/eu/alefzero/owncloud/files/services/FileUploader.java index 71c4258a..57605960 100644 --- a/src/eu/alefzero/owncloud/files/services/FileUploader.java +++ b/src/eu/alefzero/owncloud/files/services/FileUploader.java @@ -99,9 +99,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mRemotePaths = intent.getStringArrayExtra(KEY_REMOTE_FILE); } - for (int i = 0; i < mRemotePaths.length; ++i) - mRemotePaths[i] = mRemotePaths[i].replace(' ', '+'); - if (mLocalPaths.length != mRemotePaths.length) { Log.e(TAG, "Remote paths and local paths are not equal!"); return Service.START_NOT_STICKY; diff --git a/src/eu/alefzero/owncloud/files/services/InstantUploadService.java b/src/eu/alefzero/owncloud/files/services/InstantUploadService.java index 1cf22c20..b666e593 100644 --- a/src/eu/alefzero/owncloud/files/services/InstantUploadService.java +++ b/src/eu/alefzero/owncloud/files/services/InstantUploadService.java @@ -148,7 +148,7 @@ public class InstantUploadService extends Service { try { status = wdc.executeMethod(mkcol); Log.e(TAG, "mkcol returned " + status); - wdc.putFile(filepath, INSTANT_UPLOAD_DIR + "/" + Uri.encode(filename), mimetype); + wdc.putFile(filepath, INSTANT_UPLOAD_DIR + "/" + filename, mimetype); } catch (HttpException e) { e.printStackTrace(); } catch (IOException e) { diff --git a/src/eu/alefzero/owncloud/syncadapter/FileSyncAdapter.java b/src/eu/alefzero/owncloud/syncadapter/FileSyncAdapter.java index 9f0c0dc5..61975dd7 100644 --- a/src/eu/alefzero/owncloud/syncadapter/FileSyncAdapter.java +++ b/src/eu/alefzero/owncloud/syncadapter/FileSyncAdapter.java @@ -39,6 +39,7 @@ import eu.alefzero.owncloud.datamodel.FileDataStorageManager; import eu.alefzero.owncloud.datamodel.OCFile; import eu.alefzero.owncloud.files.services.FileDownloader; import eu.alefzero.webdav.WebdavEntry; +import eu.alefzero.webdav.WebdavUtils; /** * SyncAdapter implementation for syncing sample SyncAdapter contacts to the @@ -176,7 +177,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { .getModificationTimestamp()) { Intent intent = new Intent(this.getContext(), FileDownloader.class); intent.putExtra(FileDownloader.EXTRA_ACCOUNT, getAccount()); - intent.putExtra(FileDownloader.EXTRA_FILE_PATH, file.getURLDecodedRemotePath()); + intent.putExtra(FileDownloader.EXTRA_FILE_PATH, file.getRemotePath()); intent.putExtra(FileDownloader.EXTRA_REMOTE_PATH, file.getRemotePath()); intent.putExtra(FileDownloader.EXTRA_FILE_SIZE, file.getFileLength()); file.setKeepInSync(true); @@ -219,7 +220,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { for (int i=0; i < files.size() && !mCancellation; i++) { OCFile newFile = files.get(i); if (newFile.getMimetype().equals("DIR")) { - fetchData(getUri().toString() + newFile.getRemotePath(), syncResult, newFile.getFileId()); + fetchData(getUri().toString() + WebdavUtils.encode(newFile.getRemotePath()), syncResult, newFile.getFileId()); } } if (mCancellation) Log.d(TAG, "Leaving " + uri + " because cancellation request"); @@ -254,7 +255,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { } private OCFile fillOCFile(WebdavEntry we) { - OCFile file = new OCFile(we.path()); + OCFile file = new OCFile(we.decodedPath()); file.setCreationTimestamp(we.createTimestamp()); file.setFileLength(we.contentLength()); file.setMimetype(we.contentType()); diff --git a/src/eu/alefzero/owncloud/ui/activity/FileDisplayActivity.java b/src/eu/alefzero/owncloud/ui/activity/FileDisplayActivity.java index e54913a1..45f7c77d 100644 --- a/src/eu/alefzero/owncloud/ui/activity/FileDisplayActivity.java +++ b/src/eu/alefzero/owncloud/ui/activity/FileDisplayActivity.java @@ -117,7 +117,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements if(savedInstanceState != null) { mDirs = savedInstanceState.getStringArray(KEY_DIR_ARRAY); mDirectories = new CustomArrayAdapter(this, R.layout.sherlock_spinner_dropdown_item); - mDirectories.add("/"); + mDirectories.add(OCFile.PATH_SEPARATOR); if (mDirs != null) for (String s : mDirs) mDirectories.insert(s, 0); @@ -244,12 +244,11 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements AccountUtils.getCurrentOwnCloudAccount(this)); String remotepath = new String(); for (int j = mDirectories.getCount() - 2; j >= 0; --j) { - remotepath += "/" + mDirectories.getItem(j); + remotepath += OCFile.PATH_SEPARATOR + mDirectories.getItem(j); } - if (!remotepath.endsWith("/")) - remotepath += "/"; + if (!remotepath.endsWith(OCFile.PATH_SEPARATOR)) + remotepath += OCFile.PATH_SEPARATOR; remotepath += new File(filepath).getName(); - remotepath = Uri.encode(remotepath, "/"); i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath); i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath); @@ -369,7 +368,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements for (String s : mDirs) mDirectories.add(s); } else { - mDirectories.add("/"); + mDirectories.add(OCFile.PATH_SEPARATOR); } // Actionbar setup @@ -456,16 +455,16 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements String path; if (mCurrentDir == null) { // this is just a patch; we should ensure that mCurrentDir never is null - if (!mStorageManager.fileExists("/")) { - OCFile file = new OCFile("/"); + if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) { + OCFile file = new OCFile(OCFile.PATH_SEPARATOR); mStorageManager.saveFile(file); } - mCurrentDir = mStorageManager.getFileByPath("/"); + mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR); } path = FileDisplayActivity.this.mCurrentDir.getRemotePath(); // Create directory - path += Uri.encode(directoryName) + "/"; + path += directoryName + OCFile.PATH_SEPARATOR; Thread thread = new Thread(new DirectoryCreator(path, a)); thread.start(); diff --git a/src/eu/alefzero/owncloud/ui/fragment/FileDetailFragment.java b/src/eu/alefzero/owncloud/ui/fragment/FileDetailFragment.java index c94719ee..7eb0c1b8 100644 --- a/src/eu/alefzero/owncloud/ui/fragment/FileDetailFragment.java +++ b/src/eu/alefzero/owncloud/ui/fragment/FileDetailFragment.java @@ -95,6 +95,7 @@ import eu.alefzero.owncloud.files.services.FileDownloader; import eu.alefzero.owncloud.ui.activity.FileDisplayActivity; import eu.alefzero.owncloud.utils.OwnCloudVersion; import eu.alefzero.webdav.WebdavClient; +import eu.alefzero.webdav.WebdavUtils; /** * This Fragment is used to display the details about a file. @@ -223,7 +224,7 @@ public class FileDetailFragment extends SherlockFragment implements Intent i = new Intent(getActivity(), FileDownloader.class); i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount); i.putExtra(FileDownloader.EXTRA_REMOTE_PATH, mFile.getRemotePath()); - i.putExtra(FileDownloader.EXTRA_FILE_PATH, mFile.getURLDecodedRemotePath()); + i.putExtra(FileDownloader.EXTRA_FILE_PATH, mFile.getRemotePath()); i.putExtra(FileDownloader.EXTRA_FILE_SIZE, mFile.getFileLength()); v.setEnabled(false); getActivity().startService(i); @@ -602,7 +603,7 @@ public class FileDetailFragment extends SherlockFragment implements if (!newFilename.equals(mFile.getFileName())) { FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getContentResolver()); if (fdsm.getFileById(mFile.getFileId()) != null) { - OCFile newFile = new OCFile(fdsm.getFileById(mFile.getParentId()).getRemotePath()+"/"+newFilename); + OCFile newFile = new OCFile(fdsm.getFileById(mFile.getParentId()).getRemotePath() + OCFile.PATH_SEPARATOR + newFilename); newFile.setCreationTimestamp(mFile.getCreationTimestamp()); newFile.setFileId(mFile.getFileId()); newFile.setFileLength(mFile.getFileLength()); @@ -643,11 +644,11 @@ public class FileDetailFragment extends SherlockFragment implements String baseUrl = am.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL); OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION)); String webdav_path = AccountUtils.getWebdavPath(ocv); - Log.d("ASD", ""+baseUrl + webdav_path + mOld.getRemotePath()); + Log.d("ASD", ""+baseUrl + webdav_path + WebdavUtils.encode(mOld.getRemotePath())); - Log.e("ASD", Uri.parse(baseUrl).getPath() == null ? "" : Uri.parse(baseUrl).getPath() + webdav_path + mNew.getRemotePath()); - LocalMoveMethod move = new LocalMoveMethod(baseUrl + webdav_path + mOld.getRemotePath(), - Uri.parse(baseUrl).getPath() == null ? "" : Uri.parse(baseUrl).getPath() + webdav_path + mNew.getRemotePath()); + Log.e("ASD", Uri.parse(baseUrl).getPath() == null ? "" : Uri.parse(baseUrl).getPath() + webdav_path + WebdavUtils.encode(mNew.getRemotePath())); + LocalMoveMethod move = new LocalMoveMethod(baseUrl + webdav_path + WebdavUtils.encode(mOld.getRemotePath()), + Uri.parse(baseUrl).getPath() == null ? "" : Uri.parse(baseUrl).getPath() + webdav_path + WebdavUtils.encode(mNew.getRemotePath())); try { int status = wc.executeMethod(move); @@ -771,9 +772,9 @@ public class FileDetailFragment extends SherlockFragment implements String baseUrl = am.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL); OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION)); String webdav_path = AccountUtils.getWebdavPath(ocv); - Log.d("ASD", ""+baseUrl + webdav_path + mFileToRemove.getRemotePath()); + Log.d("ASD", ""+baseUrl + webdav_path + WebdavUtils.encode(mFileToRemove.getRemotePath())); - DeleteMethod delete = new DeleteMethod(baseUrl + webdav_path + mFileToRemove.getRemotePath()); + DeleteMethod delete = new DeleteMethod(baseUrl + webdav_path + WebdavUtils.encode(mFileToRemove.getRemotePath())); HttpMethodParams params = delete.getParams(); params.setSoTimeout(1000); delete.setParams(params); diff --git a/src/eu/alefzero/webdav/WebdavClient.java b/src/eu/alefzero/webdav/WebdavClient.java index dd3b4eae..9eafddc1 100644 --- a/src/eu/alefzero/webdav/WebdavClient.java +++ b/src/eu/alefzero/webdav/WebdavClient.java @@ -113,9 +113,16 @@ public class WebdavClient extends HttpClient { new EasySSLSocketFactory(), 443)); } + /** + * Downloads a file in remoteFilepath to the local targetPath. + * + * @param remoteFilepath Path to the file in the remote server, URL DECODED. + * @param targetPath Local path to save the downloaded file. + * @return 'True' when the file is successfully downloaded. + */ public boolean downloadFile(String remoteFilepath, File targetPath) { boolean ret = false; - GetMethod get = new GetMethod(mUri.toString() + remoteFilepath); + GetMethod get = new GetMethod(mUri.toString() + WebdavUtils.encode(remoteFilepath)); HttpMethodParams params = get.getParams(); params.setSoTimeout(0); // that means "infinite timeout"; it's the default value, but let's make it explicit get.setParams(params); @@ -152,11 +159,11 @@ public class WebdavClient extends HttpClient { /** * Deletes a remote file via webdav - * @param remoteFilePath + * @param remoteFilePath Remote file path of the file to delete, in URL DECODED format. * @return */ public boolean deleteFile(String remoteFilePath){ - DavMethod delete = new DeleteMethod(mUri.toString() + remoteFilePath); + DavMethod delete = new DeleteMethod(mUri.toString() + WebdavUtils.encode(remoteFilePath)); try { executeMethod(delete); } catch (Throwable e) { @@ -170,6 +177,15 @@ public class WebdavClient extends HttpClient { 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 'True' then the upload was successfully completed + */ public boolean putFile(String localFile, String remoteTarget, String contentType) { boolean result = true; @@ -180,7 +196,7 @@ public class WebdavClient extends HttpClient { FileRequestEntity entity = new FileRequestEntity(f, contentType); entity.setOnDatatransferProgressListener(mDataTransferListener); Log.e("ASD", f.exists() + " " + entity.getContentLength()); - PutMethod put = new PutMethod(mUri.toString() + remoteTarget); + PutMethod put = new PutMethod(mUri.toString() + WebdavUtils.encode(remoteTarget)); HttpMethodParams params = put.getParams(); params.setSoTimeout(0); // that means "infinite timeout"; it's the default value, but let's make it explicit put.setParams(params); @@ -218,9 +234,15 @@ public class WebdavClient extends HttpClient { return returnCode; } + /** + * 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) { try { - MkColMethod mkcol = new MkColMethod(mUri.toString() + path); + MkColMethod mkcol = new MkColMethod(mUri.toString() + WebdavUtils.encode(path)); int status = executeMethod(mkcol); Log.d(TAG, "Status returned " + status); Log.d(TAG, "uri: " + mkcol.getURI().toString()); diff --git a/src/eu/alefzero/webdav/WebdavEntry.java b/src/eu/alefzero/webdav/WebdavEntry.java index f4fbda45..84c96fbd 100644 --- a/src/eu/alefzero/webdav/WebdavEntry.java +++ b/src/eu/alefzero/webdav/WebdavEntry.java @@ -24,6 +24,7 @@ import org.apache.jackrabbit.webdav.property.DavProperty; import org.apache.jackrabbit.webdav.property.DavPropertyName; import org.apache.jackrabbit.webdav.property.DavPropertySet; +import android.net.Uri; import android.util.Log; public class WebdavEntry { @@ -92,6 +93,10 @@ public class WebdavEntry { public String path() { return mPath; } + + public String decodedPath() { + return Uri.decode(mPath); + } public String name() { return mName; diff --git a/src/eu/alefzero/webdav/WebdavUtils.java b/src/eu/alefzero/webdav/WebdavUtils.java index dc407b0a..8e7c07b6 100644 --- a/src/eu/alefzero/webdav/WebdavUtils.java +++ b/src/eu/alefzero/webdav/WebdavUtils.java @@ -23,6 +23,10 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; +import eu.alefzero.owncloud.datamodel.OCFile; + +import android.net.Uri; + public class WebdavUtils { public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat( "dd.MM.yyyy hh:mm"); @@ -55,4 +59,19 @@ public class WebdavUtils { } return null; } + + /** + * Encodes a path according to URI RFC 2396. + * + * If the received path doesn't start with "/", the method adds it. + * + * @param remoteFilePath Path + * @return Encoded path according to RFC 2396, always starting with "/" + */ + public static String encode(String remoteFilePath) { + String encodedPath = Uri.encode(remoteFilePath, "/"); + if (!encodedPath.startsWith("/")) + encodedPath = "/" + encodedPath; + return encodedPath; + } }