mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	* update code.gitea.io/sdk/gitea v0.13.1 -> v0.13.2 * update github.com/go-swagger/go-swagger v0.25.0 -> v0.26.0 * update github.com/google/uuid v1.1.2 -> v1.2.0 * update github.com/klauspost/compress v1.11.3 -> v1.11.7 * update github.com/lib/pq 083382b7e6fc -> v1.9.0 * update github.com/markbates/goth v1.65.0 -> v1.66.1 * update github.com/mattn/go-sqlite3 v1.14.4 -> v1.14.6 * update github.com/mgechev/revive 246eac737dc7 -> v1.0.3 * update github.com/minio/minio-go/v7 v7.0.6 -> v7.0.7 * update github.com/niklasfasching/go-org v1.3.2 -> v1.4.0 * update github.com/olivere/elastic/v7 v7.0.21 -> v7.0.22 * update github.com/pquerna/otp v1.2.0 -> v1.3.0 * update github.com/xanzy/go-gitlab v0.39.0 -> v0.42.0 * update github.com/yuin/goldmark v1.2.1 -> v1.3.1
		
			
				
	
	
		
			499 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			499 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| // Copyright (C) MongoDB, Inc. 2017-present.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may
 | |
| // not use this file except in compliance with the License. You may obtain
 | |
| // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| package bsonrw
 | |
| 
 | |
| import (
 | |
| 	"encoding/base64"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"math"
 | |
| 	"strconv"
 | |
| 	"time"
 | |
| 
 | |
| 	"go.mongodb.org/mongo-driver/bson/bsontype"
 | |
| 	"go.mongodb.org/mongo-driver/bson/primitive"
 | |
| )
 | |
| 
 | |
