1 /* 2 * Copyright (c) 2002-2025 Gargoyle Software Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * https://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 package org.htmlunit.attachment; 16 17 import org.htmlunit.HttpHeader; 18 import org.htmlunit.Page; 19 import org.htmlunit.WebResponse; 20 21 /** 22 * An attachment represents a page received from the server which contains a 23 * {@code Content-Disposition=attachment} header. 24 * 25 * @author Bruce Chapman 26 * @author Sudhan Moghe 27 * @author Daniel Gredler 28 * @author Ronald Brill 29 * @author Lai Quang Duong 30 */ 31 public class Attachment { 32 33 /** The attached page. */ 34 private final Page page_; 35 36 /** The file name of this attachment. */ 37 private final String attachmentFilename_; 38 39 /** 40 * Creates a new attachment for the specified page. 41 * @param page the attached page 42 */ 43 public Attachment(final Page page) { 44 this(page, null); 45 } 46 47 /** 48 * Creates a new attachment for the specified page. 49 * @param page the attached page 50 * @param attachmentFilename the file name of this attachment 51 */ 52 public Attachment(final Page page, final String attachmentFilename) { 53 page_ = page; 54 attachmentFilename_ = attachmentFilename; 55 } 56 57 /** 58 * Returns the attached page. 59 * @return the attached page 60 */ 61 public Page getPage() { 62 return page_; 63 } 64 65 /** 66 * Returns the attachment's filename, as suggested by the <code>Content-Disposition</code> 67 * header, or {@code null} if no filename was suggested. 68 * @return the attachment's suggested filename, or {@code null} if none was suggested 69 */ 70 public String getSuggestedFilename() { 71 if (attachmentFilename_ != null) { 72 return attachmentFilename_; 73 } 74 75 final WebResponse response = page_.getWebResponse(); 76 final String disp = response.getResponseHeaderValue(HttpHeader.CONTENT_DISPOSITION); 77 return getSuggestedFilename(disp); 78 } 79 80 /** 81 * Returns the attachment's filename, as suggested by the <code>Content-Disposition</code> 82 * header, or {@code null} if no filename was suggested. 83 * @param contentDispositionHeader the <code>Content-Disposition</code> header 84 * 85 * @return the attachment's suggested filename, or {@code null} if none was suggested 86 */ 87 public static String getSuggestedFilename(final String contentDispositionHeader) { 88 if (contentDispositionHeader == null) { 89 return null; 90 } 91 92 int start = contentDispositionHeader.indexOf("filename="); 93 if (start == -1) { 94 return null; 95 } 96 start += "filename=".length(); 97 if (start >= contentDispositionHeader.length()) { 98 return null; 99 } 100 101 int end = contentDispositionHeader.indexOf(';', start); 102 if (end == -1) { 103 end = contentDispositionHeader.length(); 104 } 105 if (contentDispositionHeader.charAt(start) == '"' && contentDispositionHeader.charAt(end - 1) == '"') { 106 start++; 107 end--; 108 } 109 return contentDispositionHeader.substring(start, end); 110 } 111 }