func FromURL(urlString string) (*HOTP, string, error) {
	u, err := url.Parse(urlString)
	if err != nil {
		return nil, "", err
	}

	if u.Scheme != "otpauth" {
		return nil, "", ErrInvalidHOTPURL
	} else if u.Host != "hotp" {
		return nil, "", ErrInvalidHOTPURL
	}

	v := u.Query()
	if len(v) == 0 {
		return nil, "", ErrInvalidHOTPURL
	}
	if v.Get("secret") == "" {
		return nil, "", ErrInvalidHOTPURL
	} else if algo := v.Get("algorithm"); algo != "" && algo != "SHA1" {
		return nil, "", ErrInvalidHOTPURL
	}

	var identity string
	if len(u.Path) > 1 {
		identity = u.Path[1:]
	}

	var counter uint64
	if ctr := v.Get("counter"); ctr != "" {
		counter, err = strconv.ParseUint(ctr, 10, 64)
		if err != nil {
			return nil, "", ErrInvalidHOTPURL
		}
	}

	secret, err := base32.StdEncoding.DecodeString(v.Get("secret"))
	if err != nil {
		return nil, "", ErrInvalidHOTPURL
	}

	var digits int64 = 6
	if v.Get("digits") != "" {
		digits, err = strconv.ParseInt(v.Get("digits"), 10, 8)
		if err != nil {
			return nil, "", ErrInvalidHOTPURL
		}
	}

	otp := NewHOTP(secret, counter, int(digits))
	return otp, identity, nil
}
func FromURL(urlString string) (*HOTP, string, error) {
	u, err := url.Parse(urlString)
	if err != nil {
		return nil, "", err
	}

	if u.Scheme != "otpauth" {
		return nil, "", ErrInvalidHOTPURL
	} else if u.Host != "hotp" {
		return nil, "", ErrInvalidHOTPURL
	}

	v := u.Query()
	if len(v) == 0 {
		return nil, "", ErrInvalidHOTPURL
	}
	if v.Get("secret") == "" {
		return nil, "", ErrInvalidHOTPURL
	} else if algo := v.Get("algorithm"); algo != "" && algo != "SHA1" {
		return nil, "", ErrInvalidHOTPURL
	}

	var identity string
	if len(u.Path) > 1 {
		identity = u.Path[1:]
	}

	var counter uint64
	if ctr := v.Get("counter"); ctr != "" {
		counter, err = strconv.ParseUint(ctr, 10, 64)
		if err != nil {
			return nil, "", ErrInvalidHOTPURL
		}
	}

	secret, err := base32.StdEncoding.DecodeString(v.Get("secret"))
	if err != nil {
		return nil, "", ErrInvalidHOTPURL
	}

	var digits int64 = 6
	if v.Get("digits") != "" {
		digits, err = strconv.ParseInt(v.Get("digits"), 10, 8)
		if err != nil {
			return nil, "", ErrInvalidHOTPURL
		}
	}

	otp := NewHOTP(secret, counter, int(digits))
	return otp, identity, nil
}
func FromURL ( urlString string ) ( * HOTP , string , error ) { u , err := url . Parse ( urlString ) if err != nil { return nil , " " , err } if u . Scheme != " " { return nil , " " , ErrInvalidHOTPURL } else if u . Host != " " { return nil , " " , ErrInvalidHOTPURL } v := u . Query ( ) if len ( v ) == 0 { return nil , " " , ErrInvalidHOTPURL } if v . Get ( " " ) == " " { return nil , " " , ErrInvalidHOTPURL } else if algo := v . Get ( " " ) ; algo != " " && algo != " " { return nil , " " , ErrInvalidHOTPURL } var identity string if len ( u . Path ) > 1 { identity = u . Path [ 1 : ] } var counter uint64 if ctr := v . Get ( " " ) ; ctr != " " { counter , err = strconv . ParseUint ( ctr , 10 , 64 ) if err != nil { return nil , " " , ErrInvalidHOTPURL } } secret , err := base32 . StdEncoding . DecodeString ( v . Get ( " " ) ) if err != nil { return nil , " " , ErrInvalidHOTPURL } var digits int64 = 6 if v . Get ( " " ) != " " { digits , err = strconv . ParseInt ( v . Get ( " " ) , 10 , 8 ) if err != nil { return nil , " " , ErrInvalidHOTPURL } } otp := NewHOTP ( secret , counter , int ( digits ) ) return otp , identity , nil }
// FromURL parses a new HOTP from a URL string. It returns the OTP,
// the label associated with the OTP, and any errors that occurred.
FromURL parses a new HOTP from a URL string . It returns the OTP the label associated with the OTP and any errors that occurred .