Пример #1
0
  /** {@inheritDoc} */
  @Override
  public Bundle addAccount(
      AccountAuthenticatorResponse response,
      String accountType,
      String authTokenType,
      String[] requiredFeatures,
      Bundle options)
      throws NetworkErrorException {
    Log_OC.i(TAG, "Adding account with type " + accountType + " and auth token " + authTokenType);

    final Bundle bundle = new Bundle();

    AccountManager accountManager = AccountManager.get(mContext);
    Account[] accounts = accountManager.getAccountsByType(MainApp.getAccountType());

    if (mContext.getResources().getBoolean(R.bool.multiaccount_support) || accounts.length < 1) {
      try {
        validateAccountType(accountType);
      } catch (AuthenticatorException e) {
        Log_OC.e(TAG, "Failed to validate account type " + accountType + ": " + e.getMessage());
        e.printStackTrace();
        return e.getFailureBundle();
      }

      final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
      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);

      bundle.putParcelable(AccountManager.KEY_INTENT, intent);

    } else {

      // Return an error
      bundle.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION);
      final String message =
          String.format(
              mContext.getString(R.string.auth_unsupported_multiaccount),
              mContext.getString(R.string.app_name));
      bundle.putString(AccountManager.KEY_ERROR_MESSAGE, message);

      mHandler.post(
          new Runnable() {

            @Override
            public void run() {
              Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
            }
          });
    }

    return bundle;
  }
Пример #2
0
  private OCFile obtainNewOCFileToUpload(
      String remotePath, String localPath, String mimeType, FileDataStorageManager storageManager) {
    OCFile newFile = new OCFile(remotePath);
    newFile.setStoragePath(localPath);
    newFile.setLastSyncDateForProperties(0);
    newFile.setLastSyncDateForData(0);

    // size
    if (localPath != null && localPath.length() > 0) {
      File localFile = new File(localPath);
      newFile.setFileLength(localFile.length());
      newFile.setLastSyncDateForData(localFile.lastModified());
    } // don't worry about not assigning size, the problems with localPath
    // are checked when the UploadFileOperation instance is created

    // MIME type
    if (mimeType == null || mimeType.length() <= 0) {
      try {
        mimeType =
            MimeTypeMap.getSingleton()
                .getMimeTypeFromExtension(remotePath.substring(remotePath.lastIndexOf('.') + 1));
      } catch (IndexOutOfBoundsException e) {
        Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + remotePath);
      }
    }
    if (mimeType == null) {
      mimeType = "application/octet-stream";
    }
    newFile.setMimetype(mimeType);

    return newFile;
  }
Пример #3
0
  private void populateDirectoryList() {
    setContentView(R.layout.uploader_layout);

    String full_path = "";
    for (String a : mParents) full_path += a + "/";

    Log_OC.d(TAG, "Populating view with content of : " + full_path);

    mFile = mStorageManager.getFileByPath(full_path);
    if (mFile != null) {
      Vector<OCFile> files = mStorageManager.getFolderContent(mFile);
      List<HashMap<String, Object>> data = new LinkedList<HashMap<String, Object>>();
      for (OCFile f : files) {
        HashMap<String, Object> h = new HashMap<String, Object>();
        if (f.isFolder()) {
          h.put("dirname", f.getFileName());
          data.add(h);
        }
      }
      SimpleAdapter sa =
          new SimpleAdapter(
              this,
              data,
              R.layout.uploader_list_item_layout,
              new String[] {"dirname"},
              new int[] {R.id.textView1});
      setListAdapter(sa);
      Button btn = (Button) findViewById(R.id.uploader_choose_folder);
      btn.setOnClickListener(this);
      getListView().setOnItemClickListener(this);
    }
  }
