Skip to content

Commit 8e059c6

Browse files
committed
feat: webdav for sharepoint online (OpenListTeam#460)
1 parent 395de06 commit 8e059c6

File tree

5 files changed

+85
-28
lines changed

5 files changed

+85
-28
lines changed

drivers/webdav/driver.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package webdav
33
import (
44
"github.com/Xhofe/alist/conf"
55
"github.com/Xhofe/alist/drivers/base"
6+
"github.com/Xhofe/alist/drivers/webdav/odrvcookie"
67
"github.com/Xhofe/alist/model"
78
"github.com/Xhofe/alist/utils"
89
"path/filepath"
@@ -47,7 +48,7 @@ func (driver WebDav) Items() []base.Item {
4748
Required: true,
4849
Default: "other",
4950
Values: "sharepoint,other",
50-
Description: "sharepoint temporarily unavailable",
51+
Description: "webdav vendor",
5152
},
5253
}
5354
}
@@ -56,9 +57,17 @@ func (driver WebDav) Save(account *model.Account, old *model.Account) error {
5657
if account == nil {
5758
return nil
5859
}
59-
account.Status = "work"
60+
var err error
61+
if isSharePoint(account) {
62+
_, err = odrvcookie.GetCookie(account.Username, account.Password, account.SiteUrl)
63+
}
64+
if err != nil {
65+
account.Status = err.Error()
66+
} else {
67+
account.Status = "work"
68+
}
6069
_ = model.SaveAccount(account)
61-
return nil
70+
return err
6271
}
6372

