diff --git a/drivers/webdav/driver.go b/drivers/webdav/driver.go index 705d3450..22711c4d 100644 --- a/drivers/webdav/driver.go +++ b/drivers/webdav/driver.go @@ -3,6 +3,7 @@ package webdav import ( "github.com/Xhofe/alist/conf" "github.com/Xhofe/alist/drivers/base" + "github.com/Xhofe/alist/drivers/webdav/odrvcookie" "github.com/Xhofe/alist/model" "github.com/Xhofe/alist/utils" "path/filepath" @@ -47,7 +48,7 @@ func (driver WebDav) Items() []base.Item { Required: true, Default: "other", Values: "sharepoint,other", - Description: "sharepoint temporarily unavailable", + Description: "webdav vendor", }, } } @@ -56,9 +57,17 @@ func (driver WebDav) Save(account *model.Account, old *model.Account) error { if account == nil { return nil } - account.Status = "work" + var err error + if isSharePoint(account) { + _, err = odrvcookie.GetCookie(account.Username, account.Password, account.SiteUrl) + } + if err != nil { + account.Status = err.Error() + } else { + account.Status = "work" + } _ = model.SaveAccount(account) - return nil + return err } func (driver WebDav) File(path string, account *model.Account) (*model.File, error) { diff --git a/drivers/webdav/odrvcookie/cookie.go b/drivers/webdav/odrvcookie/cookie.go new file mode 100644 index 00000000..0a7b0b79 --- /dev/null +++ b/drivers/webdav/odrvcookie/cookie.go @@ -0,0 +1,44 @@ +package odrvcookie + +import ( + "github.com/Xhofe/alist/utils/cookie" + "net/http" + "sync" + "time" +) + +type SpCookie struct { + Cookie string + expire time.Time +} + +func (sp SpCookie) IsExpire() bool { + return time.Now().Before(sp.expire) +} + +var cookiesMap = struct { + sync.Mutex + m map[string]*SpCookie +}{m: make(map[string]*SpCookie)} + +func GetCookie(username, password, siteUrl string) (string, error) { + cookiesMap.Lock() + defer cookiesMap.Unlock() + spCookie, ok := cookiesMap.m[username] + if ok { + if !spCookie.IsExpire() { + return spCookie.Cookie, nil + } + } + ca := New(username, password, siteUrl) + tokenConf, err := ca.Cookies() + if err != nil { + return "", err + } + spCookie = &SpCookie{ + Cookie: cookie.ToString([]*http.Cookie{&tokenConf.RtFa, &tokenConf.FedAuth}), + expire: time.Now().Add(time.Hour * 12), + } + cookiesMap.m[username] = spCookie + return spCookie.Cookie, nil +} diff --git a/drivers/webdav/odrvcookie/fetch.go b/drivers/webdav/odrvcookie/fetch.go index 20275e52..3c49dbbc 100644 --- a/drivers/webdav/odrvcookie/fetch.go +++ b/drivers/webdav/odrvcookie/fetch.go @@ -5,7 +5,6 @@ import ( "bytes" "encoding/xml" "html/template" - "log" "net/http" "net/http/cookiejar" "net/url" @@ -90,25 +89,29 @@ func New(pUser, pPass, pEndpoint string) CookieAuth { // Cookies creates a CookieResponse. It fetches the auth token and then // retrieves the Cookies func (ca *CookieAuth) Cookies() (CookieResponse, error) { - return ca.getSPCookie(ca.getSPToken()) + spToken, err := ca.getSPToken() + if err != nil { + return CookieResponse{}, err + } + return ca.getSPCookie(spToken) } func (ca *CookieAuth) getSPCookie(conf *SuccessResponse) (CookieResponse, error) { spRoot, err := url.Parse(ca.endpoint) if err != nil { - panic(err) + return CookieResponse{}, err } u, err := url.Parse("https://" + spRoot.Host + "/_forms/default.aspx?wa=wsignin1.0") if err != nil { - log.Fatal(err) + return CookieResponse{}, err } // To authenticate with davfs or anything else we need two cookies (rtFa and FedAuth) // In order to get them we use the token we got earlier and a cookieJar jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) if err != nil { - log.Fatal(err) + return CookieResponse{}, err } client := &http.Client{ @@ -117,7 +120,7 @@ func (ca *CookieAuth) getSPCookie(conf *SuccessResponse) (CookieResponse, error) // Send the previously aquired Token as a Post parameter if _, err = client.Post(u.String(), "text/xml", strings.NewReader(conf.Succ.Token)); err != nil { - log.Fatal(err) + return CookieResponse{}, err } cookieResponse := CookieResponse{} @@ -134,7 +137,7 @@ func (ca *CookieAuth) getSPCookie(conf *SuccessResponse) (CookieResponse, error) return cookieResponse, err } -func (ca *CookieAuth) getSPToken() *SuccessResponse { +func (ca *CookieAuth) getSPToken() (*SuccessResponse, error) { reqData := map[string]interface{}{ "Username": ca.user, "Password": ca.pass, @@ -145,20 +148,20 @@ func (ca *CookieAuth) getSPToken() *SuccessResponse { buf := &bytes.Buffer{} if err := t.Execute(buf, reqData); err != nil { - panic(err) + return nil, err } // Execute the first request which gives us an auth token for the sharepoint service // With this token we can authenticate on the login page and save the returned cookies req, err := http.NewRequest("POST", "https://login.microsoftonline.com/extSTS.srf", buf) if err != nil { - panic(err) + return nil, err } client := &http.Client{} resp, err := client.Do(req) if err != nil { - panic(err.Error()) + return nil, err } defer resp.Body.Close() @@ -169,8 +172,8 @@ func (ca *CookieAuth) getSPToken() *SuccessResponse { var conf SuccessResponse err = xml.Unmarshal(s, &conf) if err != nil { - panic(err) + return nil, err } - return &conf + return &conf, err } diff --git a/drivers/webdav/util.go b/drivers/webdav/util.go new file mode 100644 index 00000000..cf7980fd --- /dev/null +++ b/drivers/webdav/util.go @@ -0,0 +1,7 @@ +package webdav + +import "github.com/Xhofe/alist/model" + +func isSharePoint(account *model.Account) bool { + return account.InternalType == "sharepoint" +} diff --git a/drivers/webdav/webdav.go b/drivers/webdav/webdav.go index 9edc2e75..5961068a 100644 --- a/drivers/webdav/webdav.go +++ b/drivers/webdav/webdav.go @@ -5,7 +5,6 @@ import ( "github.com/Xhofe/alist/drivers/webdav/odrvcookie" "github.com/Xhofe/alist/model" "github.com/Xhofe/alist/utils" - "github.com/Xhofe/alist/utils/cookie" log "github.com/sirupsen/logrus" "github.com/studio-b12/gowebdav" "net/http" @@ -14,20 +13,15 @@ import ( func (driver WebDav) NewClient(account *model.Account) *gowebdav.Client { c := gowebdav.NewClient(account.SiteUrl, account.Username, account.Password) - if account.InternalType == "sharepoint" { - - ca := odrvcookie.New(account.Username, account.Password, account.SiteUrl) - tokenConf, err := ca.Cookies() - log.Debugln(err, tokenConf) - if err != nil { + if isSharePoint(account) { + cookie, err := odrvcookie.GetCookie(account.Username, account.Password, account.SiteUrl) + log.Debugln(cookie, err) + if err == nil { + log.Debugln("set interceptor") c.SetInterceptor(func(method string, rq *http.Request) { rq.Header.Del("Authorization") - //rq.AddCookie(&tokenConf.FedAuth) - //rq.AddCookie(&tokenConf.RtFa) - rq.Header.Set("Cookie", cookie.ToString([]*http.Cookie{&tokenConf.RtFa, &tokenConf.FedAuth})) - if method == "PROPFIND" { - rq.Header.Set("Depth", "0") - } + rq.Header.Set("Cookie", cookie) + log.Debugf("sp webdav req: %+v", rq) }) } }