diff --git a/plugins/FeedsFileFetcher.inc b/plugins/FeedsFileFetcher.inc
old mode 100755
new mode 100644
index 5d11129..8f8a22c
--- a/plugins/FeedsFileFetcher.inc
+++ b/plugins/FeedsFileFetcher.inc
@@ -118,7 +118,7 @@
       $form['source'] = array(
         '#type' => 'textfield',
         '#title' => t('File'),
-        '#description' => t('Specify a path to a file or a directory. Path must start with @scheme://', array('@scheme' => file_default_scheme())),
+        '#description' => t('Specify a path to a file or a directory. Prefix the path with a scheme. Available schemes: @schemes', array('@schemes' => implode(', ', $this->config['allowed_schemes']))),
         '#default_value' => empty($source_config['source']) ? '' : $source_config['source'],
       );
     }
@@ -129,24 +129,33 @@
    * Override parent::sourceFormValidate().
    */
   public function sourceFormValidate(&$values) {
-    $feed_dir = 'public://feeds';
-    file_prepare_directory($feed_dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-
-    // If there is a file uploaded, save it, otherwise validate input on
-    // file.
-    // @todo: Track usage of file, remove file when removing source.
-    if ($file = file_save_upload('feeds', array('file_validate_extensions' => array(0 => $this->config['allowed_extensions'])), $feed_dir)) {
-      $values['source'] = $file->uri;
-      $values['file'] = $file;
+    if (empty($this->config['direct'])) {
+      $feed_dir = $this->config['directory'];
+      if (!file_prepare_directory($feed_dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
+        form_set_error('feeds][FeedsFileFetcher][source', t('Upload failed.'));
+        watchdog('feeds', 'The upload directory %directory for the feed fetcher !name could not be created or is not accessible. A newly uploaded file could not be saved in this directory as a consequence, and the upload was canceled.', array('%directory' => $feed_dir, '!name' => 'FIXME: figure out name of importer'));
+      }
+      // Validate and save uploaded file
+      else if ($file = file_save_upload('feeds', array('file_validate_extensions' => array(0 => $this->config['allowed_extensions'])), $feed_dir)) {
+        $values['source'] = $file->uri;
+        $values['file'] = $file;
+      }
+      elseif (empty($values['source'])) {
+        form_set_error('feeds][FeedsFileFetcher][source', t('Upload a file first.'));
+      }
+      else {
+        // File present from previous upload. Nothing to validate.
+      }      
     }
-    elseif (empty($values['source'])) {
-      form_set_error('feeds][source', t('Upload a file first.'));
-    }
-    // If a file has not been uploaded and $values['source'] is not empty, make
-    // sure that this file is within Drupal's files directory as otherwise
-    // potentially any file that the web server has access to could be exposed.
-    elseif (strpos($values['source'], file_default_scheme()) !== 0) {
-      form_set_error('feeds][source', t('File needs to reside within the site\'s file directory, its path needs to start with @scheme://.', array('@scheme' => file_default_scheme())));
+    else {
+      // Check if choosen url scheme is allowed
+      if (!in_array(reset(explode(':', $values['source'])), $this->config['allowed_schemes'])) {
+        form_set_error('feeds][FeedsFileFetcher][source', t('File needs to reside within the site\'s file directory, its path needs to start with scheme://. Available schemes: @schemes', array('@schemes' => implode(', ', $this->config['allowed_schemes']))));
+      }
+      // Verify that the given directory is accessible.
+      if (!file_prepare_directory($values['source'])) {
+        form_set_error('feeds[FeedsFileFetcher][source', t('Failed to access the specified directory.'));
+      }
     }
   }
 
@@ -187,16 +196,26 @@
    * Override parent::configDefaults().
    */
   public function configDefaults() {
-    return array(
+    $schemes = $this->getSchemes();
+    $scheme = in_array('private', $schemes) ? 'private' : 'public';
+
+     return array(
       'allowed_extensions' => 'txt csv tsv xml opml',
       'direct' => FALSE,
-    );
+      'directory' => $scheme . '://feeds',
+      'allowed_schemes' => $schemes,
+     );
   }
 
   /**
    * Override parent::configForm().
    */
   public function configForm(&$form_state) {
+    $options = array();
+    foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $info) {
+      $options[$scheme] = check_plain($scheme . ': ' . $info['description']);
+    }
+   
     $form = array();
     $form['allowed_extensions'] = array(
       '#type' => 'textfield',
@@ -204,6 +223,12 @@
       '#description' => t('Allowed file extensions for upload.'),
       '#default_value' => $this->config['allowed_extensions'],
     );
+    $form['directory'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Upload directory'),
+      '#description' => t('Directory where uploaded files get stored. Prefix the path with a scheme. Available schemes: @schemes', array('@schemes' => implode(', ', $this->getSchemes()))),
+      '#default_value' => $this->config['directory'],
+    );    
     $form['direct'] = array(
       '#type' => 'checkbox',
       '#title' => t('Supply path to file or directory directly'),
@@ -212,9 +237,35 @@
         are already on the server.'),
       '#default_value' => $this->config['direct'],
     );
+    
+    if (!empty($options)) {
+      $form['allowed_schemes'] = array(
+        '#type' => 'checkboxes',
+        '#title' => t('Allowed schemes'),
+        '#default_value' => $this->config['allowed_schemes'],
+        '#options' => $options,
+        '#description' => t('Select the schemes you want to allow for direct upload'),
+      );
+    } 
+    
     return $form;
   }
 
+  /**
+   * Override parent::configForm().
+   *
+   * Ensure that the choosen directory is accessible.
+   */
+  public function configFormValidate(&$values) {
+    $ok = file_prepare_directory($values['directory'], FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    if (!$ok) {
+      form_set_error('feeds][directory', t('The choosen directory does not exist and/or attempts to create it failed.'));
+    }
+
+    // Remove zeroes from array
+    $values['allowed_schemes'] = array_filter($values['allowed_schemes']);
+  }
+  
   /**
    * Helper. Deletes a file.
    */
@@ -224,4 +275,11 @@
       file_delete($file);
     }
   }
+  
+  /**
+   * Helper function: return available schemes.
+   */
+  protected function getSchemes() {
+    return array_keys(file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE));
+  }  
 }
