mirror of
https://github.com/rclone/rclone.git
synced 2025-02-07 05:59:49 +01:00
parent
3ef9f6f016
commit
8ec57d145e
306
Godeps/Godeps.json
generated
306
Godeps/Godeps.json
generated
@ -20,13 +20,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "cloud.google.com/go/compute/metadata",
|
"ImportPath": "cloud.google.com/go/compute/metadata",
|
||||||
"Comment": "v0.6.0-23-ge0ba508",
|
"Comment": "v0.6.0-68-g0b87d14",
|
||||||
"Rev": "e0ba5081473dca0a69826693dca7f03fc0e3d086"
|
"Rev": "0b87d14d90086b53a97dfbd66f3000f7f112b494"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "cloud.google.com/go/internal",
|
"ImportPath": "cloud.google.com/go/internal",
|
||||||
"Comment": "v0.6.0-23-ge0ba508",
|
"Comment": "v0.6.0-68-g0b87d14",
|
||||||
"Rev": "e0ba5081473dca0a69826693dca7f03fc0e3d086"
|
"Rev": "0b87d14d90086b53a97dfbd66f3000f7f112b494"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/Unknwon/goconfig",
|
"ImportPath": "github.com/Unknwon/goconfig",
|
||||||
@ -39,138 +39,138 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awserr",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/awserr",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/client",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/stscreds",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/stscreds",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/defaults",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/defaults",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/endpoints",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/endpoints",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/request",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/request",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/session",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/session",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/signer/v4",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws/signer/v4",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/restxml",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/restxml",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3",
|
"ImportPath": "github.com/aws/aws-sdk-go/service/s3",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3/s3iface",
|
"ImportPath": "github.com/aws/aws-sdk-go/service/s3/s3iface",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3/s3manager",
|
"ImportPath": "github.com/aws/aws-sdk-go/service/s3/s3manager",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/sts",
|
"ImportPath": "github.com/aws/aws-sdk-go/service/sts",
|
||||||
"Comment": "v1.6.9-2-g6ad900d",
|
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cpuguy83/go-md2man/md2man",
|
"ImportPath": "github.com/cpuguy83/go-md2man/md2man",
|
||||||
@ -179,12 +179,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||||
"Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d"
|
"Comment": "v1.1.0",
|
||||||
|
"Rev": "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/go-ini/ini",
|
"ImportPath": "github.com/go-ini/ini",
|
||||||
"Comment": "v1.9.0",
|
"Comment": "v1.24.0-2-gee900ca",
|
||||||
"Rev": "193d1ecb466bf97aae8b454a5cfc192941c64809"
|
"Rev": "ee900ca565931451fe4e4409bcbd4316331cec1c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/golang/protobuf/proto",
|
"ImportPath": "github.com/golang/protobuf/proto",
|
||||||
@ -192,7 +193,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/go-querystring/query",
|
"ImportPath": "github.com/google/go-querystring/query",
|
||||||
"Rev": "9235644dd9e52eeae6fa48efd539fdc351a0af53"
|
"Rev": "53e6ce116135b80d037921a7fdd5138cf32d7a8a"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/googleapis/gax-go",
|
"ImportPath": "github.com/googleapis/gax-go",
|
||||||
@ -204,8 +205,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/jmespath/go-jmespath",
|
"ImportPath": "github.com/jmespath/go-jmespath",
|
||||||
"Comment": "0.2.2-12-g0b12d6b",
|
"Comment": "0.2.2-14-gbd40a43",
|
||||||
"Rev": "0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74"
|
"Rev": "bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/kr/fs",
|
||||||
|
"Rev": "2788f0dbd16903de03cb8186e5c7d97b69ad387b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ncw/go-acd",
|
"ImportPath": "github.com/ncw/go-acd",
|
||||||
@ -222,25 +227,26 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/pkg/sftp",
|
"ImportPath": "github.com/pkg/sftp",
|
||||||
"Rev": "bf1c2bb0012cdea62d6c5ae7212a1bb04cfa4d89"
|
"Rev": "ff7e52ffd762466ebd2c4e710d5436dccc539f54"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/pmezard/go-difflib/difflib",
|
"ImportPath": "github.com/pmezard/go-difflib/difflib",
|
||||||
|
"Comment": "v1.0.0",
|
||||||
"Rev": "792786c7400a136282c1664665ae0a8db921c6c2"
|
"Rev": "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rfjakob/eme",
|
"ImportPath": "github.com/rfjakob/eme",
|
||||||
"Comment": "v1.0-10-g601d0e2",
|
"Comment": "v1.0-15-gfd00240",
|
||||||
"Rev": "601d0e278ceda9aa2085a61c9265f6e690ef5255"
|
"Rev": "fd00240838d2e0fe6b2c58bf5b27db843d828ad5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/russross/blackfriday",
|
"ImportPath": "github.com/russross/blackfriday",
|
||||||
"Comment": "v1.4-38-g93622da",
|
"Comment": "v1.4-40-g5f33e7b",
|
||||||
"Rev": "93622da34e54fb6529bfb7c57e710f37a8d9cbd8"
|
"Rev": "5f33e7b7878355cd2b7e6b8eefc48a5472c69f70"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/shurcooL/sanitized_anchor_name",
|
"ImportPath": "github.com/shurcooL/sanitized_anchor_name",
|
||||||
"Rev": "10ef21a441db47d8b13ebcc5fd2310f636973c77"
|
"Rev": "1dba4b3954bc059efc3991ec364f9f9a35f597d2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/skratchdot/open-golang/open",
|
"ImportPath": "github.com/skratchdot/open-golang/open",
|
||||||
@ -248,15 +254,15 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/spf13/cobra",
|
"ImportPath": "github.com/spf13/cobra",
|
||||||
"Rev": "1dd5ff2e11b6dca62fdcb275eb804b94607d8b06"
|
"Rev": "b5d8e8f46a2f829f755b6e33b454e25c61c935e1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/spf13/cobra/doc",
|
"ImportPath": "github.com/spf13/cobra/doc",
|
||||||
"Rev": "1dd5ff2e11b6dca62fdcb275eb804b94607d8b06"
|
"Rev": "b5d8e8f46a2f829f755b6e33b454e25c61c935e1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/spf13/pflag",
|
"ImportPath": "github.com/spf13/pflag",
|
||||||
"Rev": "25f8b5b07aece3207895bf19f7ab517eb3b22a40"
|
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/stacktic/dropbox",
|
"ImportPath": "github.com/stacktic/dropbox",
|
||||||
@ -264,216 +270,244 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/stretchr/testify/assert",
|
"ImportPath": "github.com/stretchr/testify/assert",
|
||||||
"Comment": "v1.1.4-25-g2402e8e",
|
"Comment": "v1.1.4-27-g4d4bfba",
|
||||||
"Rev": "2402e8e7a02fc811447d11f881aa9746cdc57983"
|
"Rev": "4d4bfba8f1d1027c4fdbe371823030df51419987"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/stretchr/testify/require",
|
"ImportPath": "github.com/stretchr/testify/require",
|
||||||
"Comment": "v1.1.4-25-g2402e8e",
|
"Comment": "v1.1.4-27-g4d4bfba",
|
||||||
"Rev": "2402e8e7a02fc811447d11f881aa9746cdc57983"
|
"Rev": "4d4bfba8f1d1027c4fdbe371823030df51419987"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/tsenart/tb",
|
"ImportPath": "github.com/tsenart/tb",
|
||||||
"Rev": "19f4c3d79d2bd67d0911b2e310b999eeea4454c1"
|
"Rev": "19f4c3d79d2bd67d0911b2e310b999eeea4454c1"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/curve25519",
|
||||||
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/ed25519",
|
||||||
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/ed25519/internal/edwards25519",
|
||||||
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/nacl/secretbox",
|
"ImportPath": "golang.org/x/crypto/nacl/secretbox",
|
||||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/pbkdf2",
|
"ImportPath": "golang.org/x/crypto/pbkdf2",
|
||||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/poly1305",
|
"ImportPath": "golang.org/x/crypto/poly1305",
|
||||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/salsa20/salsa",
|
"ImportPath": "golang.org/x/crypto/salsa20/salsa",
|
||||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/scrypt",
|
"ImportPath": "golang.org/x/crypto/scrypt",
|
||||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/ssh",
|
||||||
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/ssh/agent",
|
||||||
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/ssh/terminal",
|
"ImportPath": "golang.org/x/crypto/ssh/terminal",
|
||||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/context",
|
"ImportPath": "golang.org/x/net/context",
|
||||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/context/ctxhttp",
|
"ImportPath": "golang.org/x/net/context/ctxhttp",
|
||||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/http2",
|
"ImportPath": "golang.org/x/net/http2",
|
||||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/http2/hpack",
|
"ImportPath": "golang.org/x/net/http2/hpack",
|
||||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/idna",
|
"ImportPath": "golang.org/x/net/idna",
|
||||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/internal/timeseries",
|
"ImportPath": "golang.org/x/net/internal/timeseries",
|
||||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/lex/httplex",
|
"ImportPath": "golang.org/x/net/lex/httplex",
|
||||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/trace",
|
"ImportPath": "golang.org/x/net/trace",
|
||||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/oauth2",
|
"ImportPath": "golang.org/x/oauth2",
|
||||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/oauth2/google",
|
"ImportPath": "golang.org/x/oauth2/google",
|
||||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/oauth2/internal",
|
"ImportPath": "golang.org/x/oauth2/internal",
|
||||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/oauth2/jws",
|
"ImportPath": "golang.org/x/oauth2/jws",
|
||||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/oauth2/jwt",
|
"ImportPath": "golang.org/x/oauth2/jwt",
|
||||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/sys/unix",
|
"ImportPath": "golang.org/x/sys/unix",
|
||||||
"Rev": "d75a52659825e75fff6158388dddc6a5b04f9ba5"
|
"Rev": "075e574b89e4c2d22f2286a7e2b919519c6f3547"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/text/transform",
|
"ImportPath": "golang.org/x/text/transform",
|
||||||
"Rev": "fd889fe3a20f4878f5f47672fd3ca5b86db005e2"
|
"Rev": "85c29909967d7f171f821e7a42e7b7af76fb9598"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/text/unicode/norm",
|
"ImportPath": "golang.org/x/text/unicode/norm",
|
||||||
"Rev": "fd889fe3a20f4878f5f47672fd3ca5b86db005e2"
|
"Rev": "85c29909967d7f171f821e7a42e7b7af76fb9598"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/api/drive/v2",
|
"ImportPath": "google.golang.org/api/drive/v2",
|
||||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/api/gensupport",
|
"ImportPath": "google.golang.org/api/gensupport",
|
||||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/api/googleapi",
|
"ImportPath": "google.golang.org/api/googleapi",
|
||||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/api/googleapi/internal/uritemplates",
|
"ImportPath": "google.golang.org/api/googleapi/internal/uritemplates",
|
||||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/api/storage/v1",
|
"ImportPath": "google.golang.org/api/storage/v1",
|
||||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine",
|
"ImportPath": "google.golang.org/appengine",
|
||||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
"Comment": "v1.0.0-28-g2e4a801",
|
||||||
|
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine/internal",
|
"ImportPath": "google.golang.org/appengine/internal",
|
||||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
"Comment": "v1.0.0-28-g2e4a801",
|
||||||
|
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine/internal/app_identity",
|
"ImportPath": "google.golang.org/appengine/internal/app_identity",
|
||||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
"Comment": "v1.0.0-28-g2e4a801",
|
||||||
|
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine/internal/base",
|
"ImportPath": "google.golang.org/appengine/internal/base",
|
||||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
"Comment": "v1.0.0-28-g2e4a801",
|
||||||
|
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine/internal/datastore",
|
"ImportPath": "google.golang.org/appengine/internal/datastore",
|
||||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
"Comment": "v1.0.0-28-g2e4a801",
|
||||||
|
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine/internal/log",
|
"ImportPath": "google.golang.org/appengine/internal/log",
|
||||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
"Comment": "v1.0.0-28-g2e4a801",
|
||||||
|
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine/internal/modules",
|
"ImportPath": "google.golang.org/appengine/internal/modules",
|
||||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
"Comment": "v1.0.0-28-g2e4a801",
|
||||||
|
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/appengine/internal/remote_api",
|
"ImportPath": "google.golang.org/appengine/internal/remote_api",
|
||||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
"Comment": "v1.0.0-28-g2e4a801",
|
||||||
|
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc",
|
"ImportPath": "google.golang.org/grpc",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/codes",
|
"ImportPath": "google.golang.org/grpc/codes",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/credentials",
|
"ImportPath": "google.golang.org/grpc/credentials",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/grpclog",
|
"ImportPath": "google.golang.org/grpc/grpclog",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/internal",
|
"ImportPath": "google.golang.org/grpc/internal",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/metadata",
|
"ImportPath": "google.golang.org/grpc/metadata",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/naming",
|
"ImportPath": "google.golang.org/grpc/naming",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/peer",
|
"ImportPath": "google.golang.org/grpc/peer",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/stats",
|
"ImportPath": "google.golang.org/grpc/stats",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/tap",
|
"ImportPath": "google.golang.org/grpc/tap",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "google.golang.org/grpc/transport",
|
"ImportPath": "google.golang.org/grpc/transport",
|
||||||
"Comment": "v1.0.5-9-gc810507",
|
"Comment": "v1.0.5-52-gd0c32ee",
|
||||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/kr/fs",
|
"ImportPath": "gopkg.in/yaml.v2",
|
||||||
"Rev": "2788f0dbd16903de03cb8186e5c7d97b69ad387b"
|
"Rev": "a3f3340b5840cee44f372bddb5880fcbc419b46a"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
3
vendor/cloud.google.com/go/CONTRIBUTORS
generated
vendored
3
vendor/cloud.google.com/go/CONTRIBUTORS
generated
vendored
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
# Keep the list alphabetically sorted.
|
# Keep the list alphabetically sorted.
|
||||||
|
|
||||||
|
Alexis Hunt <lexer@google.com>
|
||||||
Andreas Litt <andreas.litt@gmail.com>
|
Andreas Litt <andreas.litt@gmail.com>
|
||||||
Andrew Gerrand <adg@golang.org>
|
Andrew Gerrand <adg@golang.org>
|
||||||
Brad Fitzpatrick <bradfitz@golang.org>
|
Brad Fitzpatrick <bradfitz@golang.org>
|
||||||
@ -24,11 +25,13 @@ Ingo Oeser <nightlyone@googlemail.com>
|
|||||||
Johan Euphrosine <proppy@google.com>
|
Johan Euphrosine <proppy@google.com>
|
||||||
Jonathan Amsterdam <jba@google.com>
|
Jonathan Amsterdam <jba@google.com>
|
||||||
Luna Duclos <luna.duclos@palmstonegames.com>
|
Luna Duclos <luna.duclos@palmstonegames.com>
|
||||||
|
Magnus Hiie <magnus.hiie@gmail.com>
|
||||||
Michael McGreevy <mcgreevy@golang.org>
|
Michael McGreevy <mcgreevy@golang.org>
|
||||||
Omar Jarjur <ojarjur@google.com>
|
Omar Jarjur <ojarjur@google.com>
|
||||||
Paweł Knap <pawelknap88@gmail.com>
|
Paweł Knap <pawelknap88@gmail.com>
|
||||||
Péter Szilágyi <peterke@gmail.com>
|
Péter Szilágyi <peterke@gmail.com>
|
||||||
Sarah Adams <shadams@google.com>
|
Sarah Adams <shadams@google.com>
|
||||||
|
Thanatat Tamtan <acoshift@gmail.com>
|
||||||
Toby Burress <kurin@google.com>
|
Toby Burress <kurin@google.com>
|
||||||
Tuo Shan <shantuo@google.com>
|
Tuo Shan <shantuo@google.com>
|
||||||
Tyler Treat <ttreat31@gmail.com>
|
Tyler Treat <ttreat31@gmail.com>
|
||||||
|
7
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
7
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
@ -24,6 +24,13 @@ type ConfigProvider interface {
|
|||||||
ClientConfig(serviceName string, cfgs ...*aws.Config) Config
|
ClientConfig(serviceName string, cfgs ...*aws.Config) Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfigNoResolveEndpointProvider same as ConfigProvider except it will not
|
||||||
|
// resolve the endpoint automatically. The service client's endpoint must be
|
||||||
|
// provided via the aws.Config.Endpoint field.
|
||||||
|
type ConfigNoResolveEndpointProvider interface {
|
||||||
|
ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) Config
|
||||||
|
}
|
||||||
|
|
||||||
// A Client implements the base client request and response handling
|
// A Client implements the base client request and response handling
|
||||||
// used by all service clients.
|
// used by all service clients.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
58
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
58
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
@ -46,10 +46,11 @@ const (
|
|||||||
AcmServiceID = "acm" // Acm.
|
AcmServiceID = "acm" // Acm.
|
||||||
ApigatewayServiceID = "apigateway" // Apigateway.
|
ApigatewayServiceID = "apigateway" // Apigateway.
|
||||||
ApplicationAutoscalingServiceID = "application-autoscaling" // ApplicationAutoscaling.
|
ApplicationAutoscalingServiceID = "application-autoscaling" // ApplicationAutoscaling.
|
||||||
AppstreamServiceID = "appstream" // Appstream.
|
|
||||||
Appstream2ServiceID = "appstream2" // Appstream2.
|
Appstream2ServiceID = "appstream2" // Appstream2.
|
||||||
AutoscalingServiceID = "autoscaling" // Autoscaling.
|
AutoscalingServiceID = "autoscaling" // Autoscaling.
|
||||||
|
BatchServiceID = "batch" // Batch.
|
||||||
BudgetsServiceID = "budgets" // Budgets.
|
BudgetsServiceID = "budgets" // Budgets.
|
||||||
|
ClouddirectoryServiceID = "clouddirectory" // Clouddirectory.
|
||||||
CloudformationServiceID = "cloudformation" // Cloudformation.
|
CloudformationServiceID = "cloudformation" // Cloudformation.
|
||||||
CloudfrontServiceID = "cloudfront" // Cloudfront.
|
CloudfrontServiceID = "cloudfront" // Cloudfront.
|
||||||
CloudhsmServiceID = "cloudhsm" // Cloudhsm.
|
CloudhsmServiceID = "cloudhsm" // Cloudhsm.
|
||||||
@ -63,6 +64,7 @@ const (
|
|||||||
CognitoIdpServiceID = "cognito-idp" // CognitoIdp.
|
CognitoIdpServiceID = "cognito-idp" // CognitoIdp.
|
||||||
CognitoSyncServiceID = "cognito-sync" // CognitoSync.
|
CognitoSyncServiceID = "cognito-sync" // CognitoSync.
|
||||||
ConfigServiceID = "config" // Config.
|
ConfigServiceID = "config" // Config.
|
||||||
|
CurServiceID = "cur" // Cur.
|
||||||
DatapipelineServiceID = "datapipeline" // Datapipeline.
|
DatapipelineServiceID = "datapipeline" // Datapipeline.
|
||||||
DevicefarmServiceID = "devicefarm" // Devicefarm.
|
DevicefarmServiceID = "devicefarm" // Devicefarm.
|
||||||
DirectconnectServiceID = "directconnect" // Directconnect.
|
DirectconnectServiceID = "directconnect" // Directconnect.
|
||||||
@ -111,6 +113,7 @@ const (
|
|||||||
RekognitionServiceID = "rekognition" // Rekognition.
|
RekognitionServiceID = "rekognition" // Rekognition.
|
||||||
Route53ServiceID = "route53" // Route53.
|
Route53ServiceID = "route53" // Route53.
|
||||||
Route53domainsServiceID = "route53domains" // Route53domains.
|
Route53domainsServiceID = "route53domains" // Route53domains.
|
||||||
|
RuntimeLexServiceID = "runtime.lex" // RuntimeLex.
|
||||||
S3ServiceID = "s3" // S3.
|
S3ServiceID = "s3" // S3.
|
||||||
SdbServiceID = "sdb" // Sdb.
|
SdbServiceID = "sdb" // Sdb.
|
||||||
ServicecatalogServiceID = "servicecatalog" // Servicecatalog.
|
ServicecatalogServiceID = "servicecatalog" // Servicecatalog.
|
||||||
@ -247,6 +250,7 @@ var awsPartition = partition{
|
|||||||
"ap-southeast-2": endpoint{},
|
"ap-southeast-2": endpoint{},
|
||||||
"eu-central-1": endpoint{},
|
"eu-central-1": endpoint{},
|
||||||
"eu-west-1": endpoint{},
|
"eu-west-1": endpoint{},
|
||||||
|
"eu-west-2": endpoint{},
|
||||||
"us-east-1": endpoint{},
|
"us-east-1": endpoint{},
|
||||||
"us-east-2": endpoint{},
|
"us-east-2": endpoint{},
|
||||||
"us-west-1": endpoint{},
|
"us-west-1": endpoint{},
|
||||||
@ -278,13 +282,6 @@ var awsPartition = partition{
|
|||||||
"us-west-2": endpoint{},
|
"us-west-2": endpoint{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"appstream": service{
|
|
||||||
|
|
||||||
Endpoints: endpoints{
|
|
||||||
"ap-northeast-1": endpoint{},
|
|
||||||
"us-east-1": endpoint{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"appstream2": service{
|
"appstream2": service{
|
||||||
Defaults: endpoint{
|
Defaults: endpoint{
|
||||||
Protocols: []string{"https"},
|
Protocols: []string{"https"},
|
||||||
@ -320,6 +317,12 @@ var awsPartition = partition{
|
|||||||
"us-west-2": endpoint{},
|
"us-west-2": endpoint{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"batch": service{
|
||||||
|
|
||||||
|
Endpoints: endpoints{
|
||||||
|
"us-east-1": endpoint{},
|
||||||
|
},
|
||||||
|
},
|
||||||
"budgets": service{
|
"budgets": service{
|
||||||
PartitionEndpoint: "aws-global",
|
PartitionEndpoint: "aws-global",
|
||||||
IsRegionalized: boxedFalse,
|
IsRegionalized: boxedFalse,
|
||||||
@ -333,6 +336,17 @@ var awsPartition = partition{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"clouddirectory": service{
|
||||||
|
|
||||||
|
Endpoints: endpoints{
|
||||||
|
"ap-southeast-1": endpoint{},
|
||||||
|
"ap-southeast-2": endpoint{},
|
||||||
|
"eu-west-1": endpoint{},
|
||||||
|
"us-east-1": endpoint{},
|
||||||
|
"us-east-2": endpoint{},
|
||||||
|
"us-west-2": endpoint{},
|
||||||
|
},
|
||||||
|
},
|
||||||
"cloudformation": service{
|
"cloudformation": service{
|
||||||
|
|
||||||
Endpoints: endpoints{
|
Endpoints: endpoints{
|
||||||
@ -420,6 +434,7 @@ var awsPartition = partition{
|
|||||||
Endpoints: endpoints{
|
Endpoints: endpoints{
|
||||||
"eu-west-1": endpoint{},
|
"eu-west-1": endpoint{},
|
||||||
"us-east-1": endpoint{},
|
"us-east-1": endpoint{},
|
||||||
|
"us-east-2": endpoint{},
|
||||||
"us-west-2": endpoint{},
|
"us-west-2": endpoint{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -523,6 +538,12 @@ var awsPartition = partition{
|
|||||||
"us-west-2": endpoint{},
|
"us-west-2": endpoint{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"cur": service{
|
||||||
|
|
||||||
|
Endpoints: endpoints{
|
||||||
|
"us-east-1": endpoint{},
|
||||||
|
},
|
||||||
|
},
|
||||||
"datapipeline": service{
|
"datapipeline": service{
|
||||||
|
|
||||||
Endpoints: endpoints{
|
Endpoints: endpoints{
|
||||||
@ -829,6 +850,7 @@ var awsPartition = partition{
|
|||||||
"ap-southeast-2": endpoint{},
|
"ap-southeast-2": endpoint{},
|
||||||
"eu-central-1": endpoint{},
|
"eu-central-1": endpoint{},
|
||||||
"eu-west-1": endpoint{},
|
"eu-west-1": endpoint{},
|
||||||
|
"eu-west-2": endpoint{},
|
||||||
"sa-east-1": endpoint{},
|
"sa-east-1": endpoint{},
|
||||||
"us-east-1": endpoint{},
|
"us-east-1": endpoint{},
|
||||||
"us-east-2": endpoint{},
|
"us-east-2": endpoint{},
|
||||||
@ -996,6 +1018,7 @@ var awsPartition = partition{
|
|||||||
"ap-southeast-2": endpoint{},
|
"ap-southeast-2": endpoint{},
|
||||||
"eu-central-1": endpoint{},
|
"eu-central-1": endpoint{},
|
||||||
"eu-west-1": endpoint{},
|
"eu-west-1": endpoint{},
|
||||||
|
"eu-west-2": endpoint{},
|
||||||
"us-east-1": endpoint{},
|
"us-east-1": endpoint{},
|
||||||
"us-east-2": endpoint{},
|
"us-east-2": endpoint{},
|
||||||
"us-west-1": endpoint{},
|
"us-west-1": endpoint{},
|
||||||
@ -1041,13 +1064,20 @@ var awsPartition = partition{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"metering.marketplace": service{
|
"metering.marketplace": service{
|
||||||
|
Defaults: endpoint{
|
||||||
|
CredentialScope: credentialScope{
|
||||||
|
Service: "aws-marketplace",
|
||||||
|
},
|
||||||
|
},
|
||||||
Endpoints: endpoints{
|
Endpoints: endpoints{
|
||||||
"ap-northeast-1": endpoint{},
|
"ap-northeast-1": endpoint{},
|
||||||
|
"ap-northeast-2": endpoint{},
|
||||||
|
"ap-south-1": endpoint{},
|
||||||
"ap-southeast-1": endpoint{},
|
"ap-southeast-1": endpoint{},
|
||||||
"ap-southeast-2": endpoint{},
|
"ap-southeast-2": endpoint{},
|
||||||
"eu-central-1": endpoint{},
|
"eu-central-1": endpoint{},
|
||||||
"eu-west-1": endpoint{},
|
"eu-west-1": endpoint{},
|
||||||
|
"sa-east-1": endpoint{},
|
||||||
"us-east-1": endpoint{},
|
"us-east-1": endpoint{},
|
||||||
"us-west-1": endpoint{},
|
"us-west-1": endpoint{},
|
||||||
"us-west-2": endpoint{},
|
"us-west-2": endpoint{},
|
||||||
@ -1192,6 +1222,16 @@ var awsPartition = partition{
|
|||||||
"us-east-1": endpoint{},
|
"us-east-1": endpoint{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"runtime.lex": service{
|
||||||
|
Defaults: endpoint{
|
||||||
|
CredentialScope: credentialScope{
|
||||||
|
Service: "lex",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Endpoints: endpoints{
|
||||||
|
"us-east-1": endpoint{},
|
||||||
|
},
|
||||||
|
},
|
||||||
"s3": service{
|
"s3": service{
|
||||||
PartitionEndpoint: "us-east-1",
|
PartitionEndpoint: "us-east-1",
|
||||||
IsRegionalized: boxedTrue,
|
IsRegionalized: boxedTrue,
|
||||||
|
34
vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
generated
vendored
34
vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
generated
vendored
@ -27,6 +27,25 @@ type Options struct {
|
|||||||
// error will be returned. This option will prevent returning endpoints
|
// error will be returned. This option will prevent returning endpoints
|
||||||
// that look valid, but may not resolve to any real endpoint.
|
// that look valid, but may not resolve to any real endpoint.
|
||||||
StrictMatching bool
|
StrictMatching bool
|
||||||
|
|
||||||
|
// Enables resolving a service endpoint based on the region provided if the
|
||||||
|
// service does not exist. The service endpoint ID will be used as the service
|
||||||
|
// domain name prefix. By default the endpoint resolver requires the service
|
||||||
|
// to be known when resolving endpoints.
|
||||||
|
//
|
||||||
|
// If resolving an endpoint on the partition list the provided region will
|
||||||
|
// be used to determine which partition's domain name pattern to the service
|
||||||
|
// endpoint ID with. If both the service and region are unkonwn and resolving
|
||||||
|
// the endpoint on partition list an UnknownEndpointError error will be returned.
|
||||||
|
//
|
||||||
|
// If resolving and endpoint on a partition specific resolver that partition's
|
||||||
|
// domain name pattern will be used with the service endpoint ID. If both
|
||||||
|
// region and service do not exist when resolving an endpoint on a specific
|
||||||
|
// partition the partition's domain pattern will be used to combine the
|
||||||
|
// endpoint and region together.
|
||||||
|
//
|
||||||
|
// This option is ignored if StrictMatching is enabled.
|
||||||
|
ResolveUnknownService bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set combines all of the option functions together.
|
// Set combines all of the option functions together.
|
||||||
@ -54,6 +73,12 @@ func StrictMatchingOption(o *Options) {
|
|||||||
o.StrictMatching = true
|
o.StrictMatching = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveUnknownServiceOption sets the ResolveUnknownService option. Can be used
|
||||||
|
// as a functional option when resolving endpoints.
|
||||||
|
func ResolveUnknownServiceOption(o *Options) {
|
||||||
|
o.ResolveUnknownService = true
|
||||||
|
}
|
||||||
|
|
||||||
// A Resolver provides the interface for functionality to resolve endpoints.
|
// A Resolver provides the interface for functionality to resolve endpoints.
|
||||||
// The build in Partition and DefaultResolver return value satisfy this interface.
|
// The build in Partition and DefaultResolver return value satisfy this interface.
|
||||||
type Resolver interface {
|
type Resolver interface {
|
||||||
@ -114,15 +139,18 @@ func (p *Partition) ID() string { return p.id }
|
|||||||
//
|
//
|
||||||
// If the service cannot be found in the metadata the UnknownServiceError
|
// If the service cannot be found in the metadata the UnknownServiceError
|
||||||
// error will be returned. This validation will occur regardless if
|
// error will be returned. This validation will occur regardless if
|
||||||
// StrictMatching is enabled.
|
// StrictMatching is enabled. To enable resolving unknown services set the
|
||||||
|
// "ResolveUnknownService" option to true. When StrictMatching is disabled
|
||||||
|
// this option allows the partition resolver to resolve a endpoint based on
|
||||||
|
// the service endpoint ID provided.
|
||||||
//
|
//
|
||||||
// When resolving endpoints you can choose to enable StrictMatching. This will
|
// When resolving endpoints you can choose to enable StrictMatching. This will
|
||||||
// require the provided service and region to be known by the partition.
|
// require the provided service and region to be known by the partition.
|
||||||
// If the endpoint cannot be strictly resolved an error will be returned. This
|
// If the endpoint cannot be strictly resolved an error will be returned. This
|
||||||
// mode is useful to ensure the endpoint resolved is valid. Without
|
// mode is useful to ensure the endpoint resolved is valid. Without
|
||||||
// StrictMatching enabled the enpoint returned my look valid but may not work.
|
// StrictMatching enabled the endpoint returned my look valid but may not work.
|
||||||
// StrictMatching requires the SDK to be updated if you want to take advantage
|
// StrictMatching requires the SDK to be updated if you want to take advantage
|
||||||
// of new regions and services expantions.
|
// of new regions and services expansions.
|
||||||
//
|
//
|
||||||
// Errors that can be returned.
|
// Errors that can be returned.
|
||||||
// * UnknownServiceError
|
// * UnknownServiceError
|
||||||
|
4
vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go
generated
vendored
4
vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go
generated
vendored
@ -79,7 +79,9 @@ func (p partition) EndpointFor(service, region string, opts ...func(*Options)) (
|
|||||||
opt.Set(opts...)
|
opt.Set(opts...)
|
||||||
|
|
||||||
s, hasService := p.Services[service]
|
s, hasService := p.Services[service]
|
||||||
if !hasService {
|
if !(hasService || opt.ResolveUnknownService) {
|
||||||
|
// Only return error if the resolver will not fallback to creating
|
||||||
|
// endpoint based on service endpoint ID passed in.
|
||||||
return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services))
|
return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
34
vendor/github.com/aws/aws-sdk-go/aws/session/session.go
generated
vendored
34
vendor/github.com/aws/aws-sdk-go/aws/session/session.go
generated
vendored
@ -40,7 +40,7 @@ type Session struct {
|
|||||||
//
|
//
|
||||||
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
||||||
// the shared config file (~/.aws/config) will also be loaded, in addition to
|
// the shared config file (~/.aws/config) will also be loaded, in addition to
|
||||||
// the shared credentials file (~/.aws/config). Values set in both the
|
// the shared credentials file (~/.aws/credentials). Values set in both the
|
||||||
// shared config, and shared credentials will be taken from the shared
|
// shared config, and shared credentials will be taken from the shared
|
||||||
// credentials file.
|
// credentials file.
|
||||||
//
|
//
|
||||||
@ -83,7 +83,7 @@ func New(cfgs ...*aws.Config) *Session {
|
|||||||
//
|
//
|
||||||
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
||||||
// the shared config file (~/.aws/config) will also be loaded in addition to
|
// the shared config file (~/.aws/config) will also be loaded in addition to
|
||||||
// the shared credentials file (~/.aws/config). Values set in both the
|
// the shared credentials file (~/.aws/credentials). Values set in both the
|
||||||
// shared config, and shared credentials will be taken from the shared
|
// shared config, and shared credentials will be taken from the shared
|
||||||
// credentials file. Enabling the Shared Config will also allow the Session
|
// credentials file. Enabling the Shared Config will also allow the Session
|
||||||
// to be built with retrieving credentials with AssumeRole set in the config.
|
// to be built with retrieving credentials with AssumeRole set in the config.
|
||||||
@ -155,7 +155,7 @@ type Options struct {
|
|||||||
//
|
//
|
||||||
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
||||||
// the shared config file (~/.aws/config) will also be loaded in addition to
|
// the shared config file (~/.aws/config) will also be loaded in addition to
|
||||||
// the shared credentials file (~/.aws/config). Values set in both the
|
// the shared credentials file (~/.aws/credentials). Values set in both the
|
||||||
// shared config, and shared credentials will be taken from the shared
|
// shared config, and shared credentials will be taken from the shared
|
||||||
// credentials file. Enabling the Shared Config will also allow the Session
|
// credentials file. Enabling the Shared Config will also allow the Session
|
||||||
// to be built with retrieving credentials with AssumeRole set in the config.
|
// to be built with retrieving credentials with AssumeRole set in the config.
|
||||||
@ -404,6 +404,10 @@ func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) (
|
|||||||
func(opt *endpoints.Options) {
|
func(opt *endpoints.Options) {
|
||||||
opt.DisableSSL = aws.BoolValue(s.Config.DisableSSL)
|
opt.DisableSSL = aws.BoolValue(s.Config.DisableSSL)
|
||||||
opt.UseDualStack = aws.BoolValue(s.Config.UseDualStack)
|
opt.UseDualStack = aws.BoolValue(s.Config.UseDualStack)
|
||||||
|
|
||||||
|
// Support the condition where the service is modeled but its
|
||||||
|
// endpoint metadata is not available.
|
||||||
|
opt.ResolveUnknownService = true
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -416,3 +420,27 @@ func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) (
|
|||||||
SigningName: resolved.SigningName,
|
SigningName: resolved.SigningName,
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClientConfigNoResolveEndpoint is the same as ClientConfig with the exception
|
||||||
|
// that the EndpointResolver will not be used to resolve the endpoint. The only
|
||||||
|
// endpoint set must come from the aws.Config.Endpoint field.
|
||||||
|
func (s *Session) ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) client.Config {
|
||||||
|
s = s.Copy(cfgs...)
|
||||||
|
|
||||||
|
var resolved endpoints.ResolvedEndpoint
|
||||||
|
|
||||||
|
region := aws.StringValue(s.Config.Region)
|
||||||
|
|
||||||
|
if ep := aws.StringValue(s.Config.Endpoint); len(ep) > 0 {
|
||||||
|
resolved.URL = endpoints.AddScheme(ep, aws.BoolValue(s.Config.DisableSSL))
|
||||||
|
resolved.SigningRegion = region
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.Config{
|
||||||
|
Config: s.Config,
|
||||||
|
Handlers: s.Handlers,
|
||||||
|
Endpoint: resolved.URL,
|
||||||
|
SigningRegion: resolved.SigningRegion,
|
||||||
|
SigningName: resolved.SigningName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2
vendor/github.com/aws/aws-sdk-go/aws/types.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/types.go
generated
vendored
@ -114,5 +114,5 @@ func (b *WriteAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) {
|
|||||||
func (b *WriteAtBuffer) Bytes() []byte {
|
func (b *WriteAtBuffer) Bytes() []byte {
|
||||||
b.m.Lock()
|
b.m.Lock()
|
||||||
defer b.m.Unlock()
|
defer b.m.Unlock()
|
||||||
return b.buf[:len(b.buf):len(b.buf)]
|
return b.buf
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
@ -5,4 +5,4 @@ package aws
|
|||||||
const SDKName = "aws-sdk-go"
|
const SDKName = "aws-sdk-go"
|
||||||
|
|
||||||
// SDKVersion is the version of this SDK
|
// SDKVersion is the version of this SDK
|
||||||
const SDKVersion = "1.6.9"
|
const SDKVersion = "1.6.24"
|
||||||
|
25
vendor/github.com/aws/aws-sdk-go/service/s3/api.go
generated
vendored
25
vendor/github.com/aws/aws-sdk-go/service/s3/api.go
generated
vendored
@ -73,7 +73,7 @@ func (c *S3) AbortMultipartUploadRequest(input *AbortMultipartUploadInput) (req
|
|||||||
// API operation AbortMultipartUpload for usage and error information.
|
// API operation AbortMultipartUpload for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * NoSuchUpload
|
// * ErrCodeNoSuchUpload "NoSuchUpload"
|
||||||
// The specified multipart upload does not exist.
|
// The specified multipart upload does not exist.
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/AbortMultipartUpload
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/AbortMultipartUpload
|
||||||
@ -198,7 +198,7 @@ func (c *S3) CopyObjectRequest(input *CopyObjectInput) (req *request.Request, ou
|
|||||||
// API operation CopyObject for usage and error information.
|
// API operation CopyObject for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * ObjectNotInActiveTierError
|
// * ErrCodeObjectNotInActiveTierError "ObjectNotInActiveTierError"
|
||||||
// The source object of the COPY operation is not in the active tier and is
|
// The source object of the COPY operation is not in the active tier and is
|
||||||
// only stored in Amazon Glacier.
|
// only stored in Amazon Glacier.
|
||||||
//
|
//
|
||||||
@ -264,12 +264,11 @@ func (c *S3) CreateBucketRequest(input *CreateBucketInput) (req *request.Request
|
|||||||
// API operation CreateBucket for usage and error information.
|
// API operation CreateBucket for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * BucketAlreadyExists
|
// * ErrCodeBucketAlreadyExists "BucketAlreadyExists"
|
||||||
// The requested bucket name is not available. The bucket namespace is shared
|
// The requested bucket name is not available. The bucket namespace is shared
|
||||||
// by all users of the system. Please select a different name and try again.
|
// by all users of the system. Please select a different name and try again.
|
||||||
//
|
//
|
||||||
// * BucketAlreadyOwnedByYou
|
// * ErrCodeBucketAlreadyOwnedByYou "BucketAlreadyOwnedByYou"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/CreateBucket
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/CreateBucket
|
||||||
func (c *S3) CreateBucket(input *CreateBucketInput) (*CreateBucketOutput, error) {
|
func (c *S3) CreateBucket(input *CreateBucketInput) (*CreateBucketOutput, error) {
|
||||||
@ -2296,7 +2295,7 @@ func (c *S3) GetObjectRequest(input *GetObjectInput) (req *request.Request, outp
|
|||||||
// API operation GetObject for usage and error information.
|
// API operation GetObject for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * NoSuchKey
|
// * ErrCodeNoSuchKey "NoSuchKey"
|
||||||
// The specified key does not exist.
|
// The specified key does not exist.
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject
|
||||||
@ -2361,7 +2360,7 @@ func (c *S3) GetObjectAclRequest(input *GetObjectAclInput) (req *request.Request
|
|||||||
// API operation GetObjectAcl for usage and error information.
|
// API operation GetObjectAcl for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * NoSuchKey
|
// * ErrCodeNoSuchKey "NoSuchKey"
|
||||||
// The specified key does not exist.
|
// The specified key does not exist.
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObjectAcl
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObjectAcl
|
||||||
@ -2549,7 +2548,7 @@ func (c *S3) HeadBucketRequest(input *HeadBucketInput) (req *request.Request, ou
|
|||||||
// API operation HeadBucket for usage and error information.
|
// API operation HeadBucket for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * NoSuchBucket
|
// * ErrCodeNoSuchBucket "NoSuchBucket"
|
||||||
// The specified bucket does not exist.
|
// The specified bucket does not exist.
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/HeadBucket
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/HeadBucket
|
||||||
@ -2616,7 +2615,7 @@ func (c *S3) HeadObjectRequest(input *HeadObjectInput) (req *request.Request, ou
|
|||||||
// API operation HeadObject for usage and error information.
|
// API operation HeadObject for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * NoSuchKey
|
// * ErrCodeNoSuchKey "NoSuchKey"
|
||||||
// The specified key does not exist.
|
// The specified key does not exist.
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/HeadObject
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/HeadObject
|
||||||
@ -3111,7 +3110,7 @@ func (c *S3) ListObjectsRequest(input *ListObjectsInput) (req *request.Request,
|
|||||||
// API operation ListObjects for usage and error information.
|
// API operation ListObjects for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * NoSuchBucket
|
// * ErrCodeNoSuchBucket "NoSuchBucket"
|
||||||
// The specified bucket does not exist.
|
// The specified bucket does not exist.
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjects
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjects
|
||||||
@ -3210,7 +3209,7 @@ func (c *S3) ListObjectsV2Request(input *ListObjectsV2Input) (req *request.Reque
|
|||||||
// API operation ListObjectsV2 for usage and error information.
|
// API operation ListObjectsV2 for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * NoSuchBucket
|
// * ErrCodeNoSuchBucket "NoSuchBucket"
|
||||||
// The specified bucket does not exist.
|
// The specified bucket does not exist.
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjectsV2
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjectsV2
|
||||||
@ -4525,7 +4524,7 @@ func (c *S3) PutObjectAclRequest(input *PutObjectAclInput) (req *request.Request
|
|||||||
// API operation PutObjectAcl for usage and error information.
|
// API operation PutObjectAcl for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * NoSuchKey
|
// * ErrCodeNoSuchKey "NoSuchKey"
|
||||||
// The specified key does not exist.
|
// The specified key does not exist.
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/PutObjectAcl
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/PutObjectAcl
|
||||||
@ -4650,7 +4649,7 @@ func (c *S3) RestoreObjectRequest(input *RestoreObjectInput) (req *request.Reque
|
|||||||
// API operation RestoreObject for usage and error information.
|
// API operation RestoreObject for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * ObjectAlreadyInActiveTierError
|
// * ErrCodeObjectAlreadyInActiveTierError "ObjectAlreadyInActiveTierError"
|
||||||
// This operation is not allowed against this storage tier
|
// This operation is not allowed against this storage tier
|
||||||
//
|
//
|
||||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/RestoreObject
|
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/RestoreObject
|
||||||
|
48
vendor/github.com/aws/aws-sdk-go/service/s3/errors.go
generated
vendored
Normal file
48
vendor/github.com/aws/aws-sdk-go/service/s3/errors.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||||
|
|
||||||
|
package s3
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// ErrCodeBucketAlreadyExists for service response error code
|
||||||
|
// "BucketAlreadyExists".
|
||||||
|
//
|
||||||
|
// The requested bucket name is not available. The bucket namespace is shared
|
||||||
|
// by all users of the system. Please select a different name and try again.
|
||||||
|
ErrCodeBucketAlreadyExists = "BucketAlreadyExists"
|
||||||
|
|
||||||
|
// ErrCodeBucketAlreadyOwnedByYou for service response error code
|
||||||
|
// "BucketAlreadyOwnedByYou".
|
||||||
|
ErrCodeBucketAlreadyOwnedByYou = "BucketAlreadyOwnedByYou"
|
||||||
|
|
||||||
|
// ErrCodeNoSuchBucket for service response error code
|
||||||
|
// "NoSuchBucket".
|
||||||
|
//
|
||||||
|
// The specified bucket does not exist.
|
||||||
|
ErrCodeNoSuchBucket = "NoSuchBucket"
|
||||||
|
|
||||||
|
// ErrCodeNoSuchKey for service response error code
|
||||||
|
// "NoSuchKey".
|
||||||
|
//
|
||||||
|
// The specified key does not exist.
|
||||||
|
ErrCodeNoSuchKey = "NoSuchKey"
|
||||||
|
|
||||||
|
// ErrCodeNoSuchUpload for service response error code
|
||||||
|
// "NoSuchUpload".
|
||||||
|
//
|
||||||
|
// The specified multipart upload does not exist.
|
||||||
|
ErrCodeNoSuchUpload = "NoSuchUpload"
|
||||||
|
|
||||||
|
// ErrCodeObjectAlreadyInActiveTierError for service response error code
|
||||||
|
// "ObjectAlreadyInActiveTierError".
|
||||||
|
//
|
||||||
|
// This operation is not allowed against this storage tier
|
||||||
|
ErrCodeObjectAlreadyInActiveTierError = "ObjectAlreadyInActiveTierError"
|
||||||
|
|
||||||
|
// ErrCodeObjectNotInActiveTierError for service response error code
|
||||||
|
// "ObjectNotInActiveTierError".
|
||||||
|
//
|
||||||
|
// The source object of the COPY operation is not in the active tier and is
|
||||||
|
// only stored in Amazon Glacier.
|
||||||
|
ErrCodeObjectNotInActiveTierError = "ObjectNotInActiveTierError"
|
||||||
|
)
|
42
vendor/github.com/aws/aws-sdk-go/service/sts/api.go
generated
vendored
42
vendor/github.com/aws/aws-sdk-go/service/sts/api.go
generated
vendored
@ -153,16 +153,16 @@ func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, o
|
|||||||
// API operation AssumeRole for usage and error information.
|
// API operation AssumeRole for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * MalformedPolicyDocument
|
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
|
||||||
// The request was rejected because the policy document was malformed. The error
|
// The request was rejected because the policy document was malformed. The error
|
||||||
// message describes the specific error.
|
// message describes the specific error.
|
||||||
//
|
//
|
||||||
// * PackedPolicyTooLarge
|
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
|
||||||
// The request was rejected because the policy document was too large. The error
|
// The request was rejected because the policy document was too large. The error
|
||||||
// message describes how big the policy document is, in packed form, as a percentage
|
// message describes how big the policy document is, in packed form, as a percentage
|
||||||
// of what the API allows.
|
// of what the API allows.
|
||||||
//
|
//
|
||||||
// * RegionDisabledException
|
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||||
// STS is not activated in the requested region for the account that is being
|
// STS is not activated in the requested region for the account that is being
|
||||||
// asked to generate credentials. The account administrator must use the IAM
|
// asked to generate credentials. The account administrator must use the IAM
|
||||||
// console to activate STS in that region. For more information, see Activating
|
// console to activate STS in that region. For more information, see Activating
|
||||||
@ -297,31 +297,31 @@ func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *re
|
|||||||
// API operation AssumeRoleWithSAML for usage and error information.
|
// API operation AssumeRoleWithSAML for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * MalformedPolicyDocument
|
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
|
||||||
// The request was rejected because the policy document was malformed. The error
|
// The request was rejected because the policy document was malformed. The error
|
||||||
// message describes the specific error.
|
// message describes the specific error.
|
||||||
//
|
//
|
||||||
// * PackedPolicyTooLarge
|
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
|
||||||
// The request was rejected because the policy document was too large. The error
|
// The request was rejected because the policy document was too large. The error
|
||||||
// message describes how big the policy document is, in packed form, as a percentage
|
// message describes how big the policy document is, in packed form, as a percentage
|
||||||
// of what the API allows.
|
// of what the API allows.
|
||||||
//
|
//
|
||||||
// * IDPRejectedClaim
|
// * ErrCodeIDPRejectedClaimException "IDPRejectedClaim"
|
||||||
// The identity provider (IdP) reported that authentication failed. This might
|
// The identity provider (IdP) reported that authentication failed. This might
|
||||||
// be because the claim is invalid.
|
// be because the claim is invalid.
|
||||||
//
|
//
|
||||||
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
|
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
|
||||||
// can also mean that the claim has expired or has been explicitly revoked.
|
// can also mean that the claim has expired or has been explicitly revoked.
|
||||||
//
|
//
|
||||||
// * InvalidIdentityToken
|
// * ErrCodeInvalidIdentityTokenException "InvalidIdentityToken"
|
||||||
// The web identity token that was passed could not be validated by AWS. Get
|
// The web identity token that was passed could not be validated by AWS. Get
|
||||||
// a new identity token from the identity provider and then retry the request.
|
// a new identity token from the identity provider and then retry the request.
|
||||||
//
|
//
|
||||||
// * ExpiredTokenException
|
// * ErrCodeExpiredTokenException "ExpiredTokenException"
|
||||||
// The web identity token that was passed is expired or is not valid. Get a
|
// The web identity token that was passed is expired or is not valid. Get a
|
||||||
// new identity token from the identity provider and then retry the request.
|
// new identity token from the identity provider and then retry the request.
|
||||||
//
|
//
|
||||||
// * RegionDisabledException
|
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||||
// STS is not activated in the requested region for the account that is being
|
// STS is not activated in the requested region for the account that is being
|
||||||
// asked to generate credentials. The account administrator must use the IAM
|
// asked to generate credentials. The account administrator must use the IAM
|
||||||
// console to activate STS in that region. For more information, see Activating
|
// console to activate STS in that region. For more information, see Activating
|
||||||
@ -478,38 +478,38 @@ func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityI
|
|||||||
// API operation AssumeRoleWithWebIdentity for usage and error information.
|
// API operation AssumeRoleWithWebIdentity for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * MalformedPolicyDocument
|
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
|
||||||
// The request was rejected because the policy document was malformed. The error
|
// The request was rejected because the policy document was malformed. The error
|
||||||
// message describes the specific error.
|
// message describes the specific error.
|
||||||
//
|
//
|
||||||
// * PackedPolicyTooLarge
|
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
|
||||||
// The request was rejected because the policy document was too large. The error
|
// The request was rejected because the policy document was too large. The error
|
||||||
// message describes how big the policy document is, in packed form, as a percentage
|
// message describes how big the policy document is, in packed form, as a percentage
|
||||||
// of what the API allows.
|
// of what the API allows.
|
||||||
//
|
//
|
||||||
// * IDPRejectedClaim
|
// * ErrCodeIDPRejectedClaimException "IDPRejectedClaim"
|
||||||
// The identity provider (IdP) reported that authentication failed. This might
|
// The identity provider (IdP) reported that authentication failed. This might
|
||||||
// be because the claim is invalid.
|
// be because the claim is invalid.
|
||||||
//
|
//
|
||||||
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
|
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
|
||||||
// can also mean that the claim has expired or has been explicitly revoked.
|
// can also mean that the claim has expired or has been explicitly revoked.
|
||||||
//
|
//
|
||||||
// * IDPCommunicationError
|
// * ErrCodeIDPCommunicationErrorException "IDPCommunicationError"
|
||||||
// The request could not be fulfilled because the non-AWS identity provider
|
// The request could not be fulfilled because the non-AWS identity provider
|
||||||
// (IDP) that was asked to verify the incoming identity token could not be reached.
|
// (IDP) that was asked to verify the incoming identity token could not be reached.
|
||||||
// This is often a transient error caused by network conditions. Retry the request
|
// This is often a transient error caused by network conditions. Retry the request
|
||||||
// a limited number of times so that you don't exceed the request rate. If the
|
// a limited number of times so that you don't exceed the request rate. If the
|
||||||
// error persists, the non-AWS identity provider might be down or not responding.
|
// error persists, the non-AWS identity provider might be down or not responding.
|
||||||
//
|
//
|
||||||
// * InvalidIdentityToken
|
// * ErrCodeInvalidIdentityTokenException "InvalidIdentityToken"
|
||||||
// The web identity token that was passed could not be validated by AWS. Get
|
// The web identity token that was passed could not be validated by AWS. Get
|
||||||
// a new identity token from the identity provider and then retry the request.
|
// a new identity token from the identity provider and then retry the request.
|
||||||
//
|
//
|
||||||
// * ExpiredTokenException
|
// * ErrCodeExpiredTokenException "ExpiredTokenException"
|
||||||
// The web identity token that was passed is expired or is not valid. Get a
|
// The web identity token that was passed is expired or is not valid. Get a
|
||||||
// new identity token from the identity provider and then retry the request.
|
// new identity token from the identity provider and then retry the request.
|
||||||
//
|
//
|
||||||
// * RegionDisabledException
|
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||||
// STS is not activated in the requested region for the account that is being
|
// STS is not activated in the requested region for the account that is being
|
||||||
// asked to generate credentials. The account administrator must use the IAM
|
// asked to generate credentials. The account administrator must use the IAM
|
||||||
// console to activate STS in that region. For more information, see Activating
|
// console to activate STS in that region. For more information, see Activating
|
||||||
@ -609,7 +609,7 @@ func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessag
|
|||||||
// API operation DecodeAuthorizationMessage for usage and error information.
|
// API operation DecodeAuthorizationMessage for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * InvalidAuthorizationMessageException
|
// * ErrCodeInvalidAuthorizationMessageException "InvalidAuthorizationMessageException"
|
||||||
// The error returned if the message passed to DecodeAuthorizationMessage was
|
// The error returned if the message passed to DecodeAuthorizationMessage was
|
||||||
// invalid. This can happen if the token contains invalid characters, such as
|
// invalid. This can happen if the token contains invalid characters, such as
|
||||||
// linebreaks.
|
// linebreaks.
|
||||||
@ -814,16 +814,16 @@ func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *re
|
|||||||
// API operation GetFederationToken for usage and error information.
|
// API operation GetFederationToken for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * MalformedPolicyDocument
|
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
|
||||||
// The request was rejected because the policy document was malformed. The error
|
// The request was rejected because the policy document was malformed. The error
|
||||||
// message describes the specific error.
|
// message describes the specific error.
|
||||||
//
|
//
|
||||||
// * PackedPolicyTooLarge
|
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
|
||||||
// The request was rejected because the policy document was too large. The error
|
// The request was rejected because the policy document was too large. The error
|
||||||
// message describes how big the policy document is, in packed form, as a percentage
|
// message describes how big the policy document is, in packed form, as a percentage
|
||||||
// of what the API allows.
|
// of what the API allows.
|
||||||
//
|
//
|
||||||
// * RegionDisabledException
|
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||||
// STS is not activated in the requested region for the account that is being
|
// STS is not activated in the requested region for the account that is being
|
||||||
// asked to generate credentials. The account administrator must use the IAM
|
// asked to generate credentials. The account administrator must use the IAM
|
||||||
// console to activate STS in that region. For more information, see Activating
|
// console to activate STS in that region. For more information, see Activating
|
||||||
@ -937,7 +937,7 @@ func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.
|
|||||||
// API operation GetSessionToken for usage and error information.
|
// API operation GetSessionToken for usage and error information.
|
||||||
//
|
//
|
||||||
// Returned Error Codes:
|
// Returned Error Codes:
|
||||||
// * RegionDisabledException
|
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||||
// STS is not activated in the requested region for the account that is being
|
// STS is not activated in the requested region for the account that is being
|
||||||
// asked to generate credentials. The account administrator must use the IAM
|
// asked to generate credentials. The account administrator must use the IAM
|
||||||
// console to activate STS in that region. For more information, see Activating
|
// console to activate STS in that region. For more information, see Activating
|
||||||
|
73
vendor/github.com/aws/aws-sdk-go/service/sts/errors.go
generated
vendored
Normal file
73
vendor/github.com/aws/aws-sdk-go/service/sts/errors.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||||
|
|
||||||
|
package sts
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// ErrCodeExpiredTokenException for service response error code
|
||||||
|
// "ExpiredTokenException".
|
||||||
|
//
|
||||||
|
// The web identity token that was passed is expired or is not valid. Get a
|
||||||
|
// new identity token from the identity provider and then retry the request.
|
||||||
|
ErrCodeExpiredTokenException = "ExpiredTokenException"
|
||||||
|
|
||||||
|
// ErrCodeIDPCommunicationErrorException for service response error code
|
||||||
|
// "IDPCommunicationError".
|
||||||
|
//
|
||||||
|
// The request could not be fulfilled because the non-AWS identity provider
|
||||||
|
// (IDP) that was asked to verify the incoming identity token could not be reached.
|
||||||
|
// This is often a transient error caused by network conditions. Retry the request
|
||||||
|
// a limited number of times so that you don't exceed the request rate. If the
|
||||||
|
// error persists, the non-AWS identity provider might be down or not responding.
|
||||||
|
ErrCodeIDPCommunicationErrorException = "IDPCommunicationError"
|
||||||
|
|
||||||
|
// ErrCodeIDPRejectedClaimException for service response error code
|
||||||
|
// "IDPRejectedClaim".
|
||||||
|
//
|
||||||
|
// The identity provider (IdP) reported that authentication failed. This might
|
||||||
|
// be because the claim is invalid.
|
||||||
|
//
|
||||||
|
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
|
||||||
|
// can also mean that the claim has expired or has been explicitly revoked.
|
||||||
|
ErrCodeIDPRejectedClaimException = "IDPRejectedClaim"
|
||||||
|
|
||||||
|
// ErrCodeInvalidAuthorizationMessageException for service response error code
|
||||||
|
// "InvalidAuthorizationMessageException".
|
||||||
|
//
|
||||||
|
// The error returned if the message passed to DecodeAuthorizationMessage was
|
||||||
|
// invalid. This can happen if the token contains invalid characters, such as
|
||||||
|
// linebreaks.
|
||||||
|
ErrCodeInvalidAuthorizationMessageException = "InvalidAuthorizationMessageException"
|
||||||
|
|
||||||
|
// ErrCodeInvalidIdentityTokenException for service response error code
|
||||||
|
// "InvalidIdentityToken".
|
||||||
|
//
|
||||||
|
// The web identity token that was passed could not be validated by AWS. Get
|
||||||
|
// a new identity token from the identity provider and then retry the request.
|
||||||
|
ErrCodeInvalidIdentityTokenException = "InvalidIdentityToken"
|
||||||
|
|
||||||
|
// ErrCodeMalformedPolicyDocumentException for service response error code
|
||||||
|
// "MalformedPolicyDocument".
|
||||||
|
//
|
||||||
|
// The request was rejected because the policy document was malformed. The error
|
||||||
|
// message describes the specific error.
|
||||||
|
ErrCodeMalformedPolicyDocumentException = "MalformedPolicyDocument"
|
||||||
|
|
||||||
|
// ErrCodePackedPolicyTooLargeException for service response error code
|
||||||
|
// "PackedPolicyTooLarge".
|
||||||
|
//
|
||||||
|
// The request was rejected because the policy document was too large. The error
|
||||||
|
// message describes how big the policy document is, in packed form, as a percentage
|
||||||
|
// of what the API allows.
|
||||||
|
ErrCodePackedPolicyTooLargeException = "PackedPolicyTooLarge"
|
||||||
|
|
||||||
|
// ErrCodeRegionDisabledException for service response error code
|
||||||
|
// "RegionDisabledException".
|
||||||
|
//
|
||||||
|
// STS is not activated in the requested region for the account that is being
|
||||||
|
// asked to generate credentials. The account administrator must use the IAM
|
||||||
|
// console to activate STS in that region. For more information, see Activating
|
||||||
|
// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
|
||||||
|
// in the IAM User Guide.
|
||||||
|
ErrCodeRegionDisabledException = "RegionDisabledException"
|
||||||
|
)
|
4
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
4
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
@ -1,4 +1,6 @@
|
|||||||
Copyright (c) 2012-2013 Dave Collins <dave@davec.name>
|
ISC License
|
||||||
|
|
||||||
|
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
9
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
9
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2015 Dave Collins <dave@davec.name>
|
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -13,9 +13,10 @@
|
|||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
// when the code is not running on Google App Engine and "-tags disableunsafe"
|
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||||
// is not added to the go build command line.
|
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||||
// +build !appengine,!disableunsafe
|
// tag is deprecated and thus should not be used.
|
||||||
|
// +build !js,!appengine,!safe,!disableunsafe
|
||||||
|
|
||||||
package spew
|
package spew
|
||||||
|
|
||||||
|
9
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
9
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2015 Dave Collins <dave@davec.name>
|
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -13,9 +13,10 @@
|
|||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
// when either the code is running on Google App Engine or "-tags disableunsafe"
|
// when the code is running on Google App Engine, compiled by GopherJS, or
|
||||||
// is added to the go build command line.
|
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
||||||
// +build appengine disableunsafe
|
// tag is deprecated and thus should not be used.
|
||||||
|
// +build js appengine safe disableunsafe
|
||||||
|
|
||||||
package spew
|
package spew
|
||||||
|
|
||||||
|
2
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
13
vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
13
vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -64,9 +64,18 @@ type ConfigState struct {
|
|||||||
// inside these interface methods. As a result, this option relies on
|
// inside these interface methods. As a result, this option relies on
|
||||||
// access to the unsafe package, so it will not have any effect when
|
// access to the unsafe package, so it will not have any effect when
|
||||||
// running in environments without access to the unsafe package such as
|
// running in environments without access to the unsafe package such as
|
||||||
// Google App Engine or with the "disableunsafe" build tag specified.
|
// Google App Engine or with the "safe" build tag specified.
|
||||||
DisablePointerMethods bool
|
DisablePointerMethods bool
|
||||||
|
|
||||||
|
// DisablePointerAddresses specifies whether to disable the printing of
|
||||||
|
// pointer addresses. This is useful when diffing data structures in tests.
|
||||||
|
DisablePointerAddresses bool
|
||||||
|
|
||||||
|
// DisableCapacities specifies whether to disable the printing of capacities
|
||||||
|
// for arrays, slices, maps and channels. This is useful when diffing
|
||||||
|
// data structures in tests.
|
||||||
|
DisableCapacities bool
|
||||||
|
|
||||||
// ContinueOnMethod specifies whether or not recursion should continue once
|
// ContinueOnMethod specifies whether or not recursion should continue once
|
||||||
// a custom error or Stringer interface is invoked. The default, false,
|
// a custom error or Stringer interface is invoked. The default, false,
|
||||||
// means it will print the results of invoking the custom error or Stringer
|
// means it will print the results of invoking the custom error or Stringer
|
||||||
|
11
vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
11
vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -91,6 +91,15 @@ The following configuration options are available:
|
|||||||
which only accept pointer receivers from non-pointer variables.
|
which only accept pointer receivers from non-pointer variables.
|
||||||
Pointer method invocation is enabled by default.
|
Pointer method invocation is enabled by default.
|
||||||
|
|
||||||
|
* DisablePointerAddresses
|
||||||
|
DisablePointerAddresses specifies whether to disable the printing of
|
||||||
|
pointer addresses. This is useful when diffing data structures in tests.
|
||||||
|
|
||||||
|
* DisableCapacities
|
||||||
|
DisableCapacities specifies whether to disable the printing of
|
||||||
|
capacities for arrays, slices, maps and channels. This is useful when
|
||||||
|
diffing data structures in tests.
|
||||||
|
|
||||||
* ContinueOnMethod
|
* ContinueOnMethod
|
||||||
Enables recursion into types after invoking error and Stringer interface
|
Enables recursion into types after invoking error and Stringer interface
|
||||||
methods. Recursion after method invocation is disabled by default.
|
methods. Recursion after method invocation is disabled by default.
|
||||||
|
8
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
8
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -129,7 +129,7 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
|
|||||||
d.w.Write(closeParenBytes)
|
d.w.Write(closeParenBytes)
|
||||||
|
|
||||||
// Display pointer information.
|
// Display pointer information.
|
||||||
if len(pointerChain) > 0 {
|
if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
|
||||||
d.w.Write(openParenBytes)
|
d.w.Write(openParenBytes)
|
||||||
for i, addr := range pointerChain {
|
for i, addr := range pointerChain {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
@ -282,13 +282,13 @@ func (d *dumpState) dump(v reflect.Value) {
|
|||||||
case reflect.Map, reflect.String:
|
case reflect.Map, reflect.String:
|
||||||
valueLen = v.Len()
|
valueLen = v.Len()
|
||||||
}
|
}
|
||||||
if valueLen != 0 || valueCap != 0 {
|
if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
|
||||||
d.w.Write(openParenBytes)
|
d.w.Write(openParenBytes)
|
||||||
if valueLen != 0 {
|
if valueLen != 0 {
|
||||||
d.w.Write(lenEqualsBytes)
|
d.w.Write(lenEqualsBytes)
|
||||||
printInt(d.w, int64(valueLen), 10)
|
printInt(d.w, int64(valueLen), 10)
|
||||||
}
|
}
|
||||||
if valueCap != 0 {
|
if !d.cs.DisableCapacities && valueCap != 0 {
|
||||||
if valueLen != 0 {
|
if valueLen != 0 {
|
||||||
d.w.Write(spaceBytes)
|
d.w.Write(spaceBytes)
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
2
vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
1
vendor/github.com/go-ini/ini/.gitignore
generated
vendored
1
vendor/github.com/go-ini/ini/.gitignore
generated
vendored
@ -2,3 +2,4 @@ testdata/conf_out.ini
|
|||||||
ini.sublime-project
|
ini.sublime-project
|
||||||
ini.sublime-workspace
|
ini.sublime-workspace
|
||||||
testdata/conf_reflect.ini
|
testdata/conf_reflect.ini
|
||||||
|
.idea
|
||||||
|
17
vendor/github.com/go-ini/ini/.travis.yml
generated
vendored
Normal file
17
vendor/github.com/go-ini/ini/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
sudo: false
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.4.x
|
||||||
|
- 1.5.x
|
||||||
|
- 1.6.x
|
||||||
|
- 1.7.x
|
||||||
|
- master
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go get golang.org/x/tools/cmd/cover
|
||||||
|
- go get github.com/smartystreets/goconvey
|
||||||
|
- go test -v -cover -race
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
- u@gogs.io
|
12
vendor/github.com/go-ini/ini/Makefile
generated
vendored
Normal file
12
vendor/github.com/go-ini/ini/Makefile
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.PHONY: build test bench vet
|
||||||
|
|
||||||
|
build: vet bench
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test -v -cover -race
|
||||||
|
|
||||||
|
bench:
|
||||||
|
go test -v -cover -race -test.bench=. -test.benchmem
|
||||||
|
|
||||||
|
vet:
|
||||||
|
go vet
|
138
vendor/github.com/go-ini/ini/README.md
generated
vendored
138
vendor/github.com/go-ini/ini/README.md
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
ini [![Build Status](https://drone.io/github.com/go-ini/ini/status.png)](https://drone.io/github.com/go-ini/ini/latest) [![](http://gocover.io/_badge/github.com/go-ini/ini)](http://gocover.io/github.com/go-ini/ini)
|
INI [![Build Status](https://travis-ci.org/go-ini/ini.svg?branch=master)](https://travis-ci.org/go-ini/ini) [![Sourcegraph](https://sourcegraph.com/github.com/go-ini/ini/-/badge.svg)](https://sourcegraph.com/github.com/go-ini/ini?badge)
|
||||||
===
|
===
|
||||||
|
|
||||||
![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200)
|
![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200)
|
||||||
@ -9,7 +9,7 @@ Package ini provides INI file read and write functionality in Go.
|
|||||||
|
|
||||||
## Feature
|
## Feature
|
||||||
|
|
||||||
- Load multiple data sources(`[]byte` or file) with overwrites.
|
- Load multiple data sources(`[]byte`, file and `io.ReadCloser`) with overwrites.
|
||||||
- Read with recursion values.
|
- Read with recursion values.
|
||||||
- Read with parent-child sections.
|
- Read with parent-child sections.
|
||||||
- Read with auto-increment key names.
|
- Read with auto-increment key names.
|
||||||
@ -44,10 +44,10 @@ Please add `-u` flag to update in the future.
|
|||||||
|
|
||||||
### Loading from data sources
|
### Loading from data sources
|
||||||
|
|
||||||
A **Data Source** is either raw data in type `[]byte` or a file name with type `string` and you can load **as many as** data sources you want. Passing other types will simply return an error.
|
A **Data Source** is either raw data in type `[]byte`, a file name with type `string` or `io.ReadCloser`. You can load **as many data sources as you want**. Passing other types will simply return an error.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
cfg, err := ini.Load([]byte("raw data"), "filename")
|
cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))
|
||||||
```
|
```
|
||||||
|
|
||||||
Or start with an empty object:
|
Or start with an empty object:
|
||||||
@ -56,12 +56,72 @@ Or start with an empty object:
|
|||||||
cfg := ini.Empty()
|
cfg := ini.Empty()
|
||||||
```
|
```
|
||||||
|
|
||||||
When you cannot decide how many data sources to load at the beginning, you still able to **Append()** them later.
|
When you cannot decide how many data sources to load at the beginning, you will still be able to **Append()** them later.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
err := cfg.Append("other file", []byte("other raw data"))
|
err := cfg.Append("other file", []byte("other raw data"))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you have a list of files with possibilities that some of them may not available at the time, and you don't know exactly which ones, you can use `LooseLoad` to ignore nonexistent files without returning error.
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := ini.LooseLoad("filename", "filename_404")
|
||||||
|
```
|
||||||
|
|
||||||
|
The cool thing is, whenever the file is available to load while you're calling `Reload` method, it will be counted as usual.
|
||||||
|
|
||||||
|
#### Ignore cases of key name
|
||||||
|
|
||||||
|
When you do not care about cases of section and key names, you can use `InsensitiveLoad` to force all names to be lowercased while parsing.
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := ini.InsensitiveLoad("filename")
|
||||||
|
//...
|
||||||
|
|
||||||
|
// sec1 and sec2 are the exactly same section object
|
||||||
|
sec1, err := cfg.GetSection("Section")
|
||||||
|
sec2, err := cfg.GetSection("SecTIOn")
|
||||||
|
|
||||||
|
// key1 and key2 are the exactly same key object
|
||||||
|
key1, err := cfg.GetKey("Key")
|
||||||
|
key2, err := cfg.GetKey("KeY")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### MySQL-like boolean key
|
||||||
|
|
||||||
|
MySQL's configuration allows a key without value as follows:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[mysqld]
|
||||||
|
...
|
||||||
|
skip-host-cache
|
||||||
|
skip-name-resolve
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, this is considered as missing value. But if you know you're going to deal with those cases, you can assign advanced load options:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
|
||||||
|
```
|
||||||
|
|
||||||
|
The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read.
|
||||||
|
|
||||||
|
To generate such keys in your program, you could use `NewBooleanKey`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
key, err := sec.NewBooleanKey("skip-host-cache")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Comment
|
||||||
|
|
||||||
|
Take care that following format will be treated as comment:
|
||||||
|
|
||||||
|
1. Line begins with `#` or `;`
|
||||||
|
2. Words after `#` or `;`
|
||||||
|
3. Words after section name (i.e words after `[some section name]`)
|
||||||
|
|
||||||
|
If you want to save a value with `#` or `;`, please quote them with ``` ` ``` or ``` """ ```.
|
||||||
|
|
||||||
### Working with sections
|
### Working with sections
|
||||||
|
|
||||||
To get a section, you would need to:
|
To get a section, you would need to:
|
||||||
@ -79,7 +139,7 @@ section, err := cfg.GetSection("")
|
|||||||
When you're pretty sure the section exists, following code could make your life easier:
|
When you're pretty sure the section exists, following code could make your life easier:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
section := cfg.Section("")
|
section := cfg.Section("section name")
|
||||||
```
|
```
|
||||||
|
|
||||||
What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.
|
What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.
|
||||||
@ -133,7 +193,7 @@ names := cfg.Section("").KeyStrings()
|
|||||||
To get a clone hash of keys and corresponding values:
|
To get a clone hash of keys and corresponding values:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
hash := cfg.GetSection("").KeysHash()
|
hash := cfg.Section("").KeysHash()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Working with values
|
### Working with values
|
||||||
@ -246,6 +306,16 @@ cfg.Section("advance").Key("two_lines").String() // how about continuation lines
|
|||||||
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Well, I hate continuation lines, how do I disable that?
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := ini.LoadSources(ini.LoadOptions{
|
||||||
|
IgnoreContinuation: true,
|
||||||
|
}, "filename")
|
||||||
|
```
|
||||||
|
|
||||||
|
Holy crap!
|
||||||
|
|
||||||
Note that single quotes around values will be stripped:
|
Note that single quotes around values will be stripped:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
@ -346,6 +416,12 @@ cfg.WriteTo(writer)
|
|||||||
cfg.WriteToIndent(writer, "\t")
|
cfg.WriteToIndent(writer, "\t")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, spaces are used to align "=" sign between key and values, to disable that:
|
||||||
|
|
||||||
|
```go
|
||||||
|
ini.PrettyFormat = false
|
||||||
|
```
|
||||||
|
|
||||||
## Advanced Usage
|
## Advanced Usage
|
||||||
|
|
||||||
### Recursive Values
|
### Recursive Values
|
||||||
@ -387,6 +463,27 @@ CLONE_URL = https://%(IMPORT_PATH)s
|
|||||||
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Retrieve parent keys available to a child section
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unparseable Sections
|
||||||
|
|
||||||
|
Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
|
||||||
|
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
|
||||||
|
|
||||||
|
body := cfg.Section("COMMENTS").Body()
|
||||||
|
|
||||||
|
/* --- start ---
|
||||||
|
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
|
||||||
|
------ end --- */
|
||||||
|
```
|
||||||
|
|
||||||
### Auto-increment Key Names
|
### Auto-increment Key Names
|
||||||
|
|
||||||
If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
|
If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
|
||||||
@ -471,8 +568,8 @@ Why not?
|
|||||||
```go
|
```go
|
||||||
type Embeded struct {
|
type Embeded struct {
|
||||||
Dates []time.Time `delim:"|"`
|
Dates []time.Time `delim:"|"`
|
||||||
Places []string
|
Places []string `ini:"places,omitempty"`
|
||||||
None []int
|
None []int `ini:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Author struct {
|
type Author struct {
|
||||||
@ -507,8 +604,7 @@ GPA = 2.8
|
|||||||
|
|
||||||
[Embeded]
|
[Embeded]
|
||||||
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
||||||
Places = HangZhou,Boston
|
places = HangZhou,Boston
|
||||||
None =
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Name Mapper
|
#### Name Mapper
|
||||||
@ -542,6 +638,26 @@ func main() {
|
|||||||
|
|
||||||
Same rules of name mapper apply to `ini.ReflectFromWithMapper` function.
|
Same rules of name mapper apply to `ini.ReflectFromWithMapper` function.
|
||||||
|
|
||||||
|
#### Value Mapper
|
||||||
|
|
||||||
|
To expand values (e.g. from environment variables), you can use the `ValueMapper` to transform values:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Env struct {
|
||||||
|
Foo string `ini:"foo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfg, err := ini.Load([]byte("[env]\nfoo = ${MY_VAR}\n")
|
||||||
|
cfg.ValueMapper = os.ExpandEnv
|
||||||
|
// ...
|
||||||
|
env := &Env{}
|
||||||
|
err = cfg.Section("env").MapTo(env)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This would set the value of `env.Foo` to the value of the environment variable `MY_VAR`.
|
||||||
|
|
||||||
#### Other Notes On Map/Reflect
|
#### Other Notes On Map/Reflect
|
||||||
|
|
||||||
Any embedded struct is treated as a section by default, and there is no automatic parent-child relations in map/reflect feature:
|
Any embedded struct is treated as a section by default, and there is no automatic parent-child relations in map/reflect feature:
|
||||||
|
142
vendor/github.com/go-ini/ini/README_ZH.md
generated
vendored
142
vendor/github.com/go-ini/ini/README_ZH.md
generated
vendored
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## 功能特性
|
## 功能特性
|
||||||
|
|
||||||
- 支持覆盖加载多个数据源(`[]byte` 或文件)
|
- 支持覆盖加载多个数据源(`[]byte`、文件和 `io.ReadCloser`)
|
||||||
- 支持递归读取键值
|
- 支持递归读取键值
|
||||||
- 支持读取父子分区
|
- 支持读取父子分区
|
||||||
- 支持读取自增键名
|
- 支持读取自增键名
|
||||||
@ -37,10 +37,10 @@
|
|||||||
|
|
||||||
### 从数据源加载
|
### 从数据源加载
|
||||||
|
|
||||||
一个 **数据源** 可以是 `[]byte` 类型的原始数据,或 `string` 类型的文件路径。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
|
一个 **数据源** 可以是 `[]byte` 类型的原始数据,`string` 类型的文件路径或 `io.ReadCloser`。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
cfg, err := ini.Load([]byte("raw data"), "filename")
|
cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))
|
||||||
```
|
```
|
||||||
|
|
||||||
或者从一个空白的文件开始:
|
或者从一个空白的文件开始:
|
||||||
@ -55,6 +55,66 @@ cfg := ini.Empty()
|
|||||||
err := cfg.Append("other file", []byte("other raw data"))
|
err := cfg.Append("other file", []byte("other raw data"))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
当您想要加载一系列文件,但是不能够确定其中哪些文件是不存在的,可以通过调用函数 `LooseLoad` 来忽略它们(`Load` 会因为文件不存在而返回错误):
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := ini.LooseLoad("filename", "filename_404")
|
||||||
|
```
|
||||||
|
|
||||||
|
更牛逼的是,当那些之前不存在的文件在重新调用 `Reload` 方法的时候突然出现了,那么它们会被正常加载。
|
||||||
|
|
||||||
|
#### 忽略键名的大小写
|
||||||
|
|
||||||
|
有时候分区和键的名称大小写混合非常烦人,这个时候就可以通过 `InsensitiveLoad` 将所有分区和键名在读取里强制转换为小写:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := ini.InsensitiveLoad("filename")
|
||||||
|
//...
|
||||||
|
|
||||||
|
// sec1 和 sec2 指向同一个分区对象
|
||||||
|
sec1, err := cfg.GetSection("Section")
|
||||||
|
sec2, err := cfg.GetSection("SecTIOn")
|
||||||
|
|
||||||
|
// key1 和 key2 指向同一个键对象
|
||||||
|
key1, err := cfg.GetKey("Key")
|
||||||
|
key2, err := cfg.GetKey("KeY")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 类似 MySQL 配置中的布尔值键
|
||||||
|
|
||||||
|
MySQL 的配置文件中会出现没有具体值的布尔类型的键:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[mysqld]
|
||||||
|
...
|
||||||
|
skip-host-cache
|
||||||
|
skip-name-resolve
|
||||||
|
```
|
||||||
|
|
||||||
|
默认情况下这被认为是缺失值而无法完成解析,但可以通过高级的加载选项对它们进行处理:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
|
||||||
|
```
|
||||||
|
|
||||||
|
这些键的值永远为 `true`,且在保存到文件时也只会输出键名。
|
||||||
|
|
||||||
|
如果您想要通过程序来生成此类键,则可以使用 `NewBooleanKey`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
key, err := sec.NewBooleanKey("skip-host-cache")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 关于注释
|
||||||
|
|
||||||
|
下述几种情况的内容将被视为注释:
|
||||||
|
|
||||||
|
1. 所有以 `#` 或 `;` 开头的行
|
||||||
|
2. 所有在 `#` 或 `;` 之后的内容
|
||||||
|
3. 分区标签后的文字 (即 `[分区名]` 之后的内容)
|
||||||
|
|
||||||
|
如果你希望使用包含 `#` 或 `;` 的值,请使用 ``` ` ``` 或 ``` """ ``` 进行包覆。
|
||||||
|
|
||||||
### 操作分区(Section)
|
### 操作分区(Section)
|
||||||
|
|
||||||
获取指定分区:
|
获取指定分区:
|
||||||
@ -72,7 +132,7 @@ section, err := cfg.GetSection("")
|
|||||||
当您非常确定某个分区是存在的,可以使用以下简便方法:
|
当您非常确定某个分区是存在的,可以使用以下简便方法:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
section := cfg.Section("")
|
section := cfg.Section("section name")
|
||||||
```
|
```
|
||||||
|
|
||||||
如果不小心判断错了,要获取的分区其实是不存在的,那会发生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。
|
如果不小心判断错了,要获取的分区其实是不存在的,那会发生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。
|
||||||
@ -126,7 +186,7 @@ names := cfg.Section("").KeyStrings()
|
|||||||
获取分区下的所有键值对的克隆:
|
获取分区下的所有键值对的克隆:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
hash := cfg.GetSection("").KeysHash()
|
hash := cfg.Section("").KeysHash()
|
||||||
```
|
```
|
||||||
|
|
||||||
### 操作键值(Value)
|
### 操作键值(Value)
|
||||||
@ -239,6 +299,16 @@ cfg.Section("advance").Key("two_lines").String() // how about continuation lines
|
|||||||
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
||||||
```
|
```
|
||||||
|
|
||||||
|
可是我有时候觉得两行连在一起特别没劲,怎么才能不自动连接两行呢?
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := ini.LoadSources(ini.LoadOptions{
|
||||||
|
IgnoreContinuation: true,
|
||||||
|
}, "filename")
|
||||||
|
```
|
||||||
|
|
||||||
|
哇靠给力啊!
|
||||||
|
|
||||||
需要注意的是,值两侧的单引号会被自动剔除:
|
需要注意的是,值两侧的单引号会被自动剔除:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
@ -339,9 +409,15 @@ cfg.WriteTo(writer)
|
|||||||
cfg.WriteToIndent(writer, "\t")
|
cfg.WriteToIndent(writer, "\t")
|
||||||
```
|
```
|
||||||
|
|
||||||
### 高级用法
|
默认情况下,空格将被用于对齐键值之间的等号以美化输出结果,以下代码可以禁用该功能:
|
||||||
|
|
||||||
#### 递归读取键值
|
```go
|
||||||
|
ini.PrettyFormat = false
|
||||||
|
```
|
||||||
|
|
||||||
|
## 高级用法
|
||||||
|
|
||||||
|
### 递归读取键值
|
||||||
|
|
||||||
在获取所有键值的过程中,特殊语法 `%(<name>)s` 会被应用,其中 `<name>` 可以是相同分区或者默认分区下的键名。字符串 `%(<name>)s` 会被相应的键值所替代,如果指定的键不存在,则会用空字符串替代。您可以最多使用 99 层的递归嵌套。
|
在获取所有键值的过程中,特殊语法 `%(<name>)s` 会被应用,其中 `<name>` 可以是相同分区或者默认分区下的键名。字符串 `%(<name>)s` 会被相应的键值所替代,如果指定的键不存在,则会用空字符串替代。您可以最多使用 99 层的递归嵌套。
|
||||||
|
|
||||||
@ -361,7 +437,7 @@ cfg.Section("author").Key("GITHUB").String() // https://github.com/Unknwon
|
|||||||
cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini
|
cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 读取父子分区
|
### 读取父子分区
|
||||||
|
|
||||||
您可以在分区名称中使用 `.` 来表示两个或多个分区之间的父子关系。如果某个键在子分区中不存在,则会去它的父分区中再次寻找,直到没有父分区为止。
|
您可以在分区名称中使用 `.` 来表示两个或多个分区之间的父子关系。如果某个键在子分区中不存在,则会去它的父分区中再次寻找,直到没有父分区为止。
|
||||||
|
|
||||||
@ -380,7 +456,28 @@ CLONE_URL = https://%(IMPORT_PATH)s
|
|||||||
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 读取自增键名
|
#### 获取上级父分区下的所有键名
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 无法解析的分区
|
||||||
|
|
||||||
|
如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
|
||||||
|
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
|
||||||
|
|
||||||
|
body := cfg.Section("COMMENTS").Body()
|
||||||
|
|
||||||
|
/* --- start ---
|
||||||
|
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
|
||||||
|
------ end --- */
|
||||||
|
```
|
||||||
|
|
||||||
|
### 读取自增键名
|
||||||
|
|
||||||
如果数据源中的键名为 `-`,则认为该键使用了自增键名的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。
|
如果数据源中的键名为 `-`,则认为该键使用了自增键名的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。
|
||||||
|
|
||||||
@ -462,8 +559,8 @@ p := &Person{
|
|||||||
```go
|
```go
|
||||||
type Embeded struct {
|
type Embeded struct {
|
||||||
Dates []time.Time `delim:"|"`
|
Dates []time.Time `delim:"|"`
|
||||||
Places []string
|
Places []string `ini:"places,omitempty"`
|
||||||
None []int
|
None []int `ini:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Author struct {
|
type Author struct {
|
||||||
@ -498,8 +595,7 @@ GPA = 2.8
|
|||||||
|
|
||||||
[Embeded]
|
[Embeded]
|
||||||
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
||||||
Places = HangZhou,Boston
|
places = HangZhou,Boston
|
||||||
None =
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 名称映射器(Name Mapper)
|
#### 名称映射器(Name Mapper)
|
||||||
@ -533,6 +629,26 @@ func main() {
|
|||||||
|
|
||||||
使用函数 `ini.ReflectFromWithMapper` 时也可应用相同的规则。
|
使用函数 `ini.ReflectFromWithMapper` 时也可应用相同的规则。
|
||||||
|
|
||||||
|
#### 值映射器(Value Mapper)
|
||||||
|
|
||||||
|
值映射器允许使用一个自定义函数自动展开值的具体内容,例如:运行时获取环境变量:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Env struct {
|
||||||
|
Foo string `ini:"foo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfg, err := ini.Load([]byte("[env]\nfoo = ${MY_VAR}\n")
|
||||||
|
cfg.ValueMapper = os.ExpandEnv
|
||||||
|
// ...
|
||||||
|
env := &Env{}
|
||||||
|
err = cfg.Section("env").MapTo(env)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
本例中,`env.Foo` 将会是运行时所获取到环境变量 `MY_VAR` 的值。
|
||||||
|
|
||||||
#### 映射/反射的其它说明
|
#### 映射/反射的其它说明
|
||||||
|
|
||||||
任何嵌入的结构都会被默认认作一个不同的分区,并且不会自动产生所谓的父子分区关联:
|
任何嵌入的结构都会被默认认作一个不同的分区,并且不会自动产生所谓的父子分区关联:
|
||||||
|
32
vendor/github.com/go-ini/ini/error.go
generated
vendored
Normal file
32
vendor/github.com/go-ini/ini/error.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2016 Unknwon
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package ini
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ErrDelimiterNotFound struct {
|
||||||
|
Line string
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsErrDelimiterNotFound(err error) bool {
|
||||||
|
_, ok := err.(ErrDelimiterNotFound)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrDelimiterNotFound) Error() string {
|
||||||
|
return fmt.Sprintf("key-value delimiter not found: %s", err.Line)
|
||||||
|
}
|
925
vendor/github.com/go-ini/ini/ini.go
generated
vendored
925
vendor/github.com/go-ini/ini/ini.go
generated
vendored
File diff suppressed because it is too large
Load Diff
633
vendor/github.com/go-ini/ini/key.go
generated
vendored
Normal file
633
vendor/github.com/go-ini/ini/key.go
generated
vendored
Normal file
@ -0,0 +1,633 @@
|
|||||||
|
// Copyright 2014 Unknwon
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package ini
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Key represents a key under a section.
|
||||||
|
type Key struct {
|
||||||
|
s *Section
|
||||||
|
name string
|
||||||
|
value string
|
||||||
|
isAutoIncrement bool
|
||||||
|
isBooleanType bool
|
||||||
|
|
||||||
|
Comment string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
|
||||||
|
type ValueMapper func(string) string
|
||||||
|
|
||||||
|
// Name returns name of key.
|
||||||
|
func (k *Key) Name() string {
|
||||||
|
return k.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns raw value of key for performance purpose.
|
||||||
|
func (k *Key) Value() string {
|
||||||
|
return k.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns string representation of value.
|
||||||
|
func (k *Key) String() string {
|
||||||
|
val := k.value
|
||||||
|
if k.s.f.ValueMapper != nil {
|
||||||
|
val = k.s.f.ValueMapper(val)
|
||||||
|
}
|
||||||
|
if strings.Index(val, "%") == -1 {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < _DEPTH_VALUES; i++ {
|
||||||
|
vr := varPattern.FindString(val)
|
||||||
|
if len(vr) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take off leading '%(' and trailing ')s'.
|
||||||
|
noption := strings.TrimLeft(vr, "%(")
|
||||||
|
noption = strings.TrimRight(noption, ")s")
|
||||||
|
|
||||||
|
// Search in the same section.
|
||||||
|
nk, err := k.s.GetKey(noption)
|
||||||
|
if err != nil {
|
||||||
|
// Search again in default section.
|
||||||
|
nk, _ = k.s.f.Section("").GetKey(noption)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Substitute by new value and take off leading '%(' and trailing ')s'.
|
||||||
|
val = strings.Replace(val, vr, nk.value, -1)
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate accepts a validate function which can
|
||||||
|
// return modifed result as key value.
|
||||||
|
func (k *Key) Validate(fn func(string) string) string {
|
||||||
|
return fn(k.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseBool returns the boolean value represented by the string.
|
||||||
|
//
|
||||||
|
// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On,
|
||||||
|
// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off.
|
||||||
|
// Any other value returns an error.
|
||||||
|
func parseBool(str string) (value bool, err error) {
|
||||||
|
switch str {
|
||||||
|
case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On":
|
||||||
|
return true, nil
|
||||||
|
case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off":
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("parsing \"%s\": invalid syntax", str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool returns bool type value.
|
||||||
|
func (k *Key) Bool() (bool, error) {
|
||||||
|
return parseBool(k.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 returns float64 type value.
|
||||||
|
func (k *Key) Float64() (float64, error) {
|
||||||
|
return strconv.ParseFloat(k.String(), 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int returns int type value.
|
||||||
|
func (k *Key) Int() (int, error) {
|
||||||
|
return strconv.Atoi(k.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 returns int64 type value.
|
||||||
|
func (k *Key) Int64() (int64, error) {
|
||||||
|
return strconv.ParseInt(k.String(), 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint returns uint type valued.
|
||||||
|
func (k *Key) Uint() (uint, error) {
|
||||||
|
u, e := strconv.ParseUint(k.String(), 10, 64)
|
||||||
|
return uint(u), e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 returns uint64 type value.
|
||||||
|
func (k *Key) Uint64() (uint64, error) {
|
||||||
|
return strconv.ParseUint(k.String(), 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration returns time.Duration type value.
|
||||||
|
func (k *Key) Duration() (time.Duration, error) {
|
||||||
|
return time.ParseDuration(k.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeFormat parses with given format and returns time.Time type value.
|
||||||
|
func (k *Key) TimeFormat(format string) (time.Time, error) {
|
||||||
|
return time.Parse(format, k.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time parses with RFC3339 format and returns time.Time type value.
|
||||||
|
func (k *Key) Time() (time.Time, error) {
|
||||||
|
return k.TimeFormat(time.RFC3339)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustString returns default value if key value is empty.
|
||||||
|
func (k *Key) MustString(defaultVal string) string {
|
||||||
|
val := k.String()
|
||||||
|
if len(val) == 0 {
|
||||||
|
k.value = defaultVal
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustBool always returns value without error,
|
||||||
|
// it returns false if error occurs.
|
||||||
|
func (k *Key) MustBool(defaultVal ...bool) bool {
|
||||||
|
val, err := k.Bool()
|
||||||
|
if len(defaultVal) > 0 && err != nil {
|
||||||
|
k.value = strconv.FormatBool(defaultVal[0])
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustFloat64 always returns value without error,
|
||||||
|
// it returns 0.0 if error occurs.
|
||||||
|
func (k *Key) MustFloat64(defaultVal ...float64) float64 {
|
||||||
|
val, err := k.Float64()
|
||||||
|
if len(defaultVal) > 0 && err != nil {
|
||||||
|
k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64)
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustInt always returns value without error,
|
||||||
|
// it returns 0 if error occurs.
|
||||||
|
func (k *Key) MustInt(defaultVal ...int) int {
|
||||||
|
val, err := k.Int()
|
||||||
|
if len(defaultVal) > 0 && err != nil {
|
||||||
|
k.value = strconv.FormatInt(int64(defaultVal[0]), 10)
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustInt64 always returns value without error,
|
||||||
|
// it returns 0 if error occurs.
|
||||||
|
func (k *Key) MustInt64(defaultVal ...int64) int64 {
|
||||||
|
val, err := k.Int64()
|
||||||
|
if len(defaultVal) > 0 && err != nil {
|
||||||
|
k.value = strconv.FormatInt(defaultVal[0], 10)
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustUint always returns value without error,
|
||||||
|
// it returns 0 if error occurs.
|
||||||
|
func (k *Key) MustUint(defaultVal ...uint) uint {
|
||||||
|
val, err := k.Uint()
|
||||||
|
if len(defaultVal) > 0 && err != nil {
|
||||||
|
k.value = strconv.FormatUint(uint64(defaultVal[0]), 10)
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustUint64 always returns value without error,
|
||||||
|
// it returns 0 if error occurs.
|
||||||
|
func (k *Key) MustUint64(defaultVal ...uint64) uint64 {
|
||||||
|
val, err := k.Uint64()
|
||||||
|
if len(defaultVal) > 0 && err != nil {
|
||||||
|
k.value = strconv.FormatUint(defaultVal[0], 10)
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustDuration always returns value without error,
|
||||||
|
// it returns zero value if error occurs.
|
||||||
|
func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration {
|
||||||
|
val, err := k.Duration()
|
||||||
|
if len(defaultVal) > 0 && err != nil {
|
||||||
|
k.value = defaultVal[0].String()
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustTimeFormat always parses with given format and returns value without error,
|
||||||
|
// it returns zero value if error occurs.
|
||||||
|
func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time {
|
||||||
|
val, err := k.TimeFormat(format)
|
||||||
|
if len(defaultVal) > 0 && err != nil {
|
||||||
|
k.value = defaultVal[0].Format(format)
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustTime always parses with RFC3339 format and returns value without error,
|
||||||
|
// it returns zero value if error occurs.
|
||||||
|
func (k *Key) MustTime(defaultVal ...time.Time) time.Time {
|
||||||
|
return k.MustTimeFormat(time.RFC3339, defaultVal...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// In always returns value without error,
|
||||||
|
// it returns default value if error occurs or doesn't fit into candidates.
|
||||||
|
func (k *Key) In(defaultVal string, candidates []string) string {
|
||||||
|
val := k.String()
|
||||||
|
for _, cand := range candidates {
|
||||||
|
if val == cand {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// InFloat64 always returns value without error,
|
||||||
|
// it returns default value if error occurs or doesn't fit into candidates.
|
||||||
|
func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
|
||||||
|
val := k.MustFloat64()
|
||||||
|
for _, cand := range candidates {
|
||||||
|
if val == cand {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// InInt always returns value without error,
|
||||||
|
// it returns default value if error occurs or doesn't fit into candidates.
|
||||||
|
func (k *Key) InInt(defaultVal int, candidates []int) int {
|
||||||
|
val := k.MustInt()
|
||||||
|
for _, cand := range candidates {
|
||||||
|
if val == cand {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// InInt64 always returns value without error,
|
||||||
|
// it returns default value if error occurs or doesn't fit into candidates.
|
||||||
|
func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
|
||||||
|
val := k.MustInt64()
|
||||||
|
for _, cand := range candidates {
|
||||||
|
if val == cand {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// InUint always returns value without error,
|
||||||
|
// it returns default value if error occurs or doesn't fit into candidates.
|
||||||
|
func (k *Key) InUint(defaultVal uint, candidates []uint) uint {
|
||||||
|
val := k.MustUint()
|
||||||
|
for _, cand := range candidates {
|
||||||
|
if val == cand {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// InUint64 always returns value without error,
|
||||||
|
// it returns default value if error occurs or doesn't fit into candidates.
|
||||||
|
func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 {
|
||||||
|
val := k.MustUint64()
|
||||||
|
for _, cand := range candidates {
|
||||||
|
if val == cand {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// InTimeFormat always parses with given format and returns value without error,
|
||||||
|
// it returns default value if error occurs or doesn't fit into candidates.
|
||||||
|
func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time {
|
||||||
|
val := k.MustTimeFormat(format)
|
||||||
|
for _, cand := range candidates {
|
||||||
|
if val == cand {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// InTime always parses with RFC3339 format and returns value without error,
|
||||||
|
// it returns default value if error occurs or doesn't fit into candidates.
|
||||||
|
func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time {
|
||||||
|
return k.InTimeFormat(time.RFC3339, defaultVal, candidates)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeFloat64 checks if value is in given range inclusively,
|
||||||
|
// and returns default value if it's not.
|
||||||
|
func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 {
|
||||||
|
val := k.MustFloat64()
|
||||||
|
if val < min || val > max {
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeInt checks if value is in given range inclusively,
|
||||||
|
// and returns default value if it's not.
|
||||||
|
func (k *Key) RangeInt(defaultVal, min, max int) int {
|
||||||
|
val := k.MustInt()
|
||||||
|
if val < min || val > max {
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeInt64 checks if value is in given range inclusively,
|
||||||
|
// and returns default value if it's not.
|
||||||
|
func (k *Key) RangeInt64(defaultVal, min, max int64) int64 {
|
||||||
|
val := k.MustInt64()
|
||||||
|
if val < min || val > max {
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeTimeFormat checks if value with given format is in given range inclusively,
|
||||||
|
// and returns default value if it's not.
|
||||||
|
func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time {
|
||||||
|
val := k.MustTimeFormat(format)
|
||||||
|
if val.Unix() < min.Unix() || val.Unix() > max.Unix() {
|
||||||
|
return defaultVal
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeTime checks if value with RFC3339 format is in given range inclusively,
|
||||||
|
// and returns default value if it's not.
|
||||||
|
func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time {
|
||||||
|
return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strings returns list of string divided by given delimiter.
|
||||||
|
func (k *Key) Strings(delim string) []string {
|
||||||
|
str := k.String()
|
||||||
|
if len(str) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
vals := strings.Split(str, delim)
|
||||||
|
for i := range vals {
|
||||||
|
vals[i] = strings.TrimSpace(vals[i])
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
|
||||||
|
func (k *Key) Float64s(delim string) []float64 {
|
||||||
|
vals, _ := k.getFloat64s(delim, true, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
|
||||||
|
func (k *Key) Ints(delim string) []int {
|
||||||
|
vals, _ := k.getInts(delim, true, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
|
||||||
|
func (k *Key) Int64s(delim string) []int64 {
|
||||||
|
vals, _ := k.getInt64s(delim, true, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
|
||||||
|
func (k *Key) Uints(delim string) []uint {
|
||||||
|
vals, _ := k.getUints(delim, true, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
|
||||||
|
func (k *Key) Uint64s(delim string) []uint64 {
|
||||||
|
vals, _ := k.getUint64s(delim, true, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
||||||
|
// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
|
||||||
|
func (k *Key) TimesFormat(format, delim string) []time.Time {
|
||||||
|
vals, _ := k.getTimesFormat(format, delim, true, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter.
|
||||||
|
// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
|
||||||
|
func (k *Key) Times(delim string) []time.Time {
|
||||||
|
return k.TimesFormat(time.RFC3339, delim)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
|
||||||
|
// it will not be included to result list.
|
||||||
|
func (k *Key) ValidFloat64s(delim string) []float64 {
|
||||||
|
vals, _ := k.getFloat64s(delim, false, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
|
||||||
|
// not be included to result list.
|
||||||
|
func (k *Key) ValidInts(delim string) []int {
|
||||||
|
vals, _ := k.getInts(delim, false, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
|
||||||
|
// then it will not be included to result list.
|
||||||
|
func (k *Key) ValidInt64s(delim string) []int64 {
|
||||||
|
vals, _ := k.getInt64s(delim, false, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
|
||||||
|
// then it will not be included to result list.
|
||||||
|
func (k *Key) ValidUints(delim string) []uint {
|
||||||
|
vals, _ := k.getUints(delim, false, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
|
||||||
|
// integer, then it will not be included to result list.
|
||||||
|
func (k *Key) ValidUint64s(delim string) []uint64 {
|
||||||
|
vals, _ := k.getUint64s(delim, false, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
||||||
|
func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
|
||||||
|
vals, _ := k.getTimesFormat(format, delim, false, false)
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter.
|
||||||
|
func (k *Key) ValidTimes(delim string) []time.Time {
|
||||||
|
return k.ValidTimesFormat(time.RFC3339, delim)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
|
||||||
|
func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
|
||||||
|
return k.getFloat64s(delim, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictInts returns list of int divided by given delimiter or error on first invalid input.
|
||||||
|
func (k *Key) StrictInts(delim string) ([]int, error) {
|
||||||
|
return k.getInts(delim, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
|
||||||
|
func (k *Key) StrictInt64s(delim string) ([]int64, error) {
|
||||||
|
return k.getInt64s(delim, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictUints returns list of uint divided by given delimiter or error on first invalid input.
|
||||||
|
func (k *Key) StrictUints(delim string) ([]uint, error) {
|
||||||
|
return k.getUints(delim, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
|
||||||
|
func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
|
||||||
|
return k.getUint64s(delim, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
|
||||||
|
// or error on first invalid input.
|
||||||
|
func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
|
||||||
|
return k.getTimesFormat(format, delim, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
|
||||||
|
// or error on first invalid input.
|
||||||
|
func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
|
||||||
|
return k.StrictTimesFormat(time.RFC3339, delim)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getFloat64s returns list of float64 divided by given delimiter.
|
||||||
|
func (k *Key) getFloat64s(delim string, addInvalid, returnOnInvalid bool) ([]float64, error) {
|
||||||
|
strs := k.Strings(delim)
|
||||||
|
vals := make([]float64, 0, len(strs))
|
||||||
|
for _, str := range strs {
|
||||||
|
val, err := strconv.ParseFloat(str, 64)
|
||||||
|
if err != nil && returnOnInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err == nil || addInvalid {
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getInts returns list of int divided by given delimiter.
|
||||||
|
func (k *Key) getInts(delim string, addInvalid, returnOnInvalid bool) ([]int, error) {
|
||||||
|
strs := k.Strings(delim)
|
||||||
|
vals := make([]int, 0, len(strs))
|
||||||
|
for _, str := range strs {
|
||||||
|
val, err := strconv.Atoi(str)
|
||||||
|
if err != nil && returnOnInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err == nil || addInvalid {
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getInt64s returns list of int64 divided by given delimiter.
|
||||||
|
func (k *Key) getInt64s(delim string, addInvalid, returnOnInvalid bool) ([]int64, error) {
|
||||||
|
strs := k.Strings(delim)
|
||||||
|
vals := make([]int64, 0, len(strs))
|
||||||
|
for _, str := range strs {
|
||||||
|
val, err := strconv.ParseInt(str, 10, 64)
|
||||||
|
if err != nil && returnOnInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err == nil || addInvalid {
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getUints returns list of uint divided by given delimiter.
|
||||||
|
func (k *Key) getUints(delim string, addInvalid, returnOnInvalid bool) ([]uint, error) {
|
||||||
|
strs := k.Strings(delim)
|
||||||
|
vals := make([]uint, 0, len(strs))
|
||||||
|
for _, str := range strs {
|
||||||
|
val, err := strconv.ParseUint(str, 10, 0)
|
||||||
|
if err != nil && returnOnInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err == nil || addInvalid {
|
||||||
|
vals = append(vals, uint(val))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getUint64s returns list of uint64 divided by given delimiter.
|
||||||
|
func (k *Key) getUint64s(delim string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
|
||||||
|
strs := k.Strings(delim)
|
||||||
|
vals := make([]uint64, 0, len(strs))
|
||||||
|
for _, str := range strs {
|
||||||
|
val, err := strconv.ParseUint(str, 10, 64)
|
||||||
|
if err != nil && returnOnInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err == nil || addInvalid {
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
||||||
|
func (k *Key) getTimesFormat(format, delim string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
|
||||||
|
strs := k.Strings(delim)
|
||||||
|
vals := make([]time.Time, 0, len(strs))
|
||||||
|
for _, str := range strs {
|
||||||
|
val, err := time.Parse(format, str)
|
||||||
|
if err != nil && returnOnInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err == nil || addInvalid {
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetValue changes key value.
|
||||||
|
func (k *Key) SetValue(v string) {
|
||||||
|
if k.s.f.BlockMode {
|
||||||
|
k.s.f.lock.Lock()
|
||||||
|
defer k.s.f.lock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
k.value = v
|
||||||
|
k.s.keysHash[k.name] = v
|
||||||
|
}
|
73
vendor/github.com/go-ini/ini/parser.go
generated
vendored
73
vendor/github.com/go-ini/ini/parser.go
generated
vendored
@ -48,16 +48,31 @@ func newParser(r io.Reader) *parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOM handles header of BOM-UTF8 format.
|
// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format.
|
||||||
// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
|
// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
|
||||||
func (p *parser) BOM() error {
|
func (p *parser) BOM() error {
|
||||||
mask, err := p.buf.Peek(3)
|
mask, err := p.buf.Peek(2)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
return err
|
return err
|
||||||
} else if len(mask) < 3 {
|
} else if len(mask) < 2 {
|
||||||
return nil
|
return nil
|
||||||
} else if mask[0] == 239 && mask[1] == 187 && mask[2] == 191 {
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case mask[0] == 254 && mask[1] == 255:
|
||||||
|
fallthrough
|
||||||
|
case mask[0] == 255 && mask[1] == 254:
|
||||||
p.buf.Read(mask)
|
p.buf.Read(mask)
|
||||||
|
case mask[0] == 239 && mask[1] == 187:
|
||||||
|
mask, err := p.buf.Peek(3)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
} else if len(mask) < 3 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if mask[2] == 191 {
|
||||||
|
p.buf.Read(mask)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -111,7 +126,7 @@ func readKeyName(in []byte) (string, int, error) {
|
|||||||
// Find key-value delimiter
|
// Find key-value delimiter
|
||||||
i := strings.IndexAny(line[pos+startIdx:], "=:")
|
i := strings.IndexAny(line[pos+startIdx:], "=:")
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return "", -1, fmt.Errorf("key-value delimiter not found: %s", line)
|
return "", -1, ErrDelimiterNotFound{line}
|
||||||
}
|
}
|
||||||
endIdx = pos + i
|
endIdx = pos + i
|
||||||
return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
|
return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
|
||||||
@ -119,7 +134,7 @@ func readKeyName(in []byte) (string, int, error) {
|
|||||||
|
|
||||||
endIdx = strings.IndexAny(line, "=:")
|
endIdx = strings.IndexAny(line, "=:")
|
||||||
if endIdx < 0 {
|
if endIdx < 0 {
|
||||||
return "", -1, fmt.Errorf("key-value delimiter not found: %s", line)
|
return "", -1, ErrDelimiterNotFound{line}
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
|
return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
|
||||||
}
|
}
|
||||||
@ -178,7 +193,7 @@ func hasSurroundedQuote(in string, quote byte) bool {
|
|||||||
strings.IndexByte(in[1:], quote) == len(in)-2
|
strings.IndexByte(in[1:], quote) == len(in)-2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) readValue(in []byte) (string, error) {
|
func (p *parser) readValue(in []byte, ignoreContinuation bool) (string, error) {
|
||||||
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
|
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
@ -205,8 +220,8 @@ func (p *parser) readValue(in []byte) (string, error) {
|
|||||||
// Won't be able to reach here if value only contains whitespace.
|
// Won't be able to reach here if value only contains whitespace.
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
|
|
||||||
// Check continuation lines
|
// Check continuation lines when desired.
|
||||||
if line[len(line)-1] == '\\' {
|
if !ignoreContinuation && line[len(line)-1] == '\\' {
|
||||||
return p.readContinuationLines(line[:len(line)-1])
|
return p.readContinuationLines(line[:len(line)-1])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +250,7 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
section, _ := f.NewSection(DEFAULT_SECTION)
|
section, _ := f.NewSection(DEFAULT_SECTION)
|
||||||
|
|
||||||
var line []byte
|
var line []byte
|
||||||
|
var inUnparseableSection bool
|
||||||
for !p.isEOF {
|
for !p.isEOF {
|
||||||
line, err = p.readUntil('\n')
|
line, err = p.readUntil('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -258,12 +274,14 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
// Section
|
// Section
|
||||||
if line[0] == '[' {
|
if line[0] == '[' {
|
||||||
// Read to the next ']' (TODO: support quoted strings)
|
// Read to the next ']' (TODO: support quoted strings)
|
||||||
closeIdx := bytes.IndexByte(line, ']')
|
// TODO(unknwon): use LastIndexByte when stop supporting Go1.4
|
||||||
|
closeIdx := bytes.LastIndex(line, []byte("]"))
|
||||||
if closeIdx == -1 {
|
if closeIdx == -1 {
|
||||||
return fmt.Errorf("unclosed section: %s", line)
|
return fmt.Errorf("unclosed section: %s", line)
|
||||||
}
|
}
|
||||||
|
|
||||||
section, err = f.NewSection(string(line[1:closeIdx]))
|
name := string(line[1:closeIdx])
|
||||||
|
section, err = f.NewSection(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -278,11 +296,40 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
// Reset aotu-counter and comments
|
// Reset aotu-counter and comments
|
||||||
p.comment.Reset()
|
p.comment.Reset()
|
||||||
p.count = 1
|
p.count = 1
|
||||||
|
|
||||||
|
inUnparseableSection = false
|
||||||
|
for i := range f.options.UnparseableSections {
|
||||||
|
if f.options.UnparseableSections[i] == name ||
|
||||||
|
(f.options.Insensitive && strings.ToLower(f.options.UnparseableSections[i]) == strings.ToLower(name)) {
|
||||||
|
inUnparseableSection = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if inUnparseableSection {
|
||||||
|
section.isRawSection = true
|
||||||
|
section.rawBody += string(line)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
kname, offset, err := readKeyName(line)
|
kname, offset, err := readKeyName(line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Treat as boolean key when desired, and whole line is key name.
|
||||||
|
if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys {
|
||||||
|
kname, err := p.readValue(line, f.options.IgnoreContinuation)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
key, err := section.NewBooleanKey(kname)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
key.Comment = strings.TrimSpace(p.comment.String())
|
||||||
|
p.comment.Reset()
|
||||||
|
continue
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,9 +345,9 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key.isAutoIncr = isAutoIncr
|
key.isAutoIncrement = isAutoIncr
|
||||||
|
|
||||||
value, err := p.readValue(line[offset:])
|
value, err := p.readValue(line[offset:], f.options.IgnoreContinuation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
232
vendor/github.com/go-ini/ini/section.go
generated
vendored
Normal file
232
vendor/github.com/go-ini/ini/section.go
generated
vendored
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
// Copyright 2014 Unknwon
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package ini
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Section represents a config section.
|
||||||
|
type Section struct {
|
||||||
|
f *File
|
||||||
|
Comment string
|
||||||
|
name string
|
||||||
|
keys map[string]*Key
|
||||||
|
keyList []string
|
||||||
|
keysHash map[string]string
|
||||||
|
|
||||||
|
isRawSection bool
|
||||||
|
rawBody string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSection(f *File, name string) *Section {
|
||||||
|
return &Section{
|
||||||
|
f: f,
|
||||||
|
name: name,
|
||||||
|
keys: make(map[string]*Key),
|
||||||
|
keyList: make([]string, 0, 10),
|
||||||
|
keysHash: make(map[string]string),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns name of Section.
|
||||||
|
func (s *Section) Name() string {
|
||||||
|
return s.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body returns rawBody of Section if the section was marked as unparseable.
|
||||||
|
// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
|
||||||
|
func (s *Section) Body() string {
|
||||||
|
return strings.TrimSpace(s.rawBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKey creates a new key to given section.
|
||||||
|
func (s *Section) NewKey(name, val string) (*Key, error) {
|
||||||
|
if len(name) == 0 {
|
||||||
|
return nil, errors.New("error creating new key: empty key name")
|
||||||
|
} else if s.f.options.Insensitive {
|
||||||
|
name = strings.ToLower(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.f.BlockMode {
|
||||||
|
s.f.lock.Lock()
|
||||||
|
defer s.f.lock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if inSlice(name, s.keyList) {
|
||||||
|
s.keys[name].value = val
|
||||||
|
return s.keys[name], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s.keyList = append(s.keyList, name)
|
||||||
|
s.keys[name] = &Key{
|
||||||
|
s: s,
|
||||||
|
name: name,
|
||||||
|
value: val,
|
||||||
|
}
|
||||||
|
s.keysHash[name] = val
|
||||||
|
return s.keys[name], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBooleanKey creates a new boolean type key to given section.
|
||||||
|
func (s *Section) NewBooleanKey(name string) (*Key, error) {
|
||||||
|
key, err := s.NewKey(name, "true")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
key.isBooleanType = true
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetKey returns key in section by given name.
|
||||||
|
func (s *Section) GetKey(name string) (*Key, error) {
|
||||||
|
// FIXME: change to section level lock?
|
||||||
|
if s.f.BlockMode {
|
||||||
|
s.f.lock.RLock()
|
||||||
|
}
|
||||||
|
if s.f.options.Insensitive {
|
||||||
|
name = strings.ToLower(name)
|
||||||
|
}
|
||||||
|
key := s.keys[name]
|
||||||
|
if s.f.BlockMode {
|
||||||
|
s.f.lock.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == nil {
|
||||||
|
// Check if it is a child-section.
|
||||||
|
sname := s.name
|
||||||
|
for {
|
||||||
|
if i := strings.LastIndex(sname, "."); i > -1 {
|
||||||
|
sname = sname[:i]
|
||||||
|
sec, err := s.f.GetSection(sname)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return sec.GetKey(name)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
|
||||||
|
}
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasKey returns true if section contains a key with given name.
|
||||||
|
func (s *Section) HasKey(name string) bool {
|
||||||
|
key, _ := s.GetKey(name)
|
||||||
|
return key != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Haskey is a backwards-compatible name for HasKey.
|
||||||
|
func (s *Section) Haskey(name string) bool {
|
||||||
|
return s.HasKey(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasValue returns true if section contains given raw value.
|
||||||
|
func (s *Section) HasValue(value string) bool {
|
||||||
|
if s.f.BlockMode {
|
||||||
|
s.f.lock.RLock()
|
||||||
|
defer s.f.lock.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range s.keys {
|
||||||
|
if value == k.value {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key assumes named Key exists in section and returns a zero-value when not.
|
||||||
|
func (s *Section) Key(name string) *Key {
|
||||||
|
key, err := s.GetKey(name)
|
||||||
|
if err != nil {
|
||||||
|
// It's OK here because the only possible error is empty key name,
|
||||||
|
// but if it's empty, this piece of code won't be executed.
|
||||||
|
key, _ = s.NewKey(name, "")
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns list of keys of section.
|
||||||
|
func (s *Section) Keys() []*Key {
|
||||||
|
keys := make([]*Key, len(s.keyList))
|
||||||
|
for i := range s.keyList {
|
||||||
|
keys[i] = s.Key(s.keyList[i])
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentKeys returns list of keys of parent section.
|
||||||
|
func (s *Section) ParentKeys() []*Key {
|
||||||
|
var parentKeys []*Key
|
||||||
|
sname := s.name
|
||||||
|
for {
|
||||||
|
if i := strings.LastIndex(sname, "."); i > -1 {
|
||||||
|
sname = sname[:i]
|
||||||
|
sec, err := s.f.GetSection(sname)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parentKeys = append(parentKeys, sec.Keys()...)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return parentKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyStrings returns list of key names of section.
|
||||||
|
func (s *Section) KeyStrings() []string {
|
||||||
|
list := make([]string, len(s.keyList))
|
||||||
|
copy(list, s.keyList)
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeysHash returns keys hash consisting of names and values.
|
||||||
|
func (s *Section) KeysHash() map[string]string {
|
||||||
|
if s.f.BlockMode {
|
||||||
|
s.f.lock.RLock()
|
||||||
|
defer s.f.lock.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := map[string]string{}
|
||||||
|
for key, value := range s.keysHash {
|
||||||
|
hash[key] = value
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteKey deletes a key from section.
|
||||||
|
func (s *Section) DeleteKey(name string) {
|
||||||
|
if s.f.BlockMode {
|
||||||
|
s.f.lock.Lock()
|
||||||
|
defer s.f.lock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, k := range s.keyList {
|
||||||
|
if k == name {
|
||||||
|
s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
|
||||||
|
delete(s.keys, name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
186
vendor/github.com/go-ini/ini/struct.go
generated
vendored
186
vendor/github.com/go-ini/ini/struct.go
generated
vendored
@ -19,6 +19,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
@ -76,6 +77,59 @@ func parseDelim(actual string) string {
|
|||||||
|
|
||||||
var reflectTime = reflect.TypeOf(time.Now()).Kind()
|
var reflectTime = reflect.TypeOf(time.Now()).Kind()
|
||||||
|
|
||||||
|
// setSliceWithProperType sets proper values to slice based on its type.
|
||||||
|
func setSliceWithProperType(key *Key, field reflect.Value, delim string) error {
|
||||||
|
strs := key.Strings(delim)
|
||||||
|
numVals := len(strs)
|
||||||
|
if numVals == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var vals interface{}
|
||||||
|
|
||||||
|
sliceOf := field.Type().Elem().Kind()
|
||||||
|
switch sliceOf {
|
||||||
|
case reflect.String:
|
||||||
|
vals = strs
|
||||||
|
case reflect.Int:
|
||||||
|
vals = key.Ints(delim)
|
||||||
|
case reflect.Int64:
|
||||||
|
vals = key.Int64s(delim)
|
||||||
|
case reflect.Uint:
|
||||||
|
vals = key.Uints(delim)
|
||||||
|
case reflect.Uint64:
|
||||||
|
vals = key.Uint64s(delim)
|
||||||
|
case reflect.Float64:
|
||||||
|
vals = key.Float64s(delim)
|
||||||
|
case reflectTime:
|
||||||
|
vals = key.Times(delim)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported type '[]%s'", sliceOf)
|
||||||
|
}
|
||||||
|
|
||||||
|
slice := reflect.MakeSlice(field.Type(), numVals, numVals)
|
||||||
|
for i := 0; i < numVals; i++ {
|
||||||
|
switch sliceOf {
|
||||||
|
case reflect.String:
|
||||||
|
slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i]))
|
||||||
|
case reflect.Int:
|
||||||
|
slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i]))
|
||||||
|
case reflect.Int64:
|
||||||
|
slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i]))
|
||||||
|
case reflect.Uint:
|
||||||
|
slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i]))
|
||||||
|
case reflect.Uint64:
|
||||||
|
slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
|
||||||
|
case reflect.Float64:
|
||||||
|
slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
|
||||||
|
case reflectTime:
|
||||||
|
slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
field.Set(slice)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// setWithProperType sets proper value to field based on its type,
|
// setWithProperType sets proper value to field based on its type,
|
||||||
// but it does not return error for failing parsing,
|
// but it does not return error for failing parsing,
|
||||||
// because we want to use default value that is already assigned to strcut.
|
// because we want to use default value that is already assigned to strcut.
|
||||||
@ -108,7 +162,8 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
|
|||||||
// byte is an alias for uint8, so supporting uint8 breaks support for byte
|
// byte is an alias for uint8, so supporting uint8 breaks support for byte
|
||||||
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
durationVal, err := key.Duration()
|
durationVal, err := key.Duration()
|
||||||
if err == nil {
|
// Skip zero value
|
||||||
|
if err == nil && int(durationVal) > 0 {
|
||||||
field.Set(reflect.ValueOf(durationVal))
|
field.Set(reflect.ValueOf(durationVal))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -119,7 +174,7 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
|
|||||||
}
|
}
|
||||||
field.SetUint(uintVal)
|
field.SetUint(uintVal)
|
||||||
|
|
||||||
case reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
floatVal, err := key.Float64()
|
floatVal, err := key.Float64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@ -132,29 +187,7 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
|
|||||||
}
|
}
|
||||||
field.Set(reflect.ValueOf(timeVal))
|
field.Set(reflect.ValueOf(timeVal))
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
vals := key.Strings(delim)
|
return setSliceWithProperType(key, field, delim)
|
||||||
numVals := len(vals)
|
|
||||||
if numVals == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sliceOf := field.Type().Elem().Kind()
|
|
||||||
|
|
||||||
var times []time.Time
|
|
||||||
if sliceOf == reflectTime {
|
|
||||||
times = key.Times(delim)
|
|
||||||
}
|
|
||||||
|
|
||||||
slice := reflect.MakeSlice(field.Type(), numVals, numVals)
|
|
||||||
for i := 0; i < numVals; i++ {
|
|
||||||
switch sliceOf {
|
|
||||||
case reflectTime:
|
|
||||||
slice.Index(i).Set(reflect.ValueOf(times[i]))
|
|
||||||
default:
|
|
||||||
slice.Index(i).Set(reflect.ValueOf(vals[i]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
field.Set(slice)
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported type '%s'", t)
|
return fmt.Errorf("unsupported type '%s'", t)
|
||||||
}
|
}
|
||||||
@ -176,7 +209,8 @@ func (s *Section) mapTo(val reflect.Value) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldName := s.parseFieldName(tpField.Name, tag)
|
opts := strings.SplitN(tag, ",", 2) // strip off possible omitempty
|
||||||
|
fieldName := s.parseFieldName(tpField.Name, opts[0])
|
||||||
if len(fieldName) == 0 || !field.CanSet() {
|
if len(fieldName) == 0 || !field.CanSet() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -239,40 +273,81 @@ func MapTo(v, source interface{}, others ...interface{}) error {
|
|||||||
return MapToWithMapper(v, nil, source, others...)
|
return MapToWithMapper(v, nil, source, others...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reflectWithProperType does the opposite thing with setWithProperType.
|
// reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
|
||||||
|
func reflectSliceWithProperType(key *Key, field reflect.Value, delim string) error {
|
||||||
|
slice := field.Slice(0, field.Len())
|
||||||
|
if field.Len() == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
sliceOf := field.Type().Elem().Kind()
|
||||||
|
for i := 0; i < field.Len(); i++ {
|
||||||
|
switch sliceOf {
|
||||||
|
case reflect.String:
|
||||||
|
buf.WriteString(slice.Index(i).String())
|
||||||
|
case reflect.Int, reflect.Int64:
|
||||||
|
buf.WriteString(fmt.Sprint(slice.Index(i).Int()))
|
||||||
|
case reflect.Uint, reflect.Uint64:
|
||||||
|
buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
|
||||||
|
case reflect.Float64:
|
||||||
|
buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
|
||||||
|
case reflectTime:
|
||||||
|
buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported type '[]%s'", sliceOf)
|
||||||
|
}
|
||||||
|
buf.WriteString(delim)
|
||||||
|
}
|
||||||
|
key.SetValue(buf.String()[:buf.Len()-1])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// reflectWithProperType does the opposite thing as setWithProperType.
|
||||||
func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error {
|
func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error {
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
key.SetValue(field.String())
|
key.SetValue(field.String())
|
||||||
case reflect.Bool,
|
case reflect.Bool:
|
||||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
key.SetValue(fmt.Sprint(field.Bool()))
|
||||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
reflect.Float64,
|
key.SetValue(fmt.Sprint(field.Int()))
|
||||||
reflectTime:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
key.SetValue(fmt.Sprint(field))
|
key.SetValue(fmt.Sprint(field.Uint()))
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
key.SetValue(fmt.Sprint(field.Float()))
|
||||||
|
case reflectTime:
|
||||||
|
key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
vals := field.Slice(0, field.Len())
|
return reflectSliceWithProperType(key, field, delim)
|
||||||
if field.Len() == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
isTime := fmt.Sprint(field.Type()) == "[]time.Time"
|
|
||||||
for i := 0; i < field.Len(); i++ {
|
|
||||||
if isTime {
|
|
||||||
buf.WriteString(vals.Index(i).Interface().(time.Time).Format(time.RFC3339))
|
|
||||||
} else {
|
|
||||||
buf.WriteString(fmt.Sprint(vals.Index(i)))
|
|
||||||
}
|
|
||||||
buf.WriteString(delim)
|
|
||||||
}
|
|
||||||
key.SetValue(buf.String()[:buf.Len()-1])
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported type '%s'", t)
|
return fmt.Errorf("unsupported type '%s'", t)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CR: copied from encoding/json/encode.go with modifications of time.Time support.
|
||||||
|
// TODO: add more test coverage.
|
||||||
|
func isEmptyValue(v reflect.Value) bool {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Bool:
|
||||||
|
return !v.Bool()
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return v.Int() == 0
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return v.Uint() == 0
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v.Float() == 0
|
||||||
|
case reflectTime:
|
||||||
|
return v.Interface().(time.Time).IsZero()
|
||||||
|
case reflect.Interface, reflect.Ptr:
|
||||||
|
return v.IsNil()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Section) reflectFrom(val reflect.Value) error {
|
func (s *Section) reflectFrom(val reflect.Value) error {
|
||||||
if val.Kind() == reflect.Ptr {
|
if val.Kind() == reflect.Ptr {
|
||||||
val = val.Elem()
|
val = val.Elem()
|
||||||
@ -288,13 +363,18 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldName := s.parseFieldName(tpField.Name, tag)
|
opts := strings.SplitN(tag, ",", 2)
|
||||||
|
if len(opts) == 2 && opts[1] == "omitempty" && isEmptyValue(field) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldName := s.parseFieldName(tpField.Name, opts[0])
|
||||||
if len(fieldName) == 0 || !field.CanSet() {
|
if len(fieldName) == 0 || !field.CanSet() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) ||
|
if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) ||
|
||||||
(tpField.Type.Kind() == reflect.Struct) {
|
(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
|
||||||
// Note: The only error here is section doesn't exist.
|
// Note: The only error here is section doesn't exist.
|
||||||
sec, err := s.f.GetSection(fieldName)
|
sec, err := s.f.GetSection(fieldName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -302,7 +382,7 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
|||||||
sec, _ = s.f.NewSection(fieldName)
|
sec, _ = s.f.NewSection(fieldName)
|
||||||
}
|
}
|
||||||
if err = sec.reflectFrom(field); err != nil {
|
if err = sec.reflectFrom(field); err != nil {
|
||||||
return fmt.Errorf("error reflecting field(%s): %v", fieldName, err)
|
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -313,7 +393,7 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
|||||||
key, _ = s.NewKey(fieldName, "")
|
key, _ = s.NewKey(fieldName, "")
|
||||||
}
|
}
|
||||||
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
|
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
|
||||||
return fmt.Errorf("error reflecting field(%s): %v", fieldName, err)
|
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
10
vendor/github.com/google/go-querystring/query/encode.go
generated
vendored
10
vendor/github.com/google/go-querystring/query/encode.go
generated
vendored
@ -217,11 +217,6 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if sv.Type() == timeType {
|
|
||||||
values.Add(name, valueString(sv, opts))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for sv.Kind() == reflect.Ptr {
|
for sv.Kind() == reflect.Ptr {
|
||||||
if sv.IsNil() {
|
if sv.IsNil() {
|
||||||
break
|
break
|
||||||
@ -229,6 +224,11 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error {
|
|||||||
sv = sv.Elem()
|
sv = sv.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sv.Type() == timeType {
|
||||||
|
values.Add(name, valueString(sv, opts))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if sv.Kind() == reflect.Struct {
|
if sv.Kind() == reflect.Struct {
|
||||||
reflectValue(values, sv, name)
|
reflectValue(values, sv, name)
|
||||||
continue
|
continue
|
||||||
|
2
vendor/github.com/jmespath/go-jmespath/.gitignore
generated
vendored
2
vendor/github.com/jmespath/go-jmespath/.gitignore
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
jpgo
|
/jpgo
|
||||||
jmespath-fuzz.zip
|
jmespath-fuzz.zip
|
||||||
cpu.out
|
cpu.out
|
||||||
go-jmespath.test
|
go-jmespath.test
|
||||||
|
51
vendor/github.com/pkg/sftp/client.go
generated
vendored
51
vendor/github.com/pkg/sftp/client.go
generated
vendored
@ -495,7 +495,7 @@ func (c *Client) Remove(path string) error {
|
|||||||
// some servers, *cough* osx *cough*, return EPERM, not ENODIR.
|
// some servers, *cough* osx *cough*, return EPERM, not ENODIR.
|
||||||
// serv-u returns ssh_FX_FILE_IS_A_DIRECTORY
|
// serv-u returns ssh_FX_FILE_IS_A_DIRECTORY
|
||||||
case ssh_FX_PERMISSION_DENIED, ssh_FX_FAILURE, ssh_FX_FILE_IS_A_DIRECTORY:
|
case ssh_FX_PERMISSION_DENIED, ssh_FX_FAILURE, ssh_FX_FILE_IS_A_DIRECTORY:
|
||||||
return c.removeDirectory(path)
|
return c.RemoveDirectory(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -518,7 +518,8 @@ func (c *Client) removeFile(path string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) removeDirectory(path string) error {
|
// RemoveDirectory removes a directory path.
|
||||||
|
func (c *Client) RemoveDirectory(path string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(sshFxpRmdirPacket{
|
typ, data, err := c.sendPacket(sshFxpRmdirPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
@ -652,7 +653,7 @@ func (f *File) Read(b []byte) (int, error) {
|
|||||||
inFlight := 0
|
inFlight := 0
|
||||||
desiredInFlight := 1
|
desiredInFlight := 1
|
||||||
offset := f.offset
|
offset := f.offset
|
||||||
ch := make(chan result, 1)
|
ch := make(chan result, 2)
|
||||||
type inflightRead struct {
|
type inflightRead struct {
|
||||||
b []byte
|
b []byte
|
||||||
offset uint64
|
offset uint64
|
||||||
@ -751,7 +752,7 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
|||||||
offset := f.offset
|
offset := f.offset
|
||||||
writeOffset := offset
|
writeOffset := offset
|
||||||
fileSize := uint64(fi.Size())
|
fileSize := uint64(fi.Size())
|
||||||
ch := make(chan result, 1)
|
ch := make(chan result, 2)
|
||||||
type inflightRead struct {
|
type inflightRead struct {
|
||||||
b []byte
|
b []byte
|
||||||
offset uint64
|
offset uint64
|
||||||
@ -778,16 +779,21 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
|||||||
|
|
||||||
var copied int64
|
var copied int64
|
||||||
for firstErr.err == nil || inFlight > 0 {
|
for firstErr.err == nil || inFlight > 0 {
|
||||||
for inFlight < desiredInFlight && firstErr.err == nil {
|
if firstErr.err == nil {
|
||||||
b := make([]byte, f.c.maxPacket)
|
for inFlight+len(pendingWrites) < desiredInFlight {
|
||||||
sendReq(b, offset)
|
b := make([]byte, f.c.maxPacket)
|
||||||
offset += uint64(f.c.maxPacket)
|
sendReq(b, offset)
|
||||||
if offset > fileSize {
|
offset += uint64(f.c.maxPacket)
|
||||||
desiredInFlight = 1
|
if offset > fileSize {
|
||||||
|
desiredInFlight = 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if inFlight == 0 {
|
if inFlight == 0 {
|
||||||
|
if firstErr.err == nil && len(pendingWrites) > 0 {
|
||||||
|
return copied, errors.New("internal inconsistency")
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
@ -816,6 +822,8 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
|||||||
nbytes, err := w.Write(data)
|
nbytes, err := w.Write(data)
|
||||||
copied += int64(nbytes)
|
copied += int64(nbytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// We will never receive another DATA with offset==writeOffset, so
|
||||||
|
// the loop will drain inFlight and then exit.
|
||||||
firstErr = offsetErr{offset: req.offset + uint64(nbytes), err: err}
|
firstErr = offsetErr{offset: req.offset + uint64(nbytes), err: err}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -830,8 +838,16 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
|||||||
desiredInFlight++
|
desiredInFlight++
|
||||||
}
|
}
|
||||||
writeOffset += uint64(nbytes)
|
writeOffset += uint64(nbytes)
|
||||||
for pendingData, ok := pendingWrites[writeOffset]; ok; pendingData, ok = pendingWrites[writeOffset] {
|
for {
|
||||||
|
pendingData, ok := pendingWrites[writeOffset]
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Give go a chance to free the memory.
|
||||||
|
delete(pendingWrites, writeOffset)
|
||||||
nbytes, err := w.Write(pendingData)
|
nbytes, err := w.Write(pendingData)
|
||||||
|
// Do not move writeOffset on error so subsequent iterations won't trigger
|
||||||
|
// any writes.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
firstErr = offsetErr{offset: writeOffset + uint64(nbytes), err: err}
|
firstErr = offsetErr{offset: writeOffset + uint64(nbytes), err: err}
|
||||||
break
|
break
|
||||||
@ -841,14 +857,12 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
writeOffset += uint64(nbytes)
|
writeOffset += uint64(nbytes)
|
||||||
inFlight--
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Don't write the data yet because
|
// Don't write the data yet because
|
||||||
// this response came in out of order
|
// this response came in out of order
|
||||||
// and we need to wait for responses
|
// and we need to wait for responses
|
||||||
// for earlier segments of the file.
|
// for earlier segments of the file.
|
||||||
inFlight++ // Pending writes should still be considered inFlight.
|
|
||||||
pendingWrites[req.offset] = data
|
pendingWrites[req.offset] = data
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -884,7 +898,8 @@ func (f *File) Write(b []byte) (int, error) {
|
|||||||
inFlight := 0
|
inFlight := 0
|
||||||
desiredInFlight := 1
|
desiredInFlight := 1
|
||||||
offset := f.offset
|
offset := f.offset
|
||||||
ch := make(chan result, 1)
|
// chan must have a buffer of max value of (desiredInFlight - inFlight)
|
||||||
|
ch := make(chan result, 2)
|
||||||
var firstErr error
|
var firstErr error
|
||||||
written := len(b)
|
written := len(b)
|
||||||
for len(b) > 0 || inFlight > 0 {
|
for len(b) > 0 || inFlight > 0 {
|
||||||
@ -947,7 +962,8 @@ func (f *File) ReadFrom(r io.Reader) (int64, error) {
|
|||||||
inFlight := 0
|
inFlight := 0
|
||||||
desiredInFlight := 1
|
desiredInFlight := 1
|
||||||
offset := f.offset
|
offset := f.offset
|
||||||
ch := make(chan result, 1)
|
// chan must have a buffer of max value of (desiredInFlight - inFlight)
|
||||||
|
ch := make(chan result, 2)
|
||||||
var firstErr error
|
var firstErr error
|
||||||
read := int64(0)
|
read := int64(0)
|
||||||
b := make([]byte, f.c.maxPacket)
|
b := make([]byte, f.c.maxPacket)
|
||||||
@ -1081,10 +1097,7 @@ func unmarshalStatus(id uint32, data []byte) error {
|
|||||||
return &unexpectedIDErr{id, sid}
|
return &unexpectedIDErr{id, sid}
|
||||||
}
|
}
|
||||||
code, data := unmarshalUint32(data)
|
code, data := unmarshalUint32(data)
|
||||||
msg, data, err := unmarshalStringSafe(data)
|
msg, data, _ := unmarshalStringSafe(data)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
lang, _, _ := unmarshalStringSafe(data)
|
lang, _, _ := unmarshalStringSafe(data)
|
||||||
return &StatusError{
|
return &StatusError{
|
||||||
Code: code,
|
Code: code,
|
||||||
|
5
vendor/github.com/pkg/sftp/conn.go
generated
vendored
5
vendor/github.com/pkg/sftp/conn.go
generated
vendored
@ -14,6 +14,8 @@ type conn struct {
|
|||||||
io.Reader
|
io.Reader
|
||||||
io.WriteCloser
|
io.WriteCloser
|
||||||
sync.Mutex // used to serialise writes to sendPacket
|
sync.Mutex // used to serialise writes to sendPacket
|
||||||
|
// sendPacketTest is needed to replicate packet issues in testing
|
||||||
|
sendPacketTest func(w io.Writer, m encoding.BinaryMarshaler) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) recvPacket() (uint8, []byte, error) {
|
func (c *conn) recvPacket() (uint8, []byte, error) {
|
||||||
@ -23,6 +25,9 @@ func (c *conn) recvPacket() (uint8, []byte, error) {
|
|||||||
func (c *conn) sendPacket(m encoding.BinaryMarshaler) error {
|
func (c *conn) sendPacket(m encoding.BinaryMarshaler) error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
if c.sendPacketTest != nil {
|
||||||
|
return c.sendPacketTest(c, m)
|
||||||
|
}
|
||||||
return sendPacket(c, m)
|
return sendPacket(c, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
vendor/github.com/rfjakob/eme/.travis.yml
generated
vendored
Normal file
1
vendor/github.com/rfjakob/eme/.travis.yml
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
language: go
|
24
vendor/github.com/rfjakob/eme/README.md
generated
vendored
24
vendor/github.com/rfjakob/eme/README.md
generated
vendored
@ -1,13 +1,15 @@
|
|||||||
EME for Go [![Build Status](https://drone.io/github.com/rfjakob/eme/status.png)](https://drone.io/github.com/rfjakob/eme/latest) [![GoDoc](https://godoc.org/github.com/rfjakob/eme?status.svg)](https://godoc.org/github.com/rfjakob/eme) ![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)
|
EME for Go [![Build Status](https://travis-ci.org/rfjakob/eme.svg?branch=master)](https://travis-ci.org/rfjakob/eme) [![GoDoc](https://godoc.org/github.com/rfjakob/eme?status.svg)](https://godoc.org/github.com/rfjakob/eme) ![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)
|
||||||
==========
|
==========
|
||||||
|
|
||||||
EME (ECB-Mix-ECB) is a wide-block encryption mode developed by Halevi
|
**EME** (ECB-Mix-ECB or, clearer, **Encrypt-Mix-Encrypt**) is a wide-block
|
||||||
and Rogaway in 2003 [eme]. (see references below)
|
encryption mode developed by Halevi
|
||||||
|
and Rogaway in 2003 _[eme]_ (square-bracketed italics like _[this]_ are literature references, detailed in the
|
||||||
|
References secion).
|
||||||
|
|
||||||
EME uses multiple invocations of a block cipher to construct a new
|
EME uses multiple invocations of a block cipher to construct a new
|
||||||
cipher of bigger block size (in multiples of 16 bytes, up to 2048 bytes).
|
cipher of bigger block size (in multiples of 16 bytes, up to 2048 bytes).
|
||||||
|
|
||||||
Quoting from the original [eme] paper:
|
Quoting from the original _[eme]_ paper:
|
||||||
|
|
||||||
> We describe a block-cipher mode of operation, EME, that turns an n-bit block cipher into
|
> We describe a block-cipher mode of operation, EME, that turns an n-bit block cipher into
|
||||||
> a tweakable enciphering scheme that acts on strings of mn bits, where m ∈ [1..n]. The mode is
|
> a tweakable enciphering scheme that acts on strings of mn bits, where m ∈ [1..n]. The mode is
|
||||||
@ -16,24 +18,28 @@ Quoting from the original [eme] paper:
|
|||||||
> and a “lightweight mixing” in between. We prove EME secure, in the reduction-based sense of
|
> and a “lightweight mixing” in between. We prove EME secure, in the reduction-based sense of
|
||||||
> modern cryptography.
|
> modern cryptography.
|
||||||
|
|
||||||
|
Figure 2 from the _[eme]_ paper shows an overview of the transformation:
|
||||||
|
|
||||||
|
[![Figure 2 form [eme]](paper-eme-fig2.png)](#)
|
||||||
|
|
||||||
This is an implementation of EME in Go, complete with test vectors from IEEE.
|
This is an implementation of EME in Go, complete with test vectors from IEEE.
|
||||||
|
|
||||||
Is it patentend?
|
Is it patentend?
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
In 2007, the UC Davis has decided to abandon [patabandon] the patent
|
In 2007, the UC Davis has decided to abandon _[patabandon]_ the patent
|
||||||
application for EME [patappl].
|
application for EME _[patappl]_.
|
||||||
|
|
||||||
Related algorithms
|
Related algorithms
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
**EME-32** is EME with the cipher set to AES and the length set to 512.
|
**EME-32** is EME with the cipher set to AES and the length set to 512.
|
||||||
That is, EME-32 [eme-32-pdf] is a subset of EME.
|
That is, EME-32 _[eme-32-pdf]_ is a subset of EME.
|
||||||
|
|
||||||
**EME2**, also known as EME* [emestar], is an extended version of EME
|
**EME2**, also known as EME* _[emestar]_, is an extended version of EME
|
||||||
that has built-in handling for data that is not a multiple of 16 bytes
|
that has built-in handling for data that is not a multiple of 16 bytes
|
||||||
long.
|
long.
|
||||||
EME2 has been selected for standardization in IEEE P1619.2 [p1619.2].
|
EME2 has been selected for standardization in IEEE P1619.2 _[p1619.2]_.
|
||||||
|
|
||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
|
BIN
vendor/github.com/rfjakob/eme/paper-eme-fig2.png
generated
vendored
Normal file
BIN
vendor/github.com/rfjakob/eme/paper-eme-fig2.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
9
vendor/github.com/russross/blackfriday/README.md
generated
vendored
9
vendor/github.com/russross/blackfriday/README.md
generated
vendored
@ -169,6 +169,15 @@ implements the following extensions:
|
|||||||
You can use 3 or more backticks to mark the beginning of the
|
You can use 3 or more backticks to mark the beginning of the
|
||||||
block, and the same number to mark the end of the block.
|
block, and the same number to mark the end of the block.
|
||||||
|
|
||||||
|
To preserve classes of fenced code blocks while using the bluemonday
|
||||||
|
HTML sanitizer, use the following policy:
|
||||||
|
|
||||||
|
``` go
|
||||||
|
p := bluemonday.UGCPolicy()
|
||||||
|
p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code")
|
||||||
|
html := p.SanitizeBytes(unsafe)
|
||||||
|
```
|
||||||
|
|
||||||
* **Definition lists**. A simple definition list is made of a single-line
|
* **Definition lists**. A simple definition list is made of a single-line
|
||||||
term followed by a colon and the definition for that term.
|
term followed by a colon and the definition for that term.
|
||||||
|
|
||||||
|
6
vendor/github.com/russross/blackfriday/block.go
generated
vendored
6
vendor/github.com/russross/blackfriday/block.go
generated
vendored
@ -1244,6 +1244,12 @@ gatherlines:
|
|||||||
line = i
|
line = i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If reached end of data, the Renderer.ListItem call we're going to make below
|
||||||
|
// is definitely the last in the list.
|
||||||
|
if line >= len(data) {
|
||||||
|
*flags |= LIST_ITEM_END_OF_LIST
|
||||||
|
}
|
||||||
|
|
||||||
rawBytes := raw.Bytes()
|
rawBytes := raw.Bytes()
|
||||||
|
|
||||||
// render the contents of the list item
|
// render the contents of the list item
|
||||||
|
10
vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml
generated
vendored
10
vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml
generated
vendored
@ -1,8 +1,14 @@
|
|||||||
|
sudo: false
|
||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.5
|
- 1.7
|
||||||
|
- tip
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
||||||
|
fast_finish: true
|
||||||
install:
|
install:
|
||||||
- go get golang.org/x/tools/cmd/vet
|
- # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
|
||||||
script:
|
script:
|
||||||
- go get -t -v ./...
|
- go get -t -v ./...
|
||||||
- diff -u <(echo -n) <(gofmt -d -s .)
|
- diff -u <(echo -n) <(gofmt -d -s .)
|
||||||
|
7
vendor/github.com/shurcooL/sanitized_anchor_name/README.md
generated
vendored
7
vendor/github.com/shurcooL/sanitized_anchor_name/README.md
generated
vendored
@ -1,4 +1,7 @@
|
|||||||
# sanitized_anchor_name [![Build Status](https://travis-ci.org/shurcooL/sanitized_anchor_name.svg?branch=master)](https://travis-ci.org/shurcooL/sanitized_anchor_name) [![GoDoc](https://godoc.org/github.com/shurcooL/sanitized_anchor_name?status.svg)](https://godoc.org/github.com/shurcooL/sanitized_anchor_name)
|
sanitized_anchor_name
|
||||||
|
=====================
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/shurcooL/sanitized_anchor_name.svg?branch=master)](https://travis-ci.org/shurcooL/sanitized_anchor_name) [![GoDoc](https://godoc.org/github.com/shurcooL/sanitized_anchor_name?status.svg)](https://godoc.org/github.com/shurcooL/sanitized_anchor_name)
|
||||||
|
|
||||||
Package sanitized_anchor_name provides a func to create sanitized anchor names.
|
Package sanitized_anchor_name provides a func to create sanitized anchor names.
|
||||||
|
|
||||||
@ -28,4 +31,4 @@ fmt.Println(anchorName)
|
|||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
- [MIT License](LICENSE)
|
- [MIT License](LICENSE)
|
||||||
|
8
vendor/github.com/spf13/cobra/bash_completions.go
generated
vendored
8
vendor/github.com/spf13/cobra/bash_completions.go
generated
vendored
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Annotations for Bash completion.
|
||||||
const (
|
const (
|
||||||
BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions"
|
BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions"
|
||||||
BashCompCustom = "cobra_annotation_bash_completion_custom"
|
BashCompCustom = "cobra_annotation_bash_completion_custom"
|
||||||
@ -22,7 +23,7 @@ func preamble(out io.Writer, name string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = fmt.Fprint(out, `
|
preamStr := `
|
||||||
__debug()
|
__debug()
|
||||||
{
|
{
|
||||||
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
||||||
@ -246,7 +247,8 @@ __handle_word()
|
|||||||
__handle_word
|
__handle_word
|
||||||
}
|
}
|
||||||
|
|
||||||
`)
|
`
|
||||||
|
_, err = fmt.Fprint(out, preamStr)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,6 +568,7 @@ func gen(cmd *Command, w io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenBashCompletion generates bash completion file and writes to the passed writer.
|
||||||
func (cmd *Command) GenBashCompletion(w io.Writer) error {
|
func (cmd *Command) GenBashCompletion(w io.Writer) error {
|
||||||
if err := preamble(w, cmd.Name()); err != nil {
|
if err := preamble(w, cmd.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -585,6 +588,7 @@ func nonCompletableFlag(flag *pflag.Flag) bool {
|
|||||||
return flag.Hidden || len(flag.Deprecated) > 0
|
return flag.Hidden || len(flag.Deprecated) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenBashCompletionFile generates bash completion file.
|
||||||
func (cmd *Command) GenBashCompletionFile(filename string) error {
|
func (cmd *Command) GenBashCompletionFile(filename string) error {
|
||||||
outFile, err := os.Create(filename)
|
outFile, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
2
vendor/github.com/spf13/cobra/bash_completions.md
generated
vendored
2
vendor/github.com/spf13/cobra/bash_completions.md
generated
vendored
@ -18,7 +18,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
That will get you completions of subcommands and flags. If you make additional annotations to your code, you can get even more intelligent and flexible behavior.
|
`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior.
|
||||||
|
|
||||||
## Creating your own custom functions
|
## Creating your own custom functions
|
||||||
|
|
||||||
|
3
vendor/github.com/spf13/cobra/cobra.go
generated
vendored
3
vendor/github.com/spf13/cobra/cobra.go
generated
vendored
@ -37,7 +37,8 @@ var templateFuncs = template.FuncMap{
|
|||||||
|
|
||||||
var initializers []func()
|
var initializers []func()
|
||||||
|
|
||||||
// Automatic prefix matching can be a dangerous thing to automatically enable in CLI tools.
|
// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing
|
||||||
|
// to automatically enable in CLI tools.
|
||||||
// Set this to true to enable it.
|
// Set this to true to enable it.
|
||||||
var EnablePrefixMatching = false
|
var EnablePrefixMatching = false
|
||||||
|
|
||||||
|
60
vendor/github.com/spf13/cobra/command.go
generated
vendored
60
vendor/github.com/spf13/cobra/command.go
generated
vendored
@ -57,6 +57,9 @@ type Command struct {
|
|||||||
Deprecated string
|
Deprecated string
|
||||||
// Is this command hidden and should NOT show up in the list of available commands?
|
// Is this command hidden and should NOT show up in the list of available commands?
|
||||||
Hidden bool
|
Hidden bool
|
||||||
|
// Annotations are key/value pairs that can be used by applications to identify or
|
||||||
|
// group commands
|
||||||
|
Annotations map[string]string
|
||||||
// Full set of flags
|
// Full set of flags
|
||||||
flags *flag.FlagSet
|
flags *flag.FlagSet
|
||||||
// Set of flags childrens of this command will inherit
|
// Set of flags childrens of this command will inherit
|
||||||
@ -129,7 +132,7 @@ type Command struct {
|
|||||||
DisableFlagParsing bool
|
DisableFlagParsing bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// os.Args[1:] by default, if desired, can be overridden
|
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
|
||||||
// particularly useful when testing.
|
// particularly useful when testing.
|
||||||
func (c *Command) SetArgs(a []string) {
|
func (c *Command) SetArgs(a []string) {
|
||||||
c.args = a
|
c.args = a
|
||||||
@ -141,12 +144,12 @@ func (c *Command) SetOutput(output io.Writer) {
|
|||||||
c.output = &output
|
c.output = &output
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usage can be defined by application.
|
// SetUsageFunc sets usage function. Usage can be defined by application.
|
||||||
func (c *Command) SetUsageFunc(f func(*Command) error) {
|
func (c *Command) SetUsageFunc(f func(*Command) error) {
|
||||||
c.usageFunc = f
|
c.usageFunc = f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can be defined by Application.
|
// SetUsageTemplate sets usage template. Can be defined by Application.
|
||||||
func (c *Command) SetUsageTemplate(s string) {
|
func (c *Command) SetUsageTemplate(s string) {
|
||||||
c.usageTemplate = s
|
c.usageTemplate = s
|
||||||
}
|
}
|
||||||
@ -157,16 +160,17 @@ func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {
|
|||||||
c.flagErrorFunc = f
|
c.flagErrorFunc = f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can be defined by Application
|
// SetHelpFunc sets help function. Can be defined by Application
|
||||||
func (c *Command) SetHelpFunc(f func(*Command, []string)) {
|
func (c *Command) SetHelpFunc(f func(*Command, []string)) {
|
||||||
c.helpFunc = f
|
c.helpFunc = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHelpCommand sets help command.
|
||||||
func (c *Command) SetHelpCommand(cmd *Command) {
|
func (c *Command) SetHelpCommand(cmd *Command) {
|
||||||
c.helpCommand = cmd
|
c.helpCommand = cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can be defined by Application.
|
// SetHelpTemplate sets help template to be used. Application can use it to set custom template.
|
||||||
func (c *Command) SetHelpTemplate(s string) {
|
func (c *Command) SetHelpTemplate(s string) {
|
||||||
c.helpTemplate = s
|
c.helpTemplate = s
|
||||||
}
|
}
|
||||||
@ -183,10 +187,12 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OutOrStdout returns output to stdout
|
||||||
func (c *Command) OutOrStdout() io.Writer {
|
func (c *Command) OutOrStdout() io.Writer {
|
||||||
return c.getOut(os.Stdout)
|
return c.getOut(os.Stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OutOrStderr returns output to stderr
|
||||||
func (c *Command) OutOrStderr() io.Writer {
|
func (c *Command) OutOrStderr() io.Writer {
|
||||||
return c.getOut(os.Stderr)
|
return c.getOut(os.Stderr)
|
||||||
}
|
}
|
||||||
@ -265,6 +271,7 @@ func (c *Command) Help() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UsageString return usage string.
|
||||||
func (c *Command) UsageString() string {
|
func (c *Command) UsageString() string {
|
||||||
tmpOutput := c.output
|
tmpOutput := c.output
|
||||||
bb := new(bytes.Buffer)
|
bb := new(bytes.Buffer)
|
||||||
@ -292,6 +299,7 @@ func (c *Command) FlagErrorFunc() (f func(*Command, error) error) {
|
|||||||
|
|
||||||
var minUsagePadding = 25
|
var minUsagePadding = 25
|
||||||
|
|
||||||
|
// UsagePadding return padding for the usage.
|
||||||
func (c *Command) UsagePadding() int {
|
func (c *Command) UsagePadding() int {
|
||||||
if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {
|
if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {
|
||||||
return minUsagePadding
|
return minUsagePadding
|
||||||
@ -301,7 +309,7 @@ func (c *Command) UsagePadding() int {
|
|||||||
|
|
||||||
var minCommandPathPadding = 11
|
var minCommandPathPadding = 11
|
||||||
|
|
||||||
//
|
// CommandPathPadding return padding for the command path.
|
||||||
func (c *Command) CommandPathPadding() int {
|
func (c *Command) CommandPathPadding() int {
|
||||||
if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {
|
if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {
|
||||||
return minCommandPathPadding
|
return minCommandPathPadding
|
||||||
@ -311,6 +319,7 @@ func (c *Command) CommandPathPadding() int {
|
|||||||
|
|
||||||
var minNamePadding = 11
|
var minNamePadding = 11
|
||||||
|
|
||||||
|
// NamePadding returns padding for the name.
|
||||||
func (c *Command) NamePadding() int {
|
func (c *Command) NamePadding() int {
|
||||||
if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
|
if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
|
||||||
return minNamePadding
|
return minNamePadding
|
||||||
@ -318,6 +327,7 @@ func (c *Command) NamePadding() int {
|
|||||||
return c.parent.commandsMaxNameLen
|
return c.parent.commandsMaxNameLen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UsageTemplate returns usage template for the command.
|
||||||
func (c *Command) UsageTemplate() string {
|
func (c *Command) UsageTemplate() string {
|
||||||
if c.usageTemplate != "" {
|
if c.usageTemplate != "" {
|
||||||
return c.usageTemplate
|
return c.usageTemplate
|
||||||
@ -353,6 +363,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HelpTemplate return help template for the command.
|
||||||
func (c *Command) HelpTemplate() string {
|
func (c *Command) HelpTemplate() string {
|
||||||
if c.helpTemplate != "" {
|
if c.helpTemplate != "" {
|
||||||
return c.helpTemplate
|
return c.helpTemplate
|
||||||
@ -416,7 +427,7 @@ func stripFlags(args []string, c *Command) []string {
|
|||||||
case inFlag:
|
case inFlag:
|
||||||
inFlag = false
|
inFlag = false
|
||||||
case y == "":
|
case y == "":
|
||||||
// strip empty commands, as the go tests expect this to be ok....
|
// strip empty commands, as the go tests expect this to be ok....
|
||||||
case !strings.HasPrefix(y, "-"):
|
case !strings.HasPrefix(y, "-"):
|
||||||
commands = append(commands, y)
|
commands = append(commands, y)
|
||||||
inFlag = false
|
inFlag = false
|
||||||
@ -445,7 +456,7 @@ func argsMinusFirstX(args []string, x string) []string {
|
|||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the target command given the args and command tree
|
// Find the target command given the args and command tree
|
||||||
// Meant to be run on the highest node. Only searches down.
|
// Meant to be run on the highest node. Only searches down.
|
||||||
func (c *Command) Find(args []string) (*Command, []string, error) {
|
func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
@ -513,6 +524,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) {
|
|||||||
return commandFound, a, nil
|
return commandFound, a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SuggestionsFor provides suggestions for the typedName.
|
||||||
func (c *Command) SuggestionsFor(typedName string) []string {
|
func (c *Command) SuggestionsFor(typedName string) []string {
|
||||||
suggestions := []string{}
|
suggestions := []string{}
|
||||||
for _, cmd := range c.commands {
|
for _, cmd := range c.commands {
|
||||||
@ -533,6 +545,7 @@ func (c *Command) SuggestionsFor(typedName string) []string {
|
|||||||
return suggestions
|
return suggestions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VisitParents visits all parents of the command and invokes fn on each parent.
|
||||||
func (c *Command) VisitParents(fn func(*Command)) {
|
func (c *Command) VisitParents(fn func(*Command)) {
|
||||||
var traverse func(*Command) *Command
|
var traverse func(*Command) *Command
|
||||||
|
|
||||||
@ -548,6 +561,7 @@ func (c *Command) VisitParents(fn func(*Command)) {
|
|||||||
traverse(c)
|
traverse(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Root finds root command.
|
||||||
func (c *Command) Root() *Command {
|
func (c *Command) Root() *Command {
|
||||||
var findRoot func(*Command) *Command
|
var findRoot func(*Command) *Command
|
||||||
|
|
||||||
@ -672,7 +686,7 @@ func (c *Command) errorMsgFromParse() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call execute to use the args (os.Args[1:] by default)
|
// Execute Call execute to use the args (os.Args[1:] by default)
|
||||||
// and run through the command tree finding appropriate matches
|
// and run through the command tree finding appropriate matches
|
||||||
// for commands and then corresponding flags.
|
// for commands and then corresponding flags.
|
||||||
func (c *Command) Execute() error {
|
func (c *Command) Execute() error {
|
||||||
@ -680,6 +694,7 @@ func (c *Command) Execute() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecuteC executes the command.
|
||||||
func (c *Command) ExecuteC() (cmd *Command, err error) {
|
func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
|
|
||||||
// Regardless of what command execute is called on, run on Root only
|
// Regardless of what command execute is called on, run on Root only
|
||||||
@ -777,7 +792,7 @@ func (c *Command) initHelpCmd() {
|
|||||||
c.AddCommand(c.helpCommand)
|
c.AddCommand(c.helpCommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for testing.
|
// ResetCommands used for testing.
|
||||||
func (c *Command) ResetCommands() {
|
func (c *Command) ResetCommands() {
|
||||||
c.commands = nil
|
c.commands = nil
|
||||||
c.helpCommand = nil
|
c.helpCommand = nil
|
||||||
@ -900,7 +915,7 @@ func (c *Command) UseLine() string {
|
|||||||
return str + c.Use
|
return str + c.Use
|
||||||
}
|
}
|
||||||
|
|
||||||
// For use in determining which flags have been assigned to which commands
|
// DebugFlags used to determine which flags have been assigned to which commands
|
||||||
// and which persist.
|
// and which persist.
|
||||||
func (c *Command) DebugFlags() {
|
func (c *Command) DebugFlags() {
|
||||||
c.Println("DebugFlags called on", c.Name())
|
c.Println("DebugFlags called on", c.Name())
|
||||||
@ -955,7 +970,8 @@ func (c *Command) Name() string {
|
|||||||
if i >= 0 {
|
if i >= 0 {
|
||||||
name = name[:i]
|
name = name[:i]
|
||||||
}
|
}
|
||||||
return name
|
c.name = name
|
||||||
|
return c.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasAlias determines if a given string is an alias of the command.
|
// HasAlias determines if a given string is an alias of the command.
|
||||||
@ -968,10 +984,12 @@ func (c *Command) HasAlias(s string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NameAndAliases returns string containing name and all aliases
|
||||||
func (c *Command) NameAndAliases() string {
|
func (c *Command) NameAndAliases() string {
|
||||||
return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ")
|
return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasExample determines if the command has example.
|
||||||
func (c *Command) HasExample() bool {
|
func (c *Command) HasExample() bool {
|
||||||
return len(c.Example) > 0
|
return len(c.Example) > 0
|
||||||
}
|
}
|
||||||
@ -1068,7 +1086,7 @@ func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) f
|
|||||||
return c.globNormFunc
|
return c.globNormFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flage returns the complete FlagSet that applies
|
// Flags returns the complete FlagSet that applies
|
||||||
// to this command (local and persistent declared here and by all parents).
|
// to this command (local and persistent declared here and by all parents).
|
||||||
func (c *Command) Flags() *flag.FlagSet {
|
func (c *Command) Flags() *flag.FlagSet {
|
||||||
if c.flags == nil {
|
if c.flags == nil {
|
||||||
@ -1168,44 +1186,44 @@ func (c *Command) ResetFlags() {
|
|||||||
c.pflags.SetOutput(c.flagErrorBuf)
|
c.pflags.SetOutput(c.flagErrorBuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the command contain any flags (local plus persistent from the entire structure).
|
// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).
|
||||||
func (c *Command) HasFlags() bool {
|
func (c *Command) HasFlags() bool {
|
||||||
return c.Flags().HasFlags()
|
return c.Flags().HasFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the command contain persistent flags.
|
// HasPersistentFlags checks if the command contains persistent flags.
|
||||||
func (c *Command) HasPersistentFlags() bool {
|
func (c *Command) HasPersistentFlags() bool {
|
||||||
return c.PersistentFlags().HasFlags()
|
return c.PersistentFlags().HasFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the command has flags specifically declared locally.
|
// HasLocalFlags checks if the command has flags specifically declared locally.
|
||||||
func (c *Command) HasLocalFlags() bool {
|
func (c *Command) HasLocalFlags() bool {
|
||||||
return c.LocalFlags().HasFlags()
|
return c.LocalFlags().HasFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the command have flags inherited from its parent command.
|
// HasInheritedFlags checks if the command has flags inherited from its parent command.
|
||||||
func (c *Command) HasInheritedFlags() bool {
|
func (c *Command) HasInheritedFlags() bool {
|
||||||
return c.InheritedFlags().HasFlags()
|
return c.InheritedFlags().HasFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the command contain any flags (local plus persistent from the entire
|
// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire
|
||||||
// structure) which are not hidden or deprecated.
|
// structure) which are not hidden or deprecated.
|
||||||
func (c *Command) HasAvailableFlags() bool {
|
func (c *Command) HasAvailableFlags() bool {
|
||||||
return c.Flags().HasAvailableFlags()
|
return c.Flags().HasAvailableFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the command contain persistent flags which are not hidden or deprecated.
|
// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.
|
||||||
func (c *Command) HasAvailablePersistentFlags() bool {
|
func (c *Command) HasAvailablePersistentFlags() bool {
|
||||||
return c.PersistentFlags().HasAvailableFlags()
|
return c.PersistentFlags().HasAvailableFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the command has flags specifically declared locally which are not hidden
|
// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden
|
||||||
// or deprecated.
|
// or deprecated.
|
||||||
func (c *Command) HasAvailableLocalFlags() bool {
|
func (c *Command) HasAvailableLocalFlags() bool {
|
||||||
return c.LocalFlags().HasAvailableFlags()
|
return c.LocalFlags().HasAvailableFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the command have flags inherited from its parent command which are
|
// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are
|
||||||
// not hidden or deprecated.
|
// not hidden or deprecated.
|
||||||
func (c *Command) HasAvailableInheritedFlags() bool {
|
func (c *Command) HasAvailableInheritedFlags() bool {
|
||||||
return c.InheritedFlags().HasAvailableFlags()
|
return c.InheritedFlags().HasAvailableFlags()
|
||||||
|
6
vendor/github.com/spf13/cobra/doc/md_docs.md
generated
vendored
6
vendor/github.com/spf13/cobra/doc/md_docs.md
generated
vendored
@ -32,15 +32,15 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
kubectlcmd "k8s.io/kubernetes/pkg/kubectl/cmd"
|
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
|
|
||||||
"github.com/spf13/cobra/doc"
|
"github.com/spf13/cobra/doc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd := kubectlcmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||||
doc.GenMarkdownTree(cmd, "./")
|
doc.GenMarkdownTree(kubectl, "./")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
15
vendor/github.com/spf13/cobra/doc/util.go
generated
vendored
15
vendor/github.com/spf13/cobra/doc/util.go
generated
vendored
@ -13,7 +13,11 @@
|
|||||||
|
|
||||||
package doc
|
package doc
|
||||||
|
|
||||||
import "github.com/spf13/cobra"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
// Test to see if we have a reason to print See Also information in docs
|
// Test to see if we have a reason to print See Also information in docs
|
||||||
// Basically this is a test for a parent commend or a subcommand which is
|
// Basically this is a test for a parent commend or a subcommand which is
|
||||||
@ -31,6 +35,15 @@ func hasSeeAlso(cmd *cobra.Command) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temporary workaround for yaml lib generating incorrect yaml with long strings
|
||||||
|
// that do not contain \n.
|
||||||
|
func forceMultiLine(s string) string {
|
||||||
|
if len(s) > 60 && !strings.Contains(s, "\n") {
|
||||||
|
s = s + "\n"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
type byName []*cobra.Command
|
type byName []*cobra.Command
|
||||||
|
|
||||||
func (s byName) Len() int { return len(s) }
|
func (s byName) Len() int { return len(s) }
|
||||||
|
165
vendor/github.com/spf13/cobra/doc/yaml_docs.go
generated
vendored
Normal file
165
vendor/github.com/spf13/cobra/doc/yaml_docs.go
generated
vendored
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
// Copyright 2016 French Ben. All rights reserved.
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package doc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cmdOption struct {
|
||||||
|
Name string
|
||||||
|
Shorthand string `yaml:",omitempty"`
|
||||||
|
DefaultValue string `yaml:"default_value,omitempty"`
|
||||||
|
Usage string `yaml:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type cmdDoc struct {
|
||||||
|
Name string
|
||||||
|
Synopsis string `yaml:",omitempty"`
|
||||||
|
Description string `yaml:",omitempty"`
|
||||||
|
Options []cmdOption `yaml:",omitempty"`
|
||||||
|
InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"`
|
||||||
|
Example string `yaml:",omitempty"`
|
||||||
|
SeeAlso []string `yaml:"see_also,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenYamlTree creates yaml structured ref files for this command and all descendants
|
||||||
|
// in the directory given. This function may not work
|
||||||
|
// correctly if your command names have - in them. If you have `cmd` with two
|
||||||
|
// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third`
|
||||||
|
// it is undefined which help output will be in the file `cmd-sub-third.1`.
|
||||||
|
func GenYamlTree(cmd *cobra.Command, dir string) error {
|
||||||
|
identity := func(s string) string { return s }
|
||||||
|
emptyStr := func(s string) string { return "" }
|
||||||
|
return GenYamlTreeCustom(cmd, dir, emptyStr, identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenYamlTreeCustom creates yaml structured ref files
|
||||||
|
func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
|
||||||
|
for _, c := range cmd.Commands() {
|
||||||
|
if !c.IsAvailableCommand() || c.IsHelpCommand() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml"
|
||||||
|
filename := filepath.Join(dir, basename)
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := GenYamlCustom(cmd, f, linkHandler); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenYaml creates yaml output
|
||||||
|
func GenYaml(cmd *cobra.Command, w io.Writer) error {
|
||||||
|
return GenYamlCustom(cmd, w, func(s string) string { return s })
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenYamlCustom creates custom yaml output
|
||||||
|
func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
|
||||||
|
yamlDoc := cmdDoc{}
|
||||||
|
yamlDoc.Name = cmd.CommandPath()
|
||||||
|
|
||||||
|
yamlDoc.Synopsis = forceMultiLine(cmd.Short)
|
||||||
|
yamlDoc.Description = forceMultiLine(cmd.Long)
|
||||||
|
|
||||||
|
if len(cmd.Example) > 0 {
|
||||||
|
yamlDoc.Example = cmd.Example
|
||||||
|
}
|
||||||
|
|
||||||
|
flags := cmd.NonInheritedFlags()
|
||||||
|
if flags.HasFlags() {
|
||||||
|
yamlDoc.Options = genFlagResult(flags)
|
||||||
|
}
|
||||||
|
flags = cmd.InheritedFlags()
|
||||||
|
if flags.HasFlags() {
|
||||||
|
yamlDoc.InheritedOptions = genFlagResult(flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasSeeAlso(cmd) {
|
||||||
|
result := []string{}
|
||||||
|
if cmd.HasParent() {
|
||||||
|
parent := cmd.Parent()
|
||||||
|
result = append(result, parent.CommandPath()+" - "+parent.Short)
|
||||||
|
}
|
||||||
|
children := cmd.Commands()
|
||||||
|
sort.Sort(byName(children))
|
||||||
|
for _, child := range children {
|
||||||
|
if !child.IsAvailableCommand() || child.IsHelpCommand() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result = append(result, child.Name()+" - "+child.Short)
|
||||||
|
}
|
||||||
|
yamlDoc.SeeAlso = result
|
||||||
|
}
|
||||||
|
|
||||||
|
final, err := yaml.Marshal(&yamlDoc)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if _, err := fmt.Fprintf(w, string(final)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func genFlagResult(flags *pflag.FlagSet) []cmdOption {
|
||||||
|
var result []cmdOption
|
||||||
|
|
||||||
|
flags.VisitAll(func(flag *pflag.Flag) {
|
||||||
|
// Todo, when we mark a shorthand is deprecated, but specify an empty message.
|
||||||
|
// The flag.ShorthandDeprecated is empty as the shorthand is deprecated.
|
||||||
|
// Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok.
|
||||||
|
if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 {
|
||||||
|
opt := cmdOption{
|
||||||
|
flag.Name,
|
||||||
|
flag.Shorthand,
|
||||||
|
flag.DefValue,
|
||||||
|
forceMultiLine(flag.Usage),
|
||||||
|
}
|
||||||
|
result = append(result, opt)
|
||||||
|
} else {
|
||||||
|
opt := cmdOption{
|
||||||
|
Name: flag.Name,
|
||||||
|
DefaultValue: forceMultiLine(flag.DefValue),
|
||||||
|
Usage: forceMultiLine(flag.Usage),
|
||||||
|
}
|
||||||
|
result = append(result, opt)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
103
vendor/github.com/spf13/cobra/doc/yaml_docs.md
generated
vendored
Normal file
103
vendor/github.com/spf13/cobra/doc/yaml_docs.md
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# Generating Yaml Docs For Your Own cobra.Command
|
||||||
|
|
||||||
|
Generating yaml files from a cobra command is incredibly easy. An example is as follows:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/cobra/doc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "test",
|
||||||
|
Short: "my test program",
|
||||||
|
}
|
||||||
|
doc.GenYamlTree(cmd, "/tmp")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
That will get you a Yaml document `/tmp/test.yaml`
|
||||||
|
|
||||||
|
## Generate yaml docs for the entire command tree
|
||||||
|
|
||||||
|
This program can actually generate docs for the kubectl command in the kubernetes project
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||||
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra/doc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||||
|
doc.GenYamlTree(kubectl, "./")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./")
|
||||||
|
|
||||||
|
## Generate yaml docs for a single command
|
||||||
|
|
||||||
|
You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenYaml` instead of `GenYamlTree`
|
||||||
|
|
||||||
|
```go
|
||||||
|
out := new(bytes.Buffer)
|
||||||
|
doc.GenYaml(cmd, out)
|
||||||
|
```
|
||||||
|
|
||||||
|
This will write the yaml doc for ONLY "cmd" into the out, buffer.
|
||||||
|
|
||||||
|
## Customize the output
|
||||||
|
|
||||||
|
Both `GenYaml` and `GenYamlTree` have alternate versions with callbacks to get some control of the output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GenYamlTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GenYamlCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `filePrepender` will prepend the return value given the full filepath to the rendered Yaml file. A common use case is to add front matter to use the generated documentation with [Hugo](http://gohugo.io/):
|
||||||
|
|
||||||
|
```go
|
||||||
|
const fmTemplate = `---
|
||||||
|
date: %s
|
||||||
|
title: "%s"
|
||||||
|
slug: %s
|
||||||
|
url: %s
|
||||||
|
---
|
||||||
|
`
|
||||||
|
|
||||||
|
filePrepender := func(filename string) string {
|
||||||
|
now := time.Now().Format(time.RFC3339)
|
||||||
|
name := filepath.Base(filename)
|
||||||
|
base := strings.TrimSuffix(name, path.Ext(name))
|
||||||
|
url := "/commands/" + strings.ToLower(base) + "/"
|
||||||
|
return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename:
|
||||||
|
|
||||||
|
```go
|
||||||
|
linkHandler := func(name string) string {
|
||||||
|
base := strings.TrimSuffix(name, path.Ext(name))
|
||||||
|
return "/commands/" + strings.ToLower(base) + "/"
|
||||||
|
}
|
||||||
|
```
|
2
vendor/github.com/spf13/pflag/.gitignore
generated
vendored
Normal file
2
vendor/github.com/spf13/pflag/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.idea/*
|
||||||
|
|
2
vendor/github.com/spf13/pflag/README.md
generated
vendored
2
vendor/github.com/spf13/pflag/README.md
generated
vendored
@ -1,4 +1,6 @@
|
|||||||
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
|
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag)
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
|
147
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
Normal file
147
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- boolSlice Value
|
||||||
|
type boolSliceValue struct {
|
||||||
|
value *[]bool
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
|
||||||
|
bsv := new(boolSliceValue)
|
||||||
|
bsv.value = p
|
||||||
|
*bsv.value = val
|
||||||
|
return bsv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
|
||||||
|
// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
|
||||||
|
func (s *boolSliceValue) Set(val string) error {
|
||||||
|
|
||||||
|
// remove all quote characters
|
||||||
|
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
||||||
|
|
||||||
|
// read flag arguments with CSV parser
|
||||||
|
boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse boolean values into slice
|
||||||
|
out := make([]bool, 0, len(boolStrSlice))
|
||||||
|
for _, boolStr := range boolStrSlice {
|
||||||
|
b, err := strconv.ParseBool(strings.TrimSpace(boolStr))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out = append(out, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.changed = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns a string that uniquely represents this flag's type.
|
||||||
|
func (s *boolSliceValue) Type() string {
|
||||||
|
return "boolSlice"
|
||||||
|
}
|
||||||
|
|
||||||
|
// String defines a "native" format for this boolean slice flag value.
|
||||||
|
func (s *boolSliceValue) String() string {
|
||||||
|
|
||||||
|
boolStrSlice := make([]string, len(*s.value))
|
||||||
|
for i, b := range *s.value {
|
||||||
|
boolStrSlice[i] = strconv.FormatBool(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, _ := writeAsCSV(boolStrSlice)
|
||||||
|
|
||||||
|
return "[" + out + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolSliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []bool{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]bool, len(ss))
|
||||||
|
for i, t := range ss {
|
||||||
|
var err error
|
||||||
|
out[i], err = strconv.ParseBool(t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBoolSlice returns the []bool value of a flag with the given name.
|
||||||
|
func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {
|
||||||
|
val, err := f.getFlagType(name, "boolSlice", boolSliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []bool{}, err
|
||||||
|
}
|
||||||
|
return val.([]bool), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []bool variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
|
||||||
|
f.VarP(newBoolSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
|
||||||
|
f.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []bool variable in which to store the value of the flag.
|
||||||
|
func BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
|
||||||
|
CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
|
||||||
|
CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []bool variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {
|
||||||
|
p := []bool{}
|
||||||
|
f.BoolSliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
|
||||||
|
p := []bool{}
|
||||||
|
f.BoolSliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []bool variable that stores the value of the flag.
|
||||||
|
func BoolSlice(name string, value []bool, usage string) *[]bool {
|
||||||
|
return CommandLine.BoolSliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
|
||||||
|
return CommandLine.BoolSliceP(name, shorthand, value, usage)
|
||||||
|
}
|
146
vendor/github.com/spf13/pflag/flag.go
generated
vendored
146
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -487,9 +487,76 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlagUsages Returns a string containing the usage information for all flags in
|
// Splits the string `s` on whitespace into an initial substring up to
|
||||||
// the FlagSet
|
// `i` runes in length and the remainder. Will go `slop` over `i` if
|
||||||
func (f *FlagSet) FlagUsages() string {
|
// that encompasses the entire string (which allows the caller to
|
||||||
|
// avoid short orphan words on the final line).
|
||||||
|
func wrapN(i, slop int, s string) (string, string) {
|
||||||
|
if i+slop > len(s) {
|
||||||
|
return s, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
w := strings.LastIndexAny(s[:i], " \t")
|
||||||
|
if w <= 0 {
|
||||||
|
return s, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return s[:w], s[w+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wraps the string `s` to a maximum width `w` with leading indent
|
||||||
|
// `i`. The first line is not indented (this is assumed to be done by
|
||||||
|
// caller). Pass `w` == 0 to do no wrapping
|
||||||
|
func wrap(i, w int, s string) string {
|
||||||
|
if w == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// space between indent i and end of line width w into which
|
||||||
|
// we should wrap the text.
|
||||||
|
wrap := w - i
|
||||||
|
|
||||||
|
var r, l string
|
||||||
|
|
||||||
|
// Not enough space for sensible wrapping. Wrap as a block on
|
||||||
|
// the next line instead.
|
||||||
|
if wrap < 24 {
|
||||||
|
i = 16
|
||||||
|
wrap = w - i
|
||||||
|
r += "\n" + strings.Repeat(" ", i)
|
||||||
|
}
|
||||||
|
// If still not enough space then don't even try to wrap.
|
||||||
|
if wrap < 24 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to avoid short orphan words on the final line, by
|
||||||
|
// allowing wrapN to go a bit over if that would fit in the
|
||||||
|
// remainder of the line.
|
||||||
|
slop := 5
|
||||||
|
wrap = wrap - slop
|
||||||
|
|
||||||
|
// Handle first line, which is indented by the caller (or the
|
||||||
|
// special case above)
|
||||||
|
l, s = wrapN(wrap, slop, s)
|
||||||
|
r = r + l
|
||||||
|
|
||||||
|
// Now wrap the rest
|
||||||
|
for s != "" {
|
||||||
|
var t string
|
||||||
|
|
||||||
|
t, s = wrapN(wrap, slop, s)
|
||||||
|
r = r + "\n" + strings.Repeat(" ", i) + t
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagUsagesWrapped returns a string containing the usage information
|
||||||
|
// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
|
||||||
|
// wrapping)
|
||||||
|
func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
||||||
x := new(bytes.Buffer)
|
x := new(bytes.Buffer)
|
||||||
|
|
||||||
lines := make([]string, 0, len(f.formal))
|
lines := make([]string, 0, len(f.formal))
|
||||||
@ -546,12 +613,19 @@ func (f *FlagSet) FlagUsages() string {
|
|||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
sidx := strings.Index(line, "\x00")
|
sidx := strings.Index(line, "\x00")
|
||||||
spacing := strings.Repeat(" ", maxlen-sidx)
|
spacing := strings.Repeat(" ", maxlen-sidx)
|
||||||
fmt.Fprintln(x, line[:sidx], spacing, line[sidx+1:])
|
// maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
|
||||||
|
fmt.Fprintln(x, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return x.String()
|
return x.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlagUsages returns a string containing the usage information for all flags in
|
||||||
|
// the FlagSet
|
||||||
|
func (f *FlagSet) FlagUsages() string {
|
||||||
|
return f.FlagUsagesWrapped(0)
|
||||||
|
}
|
||||||
|
|
||||||
// PrintDefaults prints to standard error the default values of all defined command-line flags.
|
// PrintDefaults prints to standard error the default values of all defined command-line flags.
|
||||||
func PrintDefaults() {
|
func PrintDefaults() {
|
||||||
CommandLine.PrintDefaults()
|
CommandLine.PrintDefaults()
|
||||||
@ -635,7 +709,7 @@ func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {
|
|||||||
|
|
||||||
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
|
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
|
||||||
func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
|
func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
|
||||||
_ = f.VarPF(value, name, shorthand, usage)
|
f.VarPF(value, name, shorthand, usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFlag will add the flag to the FlagSet
|
// AddFlag will add the flag to the FlagSet
|
||||||
@ -752,7 +826,7 @@ func containsShorthand(arg, shorthand string) bool {
|
|||||||
return strings.Contains(arg, shorthand)
|
return strings.Contains(arg, shorthand)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) {
|
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||||
a = args
|
a = args
|
||||||
name := s[2:]
|
name := s[2:]
|
||||||
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
|
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
|
||||||
@ -786,11 +860,11 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error)
|
|||||||
err = f.failf("flag needs an argument: %s", s)
|
err = f.failf("flag needs an argument: %s", s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = f.setFlag(flag, value, s)
|
err = fn(flag, value, s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) {
|
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
||||||
if strings.HasPrefix(shorthands, "test.") {
|
if strings.HasPrefix(shorthands, "test.") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -825,16 +899,16 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShor
|
|||||||
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
|
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = f.setFlag(flag, value, shorthands)
|
err = fn(flag, value, shorthands)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) {
|
func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||||
a = args
|
a = args
|
||||||
shorthands := s[1:]
|
shorthands := s[1:]
|
||||||
|
|
||||||
for len(shorthands) > 0 {
|
for len(shorthands) > 0 {
|
||||||
shorthands, a, err = f.parseSingleShortArg(shorthands, args)
|
shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -843,7 +917,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseArgs(args []string) (err error) {
|
func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
|
||||||
for len(args) > 0 {
|
for len(args) > 0 {
|
||||||
s := args[0]
|
s := args[0]
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
@ -863,9 +937,9 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
|
|||||||
f.args = append(f.args, args...)
|
f.args = append(f.args, args...)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
args, err = f.parseLongArg(s, args)
|
args, err = f.parseLongArg(s, args, fn)
|
||||||
} else {
|
} else {
|
||||||
args, err = f.parseShortArg(s, args)
|
args, err = f.parseShortArg(s, args, fn)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -881,7 +955,41 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
|
|||||||
func (f *FlagSet) Parse(arguments []string) error {
|
func (f *FlagSet) Parse(arguments []string) error {
|
||||||
f.parsed = true
|
f.parsed = true
|
||||||
f.args = make([]string, 0, len(arguments))
|
f.args = make([]string, 0, len(arguments))
|
||||||
err := f.parseArgs(arguments)
|
|
||||||
|
assign := func(flag *Flag, value, origArg string) error {
|
||||||
|
return f.setFlag(flag, value, origArg)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := f.parseArgs(arguments, assign)
|
||||||
|
if err != nil {
|
||||||
|
switch f.errorHandling {
|
||||||
|
case ContinueOnError:
|
||||||
|
return err
|
||||||
|
case ExitOnError:
|
||||||
|
os.Exit(2)
|
||||||
|
case PanicOnError:
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type parseFunc func(flag *Flag, value, origArg string) error
|
||||||
|
|
||||||
|
// ParseAll parses flag definitions from the argument list, which should not
|
||||||
|
// include the command name. The arguments for fn are flag and value. Must be
|
||||||
|
// called after all flags in the FlagSet are defined and before flags are
|
||||||
|
// accessed by the program. The return value will be ErrHelp if -help was set
|
||||||
|
// but not defined.
|
||||||
|
func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {
|
||||||
|
f.parsed = true
|
||||||
|
f.args = make([]string, 0, len(arguments))
|
||||||
|
|
||||||
|
assign := func(flag *Flag, value, origArg string) error {
|
||||||
|
return fn(flag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := f.parseArgs(arguments, assign)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch f.errorHandling {
|
switch f.errorHandling {
|
||||||
case ContinueOnError:
|
case ContinueOnError:
|
||||||
@ -907,6 +1015,14 @@ func Parse() {
|
|||||||
CommandLine.Parse(os.Args[1:])
|
CommandLine.Parse(os.Args[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.
|
||||||
|
// The arguments for fn are flag and value. Must be called after all flags are
|
||||||
|
// defined and before flags are accessed by the program.
|
||||||
|
func ParseAll(fn func(flag *Flag, value string) error) {
|
||||||
|
// Ignore errors; CommandLine is set for ExitOnError.
|
||||||
|
CommandLine.ParseAll(os.Args[1:], fn)
|
||||||
|
}
|
||||||
|
|
||||||
// SetInterspersed sets whether to support interspersed option/non-option arguments.
|
// SetInterspersed sets whether to support interspersed option/non-option arguments.
|
||||||
func SetInterspersed(interspersed bool) {
|
func SetInterspersed(interspersed bool) {
|
||||||
CommandLine.SetInterspersed(interspersed)
|
CommandLine.SetInterspersed(interspersed)
|
||||||
|
3
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
3
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
@ -6,13 +6,10 @@ package pflag
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
goflag "flag"
|
goflag "flag"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Print
|
|
||||||
|
|
||||||
// flagValueWrapper implements pflag.Value around a flag.Value. The main
|
// flagValueWrapper implements pflag.Value around a flag.Value. The main
|
||||||
// difference here is the addition of the Type method that returns a string
|
// difference here is the addition of the Type method that returns a string
|
||||||
// name of the type. As this is generally unknown, we approximate that with
|
// name of the type. As this is generally unknown, we approximate that with
|
||||||
|
2
vendor/github.com/spf13/pflag/ip.go
generated
vendored
2
vendor/github.com/spf13/pflag/ip.go
generated
vendored
@ -6,8 +6,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = strings.TrimSpace
|
|
||||||
|
|
||||||
// -- net.IP value
|
// -- net.IP value
|
||||||
type ipValue net.IP
|
type ipValue net.IP
|
||||||
|
|
||||||
|
148
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
Normal file
148
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- ipSlice Value
|
||||||
|
type ipSliceValue struct {
|
||||||
|
value *[]net.IP
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
|
||||||
|
ipsv := new(ipSliceValue)
|
||||||
|
ipsv.value = p
|
||||||
|
*ipsv.value = val
|
||||||
|
return ipsv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
|
||||||
|
// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
|
||||||
|
func (s *ipSliceValue) Set(val string) error {
|
||||||
|
|
||||||
|
// remove all quote characters
|
||||||
|
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
||||||
|
|
||||||
|
// read flag arguments with CSV parser
|
||||||
|
ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse ip values into slice
|
||||||
|
out := make([]net.IP, 0, len(ipStrSlice))
|
||||||
|
for _, ipStr := range ipStrSlice {
|
||||||
|
ip := net.ParseIP(strings.TrimSpace(ipStr))
|
||||||
|
if ip == nil {
|
||||||
|
return fmt.Errorf("invalid string being converted to IP address: %s", ipStr)
|
||||||
|
}
|
||||||
|
out = append(out, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.changed = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns a string that uniquely represents this flag's type.
|
||||||
|
func (s *ipSliceValue) Type() string {
|
||||||
|
return "ipSlice"
|
||||||
|
}
|
||||||
|
|
||||||
|
// String defines a "native" format for this net.IP slice flag value.
|
||||||
|
func (s *ipSliceValue) String() string {
|
||||||
|
|
||||||
|
ipStrSlice := make([]string, len(*s.value))
|
||||||
|
for i, ip := range *s.value {
|
||||||
|
ipStrSlice[i] = ip.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
out, _ := writeAsCSV(ipStrSlice)
|
||||||
|
|
||||||
|
return "[" + out + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipSliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Emtpy string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []net.IP{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]net.IP, len(ss))
|
||||||
|
for i, sval := range ss {
|
||||||
|
ip := net.ParseIP(strings.TrimSpace(sval))
|
||||||
|
if ip == nil {
|
||||||
|
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
|
||||||
|
}
|
||||||
|
out[i] = ip
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIPSlice returns the []net.IP value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {
|
||||||
|
val, err := f.getFlagType(name, "ipSlice", ipSliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []net.IP{}, err
|
||||||
|
}
|
||||||
|
return val.([]net.IP), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []net.IP variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
|
||||||
|
f.VarP(newIPSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
|
||||||
|
f.VarP(newIPSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []net.IP variable in which to store the value of the flag.
|
||||||
|
func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
|
||||||
|
CommandLine.VarP(newIPSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
|
||||||
|
CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []net.IP variable that stores the value of that flag.
|
||||||
|
func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {
|
||||||
|
p := []net.IP{}
|
||||||
|
f.IPSliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
|
||||||
|
p := []net.IP{}
|
||||||
|
f.IPSliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []net.IP variable that stores the value of the flag.
|
||||||
|
func IPSlice(name string, value []net.IP, usage string) *[]net.IP {
|
||||||
|
return CommandLine.IPSliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
|
||||||
|
return CommandLine.IPSliceP(name, shorthand, value, usage)
|
||||||
|
}
|
2
vendor/github.com/spf13/pflag/ipnet.go
generated
vendored
2
vendor/github.com/spf13/pflag/ipnet.go
generated
vendored
@ -27,8 +27,6 @@ func (*ipNetValue) Type() string {
|
|||||||
return "ipNet"
|
return "ipNet"
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = strings.TrimSpace
|
|
||||||
|
|
||||||
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
|
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
|
||||||
*p = val
|
*p = val
|
||||||
return (*ipNetValue)(p)
|
return (*ipNetValue)(p)
|
||||||
|
6
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
6
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
@ -1,11 +1,5 @@
|
|||||||
package pflag
|
package pflag
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = fmt.Fprint
|
|
||||||
|
|
||||||
// -- stringArray Value
|
// -- stringArray Value
|
||||||
type stringArrayValue struct {
|
type stringArrayValue struct {
|
||||||
value *[]string
|
value *[]string
|
||||||
|
5
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
5
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
@ -3,12 +3,9 @@ package pflag
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Fprint
|
|
||||||
|
|
||||||
// -- stringSlice Value
|
// -- stringSlice Value
|
||||||
type stringSliceValue struct {
|
type stringSliceValue struct {
|
||||||
value *[]string
|
value *[]string
|
||||||
@ -39,7 +36,7 @@ func writeAsCSV(vals []string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
w.Flush()
|
w.Flush()
|
||||||
return strings.TrimSuffix(b.String(), fmt.Sprintln()), nil
|
return strings.TrimSuffix(b.String(), "\n"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringSliceValue) Set(val string) error {
|
func (s *stringSliceValue) Set(val string) error {
|
||||||
|
126
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
Normal file
126
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- uintSlice Value
|
||||||
|
type uintSliceValue struct {
|
||||||
|
value *[]uint
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {
|
||||||
|
uisv := new(uintSliceValue)
|
||||||
|
uisv.value = p
|
||||||
|
*uisv.value = val
|
||||||
|
return uisv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]uint, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
u, err := strconv.ParseUint(d, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out[i] = uint(u)
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) Type() string {
|
||||||
|
return "uintSlice"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) String() string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = fmt.Sprintf("%d", d)
|
||||||
|
}
|
||||||
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func uintSliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []uint{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]uint, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
u, err := strconv.ParseUint(d, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out[i] = uint(u)
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUintSlice returns the []uint value of a flag with the given name.
|
||||||
|
func (f *FlagSet) GetUintSlice(name string) ([]uint, error) {
|
||||||
|
val, err := f.getFlagType(name, "uintSlice", uintSliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []uint{}, err
|
||||||
|
}
|
||||||
|
return val.([]uint), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []uint variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {
|
||||||
|
f.VarP(newUintSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
|
||||||
|
f.VarP(newUintSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a uint[] variable in which to store the value of the flag.
|
||||||
|
func UintSliceVar(p *[]uint, name string, value []uint, usage string) {
|
||||||
|
CommandLine.VarP(newUintSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
|
||||||
|
CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSlice defines a []uint flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []uint variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {
|
||||||
|
p := []uint{}
|
||||||
|
f.UintSliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
|
||||||
|
p := []uint{}
|
||||||
|
f.UintSliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSlice defines a []uint flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []uint variable that stores the value of the flag.
|
||||||
|
func UintSlice(name string, value []uint, usage string) *[]uint {
|
||||||
|
return CommandLine.UintSliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
|
||||||
|
return CommandLine.UintSliceP(name, shorthand, value, usage)
|
||||||
|
}
|
6
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
6
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
@ -1062,6 +1062,8 @@ func diff(expected interface{}, actual interface{}) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var spewConfig = spew.ConfigState{
|
var spewConfig = spew.ConfigState{
|
||||||
Indent: " ",
|
Indent: " ",
|
||||||
SortKeys: true,
|
DisablePointerAddresses: true,
|
||||||
|
DisableCapacities: true,
|
||||||
|
SortKeys: true,
|
||||||
}
|
}
|
||||||
|
8
vendor/golang.org/x/crypto/curve25519/const_amd64.h
generated
vendored
Normal file
8
vendor/golang.org/x/crypto/curve25519/const_amd64.h
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This code was translated into a form compatible with 6a from the public
|
||||||
|
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||||
|
|
||||||
|
#define REDMASK51 0x0007FFFFFFFFFFFF
|
4
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
4
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
|
// These constants cannot be encoded in non-MOVQ immediates.
|
||||||
GLOBL ·REDMASK51(SB), 8, $8
|
// We access them directly from memory instead.
|
||||||
|
|
||||||
DATA ·_121666_213(SB)/8, $996687872
|
DATA ·_121666_213(SB)/8, $996687872
|
||||||
GLOBL ·_121666_213(SB), 8, $8
|
GLOBL ·_121666_213(SB), 8, $8
|
||||||
|
29
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
29
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package curve25519
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
|
|
||||||
|
|
||||||
func TestBaseScalarMult(t *testing.T) {
|
|
||||||
var a, b [32]byte
|
|
||||||
in := &a
|
|
||||||
out := &b
|
|
||||||
a[0] = 1
|
|
||||||
|
|
||||||
for i := 0; i < 200; i++ {
|
|
||||||
ScalarBaseMult(out, in)
|
|
||||||
in, out = out, in
|
|
||||||
}
|
|
||||||
|
|
||||||
result := fmt.Sprintf("%x", in[:])
|
|
||||||
if result != expectedHex {
|
|
||||||
t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
|
|
||||||
}
|
|
||||||
}
|
|
2
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// Package curve25519 provides an implementation of scalar multiplication on
|
// Package curve25519 provides an implementation of scalar multiplication on
|
||||||
// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
|
// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
|
||||||
package curve25519 // import "golang.org/x/crypto/curve25519"
|
package curve25519
|
||||||
|
|
||||||
// basePoint is the x coordinate of the generator of the curve.
|
// basePoint is the x coordinate of the generator of the curve.
|
||||||
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
4
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
4
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "const_amd64.h"
|
||||||
|
|
||||||
// func freeze(inout *[5]uint64)
|
// func freeze(inout *[5]uint64)
|
||||||
TEXT ·freeze(SB),7,$0-8
|
TEXT ·freeze(SB),7,$0-8
|
||||||
MOVQ inout+0(FP), DI
|
MOVQ inout+0(FP), DI
|
||||||
@ -16,7 +18,7 @@ TEXT ·freeze(SB),7,$0-8
|
|||||||
MOVQ 16(DI),CX
|
MOVQ 16(DI),CX
|
||||||
MOVQ 24(DI),R8
|
MOVQ 24(DI),R8
|
||||||
MOVQ 32(DI),R9
|
MOVQ 32(DI),R9
|
||||||
MOVQ ·REDMASK51(SB),AX
|
MOVQ $REDMASK51,AX
|
||||||
MOVQ AX,R10
|
MOVQ AX,R10
|
||||||
SUBQ $18,R10
|
SUBQ $18,R10
|
||||||
MOVQ $3,R11
|
MOVQ $3,R11
|
||||||
|
20
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
20
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "const_amd64.h"
|
||||||
|
|
||||||
// func ladderstep(inout *[5][5]uint64)
|
// func ladderstep(inout *[5][5]uint64)
|
||||||
TEXT ·ladderstep(SB),0,$296-8
|
TEXT ·ladderstep(SB),0,$296-8
|
||||||
MOVQ inout+0(FP),DI
|
MOVQ inout+0(FP),DI
|
||||||
@ -118,7 +120,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 72(SP)
|
MULQ 72(SP)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
@ -233,7 +235,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 32(SP)
|
MULQ 32(SP)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
@ -438,7 +440,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 72(SP)
|
MULQ 72(SP)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
@ -588,7 +590,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 32(SP)
|
MULQ 32(SP)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
@ -728,7 +730,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 152(DI)
|
MULQ 152(DI)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
@ -843,7 +845,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 192(DI)
|
MULQ 192(DI)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
@ -993,7 +995,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 32(DI)
|
MULQ 32(DI)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
@ -1143,7 +1145,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 112(SP)
|
MULQ 112(SP)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
@ -1329,7 +1331,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||||||
MULQ 192(SP)
|
MULQ 192(SP)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ ·REDMASK51(SB),DX
|
MOVQ $REDMASK51,DX
|
||||||
SHLQ $13,CX:SI
|
SHLQ $13,CX:SI
|
||||||
ANDQ DX,SI
|
ANDQ DX,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
|
4
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
4
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "const_amd64.h"
|
||||||
|
|
||||||
// func mul(dest, a, b *[5]uint64)
|
// func mul(dest, a, b *[5]uint64)
|
||||||
TEXT ·mul(SB),0,$16-24
|
TEXT ·mul(SB),0,$16-24
|
||||||
MOVQ dest+0(FP), DI
|
MOVQ dest+0(FP), DI
|
||||||
@ -121,7 +123,7 @@ TEXT ·mul(SB),0,$16-24
|
|||||||
MULQ 32(CX)
|
MULQ 32(CX)
|
||||||
ADDQ AX,R14
|
ADDQ AX,R14
|
||||||
ADCQ DX,R15
|
ADCQ DX,R15
|
||||||
MOVQ ·REDMASK51(SB),SI
|
MOVQ $REDMASK51,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
ANDQ SI,R8
|
ANDQ SI,R8
|
||||||
SHLQ $13,R11:R10
|
SHLQ $13,R11:R10
|
||||||
|
4
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
4
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "const_amd64.h"
|
||||||
|
|
||||||
// func square(out, in *[5]uint64)
|
// func square(out, in *[5]uint64)
|
||||||
TEXT ·square(SB),7,$0-16
|
TEXT ·square(SB),7,$0-16
|
||||||
MOVQ out+0(FP), DI
|
MOVQ out+0(FP), DI
|
||||||
@ -84,7 +86,7 @@ TEXT ·square(SB),7,$0-16
|
|||||||
MULQ 32(SI)
|
MULQ 32(SI)
|
||||||
ADDQ AX,R13
|
ADDQ AX,R13
|
||||||
ADCQ DX,R14
|
ADCQ DX,R14
|
||||||
MOVQ ·REDMASK51(SB),SI
|
MOVQ $REDMASK51,SI
|
||||||
SHLQ $13,R8:CX
|
SHLQ $13,R8:CX
|
||||||
ANDQ SI,CX
|
ANDQ SI,CX
|
||||||
SHLQ $13,R10:R9
|
SHLQ $13,R10:R9
|
||||||
|
183
vendor/golang.org/x/crypto/ed25519/ed25519_test.go
generated
vendored
183
vendor/golang.org/x/crypto/ed25519/ed25519_test.go
generated
vendored
@ -1,183 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ed25519
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"compress/gzip"
|
|
||||||
"crypto"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ed25519/internal/edwards25519"
|
|
||||||
)
|
|
||||||
|
|
||||||
type zeroReader struct{}
|
|
||||||
|
|
||||||
func (zeroReader) Read(buf []byte) (int, error) {
|
|
||||||
for i := range buf {
|
|
||||||
buf[i] = 0
|
|
||||||
}
|
|
||||||
return len(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshalMarshal(t *testing.T) {
|
|
||||||
pub, _, _ := GenerateKey(rand.Reader)
|
|
||||||
|
|
||||||
var A edwards25519.ExtendedGroupElement
|
|
||||||
var pubBytes [32]byte
|
|
||||||
copy(pubBytes[:], pub)
|
|
||||||
if !A.FromBytes(&pubBytes) {
|
|
||||||
t.Fatalf("ExtendedGroupElement.FromBytes failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
var pub2 [32]byte
|
|
||||||
A.ToBytes(&pub2)
|
|
||||||
|
|
||||||
if pubBytes != pub2 {
|
|
||||||
t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSignVerify(t *testing.T) {
|
|
||||||
var zero zeroReader
|
|
||||||
public, private, _ := GenerateKey(zero)
|
|
||||||
|
|
||||||
message := []byte("test message")
|
|
||||||
sig := Sign(private, message)
|
|
||||||
if !Verify(public, message, sig) {
|
|
||||||
t.Errorf("valid signature rejected")
|
|
||||||
}
|
|
||||||
|
|
||||||
wrongMessage := []byte("wrong message")
|
|
||||||
if Verify(public, wrongMessage, sig) {
|
|
||||||
t.Errorf("signature of different message accepted")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCryptoSigner(t *testing.T) {
|
|
||||||
var zero zeroReader
|
|
||||||
public, private, _ := GenerateKey(zero)
|
|
||||||
|
|
||||||
signer := crypto.Signer(private)
|
|
||||||
|
|
||||||
publicInterface := signer.Public()
|
|
||||||
public2, ok := publicInterface.(PublicKey)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(public, public2) {
|
|
||||||
t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("message")
|
|
||||||
var noHash crypto.Hash
|
|
||||||
signature, err := signer.Sign(zero, message, noHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error from Sign(): %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !Verify(public, message, signature) {
|
|
||||||
t.Errorf("Verify failed on signature from Sign()")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGolden(t *testing.T) {
|
|
||||||
// sign.input.gz is a selection of test cases from
|
|
||||||
// http://ed25519.cr.yp.to/python/sign.input
|
|
||||||
testDataZ, err := os.Open("testdata/sign.input.gz")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer testDataZ.Close()
|
|
||||||
testData, err := gzip.NewReader(testDataZ)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer testData.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(testData)
|
|
||||||
lineNo := 0
|
|
||||||
|
|
||||||
for scanner.Scan() {
|
|
||||||
lineNo++
|
|
||||||
|
|
||||||
line := scanner.Text()
|
|
||||||
parts := strings.Split(line, ":")
|
|
||||||
if len(parts) != 5 {
|
|
||||||
t.Fatalf("bad number of parts on line %d", lineNo)
|
|
||||||
}
|
|
||||||
|
|
||||||
privBytes, _ := hex.DecodeString(parts[0])
|
|
||||||
pubKey, _ := hex.DecodeString(parts[1])
|
|
||||||
msg, _ := hex.DecodeString(parts[2])
|
|
||||||
sig, _ := hex.DecodeString(parts[3])
|
|
||||||
// The signatures in the test vectors also include the message
|
|
||||||
// at the end, but we just want R and S.
|
|
||||||
sig = sig[:SignatureSize]
|
|
||||||
|
|
||||||
if l := len(pubKey); l != PublicKeySize {
|
|
||||||
t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
var priv [PrivateKeySize]byte
|
|
||||||
copy(priv[:], privBytes)
|
|
||||||
copy(priv[32:], pubKey)
|
|
||||||
|
|
||||||
sig2 := Sign(priv[:], msg)
|
|
||||||
if !bytes.Equal(sig, sig2[:]) {
|
|
||||||
t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !Verify(pubKey, msg, sig2) {
|
|
||||||
t.Errorf("signature failed to verify on line %d", lineNo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
t.Fatalf("error reading test data: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkKeyGeneration(b *testing.B) {
|
|
||||||
var zero zeroReader
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if _, _, err := GenerateKey(zero); err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSigning(b *testing.B) {
|
|
||||||
var zero zeroReader
|
|
||||||
_, priv, err := GenerateKey(zero)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
message := []byte("Hello, world!")
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Sign(priv, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkVerification(b *testing.B) {
|
|
||||||
var zero zeroReader
|
|
||||||
pub, priv, err := GenerateKey(zero)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
message := []byte("Hello, world!")
|
|
||||||
signature := Sign(priv, message)
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Verify(pub, message, signature)
|
|
||||||
}
|
|
||||||
}
|
|
BIN
vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz
generated
vendored
BIN
vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz
generated
vendored
Binary file not shown.
10
vendor/golang.org/x/crypto/poly1305/sum_amd64.s
generated
vendored
10
vendor/golang.org/x/crypto/poly1305/sum_amd64.s
generated
vendored
@ -54,9 +54,9 @@
|
|||||||
ADCQ t3, h1; \
|
ADCQ t3, h1; \
|
||||||
ADCQ $0, h2
|
ADCQ $0, h2
|
||||||
|
|
||||||
DATA poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
||||||
DATA poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
||||||
GLOBL poly1305Mask<>(SB), RODATA, $16
|
GLOBL ·poly1305Mask<>(SB), RODATA, $16
|
||||||
|
|
||||||
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
||||||
TEXT ·poly1305(SB), $0-32
|
TEXT ·poly1305(SB), $0-32
|
||||||
@ -67,8 +67,8 @@ TEXT ·poly1305(SB), $0-32
|
|||||||
|
|
||||||
MOVQ 0(AX), R11
|
MOVQ 0(AX), R11
|
||||||
MOVQ 8(AX), R12
|
MOVQ 8(AX), R12
|
||||||
ANDQ poly1305Mask<>(SB), R11 // r0
|
ANDQ ·poly1305Mask<>(SB), R11 // r0
|
||||||
ANDQ poly1305Mask<>+8(SB), R12 // r1
|
ANDQ ·poly1305Mask<>+8(SB), R12 // r1
|
||||||
XORQ R8, R8 // h0
|
XORQ R8, R8 // h0
|
||||||
XORQ R9, R9 // h1
|
XORQ R9, R9 // h1
|
||||||
XORQ R10, R10 // h2
|
XORQ R10, R10 // h2
|
||||||
|
14
vendor/golang.org/x/crypto/poly1305/sum_arm.s
generated
vendored
14
vendor/golang.org/x/crypto/poly1305/sum_arm.s
generated
vendored
@ -9,12 +9,12 @@
|
|||||||
// This code was translated into a form compatible with 5a from the public
|
// This code was translated into a form compatible with 5a from the public
|
||||||
// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
|
// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
|
||||||
|
|
||||||
DATA poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
|
DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
|
||||||
DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
|
DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
|
||||||
DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
|
DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
|
||||||
DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
|
DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
|
||||||
DATA poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
|
DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
|
||||||
GLOBL poly1305_init_constants_armv6<>(SB), 8, $20
|
GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
|
||||||
|
|
||||||
// Warning: the linker may use R11 to synthesize certain instructions. Please
|
// Warning: the linker may use R11 to synthesize certain instructions. Please
|
||||||
// take care and verify that no synthetic instructions use it.
|
// take care and verify that no synthetic instructions use it.
|
||||||
@ -27,7 +27,7 @@ TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
|
|||||||
ADD $4, R13, R8
|
ADD $4, R13, R8
|
||||||
MOVM.IB [R4-R7], (R8)
|
MOVM.IB [R4-R7], (R8)
|
||||||
MOVM.IA.W (R1), [R2-R5]
|
MOVM.IA.W (R1), [R2-R5]
|
||||||
MOVW $poly1305_init_constants_armv6<>(SB), R7
|
MOVW $·poly1305_init_constants_armv6<>(SB), R7
|
||||||
MOVW R2, R8
|
MOVW R2, R8
|
||||||
MOVW R2>>26, R9
|
MOVW R2>>26, R9
|
||||||
MOVW R3>>20, g
|
MOVW R3>>20, g
|
||||||
|
1614
vendor/golang.org/x/crypto/poly1305/sum_ref.go
generated
vendored
1614
vendor/golang.org/x/crypto/poly1305/sum_ref.go
generated
vendored
File diff suppressed because it is too large
Load Diff
2
vendor/golang.org/x/crypto/ssh/agent/client.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/agent/client.go
generated
vendored
@ -9,7 +9,7 @@
|
|||||||
//
|
//
|
||||||
// References:
|
// References:
|
||||||
// [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD
|
// [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD
|
||||||
package agent // import "golang.org/x/crypto/ssh/agent"
|
package agent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
122
vendor/golang.org/x/crypto/ssh/benchmark_test.go
generated
vendored
122
vendor/golang.org/x/crypto/ssh/benchmark_test.go
generated
vendored
@ -1,122 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type server struct {
|
|
||||||
*ServerConn
|
|
||||||
chans <-chan NewChannel
|
|
||||||
}
|
|
||||||
|
|
||||||
func newServer(c net.Conn, conf *ServerConfig) (*server, error) {
|
|
||||||
sconn, chans, reqs, err := NewServerConn(c, conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
go DiscardRequests(reqs)
|
|
||||||
return &server{sconn, chans}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) Accept() (NewChannel, error) {
|
|
||||||
n, ok := <-s.chans
|
|
||||||
if !ok {
|
|
||||||
return nil, io.EOF
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sshPipe() (Conn, *server, error) {
|
|
||||||
c1, c2, err := netPipe()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
clientConf := ClientConfig{
|
|
||||||
User: "user",
|
|
||||||
}
|
|
||||||
serverConf := ServerConfig{
|
|
||||||
NoClientAuth: true,
|
|
||||||
}
|
|
||||||
serverConf.AddHostKey(testSigners["ecdsa"])
|
|
||||||
done := make(chan *server, 1)
|
|
||||||
go func() {
|
|
||||||
server, err := newServer(c2, &serverConf)
|
|
||||||
if err != nil {
|
|
||||||
done <- nil
|
|
||||||
}
|
|
||||||
done <- server
|
|
||||||
}()
|
|
||||||
|
|
||||||
client, _, reqs, err := NewClientConn(c1, "", &clientConf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
server := <-done
|
|
||||||
if server == nil {
|
|
||||||
return nil, nil, errors.New("server handshake failed.")
|
|
||||||
}
|
|
||||||
go DiscardRequests(reqs)
|
|
||||||
|
|
||||||
return client, server, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEndToEnd(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
|
|
||||||
client, server, err := sshPipe()
|
|
||||||
if err != nil {
|
|
||||||
b.Fatalf("sshPipe: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer client.Close()
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
size := (1 << 20)
|
|
||||||
input := make([]byte, size)
|
|
||||||
output := make([]byte, size)
|
|
||||||
b.SetBytes(int64(size))
|
|
||||||
done := make(chan int, 1)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
newCh, err := server.Accept()
|
|
||||||
if err != nil {
|
|
||||||
b.Fatalf("Client: %v", err)
|
|
||||||
}
|
|
||||||
ch, incoming, err := newCh.Accept()
|
|
||||||
go DiscardRequests(incoming)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if _, err := io.ReadFull(ch, output); err != nil {
|
|
||||||
b.Fatalf("ReadFull: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ch.Close()
|
|
||||||
done <- 1
|
|
||||||
}()
|
|
||||||
|
|
||||||
ch, in, err := client.OpenChannel("speed", nil)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatalf("OpenChannel: %v", err)
|
|
||||||
}
|
|
||||||
go DiscardRequests(in)
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if _, err := ch.Write(input); err != nil {
|
|
||||||
b.Fatalf("WriteFull: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ch.Close()
|
|
||||||
b.StopTimer()
|
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
|
87
vendor/golang.org/x/crypto/ssh/buffer_test.go
generated
vendored
87
vendor/golang.org/x/crypto/ssh/buffer_test.go
generated
vendored
@ -1,87 +0,0 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var alphabet = []byte("abcdefghijklmnopqrstuvwxyz")
|
|
||||||
|
|
||||||
func TestBufferReadwrite(t *testing.T) {
|
|
||||||
b := newBuffer()
|
|
||||||
b.write(alphabet[:10])
|
|
||||||
r, _ := b.Read(make([]byte, 10))
|
|
||||||
if r != 10 {
|
|
||||||
t.Fatalf("Expected written == read == 10, written: 10, read %d", r)
|
|
||||||
}
|
|
||||||
|
|
||||||
b = newBuffer()
|
|
||||||
b.write(alphabet[:5])
|
|
||||||
r, _ = b.Read(make([]byte, 10))
|
|
||||||
if r != 5 {
|
|
||||||
t.Fatalf("Expected written == read == 5, written: 5, read %d", r)
|
|
||||||
}
|
|
||||||
|
|
||||||
b = newBuffer()
|
|
||||||
b.write(alphabet[:10])
|
|
||||||
r, _ = b.Read(make([]byte, 5))
|
|
||||||
if r != 5 {
|
|
||||||
t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r)
|
|
||||||
}
|
|
||||||
|
|
||||||
b = newBuffer()
|
|
||||||
b.write(alphabet[:5])
|
|
||||||
b.write(alphabet[5:15])
|
|
||||||
r, _ = b.Read(make([]byte, 10))
|
|
||||||
r2, _ := b.Read(make([]byte, 10))
|
|
||||||
if r != 10 || r2 != 5 || 15 != r+r2 {
|
|
||||||
t.Fatal("Expected written == read == 15")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBufferClose(t *testing.T) {
|
|
||||||
b := newBuffer()
|
|
||||||
b.write(alphabet[:10])
|
|
||||||
b.eof()
|
|
||||||
_, err := b.Read(make([]byte, 5))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected read of 5 to not return EOF")
|
|
||||||
}
|
|
||||||
b = newBuffer()
|
|
||||||
b.write(alphabet[:10])
|
|
||||||
b.eof()
|
|
||||||
r, err := b.Read(make([]byte, 5))
|
|
||||||
r2, err2 := b.Read(make([]byte, 10))
|
|
||||||
if r != 5 || r2 != 5 || err != nil || err2 != nil {
|
|
||||||
t.Fatal("expected reads of 5 and 5")
|
|
||||||
}
|
|
||||||
|
|
||||||
b = newBuffer()
|
|
||||||
b.write(alphabet[:10])
|
|
||||||
b.eof()
|
|
||||||
r, err = b.Read(make([]byte, 5))
|
|
||||||
r2, err2 = b.Read(make([]byte, 10))
|
|
||||||
r3, err3 := b.Read(make([]byte, 10))
|
|
||||||
if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF {
|
|
||||||
t.Fatal("expected reads of 5 and 5 and 0, with EOF")
|
|
||||||
}
|
|
||||||
|
|
||||||
b = newBuffer()
|
|
||||||
b.write(make([]byte, 5))
|
|
||||||
b.write(make([]byte, 10))
|
|
||||||
b.eof()
|
|
||||||
r, err = b.Read(make([]byte, 9))
|
|
||||||
r2, err2 = b.Read(make([]byte, 3))
|
|
||||||
r3, err3 = b.Read(make([]byte, 3))
|
|
||||||
r4, err4 := b.Read(make([]byte, 10))
|
|
||||||
if err != nil || err2 != nil || err3 != nil || err4 != io.EOF {
|
|
||||||
t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4)
|
|
||||||
}
|
|
||||||
if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 {
|
|
||||||
t.Fatal("Expected written == read == 15", r, r2, r3, r4)
|
|
||||||
}
|
|
||||||
}
|
|
216
vendor/golang.org/x/crypto/ssh/certs_test.go
generated
vendored
216
vendor/golang.org/x/crypto/ssh/certs_test.go
generated
vendored
@ -1,216 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cert generated by ssh-keygen 6.0p1 Debian-4.
|
|
||||||
// % ssh-keygen -s ca-key -I test user-key
|
|
||||||
const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=`
|
|
||||||
|
|
||||||
func TestParseCert(t *testing.T) {
|
|
||||||
authKeyBytes := []byte(exampleSSHCert)
|
|
||||||
|
|
||||||
key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ParseAuthorizedKey: %v", err)
|
|
||||||
}
|
|
||||||
if len(rest) > 0 {
|
|
||||||
t.Errorf("rest: got %q, want empty", rest)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := key.(*Certificate); !ok {
|
|
||||||
t.Fatalf("got %v (%T), want *Certificate", key, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
marshaled := MarshalAuthorizedKey(key)
|
|
||||||
// Before comparison, remove the trailing newline that
|
|
||||||
// MarshalAuthorizedKey adds.
|
|
||||||
marshaled = marshaled[:len(marshaled)-1]
|
|
||||||
if !bytes.Equal(authKeyBytes, marshaled) {
|
|
||||||
t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3
|
|
||||||
// % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub
|
|
||||||
// user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN
|
|
||||||
// Critical Options:
|
|
||||||
// force-command /bin/sleep
|
|
||||||
// source-address 192.168.1.0/24
|
|
||||||
// Extensions:
|
|
||||||
// permit-X11-forwarding
|
|
||||||
// permit-agent-forwarding
|
|
||||||
// permit-port-forwarding
|
|
||||||
// permit-pty
|
|
||||||
// permit-user-rc
|
|
||||||
const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ`
|
|
||||||
|
|
||||||
func TestParseCertWithOptions(t *testing.T) {
|
|
||||||
opts := map[string]string{
|
|
||||||
"source-address": "192.168.1.0/24",
|
|
||||||
"force-command": "/bin/sleep",
|
|
||||||
}
|
|
||||||
exts := map[string]string{
|
|
||||||
"permit-X11-forwarding": "",
|
|
||||||
"permit-agent-forwarding": "",
|
|
||||||
"permit-port-forwarding": "",
|
|
||||||
"permit-pty": "",
|
|
||||||
"permit-user-rc": "",
|
|
||||||
}
|
|
||||||
authKeyBytes := []byte(exampleSSHCertWithOptions)
|
|
||||||
|
|
||||||
key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ParseAuthorizedKey: %v", err)
|
|
||||||
}
|
|
||||||
if len(rest) > 0 {
|
|
||||||
t.Errorf("rest: got %q, want empty", rest)
|
|
||||||
}
|
|
||||||
cert, ok := key.(*Certificate)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("got %v (%T), want *Certificate", key, key)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(cert.CriticalOptions, opts) {
|
|
||||||
t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(cert.Extensions, exts) {
|
|
||||||
t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts)
|
|
||||||
}
|
|
||||||
marshaled := MarshalAuthorizedKey(key)
|
|
||||||
// Before comparison, remove the trailing newline that
|
|
||||||
// MarshalAuthorizedKey adds.
|
|
||||||
marshaled = marshaled[:len(marshaled)-1]
|
|
||||||
if !bytes.Equal(authKeyBytes, marshaled) {
|
|
||||||
t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateCert(t *testing.T) {
|
|
||||||
key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ParseAuthorizedKey: %v", err)
|
|
||||||
}
|
|
||||||
validCert, ok := key.(*Certificate)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("got %v (%T), want *Certificate", key, key)
|
|
||||||
}
|
|
||||||
checker := CertChecker{}
|
|
||||||
checker.IsAuthority = func(k PublicKey) bool {
|
|
||||||
return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := checker.CheckCert("user", validCert); err != nil {
|
|
||||||
t.Errorf("Unable to validate certificate: %v", err)
|
|
||||||
}
|
|
||||||
invalidCert := &Certificate{
|
|
||||||
Key: testPublicKeys["rsa"],
|
|
||||||
SignatureKey: testPublicKeys["ecdsa"],
|
|
||||||
ValidBefore: CertTimeInfinity,
|
|
||||||
Signature: &Signature{},
|
|
||||||
}
|
|
||||||
if err := checker.CheckCert("user", invalidCert); err == nil {
|
|
||||||
t.Error("Invalid cert signature passed validation")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateCertTime(t *testing.T) {
|
|
||||||
cert := Certificate{
|
|
||||||
ValidPrincipals: []string{"user"},
|
|
||||||
Key: testPublicKeys["rsa"],
|
|
||||||
ValidAfter: 50,
|
|
||||||
ValidBefore: 100,
|
|
||||||
}
|
|
||||||
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
|
|
||||||
for ts, ok := range map[int64]bool{
|
|
||||||
25: false,
|
|
||||||
50: true,
|
|
||||||
99: true,
|
|
||||||
100: false,
|
|
||||||
125: false,
|
|
||||||
} {
|
|
||||||
checker := CertChecker{
|
|
||||||
Clock: func() time.Time { return time.Unix(ts, 0) },
|
|
||||||
}
|
|
||||||
checker.IsAuthority = func(k PublicKey) bool {
|
|
||||||
return bytes.Equal(k.Marshal(),
|
|
||||||
testPublicKeys["ecdsa"].Marshal())
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := checker.CheckCert("user", &cert); (v == nil) != ok {
|
|
||||||
t.Errorf("Authenticate(%d): %v", ts, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(hanwen): tests for
|
|
||||||
//
|
|
||||||
// host keys:
|
|
||||||
// * fallbacks
|
|
||||||
|
|
||||||
func TestHostKeyCert(t *testing.T) {
|
|
||||||
cert := &Certificate{
|
|
||||||
ValidPrincipals: []string{"hostname", "hostname.domain"},
|
|
||||||
Key: testPublicKeys["rsa"],
|
|
||||||
ValidBefore: CertTimeInfinity,
|
|
||||||
CertType: HostCert,
|
|
||||||
}
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
|
|
||||||
checker := &CertChecker{
|
|
||||||
IsAuthority: func(p PublicKey) bool {
|
|
||||||
return bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
certSigner, err := NewCertSigner(cert, testSigners["rsa"])
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("NewCertSigner: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, name := range []string{"hostname", "otherhost"} {
|
|
||||||
c1, c2, err := netPipe()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("netPipe: %v", err)
|
|
||||||
}
|
|
||||||
defer c1.Close()
|
|
||||||
defer c2.Close()
|
|
||||||
|
|
||||||
errc := make(chan error)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
conf := ServerConfig{
|
|
||||||
NoClientAuth: true,
|
|
||||||
}
|
|
||||||
conf.AddHostKey(certSigner)
|
|
||||||
_, _, _, err := NewServerConn(c1, &conf)
|
|
||||||
errc <- err
|
|
||||||
}()
|
|
||||||
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "user",
|
|
||||||
HostKeyCallback: checker.CheckHostKey,
|
|
||||||
}
|
|
||||||
_, _, _, err = NewClientConn(c2, name, config)
|
|
||||||
|
|
||||||
succeed := name == "hostname"
|
|
||||||
if (err == nil) != succeed {
|
|
||||||
t.Fatalf("NewClientConn(%q): %v", name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = <-errc
|
|
||||||
if (err == nil) != succeed {
|
|
||||||
t.Fatalf("NewServerConn(%q): %v", name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
4
vendor/golang.org/x/crypto/ssh/channel.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/channel.go
generated
vendored
@ -461,8 +461,8 @@ func (m *mux) newChannel(chanType string, direction channelDirection, extraData
|
|||||||
pending: newBuffer(),
|
pending: newBuffer(),
|
||||||
extPending: newBuffer(),
|
extPending: newBuffer(),
|
||||||
direction: direction,
|
direction: direction,
|
||||||
incomingRequests: make(chan *Request, 16),
|
incomingRequests: make(chan *Request, chanSize),
|
||||||
msg: make(chan interface{}, 16),
|
msg: make(chan interface{}, chanSize),
|
||||||
chanType: chanType,
|
chanType: chanType,
|
||||||
extraData: extraData,
|
extraData: extraData,
|
||||||
mux: m,
|
mux: m,
|
||||||
|
64
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
64
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
@ -135,6 +135,7 @@ const prefixLen = 5
|
|||||||
type streamPacketCipher struct {
|
type streamPacketCipher struct {
|
||||||
mac hash.Hash
|
mac hash.Hash
|
||||||
cipher cipher.Stream
|
cipher cipher.Stream
|
||||||
|
etm bool
|
||||||
|
|
||||||
// The following members are to avoid per-packet allocations.
|
// The following members are to avoid per-packet allocations.
|
||||||
prefix [prefixLen]byte
|
prefix [prefixLen]byte
|
||||||
@ -150,7 +151,14 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
var encryptedPaddingLength [1]byte
|
||||||
|
if s.mac != nil && s.etm {
|
||||||
|
copy(encryptedPaddingLength[:], s.prefix[4:5])
|
||||||
|
s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
|
||||||
|
} else {
|
||||||
|
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||||
|
}
|
||||||
|
|
||||||
length := binary.BigEndian.Uint32(s.prefix[0:4])
|
length := binary.BigEndian.Uint32(s.prefix[0:4])
|
||||||
paddingLength := uint32(s.prefix[4])
|
paddingLength := uint32(s.prefix[4])
|
||||||
|
|
||||||
@ -159,7 +167,12 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
|||||||
s.mac.Reset()
|
s.mac.Reset()
|
||||||
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
||||||
s.mac.Write(s.seqNumBytes[:])
|
s.mac.Write(s.seqNumBytes[:])
|
||||||
s.mac.Write(s.prefix[:])
|
if s.etm {
|
||||||
|
s.mac.Write(s.prefix[:4])
|
||||||
|
s.mac.Write(encryptedPaddingLength[:])
|
||||||
|
} else {
|
||||||
|
s.mac.Write(s.prefix[:])
|
||||||
|
}
|
||||||
macSize = uint32(s.mac.Size())
|
macSize = uint32(s.mac.Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,10 +197,17 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
|||||||
}
|
}
|
||||||
mac := s.packetData[length-1:]
|
mac := s.packetData[length-1:]
|
||||||
data := s.packetData[:length-1]
|
data := s.packetData[:length-1]
|
||||||
|
|
||||||
|
if s.mac != nil && s.etm {
|
||||||
|
s.mac.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
s.cipher.XORKeyStream(data, data)
|
s.cipher.XORKeyStream(data, data)
|
||||||
|
|
||||||
if s.mac != nil {
|
if s.mac != nil {
|
||||||
s.mac.Write(data)
|
if !s.etm {
|
||||||
|
s.mac.Write(data)
|
||||||
|
}
|
||||||
s.macResult = s.mac.Sum(s.macResult[:0])
|
s.macResult = s.mac.Sum(s.macResult[:0])
|
||||||
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
|
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
|
||||||
return nil, errors.New("ssh: MAC failure")
|
return nil, errors.New("ssh: MAC failure")
|
||||||
@ -203,7 +223,13 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
|
|||||||
return errors.New("ssh: packet too large")
|
return errors.New("ssh: packet too large")
|
||||||
}
|
}
|
||||||
|
|
||||||
paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple
|
aadlen := 0
|
||||||
|
if s.mac != nil && s.etm {
|
||||||
|
// packet length is not encrypted for EtM modes
|
||||||
|
aadlen = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
|
||||||
if paddingLength < 4 {
|
if paddingLength < 4 {
|
||||||
paddingLength += packetSizeMultiple
|
paddingLength += packetSizeMultiple
|
||||||
}
|
}
|
||||||
@ -220,15 +246,37 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
|
|||||||
s.mac.Reset()
|
s.mac.Reset()
|
||||||
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
||||||
s.mac.Write(s.seqNumBytes[:])
|
s.mac.Write(s.seqNumBytes[:])
|
||||||
|
|
||||||
|
if s.etm {
|
||||||
|
// For EtM algorithms, the packet length must stay unencrypted,
|
||||||
|
// but the following data (padding length) must be encrypted
|
||||||
|
s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
|
||||||
|
}
|
||||||
|
|
||||||
s.mac.Write(s.prefix[:])
|
s.mac.Write(s.prefix[:])
|
||||||
|
|
||||||
|
if !s.etm {
|
||||||
|
// For non-EtM algorithms, the algorithm is applied on unencrypted data
|
||||||
|
s.mac.Write(packet)
|
||||||
|
s.mac.Write(padding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(s.mac != nil && s.etm) {
|
||||||
|
// For EtM algorithms, the padding length has already been encrypted
|
||||||
|
// and the packet length must remain unencrypted
|
||||||
|
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
s.cipher.XORKeyStream(packet, packet)
|
||||||
|
s.cipher.XORKeyStream(padding, padding)
|
||||||
|
|
||||||
|
if s.mac != nil && s.etm {
|
||||||
|
// For EtM algorithms, packet and padding must be encrypted
|
||||||
s.mac.Write(packet)
|
s.mac.Write(packet)
|
||||||
s.mac.Write(padding)
|
s.mac.Write(padding)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
|
||||||
s.cipher.XORKeyStream(packet, packet)
|
|
||||||
s.cipher.XORKeyStream(padding, padding)
|
|
||||||
|
|
||||||
if _, err := w.Write(s.prefix[:]); err != nil {
|
if _, err := w.Write(s.prefix[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
127
vendor/golang.org/x/crypto/ssh/cipher_test.go
generated
vendored
127
vendor/golang.org/x/crypto/ssh/cipher_test.go
generated
vendored
@ -1,127 +0,0 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/rand"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDefaultCiphersExist(t *testing.T) {
|
|
||||||
for _, cipherAlgo := range supportedCiphers {
|
|
||||||
if _, ok := cipherModes[cipherAlgo]; !ok {
|
|
||||||
t.Errorf("default cipher %q is unknown", cipherAlgo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPacketCiphers(t *testing.T) {
|
|
||||||
// Still test aes128cbc cipher although it's commented out.
|
|
||||||
cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
|
|
||||||
defer delete(cipherModes, aes128cbcID)
|
|
||||||
|
|
||||||
for cipher := range cipherModes {
|
|
||||||
kr := &kexResult{Hash: crypto.SHA1}
|
|
||||||
algs := directionAlgorithms{
|
|
||||||
Cipher: cipher,
|
|
||||||
MAC: "hmac-sha1",
|
|
||||||
Compression: "none",
|
|
||||||
}
|
|
||||||
client, err := newPacketCipher(clientKeys, algs, kr)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
server, err := newPacketCipher(clientKeys, algs, kr)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
want := "bla bla"
|
|
||||||
input := []byte(want)
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
|
||||||
t.Errorf("writePacket(%q): %v", cipher, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
packet, err := server.readPacket(0, buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("readPacket(%q): %v", cipher, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(packet) != want {
|
|
||||||
t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCBCOracleCounterMeasure(t *testing.T) {
|
|
||||||
cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
|
|
||||||
defer delete(cipherModes, aes128cbcID)
|
|
||||||
|
|
||||||
kr := &kexResult{Hash: crypto.SHA1}
|
|
||||||
algs := directionAlgorithms{
|
|
||||||
Cipher: aes128cbcID,
|
|
||||||
MAC: "hmac-sha1",
|
|
||||||
Compression: "none",
|
|
||||||
}
|
|
||||||
client, err := newPacketCipher(clientKeys, algs, kr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("newPacketCipher(client): %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
want := "bla bla"
|
|
||||||
input := []byte(want)
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
|
||||||
t.Errorf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
packetSize := buf.Len()
|
|
||||||
buf.Write(make([]byte, 2*maxPacket))
|
|
||||||
|
|
||||||
// We corrupt each byte, but this usually will only test the
|
|
||||||
// 'packet too large' or 'MAC failure' cases.
|
|
||||||
lastRead := -1
|
|
||||||
for i := 0; i < packetSize; i++ {
|
|
||||||
server, err := newPacketCipher(clientKeys, algs, kr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("newPacketCipher(client): %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fresh := &bytes.Buffer{}
|
|
||||||
fresh.Write(buf.Bytes())
|
|
||||||
fresh.Bytes()[i] ^= 0x01
|
|
||||||
|
|
||||||
before := fresh.Len()
|
|
||||||
_, err = server.readPacket(0, fresh)
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("corrupt byte %d: readPacket succeeded ", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, ok := err.(cbcError); !ok {
|
|
||||||
t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
after := fresh.Len()
|
|
||||||
bytesRead := before - after
|
|
||||||
if bytesRead < maxPacket {
|
|
||||||
t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if i > 0 && bytesRead != lastRead {
|
|
||||||
t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead)
|
|
||||||
}
|
|
||||||
lastRead = bytesRead
|
|
||||||
}
|
|
||||||
}
|
|
6
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
6
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
@ -40,7 +40,7 @@ func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = make(chan NewChannel, 16)
|
ch = make(chan NewChannel, chanSize)
|
||||||
c.channelHandlers[channelType] = ch
|
c.channelHandlers[channelType] = ch
|
||||||
return ch
|
return ch
|
||||||
}
|
}
|
||||||
@ -97,13 +97,11 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
|
|||||||
c.transport = newClientTransport(
|
c.transport = newClientTransport(
|
||||||
newTransport(c.sshConn.conn, config.Rand, true /* is client */),
|
newTransport(c.sshConn.conn, config.Rand, true /* is client */),
|
||||||
c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
|
c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
|
||||||
if err := c.transport.requestInitialKeyChange(); err != nil {
|
if err := c.transport.waitSession(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We just did the key change, so the session ID is established.
|
|
||||||
c.sessionID = c.transport.getSessionID()
|
c.sessionID = c.transport.getSessionID()
|
||||||
|
|
||||||
return c.clientAuthenticate(config)
|
return c.clientAuthenticate(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
@ -30,8 +30,10 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
|
|||||||
// then any untried methods suggested by the server.
|
// then any untried methods suggested by the server.
|
||||||
tried := make(map[string]bool)
|
tried := make(map[string]bool)
|
||||||
var lastMethods []string
|
var lastMethods []string
|
||||||
|
|
||||||
|
sessionID := c.transport.getSessionID()
|
||||||
for auth := AuthMethod(new(noneAuth)); auth != nil; {
|
for auth := AuthMethod(new(noneAuth)); auth != nil; {
|
||||||
ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand)
|
ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
472
vendor/golang.org/x/crypto/ssh/client_auth_test.go
generated
vendored
472
vendor/golang.org/x/crypto/ssh/client_auth_test.go
generated
vendored
@ -1,472 +0,0 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type keyboardInteractive map[string]string
|
|
||||||
|
|
||||||
func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
|
|
||||||
var answers []string
|
|
||||||
for _, q := range questions {
|
|
||||||
answers = append(answers, cr[q])
|
|
||||||
}
|
|
||||||
return answers, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// reused internally by tests
|
|
||||||
var clientPassword = "tiger"
|
|
||||||
|
|
||||||
// tryAuth runs a handshake with a given config against an SSH server
|
|
||||||
// with config serverConfig
|
|
||||||
func tryAuth(t *testing.T, config *ClientConfig) error {
|
|
||||||
c1, c2, err := netPipe()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("netPipe: %v", err)
|
|
||||||
}
|
|
||||||
defer c1.Close()
|
|
||||||
defer c2.Close()
|
|
||||||
|
|
||||||
certChecker := CertChecker{
|
|
||||||
IsAuthority: func(k PublicKey) bool {
|
|
||||||
return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
|
|
||||||
},
|
|
||||||
UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
|
|
||||||
if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
|
|
||||||
},
|
|
||||||
IsRevoked: func(c *Certificate) bool {
|
|
||||||
return c.Serial == 666
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
serverConfig := &ServerConfig{
|
|
||||||
PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
|
|
||||||
if conn.User() == "testuser" && string(pass) == clientPassword {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("password auth failed")
|
|
||||||
},
|
|
||||||
PublicKeyCallback: certChecker.Authenticate,
|
|
||||||
KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) {
|
|
||||||
ans, err := challenge("user",
|
|
||||||
"instruction",
|
|
||||||
[]string{"question1", "question2"},
|
|
||||||
[]bool{true, true})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
|
|
||||||
if ok {
|
|
||||||
challenge("user", "motd", nil, nil)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("keyboard-interactive failed")
|
|
||||||
},
|
|
||||||
AuthLogCallback: func(conn ConnMetadata, method string, err error) {
|
|
||||||
t.Logf("user %q, method %q: %v", conn.User(), method, err)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
serverConfig.AddHostKey(testSigners["rsa"])
|
|
||||||
|
|
||||||
go newServer(c1, serverConfig)
|
|
||||||
_, _, _, err = NewClientConn(c2, "", config)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClientAuthPublicKey(t *testing.T) {
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
PublicKeys(testSigners["rsa"]),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("unable to dial remote side: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthMethodPassword(t *testing.T) {
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
Password(clientPassword),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("unable to dial remote side: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthMethodFallback(t *testing.T) {
|
|
||||||
var passwordCalled bool
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
PublicKeys(testSigners["rsa"]),
|
|
||||||
PasswordCallback(
|
|
||||||
func() (string, error) {
|
|
||||||
passwordCalled = true
|
|
||||||
return "WRONG", nil
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("unable to dial remote side: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if passwordCalled {
|
|
||||||
t.Errorf("password auth tried before public-key auth.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthMethodWrongPassword(t *testing.T) {
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
Password("wrong"),
|
|
||||||
PublicKeys(testSigners["rsa"]),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("unable to dial remote side: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthMethodKeyboardInteractive(t *testing.T) {
|
|
||||||
answers := keyboardInteractive(map[string]string{
|
|
||||||
"question1": "answer1",
|
|
||||||
"question2": "answer2",
|
|
||||||
})
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
KeyboardInteractive(answers.Challenge),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("unable to dial remote side: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthMethodWrongKeyboardInteractive(t *testing.T) {
|
|
||||||
answers := keyboardInteractive(map[string]string{
|
|
||||||
"question1": "answer1",
|
|
||||||
"question2": "WRONG",
|
|
||||||
})
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
KeyboardInteractive(answers.Challenge),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tryAuth(t, config); err == nil {
|
|
||||||
t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the mock server will only authenticate ssh-rsa keys
|
|
||||||
func TestAuthMethodInvalidPublicKey(t *testing.T) {
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
PublicKeys(testSigners["dsa"]),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tryAuth(t, config); err == nil {
|
|
||||||
t.Fatalf("dsa private key should not have authenticated with rsa public key")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the client should authenticate with the second key
|
|
||||||
func TestAuthMethodRSAandDSA(t *testing.T) {
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
PublicKeys(testSigners["dsa"], testSigners["rsa"]),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("client could not authenticate with rsa key: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClientHMAC(t *testing.T) {
|
|
||||||
for _, mac := range supportedMACs {
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
PublicKeys(testSigners["rsa"]),
|
|
||||||
},
|
|
||||||
Config: Config{
|
|
||||||
MACs: []string{mac},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// issue 4285.
|
|
||||||
func TestClientUnsupportedCipher(t *testing.T) {
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
PublicKeys(),
|
|
||||||
},
|
|
||||||
Config: Config{
|
|
||||||
Ciphers: []string{"aes128-cbc"}, // not currently supported
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := tryAuth(t, config); err == nil {
|
|
||||||
t.Errorf("expected no ciphers in common")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClientUnsupportedKex(t *testing.T) {
|
|
||||||
if os.Getenv("GO_BUILDER_NAME") != "" {
|
|
||||||
t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198")
|
|
||||||
}
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
PublicKeys(),
|
|
||||||
},
|
|
||||||
Config: Config{
|
|
||||||
KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
|
|
||||||
t.Errorf("got %v, expected 'common algorithm'", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClientLoginCert(t *testing.T) {
|
|
||||||
cert := &Certificate{
|
|
||||||
Key: testPublicKeys["rsa"],
|
|
||||||
ValidBefore: CertTimeInfinity,
|
|
||||||
CertType: UserCert,
|
|
||||||
}
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
certSigner, err := NewCertSigner(cert, testSigners["rsa"])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewCertSigner: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
clientConfig := &ClientConfig{
|
|
||||||
User: "user",
|
|
||||||
}
|
|
||||||
clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
|
|
||||||
|
|
||||||
t.Log("should succeed")
|
|
||||||
if err := tryAuth(t, clientConfig); err != nil {
|
|
||||||
t.Errorf("cert login failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log("corrupted signature")
|
|
||||||
cert.Signature.Blob[0]++
|
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
|
||||||
t.Errorf("cert login passed with corrupted sig")
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log("revoked")
|
|
||||||
cert.Serial = 666
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
|
||||||
t.Errorf("revoked cert login succeeded")
|
|
||||||
}
|
|
||||||
cert.Serial = 1
|
|
||||||
|
|
||||||
t.Log("sign with wrong key")
|
|
||||||
cert.SignCert(rand.Reader, testSigners["dsa"])
|
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
|
||||||
t.Errorf("cert login passed with non-authoritative key")
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log("host cert")
|
|
||||||
cert.CertType = HostCert
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
|
||||||
t.Errorf("cert login passed with wrong type")
|
|
||||||
}
|
|
||||||
cert.CertType = UserCert
|
|
||||||
|
|
||||||
t.Log("principal specified")
|
|
||||||
cert.ValidPrincipals = []string{"user"}
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
if err := tryAuth(t, clientConfig); err != nil {
|
|
||||||
t.Errorf("cert login failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log("wrong principal specified")
|
|
||||||
cert.ValidPrincipals = []string{"fred"}
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
|
||||||
t.Errorf("cert login passed with wrong principal")
|
|
||||||
}
|
|
||||||
cert.ValidPrincipals = nil
|
|
||||||
|
|
||||||
t.Log("added critical option")
|
|
||||||
cert.CriticalOptions = map[string]string{"root-access": "yes"}
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
|
||||||
t.Errorf("cert login passed with unrecognized critical option")
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log("allowed source address")
|
|
||||||
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
if err := tryAuth(t, clientConfig); err != nil {
|
|
||||||
t.Errorf("cert login with source-address failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log("disallowed source address")
|
|
||||||
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
|
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
|
||||||
t.Errorf("cert login with source-address succeeded")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testPermissionsPassing(withPermissions bool, t *testing.T) {
|
|
||||||
serverConfig := &ServerConfig{
|
|
||||||
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
|
|
||||||
if conn.User() == "nopermissions" {
|
|
||||||
return nil, nil
|
|
||||||
} else {
|
|
||||||
return &Permissions{}, nil
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
serverConfig.AddHostKey(testSigners["rsa"])
|
|
||||||
|
|
||||||
clientConfig := &ClientConfig{
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
PublicKeys(testSigners["rsa"]),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if withPermissions {
|
|
||||||
clientConfig.User = "permissions"
|
|
||||||
} else {
|
|
||||||
clientConfig.User = "nopermissions"
|
|
||||||
}
|
|
||||||
|
|
||||||
c1, c2, err := netPipe()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("netPipe: %v", err)
|
|
||||||
}
|
|
||||||
defer c1.Close()
|
|
||||||
defer c2.Close()
|
|
||||||
|
|
||||||
go NewClientConn(c2, "", clientConfig)
|
|
||||||
serverConn, err := newServer(c1, serverConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if p := serverConn.Permissions; (p != nil) != withPermissions {
|
|
||||||
t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPermissionsPassing(t *testing.T) {
|
|
||||||
testPermissionsPassing(true, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNoPermissionsPassing(t *testing.T) {
|
|
||||||
testPermissionsPassing(false, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRetryableAuth(t *testing.T) {
|
|
||||||
n := 0
|
|
||||||
passwords := []string{"WRONG1", "WRONG2"}
|
|
||||||
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: "testuser",
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
RetryableAuthMethod(PasswordCallback(func() (string, error) {
|
|
||||||
p := passwords[n]
|
|
||||||
n++
|
|
||||||
return p, nil
|
|
||||||
}), 2),
|
|
||||||
PublicKeys(testSigners["rsa"]),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("unable to dial remote side: %s", err)
|
|
||||||
}
|
|
||||||
if n != 2 {
|
|
||||||
t.Fatalf("Did not try all passwords")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleRetryableAuthMethod(t *testing.T) {
|
|
||||||
user := "testuser"
|
|
||||||
NumberOfPrompts := 3
|
|
||||||
|
|
||||||
// Normally this would be a callback that prompts the user to answer the
|
|
||||||
// provided questions
|
|
||||||
Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
|
|
||||||
return []string{"answer1", "answer2"}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &ClientConfig{
|
|
||||||
User: user,
|
|
||||||
Auth: []AuthMethod{
|
|
||||||
RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
|
||||||
t.Fatalf("unable to dial remote side: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test if username is received on server side when NoClientAuth is used
|
|
||||||
func TestClientAuthNone(t *testing.T) {
|
|
||||||
user := "testuser"
|
|
||||||
serverConfig := &ServerConfig{
|
|
||||||
NoClientAuth: true,
|
|
||||||
}
|
|
||||||
serverConfig.AddHostKey(testSigners["rsa"])
|
|
||||||
|
|
||||||
clientConfig := &ClientConfig{
|
|
||||||
User: user,
|
|
||||||
}
|
|
||||||
|
|
||||||
c1, c2, err := netPipe()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("netPipe: %v", err)
|
|
||||||
}
|
|
||||||
defer c1.Close()
|
|
||||||
defer c2.Close()
|
|
||||||
|
|
||||||
go NewClientConn(c2, "", clientConfig)
|
|
||||||
serverConn, err := newServer(c1, serverConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("newServer: %v", err)
|
|
||||||
}
|
|
||||||
if serverConn.User() != user {
|
|
||||||
t.Fatalf("server: got %q, want %q", serverConn.User(), user)
|
|
||||||
}
|
|
||||||
}
|
|
39
vendor/golang.org/x/crypto/ssh/client_test.go
generated
vendored
39
vendor/golang.org/x/crypto/ssh/client_test.go
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
|
|
||||||
clientConn, serverConn := net.Pipe()
|
|
||||||
defer clientConn.Close()
|
|
||||||
receivedVersion := make(chan string, 1)
|
|
||||||
go func() {
|
|
||||||
version, err := readVersion(serverConn)
|
|
||||||
if err != nil {
|
|
||||||
receivedVersion <- ""
|
|
||||||
} else {
|
|
||||||
receivedVersion <- string(version)
|
|
||||||
}
|
|
||||||
serverConn.Close()
|
|
||||||
}()
|
|
||||||
NewClientConn(clientConn, "", config)
|
|
||||||
actual := <-receivedVersion
|
|
||||||
if actual != expected {
|
|
||||||
t.Fatalf("got %s; want %s", actual, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCustomClientVersion(t *testing.T) {
|
|
||||||
version := "Test-Client-Version-0.0"
|
|
||||||
testClientVersion(t, &ClientConfig{ClientVersion: version}, version)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDefaultClientVersion(t *testing.T) {
|
|
||||||
testClientVersion(t, &ClientConfig{}, packageVersion)
|
|
||||||
}
|
|
17
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
17
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
@ -56,7 +56,7 @@ var supportedHostKeyAlgos = []string{
|
|||||||
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
|
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
|
||||||
// because they have reached the end of their useful life.
|
// because they have reached the end of their useful life.
|
||||||
var supportedMACs = []string{
|
var supportedMACs = []string{
|
||||||
"hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
|
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportedCompressions = []string{compressionNone}
|
var supportedCompressions = []string{compressionNone}
|
||||||
@ -104,6 +104,21 @@ type directionAlgorithms struct {
|
|||||||
Compression string
|
Compression string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rekeyBytes returns a rekeying intervals in bytes.
|
||||||
|
func (a *directionAlgorithms) rekeyBytes() int64 {
|
||||||
|
// According to RFC4344 block ciphers should rekey after
|
||||||
|
// 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
|
||||||
|
// 128.
|
||||||
|
switch a.Cipher {
|
||||||
|
case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
|
||||||
|
return 16 * (1 << 32)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
|
||||||
|
return 1 << 30
|
||||||
|
}
|
||||||
|
|
||||||
type algorithms struct {
|
type algorithms struct {
|
||||||
kex string
|
kex string
|
||||||
hostKey string
|
hostKey string
|
||||||
|
2
vendor/golang.org/x/crypto/ssh/doc.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/doc.go
generated
vendored
@ -15,4 +15,4 @@ References:
|
|||||||
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
|
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
|
||||||
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
|
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
|
||||||
*/
|
*/
|
||||||
package ssh // import "golang.org/x/crypto/ssh"
|
package ssh
|
||||||
|
262
vendor/golang.org/x/crypto/ssh/example_test.go
generated
vendored
262
vendor/golang.org/x/crypto/ssh/example_test.go
generated
vendored
@ -1,262 +0,0 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleNewServerConn() {
|
|
||||||
// Public key authentication is done by comparing
|
|
||||||
// the public key of a received connection
|
|
||||||
// with the entries in the authorized_keys file.
|
|
||||||
authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to load authorized_keys, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
authorizedKeysMap := map[string]bool{}
|
|
||||||
for len(authorizedKeysBytes) > 0 {
|
|
||||||
pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
authorizedKeysMap[string(pubKey.Marshal())] = true
|
|
||||||
authorizedKeysBytes = rest
|
|
||||||
}
|
|
||||||
|
|
||||||
// An SSH server is represented by a ServerConfig, which holds
|
|
||||||
// certificate details and handles authentication of ServerConns.
|
|
||||||
config := &ssh.ServerConfig{
|
|
||||||
// Remove to disable password auth.
|
|
||||||
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
|
||||||
// Should use constant-time compare (or better, salt+hash) in
|
|
||||||
// a production setting.
|
|
||||||
if c.User() == "testuser" && string(pass) == "tiger" {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("password rejected for %q", c.User())
|
|
||||||
},
|
|
||||||
|
|
||||||
// Remove to disable public key auth.
|
|
||||||
PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
|
|
||||||
if authorizedKeysMap[string(pubKey.Marshal())] {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("unknown public key for %q", c.User())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
privateBytes, err := ioutil.ReadFile("id_rsa")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to load private key: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
private, err := ssh.ParsePrivateKey(privateBytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to parse private key: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
config.AddHostKey(private)
|
|
||||||
|
|
||||||
// Once a ServerConfig has been configured, connections can be
|
|
||||||
// accepted.
|
|
||||||
listener, err := net.Listen("tcp", "0.0.0.0:2022")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("failed to listen for connection: ", err)
|
|
||||||
}
|
|
||||||
nConn, err := listener.Accept()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("failed to accept incoming connection: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before use, a handshake must be performed on the incoming
|
|
||||||
// net.Conn.
|
|
||||||
_, chans, reqs, err := ssh.NewServerConn(nConn, config)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("failed to handshake: ", err)
|
|
||||||
}
|
|
||||||
// The incoming Request channel must be serviced.
|
|
||||||
go ssh.DiscardRequests(reqs)
|
|
||||||
|
|
||||||
// Service the incoming Channel channel.
|
|
||||||
|
|
||||||
// Service the incoming Channel channel.
|
|
||||||
for newChannel := range chans {
|
|
||||||
// Channels have a type, depending on the application level
|
|
||||||
// protocol intended. In the case of a shell, the type is
|
|
||||||
// "session" and ServerShell may be used to present a simple
|
|
||||||
// terminal interface.
|
|
||||||
if newChannel.ChannelType() != "session" {
|
|
||||||
newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
channel, requests, err := newChannel.Accept()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Could not accept channel: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sessions have out-of-band requests such as "shell",
|
|
||||||
// "pty-req" and "env". Here we handle only the
|
|
||||||
// "shell" request.
|
|
||||||
go func(in <-chan *ssh.Request) {
|
|
||||||
for req := range in {
|
|
||||||
req.Reply(req.Type == "shell", nil)
|
|
||||||
}
|
|
||||||
}(requests)
|
|
||||||
|
|
||||||
term := terminal.NewTerminal(channel, "> ")
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer channel.Close()
|
|
||||||
for {
|
|
||||||
line, err := term.ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fmt.Println(line)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleDial() {
|
|
||||||
// An SSH client is represented with a ClientConn.
|
|
||||||
//
|
|
||||||
// To authenticate with the remote server you must pass at least one
|
|
||||||
// implementation of AuthMethod via the Auth field in ClientConfig.
|
|
||||||
config := &ssh.ClientConfig{
|
|
||||||
User: "username",
|
|
||||||
Auth: []ssh.AuthMethod{
|
|
||||||
ssh.Password("yourpassword"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
client, err := ssh.Dial("tcp", "yourserver.com:22", config)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to dial: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each ClientConn can support multiple interactive sessions,
|
|
||||||
// represented by a Session.
|
|
||||||
session, err := client.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to create session: ", err)
|
|
||||||
}
|
|
||||||
defer session.Close()
|
|
||||||
|
|
||||||
// Once a Session is created, you can execute a single command on
|
|
||||||
// the remote side using the Run method.
|
|
||||||
var b bytes.Buffer
|
|
||||||
session.Stdout = &b
|
|
||||||
if err := session.Run("/usr/bin/whoami"); err != nil {
|
|
||||||
log.Fatal("Failed to run: " + err.Error())
|
|
||||||
}
|
|
||||||
fmt.Println(b.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExamplePublicKeys() {
|
|
||||||
// A public key may be used to authenticate against the remote
|
|
||||||
// server by using an unencrypted PEM-encoded private key file.
|
|
||||||
//
|
|
||||||
// If you have an encrypted private key, the crypto/x509 package
|
|
||||||
// can be used to decrypt it.
|
|
||||||
key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("unable to read private key: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the Signer for this private key.
|
|
||||||
signer, err := ssh.ParsePrivateKey(key)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("unable to parse private key: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &ssh.ClientConfig{
|
|
||||||
User: "user",
|
|
||||||
Auth: []ssh.AuthMethod{
|
|
||||||
// Use the PublicKeys method for remote authentication.
|
|
||||||
ssh.PublicKeys(signer),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to the remote server and perform the SSH handshake.
|
|
||||||
client, err := ssh.Dial("tcp", "host.com:22", config)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("unable to connect: %v", err)
|
|
||||||
}
|
|
||||||
defer client.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleClient_Listen() {
|
|
||||||
config := &ssh.ClientConfig{
|
|
||||||
User: "username",
|
|
||||||
Auth: []ssh.AuthMethod{
|
|
||||||
ssh.Password("password"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// Dial your ssh server.
|
|
||||||
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("unable to connect: ", err)
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
// Request the remote side to open port 8080 on all interfaces.
|
|
||||||
l, err := conn.Listen("tcp", "0.0.0.0:8080")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("unable to register tcp forward: ", err)
|
|
||||||
}
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
// Serve HTTP with your SSH server acting as a reverse proxy.
|
|
||||||
http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
|
||||||
fmt.Fprintf(resp, "Hello world!\n")
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleSession_RequestPty() {
|
|
||||||
// Create client config
|
|
||||||
config := &ssh.ClientConfig{
|
|
||||||
User: "username",
|
|
||||||
Auth: []ssh.AuthMethod{
|
|
||||||
ssh.Password("password"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// Connect to ssh server
|
|
||||||
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("unable to connect: ", err)
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
// Create a session
|
|
||||||
session, err := conn.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("unable to create session: ", err)
|
|
||||||
}
|
|
||||||
defer session.Close()
|
|
||||||
// Set up terminal modes
|
|
||||||
modes := ssh.TerminalModes{
|
|
||||||
ssh.ECHO: 0, // disable echoing
|
|
||||||
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
|
|
||||||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
|
||||||
}
|
|
||||||
// Request pseudo terminal
|
|
||||||
if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
|
|
||||||
log.Fatal("request for pseudo terminal failed: ", err)
|
|
||||||
}
|
|
||||||
// Start remote shell
|
|
||||||
if err := session.Shell(); err != nil {
|
|
||||||
log.Fatal("failed to start shell: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
435
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
435
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
@ -19,6 +19,11 @@ import (
|
|||||||
// messages are wrong when using ECDH.
|
// messages are wrong when using ECDH.
|
||||||
const debugHandshake = false
|
const debugHandshake = false
|
||||||
|
|
||||||
|
// chanSize sets the amount of buffering SSH connections. This is
|
||||||
|
// primarily for testing: setting chanSize=0 uncovers deadlocks more
|
||||||
|
// quickly.
|
||||||
|
const chanSize = 16
|
||||||
|
|
||||||
// keyingTransport is a packet based transport that supports key
|
// keyingTransport is a packet based transport that supports key
|
||||||
// changes. It need not be thread-safe. It should pass through
|
// changes. It need not be thread-safe. It should pass through
|
||||||
// msgNewKeys in both directions.
|
// msgNewKeys in both directions.
|
||||||
@ -53,34 +58,58 @@ type handshakeTransport struct {
|
|||||||
incoming chan []byte
|
incoming chan []byte
|
||||||
readError error
|
readError error
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
writeError error
|
||||||
|
sentInitPacket []byte
|
||||||
|
sentInitMsg *kexInitMsg
|
||||||
|
pendingPackets [][]byte // Used when a key exchange is in progress.
|
||||||
|
|
||||||
|
// If the read loop wants to schedule a kex, it pings this
|
||||||
|
// channel, and the write loop will send out a kex
|
||||||
|
// message.
|
||||||
|
requestKex chan struct{}
|
||||||
|
|
||||||
|
// If the other side requests or confirms a kex, its kexInit
|
||||||
|
// packet is sent here for the write loop to find it.
|
||||||
|
startKex chan *pendingKex
|
||||||
|
|
||||||
// data for host key checking
|
// data for host key checking
|
||||||
hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
||||||
dialAddress string
|
dialAddress string
|
||||||
remoteAddr net.Addr
|
remoteAddr net.Addr
|
||||||
|
|
||||||
readSinceKex uint64
|
// Algorithms agreed in the last key exchange.
|
||||||
|
algorithms *algorithms
|
||||||
|
|
||||||
// Protects the writing side of the connection
|
readPacketsLeft uint32
|
||||||
mu sync.Mutex
|
readBytesLeft int64
|
||||||
cond *sync.Cond
|
|
||||||
sentInitPacket []byte
|
writePacketsLeft uint32
|
||||||
sentInitMsg *kexInitMsg
|
writeBytesLeft int64
|
||||||
writtenSinceKex uint64
|
|
||||||
writeError error
|
|
||||||
|
|
||||||
// The session ID or nil if first kex did not complete yet.
|
// The session ID or nil if first kex did not complete yet.
|
||||||
sessionID []byte
|
sessionID []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type pendingKex struct {
|
||||||
|
otherInit []byte
|
||||||
|
done chan error
|
||||||
|
}
|
||||||
|
|
||||||
func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
|
func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
|
||||||
t := &handshakeTransport{
|
t := &handshakeTransport{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
serverVersion: serverVersion,
|
serverVersion: serverVersion,
|
||||||
clientVersion: clientVersion,
|
clientVersion: clientVersion,
|
||||||
incoming: make(chan []byte, 16),
|
incoming: make(chan []byte, chanSize),
|
||||||
config: config,
|
requestKex: make(chan struct{}, 1),
|
||||||
|
startKex: make(chan *pendingKex, 1),
|
||||||
|
|
||||||
|
config: config,
|
||||||
}
|
}
|
||||||
t.cond = sync.NewCond(&t.mu)
|
|
||||||
|
// We always start with a mandatory key exchange.
|
||||||
|
t.requestKex <- struct{}{}
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +124,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
|||||||
t.hostKeyAlgorithms = supportedHostKeyAlgos
|
t.hostKeyAlgorithms = supportedHostKeyAlgos
|
||||||
}
|
}
|
||||||
go t.readLoop()
|
go t.readLoop()
|
||||||
|
go t.kexLoop()
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +132,7 @@ func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
|||||||
t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
|
t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
|
||||||
t.hostKeys = config.hostKeys
|
t.hostKeys = config.hostKeys
|
||||||
go t.readLoop()
|
go t.readLoop()
|
||||||
|
go t.kexLoop()
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +140,20 @@ func (t *handshakeTransport) getSessionID() []byte {
|
|||||||
return t.sessionID
|
return t.sessionID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waitSession waits for the session to be established. This should be
|
||||||
|
// the first thing to call after instantiating handshakeTransport.
|
||||||
|
func (t *handshakeTransport) waitSession() error {
|
||||||
|
p, err := t.readPacket()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p[0] != msgNewKeys {
|
||||||
|
return fmt.Errorf("ssh: first packet should be msgNewKeys")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) id() string {
|
func (t *handshakeTransport) id() string {
|
||||||
if len(t.hostKeys) > 0 {
|
if len(t.hostKeys) > 0 {
|
||||||
return "server"
|
return "server"
|
||||||
@ -116,6 +161,20 @@ func (t *handshakeTransport) id() string {
|
|||||||
return "client"
|
return "client"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *handshakeTransport) printPacket(p []byte, write bool) {
|
||||||
|
action := "got"
|
||||||
|
if write {
|
||||||
|
action = "sent"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
|
||||||
|
log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
|
||||||
|
} else {
|
||||||
|
msg, err := decode(p)
|
||||||
|
log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) readPacket() ([]byte, error) {
|
func (t *handshakeTransport) readPacket() ([]byte, error) {
|
||||||
p, ok := <-t.incoming
|
p, ok := <-t.incoming
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -125,8 +184,10 @@ func (t *handshakeTransport) readPacket() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) readLoop() {
|
func (t *handshakeTransport) readLoop() {
|
||||||
|
first := true
|
||||||
for {
|
for {
|
||||||
p, err := t.readOnePacket()
|
p, err := t.readOnePacket(first)
|
||||||
|
first = false
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.readError = err
|
t.readError = err
|
||||||
close(t.incoming)
|
close(t.incoming)
|
||||||
@ -138,67 +199,204 @@ func (t *handshakeTransport) readLoop() {
|
|||||||
t.incoming <- p
|
t.incoming <- p
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we can't read, declare the writing part dead too.
|
// Stop writers too.
|
||||||
t.mu.Lock()
|
t.recordWriteError(t.readError)
|
||||||
defer t.mu.Unlock()
|
|
||||||
if t.writeError == nil {
|
// Unblock the writer should it wait for this.
|
||||||
t.writeError = t.readError
|
close(t.startKex)
|
||||||
}
|
|
||||||
t.cond.Broadcast()
|
// Don't close t.requestKex; it's also written to from writePacket.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
func (t *handshakeTransport) pushPacket(p []byte) error {
|
||||||
if t.readSinceKex > t.config.RekeyThreshold {
|
if debugHandshake {
|
||||||
if err := t.requestKeyChange(); err != nil {
|
t.printPacket(p, true)
|
||||||
return nil, err
|
}
|
||||||
|
return t.conn.writePacket(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *handshakeTransport) getWriteError() error {
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
return t.writeError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *handshakeTransport) recordWriteError(err error) {
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
if t.writeError == nil && err != nil {
|
||||||
|
t.writeError = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *handshakeTransport) requestKeyExchange() {
|
||||||
|
select {
|
||||||
|
case t.requestKex <- struct{}{}:
|
||||||
|
default:
|
||||||
|
// something already requested a kex, so do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *handshakeTransport) kexLoop() {
|
||||||
|
|
||||||
|
write:
|
||||||
|
for t.getWriteError() == nil {
|
||||||
|
var request *pendingKex
|
||||||
|
var sent bool
|
||||||
|
|
||||||
|
for request == nil || !sent {
|
||||||
|
var ok bool
|
||||||
|
select {
|
||||||
|
case request, ok = <-t.startKex:
|
||||||
|
if !ok {
|
||||||
|
break write
|
||||||
|
}
|
||||||
|
case <-t.requestKex:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if !sent {
|
||||||
|
if err := t.sendKexInit(); err != nil {
|
||||||
|
t.recordWriteError(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sent = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := t.getWriteError(); err != nil {
|
||||||
|
if request != nil {
|
||||||
|
request.done <- err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're not servicing t.requestKex, but that is OK:
|
||||||
|
// we never block on sending to t.requestKex.
|
||||||
|
|
||||||
|
// We're not servicing t.startKex, but the remote end
|
||||||
|
// has just sent us a kexInitMsg, so it can't send
|
||||||
|
// another key change request, until we close the done
|
||||||
|
// channel on the pendingKex request.
|
||||||
|
|
||||||
|
err := t.enterKeyExchange(request.otherInit)
|
||||||
|
|
||||||
|
t.mu.Lock()
|
||||||
|
t.writeError = err
|
||||||
|
t.sentInitPacket = nil
|
||||||
|
t.sentInitMsg = nil
|
||||||
|
t.writePacketsLeft = packetRekeyThreshold
|
||||||
|
if t.config.RekeyThreshold > 0 {
|
||||||
|
t.writeBytesLeft = int64(t.config.RekeyThreshold)
|
||||||
|
} else if t.algorithms != nil {
|
||||||
|
t.writeBytesLeft = t.algorithms.w.rekeyBytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have completed the key exchange. Since the
|
||||||
|
// reader is still blocked, it is safe to clear out
|
||||||
|
// the requestKex channel. This avoids the situation
|
||||||
|
// where: 1) we consumed our own request for the
|
||||||
|
// initial kex, and 2) the kex from the remote side
|
||||||
|
// caused another send on the requestKex channel,
|
||||||
|
clear:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-t.requestKex:
|
||||||
|
//
|
||||||
|
default:
|
||||||
|
break clear
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.done <- t.writeError
|
||||||
|
|
||||||
|
// kex finished. Push packets that we received while
|
||||||
|
// the kex was in progress. Don't look at t.startKex
|
||||||
|
// and don't increment writtenSinceKex: if we trigger
|
||||||
|
// another kex while we are still busy with the last
|
||||||
|
// one, things will become very confusing.
|
||||||
|
for _, p := range t.pendingPackets {
|
||||||
|
t.writeError = t.pushPacket(p)
|
||||||
|
if t.writeError != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.pendingPackets = t.pendingPackets[:0]
|
||||||
|
t.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drain startKex channel. We don't service t.requestKex
|
||||||
|
// because nobody does blocking sends there.
|
||||||
|
go func() {
|
||||||
|
for init := range t.startKex {
|
||||||
|
init.done <- t.writeError
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Unblock reader.
|
||||||
|
t.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// The protocol uses uint32 for packet counters, so we can't let them
|
||||||
|
// reach 1<<32. We will actually read and write more packets than
|
||||||
|
// this, though: the other side may send more packets, and after we
|
||||||
|
// hit this limit on writing we will send a few more packets for the
|
||||||
|
// key exchange itself.
|
||||||
|
const packetRekeyThreshold = (1 << 31)
|
||||||
|
|
||||||
|
func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
|
||||||
p, err := t.conn.readPacket()
|
p, err := t.conn.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t.readSinceKex += uint64(len(p))
|
if t.readPacketsLeft > 0 {
|
||||||
if debugHandshake {
|
t.readPacketsLeft--
|
||||||
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
|
} else {
|
||||||
log.Printf("%s got data (packet %d bytes)", t.id(), len(p))
|
t.requestKeyExchange()
|
||||||
} else {
|
|
||||||
msg, err := decode(p)
|
|
||||||
log.Printf("%s got %T %v (%v)", t.id(), msg, msg, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t.readBytesLeft > 0 {
|
||||||
|
t.readBytesLeft -= int64(len(p))
|
||||||
|
} else {
|
||||||
|
t.requestKeyExchange()
|
||||||
|
}
|
||||||
|
|
||||||
|
if debugHandshake {
|
||||||
|
t.printPacket(p, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if first && p[0] != msgKexInit {
|
||||||
|
return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
|
||||||
|
}
|
||||||
|
|
||||||
if p[0] != msgKexInit {
|
if p[0] != msgKexInit {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
t.mu.Lock()
|
|
||||||
|
|
||||||
firstKex := t.sessionID == nil
|
firstKex := t.sessionID == nil
|
||||||
|
|
||||||
err = t.enterKeyExchangeLocked(p)
|
kex := pendingKex{
|
||||||
if err != nil {
|
done: make(chan error, 1),
|
||||||
// drop connection
|
otherInit: p,
|
||||||
t.conn.Close()
|
|
||||||
t.writeError = err
|
|
||||||
}
|
}
|
||||||
|
t.startKex <- &kex
|
||||||
|
err = <-kex.done
|
||||||
|
|
||||||
if debugHandshake {
|
if debugHandshake {
|
||||||
log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
|
log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unblock writers.
|
|
||||||
t.sentInitMsg = nil
|
|
||||||
t.sentInitPacket = nil
|
|
||||||
t.cond.Broadcast()
|
|
||||||
t.writtenSinceKex = 0
|
|
||||||
t.mu.Unlock()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t.readSinceKex = 0
|
t.readPacketsLeft = packetRekeyThreshold
|
||||||
|
if t.config.RekeyThreshold > 0 {
|
||||||
|
t.readBytesLeft = int64(t.config.RekeyThreshold)
|
||||||
|
} else {
|
||||||
|
t.readBytesLeft = t.algorithms.r.rekeyBytes()
|
||||||
|
}
|
||||||
|
|
||||||
// By default, a key exchange is hidden from higher layers by
|
// By default, a key exchange is hidden from higher layers by
|
||||||
// translating it into msgIgnore.
|
// translating it into msgIgnore.
|
||||||
@ -213,61 +411,16 @@ func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
|||||||
return successPacket, nil
|
return successPacket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// keyChangeCategory describes whether a key exchange is the first on a
|
// sendKexInit sends a key change message.
|
||||||
// connection, or a subsequent one.
|
func (t *handshakeTransport) sendKexInit() error {
|
||||||
type keyChangeCategory bool
|
|
||||||
|
|
||||||
const (
|
|
||||||
firstKeyExchange keyChangeCategory = true
|
|
||||||
subsequentKeyExchange keyChangeCategory = false
|
|
||||||
)
|
|
||||||
|
|
||||||
// sendKexInit sends a key change message, and returns the message
|
|
||||||
// that was sent. After initiating the key change, all writes will be
|
|
||||||
// blocked until the change is done, and a failed key change will
|
|
||||||
// close the underlying transport. This function is safe for
|
|
||||||
// concurrent use by multiple goroutines.
|
|
||||||
func (t *handshakeTransport) sendKexInit(isFirst keyChangeCategory) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
// If this is the initial key change, but we already have a sessionID,
|
defer t.mu.Unlock()
|
||||||
// then do nothing because the key exchange has already completed
|
|
||||||
// asynchronously.
|
|
||||||
if !isFirst || t.sessionID == nil {
|
|
||||||
_, _, err = t.sendKexInitLocked(isFirst)
|
|
||||||
}
|
|
||||||
t.mu.Unlock()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if isFirst {
|
|
||||||
if packet, err := t.readPacket(); err != nil {
|
|
||||||
return err
|
|
||||||
} else if packet[0] != msgNewKeys {
|
|
||||||
return unexpectedMessageError(msgNewKeys, packet[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *handshakeTransport) requestInitialKeyChange() error {
|
|
||||||
return t.sendKexInit(firstKeyExchange)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *handshakeTransport) requestKeyChange() error {
|
|
||||||
return t.sendKexInit(subsequentKeyExchange)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendKexInitLocked sends a key change message. t.mu must be locked
|
|
||||||
// while this happens.
|
|
||||||
func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexInitMsg, []byte, error) {
|
|
||||||
// kexInits may be sent either in response to the other side,
|
|
||||||
// or because our side wants to initiate a key change, so we
|
|
||||||
// may have already sent a kexInit. In that case, don't send a
|
|
||||||
// second kexInit.
|
|
||||||
if t.sentInitMsg != nil {
|
if t.sentInitMsg != nil {
|
||||||
return t.sentInitMsg, t.sentInitPacket, nil
|
// kexInits may be sent either in response to the other side,
|
||||||
|
// or because our side wants to initiate a key change, so we
|
||||||
|
// may have already sent a kexInit. In that case, don't send a
|
||||||
|
// second kexInit.
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := &kexInitMsg{
|
msg := &kexInitMsg{
|
||||||
@ -295,53 +448,65 @@ func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexI
|
|||||||
packetCopy := make([]byte, len(packet))
|
packetCopy := make([]byte, len(packet))
|
||||||
copy(packetCopy, packet)
|
copy(packetCopy, packet)
|
||||||
|
|
||||||
if err := t.conn.writePacket(packetCopy); err != nil {
|
if err := t.pushPacket(packetCopy); err != nil {
|
||||||
return nil, nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
t.sentInitMsg = msg
|
t.sentInitMsg = msg
|
||||||
t.sentInitPacket = packet
|
t.sentInitPacket = packet
|
||||||
return msg, packet, nil
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) writePacket(p []byte) error {
|
func (t *handshakeTransport) writePacket(p []byte) error {
|
||||||
t.mu.Lock()
|
|
||||||
defer t.mu.Unlock()
|
|
||||||
|
|
||||||
if t.writtenSinceKex > t.config.RekeyThreshold {
|
|
||||||
t.sendKexInitLocked(subsequentKeyExchange)
|
|
||||||
}
|
|
||||||
for t.sentInitMsg != nil && t.writeError == nil {
|
|
||||||
t.cond.Wait()
|
|
||||||
}
|
|
||||||
if t.writeError != nil {
|
|
||||||
return t.writeError
|
|
||||||
}
|
|
||||||
t.writtenSinceKex += uint64(len(p))
|
|
||||||
|
|
||||||
switch p[0] {
|
switch p[0] {
|
||||||
case msgKexInit:
|
case msgKexInit:
|
||||||
return errors.New("ssh: only handshakeTransport can send kexInit")
|
return errors.New("ssh: only handshakeTransport can send kexInit")
|
||||||
case msgNewKeys:
|
case msgNewKeys:
|
||||||
return errors.New("ssh: only handshakeTransport can send newKeys")
|
return errors.New("ssh: only handshakeTransport can send newKeys")
|
||||||
default:
|
|
||||||
return t.conn.writePacket(p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
if t.writeError != nil {
|
||||||
|
return t.writeError
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.sentInitMsg != nil {
|
||||||
|
// Copy the packet so the writer can reuse the buffer.
|
||||||
|
cp := make([]byte, len(p))
|
||||||
|
copy(cp, p)
|
||||||
|
t.pendingPackets = append(t.pendingPackets, cp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.writeBytesLeft > 0 {
|
||||||
|
t.writeBytesLeft -= int64(len(p))
|
||||||
|
} else {
|
||||||
|
t.requestKeyExchange()
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.writePacketsLeft > 0 {
|
||||||
|
t.writePacketsLeft--
|
||||||
|
} else {
|
||||||
|
t.requestKeyExchange()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.pushPacket(p); err != nil {
|
||||||
|
t.writeError = err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) Close() error {
|
func (t *handshakeTransport) Close() error {
|
||||||
return t.conn.Close()
|
return t.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// enterKeyExchange runs the key exchange. t.mu must be held while running this.
|
func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||||
func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) error {
|
|
||||||
if debugHandshake {
|
if debugHandshake {
|
||||||
log.Printf("%s entered key exchange", t.id())
|
log.Printf("%s entered key exchange", t.id())
|
||||||
}
|
}
|
||||||
myInit, myInitPacket, err := t.sendKexInitLocked(subsequentKeyExchange)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
otherInit := &kexInitMsg{}
|
otherInit := &kexInitMsg{}
|
||||||
if err := Unmarshal(otherInitPacket, otherInit); err != nil {
|
if err := Unmarshal(otherInitPacket, otherInit); err != nil {
|
||||||
@ -352,20 +517,20 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
|||||||
clientVersion: t.clientVersion,
|
clientVersion: t.clientVersion,
|
||||||
serverVersion: t.serverVersion,
|
serverVersion: t.serverVersion,
|
||||||
clientKexInit: otherInitPacket,
|
clientKexInit: otherInitPacket,
|
||||||
serverKexInit: myInitPacket,
|
serverKexInit: t.sentInitPacket,
|
||||||
}
|
}
|
||||||
|
|
||||||
clientInit := otherInit
|
clientInit := otherInit
|
||||||
serverInit := myInit
|
serverInit := t.sentInitMsg
|
||||||
if len(t.hostKeys) == 0 {
|
if len(t.hostKeys) == 0 {
|
||||||
clientInit = myInit
|
clientInit, serverInit = serverInit, clientInit
|
||||||
serverInit = otherInit
|
|
||||||
|
|
||||||
magics.clientKexInit = myInitPacket
|
magics.clientKexInit = t.sentInitPacket
|
||||||
magics.serverKexInit = otherInitPacket
|
magics.serverKexInit = otherInitPacket
|
||||||
}
|
}
|
||||||
|
|
||||||
algs, err := findAgreedAlgorithms(clientInit, serverInit)
|
var err error
|
||||||
|
t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -388,16 +553,16 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kex, ok := kexAlgoMap[algs.kex]
|
kex, ok := kexAlgoMap[t.algorithms.kex]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex)
|
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
|
||||||
}
|
}
|
||||||
|
|
||||||
var result *kexResult
|
var result *kexResult
|
||||||
if len(t.hostKeys) > 0 {
|
if len(t.hostKeys) > 0 {
|
||||||
result, err = t.server(kex, algs, &magics)
|
result, err = t.server(kex, t.algorithms, &magics)
|
||||||
} else {
|
} else {
|
||||||
result, err = t.client(kex, algs, &magics)
|
result, err = t.client(kex, t.algorithms, &magics)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -409,7 +574,7 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
|||||||
}
|
}
|
||||||
result.SessionID = t.sessionID
|
result.SessionID = t.sessionID
|
||||||
|
|
||||||
t.conn.prepareKeyChange(algs, result)
|
t.conn.prepareKeyChange(t.algorithms, result)
|
||||||
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
486
vendor/golang.org/x/crypto/ssh/handshake_test.go
generated
vendored
486
vendor/golang.org/x/crypto/ssh/handshake_test.go
generated
vendored
@ -1,486 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type testChecker struct {
|
|
||||||
calls []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
|
|
||||||
if dialAddr == "bad" {
|
|
||||||
return fmt.Errorf("dialAddr is bad")
|
|
||||||
}
|
|
||||||
|
|
||||||
if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil {
|
|
||||||
return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal()))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
|
|
||||||
// therefore is buffered (net.Pipe deadlocks if both sides start with
|
|
||||||
// a write.)
|
|
||||||
func netPipe() (net.Conn, net.Conn, error) {
|
|
||||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
defer listener.Close()
|
|
||||||
c1, err := net.Dial("tcp", listener.Addr().String())
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
c2, err := listener.Accept()
|
|
||||||
if err != nil {
|
|
||||||
c1.Close()
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c1, c2, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func handshakePair(clientConf *ClientConfig, addr string) (client *handshakeTransport, server *handshakeTransport, err error) {
|
|
||||||
a, b, err := netPipe()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
trC := newTransport(a, rand.Reader, true)
|
|
||||||
trS := newTransport(b, rand.Reader, false)
|
|
||||||
clientConf.SetDefaults()
|
|
||||||
|
|
||||||
v := []byte("version")
|
|
||||||
client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr())
|
|
||||||
|
|
||||||
serverConf := &ServerConfig{}
|
|
||||||
serverConf.AddHostKey(testSigners["ecdsa"])
|
|
||||||
serverConf.AddHostKey(testSigners["rsa"])
|
|
||||||
serverConf.SetDefaults()
|
|
||||||
server = newServerTransport(trS, v, v, serverConf)
|
|
||||||
|
|
||||||
return client, server, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshakeBasic(t *testing.T) {
|
|
||||||
if runtime.GOOS == "plan9" {
|
|
||||||
t.Skip("see golang.org/issue/7237")
|
|
||||||
}
|
|
||||||
checker := &testChecker{}
|
|
||||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("handshakePair: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer trC.Close()
|
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
// Client writes a bunch of stuff, and does a key
|
|
||||||
// change in the middle. This should not confuse the
|
|
||||||
// handshake in progress
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
p := []byte{msgRequestSuccess, byte(i)}
|
|
||||||
if err := trC.writePacket(p); err != nil {
|
|
||||||
t.Fatalf("sendPacket: %v", err)
|
|
||||||
}
|
|
||||||
if i == 5 {
|
|
||||||
// halfway through, we request a key change.
|
|
||||||
err := trC.sendKexInit(subsequentKeyExchange)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("sendKexInit: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trC.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Server checks that client messages come in cleanly
|
|
||||||
i := 0
|
|
||||||
for {
|
|
||||||
p, err := trS.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if p[0] == msgNewKeys {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
want := []byte{msgRequestSuccess, byte(i)}
|
|
||||||
if bytes.Compare(p, want) != 0 {
|
|
||||||
t.Errorf("message %d: got %q, want %q", i, p, want)
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i != 10 {
|
|
||||||
t.Errorf("received %d messages, want 10.", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all went well, we registered exactly 1 key change.
|
|
||||||
if len(checker.calls) != 1 {
|
|
||||||
t.Fatalf("got %d host key checks, want 1", len(checker.calls))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub := testSigners["ecdsa"].PublicKey()
|
|
||||||
want := fmt.Sprintf("%s %v %s %x", "addr", trC.remoteAddr, pub.Type(), pub.Marshal())
|
|
||||||
if want != checker.calls[0] {
|
|
||||||
t.Errorf("got %q want %q for host key check", checker.calls[0], want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshakeError(t *testing.T) {
|
|
||||||
checker := &testChecker{}
|
|
||||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "bad")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("handshakePair: %v", err)
|
|
||||||
}
|
|
||||||
defer trC.Close()
|
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
// send a packet
|
|
||||||
packet := []byte{msgRequestSuccess, 42}
|
|
||||||
if err := trC.writePacket(packet); err != nil {
|
|
||||||
t.Errorf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now request a key change.
|
|
||||||
err = trC.sendKexInit(subsequentKeyExchange)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("sendKexInit: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// the key change will fail, and afterwards we can't write.
|
|
||||||
if err := trC.writePacket([]byte{msgRequestSuccess, 43}); err == nil {
|
|
||||||
t.Errorf("writePacket after botched rekey succeeded.")
|
|
||||||
}
|
|
||||||
|
|
||||||
readback, err := trS.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("server closed too soon: %v", err)
|
|
||||||
}
|
|
||||||
if bytes.Compare(readback, packet) != 0 {
|
|
||||||
t.Errorf("got %q want %q", readback, packet)
|
|
||||||
}
|
|
||||||
readback, err = trS.readPacket()
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("got a message %q after failed key change", readback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestForceFirstKex(t *testing.T) {
|
|
||||||
checker := &testChecker{}
|
|
||||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("handshakePair: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer trC.Close()
|
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth}))
|
|
||||||
|
|
||||||
// We setup the initial key exchange, but the remote side
|
|
||||||
// tries to send serviceRequestMsg in cleartext, which is
|
|
||||||
// disallowed.
|
|
||||||
|
|
||||||
err = trS.sendKexInit(firstKeyExchange)
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("server first kex init should reject unexpected packet")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshakeTwice(t *testing.T) {
|
|
||||||
checker := &testChecker{}
|
|
||||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("handshakePair: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer trC.Close()
|
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
// Both sides should ask for the first key exchange first.
|
|
||||||
err = trS.sendKexInit(firstKeyExchange)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("server sendKexInit: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = trC.sendKexInit(firstKeyExchange)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("client sendKexInit: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sent := 0
|
|
||||||
// send a packet
|
|
||||||
packet := make([]byte, 5)
|
|
||||||
packet[0] = msgRequestSuccess
|
|
||||||
if err := trC.writePacket(packet); err != nil {
|
|
||||||
t.Errorf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
sent++
|
|
||||||
|
|
||||||
// Send another packet. Use a fresh one, since writePacket destroys.
|
|
||||||
packet = make([]byte, 5)
|
|
||||||
packet[0] = msgRequestSuccess
|
|
||||||
if err := trC.writePacket(packet); err != nil {
|
|
||||||
t.Errorf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
sent++
|
|
||||||
|
|
||||||
// 2nd key change.
|
|
||||||
err = trC.sendKexInit(subsequentKeyExchange)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("sendKexInit: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
packet = make([]byte, 5)
|
|
||||||
packet[0] = msgRequestSuccess
|
|
||||||
if err := trC.writePacket(packet); err != nil {
|
|
||||||
t.Errorf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
sent++
|
|
||||||
|
|
||||||
packet = make([]byte, 5)
|
|
||||||
packet[0] = msgRequestSuccess
|
|
||||||
for i := 0; i < sent; i++ {
|
|
||||||
msg, err := trS.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("server closed too soon: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.Compare(msg, packet) != 0 {
|
|
||||||
t.Errorf("packet %d: got %q want %q", i, msg, packet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(checker.calls) != 2 {
|
|
||||||
t.Errorf("got %d key changes, want 2", len(checker.calls))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshakeAutoRekeyWrite(t *testing.T) {
|
|
||||||
checker := &testChecker{}
|
|
||||||
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
|
|
||||||
clientConf.RekeyThreshold = 500
|
|
||||||
trC, trS, err := handshakePair(clientConf, "addr")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("handshakePair: %v", err)
|
|
||||||
}
|
|
||||||
defer trC.Close()
|
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
packet := make([]byte, 251)
|
|
||||||
packet[0] = msgRequestSuccess
|
|
||||||
if err := trC.writePacket(packet); err != nil {
|
|
||||||
t.Errorf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
j := 0
|
|
||||||
for ; j < 5; j++ {
|
|
||||||
_, err := trS.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if j != 5 {
|
|
||||||
t.Errorf("got %d, want 5 messages", j)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(checker.calls) != 2 {
|
|
||||||
t.Errorf("got %d key changes, wanted 2", len(checker.calls))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type syncChecker struct {
|
|
||||||
called chan int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
|
|
||||||
t.called <- 1
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshakeAutoRekeyRead(t *testing.T) {
|
|
||||||
sync := &syncChecker{make(chan int, 2)}
|
|
||||||
clientConf := &ClientConfig{
|
|
||||||
HostKeyCallback: sync.Check,
|
|
||||||
}
|
|
||||||
clientConf.RekeyThreshold = 500
|
|
||||||
|
|
||||||
trC, trS, err := handshakePair(clientConf, "addr")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("handshakePair: %v", err)
|
|
||||||
}
|
|
||||||
defer trC.Close()
|
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
packet := make([]byte, 501)
|
|
||||||
packet[0] = msgRequestSuccess
|
|
||||||
if err := trS.writePacket(packet); err != nil {
|
|
||||||
t.Fatalf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
// While we read out the packet, a key change will be
|
|
||||||
// initiated.
|
|
||||||
if _, err := trC.readPacket(); err != nil {
|
|
||||||
t.Fatalf("readPacket(client): %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
<-sync.called
|
|
||||||
}
|
|
||||||
|
|
||||||
// errorKeyingTransport generates errors after a given number of
|
|
||||||
// read/write operations.
|
|
||||||
type errorKeyingTransport struct {
|
|
||||||
packetConn
|
|
||||||
readLeft, writeLeft int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (n *errorKeyingTransport) getSessionID() []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *errorKeyingTransport) writePacket(packet []byte) error {
|
|
||||||
if n.writeLeft == 0 {
|
|
||||||
n.Close()
|
|
||||||
return errors.New("barf")
|
|
||||||
}
|
|
||||||
|
|
||||||
n.writeLeft--
|
|
||||||
return n.packetConn.writePacket(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *errorKeyingTransport) readPacket() ([]byte, error) {
|
|
||||||
if n.readLeft == 0 {
|
|
||||||
n.Close()
|
|
||||||
return nil, errors.New("barf")
|
|
||||||
}
|
|
||||||
|
|
||||||
n.readLeft--
|
|
||||||
return n.packetConn.readPacket()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshakeErrorHandlingRead(t *testing.T) {
|
|
||||||
for i := 0; i < 20; i++ {
|
|
||||||
testHandshakeErrorHandlingN(t, i, -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshakeErrorHandlingWrite(t *testing.T) {
|
|
||||||
for i := 0; i < 20; i++ {
|
|
||||||
testHandshakeErrorHandlingN(t, -1, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// testHandshakeErrorHandlingN runs handshakes, injecting errors. If
|
|
||||||
// handshakeTransport deadlocks, the go runtime will detect it and
|
|
||||||
// panic.
|
|
||||||
func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int) {
|
|
||||||
msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)})
|
|
||||||
|
|
||||||
a, b := memPipe()
|
|
||||||
defer a.Close()
|
|
||||||
defer b.Close()
|
|
||||||
|
|
||||||
key := testSigners["ecdsa"]
|
|
||||||
serverConf := Config{RekeyThreshold: minRekeyThreshold}
|
|
||||||
serverConf.SetDefaults()
|
|
||||||
serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'})
|
|
||||||
serverConn.hostKeys = []Signer{key}
|
|
||||||
go serverConn.readLoop()
|
|
||||||
|
|
||||||
clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold}
|
|
||||||
clientConf.SetDefaults()
|
|
||||||
clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'})
|
|
||||||
clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()}
|
|
||||||
go clientConn.readLoop()
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(4)
|
|
||||||
|
|
||||||
for _, hs := range []packetConn{serverConn, clientConn} {
|
|
||||||
go func(c packetConn) {
|
|
||||||
for {
|
|
||||||
err := c.writePacket(msg)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
}(hs)
|
|
||||||
go func(c packetConn) {
|
|
||||||
for {
|
|
||||||
_, err := c.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
}(hs)
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDisconnect(t *testing.T) {
|
|
||||||
if runtime.GOOS == "plan9" {
|
|
||||||
t.Skip("see golang.org/issue/7237")
|
|
||||||
}
|
|
||||||
checker := &testChecker{}
|
|
||||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("handshakePair: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer trC.Close()
|
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
trC.writePacket([]byte{msgRequestSuccess, 0, 0})
|
|
||||||
errMsg := &disconnectMsg{
|
|
||||||
Reason: 42,
|
|
||||||
Message: "such is life",
|
|
||||||
}
|
|
||||||
trC.writePacket(Marshal(errMsg))
|
|
||||||
trC.writePacket([]byte{msgRequestSuccess, 0, 0})
|
|
||||||
|
|
||||||
packet, err := trS.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("readPacket 1: %v", err)
|
|
||||||
}
|
|
||||||
if packet[0] != msgRequestSuccess {
|
|
||||||
t.Errorf("got packet %v, want packet type %d", packet, msgRequestSuccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = trS.readPacket()
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("readPacket 2 succeeded")
|
|
||||||
} else if !reflect.DeepEqual(err, errMsg) {
|
|
||||||
t.Errorf("got error %#v, want %#v", err, errMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = trS.readPacket()
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("readPacket 3 succeeded")
|
|
||||||
}
|
|
||||||
}
|
|
50
vendor/golang.org/x/crypto/ssh/kex_test.go
generated
vendored
50
vendor/golang.org/x/crypto/ssh/kex_test.go
generated
vendored
@ -1,50 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
// Key exchange tests.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestKexes(t *testing.T) {
|
|
||||||
type kexResultErr struct {
|
|
||||||
result *kexResult
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, kex := range kexAlgoMap {
|
|
||||||
a, b := memPipe()
|
|
||||||
|
|
||||||
s := make(chan kexResultErr, 1)
|
|
||||||
c := make(chan kexResultErr, 1)
|
|
||||||
var magics handshakeMagics
|
|
||||||
go func() {
|
|
||||||
r, e := kex.Client(a, rand.Reader, &magics)
|
|
||||||
a.Close()
|
|
||||||
c <- kexResultErr{r, e}
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
|
|
||||||
b.Close()
|
|
||||||
s <- kexResultErr{r, e}
|
|
||||||
}()
|
|
||||||
|
|
||||||
clientRes := <-c
|
|
||||||
serverRes := <-s
|
|
||||||
if clientRes.err != nil {
|
|
||||||
t.Errorf("client: %v", clientRes.err)
|
|
||||||
}
|
|
||||||
if serverRes.err != nil {
|
|
||||||
t.Errorf("server: %v", serverRes.err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(clientRes.result, serverRes.result) {
|
|
||||||
t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
31
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
31
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
@ -10,10 +10,13 @@ import (
|
|||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
|
"crypto/md5"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -795,8 +798,8 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
|||||||
P *big.Int
|
P *big.Int
|
||||||
Q *big.Int
|
Q *big.Int
|
||||||
G *big.Int
|
G *big.Int
|
||||||
Priv *big.Int
|
|
||||||
Pub *big.Int
|
Pub *big.Int
|
||||||
|
Priv *big.Int
|
||||||
}
|
}
|
||||||
rest, err := asn1.Unmarshal(der, &k)
|
rest, err := asn1.Unmarshal(der, &k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -813,9 +816,9 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
|||||||
Q: k.Q,
|
Q: k.Q,
|
||||||
G: k.G,
|
G: k.G,
|
||||||
},
|
},
|
||||||
Y: k.Priv,
|
Y: k.Pub,
|
||||||
},
|
},
|
||||||
X: k.Pub,
|
X: k.Priv,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -878,3 +881,25 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
|||||||
copy(pk, pk1.Priv)
|
copy(pk, pk1.Priv)
|
||||||
return &pk, nil
|
return &pk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FingerprintLegacyMD5 returns the user presentation of the key's
|
||||||
|
// fingerprint as described by RFC 4716 section 4.
|
||||||
|
func FingerprintLegacyMD5(pubKey PublicKey) string {
|
||||||
|
md5sum := md5.Sum(pubKey.Marshal())
|
||||||
|
hexarray := make([]string, len(md5sum))
|
||||||
|
for i, c := range md5sum {
|
||||||
|
hexarray[i] = hex.EncodeToString([]byte{c})
|
||||||
|
}
|
||||||
|
return strings.Join(hexarray, ":")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FingerprintSHA256 returns the user presentation of the key's
|
||||||
|
// fingerprint as unpadded base64 encoded sha256 hash.
|
||||||
|
// This format was introduced from OpenSSH 6.8.
|
||||||
|
// https://www.openssh.com/txt/release-6.8
|
||||||
|
// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
|
||||||
|
func FingerprintSHA256(pubKey PublicKey) string {
|
||||||
|
sha256sum := sha256.Sum256(pubKey.Marshal())
|
||||||
|
hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
|
||||||
|
return "SHA256:" + hash
|
||||||
|
}
|
||||||
|
456
vendor/golang.org/x/crypto/ssh/keys_test.go
generated
vendored
456
vendor/golang.org/x/crypto/ssh/keys_test.go
generated
vendored
@ -1,456 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/dsa"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ed25519"
|
|
||||||
"golang.org/x/crypto/ssh/testdata"
|
|
||||||
)
|
|
||||||
|
|
||||||
func rawKey(pub PublicKey) interface{} {
|
|
||||||
switch k := pub.(type) {
|
|
||||||
case *rsaPublicKey:
|
|
||||||
return (*rsa.PublicKey)(k)
|
|
||||||
case *dsaPublicKey:
|
|
||||||
return (*dsa.PublicKey)(k)
|
|
||||||
case *ecdsaPublicKey:
|
|
||||||
return (*ecdsa.PublicKey)(k)
|
|
||||||
case ed25519PublicKey:
|
|
||||||
return (ed25519.PublicKey)(k)
|
|
||||||
case *Certificate:
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
panic("unknown key type")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKeyMarshalParse(t *testing.T) {
|
|
||||||
for _, priv := range testSigners {
|
|
||||||
pub := priv.PublicKey()
|
|
||||||
roundtrip, err := ParsePublicKey(pub.Marshal())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("ParsePublicKey(%T): %v", pub, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
k1 := rawKey(pub)
|
|
||||||
k2 := rawKey(roundtrip)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(k1, k2) {
|
|
||||||
t.Errorf("got %#v in roundtrip, want %#v", k2, k1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnsupportedCurves(t *testing.T) {
|
|
||||||
raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") {
|
|
||||||
t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") {
|
|
||||||
t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewPublicKey(t *testing.T) {
|
|
||||||
for _, k := range testSigners {
|
|
||||||
raw := rawKey(k.PublicKey())
|
|
||||||
// Skip certificates, as NewPublicKey does not support them.
|
|
||||||
if _, ok := raw.(*Certificate); ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pub, err := NewPublicKey(raw)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("NewPublicKey(%#v): %v", raw, err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(k.PublicKey(), pub) {
|
|
||||||
t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKeySignVerify(t *testing.T) {
|
|
||||||
for _, priv := range testSigners {
|
|
||||||
pub := priv.PublicKey()
|
|
||||||
|
|
||||||
data := []byte("sign me")
|
|
||||||
sig, err := priv.Sign(rand.Reader, data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Sign(%T): %v", priv, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := pub.Verify(data, sig); err != nil {
|
|
||||||
t.Errorf("publicKey.Verify(%T): %v", priv, err)
|
|
||||||
}
|
|
||||||
sig.Blob[5]++
|
|
||||||
if err := pub.Verify(data, sig); err == nil {
|
|
||||||
t.Errorf("publicKey.Verify on broken sig did not fail")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseRSAPrivateKey(t *testing.T) {
|
|
||||||
key := testPrivateKeys["rsa"]
|
|
||||||
|
|
||||||
rsa, ok := key.(*rsa.PrivateKey)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("got %T, want *rsa.PrivateKey", rsa)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := rsa.Validate(); err != nil {
|
|
||||||
t.Errorf("Validate: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseECPrivateKey(t *testing.T) {
|
|
||||||
key := testPrivateKeys["ecdsa"]
|
|
||||||
|
|
||||||
ecKey, ok := key.(*ecdsa.PrivateKey)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) {
|
|
||||||
t.Fatalf("public key does not validate.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See Issue https://github.com/golang/go/issues/6650.
|
|
||||||
func TestParseEncryptedPrivateKeysFails(t *testing.T) {
|
|
||||||
const wantSubstring = "encrypted"
|
|
||||||
for i, tt := range testdata.PEMEncryptedKeys {
|
|
||||||
_, err := ParsePrivateKey(tt.PEMBytes)
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("#%d key %s: ParsePrivateKey successfully parsed, expected an error", i, tt.Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), wantSubstring) {
|
|
||||||
t.Errorf("#%d key %s: got error %q, want substring %q", i, tt.Name, err, wantSubstring)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseDSA(t *testing.T) {
|
|
||||||
// We actually exercise the ParsePrivateKey codepath here, as opposed to
|
|
||||||
// using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
|
|
||||||
// uses.
|
|
||||||
s, err := ParsePrivateKey(testdata.PEMBytes["dsa"])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ParsePrivateKey returned error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
data := []byte("sign me")
|
|
||||||
sig, err := s.Sign(rand.Reader, data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("dsa.Sign: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.PublicKey().Verify(data, sig); err != nil {
|
|
||||||
t.Errorf("Verify failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests for authorized_keys parsing.
|
|
||||||
|
|
||||||
// getTestKey returns a public key, and its base64 encoding.
|
|
||||||
func getTestKey() (PublicKey, string) {
|
|
||||||
k := testPublicKeys["rsa"]
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
e := base64.NewEncoder(base64.StdEncoding, b)
|
|
||||||
e.Write(k.Marshal())
|
|
||||||
e.Close()
|
|
||||||
|
|
||||||
return k, b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMarshalParsePublicKey(t *testing.T) {
|
|
||||||
pub, pubSerialized := getTestKey()
|
|
||||||
line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized)
|
|
||||||
|
|
||||||
authKeys := MarshalAuthorizedKey(pub)
|
|
||||||
actualFields := strings.Fields(string(authKeys))
|
|
||||||
if len(actualFields) == 0 {
|
|
||||||
t.Fatalf("failed authKeys: %v", authKeys)
|
|
||||||
}
|
|
||||||
|
|
||||||
// drop the comment
|
|
||||||
expectedFields := strings.Fields(line)[0:2]
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(actualFields, expectedFields) {
|
|
||||||
t.Errorf("got %v, expected %v", actualFields, expectedFields)
|
|
||||||
}
|
|
||||||
|
|
||||||
actPub, _, _, _, err := ParseAuthorizedKey([]byte(line))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("cannot parse %v: %v", line, err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(actPub, pub) {
|
|
||||||
t.Errorf("got %v, expected %v", actPub, pub)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type authResult struct {
|
|
||||||
pubKey PublicKey
|
|
||||||
options []string
|
|
||||||
comments string
|
|
||||||
rest string
|
|
||||||
ok bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) {
|
|
||||||
rest := authKeys
|
|
||||||
var values []authResult
|
|
||||||
for len(rest) > 0 {
|
|
||||||
var r authResult
|
|
||||||
var err error
|
|
||||||
r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest)
|
|
||||||
r.ok = (err == nil)
|
|
||||||
t.Log(err)
|
|
||||||
r.rest = string(rest)
|
|
||||||
values = append(values, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(values, expected) {
|
|
||||||
t.Errorf("got %#v, expected %#v", values, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthorizedKeyBasic(t *testing.T) {
|
|
||||||
pub, pubSerialized := getTestKey()
|
|
||||||
line := "ssh-rsa " + pubSerialized + " user@host"
|
|
||||||
testAuthorizedKeys(t, []byte(line),
|
|
||||||
[]authResult{
|
|
||||||
{pub, nil, "user@host", "", true},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuth(t *testing.T) {
|
|
||||||
pub, pubSerialized := getTestKey()
|
|
||||||
authWithOptions := []string{
|
|
||||||
`# comments to ignore before any keys...`,
|
|
||||||
``,
|
|
||||||
`env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`,
|
|
||||||
`# comments to ignore, along with a blank line`,
|
|
||||||
``,
|
|
||||||
`env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`,
|
|
||||||
``,
|
|
||||||
`# more comments, plus a invalid entry`,
|
|
||||||
`ssh-rsa data-that-will-not-parse user@host3`,
|
|
||||||
}
|
|
||||||
for _, eol := range []string{"\n", "\r\n"} {
|
|
||||||
authOptions := strings.Join(authWithOptions, eol)
|
|
||||||
rest2 := strings.Join(authWithOptions[3:], eol)
|
|
||||||
rest3 := strings.Join(authWithOptions[6:], eol)
|
|
||||||
testAuthorizedKeys(t, []byte(authOptions), []authResult{
|
|
||||||
{pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true},
|
|
||||||
{pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true},
|
|
||||||
{nil, nil, "", "", false},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthWithQuotedSpaceInEnv(t *testing.T) {
|
|
||||||
pub, pubSerialized := getTestKey()
|
|
||||||
authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
|
|
||||||
testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{
|
|
||||||
{pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthWithQuotedCommaInEnv(t *testing.T) {
|
|
||||||
pub, pubSerialized := getTestKey()
|
|
||||||
authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
|
|
||||||
testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{
|
|
||||||
{pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthWithQuotedQuoteInEnv(t *testing.T) {
|
|
||||||
pub, pubSerialized := getTestKey()
|
|
||||||
authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`)
|
|
||||||
authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`)
|
|
||||||
testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{
|
|
||||||
{pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true},
|
|
||||||
})
|
|
||||||
|
|
||||||
testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{
|
|
||||||
{pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthWithInvalidSpace(t *testing.T) {
|
|
||||||
_, pubSerialized := getTestKey()
|
|
||||||
authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
|
|
||||||
#more to follow but still no valid keys`)
|
|
||||||
testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{
|
|
||||||
{nil, nil, "", "", false},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthWithMissingQuote(t *testing.T) {
|
|
||||||
pub, pubSerialized := getTestKey()
|
|
||||||
authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
|
|
||||||
env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`)
|
|
||||||
|
|
||||||
testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{
|
|
||||||
{pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInvalidEntry(t *testing.T) {
|
|
||||||
authInvalid := []byte(`ssh-rsa`)
|
|
||||||
_, _, _, _, err := ParseAuthorizedKey(authInvalid)
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("got valid entry for %q", authInvalid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var knownHostsParseTests = []struct {
|
|
||||||
input string
|
|
||||||
err string
|
|
||||||
|
|
||||||
marker string
|
|
||||||
comment string
|
|
||||||
hosts []string
|
|
||||||
rest string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"",
|
|
||||||
"EOF",
|
|
||||||
|
|
||||||
"", "", nil, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"# Just a comment",
|
|
||||||
"EOF",
|
|
||||||
|
|
||||||
"", "", nil, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
" \t ",
|
|
||||||
"EOF",
|
|
||||||
|
|
||||||
"", "", nil, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"localhost ssh-rsa {RSAPUB}",
|
|
||||||
"",
|
|
||||||
|
|
||||||
"", "", []string{"localhost"}, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"localhost\tssh-rsa {RSAPUB}",
|
|
||||||
"",
|
|
||||||
|
|
||||||
"", "", []string{"localhost"}, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"localhost\tssh-rsa {RSAPUB}\tcomment comment",
|
|
||||||
"",
|
|
||||||
|
|
||||||
"", "comment comment", []string{"localhost"}, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"localhost\tssh-rsa {RSAPUB}\tcomment comment\n",
|
|
||||||
"",
|
|
||||||
|
|
||||||
"", "comment comment", []string{"localhost"}, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n",
|
|
||||||
"",
|
|
||||||
|
|
||||||
"", "comment comment", []string{"localhost"}, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line",
|
|
||||||
"",
|
|
||||||
|
|
||||||
"", "comment comment", []string{"localhost"}, "next line",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment",
|
|
||||||
"",
|
|
||||||
|
|
||||||
"", "comment comment", []string{"localhost", "[host2:123]"}, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}",
|
|
||||||
"",
|
|
||||||
|
|
||||||
"marker", "", []string{"localhost", "[host2:123]"}, "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd",
|
|
||||||
"short read",
|
|
||||||
|
|
||||||
"", "", nil, "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKnownHostsParsing(t *testing.T) {
|
|
||||||
rsaPub, rsaPubSerialized := getTestKey()
|
|
||||||
|
|
||||||
for i, test := range knownHostsParseTests {
|
|
||||||
var expectedKey PublicKey
|
|
||||||
const rsaKeyToken = "{RSAPUB}"
|
|
||||||
|
|
||||||
input := test.input
|
|
||||||
if strings.Contains(input, rsaKeyToken) {
|
|
||||||
expectedKey = rsaPub
|
|
||||||
input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input))
|
|
||||||
if err != nil {
|
|
||||||
if len(test.err) == 0 {
|
|
||||||
t.Errorf("#%d: unexpectedly failed with %q", i, err)
|
|
||||||
} else if !strings.Contains(err.Error(), test.err) {
|
|
||||||
t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
} else if len(test.err) != 0 {
|
|
||||||
t.Errorf("#%d: succeeded but expected error including %q", i, test.err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(expectedKey, pubKey) {
|
|
||||||
t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
if marker != test.marker {
|
|
||||||
t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker)
|
|
||||||
}
|
|
||||||
|
|
||||||
if comment != test.comment {
|
|
||||||
t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(test.hosts, hosts) {
|
|
||||||
t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rest := string(rest); rest != test.rest {
|
|
||||||
t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
10
vendor/golang.org/x/crypto/ssh/mac.go
generated
vendored
10
vendor/golang.org/x/crypto/ssh/mac.go
generated
vendored
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
type macMode struct {
|
type macMode struct {
|
||||||
keySize int
|
keySize int
|
||||||
|
etm bool
|
||||||
new func(key []byte) hash.Hash
|
new func(key []byte) hash.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,13 +46,16 @@ func (t truncatingMAC) Size() int {
|
|||||||
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
||||||
|
|
||||||
var macModes = map[string]*macMode{
|
var macModes = map[string]*macMode{
|
||||||
"hmac-sha2-256": {32, func(key []byte) hash.Hash {
|
"hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
|
||||||
return hmac.New(sha256.New, key)
|
return hmac.New(sha256.New, key)
|
||||||
}},
|
}},
|
||||||
"hmac-sha1": {20, func(key []byte) hash.Hash {
|
"hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
|
||||||
|
return hmac.New(sha256.New, key)
|
||||||
|
}},
|
||||||
|
"hmac-sha1": {20, false, func(key []byte) hash.Hash {
|
||||||
return hmac.New(sha1.New, key)
|
return hmac.New(sha1.New, key)
|
||||||
}},
|
}},
|
||||||
"hmac-sha1-96": {20, func(key []byte) hash.Hash {
|
"hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
|
||||||
return truncatingMAC{12, hmac.New(sha1.New, key)}
|
return truncatingMAC{12, hmac.New(sha1.New, key)}
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
110
vendor/golang.org/x/crypto/ssh/mempipe_test.go
generated
vendored
110
vendor/golang.org/x/crypto/ssh/mempipe_test.go
generated
vendored
@ -1,110 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// An in-memory packetConn. It is safe to call Close and writePacket
|
|
||||||
// from different goroutines.
|
|
||||||
type memTransport struct {
|
|
||||||
eof bool
|
|
||||||
pending [][]byte
|
|
||||||
write *memTransport
|
|
||||||
sync.Mutex
|
|
||||||
*sync.Cond
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *memTransport) readPacket() ([]byte, error) {
|
|
||||||
t.Lock()
|
|
||||||
defer t.Unlock()
|
|
||||||
for {
|
|
||||||
if len(t.pending) > 0 {
|
|
||||||
r := t.pending[0]
|
|
||||||
t.pending = t.pending[1:]
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
if t.eof {
|
|
||||||
return nil, io.EOF
|
|
||||||
}
|
|
||||||
t.Cond.Wait()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *memTransport) closeSelf() error {
|
|
||||||
t.Lock()
|
|
||||||
defer t.Unlock()
|
|
||||||
if t.eof {
|
|
||||||
return io.EOF
|
|
||||||
}
|
|
||||||
t.eof = true
|
|
||||||
t.Cond.Broadcast()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *memTransport) Close() error {
|
|
||||||
err := t.write.closeSelf()
|
|
||||||
t.closeSelf()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *memTransport) writePacket(p []byte) error {
|
|
||||||
t.write.Lock()
|
|
||||||
defer t.write.Unlock()
|
|
||||||
if t.write.eof {
|
|
||||||
return io.EOF
|
|
||||||
}
|
|
||||||
c := make([]byte, len(p))
|
|
||||||
copy(c, p)
|
|
||||||
t.write.pending = append(t.write.pending, c)
|
|
||||||
t.write.Cond.Signal()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func memPipe() (a, b packetConn) {
|
|
||||||
t1 := memTransport{}
|
|
||||||
t2 := memTransport{}
|
|
||||||
t1.write = &t2
|
|
||||||
t2.write = &t1
|
|
||||||
t1.Cond = sync.NewCond(&t1.Mutex)
|
|
||||||
t2.Cond = sync.NewCond(&t2.Mutex)
|
|
||||||
return &t1, &t2
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMemPipe(t *testing.T) {
|
|
||||||
a, b := memPipe()
|
|
||||||
if err := a.writePacket([]byte{42}); err != nil {
|
|
||||||
t.Fatalf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
if err := a.Close(); err != nil {
|
|
||||||
t.Fatal("Close: ", err)
|
|
||||||
}
|
|
||||||
p, err := b.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("readPacket: ", err)
|
|
||||||
}
|
|
||||||
if len(p) != 1 || p[0] != 42 {
|
|
||||||
t.Fatalf("got %v, want {42}", p)
|
|
||||||
}
|
|
||||||
p, err = b.readPacket()
|
|
||||||
if err != io.EOF {
|
|
||||||
t.Fatalf("got %v, %v, want EOF", p, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDoubleClose(t *testing.T) {
|
|
||||||
a, _ := memPipe()
|
|
||||||
err := a.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Close: %v", err)
|
|
||||||
}
|
|
||||||
err = a.Close()
|
|
||||||
if err != io.EOF {
|
|
||||||
t.Errorf("expect EOF on double close.")
|
|
||||||
}
|
|
||||||
}
|
|
288
vendor/golang.org/x/crypto/ssh/messages_test.go
generated
vendored
288
vendor/golang.org/x/crypto/ssh/messages_test.go
generated
vendored
@ -1,288 +0,0 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"math/big"
|
|
||||||
"math/rand"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
"testing/quick"
|
|
||||||
)
|
|
||||||
|
|
||||||
var intLengthTests = []struct {
|
|
||||||
val, length int
|
|
||||||
}{
|
|
||||||
{0, 4 + 0},
|
|
||||||
{1, 4 + 1},
|
|
||||||
{127, 4 + 1},
|
|
||||||
{128, 4 + 2},
|
|
||||||
{-1, 4 + 1},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntLength(t *testing.T) {
|
|
||||||
for _, test := range intLengthTests {
|
|
||||||
v := new(big.Int).SetInt64(int64(test.val))
|
|
||||||
length := intLength(v)
|
|
||||||
if length != test.length {
|
|
||||||
t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type msgAllTypes struct {
|
|
||||||
Bool bool `sshtype:"21"`
|
|
||||||
Array [16]byte
|
|
||||||
Uint64 uint64
|
|
||||||
Uint32 uint32
|
|
||||||
Uint8 uint8
|
|
||||||
String string
|
|
||||||
Strings []string
|
|
||||||
Bytes []byte
|
|
||||||
Int *big.Int
|
|
||||||
Rest []byte `ssh:"rest"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value {
|
|
||||||
m := &msgAllTypes{}
|
|
||||||
m.Bool = rand.Intn(2) == 1
|
|
||||||
randomBytes(m.Array[:], rand)
|
|
||||||
m.Uint64 = uint64(rand.Int63n(1<<63 - 1))
|
|
||||||
m.Uint32 = uint32(rand.Intn((1 << 31) - 1))
|
|
||||||
m.Uint8 = uint8(rand.Intn(1 << 8))
|
|
||||||
m.String = string(m.Array[:])
|
|
||||||
m.Strings = randomNameList(rand)
|
|
||||||
m.Bytes = m.Array[:]
|
|
||||||
m.Int = randomInt(rand)
|
|
||||||
m.Rest = m.Array[:]
|
|
||||||
return reflect.ValueOf(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMarshalUnmarshal(t *testing.T) {
|
|
||||||
rand := rand.New(rand.NewSource(0))
|
|
||||||
iface := &msgAllTypes{}
|
|
||||||
ty := reflect.ValueOf(iface).Type()
|
|
||||||
|
|
||||||
n := 100
|
|
||||||
if testing.Short() {
|
|
||||||
n = 5
|
|
||||||
}
|
|
||||||
for j := 0; j < n; j++ {
|
|
||||||
v, ok := quick.Value(ty, rand)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("failed to create value")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
m1 := v.Elem().Interface()
|
|
||||||
m2 := iface
|
|
||||||
|
|
||||||
marshaled := Marshal(m1)
|
|
||||||
if err := Unmarshal(marshaled, m2); err != nil {
|
|
||||||
t.Errorf("Unmarshal %#v: %s", m1, err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(v.Interface(), m2) {
|
|
||||||
t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshalEmptyPacket(t *testing.T) {
|
|
||||||
var b []byte
|
|
||||||
var m channelRequestSuccessMsg
|
|
||||||
if err := Unmarshal(b, &m); err == nil {
|
|
||||||
t.Fatalf("unmarshal of empty slice succeeded")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshalUnexpectedPacket(t *testing.T) {
|
|
||||||
type S struct {
|
|
||||||
I uint32 `sshtype:"43"`
|
|
||||||
S string
|
|
||||||
B bool
|
|
||||||
}
|
|
||||||
|
|
||||||
s := S{11, "hello", true}
|
|
||||||
packet := Marshal(s)
|
|
||||||
packet[0] = 42
|
|
||||||
roundtrip := S{}
|
|
||||||
err := Unmarshal(packet, &roundtrip)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error, not nil")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMarshalPtr(t *testing.T) {
|
|
||||||
s := struct {
|
|
||||||
S string
|
|
||||||
}{"hello"}
|
|
||||||
|
|
||||||
m1 := Marshal(s)
|
|
||||||
m2 := Marshal(&s)
|
|
||||||
if !bytes.Equal(m1, m2) {
|
|
||||||
t.Errorf("got %q, want %q for marshaled pointer", m2, m1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBareMarshalUnmarshal(t *testing.T) {
|
|
||||||
type S struct {
|
|
||||||
I uint32
|
|
||||||
S string
|
|
||||||
B bool
|
|
||||||
}
|
|
||||||
|
|
||||||
s := S{42, "hello", true}
|
|
||||||
packet := Marshal(s)
|
|
||||||
roundtrip := S{}
|
|
||||||
Unmarshal(packet, &roundtrip)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(s, roundtrip) {
|
|
||||||
t.Errorf("got %#v, want %#v", roundtrip, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBareMarshal(t *testing.T) {
|
|
||||||
type S2 struct {
|
|
||||||
I uint32
|
|
||||||
}
|
|
||||||
s := S2{42}
|
|
||||||
packet := Marshal(s)
|
|
||||||
i, rest, ok := parseUint32(packet)
|
|
||||||
if len(rest) > 0 || !ok {
|
|
||||||
t.Errorf("parseInt(%q): parse error", packet)
|
|
||||||
}
|
|
||||||
if i != s.I {
|
|
||||||
t.Errorf("got %d, want %d", i, s.I)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshalShortKexInitPacket(t *testing.T) {
|
|
||||||
// This used to panic.
|
|
||||||
// Issue 11348
|
|
||||||
packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff}
|
|
||||||
kim := &kexInitMsg{}
|
|
||||||
if err := Unmarshal(packet, kim); err == nil {
|
|
||||||
t.Error("truncated packet unmarshaled without error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMarshalMultiTag(t *testing.T) {
|
|
||||||
var res struct {
|
|
||||||
A uint32 `sshtype:"1|2"`
|
|
||||||
}
|
|
||||||
|
|
||||||
good1 := struct {
|
|
||||||
A uint32 `sshtype:"1"`
|
|
||||||
}{
|
|
||||||
1,
|
|
||||||
}
|
|
||||||
good2 := struct {
|
|
||||||
A uint32 `sshtype:"2"`
|
|
||||||
}{
|
|
||||||
1,
|
|
||||||
}
|
|
||||||
|
|
||||||
if e := Unmarshal(Marshal(good1), &res); e != nil {
|
|
||||||
t.Errorf("error unmarshaling multipart tag: %v", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
if e := Unmarshal(Marshal(good2), &res); e != nil {
|
|
||||||
t.Errorf("error unmarshaling multipart tag: %v", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
bad1 := struct {
|
|
||||||
A uint32 `sshtype:"3"`
|
|
||||||
}{
|
|
||||||
1,
|
|
||||||
}
|
|
||||||
if e := Unmarshal(Marshal(bad1), &res); e == nil {
|
|
||||||
t.Errorf("bad struct unmarshaled without error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func randomBytes(out []byte, rand *rand.Rand) {
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
out[i] = byte(rand.Int31())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func randomNameList(rand *rand.Rand) []string {
|
|
||||||
ret := make([]string, rand.Int31()&15)
|
|
||||||
for i := range ret {
|
|
||||||
s := make([]byte, 1+(rand.Int31()&15))
|
|
||||||
for j := range s {
|
|
||||||
s[j] = 'a' + uint8(rand.Int31()&15)
|
|
||||||
}
|
|
||||||
ret[i] = string(s)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func randomInt(rand *rand.Rand) *big.Int {
|
|
||||||
return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
|
||||||
ki := &kexInitMsg{}
|
|
||||||
randomBytes(ki.Cookie[:], rand)
|
|
||||||
ki.KexAlgos = randomNameList(rand)
|
|
||||||
ki.ServerHostKeyAlgos = randomNameList(rand)
|
|
||||||
ki.CiphersClientServer = randomNameList(rand)
|
|
||||||
ki.CiphersServerClient = randomNameList(rand)
|
|
||||||
ki.MACsClientServer = randomNameList(rand)
|
|
||||||
ki.MACsServerClient = randomNameList(rand)
|
|
||||||
ki.CompressionClientServer = randomNameList(rand)
|
|
||||||
ki.CompressionServerClient = randomNameList(rand)
|
|
||||||
ki.LanguagesClientServer = randomNameList(rand)
|
|
||||||
ki.LanguagesServerClient = randomNameList(rand)
|
|
||||||
if rand.Int31()&1 == 1 {
|
|
||||||
ki.FirstKexFollows = true
|
|
||||||
}
|
|
||||||
return reflect.ValueOf(ki)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
|
||||||
dhi := &kexDHInitMsg{}
|
|
||||||
dhi.X = randomInt(rand)
|
|
||||||
return reflect.ValueOf(dhi)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
_kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
|
|
||||||
_kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
|
|
||||||
|
|
||||||
_kexInit = Marshal(_kexInitMsg)
|
|
||||||
_kexDHInit = Marshal(_kexDHInitMsg)
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkMarshalKexInitMsg(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Marshal(_kexInitMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkUnmarshalKexInitMsg(b *testing.B) {
|
|
||||||
m := new(kexInitMsg)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Unmarshal(_kexInit, m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMarshalKexDHInitMsg(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Marshal(_kexDHInitMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) {
|
|
||||||
m := new(kexDHInitMsg)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Unmarshal(_kexDHInit, m)
|
|
||||||
}
|
|
||||||
}
|
|
4
vendor/golang.org/x/crypto/ssh/mux.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/mux.go
generated
vendored
@ -116,9 +116,9 @@ func (m *mux) Wait() error {
|
|||||||
func newMux(p packetConn) *mux {
|
func newMux(p packetConn) *mux {
|
||||||
m := &mux{
|
m := &mux{
|
||||||
conn: p,
|
conn: p,
|
||||||
incomingChannels: make(chan NewChannel, 16),
|
incomingChannels: make(chan NewChannel, chanSize),
|
||||||
globalResponses: make(chan interface{}, 1),
|
globalResponses: make(chan interface{}, 1),
|
||||||
incomingRequests: make(chan *Request, 16),
|
incomingRequests: make(chan *Request, chanSize),
|
||||||
errCond: newCond(),
|
errCond: newCond(),
|
||||||
}
|
}
|
||||||
if debugMux {
|
if debugMux {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user