Пример #4
0
  /**
   * Checks if the new name to set is valid in the file system
   *
   * <p>The only way to be sure is trying to create a file with that name. It's made in the temporal
   * directory for downloads, out of any account, and then removed.
   *
   * <p>IMPORTANT: The test must be made in the same file system where files are download. The
   * internal storage could be formatted with a different file system.
   *
   * <p>TODO move this method, and maybe FileDownload.get***Path(), to a class with utilities
   * specific for the interactions with the file system
   *
   * @return 'True' if a temporal file named with the name to set could be created in the file
   *     system where local files are stored.
   * @throws IOException When the temporal folder can not be created.
   */
  private boolean isValidNewName() throws IOException {
    // check tricky names
    if (mNewName == null
        || mNewName.length() <= 0
        || mNewName.contains(File.separator)
        || mNewName.contains("%")) {
      return false;
    }
    // create a test file
    String tmpFolderName = FileStorageUtils.getTemporalPath("");
    File testFile = new File(tmpFolderName + mNewName);
    File tmpFolder = testFile.getParentFile();
    tmpFolder.mkdirs();
    if (!tmpFolder.isDirectory()) {
      throw new IOException("Unexpected error: temporal directory could not be created");
    }
    try {
      testFile
          .createNewFile(); // return value is ignored; it could be 'false' because the file already
                            // existed, that doesn't invalidate the name
    } catch (IOException e) {
      Log_OC.i(TAG, "Test for validity of name " + mNewName + " in the file system failed");
      return false;
    }
    boolean result = (testFile.exists() && testFile.isFile());

    // cleaning ; result is ignored, since there is not much we could do in case of failure, but
    // repeat and repeat...
    testFile.delete();

    return result;
  }
 private void onCreateRemoteFolderOperationFinish(
     CreateRemoteFolderOperation operation, RemoteOperationResult result) {
   if (result.isSuccess()) {
     saveFolderInDB();
   } else {
     Log_OC.e(TAG, mRemotePath + "hasn't been created");
   }
 }
Пример #6
0
  /**
   * Entry point to add a new operation to the queue of operations.
   *
   * <p>New operations are added calling to startService(), resulting in a call to this method. This
   * ensures the service will keep on working although the caller activity goes away.
   *
   * <p>IMPORTANT: the only operations performed here right now is {@link GetSharedFilesOperation}.
   * The class is taking advantage of it due to time constraints.
   */
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    if (!intent.hasExtra(EXTRA_ACCOUNT) && !intent.hasExtra(EXTRA_SERVER_URL)) {
      Log_OC.e(TAG, "Not enough information provided in intent");
      return START_NOT_STICKY;
    }
    try {
      Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
      String serverUrl = intent.getStringExtra(EXTRA_SERVER_URL);

      Target target = new Target(account, (serverUrl == null) ? null : Uri.parse(serverUrl));
      RemoteOperation operation = null;

      String action = intent.getAction();
      if (action.equals(ACTION_CREATE_SHARE)) { // Create Share
        String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
        Intent sendIntent = intent.getParcelableExtra(EXTRA_SEND_INTENT);
        if (remotePath.length() > 0) {
          operation =
              new CreateShareOperation(
                  remotePath, ShareType.PUBLIC_LINK, "", false, "", 1, sendIntent);
        }
      } else if (action.equals(ACTION_UNSHARE)) { // Unshare file
        String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
        if (remotePath.length() > 0) {
          operation = new UnshareLinkOperation(remotePath, this.getApplicationContext());
        }
      } else {
        // nothing we are going to handle
        return START_NOT_STICKY;
      }

      mPendingOperations.add(new Pair<Target, RemoteOperation>(target, operation));
      // sendBroadcastNewOperation(target, operation);

      Message msg = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      mServiceHandler.sendMessage(msg);

    } catch (IllegalArgumentException e) {
      Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage());
      return START_NOT_STICKY;
    }

    return START_NOT_STICKY;
  }
  /** Save new directory in local database */
  public void saveFolderInDB() {
    OCFile newDir = new OCFile(mRemotePath);
    newDir.setMimetype("DIR");
    long parentId =
        mStorageManager.getFileByPath(FileStorageUtils.getParentPath(mRemotePath)).getFileId();
    newDir.setParentId(parentId);
    newDir.setModificationTimestamp(System.currentTimeMillis());
    mStorageManager.saveFile(newDir);

    Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database");
  }