| func wrapperKeyBSONType(key string) bsontype.Type {
 | |
| 	switch string(key) {
 | |
| 	case "$numberInt":
 | |
| 		return bsontype.Int32
 | |
| 	case "$numberLong":
 | |
| 		return bsontype.Int64
 | |
| 	case "$oid":
 | |
| 		return bsontype.ObjectID
 | |
| 	case "$symbol":
 | |
| 		return bsontype.Symbol
 | |
| 	case "$numberDouble":
 | |
| 		return bsontype.Double
 | |
| 	case "$numberDecimal":
 | |
| 		return bsontype.Decimal128
 | |
| 	case "$binary":
 | |
| 		return bsontype.Binary
 | |
| 	case "$code":
 | |
| 		return bsontype.JavaScript
 | |
| 	case "$scope":
 | |
| 		return bsontype.CodeWithScope
 | |
| 	case "$timestamp":
 | |
| 		return bsontype.Timestamp
 | |
| 	case "$regularExpression":
 | |
| 		return bsontype.Regex
 | |
| 	case "$dbPointer":
 | |
| 		return bsontype.DBPointer
 | |
| 	case "$date":
 | |
| 		return bsontype.DateTime
 | |
| 	case "$ref":
 | |
| 		fallthrough
 | |
| 	case "$id":
 | |
| 		fallthrough
 | |
| 	case "$db":
 | |
| 		return bsontype.EmbeddedDocument // dbrefs aren't bson types
 | |
| 	case "$minKey":
 | |
| 		return bsontype.MinKey
 | |
| 	case "$maxKey":
 | |
| 		return bsontype.MaxKey
 | |
| 	case "$undefined":
 | |
| 		return bsontype.Undefined
 | |
| 	}
 | |
| 
 | |
| 	return bsontype.EmbeddedDocument
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseBinary() (b []byte, subType byte, err error) {
 | |
| 	if ejv.t != bsontype.EmbeddedDocument {
 | |
| 		return nil, 0, fmt.Errorf("$binary value should be object, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	binObj := ejv.v.(*extJSONObject)
 | |
| 	bFound := false
 | |
| 	stFound := false
 | |
| 
 | |
| 	for i, key := range binObj.keys {
 | |
| 		val := binObj.values[i]
 | |
| 
 | |
| 		switch key {
 | |
| 		case "base64":
 | |
| 			if bFound {
 | |
| 				return nil, 0, errors.New("duplicate base64 key in $binary")
 | |
| 			}
 | |
| 
 | |
| 			if val.t != bsontype.String {
 | |
| 				return nil, 0, fmt.Errorf("$binary base64 value should be string, but instead is %s", val.t)
 | |
| 			}
 | |
| 
 | |
| 			base64Bytes, err := base64.StdEncoding.DecodeString(val.v.(string))
 | |
| 			if err != nil {
 | |
| 				return nil, 0, fmt.Errorf("invalid $binary base64 string: %s", val.v.(string))
 | |
| 			}
 | |
| 
 | |
| 			b = base64Bytes
 | |
| 			bFound = true
 | |
| 		case "subType":
 | |
| 			if stFound {
 | |
| 				return nil, 0, errors.New("duplicate subType key in $binary")
 | |
| 			}
 | |
| 
 | |
| 			if val.t != bsontype.String {
 | |
| 				return nil, 0, fmt.Errorf("$binary subType value should be string, but instead is %s", val.t)
 | |
| 			}
 | |
| 
 | |
| 			i, err := strconv.ParseInt(val.v.(string), 16, 64)
 | |
| 			if err != nil {
 | |
| 				return nil, 0, fmt.Errorf("invalid $binary subType string: %s", val.v.(string))
 | |
| 			}
 | |
| 
 | |
| 			subType = byte(i)
 | |
| 			stFound = true
 | |
| 		default:
 | |
| 			return nil, 0, fmt.Errorf("invalid key in $binary object: %s", key)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !bFound {
 | |
| 		return nil, 0, errors.New("missing base64 field in $binary object")
 | |
| 	}
 | |
| 
 | |
| 	if !stFound {
 | |
| 		return nil, 0, errors.New("missing subType field in $binary object")
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	return b, subType, nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseDBPointer() (ns string, oid primitive.ObjectID, err error) {
 | |
| 	if ejv.t != bsontype.EmbeddedDocument {
 | |
| 		return "", primitive.NilObjectID, fmt.Errorf("$dbPointer value should be object, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	dbpObj := ejv.v.(*extJSONObject)
 | |
| 	oidFound := false
 | |
| 	nsFound := false
 | |
| 
 | |
| 	for i, key := range dbpObj.keys {
 | |
| 		val := dbpObj.values[i]
 | |
| 
 | |
| 		switch key {
 | |
| 		case "$ref":
 | |
| 			if nsFound {
 | |
| 				return "", primitive.NilObjectID, errors.New("duplicate $ref key in $dbPointer")
 | |
| 			}
 | |
| 
 | |
| 			if val.t != bsontype.String {
 | |
| 				return "", primitive.NilObjectID, fmt.Errorf("$dbPointer $ref value should be string, but instead is %s", val.t)
 | |
| 			}
 | |
| 
 | |
| 			ns = val.v.(string)
 | |
| 			nsFound = true
 | |
| 		case "$id":
 | |
| 			if oidFound {
 | |
| 				return "", primitive.NilObjectID, errors.New("duplicate $id key in $dbPointer")
 | |
| 			}
 | |
| 
 | |
| 			if val.t != bsontype.String {
 | |
| 				return "", primitive.NilObjectID, fmt.Errorf("$dbPointer $id value should be string, but instead is %s", val.t)
 | |
| 			}
 | |
| 
 | |
| 			oid, err = primitive.ObjectIDFromHex(val.v.(string))
 | |
| 			if err != nil {
 | |
| 				return "", primitive.NilObjectID, err
 | |
| 			}
 | |
| 
 | |
| 			oidFound = true
 | |
| 		default:
 | |
| 			return "", primitive.NilObjectID, fmt.Errorf("invalid key in $dbPointer object: %s", key)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !nsFound {
 | |
| 		return "", oid, errors.New("missing $ref field in $dbPointer object")
 | |
| 	}
 | |
| 
 | |
| 	if !oidFound {
 | |
| 		return "", oid, errors.New("missing $id field in $dbPointer object")
 | |
| 	}
 | |
| 
 | |
| 	return ns, oid, nil
 | |
| }
 | |
| 
 | |
| const (
 | |
| 	rfc3339Milli = "2006-01-02T15:04:05.999Z07:00"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	timeFormats = []string{rfc3339Milli, "2006-01-02T15:04:05.999Z0700"}
 | |
| )
 | |
| 
 | |
| func (ejv *extJSONValue) parseDateTime() (int64, error) {
 | |
| 	switch ejv.t {
 | |
| 	case bsontype.Int32:
 | |
| 		return int64(ejv.v.(int32)), nil
 | |
| 	case bsontype.Int64:
 | |
| 		return ejv.v.(int64), nil
 | |
| 	case bsontype.String:
 | |
| 		return parseDatetimeString(ejv.v.(string))
 | |
| 	case bsontype.EmbeddedDocument:
 | |
| 		return parseDatetimeObject(ejv.v.(*extJSONObject))
 | |
| 	default:
 | |
| 		return 0, fmt.Errorf("$date value should be string or object, but instead is %s", ejv.t)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func parseDatetimeString(data string) (int64, error) {
 | |
| 	var t time.Time
 | |
| 	var err error
 | |
| 	// try acceptable time formats until one matches
 | |
| 	for _, format := range timeFormats {
 | |
| 		t, err = time.Parse(format, data)
 | |
| 		if err == nil {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 	if err != nil {
 | |
| 		return 0, fmt.Errorf("invalid $date value string: %s", data)
 | |
| 	}
 | |
| 
 | |
| 	return int64(primitive.NewDateTimeFromTime(t)), nil
 | |
| }
 | |
| 
 | |
| func parseDatetimeObject(data *extJSONObject) (d int64, err error) {
 | |
| 	dFound := false
 | |
| 
 | |
| 	for i, key := range data.keys {
 | |
| 		val := data.values[i]
 | |
| 
 | |
| 		switch key {
 | |
| 		case "$numberLong":
 | |
| 			if dFound {
 | |
| 				return 0, errors.New("duplicate $numberLong key in $date")
 | |
| 			}
 | |
| 
 | |
| 			if val.t != bsontype.String {
 | |
| 				return 0, fmt.Errorf("$date $numberLong field should be string, but instead is %s", val.t)
 | |
| 			}
 | |
| 
 | |
| 			d, err = val.parseInt64()
 | |
| 			if err != nil {
 | |
| 				return 0, err
 | |
| 			}
 | |
| 			dFound = true
 | |
| 		default:
 | |
| 			return 0, fmt.Errorf("invalid key in $date object: %s", key)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !dFound {
 | |
| 		return 0, errors.New("missing $numberLong field in $date object")
 | |
| 	}
 | |
| 
 | |
| 	return d, nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseDecimal128() (primitive.Decimal128, error) {
 | |
| 	if ejv.t != bsontype.String {
 | |
| 		return primitive.Decimal128{}, fmt.Errorf("$numberDecimal value should be string, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	d, err := primitive.ParseDecimal128(ejv.v.(string))
 | |
| 	if err != nil {
 | |
| 		return primitive.Decimal128{}, fmt.Errorf("$invalid $numberDecimal string: %s", ejv.v.(string))
 | |
| 	}
 | |
| 
 | |
| 	return d, nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseDouble() (float64, error) {
 | |
| 	if ejv.t == bsontype.Double {
 | |
| 		return ejv.v.(float64), nil
 | |
| 	}
 | |
| 
 | |
| 	if ejv.t != bsontype.String {
 | |
| 		return 0, fmt.Errorf("$numberDouble value should be string, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	switch string(ejv.v.(string)) {
 | |
| 	case "Infinity":
 | |
| 		return math.Inf(1), nil
 | |
| 	case "-Infinity":
 | |
| 		return math.Inf(-1), nil
 | |
| 	case "NaN":
 | |
| 		return math.NaN(), nil
 | |
| 	}
 | |
| 
 | |
| 	f, err := strconv.ParseFloat(ejv.v.(string), 64)
 | |
| 	if err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 
 | |
| 	return f, nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseInt32() (int32, error) {
 | |
| 	if ejv.t == bsontype.Int32 {
 | |
| 		return ejv.v.(int32), nil
 | |
| 	}
 | |
| 
 | |
| 	if ejv.t != bsontype.String {
 | |
| 		return 0, fmt.Errorf("$numberInt value should be string, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	i, err := strconv.ParseInt(ejv.v.(string), 10, 64)
 | |
| 	if err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 
 | |
| 	if i < math.MinInt32 || i > math.MaxInt32 {
 | |
| 		return 0, fmt.Errorf("$numberInt value should be int32 but instead is int64: %d", i)
 | |
| 	}
 | |
| 
 | |
| 	return int32(i), nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseInt64() (int64, error) {
 | |
| 	if ejv.t == bsontype.Int64 {
 | |
| 		return ejv.v.(int64), nil
 | |
| 	}
 | |
| 
 | |
| 	if ejv.t != bsontype.String {
 | |
| 		return 0, fmt.Errorf("$numberLong value should be string, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	i, err := strconv.ParseInt(ejv.v.(string), 10, 64)
 | |
| 	if err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 
 | |
| 	return i, nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseJavascript() (code string, err error) {
 | |
| 	if ejv.t != bsontype.String {
 | |
| 		return "", fmt.Errorf("$code value should be string, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	return ejv.v.(string), nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseMinMaxKey(minmax string) error {
 | |
| 	if ejv.t != bsontype.Int32 {
 | |
| 		return fmt.Errorf("$%sKey value should be int32, but instead is %s", minmax, ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	if ejv.v.(int32) != 1 {
 | |
| 		return fmt.Errorf("$%sKey value must be 1, but instead is %d", minmax, ejv.v.(int32))
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseObjectID() (primitive.ObjectID, error) {
 | |
| 	if ejv.t != bsontype.String {
 | |
| 		return primitive.NilObjectID, fmt.Errorf("$oid value should be string, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	return primitive.ObjectIDFromHex(ejv.v.(string))
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseRegex() (pattern, options string, err error) {
 | |
| 	if ejv.t != bsontype.EmbeddedDocument {
 | |
| 		return "", "", fmt.Errorf("$regularExpression value should be object, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	regexObj := ejv.v.(*extJSONObject)
 | |
| 	patFound := false
 | |
| 	optFound := false
 | |
| 
 | |
| 	for i, key := range regexObj.keys {
 | |
| 		val := regexObj.values[i]
 | |
| 
 | |
| 		switch string(key) {
 | |
| 		case "pattern":
 | |
| 			if patFound {
 | |
| 				return "", "", errors.New("duplicate pattern key in $regularExpression")
 | |
| 			}
 | |
| 
 | |
| 			if val.t != bsontype.String {
 | |
| 				return "", "", fmt.Errorf("$regularExpression pattern value should be string, but instead is %s", val.t)
 | |
| 			}
 | |
| 
 | |
| 			pattern = val.v.(string)
 | |
| 			patFound = true
 | |
| 		case "options":
 | |
| 			if optFound {
 | |
| 				return "", "", errors.New("duplicate options key in $regularExpression")
 | |
| 			}
 | |
| 
 | |
| 			if val.t != bsontype.String {
 | |
| 				return "", "", fmt.Errorf("$regularExpression options value should be string, but instead is %s", val.t)
 | |
| 			}
 | |
| 
 | |
| 			options = val.v.(string)
 | |
| 			optFound = true
 | |
| 		default:
 | |
| 			return "", "", fmt.Errorf("invalid key in $regularExpression object: %s", key)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !patFound {
 | |
| 		return "", "", errors.New("missing pattern field in $regularExpression object")
 | |
| 	}
 | |
| 
 | |
| 	if !optFound {
 | |
| 		return "", "", errors.New("missing options field in $regularExpression object")
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	return pattern, options, nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseSymbol() (string, error) {
 | |
| 	if ejv.t != bsontype.String {
 | |
| 		return "", fmt.Errorf("$symbol value should be string, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	return ejv.v.(string), nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseTimestamp() (t, i uint32, err error) {
 | |
| 	if ejv.t != bsontype.EmbeddedDocument {
 | |
| 		return 0, 0, fmt.Errorf("$timestamp value should be object, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	handleKey := func(key string, val *extJSONValue, flag bool) (uint32, error) {
 | |
| 		if flag {
 | |
| 			return 0, fmt.Errorf("duplicate %s key in $timestamp", key)
 | |
| 		}
 | |
| 
 | |
| 		switch val.t {
 | |
| 		case bsontype.Int32:
 | |
| 			value := val.v.(int32)
 | |
| 
 | |
| 			if value < 0 {
 | |
| 				return 0, fmt.Errorf("$timestamp %s number should be uint32: %d", key, value)
 | |
| 			}
 | |
| 
 | |
| 			return uint32(value), nil
 | |
| 		case bsontype.Int64:
 | |
| 			value := val.v.(int64)
 | |
| 			if value < 0 || value > int64(math.MaxUint32) {
 | |
| 				return 0, fmt.Errorf("$timestamp %s number should be uint32: %d", key, value)
 | |
| 			}
 | |
| 
 | |
| 			return uint32(value), nil
 | |
| 		default:
 | |
| 			return 0, fmt.Errorf("$timestamp %s value should be uint32, but instead is %s", key, val.t)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	tsObj := ejv.v.(*extJSONObject)
 | |
| 	tFound := false
 | |
| 	iFound := false
 | |
| 
 | |
| 	for j, key := range tsObj.keys {
 | |
| 		val := tsObj.values[j]
 | |
| 
 | |
| 		switch key {
 | |
| 		case "t":
 | |
| 			if t, err = handleKey(key, val, tFound); err != nil {
 | |
| 				return 0, 0, err
 | |
| 			}
 | |
| 
 | |
| 			tFound = true
 | |
| 		case "i":
 | |
| 			if i, err = handleKey(key, val, iFound); err != nil {
 | |
| 				return 0, 0, err
 | |
| 			}
 | |
| 
 | |
| 			iFound = true
 | |
| 		default:
 | |
| 			return 0, 0, fmt.Errorf("invalid key in $timestamp object: %s", key)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !tFound {
 | |
| 		return 0, 0, errors.New("missing t field in $timestamp object")
 | |
| 	}
 | |
| 
 | |
| 	if !iFound {
 | |
| 		return 0, 0, errors.New("missing i field in $timestamp object")
 | |
| 	}
 | |
| 
 | |
| 	return t, i, nil
 | |
| }
 | |
| 
 | |
| func (ejv *extJSONValue) parseUndefined() error {
 | |
| 	if ejv.t != bsontype.Boolean {
 | |
| 		return fmt.Errorf("undefined value should be boolean, but instead is %s", ejv.t)
 | |
| 	}
 | |
| 
 | |
| 	if !ejv.v.(bool) {
 | |
| 		return fmt.Errorf("$undefined balue boolean should be true, but instead is %v", ejv.v.(bool))
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 |