90 lines
1.5 KiB
Go
90 lines
1.5 KiB
Go
package obj
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type QURL struct {
|
|
ID uint64
|
|
URL string
|
|
Created time.Time
|
|
IP []byte
|
|
Browser string
|
|
}
|
|
|
|
func (q *QURL) CheckValid() error {
|
|
if q == nil {
|
|
return fmt.Errorf("QURL is nil")
|
|
}
|
|
|
|
if q.URL == "" {
|
|
return fmt.Errorf("URL may not be empty")
|
|
}
|
|
|
|
u, err := url.Parse(q.URL)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if u.Scheme == "" {
|
|
return fmt.Errorf("URLs must begin with a scheme (e.g. https:)")
|
|
}
|
|
|
|
if u.Host == "" && u.RawQuery == "" && u.RawPath == "" && u.Fragment == "" {
|
|
return fmt.Errorf("URLs must contain a path, host, query or fragment element")
|
|
}
|
|
|
|
if !u.IsAbs() {
|
|
return fmt.Errorf("Relative URLs are not allowed")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
const alpha = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
const alphalen = uint64(len(alpha))
|
|
|
|
func ToString(v uint64) string {
|
|
var r strings.Builder
|
|
var i uint64
|
|
for i = v; i >= alphalen; i = (i / alphalen) - 1 {
|
|
r.WriteByte(alpha[i%alphalen])
|
|
}
|
|
r.WriteByte(alpha[i])
|
|
return r.String()
|
|
}
|
|
|
|
func FromString(s string) (uint64, error) {
|
|
var r uint64
|
|
vlen := uint64(len(s))
|
|
|
|
for i := uint64(0); i < vlen; i++ {
|
|
x := strings.IndexByte(alpha, s[i])
|
|
if x == -1 {
|
|
return 0, fmt.Errorf("Invalid character [%s]", s[i])
|
|
}
|
|
|
|
if i == 0 {
|
|
r += uint64(x)
|
|
} else {
|
|
r += (uint64(x+1) * pow(alphalen, i))
|
|
}
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func pow(a, b uint64) uint64 {
|
|
p := uint64(1)
|
|
for b > 0 {
|
|
if b&1 != 0 {
|
|
p *= a
|
|
}
|
|
b >>= 1
|
|
a *= a
|
|
}
|
|
return p
|
|
}
|