Пример #8
0
 /** Service initialization */
 @Override
 public void onCreate() {
   super.onCreate();
   Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
   mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
   HandlerThread thread =
       new HandlerThread("FileUploaderThread", Process.THREAD_PRIORITY_BACKGROUND);
   thread.start();
   mServiceLooper = thread.getLooper();
   mServiceHandler = new ServiceHandler(mServiceLooper, this);
   mBinder = new FileUploaderBinder();
 }
  @Override
  protected RemoteOperationResult run(OwnCloudClient client) {
    CreateRemoteFolderOperation operation =
        new CreateRemoteFolderOperation(mRemotePath, mCreateFullPath);
    RemoteOperationResult result = operation.execute(client);

    if (result.isSuccess()) {
      saveFolderInDB();
    } else {
      Log_OC.e(TAG, mRemotePath + "hasn't been created");
    }

    return result;
  }
Пример #10
0
  /**
   * Performs the rename operation.
   *
   * @param client Client object to communicate with the remote ownCloud server.
   */
  @Override
  protected RemoteOperationResult run(OwnCloudClient client) {
    RemoteOperationResult result = null;

    // check if the new name is valid in the local file system
    try {
      if (!isValidNewName()) {
        return new RemoteOperationResult(ResultCode.INVALID_LOCAL_FILE_NAME);
      }
      String parent = (new File(mFile.getRemotePath())).getParent();
      parent = (parent.endsWith(OCFile.PATH_SEPARATOR)) ? parent : parent + OCFile.PATH_SEPARATOR;
      mNewRemotePath = parent + mNewName;
      if (mFile.isFolder()) {
        mNewRemotePath += OCFile.PATH_SEPARATOR;
      }

      // ckeck local overwrite
      if (mStorageManager.getFileByPath(mNewRemotePath) != null) {
        return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
      }

      RenameRemoteFileOperation operation =
          new RenameRemoteFileOperation(
              mFile.getFileName(), mFile.getRemotePath(), mNewName, mFile.isFolder());
      result = operation.execute(client);

      if (result.isSuccess()) {
        if (mFile.isFolder()) {
          saveLocalDirectory();

        } else {
          saveLocalFile();
        }
      }

    } catch (IOException e) {
      Log_OC.e(
          TAG,
          "Rename "
              + mFile.getRemotePath()
              + " to "
              + ((mNewRemotePath == null) ? mNewName : mNewRemotePath)
              + ": "
              + ((result != null) ? result.getLogMessage() : ""),
          e);
    }

    return result;
  }
Пример #11
0
 @Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   getWindow().requestFeature(Window.FEATURE_NO_TITLE);
   mParents = new Stack<String>();
   mParents.add("");
   if (prepareStreamsToUpload()) {
     mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
     Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType());
     if (accounts.length == 0) {
       Log_OC.i(TAG, "No ownCloud account is available");
       showDialog(DIALOG_NO_ACCOUNT);
     } else if (accounts.length > 1) {
       Log_OC.i(TAG, "More then one ownCloud is available");
       showDialog(DIALOG_MULTIPLE_ACCOUNT);
     } else {
       mAccount = accounts[0];
       mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
       populateDirectoryList();
     }
   } else {
     showDialog(DIALOG_NO_STREAM);
   }
 }
Пример #12
0
 @Override
 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
   // click on folder in the list
   Log_OC.d(TAG, "on item click");
   Vector<OCFile> tmpfiles = mStorageManager.getFolderContent(mFile);
   if (tmpfiles.size() <= 0) return;
   // filter on dirtype
   Vector<OCFile> files = new Vector<OCFile>();
   for (OCFile f : tmpfiles) if (f.isFolder()) files.add(f);
   if (files.size() < position) {
     throw new IndexOutOfBoundsException("Incorrect item selected");
   }
   mParents.push(files.get(position).getFileName());
   populateDirectoryList();
 }
Пример #13
0
  @Override
  public void onClick(View v) {
    // click on button
    switch (v.getId()) {
      case R.id.uploader_choose_folder:
        mUploadPath =
            ""; // first element in mParents is root dir, represented by ""; init mUploadPath with
        // "/" results in a "//" prefix
        for (String p : mParents) mUploadPath += p + OCFile.PATH_SEPARATOR;
        Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);

        uploadFiles();

        break;
      default:
        throw new IllegalArgumentException("Wrong element clicked");
    }
  }
