mirror of
				https://github.com/owncloud/android-library.git
				synced 2025-11-04 12:28:25 +00:00 
			
		
		
		
	Merge pull request #71 from owncloud/forbidden_characters_from_server
Support check of forbidden characters in server, for OC >= 8.1
This commit is contained in:
		
						commit
						344d5b22e4
					
				@ -52,6 +52,7 @@ import com.owncloud.android.lib.common.accounts.AccountUtils;
 | 
				
			|||||||
import com.owncloud.android.lib.common.network.RedirectionPath;
 | 
					import com.owncloud.android.lib.common.network.RedirectionPath;
 | 
				
			||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
 | 
					import com.owncloud.android.lib.common.network.WebdavUtils;
 | 
				
			||||||
import com.owncloud.android.lib.common.utils.Log_OC;
 | 
					import com.owncloud.android.lib.common.utils.Log_OC;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class OwnCloudClient extends HttpClient {
 | 
					public class OwnCloudClient extends HttpClient {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
@ -69,6 +70,8 @@ public class OwnCloudClient extends HttpClient {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    private Uri mBaseUri;
 | 
					    private Uri mBaseUri;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private OwnCloudVersion mVersion = null;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructor
 | 
					     * Constructor
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -441,4 +444,12 @@ public class OwnCloudClient extends HttpClient {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setOwnCloudVersion(String version){
 | 
				
			||||||
 | 
					        OwnCloudVersion ver = new OwnCloudVersion(version);
 | 
				
			||||||
 | 
					        mVersion = ver;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public OwnCloudVersion getOwnCloudVersion(){
 | 
				
			||||||
 | 
					        return mVersion;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,146 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/* ownCloud Android Library is available under MIT license
 | 
				
			||||||
 | 
					 *   Copyright (C) 2015 ownCloud Inc.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 *   of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 *   in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 *   copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 *   furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 *   all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
 | 
					 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
 | 
					 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
				
			||||||
 | 
					 *   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
				
			||||||
 | 
					 *   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
				
			||||||
 | 
					 *   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 *   THE SOFTWARE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					package com.owncloud.android.lib.common.operations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.util.Xml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.xmlpull.v1.XmlPullParser;
 | 
				
			||||||
 | 
					import org.xmlpull.v1.XmlPullParserException;
 | 
				
			||||||
 | 
					import org.xmlpull.v1.XmlPullParserFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Parser for Invalid Character server exception
 | 
				
			||||||
 | 
					 * @author masensio
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class InvalidCharacterExceptionParser {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final String EXCEPTION_STRING = "OC\\Connector\\Sabre\\Exception\\InvalidPath";
 | 
				
			||||||
 | 
						private static final String EXCEPTION_UPLOAD_STRING = "OCP\\Files\\InvalidPathException";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // No namespaces
 | 
				
			||||||
 | 
						private static final String ns = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Nodes for XML Parser
 | 
				
			||||||
 | 
					    private static final String NODE_ERROR = "d:error";
 | 
				
			||||||
 | 
						private static final String NODE_EXCEPTION = "s:exception";
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
						 * Parse is as an Invalid Path Exception
 | 
				
			||||||
 | 
						 * @param is
 | 
				
			||||||
 | 
						 * @return if The exception is an Invalid Char Exception
 | 
				
			||||||
 | 
						 * @throws XmlPullParserException
 | 
				
			||||||
 | 
						 * @throws IOException
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public boolean parseXMLResponse(InputStream is) throws XmlPullParserException,
 | 
				
			||||||
 | 
					            IOException {
 | 
				
			||||||
 | 
					        boolean result = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								// XMLPullParser
 | 
				
			||||||
 | 
								XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
 | 
				
			||||||
 | 
								factory.setNamespaceAware(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								XmlPullParser parser = Xml.newPullParser();
 | 
				
			||||||
 | 
								parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
 | 
				
			||||||
 | 
								parser.setInput(is, null);
 | 
				
			||||||
 | 
								parser.nextTag();
 | 
				
			||||||
 | 
								result = readError(parser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							} finally {
 | 
				
			||||||
 | 
								is.close();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Parse OCS node
 | 
				
			||||||
 | 
						 * @param parser
 | 
				
			||||||
 | 
						 * @return List of ShareRemoteFiles
 | 
				
			||||||
 | 
						 * @throws XmlPullParserException
 | 
				
			||||||
 | 
						 * @throws IOException
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private boolean readError (XmlPullParser parser) throws XmlPullParserException, IOException {
 | 
				
			||||||
 | 
							String exception = "";
 | 
				
			||||||
 | 
							parser.require(XmlPullParser.START_TAG,  ns , NODE_ERROR);
 | 
				
			||||||
 | 
							while (parser.next() != XmlPullParser.END_TAG) {
 | 
				
			||||||
 | 
								if (parser.getEventType() != XmlPullParser.START_TAG) {
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								String name = parser.getName();
 | 
				
			||||||
 | 
								// read NODE_EXCEPTION
 | 
				
			||||||
 | 
								if (name.equalsIgnoreCase(NODE_EXCEPTION)) {
 | 
				
			||||||
 | 
									exception = readText(parser);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									skip(parser);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return exception.equalsIgnoreCase(EXCEPTION_STRING) ||
 | 
				
			||||||
 | 
									exception.equalsIgnoreCase(EXCEPTION_UPLOAD_STRING);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Skip tags in parser procedure
 | 
				
			||||||
 | 
						 * @param parser
 | 
				
			||||||
 | 
						 * @throws XmlPullParserException
 | 
				
			||||||
 | 
						 * @throws IOException
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
 | 
				
			||||||
 | 
							if (parser.getEventType() != XmlPullParser.START_TAG) {
 | 
				
			||||||
 | 
								throw new IllegalStateException();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							int depth = 1;
 | 
				
			||||||
 | 
							while (depth != 0) {
 | 
				
			||||||
 | 
								switch (parser.next()) {
 | 
				
			||||||
 | 
								case XmlPullParser.END_TAG:
 | 
				
			||||||
 | 
									depth--;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case XmlPullParser.START_TAG:
 | 
				
			||||||
 | 
									depth++;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    	/**
 | 
				
			||||||
 | 
						 * Read the text from a node
 | 
				
			||||||
 | 
						 * @param parser
 | 
				
			||||||
 | 
						 * @return Text of the node
 | 
				
			||||||
 | 
						 * @throws IOException
 | 
				
			||||||
 | 
						 * @throws XmlPullParserException
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
 | 
				
			||||||
 | 
							String result = "";
 | 
				
			||||||
 | 
							if (parser.next() == XmlPullParser.TEXT) {
 | 
				
			||||||
 | 
								result = parser.getText();
 | 
				
			||||||
 | 
								parser.nextTag();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -24,7 +24,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.owncloud.android.lib.common.operations;
 | 
					package com.owncloud.android.lib.common.operations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.ByteArrayInputStream;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.io.InputStream;
 | 
				
			||||||
import java.io.Serializable;
 | 
					import java.io.Serializable;
 | 
				
			||||||
import java.net.MalformedURLException;
 | 
					import java.net.MalformedURLException;
 | 
				
			||||||
import java.net.SocketException;
 | 
					import java.net.SocketException;
 | 
				
			||||||
@ -60,7 +62,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
 | 
				
			|||||||
public class RemoteOperationResult implements Serializable {
 | 
					public class RemoteOperationResult implements Serializable {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	/** Generated - should be refreshed every time the class changes!! */;
 | 
						/** Generated - should be refreshed every time the class changes!! */;
 | 
				
			||||||
    private static final long serialVersionUID = 25745846447996048L;
 | 
					    private static final long serialVersionUID = -1909603208238358633L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final String TAG = RemoteOperationResult.class.getSimpleName();
 | 
					    private static final String TAG = RemoteOperationResult.class.getSimpleName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -103,7 +105,8 @@ public class RemoteOperationResult implements Serializable {
 | 
				
			|||||||
		SHARE_FORBIDDEN,
 | 
							SHARE_FORBIDDEN,
 | 
				
			||||||
		OK_REDIRECT_TO_NON_SECURE_CONNECTION, 
 | 
							OK_REDIRECT_TO_NON_SECURE_CONNECTION, 
 | 
				
			||||||
		INVALID_MOVE_INTO_DESCENDANT, 
 | 
							INVALID_MOVE_INTO_DESCENDANT, 
 | 
				
			||||||
		PARTIAL_MOVE_DONE
 | 
							PARTIAL_MOVE_DONE,
 | 
				
			||||||
 | 
					        INVALID_CHARACTER_DETECT_IN_SERVER
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private boolean mSuccess = false;
 | 
					    private boolean mSuccess = false;
 | 
				
			||||||
@ -118,7 +121,9 @@ public class RemoteOperationResult implements Serializable {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public RemoteOperationResult(ResultCode code) {
 | 
					    public RemoteOperationResult(ResultCode code) {
 | 
				
			||||||
        mCode = code;
 | 
					        mCode = code;
 | 
				
			||||||
		mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL || code == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION);
 | 
							mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL ||
 | 
				
			||||||
 | 
					                code == ResultCode.OK_NO_SSL ||
 | 
				
			||||||
 | 
					                code == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION);
 | 
				
			||||||
        mData = null;
 | 
					        mData = null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -151,7 +156,8 @@ public class RemoteOperationResult implements Serializable {
 | 
				
			|||||||
                break;
 | 
					                break;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                mCode = ResultCode.UNHANDLED_HTTP_CODE;
 | 
					                mCode = ResultCode.UNHANDLED_HTTP_CODE;
 | 
				
			||||||
                Log_OC.d(TAG, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + httpCode);
 | 
					                Log_OC.d(TAG, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " +
 | 
				
			||||||
 | 
					                        httpCode);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -174,6 +180,37 @@ public class RemoteOperationResult implements Serializable {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public RemoteOperationResult(boolean success, String bodyResponse, int httpCode) {
 | 
				
			||||||
 | 
					        mSuccess = success;
 | 
				
			||||||
 | 
					        mHttpCode = httpCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (success) {
 | 
				
			||||||
 | 
					            mCode = ResultCode.OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } else if (httpCode > 0) {
 | 
				
			||||||
 | 
					            switch (httpCode) {
 | 
				
			||||||
 | 
					                case HttpStatus.SC_BAD_REQUEST:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
 | 
				
			||||||
 | 
					                    InvalidCharacterExceptionParser xmlParser = new InvalidCharacterExceptionParser();
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        if (xmlParser.parseXMLResponse(is))
 | 
				
			||||||
 | 
					                            mCode = ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    } catch (Exception e) {
 | 
				
			||||||
 | 
					                        mCode = ResultCode.UNHANDLED_HTTP_CODE;
 | 
				
			||||||
 | 
					                        Log_OC.e(TAG, "Exception reading exception from server", e);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    mCode = ResultCode.UNHANDLED_HTTP_CODE;
 | 
				
			||||||
 | 
					                    Log_OC.d(TAG, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " +
 | 
				
			||||||
 | 
					                            httpCode);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public RemoteOperationResult(Exception e) {
 | 
					    public RemoteOperationResult(Exception e) {
 | 
				
			||||||
        mException = e;
 | 
					        mException = e;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -265,7 +302,8 @@ public class RemoteOperationResult implements Serializable {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        Throwable cause = mException.getCause();
 | 
					        Throwable cause = mException.getCause();
 | 
				
			||||||
        Throwable previousCause = null;
 | 
					        Throwable previousCause = null;
 | 
				
			||||||
        while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
 | 
					        while (cause != null && cause != previousCause &&
 | 
				
			||||||
 | 
					                !(cause instanceof CertificateCombinedException)) {
 | 
				
			||||||
            previousCause = cause;
 | 
					            previousCause = cause;
 | 
				
			||||||
            cause = cause.getCause();
 | 
					            cause = cause.getCause();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -315,8 +353,10 @@ public class RemoteOperationResult implements Serializable {
 | 
				
			|||||||
                return "Unrecovered transport exception";
 | 
					                return "Unrecovered transport exception";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            } else if (mException instanceof AccountNotFoundException) {
 | 
					            } else if (mException instanceof AccountNotFoundException) {
 | 
				
			||||||
                Account failedAccount = ((AccountNotFoundException)mException).getFailedAccount();
 | 
					                Account failedAccount =
 | 
				
			||||||
                return mException.getMessage() + " (" + (failedAccount != null ? failedAccount.name : "NULL") + ")";
 | 
					                        ((AccountNotFoundException)mException).getFailedAccount();
 | 
				
			||||||
 | 
					                return mException.getMessage() + " (" +
 | 
				
			||||||
 | 
					                        (failedAccount != null ? failedAccount.name : "NULL") + ")";
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            } else if (mException instanceof AccountsException) {
 | 
					            } else if (mException instanceof AccountsException) {
 | 
				
			||||||
                return "Exception while using account";
 | 
					                return "Exception while using account";
 | 
				
			||||||
@ -353,7 +393,8 @@ public class RemoteOperationResult implements Serializable {
 | 
				
			|||||||
                return "The file name contains an forbidden character";
 | 
					                return "The file name contains an forbidden character";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")";
 | 
					        return "Operation finished with HTTP status code " + mHttpCode + " (" +
 | 
				
			||||||
 | 
					                (isSuccess() ? "success" : "fail") + ")";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -385,7 +426,8 @@ public class RemoteOperationResult implements Serializable {
 | 
				
			|||||||
	 * @return boolean true/false
 | 
						 * @return boolean true/false
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public boolean isNonSecureRedirection() {
 | 
						public boolean isNonSecureRedirection() {
 | 
				
			||||||
		return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://")));
 | 
							return (mRedirectedLocation != null &&
 | 
				
			||||||
 | 
					                !(mRedirectedLocation.toLowerCase().startsWith("https://")));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String getAuthenticateHeader() {
 | 
					    public String getAuthenticateHeader() {
 | 
				
			||||||
 | 
				
			|||||||
@ -24,8 +24,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.owncloud.android.lib.resources.files;
 | 
					package com.owncloud.android.lib.resources.files;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.ByteArrayInputStream;
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.io.InputStream;
 | 
				
			||||||
import java.io.RandomAccessFile;
 | 
					import java.io.RandomAccessFile;
 | 
				
			||||||
import java.nio.channels.FileChannel;
 | 
					import java.nio.channels.FileChannel;
 | 
				
			||||||
import java.util.Random;
 | 
					import java.util.Random;
 | 
				
			||||||
@ -37,6 +39,7 @@ import com.owncloud.android.lib.common.OwnCloudClient;
 | 
				
			|||||||
import com.owncloud.android.lib.common.network.ChunkFromFileChannelRequestEntity;
 | 
					import com.owncloud.android.lib.common.network.ChunkFromFileChannelRequestEntity;
 | 
				
			||||||
import com.owncloud.android.lib.common.network.ProgressiveDataTransferer;
 | 
					import com.owncloud.android.lib.common.network.ProgressiveDataTransferer;
 | 
				
			||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
 | 
					import com.owncloud.android.lib.common.network.WebdavUtils;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.common.operations.InvalidCharacterExceptionParser;
 | 
				
			||||||
import com.owncloud.android.lib.common.utils.Log_OC;
 | 
					import com.owncloud.android.lib.common.utils.Log_OC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -46,7 +49,7 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
 | 
				
			|||||||
    private static final String OC_CHUNKED_HEADER = "OC-Chunked";
 | 
					    private static final String OC_CHUNKED_HEADER = "OC-Chunked";
 | 
				
			||||||
    private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
 | 
					    private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType) {
 | 
					    public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType){
 | 
				
			||||||
		 super(storagePath, remotePath, mimeType);	
 | 
							 super(storagePath, remotePath, mimeType);	
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -61,17 +64,21 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
 | 
				
			|||||||
            raf = new RandomAccessFile(file, "r");
 | 
					            raf = new RandomAccessFile(file, "r");
 | 
				
			||||||
            channel = raf.getChannel();
 | 
					            channel = raf.getChannel();
 | 
				
			||||||
            mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file);
 | 
					            mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file);
 | 
				
			||||||
            //((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners());
 | 
					            //((ProgressiveDataTransferer)mEntity).
 | 
				
			||||||
 | 
					            // addDatatransferProgressListeners(getDataTransferListeners());
 | 
				
			||||||
            synchronized (mDataTransferListeners) {
 | 
					            synchronized (mDataTransferListeners) {
 | 
				
			||||||
				((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
 | 
									((ProgressiveDataTransferer)mEntity)
 | 
				
			||||||
 | 
					                        .addDatatransferProgressListeners(mDataTransferListeners);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            long offset = 0;
 | 
					            long offset = 0;
 | 
				
			||||||
            String uriPrefix = client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
 | 
					            String uriPrefix = client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath) +
 | 
				
			||||||
 | 
					                    "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
 | 
				
			||||||
            long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
 | 
					            long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
 | 
				
			||||||
            for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
 | 
					            for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
 | 
				
			||||||
                if (mPutMethod != null) {
 | 
					                if (mPutMethod != null) {
 | 
				
			||||||
                    mPutMethod.releaseConnection();    // let the connection available for other methods
 | 
					                    mPutMethod.releaseConnection();     // let the connection available
 | 
				
			||||||
 | 
					                                                        // for other methods
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
 | 
					                mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
 | 
				
			||||||
                mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
 | 
					                mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
 | 
				
			||||||
@ -79,8 +86,26 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
 | 
				
			|||||||
                ((ChunkFromFileChannelRequestEntity) mEntity).setOffset(offset);
 | 
					                ((ChunkFromFileChannelRequestEntity) mEntity).setOffset(offset);
 | 
				
			||||||
                mPutMethod.setRequestEntity(mEntity);
 | 
					                mPutMethod.setRequestEntity(mEntity);
 | 
				
			||||||
                status = client.executeMethod(mPutMethod);
 | 
					                status = client.executeMethod(mPutMethod);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (status == 400) {
 | 
				
			||||||
 | 
					                    InvalidCharacterExceptionParser xmlParser =
 | 
				
			||||||
 | 
					                            new InvalidCharacterExceptionParser();
 | 
				
			||||||
 | 
					                    InputStream is = new ByteArrayInputStream(
 | 
				
			||||||
 | 
					                            mPutMethod.getResponseBodyAsString().getBytes());
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        mForbiddenCharsInServer = xmlParser.parseXMLResponse(is);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    } catch (Exception e) {
 | 
				
			||||||
 | 
					                        mForbiddenCharsInServer = false;
 | 
				
			||||||
 | 
					                        Log_OC.e(TAG, "Exception reading exception from server", e);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
 | 
					                client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
 | 
				
			||||||
                Log_OC.d(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status);
 | 
					                Log_OC.d(TAG, "Upload of " + mLocalPath + " to " + mRemotePath +
 | 
				
			||||||
 | 
					                        ", chunk index " + chunkIndex + ", count " + chunkCount +
 | 
				
			||||||
 | 
					                        ", HTTP result status " + status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!isSuccess(status))
 | 
					                if (!isSuccess(status))
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.owncloud.android.lib.resources.files;
 | 
					package com.owncloud.android.lib.resources.files;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.commons.httpclient.HttpStatus;
 | 
					 | 
				
			||||||
import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
 | 
					import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.owncloud.android.lib.common.OwnCloudClient;
 | 
					import com.owncloud.android.lib.common.OwnCloudClient;
 | 
				
			||||||
@ -33,7 +32,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
 | 
				
			|||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
				
			||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 | 
				
			||||||
import com.owncloud.android.lib.common.utils.Log_OC;
 | 
					import com.owncloud.android.lib.common.utils.Log_OC;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -58,7 +57,8 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
 | 
				
			|||||||
     * Constructor
 | 
					     * Constructor
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @param remotePath            Full path to the new directory to create in the remote server.
 | 
					     * @param remotePath            Full path to the new directory to create in the remote server.
 | 
				
			||||||
     * @param createFullPath        'True' means that all the ancestor folders should be created if don't exist yet.
 | 
					     * @param createFullPath        'True' means that all the ancestor folders should be created
 | 
				
			||||||
 | 
					     *                              if don't exist yet.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public CreateRemoteFolderOperation(String remotePath, boolean createFullPath) {
 | 
					    public CreateRemoteFolderOperation(String remotePath, boolean createFullPath) {
 | 
				
			||||||
        mRemotePath = remotePath;
 | 
					        mRemotePath = remotePath;
 | 
				
			||||||
@ -73,7 +73,10 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    protected RemoteOperationResult run(OwnCloudClient client) {
 | 
					    protected RemoteOperationResult run(OwnCloudClient client) {
 | 
				
			||||||
        RemoteOperationResult result = null;
 | 
					        RemoteOperationResult result = null;
 | 
				
			||||||
        boolean noInvalidChars = FileUtils.isValidPath(mRemotePath);
 | 
					        OwnCloudVersion version = client.getOwnCloudVersion();
 | 
				
			||||||
 | 
					        boolean versionWithForbiddenChars =
 | 
				
			||||||
 | 
					                (version != null && version.isVersionWithForbiddenCharacters());
 | 
				
			||||||
 | 
					        boolean noInvalidChars = FileUtils.isValidPath(mRemotePath, versionWithForbiddenChars);
 | 
				
			||||||
        if (noInvalidChars) {
 | 
					        if (noInvalidChars) {
 | 
				
			||||||
        	result = createFolder(client);
 | 
					        	result = createFolder(client);
 | 
				
			||||||
    		if (!result.isSuccess() && mCreateFullPath && 
 | 
					    		if (!result.isSuccess() && mCreateFullPath && 
 | 
				
			||||||
@ -98,8 +101,16 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
 | 
				
			|||||||
    	try {
 | 
					    	try {
 | 
				
			||||||
    		mkcol = new MkColMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath));
 | 
					    		mkcol = new MkColMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath));
 | 
				
			||||||
    		int status =  client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);
 | 
					    		int status =  client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);
 | 
				
			||||||
    		result = new RemoteOperationResult(mkcol.succeeded(), status, mkcol.getResponseHeaders());
 | 
					            if ( status == 400 ) {
 | 
				
			||||||
 | 
					                result = new RemoteOperationResult(mkcol.succeeded(),
 | 
				
			||||||
 | 
					                        mkcol.getResponseBodyAsString(), status);
 | 
				
			||||||
 | 
					                Log_OC.d(TAG, mkcol.getResponseBodyAsString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                result = new RemoteOperationResult(mkcol.succeeded(), status,
 | 
				
			||||||
 | 
					                        mkcol.getResponseHeaders());
 | 
				
			||||||
                Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
 | 
					                Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            client.exhaustResponse(mkcol.getResponseBodyAsStream());
 | 
					            client.exhaustResponse(mkcol.getResponseBodyAsStream());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    	} catch (Exception e) {
 | 
					    	} catch (Exception e) {
 | 
				
			||||||
 | 
				
			|||||||
@ -27,9 +27,12 @@ package com.owncloud.android.lib.resources.files;
 | 
				
			|||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.owncloud.android.lib.common.utils.Log_OC;
 | 
					import com.owncloud.android.lib.common.utils.Log_OC;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class FileUtils {
 | 
					public class FileUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static final  String TAG = FileUtils.class.getSimpleName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static final String PATH_SEPARATOR = "/";
 | 
						public static final String PATH_SEPARATOR = "/";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -40,39 +43,44 @@ public class FileUtils {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Validate the fileName to detect if contains any forbidden character: / , \ , < , > , : , " , | , ? , *
 | 
						 * Validate the fileName to detect if contains any forbidden character: / , \ , < , > ,
 | 
				
			||||||
 | 
						 * : , " , | , ? , *
 | 
				
			||||||
	 * @param fileName
 | 
						 * @param fileName
 | 
				
			||||||
 | 
						 * @param versionSupportsForbiddenChars
 | 
				
			||||||
	 * @return
 | 
						 * @return
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public static boolean isValidName(String fileName) {
 | 
						public static boolean isValidName(String fileName, boolean versionSupportsForbiddenChars) {
 | 
				
			||||||
		boolean result = true;
 | 
							boolean result = true;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		Log_OC.d("FileUtils", "fileName =======" + fileName);
 | 
							Log_OC.d(TAG, "fileName =======" + fileName);
 | 
				
			||||||
		if (fileName.contains(PATH_SEPARATOR) ||
 | 
							if ( (versionSupportsForbiddenChars && fileName.contains(PATH_SEPARATOR)) ||
 | 
				
			||||||
 | 
									(!versionSupportsForbiddenChars && ( fileName.contains(PATH_SEPARATOR) ||
 | 
				
			||||||
				fileName.contains("\\") || fileName.contains("<") || fileName.contains(">") ||
 | 
									fileName.contains("\\") || fileName.contains("<") || fileName.contains(">") ||
 | 
				
			||||||
				fileName.contains(":") || fileName.contains("\"") || fileName.contains("|") ||
 | 
									fileName.contains(":") || fileName.contains("\"") || fileName.contains("|") ||
 | 
				
			||||||
				fileName.contains("?") || fileName.contains("*")) {
 | 
									fileName.contains("?") || fileName.contains("*") ) ) ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			result = false;
 | 
								result = false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return result;
 | 
							return result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Validate the path to detect if contains any forbidden character: \ , < , > , : , " , | , ? , *
 | 
						 * Validate the path to detect if contains any forbidden character: \ , < , > , : , " , | ,
 | 
				
			||||||
 | 
						 * ? , *
 | 
				
			||||||
	 * @param path
 | 
						 * @param path
 | 
				
			||||||
	 * @return
 | 
						 * @return
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public static boolean isValidPath(String path) {
 | 
						public static boolean isValidPath(String path, boolean versionSupportsForbidenChars) {
 | 
				
			||||||
		boolean result = true;
 | 
							boolean result = true;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		Log_OC.d("FileUtils", "path ....... " + path);
 | 
							Log_OC.d(TAG, "path ....... " + path);
 | 
				
			||||||
		if (path.contains("\\") || path.contains("<") || path.contains(">") ||
 | 
							if (!versionSupportsForbidenChars &&
 | 
				
			||||||
 | 
									(path.contains("\\") || path.contains("<") || path.contains(">") ||
 | 
				
			||||||
				path.contains(":") || path.contains("\"") || path.contains("|") || 
 | 
									path.contains(":") || path.contains("\"") || path.contains("|") || 
 | 
				
			||||||
				path.contains("?") || path.contains("*")) {
 | 
									path.contains("?") || path.contains("*") ) ){
 | 
				
			||||||
			result = false;
 | 
								result = false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return result;
 | 
							return result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,8 @@ import com.owncloud.android.lib.common.network.WebdavUtils;
 | 
				
			|||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperation;
 | 
				
			||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
				
			||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.common.utils.Log_OC;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -88,8 +90,12 @@ public class MoveRemoteFileOperation extends RemoteOperation {
 | 
				
			|||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	protected RemoteOperationResult run(OwnCloudClient client) {
 | 
						protected RemoteOperationResult run(OwnCloudClient client) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							OwnCloudVersion version = client.getOwnCloudVersion();
 | 
				
			||||||
 | 
							boolean versionWithForbiddenChars =
 | 
				
			||||||
 | 
					                (version != null && version.isVersionWithForbiddenCharacters());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    	/// check parameters
 | 
					    	/// check parameters
 | 
				
			||||||
        if (!FileUtils.isValidPath(mTargetRemotePath)) {
 | 
					        if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
 | 
				
			||||||
        	return new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
 | 
					        	return new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -128,8 +134,11 @@ public class MoveRemoteFileOperation extends RemoteOperation {
 | 
				
			|||||||
    		/// for other errors that could be explicitly handled, check first:
 | 
					    		/// for other errors that could be explicitly handled, check first:
 | 
				
			||||||
    		/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4
 | 
					    		/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4
 | 
				
			||||||
        		
 | 
					        		
 | 
				
			||||||
 | 
					        	} else if (status == 400) {
 | 
				
			||||||
 | 
									result = new RemoteOperationResult(move.succeeded(),
 | 
				
			||||||
 | 
											move.getResponseBodyAsString(), status);
 | 
				
			||||||
 | 
									Log_OC.d(TAG, move.getResponseBodyAsString());
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
        		
 | 
					 | 
				
			||||||
					result = new RemoteOperationResult(
 | 
										result = new RemoteOperationResult(
 | 
				
			||||||
							isSuccess(status), 	// move.succeeded()? trustful?
 | 
												isSuccess(status), 	// move.succeeded()? trustful?
 | 
				
			||||||
							status,
 | 
												status,
 | 
				
			||||||
 | 
				
			|||||||
@ -34,6 +34,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
 | 
				
			|||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
				
			||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 | 
				
			||||||
import com.owncloud.android.lib.common.utils.Log_OC;
 | 
					import com.owncloud.android.lib.common.utils.Log_OC;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -89,16 +90,17 @@ public class RenameRemoteFileOperation extends RemoteOperation {
 | 
				
			|||||||
		
 | 
							
 | 
				
			||||||
		LocalMoveMethod move = null;
 | 
							LocalMoveMethod move = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        boolean noInvalidChars = FileUtils.isValidPath(mNewRemotePath);
 | 
					        OwnCloudVersion version = client.getOwnCloudVersion();
 | 
				
			||||||
 | 
					        boolean versionWithForbiddenChars =
 | 
				
			||||||
 | 
					                (version != null && version.isVersionWithForbiddenCharacters());
 | 
				
			||||||
 | 
					        boolean noInvalidChars = FileUtils.isValidPath(mNewRemotePath, versionWithForbiddenChars);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (noInvalidChars) {
 | 
					        if (noInvalidChars) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (mNewName.equals(mOldName)) {
 | 
					                if (mNewName.equals(mOldName)) {
 | 
				
			||||||
                    return new RemoteOperationResult(ResultCode.OK);
 | 
					                    return new RemoteOperationResult(ResultCode.OK);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            
 | 
					 | 
				
			||||||
                // check if a file with the new name already exists
 | 
					                // check if a file with the new name already exists
 | 
				
			||||||
                if (client.existsFile(mNewRemotePath)) {
 | 
					                if (client.existsFile(mNewRemotePath)) {
 | 
				
			||||||
                    return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
 | 
					                    return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
 | 
				
			||||||
@ -107,13 +109,21 @@ public class RenameRemoteFileOperation extends RemoteOperation {
 | 
				
			|||||||
                move = new LocalMoveMethod( client.getWebdavUri() +
 | 
					                move = new LocalMoveMethod( client.getWebdavUri() +
 | 
				
			||||||
                        WebdavUtils.encodePath(mOldRemotePath),
 | 
					                        WebdavUtils.encodePath(mOldRemotePath),
 | 
				
			||||||
                        client.getWebdavUri() + WebdavUtils.encodePath(mNewRemotePath));
 | 
					                        client.getWebdavUri() + WebdavUtils.encodePath(mNewRemotePath));
 | 
				
			||||||
            int status = client.executeMethod(move, RENAME_READ_TIMEOUT, RENAME_CONNECTION_TIMEOUT);
 | 
					                int status = client.executeMethod(move, RENAME_READ_TIMEOUT,
 | 
				
			||||||
 | 
					                        RENAME_CONNECTION_TIMEOUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            move.getResponseBodyAsString(); // exhaust response, although not interesting
 | 
					                if (status == 400) {
 | 
				
			||||||
            result = new RemoteOperationResult(move.succeeded(), status, move.getResponseHeaders());
 | 
					                    result = new RemoteOperationResult(move.succeeded(),
 | 
				
			||||||
 | 
					                            move.getResponseBodyAsString(), status);
 | 
				
			||||||
 | 
					                    Log_OC.d(TAG, move.getResponseBodyAsString());
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    client.exhaustResponse(move.getResponseBodyAsStream());//exhaust response,
 | 
				
			||||||
 | 
					                                                                         // although not interesting
 | 
				
			||||||
 | 
					                    result = new RemoteOperationResult(move.succeeded(), status,
 | 
				
			||||||
 | 
					                            move.getResponseHeaders());
 | 
				
			||||||
                    Log_OC.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " +
 | 
					                    Log_OC.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " +
 | 
				
			||||||
                            result.getLogMessage());
 | 
					                            result.getLogMessage());
 | 
				
			||||||
            
 | 
					                }
 | 
				
			||||||
            } catch (Exception e) {
 | 
					            } catch (Exception e) {
 | 
				
			||||||
                result = new RemoteOperationResult(e);
 | 
					                result = new RemoteOperationResult(e);
 | 
				
			||||||
                Log_OC.e(TAG, "Rename " + mOldRemotePath + " to " +
 | 
					                Log_OC.e(TAG, "Rename " + mOldRemotePath + " to " +
 | 
				
			||||||
@ -124,6 +134,7 @@ public class RenameRemoteFileOperation extends RemoteOperation {
 | 
				
			|||||||
                if (move != null)
 | 
					                if (move != null)
 | 
				
			||||||
                    move.releaseConnection();
 | 
					                    move.releaseConnection();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
        	result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
 | 
					        	result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -24,8 +24,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.owncloud.android.lib.resources.files;
 | 
					package com.owncloud.android.lib.resources.files;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.ByteArrayInputStream;
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.io.InputStream;
 | 
				
			||||||
import java.util.HashSet;
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
import java.util.concurrent.atomic.AtomicBoolean;
 | 
					import java.util.concurrent.atomic.AtomicBoolean;
 | 
				
			||||||
@ -40,9 +42,11 @@ import com.owncloud.android.lib.common.network.FileRequestEntity;
 | 
				
			|||||||
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
 | 
					import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
 | 
				
			||||||
import com.owncloud.android.lib.common.network.ProgressiveDataTransferer;
 | 
					import com.owncloud.android.lib.common.network.ProgressiveDataTransferer;
 | 
				
			||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
 | 
					import com.owncloud.android.lib.common.network.WebdavUtils;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.common.operations.InvalidCharacterExceptionParser;
 | 
				
			||||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
 | 
					import com.owncloud.android.lib.common.operations.OperationCancelledException;
 | 
				
			||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperation;
 | 
				
			||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
					import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
				
			||||||
 | 
					import com.owncloud.android.lib.common.utils.Log_OC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Remote operation performing the upload of a remote file to the ownCloud server.
 | 
					 * Remote operation performing the upload of a remote file to the ownCloud server.
 | 
				
			||||||
@ -53,12 +57,15 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class UploadRemoteFileOperation extends RemoteOperation {
 | 
					public class UploadRemoteFileOperation extends RemoteOperation {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static final String TAG = UploadRemoteFileOperation.class.getSimpleName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length";
 | 
						protected static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected String mLocalPath;
 | 
						protected String mLocalPath;
 | 
				
			||||||
	protected String mRemotePath;
 | 
						protected String mRemotePath;
 | 
				
			||||||
	protected String mMimeType;
 | 
						protected String mMimeType;
 | 
				
			||||||
	protected PutMethod mPutMethod = null;
 | 
						protected PutMethod mPutMethod = null;
 | 
				
			||||||
 | 
						protected boolean mForbiddenCharsInServer = false;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
 | 
						private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
 | 
				
			||||||
	protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
 | 
						protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
 | 
				
			||||||
@ -87,10 +94,13 @@ public class UploadRemoteFileOperation extends RemoteOperation {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int status = uploadFile(client);
 | 
								int status = uploadFile(client);
 | 
				
			||||||
 | 
								if (mForbiddenCharsInServer){
 | 
				
			||||||
 | 
									result = new RemoteOperationResult(
 | 
				
			||||||
 | 
											RemoteOperationResult.ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
				result = new RemoteOperationResult(isSuccess(status), status,
 | 
									result = new RemoteOperationResult(isSuccess(status), status,
 | 
				
			||||||
						(mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
 | 
											(mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} catch (Exception e) {
 | 
							} catch (Exception e) {
 | 
				
			||||||
			// TODO something cleaner with cancellations
 | 
								// TODO something cleaner with cancellations
 | 
				
			||||||
			if (mCancellationRequested.get()) {
 | 
								if (mCancellationRequested.get()) {
 | 
				
			||||||
@ -120,6 +130,20 @@ public class UploadRemoteFileOperation extends RemoteOperation {
 | 
				
			|||||||
			mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(f.length()));
 | 
								mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(f.length()));
 | 
				
			||||||
			mPutMethod.setRequestEntity(mEntity);
 | 
								mPutMethod.setRequestEntity(mEntity);
 | 
				
			||||||
			status = client.executeMethod(mPutMethod);
 | 
								status = client.executeMethod(mPutMethod);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (status == 400) {
 | 
				
			||||||
 | 
									InvalidCharacterExceptionParser xmlParser = new InvalidCharacterExceptionParser();
 | 
				
			||||||
 | 
									InputStream is = new ByteArrayInputStream(
 | 
				
			||||||
 | 
											mPutMethod.getResponseBodyAsString().getBytes());
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										mForbiddenCharsInServer = xmlParser.parseXMLResponse(is);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									} catch (Exception e) {
 | 
				
			||||||
 | 
										mForbiddenCharsInServer = false;
 | 
				
			||||||
 | 
										Log_OC.e(TAG, "Exception reading exception from server", e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
 | 
								client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} finally {
 | 
							} finally {
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,8 @@ public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    public static final int MINIMUM_VERSION_FOR_SHARING_API = 0x05001B00; // 5.0.27
 | 
					    public static final int MINIMUM_VERSION_FOR_SHARING_API = 0x05001B00; // 5.0.27
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final int MINIMUM_VERSION_WITH_FORBIDDEN_CHARS = 0x08010000; // 8.1
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    private static final int MAX_DOTS = 3;
 | 
					    private static final int MAX_DOTS = 3;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // format is in version
 | 
					    // format is in version
 | 
				
			||||||
@ -121,5 +123,9 @@ public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
 | 
				
			|||||||
    	return (mVersion >= MINIMUM_VERSION_FOR_SHARING_API);
 | 
					    	return (mVersion >= MINIMUM_VERSION_FOR_SHARING_API);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isVersionWithForbiddenCharacters() {
 | 
				
			||||||
 | 
					        return (mVersion >= MINIMUM_VERSION_WITH_FORBIDDEN_CHARS);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user