package sync import ( "errors" "io" "net/http" "net/url" "os" "path" "strings" "github.com/studio-b12/gowebdav" ) // CloudImporter implements an Importer, where files to imports are located // remotely, under a WebDAV server (such as sabre/dav, owncloud, ...). type CloudImporter struct { // baseDAV is the URL (most probably http or https one) to the root directory. // It should contains all themes, in separated directories. baseDAV url.URL // username is the username used to perform authentication through BasicAuth. username string // password is the password used to perform authentication through BasicAuth. password string } // NewCloudImporter registers a new object CloudImporter, as the URL conversion // can returns errors. func NewCloudImporter(baseDAV string, username string, password string) (*CloudImporter, error) { if r, err := url.Parse(baseDAV); err != nil { return nil, err } else { return &CloudImporter{*r, username, password}, nil } } func (i CloudImporter) Kind() string { return "cloud file importer: " + i.baseDAV.String() } func (i CloudImporter) Id() *string { return nil } func (i CloudImporter) Init() error { return nil } func (i CloudImporter) Sync() error { return nil } func (i CloudImporter) Exists(filename string) bool { fullURL := i.baseDAV fullURL.Path = path.Join(fullURL.Path, filename) client := http.Client{} if req, err := http.NewRequest("HEAD", fullURL.String(), nil); err == nil { req.SetBasicAuth(i.username, i.password) if resp, err := client.Do(req); err == nil { defer resp.Body.Close() return resp.StatusCode == http.StatusOK } } return false } func (i CloudImporter) toURL(filename string) string { fullURL := i.baseDAV fullURL.Path = path.Join(fullURL.Path, filename) return fullURL.String() } func (i CloudImporter) importFile(URI string, next func(string, string) (interface{}, error)) (interface{}, error) { return ImportFile(i, URI, next) } func (i CloudImporter) GetFile(filename string) (io.Reader, error) { fullURL := i.baseDAV fullURL.Path = path.Join(fullURL.Path, filename) client := http.Client{} if req, err := http.NewRequest("GET", fullURL.String(), nil); err != nil { return nil, err } else { req.SetBasicAuth(i.username, i.password) if resp, err := client.Do(req); err != nil { return nil, err } else { if resp.StatusCode != http.StatusOK { resp.Body.Close() return nil, errors.New(resp.Status) } else { return resp.Body, nil } } } } func (i CloudImporter) writeFile(filename string, reader io.Reader) error { fullURL := i.baseDAV fullURL.Path = path.Join(fullURL.Path, filename) client := http.Client{} if req, err := http.NewRequest("PUT", fullURL.String(), reader); err != nil { return err } else { req.SetBasicAuth(i.username, i.password) if resp, err := client.Do(req); err != nil { return err } else { defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return errors.New(resp.Status) } else { return nil } } } } func (i CloudImporter) ListDir(filename string) ([]string, error) { client := gowebdav.NewClient(i.baseDAV.String(), i.username, i.password) if files, err := client.ReadDir(strings.Replace(url.PathEscape(filename), "%2F", "/", -1)); err != nil { return nil, err } else { res := make([]string, 0) for _, file := range files { res = append(res, file.Name()) } return res, nil } } func (i CloudImporter) Stat(filename string) (os.FileInfo, error) { return gowebdav.NewClient(i.baseDAV.String(), i.username, i.password).Stat(strings.Replace(url.PathEscape(filename), "%2F", "/", -1)) }