Пример #14
0
  /** {@inheritDoc} */
  @Override
  public Bundle getAuthToken(
      AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
      throws NetworkErrorException {
    /// validate parameters
    try {
      validateAccountType(account.type);
      validateAuthTokenType(authTokenType);
    } catch (AuthenticatorException e) {
      Log_OC.e(TAG, "Failed to validate account type " + account.type + ": " + e.getMessage());
      e.printStackTrace();
      return e.getFailureBundle();
    }

    /// check if required token is stored
    final AccountManager am = AccountManager.get(mContext);
    String accessToken;
    if (authTokenType.equals(AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType()))) {
      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, MainApp.getAccountType());
      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(KEY_AUTH_TOKEN_TYPE, authTokenType);
    intent.putExtra(KEY_LOGIN_OPTIONS, options);
    intent.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, account);
    intent.putExtra(AuthenticatorActivity.EXTRA_ENFORCED_UPDATE, true);
    intent.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);

    final Bundle bundle = new Bundle();
    bundle.putParcelable(AccountManager.KEY_INTENT, intent);
    return bundle;
  }
Пример #15
0
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   Log_OC.i(TAG, "result received. req: " + requestCode + " res: " + resultCode);
   if (requestCode == REQUEST_CODE_SETUP_ACCOUNT) {
     dismissDialog(DIALOG_NO_ACCOUNT);
     if (resultCode == RESULT_CANCELED) {
       finish();
     }
     Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAuthTokenType());
     if (accounts.length == 0) {
       showDialog(DIALOG_NO_ACCOUNT);
     } else {
       // there is no need for checking for is there more then one
       // account at this point
       // since account setup can set only one account at time
       mAccount = accounts[0];
       populateDirectoryList();
     }
   }
 }
