github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/pkg/shortcut/shortcut.go (about) 1 // Package shortcut can be used to manipulate files in the .url format (from 2 // windows). See 3 // http://www.lyberty.com/encyc/articles/tech/dot_url_format_-_an_unofficial_guide.html 4 package shortcut 5 6 import ( 7 "bytes" 8 "errors" 9 "io" 10 ) 11 12 // ErrInvalidShortcut is the error when a .url file cannot be parsed. 13 var ErrInvalidShortcut = errors.New("The file is not in the expected format") 14 15 // Result is the result of the parsing of a .url file. 16 type Result struct { 17 URL string 18 } 19 20 var ( 21 section = []byte("[InternetShortcut]") 22 urlField = []byte("URL") 23 ) 24 25 // Parse extracts information from a .url file. 26 func Parse(r io.Reader) (Result, error) { 27 var result Result 28 buf, err := io.ReadAll(r) 29 if err != nil { 30 return result, err 31 } 32 lines := bytes.Split(buf, []byte{'\n'}) 33 firstLine := bytes.TrimSuffix(lines[0], []byte{'\r'}) 34 if len(lines) < 2 || !bytes.Equal(firstLine, section) { 35 return result, ErrInvalidShortcut 36 } 37 for _, line := range lines[1:] { 38 line = bytes.TrimSuffix(line, []byte{'\r'}) 39 parts := bytes.SplitN(line, []byte{'='}, 2) 40 if len(parts) == 2 && bytes.Equal(parts[0], urlField) { 41 result.URL = string(parts[1]) 42 } 43 } 44 return result, nil 45 } 46 47 // Generate creates the content of a .url file for the given destination URL. 48 func Generate(url string) []byte { 49 u := []byte(url) 50 n := len(section) + 2 + len(urlField) + 1 + len(u) + 2 51 buf := make([]byte, n) 52 i := 0 53 copy(buf[i:i+len(section)], section) 54 i += len(section) 55 buf[i] = '\r' 56 i++ 57 buf[i] = '\n' 58 i++ 59 copy(buf[i:i+len(urlField)], urlField) 60 i += len(urlField) 61 buf[i] = '=' 62 i++ 63 copy(buf[i:i+len(u)], u) 64 i += len(u) 65 buf[i] = '\r' 66 i++ 67 buf[i] = '\n' 68 return buf 69 }