feat: usos sign-in, private calendar feed and timetable archive
This commit is contained in:
commit
7d4e21f977
33 files changed
+3270
No files matched your search
@@ -0,0 +1,92 @@
|
||||
package usos
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const unreserved = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
|
||||
|
||||
func percentEncode(s string) string {
|
||||
var b strings.Builder
|
||||
for i := range len(s) {
|
||||
c := s[i]
|
||||
if strings.IndexByte(unreserved, c) >= 0 {
|
||||
b.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
b.WriteByte('%')
|
||||
b.WriteString(strings.ToUpper(hex.EncodeToString([]byte{c})))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func signature(method, endpoint string, params url.Values, consumerSecret, tokenSecret string) string {
|
||||
pairs := make([]string, 0, len(params))
|
||||
for key, values := range params {
|
||||
for _, value := range values {
|
||||
pairs = append(pairs, percentEncode(key)+"="+percentEncode(value))
|
||||
}
|
||||
}
|
||||
sort.Strings(pairs)
|
||||
base := method + "&" + percentEncode(endpoint) + "&" + percentEncode(strings.Join(pairs, "&"))
|
||||
mac := hmac.New(sha1.New, []byte(percentEncode(consumerSecret)+"&"+percentEncode(tokenSecret)))
|
||||
mac.Write([]byte(base))
|
||||
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
||||
}
|
||||
|
||||
func nonce() string {
|
||||
buf := make([]byte, 16)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hex.EncodeToString(buf)
|
||||
}
|
||||
|
||||
func (c *Client) authorization(endpoint string, token *Token, params url.Values) (header string, body url.Values) {
|
||||
oauth := url.Values{
|
||||
"oauth_consumer_key": {c.Key},
|
||||
"oauth_nonce": {nonce()},
|
||||
"oauth_signature_method": {"HMAC-SHA1"},
|
||||
"oauth_timestamp": {strconv.FormatInt(time.Now().Unix(), 10)},
|
||||
"oauth_version": {"1.0"},
|
||||
}
|
||||
tokenSecret := ""
|
||||
if token != nil {
|
||||
oauth.Set("oauth_token", token.Key)
|
||||
tokenSecret = token.Secret
|
||||
}
|
||||
body = url.Values{}
|
||||
all := url.Values{}
|
||||
for key, values := range params {
|
||||
if strings.HasPrefix(key, "oauth_") {
|
||||
oauth[key] = values
|
||||
} else {
|
||||
body[key] = values
|
||||
}
|
||||
all[key] = values
|
||||
}
|
||||
for key, values := range oauth {
|
||||
all[key] = values
|
||||
}
|
||||
oauth.Set("oauth_signature", signature("POST", endpoint, all, c.Secret, tokenSecret))
|
||||
|
||||
keys := make([]string, 0, len(oauth))
|
||||
for key := range oauth {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
parts := make([]string, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
parts = append(parts, key+`="`+percentEncode(oauth.Get(key))+`"`)
|
||||
}
|
||||
return "OAuth " + strings.Join(parts, ", "), body
|
||||
}
|
||||
Reference in new issue
Block a user