6473
func (driver WebDav) File(path string, account *model.Account) (*model.File, error) {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package odrvcookie
2+
3+
import (
4+
"github.com/Xhofe/alist/utils/cookie"
5+
"net/http"
6+
"sync"
7+
"time"
8+
)
9+
10+
type SpCookie struct {
11+
Cookie string
12+
expire time.Time
13+
}
14+
15+
func (sp SpCookie) IsExpire() bool {
16+
return time.Now().Before(sp.expire)
17+
}
18+
19+
var cookiesMap = struct {
20+
sync.Mutex
21+
m map[string]*SpCookie
22+
}{m: make(map[string]*SpCookie)}
23+
24+
func GetCookie(username, password, siteUrl string) (string, error) {
25+
cookiesMap.Lock()
26+
defer cookiesMap.Unlock()
27+
spCookie, ok := cookiesMap.m[username]
28+
if ok {
29+
if !spCookie.IsExpire() {
30+
return spCookie.Cookie, nil
31+
}
32+
}
33+
ca := New(username, password, siteUrl)
34+
tokenConf, err := ca.Cookies()
35+
if err != nil {
36+
return "", err
37+
}
38+
spCookie = &SpCookie{
39+
Cookie: cookie.ToString([]*http.Cookie{&tokenConf.RtFa, &tokenConf.FedAuth}),
40+
expire: time.Now().Add(time.Hour * 12),
41+
}
42+
cookiesMap.m[username] = spCookie
43+
return spCookie.Cookie, nil
44+
}

drivers/webdav/odrvcookie/fetch.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"bytes"
66
"encoding/xml"
77
"html/template"
8-
"log"
98
"net/http"
109
"net/http/cookiejar"
1110
"net/url"
@@ -90,25 +89,29 @@ func New(pUser, pPass, pEndpoint string) CookieAuth {
9089
// Cookies creates a CookieResponse. It fetches the auth token and then
9190
// retrieves the Cookies
9291
func (ca *CookieAuth) Cookies() (CookieResponse, error) {
93-
return ca.getSPCookie(ca.getSPToken())
92+
spToken, err := ca.getSPToken()
93+
if err != nil {
94+
return CookieResponse{}, err
95+
}
96+
return ca.getSPCookie(spToken)
9497
}
9598

9699
func (ca *CookieAuth) getSPCookie(conf *SuccessResponse) (CookieResponse, error) {
97100
spRoot, err := url.Parse(ca.endpoint)
98101
if err != nil {
99-
panic(err)
102+
return CookieResponse{}, err
100103
}
101104

102105
u, err := url.Parse("https://" + spRoot.Host + "/_forms/default.aspx?wa=wsignin1.0")
103106
if err != nil {
104-
log.Fatal(err)
107+
return CookieResponse{}, err
105108
}
106109

107110
// To authenticate with davfs or anything else we need two cookies (rtFa and FedAuth)
108111
// In order to get them we use the token we got earlier and a cookieJar
109112
jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
110113
if err != nil {
111-
log.Fatal(err)
114+
return CookieResponse{}, err
112115
}
113116

114117
client := &http.Client{
@@ -117,7 +120,7 @@ func (ca *CookieAuth) getSPCookie(conf *SuccessResponse) (CookieResponse, error)
117120

118121
// Send the previously aquired Token as a Post parameter
119122
if _, err = client.Post(u.String(), "text/xml", strings.NewReader(conf.Succ.Token)); err != nil {
120-
log.Fatal(err)
123+
return CookieResponse{}, err
121124
}
122125

123126
cookieResponse := CookieResponse{}
@@ -134,7 +137,7 @@ func (ca *CookieAuth) getSPCookie(conf *SuccessResponse) (CookieResponse, error)
134137
return cookieResponse, err
135138
}
136139

137-
func (ca *CookieAuth) getSPToken() *SuccessResponse {
140+
func (ca *CookieAuth) getSPToken() (*SuccessResponse, error) {
138141
reqData := map[string]interface{}{
139142
"Username": ca.user,
140143
"Password": ca.pass,
@@ -145,20 +148,20 @@ func (ca *CookieAuth) getSPToken() *SuccessResponse {
145148

146149
buf := &bytes.Buffer{}
147150
if err := t.Execute(buf, reqData); err != nil {
148-
panic(err)
151+
return nil, err
149152
}
150153

151154
// Execute the first request which gives us an auth token for the sharepoint service
152155
// With this token we can authenticate on the login page and save the returned cookies
153156
req, err := http.NewRequest("POST", "https://login.microsoftonline.com/extSTS.srf", buf)
154157
if err != nil {
155-
panic(err)
158+
return nil, err
156159
}
157160

158161
client := &http.Client{}
159162
resp, err := client.Do(req)
160163
if err != nil {
161-
panic(err.Error())
164+
return nil, err
162165
}
163166
defer resp.Body.Close()
164167

@@ -169,8 +172,8 @@ func (ca *CookieAuth) getSPToken() *SuccessResponse {
169172
var conf SuccessResponse
170173
err = xml.Unmarshal(s, &conf)
171174
if err != nil {
172-
panic(err)
175+
return nil, err
173176
}
174177

175-
return &conf
178+
return &conf, err
176179
}

drivers/webdav/util.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package webdav
2+
3+
import "github.com/Xhofe/alist/model"
4+
5+
func isSharePoint(account *model.Account) bool {
6+
return account.InternalType == "sharepoint"
7+
}

drivers/webdav/webdav.go

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"github.com/Xhofe/alist/drivers/webdav/odrvcookie"
66
"github.com/Xhofe/alist/model"
77
"github.com/Xhofe/alist/utils"
8-
"github.com/Xhofe/alist/utils/cookie"
98
log "github.com/sirupsen/logrus"
109
"github.com/studio-b12/gowebdav"
1110
"net/http"
@@ -14,20 +13,15 @@ import (
1413

1514
func (driver WebDav) NewClient(account *model.Account) *gowebdav.Client {
1615
c := gowebdav.NewClient(account.SiteUrl, account.Username, account.Password)
17-
if account.InternalType == "sharepoint" {
18-
19-
ca := odrvcookie.New(account.Username, account.Password, account.SiteUrl)
20-
tokenConf, err := ca.Cookies()
21-
log.Debugln(err, tokenConf)
22-
if err != nil {
16+
if isSharePoint(account) {
17+
cookie, err := odrvcookie.GetCookie(account.Username, account.Password, account.SiteUrl)
18+
log.Debugln(cookie, err)
19+
if err == nil {
20+
log.Debugln("set interceptor")
2321
c.SetInterceptor(func(method string, rq *http.Request) {
2422
rq.Header.Del("Authorization")
25-
//rq.AddCookie(&tokenConf.FedAuth)
26-
//rq.AddCookie(&tokenConf.RtFa)
27-
rq.Header.Set("Cookie", cookie.ToString([]*http.Cookie{&tokenConf.RtFa, &tokenConf.FedAuth}))
28-
if method == "PROPFIND" {
29-
rq.Header.Set("Depth", "0")
30-
}
23+
rq.Header.Set("Cookie", cookie)
24+
log.Debugf("sp webdav req: %+v", rq)
3125
})
3226
}
3327
}

0 commit comments

Comments
 (0)