github.com/cavaliergopher/grab/v3@v3.0.1/util.go (about) 1 package grab 2 3 import ( 4 "fmt" 5 "mime" 6 "net/http" 7 "os" 8 "path" 9 "path/filepath" 10 "strings" 11 "time" 12 ) 13 14 // setLastModified sets the last modified timestamp of a local file according to 15 // the Last-Modified header returned by a remote server. 16 func setLastModified(resp *http.Response, filename string) error { 17 // https://tools.ietf.org/html/rfc7232#section-2.2 18 // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified 19 header := resp.Header.Get("Last-Modified") 20 if header == "" { 21 return nil 22 } 23 lastmod, err := time.Parse(http.TimeFormat, header) 24 if err != nil { 25 return nil 26 } 27 return os.Chtimes(filename, lastmod, lastmod) 28 } 29 30 // mkdirp creates all missing parent directories for the destination file path. 31 func mkdirp(path string) error { 32 dir := filepath.Dir(path) 33 if fi, err := os.Stat(dir); err != nil { 34 if !os.IsNotExist(err) { 35 return fmt.Errorf("error checking destination directory: %v", err) 36 } 37 if err := os.MkdirAll(dir, 0777); err != nil { 38 return fmt.Errorf("error creating destination directory: %v", err) 39 } 40 } else if !fi.IsDir() { 41 panic("grab: developer error: destination path is not directory") 42 } 43 return nil 44 } 45 46 // guessFilename returns a filename for the given http.Response. If none can be 47 // determined ErrNoFilename is returned. 48 // 49 // TODO: NoStore operations should not require a filename 50 func guessFilename(resp *http.Response) (string, error) { 51 filename := resp.Request.URL.Path 52 if cd := resp.Header.Get("Content-Disposition"); cd != "" { 53 if _, params, err := mime.ParseMediaType(cd); err == nil { 54 if val, ok := params["filename"]; ok { 55 filename = val 56 } // else filename directive is missing.. fallback to URL.Path 57 } 58 } 59 60 // sanitize 61 if filename == "" || strings.HasSuffix(filename, "/") || strings.Contains(filename, "\x00") { 62 return "", ErrNoFilename 63 } 64 65 filename = filepath.Base(path.Clean("/" + filename)) 66 if filename == "" || filename == "." || filename == "/" { 67 return "", ErrNoFilename 68 } 69 70 return filename, nil 71 }