Пример #16
0
  /** {@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;
  }
Пример #17
0
  /**
   * Updates the status notification with the result of an upload operation.
   *
   * @param uploadResult Result of the upload operation.
   * @param upload Finished upload operation
   */
  private void notifyUploadResult(RemoteOperationResult uploadResult, UploadFileOperation upload) {
    Log_OC.d(TAG, "NotifyUploadResult with resultCode: " + uploadResult.getCode());
    if (uploadResult.isCancelled()) {
      // / cancelled operation -> silent removal of progress notification
      mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);

    } else if (uploadResult.isSuccess()) {
      // / success -> silent update of progress notification to success
      // message
      mNotification.flags ^= Notification.FLAG_ONGOING_EVENT; // remove
      // the
      // ongoing
      // flag
      mNotification.flags |= Notification.FLAG_AUTO_CANCEL;
      mNotification.contentView = mDefaultNotificationContentView;

      /// includes a pending intent in the notification showing the details view of the file
      Intent showDetailsIntent = null;
      if (PreviewImageFragment.canBePreviewed(upload.getFile())) {
        showDetailsIntent = new Intent(this, PreviewImageActivity.class);
      } else {
        showDetailsIntent = new Intent(this, FileDisplayActivity.class);
      }
      showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, upload.getFile());
      showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount());
      showDetailsIntent.putExtra(FileActivity.EXTRA_FROM_NOTIFICATION, true);
      showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
      mNotification.contentIntent =
          PendingIntent.getActivity(
              getApplicationContext(), (int) System.currentTimeMillis(), showDetailsIntent, 0);

      mNotification.setLatestEventInfo(
          getApplicationContext(),
          getString(R.string.uploader_upload_succeeded_ticker),
          String.format(
              getString(R.string.uploader_upload_succeeded_content_single), upload.getFileName()),
          mNotification.contentIntent);

      mNotificationManager.notify(
          R.string.uploader_upload_in_progress_ticker, mNotification); // NOT
      // AN
      DbHandler db = new DbHandler(this.getBaseContext());
      db.removeIUPendingFile(mCurrentUpload.getOriginalStoragePath());
      db.close();

    } else {

      // / fail -> explicit failure notification
      mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
      Notification finalNotification =
          new Notification(
              DisplayUtils.getSeasonalIconId(),
              getString(R.string.uploader_upload_failed_ticker),
              System.currentTimeMillis());
      finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
      String content = null;

      boolean needsToUpdateCredentials =
          (uploadResult.getCode() == ResultCode.UNAUTHORIZED
              ||
              // (uploadResult.isTemporalRedirection() && uploadResult.isIdPRedirection() &&
              (uploadResult.isIdPRedirection() && mUploadClient.getCredentials() == null));
      // MainApp.getAuthTokenTypeSamlSessionCookie().equals(mUploadClient.getAuthTokenType())));
      if (needsToUpdateCredentials) {
        // 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_ENFORCED_UPDATE, true);
        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);
        content =
            String.format(
                getString(R.string.uploader_upload_failed_content_single), upload.getFileName());
        finalNotification.setLatestEventInfo(
            getApplicationContext(),
            getString(R.string.uploader_upload_failed_ticker),
            content,
            finalNotification.contentIntent);
        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);
        // }

        if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL
            || uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) {
          // TODO we need a class to provide error messages for the users
          // from a RemoteOperationResult and a RemoteOperation
          content =
              String.format(
                  getString(R.string.error__upload__local_file_not_copied),
                  upload.getFileName(),
                  getString(R.string.app_name));
        } else if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
          content = getString(R.string.failed_upload_quota_exceeded_text);
        } else {
          content =
              String.format(
                  getString(R.string.uploader_upload_failed_content_single), upload.getFileName());
        }

        // we add only for instant-uploads the InstantUploadActivity and the
        // db entry
        Intent detailUploadIntent = null;
        if (upload.isInstant() && InstantUploadActivity.IS_ENABLED) {
          detailUploadIntent = new Intent(this, InstantUploadActivity.class);
          detailUploadIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount());
        } else {
          detailUploadIntent = new Intent(this, FailedUploadActivity.class);
          detailUploadIntent.putExtra(FailedUploadActivity.MESSAGE, content);
        }
        finalNotification.contentIntent =
            PendingIntent.getActivity(
                getApplicationContext(),
                (int) System.currentTimeMillis(),
                detailUploadIntent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);

        if (upload.isInstant()) {
          DbHandler db = null;
          try {
            db = new DbHandler(this.getBaseContext());
            String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode();
            Log_OC.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
            if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
              message = getString(R.string.failed_upload_quota_exceeded_text);
              if (db.updateFileState(
                      upload.getOriginalStoragePath(),
                      DbHandler.UPLOAD_STATUS_UPLOAD_FAILED,
                      message)
                  == 0) {
                db.putFileForLater(
                    upload.getOriginalStoragePath(), upload.getAccount().name, message);
              }
            }
          } finally {
            if (db != null) {
              db.close();
            }
          }
        }
      }
      finalNotification.setLatestEventInfo(
          getApplicationContext(),
          getString(R.string.uploader_upload_failed_ticker),
          content,
          finalNotification.contentIntent);

      mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification);
    }
  }
