1// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package http
6
7import (
8	"mime/multipart"
9	"net/textproto"
10	"net/url"
11	_ "unsafe" // for linkname
12)
13
14// cloneURLValues should be an internal detail,
15// but widely used packages access it using linkname.
16// Notable members of the hall of shame include:
17//   - github.com/searKing/golang
18//
19// Do not remove or change the type signature.
20// See go.dev/issue/67401.
21//
22//go:linkname cloneURLValues
23func cloneURLValues(v url.Values) url.Values {
24	if v == nil {
25		return nil
26	}
27	// http.Header and url.Values have the same representation, so temporarily
28	// treat it like http.Header, which does have a clone:
29	return url.Values(Header(v).Clone())
30}
31
32// cloneURL should be an internal detail,
33// but widely used packages access it using linkname.
34// Notable members of the hall of shame include:
35//   - github.com/searKing/golang
36//
37// Do not remove or change the type signature.
38// See go.dev/issue/67401.
39//
40//go:linkname cloneURL
41func cloneURL(u *url.URL) *url.URL {
42	if u == nil {
43		return nil
44	}
45	u2 := new(url.URL)
46	*u2 = *u
47	if u.User != nil {
48		u2.User = new(url.Userinfo)
49		*u2.User = *u.User
50	}
51	return u2
52}
53
54// cloneMultipartForm should be an internal detail,
55// but widely used packages access it using linkname.
56// Notable members of the hall of shame include:
57//   - github.com/searKing/golang
58//
59// Do not remove or change the type signature.
60// See go.dev/issue/67401.
61//
62//go:linkname cloneMultipartForm
63func cloneMultipartForm(f *multipart.Form) *multipart.Form {
64	if f == nil {
65		return nil
66	}
67	f2 := &multipart.Form{
68		Value: (map[string][]string)(Header(f.Value).Clone()),
69	}
70	if f.File != nil {
71		m := make(map[string][]*multipart.FileHeader)
72		for k, vv := range f.File {
73			vv2 := make([]*multipart.FileHeader, len(vv))
74			for i, v := range vv {
75				vv2[i] = cloneMultipartFileHeader(v)
76			}
77			m[k] = vv2
78		}
79		f2.File = m
80	}
81	return f2
82}
83
84// cloneMultipartFileHeader should be an internal detail,
85// but widely used packages access it using linkname.
86// Notable members of the hall of shame include:
87//   - github.com/searKing/golang
88//
89// Do not remove or change the type signature.
90// See go.dev/issue/67401.
91//
92//go:linkname cloneMultipartFileHeader
93func cloneMultipartFileHeader(fh *multipart.FileHeader) *multipart.FileHeader {
94	if fh == nil {
95		return nil
96	}
97	fh2 := new(multipart.FileHeader)
98	*fh2 = *fh
99	fh2.Header = textproto.MIMEHeader(Header(fh.Header).Clone())
100	return fh2
101}
102
103// cloneOrMakeHeader invokes Header.Clone but if the
104// result is nil, it'll instead make and return a non-nil Header.
105//
106// cloneOrMakeHeader should be an internal detail,
107// but widely used packages access it using linkname.
108// Notable members of the hall of shame include:
109//   - github.com/searKing/golang
110//
111// Do not remove or change the type signature.
112// See go.dev/issue/67401.
113//
114//go:linkname cloneOrMakeHeader
115func cloneOrMakeHeader(hdr Header) Header {
116	clone := hdr.Clone()
117	if clone == nil {
118		clone = make(Header)
119	}
120	return clone
121}
122