? media_mover_ftp.patch
? mediamover-440078-ftp-folders-v2.patch
? test.diff
Index: media_mover_ftp.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/media_mover/media_mover_ftp/Attic/media_mover_ftp.module,v
retrieving revision 1.1.2.7.2.14
diff -u -p -r1.1.2.7.2.14 media_mover_ftp.module
--- media_mover_ftp.module	1 Apr 2009 02:18:57 -0000	1.1.2.7.2.14
+++ media_mover_ftp.module	27 Apr 2009 16:01:05 -0000
@@ -198,18 +198,37 @@ function media_mover_ftp_config($configu
       '#description' => t('If a file on the remote server does not have a valid token, it will still be harvested. This is useful if you are using an FTP server with non-user content.'),
       '#default_value' => $configuration['mm_ftp_harvest_without_tokens'],
     );
-    $form['mm_ftp_conf']["mm_ftp_delete_files"] = array(
+    $form['mm_ftp_conf']['mm_ftp_delete_files'] = array(
       '#type' => 'checkbox',
       '#title' => t('Delete files'),
       '#description' => t('Delete the files on server after harvest'),
       '#default_value' => $configuration['mm_ftp_delete_files'],
     );
-    $form['mm_ftp_conf']["mm_ftp_delete_files_no_token"] = array(
+    $form['mm_ftp_conf']['mm_ftp_delete_files_no_token'] = array(
       '#type' => 'checkbox',
       '#title' => t('Delete files without tokens'),
       '#description' => t('Remove files from the FTP server that do not have tokens. These will not be harvested. These files will be lost forever. Leaving this unchecked will leave the files on the FTP server.'),
       '#default_value' => $configuration['mm_ftp_delete_files_no_token'],
     );
+    $form['mm_ftp_conf']['mm_ftp_harvest_folders'] = array(
+     '#type' => 'checkbox',
+     '#title' => t('Harvest files from folders'),
+     '#description' => t('Allow files to be uploaded as a token folder. A token folder is a folder with the folder name and token (eg: my_folder.2xz3f) which will identify all the enclosed files. If an individual file has a token this will override the folder token data.'),
+     '#default_value' => $configuration['mm_ftp_harvest_folders'],
+   );
+   $form['mm_ftp_conf']['mm_ftp_harvest_delete_folders'] = array(
+     '#type' => 'checkbox',
+     '#title' => t('Delete token folders after harvest'),
+     '#description' => t('Removes folders with tokens (and their contents) after harvest  **WARNING THIS WILL DELETE EVERYTHING IN THE FOLDER**'),
+     '#default_value' => $configuration['mm_ftp_harvest_delete_folders'],
+   );
+   $form['mm_ftp_conf']['mm_ftp_harvest_delete_non_token_folders'] = array(
+     '#type' => 'checkbox',
+     '#title' => t('Delete any non token folders'),
+     '#description' => t('Removes folders (and their contents) without tokens - **WARNING THIS WILL DELETE EVERYTHING THE FOLDER**'),
+     '#default_value' => $configuration['mm_ftp_harvest_delete_non_token_folders'],
+   );
+    
   }
 
   // storage specific settings
@@ -297,21 +316,24 @@ function media_mover_ftp_connect($config
   // build the ftp connection
   $connection['ftp_connection'] = ftp_connect($configuration['mm_ftp_host']);
   $connection['ftp_login'] = ftp_login($connection['ftp_connection'], $configuration['mm_ftp_user'], $configuration['mm_ftp_pass']);
-  $connection['ftp_list'] = ftp_rawlist($connection['ftp_connection'], $configuration['mm_ftp_dir']);
+  $connection['ftp_list'] = media_mover_ftp_completed_rawlist(ftp_rawlist($connection['ftp_connection'], $configuration['mm_ftp_dir']));
 
   // check the connection to the server
   if (! $connection['ftp_connection']) {
     $message = 'Unable to connect to server %server';
     $params = array('%server' => $configuration['mm_ftp_host']);
   }
+  // can we login?
   elseif (! $connection['ftp_login']) {
     $message = 'Unable to login to server %server with username %user';
     $params =  array('%server' => $configuration['mm_ftp_host'], '%user' => $configuration['mm_ftp_user']);
   }
+  // can we get a list of files?
   elseif ( $connection['ftp_list'] === FALSE) {
     $message = 'Unable to get file list from server %server with username %user';
     $params = array('%server' => $configuration['mm_ftp_host'], '%user' => $configuration['mm_ftp_user']);
   }
+  
   // did we have an error condition?
   if ($message) {
     if ($display) { drupal_set_message(t($message, $params), 'error'); }
@@ -334,19 +356,20 @@ function media_mover_ftp_connect($config
 function mm_ftp_parse_file($file_item, $configuration, $return = 'path') {
   $info = array();
   // parse the $file_item
-  $vinfo = preg_split("/[\s]+/", $file_item, 9);
-  if ($vinfo[0][0] == "-") {
-    $info['chmod'] = $vinfo[0];
-    $info['name'] = $vinfo[8];
-    $info['dir'] = $configuration['mm_ftp_dir'];
-    list($info['hour'], $info['minute']) = split(":", $vinfo[7]);
-    $info['hour'] = $info['hour'] + 0; // mktime expects hour to be long, not a string
-    $info['minute'] = $info['minute'] + 0; // mktime expects minute to be long, not a string
-    $info['month'] = $vinfo[5] + 0; // mktime expects month to be long, not a string
-    $info['day'] = $vinfo[6] + 0; // mktime expects day to be long, not a string
-    $info['created'] = mktime($info['hour'], $info['minute'], 0, $info['month'], $info['day'], date(Y));
-    $info['size'] = $vinfo[4];
-    // we just need the file path
+  $info['is_dir'] = ($file_item[0][0] == "-"? FALSE : TRUE);
+  $info['chmod'] = $file_item[0];
+  $info['name'] = $file_item[8];
+  $info['dir'] = $dir;
+  list($info['hour'], $info['minute']) = split(":", $file_item[7]);
+  $info['hour'] = $file_item['hour'] + 0; // mktime expects hour to be long, not a string
+  $info['minute'] = $file_item['minute'] + 0; // mktime expects minute to be long, not a string
+  $info['month'] = $file_item[5] + 0; // mktime expects month to be long, not a string
+  $info['day'] = $file_item[6] + 0; // mktime expects day to be long, not a string
+  $info['created'] = mktime($info['hour'], $info['minute'], 0, $info['month'], $info['day'], date(Y));
+  $info['size'] = $file_item[4];
+    
+  // only return path if its a dir
+  if ($return == 'path' AND ! $info['is_dir']) {
     if ($return == 'path') {
       return $info['dir'] .'/'. $info['name'];
     }
@@ -354,6 +377,38 @@ function mm_ftp_parse_file($file_item, $
   }
   else {
     // We are not looking at a file but at a directory ("d") or a link ("l") for instance
+    return $info['dir'] .'/'. $info['name'];
+  } 
+  elseif ($return == 'info') {
+   return $info;
+  }
+}
+
+
+/**
+ * A wrapper for the ftp_rawlist() php function to only return files which have
+ * finished uploading.
+ * It does this by calling ftp_rawlist twice with a 1 second pause, then checking
+ * the results for inconsitancies (uploading file will have increased in size).
+ *
+ * @param resource $stream
+ * @param string $dir
+ * @param bool $strict
+ *  If strict is TRUE the if any files are still uploading then false is returned
+ * @return array 
+ */
+function media_mover_ftp_completed_rawlist($stream, $dir, $strict = FALSE) {
+  // get 2 listings 1 second appart
+  $pass1 = ftp_rawlist($stream, $dir);
+  sleep(1);
+  $pass2 = ftp_rawlist($stream, $dir);
+ 
+  // get a list of only the results in both listings (ie fully uploaded files)
+  $result = array_intersect($pass1, $pass2);
+ 
+  // set results to false if in there is a difference and in strict mode
+  if($strict AND count($result) !== count($pass2)) {
+    $result = FALSE;
   }
 }
 
@@ -409,6 +464,7 @@ function media_mover_ftp_token_ftp_form_
   return;
 }
 
+
 /**
  * Outbound mail functions
  *
@@ -582,5 +638,22 @@ function media_mover_ftp_token_extract($
   if ($type == 'token') {
     return $token;
   }
-  return $filename;
+  
+  // check for folder based token
+  if ($configuration['mm_ftp_harvest_folders'] AND $token == '') {
+    // remove base ftp dir to avoid false positives
+    $filename = substr($filename, strlen($configuration['mm_ftp_dir']));
+    
+    // new patern to search for the size digit code between two /'s
+    $folder_pattern = '/\/([0-9a-zA-z]{'. MM_FTP_TOKEN_LENGTH .'})\//';
+    preg_match($folder_pattern, $filename, $matches);
+    
+    if ($matches[1]) {
+      $token = $matches[1];
+      $filename = str_replace('.'. $token, '', $filename);
+    }
+  }
+  
+  // return just the filename, not full path
+  return basename($filename);
 }
\ No newline at end of file
