package hudson.plugins.s3;

import hudson.model.AbstractBuild;
import hudson.model.Run;

import java.io.Serializable;


/**
 * Provides a way to construct a destination bucket name and object name based
 * on the bucket name provided by the user.
 * 
 * The convention implemented here is that a / in a bucket name is used to
 * construct a structure in the object name.  That is, a put of file.txt to bucket name
 * of "mybucket/v1" will cause the object "v1/file.txt" to be created in the mybucket.
 * 
 */
public class Destination implements Serializable {
  private static final long serialVersionUID = 1L;
  public final String bucketName; 
  public final String objectName; 
  
  public Destination(final String userBucketName, final String fileName) {
    
    if (userBucketName == null || fileName == null) 
      throw new IllegalArgumentException("Not defined for null parameters: "+userBucketName+","+fileName);
    
    final String[] bucketNameArray = userBucketName.split("/", 2);
    
    bucketName = bucketNameArray[0];
    
    if (bucketNameArray.length > 1) {
        objectName = bucketNameArray[1] + "/" + fileName;
    } else {
        objectName = fileName;
    }
  }

@Override
 public String toString() {
   return "Destination [bucketName="+bucketName+", objectName="+objectName+"]";
 }
  

  public static Destination newFromRun(Run run, String bucketName, String fileName)
  {
    String projectName = run.getParent().getName();
    int buildID = run.getNumber();
    return new Destination(bucketName, "jobs/" + projectName + "/" + buildID + "/" + fileName);
  }

  public static Destination newFromRun(Run run, S3Artifact artifact) 
  {
    return newFromRun(run, artifact.getBucket(), artifact.getName());
  }
    
  public static Destination newFromBuild(AbstractBuild<?, ?> build, String bucketName, String fileName)
  {
    String projectName = build.getParent().getName();
    int buildID =build.getNumber();
    return new Destination(bucketName, "jobs/" + projectName + "/" + buildID + "/" + fileName);
  }
}

@@ -989,16 +989,115 @@
 /%22, 2);%0A
+    final String platformAgnosticFileName = cleanFilenameFromPlatformSpecificCharacters(fileName);%0A
     %0A   
@@ -1217,25 +1217,41 @@
 %5B1%5D + %22/%22 + 
-f
+platformAgnosticF
 ileName;%0A   
@@ -1281,17 +1281,33 @@
 tName = 
-f
+platformAgnosticF
 ileName;
@@ -1318,16 +1318,153 @@
  %7D%0A  %7D%0A%0A
+    private String cleanFilenameFromPlatformSpecificCharacters(String fileName) %7B%0A        return fileName.replace(%22%5C%5C%22, %22/%22);%0A    %7D%0A%0A    
 @Overrid

Replace platform-agnostic slashes with standards