mirror of https://github.com/containers/podman.git
				
				
				
			
		
			
				
	
	
		
			144 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
| package handlers
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"reflect"
 | |
| 	"strings"
 | |
| 	"syscall"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/containers/podman/v5/libpod/define"
 | |
| 	"github.com/containers/podman/v5/pkg/util"
 | |
| 	"github.com/gorilla/schema"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| // NewAPIDecoder returns a configured schema.Decoder
 | |
| func NewAPIDecoder() *schema.Decoder {
 | |
| 	_ = ParseDateTime
 | |
| 
 | |
| 	d := schema.NewDecoder()
 | |
| 	d.IgnoreUnknownKeys(true)
 | |
| 	d.RegisterConverter(map[string][]string{}, convertURLValuesString)
 | |
| 	d.RegisterConverter(time.Time{}, convertTimeString)
 | |
| 	d.RegisterConverter(define.ContainerStatus(0), convertContainerStatusString)
 | |
| 	d.RegisterConverter(map[string]string{}, convertStringMap)
 | |
| 
 | |
| 	var Signal syscall.Signal
 | |
| 	d.RegisterConverter(Signal, convertSignal)
 | |
| 	return d
 | |
| }
 | |
| 
 | |
| func NewCompatAPIDecoder() *schema.Decoder {
 | |
| 	dec := NewAPIDecoder()
 | |
| 
 | |
| 	// mimic behaviour of github.com/docker/docker/api/server/httputils.BoolValue()
 | |
| 	dec.RegisterConverter(true, func(s string) reflect.Value {
 | |
| 		s = strings.ToLower(strings.TrimSpace(s))
 | |
| 		return reflect.ValueOf(!(s == "" || s == "0" || s == "no" || s == "false" || s == "none"))
 | |
| 	})
 | |
| 
 | |
| 	return dec
 | |
| }
 | |
| 
 | |
| // On client:
 | |
| //
 | |
| //	v := map[string][]string{
 | |
| //		"dangling": {"true"},
 | |
| //	}
 | |
| //
 | |
| //	payload, err := jsoniter.MarshalToString(v)
 | |
| //	if err != nil {
 | |
| //		panic(err)
 | |
| //	}
 | |
| //	payload = url.QueryEscape(payload)
 | |
| func convertURLValuesString(query string) reflect.Value {
 | |
| 	f := map[string][]string{}
 | |
| 
 | |
| 	err := json.Unmarshal([]byte(query), &f)
 | |
| 	if err != nil {
 | |
| 		logrus.Infof("convertURLValuesString: Failed to Unmarshal %s: %s", query, err.Error())
 | |
| 	}
 | |
| 
 | |
| 	return reflect.ValueOf(f)
 | |
| }
 | |
| 
 | |
| func convertStringMap(query string) reflect.Value {
 | |
| 	res := make(map[string]string)
 | |
| 	err := json.Unmarshal([]byte(query), &res)
 | |
| 	if err != nil {
 | |
| 		logrus.Infof("convertStringMap: Failed to Unmarshal %s: %s", query, err.Error())
 | |
| 	}
 | |
| 	return reflect.ValueOf(res)
 | |
| }
 | |
| 
 | |
| func convertContainerStatusString(query string) reflect.Value {
 | |
| 	result, err := define.StringToContainerStatus(query)
 | |
| 	if err != nil {
 | |
| 		logrus.Infof("convertContainerStatusString: Failed to parse %s: %s", query, err.Error())
 | |
| 
 | |
| 		// We return nil here instead of result because reflect.ValueOf().IsValid() will be true
 | |
| 		// in github.com/gorilla/schema's decoder, which means there's no parsing error
 | |
| 		return reflect.ValueOf(nil)
 | |
| 	}
 | |
| 
 | |
| 	return reflect.ValueOf(result)
 | |
| }
 | |
| 
 | |
| // isZero() can be used to determine if parsing failed.
 | |
| func convertTimeString(query string) reflect.Value {
 | |
| 	var (
 | |
| 		err error
 | |
| 		t   time.Time
 | |
| 	)
 | |
| 
 | |
| 	for _, f := range []string{
 | |
| 		time.UnixDate,
 | |
| 		time.ANSIC,
 | |
| 		time.RFC1123,
 | |
| 		time.RFC1123Z,
 | |
| 		time.RFC3339,
 | |
| 		time.RFC3339Nano,
 | |
| 		time.RFC822,
 | |
| 		time.RFC822Z,
 | |
| 		time.RFC850,
 | |
| 		time.RubyDate,
 | |
| 		time.Stamp,
 | |
| 		time.StampMicro,
 | |
| 		time.StampMilli,
 | |
| 		time.StampNano,
 | |
| 	} {
 | |
| 		t, err = time.Parse(f, query)
 | |
| 		if err == nil {
 | |
| 			return reflect.ValueOf(t)
 | |
| 		}
 | |
| 
 | |
| 		if _, isParseError := err.(*time.ParseError); isParseError {
 | |
| 			// Try next format
 | |
| 			continue
 | |
| 		} else {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// We've exhausted all formats, or something bad happened
 | |
| 	if err != nil {
 | |
| 		logrus.Infof("convertTimeString: Failed to parse %s: %s", query, err.Error())
 | |
| 	}
 | |
| 	return reflect.ValueOf(time.Time{})
 | |
| }
 | |
| 
 | |
| // ParseDateTime is a helper function to aid in parsing different Time/Date formats
 | |
| // isZero() can be used to determine if parsing failed.
 | |
| func ParseDateTime(query string) time.Time {
 | |
| 	return convertTimeString(query).Interface().(time.Time)
 | |
| }
 | |
| 
 | |
| func convertSignal(query string) reflect.Value {
 | |
| 	signal, err := util.ParseSignal(query)
 | |
| 	if err != nil {
 | |
| 		logrus.Infof("convertSignal: Failed to parse %s: %s", query, err.Error())
 | |
| 	}
 | |
| 	return reflect.ValueOf(signal)
 | |
| }
 |