Пример #18
0
  /**
   * Entry point to add one or several files to the queue of uploads.
   *
   * <p>New uploads are added calling to startService(), resulting in a call to this method. This
   * ensures the service will keep on working although the caller activity goes away.
   */
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    if (!intent.hasExtra(KEY_ACCOUNT)
        || !intent.hasExtra(KEY_UPLOAD_TYPE)
        || !(intent.hasExtra(KEY_LOCAL_FILE) || intent.hasExtra(KEY_FILE))) {
      Log_OC.e(TAG, "Not enough information provided in intent");
      return Service.START_NOT_STICKY;
    }
    int uploadType = intent.getIntExtra(KEY_UPLOAD_TYPE, -1);
    if (uploadType == -1) {
      Log_OC.e(TAG, "Incorrect upload type provided");
      return Service.START_NOT_STICKY;
    }
    Account account = intent.getParcelableExtra(KEY_ACCOUNT);

    String[] localPaths = null, remotePaths = null, mimeTypes = null;
    OCFile[] files = null;
    if (uploadType == UPLOAD_SINGLE_FILE) {

      if (intent.hasExtra(KEY_FILE)) {
        files = new OCFile[] {intent.getParcelableExtra(KEY_FILE)};

      } else {
        localPaths = new String[] {intent.getStringExtra(KEY_LOCAL_FILE)};
        remotePaths = new String[] {intent.getStringExtra(KEY_REMOTE_FILE)};
        mimeTypes = new String[] {intent.getStringExtra(KEY_MIME_TYPE)};
      }

    } else { // mUploadType == UPLOAD_MULTIPLE_FILES

      if (intent.hasExtra(KEY_FILE)) {
        files = (OCFile[]) intent.getParcelableArrayExtra(KEY_FILE); // TODO
        // will
        // this
        // casting
        // work
        // fine?

      } else {
        localPaths = intent.getStringArrayExtra(KEY_LOCAL_FILE);
        remotePaths = intent.getStringArrayExtra(KEY_REMOTE_FILE);
        mimeTypes = intent.getStringArrayExtra(KEY_MIME_TYPE);
      }
    }

    FileDataStorageManager storageManager =
        new FileDataStorageManager(account, getContentResolver());

    boolean forceOverwrite = intent.getBooleanExtra(KEY_FORCE_OVERWRITE, false);
    boolean isInstant = intent.getBooleanExtra(KEY_INSTANT_UPLOAD, false);
    int localAction = intent.getIntExtra(KEY_LOCAL_BEHAVIOUR, LOCAL_BEHAVIOUR_COPY);

    if (intent.hasExtra(KEY_FILE) && files == null) {
      Log_OC.e(TAG, "Incorrect array for OCFiles provided in upload intent");
      return Service.START_NOT_STICKY;

    } else if (!intent.hasExtra(KEY_FILE)) {
      if (localPaths == null) {
        Log_OC.e(TAG, "Incorrect array for local paths provided in upload intent");
        return Service.START_NOT_STICKY;
      }
      if (remotePaths == null) {
        Log_OC.e(TAG, "Incorrect array for remote paths provided in upload intent");
        return Service.START_NOT_STICKY;
      }
      if (localPaths.length != remotePaths.length) {
        Log_OC.e(TAG, "Different number of remote paths and local paths!");
        return Service.START_NOT_STICKY;
      }

      files = new OCFile[localPaths.length];
      for (int i = 0; i < localPaths.length; i++) {
        files[i] =
            obtainNewOCFileToUpload(
                remotePaths[i],
                localPaths[i],
                ((mimeTypes != null) ? mimeTypes[i] : (String) null),
                storageManager);
        if (files[i] == null) {
          // TODO @andomaex add failure Notification
          return Service.START_NOT_STICKY;
        }
      }
    }

    AccountManager aMgr = AccountManager.get(this);
    String version = aMgr.getUserData(account, OwnCloudAccount.Constants.KEY_OC_VERSION);
    String versionString =
        aMgr.getUserData(account, OwnCloudAccount.Constants.KEY_OC_VERSION_STRING);
    OwnCloudVersion ocv = new OwnCloudVersion(version, versionString);
    boolean chunked = FileUploader.chunkedUploadIsSupported(ocv);
    AbstractList<String> requestedUploads = new Vector<String>();
    String uploadKey = null;
    UploadFileOperation newUpload = null;
    try {
      for (int i = 0; i < files.length; i++) {
        uploadKey = buildRemoteName(account, files[i].getRemotePath());
        newUpload =
            new UploadFileOperation(
                account,
                files[i],
                chunked,
                isInstant,
                forceOverwrite,
                localAction,
                getApplicationContext());
        if (isInstant) {
          newUpload.setRemoteFolderToBeCreated();
        }
        mPendingUploads.putIfAbsent(
            uploadKey, newUpload); // Grants that the file only upload once time

        newUpload.addDatatransferProgressListener(this);
        newUpload.addDatatransferProgressListener((FileUploaderBinder) mBinder);
        requestedUploads.add(uploadKey);
      }

    } catch (IllegalArgumentException e) {
      Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage());
      return START_NOT_STICKY;

    } catch (IllegalStateException e) {
      Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage());
      return START_NOT_STICKY;

    } catch (Exception e) {
      Log_OC.e(TAG, "Unexpected exception while processing upload intent", e);
      return START_NOT_STICKY;
    }

    if (requestedUploads.size() > 0) {
      Message msg = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      msg.obj = requestedUploads;
      mServiceHandler.sendMessage(msg);
    }
    Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
    return Service.START_NOT_STICKY;
  }
Пример #19
0
  /**
   * Core upload method: sends the file(s) to upload
   *
   * @param uploadKey Key to access the upload to perform, contained in mPendingUploads
   */
  public void uploadFile(String uploadKey) {

    synchronized (mPendingUploads) {
      mCurrentUpload = mPendingUploads.get(uploadKey);
    }

    if (mCurrentUpload != null) {

      notifyUploadStart(mCurrentUpload);

      RemoteOperationResult uploadResult = null, grantResult = 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 =
              OwnCloudClientFactory.createOwnCloudClient(mLastAccount, getApplicationContext());
        }

        /// check the existence of the parent folder for the file to upload
        String remoteParentPath = new File(mCurrentUpload.getRemotePath()).getParent();
        remoteParentPath =
            remoteParentPath.endsWith(OCFile.PATH_SEPARATOR)
                ? remoteParentPath
                : remoteParentPath + OCFile.PATH_SEPARATOR;
        grantResult = grantFolderExistence(remoteParentPath);

        /// perform the upload
        if (grantResult.isSuccess()) {
          OCFile parent = mStorageManager.getFileByPath(remoteParentPath);
          mCurrentUpload.getFile().setParentId(parent.getFileId());
          uploadResult = mCurrentUpload.execute(mUploadClient);
          if (uploadResult.isSuccess()) {
            saveUploadedFile();
          }
        } else {
          uploadResult = grantResult;
        }

      } 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.");
        }
        if (uploadResult.isException()) {
          // enforce the creation of a new client object for next uploads; this grant that a new
          // socket will
          // be created in the future if the current exception is due to an abrupt lose of network
          // connection
          mUploadClient = null;
        }
      }

      /// notify result

      notifyUploadResult(uploadResult, mCurrentUpload);
      sendFinalBroadcast(mCurrentUpload, uploadResult);
    }
  }
Пример #20
0
  /** Performs the next operation in the queue */
  private void nextOperation() {

    Pair<Target, RemoteOperation> next = null;
    synchronized (mPendingOperations) {
      next = mPendingOperations.peek();
    }

    if (next != null) {

      mCurrentOperation = next.second;
      RemoteOperationResult result = null;
      try {
        /// prepare client object to send the request to the ownCloud server
        if (mLastTarget == null || !mLastTarget.equals(next.first)) {
          mLastTarget = next.first;
          if (mLastTarget.mAccount != null) {
            mOwnCloudClient =
                OwnCloudClientFactory.createOwnCloudClient(
                    mLastTarget.mAccount, getApplicationContext());
            mStorageManager =
                new FileDataStorageManager(mLastTarget.mAccount, getContentResolver());
          } else {
            mOwnCloudClient =
                OwnCloudClientFactory.createOwnCloudClient(
                    mLastTarget.mServerUrl,
                    getApplicationContext(),
                    true); // this is not good enough
            mStorageManager = null;
          }
        }

        /// perform the operation
        if (mCurrentOperation instanceof SyncOperation) {
          result = ((SyncOperation) mCurrentOperation).execute(mOwnCloudClient, mStorageManager);
        } else {
          result = mCurrentOperation.execute(mOwnCloudClient);
        }

      } catch (AccountsException e) {
        if (mLastTarget.mAccount == null) {
          Log_OC.e(TAG, "Error while trying to get autorization for a NULL account", e);
        } else {
          Log_OC.e(
              TAG, "Error while trying to get autorization for " + mLastTarget.mAccount.name, e);
        }
        result = new RemoteOperationResult(e);

      } catch (IOException e) {
        if (mLastTarget.mAccount == null) {
          Log_OC.e(TAG, "Error while trying to get autorization for a NULL account", e);
        } else {
          Log_OC.e(
              TAG, "Error while trying to get autorization for " + mLastTarget.mAccount.name, e);
        }
        result = new RemoteOperationResult(e);
      } catch (Exception e) {
        if (mLastTarget.mAccount == null) {
          Log_OC.e(TAG, "Unexpected error for a NULL account", e);
        } else {
          Log_OC.e(TAG, "Unexpected error for " + mLastTarget.mAccount.name, e);
        }
        result = new RemoteOperationResult(e);

      } finally {
        synchronized (mPendingOperations) {
          mPendingOperations.poll();
        }
      }

      // sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result);
      callbackOperationListeners(mLastTarget, mCurrentOperation, result);
    }
  }