diff --git a/go.mod b/go.mod index 1120cee..750c887 100644 --- a/go.mod +++ b/go.mod @@ -6,34 +6,35 @@ require ( code.gitea.io/gitea-vet v0.2.1 code.gitea.io/sdk/gitea v0.15.0 gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b - github.com/AlecAivazis/survey/v2 v2.2.8 - github.com/Microsoft/go-winio v0.4.16 // indirect - github.com/adrg/xdg v0.3.1 - github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e - github.com/charmbracelet/glamour v0.2.0 - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/go-git/go-git/v5 v5.2.0 + github.com/AlecAivazis/survey/v2 v2.3.1 + github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c // indirect + github.com/adrg/xdg v0.3.3 + github.com/alecthomas/chroma v0.9.2 // indirect + github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de + github.com/charmbracelet/glamour v0.3.0 + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/go-git/go-git/v5 v5.4.2 github.com/hashicorp/go-version v1.3.0 // indirect - github.com/imdario/mergo v0.3.11 // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/kevinburke/ssh_config v1.1.0 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect - github.com/muesli/termenv v0.7.4 + github.com/microcosm-cc/bluemonday v1.0.15 // indirect + github.com/muesli/reflow v0.3.0 // indirect + github.com/muesli/termenv v0.9.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/rivo/uniseg v0.2.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sergi/go-diff v1.2.0 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/stretchr/testify v1.7.0 github.com/urfave/cli/v2 v2.3.0 - github.com/xanzy/ssh-agent v0.3.0 // indirect - golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect - golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3 // indirect - golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect - golang.org/x/text v0.3.5 // indirect - golang.org/x/tools v0.1.0 // indirect + github.com/xanzy/ssh-agent v0.3.1 // indirect + github.com/yuin/goldmark v1.4.0 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 + golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect + golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect + golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/tools v0.1.5 // indirect gopkg.in/yaml.v2 v2.4.0 ) -replace github.com/charmbracelet/glamour => github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2 +replace github.com/charmbracelet/glamour => github.com/noerw/glamour v0.3.0-patch diff --git a/go.sum b/go.sum index 8fa0cab..4e7d80c 100644 --- a/go.sum +++ b/go.sum @@ -4,22 +4,27 @@ code.gitea.io/sdk/gitea v0.15.0 h1:tsNhxDM/2N1Ohv1Xq5UWrht/esg0WmtRj4wsHVHriTg= code.gitea.io/sdk/gitea v0.15.0/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA= gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b h1:CLYsMGcGLohESQDMth+RgJ4cB3CCHToxnj0zBbvB3sE= gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b/go.mod h1:Fc8iyPm4NINRWujeIk2bTfcbGc4ZYY29/oMAAGcr4qI= -github.com/AlecAivazis/survey/v2 v2.2.8 h1:TgxCwybKdBckmC+/P9/5h49rw/nAHe/itZL0dgHs+Q0= -github.com/AlecAivazis/survey/v2 v2.2.8/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= +github.com/AlecAivazis/survey/v2 v2.3.1 h1:lzkuHA60pER7L4eYL8qQJor4bUWlJe4V0gqAT19tdOA= +github.com/AlecAivazis/survey/v2 v2.3.1/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= -github.com/adrg/xdg v0.3.1 h1:uIyL9BYfXaFgDyVRKE8wjtm6ETQULweQqTofphEFJYY= -github.com/adrg/xdg v0.3.1/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c h1:FP7mMdsXy0ybzar1sJeIcZtaJka0U/ZmLTW4wRpolYk= +github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= +github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/adrg/xdg v0.3.3 h1:s/tV7MdqQnzB1nKY8aqHvAMD+uCiuEDzVB5HLRY849U= +github.com/adrg/xdg v0.3.3/go.mod h1:61xAR2VZcggl2St4O9ohF5qCKe08+JDmE4VNzPFQvOQ= github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U= github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI= -github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE= -github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM= +github.com/alecthomas/chroma v0.8.2/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM= +github.com/alecthomas/chroma v0.9.2 h1:yU1sE2+TZbLIQPMk30SolL2Hn53SR/Pv750f7qZ/XMs= +github.com/alecthomas/chroma v0.9.2/go.mod h1:eMuEnpA18XbG/WhOWtCzJHS7WqEtDAI+HxdwoW0nVSk= github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo= github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0= github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE= @@ -27,25 +32,25 @@ github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkx github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e h1:OjdSMCht0ZVX7IH0nTdf00xEustvbtUGRgMh3gbdmOg= -github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw= +github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA= +github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU= -github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= @@ -54,12 +59,13 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= -github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= -github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= -github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI= -github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= +github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= +github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= +github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= +github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= @@ -69,55 +75,60 @@ github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04 github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o= +github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg= -github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w= +github.com/microcosm-cc/bluemonday v1.0.6/go.mod h1:HOT/6NaBlR0f9XlxD3zolN6Z3N8Lp4pvhp+jLS5ihnI= +github.com/microcosm-cc/bluemonday v1.0.15 h1:J4uN+qPng9rvkBZBoBb8YGR+ijuklIMpSOZZLjYpbeY= +github.com/microcosm-cc/bluemonday v1.0.15/go.mod h1:ZLvAzeakRwrGnzQEvstVzVt3ZpqOF2+sdFr0Om+ce30= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/muesli/reflow v0.2.0 h1:2o0UBJPHHH4fa2GCXU4Rg4DwOtWPMekCeyc5EWbAQp0= github.com/muesli/reflow v0.2.0/go.mod h1:qT22vjVmM9MIUeLgsVYe/Ye7eZlbv9dZjL3dVhUqLX8= -github.com/muesli/termenv v0.7.4 h1:/pBqvU5CpkY53tU0vVn+xgs2ZTX63aH5nY+SSps5Xa8= -github.com/muesli/termenv v0.7.4/go.mod h1:pZ7qY9l3F7e5xsAOS0zCew2tME+p7bWeBkotCEcIIcc= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= +github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= +github.com/muesli/termenv v0.8.1/go.mod h1:kzt/D/4a88RoheZmwfqorY3A+tnsSMA9HJC/fQSFKo0= +github.com/muesli/termenv v0.9.0 h1:wnbOaGz+LUR3jNT0zOzinPnyDaCZUQRZj9GxK8eRVl8= +github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtlyx2mBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2 h1:ACjOTGUGi7rt3JQU9GIFFs8sueFGShy6GcGjQhMmKjs= -github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2/go.mod h1:WIVFX8Y2VIK1Y/1qtXYL/Vvzqlcbo3VgVop9i2piPkE= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/noerw/glamour v0.3.0-patch h1:yc3wdbUIySok6KYeX5BtWnlj+PvP1uYeCeTSwq2rtSw= +github.com/noerw/glamour v0.3.0-patch/go.mod h1:TzF0koPZhqq0YVBNL100cPHznAAjVj7fksX2RInwjGw= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -135,10 +146,12 @@ github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7 github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597 h1:nZY1S2jo+VtDrUfjO9XYI137O41hhRkxZNV5Fb5ixCA= github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597/go.mod h1:F8CBHSOjnzjx9EeXyWJTAzJyVxN+Y8JH2WjLMn4utiw= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -147,74 +160,83 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= +github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.1 h1:eVwehsLsZlCJCwXyGLgg+Q4iFWE/eTIMG0e8waCmm/I= -github.com/yuin/goldmark v1.3.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.3.3/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0 h1:OtISOGfH6sOWa1/qXqqAiOIAO6Z5J3AEAE18WAq6BiQ= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os= github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= +golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3 h1:RdE7htvBru4I4VZQofQjCZk5W9+aLNlSF5n0zgVwm8s= -golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -222,8 +244,9 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/AlecAivazis/survey/v2/README.md b/vendor/github.com/AlecAivazis/survey/v2/README.md index 4569ad7..d2d76c1 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/README.md +++ b/vendor/github.com/AlecAivazis/survey/v2/README.md @@ -3,7 +3,7 @@ [![Build Status](https://travis-ci.org/AlecAivazis/survey.svg?branch=feature%2Fpretty)](https://travis-ci.org/AlecAivazis/survey) [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg)](https://pkg.go.dev/github.com/AlecAivazis/survey/v2) -A library for building interactive prompts. +A library for building interactive and accessible prompts on terminals supporting ANSI escape sequences. @@ -295,7 +295,7 @@ survey.AskOne(prompt, &color, survey.WithFilter(myFilter)) ## Keeping the filter active -By default the filter will disappear if the user selects one of the filtered elements. Once the user selects one element the filter setting is gone. +By default the filter will disappear if the user selects one of the filtered elements. Once the user selects one element the filter setting is gone. However the user can prevent this from happening and keep the filter active for multiple selections in a e.g. MultiSelect: @@ -342,11 +342,13 @@ survey.AskOne(prompt, &color, survey.WithValidator(survey.Required)) `survey` comes prepackaged with a few validators to fit common situations. Currently these validators include: -| name | valid types | description | notes | -| ------------ | ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------- | -| Required | any | Rejects zero values of the response type | Boolean values pass straight through since the zero value (false) is a valid response | -| MinLength(n) | string | Enforces that a response is at least the given length | | -| MaxLength(n) | string | Enforces that a response is no longer than the given length | | +| name | valid types | description | notes | +| ------------ | -------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| Required | any | Rejects zero values of the response type | Boolean values pass straight through since the zero value (false) is a valid response | +| MinLength(n) | string | Enforces that a response is at least the given length | | +| MaxLength(n) | string | Enforces that a response is no longer than the given length | | +| MaxItems(n) | []OptionAnswer | Enforces that a response has no more selections of the indicated | | +| MinItems(n) | []OptionAnswer | Enforces that a response has no less selections of the indicated | | ## Help Text @@ -456,6 +458,12 @@ For some examples, you can see any of the tests in this repo. ## FAQ +### What kinds of IO are supported by `survey`? + +survey aims to support most terminal emulators; it expects support for ANSI escape sequences. +This means that reading from piped stdin or writing to piped stdout is **not supported**, +and likely to break your application in these situations. See [#337](https://github.com/AlecAivazis/survey/pull/337#issue-581351617) + ### Why isn't sending a SIGINT (aka. CTRL-C) signal working? When you send an interrupt signal to the process, it only interrupts the current prompt instead of the entire process. This manifests in a `github.com/AlecAivazis/survey/v2/terminal.InterruptErr` being returned from `Ask` and `AskOne`. If you want to stop the process, handle the returned error in your code: diff --git a/vendor/github.com/AlecAivazis/survey/v2/_tasks.hcl b/vendor/github.com/AlecAivazis/survey/v2/_tasks.hcl index ae970f3..0eefcb5 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/_tasks.hcl +++ b/vendor/github.com/AlecAivazis/survey/v2/_tasks.hcl @@ -1,19 +1,19 @@ task "install-deps" { description = "Install all of package dependencies" pipeline = [ - "go get {{.files}}", + "go get -v {{.files}}", ] } task "tests" { description = "Run the test suite" - command = "go test {{.files}}" - environment { + command = "go test -v {{.files}}" + environment = { GOFLAGS = "-mod=vendor" } } -variables { +variables = { files = "$(go list -v ./... | grep -iEv \"tests|examples\")" } diff --git a/vendor/github.com/AlecAivazis/survey/v2/core/template.go b/vendor/github.com/AlecAivazis/survey/v2/core/template.go index 24dade3..6b3d20c 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/core/template.go +++ b/vendor/github.com/AlecAivazis/survey/v2/core/template.go @@ -29,7 +29,7 @@ var TemplateFuncsNoColor = map[string]interface{}{ //for colored output. The second string does not contain escape codes //and can be used by the renderer for layout purposes. func RunTemplate(tmpl string, data interface{}) (string, string, error) { - tPair, err := getTemplatePair(tmpl) + tPair, err := GetTemplatePair(tmpl) if err != nil { return "", "", err } @@ -52,12 +52,12 @@ var ( memoMutex = &sync.RWMutex{} ) -//getTemplatePair returns a pair of compiled templates where the +//GetTemplatePair returns a pair of compiled templates where the //first template is generated for user-facing output and the //second is generated for use by the renderer. The second //template does not contain any color escape codes, whereas //the first template may or may not depending on DisableColor. -func getTemplatePair(tmpl string) ([2]*template.Template, error) { +func GetTemplatePair(tmpl string) ([2]*template.Template, error) { memoMutex.RLock() if t, ok := memoizedGetTemplate[tmpl]; ok { memoMutex.RUnlock() diff --git a/vendor/github.com/AlecAivazis/survey/v2/core/write.go b/vendor/github.com/AlecAivazis/survey/v2/core/write.go index 47d0e49..dfe9b49 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/core/write.go +++ b/vendor/github.com/AlecAivazis/survey/v2/core/write.go @@ -24,6 +24,11 @@ type OptionAnswer struct { Index int } +type reflectField struct { + value reflect.Value + fieldType reflect.StructField +} + func OptionAnswerList(incoming []string) []OptionAnswer { list := []OptionAnswer{} for i, opt := range incoming { @@ -63,13 +68,12 @@ func WriteAnswer(t interface{}, name string, v interface{}) (err error) { } // get the name of the field that matches the string we were given - fieldIndex, err := findFieldIndex(elem, name) + field, _, err := findField(elem, name) // if something went wrong if err != nil { // bubble up return err } - field := elem.Field(fieldIndex) // handle references to the Settable interface aswell if s, ok := field.Interface().(Settable); ok { // use the interface method @@ -156,37 +160,51 @@ func IsFieldNotMatch(err error) (string, bool) { // BUG(AlecAivazis): the current implementation might cause weird conflicts if there are // two fields with same name that only differ by casing. -func findFieldIndex(s reflect.Value, name string) (int, error) { - // the type of the value - sType := s.Type() +func findField(s reflect.Value, name string) (reflect.Value, reflect.StructField, error) { + + fields := flattenFields(s) // first look for matching tags so we can overwrite matching field names - for i := 0; i < sType.NumField(); i++ { - // the field we are current scanning - field := sType.Field(i) - + for _, f := range fields { // the value of the survey tag - tag := field.Tag.Get(tagName) + tag := f.fieldType.Tag.Get(tagName) // if the tag matches the name we are looking for if tag != "" && tag == name { // then we found our index - return i, nil + return f.value, f.fieldType, nil } } // then look for matching names - for i := 0; i < sType.NumField(); i++ { - // the field we are current scanning - field := sType.Field(i) - + for _, f := range fields { // if the name of the field matches what we're looking for - if strings.ToLower(field.Name) == strings.ToLower(name) { - return i, nil + if strings.ToLower(f.fieldType.Name) == strings.ToLower(name) { + return f.value, f.fieldType, nil } } // we didn't find the field - return -1, errFieldNotMatch{name} + return reflect.Value{}, reflect.StructField{}, errFieldNotMatch{name} +} + +func flattenFields(s reflect.Value) []reflectField { + sType := s.Type() + numField := sType.NumField() + fields := make([]reflectField, 0, numField) + for i := 0; i < numField; i++ { + fieldType := sType.Field(i) + field := s.Field(i) + + if field.Kind() == reflect.Struct && fieldType.Anonymous { + // field is a promoted structure + for _, f := range flattenFields(field) { + fields = append(fields, f) + } + continue + } + fields = append(fields, reflectField{field, fieldType}) + } + return fields } // isList returns true if the element is something we can Len() diff --git a/vendor/github.com/AlecAivazis/survey/v2/go.mod b/vendor/github.com/AlecAivazis/survey/v2/go.mod index 81d8521..de87fb9 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/go.mod +++ b/vendor/github.com/AlecAivazis/survey/v2/go.mod @@ -11,9 +11,9 @@ require ( github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.2.1 - golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 - golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1 // indirect - golang.org/x/text v0.3.0 + golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 // indirect + golang.org/x/term v0.0.0-20210503060354-a79de5458b56 + golang.org/x/text v0.3.3 ) go 1.13 diff --git a/vendor/github.com/AlecAivazis/survey/v2/go.sum b/vendor/github.com/AlecAivazis/survey/v2/go.sum index 96af509..93dd6e6 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/go.sum +++ b/vendor/github.com/AlecAivazis/survey/v2/go.sum @@ -25,7 +25,11 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1 h1:R4dVlxdmKenVdMRS/tTspEpSTRWINYrHD8ySIU9yCIU= -golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w= +golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/vendor/github.com/AlecAivazis/survey/v2/input.go b/vendor/github.com/AlecAivazis/survey/v2/input.go index 2e9ad3c..a1abab1 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/input.go +++ b/vendor/github.com/AlecAivazis/survey/v2/input.go @@ -1,6 +1,8 @@ package survey import ( + "errors" + "github.com/AlecAivazis/survey/v2/core" "github.com/AlecAivazis/survey/v2/terminal" ) @@ -19,8 +21,8 @@ type Input struct { Default string Help string Suggest func(toComplete string) []string - typedAnswer string answer string + typedAnswer string options []core.OptionAnswer selectedIndex int showingHelp bool @@ -58,86 +60,90 @@ var InputQuestionTemplate = ` {{- if and .Suggest }}{{color "cyan"}}{{ print .Config.SuggestInput }} for suggestions{{end -}} ]{{color "reset"}} {{end}} {{- if .Default}}{{color "white"}}({{.Default}}) {{color "reset"}}{{end}} - {{- .Answer -}} {{- end}}` -func (i *Input) OnChange(key rune, config *PromptConfig) (bool, error) { - if key == terminal.KeyEnter || key == '\n' { - if i.answer != config.HelpInput || i.Help == "" { - // we're done - return true, nil - } else { - i.answer = "" - i.showingHelp = true - } - } else if key == terminal.KeyDeleteWord || key == terminal.KeyDeleteLine { - i.answer = "" - } else if key == terminal.KeyEscape && i.Suggest != nil { - if len(i.options) > 0 { +func (i *Input) onRune(config *PromptConfig) terminal.OnRuneFn { + return terminal.OnRuneFn(func(key rune, line []rune) ([]rune, bool, error) { + if i.options != nil && (key == terminal.KeyEnter || key == '\n') { + return []rune(i.answer), true, nil + } else if i.options != nil && key == terminal.KeyEscape { i.answer = i.typedAnswer - } - i.options = nil - } else if key == terminal.KeyArrowUp && len(i.options) > 0 { - if i.selectedIndex == 0 { - i.selectedIndex = len(i.options) - 1 - } else { - i.selectedIndex-- - } - i.answer = i.options[i.selectedIndex].Value - } else if (key == terminal.KeyArrowDown || key == terminal.KeyTab) && len(i.options) > 0 { - if i.selectedIndex == len(i.options)-1 { + i.options = nil + } else if key == terminal.KeyArrowUp && len(i.options) > 0 { + if i.selectedIndex == 0 { + i.selectedIndex = len(i.options) - 1 + } else { + i.selectedIndex-- + } + i.answer = i.options[i.selectedIndex].Value + } else if (key == terminal.KeyArrowDown || key == terminal.KeyTab) && len(i.options) > 0 { + if i.selectedIndex == len(i.options)-1 { + i.selectedIndex = 0 + } else { + i.selectedIndex++ + } + i.answer = i.options[i.selectedIndex].Value + } else if key == terminal.KeyTab && i.Suggest != nil { + i.answer = string(line) + i.typedAnswer = i.answer + options := i.Suggest(i.answer) i.selectedIndex = 0 - } else { - i.selectedIndex++ - } - i.answer = i.options[i.selectedIndex].Value - } else if key == terminal.KeyTab && i.Suggest != nil { - options := i.Suggest(i.answer) - i.selectedIndex = 0 - i.typedAnswer = i.answer - if len(options) > 0 { + if len(options) == 0 { + return line, false, nil + } + i.answer = options[0] if len(options) == 1 { + i.typedAnswer = i.answer i.options = nil } else { i.options = core.OptionAnswerList(options) } - } - } else if key == terminal.KeyDelete || key == terminal.KeyBackspace { - if i.answer != "" { - runeAnswer := []rune(i.answer) - i.answer = string(runeAnswer[0 : len(runeAnswer)-1]) - } - } else if key >= terminal.KeySpace { - i.answer += string(key) - i.typedAnswer = i.answer - i.options = nil - } + } else { + if i.options == nil { + return line, false, nil + } - pageSize := config.PageSize - opts, idx := paginate(pageSize, i.options, i.selectedIndex) - err := i.Render( - InputQuestionTemplate, - InputTemplateData{ - Input: *i, - Answer: i.answer, - ShowHelp: i.showingHelp, - SelectedIndex: idx, - PageEntries: opts, - Config: config, - }, - ) + if key >= terminal.KeySpace { + i.answer += string(key) + } + i.typedAnswer = i.answer - return err != nil, err + i.options = nil + } + + pageSize := config.PageSize + opts, idx := paginate(pageSize, i.options, i.selectedIndex) + err := i.Render( + InputQuestionTemplate, + InputTemplateData{ + Input: *i, + Answer: i.answer, + ShowHelp: i.showingHelp, + SelectedIndex: idx, + PageEntries: opts, + Config: config, + }, + ) + + if err == nil { + err = readLineAgain + } + + return []rune(i.typedAnswer), true, err + }) } +var readLineAgain = errors.New("read line again") + func (i *Input) Prompt(config *PromptConfig) (interface{}, error) { // render the template err := i.Render( InputQuestionTemplate, InputTemplateData{ - Input: *i, - Config: config, + Input: *i, + Config: config, + ShowHelp: i.showingHelp, }, ) if err != nil { @@ -150,30 +156,39 @@ func (i *Input) Prompt(config *PromptConfig) (interface{}, error) { defer rr.RestoreTermMode() cursor := i.NewCursor() - cursor.Hide() // hide the cursor - defer cursor.Show() // show the cursor when we're done + if !config.ShowCursor { + cursor.Hide() // hide the cursor + defer cursor.Show() // show the cursor when we're done + } + + var line []rune - // start waiting for input for { - r, _, err := rr.ReadRune() - if err != nil { - return "", err - } - if r == terminal.KeyInterrupt { - return "", terminal.InterruptErr - } - if r == terminal.KeyEndTransmission { - break + if i.options != nil { + line = []rune{} + } + + line, err = rr.ReadLineWithDefault(0, line, i.onRune(config)) + if err == readLineAgain { + continue } - b, err := i.OnChange(r, config) if err != nil { return "", err } - if b { - break - } + break + } + + i.answer = string(line) + // readline print an empty line, go up before we render the follow up + cursor.Up(1) + + // if we ran into the help string + if i.answer == config.HelpInput && i.Help != "" { + // show the help and prompt again + i.showingHelp = true + return i.Prompt(config) } // if the line is empty diff --git a/vendor/github.com/AlecAivazis/survey/v2/multiselect.go b/vendor/github.com/AlecAivazis/survey/v2/multiselect.go index 3d4f95b..1e94f80 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/multiselect.go +++ b/vendor/github.com/AlecAivazis/survey/v2/multiselect.go @@ -45,9 +45,27 @@ type MultiSelectTemplateData struct { ShowHelp bool PageEntries []core.OptionAnswer Config *PromptConfig + + // These fields are used when rendering an individual option + CurrentOpt core.OptionAnswer + CurrentIndex int +} + +// IterateOption sets CurrentOpt and CurrentIndex appropriately so a multiselect option can be rendered individually +func (m MultiSelectTemplateData) IterateOption(ix int, opt core.OptionAnswer) interface{} { + copy := m + copy.CurrentIndex = ix + copy.CurrentOpt = opt + return copy } var MultiSelectQuestionTemplate = ` +{{- define "option"}} + {{- if eq .SelectedIndex .CurrentIndex }}{{color .Config.Icons.SelectFocus.Format }}{{ .Config.Icons.SelectFocus.Text }}{{color "reset"}}{{else}} {{end}} + {{- if index .Checked .CurrentOpt.Index }}{{color .Config.Icons.MarkedOption.Format }} {{ .Config.Icons.MarkedOption.Text }} {{else}}{{color .Config.Icons.UnmarkedOption.Format }} {{ .Config.Icons.UnmarkedOption.Text }} {{end}} + {{- color "reset"}} + {{- " "}}{{- .CurrentOpt.Value}} +{{end}} {{- if .ShowHelp }}{{- color .Config.Icons.Help.Format }}{{ .Config.Icons.Help.Text }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}} {{- color .Config.Icons.Question.Format }}{{ .Config.Icons.Question.Text }} {{color "reset"}} {{- color "default+hb"}}{{ .Message }}{{ .FilterMessage }}{{color "reset"}} @@ -56,10 +74,7 @@ var MultiSelectQuestionTemplate = ` {{- " "}}{{- color "cyan"}}[Use arrows to move, space to select, to all, to none, type to filter{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}} {{- "\n"}} {{- range $ix, $option := .PageEntries}} - {{- if eq $ix $.SelectedIndex }}{{color $.Config.Icons.SelectFocus.Format }}{{ $.Config.Icons.SelectFocus.Text }}{{color "reset"}}{{else}} {{end}} - {{- if index $.Checked $option.Index }}{{color $.Config.Icons.MarkedOption.Format }} {{ $.Config.Icons.MarkedOption.Text }} {{else}}{{color $.Config.Icons.UnmarkedOption.Format }} {{ $.Config.Icons.UnmarkedOption.Text }} {{end}} - {{- color "reset"}} - {{- " "}}{{$option.Value}}{{"\n"}} + {{- template "option" $.IterateOption $ix $option}} {{- end}} {{- end}}` @@ -159,18 +174,17 @@ func (m *MultiSelect) OnChange(key rune, config *PromptConfig) { // and we have modified the filter then we should move the page back! opts, idx := paginate(pageSize, options, m.selectedIndex) + tmplData := MultiSelectTemplateData{ + MultiSelect: *m, + SelectedIndex: idx, + Checked: m.checked, + ShowHelp: m.showingHelp, + PageEntries: opts, + Config: config, + } + // render the options - m.Render( - MultiSelectQuestionTemplate, - MultiSelectTemplateData{ - MultiSelect: *m, - SelectedIndex: idx, - Checked: m.checked, - ShowHelp: m.showingHelp, - PageEntries: opts, - Config: config, - }, - ) + m.RenderWithCursorOffset(MultiSelectQuestionTemplate, tmplData, opts, idx) } func (m *MultiSelect) filterOptions(config *PromptConfig) []core.OptionAnswer { @@ -250,20 +264,21 @@ func (m *MultiSelect) Prompt(config *PromptConfig) (interface{}, error) { opts, idx := paginate(pageSize, core.OptionAnswerList(m.Options), m.selectedIndex) cursor := m.NewCursor() - cursor.Hide() // hide the cursor - defer cursor.Show() // show the cursor when we're done + cursor.Save() // for proper cursor placement during selection + cursor.Hide() // hide the cursor + defer cursor.Show() // show the cursor when we're done + defer cursor.Restore() // clear any accessibility offsetting on exit + + tmplData := MultiSelectTemplateData{ + MultiSelect: *m, + SelectedIndex: idx, + Checked: m.checked, + PageEntries: opts, + Config: config, + } // ask the question - err := m.Render( - MultiSelectQuestionTemplate, - MultiSelectTemplateData{ - MultiSelect: *m, - SelectedIndex: idx, - Checked: m.checked, - PageEntries: opts, - Config: config, - }, - ) + err := m.RenderWithCursorOffset(MultiSelectQuestionTemplate, tmplData, opts, idx) if err != nil { return "", err } diff --git a/vendor/github.com/AlecAivazis/survey/v2/renderer.go b/vendor/github.com/AlecAivazis/survey/v2/renderer.go index 5425121..5503d81 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/renderer.go +++ b/vendor/github.com/AlecAivazis/survey/v2/renderer.go @@ -7,7 +7,7 @@ import ( "github.com/AlecAivazis/survey/v2/core" "github.com/AlecAivazis/survey/v2/terminal" - goterm "golang.org/x/crypto/ssh/terminal" + "golang.org/x/term" ) type Renderer struct { @@ -69,6 +69,14 @@ func (r *Renderer) Error(config *PromptConfig, invalid error) error { return nil } +func (r *Renderer) OffsetCursor(offset int) { + cursor := r.NewCursor() + for offset > 0 { + cursor.PreviousLine(1) + offset-- + } +} + func (r *Renderer) Render(tmpl string, data interface{}) error { // cleanup the currently rendered text lineCount := r.countLines(r.renderedText) @@ -91,6 +99,21 @@ func (r *Renderer) Render(tmpl string, data interface{}) error { return nil } +func (r *Renderer) RenderWithCursorOffset(tmpl string, data IterableOpts, opts []core.OptionAnswer, idx int) error { + cursor := r.NewCursor() + cursor.Restore() // clear any accessibility offsetting + + if err := r.Render(tmpl, data); err != nil { + return err + } + cursor.Save() + + offset := computeCursorOffset(MultiSelectQuestionTemplate, data, opts, idx, r.termWidthSafe()) + r.OffsetCursor(offset) + + return nil +} + // appendRenderedError appends text to the renderer's error buffer // which is used to track what has been printed. It is not exported // as errors should only be displayed via Error(config, error). @@ -119,19 +142,24 @@ func (r *Renderer) resetPrompt(lines int) { func (r *Renderer) termWidth() (int, error) { fd := int(r.stdio.Out.Fd()) - termWidth, _, err := goterm.GetSize(fd) + termWidth, _, err := term.GetSize(fd) return termWidth, err } -// countLines will return the count of `\n` with the addition of any -// lines that have wrapped due to narrow terminal width -func (r *Renderer) countLines(buf bytes.Buffer) int { +func (r *Renderer) termWidthSafe() int { w, err := r.termWidth() if err != nil || w == 0 { // if we got an error due to terminal.GetSize not being supported // on current platform then just assume a very wide terminal w = 10000 } + return w +} + +// countLines will return the count of `\n` with the addition of any +// lines that have wrapped due to narrow terminal width +func (r *Renderer) countLines(buf bytes.Buffer) int { + w := r.termWidthSafe() bufBytes := buf.Bytes() diff --git a/vendor/github.com/AlecAivazis/survey/v2/select.go b/vendor/github.com/AlecAivazis/survey/v2/select.go index fdce038..915f34b 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/select.go +++ b/vendor/github.com/AlecAivazis/survey/v2/select.go @@ -43,9 +43,26 @@ type SelectTemplateData struct { ShowAnswer bool ShowHelp bool Config *PromptConfig + + // These fields are used when rendering an individual option + CurrentOpt core.OptionAnswer + CurrentIndex int +} + +// IterateOption sets CurrentOpt and CurrentIndex appropriately so a select option can be rendered individually +func (s SelectTemplateData) IterateOption(ix int, opt core.OptionAnswer) interface{} { + copy := s + copy.CurrentIndex = ix + copy.CurrentOpt = opt + return copy } var SelectQuestionTemplate = ` +{{- define "option"}} + {{- if eq .SelectedIndex .CurrentIndex }}{{color .Config.Icons.SelectFocus.Format }}{{ .Config.Icons.SelectFocus.Text }} {{else}}{{color "default"}} {{end}} + {{- .CurrentOpt.Value}} + {{- color "reset"}} +{{end}} {{- if .ShowHelp }}{{- color .Config.Icons.Help.Format }}{{ .Config.Icons.Help.Text }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}} {{- color .Config.Icons.Question.Format }}{{ .Config.Icons.Question.Text }} {{color "reset"}} {{- color "default+hb"}}{{ .Message }}{{ .FilterMessage }}{{color "reset"}} @@ -53,10 +70,8 @@ var SelectQuestionTemplate = ` {{- else}} {{- " "}}{{- color "cyan"}}[Use arrows to move, type to filter{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}} {{- "\n"}} - {{- range $ix, $choice := .PageEntries}} - {{- if eq $ix $.SelectedIndex }}{{color $.Config.Icons.SelectFocus.Format }}{{ $.Config.Icons.SelectFocus.Text }} {{else}}{{color "default"}} {{end}} - {{- $choice.Value}} - {{- color "reset"}}{{"\n"}} + {{- range $ix, $option := .PageEntries}} + {{- template "option" $.IterateOption $ix $option}} {{- end}} {{- end}}` @@ -152,17 +167,16 @@ func (s *Select) OnChange(key rune, config *PromptConfig) bool { // and we have modified the filter then we should move the page back! opts, idx := paginate(pageSize, options, s.selectedIndex) + tmplData := SelectTemplateData{ + Select: *s, + SelectedIndex: idx, + ShowHelp: s.showingHelp, + PageEntries: opts, + Config: config, + } + // render the options - s.Render( - SelectQuestionTemplate, - SelectTemplateData{ - Select: *s, - SelectedIndex: idx, - ShowHelp: s.showingHelp, - PageEntries: opts, - Config: config, - }, - ) + s.RenderWithCursorOffset(SelectQuestionTemplate, tmplData, opts, idx) // keep prompting return false @@ -234,16 +248,22 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) { // figure out the options and index to render opts, idx := paginate(pageSize, core.OptionAnswerList(s.Options), sel) + cursor := s.NewCursor() + cursor.Save() // for proper cursor placement during selection + cursor.Hide() // hide the cursor + defer cursor.Show() // show the cursor when we're done + defer cursor.Restore() // clear any accessibility offsetting on exit + + tmplData := SelectTemplateData{ + Select: *s, + SelectedIndex: idx, + ShowHelp: s.showingHelp, + PageEntries: opts, + Config: config, + } + // ask the question - err := s.Render( - SelectQuestionTemplate, - SelectTemplateData{ - Select: *s, - PageEntries: opts, - SelectedIndex: idx, - Config: config, - }, - ) + err := s.RenderWithCursorOffset(SelectQuestionTemplate, tmplData, opts, idx) if err != nil { return "", err } @@ -255,10 +275,6 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) { rr.SetTermMode() defer rr.RestoreTermMode() - cursor := s.NewCursor() - cursor.Hide() // hide the cursor - defer cursor.Show() // show the cursor when we're done - // start waiting for input for { r, _, err := rr.ReadRune() @@ -317,6 +333,8 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) { } func (s *Select) Cleanup(config *PromptConfig, val interface{}) error { + cursor := s.NewCursor() + cursor.Restore() return s.Render( SelectQuestionTemplate, SelectTemplateData{ diff --git a/vendor/github.com/AlecAivazis/survey/v2/survey.go b/vendor/github.com/AlecAivazis/survey/v2/survey.go index e004cf3..1aae459 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/survey.go +++ b/vendor/github.com/AlecAivazis/survey/v2/survey.go @@ -1,10 +1,12 @@ package survey import ( + "bytes" "errors" "io" "os" "strings" + "unicode/utf8" "github.com/AlecAivazis/survey/v2/core" "github.com/AlecAivazis/survey/v2/terminal" @@ -55,6 +57,7 @@ func defaultAskOptions() *AskOptions { return strings.Contains(strings.ToLower(value), filter) }, KeepFilter: false, + ShowCursor: false, }, } } @@ -114,6 +117,7 @@ type PromptConfig struct { SuggestInput string Filter func(filter string, option string, index int) bool KeepFilter bool + ShowCursor bool } // Prompt is the primary interface for the objects that can take user input @@ -219,6 +223,17 @@ func WithIcons(setIcons func(*IconSet)) AskOpt { } } +// WithShowCursor sets the show cursor behavior when prompting the user +func WithShowCursor(ShowCursor bool) AskOpt { + return func(options *AskOptions) error { + // set the page size + options.PromptConfig.ShowCursor = ShowCursor + + // nothing went wrong + return nil + } +} + /* AskOne performs the prompt for a single prompt and asks for validation if required. Response types should be something that can be casted from the response type designated @@ -398,3 +413,42 @@ func paginate(pageSize int, choices []core.OptionAnswer, sel int) ([]core.Option // return the subset we care about and the index return choices[start:end], cursor } + +type IterableOpts interface { + IterateOption(int, core.OptionAnswer) interface{} +} + +func computeCursorOffset(tmpl string, data IterableOpts, opts []core.OptionAnswer, idx, tWidth int) int { + tmpls, err := core.GetTemplatePair(tmpl) + + if err != nil { + return 0 + } + + t := tmpls[0] + + renderOpt := func(ix int, opt core.OptionAnswer) string { + buf := bytes.NewBufferString("") + t.ExecuteTemplate(buf, "option", data.IterateOption(ix, opt)) + return buf.String() + } + + offset := len(opts) - idx + + for i, o := range opts { + if i < idx { + continue + } + renderedOpt := renderOpt(i, o) + valWidth := utf8.RuneCount([]byte(renderedOpt)) + if valWidth > tWidth { + splitCount := valWidth / tWidth + if valWidth%tWidth == 0 { + splitCount -= 1 + } + offset += splitCount + } + } + + return offset +} diff --git a/vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go b/vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go index c294ca4..1ac74fd 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go +++ b/vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go @@ -43,11 +43,13 @@ func (c *Cursor) Back(n int) { // NextLine moves cursor to beginning of the line n lines down. func (c *Cursor) NextLine(n int) { c.Down(1) + c.HorizontalAbsolute(0) } // PreviousLine moves cursor to beginning of the line n lines up. func (c *Cursor) PreviousLine(n int) { c.Up(1) + c.HorizontalAbsolute(0) } // HorizontalAbsolute moves cursor horizontally to x. @@ -167,8 +169,11 @@ func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) { // hide the cursor (so it doesn't blink when getting the size of the terminal) c.Hide() + defer c.Show() + // save the current location of the cursor c.Save() + defer c.Restore() // move the cursor to the very bottom of the terminal c.Move(999, 999) @@ -179,11 +184,6 @@ func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) { return nil, err } - // move back where we began - c.Restore() - - // show the cursor - c.Show() // since the bottom was calculated in the lower right corner, it // is the dimensions we are looking for return bottom, nil diff --git a/vendor/github.com/AlecAivazis/survey/v2/terminal/runereader.go b/vendor/github.com/AlecAivazis/survey/v2/terminal/runereader.go index 05e9101..94c915c 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/terminal/runereader.go +++ b/vendor/github.com/AlecAivazis/survey/v2/terminal/runereader.go @@ -31,7 +31,13 @@ func (rr *RuneReader) printChar(char rune, mask rune) { } } -func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { +type OnRuneFn func(rune, []rune) ([]rune, bool, error) + +func (rr *RuneReader) ReadLine(mask rune, onRunes ...OnRuneFn) ([]rune, error) { + return rr.ReadLineWithDefault(mask, []rune{}, onRunes...) +} + +func (rr *RuneReader) ReadLineWithDefault(mask rune, d []rune, onRunes ...OnRuneFn) ([]rune, error) { line := []rune{} // we only care about horizontal displacements from the origin so start counting at 0 index := 0 @@ -41,19 +47,56 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { Out: rr.stdio.Out, } + onRune := func(r rune, line []rune) ([]rune, bool, error) { + return line, false, nil + } + + // if the user pressed a key the caller was interested in capturing + if len(onRunes) > 0 { + onRune = onRunes[0] + } + // we get the terminal width and height (if resized after this point the property might become invalid) terminalSize, _ := cursor.Size(rr.Buffer()) // we set the current location of the cursor once cursorCurrent, _ := cursor.Location(rr.Buffer()) + increment := func() { + if cursorCurrent.CursorIsAtLineEnd(terminalSize) { + cursorCurrent.X = COORDINATE_SYSTEM_BEGIN + cursorCurrent.Y++ + } else { + cursorCurrent.X++ + } + } + decrement := func() { + if cursorCurrent.CursorIsAtLineBegin() { + cursorCurrent.X = terminalSize.X + cursorCurrent.Y-- + } else { + cursorCurrent.X-- + } + } + + if len(d) > 0 { + index = len(d) + fmt.Fprint(rr.stdio.Out, string(d)) + line = d + for range d { + increment() + } + } + for { // wait for some input r, _, err := rr.ReadRune() if err != nil { return line, err } - // increment cursor location - cursorCurrent.X++ + + if l, stop, err := onRune(r, line); stop || err != nil { + return l, err + } // if the user pressed enter or some other newline/termination like ctrl+d if r == '\r' || r == '\n' || r == KeyEndTransmission { @@ -63,13 +106,10 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { EraseLine(rr.stdio.Out, ERASE_LINE_END) cursor.PreviousLine(1) cursor.Forward(int(terminalSize.X)) - cursorCurrent.X = terminalSize.X - cursorCurrent.Y-- - } else { cursor.Back(1) - cursorCurrent.X-- } + decrement() index-- } // move the cursor the a new line @@ -148,6 +188,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { // decrement the index index-- + decrement() } else { // otherwise the user pressed backspace while at the beginning of the line soundBell(rr.stdio.Out) @@ -170,6 +211,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { } //decrement the index index-- + decrement() } else { // otherwise we are at the beginning of where we started reading lines @@ -192,6 +234,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { cursor.Forward(runeWidth(line[index])) } index++ + increment() } else { // otherwise we are at the end of the word and can't go past @@ -208,12 +251,11 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { if cursorCurrent.CursorIsAtLineBegin() { cursor.PreviousLine(1) cursor.Forward(int(terminalSize.X)) - cursorCurrent.X = terminalSize.X cursorCurrent.Y-- - + cursorCurrent.X = terminalSize.X } else { cursor.Back(runeWidth(line[index-1])) - cursorCurrent.X-- + cursorCurrent.X -= Short(runeWidth(line[index-1])) } index-- } @@ -223,12 +265,11 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { for index != len(line) { if cursorCurrent.CursorIsAtLineEnd(terminalSize) { cursor.NextLine(1) - cursorCurrent.X = COORDINATE_SYSTEM_BEGIN cursorCurrent.Y++ - + cursorCurrent.X = COORDINATE_SYSTEM_BEGIN } else { cursor.Forward(runeWidth(line[index])) - cursorCurrent.X++ + cursorCurrent.X += Short(runeWidth(line[index])) } index++ } @@ -277,6 +318,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { line = append(line, r) // save the location of the cursor index++ + increment() // print out the character rr.printChar(r, mask) } else { @@ -293,7 +335,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { EraseLine(rr.stdio.Out, ERASE_LINE_END) // print out the character rr.printChar(char, mask) - cursorCurrent.X++ + increment() } // if we are at the last line, we want to visually insert a new line and append to it. if cursorCurrent.CursorIsAtLineEnd(terminalSize) && cursorCurrent.Y == terminalSize.Y { @@ -316,6 +358,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) { } // increment the index index++ + increment() } } diff --git a/vendor/github.com/AlecAivazis/survey/v2/validate.go b/vendor/github.com/AlecAivazis/survey/v2/validate.go index ba7e127..462dc5e 100644 --- a/vendor/github.com/AlecAivazis/survey/v2/validate.go +++ b/vendor/github.com/AlecAivazis/survey/v2/validate.go @@ -4,6 +4,8 @@ import ( "errors" "fmt" "reflect" + + "github.com/AlecAivazis/survey/v2/core" ) // Required does not allow an empty value @@ -58,6 +60,44 @@ func MinLength(length int) Validator { } } +// MaxItems requires that the list is no longer than the specified value +func MaxItems(numberItems int) Validator { + // return a validator that checks the length of the list + return func(val interface{}) error { + if list, ok := val.([]core.OptionAnswer); ok { + // if the list is longer than the given value + if len(list) > numberItems { + // yell loudly + return fmt.Errorf("value is too long. Max items is %v", numberItems) + } + } else { + // otherwise we cannot convert the value into a list of answer and cannot enforce length + return fmt.Errorf("cannot impose the length on something other than a list of answers") + } + // the input is fine + return nil + } +} + +// MinItems requires that the list is longer or equal in length to the specified value +func MinItems(numberItems int) Validator { + // return a validator that checks the length of the list + return func(val interface{}) error { + if list, ok := val.([]core.OptionAnswer); ok { + // if the list is shorter than the given value + if len(list) < numberItems { + // yell loudly + return fmt.Errorf("value is too long. Min items is %v", numberItems) + } + } else { + // otherwise we cannot convert the value into a list of answer and cannot enforce length + return fmt.Errorf("cannot impose the length on something other than a list of answers") + } + // the input is fine + return nil + } +} + // ComposeValidators is a variadic function used to create one validator from many. func ComposeValidators(validators ...Validator) Validator { // return a validator that calls each one sequentially diff --git a/vendor/github.com/Microsoft/go-winio/CODEOWNERS b/vendor/github.com/Microsoft/go-winio/CODEOWNERS new file mode 100644 index 0000000..ae1b494 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/CODEOWNERS @@ -0,0 +1 @@ + * @microsoft/containerplat diff --git a/vendor/github.com/Microsoft/go-winio/README.md b/vendor/github.com/Microsoft/go-winio/README.md index 5680010..60c93fe 100644 --- a/vendor/github.com/Microsoft/go-winio/README.md +++ b/vendor/github.com/Microsoft/go-winio/README.md @@ -1,4 +1,4 @@ -# go-winio +# go-winio [![Build Status](https://github.com/microsoft/go-winio/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/go-winio/actions/workflows/ci.yml) This repository contains utilities for efficiently performing Win32 IO operations in Go. Currently, this is focused on accessing named pipes and other file handles, and diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go index ada2fba..3ab6bff 100644 --- a/vendor/github.com/Microsoft/go-winio/fileinfo.go +++ b/vendor/github.com/Microsoft/go-winio/fileinfo.go @@ -5,21 +5,14 @@ package winio import ( "os" "runtime" - "syscall" "unsafe" -) -//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx -//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle - -const ( - fileBasicInfo = 0 - fileIDInfo = 0x12 + "golang.org/x/sys/windows" ) // FileBasicInfo contains file access time and file attributes information. type FileBasicInfo struct { - CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime + CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime FileAttributes uint32 pad uint32 // padding } @@ -27,7 +20,7 @@ type FileBasicInfo struct { // GetFileBasicInfo retrieves times and attributes for a file. func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { bi := &FileBasicInfo{} - if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) @@ -36,13 +29,32 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { // SetFileBasicInfo sets times and attributes for a file. func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { - if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} } runtime.KeepAlive(f) return nil } +// FileStandardInfo contains extended information for the file. +// FILE_STANDARD_INFO in WinBase.h +// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info +type FileStandardInfo struct { + AllocationSize, EndOfFile int64 + NumberOfLinks uint32 + DeletePending, Directory bool +} + +// GetFileStandardInfo retrieves ended information for the file. +func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) { + si := &FileStandardInfo{} + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil { + return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return si, nil +} + // FileIDInfo contains the volume serial number and file ID for a file. This pair should be // unique on a system. type FileIDInfo struct { @@ -53,7 +65,7 @@ type FileIDInfo struct { // GetFileID retrieves the unique (volume, file ID) pair for a file. func GetFileID(f *os.File) (*FileIDInfo, error) { fileID := &FileIDInfo{} - if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) diff --git a/vendor/github.com/Microsoft/go-winio/go.mod b/vendor/github.com/Microsoft/go-winio/go.mod index a2eb649..98a8dea 100644 --- a/vendor/github.com/Microsoft/go-winio/go.mod +++ b/vendor/github.com/Microsoft/go-winio/go.mod @@ -4,6 +4,6 @@ go 1.12 require ( github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.4.1 - golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 + github.com/sirupsen/logrus v1.7.0 + golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c ) diff --git a/vendor/github.com/Microsoft/go-winio/go.sum b/vendor/github.com/Microsoft/go-winio/go.sum index 6da76a4..aa6ad3b 100644 --- a/vendor/github.com/Microsoft/go-winio/go.sum +++ b/vendor/github.com/Microsoft/go-winio/go.sum @@ -1,16 +1,14 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go index dbfe790..b632f8f 100644 --- a/vendor/github.com/Microsoft/go-winio/hvsock.go +++ b/vendor/github.com/Microsoft/go-winio/hvsock.go @@ -1,3 +1,5 @@ +// +build windows + package winio import ( diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go index 5864065..f497c0e 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go @@ -1,3 +1,5 @@ +// +build windows + // Package guid provides a GUID type. The backing structure for a GUID is // identical to that used by the golang.org/x/sys/windows GUID type. // There are two main binary encodings used for a GUID, the big-endian encoding, diff --git a/vendor/github.com/Microsoft/go-winio/privilege.go b/vendor/github.com/Microsoft/go-winio/privilege.go index 9c83d36..c3dd7c2 100644 --- a/vendor/github.com/Microsoft/go-winio/privilege.go +++ b/vendor/github.com/Microsoft/go-winio/privilege.go @@ -28,8 +28,9 @@ const ( ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 - SeBackupPrivilege = "SeBackupPrivilege" - SeRestorePrivilege = "SeRestorePrivilege" + SeBackupPrivilege = "SeBackupPrivilege" + SeRestorePrivilege = "SeRestorePrivilege" + SeSecurityPrivilege = "SeSecurityPrivilege" ) const ( diff --git a/vendor/github.com/Microsoft/go-winio/syscall.go b/vendor/github.com/Microsoft/go-winio/syscall.go index 5cb52bc..5955c99 100644 --- a/vendor/github.com/Microsoft/go-winio/syscall.go +++ b/vendor/github.com/Microsoft/go-winio/syscall.go @@ -1,3 +1,3 @@ package winio -//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go +//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go index e26b01f..176ff75 100644 --- a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go @@ -19,6 +19,7 @@ const ( var ( errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL ) // errnoErr returns common boxed Errno values, to prevent @@ -26,7 +27,7 @@ var ( func errnoErr(e syscall.Errno) error { switch e { case 0: - return nil + return errERROR_EINVAL case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } @@ -37,243 +38,62 @@ func errnoErr(e syscall.Errno) error { } var ( - modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") - modntdll = windows.NewLazySystemDLL("ntdll.dll") modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + modntdll = windows.NewLazySystemDLL("ntdll.dll") + modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") - procCancelIoEx = modkernel32.NewProc("CancelIoEx") - procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") - procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") - procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") - procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") - procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") - procCreateFileW = modkernel32.NewProc("CreateFileW") - procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") - procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") - procLocalAlloc = modkernel32.NewProc("LocalAlloc") - procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") - procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") - procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") - procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") - procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") - procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") - procLocalFree = modkernel32.NewProc("LocalFree") procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") - procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") - procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") - procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") - procRevertToSelf = modadvapi32.NewProc("RevertToSelf") - procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") - procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") - procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") + procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procBackupRead = modkernel32.NewProc("BackupRead") procBackupWrite = modkernel32.NewProc("BackupWrite") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") + procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") + procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") + procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procLocalAlloc = modkernel32.NewProc("LocalAlloc") + procLocalFree = modkernel32.NewProc("LocalFree") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") + procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") + procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") + procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") + procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") procbind = modws2_32.NewProc("bind") ) -func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) - newport = syscall.Handle(r0) - if newport == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { +func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { var _p0 uint32 - if wait { + if releaseAll { _p0 = 1 - } else { - _p0 = 0 } - r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) + r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) + success = r0 != 0 + if true { + err = errnoErr(e1) + } + return +} + +func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(name) - if err != nil { - return - } - return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) -} - -func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) - handle = syscall.Handle(r0) - if handle == syscall.InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(name) - if err != nil { - return - } - return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) -} - -func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) - handle = syscall.Handle(r0) - if handle == syscall.InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { - r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0) - ptr = uintptr(r0) - return -} - -func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { - r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) - status = ntstatus(r0) - return -} - -func rtlNtStatusToDosError(status ntstatus) (winerr error) { - r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) - if r0 != 0 { - winerr = syscall.Errno(r0) - } - return -} - -func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { - r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) - status = ntstatus(r0) - return -} - -func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { - r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) - status = ntstatus(r0) - return -} - -func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(accountName) - if err != nil { - return - } - return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) -} - -func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -281,11 +101,7 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS func convertSidToStringSid(sid *byte, str **uint16) (err error) { r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -302,126 +118,73 @@ func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision ui func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) { r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func localFree(mem uintptr) { - syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) - return -} - func getSecurityDescriptorLength(sd uintptr) (len uint32) { r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) len = uint32(r0) return } -func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { - var _p0 uint32 - if releaseAll { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) - success = r0 != 0 - if true { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - func impersonateSelf(level uint32) (err error) { r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func revertToSelf() (err error) { - r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) +func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(accountName) + if err != nil { + return + } + return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) +} + +func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { - var _p0 uint32 - if openAsSelf { - _p0 = 1 - } else { - _p0 = 0 +func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return } - r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) + return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId) +} + +func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func getCurrentThread() (h syscall.Handle) { - r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) - h = syscall.Handle(r0) +func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + return _lookupPrivilegeName(_p0, luid, buffer, size) +} + +func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } return } @@ -442,53 +205,27 @@ func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err err func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) { r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(systemName) - if err != nil { - return +func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { + var _p0 uint32 + if openAsSelf { + _p0 = 1 } - return _lookupPrivilegeName(_p0, luid, buffer, size) -} - -func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) + r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(systemName) - if err != nil { - return - } - return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId) -} - -func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0) +func revertToSelf() (err error) { + r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -501,22 +238,14 @@ func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, proce var _p1 uint32 if abort { _p1 = 1 - } else { - _p1 = 0 } var _p2 uint32 if processSecurity { _p2 = 1 - } else { - _p2 = 0 } r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -529,22 +258,162 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p var _p1 uint32 if abort { _p1 = 1 - } else { - _p1 = 0 } var _p2 uint32 if processSecurity { _p2 = 1 - } else { - _p2 = 0 } r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) + } + return +} + +func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) +} + +func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + err = errnoErr(e1) + } + return +} + +func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) + newport = syscall.Handle(r0) + if newport == 0 { + err = errnoErr(e1) + } + return +} + +func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) +} + +func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + err = errnoErr(e1) + } + return +} + +func getCurrentThread() (h syscall.Handle) { + r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) + h = syscall.Handle(r0) + return +} + +func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { + r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0) + ptr = uintptr(r0) + return +} + +func localFree(mem uintptr) { + syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) + return +} + +func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { + r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) + status = ntstatus(r0) + return +} + +func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { + r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) + status = ntstatus(r0) + return +} + +func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { + r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) + status = ntstatus(r0) + return +} + +func rtlNtStatusToDosError(status ntstatus) (winerr error) { + r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) + if r0 != 0 { + winerr = syscall.Errno(r0) + } + return +} + +func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { + var _p0 uint32 + if wait { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) + if r1 == 0 { + err = errnoErr(e1) } return } @@ -552,11 +421,7 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) { r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) if r1 == socketError { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } diff --git a/vendor/github.com/ProtonMail/go-crypto/AUTHORS b/vendor/github.com/ProtonMail/go-crypto/AUTHORS new file mode 100644 index 0000000..2b00ddb --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS b/vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS new file mode 100644 index 0000000..1fbd3e9 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/github.com/ProtonMail/go-crypto/LICENSE b/vendor/github.com/ProtonMail/go-crypto/LICENSE new file mode 100644 index 0000000..6a66aea --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/ProtonMail/go-crypto/PATENTS b/vendor/github.com/ProtonMail/go-crypto/PATENTS new file mode 100644 index 0000000..7330990 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go b/vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go new file mode 100644 index 0000000..3ed3f43 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go @@ -0,0 +1,381 @@ +package bitcurves + +// Copyright 2010 The Go Authors. All rights reserved. +// Copyright 2011 ThePiachu. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bitelliptic implements several Koblitz elliptic curves over prime +// fields. + +// This package operates, internally, on Jacobian coordinates. For a given +// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1) +// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole +// calculation can be performed within the transform (as in ScalarMult and +// ScalarBaseMult). But even for Add and Double, it's faster to apply and +// reverse the transform than to operate in affine coordinates. + +import ( + "crypto/elliptic" + "io" + "math/big" + "sync" +) + +// A BitCurve represents a Koblitz Curve with a=0. +// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html +type BitCurve struct { + Name string + P *big.Int // the order of the underlying field + N *big.Int // the order of the base point + B *big.Int // the constant of the BitCurve equation + Gx, Gy *big.Int // (x,y) of the base point + BitSize int // the size of the underlying field +} + +// Params returns the parameters of the given BitCurve (see BitCurve struct) +func (bitCurve *BitCurve) Params() (cp *elliptic.CurveParams) { + cp = new(elliptic.CurveParams) + cp.Name = bitCurve.Name + cp.P = bitCurve.P + cp.N = bitCurve.N + cp.Gx = bitCurve.Gx + cp.Gy = bitCurve.Gy + cp.BitSize = bitCurve.BitSize + return cp +} + +// IsOnCurve returns true if the given (x,y) lies on the BitCurve. +func (bitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool { + // y² = x³ + b + y2 := new(big.Int).Mul(y, y) //y² + y2.Mod(y2, bitCurve.P) //y²%P + + x3 := new(big.Int).Mul(x, x) //x² + x3.Mul(x3, x) //x³ + + x3.Add(x3, bitCurve.B) //x³+B + x3.Mod(x3, bitCurve.P) //(x³+B)%P + + return x3.Cmp(y2) == 0 +} + +// affineFromJacobian reverses the Jacobian transform. See the comment at the +// top of the file. +func (bitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) { + if z.Cmp(big.NewInt(0)) == 0 { + panic("bitcurve: Can't convert to affine with Jacobian Z = 0") + } + // x = YZ^2 mod P + zinv := new(big.Int).ModInverse(z, bitCurve.P) + zinvsq := new(big.Int).Mul(zinv, zinv) + + xOut = new(big.Int).Mul(x, zinvsq) + xOut.Mod(xOut, bitCurve.P) + // y = YZ^3 mod P + zinvsq.Mul(zinvsq, zinv) + yOut = new(big.Int).Mul(y, zinvsq) + yOut.Mod(yOut, bitCurve.P) + return xOut, yOut +} + +// Add returns the sum of (x1,y1) and (x2,y2) +func (bitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + z := new(big.Int).SetInt64(1) + x, y, z := bitCurve.addJacobian(x1, y1, z, x2, y2, z) + return bitCurve.affineFromJacobian(x, y, z) +} + +// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and +// (x2, y2, z2) and returns their sum, also in Jacobian form. +func (bitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { + // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl + z1z1 := new(big.Int).Mul(z1, z1) + z1z1.Mod(z1z1, bitCurve.P) + z2z2 := new(big.Int).Mul(z2, z2) + z2z2.Mod(z2z2, bitCurve.P) + + u1 := new(big.Int).Mul(x1, z2z2) + u1.Mod(u1, bitCurve.P) + u2 := new(big.Int).Mul(x2, z1z1) + u2.Mod(u2, bitCurve.P) + h := new(big.Int).Sub(u2, u1) + if h.Sign() == -1 { + h.Add(h, bitCurve.P) + } + i := new(big.Int).Lsh(h, 1) + i.Mul(i, i) + j := new(big.Int).Mul(h, i) + + s1 := new(big.Int).Mul(y1, z2) + s1.Mul(s1, z2z2) + s1.Mod(s1, bitCurve.P) + s2 := new(big.Int).Mul(y2, z1) + s2.Mul(s2, z1z1) + s2.Mod(s2, bitCurve.P) + r := new(big.Int).Sub(s2, s1) + if r.Sign() == -1 { + r.Add(r, bitCurve.P) + } + r.Lsh(r, 1) + v := new(big.Int).Mul(u1, i) + + x3 := new(big.Int).Set(r) + x3.Mul(x3, x3) + x3.Sub(x3, j) + x3.Sub(x3, v) + x3.Sub(x3, v) + x3.Mod(x3, bitCurve.P) + + y3 := new(big.Int).Set(r) + v.Sub(v, x3) + y3.Mul(y3, v) + s1.Mul(s1, j) + s1.Lsh(s1, 1) + y3.Sub(y3, s1) + y3.Mod(y3, bitCurve.P) + + z3 := new(big.Int).Add(z1, z2) + z3.Mul(z3, z3) + z3.Sub(z3, z1z1) + if z3.Sign() == -1 { + z3.Add(z3, bitCurve.P) + } + z3.Sub(z3, z2z2) + if z3.Sign() == -1 { + z3.Add(z3, bitCurve.P) + } + z3.Mul(z3, h) + z3.Mod(z3, bitCurve.P) + + return x3, y3, z3 +} + +// Double returns 2*(x,y) +func (bitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + z1 := new(big.Int).SetInt64(1) + return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z1)) +} + +// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and +// returns its double, also in Jacobian form. +func (bitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { + // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + + a := new(big.Int).Mul(x, x) //X1² + b := new(big.Int).Mul(y, y) //Y1² + c := new(big.Int).Mul(b, b) //B² + + d := new(big.Int).Add(x, b) //X1+B + d.Mul(d, d) //(X1+B)² + d.Sub(d, a) //(X1+B)²-A + d.Sub(d, c) //(X1+B)²-A-C + d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C) + + e := new(big.Int).Mul(big.NewInt(3), a) //3*A + f := new(big.Int).Mul(e, e) //E² + + x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D + x3.Sub(f, x3) //F-2*D + x3.Mod(x3, bitCurve.P) + + y3 := new(big.Int).Sub(d, x3) //D-X3 + y3.Mul(e, y3) //E*(D-X3) + y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C + y3.Mod(y3, bitCurve.P) + + z3 := new(big.Int).Mul(y, z) //Y1*Z1 + z3.Mul(big.NewInt(2), z3) //3*Y1*Z1 + z3.Mod(z3, bitCurve.P) + + return x3, y3, z3 +} + +//TODO: double check if it is okay +// ScalarMult returns k*(Bx,By) where k is a number in big-endian form. +func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { + // We have a slight problem in that the identity of the group (the + // point at infinity) cannot be represented in (x, y) form on a finite + // machine. Thus the standard add/double algorithm has to be tweaked + // slightly: our initial state is not the identity, but x, and we + // ignore the first true bit in |k|. If we don't find any true bits in + // |k|, then we return nil, nil, because we cannot return the identity + // element. + + Bz := new(big.Int).SetInt64(1) + x := Bx + y := By + z := Bz + + seenFirstTrue := false + for _, byte := range k { + for bitNum := 0; bitNum < 8; bitNum++ { + if seenFirstTrue { + x, y, z = bitCurve.doubleJacobian(x, y, z) + } + if byte&0x80 == 0x80 { + if !seenFirstTrue { + seenFirstTrue = true + } else { + x, y, z = bitCurve.addJacobian(Bx, By, Bz, x, y, z) + } + } + byte <<= 1 + } + } + + if !seenFirstTrue { + return nil, nil + } + + return bitCurve.affineFromJacobian(x, y, z) +} + +// ScalarBaseMult returns k*G, where G is the base point of the group and k is +// an integer in big-endian form. +func (bitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { + return bitCurve.ScalarMult(bitCurve.Gx, bitCurve.Gy, k) +} + +var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f} + +//TODO: double check if it is okay +// GenerateKey returns a public/private key pair. The private key is generated +// using the given reader, which must return random data. +func (bitCurve *BitCurve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err error) { + byteLen := (bitCurve.BitSize + 7) >> 3 + priv = make([]byte, byteLen) + + for x == nil { + _, err = io.ReadFull(rand, priv) + if err != nil { + return + } + // We have to mask off any excess bits in the case that the size of the + // underlying field is not a whole number of bytes. + priv[0] &= mask[bitCurve.BitSize%8] + // This is because, in tests, rand will return all zeros and we don't + // want to get the point at infinity and loop forever. + priv[1] ^= 0x42 + x, y = bitCurve.ScalarBaseMult(priv) + } + return +} + +// Marshal converts a point into the form specified in section 4.3.6 of ANSI +// X9.62. +func (bitCurve *BitCurve) Marshal(x, y *big.Int) []byte { + byteLen := (bitCurve.BitSize + 7) >> 3 + + ret := make([]byte, 1+2*byteLen) + ret[0] = 4 // uncompressed point + + xBytes := x.Bytes() + copy(ret[1+byteLen-len(xBytes):], xBytes) + yBytes := y.Bytes() + copy(ret[1+2*byteLen-len(yBytes):], yBytes) + return ret +} + +// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On +// error, x = nil. +func (bitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) { + byteLen := (bitCurve.BitSize + 7) >> 3 + if len(data) != 1+2*byteLen { + return + } + if data[0] != 4 { // uncompressed form + return + } + x = new(big.Int).SetBytes(data[1 : 1+byteLen]) + y = new(big.Int).SetBytes(data[1+byteLen:]) + return +} + +//curve parameters taken from: +//http://www.secg.org/collateral/sec2_final.pdf + +var initonce sync.Once +var secp160k1 *BitCurve +var secp192k1 *BitCurve +var secp224k1 *BitCurve +var secp256k1 *BitCurve + +func initAll() { + initS160() + initS192() + initS224() + initS256() +} + +func initS160() { + // See SEC 2 section 2.4.1 + secp160k1 = new(BitCurve) + secp160k1.Name = "secp160k1" + secp160k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", 16) + secp160k1.N, _ = new(big.Int).SetString("0100000000000000000001B8FA16DFAB9ACA16B6B3", 16) + secp160k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000007", 16) + secp160k1.Gx, _ = new(big.Int).SetString("3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", 16) + secp160k1.Gy, _ = new(big.Int).SetString("938CF935318FDCED6BC28286531733C3F03C4FEE", 16) + secp160k1.BitSize = 160 +} + +func initS192() { + // See SEC 2 section 2.5.1 + secp192k1 = new(BitCurve) + secp192k1.Name = "secp192k1" + secp192k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", 16) + secp192k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 16) + secp192k1.B, _ = new(big.Int).SetString("000000000000000000000000000000000000000000000003", 16) + secp192k1.Gx, _ = new(big.Int).SetString("DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", 16) + secp192k1.Gy, _ = new(big.Int).SetString("9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", 16) + secp192k1.BitSize = 192 +} + +func initS224() { + // See SEC 2 section 2.6.1 + secp224k1 = new(BitCurve) + secp224k1.Name = "secp224k1" + secp224k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", 16) + secp224k1.N, _ = new(big.Int).SetString("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 16) + secp224k1.B, _ = new(big.Int).SetString("00000000000000000000000000000000000000000000000000000005", 16) + secp224k1.Gx, _ = new(big.Int).SetString("A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", 16) + secp224k1.Gy, _ = new(big.Int).SetString("7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", 16) + secp224k1.BitSize = 224 +} + +func initS256() { + // See SEC 2 section 2.7.1 + secp256k1 = new(BitCurve) + secp256k1.Name = "secp256k1" + secp256k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16) + secp256k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16) + secp256k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16) + secp256k1.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16) + secp256k1.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16) + secp256k1.BitSize = 256 +} + +// S160 returns a BitCurve which implements secp160k1 (see SEC 2 section 2.4.1) +func S160() *BitCurve { + initonce.Do(initAll) + return secp160k1 +} + +// S192 returns a BitCurve which implements secp192k1 (see SEC 2 section 2.5.1) +func S192() *BitCurve { + initonce.Do(initAll) + return secp192k1 +} + +// S224 returns a BitCurve which implements secp224k1 (see SEC 2 section 2.6.1) +func S224() *BitCurve { + initonce.Do(initAll) + return secp224k1 +} + +// S256 returns a BitCurve which implements bitcurves (see SEC 2 section 2.7.1) +func S256() *BitCurve { + initonce.Do(initAll) + return secp256k1 +} diff --git a/vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go b/vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go new file mode 100644 index 0000000..77fb8b9 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go @@ -0,0 +1,134 @@ +// Package brainpool implements Brainpool elliptic curves. +// Implementation of rcurves is from github.com/ebfe/brainpool +// Note that these curves are implemented with naive, non-constant time operations +// and are likely not suitable for enviroments where timing attacks are a concern. +package brainpool + +import ( + "crypto/elliptic" + "math/big" + "sync" +) + +var ( + once sync.Once + p256t1, p384t1, p512t1 *elliptic.CurveParams + p256r1, p384r1, p512r1 *rcurve +) + +func initAll() { + initP256t1() + initP384t1() + initP512t1() + initP256r1() + initP384r1() + initP512r1() +} + +func initP256t1() { + p256t1 = &elliptic.CurveParams{Name: "brainpoolP256t1"} + p256t1.P, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16) + p256t1.N, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16) + p256t1.B, _ = new(big.Int).SetString("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16) + p256t1.Gx, _ = new(big.Int).SetString("A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", 16) + p256t1.Gy, _ = new(big.Int).SetString("2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", 16) + p256t1.BitSize = 256 +} + +func initP256r1() { + twisted := p256t1 + params := &elliptic.CurveParams{ + Name: "brainpoolP256r1", + P: twisted.P, + N: twisted.N, + BitSize: twisted.BitSize, + } + params.Gx, _ = new(big.Int).SetString("8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", 16) + params.Gy, _ = new(big.Int).SetString("547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", 16) + z, _ := new(big.Int).SetString("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0", 16) + p256r1 = newrcurve(twisted, params, z) +} + +func initP384t1() { + p384t1 = &elliptic.CurveParams{Name: "brainpoolP384t1"} + p384t1.P, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16) + p384t1.N, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16) + p384t1.B, _ = new(big.Int).SetString("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16) + p384t1.Gx, _ = new(big.Int).SetString("18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", 16) + p384t1.Gy, _ = new(big.Int).SetString("25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", 16) + p384t1.BitSize = 384 +} + +func initP384r1() { + twisted := p384t1 + params := &elliptic.CurveParams{ + Name: "brainpoolP384r1", + P: twisted.P, + N: twisted.N, + BitSize: twisted.BitSize, + } + params.Gx, _ = new(big.Int).SetString("1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", 16) + params.Gy, _ = new(big.Int).SetString("8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", 16) + z, _ := new(big.Int).SetString("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C", 16) + p384r1 = newrcurve(twisted, params, z) +} + +func initP512t1() { + p512t1 = &elliptic.CurveParams{Name: "brainpoolP512t1"} + p512t1.P, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16) + p512t1.N, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16) + p512t1.B, _ = new(big.Int).SetString("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16) + p512t1.Gx, _ = new(big.Int).SetString("640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", 16) + p512t1.Gy, _ = new(big.Int).SetString("5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", 16) + p512t1.BitSize = 512 +} + +func initP512r1() { + twisted := p512t1 + params := &elliptic.CurveParams{ + Name: "brainpoolP512r1", + P: twisted.P, + N: twisted.N, + BitSize: twisted.BitSize, + } + params.Gx, _ = new(big.Int).SetString("81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", 16) + params.Gy, _ = new(big.Int).SetString("7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", 16) + z, _ := new(big.Int).SetString("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB", 16) + p512r1 = newrcurve(twisted, params, z) +} + +// P256t1 returns a Curve which implements Brainpool P256t1 (see RFC 5639, section 3.4) +func P256t1() elliptic.Curve { + once.Do(initAll) + return p256t1 +} + +// P256r1 returns a Curve which implements Brainpool P256r1 (see RFC 5639, section 3.4) +func P256r1() elliptic.Curve { + once.Do(initAll) + return p256r1 +} + +// P384t1 returns a Curve which implements Brainpool P384t1 (see RFC 5639, section 3.6) +func P384t1() elliptic.Curve { + once.Do(initAll) + return p384t1 +} + +// P384r1 returns a Curve which implements Brainpool P384r1 (see RFC 5639, section 3.6) +func P384r1() elliptic.Curve { + once.Do(initAll) + return p384r1 +} + +// P512t1 returns a Curve which implements Brainpool P512t1 (see RFC 5639, section 3.7) +func P512t1() elliptic.Curve { + once.Do(initAll) + return p512t1 +} + +// P512r1 returns a Curve which implements Brainpool P512r1 (see RFC 5639, section 3.7) +func P512r1() elliptic.Curve { + once.Do(initAll) + return p512r1 +} diff --git a/vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go b/vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go new file mode 100644 index 0000000..2d53550 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go @@ -0,0 +1,83 @@ +package brainpool + +import ( + "crypto/elliptic" + "math/big" +) + +var _ elliptic.Curve = (*rcurve)(nil) + +type rcurve struct { + twisted elliptic.Curve + params *elliptic.CurveParams + z *big.Int + zinv *big.Int + z2 *big.Int + z3 *big.Int + zinv2 *big.Int + zinv3 *big.Int +} + +var ( + two = big.NewInt(2) + three = big.NewInt(3) +) + +func newrcurve(twisted elliptic.Curve, params *elliptic.CurveParams, z *big.Int) *rcurve { + zinv := new(big.Int).ModInverse(z, params.P) + return &rcurve{ + twisted: twisted, + params: params, + z: z, + zinv: zinv, + z2: new(big.Int).Exp(z, two, params.P), + z3: new(big.Int).Exp(z, three, params.P), + zinv2: new(big.Int).Exp(zinv, two, params.P), + zinv3: new(big.Int).Exp(zinv, three, params.P), + } +} + +func (curve *rcurve) toTwisted(x, y *big.Int) (*big.Int, *big.Int) { + var tx, ty big.Int + tx.Mul(x, curve.z2) + tx.Mod(&tx, curve.params.P) + ty.Mul(y, curve.z3) + ty.Mod(&ty, curve.params.P) + return &tx, &ty +} + +func (curve *rcurve) fromTwisted(tx, ty *big.Int) (*big.Int, *big.Int) { + var x, y big.Int + x.Mul(tx, curve.zinv2) + x.Mod(&x, curve.params.P) + y.Mul(ty, curve.zinv3) + y.Mod(&y, curve.params.P) + return &x, &y +} + +func (curve *rcurve) Params() *elliptic.CurveParams { + return curve.params +} + +func (curve *rcurve) IsOnCurve(x, y *big.Int) bool { + return curve.twisted.IsOnCurve(curve.toTwisted(x, y)) +} + +func (curve *rcurve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) { + tx1, ty1 := curve.toTwisted(x1, y1) + tx2, ty2 := curve.toTwisted(x2, y2) + return curve.fromTwisted(curve.twisted.Add(tx1, ty1, tx2, ty2)) +} + +func (curve *rcurve) Double(x1, y1 *big.Int) (x, y *big.Int) { + return curve.fromTwisted(curve.twisted.Double(curve.toTwisted(x1, y1))) +} + +func (curve *rcurve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) { + tx1, ty1 := curve.toTwisted(x1, y1) + return curve.fromTwisted(curve.twisted.ScalarMult(tx1, ty1, scalar)) +} + +func (curve *rcurve) ScalarBaseMult(scalar []byte) (x, y *big.Int) { + return curve.fromTwisted(curve.twisted.ScalarBaseMult(scalar)) +} \ No newline at end of file diff --git a/vendor/github.com/ProtonMail/go-crypto/eax/eax.go b/vendor/github.com/ProtonMail/go-crypto/eax/eax.go new file mode 100644 index 0000000..6b6bc7a --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/eax/eax.go @@ -0,0 +1,162 @@ +// Copyright (C) 2019 ProtonTech AG + +// Package eax provides an implementation of the EAX +// (encrypt-authenticate-translate) mode of operation, as described in +// Bellare, Rogaway, and Wagner "THE EAX MODE OF OPERATION: A TWO-PASS +// AUTHENTICATED-ENCRYPTION SCHEME OPTIMIZED FOR SIMPLICITY AND EFFICIENCY." +// In FSE'04, volume 3017 of LNCS, 2004 +package eax + +import ( + "crypto/cipher" + "crypto/subtle" + "errors" + "github.com/ProtonMail/go-crypto/internal/byteutil" +) + +const ( + defaultTagSize = 16 + defaultNonceSize = 16 +) + +type eax struct { + block cipher.Block // Only AES-{128, 192, 256} supported + tagSize int // At least 12 bytes recommended + nonceSize int +} + +func (e *eax) NonceSize() int { + return e.nonceSize +} + +func (e *eax) Overhead() int { + return e.tagSize +} + +// NewEAX returns an EAX instance with AES-{KEYLENGTH} and default nonce and +// tag lengths. Supports {128, 192, 256}- bit key length. +func NewEAX(block cipher.Block) (cipher.AEAD, error) { + return NewEAXWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize) +} + +// NewEAXWithNonceAndTagSize returns an EAX instance with AES-{keyLength} and +// given nonce and tag lengths in bytes. Panics on zero nonceSize and +// exceedingly long tags. +// +// It is recommended to use at least 12 bytes as tag length (see, for instance, +// NIST SP 800-38D). +// +// Only to be used for compatibility with existing cryptosystems with +// non-standard parameters. For all other cases, prefer NewEAX. +func NewEAXWithNonceAndTagSize( + block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) { + if nonceSize < 1 { + return nil, eaxError("Cannot initialize EAX with nonceSize = 0") + } + if tagSize > block.BlockSize() { + return nil, eaxError("Custom tag length exceeds blocksize") + } + return &eax{ + block: block, + tagSize: tagSize, + nonceSize: nonceSize, + }, nil +} + +func (e *eax) Seal(dst, nonce, plaintext, adata []byte) []byte { + if len(nonce) > e.nonceSize { + panic("crypto/eax: Nonce too long for this instance") + } + ret, out := byteutil.SliceForAppend(dst, len(plaintext) + e.tagSize) + omacNonce := e.omacT(0, nonce) + omacAdata := e.omacT(1, adata) + + // Encrypt message using CTR mode and omacNonce as IV + ctr := cipher.NewCTR(e.block, omacNonce) + ciphertextData := out[:len(plaintext)] + ctr.XORKeyStream(ciphertextData, plaintext) + + omacCiphertext := e.omacT(2, ciphertextData) + + tag := out[len(plaintext):] + for i := 0; i < e.tagSize; i++ { + tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i] + } + return ret +} + +func (e* eax) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) { + if len(nonce) > e.nonceSize { + panic("crypto/eax: Nonce too long for this instance") + } + if len(ciphertext) < e.tagSize { + return nil, eaxError("Ciphertext shorter than tag length") + } + sep := len(ciphertext) - e.tagSize + + // Compute tag + omacNonce := e.omacT(0, nonce) + omacAdata := e.omacT(1, adata) + omacCiphertext := e.omacT(2, ciphertext[:sep]) + + tag := make([]byte, e.tagSize) + for i := 0; i < e.tagSize; i++ { + tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i] + } + + // Compare tags + if subtle.ConstantTimeCompare(ciphertext[sep:], tag) != 1 { + return nil, eaxError("Tag authentication failed") + } + + // Decrypt ciphertext + ret, out := byteutil.SliceForAppend(dst, len(ciphertext)) + ctr := cipher.NewCTR(e.block, omacNonce) + ctr.XORKeyStream(out, ciphertext[:sep]) + + return ret[:sep], nil +} + +// Tweakable OMAC - Calls OMAC_K([t]_n || plaintext) +func (e *eax) omacT(t byte, plaintext []byte) []byte { + blockSize := e.block.BlockSize() + byteT := make([]byte, blockSize) + byteT[blockSize-1] = t + concat := append(byteT, plaintext...) + return e.omac(concat) +} + +func (e *eax) omac(plaintext []byte) []byte { + blockSize := e.block.BlockSize() + // L ← E_K(0^n); B ← 2L; P ← 4L + L := make([]byte, blockSize) + e.block.Encrypt(L, L) + B := byteutil.GfnDouble(L) + P := byteutil.GfnDouble(B) + + // CBC with IV = 0 + cbc := cipher.NewCBCEncrypter(e.block, make([]byte, blockSize)) + padded := e.pad(plaintext, B, P) + cbcCiphertext := make([]byte, len(padded)) + cbc.CryptBlocks(cbcCiphertext, padded) + + return cbcCiphertext[len(cbcCiphertext)-blockSize:] +} + +func (e *eax) pad(plaintext, B, P []byte) []byte { + // if |M| in {n, 2n, 3n, ...} + blockSize := e.block.BlockSize() + if len(plaintext) != 0 && len(plaintext)%blockSize == 0 { + return byteutil.RightXor(plaintext, B) + } + + // else return (M || 1 || 0^(n−1−(|M| % n))) xor→ P + ending := make([]byte, blockSize-len(plaintext)%blockSize) + ending[0] = 0x80 + padded := append(plaintext, ending...) + return byteutil.RightXor(padded, P) +} + +func eaxError(err string) error { + return errors.New("crypto/eax: " + err) +} diff --git a/vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go b/vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go new file mode 100644 index 0000000..ddb53d0 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go @@ -0,0 +1,58 @@ +package eax + +// Test vectors from +// https://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf +var testVectors = []struct { + msg, key, nonce, header, ciphertext string +}{ + {"", + "233952DEE4D5ED5F9B9C6D6FF80FF478", + "62EC67F9C3A4A407FCB2A8C49031A8B3", + "6BFB914FD07EAE6B", + "E037830E8389F27B025A2D6527E79D01"}, + {"F7FB", + "91945D3F4DCBEE0BF45EF52255F095A4", + "BECAF043B0A23D843194BA972C66DEBD", + "FA3BFD4806EB53FA", + "19DD5C4C9331049D0BDAB0277408F67967E5"}, + {"1A47CB4933", + "01F74AD64077F2E704C0F60ADA3DD523", + "70C3DB4F0D26368400A10ED05D2BFF5E", + "234A3463C1264AC6", + "D851D5BAE03A59F238A23E39199DC9266626C40F80"}, + {"481C9E39B1", + "D07CF6CBB7F313BDDE66B727AFD3C5E8", + "8408DFFF3C1A2B1292DC199E46B7D617", + "33CCE2EABFF5A79D", + "632A9D131AD4C168A4225D8E1FF755939974A7BEDE"}, + {"40D0C07DA5E4", + "35B6D0580005BBC12B0587124557D2C2", + "FDB6B06676EEDC5C61D74276E1F8E816", + "AEB96EAEBE2970E9", + "071DFE16C675CB0677E536F73AFE6A14B74EE49844DD"}, + {"4DE3B35C3FC039245BD1FB7D", + "BD8E6E11475E60B268784C38C62FEB22", + "6EAC5C93072D8E8513F750935E46DA1B", + "D4482D1CA78DCE0F", + "835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F"}, + {"8B0A79306C9CE7ED99DAE4F87F8DD61636", + "7C77D6E813BED5AC98BAA417477A2E7D", + "1A8C98DCD73D38393B2BF1569DEEFC19", + "65D2017990D62528", + "02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2"}, + {"1BDA122BCE8A8DBAF1877D962B8592DD2D56", + "5FFF20CAFAB119CA2FC73549E20F5B0D", + "DDE59B97D722156D4D9AFF2BC7559826", + "54B9F04E6A09189A", + "2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A"}, + {"6CF36720872B8513F6EAB1A8A44438D5EF11", + "A4A4782BCFFD3EC5E7EF6D8C34A56123", + "B781FCF2F75FA5A8DE97A9CA48E522EC", + "899A175897561D7E", + "0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700"}, + {"CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7", + "8395FCF1E95BEBD697BD010BC766AAC3", + "22E7ADD93CFC6393C57EC0B3C17D6B44", + "126735FCC320D25A", + "CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E"}, +} diff --git a/vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go b/vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go new file mode 100644 index 0000000..4eb19f2 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go @@ -0,0 +1,131 @@ +// These vectors include key length in {128, 192, 256}, tag size 128, and +// random nonce, header, and plaintext lengths. + +// This file was automatically generated. + +package eax + +var randomVectors = []struct { + key, nonce, header, plaintext, ciphertext string +}{ + {"DFDE093F36B0356E5A81F609786982E3", + "1D8AC604419001816905BA72B14CED7E", + "152A1517A998D7A24163FCDD146DE81AC347C8B97088F502093C1ABB8F6E33D9A219C34D7603A18B1F5ABE02E56661B7D7F67E81EC08C1302EF38D80A859486D450E94A4F26AD9E68EEBBC0C857A0FC5CF9E641D63D565A7E361BC8908F5A8DC8FD6", + "1C8EAAB71077FE18B39730A3156ADE29C5EE824C7EE86ED2A253B775603FB237116E654F6FEC588DD27F523A0E01246FE73FE348491F2A8E9ABC6CA58D663F71CDBCF4AD798BE46C42AE6EE8B599DB44A1A48D7BBBBA0F7D2750181E1C5E66967F7D57CBD30AFBDA5727", + "79E7E150934BBEBF7013F61C60462A14D8B15AF7A248AFB8A344EF021C1500E16666891D6E973D8BB56B71A371F12CA34660C4410C016982B20F547E3762A58B7BF4F20236CADCF559E2BE7D783B13723B2741FC7CDC8997D839E39A3DDD2BADB96743DD7049F1BDB0516A262869915B3F70498AFB7B191BF960"}, + {"F10619EF02E5D94D7550EB84ED364A21", + "8DC0D4F2F745BBAE835CC5574B942D20", + "FE561358F2E8DF7E1024FF1AE9A8D36EBD01352214505CB99D644777A8A1F6027FA2BDBFC529A9B91136D5F2416CFC5F0F4EC3A1AFD32BDDA23CA504C5A5CB451785FABF4DFE4CD50D817491991A60615B30286361C100A95D1712F2A45F8E374461F4CA2B", + "D7B5A971FC219631D30EFC3664AE3127D9CF3097DAD9C24AC7905D15E8D9B25B026B31D68CAE00975CDB81EB1FD96FD5E1A12E2BB83FA25F1B1D91363457657FC03875C27F2946C5", + "2F336ED42D3CC38FC61660C4CD60BA4BD438B05F5965D8B7B399D2E7167F5D34F792D318F94DB15D67463AC449E13D568CC09BFCE32A35EE3EE96A041927680AE329811811E27F2D1E8E657707AF99BA96D13A478D695D59"}, + {"429F514EFC64D98A698A9247274CFF45", + "976AA5EB072F912D126ACEBC954FEC38", + "A71D89DC5B6CEDBB7451A27C3C2CAE09126DB4C421", + "5632FE62AB1DC549D54D3BC3FC868ACCEDEFD9ECF5E9F8", + "848AE4306CA8C7F416F8707625B7F55881C0AB430353A5C967CDA2DA787F581A70E34DBEBB2385"}, + {"398138F309085F47F8457CDF53895A63", + "F8A8A7F2D28E5FFF7BBC2F24353F7A36", + "5D633C21BA7764B8855CAB586F3746E236AD486039C83C6B56EFA9C651D38A41D6B20DAEE3418BFEA44B8BD6", + "A3BBAA91920AF5E10659818B1B3B300AC79BFC129C8329E75251F73A66D3AE0128EB91D5031E0A65C329DB7D1E9C0493E268", + "D078097267606E5FB07CFB7E2B4B718172A82C6A4CEE65D549A4DFB9838003BD2FBF64A7A66988AC1A632FD88F9E9FBB57C5A78AD2E086EACBA3DB68511D81C2970A"}, + {"7A4151EBD3901B42CBA45DAFB2E931BA", + "0FC88ACEE74DD538040321C330974EB8", + "250464FB04733BAB934C59E6AD2D6AE8D662CBCFEFBE61E5A308D4211E58C4C25935B72C69107722E946BFCBF416796600542D76AEB73F2B25BF53BAF97BDEB36ED3A7A51C31E7F170EB897457E7C17571D1BA0A908954E9", + "88C41F3EBEC23FAB8A362D969CAC810FAD4F7CA6A7F7D0D44F060F92E37E1183768DD4A8C733F71C96058D362A39876D183B86C103DE", + "74A25B2182C51096D48A870D80F18E1CE15867778E34FCBA6BD7BFB3739FDCD42AD0F2D9F4EBA29085285C6048C15BCE5E5166F1F962D3337AA88E6062F05523029D0A7F0BF9"}, + {"BFB147E1CD5459424F8C0271FC0E0DC5", + "EABCC126442BF373969EA3015988CC45", + "4C0880E1D71AA2C7", + "BE1B5EC78FBF73E7A6682B21BA7E0E5D2D1C7ABE", + "5660D7C1380E2F306895B1402CB2D6C37876504276B414D120F4CF92FDDDBB293A238EA0"}, + {"595DD6F52D18BC2CA8EB4EDAA18D9FA3", + "0F84B5D36CF4BC3B863313AF3B4D2E97", + "30AE6CC5F99580F12A779D98BD379A60948020C0B6FBD5746B30BA3A15C6CD33DAF376C70A9F15B6C0EB410A93161F7958AE23", + "8EF3687A1642B070970B0B91462229D1D76ABC154D18211F7152AA9FF368", + "317C1DDB11417E5A9CC4DDE7FDFF6659A5AC4B31DE025212580A05CDAC6024D3E4AE7C2966E52B9129E9ECDBED86"}, + {"44E6F2DC8FDC778AD007137D11410F50", + "270A237AD977F7187AA6C158A0BAB24F", + "509B0F0EB12E2AA5C5BA2DE553C07FAF4CE0C9E926531AA709A3D6224FCB783ACCF1559E10B1123EBB7D52E8AB54E6B5352A9ED0D04124BF0E9D9BACFD7E32B817B2E625F5EE94A64EDE9E470DE7FE6886C19B294F9F828209FE257A78", + "8B3D7815DF25618A5D0C55A601711881483878F113A12EC36CF64900549A3199555528559DC118F789788A55FAFD944E6E99A9CA3F72F238CD3F4D88223F7A745992B3FAED1848", + "1CC00D79F7AD82FDA71B58D286E5F34D0CC4CEF30704E771CC1E50746BDF83E182B078DB27149A42BAE619DF0F85B0B1090AD55D3B4471B0D6F6ECCD09C8F876B30081F0E7537A9624F8AAF29DA85E324122EFB4D68A56"}, + {"BB7BC352A03044B4428D8DBB4B0701FDEC4649FD17B81452", + "8B4BBE26CCD9859DCD84884159D6B0A4", + "2212BEB0E78E0F044A86944CF33C8D5C80D9DBE1034BF3BCF73611835C7D3A52F5BD2D81B68FD681B68540A496EE5DA16FD8AC8824E60E1EC2042BE28FB0BFAD4E4B03596446BDD8C37D936D9B3D5295BE19F19CF5ACE1D33A46C952CE4DE5C12F92C1DD051E04AEED", + "9037234CC44FFF828FABED3A7084AF40FA7ABFF8E0C0EFB57A1CC361E18FC4FAC1AB54F3ABFE9FF77263ACE16C3A", + "A9391B805CCD956081E0B63D282BEA46E7025126F1C1631239C33E92AA6F92CD56E5A4C56F00FF9658E93D48AF4EF0EF81628E34AD4DB0CDAEDCD2A17EE7"}, + {"99C0AD703196D2F60A74E6B378B838B31F82EA861F06FC4E", + "92745C018AA708ECFEB1667E9F3F1B01", + "828C69F376C0C0EC651C67749C69577D589EE39E51404D80EBF70C8660A8F5FD375473F4A7C611D59CB546A605D67446CE2AA844135FCD78BB5FBC90222A00D42920BB1D7EEDFB0C4672554F583EF23184F89063CDECBE482367B5F9AF3ACBC3AF61392BD94CBCD9B64677", + "A879214658FD0A5B0E09836639BF82E05EC7A5EF71D4701934BDA228435C68AC3D5CEB54997878B06A655EEACEFB1345C15867E7FE6C6423660C8B88DF128EBD6BCD85118DBAE16E9252FFB204324E5C8F38CA97759BDBF3CB0083", + "51FE87996F194A2585E438B023B345439EA60D1AEBED4650CDAF48A4D4EEC4FC77DC71CC4B09D3BEEF8B7B7AF716CE2B4EFFB3AC9E6323C18AC35E0AA6E2BBBC8889490EB6226C896B0D105EAB42BFE7053CCF00ED66BA94C1BA09A792AA873F0C3B26C5C5F9A936E57B25"}, + {"7086816D00D648FB8304AA8C9E552E1B69A9955FB59B25D1", + "0F45CF7F0BF31CCEB85D9DA10F4D749F", + "93F27C60A417D9F0669E86ACC784FC8917B502DAF30A6338F11B30B94D74FEFE2F8BE1BBE2EAD10FAB7EED3C6F72B7C3ECEE1937C32ED4970A6404E139209C05", + "877F046601F3CBE4FB1491943FA29487E738F94B99AF206262A1D6FF856C9AA0B8D4D08A54370C98F8E88FA3DCC2B14C1F76D71B2A4C7963AEE8AF960464C5BEC8357AD00DC8", + "FE96906B895CE6A8E72BC72344E2C8BB3C63113D70EAFA26C299BAFE77A8A6568172EB447FB3E86648A0AF3512DEB1AAC0819F3EC553903BF28A9FB0F43411237A774BF9EE03E445D280FBB9CD12B9BAAB6EF5E52691"}, + {"062F65A896D5BF1401BADFF70E91B458E1F9BD4888CB2E4D", + "5B11EA1D6008EBB41CF892FCA5B943D1", + "BAF4FF5C8242", + "A8870E091238355984EB2F7D61A865B9170F440BFF999A5993DD41A10F4440D21FF948DDA2BF663B2E03AC3324492DC5E40262ECC6A65C07672353BE23E7FB3A9D79FF6AA38D97960905A38DECC312CB6A59E5467ECF06C311CD43ADC0B543EDF34FE8BE611F176460D5627CA51F8F8D9FED71F55C", + "B10E127A632172CF8AA7539B140D2C9C2590E6F28C3CB892FC498FCE56A34F732FBFF32E79C7B9747D9094E8635A0C084D6F0247F9768FB5FF83493799A9BEC6C39572120C40E9292C8C947AE8573462A9108C36D9D7112E6995AE5867E6C8BB387D1C5D4BEF524F391B9FD9F0A3B4BFA079E915BCD920185CFD38D114C558928BD7D47877"}, + {"38A8E45D6D705A11AF58AED5A1344896998EACF359F2E26A", + "FD82B5B31804FF47D44199B533D0CF84", + "DE454D4E62FE879F2050EE3E25853623D3E9AC52EEC1A1779A48CFAF5ECA0BFDE44749391866D1", + "B804", + "164BB965C05EBE0931A1A63293EDF9C38C27"}, + {"34C33C97C6D7A0850DA94D78A58DC61EC717CD7574833068", + "343BE00DA9483F05C14F2E9EB8EA6AE8", + "78312A43EFDE3CAE34A65796FF059A3FE15304EEA5CF1D9306949FE5BF3349D4977D4EBE76C040FE894C5949E4E4D6681153DA87FB9AC5062063CA2EA183566343362370944CE0362D25FC195E124FD60E8682E665D13F2229DDA3E4B2CB1DCA", + "CC11BB284B1153578E4A5ED9D937B869DAF00F5B1960C23455CA9CC43F486A3BE0B66254F1041F04FDF459C8640465B6E1D2CF899A381451E8E7FCB50CF87823BE77E24B132BBEEDC72E53369B275E1D8F49ECE59F4F215230AC4FE133FC80E4F634EE80BA4682B62C86", + "E7F703DC31A95E3A4919FF957836CB76C063D81702AEA4703E1C2BF30831E58C4609D626EC6810E12EAA5B930F049FF9EFC22C3E3F1EBD4A1FB285CB02A1AC5AD46B425199FC0A85670A5C4E3DAA9636C8F64C199F42F18AAC8EA7457FD377F322DD7752D7D01B946C8F0A97E6113F0D50106F319AFD291AAACE"}, + {"C6ECF7F053573E403E61B83052A343D93CBCC179D1E835BE", + "E280E13D7367042E3AA09A80111B6184", + "21486C9D7A9647", + "5F2639AFA6F17931853791CD8C92382BBB677FD72D0AB1A080D0E49BFAA21810E963E4FACD422E92F65CBFAD5884A60CD94740DF31AF02F95AA57DA0C4401B0ED906", + "5C51DB20755302070C45F52E50128A67C8B2E4ED0EACB7E29998CCE2E8C289DD5655913EC1A51CC3AABE5CDC2402B2BE7D6D4BF6945F266FBD70BA9F37109067157AE7530678B45F64475D4EBFCB5FFF46A5"}, + {"5EC6CF7401BC57B18EF154E8C38ACCA8959E57D2F3975FF5", + "656B41CB3F9CF8C08BAD7EBFC80BD225", + "6B817C2906E2AF425861A7EF59BA5801F143EE2A139EE72697CDE168B4", + "2C0E1DDC9B1E5389BA63845B18B1F8A1DB062037151BCC56EF7C21C0BB4DAE366636BBA975685D7CC5A94AFBE89C769016388C56FB7B57CE750A12B718A8BDCF70E80E8659A8330EFC8F86640F21735E8C80E23FE43ABF23507CE3F964AE4EC99D", + "ED780CF911E6D1AA8C979B889B0B9DC1ABE261832980BDBFB576901D9EF5AB8048998E31A15BE54B3E5845A4D136AD24D0BDA1C3006168DF2F8AC06729CB0818867398150020131D8F04EDF1923758C9EABB5F735DE5EA1758D4BC0ACFCA98AFD202E9839B8720253693B874C65586C6F0"}, + {"C92F678EB2208662F5BCF3403EC05F5961E957908A3E79421E1D25FC19054153", + "DA0F3A40983D92F2D4C01FED33C7A192", + "2B6E9D26DB406A0FAB47608657AA10EFC2B4AA5F459B29FF85AC9A40BFFE7AEB04F77E9A11FAAA116D7F6D4DA417671A9AB02C588E0EF59CB1BFB4B1CC931B63A3B3A159FCEC97A04D1E6F0C7E6A9CEF6B0ABB04758A69F1FE754DF4C2610E8C46B6CF413BDB31351D55BEDCB7B4A13A1C98E10984475E0F2F957853", + "F37326A80E08", + "83519E53E321D334F7C10B568183775C0E9AAE55F806"}, + {"6847E0491BE57E72995D186D50094B0B3593957A5146798FCE68B287B2FB37B5", + "3EE1182AEBB19A02B128F28E1D5F7F99", + "D9F35ABB16D776CE", + "DB7566ED8EA95BDF837F23DB277BAFBC5E70D1105ADFD0D9EF15475051B1EF94709C67DCA9F8D5", + "2CDCED0C9EBD6E2A508822A685F7DCD1CDD99E7A5FCA786C234E7F7F1D27EC49751AD5DCFA30C5EDA87C43CAE3B919B6BBCFE34C8EDA59"}, + {"82B019673642C08388D3E42075A4D5D587558C229E4AB8F660E37650C4C41A0A", + "336F5D681E0410FAE7B607246092C6DC", + "D430CBD8FE435B64214E9E9CDC5DE99D31CFCFB8C10AA0587A49DF276611", + "998404153AD77003E1737EDE93ED79859EE6DCCA93CB40C4363AA817ABF2DBBD46E42A14A7183B6CC01E12A577888141363D0AE011EB6E8D28C0B235", + "9BEF69EEB60BD3D6065707B7557F25292A8872857CFBD24F2F3C088E4450995333088DA50FD9121221C504DF1D0CD5EFE6A12666C5D5BB12282CF4C19906E9CFAB97E9BDF7F49DC17CFC384B"}, + {"747B2E269B1859F0622C15C8BAD6A725028B1F94B8DB7326948D1E6ED663A8BC", + "AB91F7245DDCE3F1C747872D47BE0A8A", + "3B03F786EF1DDD76E1D42646DA4CD2A5165DC5383CE86D1A0B5F13F910DC278A4E451EE0192CBA178E13B3BA27FDC7840DF73D2E104B", + "6B803F4701114F3E5FE21718845F8416F70F626303F545BE197189E0A2BA396F37CE06D389EB2658BC7D56D67868708F6D0D32", + "1570DDB0BCE75AA25D1957A287A2C36B1A5F2270186DA81BA6112B7F43B0F3D1D0ED072591DCF1F1C99BBB25621FC39B896FF9BD9413A2845363A9DCD310C32CF98E57"}, + {"02E59853FB29AEDA0FE1C5F19180AD99A12FF2F144670BB2B8BADF09AD812E0A", + "C691294EF67CD04D1B9242AF83DD1421", + "879334DAE3", + "1E17F46A98FEF5CBB40759D95354", + "FED8C3FF27DDF6313AED444A2985B36CBA268AAD6AAC563C0BA28F6DB5DB"}, + {"F6C1FB9B4188F2288FF03BD716023198C3582CF2A037FC2F29760916C2B7FCDB", + "4228DA0678CA3534588859E77DFF014C", + "D8153CAF35539A61DD8D05B3C9B44F01E564FB9348BCD09A1C23B84195171308861058F0A3CD2A55B912A3AAEE06FF4D356C77275828F2157C2FC7C115DA39E443210CCC56BEDB0CC99BBFB227ABD5CC454F4E7F547C7378A659EEB6A7E809101A84F866503CB18D4484E1FA09B3EC7FC75EB2E35270800AA7", + "23B660A779AD285704B12EC1C580387A47BEC7B00D452C6570", + "5AA642BBABA8E49849002A2FAF31DB8FC7773EFDD656E469CEC19B3206D4174C9A263D0A05484261F6"}, + {"8FF6086F1FADB9A3FBE245EAC52640C43B39D43F89526BB5A6EBA47710931446", + "943188480C99437495958B0AE4831AA9", + "AD5CD0BDA426F6EBA23C8EB23DC73FF9FEC173355EDBD6C9344C4C4383F211888F7CE6B29899A6801DF6B38651A7C77150941A", + "80CD5EA8D7F81DDF5070B934937912E8F541A5301877528EB41AB60C020968D459960ED8FB73083329841A", + "ABAE8EB7F36FCA2362551E72DAC890BA1BB6794797E0FC3B67426EC9372726ED4725D379EA0AC9147E48DCD0005C502863C2C5358A38817C8264B5"}, + {"A083B54E6B1FE01B65D42FCD248F97BB477A41462BBFE6FD591006C022C8FD84", + "B0490F5BD68A52459556B3749ACDF40E", + "8892E047DA5CFBBDF7F3CFCBD1BD21C6D4C80774B1826999234394BD3E513CC7C222BB40E1E3140A152F19B3802F0D036C24A590512AD0E8", + "D7B15752789DC94ED0F36778A5C7BBB207BEC32BAC66E702B39966F06E381E090C6757653C3D26A81EC6AD6C364D66867A334C91BB0B8A8A4B6EACDF0783D09010AEBA2DD2062308FE99CC1F", + "C071280A732ADC93DF272BF1E613B2BB7D46FC6665EF2DC1671F3E211D6BDE1D6ADDD28DF3AA2E47053FC8BB8AE9271EC8BC8B2CFFA320D225B451685B6D23ACEFDD241FE284F8ADC8DB07F456985B14330BBB66E0FB212213E05B3E"}, +} diff --git a/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go b/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go new file mode 100644 index 0000000..a6bdf51 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go @@ -0,0 +1,92 @@ +// Copyright (C) 2019 ProtonTech AG +// This file contains necessary tools for the aex and ocb packages. +// +// These functions SHOULD NOT be used elsewhere, since they are optimized for +// specific input nature in the EAX and OCB modes of operation. + +package byteutil + +// GfnDouble computes 2 * input in the field of 2^n elements. +// The irreducible polynomial in the finite field for n=128 is +// x^128 + x^7 + x^2 + x + 1 (equals 0x87) +// Constant-time execution in order to avoid side-channel attacks +func GfnDouble(input []byte) []byte { + if len(input) != 16 { + panic("Doubling in GFn only implemented for n = 128") + } + // If the first bit is zero, return 2L = L << 1 + // Else return (L << 1) xor 0^120 10000111 + shifted := ShiftBytesLeft(input) + shifted[15] ^= ((input[0] >> 7) * 0x87) + return shifted +} + +// ShiftBytesLeft outputs the byte array corresponding to x << 1 in binary. +func ShiftBytesLeft(x []byte) []byte { + l := len(x) + dst := make([]byte, l) + for i := 0; i < l-1; i++ { + dst[i] = (x[i] << 1) | (x[i+1] >> 7) + } + dst[l-1] = x[l-1] << 1 + return dst +} + +// ShiftNBytesLeft puts in dst the byte array corresponding to x << n in binary. +func ShiftNBytesLeft(dst, x []byte, n int) { + // Erase first n / 8 bytes + copy(dst, x[n/8:]) + + // Shift the remaining n % 8 bits + bits := uint(n % 8) + l := len(dst) + for i := 0; i < l-1; i++ { + dst[i] = (dst[i] << bits) | (dst[i+1] >> uint(8 - bits)) + } + dst[l-1] = dst[l-1] << bits + + // Append trailing zeroes + dst = append(dst, make([]byte, n/8)...) +} + +// XorBytesMut assumes equal input length, replaces X with X XOR Y +func XorBytesMut(X, Y []byte) { + for i := 0; i < len(X); i++ { + X[i] ^= Y[i] + } +} + + +// XorBytes assumes equal input length, puts X XOR Y into Z +func XorBytes(Z, X, Y []byte) { + for i := 0; i < len(X); i++ { + Z[i] = X[i] ^ Y[i] + } +} + +// RightXor XORs smaller input (assumed Y) at the right of the larger input (assumed X) +func RightXor(X, Y []byte) []byte { + offset := len(X) - len(Y) + xored := make([]byte, len(X)); + copy(xored, X) + for i := 0; i < len(Y); i++ { + xored[offset + i] ^= Y[i] + } + return xored +} + +// SliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func SliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go b/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go new file mode 100644 index 0000000..7f78cfa --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go @@ -0,0 +1,317 @@ +// Copyright (C) 2019 ProtonTech AG + +// Package ocb provides an implementation of the OCB (offset codebook) mode of +// operation, as described in RFC-7253 of the IRTF and in Rogaway, Bellare, +// Black and Krovetz - OCB: A BLOCK-CIPHER MODE OF OPERATION FOR EFFICIENT +// AUTHENTICATED ENCRYPTION (2003). +// Security considerations (from RFC-7253): A private key MUST NOT be used to +// encrypt more than 2^48 blocks. Tag length should be at least 12 bytes (a +// brute-force forging adversary succeeds after 2^{tag length} attempts). A +// single key SHOULD NOT be used to decrypt ciphertext with different tag +// lengths. Nonces need not be secret, but MUST NOT be reused. +// This package only supports underlying block ciphers with 128-bit blocks, +// such as AES-{128, 192, 256}, but may be extended to other sizes. +package ocb + +import ( + "bytes" + "crypto/cipher" + "crypto/subtle" + "errors" + "github.com/ProtonMail/go-crypto/internal/byteutil" + "math/bits" +) + +type ocb struct { + block cipher.Block + tagSize int + nonceSize int + mask mask + // Optimized en/decrypt: For each nonce N used to en/decrypt, the 'Ktop' + // internal variable can be reused for en/decrypting with nonces sharing + // all but the last 6 bits with N. The prefix of the first nonce used to + // compute the new Ktop, and the Ktop value itself, are stored in + // reusableKtop. If using incremental nonces, this saves one block cipher + // call every 63 out of 64 OCB encryptions, and stores one nonce and one + // output of the block cipher in memory only. + reusableKtop reusableKtop +} + +type mask struct { + // L_*, L_$, (L_i)_{i ∈ N} + lAst []byte + lDol []byte + L [][]byte +} + +type reusableKtop struct { + noncePrefix []byte + Ktop []byte +} + +const ( + defaultTagSize = 16 + defaultNonceSize = 15 +) + +const ( + enc = iota + dec +) + +func (o *ocb) NonceSize() int { + return o.nonceSize +} + +func (o *ocb) Overhead() int { + return o.tagSize +} + +// NewOCB returns an OCB instance with the given block cipher and default +// tag and nonce sizes. +func NewOCB(block cipher.Block) (cipher.AEAD, error) { + return NewOCBWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize) +} + +// NewOCBWithNonceAndTagSize returns an OCB instance with the given block +// cipher, nonce length, and tag length. Panics on zero nonceSize and +// exceedingly long tag size. +// +// It is recommended to use at least 12 bytes as tag length. +func NewOCBWithNonceAndTagSize( + block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) { + if block.BlockSize() != 16 { + return nil, ocbError("Block cipher must have 128-bit blocks") + } + if nonceSize < 1 { + return nil, ocbError("Incorrect nonce length") + } + if nonceSize >= block.BlockSize() { + return nil, ocbError("Nonce length exceeds blocksize - 1") + } + if tagSize > block.BlockSize() { + return nil, ocbError("Custom tag length exceeds blocksize") + } + return &ocb{ + block: block, + tagSize: tagSize, + nonceSize: nonceSize, + mask: initializeMaskTable(block), + reusableKtop: reusableKtop{ + noncePrefix: nil, + Ktop: nil, + }, + }, nil +} + +func (o *ocb) Seal(dst, nonce, plaintext, adata []byte) []byte { + if len(nonce) > o.nonceSize { + panic("crypto/ocb: Incorrect nonce length given to OCB") + } + ret, out := byteutil.SliceForAppend(dst, len(plaintext)+o.tagSize) + o.crypt(enc, out, nonce, adata, plaintext) + return ret +} + +func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) { + if len(nonce) > o.nonceSize { + panic("Nonce too long for this instance") + } + if len(ciphertext) < o.tagSize { + return nil, ocbError("Ciphertext shorter than tag length") + } + sep := len(ciphertext) - o.tagSize + ret, out := byteutil.SliceForAppend(dst, len(ciphertext)) + ciphertextData := ciphertext[:sep] + tag := ciphertext[sep:] + o.crypt(dec, out, nonce, adata, ciphertextData) + if subtle.ConstantTimeCompare(ret[sep:], tag) == 1 { + ret = ret[:sep] + return ret, nil + } + for i := range out { + out[i] = 0 + } + return nil, ocbError("Tag authentication failed") +} + +// On instruction enc (resp. dec), crypt is the encrypt (resp. decrypt) +// function. It returns the resulting plain/ciphertext with the tag appended. +func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte { + // + // Consider X as a sequence of 128-bit blocks + // + // Note: For encryption (resp. decryption), X is the plaintext (resp., the + // ciphertext without the tag). + blockSize := o.block.BlockSize() + + // + // Nonce-dependent and per-encryption variables + // + // Zero out the last 6 bits of the nonce into truncatedNonce to see if Ktop + // is already computed. + truncatedNonce := make([]byte, len(nonce)) + copy(truncatedNonce, nonce) + truncatedNonce[len(truncatedNonce)-1] &= 192 + Ktop := make([]byte, blockSize) + if bytes.Equal(truncatedNonce, o.reusableKtop.noncePrefix) { + Ktop = o.reusableKtop.Ktop + } else { + // Nonce = num2str(TAGLEN mod 128, 7) || zeros(120 - bitlen(N)) || 1 || N + paddedNonce := append(make([]byte, blockSize-1-len(nonce)), 1) + paddedNonce = append(paddedNonce, truncatedNonce...) + paddedNonce[0] |= byte(((8 * o.tagSize) % (8 * blockSize)) << 1) + // Last 6 bits of paddedNonce are already zero. Encrypt into Ktop + paddedNonce[blockSize-1] &= 192 + Ktop = paddedNonce + o.block.Encrypt(Ktop, Ktop) + o.reusableKtop.noncePrefix = truncatedNonce + o.reusableKtop.Ktop = Ktop + } + + // Stretch = Ktop || ((lower half of Ktop) XOR (lower half of Ktop << 8)) + xorHalves := make([]byte, blockSize/2) + byteutil.XorBytes(xorHalves, Ktop[:blockSize/2], Ktop[1:1+blockSize/2]) + stretch := append(Ktop, xorHalves...) + bottom := int(nonce[len(nonce)-1] & 63) + offset := make([]byte, len(stretch)) + byteutil.ShiftNBytesLeft(offset, stretch, bottom) + offset = offset[:blockSize] + + // + // Process any whole blocks + // + // Note: For encryption Y is ciphertext || tag, for decryption Y is + // plaintext || tag. + checksum := make([]byte, blockSize) + m := len(X) / blockSize + for i := 0; i < m; i++ { + index := bits.TrailingZeros(uint(i + 1)) + if len(o.mask.L)-1 < index { + o.mask.extendTable(index) + } + byteutil.XorBytesMut(offset, o.mask.L[bits.TrailingZeros(uint(i+1))]) + blockX := X[i*blockSize : (i+1)*blockSize] + blockY := Y[i*blockSize : (i+1)*blockSize] + byteutil.XorBytes(blockY, blockX, offset) + switch instruction { + case enc: + o.block.Encrypt(blockY, blockY) + byteutil.XorBytesMut(blockY, offset) + byteutil.XorBytesMut(checksum, blockX) + case dec: + o.block.Decrypt(blockY, blockY) + byteutil.XorBytesMut(blockY, offset) + byteutil.XorBytesMut(checksum, blockY) + } + } + // + // Process any final partial block and compute raw tag + // + tag := make([]byte, blockSize) + if len(X)%blockSize != 0 { + byteutil.XorBytesMut(offset, o.mask.lAst) + pad := make([]byte, blockSize) + o.block.Encrypt(pad, offset) + chunkX := X[blockSize*m:] + chunkY := Y[blockSize*m : len(X)] + byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)]) + // P_* || bit(1) || zeroes(127) - len(P_*) + switch instruction { + case enc: + paddedY := append(chunkX, byte(128)) + paddedY = append(paddedY, make([]byte, blockSize-len(chunkX)-1)...) + byteutil.XorBytesMut(checksum, paddedY) + case dec: + paddedX := append(chunkY, byte(128)) + paddedX = append(paddedX, make([]byte, blockSize-len(chunkY)-1)...) + byteutil.XorBytesMut(checksum, paddedX) + } + byteutil.XorBytes(tag, checksum, offset) + byteutil.XorBytesMut(tag, o.mask.lDol) + o.block.Encrypt(tag, tag) + byteutil.XorBytesMut(tag, o.hash(adata)) + copy(Y[blockSize*m+len(chunkY):], tag[:o.tagSize]) + } else { + byteutil.XorBytes(tag, checksum, offset) + byteutil.XorBytesMut(tag, o.mask.lDol) + o.block.Encrypt(tag, tag) + byteutil.XorBytesMut(tag, o.hash(adata)) + copy(Y[blockSize*m:], tag[:o.tagSize]) + } + return Y +} + +// This hash function is used to compute the tag. Per design, on empty input it +// returns a slice of zeros, of the same length as the underlying block cipher +// block size. +func (o *ocb) hash(adata []byte) []byte { + // + // Consider A as a sequence of 128-bit blocks + // + A := make([]byte, len(adata)) + copy(A, adata) + blockSize := o.block.BlockSize() + + // + // Process any whole blocks + // + sum := make([]byte, blockSize) + offset := make([]byte, blockSize) + m := len(A) / blockSize + for i := 0; i < m; i++ { + chunk := A[blockSize*i : blockSize*(i+1)] + index := bits.TrailingZeros(uint(i + 1)) + // If the mask table is too short + if len(o.mask.L)-1 < index { + o.mask.extendTable(index) + } + byteutil.XorBytesMut(offset, o.mask.L[index]) + byteutil.XorBytesMut(chunk, offset) + o.block.Encrypt(chunk, chunk) + byteutil.XorBytesMut(sum, chunk) + } + + // + // Process any final partial block; compute final hash value + // + if len(A)%blockSize != 0 { + byteutil.XorBytesMut(offset, o.mask.lAst) + // Pad block with 1 || 0 ^ 127 - bitlength(a) + ending := make([]byte, blockSize-len(A)%blockSize) + ending[0] = 0x80 + encrypted := append(A[blockSize*m:], ending...) + byteutil.XorBytesMut(encrypted, offset) + o.block.Encrypt(encrypted, encrypted) + byteutil.XorBytesMut(sum, encrypted) + } + return sum +} + +func initializeMaskTable(block cipher.Block) mask { + // + // Key-dependent variables + // + lAst := make([]byte, block.BlockSize()) + block.Encrypt(lAst, lAst) + lDol := byteutil.GfnDouble(lAst) + L := make([][]byte, 1) + L[0] = byteutil.GfnDouble(lDol) + + return mask{ + lAst: lAst, + lDol: lDol, + L: L, + } +} + +// Extends the L array of mask m up to L[limit], with L[i] = GfnDouble(L[i-1]) +func (m *mask) extendTable(limit int) { + for i := len(m.L); i <= limit; i++ { + m.L = append(m.L, byteutil.GfnDouble(m.L[i-1])) + } +} + +func ocbError(err string) error { + return errors.New("crypto/ocb: " + err) +} diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go b/vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go new file mode 100644 index 0000000..0efaf34 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go @@ -0,0 +1,136 @@ +// In the test vectors provided by RFC 7253, the "bottom" +// internal variable, which defines "offset" for the first time, does not +// exceed 15. However, it can attain values up to 63. + +// These vectors include key length in {128, 192, 256}, tag size 128, and +// random nonce, header, and plaintext lengths. + +// This file was automatically generated. + +package ocb + +var randomVectors = []struct { + key, nonce, header, plaintext, ciphertext string +}{ + + {"9438C5D599308EAF13F800D2D31EA7F0", + "C38EE4801BEBFFA1CD8635BE", + "0E507B7DADD8A98CDFE272D3CB6B3E8332B56AE583FB049C0874D4200BED16BD1A044182434E9DA0E841F182DFD5B3016B34641CED0784F1745F63AB3D0DA22D3351C9EF9A658B8081E24498EBF61FCE40DA6D8E184536", + "962D227786FB8913A8BAD5DC3250", + "EEDEF5FFA5986D1E3BF86DDD33EF9ADC79DCA06E215FA772CCBA814F63AD"}, + {"BA7DE631C7D6712167C6724F5B9A2B1D", + "35263EBDA05765DC0E71F1F5", + "0103257B4224507C0242FEFE821EA7FA42E0A82863E5F8B68F7D881B4B44FA428A2B6B21D2F591260802D8AB6D83", + "9D6D1FC93AE8A64E7889B7B2E3521EFA9B920A8DDB692E6F833DDC4A38AFA535E5E2A3ED82CB7E26404AB86C54D01C4668F28398C2DF33D5D561CBA1C8DCFA7A912F5048E545B59483C0E3221F54B14DAA2E4EB657B3BEF9554F34CAD69B2724AE962D3D8A", + "E93852D1985C5E775655E937FA79CE5BF28A585F2AF53A5018853B9634BE3C84499AC0081918FDCE0624494D60E25F76ACD6853AC7576E3C350F332249BFCABD4E73CEABC36BE4EDDA40914E598AE74174A0D7442149B26990899491BDDFE8FC54D6C18E83AE9E9A6FFBF5D376565633862EEAD88D"}, + {"2E74B25289F6FD3E578C24866E9C72A5", + "FD912F15025AF8414642BA1D1D", + "FB5FB8C26F365EEDAB5FE260C6E3CCD27806729C8335F146063A7F9EA93290E56CF84576EB446350D22AD730547C267B1F0BBB97EB34E1E2C41A", + "6C092EBF78F76EE8C1C6E592277D9545BA16EDB67BC7D8480B9827702DC2F8A129E2B08A2CE710CA7E1DA45CE162BB6CD4B512E632116E2211D3C90871EFB06B8D4B902681C7FB", + "6AC0A77F26531BF4F354A1737F99E49BE32ECD909A7A71AD69352906F54B08A9CE9B8CA5D724CBFFC5673437F23F630697F3B84117A1431D6FA8CC13A974FB4AD360300522E09511B99E71065D5AC4BBCB1D791E864EF4"}, + {"E7EC507C802528F790AFF5303A017B17", + "4B97A7A568940A9E3CE7A99E93031E", + "28349BDC5A09390C480F9B8AA3EDEA3DDB8B9D64BCA322C570B8225DF0E31190DAB25A4014BA39519E02ABFB12B89AA28BBFD29E486E7FB28734258C817B63CED9912DBAFEBB93E2798AB2890DE3B0ACFCFF906AB15563EF7823CE83D27CDB251195E22BD1337BCBDE65E7C2C427321C463C2777BFE5AEAA", + "9455B3EA706B74", + "7F33BA3EA848D48A96B9530E26888F43EBD4463C9399B6"}, + {"6C928AA3224736F28EE7378DE0090191", + "8936138E2E4C6A13280017A1622D", + "6202717F2631565BDCDC57C6584543E72A7C8BD444D0D108ED35069819633C", + "DA0691439E5F035F3E455269D14FE5C201C8C9B0A3FE2D3F86BCC59387C868FE65733D388360B31E3CE28B4BF6A8BE636706B536D5720DB66B47CF1C7A5AFD6F61E0EF90F1726D6B0E169F9A768B2B7AE4EE00A17F630AC905FCAAA1B707FFF25B3A1AAE83B504837C64A5639B2A34002B300EC035C9B43654DA55", + "B8804D182AB0F0EEB464FA7BD1329AD6154F982013F3765FEDFE09E26DAC078C9C1439BFC1159D6C02A25E3FF83EF852570117B315852AD5EE20E0FA3AA0A626B0E43BC0CEA38B44579DD36803455FB46989B90E6D229F513FD727AF8372517E9488384C515D6067704119C931299A0982EDDFB9C2E86A90C450C077EB222511EC9CCABC9FCFDB19F70088"}, + {"ECEA315CA4B3F425B0C9957A17805EA4", + "664CDAE18403F4F9BA13015A44FC", + "642AFB090D6C6DB46783F08B01A3EF2A8FEB5736B531EAC226E7888FCC8505F396818F83105065FACB3267485B9E5E4A0261F621041C08FCCB2A809A49AB5252A91D0971BCC620B9D614BD77E57A0EED2FA5", + "6852C31F8083E20E364CEA21BB7854D67CEE812FE1C9ED2425C0932A90D3780728D1BB", + "2ECEF962A9695A463ADABB275BDA9FF8B2BA57AEC2F52EFFB700CD9271A74D2A011C24AEA946051BD6291776429B7E681BA33E"}, + {"4EE616C4A58AAA380878F71A373461F6", + "91B8C9C176D9C385E9C47E52", + "CDA440B7F9762C572A718AC754EDEECC119E5EE0CCB9FEA4FFB22EEE75087C032EBF3DA9CDD8A28CC010B99ED45143B41A4BA50EA2A005473F89639237838867A57F23B0F0ED3BF22490E4501DAC9C658A9B9F", + "D6E645FA9AE410D15B8123FD757FA356A8DBE9258DDB5BE88832E615910993F497EC", + "B70ED7BF959FB2AAED4F36174A2A99BFB16992C8CDF369C782C4DB9C73DE78C5DB8E0615F647243B97ACDB24503BC9CADC48"}, + {"DCD475773136C830D5E3D0C5FE05B7FF", + "BB8E1FBB483BE7616A922C4A", + "36FEF2E1CB29E76A6EA663FC3AF66ECD7404F466382F7B040AABED62293302B56E8783EF7EBC21B4A16C3E78A7483A0A403F253A2CDC5BBF79DC3DAE6C73F39A961D8FBBE8D41B", + "441E886EA38322B2437ECA7DEB5282518865A66780A454E510878E61BFEC3106A3CD93D2A02052E6F9E1832F9791053E3B76BF4C07EFDD6D4106E3027FABB752E60C1AA425416A87D53938163817A1051EBA1D1DEEB4B9B25C7E97368B52E5911A31810B0EC5AF547559B6142D9F4C4A6EF24A4CF75271BF9D48F62B", + "1BE4DD2F4E25A6512C2CC71D24BBB07368589A94C2714962CD0ACE5605688F06342587521E75F0ACAFFD86212FB5C34327D238DB36CF2B787794B9A4412E7CD1410EA5DDD2450C265F29CF96013CD213FD2880657694D718558964BC189B4A84AFCF47EB012935483052399DBA5B088B0A0477F20DFE0E85DCB735E21F22A439FB837DD365A93116D063E607"}, + {"3FBA2B3D30177FFE15C1C59ED2148BB2C091F5615FBA7C07", + "FACF804A4BEBF998505FF9DE", + "8213B9263B2971A5BDA18DBD02208EE1", + "15B323926993B326EA19F892D704439FC478828322AF72118748284A1FD8A6D814E641F70512FD706980337379F31DC63355974738D7FEA87AD2858C0C2EBBFBE74371C21450072373C7B651B334D7C4D43260B9D7CCD3AF9EDB", + "6D35DC1469B26E6AAB26272A41B46916397C24C485B61162E640A062D9275BC33DDCFD3D9E1A53B6C8F51AC89B66A41D59B3574197A40D9B6DCF8A4E2A001409C8112F16B9C389E0096179DB914E05D6D11ED0005AD17E1CE105A2F0BAB8F6B1540DEB968B7A5428FF44"}, + {"53B52B8D4D748BCDF1DDE68857832FA46227FA6E2F32EFA1", + "0B0EF53D4606B28D1398355F", + "F23882436349094AF98BCACA8218E81581A043B19009E28EFBF2DE37883E04864148CC01D240552CA8844EC1456F42034653067DA67E80F87105FD06E14FF771246C9612867BE4D215F6D761", + "F15030679BD4088D42CAC9BF2E9606EAD4798782FA3ED8C57EBE7F84A53236F51B25967C6489D0CD20C9EEA752F9BC", + "67B96E2D67C3729C96DAEAEDF821D61C17E648643A2134C5621FEC621186915AD80864BFD1EB5B238BF526A679385E012A457F583AFA78134242E9D9C1B4E4"}, + {"0272DD80F23399F49BFC320381A5CD8225867245A49A7D41", + "5C83F4896D0738E1366B1836", + "69B0337289B19F73A12BAEEA857CCAF396C11113715D9500CCCF48BA08CFF12BC8B4BADB3084E63B85719DB5058FA7C2C11DEB096D7943CFA7CAF5", + "C01AD10FC8B562CD17C7BC2FAB3E26CBDFF8D7F4DEA816794BBCC12336991712972F52816AABAB244EB43B0137E2BAC1DD413CE79531E78BEF782E6B439612BB3AEF154DE3502784F287958EBC159419F9EBA27916A28D6307324129F506B1DE80C1755A929F87", + "FEFE52DD7159C8DD6E8EC2D3D3C0F37AB6CB471A75A071D17EC4ACDD8F3AA4D7D4F7BB559F3C09099E3D9003E5E8AA1F556B79CECDE66F85B08FA5955E6976BF2695EA076388A62D2AD5BAB7CBF1A7F3F4C8D5CDF37CDE99BD3E30B685D9E5EEE48C7C89118EF4878EB89747F28271FA2CC45F8E9E7601"}, + {"3EEAED04A455D6E5E5AB53CFD5AFD2F2BC625C7BF4BE49A5", + "36B88F63ADBB5668588181D774", + "D367E3CB3703E762D23C6533188EF7028EFF9D935A3977150361997EC9DEAF1E4794BDE26AA8B53C124980B1362EC86FCDDFC7A90073171C1BAEE351A53234B86C66E8AB92FAE99EC6967A6D3428892D80", + "573454C719A9A55E04437BF7CBAAF27563CCCD92ADD5E515CD63305DFF0687E5EEF790C5DCA5C0033E9AB129505E2775438D92B38F08F3B0356BA142C6F694", + "E9F79A5B432D9E682C9AAA5661CFC2E49A0FCB81A431E54B42EB73DD3BED3F377FEC556ABA81624BA64A5D739AD41467460088F8D4F442180A9382CA635745473794C382FCDDC49BA4EB6D8A44AE3C"}, + {"B695C691538F8CBD60F039D0E28894E3693CC7C36D92D79D", + "BC099AEB637361BAC536B57618", + "BFFF1A65AE38D1DC142C71637319F5F6508E2CB33C9DCB94202B359ED5A5ED8042E7F4F09231D32A7242976677E6F4C549BF65FADC99E5AF43F7A46FD95E16C2", + "081DF3FD85B415D803F0BE5AC58CFF0023FDDED99788296C3731D8", + "E50C64E3614D94FE69C47092E46ACC9957C6FEA2CCBF96BC62FBABE7424753C75F9C147C42AE26FE171531"}, + {"C9ACBD2718F0689A1BE9802A551B6B8D9CF5614DAF5E65ED", + "B1B0AAF373B8B026EB80422051D8", + "6648C0E61AC733C76119D23FB24548D637751387AA2EAE9D80E912B7BD486CAAD9EAF4D7A5FE2B54AAD481E8EC94BB4D558000896E2010462B70C9FED1E7273080D1", + "189F591F6CB6D59AFEDD14C341741A8F1037DC0DF00FC57CE65C30F49E860255CEA5DC6019380CC0FE8880BC1A9E685F41C239C38F36E3F2A1388865C5C311059C0A", + "922A5E949B61D03BE34AB5F4E58607D4504EA14017BB363DAE3C873059EA7A1C77A746FB78981671D26C2CF6D9F24952D510044CE02A10177E9DB42D0145211DFE6E84369C5E3BC2669EAB4147B2822895F9"}, + {"7A832BD2CF5BF4919F353CE2A8C86A5E406DA2D52BE16A72", + "2F2F17CECF7E5A756D10785A3CB9DB", + "61DA05E3788CC2D8405DBA70C7A28E5AF699863C9F72E6C6770126929F5D6FA267F005EBCF49495CB46400958A3AE80D1289D1C671", + "44E91121195A41AF14E8CFDBD39A4B517BE0DF1A72977ED8A3EEF8EEDA1166B2EB6DB2C4AE2E74FA0F0C74537F659BFBD141E5DDEC67E64EDA85AABD3F52C85A785B9FB3CECD70E7DF", + "BEDF596EA21288D2B84901E188F6EE1468B14D5161D3802DBFE00D60203A24E2AB62714BF272A45551489838C3A7FEAADC177B591836E73684867CCF4E12901DCF2064058726BBA554E84ADC5136F507E961188D4AF06943D3"}, + {"1508E8AE9079AA15F1CEC4F776B4D11BCCB061B58AA56C18", + "BCA625674F41D1E3AB47672DC0C3", + "8B12CF84F16360F0EAD2A41BC021530FFCEC7F3579CAE658E10E2D3D81870F65AFCED0C77C6C4C6E6BA424FF23088C796BA6195ABA35094BF1829E089662E7A95FC90750AE16D0C8AFA55DAC789D7735B970B58D4BE7CEC7341DA82A0179A01929C27A59C5063215B859EA43", + "E525422519ECE070E82C", + "B47BC07C3ED1C0A43BA52C43CBACBCDBB29CAF1001E09FDF7107"}, + {"7550C2761644E911FE9ADD119BAC07376BEA442845FEAD876D7E7AC1B713E464", + "36D2EC25ADD33CDEDF495205BBC923", + "7FCFE81A3790DE97FFC3DE160C470847EA7E841177C2F759571CBD837EA004A6CA8C6F4AEBFF2E9FD552D73EB8A30705D58D70C0B67AEEA280CBBF0A477358ACEF1E7508F2735CD9A0E4F9AC92B8C008F575D3B6278F1C18BD01227E3502E5255F3AB1893632AD00C717C588EF652A51A43209E7EE90", + "2B1A62F8FDFAA3C16470A21AD307C9A7D03ADE8EF72C69B06F8D738CDE578D7AEFD0D40BD9C022FB9F580DF5394C998ACCCEFC5471A3996FB8F1045A81FDC6F32D13502EA65A211390C8D882B8E0BEFD8DD8CBEF51D1597B124E9F7F", + "C873E02A22DB89EB0787DB6A60B99F7E4A0A085D5C4232A81ADCE2D60AA36F92DDC33F93DD8640AC0E08416B187FB382B3EC3EE85A64B0E6EE41C1366A5AD2A282F66605E87031CCBA2FA7B2DA201D975994AADE3DD1EE122AE09604AD489B84BF0C1AB7129EE16C6934850E"}, + {"A51300285E554FDBDE7F771A9A9A80955639DD87129FAEF74987C91FB9687C71", + "81691D5D20EC818FCFF24B33DECC", + "C948093218AA9EB2A8E44A87EEA73FC8B6B75A196819A14BD83709EA323E8DF8B491045220E1D88729A38DBCFFB60D3056DAD4564498FD6574F74512945DEB34B69329ACED9FFC05D5D59DFCD5B973E2ACAFE6AD1EF8BBBC49351A2DD12508ED89ED", + "EB861165DAF7625F827C6B574ED703F03215", + "C6CD1CE76D2B3679C1B5AA1CFD67CCB55444B6BFD3E22C81CBC9BB738796B83E54E3"}, + {"8CE0156D26FAEB7E0B9B800BBB2E9D4075B5EAC5C62358B0E7F6FCE610223282", + "D2A7B94DD12CDACA909D3AD7", + "E021A78F374FC271389AB9A3E97077D755", + "7C26000B58929F5095E1CEE154F76C2A299248E299F9B5ADE6C403AA1FD4A67FD4E0232F214CE7B919EE7A1027D2B76C57475715CD078461", + "C556FB38DF069B56F337B5FF5775CE6EAA16824DFA754F20B78819028EA635C3BB7AA731DE8776B2DCB67DCA2D33EEDF3C7E52EA450013722A41755A0752433ED17BDD5991AAE77A"}, + {"1E8000A2CE00A561C9920A30BF0D7B983FEF8A1014C8F04C35CA6970E6BA02BD", + "65ED3D63F79F90BBFD19775E", + "336A8C0B7243582A46B221AA677647FCAE91", + "134A8B34824A290E7B", + "914FBEF80D0E6E17F8BDBB6097EBF5FBB0554952DC2B9E5151"}, + {"53D5607BBE690B6E8D8F6D97F3DF2BA853B682597A214B8AA0EA6E598650AF15", + "C391A856B9FE234E14BA1AC7BB40FF", + "479682BC21349C4BE1641D5E78FE2C79EC1B9CF5470936DCAD9967A4DCD7C4EFADA593BC9EDE71E6A08829B8580901B61E274227E9D918502DE3", + "EAD154DC09C5E26C5D26FF33ED148B27120C7F2C23225CC0D0631B03E1F6C6D96FEB88C1A4052ACB4CE746B884B6502931F407021126C6AAB8C514C077A5A38438AE88EE", + "938821286EBB671D999B87C032E1D6055392EB564E57970D55E545FC5E8BAB90E6E3E3C0913F6320995FC636D72CD9919657CC38BD51552F4A502D8D1FE56DB33EBAC5092630E69EBB986F0E15CEE9FC8C052501"}, + {"294362FCC984F440CEA3E9F7D2C06AF20C53AAC1B3738CA2186C914A6E193ABB", + "B15B61C8BB39261A8F55AB178EC3", + "D0729B6B75BB", + "2BD089ADCE9F334BAE3B065996C7D616DD0C27DF4218DCEEA0FBCA0F968837CE26B0876083327E25681FDDD620A32EC0DA12F73FAE826CC94BFF2B90A54D2651", + "AC94B25E4E21DE2437B806966CCD5D9385EF0CD4A51AB9FA6DE675C7B8952D67802E9FEC1FDE9F5D1EAB06057498BC0EEA454804FC9D2068982A3E24182D9AC2E7AB9994DDC899A604264583F63D066B"}, + {"959DBFEB039B1A5B8CE6A44649B602AAA5F98A906DB96143D202CD2024F749D9", + "01D7BDB1133E9C347486C1EFA6", + "F3843955BD741F379DD750585EDC55E2CDA05CCBA8C1F4622AC2FE35214BC3A019B8BD12C4CC42D9213D1E1556941E8D8450830287FFB3B763A13722DD4140ED9846FB5FFF745D7B0B967D810A068222E10B259AF1D392035B0D83DC1498A6830B11B2418A840212599171E0258A1C203B05362978", + "A21811232C950FA8B12237C2EBD6A7CD2C3A155905E9E0C7C120", + "63C1CE397B22F1A03F1FA549B43178BC405B152D3C95E977426D519B3DFCA28498823240592B6EEE7A14"}, + {"096AE499F5294173F34FF2B375F0E5D5AB79D0D03B33B1A74D7D576826345DF4", + "0C52B3D11D636E5910A4DD76D32C", + "229E9ECA3053789E937447BC719467075B6138A142DA528DA8F0CF8DDF022FD9AF8E74779BA3AC306609", + "8B7A00038783E8BAF6EDEAE0C4EAB48FC8FD501A588C7E4A4DB71E3604F2155A97687D3D2FFF8569261375A513CF4398CE0F87CA1658A1050F6EF6C4EA3E25", + "C20B6CF8D3C8241825FD90B2EDAC7593600646E579A8D8DAAE9E2E40C3835FE801B2BE4379131452BC5182C90307B176DFBE2049544222FE7783147B690774F6D9D7CEF52A91E61E298E9AA15464AC"}, +} diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go b/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go new file mode 100644 index 0000000..8430855 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go @@ -0,0 +1,78 @@ +package ocb + +import ( + "encoding/hex" +) + +// Test vectors from https://tools.ietf.org/html/rfc7253. Note that key is +// shared accross tests. +var testKey, _ = hex.DecodeString("000102030405060708090A0B0C0D0E0F") + +var rfc7253testVectors = []struct { + nonce, header, plaintext, ciphertext string +}{ + {"BBAA99887766554433221100", + "", + "", + "785407BFFFC8AD9EDCC5520AC9111EE6"}, + {"BBAA99887766554433221101", + "0001020304050607", + "0001020304050607", + "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009"}, + {"BBAA99887766554433221102", + "0001020304050607", + "", + "81017F8203F081277152FADE694A0A00"}, + {"BBAA99887766554433221103", + "", + "0001020304050607", + "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9"}, + {"BBAA99887766554433221104", + "000102030405060708090A0B0C0D0E0F", + "000102030405060708090A0B0C0D0E0F", + "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358"}, + {"BBAA99887766554433221105", + "000102030405060708090A0B0C0D0E0F", + "", + "8CF761B6902EF764462AD86498CA6B97"}, + {"BBAA99887766554433221106", + "", + "000102030405060708090A0B0C0D0E0F", + "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D"}, + {"BBAA99887766554433221107", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F"}, + {"BBAA99887766554433221108", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "", + "6DC225A071FC1B9F7C69F93B0F1E10DE"}, + {"BBAA99887766554433221109", + "", + "000102030405060708090A0B0C0D0E0F1011121314151617", + "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF"}, + {"BBAA9988776655443322110A", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240"}, + {"BBAA9988776655443322110B", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "", + "FE80690BEE8A485D11F32965BC9D2A32"}, + {"BBAA9988776655443322110C", + "", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF"}, + {"BBAA9988776655443322110D", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60"}, + {"BBAA9988776655443322110E", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "", + "C5CD9D1850C141E358649994EE701B68"}, + {"BBAA9988776655443322110F", + "", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479"}, +} diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go b/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go new file mode 100644 index 0000000..5dc158f --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go @@ -0,0 +1,24 @@ +package ocb + +// Second set of test vectors from https://tools.ietf.org/html/rfc7253 +var rfc7253TestVectorTaglen96 = struct { + key, nonce, header, plaintext, ciphertext string +}{"0F0E0D0C0B0A09080706050403020100", + "BBAA9988776655443322110D", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", + "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA"} + +var rfc7253AlgorithmTest = []struct { + KEYLEN, TAGLEN int + OUTPUT string }{ + {128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"}, + {192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"}, + {256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"}, + {128, 96, "77A3D8E73589158D25D01209"}, + {192, 96, "05D56EAD2752C86BE6932C5E"}, + {256, 96, "5458359AC23B0CBA9E6330DD"}, + {128, 64, "192C9B7BD90BA06A"}, + {192, 64, "0066BC6E0EF34E24"}, + {256, 64, "7D4EA5D445501CBE"}, + } diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go new file mode 100644 index 0000000..3c6251d --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go @@ -0,0 +1,153 @@ +// Copyright 2014 Matthew Endsley +// All rights reserved +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted providing that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// Package keywrap is an implementation of the RFC 3394 AES key wrapping +// algorithm. This is used in OpenPGP with elliptic curve keys. +package keywrap + +import ( + "crypto/aes" + "encoding/binary" + "errors" +) + +var ( + // ErrWrapPlaintext is returned if the plaintext is not a multiple + // of 64 bits. + ErrWrapPlaintext = errors.New("keywrap: plainText must be a multiple of 64 bits") + + // ErrUnwrapCiphertext is returned if the ciphertext is not a + // multiple of 64 bits. + ErrUnwrapCiphertext = errors.New("keywrap: cipherText must by a multiple of 64 bits") + + // ErrUnwrapFailed is returned if unwrapping a key fails. + ErrUnwrapFailed = errors.New("keywrap: failed to unwrap key") + + // NB: the AES NewCipher call only fails if the key is an invalid length. + + // ErrInvalidKey is returned when the AES key is invalid. + ErrInvalidKey = errors.New("keywrap: invalid AES key") +) + +// Wrap a key using the RFC 3394 AES Key Wrap Algorithm. +func Wrap(key, plainText []byte) ([]byte, error) { + if len(plainText)%8 != 0 { + return nil, ErrWrapPlaintext + } + + c, err := aes.NewCipher(key) + if err != nil { + return nil, ErrInvalidKey + } + + nblocks := len(plainText) / 8 + + // 1) Initialize variables. + var block [aes.BlockSize]byte + // - Set A = IV, an initial value (see 2.2.3) + for ii := 0; ii < 8; ii++ { + block[ii] = 0xA6 + } + + // - For i = 1 to n + // - Set R[i] = P[i] + intermediate := make([]byte, len(plainText)) + copy(intermediate, plainText) + + // 2) Calculate intermediate values. + for ii := 0; ii < 6; ii++ { + for jj := 0; jj < nblocks; jj++ { + // - B = AES(K, A | R[i]) + copy(block[8:], intermediate[jj*8:jj*8+8]) + c.Encrypt(block[:], block[:]) + + // - A = MSB(64, B) ^ t where t = (n*j)+1 + t := uint64(ii*nblocks + jj + 1) + val := binary.BigEndian.Uint64(block[:8]) ^ t + binary.BigEndian.PutUint64(block[:8], val) + + // - R[i] = LSB(64, B) + copy(intermediate[jj*8:jj*8+8], block[8:]) + } + } + + // 3) Output results. + // - Set C[0] = A + // - For i = 1 to n + // - C[i] = R[i] + return append(block[:8], intermediate...), nil +} + +// Unwrap a key using the RFC 3394 AES Key Wrap Algorithm. +func Unwrap(key, cipherText []byte) ([]byte, error) { + if len(cipherText)%8 != 0 { + return nil, ErrUnwrapCiphertext + } + + c, err := aes.NewCipher(key) + if err != nil { + return nil, ErrInvalidKey + } + + nblocks := len(cipherText)/8 - 1 + + // 1) Initialize variables. + var block [aes.BlockSize]byte + // - Set A = C[0] + copy(block[:8], cipherText[:8]) + + // - For i = 1 to n + // - Set R[i] = C[i] + intermediate := make([]byte, len(cipherText)-8) + copy(intermediate, cipherText[8:]) + + // 2) Compute intermediate values. + for jj := 5; jj >= 0; jj-- { + for ii := nblocks - 1; ii >= 0; ii-- { + // - B = AES-1(K, (A ^ t) | R[i]) where t = n*j+1 + // - A = MSB(64, B) + t := uint64(jj*nblocks + ii + 1) + val := binary.BigEndian.Uint64(block[:8]) ^ t + binary.BigEndian.PutUint64(block[:8], val) + + copy(block[8:], intermediate[ii*8:ii*8+8]) + c.Decrypt(block[:], block[:]) + + // - R[i] = LSB(B, 64) + copy(intermediate[ii*8:ii*8+8], block[8:]) + } + } + + // 3) Output results. + // - If A is an appropriate initial value (see 2.2.3), + for ii := 0; ii < 8; ii++ { + if block[ii] != 0xA6 { + return nil, ErrUnwrapFailed + } + } + + // - For i = 1 to n + // - P[i] = R[i] + return intermediate, nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go similarity index 97% rename from vendor/golang.org/x/crypto/openpgp/armor/armor.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go index 36a6804..3b357e5 100644 --- a/vendor/golang.org/x/crypto/openpgp/armor/armor.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go @@ -4,13 +4,13 @@ // Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is // very similar to PEM except that it has an additional CRC checksum. -package armor // import "golang.org/x/crypto/openpgp/armor" +package armor // import "github.com/ProtonMail/go-crypto/openpgp/armor" import ( "bufio" "bytes" "encoding/base64" - "golang.org/x/crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/errors" "io" ) diff --git a/vendor/golang.org/x/crypto/openpgp/armor/encode.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go similarity index 100% rename from vendor/golang.org/x/crypto/openpgp/armor/encode.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go similarity index 80% rename from vendor/golang.org/x/crypto/openpgp/canonical_text.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go index e601e38..a94f615 100644 --- a/vendor/golang.org/x/crypto/openpgp/canonical_text.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go @@ -4,7 +4,10 @@ package openpgp -import "hash" +import ( + "hash" + "io" +) // NewCanonicalTextHash reformats text written to it into the canonical // form and then applies the hash h. See RFC 4880, section 5.2.1. @@ -19,28 +22,31 @@ type canonicalTextHash struct { var newline = []byte{'\r', '\n'} -func (cth *canonicalTextHash) Write(buf []byte) (int, error) { +func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) { start := 0 - for i, c := range buf { - switch cth.s { + switch *s { case 0: if c == '\r' { - cth.s = 1 + *s = 1 } else if c == '\n' { - cth.h.Write(buf[start:i]) - cth.h.Write(newline) + cw.Write(buf[start:i]) + cw.Write(newline) start = i + 1 } case 1: - cth.s = 0 + *s = 0 } } - cth.h.Write(buf[start:]) + cw.Write(buf[start:]) return len(buf), nil } +func (cth *canonicalTextHash) Write(buf []byte) (int, error) { + return writeCanonical(cth.h, buf, &cth.s) +} + func (cth *canonicalTextHash) Sum(in []byte) []byte { return cth.h.Sum(in) } diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go new file mode 100644 index 0000000..0b49be4 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go @@ -0,0 +1,165 @@ +// Copyright 2017 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 ecdh implements ECDH encryption, suitable for OpenPGP, +// as specified in RFC 6637, section 8. +package ecdh + +import ( + "bytes" + "crypto/elliptic" + "errors" + "io" + "math/big" + + "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap" + "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" + "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" +) + +type KDF struct { + Hash algorithm.Hash + Cipher algorithm.Cipher +} + +type PublicKey struct { + ecc.CurveType + elliptic.Curve + X, Y *big.Int + KDF +} + +type PrivateKey struct { + PublicKey + D []byte +} + +func GenerateKey(c elliptic.Curve, kdf KDF, rand io.Reader) (priv *PrivateKey, err error) { + priv = new(PrivateKey) + priv.PublicKey.Curve = c + priv.PublicKey.KDF = kdf + priv.D, priv.PublicKey.X, priv.PublicKey.Y, err = elliptic.GenerateKey(c, rand) + return +} + +func Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte) (vsG, c []byte, err error) { + if len(msg) > 40 { + return nil, nil, errors.New("ecdh: message too long") + } + // the sender MAY use 21, 13, and 5 bytes of padding for AES-128, + // AES-192, and AES-256, respectively, to provide the same number of + // octets, 40 total, as an input to the key wrapping method. + padding := make([]byte, 40-len(msg)) + for i := range padding { + padding[i] = byte(40 - len(msg)) + } + m := append(msg, padding...) + + if pub.CurveType == ecc.Curve25519 { + return X25519Encrypt(random, pub, m, curveOID, fingerprint) + } + + d, x, y, err := elliptic.GenerateKey(pub.Curve, random) + if err != nil { + return nil, nil, err + } + + vsG = elliptic.Marshal(pub.Curve, x, y) + zbBig, _ := pub.Curve.ScalarMult(pub.X, pub.Y, d) + + byteLen := (pub.Curve.Params().BitSize + 7) >> 3 + zb := make([]byte, byteLen) + zbBytes := zbBig.Bytes() + copy(zb[byteLen-len(zbBytes):], zbBytes) + + z, err := buildKey(pub, zb, curveOID, fingerprint, false, false) + if err != nil { + return nil, nil, err + } + + if c, err = keywrap.Wrap(z, m); err != nil { + return nil, nil, err + } + + return vsG, c, nil + +} + +func Decrypt(priv *PrivateKey, vsG, m, curveOID, fingerprint []byte) (msg []byte, err error) { + if priv.PublicKey.CurveType == ecc.Curve25519 { + return X25519Decrypt(priv, vsG, m, curveOID, fingerprint) + } + x, y := elliptic.Unmarshal(priv.Curve, vsG) + zbBig, _ := priv.Curve.ScalarMult(x, y, priv.D) + + byteLen := (priv.Curve.Params().BitSize + 7) >> 3 + zb := make([]byte, byteLen) + zbBytes := zbBig.Bytes() + copy(zb[byteLen-len(zbBytes):], zbBytes) + + z, err := buildKey(&priv.PublicKey, zb, curveOID, fingerprint, false, false) + if err != nil { + return nil, err + } + + c, err := keywrap.Unwrap(z, m) + if err != nil { + return nil, err + } + + return c[:len(c)-int(c[len(c)-1])], nil +} + +func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLeading, stripTrailing bool) ([]byte, error) { + // Param = curve_OID_len || curve_OID || public_key_alg_ID || 03 + // || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap + // || "Anonymous Sender " || recipient_fingerprint; + param := new(bytes.Buffer) + if _, err := param.Write(curveOID); err != nil { + return nil, err + } + algKDF := []byte{18, 3, 1, pub.KDF.Hash.Id(), pub.KDF.Cipher.Id()} + if _, err := param.Write(algKDF); err != nil { + return nil, err + } + if _, err := param.Write([]byte("Anonymous Sender ")); err != nil { + return nil, err + } + // For v5 keys, the 20 leftmost octets of the fingerprint are used. + if _, err := param.Write(fingerprint[:20]); err != nil { + return nil, err + } + if param.Len() - len(curveOID) != 45 { + return nil, errors.New("ecdh: malformed KDF Param") + } + + // MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param ); + h := pub.KDF.Hash.New() + if _, err := h.Write([]byte{0x0, 0x0, 0x0, 0x1}); err != nil { + return nil, err + } + zbLen := len(zb) + i := 0 + j := zbLen - 1 + if stripLeading { + // Work around old go crypto bug where the leading zeros are missing. + for ; i < zbLen && zb[i] == 0; i++ {} + } + if stripTrailing { + // Work around old OpenPGP.js bug where insignificant trailing zeros in + // this little-endian number are missing. + // (See https://github.com/openpgpjs/openpgpjs/pull/853.) + for ; j >= 0 && zb[j] == 0; j-- {} + } + if _, err := h.Write(zb[i:j+1]); err != nil { + return nil, err + } + if _, err := h.Write(param.Bytes()); err != nil { + return nil, err + } + mb := h.Sum(nil) + + return mb[:pub.KDF.Cipher.KeySize()], nil // return oBits leftmost bits of MB. + +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/x25519.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/x25519.go new file mode 100644 index 0000000..15b41a3 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/x25519.go @@ -0,0 +1,157 @@ +// Copyright 2017 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 ecdh implements ECDH encryption, suitable for OpenPGP, +// as specified in RFC 6637, section 8. +package ecdh + +import ( + "errors" + "io" + "math/big" + + "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap" + "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" + "golang.org/x/crypto/curve25519" +) + +// Generates a private-public key-pair. +// 'priv' is a private key; a scalar belonging to the set +// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of the +// curve. 'pub' is simply 'priv' * G where G is the base point. +// See https://cr.yp.to/ecdh.html and RFC7748, sec 5. +func x25519GenerateKeyPairBytes(rand io.Reader) (priv [32]byte, pub [32]byte, err error) { + var n, helper = new(big.Int), new(big.Int) + n.SetUint64(1) + n.Lsh(n, 252) + helper.SetString("27742317777372353535851937790883648493", 10) + n.Add(n, helper) + + for true { + _, err = io.ReadFull(rand, priv[:]) + if err != nil { + return + } + // The following ensures that the private key is a number of the form + // 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of + // of the curve. + priv[0] &= 248 + priv[31] &= 127 + priv[31] |= 64 + + // If the scalar is out of range, sample another random number. + if new(big.Int).SetBytes(priv[:]).Cmp(n) >= 0 { + continue + } + + curve25519.ScalarBaseMult(&pub, &priv) + return + } + return +} + +// X25519GenerateKey samples the key pair according to the correct distribution. +// It also sets the given key-derivation function and returns the *PrivateKey +// object along with an error. +func X25519GenerateKey(rand io.Reader, kdf KDF) (priv *PrivateKey, err error) { + ci := ecc.FindByName("Curve25519") + priv = new(PrivateKey) + priv.PublicKey.Curve = ci.Curve + d, pubKey, err := x25519GenerateKeyPairBytes(rand) + if err != nil { + return nil, err + } + priv.PublicKey.KDF = kdf + priv.D = make([]byte, 32) + copyReversed(priv.D, d[:]) + priv.PublicKey.CurveType = ci.CurveType + priv.PublicKey.Curve = ci.Curve + /* + * Note that ECPoint.point differs from the definition of public keys in + * [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is + * more uniform with how big integers are represented in TLS, and (2) there + * is an additional length byte (so ECpoint.point is actually 33 bytes), + * again for uniformity (and extensibility). + */ + var encodedKey = make([]byte, 33) + encodedKey[0] = 0x40 + copy(encodedKey[1:], pubKey[:]) + priv.PublicKey.X = new(big.Int).SetBytes(encodedKey[:]) + priv.PublicKey.Y = new(big.Int) + return priv, nil +} + +func X25519Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte) (vsG, c []byte, err error) { + d, ephemeralKey, err := x25519GenerateKeyPairBytes(random) + if err != nil { + return nil, nil, err + } + var pubKey [32]byte + + if pub.X.BitLen() > 33*264 { + return nil, nil, errors.New("ecdh: invalid key") + } + copy(pubKey[:], pub.X.Bytes()[1:]) + + var zb [32]byte + curve25519.ScalarBaseMult(&zb, &d) + curve25519.ScalarMult(&zb, &d, &pubKey) + z, err := buildKey(pub, zb[:], curveOID, fingerprint, false, false) + + if err != nil { + return nil, nil, err + } + + if c, err = keywrap.Wrap(z, msg); err != nil { + return nil, nil, err + } + + var vsg [33]byte + vsg[0] = 0x40 + copy(vsg[1:], ephemeralKey[:]) + + return vsg[:], c, nil +} + +func X25519Decrypt(priv *PrivateKey, vsG, m, curveOID, fingerprint []byte) (msg []byte, err error) { + var zb, d, ephemeralKey [32]byte + if len(vsG) != 33 || vsG[0] != 0x40 { + return nil, errors.New("ecdh: invalid key") + } + copy(ephemeralKey[:], vsG[1:33]) + + copyReversed(d[:], priv.D) + curve25519.ScalarBaseMult(&zb, &d) + curve25519.ScalarMult(&zb, &d, &ephemeralKey) + + var c []byte + + for i := 0; i < 3; i++ { + // Try buildKey three times for compat, see comments in buildKey. + z, err := buildKey(&priv.PublicKey, zb[:], curveOID, fingerprint, i == 1, i == 2) + if err != nil { + return nil, err + } + + res, err := keywrap.Unwrap(z, m) + if i == 2 && err != nil { + // Only return an error after we've tried all variants of buildKey. + return nil, err + } + + c = res + if err == nil { + break + } + } + + return c[:len(c)-int(c[len(c)-1])], nil +} + +func copyReversed(out []byte, in []byte) { + l := len(in) + for i := 0; i < l; i++ { + out[i] = in[l-i-1] + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go similarity index 97% rename from vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go index 72a6a73..6a07d8f 100644 --- a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go @@ -10,7 +10,7 @@ // This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it // unsuitable for other protocols. RSA should be used in preference in any // case. -package elgamal // import "golang.org/x/crypto/openpgp/elgamal" +package elgamal // import "github.com/ProtonMail/go-crypto/openpgp/elgamal" import ( "crypto/rand" diff --git a/vendor/golang.org/x/crypto/openpgp/errors/errors.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go similarity index 56% rename from vendor/golang.org/x/crypto/openpgp/errors/errors.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go index eb0550b..17e2bcf 100644 --- a/vendor/golang.org/x/crypto/openpgp/errors/errors.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Package errors contains common error types for the OpenPGP packages. -package errors // import "golang.org/x/crypto/openpgp/errors" +package errors // import "github.com/ProtonMail/go-crypto/openpgp/errors" import ( "strconv" @@ -41,6 +41,25 @@ func (b SignatureError) Error() string { return "openpgp: invalid signature: " + string(b) } +var ErrMDCHashMismatch error = SignatureError("MDC hash mismatch") +var ErrMDCMissing error = SignatureError("MDC packet not found") + +type signatureExpiredError int + +func (se signatureExpiredError) Error() string { + return "openpgp: signature expired" +} + +var ErrSignatureExpired error = signatureExpiredError(0) + +type keyExpiredError int + +func (ke keyExpiredError) Error() string { + return "openpgp: key expired" +} + +var ErrKeyExpired error = keyExpiredError(0) + type keyIncorrectError int func (ki keyIncorrectError) Error() string { @@ -49,6 +68,14 @@ func (ki keyIncorrectError) Error() string { var ErrKeyIncorrect error = keyIncorrectError(0) +// KeyInvalidError indicates that the public key parameters are invalid +// as they do not match the private ones +type KeyInvalidError string + +func (e KeyInvalidError) Error() string { + return "openpgp: invalid key: " + string(e) +} + type unknownIssuerError int func (unknownIssuerError) Error() string { @@ -70,3 +97,20 @@ type UnknownPacketTypeError uint8 func (upte UnknownPacketTypeError) Error() string { return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) } + +// AEADError indicates that there is a problem when initializing or using a +// AEAD instance, configuration struct, nonces or index values. +type AEADError string + +func (ae AEADError) Error() string { + return "openpgp: aead error: " + string(ae) +} + +// ErrDummyPrivateKey results when operations are attempted on a private key +// that is just a dummy key. See +// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109 +type ErrDummyPrivateKey string + +func (dke ErrDummyPrivateKey) Error() string { + return "openpgp: s2k GNU dummy key: " + string(dke) +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go new file mode 100644 index 0000000..17a1bfe --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go @@ -0,0 +1,65 @@ +// Copyright (C) 2019 ProtonTech AG + +package algorithm + +import ( + "crypto/cipher" + "github.com/ProtonMail/go-crypto/eax" + "github.com/ProtonMail/go-crypto/ocb" +) + +// AEADMode defines the Authenticated Encryption with Associated Data mode of +// operation. +type AEADMode uint8 + +// Supported modes of operation (see RFC4880bis [EAX] and RFC7253) +const ( + AEADModeEAX = AEADMode(1) + AEADModeOCB = AEADMode(2) + AEADModeGCM = AEADMode(100) +) + +// TagLength returns the length in bytes of authentication tags. +func (mode AEADMode) TagLength() int { + switch mode { + case AEADModeEAX: + return 16 + case AEADModeOCB: + return 16 + case AEADModeGCM: + return 16 + default: + return 0 + } +} + +// NonceLength returns the length in bytes of nonces. +func (mode AEADMode) NonceLength() int { + switch mode { + case AEADModeEAX: + return 16 + case AEADModeOCB: + return 15 + case AEADModeGCM: + return 12 + default: + return 0 + } +} + +// New returns a fresh instance of the given mode +func (mode AEADMode) New(block cipher.Block) (alg cipher.AEAD) { + var err error + switch mode { + case AEADModeEAX: + alg, err = eax.NewEAX(block) + case AEADModeOCB: + alg, err = ocb.NewOCB(block) + case AEADModeGCM: + alg, err = cipher.NewGCM(block) + } + if err != nil { + panic(err.Error()) + } + return alg +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go new file mode 100644 index 0000000..5760cff --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go @@ -0,0 +1,107 @@ +// Copyright 2017 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 algorithm + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/des" + + "golang.org/x/crypto/cast5" +) + +// Cipher is an official symmetric key cipher algorithm. See RFC 4880, +// section 9.2. +type Cipher interface { + // Id returns the algorithm ID, as a byte, of the cipher. + Id() uint8 + // KeySize returns the key size, in bytes, of the cipher. + KeySize() int + // BlockSize returns the block size, in bytes, of the cipher. + BlockSize() int + // New returns a fresh instance of the given cipher. + New(key []byte) cipher.Block +} + +// The following constants mirror the OpenPGP standard (RFC 4880). +const ( + TripleDES = CipherFunction(2) + CAST5 = CipherFunction(3) + AES128 = CipherFunction(7) + AES192 = CipherFunction(8) + AES256 = CipherFunction(9) +) + +// CipherById represents the different block ciphers specified for OpenPGP. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 +var CipherById = map[uint8]Cipher{ + TripleDES.Id(): TripleDES, + CAST5.Id(): CAST5, + AES128.Id(): AES128, + AES192.Id(): AES192, + AES256.Id(): AES256, +} + +type CipherFunction uint8 + +// ID returns the algorithm Id, as a byte, of cipher. +func (sk CipherFunction) Id() uint8 { + return uint8(sk) +} + +var keySizeByID = map[uint8]int{ + TripleDES.Id(): 24, + CAST5.Id(): cast5.KeySize, + AES128.Id(): 16, + AES192.Id(): 24, + AES256.Id(): 32, +} + +// KeySize returns the key size, in bytes, of cipher. +func (cipher CipherFunction) KeySize() int { + switch cipher { + case TripleDES: + return 24 + case CAST5: + return cast5.KeySize + case AES128: + return 16 + case AES192: + return 24 + case AES256: + return 32 + } + return 0 +} + +// BlockSize returns the block size, in bytes, of cipher. +func (cipher CipherFunction) BlockSize() int { + switch cipher { + case TripleDES: + return des.BlockSize + case CAST5: + return 8 + case AES128, AES192, AES256: + return 16 + } + return 0 +} + +// New returns a fresh instance of the given cipher. +func (cipher CipherFunction) New(key []byte) (block cipher.Block) { + var err error + switch cipher { + case TripleDES: + block, err = des.NewTripleDESCipher(key) + case CAST5: + block, err = cast5.NewCipher(key) + case AES128, AES192, AES256: + block, err = aes.NewCipher(key) + } + if err != nil { + panic(err.Error()) + } + return +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go new file mode 100644 index 0000000..3f1b61b --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go @@ -0,0 +1,86 @@ +// Copyright 2017 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 algorithm + +import ( + "crypto" + "fmt" + "hash" +) + +// Hash is an official hash function algorithm. See RFC 4880, section 9.4. +type Hash interface { + // Id returns the algorithm ID, as a byte, of Hash. + Id() uint8 + // Available reports whether the given hash function is linked into the binary. + Available() bool + // HashFunc simply returns the value of h so that Hash implements SignerOpts. + HashFunc() crypto.Hash + // New returns a new hash.Hash calculating the given hash function. New + // panics if the hash function is not linked into the binary. + New() hash.Hash + // Size returns the length, in bytes, of a digest resulting from the given + // hash function. It doesn't require that the hash function in question be + // linked into the program. + Size() int + // String is the name of the hash function corresponding to the given + // OpenPGP hash id. + String() string +} + +// The following vars mirror the crypto/Hash supported hash functions. +var ( + MD5 Hash = cryptoHash{1, crypto.MD5} + SHA1 Hash = cryptoHash{2, crypto.SHA1} + RIPEMD160 Hash = cryptoHash{3, crypto.RIPEMD160} + SHA256 Hash = cryptoHash{8, crypto.SHA256} + SHA384 Hash = cryptoHash{9, crypto.SHA384} + SHA512 Hash = cryptoHash{10, crypto.SHA512} + SHA224 Hash = cryptoHash{11, crypto.SHA224} +) + +// HashById represents the different hash functions specified for OpenPGP. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14 +var ( + HashById = map[uint8]Hash{ + MD5.Id(): MD5, + SHA1.Id(): SHA1, + RIPEMD160.Id(): RIPEMD160, + SHA256.Id(): SHA256, + SHA384.Id(): SHA384, + SHA512.Id(): SHA512, + SHA224.Id(): SHA224, + } +) + +// cryptoHash contains pairs relating OpenPGP's hash identifier with +// Go's crypto.Hash type. See RFC 4880, section 9.4. +type cryptoHash struct { + id uint8 + crypto.Hash +} + +// Id returns the algorithm ID, as a byte, of cryptoHash. +func (h cryptoHash) Id() uint8 { + return h.id +} + +var hashNames = map[uint8]string{ + MD5.Id(): "MD5", + SHA1.Id(): "SHA1", + RIPEMD160.Id(): "RIPEMD160", + SHA256.Id(): "SHA256", + SHA384.Id(): "SHA384", + SHA512.Id(): "SHA512", + SHA224.Id(): "SHA224", +} + +func (h cryptoHash) String() string { + s, ok := hashNames[h.id] + if !ok { + panic(fmt.Sprintf("Unsupported hash function %d", h.id)) + } + return s +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveInfo.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveInfo.go new file mode 100644 index 0000000..f91042f --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveInfo.go @@ -0,0 +1,118 @@ +package ecc + +import ( + "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" + "crypto/elliptic" + "bytes" + "github.com/ProtonMail/go-crypto/bitcurves" + "github.com/ProtonMail/go-crypto/brainpool" +) + +type SignatureAlgorithm uint8 + +const ( + ECDSA SignatureAlgorithm = 1 + EdDSA SignatureAlgorithm = 2 +) + +type CurveInfo struct { + Name string + Oid *encoding.OID + Curve elliptic.Curve + SigAlgorithm SignatureAlgorithm + CurveType CurveType +} + +var curves = []CurveInfo{ + { + Name: "NIST curve P-256", + Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}), + Curve: elliptic.P256(), + CurveType: NISTCurve, + SigAlgorithm: ECDSA, + }, + { + Name: "NIST curve P-384", + Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}), + Curve: elliptic.P384(), + CurveType: NISTCurve, + SigAlgorithm: ECDSA, + }, + { + Name: "NIST curve P-521", + Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}), + Curve: elliptic.P521(), + CurveType: NISTCurve, + SigAlgorithm: ECDSA, + }, + { + Name: "SecP256k1", + Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}), + Curve: bitcurves.S256(), + CurveType: BitCurve, + SigAlgorithm: ECDSA, + }, + { + Name: "Curve25519", + Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}), + Curve: elliptic.P256(),// filler + CurveType: Curve25519, + SigAlgorithm: ECDSA, + }, + { + Name: "Ed25519", + Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}), + Curve: elliptic.P256(), // filler + CurveType: NISTCurve, + SigAlgorithm: EdDSA, + }, + { + Name: "Brainpool P256r1", + Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}), + Curve: brainpool.P256r1(), + CurveType: BrainpoolCurve, + SigAlgorithm: ECDSA, + }, + { + Name: "BrainpoolP384r1", + Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}), + Curve: brainpool.P384r1(), + CurveType: BrainpoolCurve, + SigAlgorithm: ECDSA, + }, + { + Name: "BrainpoolP512r1", + Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}), + Curve: brainpool.P512r1(), + CurveType: BrainpoolCurve, + SigAlgorithm: ECDSA, + }, +} + +func FindByCurve(curve elliptic.Curve) *CurveInfo { + for _, curveInfo := range curves { + if curveInfo.Curve == curve { + return &curveInfo + } + } + return nil +} + +func FindByOid(oid encoding.Field) *CurveInfo { + var rawBytes = oid.Bytes() + for _, curveInfo := range curves { + if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) { + return &curveInfo + } + } + return nil +} + +func FindByName(name string) *CurveInfo { + for _, curveInfo := range curves { + if curveInfo.Name == name { + return &curveInfo + } + } + return nil +} \ No newline at end of file diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveType.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveType.go new file mode 100644 index 0000000..de8bca0 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveType.go @@ -0,0 +1,10 @@ +package ecc + +type CurveType uint8 + +const ( + NISTCurve CurveType = 1 + Curve25519 CurveType = 2 + BitCurve CurveType = 3 + BrainpoolCurve CurveType = 4 +) \ No newline at end of file diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go new file mode 100644 index 0000000..6c92148 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go @@ -0,0 +1,27 @@ +// Copyright 2017 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 encoding implements openpgp packet field encodings as specified in +// RFC 4880 and 6637. +package encoding + +import "io" + +// Field is an encoded field of an openpgp packet. +type Field interface { + // Bytes returns the decoded data. + Bytes() []byte + + // BitLength is the size in bits of the decoded data. + BitLength() uint16 + + // EncodedBytes returns the encoded data. + EncodedBytes() []byte + + // EncodedLength is the size in bytes of the encoded data. + EncodedLength() uint16 + + // ReadFrom reads the next Field from r. + ReadFrom(r io.Reader) (int64, error) +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go new file mode 100644 index 0000000..02e5e69 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go @@ -0,0 +1,91 @@ +// Copyright 2017 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 encoding + +import ( + "io" + "math/big" + "math/bits" +) + +// An MPI is used to store the contents of a big integer, along with the bit +// length that was specified in the original input. This allows the MPI to be +// reserialized exactly. +type MPI struct { + bytes []byte + bitLength uint16 +} + +// NewMPI returns a MPI initialized with bytes. +func NewMPI(bytes []byte) *MPI { + for len(bytes) != 0 && bytes[0] == 0 { + bytes = bytes[1:] + } + if len(bytes) == 0 { + bitLength := uint16(0) + return &MPI{bytes, bitLength} + } + bitLength := 8*uint16(len(bytes)-1) + uint16(bits.Len8(bytes[0])) + return &MPI{bytes, bitLength} +} + +// Bytes returns the decoded data. +func (m *MPI) Bytes() []byte { + return m.bytes +} + +// BitLength is the size in bits of the decoded data. +func (m *MPI) BitLength() uint16 { + return m.bitLength +} + +// EncodedBytes returns the encoded data. +func (m *MPI) EncodedBytes() []byte { + return append([]byte{byte(m.bitLength >> 8), byte(m.bitLength)}, m.bytes...) +} + +// EncodedLength is the size in bytes of the encoded data. +func (m *MPI) EncodedLength() uint16 { + return uint16(2 + len(m.bytes)) +} + +// ReadFrom reads into m the next MPI from r. +func (m *MPI) ReadFrom(r io.Reader) (int64, error) { + var buf [2]byte + n, err := io.ReadFull(r, buf[0:]) + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return int64(n), err + } + + m.bitLength = uint16(buf[0])<<8 | uint16(buf[1]) + m.bytes = make([]byte, (int(m.bitLength)+7)/8) + + nn, err := io.ReadFull(r, m.bytes) + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + + // remove leading zero bytes from malformed GnuPG encoded MPIs: + // https://bugs.gnupg.org/gnupg/issue1853 + // for _, b := range m.bytes { + // if b != 0 { + // break + // } + // m.bytes = m.bytes[1:] + // m.bitLength -= 8 + // } + + return int64(n) + int64(nn), err +} + +// SetBig initializes m with the bits from n. +func (m *MPI) SetBig(n *big.Int) *MPI { + m.bytes = n.Bytes() + m.bitLength = uint16(n.BitLen()) + return m +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go new file mode 100644 index 0000000..ee39fd6 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go @@ -0,0 +1,88 @@ +// Copyright 2017 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 encoding + +import ( + "io" + + "github.com/ProtonMail/go-crypto/openpgp/errors" +) + +// OID is used to store a variable-length field with a one-octet size +// prefix. See https://tools.ietf.org/html/rfc6637#section-9. +type OID struct { + bytes []byte +} + +const ( + // maxOID is the maximum number of bytes in a OID. + maxOID = 254 + // reservedOIDLength1 and reservedOIDLength2 are OID lengths that the RFC + // specifies are reserved. + reservedOIDLength1 = 0 + reservedOIDLength2 = 0xff +) + +// NewOID returns a OID initialized with bytes. +func NewOID(bytes []byte) *OID { + switch len(bytes) { + case reservedOIDLength1, reservedOIDLength2: + panic("encoding: NewOID argument length is reserved") + default: + if len(bytes) > maxOID { + panic("encoding: NewOID argment too large") + } + } + + return &OID{ + bytes: bytes, + } +} + +// Bytes returns the decoded data. +func (o *OID) Bytes() []byte { + return o.bytes +} + +// BitLength is the size in bits of the decoded data. +func (o *OID) BitLength() uint16 { + return uint16(len(o.bytes) * 8) +} + +// EncodedBytes returns the encoded data. +func (o *OID) EncodedBytes() []byte { + return append([]byte{byte(len(o.bytes))}, o.bytes...) +} + +// EncodedLength is the size in bytes of the encoded data. +func (o *OID) EncodedLength() uint16 { + return uint16(1 + len(o.bytes)) +} + +// ReadFrom reads into b the next OID from r. +func (o *OID) ReadFrom(r io.Reader) (int64, error) { + var buf [1]byte + n, err := io.ReadFull(r, buf[:]) + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return int64(n), err + } + + switch buf[0] { + case reservedOIDLength1, reservedOIDLength2: + return int64(n), errors.UnsupportedError("reserved for future extensions") + } + + o.bytes = make([]byte, buf[0]) + + nn, err := io.ReadFull(r, o.bytes) + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + + return int64(n) + int64(nn), err +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go new file mode 100644 index 0000000..0d2eb45 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go @@ -0,0 +1,375 @@ +// 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 openpgp + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + goerrors "errors" + "io" + "math/big" + + "github.com/ProtonMail/go-crypto/openpgp/ecdh" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" + "github.com/ProtonMail/go-crypto/openpgp/packet" + "golang.org/x/crypto/ed25519" +) + +// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a +// single identity composed of the given full name, comment and email, any of +// which may be empty but must not contain any of "()<>\x00". +// If config is nil, sensible defaults will be used. +func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { + creationTime := config.Now() + keyLifetimeSecs := config.KeyLifetime() + + uid := packet.NewUserId(name, comment, email) + if uid == nil { + return nil, errors.InvalidArgumentError("user id field contained invalid characters") + } + + // Generate a primary signing key + primaryPrivRaw, err := newSigner(config) + if err != nil { + return nil, err + } + primary := packet.NewSignerPrivateKey(creationTime, primaryPrivRaw) + if config != nil && config.V5Keys { + primary.UpgradeToV5() + } + + isPrimaryId := true + selfSignature := &packet.Signature{ + Version: primary.PublicKey.Version, + SigType: packet.SigTypePositiveCert, + PubKeyAlgo: primary.PublicKey.PubKeyAlgo, + Hash: config.Hash(), + CreationTime: creationTime, + KeyLifetimeSecs: &keyLifetimeSecs, + IssuerKeyId: &primary.PublicKey.KeyId, + IssuerFingerprint: primary.PublicKey.Fingerprint, + IsPrimaryId: &isPrimaryId, + FlagsValid: true, + FlagSign: true, + FlagCertify: true, + MDC: true, // true by default, see 5.8 vs. 5.14 + AEAD: config.AEAD() != nil, + V5Keys: config != nil && config.V5Keys, + } + + // Set the PreferredHash for the SelfSignature from the packet.Config. + // If it is not the must-implement algorithm from rfc4880bis, append that. + selfSignature.PreferredHash = []uint8{hashToHashId(config.Hash())} + if config.Hash() != crypto.SHA256 { + selfSignature.PreferredHash = append(selfSignature.PreferredHash, hashToHashId(crypto.SHA256)) + } + + // Likewise for DefaultCipher. + selfSignature.PreferredSymmetric = []uint8{uint8(config.Cipher())} + if config.Cipher() != packet.CipherAES128 { + selfSignature.PreferredSymmetric = append(selfSignature.PreferredSymmetric, uint8(packet.CipherAES128)) + } + + // And for DefaultMode. + selfSignature.PreferredAEAD = []uint8{uint8(config.AEAD().Mode())} + if config.AEAD().Mode() != packet.AEADModeEAX { + selfSignature.PreferredAEAD = append(selfSignature.PreferredAEAD, uint8(packet.AEADModeEAX)) + } + + // User ID binding signature + err = selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config) + if err != nil { + return nil, err + } + + // Generate an encryption subkey + subPrivRaw, err := newDecrypter(config) + if err != nil { + return nil, err + } + sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw) + sub.IsSubkey = true + sub.PublicKey.IsSubkey = true + if config != nil && config.V5Keys { + sub.UpgradeToV5() + } + + // NOTE: No KeyLifetimeSecs here, but we will not return this subkey in EncryptionKey() + // if the primary/master key has expired. + subKey := Subkey{ + PublicKey: &sub.PublicKey, + PrivateKey: sub, + Sig: &packet.Signature{ + Version: primary.PublicKey.Version, + CreationTime: creationTime, + SigType: packet.SigTypeSubkeyBinding, + PubKeyAlgo: primary.PublicKey.PubKeyAlgo, + Hash: config.Hash(), + FlagsValid: true, + FlagEncryptStorage: true, + FlagEncryptCommunications: true, + IssuerKeyId: &primary.PublicKey.KeyId, + }, + } + + // Subkey binding signature + err = subKey.Sig.SignKey(subKey.PublicKey, primary, config) + if err != nil { + return nil, err + } + + return &Entity{ + PrimaryKey: &primary.PublicKey, + PrivateKey: primary, + Identities: map[string]*Identity{ + uid.Id: &Identity{ + Name: uid.Id, + UserId: uid, + SelfSignature: selfSignature, + Signatures: []*packet.Signature{selfSignature}, + }, + }, + Subkeys: []Subkey{subKey}, + }, nil +} + +// AddSigningSubkey adds a signing keypair as a subkey to the Entity. +// If config is nil, sensible defaults will be used. +func (e *Entity) AddSigningSubkey(config *packet.Config) error { + creationTime := config.Now() + keyLifetimeSecs := config.KeyLifetime() + + subPrivRaw, err := newSigner(config) + if err != nil { + return err + } + sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw) + + subkey := Subkey{ + PublicKey: &sub.PublicKey, + PrivateKey: sub, + Sig: &packet.Signature{ + Version: e.PrimaryKey.Version, + CreationTime: creationTime, + KeyLifetimeSecs: &keyLifetimeSecs, + SigType: packet.SigTypeSubkeyBinding, + PubKeyAlgo: e.PrimaryKey.PubKeyAlgo, + Hash: config.Hash(), + FlagsValid: true, + FlagSign: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + EmbeddedSignature: &packet.Signature{ + Version: e.PrimaryKey.Version, + CreationTime: creationTime, + SigType: packet.SigTypePrimaryKeyBinding, + PubKeyAlgo: sub.PublicKey.PubKeyAlgo, + Hash: config.Hash(), + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + }, + } + if config != nil && config.V5Keys { + subkey.PublicKey.UpgradeToV5() + } + + err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, subkey.PrivateKey, config) + if err != nil { + return err + } + + subkey.PublicKey.IsSubkey = true + subkey.PrivateKey.IsSubkey = true + if err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config); err != nil { + return err + } + + e.Subkeys = append(e.Subkeys, subkey) + return nil +} + +// AddEncryptionSubkey adds an encryption keypair as a subkey to the Entity. +// If config is nil, sensible defaults will be used. +func (e *Entity) AddEncryptionSubkey(config *packet.Config) error { + creationTime := config.Now() + keyLifetimeSecs := config.KeyLifetime() + + subPrivRaw, err := newDecrypter(config) + if err != nil { + return err + } + sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw) + + subkey := Subkey{ + PublicKey: &sub.PublicKey, + PrivateKey: sub, + Sig: &packet.Signature{ + Version: e.PrimaryKey.Version, + CreationTime: creationTime, + KeyLifetimeSecs: &keyLifetimeSecs, + SigType: packet.SigTypeSubkeyBinding, + PubKeyAlgo: e.PrimaryKey.PubKeyAlgo, + Hash: config.Hash(), + FlagsValid: true, + FlagEncryptStorage: true, + FlagEncryptCommunications: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + } + if config != nil && config.V5Keys { + subkey.PublicKey.UpgradeToV5() + } + + subkey.PublicKey.IsSubkey = true + subkey.PrivateKey.IsSubkey = true + if err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config); err != nil { + return err + } + + e.Subkeys = append(e.Subkeys, subkey) + return nil +} + +// Generates a signing key +func newSigner(config *packet.Config) (signer crypto.Signer, err error) { + switch config.PublicKeyAlgorithm() { + case packet.PubKeyAlgoRSA: + bits := config.RSAModulusBits() + if bits < 1024 { + return nil, errors.InvalidArgumentError("bits must be >= 1024") + } + if config != nil && len(config.RSAPrimes) >= 2 { + primes := config.RSAPrimes[0:2] + config.RSAPrimes = config.RSAPrimes[2:] + return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes) + } + return rsa.GenerateKey(config.Random(), bits) + case packet.PubKeyAlgoEdDSA: + _, priv, err := ed25519.GenerateKey(config.Random()) + if err != nil { + return nil, err + } + return &priv, nil + default: + return nil, errors.InvalidArgumentError("unsupported public key algorithm") + } +} + +// Generates an encryption/decryption key +func newDecrypter(config *packet.Config) (decrypter interface{}, err error) { + switch config.PublicKeyAlgorithm() { + case packet.PubKeyAlgoRSA: + bits := config.RSAModulusBits() + if bits < 1024 { + return nil, errors.InvalidArgumentError("bits must be >= 1024") + } + if config != nil && len(config.RSAPrimes) >= 2 { + primes := config.RSAPrimes[0:2] + config.RSAPrimes = config.RSAPrimes[2:] + return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes) + } + return rsa.GenerateKey(config.Random(), bits) + case packet.PubKeyAlgoEdDSA: + fallthrough // When passing EdDSA, we generate an ECDH subkey + case packet.PubKeyAlgoECDH: + var kdf = ecdh.KDF{ + Hash: algorithm.SHA512, + Cipher: algorithm.AES256, + } + return ecdh.X25519GenerateKey(config.Random(), kdf) + default: + return nil, errors.InvalidArgumentError("unsupported public key algorithm") + } +} + +var bigOne = big.NewInt(1) + +// generateRSAKeyWithPrimes generates a multi-prime RSA keypair of the +// given bit size, using the given random source and prepopulated primes. +func generateRSAKeyWithPrimes(random io.Reader, nprimes int, bits int, prepopulatedPrimes []*big.Int) (*rsa.PrivateKey, error) { + priv := new(rsa.PrivateKey) + priv.E = 65537 + + if nprimes < 2 { + return nil, goerrors.New("generateRSAKeyWithPrimes: nprimes must be >= 2") + } + + if bits < 1024 { + return nil, goerrors.New("generateRSAKeyWithPrimes: bits must be >= 1024") + } + + primes := make([]*big.Int, nprimes) + +NextSetOfPrimes: + for { + todo := bits + // crypto/rand should set the top two bits in each prime. + // Thus each prime has the form + // p_i = 2^bitlen(p_i) × 0.11... (in base 2). + // And the product is: + // P = 2^todo × α + // where α is the product of nprimes numbers of the form 0.11... + // + // If α < 1/2 (which can happen for nprimes > 2), we need to + // shift todo to compensate for lost bits: the mean value of 0.11... + // is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2 + // will give good results. + if nprimes >= 7 { + todo += (nprimes - 2) / 5 + } + for i := 0; i < nprimes; i++ { + var err error + if len(prepopulatedPrimes) == 0 { + primes[i], err = rand.Prime(random, todo/(nprimes-i)) + if err != nil { + return nil, err + } + } else { + primes[i] = prepopulatedPrimes[0] + prepopulatedPrimes = prepopulatedPrimes[1:] + } + + todo -= primes[i].BitLen() + } + + // Make sure that primes is pairwise unequal. + for i, prime := range primes { + for j := 0; j < i; j++ { + if prime.Cmp(primes[j]) == 0 { + continue NextSetOfPrimes + } + } + } + + n := new(big.Int).Set(bigOne) + totient := new(big.Int).Set(bigOne) + pminus1 := new(big.Int) + for _, prime := range primes { + n.Mul(n, prime) + pminus1.Sub(prime, bigOne) + totient.Mul(totient, pminus1) + } + if n.BitLen() != bits { + // This should never happen for nprimes == 2 because + // crypto/rand should set the top two bits in each prime. + // For nprimes > 2 we hope it does not happen often. + continue NextSetOfPrimes + } + + priv.D = new(big.Int) + e := big.NewInt(int64(priv.E)) + ok := priv.D.ModInverse(e, totient) + + if ok != nil { + priv.Primes = primes + priv.N = n + break + } + } + + priv.Precompute() + return priv, nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go similarity index 73% rename from vendor/golang.org/x/crypto/openpgp/keys.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go index faa2fb3..c3fedf7 100644 --- a/vendor/golang.org/x/crypto/openpgp/keys.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go @@ -5,13 +5,13 @@ package openpgp import ( - "crypto/rsa" + goerrors "errors" "io" "time" - "golang.org/x/crypto/openpgp/armor" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/packet" + "github.com/ProtonMail/go-crypto/openpgp/armor" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/packet" ) // PublicKeyType is the armor type for a PGP public key. @@ -71,9 +71,9 @@ type KeyRing interface { DecryptionKeys() []Key } -// primaryIdentity returns the Identity marked as primary or the first identity +// PrimaryIdentity returns the Identity marked as primary or the first identity // if none are so marked. -func (e *Entity) primaryIdentity() *Identity { +func (e *Entity) PrimaryIdentity() *Identity { var firstIdentity *Identity for _, ident := range e.Identities { if firstIdentity == nil { @@ -86,18 +86,24 @@ func (e *Entity) primaryIdentity() *Identity { return firstIdentity } -// encryptionKey returns the best candidate Key for encrypting a message to the +// EncryptionKey returns the best candidate Key for encrypting a message to the // given Entity. -func (e *Entity) encryptionKey(now time.Time) (Key, bool) { - candidateSubkey := -1 +func (e *Entity) EncryptionKey(now time.Time) (Key, bool) { + // Fail to find any encryption key if the primary key has expired. + i := e.PrimaryIdentity() + primaryKeyExpired := e.PrimaryKey.KeyExpired(i.SelfSignature, now) + if primaryKeyExpired { + return Key{}, false + } - // Iterate the keys to find the newest key + // Iterate the keys to find the newest, unexpired one + candidateSubkey := -1 var maxTime time.Time for i, subkey := range e.Subkeys { if subkey.Sig.FlagsValid && subkey.Sig.FlagEncryptCommunications && subkey.PublicKey.PubKeyAlgo.CanEncrypt() && - !subkey.Sig.KeyExpired(now) && + !subkey.PublicKey.KeyExpired(subkey.Sig, now) && (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { candidateSubkey = i maxTime = subkey.Sig.CreationTime @@ -112,30 +118,44 @@ func (e *Entity) encryptionKey(now time.Time) (Key, bool) { // If we don't have any candidate subkeys for encryption and // the primary key doesn't have any usage metadata then we // assume that the primary key is ok. Or, if the primary key is - // marked as ok to encrypt to, then we can obviously use it. - i := e.primaryIdentity() + // marked as ok to encrypt with, then we can obviously use it. + // Also, check expiry again just to be safe. if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && - e.PrimaryKey.PubKeyAlgo.CanEncrypt() && - !i.SelfSignature.KeyExpired(now) { + e.PrimaryKey.PubKeyAlgo.CanEncrypt() && !primaryKeyExpired { return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true } - // This Entity appears to be signing only. return Key{}, false } -// signingKey return the best candidate Key for signing a message with this +// SigningKey return the best candidate Key for signing a message with this // Entity. -func (e *Entity) signingKey(now time.Time) (Key, bool) { - candidateSubkey := -1 +func (e *Entity) SigningKey(now time.Time) (Key, bool) { + return e.SigningKeyById(now, 0) +} - for i, subkey := range e.Subkeys { +// SigningKeyById return the Key for signing a message with this +// Entity and keyID. +func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) { + // Fail to find any signing key if the primary key has expired. + i := e.PrimaryIdentity() + primaryKeyExpired := e.PrimaryKey.KeyExpired(i.SelfSignature, now) + if primaryKeyExpired { + return Key{}, false + } + + // Iterate the keys to find the newest, unexpired one + candidateSubkey := -1 + var maxTime time.Time + for idx, subkey := range e.Subkeys { if subkey.Sig.FlagsValid && subkey.Sig.FlagSign && subkey.PublicKey.PubKeyAlgo.CanSign() && - !subkey.Sig.KeyExpired(now) { - candidateSubkey = i - break + !subkey.PublicKey.KeyExpired(subkey.Sig, now) && + (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) && + (id == 0 || subkey.PrivateKey.KeyId == id) { + candidateSubkey = idx + maxTime = subkey.Sig.CreationTime } } @@ -145,13 +165,15 @@ func (e *Entity) signingKey(now time.Time) (Key, bool) { } // If we have no candidate subkey then we assume that it's ok to sign - // with the primary key. - i := e.primaryIdentity() + // with the primary key. Or, if the primary key is marked as ok to + // sign with, then we can use it. Also, check expiry again just to be safe. if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && - !i.SelfSignature.KeyExpired(now) { + e.PrimaryKey.PubKeyAlgo.CanSign() && !primaryKeyExpired && + (id == 0 || e.PrivateKey.KeyId == id) { return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true } + // No keys with a valid Signing Flag or no keys matched the id passed in return Key{}, false } @@ -420,11 +442,14 @@ func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error { break } - if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { + if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.CheckKeyIdOrFingerprint(e.PrimaryKey) { if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { return errors.StructuralError("user ID self-signature invalid: " + err.Error()) } - identity.SelfSignature = sig + if identity.SelfSignature == nil || sig.CreationTime.After(identity.SelfSignature.CreationTime) { + identity.SelfSignature = sig + } + identity.Signatures = append(identity.Signatures, sig) e.Identities[pkt.Id] = identity } else { identity.Signatures = append(identity.Signatures, sig) @@ -465,7 +490,6 @@ func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *p case packet.SigTypeSubkeyRevocation: subKey.Sig = sig case packet.SigTypeSubkeyBinding: - if shouldReplaceSubkeySig(subKey.Sig, sig) { subKey.Sig = sig } @@ -497,99 +521,30 @@ func shouldReplaceSubkeySig(existingSig, potentialNewSig *packet.Signature) bool return potentialNewSig.CreationTime.After(existingSig.CreationTime) } -const defaultRSAKeyBits = 2048 - -// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a -// single identity composed of the given full name, comment and email, any of -// which may be empty but must not contain any of "()<>\x00". -// If config is nil, sensible defaults will be used. -func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { - creationTime := config.Now() - - bits := defaultRSAKeyBits - if config != nil && config.RSABits != 0 { - bits = config.RSABits - } - - uid := packet.NewUserId(name, comment, email) - if uid == nil { - return nil, errors.InvalidArgumentError("user id field contained invalid characters") - } - signingPriv, err := rsa.GenerateKey(config.Random(), bits) - if err != nil { - return nil, err - } - encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) - if err != nil { - return nil, err - } - - e := &Entity{ - PrimaryKey: packet.NewRSAPublicKey(creationTime, &signingPriv.PublicKey), - PrivateKey: packet.NewRSAPrivateKey(creationTime, signingPriv), - Identities: make(map[string]*Identity), - } - isPrimaryId := true - e.Identities[uid.Id] = &Identity{ - Name: uid.Id, - UserId: uid, - SelfSignature: &packet.Signature{ - CreationTime: creationTime, - SigType: packet.SigTypePositiveCert, - PubKeyAlgo: packet.PubKeyAlgoRSA, - Hash: config.Hash(), - IsPrimaryId: &isPrimaryId, - FlagsValid: true, - FlagSign: true, - FlagCertify: true, - IssuerKeyId: &e.PrimaryKey.KeyId, - }, - } - err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config) - if err != nil { - return nil, err - } - - // If the user passes in a DefaultHash via packet.Config, - // set the PreferredHash for the SelfSignature. - if config != nil && config.DefaultHash != 0 { - e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} - } - - // Likewise for DefaultCipher. - if config != nil && config.DefaultCipher != 0 { - e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} - } - - e.Subkeys = make([]Subkey, 1) - e.Subkeys[0] = Subkey{ - PublicKey: packet.NewRSAPublicKey(creationTime, &encryptingPriv.PublicKey), - PrivateKey: packet.NewRSAPrivateKey(creationTime, encryptingPriv), - Sig: &packet.Signature{ - CreationTime: creationTime, - SigType: packet.SigTypeSubkeyBinding, - PubKeyAlgo: packet.PubKeyAlgoRSA, - Hash: config.Hash(), - FlagsValid: true, - FlagEncryptStorage: true, - FlagEncryptCommunications: true, - IssuerKeyId: &e.PrimaryKey.KeyId, - }, - } - e.Subkeys[0].PublicKey.IsSubkey = true - e.Subkeys[0].PrivateKey.IsSubkey = true - err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config) - if err != nil { - return nil, err - } - return e, nil -} - // SerializePrivate serializes an Entity, including private key material, but // excluding signatures from other entities, to the given Writer. // Identities and subkeys are re-signed in case they changed since NewEntry. // If config is nil, sensible defaults will be used. func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { + if e.PrivateKey.Dummy() { + return errors.ErrDummyPrivateKey("dummy private key cannot re-sign identities") + } + return e.serializePrivate(w, config, true) +} + +// SerializePrivateWithoutSigning serializes an Entity, including private key +// material, but excluding signatures from other entities, to the given Writer. +// Self-signatures of identities and subkeys are not re-signed. This is useful +// when serializing GNU dummy keys, among other things. +// If config is nil, sensible defaults will be used. +func (e *Entity) SerializePrivateWithoutSigning(w io.Writer, config *packet.Config) (err error) { + return e.serializePrivate(w, config, false) +} + +func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign bool) (err error) { + if e.PrivateKey == nil { + return goerrors.New("openpgp: private key is missing") + } err = e.PrivateKey.Serialize(w) if err != nil { return @@ -599,9 +554,11 @@ func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error if err != nil { return } - err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) - if err != nil { - return + if reSign { + err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) + if err != nil { + return + } } err = ident.SelfSignature.Serialize(w) if err != nil { @@ -613,9 +570,18 @@ func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error if err != nil { return } - err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) - if err != nil { - return + if reSign { + err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) + if err != nil { + return + } + if subkey.Sig.EmbeddedSignature != nil { + err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, + subkey.PrivateKey, config) + if err != nil { + return + } + } } err = subkey.Sig.Serialize(w) if err != nil { @@ -637,10 +603,6 @@ func (e *Entity) Serialize(w io.Writer) error { if err != nil { return err } - err = ident.SelfSignature.Serialize(w) - if err != nil { - return err - } for _, sig := range ident.Signatures { err = sig.Serialize(w) if err != nil { @@ -679,6 +641,7 @@ func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Co } sig := &packet.Signature{ + Version: signer.PrivateKey.Version, SigType: packet.SigTypeGenericCert, PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, Hash: config.Hash(), @@ -691,3 +654,54 @@ func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Co ident.Signatures = append(ident.Signatures, sig) return nil } + +// RevokeKey generates a key revocation signature (packet.SigTypeKeyRevocation) with the +// specified reason code and text (RFC4880 section-5.2.3.23). +// If config is nil, sensible defaults will be used. +func (e *Entity) RevokeKey(reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error { + reasonCode := uint8(reason) + revSig := &packet.Signature{ + Version: e.PrimaryKey.Version, + CreationTime: config.Now(), + SigType: packet.SigTypeKeyRevocation, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + RevocationReason: &reasonCode, + RevocationReasonText: reasonText, + IssuerKeyId: &e.PrimaryKey.KeyId, + } + + if err := revSig.RevokeKey(e.PrimaryKey, e.PrivateKey, config); err != nil { + return err + } + e.Revocations = append(e.Revocations, revSig) + return nil +} + +// RevokeSubkey generates a subkey revocation signature (packet.SigTypeSubkeyRevocation) for +// a subkey with the specified reason code and text (RFC4880 section-5.2.3.23). +// If config is nil, sensible defaults will be used. +func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error { + if err := e.PrimaryKey.VerifyKeySignature(sk.PublicKey, sk.Sig); err != nil { + return errors.InvalidArgumentError("given subkey is not associated with this key") + } + + reasonCode := uint8(reason) + revSig := &packet.Signature{ + Version: e.PrimaryKey.Version, + CreationTime: config.Now(), + SigType: packet.SigTypeSubkeyRevocation, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + RevocationReason: &reasonCode, + RevocationReasonText: reasonText, + IssuerKeyId: &e.PrimaryKey.KeyId, + } + + if err := revSig.RevokeKey(sk.PublicKey, e.PrivateKey, config); err != nil { + return err + } + + sk.Sig = revSig + return nil +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go new file mode 100644 index 0000000..21d17c2 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go @@ -0,0 +1,336 @@ +package openpgp + +const expiringKeyHex = "c6c04d0451d0c680010800abbb021fd03ffc4e96618901180c3fdcb060ee69eeead97b91256d11420d80b5f1b51930248044130bd300605cf8a05b7a40d3d8cfb0a910be2e3db50dcd50a9c54064c2a5550801daa834ff4480b33d3d3ca495ff8a4e84a886977d17d998f881241a874083d8b995beab555b6d22b8a4817ab17ac3e7304f7d4d2c05c495fb2218348d3bc13651db1d92732e368a9dd7dcefa6eddff30b94706a9aaee47e9d39321460b740c59c6fc3c2fd8ab6c0fb868cb87c0051f0321301fe0f0e1820b15e7fb7063395769b525005c7e30a7ce85984f5cac00504e7b4fdc45d74958de8388436fd5c7ba9ea121f1c851b5911dd1b47a14d81a09e92ef37721e2325b6790011010001cd00c2c07b041001080025050251d0c680050900278d00060b09070803020415080a0203160201021901021b03021e01000a0910e7b484133a890a35ae4b0800a1beb82e7f28eaf5273d6af9d3391314f6280b2b624eaca2851f89a9ebcaf80ac589ebd509f168bc4322106ca2e2ce77a76e071a3c7444787d65216b5f05e82c77928860b92aace3b7d0327db59492f422eb9dfab7249266d37429870b091a98aba8724c2259ebf8f85093f21255eafa75aa841e31d94f2ac891b9755fed455e539044ee69fc47950b80e003fc9f298d695660f28329eaa38037c367efde1727458e514faf990d439a21461b719edaddf9296d3d0647b43ca56cb8dbf63b4fcf8b9968e7928c463470fab3b98e44d0d95645062f94b2d04fe56bd52822b71934db8ce845622c40b92fcbe765a142e7f38b61a6aa9606c8e8858dcd3b6eb1894acec04d0451d1f06b01080088bea67444e1789390e7c0335c86775502d58ec783d99c8ef4e06de235ed3dd4b0467f6f358d818c7d8989d43ec6d69fcbc8c32632d5a1b605e3fa8e41d695fcdcaa535936cd0157f9040dce362519803b908eafe838bb13216c885c6f93e9e8d5745607f0d062322085d6bdc760969149a8ff8dd9f5c18d9bfe2e6f63a06e17694cf1f67587c6fb70e9aebf90ffc528ca3b615ac7c9d4a21ea4f7c06f2e98fbbd90a859b8608bf9ea638e3a54289ce44c283110d0c45fa458de6251cd6e7baf71f80f12c8978340490fd90c92b81736ae902ed958e478dceae2835953d189c45d182aff02ea2be61b81d8e94430f041d638647b43e2fcb45fd512fbf5068b810011010001c2c06504180108000f050251d1f06b050900081095021b0c000a0910e7b484133a890a35e63407fe2ec88d6d1e6c9ce7553ece0cb2524747217bad29f251d33df84599ffcc900141a355abd62126800744068a5e05dc167056aa9205273dc7765a2ed49db15c2a83b8d6e6429c902136f1e12229086c1c10c0053242c2a4ae1930db58163387a48cad64607ff2153c320e42843dec28e3fce90e7399d63ac0affa2fee1f0adc0953c89eb3f46ef1d6c04328ed13b491669d5120a3782e3ffb7c69575fb77eebd108794f4dda9d34be2bae57e8e59ec8ebfda2f6f06104b2321be408ea146e2db482b00c5055c8618de36ac9716f80da2617e225556d0fce61b01c8cea2d1e0ea982c31711060ca370f2739366e1e708f38405d784b49d16a26cf62d152eae734327cec04d0451d1f07b010800d5af91c5e7c2fd8951c8d254eab0c97cdcb66822f868b79b78c366255059a68fd74ebca9adb9b970cd9e586690e6e0756705432306878c897b10a4b4ca0005966f99ac8fa4e6f9caf54bf8e53844544beee9872a7ac64c119cf1393d96e674254b661f61ee975633d0e8a8672531edb6bb8e211204e7754a9efa802342118eee850beea742bac95a3f706cc2024cf6037a308bb68162b2f53b9a6346a96e6d31871a2456186e24a1c7a82b82ac04afdfd57cd7fb9ba77a9c760d40b76a170f7be525e5fb6a9848cc726e806187710d9b190387df28700f321f988a392899f93815cc937f309129eb94d5299c5547cb2c085898e6639496e70d746c9d3fb9881d0011010001c2c06504180108000f050251d1f07b050900266305021b0c000a0910e7b484133a890a35bff207fd10dfe8c4a6ea1dd30568012b6fd6891a763c87ad0f7a1d112aad9e8e3239378a3b85588c235865bac2e614348cb4f216d7217f53b3ef48c192e0a4d31d64d7bfa5faccf21155965fa156e887056db644a05ad08a85cc6152d1377d9e37b46f4ff462bbe68ace2dc586ef90070314576c985d8037c2ba63f0a7dc17a62e15bd77e88bc61d9d00858979709f12304264a4cf4225c5cf86f12c8e19486cb9cdcc69f18f027e5f16f4ca8b50e28b3115eaff3a345acd21f624aef81f6ede515c1b55b26b84c1e32264754eab672d5489b287e7277ea855e0a5ff2aa9e8b8c76d579a964ec225255f4d57bf66639ccb34b64798846943e162a41096a7002ca21c7f56" +const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" +const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" +const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011" + +const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Charset: UTF-8 + +mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY +ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG +zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 +QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ +QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo +9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu +Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ +dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R +JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL +ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew +RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW +/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu +yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv +2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR +bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL +C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP +WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y +MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA +EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ +MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N +1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm ++ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N +lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW +CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF +4artDmrG +=7FfJ +-----END PGP PUBLIC KEY BLOCK-----` + +const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY +ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG +zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 +QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ +QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo +9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu +Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ +dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R +JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL +ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew +RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW +/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu +yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAIINDqlj7X6jYKc6DjwrOkjQ +UIRWbQQar0LwmNilehmt70g5DCL1SYm9q4LcgJJ2Nhxj0/5qqsYib50OSWMcKeEe +iRXpXzv1ObpcQtI5ithp0gR53YPXBib80t3bUzomQ5UyZqAAHzMp3BKC54/vUrSK +FeRaxDzNLrCeyI00+LHNUtwghAqHvdNcsIf8VRumK8oTm3RmDh0TyjASWYbrt9c8 +R1Um3zuoACOVy+mEIgIzsfHq0u7dwYwJB5+KeM7ZLx+HGIYdUYzHuUE1sLwVoELh ++SHIGHI1HDicOjzqgajShuIjj5hZTyQySVprrsLKiXS6NEwHAP20+XjayJ/R3tEA +EQEAAYkCPgQYAQIBKAUCU5ygeQIbAsBdIAQZAQIABgUCU5ygeQAKCRCpVlnFZmhO +52RJB/9uD1MSa0wjY6tHOIgquZcP3bHBvHmrHNMw9HR2wRCMO91ZkhrpdS3ZHtgb +u3/55etj0FdvDo1tb8P8FGSVtO5Vcwf5APM8sbbqoi8L951Q3i7qt847lfhu6sMl +w0LWFvPTOLHrliZHItPRjOltS1WAWfr2jUYhsU9ytaDAJmvf9DujxEOsN5G1YJep +54JCKVCkM/y585Zcnn+yxk/XwqoNQ0/iJUT9qRrZWvoeasxhl1PQcwihCwss44A+ +YXaAt3hbk+6LEQuZoYS73yR3WHj+42tfm7YxRGeubXfgCEz/brETEWXMh4pe0vCL +bfWrmfSPq2rDegYcAybxRQz0lF8PAAoJEO3UDQUIHpI/exkH/0vQfdHA8g/N4T6E +i6b1CUVBAkvtdJpCATZjWPhXmShOw62gkDw306vHPilL4SCvEEi4KzG72zkp6VsB +DSRcpxCwT4mHue+duiy53/aRMtSJ+vDfiV1Vhq+3sWAck/yUtfDU9/u4eFaiNok1 +8/Gd7reyuZt5CiJnpdPpjCwelK21l2w7sHAnJF55ITXdOxI8oG3BRKufz0z5lyDY +s2tXYmhhQIggdgelN8LbcMhWs/PBbtUr6uZlNJG2lW1yscD4aI529VjwJlCeo745 +U7pO4eF05VViUJ2mmfoivL3tkhoTUWhx8xs8xCUcCg8DoEoSIhxtOmoTPR22Z9BL +6LCg2mg= +=Dhm4 +-----END PGP PUBLIC KEY BLOCK-----` + +const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo +7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom +lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0 +E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC +CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw +6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH +7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv +X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7 +GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl +y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw +R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW +CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+ +LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO +aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx +yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl +BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr +Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK +CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp +C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ +SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/ +MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70= +=vtbN +-----END PGP PUBLIC KEY BLOCK-----` + +const revokedUserIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFsgO5EBCADhREPmcjsPkXe1z7ctvyWL0S7oa9JaoGZ9oPDHFDlQxd0qlX2e +DZJZDg0qYvVixmaULIulApq1puEsaJCn3lHUbHlb4PYKwLEywYXM28JN91KtLsz/ +uaEX2KC5WqeP40utmzkNLq+oRX/xnRMgwbO7yUNVG2UlEa6eI+xOXO3YtLdmJMBW +ClQ066ZnOIzEo1JxnIwha1CDBMWLLfOLrg6l8InUqaXbtEBbnaIYO6fXVXELUjkx +nmk7t/QOk0tXCy8muH9UDqJkwDUESY2l79XwBAcx9riX8vY7vwC34pm22fAUVLCJ +x1SJx0J8bkeNp38jKM2Zd9SUQqSbfBopQ4pPABEBAAG0I0dvbGFuZyBHb3BoZXIg +PG5vLXJlcGx5QGdvbGFuZy5jb20+iQFUBBMBCgA+FiEE5Ik5JLcNx6l6rZfw1oFy +9I6cUoMFAlsgO5ECGwMFCQPCZwAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ +1oFy9I6cUoMIkwf8DNPeD23i4jRwd/pylbvxwZintZl1fSwTJW1xcOa1emXaEtX2 +depuqhP04fjlRQGfsYAQh7X9jOJxAHjTmhqFBi5sD7QvKU00cPFYbJ/JTx0B41bl +aXnSbGhRPh63QtEZL7ACAs+shwvvojJqysx7kyVRu0EW2wqjXdHwR/SJO6nhNBa2 +DXzSiOU/SUA42mmG+5kjF8Aabq9wPwT9wjraHShEweNerNMmOqJExBOy3yFeyDpa +XwEZFzBfOKoxFNkIaVf5GSdIUGhFECkGvBMB935khftmgR8APxdU4BE7XrXexFJU +8RCuPXonm4WQOwTWR0vQg64pb2WKAzZ8HhwTGbQiR29sYW5nIEdvcGhlciA8cmV2 +b2tlZEBnb2xhbmcuY29tPokBNgQwAQoAIBYhBOSJOSS3Dcepeq2X8NaBcvSOnFKD +BQJbIDv3Ah0AAAoJENaBcvSOnFKDfWMIAKhI/Tvu3h8fSUxp/gSAcduT6bC1JttG +0lYQ5ilKB/58lBUA5CO3ZrKDKlzW3M8VEcvohVaqeTMKeoQd5rCZq8KxHn/KvN6N +s85REfXfniCKfAbnGgVXX3kDmZ1g63pkxrFu0fDZjVDXC6vy+I0sGyI/Inro0Pzb +tvn0QCsxjapKK15BtmSrpgHgzVqVg0cUp8vqZeKFxarYbYB2idtGRci4b9tObOK0 +BSTVFy26+I/mrFGaPrySYiy2Kz5NMEcRhjmTxJ8jSwEr2O2sUR0yjbgUAXbTxDVE +/jg5fQZ1ACvBRQnB7LvMHcInbzjyeTM3FazkkSYQD6b97+dkWwb1iWG5AQ0EWyA7 +kQEIALkg04REDZo1JgdYV4x8HJKFS4xAYWbIva1ZPqvDNmZRUbQZR2+gpJGEwn7z +VofGvnOYiGW56AS5j31SFf5kro1+1bZQ5iOONBng08OOo58/l1hRseIIVGB5TGSa +PCdChKKHreJI6hS3mShxH6hdfFtiZuB45rwoaArMMsYcjaezLwKeLc396cpUwwcZ +snLUNd1Xu5EWEF2OdFkZ2a1qYdxBvAYdQf4+1Nr+NRIx1u1NS9c8jp3PuMOkrQEi +bNtc1v6v0Jy52mKLG4y7mC/erIkvkQBYJdxPaP7LZVaPYc3/xskcyijrJ/5ufoD8 +K71/ShtsZUXSQn9jlRaYR0EbojMAEQEAAYkBPAQYAQoAJhYhBOSJOSS3Dcepeq2X +8NaBcvSOnFKDBQJbIDuRAhsMBQkDwmcAAAoJENaBcvSOnFKDkFMIAIt64bVZ8x7+ +TitH1bR4pgcNkaKmgKoZz6FXu80+SnbuEt2NnDyf1cLOSimSTILpwLIuv9Uft5Pb +OraQbYt3xi9yrqdKqGLv80bxqK0NuryNkvh9yyx5WoG1iKqMj9/FjGghuPrRaT4l +QinNAghGVkEy1+aXGFrG2DsOC1FFI51CC2WVTzZ5RwR2GpiNRfESsU1rZAUqf/2V +yJl9bD5R4SUNy8oQmhOxi+gbhD4Ao34e4W0ilibslI/uawvCiOwlu5NGd8zv5n+U +heiQvzkApQup5c+BhH5zFDFdKJ2CBByxw9+7QjMFI/wgLixKuE0Ob2kAokXf7RlB +7qTZOahrETw= +=IKnw +-----END PGP PUBLIC KEY BLOCK-----` + +const keyWithSubKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- + +mI0EWyKwKQEEALwXhKBnyaaNFeK3ljfc/qn9X/QFw+28EUfgZPHjRmHubuXLE2uR +s3ZoSXY2z7Dkv+NyHYMt8p+X8q5fR7JvUjK2XbPyKoiJVnHINll83yl67DaWfKNL +EjNoO0kIfbXfCkZ7EG6DL+iKtuxniGTcnGT47e+HJSqb/STpLMnWwXjBABEBAAG0 +I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQQ/ +lRafP/p9PytHbwxMvYJsOQdOOAUCWyKwKQIbAwULCQgHAwUVCgkICwUWAgMBAAIe +AQIXgAAKCRBMvYJsOQdOOOsFBAC62mXww8XuqvYLcVOvHkWLT6mhxrQOJXnlfpn7 +2uBV9CMhoG/Ycd43NONsJrB95Apr9TDIqWnVszNbqPCuBhZQSGLdbiDKjxnCWBk0 +69qv4RNtkpOhYB7jK4s8F5oQZqId6JasT/PmJTH92mhBYhhTQr0GYFuPX2UJdkw9 +Sn9C67iNBFsisDUBBAC3A+Yo9lgCnxi/pfskyLrweYif6kIXWLAtLTsM6g/6jt7b +wTrknuCPyTv0QKGXsAEe/cK/Xq3HvX9WfXPGIHc/X56ZIsHQ+RLowbZV/Lhok1IW +FAuQm8axr/by80cRwFnzhfPc/ukkAq2Qyj4hLsGblu6mxeAhzcp8aqmWOO2H9QAR +AQABiLYEKAEKACAWIQQ/lRafP/p9PytHbwxMvYJsOQdOOAUCWyK16gIdAAAKCRBM +vYJsOQdOOB1vA/4u4uLONsE+2GVOyBsHyy7uTdkuxaR9b54A/cz6jT/tzUbeIzgx +22neWhgvIEghnUZd0vEyK9k1wy5vbDlEo6nKzHso32N1QExGr5upRERAxweDxGOj +7luDwNypI7QcifE64lS/JmlnunwRCdRWMKc0Fp+7jtRc5mpwyHN/Suf5RokBagQY +AQoAIBYhBD+VFp8/+n0/K0dvDEy9gmw5B044BQJbIrA1AhsCAL8JEEy9gmw5B044 +tCAEGQEKAB0WIQSNdnkaWY6t62iX336UXbGvYdhXJwUCWyKwNQAKCRCUXbGvYdhX +JxJSA/9fCPHP6sUtGF1o3G1a3yvOUDGr1JWcct9U+QpbCt1mZoNopCNDDQAJvDWl +mvDgHfuogmgNJRjOMznvahbF+wpTXmB7LS0SK412gJzl1fFIpK4bgnhu0TwxNsO1 +8UkCZWqxRMgcNUn9z6XWONK8dgt5JNvHSHrwF4CxxwjL23AAtK+FA/UUoi3U4kbC +0XnSr1Sl+mrzQi1+H7xyMe7zjqe+gGANtskqexHzwWPUJCPZ5qpIa2l8ghiUim6b +4ymJ+N8/T8Yva1FaPEqfMzzqJr8McYFm0URioXJPvOAlRxdHPteZ0qUopt/Jawxl +Xt6B9h1YpeLoJwjwsvbi98UTRs0jXwoY +=3fWu +-----END PGP PUBLIC KEY BLOCK-----` + +const keyWithSubKeyAndBadSelfSigOrder = `-----BEGIN PGP PUBLIC KEY BLOCK----- + +mI0EWyLLDQEEAOqIOpJ/ha1OYAGduu9tS3rBz5vyjbNgJO4sFveEM0mgsHQ0X9/L +plonW+d0gRoO1dhJ8QICjDAc6+cna1DE3tEb5m6JtQ30teLZuqrR398Cf6w7NNVz +r3lrlmnH9JaKRuXl7tZciwyovneBfZVCdtsRZjaLI1uMQCz/BToiYe3DABEBAAG0 +I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQRZ +sixZOfQcZdW0wUqmgmdsv1O9xgUCWyLLDQIbAwULCQgHAwUVCgkICwUWAgMBAAIe +AQIXgAAKCRCmgmdsv1O9xql2A/4pix98NxjhdsXtazA9agpAKeADf9tG4Za27Gj+ +3DCww/E4iP2X35jZimSm/30QRB6j08uGCqd9vXkkJxtOt63y/IpVOtWX6vMWSTUm +k8xKkaYMP0/IzKNJ1qC/qYEUYpwERBKg9Z+k99E2Ql4kRHdxXUHq6OzY79H18Y+s +GdeM/riNBFsiyxsBBAC54Pxg/8ZWaZX1phGdwfe5mek27SOYpC0AxIDCSOdMeQ6G +HPk38pywl1d+S+KmF/F4Tdi+kWro62O4eG2uc/T8JQuRDUhSjX0Qa51gPzJrUOVT +CFyUkiZ/3ZDhtXkgfuso8ua2ChBgR9Ngr4v43tSqa9y6AK7v0qjxD1x+xMrjXQAR +AQABiQFxBBgBCgAmAhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsizTIFCQAN +MRcAv7QgBBkBCgAdFiEEJcoVUVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62j +UpRPICQq5gQApoWIigZxXFoM0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBS +YnjyA4+n1D+zB2VqliD2QrsX12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZs +nRJmXV+bsvD4sidLZLjdwOVa3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/ +U73GGi0D/i20VW8AWYAPACm2zMlzExKTOAV01YTQH/3vW0WLrOse53WcIVZga6es +HuO4So0SOEAvxKMe5HpRIu2dJxTvd99Bo9xk9xJU0AoFrO0vNCRnL+5y68xMlODK +lEw5/kl0jeaTBp6xX0HDQOEVOpPGUwWV4Ij2EnvfNDXaE1vK1kffiQFrBBgBCgAg +AhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsi0AYAv7QgBBkBCgAdFiEEJcoV +UVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62jUpRPICQq5gQApoWIigZxXFoM +0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBSYnjyA4+n1D+zB2VqliD2QrsX +12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZsnRJmXV+bsvD4sidLZLjdwOVa +3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/U73GRl0EAJokkXmy4zKDHWWi +wvK9gi2gQgRkVnu2AiONxJb5vjeLhM/07BRmH6K1o+w3fOeEQp4FjXj1eQ5fPSM6 +Hhwx2CTl9SDnPSBMiKXsEFRkmwQ2AAsQZLmQZvKBkLZYeBiwf+IY621eYDhZfo+G +1dh1WoUCyREZsJQg2YoIpWIcvw+a +=bNRo +-----END PGP PUBLIC KEY BLOCK----- +` + +const onlySubkeyNoPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v1 + +lQCVBFggvocBBAC7vBsHn7MKmS6IiiZNTXdciplVgS9cqVd+RTdIAoyNTcsiV1H0 +GQ3QtodOPeDlQDNoqinqaobd7R9g3m3hS53Nor7yBZkCWQ5x9v9JxRtoAq0sklh1 +I1X2zEqZk2l6YrfBF/64zWrhjnW3j23szkrAIVu0faQXbQ4z56tmZrw11wARAQAB +/gdlAkdOVQG0CUdOVSBEdW1teYi4BBMBAgAiBQJYIL6HAhsDBgsJCAcDAgYVCAIJ +CgsEFgIDAQIeAQIXgAAKCRCd1xxWp1CYAnjGA/9synn6ZXJUKAXQzySgmCZvCIbl +rqBfEpxwLG4Q/lONhm5vthAE0z49I8hj5Gc5e2tLYUtq0o0OCRdCrYHa/efOYWpJ +6RsK99bePOisVzmOABLIgZkcr022kHoMCmkPgv9CUGKP1yqbGl+zzAwQfUjRUmvD +ZIcWLHi2ge4GzPMPi50B2ARYIL6cAQQAxWHnicKejAFcFcF1/3gUSgSH7eiwuBPX +M7vDdgGzlve1o1jbV4tzrjN9jsCl6r0nJPDMfBSzgLr1auNTRG6HpJ4abcOx86ED +Ad+avDcQPZb7z3dPhH/gb2lQejZsHh7bbeOS8WMSzHV3RqCLd8J/xwWPNR5zKn1f +yp4IGfopidMAEQEAAQAD+wQOelnR82+dxyM2IFmZdOB9wSXQeCVOvxSaNMh6Y3lk +UOOkO8Nlic4x0ungQRvjoRs4wBmCuwFK/MII6jKui0B7dn/NDf51i7rGdNGuJXDH +e676By1sEY/NGkc74jr74T+5GWNU64W0vkpfgVmjSAzsUtpmhJMXsc7beBhJdnVl +AgDKCb8hZqj1alcdmLoNvb7ibA3K/V8J462CPD7bMySPBa/uayoFhNxibpoXml2r +oOtHa5izF3b0/9JY97F6rqkdAgD6GdTJ+xmlCoz1Sewoif1I6krq6xoa7gOYpIXo +UL1Afr+LiJeyAnF/M34j/kjIVmPanZJjry0kkjHE5ILjH3uvAf4/6n9np+Th8ujS +YDCIzKwR7639+H+qccOaddCep8Y6KGUMVdD/vTKEx1rMtK+hK/CDkkkxnFslifMJ +kqoqv3WUqCWJAT0EGAECAAkFAlggvpwCGwIAqAkQndccVqdQmAKdIAQZAQIABgUC +WCC+nAAKCRDmGUholQPwvQk+A/9latnSsR5s5/1A9TFki11GzSEnfLbx46FYOdkW +n3YBxZoPQGxNA1vIn8GmouxZInw9CF4jdOJxEdzLlYQJ9YLTLtN5tQEMl/19/bR8 +/qLacAZ9IOezYRWxxZsyn6//jfl7A0Y+FV59d4YajKkEfItcIIlgVBSW6T+TNQT3 +R+EH5HJ/A/4/AN0CmBhhE2vGzTnVU0VPrE4V64pjn1rufFdclgpixNZCuuqpKpoE +VVHn6mnBf4njKjZrAGPs5kfQ+H4NsM7v3Zz4yV6deu9FZc4O6E+V1WJ38rO8eBix +7G2jko106CC6vtxsCPVIzY7aaG3H5pjRtomw+pX7SzrQ7FUg2PGumg== +=F/T0 +-----END PGP PRIVATE KEY BLOCK-----` + +const ecdsaPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- + +xaUEX1KsSRMIKoZIzj0DAQcCAwTpYqJsnJiFhKKh+8TulWD+lVmerBFNS+Ii +B+nlG3T0xQQ4Sy5eIjJ0CExIQQzi3EElF/Z2l4F3WC5taFA11NgA/gkDCHSS +PThf1M2K4LN8F1MRcvR+sb7i0nH55ojkwuVB1DE6jqIT9m9i+mX1tzjSAS+6 +lPQiweCJvG7xTC7Hs3AzRapf/r1At4TB+v+5G2/CKynNFEJpbGwgPGJpbGxA +aG9tZS5jb20+wncEEBMIAB8FAl9SrEkGCwkHCAMCBBUICgIDFgIBAhkBAhsD +Ah4BAAoJEMpwT3+q3+xqw5UBAMebZN9isEZ1ML+R/jWAAWMwa/knMugrEZ1v +Bl9+ZwM0AQCZdf80/wYY4Nve01qSRFv8OmKswLli3TvDv6FKc4cLz8epBF9S +rEkSCCqGSM49AwEHAgMEAjKnT9b5wY2bf9TpAV3d7OUfPOxKj9c4VzeVzSrH +AtQgo/MuI1cdYVURicV4i76DNjFhQHQFTk7BrC+C2u1yqQMBCAf+CQMIHImA +iYfzQtjgQWSFZYUkCFpbbwhNF0ch+3HNaZkaHCnZRIsWsRnc6FCb6lRQyK9+ +Dq59kHlduE5QgY40894jfmP2JdJHU6nBdYrivbEdbMJhBBgTCAAJBQJfUqxJ +AhsMAAoJEMpwT3+q3+xqUI0BAMykhV08kQ4Ip9Qlbss6Jdufv7YrU0Vd5hou +b5TmiPd0APoDBh3qIic+aLLUcAuG3+Gt1P1AbUlmqV61ozn1WfHxfw== +=KLN8 +-----END PGP PRIVATE KEY BLOCK-----` + +const dsaPrivateKeyWithElGamalSubkey = `-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQOBBF9/MLsRCACeaF6BI0jTgDAs86t8/kXPfwlPvR2MCYzB0BCqAdcq1hV/GTYd +oNmJRna/ZJfsI/vf+d8Nv+EYOQkPheFS1MJVBitkAXjQPgm8i1tQWen1FCWZxqGk +/vwZYF4yo8GhZ+Wxi3w09W9Cp9QM/CTmyE1Xe7wpPBGe+oD+me8Zxjyt8JBS4Qx+ +gvWbfHxfHnggh4pz7U8QkItlLsBNQEdX4R5+zwRN66g2ZSX/shaa/EkVnihUhD7r +njP9I51ORWucTQD6OvgooaNQZCkQ/Se9TzdakwWKS2XSIFXiY/e2E5ZgKI/pfKDU +iA/KessxddPb7nP/05OIJqg9AoDrD4vmehLzAQD+zsUS3LDU1m9/cG4LMsQbT2VK +Te4HqbGIAle+eu/asQf8DDJMrbZpiJZvADum9j0TJ0oep6VdMbzo9RSDKvlLKT9m +kG63H8oDWnCZm1a+HmGq9YIX+JHWmsLXXsFLeEouLzHO+mZo0X28eji3V2T87hyR +MmUM0wFo4k7jK8uVmkDXv3XwNp2uByWxUKZd7EnWmcEZWqIiexJ7XpCS0Pg3tRaI +zxve0SRe/dxfUPnTk/9KQ9hS6DWroBKquL182zx1Fggh4LIWWE2zq+UYn8BI0E8A +rmIDFJdF8ymFQGRrEy6g79NnkPmkrZWsgMRYY65P6v4zLVmqohJKkpm3/Uxa6QAP +CCoPh/JTOvPeCP2bOJH8z4Z9Py3ouMIjofQW8sXqRgf/RIHbh0KsINHrwwZ4gVIr +MK3RofpaYxw1ztPIWb4cMWoWZHH1Pxh7ggTGSBpAhKXkiWw2Rxat8QF5aA7e962c +bLvVv8dqsPrD/RnVJHag89cbPTzjn7gY9elE8EM8ithV3oQkwHTr4avYlpDZsgNd +hUW3YgRwGo31tdzxoG04AcpV2t+07P8XMPr9hsfWs4rHohXPi38Hseu1Ji+dBoWQ +3+1w/HH3o55s+jy4Ruaz78AIrjbmAJq+6rA2mIcCgrhw3DnzuwQAKeBvSeqn9zfS +ZC812osMBVmkycwelpaIh64WZ0vWL3GvdXDctV2kXM+qVpDTLEny0LuiXxrwCKQL +Ev4HAwK9uQBcreDEEud7pfRb8EYP5lzO2ZA7RaIvje6EWAGBvJGMRT0QQE5SGqc7 +Fw5geigBdt+vVyRuNNhg3c2fdn/OBQaYu0J/8AiOogG8EaM8tCFlbGdhbWFsQGRz +YS5jb20gPGVsZ2FtYWxAZHNhLmNvbT6IkAQTEQgAOBYhBI+gnfiHQxB35/Dp0XAQ +aE/rsWC5BQJffzC7AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEHAQaE/r +sWC5A4EA/0GcJmyPtN+Klc7b9sVT3JgKTRnB/URxOJfYJofP0hZLAQCkqyMO+adV +JvbgDH0zaITQWZSSXPqpgMpCA6juTrDsd50CawRffzC7EAgAxFFFSAAEQzWTgKU5 +EBtpxxoPzHqcChawTHRxHxjcELXzmUBS5PzfA1HXSPnNqK/x3Ut5ycC3CsW41Fnt +Gm3706Wu9VFbFZVn55F9lPiplUo61n5pqMvOr1gmuQsdXiTa0t5FRa4TZ2VSiHFw +vdAVSPTUsT4ZxJ1rPyFYRtq1n3pQcvdZowd07r0JnzTMjLLMFYCKhwIowoOC4zqJ +iB8enjwOlpaqBATRm9xpVF7SJkroPF6/B1vdhj7E3c1aJyHlo0PYBAg756sSHWHg +UuLyUQ4TA0hcCVenn/L/aSY2LnbdZB1EBhlYjA7dTCgwIqsQhfQmPkjz6g64A7+Y +HbbrLwADBQgAk14QIEQ+J/VHetpQV/jt2pNsFK1kVK7mXK0spTExaC2yj2sXlHjL +Ie3bO5T/KqmIaBEB5db5fA5xK9cZt79qrQHDKsEqUetUeMUWLBx77zBsus3grIgy +bwDZKseRzQ715pwxquxQlScGoDIBKEh08HpwHkq140eIj3w+MAIfndaZaSCNaxaP +Snky7BQmJ7Wc7qrIwoQP6yrnUqyW2yNi81nJYUhxjChqaFSlwzLs/iNGryBKo0ic +BqVIRjikKHBlwBng6WyrltQo/Vt9GG8w+lqaAVXbJRlaBZJUR+2NKi/YhP3qQse3 +v8fi4kns0gh5LK+2C01RvdX4T49QSExuIf4HAwLJqYIGwadA2uem5v7/765ZtFWV +oL0iZ0ueTJDby4wTFDpLVzzDi/uVcB0ZRFrGOp7w6OYcNYTtV8n3xmli2Q5Trw0c +wZVzvg+ABKWiv7faBjMczIFF8y6WZKOIeAQYEQgAIBYhBI+gnfiHQxB35/Dp0XAQ +aE/rsWC5BQJffzC7AhsMAAoJEHAQaE/rsWC5ZmIA/jhS4r4lClbvjuPWt0Yqdn7R +fss2SPMYvMrrDh42aE0OAQD8xn4G6CN8UtW9xihXOY6FpxiJ/sMc2VaneeUd34oa +4g== +=XZm8 +-----END PGP PRIVATE KEY BLOCK-----` + +// https://tests.sequoia-pgp.org/#Certificate_expiration +// P _ U p +const expiringPrimaryUIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv +/seOXpgecTdOcVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz +/56fW2O0F23qIRd8UUJp5IIlN4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/ +5whqsyroEWDJoSV0yOb25B/iwk/pLUFoyhDG9bj0kIzDxrEqW+7Ba8nocQlecMF3 +X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8Je/ECwUWYUiAZxLIlMv +9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx5wRZ4F0 +qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7eb +SGXrl5ZMpbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wb +vLIwa3T4CyshfT0AEQEAAc0hQm9iIEJhYmJhZ2UgPGJvYkBvcGVucGdwLmV4YW1w +bGU+wsEUBBMBCgBIBYJfiWKKBYkBX+/UBQsJCAcCCRD7/MgqAV5zMAYVCgkICwIE +FgIDAQIXgAIbAwIeARYhBNGmbhojsYLJmA94jPv8yCoBXnMwAAAf0wv/a++a3DkL +CttbK4LRIiSry2wb97mxYQoWYzvkKYD1IP/KiamRwzjBKuRSE0qZ2uonQDRGc+zl +1H9dwkDLL4T9uJngCCPCBgFW/hOFPvF+WYEKHtOzunqx6KwDHkpdH+hpzfFzIhDo +aXiVnDGvJ3H/bVTKq1m2KPXO2ckkXPQXJX9Fx6kPHdvcq+3ZI75IzbD/ue5lBcsy +OKLzVu+KLxzlzGui6v1V0fTvU/uqvHlvUxcDAqMnIsDUPakjK2RDeQ38qtN6+PQ5 +/dT7vx2Wtzesqn2eDbDf5uRfSgmp2hJLJniAKjMCBVAJiOgPb0LXUIcwCGxaiWOA +g5ZvNWjX5bZ/FxqpLpOE9OReI5YY7ns7zqP4thLYYWe0Qdp9a2ezVrgzgrh/SLla +d73x/S9TrmLtYGGlbVUByJW+GXjW2Tt6iaa/WDFzx8NvZ/wzIAdGSEfLcvS+JBSP +2ppdY5Ac/2dK3PzYABkHvB/rhXIwlXnrFDU9efRHZfFqQqGauA64wfdIzsDNBF2l +nPIBDADWML9cbGMrp12CtF9b2P6z9TTT74S8iyBOzaSvdGDQY/sUtZXRg21HWamX +nn9sSXvIDEINOQ6A9QxdxoqWdCHrOuW3ofneYXoG+zeKc4dC86wa1TR2q9vW+RMX +SO4uImA+Uzula/6k1DogDf28qhCxMwG/i/m9g1c/0aApuDyKdQ1PXsHHNlgd/Dn6 +rrd5y2AObaifV7wIhEJnvqgFXDN2RXGjLeCOHV4Q2WTYPg/S4k1nMXVDwZXrvIsA +0YwIMgIT86Rafp1qKlgPNbiIlC1g9RY/iFaGN2b4Ir6GDohBQSfZW2+LXoPZuVE/ +wGlQ01rh827KVZW4lXvqsge+wtnWlszcselGATyzqOK9LdHPdZGzROZYI2e8c+pa +LNDdVPL6vdRBUnkCaEkOtl1mr2JpQi5nTU+gTX4IeInC7E+1a9UDF/Y85ybUz8XV +8rUnR76UqVC7KidNepdHbZjjXCt8/Zo+Tec9JNbYNQB/e9ExmDntmlHEsSEQzFwz +j8sxH48AEQEAAcLA9gQYAQoAIBYhBNGmbhojsYLJmA94jPv8yCoBXnMwBQJdpZzy +AhsMAAoJEPv8yCoBXnMw6f8L/26C34dkjBffTzMj5Bdzm8MtF67OYneJ4TQMw7+4 +1IL4rVcSKhIhk/3Ud5knaRtP2ef1+5F66h9/RPQOJ5+tvBwhBAcUWSupKnUrdVaZ +QanYmtSxcVV2PL9+QEiNN3tzluhaWO//rACxJ+K/ZXQlIzwQVTpNhfGzAaMVV9zp +f3u0k14itcv6alKY8+rLZvO1wIIeRZLmU0tZDD5HtWDvUV7rIFI1WuoLb+KZgbYn +3OWjCPHVdTrdZ2CqnZbG3SXw6awH9bzRLV9EXkbhIMez0deCVdeo+wFFklh8/5VK +2b0vk/+wqMJxfpa1lHvJLobzOP9fvrswsr92MA2+k901WeISR7qEzcI0Fdg8AyFA +ExaEK6VyjP7SXGLwvfisw34OxuZr3qmx1Sufu4toH3XrB7QJN8XyqqbsGxUCBqWi +f9RSK4xjzRTe56iPeiSJJOIciMP9i2ldI+KgLycyeDvGoBj0HCLO3gVaBe4ubVrj +5KjhX2PVNEJd3XZRzaXZE2aAMQ== +=522n +-----END PGP PUBLIC KEY BLOCK-----` diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go new file mode 100644 index 0000000..7350974 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go @@ -0,0 +1,56 @@ +// Copyright (C) 2019 ProtonTech AG + +package packet + +import "math/bits" + +// AEADConfig collects a number of AEAD parameters along with sensible defaults. +// A nil AEADConfig is valid and results in all default values. +type AEADConfig struct { + // The AEAD mode of operation. + DefaultMode AEADMode + // Amount of octets in each chunk of data + ChunkSize uint64 +} + +// Mode returns the AEAD mode of operation. +func (conf *AEADConfig) Mode() AEADMode { + if conf == nil || conf.DefaultMode == 0 { + return AEADModeEAX + } + mode := conf.DefaultMode + if mode != AEADModeEAX && mode != AEADModeOCB && + mode != AEADModeExperimentalGCM { + panic("AEAD mode unsupported") + } + return mode +} + +// ChunkSizeByte returns the byte indicating the chunk size. The effective +// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6) +func (conf *AEADConfig) ChunkSizeByte() byte { + if conf == nil || conf.ChunkSize == 0 { + return 12 // 1 << (12 + 6) == 262144 bytes + } + + chunkSize := conf.ChunkSize + exponent := bits.Len64(chunkSize) - 1 + switch { + case exponent < 6: + exponent = 6 + case exponent > 27: + exponent = 27 + } + + return byte(exponent - 6) +} + +// decodeAEADChunkSize returns the effective chunk size. In 32-bit systems, the +// maximum returned value is 1 << 30. +func decodeAEADChunkSize(c byte) int { + size := uint64(1 << (c + 6)) + if size != uint64(int(size)) { + return 1 << 30 + } + return int(size) +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go new file mode 100644 index 0000000..85c53f0 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go @@ -0,0 +1,364 @@ +// Copyright (C) 2019 ProtonTech AG + +package packet + +import ( + "bytes" + "crypto/cipher" + "crypto/rand" + "encoding/binary" + "io" + + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" +) + +// AEADEncrypted represents an AEAD Encrypted Packet (tag 20, RFC4880bis-5.16). +type AEADEncrypted struct { + cipher CipherFunction + mode AEADMode + chunkSizeByte byte + Contents io.Reader // Encrypted chunks and tags + initialNonce []byte // Referred to as IV in RFC4880-bis +} + +// Only currently defined version +const aeadEncryptedVersion = 1 + +// An AEAD opener/sealer, its configuration, and data for en/decryption. +type aeadCrypter struct { + aead cipher.AEAD + chunkSize int + initialNonce []byte + associatedData []byte // Chunk-independent associated data + chunkIndex []byte // Chunk counter + bytesProcessed int // Amount of plaintext bytes encrypted/decrypted + buffer bytes.Buffer // Buffered bytes accross chunks +} + +// aeadEncrypter encrypts and writes bytes. It encrypts when necessary according +// to the AEAD block size, and buffers the extra encrypted bytes for next write. +type aeadEncrypter struct { + aeadCrypter // Embedded plaintext sealer + writer io.WriteCloser // 'writer' is a partialLengthWriter +} + +// aeadDecrypter reads and decrypts bytes. It buffers extra decrypted bytes when +// necessary, similar to aeadEncrypter. +type aeadDecrypter struct { + aeadCrypter // Embedded ciphertext opener + reader io.Reader // 'reader' is a partialLengthReader + peekedBytes []byte // Used to detect last chunk + eof bool +} + +func (ae *AEADEncrypted) parse(buf io.Reader) error { + headerData := make([]byte, 4) + if n, err := io.ReadFull(buf, headerData); n < 4 { + return errors.AEADError("could not read aead header:" + err.Error()) + } + // Read initial nonce + mode := AEADMode(headerData[2]) + nonceLen := mode.NonceLength() + if nonceLen == 0 { + return errors.AEADError("unknown mode") + } + initialNonce := make([]byte, nonceLen) + if n, err := io.ReadFull(buf, initialNonce); n < nonceLen { + return errors.AEADError("could not read aead nonce:" + err.Error()) + } + ae.Contents = buf + ae.initialNonce = initialNonce + c := headerData[1] + if _, ok := algorithm.CipherById[c]; !ok { + return errors.UnsupportedError("unknown cipher: " + string(c)) + } + ae.cipher = CipherFunction(c) + ae.mode = mode + ae.chunkSizeByte = byte(headerData[3]) + return nil +} + +// Decrypt returns a io.ReadCloser from which decrypted bytes can be read, or +// an error. +func (ae *AEADEncrypted) Decrypt(ciph CipherFunction, key []byte) (io.ReadCloser, error) { + return ae.decrypt(key) +} + +// decrypt prepares an aeadCrypter and returns a ReadCloser from which +// decrypted bytes can be read (see aeadDecrypter.Read()). +func (ae *AEADEncrypted) decrypt(key []byte) (io.ReadCloser, error) { + blockCipher := ae.cipher.new(key) + aead := ae.mode.new(blockCipher) + // Carry the first tagLen bytes + tagLen := ae.mode.TagLength() + peekedBytes := make([]byte, tagLen) + n, err := io.ReadFull(ae.Contents, peekedBytes) + if n < tagLen || (err != nil && err != io.EOF) { + return nil, errors.AEADError("Not enough data to decrypt:" + err.Error()) + } + chunkSize := decodeAEADChunkSize(ae.chunkSizeByte) + return &aeadDecrypter{ + aeadCrypter: aeadCrypter{ + aead: aead, + chunkSize: chunkSize, + initialNonce: ae.initialNonce, + associatedData: ae.associatedData(), + chunkIndex: make([]byte, 8), + }, + reader: ae.Contents, + peekedBytes: peekedBytes}, nil +} + +// Read decrypts bytes and reads them into dst. It decrypts when necessary and +// buffers extra decrypted bytes. It returns the number of bytes copied into dst +// and an error. +func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) { + // Return buffered plaintext bytes from previous calls + if ar.buffer.Len() > 0 { + return ar.buffer.Read(dst) + } + + // Return EOF if we've previously validated the final tag + if ar.eof { + return 0, io.EOF + } + + // Read a chunk + tagLen := ar.aead.Overhead() + cipherChunkBuf := new(bytes.Buffer) + _, errRead := io.CopyN(cipherChunkBuf, ar.reader, int64(ar.chunkSize + tagLen)) + cipherChunk := cipherChunkBuf.Bytes() + if errRead != nil && errRead != io.EOF { + return 0, errRead + } + decrypted, errChunk := ar.openChunk(cipherChunk) + if errChunk != nil { + return 0, errChunk + } + + // Return decrypted bytes, buffering if necessary + if len(dst) < len(decrypted) { + n = copy(dst, decrypted[:len(dst)]) + ar.buffer.Write(decrypted[len(dst):]) + } else { + n = copy(dst, decrypted) + } + + // Check final authentication tag + if errRead == io.EOF { + errChunk := ar.validateFinalTag(ar.peekedBytes) + if errChunk != nil { + return n, errChunk + } + ar.eof = true // Mark EOF for when we've returned all buffered data + } + return +} + +// Close is noOp. The final authentication tag of the stream was already +// checked in the last Read call. In the future, this function could be used to +// wipe the reader and peeked, decrypted bytes, if necessary. +func (ar *aeadDecrypter) Close() (err error) { + return nil +} + +// SerializeAEADEncrypted initializes the aeadCrypter and returns a writer. +// This writer encrypts and writes bytes (see aeadEncrypter.Write()). +func SerializeAEADEncrypted(w io.Writer, key []byte, cipher CipherFunction, mode AEADMode, config *Config) (io.WriteCloser, error) { + writeCloser := noOpCloser{w} + writer, err := serializeStreamHeader(writeCloser, packetTypeAEADEncrypted) + if err != nil { + return nil, err + } + + // Data for en/decryption: tag, version, cipher, aead mode, chunk size + aeadConf := config.AEAD() + prefix := []byte{ + 0xD4, + aeadEncryptedVersion, + byte(config.Cipher()), + byte(aeadConf.Mode()), + aeadConf.ChunkSizeByte(), + } + n, err := writer.Write(prefix[1:]) + if err != nil || n < 4 { + return nil, errors.AEADError("could not write AEAD headers") + } + // Sample nonce + nonceLen := aeadConf.Mode().NonceLength() + nonce := make([]byte, nonceLen) + n, err = rand.Read(nonce) + if err != nil { + panic("Could not sample random nonce") + } + _, err = writer.Write(nonce) + if err != nil { + return nil, err + } + blockCipher := CipherFunction(config.Cipher()).new(key) + alg := AEADMode(aeadConf.Mode()).new(blockCipher) + + chunkSize := decodeAEADChunkSize(aeadConf.ChunkSizeByte()) + return &aeadEncrypter{ + aeadCrypter: aeadCrypter{ + aead: alg, + chunkSize: chunkSize, + associatedData: prefix, + chunkIndex: make([]byte, 8), + initialNonce: nonce, + }, + writer: writer}, nil +} + +// Write encrypts and writes bytes. It encrypts when necessary and buffers extra +// plaintext bytes for next call. When the stream is finished, Close() MUST be +// called to append the final tag. +func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) { + // Append plaintextBytes to existing buffered bytes + n, err = aw.buffer.Write(plaintextBytes) + if err != nil { + return n, err + } + // Encrypt and write chunks + for aw.buffer.Len() >= aw.chunkSize { + plainChunk := aw.buffer.Next(aw.chunkSize) + encryptedChunk, err := aw.sealChunk(plainChunk) + if err != nil { + return n, err + } + _, err = aw.writer.Write(encryptedChunk) + if err != nil { + return n, err + } + } + return +} + +// Close encrypts and writes the remaining buffered plaintext if any, appends +// the final authentication tag, and closes the embedded writer. This function +// MUST be called at the end of a stream. +func (aw *aeadEncrypter) Close() (err error) { + // Encrypt and write a chunk if there's buffered data left, or if we haven't + // written any chunks yet. + if aw.buffer.Len() > 0 || aw.bytesProcessed == 0 { + plainChunk := aw.buffer.Bytes() + lastEncryptedChunk, err := aw.sealChunk(plainChunk) + if err != nil { + return err + } + _, err = aw.writer.Write(lastEncryptedChunk) + if err != nil { + return err + } + } + // Compute final tag (associated data: packet tag, version, cipher, aead, + // chunk size, index, total number of encrypted octets). + adata := append(aw.associatedData[:], aw.chunkIndex[:]...) + adata = append(adata, make([]byte, 8)...) + binary.BigEndian.PutUint64(adata[13:], uint64(aw.bytesProcessed)) + nonce := aw.computeNextNonce() + finalTag := aw.aead.Seal(nil, nonce, nil, adata) + _, err = aw.writer.Write(finalTag) + if err != nil { + return err + } + return aw.writer.Close() +} + +// sealChunk Encrypts and authenticates the given chunk. +func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) { + if len(data) > aw.chunkSize { + return nil, errors.AEADError("chunk exceeds maximum length") + } + if aw.associatedData == nil { + return nil, errors.AEADError("can't seal without headers") + } + adata := append(aw.associatedData, aw.chunkIndex...) + nonce := aw.computeNextNonce() + encrypted := aw.aead.Seal(nil, nonce, data, adata) + aw.bytesProcessed += len(data) + if err := aw.aeadCrypter.incrementIndex(); err != nil { + return nil, err + } + return encrypted, nil +} + +// openChunk decrypts and checks integrity of an encrypted chunk, returning +// the underlying plaintext and an error. It access peeked bytes from next +// chunk, to identify the last chunk and decrypt/validate accordingly. +func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) { + tagLen := ar.aead.Overhead() + // Restore carried bytes from last call + chunkExtra := append(ar.peekedBytes, data...) + // 'chunk' contains encrypted bytes, followed by an authentication tag. + chunk := chunkExtra[:len(chunkExtra)-tagLen] + ar.peekedBytes = chunkExtra[len(chunkExtra)-tagLen:] + adata := append(ar.associatedData, ar.chunkIndex...) + nonce := ar.computeNextNonce() + plainChunk, err := ar.aead.Open(nil, nonce, chunk, adata) + if err != nil { + return nil, err + } + ar.bytesProcessed += len(plainChunk) + if err = ar.aeadCrypter.incrementIndex(); err != nil { + return nil, err + } + return plainChunk, nil +} + +// Checks the summary tag. It takes into account the total decrypted bytes into +// the associated data. It returns an error, or nil if the tag is valid. +func (ar *aeadDecrypter) validateFinalTag(tag []byte) error { + // Associated: tag, version, cipher, aead, chunk size, index, and octets + amountBytes := make([]byte, 8) + binary.BigEndian.PutUint64(amountBytes, uint64(ar.bytesProcessed)) + adata := append(ar.associatedData, ar.chunkIndex...) + adata = append(adata, amountBytes...) + nonce := ar.computeNextNonce() + _, err := ar.aead.Open(nil, nonce, tag, adata) + if err != nil { + return err + } + return nil +} + +// Associated data for chunks: tag, version, cipher, mode, chunk size byte +func (ae *AEADEncrypted) associatedData() []byte { + return []byte{ + 0xD4, + aeadEncryptedVersion, + byte(ae.cipher), + byte(ae.mode), + ae.chunkSizeByte} +} + +// computeNonce takes the incremental index and computes an eXclusive OR with +// the least significant 8 bytes of the receivers' initial nonce (see sec. +// 5.16.1 and 5.16.2). It returns the resulting nonce. +func (wo *aeadCrypter) computeNextNonce() (nonce []byte) { + nonce = make([]byte, len(wo.initialNonce)) + copy(nonce, wo.initialNonce) + offset := len(wo.initialNonce) - 8 + for i := 0; i < 8; i++ { + nonce[i+offset] ^= wo.chunkIndex[i] + } + return +} + +// incrementIndex perfoms an integer increment by 1 of the integer represented by the +// slice, modifying it accordingly. +func (wo *aeadCrypter) incrementIndex() error { + index := wo.chunkIndex + if len(index) == 0 { + return errors.AEADError("Index has length 0") + } + for i := len(index) - 1; i >= 0; i-- { + if index[i] < 255 { + index[i]++ + return nil + } + index[i] = 0 + } + return errors.AEADError("cannot further increment index") +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go similarity index 98% rename from vendor/golang.org/x/crypto/openpgp/packet/compressed.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go index e8f0b5c..c55cecd 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go @@ -8,7 +8,7 @@ import ( "compress/bzip2" "compress/flate" "compress/zlib" - "golang.org/x/crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/errors" "io" "strconv" ) diff --git a/vendor/golang.org/x/crypto/openpgp/packet/config.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go similarity index 51% rename from vendor/golang.org/x/crypto/openpgp/packet/config.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go index c76eecc..5652dd8 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/config.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go @@ -8,6 +8,7 @@ import ( "crypto" "crypto/rand" "io" + "math/big" "time" ) @@ -46,6 +47,37 @@ type Config struct { // RSABits is the number of bits in new RSA keys made with NewEntity. // If zero, then 2048 bit keys are created. RSABits int + // The public key algorithm to use - will always create a signing primary + // key and encryption subkey. + Algorithm PublicKeyAlgorithm + // Some known primes that are optionally prepopulated by the caller + RSAPrimes []*big.Int + // AEADConfig configures the use of the new AEAD Encrypted Data Packet, + // defined in the draft of the next version of the OpenPGP specification. + // If a non-nil AEADConfig is passed, usage of this packet is enabled. By + // default, it is disabled. See the documentation of AEADConfig for more + // configuration options related to AEAD. + // **Note: using this option may break compatibility with other OpenPGP + // implementations, as well as future versions of this library.** + AEADConfig *AEADConfig + // V5Keys configures version 5 key generation. If false, this package still + // supports version 5 keys, but produces version 4 keys. + V5Keys bool + // "The validity period of the key. This is the number of seconds after + // the key creation time that the key expires. If this is not present + // or has a value of zero, the key never expires. This is found only on + // a self-signature."" + // https://tools.ietf.org/html/rfc4880#section-5.2.3.6 + KeyLifetimeSecs uint32 + // "The validity period of the signature. This is the number of seconds + // after the signature creation time that the signature expires. If + // this is not present or has a value of zero, it never expires." + // https://tools.ietf.org/html/rfc4880#section-5.2.3.10 + SigLifetimeSecs uint32 + // SigningKeyId is used to specify the signing key to use (by Key ID). + // By default, the signing key is selected automatically, preferring + // signing subkeys if available. + SigningKeyId uint64 } func (c *Config) Random() io.Reader { @@ -76,6 +108,22 @@ func (c *Config) Now() time.Time { return c.Time() } +// KeyLifetime returns the validity period of the key. +func (c *Config) KeyLifetime() uint32 { + if c == nil { + return 0 + } + return c.KeyLifetimeSecs +} + +// SigLifetime returns the validity period of the signature. +func (c *Config) SigLifetime() uint32 { + if c == nil { + return 0 + } + return c.SigLifetimeSecs +} + func (c *Config) Compression() CompressionAlgo { if c == nil { return CompressionNone @@ -89,3 +137,31 @@ func (c *Config) PasswordHashIterations() int { } return c.S2KCount } + +func (c *Config) RSAModulusBits() int { + if c == nil || c.RSABits == 0 { + return 2048 + } + return c.RSABits +} + +func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm { + if c == nil || c.Algorithm == 0 { + return PubKeyAlgoRSA + } + return c.Algorithm +} + +func (c *Config) AEAD() *AEADConfig { + if c == nil { + return nil + } + return c.AEADConfig +} + +func (c *Config) SigningKey() uint64 { + if c == nil { + return 0 + } + return c.SigningKeyId +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go similarity index 58% rename from vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go index 6d76397..801aec9 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go @@ -12,8 +12,10 @@ import ( "math/big" "strconv" - "golang.org/x/crypto/openpgp/elgamal" - "golang.org/x/crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/ecdh" + "github.com/ProtonMail/go-crypto/openpgp/elgamal" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" ) const encryptedKeyVersion = 3 @@ -26,7 +28,7 @@ type EncryptedKey struct { CipherFunc CipherFunction // only valid after a successful Decrypt Key []byte // only valid after a successful Decrypt - encryptedMPI1, encryptedMPI2 parsedMPI + encryptedMPI1, encryptedMPI2 encoding.Field } func (e *EncryptedKey) parse(r io.Reader) (err error) { @@ -42,17 +44,28 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) { e.Algo = PublicKeyAlgorithm(buf[9]) switch e.Algo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) - if err != nil { + e.encryptedMPI1 = new(encoding.MPI) + if _, err = e.encryptedMPI1.ReadFrom(r); err != nil { return } case PubKeyAlgoElGamal: - e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) - if err != nil { + e.encryptedMPI1 = new(encoding.MPI) + if _, err = e.encryptedMPI1.ReadFrom(r); err != nil { return } - e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) - if err != nil { + + e.encryptedMPI2 = new(encoding.MPI) + if _, err = e.encryptedMPI2.ReadFrom(r); err != nil { + return + } + case PubKeyAlgoECDH: + e.encryptedMPI1 = new(encoding.MPI) + if _, err = e.encryptedMPI1.ReadFrom(r); err != nil { + return + } + + e.encryptedMPI2 = new(encoding.OID) + if _, err = e.encryptedMPI2.ReadFrom(r); err != nil { return } } @@ -72,6 +85,16 @@ func checksumKeyMaterial(key []byte) uint16 { // private key must have been decrypted first. // If config is nil, sensible defaults will be used. func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { + if e.KeyId != 0 && e.KeyId != priv.KeyId { + return errors.InvalidArgumentError("cannot decrypt encrypted session key for key id " + strconv.FormatUint(e.KeyId, 16) + " with private key id " + strconv.FormatUint(priv.KeyId, 16)) + } + if e.Algo != priv.PubKeyAlgo { + return errors.InvalidArgumentError("cannot decrypt encrypted session key of type " + strconv.Itoa(int(e.Algo)) + " with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) + } + if priv.Dummy() { + return errors.ErrDummyPrivateKey("dummy key found") + } + var err error var b []byte @@ -81,13 +104,18 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: // Supports both *rsa.PrivateKey and crypto.Decrypter k := priv.PrivateKey.(crypto.Decrypter) - b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil) + b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.Bytes()), nil) case PubKeyAlgoElGamal: - c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) - c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) + c1 := new(big.Int).SetBytes(e.encryptedMPI1.Bytes()) + c2 := new(big.Int).SetBytes(e.encryptedMPI2.Bytes()) b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) + case PubKeyAlgoECDH: + vsG := e.encryptedMPI1.Bytes() + m := e.encryptedMPI2.Bytes() + oid := priv.PublicKey.oid.EncodedBytes() + b, err = ecdh.Decrypt(priv.PrivateKey.(*ecdh.PrivateKey), vsG, m, oid, priv.PublicKey.Fingerprint[:]) default: - err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) + err = errors.InvalidArgumentError("cannot decrypt encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) } if err != nil { @@ -110,14 +138,19 @@ func (e *EncryptedKey) Serialize(w io.Writer) error { var mpiLen int switch e.Algo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - mpiLen = 2 + len(e.encryptedMPI1.bytes) + mpiLen = int(e.encryptedMPI1.EncodedLength()) case PubKeyAlgoElGamal: - mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes) + mpiLen = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength()) + case PubKeyAlgoECDH: + mpiLen = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength()) default: return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) } - serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) + err := serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) + if err != nil { + return err + } w.Write([]byte{encryptedKeyVersion}) binary.Write(w, binary.BigEndian, e.KeyId) @@ -125,14 +158,23 @@ func (e *EncryptedKey) Serialize(w io.Writer) error { switch e.Algo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - writeMPIs(w, e.encryptedMPI1) + _, err := w.Write(e.encryptedMPI1.EncodedBytes()) + return err case PubKeyAlgoElGamal: - writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) + if _, err := w.Write(e.encryptedMPI1.EncodedBytes()); err != nil { + return err + } + _, err := w.Write(e.encryptedMPI2.EncodedBytes()) + return err + case PubKeyAlgoECDH: + if _, err := w.Write(e.encryptedMPI1.EncodedBytes()); err != nil { + return err + } + _, err := w.Write(e.encryptedMPI2.EncodedBytes()) + return err default: panic("internal error") } - - return nil } // SerializeEncryptedKey serializes an encrypted key packet to w that contains @@ -156,6 +198,8 @@ func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunctio return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) case PubKeyAlgoElGamal: return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) + case PubKeyAlgoECDH: + return serializeEncryptedKeyECDH(w, config.Random(), buf, pub.PublicKey.(*ecdh.PublicKey), keyBlock, pub.oid, pub.Fingerprint) case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) } @@ -169,7 +213,8 @@ func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) } - packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) + cipherMPI := encoding.NewMPI(cipherText) + packetLen := 10 /* header length */ + int(cipherMPI.EncodedLength()) err = serializeHeader(w, packetTypeEncryptedKey, packetLen) if err != nil { @@ -179,7 +224,8 @@ func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub if err != nil { return err } - return writeMPI(w, 8*uint16(len(cipherText)), cipherText) + _, err = w.Write(cipherMPI.EncodedBytes()) + return err } func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { @@ -200,9 +246,37 @@ func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, if err != nil { return err } - err = writeBig(w, c1) + if _, err = w.Write(new(encoding.MPI).SetBig(c1).EncodedBytes()); err != nil { + return err + } + _, err = w.Write(new(encoding.MPI).SetBig(c2).EncodedBytes()) + return err +} + +func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub *ecdh.PublicKey, keyBlock []byte, oid encoding.Field, fingerprint []byte) error { + vsG, c, err := ecdh.Encrypt(rand, pub, keyBlock, oid.EncodedBytes(), fingerprint) + if err != nil { + return errors.InvalidArgumentError("ECDH encryption failed: " + err.Error()) + } + + g := encoding.NewMPI(vsG) + m := encoding.NewOID(c) + + packetLen := 10 /* header length */ + packetLen += int(g.EncodedLength()) + int(m.EncodedLength()) + + err = serializeHeader(w, packetTypeEncryptedKey, packetLen) if err != nil { return err } - return writeBig(w, c2) + + _, err = w.Write(header[:]) + if err != nil { + return err + } + if _, err = w.Write(g.EncodedBytes()); err != nil { + return err + } + _, err = w.Write(m.EncodedBytes()) + return err } diff --git a/vendor/golang.org/x/crypto/openpgp/packet/literal.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go similarity index 96% rename from vendor/golang.org/x/crypto/openpgp/packet/literal.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go index 1a9ec6e..4be9876 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/literal.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go @@ -11,6 +11,7 @@ import ( // LiteralData represents an encrypted file. See RFC 4880, section 5.9. type LiteralData struct { + Format uint8 IsBinary bool FileName string Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. @@ -31,7 +32,8 @@ func (l *LiteralData) parse(r io.Reader) (err error) { return } - l.IsBinary = buf[0] == 'b' + l.Format = buf[0] + l.IsBinary = l.Format == 'b' fileNameLen := int(buf[1]) _, err = readFull(r, buf[:fileNameLen]) diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/ocfb.go similarity index 92% rename from vendor/golang.org/x/crypto/openpgp/packet/ocfb.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/ocfb.go index ce2a33a..4f26d0a 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/ocfb.go @@ -85,8 +85,7 @@ type ocfbDecrypter struct { // NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's // cipher feedback mode using the given cipher.Block. Prefix must be the first // blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's -// block size. If an incorrect key is detected then nil is returned. On -// successful exit, blockSize+2 bytes of decrypted data are written into +// block size. On successful exit, blockSize+2 bytes of decrypted data are written into // prefix. Resync determines if the "resynchronization step" from RFC 4880, // 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { @@ -112,11 +111,6 @@ func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption prefixCopy[blockSize] ^= x.fre[0] prefixCopy[blockSize+1] ^= x.fre[1] - if prefixCopy[blockSize-2] != prefixCopy[blockSize] || - prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { - return nil - } - if resync { block.Encrypt(x.fre, prefix[2:]) } else { diff --git a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go similarity index 94% rename from vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go index 1713503..41c35de 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go @@ -7,8 +7,8 @@ package packet import ( "crypto" "encoding/binary" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/s2k" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/s2k" "io" "strconv" ) diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go similarity index 98% rename from vendor/golang.org/x/crypto/openpgp/packet/opaque.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go index 456d807..e387919 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go @@ -9,7 +9,7 @@ import ( "io" "io/ioutil" - "golang.org/x/crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/errors" ) // OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go similarity index 71% rename from vendor/golang.org/x/crypto/openpgp/packet/packet.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go index 9728d61..fe0da9d 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/packet.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go @@ -4,20 +4,16 @@ // Package packet implements parsing and serialization of OpenPGP packets, as // specified in RFC 4880. -package packet // import "golang.org/x/crypto/openpgp/packet" +package packet // import "github.com/ProtonMail/go-crypto/openpgp/packet" import ( - "bufio" - "crypto/aes" + "bytes" "crypto/cipher" - "crypto/des" "crypto/rsa" "io" - "math/big" - "math/bits" - "golang.org/x/crypto/cast5" - "golang.org/x/crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" ) // readFull is the same as io.ReadFull except that reading zero bytes returns @@ -100,68 +96,43 @@ func (r *partialLengthReader) Read(p []byte) (n int, err error) { // See RFC 4880, section 4.2.2.4. type partialLengthWriter struct { w io.WriteCloser + buf bytes.Buffer lengthByte [1]byte - sentFirst bool - buf []byte } -// RFC 4880 4.2.2.4: the first partial length MUST be at least 512 octets long. -const minFirstPartialWrite = 512 - func (w *partialLengthWriter) Write(p []byte) (n int, err error) { - off := 0 - if !w.sentFirst { - if len(w.buf) > 0 || len(p) < minFirstPartialWrite { - off = len(w.buf) - w.buf = append(w.buf, p...) - if len(w.buf) < minFirstPartialWrite { - return len(p), nil + bufLen := w.buf.Len() + if bufLen > 512 { + for power := uint(30); ; power-- { + l := 1 << power + if bufLen >= l { + w.lengthByte[0] = 224 + uint8(power) + _, err = w.w.Write(w.lengthByte[:]) + if err != nil { + return + } + var m int + m, err = w.w.Write(w.buf.Next(l)) + if err != nil { + return + } + if m != l { + return 0, io.ErrShortWrite + } + break } - p = w.buf - w.buf = nil } - w.sentFirst = true } - - power := uint8(30) - for len(p) > 0 { - l := 1 << power - if len(p) < l { - power = uint8(bits.Len32(uint32(len(p)))) - 1 - l = 1 << power - } - w.lengthByte[0] = 224 + power - _, err = w.w.Write(w.lengthByte[:]) - if err == nil { - var m int - m, err = w.w.Write(p[:l]) - n += m - } - if err != nil { - if n < off { - return 0, err - } - return n - off, err - } - p = p[l:] - } - return n - off, nil + return w.buf.Write(p) } -func (w *partialLengthWriter) Close() error { - if len(w.buf) > 0 { - // In this case we can't send a 512 byte packet. - // Just send what we have. - p := w.buf - w.sentFirst = true - w.buf = nil - if _, err := w.Write(p); err != nil { - return err - } +func (w *partialLengthWriter) Close() (err error) { + len := w.buf.Len() + err = serializeLength(w.w, len) + if err != nil { + return err } - - w.lengthByte[0] = 0 - _, err := w.w.Write(w.lengthByte[:]) + _, err = w.buf.WriteTo(w.w) if err != nil { return err } @@ -246,25 +217,43 @@ func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, // serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section // 4.2. func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { - var buf [6]byte + err = serializeType(w, ptype) + if err != nil { + return + } + return serializeLength(w, length) +} + +// serializeType writes an OpenPGP packet type to w. See RFC 4880, section +// 4.2. +func serializeType(w io.Writer, ptype packetType) (err error) { + var buf [1]byte + buf[0] = 0x80 | 0x40 | byte(ptype) + _, err = w.Write(buf[:]) + return +} + +// serializeLength writes an OpenPGP packet length to w. See RFC 4880, section +// 4.2.2. +func serializeLength(w io.Writer, length int) (err error) { + var buf [5]byte var n int - buf[0] = 0x80 | 0x40 | byte(ptype) if length < 192 { - buf[1] = byte(length) - n = 2 + buf[0] = byte(length) + n = 1 } else if length < 8384 { length -= 192 - buf[1] = 192 + byte(length>>8) - buf[2] = byte(length) - n = 3 + buf[0] = 192 + byte(length>>8) + buf[1] = byte(length) + n = 2 } else { - buf[1] = 255 - buf[2] = byte(length >> 24) - buf[3] = byte(length >> 16) - buf[4] = byte(length >> 8) - buf[5] = byte(length) - n = 6 + buf[0] = 255 + buf[1] = byte(length >> 24) + buf[2] = byte(length >> 16) + buf[3] = byte(length >> 8) + buf[4] = byte(length) + n = 5 } _, err = w.Write(buf[:n]) @@ -275,9 +264,7 @@ func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { // length of the packet is unknown. It returns a io.WriteCloser which can be // used to write the contents of the packet. See RFC 4880, section 4.2. func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { - var buf [1]byte - buf[0] = 0x80 | 0x40 | byte(ptype) - _, err = w.Write(buf[:]) + err = serializeType(w, ptype) if err != nil { return } @@ -329,19 +316,13 @@ const ( packetTypePublicSubkey packetType = 14 packetTypeUserAttribute packetType = 17 packetTypeSymmetricallyEncryptedMDC packetType = 18 + packetTypeAEADEncrypted packetType = 20 ) -// peekVersion detects the version of a public key packet about to -// be read. A bufio.Reader at the original position of the io.Reader -// is returned. -func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { - bufr = bufio.NewReader(r) - var verBuf []byte - if verBuf, err = bufr.Peek(1); err != nil { - return - } - ver = verBuf[0] - return +// EncryptedDataPacket holds encrypted data. It is currently implemented by +// SymmetricallyEncrypted and AEADEncrypted. +type EncryptedDataPacket interface { + Decrypt(CipherFunction, []byte) (io.ReadCloser, error) } // Read reads a single OpenPGP packet from the given io.Reader. If there is an @@ -356,16 +337,7 @@ func Read(r io.Reader) (p Packet, err error) { case packetTypeEncryptedKey: p = new(EncryptedKey) case packetTypeSignature: - var version byte - // Detect signature version - if contents, version, err = peekVersion(contents); err != nil { - return - } - if version < 4 { - p = new(SignatureV3) - } else { - p = new(Signature) - } + p = new(Signature) case packetTypeSymmetricKeyEncrypted: p = new(SymmetricKeyEncrypted) case packetTypeOnePassSignature: @@ -377,20 +349,12 @@ func Read(r io.Reader) (p Packet, err error) { } p = pk case packetTypePublicKey, packetTypePublicSubkey: - var version byte - if contents, version, err = peekVersion(contents); err != nil { - return - } isSubkey := tag == packetTypePublicSubkey - if version < 4 { - p = &PublicKeyV3{IsSubkey: isSubkey} - } else { - p = &PublicKey{IsSubkey: isSubkey} - } + p = &PublicKey{IsSubkey: isSubkey} case packetTypeCompressed: p = new(Compressed) case packetTypeSymmetricallyEncrypted: - p = new(SymmetricallyEncrypted) + err = errors.UnsupportedError("Symmetrically encrypted packets without MDC are not supported") case packetTypeLiteralData: p = new(LiteralData) case packetTypeUserId: @@ -401,6 +365,8 @@ func Read(r io.Reader) (p Packet, err error) { se := new(SymmetricallyEncrypted) se.MDC = true p = se + case packetTypeAEADEncrypted: + p = new(AEADEncrypted) default: err = errors.UnknownPacketTypeError(tag) } @@ -418,8 +384,8 @@ func Read(r io.Reader) (p Packet, err error) { type SignatureType uint8 const ( - SigTypeBinary SignatureType = 0 - SigTypeText = 1 + SigTypeBinary SignatureType = 0x00 + SigTypeText = 0x01 SigTypeGenericCert = 0x10 SigTypePersonaCert = 0x11 SigTypeCasualCert = 0x12 @@ -443,6 +409,8 @@ const ( // RFC 6637, Section 5. PubKeyAlgoECDH PublicKeyAlgorithm = 18 PubKeyAlgoECDSA PublicKeyAlgorithm = 19 + // https://www.ietf.org/archive/id/draft-koch-eddsa-for-openpgp-04.txt + PubKeyAlgoEdDSA PublicKeyAlgorithm = 22 // Deprecated in RFC 4880, Section 13.5. Use key flags instead. PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 @@ -453,7 +421,7 @@ const ( // key of the given type. func (pka PublicKeyAlgorithm) CanEncrypt() bool { switch pka { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH: return true } return false @@ -463,7 +431,7 @@ func (pka PublicKeyAlgorithm) CanEncrypt() bool { // sign a message. func (pka PublicKeyAlgorithm) CanSign() bool { switch pka { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA: return true } return false @@ -471,7 +439,7 @@ func (pka PublicKeyAlgorithm) CanSign() bool { // CipherFunction represents the different block ciphers specified for OpenPGP. See // http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 -type CipherFunction uint8 +type CipherFunction algorithm.CipherFunction const ( Cipher3DES CipherFunction = 2 @@ -483,81 +451,17 @@ const ( // KeySize returns the key size, in bytes, of cipher. func (cipher CipherFunction) KeySize() int { - switch cipher { - case Cipher3DES: - return 24 - case CipherCAST5: - return cast5.KeySize - case CipherAES128: - return 16 - case CipherAES192: - return 24 - case CipherAES256: - return 32 - } - return 0 + return algorithm.CipherFunction(cipher).KeySize() } // blockSize returns the block size, in bytes, of cipher. func (cipher CipherFunction) blockSize() int { - switch cipher { - case Cipher3DES: - return des.BlockSize - case CipherCAST5: - return 8 - case CipherAES128, CipherAES192, CipherAES256: - return 16 - } - return 0 + return algorithm.CipherFunction(cipher).BlockSize() } // new returns a fresh instance of the given cipher. func (cipher CipherFunction) new(key []byte) (block cipher.Block) { - switch cipher { - case Cipher3DES: - block, _ = des.NewTripleDESCipher(key) - case CipherCAST5: - block, _ = cast5.NewCipher(key) - case CipherAES128, CipherAES192, CipherAES256: - block, _ = aes.NewCipher(key) - } - return -} - -// readMPI reads a big integer from r. The bit length returned is the bit -// length that was specified in r. This is preserved so that the integer can be -// reserialized exactly. -func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { - var buf [2]byte - _, err = readFull(r, buf[0:]) - if err != nil { - return - } - bitLength = uint16(buf[0])<<8 | uint16(buf[1]) - numBytes := (int(bitLength) + 7) / 8 - mpi = make([]byte, numBytes) - _, err = readFull(r, mpi) - // According to RFC 4880 3.2. we should check that the MPI has no leading - // zeroes (at least when not an encrypted MPI?), but this implementation - // does generate leading zeroes, so we keep accepting them. - return -} - -// writeMPI serializes a big integer to w. -func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { - // Note that we can produce leading zeroes, in violation of RFC 4880 3.2. - // Implementations seem to be tolerant of them, and stripping them would - // make it complex to guarantee matching re-serialization. - _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) - if err == nil { - _, err = w.Write(mpiBytes) - } - return -} - -// writeBig serializes a *big.Int to w. -func writeBig(w io.Writer, i *big.Int) error { - return writeMPI(w, uint16(i.BitLen()), i.Bytes()) + return algorithm.CipherFunction(cipher).New(key) } // padToKeySize left-pads a MPI with zeroes to match the length of the @@ -582,3 +486,37 @@ const ( CompressionZIP CompressionAlgo = 1 CompressionZLIB CompressionAlgo = 2 ) + +// AEADMode represents the different Authenticated Encryption with Associated +// Data specified for OpenPGP. +type AEADMode algorithm.AEADMode + +const ( + AEADModeEAX AEADMode = 1 + AEADModeOCB AEADMode = 2 + AEADModeExperimentalGCM AEADMode = 100 +) + +func (mode AEADMode) NonceLength() int { + return algorithm.AEADMode(mode).NonceLength() +} + +func (mode AEADMode) TagLength() int { + return algorithm.AEADMode(mode).TagLength() +} + +// new returns a fresh instance of the given mode. +func (mode AEADMode) new(block cipher.Block) cipher.AEAD { + return algorithm.AEADMode(mode).New(block) +} + +// ReasonForRevocation represents a revocation reason code as per RFC4880 +// section 5.2.3.23. +type ReasonForRevocation uint8 + +const ( + NoReason ReasonForRevocation = 0 + KeySuperseded ReasonForRevocation = 1 + KeyCompromised ReasonForRevocation = 2 + KeyRetired ReasonForRevocation = 3 +) diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go new file mode 100644 index 0000000..854f9c4 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go @@ -0,0 +1,780 @@ +// 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 packet + +import ( + "bytes" + "crypto" + "crypto/cipher" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" + "fmt" + "io" + "io/ioutil" + "math/big" + "strconv" + "time" + + "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" + "golang.org/x/crypto/curve25519" + + "github.com/ProtonMail/go-crypto/openpgp/ecdh" + "github.com/ProtonMail/go-crypto/openpgp/elgamal" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" + "github.com/ProtonMail/go-crypto/openpgp/s2k" + "golang.org/x/crypto/ed25519" +) + +// PrivateKey represents a possibly encrypted private key. See RFC 4880, +// section 5.5.3. +type PrivateKey struct { + PublicKey + Encrypted bool // if true then the private key is unavailable until Decrypt has been called. + encryptedData []byte + cipher CipherFunction + s2k func(out, in []byte) + // An *{rsa|dsa|elgamal|ecdh|ecdsa|ed25519}.PrivateKey or + // crypto.Signer/crypto.Decrypter (Decryptor RSA only). + PrivateKey interface{} + sha1Checksum bool + iv []byte + + // Type of encryption of the S2K packet + // Allowed values are 0 (Not encrypted), 254 (SHA1), or + // 255 (2-byte checksum) + s2kType S2KType + // Full parameters of the S2K packet + s2kParams *s2k.Params +} + +//S2KType s2k packet type +type S2KType uint8 + +const ( + // S2KNON unencrypt + S2KNON S2KType = 0 + // S2KSHA1 sha1 sum check + S2KSHA1 S2KType = 254 + // S2KCHECKSUM sum check + S2KCHECKSUM S2KType = 255 +) + +func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewEdDSAPrivateKey(creationTime time.Time, priv *ed25519.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pub := priv.Public().(ed25519.PublicKey) + pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pub) + pk.PrivateKey = priv + return pk +} + +func NewECDHPrivateKey(creationTime time.Time, priv *ecdh.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that +// implements RSA, ECDSA or EdDSA. +func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *PrivateKey { + pk := new(PrivateKey) + // In general, the public Keys should be used as pointers. We still + // type-switch on the values, for backwards-compatibility. + switch pubkey := signer.Public().(type) { + case *rsa.PublicKey: + pk.PublicKey = *NewRSAPublicKey(creationTime, pubkey) + case rsa.PublicKey: + pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey) + case *ecdsa.PublicKey: + pk.PublicKey = *NewECDSAPublicKey(creationTime, pubkey) + case ecdsa.PublicKey: + pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey) + case *ed25519.PublicKey: + pk.PublicKey = *NewEdDSAPublicKey(creationTime, pubkey) + case ed25519.PublicKey: + pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey) + default: + panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") + } + pk.PrivateKey = signer + return pk +} + +// NewDecrypterPrivateKey creates a PrivateKey from a *{rsa|elgamal|ecdh}.PrivateKey. +func NewDecrypterPrivateKey(creationTime time.Time, decrypter interface{}) *PrivateKey { + pk := new(PrivateKey) + switch priv := decrypter.(type) { + case *rsa.PrivateKey: + pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) + case *elgamal.PrivateKey: + pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) + case *ecdh.PrivateKey: + pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey) + default: + panic("openpgp: unknown decrypter type in NewDecrypterPrivateKey") + } + pk.PrivateKey = decrypter + return pk +} + +func (pk *PrivateKey) parse(r io.Reader) (err error) { + err = (&pk.PublicKey).parse(r) + if err != nil { + return + } + v5 := pk.PublicKey.Version == 5 + + var buf [1]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + pk.s2kType = S2KType(buf[0]) + var optCount [1]byte + if v5 { + if _, err = readFull(r, optCount[:]); err != nil { + return + } + } + + switch pk.s2kType { + case S2KNON: + pk.s2k = nil + pk.Encrypted = false + case S2KSHA1, S2KCHECKSUM: + if v5 && pk.s2kType == S2KCHECKSUM { + return errors.StructuralError("wrong s2k identifier for version 5") + } + _, err = readFull(r, buf[:]) + if err != nil { + return + } + pk.cipher = CipherFunction(buf[0]) + pk.s2kParams, err = s2k.ParseIntoParams(r) + if err != nil { + return + } + if pk.s2kParams.Dummy() { + return + } + pk.s2k, err = pk.s2kParams.Function() + if err != nil { + return + } + pk.Encrypted = true + if pk.s2kType == S2KSHA1 { + pk.sha1Checksum = true + } + default: + return errors.UnsupportedError("deprecated s2k function in private key") + } + + if pk.Encrypted { + blockSize := pk.cipher.blockSize() + if blockSize == 0 { + return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) + } + pk.iv = make([]byte, blockSize) + _, err = readFull(r, pk.iv) + if err != nil { + return + } + } + + var privateKeyData []byte + if v5 { + var n [4]byte /* secret material four octet count */ + _, err = readFull(r, n[:]) + if err != nil { + return + } + count := uint32(uint32(n[0])<<24 | uint32(n[1])<<16 | uint32(n[2])<<8 | uint32(n[3])) + if !pk.Encrypted { + count = count + 2 /* two octet checksum */ + } + privateKeyData = make([]byte, count) + _, err = readFull(r, privateKeyData) + if err != nil { + return + } + } else { + privateKeyData, err = ioutil.ReadAll(r) + if err != nil { + return + } + } + if !pk.Encrypted { + return pk.parsePrivateKey(privateKeyData) + } + + pk.encryptedData = privateKeyData + return +} + +// Dummy returns true if the private key is a dummy key. This is a GNU extension. +func (pk *PrivateKey) Dummy() bool { + return pk.s2kParams.Dummy() +} + +func mod64kHash(d []byte) uint16 { + var h uint16 + for _, b := range d { + h += uint16(b) + } + return h +} + +func (pk *PrivateKey) Serialize(w io.Writer) (err error) { + contents := bytes.NewBuffer(nil) + err = pk.PublicKey.serializeWithoutHeaders(contents) + if err != nil { + return + } + if _, err = contents.Write([]byte{uint8(pk.s2kType)}); err != nil { + return + } + + optional := bytes.NewBuffer(nil) + if pk.Encrypted || pk.Dummy() { + optional.Write([]byte{uint8(pk.cipher)}) + if err := pk.s2kParams.Serialize(optional); err != nil { + return err + } + if pk.Encrypted { + optional.Write(pk.iv) + } + } + if pk.Version == 5 { + contents.Write([]byte{uint8(optional.Len())}) + } + io.Copy(contents, optional) + + if !pk.Dummy() { + l := 0 + var priv []byte + if !pk.Encrypted { + buf := bytes.NewBuffer(nil) + err = pk.serializePrivateKey(buf) + if err != nil { + return err + } + l = buf.Len() + if pk.sha1Checksum { + h := sha1.New() + h.Write(buf.Bytes()) + buf.Write(h.Sum(nil)) + } else { + checksum := mod64kHash(buf.Bytes()) + buf.Write([]byte{byte(checksum >> 8), byte(checksum)}) + } + priv = buf.Bytes() + } else { + priv, l = pk.encryptedData, len(pk.encryptedData) + } + + if pk.Version == 5 { + contents.Write([]byte{byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l)}) + } + contents.Write(priv) + } + + ptype := packetTypePrivateKey + if pk.IsSubkey { + ptype = packetTypePrivateSubkey + } + err = serializeHeader(w, ptype, contents.Len()) + if err != nil { + return + } + _, err = io.Copy(w, contents) + if err != nil { + return + } + return +} + +func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { + if _, err := w.Write(new(encoding.MPI).SetBig(priv.D).EncodedBytes()); err != nil { + return err + } + if _, err := w.Write(new(encoding.MPI).SetBig(priv.Primes[1]).EncodedBytes()); err != nil { + return err + } + if _, err := w.Write(new(encoding.MPI).SetBig(priv.Primes[0]).EncodedBytes()); err != nil { + return err + } + _, err := w.Write(new(encoding.MPI).SetBig(priv.Precomputed.Qinv).EncodedBytes()) + return err +} + +func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { + _, err := w.Write(new(encoding.MPI).SetBig(priv.X).EncodedBytes()) + return err +} + +func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { + _, err := w.Write(new(encoding.MPI).SetBig(priv.X).EncodedBytes()) + return err +} + +func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { + _, err := w.Write(new(encoding.MPI).SetBig(priv.D).EncodedBytes()) + return err +} + +func serializeEdDSAPrivateKey(w io.Writer, priv *ed25519.PrivateKey) error { + keySize := ed25519.PrivateKeySize - ed25519.PublicKeySize + _, err := w.Write(encoding.NewMPI((*priv)[:keySize]).EncodedBytes()) + return err +} + +func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error { + _, err := w.Write(encoding.NewMPI(priv.D).EncodedBytes()) + return err +} + +// Decrypt decrypts an encrypted private key using a passphrase. +func (pk *PrivateKey) Decrypt(passphrase []byte) error { + if pk.Dummy() { + return errors.ErrDummyPrivateKey("dummy key found") + } + if !pk.Encrypted { + return nil + } + + key := make([]byte, pk.cipher.KeySize()) + pk.s2k(key, passphrase) + block := pk.cipher.new(key) + cfb := cipher.NewCFBDecrypter(block, pk.iv) + + data := make([]byte, len(pk.encryptedData)) + cfb.XORKeyStream(data, pk.encryptedData) + + if pk.sha1Checksum { + if len(data) < sha1.Size { + return errors.StructuralError("truncated private key data") + } + h := sha1.New() + h.Write(data[:len(data)-sha1.Size]) + sum := h.Sum(nil) + if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { + return errors.StructuralError("private key checksum failure") + } + data = data[:len(data)-sha1.Size] + } else { + if len(data) < 2 { + return errors.StructuralError("truncated private key data") + } + var sum uint16 + for i := 0; i < len(data)-2; i++ { + sum += uint16(data[i]) + } + if data[len(data)-2] != uint8(sum>>8) || + data[len(data)-1] != uint8(sum) { + return errors.StructuralError("private key checksum failure") + } + data = data[:len(data)-2] + } + + err := pk.parsePrivateKey(data) + if _, ok := err.(errors.KeyInvalidError); ok { + return errors.KeyInvalidError("invalid key parameters") + } + if err != nil { + return err + } + + // Mark key as unencrypted + pk.s2kType = S2KNON + pk.s2k = nil + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +// Encrypt encrypts an unencrypted private key using a passphrase. +func (pk *PrivateKey) Encrypt(passphrase []byte) error { + priv := bytes.NewBuffer(nil) + err := pk.serializePrivateKey(priv) + if err != nil { + return err + } + + //Default config of private key encryption + pk.cipher = CipherAES256 + s2kConfig := &s2k.Config{ + S2KMode: 3, //Iterated + S2KCount: 65536, + Hash: crypto.SHA256, + } + + pk.s2kParams, err = s2k.Generate(rand.Reader, s2kConfig) + if err != nil { + return err + } + privateKeyBytes := priv.Bytes() + key := make([]byte, pk.cipher.KeySize()) + + pk.sha1Checksum = true + pk.s2k, err = pk.s2kParams.Function() + if err != nil { + return err + } + pk.s2k(key, passphrase) + block := pk.cipher.new(key) + pk.iv = make([]byte, pk.cipher.blockSize()) + _, err = rand.Read(pk.iv) + if err != nil { + return err + } + cfb := cipher.NewCFBEncrypter(block, pk.iv) + + if pk.sha1Checksum { + pk.s2kType = S2KSHA1 + h := sha1.New() + h.Write(privateKeyBytes) + sum := h.Sum(nil) + privateKeyBytes = append(privateKeyBytes, sum...) + } else { + pk.s2kType = S2KCHECKSUM + var sum uint16 + for _, b := range privateKeyBytes { + sum += uint16(b) + } + priv.Write([]byte{uint8(sum >> 8), uint8(sum)}) + } + + pk.encryptedData = make([]byte, len(privateKeyBytes)) + cfb.XORKeyStream(pk.encryptedData, privateKeyBytes) + pk.Encrypted = true + pk.PrivateKey = nil + return err +} + +func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) { + switch priv := pk.PrivateKey.(type) { + case *rsa.PrivateKey: + err = serializeRSAPrivateKey(w, priv) + case *dsa.PrivateKey: + err = serializeDSAPrivateKey(w, priv) + case *elgamal.PrivateKey: + err = serializeElGamalPrivateKey(w, priv) + case *ecdsa.PrivateKey: + err = serializeECDSAPrivateKey(w, priv) + case *ed25519.PrivateKey: + err = serializeEdDSAPrivateKey(w, priv) + case *ecdh.PrivateKey: + err = serializeECDHPrivateKey(w, priv) + default: + err = errors.InvalidArgumentError("unknown private key type") + } + return +} + +func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { + switch pk.PublicKey.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: + return pk.parseRSAPrivateKey(data) + case PubKeyAlgoDSA: + return pk.parseDSAPrivateKey(data) + case PubKeyAlgoElGamal: + return pk.parseElGamalPrivateKey(data) + case PubKeyAlgoECDSA: + return pk.parseECDSAPrivateKey(data) + case PubKeyAlgoECDH: + return pk.parseECDHPrivateKey(data) + case PubKeyAlgoEdDSA: + return pk.parseEdDSAPrivateKey(data) + } + panic("impossible") +} + +func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { + rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) + rsaPriv := new(rsa.PrivateKey) + rsaPriv.PublicKey = *rsaPub + + buf := bytes.NewBuffer(data) + d := new(encoding.MPI) + if _, err := d.ReadFrom(buf); err != nil { + return err + } + + p := new(encoding.MPI) + if _, err := p.ReadFrom(buf); err != nil { + return err + } + + q := new(encoding.MPI) + if _, err := q.ReadFrom(buf); err != nil { + return err + } + + rsaPriv.D = new(big.Int).SetBytes(d.Bytes()) + rsaPriv.Primes = make([]*big.Int, 2) + rsaPriv.Primes[0] = new(big.Int).SetBytes(p.Bytes()) + rsaPriv.Primes[1] = new(big.Int).SetBytes(q.Bytes()) + if err := rsaPriv.Validate(); err != nil { + return errors.KeyInvalidError(err.Error()) + } + rsaPriv.Precompute() + pk.PrivateKey = rsaPriv + + return nil +} + +func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { + dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) + dsaPriv := new(dsa.PrivateKey) + dsaPriv.PublicKey = *dsaPub + + buf := bytes.NewBuffer(data) + x := new(encoding.MPI) + if _, err := x.ReadFrom(buf); err != nil { + return err + } + + dsaPriv.X = new(big.Int).SetBytes(x.Bytes()) + if err := validateDSAParameters(dsaPriv); err != nil { + return err + } + pk.PrivateKey = dsaPriv + + return nil +} + +func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { + pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) + priv := new(elgamal.PrivateKey) + priv.PublicKey = *pub + + buf := bytes.NewBuffer(data) + x := new(encoding.MPI) + if _, err := x.ReadFrom(buf); err != nil { + return err + } + + priv.X = new(big.Int).SetBytes(x.Bytes()) + if err := validateElGamalParameters(priv); err != nil { + return err + } + pk.PrivateKey = priv + + return nil +} + +func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { + ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) + ecdsaPriv := new(ecdsa.PrivateKey) + ecdsaPriv.PublicKey = *ecdsaPub + + buf := bytes.NewBuffer(data) + d := new(encoding.MPI) + if _, err := d.ReadFrom(buf); err != nil { + return err + } + + ecdsaPriv.D = new(big.Int).SetBytes(d.Bytes()) + if err := validateECDSAParameters(ecdsaPriv); err != nil { + return err + } + pk.PrivateKey = ecdsaPriv + + return nil +} + +func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) { + ecdhPub := pk.PublicKey.PublicKey.(*ecdh.PublicKey) + ecdhPriv := new(ecdh.PrivateKey) + ecdhPriv.PublicKey = *ecdhPub + + buf := bytes.NewBuffer(data) + d := new(encoding.MPI) + if _, err := d.ReadFrom(buf); err != nil { + return err + } + + ecdhPriv.D = d.Bytes() + if err := validateECDHParameters(ecdhPriv); err != nil { + return err + } + pk.PrivateKey = ecdhPriv + + return nil +} + +func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) { + eddsaPub := pk.PublicKey.PublicKey.(*ed25519.PublicKey) + eddsaPriv := make(ed25519.PrivateKey, ed25519.PrivateKeySize) + + buf := bytes.NewBuffer(data) + d := new(encoding.MPI) + if _, err := d.ReadFrom(buf); err != nil { + return err + } + + priv := d.Bytes() + copy(eddsaPriv[32-len(priv):32], priv) + copy(eddsaPriv[32:], (*eddsaPub)[:]) + if err := validateEdDSAParameters(&eddsaPriv); err != nil { + return err + } + pk.PrivateKey = &eddsaPriv + + return nil +} + +func validateECDSAParameters(priv *ecdsa.PrivateKey) error { + return validateCommonECC(priv.Curve, priv.D.Bytes(), priv.X, priv.Y) +} + +func validateECDHParameters(priv *ecdh.PrivateKey) error { + if priv.CurveType != ecc.Curve25519 { + return validateCommonECC(priv.Curve, priv.D, priv.X, priv.Y) + } + // Handle Curve25519 + Q := priv.X.Bytes()[1:] + var d [32]byte + // Copy reversed d + l := len(priv.D) + for i := 0; i < l; i++ { + d[i] = priv.D[l-i-1] + } + var expectedQ [32]byte + curve25519.ScalarBaseMult(&expectedQ, &d) + if !bytes.Equal(Q, expectedQ[:]) { + return errors.KeyInvalidError("ECDH curve25519: invalid point") + } + return nil +} + +func validateCommonECC(curve elliptic.Curve, d []byte, X, Y *big.Int) error { + // the public point should not be at infinity (0,0) + zero := new(big.Int) + if X.Cmp(zero) == 0 && Y.Cmp(zero) == 0 { + return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", curve.Params().Name)) + } + // re-derive the public point Q' = (X,Y) = dG + // to compare to declared Q in public key + expectedX, expectedY := curve.ScalarBaseMult(d) + if X.Cmp(expectedX) != 0 || Y.Cmp(expectedY) != 0 { + return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", curve.Params().Name)) + } + return nil +} + +func validateEdDSAParameters(priv *ed25519.PrivateKey) error { + // In EdDSA, the serialized public point is stored as part of private key (together with the seed), + // hence we can re-derive the key from the seed + seed := priv.Seed() + expectedPriv := ed25519.NewKeyFromSeed(seed) + if !bytes.Equal(*priv, expectedPriv) { + return errors.KeyInvalidError("eddsa: invalid point") + } + return nil +} + +func validateDSAParameters(priv *dsa.PrivateKey) error { + p := priv.P // group prime + q := priv.Q // subgroup order + g := priv.G // g has order q mod p + x := priv.X // secret + y := priv.Y // y == g**x mod p + one := big.NewInt(1) + // expect g, y >= 2 and g < p + if g.Cmp(one) <= 0 || y.Cmp(one) <= 0 || g.Cmp(p) > 0 { + return errors.KeyInvalidError("dsa: invalid group") + } + // expect p > q + if p.Cmp(q) <= 0 { + return errors.KeyInvalidError("dsa: invalid group prime") + } + // q should be large enough and divide p-1 + pSub1 := new(big.Int).Sub(p, one) + if q.BitLen() < 150 || new(big.Int).Mod(pSub1, q).Cmp(big.NewInt(0)) != 0 { + return errors.KeyInvalidError("dsa: invalid order") + } + // confirm that g has order q mod p + if !q.ProbablyPrime(32) || new(big.Int).Exp(g, q, p).Cmp(one) != 0 { + return errors.KeyInvalidError("dsa: invalid order") + } + // check y + if new(big.Int).Exp(g, x, p).Cmp(y) != 0 { + return errors.KeyInvalidError("dsa: mismatching values") + } + + return nil +} + +func validateElGamalParameters(priv *elgamal.PrivateKey) error { + p := priv.P // group prime + g := priv.G // g has order p-1 mod p + x := priv.X // secret + y := priv.Y // y == g**x mod p + one := big.NewInt(1) + // Expect g, y >= 2 and g < p + if g.Cmp(one) <= 0 || y.Cmp(one) <= 0 || g.Cmp(p) > 0 { + return errors.KeyInvalidError("elgamal: invalid group") + } + if p.BitLen() < 1024 { + return errors.KeyInvalidError("elgamal: group order too small") + } + pSub1 := new(big.Int).Sub(p, one) + if new(big.Int).Exp(g, pSub1, p).Cmp(one) != 0 { + return errors.KeyInvalidError("elgamal: invalid group") + } + // Since p-1 is not prime, g might have a smaller order that divides p-1. + // We cannot confirm the exact order of g, but we make sure it is not too small. + gExpI := new(big.Int).Set(g) + i := 1 + threshold := 2 << 17 // we want order > threshold + for i < threshold { + i++ // we check every order to make sure key validation is not easily bypassed by guessing y' + gExpI.Mod(new(big.Int).Mul(gExpI, g), p) + if gExpI.Cmp(one) == 0 { + return errors.KeyInvalidError("elgamal: order too small") + } + } + // Check y + if new(big.Int).Exp(g, x, p).Cmp(y) != 0 { + return errors.KeyInvalidError("elgamal: mismatching values") + } + + return nil +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go new file mode 100644 index 0000000..029b8f1 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go @@ -0,0 +1,12 @@ +package packet + +// Generated with `gpg --export-secret-keys "Test Key 2"` +const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec" + +// Generated by `gpg --export-secret-keys` followed by a manual extraction of +// the ElGamal subkey from the packets. +const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc" + +// pkcs1PrivKeyHex is a PKCS#1, RSA private key. +// Generated by `openssl genrsa 1024 | openssl rsa -outform DER | xxd -p` +const pkcs1PrivKeyHex = "3082025d02010002818100e98edfa1c3b35884a54d0b36a6a603b0290fa85e49e30fa23fc94fef9c6790bc4849928607aa48d809da326fb42a969d06ad756b98b9c1a90f5d4a2b6d0ac05953c97f4da3120164a21a679793ce181c906dc01d235cc085ddcdf6ea06c389b6ab8885dfd685959e693138856a68a7e5db263337ff82a088d583a897cf2d59e9020301000102818100b6d5c9eb70b02d5369b3ee5b520a14490b5bde8a317d36f7e4c74b7460141311d1e5067735f8f01d6f5908b2b96fbd881f7a1ab9a84d82753e39e19e2d36856be960d05ac9ef8e8782ea1b6d65aee28fdfe1d61451e8cff0adfe84322f12cf455028b581cf60eb9e0e140ba5d21aeba6c2634d7c65318b9a665fc01c3191ca21024100fa5e818da3705b0fa33278bb28d4b6f6050388af2d4b75ec9375dd91ccf2e7d7068086a8b82a8f6282e4fbbdb8a7f2622eb97295249d87acea7f5f816f54d347024100eecf9406d7dc49cdfb95ab1eff4064de84c7a30f64b2798936a0d2018ba9eb52e4b636f82e96c49cc63b80b675e91e40d1b2e4017d4b9adaf33ab3d9cf1c214f024100c173704ace742c082323066226a4655226819a85304c542b9dacbeacbf5d1881ee863485fcf6f59f3a604f9b42289282067447f2b13dfeed3eab7851fc81e0550240741fc41f3fc002b382eed8730e33c5d8de40256e4accee846667f536832f711ab1d4590e7db91a8a116ac5bff3be13d3f9243ff2e976662aa9b395d907f8e9c9024046a5696c9ef882363e06c9fa4e2f5b580906452befba03f4a99d0f873697ef1f851d2226ca7934b30b7c3e80cb634a67172bbbf4781735fe3e09263e2dd723e7" diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go new file mode 100644 index 0000000..28971c1 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go @@ -0,0 +1,825 @@ +// 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 packet + +import ( + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/sha1" + "crypto/sha256" + _ "crypto/sha512" + "encoding/binary" + "fmt" + "hash" + "io" + "math/big" + "strconv" + "time" + + "github.com/ProtonMail/go-crypto/openpgp/ecdh" + "github.com/ProtonMail/go-crypto/openpgp/elgamal" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" + "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" + "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" + "golang.org/x/crypto/ed25519" +) + +type kdfHashFunction byte +type kdfAlgorithm byte + +// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. +type PublicKey struct { + Version int + CreationTime time.Time + PubKeyAlgo PublicKeyAlgorithm + PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey + Fingerprint []byte + KeyId uint64 + IsSubkey bool + + // RFC 4880 fields + n, e, p, q, g, y encoding.Field + + // RFC 6637 fields + // oid contains the OID byte sequence identifying the elliptic curve used + oid encoding.Field + + // kdf stores key derivation function parameters + // used for ECDH encryption. See RFC 6637, Section 9. + kdf encoding.Field +} + +// UpgradeToV5 updates the version of the key to v5, and updates all necessary +// fields. +func (pk *PublicKey) UpgradeToV5() { + pk.Version = 5 + pk.setFingerprintAndKeyId() +} + +// signingKey provides a convenient abstraction over signature verification +// for v3 and v4 public keys. +type signingKey interface { + SerializeForHash(io.Writer) error + SerializeSignaturePrefix(io.Writer) + serializeWithoutHeaders(io.Writer) error +} + +// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. +func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { + pk := &PublicKey{ + Version: 4, + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoRSA, + PublicKey: pub, + n: new(encoding.MPI).SetBig(pub.N), + e: new(encoding.MPI).SetBig(big.NewInt(int64(pub.E))), + } + + pk.setFingerprintAndKeyId() + return pk +} + +// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. +func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { + pk := &PublicKey{ + Version: 4, + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoDSA, + PublicKey: pub, + p: new(encoding.MPI).SetBig(pub.P), + q: new(encoding.MPI).SetBig(pub.Q), + g: new(encoding.MPI).SetBig(pub.G), + y: new(encoding.MPI).SetBig(pub.Y), + } + + pk.setFingerprintAndKeyId() + return pk +} + +// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. +func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { + pk := &PublicKey{ + Version: 4, + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoElGamal, + PublicKey: pub, + p: new(encoding.MPI).SetBig(pub.P), + g: new(encoding.MPI).SetBig(pub.G), + y: new(encoding.MPI).SetBig(pub.Y), + } + + pk.setFingerprintAndKeyId() + return pk +} + +func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { + pk := &PublicKey{ + Version: 4, + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoECDSA, + PublicKey: pub, + p: encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)), + } + + curveInfo := ecc.FindByCurve(pub.Curve) + if curveInfo == nil { + panic("unknown elliptic curve") + } + pk.oid = curveInfo.Oid + pk.setFingerprintAndKeyId() + return pk +} + +func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey { + var pk *PublicKey + var curveInfo *ecc.CurveInfo + var kdf = encoding.NewOID([]byte{0x1, pub.Hash.Id(), pub.Cipher.Id()}) + if pub.CurveType == ecc.Curve25519 { + pk = &PublicKey{ + Version: 4, + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoECDH, + PublicKey: pub, + p: encoding.NewMPI(pub.X.Bytes()), + kdf: kdf, + } + curveInfo = ecc.FindByName("Curve25519") + } else { + pk = &PublicKey{ + Version: 4, + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoECDH, + PublicKey: pub, + p: encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)), + kdf: kdf, + } + curveInfo = ecc.FindByCurve(pub.Curve) + } + if curveInfo == nil { + panic("unknown elliptic curve") + } + pk.oid = curveInfo.Oid + pk.setFingerprintAndKeyId() + return pk +} + +func NewEdDSAPublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey { + curveInfo := ecc.FindByName("Ed25519") + pk := &PublicKey{ + Version: 4, + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoEdDSA, + PublicKey: pub, + oid: curveInfo.Oid, + // Native point format, see draft-koch-eddsa-for-openpgp-04, Appendix B + p: encoding.NewMPI(append([]byte{0x40}, *pub...)), + } + + pk.setFingerprintAndKeyId() + return pk +} + +func (pk *PublicKey) parse(r io.Reader) (err error) { + // RFC 4880, section 5.5.2 + var buf [6]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != 4 && buf[0] != 5 { + return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0]))) + } + + pk.Version = int(buf[0]) + if pk.Version == 5 { + var n [4]byte + _, err = readFull(r, n[:]) + if err != nil { + return + } + } + pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) + pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + err = pk.parseRSA(r) + case PubKeyAlgoDSA: + err = pk.parseDSA(r) + case PubKeyAlgoElGamal: + err = pk.parseElGamal(r) + case PubKeyAlgoECDSA: + err = pk.parseECDSA(r) + case PubKeyAlgoECDH: + err = pk.parseECDH(r) + case PubKeyAlgoEdDSA: + err = pk.parseEdDSA(r) + default: + err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) + } + if err != nil { + return + } + + pk.setFingerprintAndKeyId() + return +} + +func (pk *PublicKey) setFingerprintAndKeyId() { + // RFC 4880, section 12.2 + if pk.Version == 5 { + fingerprint := sha256.New() + pk.SerializeForHash(fingerprint) + pk.Fingerprint = make([]byte, 32) + copy(pk.Fingerprint, fingerprint.Sum(nil)) + pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8]) + } else { + fingerprint := sha1.New() + pk.SerializeForHash(fingerprint) + pk.Fingerprint = make([]byte, 20) + copy(pk.Fingerprint, fingerprint.Sum(nil)) + pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) + } +} + +// parseRSA parses RSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKey) parseRSA(r io.Reader) (err error) { + pk.n = new(encoding.MPI) + if _, err = pk.n.ReadFrom(r); err != nil { + return + } + pk.e = new(encoding.MPI) + if _, err = pk.e.ReadFrom(r); err != nil { + return + } + + if len(pk.e.Bytes()) > 3 { + err = errors.UnsupportedError("large public exponent") + return + } + rsa := &rsa.PublicKey{ + N: new(big.Int).SetBytes(pk.n.Bytes()), + E: 0, + } + for i := 0; i < len(pk.e.Bytes()); i++ { + rsa.E <<= 8 + rsa.E |= int(pk.e.Bytes()[i]) + } + pk.PublicKey = rsa + return +} + +// parseDSA parses DSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKey) parseDSA(r io.Reader) (err error) { + pk.p = new(encoding.MPI) + if _, err = pk.p.ReadFrom(r); err != nil { + return + } + pk.q = new(encoding.MPI) + if _, err = pk.q.ReadFrom(r); err != nil { + return + } + pk.g = new(encoding.MPI) + if _, err = pk.g.ReadFrom(r); err != nil { + return + } + pk.y = new(encoding.MPI) + if _, err = pk.y.ReadFrom(r); err != nil { + return + } + + dsa := new(dsa.PublicKey) + dsa.P = new(big.Int).SetBytes(pk.p.Bytes()) + dsa.Q = new(big.Int).SetBytes(pk.q.Bytes()) + dsa.G = new(big.Int).SetBytes(pk.g.Bytes()) + dsa.Y = new(big.Int).SetBytes(pk.y.Bytes()) + pk.PublicKey = dsa + return +} + +// parseElGamal parses ElGamal public key material from the given Reader. See +// RFC 4880, section 5.5.2. +func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { + pk.p = new(encoding.MPI) + if _, err = pk.p.ReadFrom(r); err != nil { + return + } + pk.g = new(encoding.MPI) + if _, err = pk.g.ReadFrom(r); err != nil { + return + } + pk.y = new(encoding.MPI) + if _, err = pk.y.ReadFrom(r); err != nil { + return + } + + elgamal := new(elgamal.PublicKey) + elgamal.P = new(big.Int).SetBytes(pk.p.Bytes()) + elgamal.G = new(big.Int).SetBytes(pk.g.Bytes()) + elgamal.Y = new(big.Int).SetBytes(pk.y.Bytes()) + pk.PublicKey = elgamal + return +} + +// parseECDSA parses ECDSA public key material from the given Reader. See +// RFC 6637, Section 9. +func (pk *PublicKey) parseECDSA(r io.Reader) (err error) { + pk.oid = new(encoding.OID) + if _, err = pk.oid.ReadFrom(r); err != nil { + return + } + pk.p = new(encoding.MPI) + if _, err = pk.p.ReadFrom(r); err != nil { + return + } + + var c elliptic.Curve + curveInfo := ecc.FindByOid(pk.oid) + if curveInfo == nil || curveInfo.SigAlgorithm != ecc.ECDSA { + return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) + } + c = curveInfo.Curve + x, y := elliptic.Unmarshal(c, pk.p.Bytes()) + if x == nil { + return errors.UnsupportedError("failed to parse EC point") + } + pk.PublicKey = &ecdsa.PublicKey{Curve: c, X: x, Y: y} + return +} + +// parseECDH parses ECDH public key material from the given Reader. See +// RFC 6637, Section 9. +func (pk *PublicKey) parseECDH(r io.Reader) (err error) { + pk.oid = new(encoding.OID) + if _, err = pk.oid.ReadFrom(r); err != nil { + return + } + pk.p = new(encoding.MPI) + if _, err = pk.p.ReadFrom(r); err != nil { + return + } + pk.kdf = new(encoding.OID) + if _, err = pk.kdf.ReadFrom(r); err != nil { + return + } + + curveInfo := ecc.FindByOid(pk.oid) + if curveInfo == nil { + return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) + } + + c := curveInfo.Curve + cType := curveInfo.CurveType + + var x, y *big.Int + if cType == ecc.Curve25519 { + x = new(big.Int) + x.SetBytes(pk.p.Bytes()) + } else { + x, y = elliptic.Unmarshal(c, pk.p.Bytes()) + } + if x == nil { + return errors.UnsupportedError("failed to parse EC point") + } + + if kdfLen := len(pk.kdf.Bytes()); kdfLen < 3 { + return errors.UnsupportedError("unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) + } + if reserved := pk.kdf.Bytes()[0]; reserved != 0x01 { + return errors.UnsupportedError("unsupported KDF reserved field: " + strconv.Itoa(int(reserved))) + } + kdfHash, ok := algorithm.HashById[pk.kdf.Bytes()[1]] + if !ok { + return errors.UnsupportedError("unsupported ECDH KDF hash: " + strconv.Itoa(int(pk.kdf.Bytes()[1]))) + } + kdfCipher, ok := algorithm.CipherById[pk.kdf.Bytes()[2]] + if !ok { + return errors.UnsupportedError("unsupported ECDH KDF cipher: " + strconv.Itoa(int(pk.kdf.Bytes()[2]))) + } + + pk.PublicKey = &ecdh.PublicKey{ + CurveType: cType, + Curve: c, + X: x, + Y: y, + KDF: ecdh.KDF{ + Hash: kdfHash, + Cipher: kdfCipher, + }, + } + return +} + +func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) { + pk.oid = new(encoding.OID) + if _, err = pk.oid.ReadFrom(r); err != nil { + return + } + curveInfo := ecc.FindByOid(pk.oid) + if curveInfo == nil || curveInfo.SigAlgorithm != ecc.EdDSA { + return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) + } + pk.p = new(encoding.MPI) + if _, err = pk.p.ReadFrom(r); err != nil { + return + } + + eddsa := make(ed25519.PublicKey, ed25519.PublicKeySize) + switch flag := pk.p.Bytes()[0]; flag { + case 0x04: + // TODO: see _grcy_ecc_eddsa_ensure_compact in grcypt + return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag))) + case 0x40: + copy(eddsa[:], pk.p.Bytes()[1:]) + default: + return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag))) + } + + pk.PublicKey = &eddsa + return +} + +// SerializeForHash serializes the PublicKey to w with the special packet +// header format needed for hashing. +func (pk *PublicKey) SerializeForHash(w io.Writer) error { + pk.SerializeSignaturePrefix(w) + return pk.serializeWithoutHeaders(w) +} + +// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. +// The prefix is used when calculating a signature over this public key. See +// RFC 4880, section 5.2.4. +func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) { + var pLength = pk.algorithmSpecificByteCount() + if pk.Version == 5 { + pLength += 10 // version, timestamp (4), algorithm, key octet count (4). + w.Write([]byte{ + 0x9A, + byte(pLength >> 24), + byte(pLength >> 16), + byte(pLength >> 8), + byte(pLength), + }) + return + } + pLength += 6 + w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) +} + +func (pk *PublicKey) Serialize(w io.Writer) (err error) { + length := 6 // 6 byte header + length += pk.algorithmSpecificByteCount() + if pk.Version == 5 { + length += 4 // octet key count + } + packetType := packetTypePublicKey + if pk.IsSubkey { + packetType = packetTypePublicSubkey + } + err = serializeHeader(w, packetType, length) + if err != nil { + return + } + return pk.serializeWithoutHeaders(w) +} + +func (pk *PublicKey) algorithmSpecificByteCount() int { + length := 0 + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + length += int(pk.n.EncodedLength()) + length += int(pk.e.EncodedLength()) + case PubKeyAlgoDSA: + length += int(pk.p.EncodedLength()) + length += int(pk.q.EncodedLength()) + length += int(pk.g.EncodedLength()) + length += int(pk.y.EncodedLength()) + case PubKeyAlgoElGamal: + length += int(pk.p.EncodedLength()) + length += int(pk.g.EncodedLength()) + length += int(pk.y.EncodedLength()) + case PubKeyAlgoECDSA: + length += int(pk.oid.EncodedLength()) + length += int(pk.p.EncodedLength()) + case PubKeyAlgoECDH: + length += int(pk.oid.EncodedLength()) + length += int(pk.p.EncodedLength()) + length += int(pk.kdf.EncodedLength()) + case PubKeyAlgoEdDSA: + length += int(pk.oid.EncodedLength()) + length += int(pk.p.EncodedLength()) + default: + panic("unknown public key algorithm") + } + return length +} + +// serializeWithoutHeaders marshals the PublicKey to w in the form of an +// OpenPGP public key packet, not including the packet header. +func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { + t := uint32(pk.CreationTime.Unix()) + if _, err = w.Write([]byte{ + byte(pk.Version), + byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t), + byte(pk.PubKeyAlgo), + }); err != nil { + return + } + + if pk.Version == 5 { + n := pk.algorithmSpecificByteCount() + if _, err = w.Write([]byte{ + byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n), + }); err != nil { + return + } + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + if _, err = w.Write(pk.n.EncodedBytes()); err != nil { + return + } + _, err = w.Write(pk.e.EncodedBytes()) + return + case PubKeyAlgoDSA: + if _, err = w.Write(pk.p.EncodedBytes()); err != nil { + return + } + if _, err = w.Write(pk.q.EncodedBytes()); err != nil { + return + } + if _, err = w.Write(pk.g.EncodedBytes()); err != nil { + return + } + _, err = w.Write(pk.y.EncodedBytes()) + return + case PubKeyAlgoElGamal: + if _, err = w.Write(pk.p.EncodedBytes()); err != nil { + return + } + if _, err = w.Write(pk.g.EncodedBytes()); err != nil { + return + } + _, err = w.Write(pk.y.EncodedBytes()) + return + case PubKeyAlgoECDSA: + if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { + return + } + _, err = w.Write(pk.p.EncodedBytes()) + return + case PubKeyAlgoECDH: + if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { + return + } + if _, err = w.Write(pk.p.EncodedBytes()); err != nil { + return + } + _, err = w.Write(pk.kdf.EncodedBytes()) + return + case PubKeyAlgoEdDSA: + if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { + return + } + _, err = w.Write(pk.p.EncodedBytes()) + return + } + return errors.InvalidArgumentError("bad public-key algorithm") +} + +// CanSign returns true iff this public key can generate signatures +func (pk *PublicKey) CanSign() bool { + return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH +} + +// VerifySignature returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) { + sig.AddMetadataToHashSuffix() + } + signed.Write(sig.HashSuffix) + hashBytes := signed.Sum(nil) + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) + err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.Bytes())) + if err != nil { + return errors.SignatureError("RSA verification failure") + } + return nil + case PubKeyAlgoDSA: + dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 + if len(hashBytes) > subgroupSize { + hashBytes = hashBytes[:subgroupSize] + } + if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.Bytes()), new(big.Int).SetBytes(sig.DSASigS.Bytes())) { + return errors.SignatureError("DSA verification failure") + } + return nil + case PubKeyAlgoECDSA: + ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) + if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.Bytes()), new(big.Int).SetBytes(sig.ECDSASigS.Bytes())) { + return errors.SignatureError("ECDSA verification failure") + } + return nil + case PubKeyAlgoEdDSA: + eddsaPublicKey := pk.PublicKey.(*ed25519.PublicKey) + + sigR := sig.EdDSASigR.Bytes() + sigS := sig.EdDSASigS.Bytes() + + eddsaSig := make([]byte, ed25519.SignatureSize) + copy(eddsaSig[32-len(sigR):32], sigR) + copy(eddsaSig[64-len(sigS):], sigS) + + if !ed25519.Verify(*eddsaPublicKey, hashBytes, eddsaSig) { + return errors.SignatureError("EdDSA verification failure") + } + return nil + default: + return errors.SignatureError("Unsupported public key algorithm used in signature") + } +} + +// keySignatureHash returns a Hash of the message that needs to be signed for +// pk to assert a subkey relationship to signed. +func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + err = pk.SerializeForHash(h) + if err != nil { + return nil, err + } + + err = signed.SerializeForHash(h) + return +} + +// VerifyKeySignature returns nil iff sig is a valid signature, made by this +// public key, of signed. +func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { + h, err := keySignatureHash(pk, signed, sig.Hash) + if err != nil { + return err + } + if err = pk.VerifySignature(h, sig); err != nil { + return err + } + + if sig.FlagSign { + // Signing subkeys must be cross-signed. See + // https://www.gnupg.org/faq/subkey-cross-certify.html. + if sig.EmbeddedSignature == nil { + return errors.StructuralError("signing subkey is missing cross-signature") + } + // Verify the cross-signature. This is calculated over the same + // data as the main signature, so we cannot just recursively + // call signed.VerifyKeySignature(...) + if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { + return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) + } + if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { + return errors.StructuralError("error while verifying cross-signature: " + err.Error()) + } + } + + return nil +} + +func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + err = pk.SerializeForHash(h) + + return +} + +// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this +// public key. +func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { + h, err := keyRevocationHash(pk, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature, +// made by the passed in signingKey. +func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signingKey *PublicKey) (err error) { + h, err := keyRevocationHash(pk, sig.Hash) + if err != nil { + return err + } + return signingKey.VerifySignature(h, sig) +} + +// userIdSignatureHash returns a Hash of the message that needs to be signed +// to assert that pk is a valid key for id. +func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + var buf [5]byte + buf[0] = 0xb4 + buf[1] = byte(len(id) >> 24) + buf[2] = byte(len(id) >> 16) + buf[3] = byte(len(id) >> 8) + buf[4] = byte(len(id)) + h.Write(buf[:]) + h.Write([]byte(id)) + + return +} + +// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { + h, err := userIdSignatureHash(id, pub, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +// KeyIdString returns the public key's fingerprint in capital hex +// (e.g. "6C7EE1B8621CC013"). +func (pk *PublicKey) KeyIdString() string { + return fmt.Sprintf("%X", pk.Fingerprint[12:20]) +} + +// KeyIdShortString returns the short form of public key's fingerprint +// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). +func (pk *PublicKey) KeyIdShortString() string { + return fmt.Sprintf("%X", pk.Fingerprint[16:20]) +} + +// BitLength returns the bit length for the given public key. +func (pk *PublicKey) BitLength() (bitLength uint16, err error) { + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + bitLength = pk.n.BitLength() + case PubKeyAlgoDSA: + bitLength = pk.p.BitLength() + case PubKeyAlgoElGamal: + bitLength = pk.p.BitLength() + case PubKeyAlgoECDSA: + bitLength = pk.p.BitLength() + case PubKeyAlgoECDH: + bitLength = pk.p.BitLength() + case PubKeyAlgoEdDSA: + bitLength = pk.p.BitLength() + default: + err = errors.InvalidArgumentError("bad public-key algorithm") + } + return +} + +// KeyExpired returns whether sig is a self-signature of a key that has +// expired or is created in the future. +func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool { + if pk.CreationTime.After(currentTime) { + return true + } + if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 { + return false + } + expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) + return currentTime.After(expiry) +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go new file mode 100644 index 0000000..b255f1f --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go @@ -0,0 +1,24 @@ +package packet + +const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb" + +const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001" + +const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed" + +const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0" + +const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b" + +const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4" + +const ecdhFingerprintHex = "722354df2475a42164d1d49faa8b938f9a201946" + +const ecdhPkDataHex = "b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec91803010909" + +const eddsaFingerprintHex = "b2d5e5ec0e6deca6bc8eeeb00907e75e1dd99ad8" + +const eddsaPkDataHex = "98330456e2132b16092b06010401da470f01010740bbda39266affa511a8c2d02edf690fb784b0499c4406185811a163539ef11dc1b41d74657374696e67203c74657374696e674074657374696e672e636f6d3e8879041316080021050256e2132b021b03050b09080702061508090a0b020416020301021e01021780000a09100907e75e1dd99ad86d0c00fe39d2008359352782bc9b61ac382584cd8eff3f57a18c2287e3afeeb05d1f04ba00fe2d0bc1ddf3ff8adb9afa3e7d9287244b4ec567f3db4d60b74a9b5465ed528203" + +// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key +const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267` diff --git a/vendor/golang.org/x/crypto/openpgp/packet/reader.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go similarity index 94% rename from vendor/golang.org/x/crypto/openpgp/packet/reader.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go index 34bc7c6..94ae9ad 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/reader.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go @@ -5,8 +5,9 @@ package packet import ( - "golang.org/x/crypto/openpgp/errors" "io" + + "github.com/ProtonMail/go-crypto/openpgp/errors" ) // Reader reads packets from an io.Reader and allows packets to be 'unread' so @@ -42,6 +43,7 @@ func (r *Reader) Next() (p Packet, err error) { r.readers = r.readers[:len(r.readers)-1] continue } + // TODO: Add strict mode that rejects unknown packets, instead of ignoring them. if _, ok := err.(errors.UnknownPacketTypeError); !ok { return nil, err } diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go similarity index 62% rename from vendor/golang.org/x/crypto/openpgp/packet/signature.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go index b2a24a5..4662ec3 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/signature.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go @@ -17,8 +17,9 @@ import ( "strconv" "time" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/s2k" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" + "github.com/ProtonMail/go-crypto/openpgp/s2k" ) const ( @@ -31,6 +32,7 @@ const ( // Signature represents a signature. See RFC 4880, section 5.2. type Signature struct { + Version int SigType SignatureType PubKeyAlgo PublicKeyAlgorithm Hash crypto.Hash @@ -39,12 +41,19 @@ type Signature struct { HashSuffix []byte // HashTag contains the first two bytes of the hash for fast rejection // of bad signed data. - HashTag [2]byte + HashTag [2]byte + + // Metadata includes format, filename and time, and is protected by v5 + // signatures of type 0x00 or 0x01. This metadata is included into the hash + // computation; if nil, six 0x00 bytes are used instead. See section 5.2.4. + Metadata *LiteralData + CreationTime time.Time - RSASignature parsedMPI - DSASigR, DSASigS parsedMPI - ECDSASigR, ECDSASigS parsedMPI + RSASignature encoding.Field + DSASigR, DSASigS encoding.Field + ECDSASigR, ECDSASigS encoding.Field + EdDSASigR, EdDSASigS encoding.Field // rawSubpackets contains the unparsed subpackets, in order. rawSubpackets []outputSubpacket @@ -54,9 +63,16 @@ type Signature struct { SigLifetimeSecs, KeyLifetimeSecs *uint32 PreferredSymmetric, PreferredHash, PreferredCompression []uint8 + PreferredAEAD []uint8 IssuerKeyId *uint64 + IssuerFingerprint []byte IsPrimaryId *bool + // PolicyURI can be set to the URI of a document that describes the + // policy under which the signature was issued. See RFC 4880, section + // 5.2.3.20 for details. + PolicyURI string + // FlagsValid is set if any flags were given. See RFC 4880, section // 5.2.3.21 for details. FlagsValid bool @@ -67,9 +83,10 @@ type Signature struct { RevocationReason *uint8 RevocationReasonText string - // MDC is set if this signature has a feature packet that indicates - // support for MDC subpackets. - MDC bool + // In a self-signature, these flags are set there is a features subpacket + // indicating that the issuer implementation supports these features + // (section 5.2.5.25). + MDC, AEAD, V5Keys bool // EmbeddedSignature, if non-nil, is a signature of the parent key, by // this key. This prevents an attacker from claiming another's signing @@ -86,11 +103,11 @@ func (sig *Signature) parse(r io.Reader) (err error) { if err != nil { return } - if buf[0] != 4 { + if buf[0] != 4 && buf[0] != 5 { err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) return } - + sig.Version = int(buf[0]) _, err = readFull(r, buf[:5]) if err != nil { return @@ -98,7 +115,7 @@ func (sig *Signature) parse(r io.Reader) (err error) { sig.SigType = SignatureType(buf[0]) sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA: default: err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) return @@ -111,24 +128,12 @@ func (sig *Signature) parse(r io.Reader) (err error) { } hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) - l := 6 + hashedSubpacketsLength - sig.HashSuffix = make([]byte, l+6) - sig.HashSuffix[0] = 4 - copy(sig.HashSuffix[1:], buf[:5]) - hashedSubpackets := sig.HashSuffix[6:l] + hashedSubpackets := make([]byte, hashedSubpacketsLength) _, err = readFull(r, hashedSubpackets) if err != nil { return } - // See RFC 4880, section 5.2.4 - trailer := sig.HashSuffix[l:] - trailer[0] = 4 - trailer[1] = 0xff - trailer[2] = uint8(l >> 24) - trailer[3] = uint8(l >> 16) - trailer[4] = uint8(l >> 8) - trailer[5] = uint8(l) - + sig.buildHashSuffix(hashedSubpackets) err = parseSignatureSubpackets(sig, hashedSubpackets, true) if err != nil { return @@ -156,16 +161,33 @@ func (sig *Signature) parse(r io.Reader) (err error) { switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) + sig.RSASignature = new(encoding.MPI) + _, err = sig.RSASignature.ReadFrom(r) case PubKeyAlgoDSA: - sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) - if err == nil { - sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) + sig.DSASigR = new(encoding.MPI) + if _, err = sig.DSASigR.ReadFrom(r); err != nil { + return } + + sig.DSASigS = new(encoding.MPI) + _, err = sig.DSASigS.ReadFrom(r) case PubKeyAlgoECDSA: - sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) - if err == nil { - sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) + sig.ECDSASigR = new(encoding.MPI) + if _, err = sig.ECDSASigR.ReadFrom(r); err != nil { + return + } + + sig.ECDSASigS = new(encoding.MPI) + _, err = sig.ECDSASigS.ReadFrom(r) + case PubKeyAlgoEdDSA: + sig.EdDSASigR = new(encoding.MPI) + if _, err = sig.EdDSASigR.ReadFrom(r); err != nil { + return + } + + sig.EdDSASigS = new(encoding.MPI) + if _, err = sig.EdDSASigS.ReadFrom(r); err != nil { + return } default: panic("unreachable") @@ -201,10 +223,13 @@ const ( prefHashAlgosSubpacket signatureSubpacketType = 21 prefCompressionSubpacket signatureSubpacketType = 22 primaryUserIdSubpacket signatureSubpacketType = 25 + policyUriSubpacket signatureSubpacketType = 26 keyFlagsSubpacket signatureSubpacketType = 27 reasonForRevocationSubpacket signatureSubpacketType = 29 featuresSubpacket signatureSubpacketType = 30 embeddedSignatureSubpacket signatureSubpacketType = 32 + issuerFingerprintSubpacket signatureSubpacketType = 33 + prefAeadAlgosSubpacket signatureSubpacketType = 34 ) // parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. @@ -290,6 +315,9 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r sig.PreferredSymmetric = make([]byte, len(subpacket)) copy(sig.PreferredSymmetric, subpacket) case issuerSubpacket: + if sig.Version > 4 { + err = errors.StructuralError("issuer subpacket found in v5 key") + } // Issuer, section 5.2.3.5 if len(subpacket) != 8 { err = errors.StructuralError("issuer subpacket with bad length") @@ -361,9 +389,21 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r case featuresSubpacket: // Features subpacket, section 5.2.3.24 specifies a very general // mechanism for OpenPGP implementations to signal support for new - // features. In practice, the subpacket is used exclusively to - // indicate support for MDC-protected encryption. - sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 + // features. + if !isHashed { + return + } + if len(subpacket) > 0 { + if subpacket[0]&0x01 != 0 { + sig.MDC = true + } + if subpacket[0]&0x02 != 0 { + sig.AEAD = true + } + if subpacket[0]&0x04 != 0 { + sig.V5Keys = true + } + } case embeddedSignatureSubpacket: // Only usage is in signatures that cross-certify // signing subkeys. section 5.2.3.26 describes the @@ -382,6 +422,32 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) } + case policyUriSubpacket: + // Policy URI, section 5.2.3.20 + if !isHashed { + return + } + sig.PolicyURI = string(subpacket) + case issuerFingerprintSubpacket: + v, l := subpacket[0], len(subpacket[1:]) + if v == 5 && l != 32 || v != 5 && l != 20 { + return nil, errors.StructuralError("bad fingerprint length") + } + sig.IssuerFingerprint = make([]byte, l) + copy(sig.IssuerFingerprint, subpacket[1:]) + sig.IssuerKeyId = new(uint64) + if v == 5 { + *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[1:9]) + } else { + *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[13:21]) + } + case prefAeadAlgosSubpacket: + // Preferred symmetric algorithms, section 5.2.3.8 + if !isHashed { + return + } + sig.PreferredAEAD = make([]byte, len(subpacket)) + copy(sig.PreferredAEAD, subpacket) default: if isCritical { err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) @@ -406,6 +472,13 @@ func subpacketLengthLength(length int) int { return 5 } +func (sig *Signature) CheckKeyIdOrFingerprint(pk *PublicKey) bool { + if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) >= 20 { + return bytes.Equal(sig.IssuerFingerprint, pk.Fingerprint) + } + return sig.IssuerKeyId != nil && *sig.IssuerKeyId == pk.KeyId +} + // serializeSubpacketLength marshals the given length into to. func serializeSubpacketLength(to []byte, length int) int { // RFC 4880, Section 4.2.2. @@ -446,6 +519,9 @@ func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { if subpacket.hashed == hashed { n := serializeSubpacketLength(to, len(subpacket.contents)+1) to[n] = byte(subpacket.subpacketType) + if subpacket.isCritical { + to[n] |= 0x80 + } to = to[1+n:] n = copy(to, subpacket.contents) to = to[n:] @@ -454,49 +530,66 @@ func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { return } -// KeyExpired returns whether sig is a self-signature of a key that has -// expired. -func (sig *Signature) KeyExpired(currentTime time.Time) bool { - if sig.KeyLifetimeSecs == nil { +// SigExpired returns whether sig is a signature that has expired or is created +// in the future. +func (sig *Signature) SigExpired(currentTime time.Time) bool { + if sig.CreationTime.After(currentTime) { + return true + } + if sig.SigLifetimeSecs == nil || *sig.SigLifetimeSecs == 0 { return false } - expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) + expiry := sig.CreationTime.Add(time.Duration(*sig.SigLifetimeSecs) * time.Second) return currentTime.After(expiry) } // buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. -func (sig *Signature) buildHashSuffix() (err error) { - hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) - - var ok bool - l := 6 + hashedSubpacketsLen - sig.HashSuffix = make([]byte, l+6) - sig.HashSuffix[0] = 4 - sig.HashSuffix[1] = uint8(sig.SigType) - sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) - sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) +func (sig *Signature) buildHashSuffix(hashedSubpackets []byte) (err error) { + hash, ok := s2k.HashToHashId(sig.Hash) if !ok { sig.HashSuffix = nil return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) } - sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) - sig.HashSuffix[5] = byte(hashedSubpacketsLen) - serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) - trailer := sig.HashSuffix[l:] - trailer[0] = 4 - trailer[1] = 0xff - trailer[2] = byte(l >> 24) - trailer[3] = byte(l >> 16) - trailer[4] = byte(l >> 8) - trailer[5] = byte(l) + + hashedFields := bytes.NewBuffer([]byte{ + uint8(sig.Version), + uint8(sig.SigType), + uint8(sig.PubKeyAlgo), + uint8(hash), + uint8(len(hashedSubpackets) >> 8), + uint8(len(hashedSubpackets)), + }) + hashedFields.Write(hashedSubpackets) + + var l uint64 = uint64(6 + len(hashedSubpackets)) + if sig.Version == 5 { + hashedFields.Write([]byte{0x05, 0xff}) + hashedFields.Write([]byte{ + uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32), + uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l), + }) + } else { + hashedFields.Write([]byte{0x04, 0xff}) + hashedFields.Write([]byte{ + uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l), + }) + } + sig.HashSuffix = make([]byte, hashedFields.Len()) + copy(sig.HashSuffix, hashedFields.Bytes()) return } func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { - err = sig.buildHashSuffix() + hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) + hashedSubpackets := make([]byte, hashedSubpacketsLen) + serializeSubpackets(hashedSubpackets, sig.outSubpackets, true) + err = sig.buildHashSuffix(hashedSubpackets) if err != nil { return } + if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) { + sig.AddMetadataToHashSuffix() + } h.Write(sig.HashSuffix) digest = h.Sum(nil) @@ -509,17 +602,26 @@ func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { // On success, the signature is stored in sig. Call Serialize to write it out. // If config is nil, sensible defaults will be used. func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { - sig.outSubpackets = sig.buildSubpackets() + if priv.Dummy() { + return errors.ErrDummyPrivateKey("dummy key found") + } + sig.Version = priv.PublicKey.Version + sig.IssuerFingerprint = priv.PublicKey.Fingerprint + sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey) + if err != nil { + return err + } digest, err := sig.signPrepareHash(h) if err != nil { return } - switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: // supports both *rsa.PrivateKey and crypto.Signer - sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) - sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) + sigdata, err := priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) + if err == nil { + sig.RSASignature = encoding.NewMPI(sigdata) + } case PubKeyAlgoDSA: dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) @@ -530,10 +632,8 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e } r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) if err == nil { - sig.DSASigR.bytes = r.Bytes() - sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) - sig.DSASigS.bytes = s.Bytes() - sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) + sig.DSASigR = new(encoding.MPI).SetBig(r) + sig.DSASigS = new(encoding.MPI).SetBig(s) } case PubKeyAlgoECDSA: var r, s *big.Int @@ -548,8 +648,14 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e } } if err == nil { - sig.ECDSASigR = fromBig(r) - sig.ECDSASigS = fromBig(s) + sig.ECDSASigR = new(encoding.MPI).SetBig(r) + sig.ECDSASigS = new(encoding.MPI).SetBig(s) + } + case PubKeyAlgoEdDSA: + sigdata, err := priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, crypto.Hash(0)) + if err == nil { + sig.EdDSASigR = encoding.NewMPI(sigdata[:32]) + sig.EdDSASigS = encoding.NewMPI(sigdata[32:]) } default: err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) @@ -576,6 +682,9 @@ func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { // Serialize to write it out. // If config is nil, sensible defaults will be used. func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { + if priv.Dummy() { + return errors.ErrDummyPrivateKey("dummy key found") + } h, err := userIdSignatureHash(id, pub, sig.Hash) if err != nil { return err @@ -583,10 +692,25 @@ func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, co return sig.Sign(h, priv, config) } +// CrossSignKey computes a signature from signingKey on pub hashed using hashKey. On success, +// the signature is stored in sig. Call Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) CrossSignKey(pub *PublicKey, hashKey *PublicKey, signingKey *PrivateKey, + config *Config) error { + h, err := keySignatureHash(hashKey, pub, sig.Hash) + if err != nil { + return err + } + return sig.Sign(h, signingKey, config) +} + // SignKey computes a signature from priv, asserting that pub is a subkey. On // success, the signature is stored in sig. Call Serialize to write it out. // If config is nil, sensible defaults will be used. func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { + if priv.Dummy() { + return errors.ErrDummyPrivateKey("dummy key found") + } h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) if err != nil { return err @@ -594,26 +718,40 @@ func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) return sig.Sign(h, priv, config) } +// RevokeKey computes a revocation signature of pub using priv. On success, the signature is +// stored in sig. Call Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) RevokeKey(pub *PublicKey, priv *PrivateKey, config *Config) error { + h, err := keyRevocationHash(pub, sig.Hash) + if err != nil { + return err + } + return sig.Sign(h, priv, config) +} + // Serialize marshals sig to w. Sign, SignUserId or SignKey must have been // called first. func (sig *Signature) Serialize(w io.Writer) (err error) { if len(sig.outSubpackets) == 0 { sig.outSubpackets = sig.rawSubpackets } - if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { + if sig.RSASignature == nil && sig.DSASigR == nil && sig.ECDSASigR == nil && sig.EdDSASigR == nil { return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") } sigLength := 0 switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sigLength = 2 + len(sig.RSASignature.bytes) + sigLength = int(sig.RSASignature.EncodedLength()) case PubKeyAlgoDSA: - sigLength = 2 + len(sig.DSASigR.bytes) - sigLength += 2 + len(sig.DSASigS.bytes) + sigLength = int(sig.DSASigR.EncodedLength()) + sigLength += int(sig.DSASigS.EncodedLength()) case PubKeyAlgoECDSA: - sigLength = 2 + len(sig.ECDSASigR.bytes) - sigLength += 2 + len(sig.ECDSASigS.bytes) + sigLength = int(sig.ECDSASigR.EncodedLength()) + sigLength += int(sig.ECDSASigS.EncodedLength()) + case PubKeyAlgoEdDSA: + sigLength = int(sig.EdDSASigR.EncodedLength()) + sigLength += int(sig.EdDSASigS.EncodedLength()) default: panic("impossible") } @@ -622,16 +760,29 @@ func (sig *Signature) Serialize(w io.Writer) (err error) { length := len(sig.HashSuffix) - 6 /* trailer not included */ + 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + 2 /* hash tag */ + sigLength + if sig.Version == 5 { + length -= 4 // eight-octet instead of four-octet big endian + } err = serializeHeader(w, packetTypeSignature, length) if err != nil { return } + err = sig.serializeBody(w) + if err != nil { + return err + } + return +} - _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) +func (sig *Signature) serializeBody(w io.Writer) (err error) { + hashedSubpacketsLen := uint16(uint16(sig.HashSuffix[4])<<8) | uint16(sig.HashSuffix[5]) + fields := sig.HashSuffix[:6+hashedSubpacketsLen] + _, err = w.Write(fields) if err != nil { return } + unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) unhashedSubpackets[1] = byte(unhashedSubpacketsLen) @@ -648,11 +799,22 @@ func (sig *Signature) Serialize(w io.Writer) (err error) { switch sig.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - err = writeMPIs(w, sig.RSASignature) + _, err = w.Write(sig.RSASignature.EncodedBytes()) case PubKeyAlgoDSA: - err = writeMPIs(w, sig.DSASigR, sig.DSASigS) + if _, err = w.Write(sig.DSASigR.EncodedBytes()); err != nil { + return + } + _, err = w.Write(sig.DSASigS.EncodedBytes()) case PubKeyAlgoECDSA: - err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) + if _, err = w.Write(sig.ECDSASigR.EncodedBytes()); err != nil { + return + } + _, err = w.Write(sig.ECDSASigS.EncodedBytes()) + case PubKeyAlgoEdDSA: + if _, err = w.Write(sig.EdDSASigR.EncodedBytes()); err != nil { + return + } + _, err = w.Write(sig.EdDSASigS.EncodedBytes()) default: panic("impossible") } @@ -667,17 +829,20 @@ type outputSubpacket struct { contents []byte } -func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { +func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubpacket, err error) { creationTime := make([]byte, 4) binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) - if sig.IssuerKeyId != nil { + if sig.IssuerKeyId != nil && sig.Version == 4 { keyId := make([]byte, 8) binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) - subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) + subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, true, keyId}) + } + if sig.IssuerFingerprint != nil { + contents := append([]uint8{uint8(issuer.Version)}, sig.IssuerFingerprint...) + subpackets = append(subpackets, outputSubpacket{true, issuerFingerprintSubpacket, true, contents}) } - if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { sigLifetime := make([]byte, 4) binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) @@ -703,7 +868,22 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) } - // The following subpackets may only appear in self-signatures + // The following subpackets may only appear in self-signatures. + + var features = byte(0x00) + if sig.MDC { + features |= 0x01 + } + if sig.AEAD { + features |= 0x02 + } + if sig.V5Keys { + features |= 0x04 + } + + if features != 0x00 { + subpackets = append(subpackets, outputSubpacket{true, featuresSubpacket, false, []byte{features}}) + } if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { keyLifetime := make([]byte, 4) @@ -727,5 +907,77 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) } + if len(sig.PolicyURI) > 0 { + subpackets = append(subpackets, outputSubpacket{true, policyUriSubpacket, false, []uint8(sig.PolicyURI)}) + } + + if len(sig.PreferredAEAD) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefAeadAlgosSubpacket, false, sig.PreferredAEAD}) + } + + // Revocation reason appears only in revocation signatures and is serialized as per section 5.2.3.23. + if sig.RevocationReason != nil { + subpackets = append(subpackets, outputSubpacket{true, reasonForRevocationSubpacket, true, + append([]uint8{*sig.RevocationReason}, []uint8(sig.RevocationReasonText)...)}) + } + + // EmbeddedSignature appears only in subkeys capable of signing and is serialized as per section 5.2.3.26. + if sig.EmbeddedSignature != nil { + var buf bytes.Buffer + err = sig.EmbeddedSignature.serializeBody(&buf) + if err != nil { + return + } + subpackets = append(subpackets, outputSubpacket{true, embeddedSignatureSubpacket, true, buf.Bytes()}) + } + return } + +// AddMetadataToHashSuffix modifies the current hash suffix to include metadata +// (format, filename, and time). Version 5 keys protect this data including it +// in the hash computation. See section 5.2.4. +func (sig *Signature) AddMetadataToHashSuffix() { + if sig == nil || sig.Version != 5 { + return + } + if sig.SigType != 0x00 && sig.SigType != 0x01 { + return + } + lit := sig.Metadata + if lit == nil { + // This will translate into six 0x00 bytes. + lit = &LiteralData{} + } + + // Extract the current byte count + n := sig.HashSuffix[len(sig.HashSuffix)-8:] + l := uint64( + uint64(n[0])<<56 | uint64(n[1])<<48 | uint64(n[2])<<40 | uint64(n[3])<<32 | + uint64(n[4])<<24 | uint64(n[5])<<16 | uint64(n[6])<<8 | uint64(n[7])) + + suffix := bytes.NewBuffer(nil) + suffix.Write(sig.HashSuffix[:l]) + + // Add the metadata + var buf [4]byte + buf[0] = lit.Format + fileName := lit.FileName + if len(lit.FileName) > 255 { + fileName = fileName[:255] + } + buf[1] = byte(len(fileName)) + suffix.Write(buf[:2]) + suffix.Write([]byte(lit.FileName)) + binary.BigEndian.PutUint32(buf[:], lit.Time) + suffix.Write(buf[:]) + + // Update the counter and restore trailing bytes + l = uint64(suffix.Len()) + suffix.Write([]byte{0x05, 0xff}) + suffix.Write([]byte{ + uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32), + uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l), + }) + sig.HashSuffix = suffix.Bytes() +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go new file mode 100644 index 0000000..0e9f51d --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go @@ -0,0 +1,267 @@ +// 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 packet + +import ( + "bytes" + "crypto/cipher" + "io" + "strconv" + + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/s2k" +) + +// This is the largest session key that we'll support. Since no 512-bit cipher +// has even been seriously used, this is comfortably large. +const maxSessionKeySizeInBytes = 64 + +// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC +// 4880, section 5.3. +type SymmetricKeyEncrypted struct { + Version int + CipherFunc CipherFunction + Mode AEADMode + s2k func(out, in []byte) + aeadNonce []byte + encryptedKey []byte +} + +func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { + // RFC 4880, section 5.3. + var buf [2]byte + if _, err := readFull(r, buf[:]); err != nil { + return err + } + ske.Version = int(buf[0]) + if ske.Version != 4 && ske.Version != 5 { + return errors.UnsupportedError("unknown SymmetricKeyEncrypted version") + } + ske.CipherFunc = CipherFunction(buf[1]) + if ske.CipherFunc.KeySize() == 0 { + return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) + } + + if ske.Version == 5 { + mode := make([]byte, 1) + if _, err := r.Read(mode); err != nil { + return errors.StructuralError("cannot read AEAD octect from packet") + } + ske.Mode = AEADMode(mode[0]) + } + + var err error + if ske.s2k, err = s2k.Parse(r); err != nil { + if _, ok := err.(errors.ErrDummyPrivateKey); ok { + return errors.UnsupportedError("missing key GNU extension in session key") + } + return err + } + + if ske.Version == 5 { + // AEAD nonce + nonce := make([]byte, ske.Mode.NonceLength()) + _, err := readFull(r, nonce) + if err != nil && err != io.ErrUnexpectedEOF { + return err + } + ske.aeadNonce = nonce + } + + encryptedKey := make([]byte, maxSessionKeySizeInBytes) + // The session key may follow. We just have to try and read to find + // out. If it exists then we limit it to maxSessionKeySizeInBytes. + n, err := readFull(r, encryptedKey) + if err != nil && err != io.ErrUnexpectedEOF { + return err + } + + if n != 0 { + if n == maxSessionKeySizeInBytes { + return errors.UnsupportedError("oversized encrypted session key") + } + ske.encryptedKey = encryptedKey[:n] + } + return nil +} + +// Decrypt attempts to decrypt an encrypted session key and returns the key and +// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data +// packet. +func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { + key := make([]byte, ske.CipherFunc.KeySize()) + ske.s2k(key, passphrase) + if len(ske.encryptedKey) == 0 { + return key, ske.CipherFunc, nil + } + switch ske.Version { + case 4: + plaintextKey, cipherFunc, err := ske.decryptV4(key) + return plaintextKey, cipherFunc, err + case 5: + plaintextKey, err := ske.decryptV5(key) + return plaintextKey, CipherFunction(0), err + } + err := errors.UnsupportedError("unknown SymmetricKeyEncrypted version") + return nil, CipherFunction(0), err +} + +func (ske *SymmetricKeyEncrypted) decryptV4(key []byte) ([]byte, CipherFunction, error) { + // the IV is all zeros + iv := make([]byte, ske.CipherFunc.blockSize()) + c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) + plaintextKey := make([]byte, len(ske.encryptedKey)) + c.XORKeyStream(plaintextKey, ske.encryptedKey) + cipherFunc := CipherFunction(plaintextKey[0]) + if cipherFunc.blockSize() == 0 { + return nil, ske.CipherFunc, errors.UnsupportedError( + "unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + plaintextKey = plaintextKey[1:] + if len(plaintextKey) != cipherFunc.KeySize() { + return nil, cipherFunc, errors.StructuralError( + "length of decrypted key not equal to cipher keysize") + } + return plaintextKey, cipherFunc, nil +} + +func (ske *SymmetricKeyEncrypted) decryptV5(key []byte) ([]byte, error) { + blockCipher := CipherFunction(ske.CipherFunc).new(key) + aead := ske.Mode.new(blockCipher) + + adata := []byte{0xc3, byte(5), byte(ske.CipherFunc), byte(ske.Mode)} + plaintextKey, err := aead.Open(nil, ske.aeadNonce, ske.encryptedKey, adata) + if err != nil { + return nil, err + } + return plaintextKey, nil +} + +// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. +// The packet contains a random session key, encrypted by a key derived from +// the given passphrase. The session key is returned and must be passed to +// SerializeSymmetricallyEncrypted or SerializeAEADEncrypted, depending on +// whether config.AEADConfig != nil. +// If config is nil, sensible defaults will be used. +func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { + cipherFunc := config.Cipher() + keySize := cipherFunc.KeySize() + if keySize == 0 { + return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + + sessionKey := make([]byte, keySize) + _, err = io.ReadFull(config.Random(), sessionKey) + if err != nil { + return + } + + err = SerializeSymmetricKeyEncryptedReuseKey(w, sessionKey, passphrase, config) + if err != nil { + return + } + + key = sessionKey + return +} + +// SerializeSymmetricKeyEncryptedReuseKey serializes a symmetric key packet to w. +// The packet contains the given session key, encrypted by a key derived from +// the given passphrase. The session key must be passed to +// SerializeSymmetricallyEncrypted or SerializeAEADEncrypted, depending on +// whether config.AEADConfig != nil. +// If config is nil, sensible defaults will be used. +func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, config *Config) (err error) { + var version int + if config.AEAD() != nil { + version = 5 + } else { + version = 4 + } + cipherFunc := config.Cipher() + keySize := cipherFunc.KeySize() + if keySize == 0 { + return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + + s2kBuf := new(bytes.Buffer) + keyEncryptingKey := make([]byte, keySize) + // s2k.Serialize salts and stretches the passphrase, and writes the + // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. + err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()}) + if err != nil { + return + } + s2kBytes := s2kBuf.Bytes() + + var packetLength int + switch version { + case 4: + packetLength = 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize + case 5: + nonceLen := config.AEAD().Mode().NonceLength() + tagLen := config.AEAD().Mode().TagLength() + packetLength = 3 + len(s2kBytes) + nonceLen + keySize + tagLen + } + err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) + if err != nil { + return + } + + buf := make([]byte, 2) + // Symmetric Key Encrypted Version + buf[0] = byte(version) + // Cipher function + buf[1] = byte(cipherFunc) + + if version == 5 { + // AEAD mode + buf = append(buf, byte(config.AEAD().Mode())) + } + _, err = w.Write(buf) + if err != nil { + return + } + _, err = w.Write(s2kBytes) + if err != nil { + return + } + + switch version { + case 4: + iv := make([]byte, cipherFunc.blockSize()) + c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) + encryptedCipherAndKey := make([]byte, keySize+1) + c.XORKeyStream(encryptedCipherAndKey, buf[1:]) + c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) + _, err = w.Write(encryptedCipherAndKey) + if err != nil { + return + } + case 5: + blockCipher := cipherFunc.new(keyEncryptingKey) + mode := config.AEAD().Mode() + aead := mode.new(blockCipher) + // Sample nonce using random reader + nonce := make([]byte, config.AEAD().Mode().NonceLength()) + _, err = io.ReadFull(config.Random(), nonce) + if err != nil { + return + } + // Seal and write (encryptedData includes auth. tag) + adata := []byte{0xc3, byte(5), byte(cipherFunc), byte(mode)} + encryptedData := aead.Seal(nil, nonce, sessionKey, adata) + _, err = w.Write(nonce) + if err != nil { + return + } + _, err = w.Write(encryptedData) + if err != nil { + return + } + } + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go similarity index 87% rename from vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go index 6126030..8b84de1 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go @@ -8,18 +8,19 @@ import ( "crypto/cipher" "crypto/sha1" "crypto/subtle" - "golang.org/x/crypto/openpgp/errors" "hash" "io" "strconv" + + "github.com/ProtonMail/go-crypto/openpgp/errors" ) // SymmetricallyEncrypted represents a symmetrically encrypted byte string. The -// encrypted contents will consist of more OpenPGP packets. See RFC 4880, +// encrypted Contents will consist of more OpenPGP packets. See RFC 4880, // sections 5.7 and 5.13. type SymmetricallyEncrypted struct { MDC bool // true iff this is a type 18 packet and thus has an embedded MAC. - contents io.Reader + Contents io.Reader prefix []byte } @@ -37,13 +38,13 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) error { return errors.UnsupportedError("unknown SymmetricallyEncrypted version") } } - se.contents = r + se.Contents = r return nil } -// Decrypt returns a ReadCloser, from which the decrypted contents of the -// packet can be read. An incorrect key can, with high probability, be detected -// immediately and this will result in a KeyIncorrect error being returned. +// Decrypt returns a ReadCloser, from which the decrypted Contents of the +// packet can be read. An incorrect key will only be detected after trying +// to decrypt the entire data. func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { keySize := c.KeySize() if keySize == 0 { @@ -55,7 +56,7 @@ func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.Read if se.prefix == nil { se.prefix = make([]byte, c.blockSize()+2) - _, err := readFull(se.contents, se.prefix) + _, err := readFull(se.Contents, se.prefix) if err != nil { return nil, err } @@ -70,11 +71,8 @@ func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.Read } s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) - if s == nil { - return nil, errors.ErrKeyIncorrect - } - plaintext := cipher.StreamReader{S: s, R: se.contents} + plaintext := cipher.StreamReader{S: s, R: se.Contents} if se.MDC { // MDC packets have an embedded hash that we need to check. @@ -104,7 +102,7 @@ const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size // An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold // of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an -// MDC packet containing a hash of the previous contents which is checked +// MDC packet containing a hash of the previous Contents which is checked // against the running hash. See RFC 4880, section 5.13. type seMDCReader struct { in io.Reader @@ -180,7 +178,7 @@ const mdcPacketTagByte = byte(0x80) | 0x40 | 19 func (ser *seMDCReader) Close() error { if ser.error { - return errors.SignatureError("error during reading") + return errors.ErrMDCMissing } for !ser.eof { @@ -191,18 +189,20 @@ func (ser *seMDCReader) Close() error { break } if err != nil { - return errors.SignatureError("error during reading") + return errors.ErrMDCMissing } } - if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { - return errors.SignatureError("MDC packet not found") - } ser.h.Write(ser.trailer[:2]) final := ser.h.Sum(nil) if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { - return errors.SignatureError("hash mismatch") + return errors.ErrMDCHashMismatch + } + // The hash already includes the MDC header, but we still check its value + // to confirm encryption correctness + if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { + return errors.ErrMDCMissing } return nil } @@ -253,7 +253,7 @@ func (c noOpCloser) Close() error { // to w and returns a WriteCloser to which the to-be-encrypted packets can be // written. // If config is nil, sensible defaults will be used. -func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { +func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (Contents io.WriteCloser, err error) { if c.KeySize() != len(key) { return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") } @@ -285,6 +285,6 @@ func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, h := sha1.New() h.Write(iv) h.Write(iv[blockSize-2:]) - contents = &seMDCWriter{w: plaintext, h: h} + Contents = &seMDCWriter{w: plaintext, h: h} return } diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go similarity index 97% rename from vendor/golang.org/x/crypto/openpgp/packet/userattribute.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go index d19ffbc..0f760ad 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go @@ -69,7 +69,10 @@ func (uat *UserAttribute) parse(r io.Reader) (err error) { func (uat *UserAttribute) Serialize(w io.Writer) (err error) { var buf bytes.Buffer for _, sp := range uat.Contents { - sp.Serialize(&buf) + err = sp.Serialize(&buf) + if err != nil { + return err + } } if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { return err diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go similarity index 100% rename from vendor/golang.org/x/crypto/openpgp/packet/userid.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go similarity index 67% rename from vendor/golang.org/x/crypto/openpgp/read.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/read.go index 6ec664f..a649ebb 100644 --- a/vendor/golang.org/x/crypto/openpgp/read.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Package openpgp implements high level operations on OpenPGP messages. -package openpgp // import "golang.org/x/crypto/openpgp" +package openpgp // import "github.com/ProtonMail/go-crypto/openpgp" import ( "crypto" @@ -12,9 +12,9 @@ import ( "io" "strconv" - "golang.org/x/crypto/openpgp/armor" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/packet" + "github.com/ProtonMail/go-crypto/openpgp/armor" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/packet" ) // SignatureType is the armor type for a PGP signature. @@ -56,9 +56,9 @@ type MessageDetails struct { // been consumed. Once EOF has been seen, the following fields are // valid. (An authentication code failure is reported as a // SignatureError error when reading from UnverifiedBody.) - SignatureError error // nil if the signature is good. - Signature *packet.Signature // the signature packet itself, if v4 (default) - SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature + Signature *packet.Signature // the signature packet itself. + SignatureError error // nil if the signature is good. + UnverifiedSignatures []*packet.Signature // all other unverified signature packets. decrypted io.ReadCloser } @@ -88,7 +88,8 @@ func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *pa var symKeys []*packet.SymmetricKeyEncrypted var pubKeys []keyEnvelopePair - var se *packet.SymmetricallyEncrypted + // Integrity protected encrypted packet: SymmetricallyEncrypted or AEADEncrypted + var edp packet.EncryptedDataPacket packets := packet.NewReader(r) md = new(MessageDetails) @@ -113,7 +114,7 @@ ParsePackets: // This packet contains the decryption key encrypted to a public key. md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) switch p.Algo { - case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: + case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH: break default: continue @@ -127,8 +128,8 @@ ParsePackets: for _, k := range keys { pubKeys = append(pubKeys, keyEnvelopePair{k, p}) } - case *packet.SymmetricallyEncrypted: - se = p + case *packet.SymmetricallyEncrypted, *packet.AEADEncrypted: + edp = p.(packet.EncryptedDataPacket) break ParsePackets case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: // This message isn't encrypted. @@ -136,7 +137,7 @@ ParsePackets: return nil, errors.StructuralError("key material not followed by encrypted message") } packets.Unread(p) - return readSignedMessage(packets, nil, keyring) + return readSignedMessage(packets, nil, keyring, config) } } @@ -158,12 +159,13 @@ FindKey: } if !pk.key.PrivateKey.Encrypted { if len(pk.encryptedKey.Key) == 0 { - pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) + errDec := pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) + if errDec != nil { + continue + } } - if len(pk.encryptedKey.Key) == 0 { - continue - } - decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) + // Try to decrypt symmetrically encrypted + decrypted, err = edp.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) if err != nil && err != errors.ErrKeyIncorrect { return nil, err } @@ -198,8 +200,12 @@ FindKey: if len(symKeys) != 0 && passphrase != nil { for _, s := range symKeys { key, cipherFunc, err := s.Decrypt(passphrase) + // On wrong passphrase, session key decryption is very likely to result in an invalid cipherFunc: + // only for < 5% of cases we will proceed to decrypt the data if err == nil { - decrypted, err = se.Decrypt(cipherFunc, key) + decrypted, err = edp.Decrypt(cipherFunc, key) + // TODO: ErrKeyIncorrect is no longer thrown on SEIP decryption, + // but it might still be relevant for when we implement AEAD decryption (otherwise, remove?) if err != nil && err != errors.ErrKeyIncorrect { return nil, err } @@ -207,7 +213,6 @@ FindKey: break FindKey } } - } } } @@ -216,13 +221,17 @@ FindKey: if err := packets.Push(decrypted); err != nil { return nil, err } - return readSignedMessage(packets, md, keyring) + mdFinal, sensitiveParsingErr := readSignedMessage(packets, md, keyring, config) + if sensitiveParsingErr != nil { + return nil, errors.StructuralError("parsing error") + } + return mdFinal, nil } // readSignedMessage reads a possibly signed message if mdin is non-zero then // that structure is updated and returned. Otherwise a fresh MessageDetails is // used. -func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) { +func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing, config *packet.Config) (md *MessageDetails, err error) { if mdin == nil { mdin = new(MessageDetails) } @@ -231,6 +240,7 @@ func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring Key var p packet.Packet var h hash.Hash var wrappedHash hash.Hash + var prevLast bool FindLiteralData: for { p, err = packets.Next() @@ -243,14 +253,17 @@ FindLiteralData: return nil, err } case *packet.OnePassSignature: - if !p.IsLast { - return nil, errors.UnsupportedError("nested signatures") + if prevLast { + return nil, errors.UnsupportedError("nested signature packets") + } + + if p.IsLast { + prevLast = true } h, wrappedHash, err = hashForSignature(p.Hash, p.SigType) if err != nil { - md = nil - return + md.SignatureError = err } md.IsSigned = true @@ -265,8 +278,8 @@ FindLiteralData: } } - if md.SignedBy != nil { - md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md} + if md.IsSigned && md.SignatureError == nil { + md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md, config} } else if md.decrypted != nil { md.UnverifiedBody = checkReader{md} } else { @@ -282,6 +295,9 @@ FindLiteralData: // returns two hashes. The second should be used to hash the message itself and // performs any needed preprocessing. func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) { + if hashId == crypto.MD5 { + return nil, nil, errors.UnsupportedError("insecure hash algorithm: MD5") + } if !hashId.Available() { return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) } @@ -304,15 +320,21 @@ type checkReader struct { md *MessageDetails } -func (cr checkReader) Read(buf []byte) (n int, err error) { - n, err = cr.md.LiteralData.Body.Read(buf) - if err == io.EOF { +func (cr checkReader) Read(buf []byte) (int, error) { + n, sensitiveParsingError := cr.md.LiteralData.Body.Read(buf) + if sensitiveParsingError == io.EOF { mdcErr := cr.md.decrypted.Close() if mdcErr != nil { - err = mdcErr + return n, mdcErr } + return n, io.EOF } - return + + if sensitiveParsingError != nil { + return n, errors.StructuralError("parsing error") + } + + return n, nil } // signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes @@ -322,26 +344,51 @@ type signatureCheckReader struct { packets *packet.Reader h, wrappedHash hash.Hash md *MessageDetails + config *packet.Config } -func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { - n, err = scr.md.LiteralData.Body.Read(buf) - scr.wrappedHash.Write(buf[:n]) - if err == io.EOF { +func (scr *signatureCheckReader) Read(buf []byte) (int, error) { + n, sensitiveParsingError := scr.md.LiteralData.Body.Read(buf) + + // Hash only if required + if scr.md.SignedBy != nil { + scr.wrappedHash.Write(buf[:n]) + } + + if sensitiveParsingError == io.EOF { var p packet.Packet - p, scr.md.SignatureError = scr.packets.Next() - if scr.md.SignatureError != nil { - return + var readError error + var sig *packet.Signature + + p, readError = scr.packets.Next() + for readError == nil { + var ok bool + if sig, ok = p.(*packet.Signature); ok { + if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) { + sig.Metadata = scr.md.LiteralData + } + + // If signature KeyID matches + if scr.md.SignedBy != nil && *sig.IssuerKeyId == scr.md.SignedByKeyId { + scr.md.Signature = sig + scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) + if scr.md.SignatureError == nil && scr.md.Signature.SigExpired(scr.config.Now()) { + scr.md.SignatureError = errors.ErrSignatureExpired + } + } else { + scr.md.UnverifiedSignatures = append(scr.md.UnverifiedSignatures, sig) + } + } + + p, readError = scr.packets.Next() } - var ok bool - if scr.md.Signature, ok = p.(*packet.Signature); ok { - scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) - } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { - scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) - } else { - scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") - return + if scr.md.SignedBy != nil && scr.md.Signature == nil { + if scr.md.UnverifiedSignatures == nil { + scr.md.SignatureError = errors.StructuralError("LiteralData not followed by signature") + } else { + scr.md.SignatureError = errors.StructuralError("No matching signature found") + } } // The SymmetricallyEncrypted packet, if any, might have an @@ -350,24 +397,39 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { if scr.md.decrypted != nil { mdcErr := scr.md.decrypted.Close() if mdcErr != nil { - err = mdcErr + return n, mdcErr } } + return n, io.EOF } - return + + if sensitiveParsingError != nil { + return n, errors.StructuralError("parsing error") + } + + return n, nil } // CheckDetachedSignature takes a signed file and a detached signature and // returns the signer if the signature is valid. If the signer isn't known, // ErrUnknownIssuer is returned. -func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { +func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) { + var expectedHashes []crypto.Hash + return CheckDetachedSignatureAndHash(keyring, signed, signature, expectedHashes, config) +} + +// CheckDetachedSignatureAndHash performs the same actions as +// CheckDetachedSignature and checks that the expected hash functions were used. +func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) { var issuerKeyId uint64 var hashFunc crypto.Hash var sigType packet.SignatureType var keys []Key var p packet.Packet + expectedHashesLen := len(expectedHashes) packets := packet.NewReader(signature) + var sig *packet.Signature for { p, err = packets.Next() if err == io.EOF { @@ -377,21 +439,26 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe return nil, err } - switch sig := p.(type) { - case *packet.Signature: - if sig.IssuerKeyId == nil { - return nil, errors.StructuralError("signature doesn't have an issuer") - } - issuerKeyId = *sig.IssuerKeyId - hashFunc = sig.Hash - sigType = sig.SigType - case *packet.SignatureV3: - issuerKeyId = sig.IssuerKeyId - hashFunc = sig.Hash - sigType = sig.SigType - default: + var ok bool + sig, ok = p.(*packet.Signature) + if !ok { return nil, errors.StructuralError("non signature packet found") } + if sig.IssuerKeyId == nil { + return nil, errors.StructuralError("signature doesn't have an issuer") + } + issuerKeyId = *sig.IssuerKeyId + hashFunc = sig.Hash + sigType = sig.SigType + + for i, expectedHash := range expectedHashes { + if hashFunc == expectedHash { + break + } + if i+1 == expectedHashesLen { + return nil, errors.StructuralError("hash algorithm mismatch with cleartext message headers") + } + } keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) if len(keys) > 0 { @@ -413,16 +480,15 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe } for _, key := range keys { - switch sig := p.(type) { - case *packet.Signature: - err = key.PublicKey.VerifySignature(h, sig) - case *packet.SignatureV3: - err = key.PublicKey.VerifySignatureV3(h, sig) - default: - panic("unreachable") - } - + err = key.PublicKey.VerifySignature(h, sig) if err == nil { + now := config.Now() + if sig.SigExpired(now) { + return key.Entity, errors.ErrSignatureExpired + } + if key.PublicKey.KeyExpired(key.SelfSignature, now) { + return key.Entity, errors.ErrKeyExpired + } return key.Entity, nil } } @@ -432,11 +498,11 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe // CheckArmoredDetachedSignature performs the same actions as // CheckDetachedSignature but expects the signature to be armored. -func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { +func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) { body, err := readArmored(signature, SignatureType) if err != nil { return } - return CheckDetachedSignature(keyring, signed, body) + return CheckDetachedSignature(keyring, signed, body, config) } diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go new file mode 100644 index 0000000..8caed36 --- /dev/null +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go @@ -0,0 +1,173 @@ +package openpgp + +const testKey1KeyId = 0xA34D7E18C20C31BB +const testKey3KeyId = 0x338934250CCC0360 +const testKeyP256KeyId = 0xd44a2c495918513e + +const signedInput = "Signed message\nline 2\nline 3\n" +const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n" + +const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b" + +const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77" + +const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39" + +const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83" + +const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817" + +// The plaintext is https://www.gutenberg.org/cache/epub/1080/pg1080.txt +const modestProposalSha512 = "lbbrB1+WP3T9AaC9OQqBdOcCjgeEQadlulXsNPgVx0tyqPzDHwUugZ2gE7V0ESKAw6kAVfgkcuvfgxAAGaeHtw==" + +const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003" + +const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000" + +const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000" + +const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300" + +const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200" + +const signedEncryptedMessageHex = "c18c032a67d68660df41c70103ff5a84c9a72f80e74ef0384c2d6a9ebfe2b09e06a8f298394f6d2abf174e40934ab0ec01fb2d0ddf21211c6fe13eb238563663b017a6b44edca552eb4736c4b7dc6ed907dd9e12a21b51b64b46f902f76fb7aaf805c1db8070574d8d0431a23e324a750f77fb72340a17a42300ee4ca8207301e95a731da229a63ab9c6b44541fbd2c11d016d810b3b3b2b38f15b5b40f0a4910332829c2062f1f7cc61f5b03677d73c54cafa1004ced41f315d46444946faae571d6f426e6dbd45d9780eb466df042005298adabf7ce0ef766dfeb94cd449c7ed0046c880339599c4711af073ce649b1e237c40b50a5536283e03bdbb7afad78bd08707715c67fb43295f905b4c479178809d429a8e167a9a8c6dfd8ab20b4edebdc38d6dec879a3202e1b752690d9bb5b0c07c5a227c79cc200e713a99251a4219d62ad5556900cf69bd384b6c8e726c7be267471d0d23af956da165af4af757246c2ebcc302b39e8ef2fccb4971b234fcda22d759ddb20e27269ee7f7fe67898a9de721bfa02ab0becaa046d00ea16cb1afc4e2eab40d0ac17121c565686e5cbd0cbdfbd9d6db5c70278b9c9db5a83176d04f61fbfbc4471d721340ede2746e5c312ded4f26787985af92b64fae3f253dbdde97f6a5e1996fd4d865599e32ff76325d3e9abe93184c02988ee89a4504356a4ef3b9b7a57cbb9637ca90af34a7676b9ef559325c3cca4e29d69fec1887f5440bb101361d744ad292a8547f22b4f22b419a42aa836169b89190f46d9560824cb2ac6e8771de8223216a5e647e132ab9eebcba89569ab339cb1c3d70fe806b31f4f4c600b4103b8d7583ebff16e43dcda551e6530f975122eb8b29" + +const verifiedSignatureEncryptedMessageHex = "c2b304000108000605026048f6d600210910a34d7e18c20c31bb1621045fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb9a3b0400a32ddac1af259c1b0abab0041327ea04970944401978fb647dd1cf9aba4f164e43f0d8a9389501886474bdd4a6e77f6aea945c07dfbf87743835b44cc2c39a1f9aeecfa83135abc92e18e50396f2e6a06c44e0188b0081effbfb4160d28f118d4ff73dd199a102e47cffd8c7ff2bacd83ae72b5820c021a486766dd587b5da61" + +const unverifiedSignatureEncryptedMessageHex = "c2b304000108000605026048f6d600210910a34d7e18c20c31bb1621045fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb9a3b0400a32ddac1af259c1b0abab0041327ea04970944401978fb647dd1cf9aba4f164e43f0d8a9389501886474bdd4a6e77f6aea945c07dfbf87743835b44cc2c39a1f9aeecfa83135abc92e18e50396f2e6a06c44e0188b0081effbfb4160d28f118d4ff73dd199a102e47cffd8c7ff2bacd83ae72b5820c021a486766dd587b5da61" + +const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3" + +const signatureEncryptedMessage2Hex = "c24604001102000605024dfd0166000a091033af447ccd759b09bae600a096ec5e63ecf0a403085e10f75cc3bab327663282009f51fad9df457ed8d2b70d8a73c76e0443eac0f377" + +const symmetricallyEncryptedCompressedHex = "c32e040903085a357c1a7b5614ed00cc0d1d92f428162058b3f558a0fb0980d221ebac6c97d5eda4e0fe32f6e706e94dd263012d6ca1ef8c4bbd324098225e603a10c85ebf09cbf7b5aeeb5ce46381a52edc51038b76a8454483be74e6dcd1e50d5689a8ae7eceaeefed98a0023d49b22eb1f65c2aa1ef1783bb5e1995713b0457102ec3c3075fe871267ffa4b686ad5d52000d857" + +const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" + +const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" + +const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" + +const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" + +const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp +idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn +vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB +AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X +0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL +IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk +VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn +gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 +TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx +q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz +dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA +CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 +ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ +eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid +AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV +bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK +/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA +A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX +TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc +lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 +rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN +oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 +QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU +nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC +AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp +BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad +AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL +VrM0m72/jnpKo04= +=zNCn +-----END PGP PRIVATE KEY BLOCK-----` + +const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Charset: UTF-8 + +xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4 +sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk +Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/ +AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD +24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX ++WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8 +B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX +fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA +FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9 +ex7En5r7rHR5xwX82Msc+Rq9dSyO +=7MrZ +-----END PGP PUBLIC KEY BLOCK-----` + +const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003` + +const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101` + +const rsaSignatureBadMPIlength = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` + +const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101` + +const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000` + +const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: GPGTools - https://gpgtools.org + +mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY +BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z +tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0 +JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV +/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+ +K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H +JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx +YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1 +b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi +UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M +pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM +AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz +786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd +EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB +=RZia +-----END PGP PUBLIC KEY BLOCK----- +` + +const signedMessageV3 = `-----BEGIN PGP MESSAGE----- +Comment: GPGTools - https://gpgtools.org + +owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP +q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka +uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka +DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d +iT57d/OhWwA= +=hG7R +-----END PGP MESSAGE----- +` + +// https://mailarchive.ietf.org/arch/msg/openpgp/9SheW_LENE0Kxf7haNllovPyAdY/ +const v5PrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- + +lGEFXJH05BYAAAAtCSsGAQQB2kcPAQEHQFhZlVcVVtwf+21xNQPX+ecMJJBL0MPd +fj75iux+my8QAAAAAAAiAQCHZ1SnSUmWqxEsoI6facIVZQu6mph3cBFzzTvcm5lA +Ng5ctBhlbW1hLmdvbGRtYW5AZXhhbXBsZS5uZXSIlgUTFggASCIhBRk0e8mHJGQC +X5nfPsLgAA7ZiEiS4fez6kyUAJFZVptUBQJckfTkAhsDBQsJCAcCAyICAQYVCgkI +CwIEFgIDAQIeBwIXgAAA9cAA/jiR3yMsZMeEQ40u6uzEoXa6UXeV/S3wwJAXRJy9 +M8s0AP9vuL/7AyTfFXwwzSjDnYmzS0qAhbLDQ643N+MXGBJ2BZxmBVyR9OQSAAAA +MgorBgEEAZdVAQUBAQdA+nysrzml2UCweAqtpDuncSPlvrcBWKU0yfU0YvYWWAoD +AQgHAAAAAAAiAP9OdAPppjU1WwpqjIItkxr+VPQRT8Zm/Riw7U3F6v3OiBFHiHoF +GBYIACwiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVAUCXJH05AIb +DAAAOSQBAP4BOOIR/sGLNMOfeb5fPs/02QMieoiSjIBnijhob2U5AQC+RtOHCHx7 +TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw== +=IiS2 +-----END PGP PRIVATE KEY BLOCK-----` + +// Generated with the above private key +const v5PrivKeyMsg = `-----BEGIN PGP MESSAGE----- +Version: OpenPGP.js v4.10.7 +Comment: https://openpgpjs.org + +xA0DAQoWGTR7yYckZAIByxF1B21zZy50eHRfbIGSdGVzdMJ3BQEWCgAGBQJf +bIGSACMiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVDQvAP9G +y29VPonFXqi2zKkpZrvyvZxg+n5e8Nt9wNbuxeCd3QD/TtO2s+JvjrE4Siwv +UQdl5MlBka1QSNbMq2Bz7XwNPg4= +=6lbM +-----END PGP MESSAGE-----` diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go similarity index 51% rename from vendor/golang.org/x/crypto/openpgp/s2k/s2k.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go index 4b9a44c..14f5854 100644 --- a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go @@ -4,7 +4,7 @@ // Package s2k implements the various OpenPGP string-to-key transforms as // specified in RFC 4800 section 3.7.1. -package s2k // import "golang.org/x/crypto/openpgp/s2k" +package s2k // import "github.com/ProtonMail/go-crypto/openpgp/s2k" import ( "crypto" @@ -12,49 +12,67 @@ import ( "io" "strconv" - "golang.org/x/crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" ) // Config collects configuration parameters for s2k key-stretching -// transformatioms. A nil *Config is valid and results in all default +// transformations. A nil *Config is valid and results in all default // values. Currently, Config is used only by the Serialize function in // this package. type Config struct { + // S2KMode is the mode of s2k function. + // It can be 0 (simple), 1(salted), 3(iterated) + // 2(reserved) 100-110(private/experimental). + S2KMode uint8 // Hash is the default hash function to be used. If - // nil, SHA1 is used. + // nil, SHA256 is used. Hash crypto.Hash // S2KCount is only used for symmetric encryption. It // determines the strength of the passphrase stretching when // the said passphrase is hashed to produce a key. S2KCount - // should be between 1024 and 65011712, inclusive. If Config - // is nil or S2KCount is 0, the value 65536 used. Not all + // should be between 65536 and 65011712, inclusive. If Config + // is nil or S2KCount is 0, the value 16777216 used. Not all // values in the above range can be represented. S2KCount will // be rounded up to the next representable value if it cannot - // be encoded exactly. When set, it is strongly encrouraged to - // use a value that is at least 65536. See RFC 4880 Section - // 3.7.1.3. + // be encoded exactly. See RFC 4880 Section 3.7.1.3. S2KCount int } +// Params contains all the parameters of the s2k packet +type Params struct { + // mode is the mode of s2k function. + // It can be 0 (simple), 1(salted), 3(iterated) + // 2(reserved) 100-110(private/experimental). + mode uint8 + // hashId is the ID of the hash function used in any of the modes + hashId byte + // salt is a byte array to use as a salt in hashing process + salt []byte + // countByte is used to determine how many rounds of hashing are to + // be performed in s2k mode 3. See RFC 4880 Section 3.7.1.3. + countByte byte +} + func (c *Config) hash() crypto.Hash { if c == nil || uint(c.Hash) == 0 { - // SHA1 is the historical default in this package. - return crypto.SHA1 + return crypto.SHA256 } return c.Hash } -func (c *Config) encodedCount() uint8 { +// EncodedCount get encoded count +func (c *Config) EncodedCount() uint8 { if c == nil || c.S2KCount == 0 { - return 96 // The common case. Correspoding to 65536 + return 224 // The common case. Corresponding to 16777216 } i := c.S2KCount + switch { - // Behave like GPG. Should we make 65536 the lowest value used? - case i < 1024: - i = 1024 + case i < 65536: + i = 65536 case i > 65011712: i = 65011712 } @@ -68,11 +86,11 @@ func (c *Config) encodedCount() uint8 { // if i is not in the above range (encodedCount above takes care to // pass i in the correct range). See RFC 4880 Section 3.7.7.1. func encodeCount(i int) uint8 { - if i < 1024 || i > 65011712 { + if i < 65536 || i > 65011712 { panic("count arg i outside the required range") } - for encoded := 0; encoded < 256; encoded++ { + for encoded := 96; encoded < 256; encoded++ { count := decodeCount(uint8(encoded)) if count >= i { return uint8(encoded) @@ -151,9 +169,44 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { } } +// Generate generates valid parameters from given configuration. +// It will enforce salted + hashed s2k method +func Generate(rand io.Reader, c *Config) (*Params, error) { + hashId, ok := HashToHashId(c.Hash) + if !ok { + return nil, errors.UnsupportedError("no such hash") + } + + params := &Params{ + mode: 3, // Enforce iterared + salted method + hashId: hashId, + salt: make([]byte, 8), + countByte: c.EncodedCount(), + } + + if _, err := io.ReadFull(rand, params.salt); err != nil { + return nil, err + } + + return params, nil +} + // Parse reads a binary specification for a string-to-key transformation from r -// and returns a function which performs that transform. +// and returns a function which performs that transform. If the S2K is a special +// GNU extension that indicates that the private key is missing, then the error +// returned is errors.ErrDummyPrivateKey. func Parse(r io.Reader) (f func(out, in []byte), err error) { + params, err := ParseIntoParams(r) + if err != nil { + return nil, err + } + + return params.Function() +} + +// ParseIntoParams reads a binary specification for a string-to-key +// transformation from r and returns a struct describing the s2k parameters. +func ParseIntoParams(r io.Reader) (params *Params, err error) { var buf [9]byte _, err = io.ReadFull(r, buf[:2]) @@ -161,91 +214,135 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) { return } - hash, ok := HashIdToHash(buf[1]) - if !ok { - return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) + params = &Params{ + mode: buf[0], + hashId: buf[1], } - if !hash.Available() { - return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) - } - h := hash.New() - switch buf[0] { + switch params.mode { case 0: - f := func(out, in []byte) { - Simple(out, h, in) - } - return f, nil + return params, nil case 1: _, err = io.ReadFull(r, buf[:8]) if err != nil { - return + return nil, err } - f := func(out, in []byte) { - Salted(out, h, in, buf[:8]) - } - return f, nil + + params.salt = buf[:8] + return params, nil case 3: _, err = io.ReadFull(r, buf[:9]) if err != nil { - return + return nil, err } - count := decodeCount(buf[8]) + + params.salt = buf[:8] + params.countByte = buf[8] + return params, nil + case 101: + // This is a GNU extension. See + // https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109 + if _, err = io.ReadFull(r, buf[:4]); err != nil { + return nil, err + } + if buf[0] == 'G' && buf[1] == 'N' && buf[2] == 'U' && buf[3] == 1 { + return params, nil + } + return nil, errors.UnsupportedError("GNU S2K extension") + } + + return nil, errors.UnsupportedError("S2K function") +} + +func (params *Params) Dummy() bool { + return params != nil && params.mode == 101 +} + +func (params *Params) Function() (f func(out, in []byte), err error) { + if params.Dummy() { + return nil, errors.ErrDummyPrivateKey("dummy key found") + } + hashObj, ok := HashIdToHash(params.hashId) + if !ok { + return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(params.hashId))) + } + if !hashObj.Available() { + return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashObj))) + } + + switch params.mode { + case 0: f := func(out, in []byte) { - Iterated(out, h, in, buf[:8], count) + Simple(out, hashObj.New(), in) } + + return f, nil + case 1: + f := func(out, in []byte) { + Salted(out, hashObj.New(), in, params.salt) + } + + return f, nil + case 3: + f := func(out, in []byte) { + Iterated(out, hashObj.New(), in, params.salt, decodeCount(params.countByte)) + } + return f, nil } return nil, errors.UnsupportedError("S2K function") } +func (params *Params) Serialize(w io.Writer) (err error) { + if _, err = w.Write([]byte{params.mode}); err != nil { + return + } + if _, err = w.Write([]byte{params.hashId}); err != nil { + return + } + if params.Dummy() { + _, err = w.Write(append([]byte("GNU"), 1)) + return + } + if params.mode > 0 { + if _, err = w.Write(params.salt); err != nil { + return + } + if params.mode == 3 { + _, err = w.Write([]byte{params.countByte}) + } + } + return +} + // Serialize salts and stretches the given passphrase and writes the // resulting key into key. It also serializes an S2K descriptor to // w. The key stretching can be configured with c, which may be // nil. In that case, sensible defaults will be used. func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { - var buf [11]byte - buf[0] = 3 /* iterated and salted */ - buf[1], _ = HashToHashId(c.hash()) - salt := buf[2:10] - if _, err := io.ReadFull(rand, salt); err != nil { + params, err := Generate(rand, c) + if err != nil { return err } - encodedCount := c.encodedCount() - count := decodeCount(encodedCount) - buf[10] = encodedCount - if _, err := w.Write(buf[:]); err != nil { + err = params.Serialize(w) + if err != nil { return err } - Iterated(key, c.hash().New(), passphrase, salt, count) + f, err := params.Function() + if err != nil { + return err + } + f(key, passphrase) return nil } -// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with -// Go's crypto.Hash type. See RFC 4880, section 9.4. -var hashToHashIdMapping = []struct { - id byte - hash crypto.Hash - name string -}{ - {1, crypto.MD5, "MD5"}, - {2, crypto.SHA1, "SHA1"}, - {3, crypto.RIPEMD160, "RIPEMD160"}, - {8, crypto.SHA256, "SHA256"}, - {9, crypto.SHA384, "SHA384"}, - {10, crypto.SHA512, "SHA512"}, - {11, crypto.SHA224, "SHA224"}, -} - // HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP // hash id. func HashIdToHash(id byte) (h crypto.Hash, ok bool) { - for _, m := range hashToHashIdMapping { - if m.id == id { - return m.hash, true - } + if hash, ok := algorithm.HashById[id]; ok { + return hash.HashFunc(), true } return 0, false } @@ -253,20 +350,17 @@ func HashIdToHash(id byte) (h crypto.Hash, ok bool) { // HashIdToString returns the name of the hash function corresponding to the // given OpenPGP hash id. func HashIdToString(id byte) (name string, ok bool) { - for _, m := range hashToHashIdMapping { - if m.id == id { - return m.name, true - } + if hash, ok := algorithm.HashById[id]; ok { + return hash.String(), true } - return "", false } // HashIdToHash returns an OpenPGP hash id which corresponds the given Hash. func HashToHashId(h crypto.Hash) (id byte, ok bool) { - for _, m := range hashToHashIdMapping { - if m.hash == h { - return m.id, true + for id, hash := range algorithm.HashById { + if hash.HashFunc() == h { + return id, true } } return 0, false diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go similarity index 60% rename from vendor/golang.org/x/crypto/openpgp/write.go rename to vendor/github.com/ProtonMail/go-crypto/openpgp/write.go index 4ee7178..f0d7fe1 100644 --- a/vendor/golang.org/x/crypto/openpgp/write.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go @@ -11,10 +11,10 @@ import ( "strconv" "time" - "golang.org/x/crypto/openpgp/armor" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/packet" - "golang.org/x/crypto/openpgp/s2k" + "github.com/ProtonMail/go-crypto/openpgp/armor" + "github.com/ProtonMail/go-crypto/openpgp/errors" + "github.com/ProtonMail/go-crypto/openpgp/packet" + "github.com/ProtonMail/go-crypto/openpgp/s2k" ) // DetachSign signs message with the private key from signer (which must @@ -60,27 +60,35 @@ func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType p } func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { - if signer.PrivateKey == nil { + signingKey, ok := signer.SigningKeyById(config.Now(), config.SigningKey()) + if !ok { + return errors.InvalidArgumentError("no valid signing keys") + } + if signingKey.PrivateKey == nil { return errors.InvalidArgumentError("signing key doesn't have a private key") } - if signer.PrivateKey.Encrypted { + if signingKey.PrivateKey.Encrypted { return errors.InvalidArgumentError("signing key is encrypted") } sig := new(packet.Signature) sig.SigType = sigType - sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo + sig.PubKeyAlgo = signingKey.PrivateKey.PubKeyAlgo sig.Hash = config.Hash() sig.CreationTime = config.Now() - sig.IssuerKeyId = &signer.PrivateKey.KeyId + sigLifetimeSecs := config.SigLifetime() + sig.SigLifetimeSecs = &sigLifetimeSecs + sig.IssuerKeyId = &signingKey.PrivateKey.KeyId h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) if err != nil { return } - io.Copy(wrappedHash, message) + if _, err = io.Copy(wrappedHash, message); err != nil { + return err + } - err = sig.Sign(h, signer.PrivateKey, config) + err = sig.Sign(h, signingKey.PrivateKey, config) if err != nil { return } @@ -115,18 +123,27 @@ func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHi if err != nil { return } - w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) - if err != nil { - return + + var w io.WriteCloser + if config.AEAD() != nil { + w, err = packet.SerializeAEADEncrypted(ciphertext, key, config.Cipher(), config.AEAD().Mode(), config) + if err != nil { + return + } + } else { + w, err = packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) + if err != nil { + return + } } - literaldata := w + literalData := w if algo := config.Compression(); algo != packet.CompressionNone { var compConfig *packet.CompressionConfig if config != nil { compConfig = config.CompressionConfig } - literaldata, err = packet.SerializeCompressed(w, algo, compConfig) + literalData, err = packet.SerializeCompressed(w, algo, compConfig) if err != nil { return } @@ -136,7 +153,7 @@ func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHi if !hints.ModTime.IsZero() { epochSeconds = uint32(hints.ModTime.Unix()) } - return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) + return packet.SerializeLiteral(literalData, hints.IsBinary, hints.FileName, epochSeconds) } // intersectPreferences mutates and returns a prefix of a that contains only @@ -164,15 +181,51 @@ func hashToHashId(h crypto.Hash) uint8 { return v } +// EncryptText encrypts a message to a number of recipients and, optionally, +// signs it. Optional information is contained in 'hints', also encrypted, that +// aids the recipients in processing the message. The resulting WriteCloser +// must be closed after the contents of the file have been written. If config +// is nil, sensible defaults will be used. The signing is done in text mode. +func EncryptText(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + return encrypt(ciphertext, ciphertext, to, signed, hints, packet.SigTypeText, config) +} + +// Encrypt encrypts a message to a number of recipients and, optionally, signs +// it. hints contains optional information, that is also encrypted, that aids +// the recipients in processing the message. The resulting WriteCloser must +// be closed after the contents of the file have been written. +// If config is nil, sensible defaults will be used. +func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + return encrypt(ciphertext, ciphertext, to, signed, hints, packet.SigTypeBinary, config) +} + +// EncryptSplit encrypts a message to a number of recipients and, optionally, signs +// it. hints contains optional information, that is also encrypted, that aids +// the recipients in processing the message. The resulting WriteCloser must +// be closed after the contents of the file have been written. +// If config is nil, sensible defaults will be used. +func EncryptSplit(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + return encrypt(keyWriter, dataWriter, to, signed, hints, packet.SigTypeBinary, config) +} + +// EncryptTextSplit encrypts a message to a number of recipients and, optionally, signs +// it. hints contains optional information, that is also encrypted, that aids +// the recipients in processing the message. The resulting WriteCloser must +// be closed after the contents of the file have been written. +// If config is nil, sensible defaults will be used. +func EncryptTextSplit(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + return encrypt(keyWriter, dataWriter, to, signed, hints, packet.SigTypeText, config) +} + // writeAndSign writes the data as a payload package and, optionally, signs // it. hints contains optional information, that is also encrypted, // that aids the recipients in processing the message. The resulting // WriteCloser must be closed after the contents of the file have been // written. If config is nil, sensible defaults will be used. -func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { +func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, sigType packet.SignatureType, config *packet.Config) (plaintext io.WriteCloser, err error) { var signer *packet.PrivateKey if signed != nil { - signKey, ok := signed.signingKey(config.Now()) + signKey, ok := signed.SigningKeyById(config.Now(), config.SigningKey()) if !ok { return nil, errors.InvalidArgumentError("no valid signing keys") } @@ -214,7 +267,7 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit if signer != nil { ops := &packet.OnePassSignature{ - SigType: packet.SigTypeBinary, + SigType: sigType, Hash: hash, PubKeyAlgo: signer.PubKeyAlgo, KeyId: signer.KeyId, @@ -247,17 +300,29 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit } if signer != nil { - return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil + h, wrappedHash, err := hashForSignature(hash, sigType) + if err != nil { + return nil, err + } + metadata := &packet.LiteralData{ + Format: 't', + FileName: hints.FileName, + Time: epochSeconds, + } + if hints.IsBinary { + metadata.Format = 'b' + } + return signatureWriter{payload, literalData, hash, wrappedHash, h, signer, sigType, config, metadata}, nil } return literalData, nil } -// Encrypt encrypts a message to a number of recipients and, optionally, signs +// encrypt encrypts a message to a number of recipients and, optionally, signs // it. hints contains optional information, that is also encrypted, that aids // the recipients in processing the message. The resulting WriteCloser must // be closed after the contents of the file have been written. // If config is nil, sensible defaults will be used. -func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { +func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, sigType packet.SignatureType, config *packet.Config) (plaintext io.WriteCloser, err error) { if len(to) == 0 { return nil, errors.InvalidArgumentError("no encryption recipient provided") } @@ -276,21 +341,39 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint hashToHashId(crypto.SHA1), hashToHashId(crypto.RIPEMD160), } + candidateAeadModes := []uint8{ + uint8(packet.AEADModeEAX), + uint8(packet.AEADModeOCB), + uint8(packet.AEADModeExperimentalGCM), + } + candidateCompression := []uint8{ + uint8(packet.CompressionNone), + uint8(packet.CompressionZIP), + uint8(packet.CompressionZLIB), + } // In the event that a recipient doesn't specify any supported ciphers // or hash functions, these are the ones that we assume that every // implementation supports. - defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] - defaultHashes := candidateHashes[len(candidateHashes)-1:] + defaultCiphers := candidateCiphers[0:1] + defaultHashes := candidateHashes[0:1] + defaultAeadModes := candidateAeadModes[0:1] + defaultCompression := candidateCompression[0:1] encryptKeys := make([]Key, len(to)) + // AEAD is used only if every key supports it. + aeadSupported := true + for i := range to { var ok bool - encryptKeys[i], ok = to[i].encryptionKey(config.Now()) + encryptKeys[i], ok = to[i].EncryptionKey(config.Now()) if !ok { return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") } - sig := to[i].primaryIdentity().SelfSignature + sig := to[i].PrimaryIdentity().SelfSignature + if sig.AEAD == false { + aeadSupported = false + } preferredSymmetric := sig.PreferredSymmetric if len(preferredSymmetric) == 0 { @@ -300,15 +383,26 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint if len(preferredHashes) == 0 { preferredHashes = defaultHashes } + preferredAeadModes := sig.PreferredAEAD + if len(preferredAeadModes) == 0 { + preferredAeadModes = defaultAeadModes + } + preferredCompression := sig.PreferredCompression + if len(preferredCompression) == 0 { + preferredCompression = defaultCompression + } candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) candidateHashes = intersectPreferences(candidateHashes, preferredHashes) + candidateAeadModes = intersectPreferences(candidateAeadModes, preferredAeadModes) + candidateCompression = intersectPreferences(candidateCompression, preferredCompression) } - if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { + if len(candidateCiphers) == 0 || len(candidateHashes) == 0 || len(candidateAeadModes) == 0 { return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") } cipher := packet.CipherFunction(candidateCiphers[0]) + mode := packet.AEADMode(candidateAeadModes[0]) // If the cipher specified by config is a candidate, we'll use that. configuredCipher := config.Cipher() for _, c := range candidateCiphers { @@ -325,17 +419,29 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint } for _, key := range encryptKeys { - if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { + if err := packet.SerializeEncryptedKey(keyWriter, key.PublicKey, cipher, symKey, config); err != nil { return nil, err } } - payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) + var payload io.WriteCloser + if aeadSupported { + payload, err = packet.SerializeAEADEncrypted(dataWriter, symKey, cipher, mode, config) + if err != nil { + return + } + } else { + payload, err = packet.SerializeSymmetricallyEncrypted(dataWriter, cipher, symKey, config) + if err != nil { + return + } + } + payload, err = handleCompression(payload, candidateCompression, config) if err != nil { - return + return nil, err } - return writeAndSign(payload, candidateHashes, signed, hints, config) + return writeAndSign(payload, candidateHashes, signed, hints, sigType, config) } // Sign signs a message. The resulting WriteCloser must be closed after the @@ -355,13 +461,17 @@ func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Con hashToHashId(crypto.SHA1), hashToHashId(crypto.RIPEMD160), } - defaultHashes := candidateHashes[len(candidateHashes)-1:] - preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash + defaultHashes := candidateHashes[0:1] + preferredHashes := signed.PrimaryIdentity().SelfSignature.PreferredHash if len(preferredHashes) == 0 { preferredHashes = defaultHashes } candidateHashes = intersectPreferences(candidateHashes, preferredHashes) - return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config) + if len(candidateHashes) == 0 { + return nil, errors.InvalidArgumentError("cannot sign because signing key shares no common algorithms with candidate hashes") + } + + return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, packet.SigTypeBinary, config) } // signatureWriter hashes the contents of a message while passing it along to @@ -371,23 +481,35 @@ type signatureWriter struct { encryptedData io.WriteCloser literalData io.WriteCloser hashType crypto.Hash + wrappedHash hash.Hash h hash.Hash signer *packet.PrivateKey + sigType packet.SignatureType config *packet.Config + metadata *packet.LiteralData // V5 signatures protect document metadata } func (s signatureWriter) Write(data []byte) (int, error) { - s.h.Write(data) - return s.literalData.Write(data) + s.wrappedHash.Write(data) + switch s.sigType { + case packet.SigTypeBinary: + return s.literalData.Write(data) + case packet.SigTypeText: + flag := 0 + return writeCanonical(s.literalData, data, &flag) + } + return 0, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(s.sigType))) } func (s signatureWriter) Close() error { sig := &packet.Signature{ - SigType: packet.SigTypeBinary, + Version: s.signer.Version, + SigType: s.sigType, PubKeyAlgo: s.signer.PubKeyAlgo, Hash: s.hashType, CreationTime: s.config.Now(), IssuerKeyId: &s.signer.KeyId, + Metadata: s.metadata, } if err := sig.Sign(s.h, s.signer, s.config); err != nil { @@ -416,3 +538,31 @@ func (c noOpCloser) Write(data []byte) (n int, err error) { func (c noOpCloser) Close() error { return nil } + +func handleCompression(compressed io.WriteCloser, candidateCompression []uint8, config *packet.Config) (data io.WriteCloser, err error) { + data = compressed + confAlgo := config.Compression() + if confAlgo == packet.CompressionNone { + return + } + finalAlgo := packet.CompressionNone + // if compression specified by config available we will use it + for _, c := range candidateCompression { + if uint8(confAlgo) == c { + finalAlgo = confAlgo + break + } + } + + if finalAlgo != packet.CompressionNone { + var compConfig *packet.CompressionConfig + if config != nil { + compConfig = config.CompressionConfig + } + data, err = packet.SerializeCompressed(compressed, finalAlgo, compConfig) + if err != nil { + return + } + } + return data, nil +} diff --git a/vendor/github.com/acomagu/bufpipe/README.md b/vendor/github.com/acomagu/bufpipe/README.md new file mode 100644 index 0000000..19df083 --- /dev/null +++ b/vendor/github.com/acomagu/bufpipe/README.md @@ -0,0 +1,42 @@ +# bufpipe: Buffered Pipe + +[![CircleCI](https://img.shields.io/circleci/build/github/acomagu/bufpipe.svg?style=flat-square)](https://circleci.com/gh/acomagu/bufpipe) [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/acomagu/bufpipe) + +The buffered version of io.Pipe. It's safe for concurrent use. + +## How does it differ from io.Pipe? + +Writes never block because the pipe has variable-sized buffer. + +```Go +r, w := bufpipe.New(nil) +io.WriteString(w, "abc") // No blocking. +io.WriteString(w, "def") // No blocking, too. +w.Close() +io.Copy(os.Stdout, r) +// Output: abcdef +``` + +[Playground](https://play.golang.org/p/PdyBAS3pVob) + +## How does it differ from bytes.Buffer? + +Reads block if the internal buffer is empty until the writer is closed. + +```Go +r, w := bufpipe.New(nil) + +done := make(chan struct{}) +go func() { + io.Copy(os.Stdout, r) // The reads block until the writer is closed. + done <- struct{}{} +}() + +io.WriteString(w, "abc") +io.WriteString(w, "def") +w.Close() +<-done +// Output: abcdef +``` + +[Playground](https://play.golang.org/p/UppmyLeRgX6) diff --git a/vendor/github.com/acomagu/bufpipe/bufpipe.go b/vendor/github.com/acomagu/bufpipe/bufpipe.go new file mode 100644 index 0000000..846dbcc --- /dev/null +++ b/vendor/github.com/acomagu/bufpipe/bufpipe.go @@ -0,0 +1,128 @@ +package bufpipe + +import ( + "bytes" + "errors" + "io" + "sync" +) + +// ErrClosedPipe is the error used for read or write operations on a closed pipe. +var ErrClosedPipe = errors.New("bufpipe: read/write on closed pipe") + +type pipe struct { + cond *sync.Cond + buf *bytes.Buffer + rerr, werr error +} + +// A PipeReader is the read half of a pipe. +type PipeReader struct { + *pipe +} + +// A PipeWriter is the write half of a pipe. +type PipeWriter struct { + *pipe +} + +// New creates a synchronous pipe using buf as its initial contents. It can be +// used to connect code expecting an io.Reader with code expecting an io.Writer. +// +// Unlike io.Pipe, writes never block because the internal buffer has variable +// size. Reads block only when the buffer is empty. +// +// It is safe to call Read and Write in parallel with each other or with Close. +// Parallel calls to Read and parallel calls to Write are also safe: the +// individual calls will be gated sequentially. +// +// The new pipe takes ownership of buf, and the caller should not use buf after +// this call. New is intended to prepare a PipeReader to read existing data. It +// can also be used to set the initial size of the internal buffer for writing. +// To do that, buf should have the desired capacity but a length of zero. +func New(buf []byte) (*PipeReader, *PipeWriter) { + p := &pipe{ + buf: bytes.NewBuffer(buf), + cond: sync.NewCond(new(sync.Mutex)), + } + return &PipeReader{ + pipe: p, + }, &PipeWriter{ + pipe: p, + } +} + +// Read implements the standard Read interface: it reads data from the pipe, +// reading from the internal buffer, otherwise blocking until a writer arrives +// or the write end is closed. If the write end is closed with an error, that +// error is returned as err; otherwise err is io.EOF. +func (r *PipeReader) Read(data []byte) (int, error) { + r.cond.L.Lock() + defer r.cond.L.Unlock() + +RETRY: + n, err := r.buf.Read(data) + // If not closed and no read, wait for writing. + if err == io.EOF && r.rerr == nil && n == 0 { + r.cond.Wait() + goto RETRY + } + if err == io.EOF { + return n, r.rerr + } + return n, err +} + +// Close closes the reader; subsequent writes from the write half of the pipe +// will return error ErrClosedPipe. +func (r *PipeReader) Close() error { + return r.CloseWithError(nil) +} + +// CloseWithError closes the reader; subsequent writes to the write half of the +// pipe will return the error err. +func (r *PipeReader) CloseWithError(err error) error { + r.cond.L.Lock() + defer r.cond.L.Unlock() + + if err == nil { + err = ErrClosedPipe + } + r.werr = err + return nil +} + +// Write implements the standard Write interface: it writes data to the internal +// buffer. If the read end is closed with an error, that err is returned as err; +// otherwise err is ErrClosedPipe. +func (w *PipeWriter) Write(data []byte) (int, error) { + w.cond.L.Lock() + defer w.cond.L.Unlock() + + if w.werr != nil { + return 0, w.werr + } + + n, err := w.buf.Write(data) + w.cond.Signal() + return n, err +} + +// Close closes the writer; subsequent reads from the read half of the pipe will +// return io.EOF once the internal buffer get empty. +func (w *PipeWriter) Close() error { + return w.CloseWithError(nil) +} + +// Close closes the writer; subsequent reads from the read half of the pipe will +// return err once the internal buffer get empty. +func (w *PipeWriter) CloseWithError(err error) error { + w.cond.L.Lock() + defer w.cond.L.Unlock() + + if err == nil { + err = io.EOF + } + w.rerr = err + return nil +} diff --git a/vendor/github.com/acomagu/bufpipe/doc.go b/vendor/github.com/acomagu/bufpipe/doc.go new file mode 100644 index 0000000..16a3948 --- /dev/null +++ b/vendor/github.com/acomagu/bufpipe/doc.go @@ -0,0 +1,2 @@ +// Package bufpipe provides a IO pipe, has variable-sized buffer. +package bufpipe diff --git a/vendor/github.com/acomagu/bufpipe/go.mod b/vendor/github.com/acomagu/bufpipe/go.mod new file mode 100644 index 0000000..bab097a --- /dev/null +++ b/vendor/github.com/acomagu/bufpipe/go.mod @@ -0,0 +1,5 @@ +module github.com/acomagu/bufpipe + +go 1.12 + +require github.com/matryer/is v1.2.0 diff --git a/vendor/github.com/acomagu/bufpipe/go.sum b/vendor/github.com/acomagu/bufpipe/go.sum new file mode 100644 index 0000000..6378c9b --- /dev/null +++ b/vendor/github.com/acomagu/bufpipe/go.sum @@ -0,0 +1,2 @@ +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= diff --git a/vendor/github.com/adrg/xdg/README.md b/vendor/github.com/adrg/xdg/README.md index 07c8ca5..a52d80e 100644 --- a/vendor/github.com/adrg/xdg/README.md +++ b/vendor/github.com/adrg/xdg/README.md @@ -1,6 +1,6 @@

- xdg logo + xdg logo

@@ -44,7 +44,7 @@ applications should use the XDG defined locations instead of hardcoding paths. The package also includes the locations of well known [user directories](https://wiki.archlinux.org/index.php/XDG_user_directories) and an implementation of the [state directory](https://wiki.debian.org/XDGBaseDirectorySpecification#Proposal:_STATE_directory) proposal. -Windows, macOS and most flavors of Unix are supported. +Most flavors of Unix, Windows, macOS and Plan 9 are supported. Full documentation can be found at: https://pkg.go.dev/github.com/adrg/xdg. @@ -58,75 +58,56 @@ present in the environment. #### XDG Base Directory -| | Unix | macOS | Windows | -| :-------------- | :---------------------------------- | :------------------------------------------------------------------------------------ | :-------------------------------------- | -| XDG_DATA_HOME | `~/.local/share` | `~/Library/Application Support` | `%LOCALAPPDATA%` | -| XDG_DATA_DIRS | `/usr/local/share`
`/usr/share` | `/Library/Application Support` | `%APPDATA%\Roaming`
`%PROGRAMDATA%` | -| XDG_CONFIG_HOME | `~/.config` | `~/Library/Application Support` | `%LOCALAPPDATA%` | -| XDG_CONFIG_DIRS | `/etc/xdg` | `~/Library/Preferences`
`/Library/Application Support`
`/Library/Preferences` | `%PROGRAMDATA%` | -| XDG_CACHE_HOME | `~/.cache` | `~/Library/Caches` | `%LOCALAPPDATA%\cache` | -| XDG_RUNTIME_DIR | `/run/user/UID` | `~/Library/Application Support` | `%LOCALAPPDATA%` | +| | Unix | macOS | Windows | Plan 9 | +| :--------------------------------------------- | :---------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :------------------------- | +| XDG_DATA_HOME | ~/.local/share | ~/Library/Application Support | %LOCALAPPDATA% | $home/lib | +| XDG_DATA_DIRS | /usr/local/share
/usr/share | /Library/Application Support | %APPDATA%\Roaming
%PROGRAMDATA% | /lib | +| XDG_CONFIG_HOME | ~/.config | ~/Library/Application Support | %LOCALAPPDATA% | $home/lib | +| XDG_CONFIG_DIRS | /etc/xdg | ~/Library/Preferences
/Library/Application Support
/Library/Preferences | %PROGRAMDATA% | /lib | +| XDG_CACHE_HOME | ~/.cache | ~/Library/Caches | %LOCALAPPDATA%\cache | $home/lib/cache | +| XDG_RUNTIME_DIR | /run/user/UID | ~/Library/Application Support | %LOCALAPPDATA% | /tmp | #### XDG user directories -| | Unix | macOS | Windows | -| :------------------ | :------------ | :------------ | :------------------------ | -| XDG_DESKTOP_DIR | `~/Desktop` | `~/Desktop` | `%USERPROFILE%/Desktop` | -| XDG_DOWNLOAD_DIR | `~/Downloads` | `~/Downloads` | `%USERPROFILE%/Downloads` | -| XDG_DOCUMENTS_DIR | `~/Documents` | `~/Documents` | `%USERPROFILE%/Documents` | -| XDG_MUSIC_DIR | `~/Music` | `~/Music` | `%USERPROFILE%/Music` | -| XDG_PICTURES_DIR | `~/Pictures` | `~/Pictures` | `%USERPROFILE%/Pictures` | -| XDG_VIDEOS_DIR | `~/Videos` | `~/Movies` | `%USERPROFILE%/Videos` | -| XDG_TEMPLATES_DIR | `~/Templates` | `~/Templates` | `%USERPROFILE%/Templates` | -| XDG_PUBLICSHARE_DIR | `~/Public` | `~/Public` | `%PUBLIC%` | +| | Unix | macOS | Windows | Plan 9 | +| :------------------------------------------------- | :--------------------- | :--------------------- | :--------------------------------- | :------------------------- | +| XDG_DESKTOP_DIR | ~/Desktop | ~/Desktop | %USERPROFILE%\Desktop | $home/desktop | +| XDG_DOWNLOAD_DIR | ~/Downloads | ~/Downloads | %USERPROFILE%\Downloads | $home/downloads | +| XDG_DOCUMENTS_DIR | ~/Documents | ~/Documents | %USERPROFILE%\Documents | $home/documents | +| XDG_MUSIC_DIR | ~/Music | ~/Music | %USERPROFILE%\Music | $home/music | +| XDG_PICTURES_DIR | ~/Pictures | ~/Pictures | %USERPROFILE%\Pictures | $home/pictures | +| XDG_VIDEOS_DIR | ~/Videos | ~/Movies | %USERPROFILE%\Videos | $home/videos | +| XDG_TEMPLATES_DIR | ~/Templates | ~/Templates | %USERPROFILE%\Templates | $home/templates | +| XDG_PUBLICSHARE_DIR | ~/Public | ~/Public | %PUBLIC% | $home/public | #### Non-standard directories State directory -``` -Unix - • ~/.local/state -macOS - • ~/Library/Application Support -Windows - • %LOCALAPPDATA% -``` +| | Unix | macOS | Windows | Plan 9 | +| :-------------------------------------------- | :------------------------ | :--------------------------------------- | :------------------------ | :------------------------- | +| XDG_STATE_HOME | ~/.local/state | ~/Library/Application Support | %LOCALAPPDATA% | $home/lib/state | Application directories -``` -Unix - • $XDG_DATA_HOME/applications - • ~/.local/share/applications - • /usr/local/share/applications - • /usr/share/applications - • $XDG_DATA_DIRS/applications -macOS - • /Applications -Windows - • %APPDATA%\Roaming\Microsoft\Windows\Start Menu\Programs -``` +| Unix | macOS | Windows | Plan 9 | +| :--------------------------------------- | :----------------------- | :----------------------------------------------------------------- | :-------------------- | +| $XDG_DATA_HOME/applications | /Applications | %APPDATA%\Roaming\Microsoft\Windows\Start Menu\Programs | $home/bin | +| ~/.local/share/applications | | | /bin | +| /usr/local/share/applications | | | | +| /usr/share/applications | | | | +| $XDG_DATA_DIRS/applications | | | | Font directories -``` -Unix - • $XDG_DATA_HOME/fonts - • ~/.fonts - • ~/.local/share/fonts - • /usr/local/share/fonts - • /usr/share/fonts - • $XDG_DATA_DIRS/fonts -macOS - • ~/Library/Fonts - • /Library/Fonts - • /System/Library/Fonts - • /Network/Library/Fonts -Windows - • %windir%\Fonts - • %LOCALAPPDATA%\Microsoft\Windows\Fonts -``` +| Unix | macOS | Windows | Plan 9 | +| :-------------------------------- | :-------------------------------- | :------------------------------------------------ | :------------------------ | +| $XDG_DATA_HOME/fonts | ~/Library/Fonts | %windir%\Fonts | $home/lib/font | +| ~/.fonts | /Library/Fonts | %LOCALAPPDATA%\Microsoft\Windows\Fonts | /lib/font | +| ~/.local/share/fonts | /System/Library/Fonts | | | +| /usr/local/share/fonts | /Network/Library/Fonts | | | +| /usr/share/fonts | | | | +| $XDG_DATA_DIRS/fonts | | | | ## Usage @@ -228,7 +209,8 @@ See [CONTRIBUTING.MD](CONTRIBUTING.md). [wichert](https://github.com/wichert), [bouncepaw](https://github.com/bouncepaw), [gabriel-vasile](https://github.com/gabriel-vasile), -[KalleDK](https://github.com/KalleDK). +[KalleDK](https://github.com/KalleDK), +[djdv](https://github.com/djdv). ## References diff --git a/vendor/github.com/adrg/xdg/codecov.yml b/vendor/github.com/adrg/xdg/codecov.yml new file mode 100644 index 0000000..54ee338 --- /dev/null +++ b/vendor/github.com/adrg/xdg/codecov.yml @@ -0,0 +1,11 @@ +coverage: + status: + project: + default: + target: 90% + threshold: 1% + patch: + default: + target: 100% +ignore: + - "paths_plan9.go" diff --git a/vendor/github.com/adrg/xdg/go.mod b/vendor/github.com/adrg/xdg/go.mod index 6555bb8..48ac549 100644 --- a/vendor/github.com/adrg/xdg/go.mod +++ b/vendor/github.com/adrg/xdg/go.mod @@ -2,4 +2,4 @@ module github.com/adrg/xdg go 1.14 -require github.com/stretchr/testify v1.6.1 +require github.com/stretchr/testify v1.7.0 diff --git a/vendor/github.com/adrg/xdg/go.sum b/vendor/github.com/adrg/xdg/go.sum index afe7890..26500d5 100644 --- a/vendor/github.com/adrg/xdg/go.sum +++ b/vendor/github.com/adrg/xdg/go.sum @@ -2,9 +2,10 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/vendor/github.com/adrg/xdg/paths_plan9.go b/vendor/github.com/adrg/xdg/paths_plan9.go new file mode 100644 index 0000000..b35b02b --- /dev/null +++ b/vendor/github.com/adrg/xdg/paths_plan9.go @@ -0,0 +1,42 @@ +package xdg + +import ( + "path/filepath" +) + +func initBaseDirs(home string) { + homeLibDir := filepath.Join(home, "lib") + rootLibDir := "/lib" + + // Initialize base directories. + baseDirs.dataHome = xdgPath(envDataHome, homeLibDir) + baseDirs.data = xdgPaths(envDataDirs, rootLibDir) + baseDirs.configHome = xdgPath(envConfigHome, homeLibDir) + baseDirs.config = xdgPaths(envConfigDirs, rootLibDir) + baseDirs.cacheHome = xdgPath(envCacheHome, filepath.Join(homeLibDir, "cache")) + baseDirs.runtime = xdgPath(envRuntimeDir, "/tmp") + + // Initialize non-standard directories. + baseDirs.stateHome = xdgPath(envStateHome, filepath.Join(homeLibDir, "state")) + + baseDirs.applications = []string{ + filepath.Join(home, "bin"), + "/bin", + } + + baseDirs.fonts = []string{ + filepath.Join(homeLibDir, "font"), + "/lib/font", + } +} + +func initUserDirs(home string) { + UserDirs.Desktop = xdgPath(envDesktopDir, filepath.Join(home, "desktop")) + UserDirs.Download = xdgPath(envDownloadDir, filepath.Join(home, "downloads")) + UserDirs.Documents = xdgPath(envDocumentsDir, filepath.Join(home, "documents")) + UserDirs.Music = xdgPath(envMusicDir, filepath.Join(home, "music")) + UserDirs.Pictures = xdgPath(envPicturesDir, filepath.Join(home, "pictures")) + UserDirs.Videos = xdgPath(envVideosDir, filepath.Join(home, "videos")) + UserDirs.Templates = xdgPath(envTemplatesDir, filepath.Join(home, "templates")) + UserDirs.PublicShare = xdgPath(envPublicShareDir, filepath.Join(home, "public")) +} diff --git a/vendor/github.com/adrg/xdg/paths_unix.go b/vendor/github.com/adrg/xdg/paths_unix.go index 8dd0766..3edef5f 100644 --- a/vendor/github.com/adrg/xdg/paths_unix.go +++ b/vendor/github.com/adrg/xdg/paths_unix.go @@ -1,4 +1,4 @@ -// +build aix dragonfly freebsd linux nacl netbsd openbsd solaris +// +build aix dragonfly freebsd js,wasm nacl linux netbsd openbsd solaris package xdg diff --git a/vendor/github.com/adrg/xdg/stat.go b/vendor/github.com/adrg/xdg/stat.go new file mode 100644 index 0000000..4ddcf8b --- /dev/null +++ b/vendor/github.com/adrg/xdg/stat.go @@ -0,0 +1,10 @@ +// +build !windows + +package xdg + +import "os" + +func pathExists(path string) bool { + _, err := os.Stat(path) + return err == nil || os.IsExist(err) +} diff --git a/vendor/github.com/adrg/xdg/stat_windows.go b/vendor/github.com/adrg/xdg/stat_windows.go new file mode 100644 index 0000000..8065975 --- /dev/null +++ b/vendor/github.com/adrg/xdg/stat_windows.go @@ -0,0 +1,15 @@ +package xdg + +import ( + "os" + "path/filepath" +) + +func pathExists(path string) bool { + fi, err := os.Lstat(path) + if fi != nil && fi.Mode()&os.ModeSymlink != 0 { + _, err = filepath.EvalSymlinks(path) + } + + return err == nil || os.IsExist(err) +} diff --git a/vendor/github.com/adrg/xdg/utils.go b/vendor/github.com/adrg/xdg/utils.go index 8d5b196..8cd8104 100644 --- a/vendor/github.com/adrg/xdg/utils.go +++ b/vendor/github.com/adrg/xdg/utils.go @@ -33,11 +33,6 @@ func homeDir() string { return "" } -func exists(path string) bool { - _, err := os.Stat(path) - return err == nil || os.IsExist(err) -} - func expandPath(path, homeDir string) string { if path == "" || homeDir == "" { return path @@ -58,7 +53,7 @@ func createPath(name string, paths []string) (string, error) { path := filepath.Join(p, name) dir := filepath.Dir(path) - if exists(dir) { + if pathExists(dir) { return path, nil } if err := os.MkdirAll(dir, os.ModeDir|0700); err == nil { @@ -76,7 +71,7 @@ func searchFile(name string, paths []string) (string, error) { var searchedPaths []string for _, p := range paths { path := filepath.Join(p, name) - if exists(path) { + if pathExists(path) { return path, nil } diff --git a/vendor/github.com/alecthomas/chroma/.golangci.yml b/vendor/github.com/alecthomas/chroma/.golangci.yml index 9a73537..ba75573 100644 --- a/vendor/github.com/alecthomas/chroma/.golangci.yml +++ b/vendor/github.com/alecthomas/chroma/.golangci.yml @@ -25,6 +25,17 @@ linters: - testpackage - godot - nestif + - paralleltest + - nlreturn + - cyclop + - exhaustivestruct + - gci + - gofumpt + - errorlint + - exhaustive + - ifshort + - wrapcheck + - stylecheck linters-settings: govet: @@ -36,6 +47,11 @@ linters-settings: goconst: min-len: 8 min-occurrences: 3 + forbidigo: + forbid: + - (Must)?NewLexer + exclude_godoc_examples: false + issues: max-per-linter: 0 diff --git a/vendor/github.com/alecthomas/chroma/.goreleaser.yml b/vendor/github.com/alecthomas/chroma/.goreleaser.yml index 99d13e3..f8abfdd 100644 --- a/vendor/github.com/alecthomas/chroma/.goreleaser.yml +++ b/vendor/github.com/alecthomas/chroma/.goreleaser.yml @@ -6,6 +6,8 @@ release: brews: - install: bin.install "chroma" +env: + - CGO_ENABLED=0 builds: - goos: - linux diff --git a/vendor/github.com/alecthomas/chroma/.travis.yml b/vendor/github.com/alecthomas/chroma/.travis.yml deleted file mode 100644 index 4850b0c..0000000 --- a/vendor/github.com/alecthomas/chroma/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -sudo: false -language: go -go: - - "1.13.x" -script: - - go test -v ./... - - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.26.0 - - ./bin/golangci-lint run - - git clean -fdx . -after_success: - curl -sL https://git.io/goreleaser | bash && goreleaser - diff --git a/vendor/github.com/alecthomas/chroma/Makefile b/vendor/github.com/alecthomas/chroma/Makefile index 1b8320a..010ec03 100644 --- a/vendor/github.com/alecthomas/chroma/Makefile +++ b/vendor/github.com/alecthomas/chroma/Makefile @@ -1,5 +1,7 @@ .PHONY: chromad upload all +VERSION ?= $(shell git describe --tags --dirty --always) + all: README.md tokentype_string.go README.md: lexers/*/*.go @@ -9,10 +11,8 @@ tokentype_string.go: types.go go generate chromad: - (cd ./cmd/chromad && go get github.com/GeertJohan/go.rice/rice@master && go install github.com/GeertJohan/go.rice/rice) rm -f chromad - (export CGOENABLED=0 GOOS=linux ; cd ./cmd/chromad && go build -o ../../chromad .) - rice append -i ./cmd/chromad --exec=./chromad + (export CGOENABLED=0 GOOS=linux ; cd ./cmd/chromad && go build -ldflags="-X 'main.version=$(VERSION)'" -o ../../chromad .) upload: chromad scp chromad root@swapoff.org: && \ diff --git a/vendor/github.com/alecthomas/chroma/README.md b/vendor/github.com/alecthomas/chroma/README.md index 490adea..95d54e6 100644 --- a/vendor/github.com/alecthomas/chroma/README.md +++ b/vendor/github.com/alecthomas/chroma/README.md @@ -1,4 +1,4 @@ -# Chroma — A general purpose syntax highlighter in pure Go [![Golang Documentation](https://godoc.org/github.com/alecthomas/chroma?status.svg)](https://godoc.org/github.com/alecthomas/chroma) [![Build Status](https://travis-ci.org/alecthomas/chroma.svg)](https://travis-ci.org/alecthomas/chroma) [![Gitter chat](https://badges.gitter.im/alecthomas.svg)](https://gitter.im/alecthomas/Lobby) +# Chroma — A general purpose syntax highlighter in pure Go [![Golang Documentation](https://godoc.org/github.com/alecthomas/chroma?status.svg)](https://godoc.org/github.com/alecthomas/chroma) [![CircleCI](https://img.shields.io/circleci/project/github/alecthomas/chroma.svg)](https://circleci.com/gh/alecthomas/chroma) [![Go Report Card](https://goreportcard.com/badge/github.com/alecthomas/chroma)](https://goreportcard.com/report/github.com/alecthomas/chroma) [![Slack chat](https://img.shields.io/static/v1?logo=slack&style=flat&label=slack&color=green&message=gophers)](https://invite.slack.golangbridge.org/) > **NOTE:** As Chroma has just been released, its API is still in flux. That said, the high-level interface should not change significantly. @@ -36,29 +36,30 @@ translators for Pygments lexers and styles. Prefix | Language :----: | -------- A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk -B | Ballerina, Base Makefile, Bash, Batchfile, BlitzBasic, BNF, Brainfuck -C | C, C#, C++, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython -D | D, Dart, Diff, Django/Jinja, Docker, DTD +B | Ballerina, Base Makefile, Bash, Batchfile, BibTeX, BlitzBasic, BNF, Brainfuck +C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython +D | D, Dart, Diff, Django/Jinja, Docker, DTD, Dylan E | EBNF, Elixir, Elm, EmacsLisp, Erlang F | Factor, Fish, Forth, Fortran, FSharp -G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groovy -H | Handlebars, Haskell, Haxe, HCL, Hexdump, HTML, HTTP, Hy -I | Idris, INI, Io +G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, Gherkin, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groff, Groovy +H | Handlebars, Haskell, Haxe, HCL, Hexdump, HLB, HTML, HTTP, Hy +I | Idris, Igor, INI, Io J | J, Java, JavaScript, JSON, Julia, Jungle K | Kotlin L | Lighttpd configuration file, LLVM, Lua M | Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, MLIR, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL N | NASM, Newspeak, Nginx configuration file, Nim, Nix O | Objective-C, OCaml, Octave, OpenSCAD, Org Mode -P | PacmanConf, Perl, PHP, Pig, PkgConfig, PL/pgSQL, plaintext, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, Protocol Buffer, Puppet, Python, Python 3 +P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, PromQL, Protocol Buffer, Puppet, Python 2, Python Q | QBasic -R | R, Racket, Ragel, react, reg, reStructuredText, Rexx, Ruby, Rust -S | Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, SML, Snobol, Solidity, SPARQL, SQL, SquidConf, Swift, SYSTEMD, systemverilog +R | R, Racket, Ragel, Raku, react, ReasonML, reg, reStructuredText, Rexx, Ruby, Rust +S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Standard ML, Stylus, Svelte, Swift, SYSTEMD, systemverilog T | TableGen, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData V | VB.net, verilog, VHDL, VimL, vue W | WDTE X | XML, Xorg -Y | YAML +Y | YAML, YANG +Z | Zig _I will attempt to keep this section up to date, but an authoritative list can be @@ -183,7 +184,7 @@ following constructor options: - `ClassPrefix(prefix)` - prefix each generated CSS class. - `TabWidth(width)` - Set the rendered tab width, in characters. - `WithLineNumbers()` - Render line numbers (style with `LineNumbers`). -- `LinkableLineNumbers()` - Make the line numbers linkable. +- `LinkableLineNumbers()` - Make the line numbers linkable and be a link to themselves. - `HighlightLines(ranges)` - Highlight lines in these ranges (style with `LineHighlight`). - `LineNumbersInTable()` - Use a table for formatting line numbers and code, rather than spans. @@ -209,13 +210,13 @@ using the included Python 3 script `pygments2chroma.py`. I use something like the following: ```sh -python3 ~/Projects/chroma/_tools/pygments2chroma.py \ +python3 _tools/pygments2chroma.py \ pygments.lexers.jvm.KotlinLexer \ - > ~/Projects/chroma/lexers/kotlin.go \ - && gofmt -s -w ~/Projects/chroma/lexers/*.go + > lexers/k/kotlin.go \ + && gofmt -s -w lexers/k/kotlin.go ``` -See notes in [pygments-lexers.go](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt) +See notes in [pygments-lexers.txt](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt) for a list of lexers, and notes on some of the issues importing them. @@ -254,12 +255,30 @@ A command-line interface to Chroma is included. It can be installed with: go get -u github.com/alecthomas/chroma/cmd/chroma ``` +The CLI can be used as a preprocessor to colorise output of `less(1)`, +see documentation for the `LESSOPEN` environment variable. + +The `--fail` flag can be used to suppress output and return with exit status +1 to facilitate falling back to some other preprocessor in case chroma +does not resolve a specific lexer to use for the given file. For example: + +```shell +export LESSOPEN='| p() { chroma --fail "$1" || cat "$1"; }; p "%s"' +``` + +Replace `cat` with your favourite fallback preprocessor. + +When invoked as `.lessfilter`, the `--fail` flag is automatically turned +on under the hood for easy integration with [lesspipe shipping with +Debian and derivatives](https://manpages.debian.org/lesspipe#USER_DEFINED_FILTERS); +for that setup the `chroma` executable can be just symlinked to `~/.lessfilter`. + ## What's missing compared to Pygments? - Quite a few lexers, for various reasons (pull-requests welcome): - Pygments lexers for complex languages often include custom code to - handle certain aspects, such as Perl6's ability to nest code inside + handle certain aspects, such as Raku's ability to nest code inside regular expressions. These require time and effort to convert. - I mostly only converted languages I had heard of, to reduce the porting cost. - Some more esoteric features of Pygments are omitted for simplicity. diff --git a/vendor/github.com/alecthomas/chroma/formatters/html/html.go b/vendor/github.com/alecthomas/chroma/formatters/html/html.go index ad48da1..5121529 100644 --- a/vendor/github.com/alecthomas/chroma/formatters/html/html.go +++ b/vendor/github.com/alecthomas/chroma/formatters/html/html.go @@ -131,7 +131,7 @@ var ( } defaultPreWrapper = preWrapper{ start: func(code bool, styleAttr string) string { - return fmt.Sprintf("", styleAttr) + return fmt.Sprintf(`
`, styleAttr)
 		},
 		end: func(code bool) string {
 			return "
" @@ -211,7 +211,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma. fmt.Fprintf(w, "", f.styleAttr(css, chroma.LineHighlight)) } - fmt.Fprintf(w, "%*d\n", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), lineDigits, line) + fmt.Fprintf(w, "%s\n", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line)) if highlight { fmt.Fprintf(w, "") @@ -237,7 +237,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma. } if f.lineNumbers && !wrapInTable { - fmt.Fprintf(w, "%*d", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), lineDigits, line) + fmt.Fprintf(w, "%s", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line)) } for _, token := range tokens { @@ -272,7 +272,19 @@ func (f *Formatter) lineIDAttribute(line int) string { if !f.linkableLineNumbers { return "" } - return fmt.Sprintf(" id=\"%s%d\"", f.lineNumbersIDPrefix, line) + return fmt.Sprintf(" id=\"%s\"", f.lineID(line)) +} + +func (f *Formatter) lineTitleWithLinkIfNeeded(lineDigits, line int) string { + title := fmt.Sprintf("%*d", lineDigits, line) + if !f.linkableLineNumbers { + return title + } + return fmt.Sprintf("%s", f.lineID(line), title) +} + +func (f *Formatter) lineID(line int) string { + return fmt.Sprintf("%s%d", f.lineNumbersIDPrefix, line) } func (f *Formatter) shouldHighlight(highlightIndex, line int) (bool, bool) { diff --git a/vendor/github.com/alecthomas/chroma/formatters/svg/svg.go b/vendor/github.com/alecthomas/chroma/formatters/svg/svg.go index 631fa14..5cfd950 100644 --- a/vendor/github.com/alecthomas/chroma/formatters/svg/svg.go +++ b/vendor/github.com/alecthomas/chroma/formatters/svg/svg.go @@ -120,7 +120,7 @@ func maxLineWidth(lines [][]chroma.Token) int { for _, tokens := range lines { length := 0 for _, token := range tokens { - length += len(strings.Replace(token.String(), ` `, " ", -1)) + length += len(strings.ReplaceAll(token.String(), ` `, " ")) } if length > maxWidth { maxWidth = length @@ -136,7 +136,7 @@ func (f *Formatter) writeTokenBackgrounds(w io.Writer, lines [][]chroma.Token, s for index, tokens := range lines { lineLength := 0 for _, token := range tokens { - length := len(strings.Replace(token.String(), ` `, " ", -1)) + length := len(strings.ReplaceAll(token.String(), ` `, " ")) tokenBackground := style.Get(token.Type).Background if tokenBackground.IsSet() && tokenBackground != style.Get(chroma.Background).Background { fmt.Fprintf(w, "\n", escapeString(token.String()), lineLength, 1.2*float64(index)+0.25, length, style.Get(token.Type).Background.String()) diff --git a/vendor/github.com/alecthomas/chroma/formatters/tty_indexed.go b/vendor/github.com/alecthomas/chroma/formatters/tty_indexed.go index eb90ea7..47fbb1a 100644 --- a/vendor/github.com/alecthomas/chroma/formatters/tty_indexed.go +++ b/vendor/github.com/alecthomas/chroma/formatters/tty_indexed.go @@ -17,6 +17,20 @@ var c = chroma.MustParseColour var ttyTables = map[int]*ttyTable{ 8: { + foreground: map[chroma.Colour]string{ + c("#000000"): "\033[30m", c("#7f0000"): "\033[31m", c("#007f00"): "\033[32m", c("#7f7fe0"): "\033[33m", + c("#00007f"): "\033[34m", c("#7f007f"): "\033[35m", c("#007f7f"): "\033[36m", c("#e5e5e5"): "\033[37m", + c("#555555"): "\033[1m\033[30m", c("#ff0000"): "\033[1m\033[31m", c("#00ff00"): "\033[1m\033[32m", c("#ffff00"): "\033[1m\033[33m", + c("#0000ff"): "\033[1m\033[34m", c("#ff00ff"): "\033[1m\033[35m", c("#00ffff"): "\033[1m\033[36m", c("#ffffff"): "\033[1m\033[37m", + }, + background: map[chroma.Colour]string{ + c("#000000"): "\033[40m", c("#7f0000"): "\033[41m", c("#007f00"): "\033[42m", c("#7f7fe0"): "\033[43m", + c("#00007f"): "\033[44m", c("#7f007f"): "\033[45m", c("#007f7f"): "\033[46m", c("#e5e5e5"): "\033[47m", + c("#555555"): "\033[1m\033[40m", c("#ff0000"): "\033[1m\033[41m", c("#00ff00"): "\033[1m\033[42m", c("#ffff00"): "\033[1m\033[43m", + c("#0000ff"): "\033[1m\033[44m", c("#ff00ff"): "\033[1m\033[45m", c("#00ffff"): "\033[1m\033[46m", c("#ffffff"): "\033[1m\033[47m", + }, + }, + 16: { foreground: map[chroma.Colour]string{ c("#000000"): "\033[30m", c("#7f0000"): "\033[31m", c("#007f00"): "\033[32m", c("#7f7fe0"): "\033[33m", c("#00007f"): "\033[34m", c("#7f007f"): "\033[35m", c("#007f7f"): "\033[36m", c("#e5e5e5"): "\033[37m", @@ -227,15 +241,11 @@ type indexedTTYFormatter struct { func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) { theme := styleToEscapeSequence(c.table, style) for token := it(); token != chroma.EOF; token = it() { - // TODO: Cache token lookups? clr, ok := theme[token.Type] if !ok { clr, ok = theme[token.Type.SubCategory()] if !ok { clr = theme[token.Type.Category()] - // if !ok { - // clr = theme[chroma.InheritStyle] - // } } } if clr != "" { @@ -249,10 +259,22 @@ func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma return nil } +// TTY is an 8-colour terminal formatter. +// +// The Lab colour space is used to map RGB values to the most appropriate index colour. +var TTY = Register("terminal", &indexedTTYFormatter{ttyTables[8]}) + // TTY8 is an 8-colour terminal formatter. // // The Lab colour space is used to map RGB values to the most appropriate index colour. -var TTY8 = Register("terminal", &indexedTTYFormatter{ttyTables[8]}) +var TTY8 = Register("terminal8", &indexedTTYFormatter{ttyTables[8]}) + +// TTY16 is a 16-colour terminal formatter. +// +// It uses \033[3xm for normal colours and \033[90Xm for bright colours. +// +// The Lab colour space is used to map RGB values to the most appropriate index colour. +var TTY16 = Register("terminal16", &indexedTTYFormatter{ttyTables[16]}) // TTY256 is a 256-colour terminal formatter. // diff --git a/vendor/github.com/alecthomas/chroma/go.mod b/vendor/github.com/alecthomas/chroma/go.mod index 10e6d6e..3baf1cb 100644 --- a/vendor/github.com/alecthomas/chroma/go.mod +++ b/vendor/github.com/alecthomas/chroma/go.mod @@ -8,7 +8,7 @@ require ( github.com/alecthomas/kong v0.2.4 github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 // indirect github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 - github.com/dlclark/regexp2 v1.2.0 + github.com/dlclark/regexp2 v1.4.0 github.com/mattn/go-colorable v0.1.6 github.com/mattn/go-isatty v0.0.12 github.com/pkg/errors v0.9.1 // indirect diff --git a/vendor/github.com/alecthomas/chroma/go.sum b/vendor/github.com/alecthomas/chroma/go.sum index fb943fc..12000b7 100644 --- a/vendor/github.com/alecthomas/chroma/go.sum +++ b/vendor/github.com/alecthomas/chroma/go.sum @@ -11,13 +11,12 @@ github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk= -github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -26,7 +25,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/vendor/github.com/alecthomas/chroma/iterator.go b/vendor/github.com/alecthomas/chroma/iterator.go index c8845a1..d5175de 100644 --- a/vendor/github.com/alecthomas/chroma/iterator.go +++ b/vendor/github.com/alecthomas/chroma/iterator.go @@ -4,7 +4,7 @@ import "strings" // An Iterator across tokens. // -// nil will be returned at the end of the Token stream. +// EOF will be returned at the end of the Token stream. // // If an error occurs within an Iterator, it may propagate this in a panic. Formatters should recover. type Iterator func() Token diff --git a/vendor/github.com/alecthomas/chroma/lexer.go b/vendor/github.com/alecthomas/chroma/lexer.go index 1269d33..fe62519 100644 --- a/vendor/github.com/alecthomas/chroma/lexer.go +++ b/vendor/github.com/alecthomas/chroma/lexer.go @@ -2,6 +2,7 @@ package chroma import ( "fmt" + "strings" ) var ( @@ -98,9 +99,11 @@ type Lexer interface { // Lexers is a slice of lexers sortable by name. type Lexers []Lexer -func (l Lexers) Len() int { return len(l) } -func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l Lexers) Less(i, j int) bool { return l[i].Config().Name < l[j].Config().Name } +func (l Lexers) Len() int { return len(l) } +func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] } +func (l Lexers) Less(i, j int) bool { + return strings.ToLower(l[i].Config().Name) < strings.ToLower(l[j].Config().Name) +} // PrioritisedLexers is a slice of lexers sortable by priority. type PrioritisedLexers []Lexer diff --git a/vendor/github.com/alecthomas/chroma/lexers/README.md b/vendor/github.com/alecthomas/chroma/lexers/README.md index 2421710..b4ed292 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/README.md +++ b/vendor/github.com/alecthomas/chroma/lexers/README.md @@ -3,6 +3,9 @@ The tests in this directory feed a known input `testdata/.actual` into the parser for `` and check that its output matches `.exported`. +It is also possible to perform several tests on a same parser ``, by placing know inputs `*.actual` into a +directory `testdata//`. + ## Running the tests Run the tests as normal: diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/abap.go b/vendor/github.com/alecthomas/chroma/lexers/a/abap.go index 61c294e..268aa6a 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/abap.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/abap.go @@ -6,7 +6,7 @@ import ( ) // ABAP lexer. -var Abap = internal.Register(MustNewLexer( +var Abap = internal.Register(MustNewLazyLexer( &Config{ Name: "ABAP", Aliases: []string{"abap"}, @@ -14,7 +14,11 @@ var Abap = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-abap"}, CaseInsensitive: true, }, - Rules{ + abapRules, +)) + +func abapRules() Rules { + return Rules{ "common": { {`\s+`, Text, nil}, {`^\*.*$`, CommentSingle, nil}, @@ -52,5 +56,5 @@ var Abap = internal.Register(MustNewLexer( {`[/;:()\[\],.]`, Punctuation, nil}, {`(!)(\w+)`, ByGroups(Operator, Name), nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/abnf.go b/vendor/github.com/alecthomas/chroma/lexers/a/abnf.go index ff29aed..85c47af 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/abnf.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/abnf.go @@ -6,14 +6,18 @@ import ( ) // Abnf lexer. -var Abnf = internal.Register(MustNewLexer( +var Abnf = internal.Register(MustNewLazyLexer( &Config{ Name: "ABNF", Aliases: []string{"abnf"}, Filenames: []string{"*.abnf"}, MimeTypes: []string{"text/x-abnf"}, }, - Rules{ + abnfRules, +)) + +func abnfRules() Rules { + return Rules{ "root": { {`;.*$`, CommentSingle, nil}, {`(%[si])?"[^"]*"`, Literal, nil}, @@ -34,5 +38,5 @@ var Abnf = internal.Register(MustNewLexer( {`\s+`, Text, nil}, {`.`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/actionscript.go b/vendor/github.com/alecthomas/chroma/lexers/a/actionscript.go index 43d3852..df55d6d 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/actionscript.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/actionscript.go @@ -6,7 +6,7 @@ import ( ) // Actionscript lexer. -var Actionscript = internal.Register(MustNewLexer( +var Actionscript = internal.Register(MustNewLazyLexer( &Config{ Name: "ActionScript", Aliases: []string{"as", "actionscript"}, @@ -15,7 +15,11 @@ var Actionscript = internal.Register(MustNewLexer( NotMultiline: true, DotAll: true, }, - Rules{ + actionscriptRules, +)) + +func actionscriptRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`//.*?\n`, CommentSingle, nil}, @@ -35,5 +39,5 @@ var Actionscript = internal.Register(MustNewLexer( {`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil}, {`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/actionscript3.go b/vendor/github.com/alecthomas/chroma/lexers/a/actionscript3.go index 3404bd5..45596dc 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/actionscript3.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/actionscript3.go @@ -6,7 +6,7 @@ import ( ) // Actionscript 3 lexer. -var Actionscript3 = internal.Register(MustNewLexer( +var Actionscript3 = internal.Register(MustNewLazyLexer( &Config{ Name: "ActionScript 3", Aliases: []string{"as3", "actionscript3"}, @@ -14,7 +14,11 @@ var Actionscript3 = internal.Register(MustNewLexer( MimeTypes: []string{"application/x-actionscript3", "text/x-actionscript3", "text/actionscript3"}, DotAll: true, }, - Rules{ + actionscript3Rules, +)) + +func actionscript3Rules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`(function\s+)([$a-zA-Z_]\w*)(\s*)(\()`, ByGroups(KeywordDeclaration, NameFunction, Text, Operator), Push("funcparams")}, @@ -52,5 +56,5 @@ var Actionscript3 = internal.Register(MustNewLexer( {`,`, Operator, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/ada.go b/vendor/github.com/alecthomas/chroma/lexers/a/ada.go index d9b34e3..9167271 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/ada.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/ada.go @@ -6,7 +6,7 @@ import ( ) // Ada lexer. -var Ada = internal.Register(MustNewLexer( +var Ada = internal.Register(MustNewLazyLexer( &Config{ Name: "Ada", Aliases: []string{"ada", "ada95", "ada2005"}, @@ -14,7 +14,11 @@ var Ada = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-ada"}, CaseInsensitive: true, }, - Rules{ + adaRules, +)) + +func adaRules() Rules { + return Rules{ "root": { {`[^\S\n]+`, Text, nil}, {`--.*?\n`, CommentSingle, nil}, @@ -110,5 +114,5 @@ var Ada = internal.Register(MustNewLexer( {`\)`, Punctuation, Pop(1)}, Include("root"), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/al.go b/vendor/github.com/alecthomas/chroma/lexers/a/al.go new file mode 100644 index 0000000..d701644 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/a/al.go @@ -0,0 +1,48 @@ +package a + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// Al lexer. +var Al = internal.Register(MustNewLazyLexer( + &Config{ + Name: "AL", + Aliases: []string{"al"}, + Filenames: []string{"*.al", "*.dal"}, + MimeTypes: []string{"text/x-al"}, + DotAll: true, + CaseInsensitive: true, + }, + alRules, +)) + +// https://github.com/microsoft/AL/blob/master/grammar/alsyntax.tmlanguage +func alRules() Rules { + return Rules{ + "root": { + {`\s+`, TextWhitespace, nil}, + {`(?s)\/\*.*?\\*\*\/`, CommentMultiline, nil}, + {`(?s)//.*?\n`, CommentSingle, nil}, + {`\"([^\"])*\"`, Text, nil}, + {`'([^'])*'`, LiteralString, nil}, + {`\b(?i:(ARRAY|ASSERTERROR|BEGIN|BREAK|CASE|DO|DOWNTO|ELSE|END|EVENT|EXIT|FOR|FOREACH|FUNCTION|IF|IMPLEMENTS|IN|INDATASET|INTERFACE|INTERNAL|LOCAL|OF|PROCEDURE|PROGRAM|PROTECTED|REPEAT|RUNONCLIENT|SECURITYFILTERING|SUPPRESSDISPOSE|TEMPORARY|THEN|TO|TRIGGER|UNTIL|VAR|WHILE|WITH|WITHEVENTS))\b`, Keyword, nil}, + {`\b(?i:(AND|DIV|MOD|NOT|OR|XOR))\b`, OperatorWord, nil}, + {`\b(?i:(AVERAGE|CONST|COUNT|EXIST|FIELD|FILTER|LOOKUP|MAX|MIN|ORDER|SORTING|SUM|TABLEDATA|UPPERLIMIT|WHERE|ASCENDING|DESCENDING))\b`, Keyword, nil}, + // Added new objects types of BC 2021 wave 1 (REPORTEXTENSION|Entitlement|PermissionSet|PermissionSetExtension) + {`\b(?i:(CODEUNIT|PAGE|PAGEEXTENSION|PAGECUSTOMIZATION|DOTNET|ENUM|ENUMEXTENSION|VALUE|QUERY|REPORT|TABLE|TABLEEXTENSION|XMLPORT|PROFILE|CONTROLADDIN|REPORTEXTENSION|Entitlement|PermissionSet|PermissionSetExtension))\b`, Keyword, nil}, + {`\b(?i:(Action|Array|Automation|BigInteger|BigText|Blob|Boolean|Byte|Char|ClientType|Code|Codeunit|CompletionTriggerErrorLevel|ConnectionType|Database|DataClassification|DataScope|Date|DateFormula|DateTime|Decimal|DefaultLayout|Dialog|Dictionary|DotNet|DotNetAssembly|DotNetTypeDeclaration|Duration|Enum|ErrorInfo|ErrorType|ExecutionContext|ExecutionMode|FieldClass|FieldRef|FieldType|File|FilterPageBuilder|Guid|InStream|Integer|Joker|KeyRef|List|ModuleDependencyInfo|ModuleInfo|None|Notification|NotificationScope|ObjectType|Option|OutStream|Page|PageResult|Query|Record|RecordId|RecordRef|Report|ReportFormat|SecurityFilter|SecurityFiltering|Table|TableConnectionType|TableFilter|TestAction|TestField|TestFilterField|TestPage|TestPermissions|TestRequestPage|Text|TextBuilder|TextConst|TextEncoding|Time|TransactionModel|TransactionType|Variant|Verbosity|Version|XmlPort|HttpContent|HttpHeaders|HttpClient|HttpRequestMessage|HttpResponseMessage|JsonToken|JsonValue|JsonArray|JsonObject|View|Views|XmlAttribute|XmlAttributeCollection|XmlComment|XmlCData|XmlDeclaration|XmlDocument|XmlDocumentType|XmlElement|XmlNamespaceManager|XmlNameTable|XmlNode|XmlNodeList|XmlProcessingInstruction|XmlReadOptions|XmlText|XmlWriteOptions|WebServiceActionContext|WebServiceActionResultCode|SessionSettings))\b`, Keyword, nil}, + {`\b([<>]=|<>|<|>)\b?`, Operator, nil}, + {`\b(\-|\+|\/|\*)\b`, Operator, nil}, + {`\s*(\:=|\+=|-=|\/=|\*=)\s*?`, Operator, nil}, + {`\b(?i:(ADDFIRST|ADDLAST|ADDAFTER|ADDBEFORE|ACTION|ACTIONS|AREA|ASSEMBLY|CHARTPART|CUEGROUP|CUSTOMIZES|COLUMN|DATAITEM|DATASET|ELEMENTS|EXTENDS|FIELD|FIELDGROUP|FIELDATTRIBUTE|FIELDELEMENT|FIELDGROUPS|FIELDS|FILTER|FIXED|GRID|GROUP|MOVEAFTER|MOVEBEFORE|KEY|KEYS|LABEL|LABELS|LAYOUT|MODIFY|MOVEFIRST|MOVELAST|MOVEBEFORE|MOVEAFTER|PART|REPEATER|USERCONTROL|REQUESTPAGE|SCHEMA|SEPARATOR|SYSTEMPART|TABLEELEMENT|TEXTATTRIBUTE|TEXTELEMENT|TYPE))\b`, Keyword, nil}, + {`\s*[(\.\.)&\|]\s*`, Operator, nil}, + {`\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\b`, LiteralNumber, nil}, + {`[;:,]`, Punctuation, nil}, + {`#[ \t]*(if|else|elif|endif|define|undef|region|endregion|pragma)\b.*?\n`, CommentPreproc, nil}, + {`\w+`, Text, nil}, + {`.`, Text, nil}, + }, + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/angular2.go b/vendor/github.com/alecthomas/chroma/lexers/a/angular2.go index 5258c92..a947eda 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/angular2.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/angular2.go @@ -6,14 +6,18 @@ import ( ) // Angular2 lexer. -var Angular2 = internal.Register(MustNewLexer( +var Angular2 = internal.Register(MustNewLazyLexer( &Config{ Name: "Angular2", Aliases: []string{"ng2"}, Filenames: []string{}, MimeTypes: []string{}, }, - Rules{ + angular2Rules, +)) + +func angular2Rules() Rules { + return Rules{ "root": { {`[^{([*#]+`, Other, nil}, {`(\{\{)(\s*)`, ByGroups(CommentPreproc, Text), Push("ngExpression")}, @@ -38,5 +42,5 @@ var Angular2 = internal.Register(MustNewLexer( {`'.*?'`, LiteralString, Pop(1)}, {`[^\s>]+`, LiteralString, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/antlr.go b/vendor/github.com/alecthomas/chroma/lexers/a/antlr.go index d7649d4..c744353 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/antlr.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/antlr.go @@ -6,14 +6,18 @@ import ( ) // ANTLR lexer. -var ANTLR = internal.Register(MustNewLexer( +var ANTLR = internal.Register(MustNewLazyLexer( &Config{ Name: "ANTLR", Aliases: []string{"antlr"}, Filenames: []string{}, MimeTypes: []string{}, }, - Rules{ + antlrRules, +)) + +func antlrRules() Rules { + return Rules{ "whitespace": { {`\s+`, TextWhitespace, nil}, }, @@ -97,5 +101,5 @@ var ANTLR = internal.Register(MustNewLexer( {`(\$[a-zA-Z]+)(\.?)(text|value)?`, ByGroups(NameVariable, Punctuation, NameProperty), nil}, {`(\\\\|\\\]|\\\[|[^\[\]])+`, Other, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/apache.go b/vendor/github.com/alecthomas/chroma/lexers/a/apache.go index 6c56a1d..5685eb1 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/apache.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/apache.go @@ -6,7 +6,7 @@ import ( ) // Apacheconf lexer. -var Apacheconf = internal.Register(MustNewLexer( +var Apacheconf = internal.Register(MustNewLazyLexer( &Config{ Name: "ApacheConf", Aliases: []string{"apacheconf", "aconf", "apache"}, @@ -14,7 +14,11 @@ var Apacheconf = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-apacheconf"}, CaseInsensitive: true, }, - Rules{ + apacheconfRules, +)) + +func apacheconfRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`(#.*?)$`, Comment, nil}, @@ -34,5 +38,5 @@ var Apacheconf = internal.Register(MustNewLexer( {`"([^"\\]*(?:\\.[^"\\]*)*)"`, LiteralStringDouble, nil}, {`[^\s"\\]+`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/apl.go b/vendor/github.com/alecthomas/chroma/lexers/a/apl.go index 820e13b..6cf1ea0 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/apl.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/apl.go @@ -6,14 +6,18 @@ import ( ) // Apl lexer. -var Apl = internal.Register(MustNewLexer( +var Apl = internal.Register(MustNewLazyLexer( &Config{ Name: "APL", Aliases: []string{"apl"}, Filenames: []string{"*.apl"}, MimeTypes: []string{}, }, - Rules{ + aplRules, +)) + +func aplRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`[⍝#].*$`, CommentSingle, nil}, @@ -32,5 +36,5 @@ var Apl = internal.Register(MustNewLexer( {`[⍺⍵⍶⍹∇:]`, NameBuiltinPseudo, nil}, {`[{}]`, KeywordType, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/applescript.go b/vendor/github.com/alecthomas/chroma/lexers/a/applescript.go index db83ed0..b6a53c5 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/applescript.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/applescript.go @@ -6,7 +6,7 @@ import ( ) // Applescript lexer. -var Applescript = internal.Register(MustNewLexer( +var Applescript = internal.Register(MustNewLazyLexer( &Config{ Name: "AppleScript", Aliases: []string{"applescript"}, @@ -14,7 +14,11 @@ var Applescript = internal.Register(MustNewLexer( MimeTypes: []string{}, DotAll: true, }, - Rules{ + applescriptRules, +)) + +func applescriptRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`¬\n`, LiteralStringEscape, nil}, @@ -51,5 +55,5 @@ var Applescript = internal.Register(MustNewLexer( {`[^*(]+`, CommentMultiline, nil}, {`[*(]`, CommentMultiline, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/a/arduino.go b/vendor/github.com/alecthomas/chroma/lexers/a/arduino.go index b0cd8c9..0edbe3f 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/a/arduino.go +++ b/vendor/github.com/alecthomas/chroma/lexers/a/arduino.go @@ -6,7 +6,7 @@ import ( ) // Arduino lexer. -var Arduino = internal.Register(MustNewLexer( +var Arduino = internal.Register(MustNewLazyLexer( &Config{ Name: "Arduino", Aliases: []string{"arduino"}, @@ -14,7 +14,11 @@ var Arduino = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-arduino"}, EnsureNL: true, }, - Rules{ + arduinoRules, +)) + +func arduinoRules() Rules { + return Rules{ "statements": { {Words(``, `\b`, `catch`, `const_cast`, `delete`, `dynamic_cast`, `explicit`, `export`, `friend`, `mutable`, `namespace`, `new`, `operator`, `private`, `protected`, `public`, `reinterpret_cast`, `restrict`, `static_cast`, `template`, `this`, `throw`, `throws`, `try`, `typeid`, `typename`, `using`, `virtual`, `constexpr`, `nullptr`, `decltype`, `thread_local`, `alignas`, `alignof`, `static_assert`, `noexcept`, `override`, `final`), Keyword, nil}, {`char(16_t|32_t)\b`, KeywordType, nil}, @@ -106,5 +110,5 @@ var Arduino = internal.Register(MustNewLexer( {`^\s*#endif.*?(?|\n\x1a]))(?:(?:[^\n\x1a^]|\^[\n\x1a]?[\w\W])*)`, CommentSingle, nil}, {`(?=((?:(?<=^[^:])|^[^:]?)[\t\v\f\r ,;=\xa0]*)(:))`, Text, Push("follow")}, @@ -190,5 +194,5 @@ var Batchfile = internal.Register(MustNewLexer( {`else(?=\^?[\t\v\f\r ,;=\xa0]|[&<>|\n\x1a])`, Keyword, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go b/vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go index 1d76b1d..d6a0ae3 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go +++ b/vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go @@ -6,7 +6,7 @@ import ( ) // Bibtex lexer. -var Bibtex = internal.Register(MustNewLexer( +var Bibtex = internal.Register(MustNewLazyLexer( &Config{ Name: "BibTeX", Aliases: []string{"bib", "bibtex"}, @@ -15,7 +15,11 @@ var Bibtex = internal.Register(MustNewLexer( NotMultiline: true, CaseInsensitive: true, }, - Rules{ + bibtexRules, +)) + +func bibtexRules() Rules { + return Rules{ "root": { Include("whitespace"), {`@comment`, Comment, nil}, @@ -72,5 +76,5 @@ var Bibtex = internal.Register(MustNewLexer( "whitespace": { {`\s+`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/b/blitz.go b/vendor/github.com/alecthomas/chroma/lexers/b/blitz.go index 5d5ffc8..119f96b 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/b/blitz.go +++ b/vendor/github.com/alecthomas/chroma/lexers/b/blitz.go @@ -6,7 +6,7 @@ import ( ) // Blitzbasic lexer. -var Blitzbasic = internal.Register(MustNewLexer( +var Blitzbasic = internal.Register(MustNewLazyLexer( &Config{ Name: "BlitzBasic", Aliases: []string{"blitzbasic", "b3d", "bplus"}, @@ -14,7 +14,11 @@ var Blitzbasic = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-bb"}, CaseInsensitive: true, }, - Rules{ + blitzbasicRules, +)) + +func blitzbasicRules() Rules { + return Rules{ "root": { {`[ \t]+`, Text, nil}, {`;.*?\n`, CommentSingle, nil}, @@ -44,5 +48,5 @@ var Blitzbasic = internal.Register(MustNewLexer( {`"C?`, LiteralStringDouble, Pop(1)}, {`[^"]+`, LiteralStringDouble, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/b/bnf.go b/vendor/github.com/alecthomas/chroma/lexers/b/bnf.go index 5123a45..dcf7360 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/b/bnf.go +++ b/vendor/github.com/alecthomas/chroma/lexers/b/bnf.go @@ -6,19 +6,23 @@ import ( ) // Bnf lexer. -var Bnf = internal.Register(MustNewLexer( +var Bnf = internal.Register(MustNewLazyLexer( &Config{ Name: "BNF", Aliases: []string{"bnf"}, Filenames: []string{"*.bnf"}, MimeTypes: []string{"text/x-bnf"}, }, - Rules{ + bnfRules, +)) + +func bnfRules() Rules { + return Rules{ "root": { {`(<)([ -;=?-~]+)(>)`, ByGroups(Punctuation, NameClass, Punctuation), nil}, {`::=`, Operator, nil}, {`[^<>:]+`, Text, nil}, {`.`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/b/brainfuck.go b/vendor/github.com/alecthomas/chroma/lexers/b/brainfuck.go index 6fac5f5..d35e9c6 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/b/brainfuck.go +++ b/vendor/github.com/alecthomas/chroma/lexers/b/brainfuck.go @@ -6,14 +6,18 @@ import ( ) // Brainfuck lexer. -var Brainfuck = internal.Register(MustNewLexer( +var Brainfuck = internal.Register(MustNewLazyLexer( &Config{ Name: "Brainfuck", Aliases: []string{"brainfuck", "bf"}, Filenames: []string{"*.bf", "*.b"}, MimeTypes: []string{"application/x-brainfuck"}, }, - Rules{ + brainfuckRules, +)) + +func brainfuckRules() Rules { + return Rules{ "common": { {`[.,]+`, NameTag, nil}, {`[+-]+`, NameBuiltin, nil}, @@ -30,5 +34,5 @@ var Brainfuck = internal.Register(MustNewLexer( {`\]`, Keyword, Pop(1)}, Include("common"), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/c.go b/vendor/github.com/alecthomas/chroma/lexers/c/c.go index df2c0fa..3698c4f 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/c.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/c.go @@ -6,14 +6,19 @@ import ( ) // C lexer. -var C = internal.Register(MustNewLexer( +var C = internal.Register(MustNewLazyLexer( &Config{ Name: "C", Aliases: []string{"c"}, - Filenames: []string{"*.c", "*.h", "*.idc"}, - MimeTypes: []string{"text/x-chdr", "text/x-csrc"}, + Filenames: []string{"*.c", "*.h", "*.idc", "*.x[bp]m"}, + MimeTypes: []string{"text/x-chdr", "text/x-csrc", "image/x-xbitmap", "image/x-xpixmap"}, + EnsureNL: true, }, - Rules{ + cRules, +)) + +func cRules() Rules { + return Rules{ "whitespace": { {`^#if\s+0`, CommentPreproc, Push("if0")}, {`^#`, CommentPreproc, Push("macro")}, @@ -38,7 +43,7 @@ var C = internal.Register(MustNewLexer( {`[~!%^&*+=|?:<>/-]`, Operator, nil}, {`[()\[\],.]`, Punctuation, nil}, {Words(``, `\b`, `asm`, `auto`, `break`, `case`, `const`, `continue`, `default`, `do`, `else`, `enum`, `extern`, `for`, `goto`, `if`, `register`, `restricted`, `return`, `sizeof`, `static`, `struct`, `switch`, `typedef`, `union`, `volatile`, `while`), Keyword, nil}, - {`(bool|int|long|float|short|double|char|unsigned|signed|void)\b`, KeywordType, nil}, + {`(bool|int|long|float|short|double|char((8|16|32)_t)?|unsigned|signed|void|u?int(_fast|_least|)(8|16|32|64)_t)\b`, KeywordType, nil}, {Words(``, `\b`, `inline`, `_inline`, `__inline`, `naked`, `restrict`, `thread`, `typename`), KeywordReserved, nil}, {`(__m(128i|128d|128|64))\b`, KeywordReserved, nil}, {Words(`__`, `\b`, `asm`, `int8`, `based`, `except`, `int16`, `stdcall`, `cdecl`, `fastcall`, `int32`, `declspec`, `finally`, `int64`, `try`, `leave`, `wchar_t`, `w64`, `unaligned`, `raise`, `noop`, `identifier`, `forceinline`, `assume`), KeywordReserved, nil}, @@ -87,5 +92,5 @@ var C = internal.Register(MustNewLexer( {`^\s*#endif.*?(?\]`, NameDecorator, Push("matcher")}, - // These cannot have matchers but may have things that look like - // matchers in their arguments, so we just parse as a subdirective. - {`try_files`, Keyword, Push("subdirective")}, - // These are special, they can nest more directives - {`handle_errors|handle|route|handle_path|not`, Keyword, Push("nested_directive")}, - // Any other directive - {`[^\s#]+`, Keyword, Push("directive")}, - Include("base"), - }, - "matcher": { - {`\{`, Punctuation, Push("block")}, - // Not can be one-liner - {`not`, Keyword, Push("deep_not_matcher")}, - // Any other same-line matcher - {`[^\s#]+`, Keyword, Push("arguments")}, - // Terminators - {`\n`, Text, Pop(1)}, - {`\}`, Punctuation, Pop(1)}, - Include("base"), - }, - "block": { - {`\}`, Punctuation, Pop(2)}, - // Not can be one-liner - {`not`, Keyword, Push("not_matcher")}, - // Any other subdirective - {`[^\s#]+`, Keyword, Push("subdirective")}, - Include("base"), - }, - "nested_block": { - {`\}`, Punctuation, Pop(2)}, - // Matcher definition - {`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")}, - // Something that starts with literally < is probably a docs stub - {`\<[^#]+\>`, Keyword, Push("nested_directive")}, - // Any other directive - {`[^\s#]+`, Keyword, Push("nested_directive")}, - Include("base"), - }, - "not_matcher": { - {`\}`, Punctuation, Pop(2)}, - {`\{(?=\s)`, Punctuation, Push("block")}, - {`[^\s#]+`, Keyword, Push("arguments")}, - {`\s+`, Text, nil}, - }, - "deep_not_matcher": { - {`\}`, Punctuation, Pop(2)}, - {`\{(?=\s)`, Punctuation, Push("block")}, - {`[^\s#]+`, Keyword, Push("deep_subdirective")}, - {`\s+`, Text, nil}, - }, - "directive": { - {`\{(?=\s)`, Punctuation, Push("block")}, - Include("matcher_token"), - Include("comments_pop_1"), - {`\n`, Text, Pop(1)}, - Include("base"), - }, - "nested_directive": { - {`\{(?=\s)`, Punctuation, Push("nested_block")}, - Include("matcher_token"), - Include("comments_pop_1"), - {`\n`, Text, Pop(1)}, - Include("base"), - }, - "subdirective": { - {`\{(?=\s)`, Punctuation, Push("block")}, - Include("comments_pop_1"), - {`\n`, Text, Pop(1)}, - Include("base"), - }, - "arguments": { - {`\{(?=\s)`, Punctuation, Push("block")}, - Include("comments_pop_2"), - {`\\\n`, Text, nil}, // Skip escaped newlines - {`\n`, Text, Pop(2)}, - Include("base"), - }, - "deep_subdirective": { - {`\{(?=\s)`, Punctuation, Push("block")}, - Include("comments_pop_3"), - {`\n`, Text, Pop(3)}, - Include("base"), - }, - "matcher_token": { - {`@[^\s]+`, NameDecorator, Push("arguments")}, // Named matcher - {`/[^\s]+`, NameDecorator, Push("arguments")}, // Path matcher - {`\*`, NameDecorator, Push("arguments")}, // Wildcard path matcher - {`\[\\]`, NameDecorator, Push("arguments")}, // Matcher token stub for docs - }, - "comments": { - {`^#.*\n`, CommentSingle, nil}, // Comment at start of line - {`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace - }, - "comments_pop_1": { - {`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line - {`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace - }, - "comments_pop_2": { - {`^#.*\n`, CommentSingle, Pop(2)}, // Comment at start of line - {`\s+#.*\n`, CommentSingle, Pop(2)}, // Comment preceded by whitespace - }, - "comments_pop_3": { - {`^#.*\n`, CommentSingle, Pop(3)}, // Comment at start of line - {`\s+#.*\n`, CommentSingle, Pop(3)}, // Comment preceded by whitespace - }, - "base": { - Include("comments"), - {`(on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace)\b`, NameConstant, nil}, - {`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil}, - {`[a-z-]+/[a-z-+]+`, LiteralString, nil}, - {`[0-9]+[km]?\b`, LiteralNumberInteger, nil}, - {`\{[\w+.\$-]+\}`, LiteralStringEscape, nil}, // Placeholder - {`\[(?=[^#{}$]+\])`, Punctuation, nil}, - {`\]|\|`, Punctuation, nil}, - {`[^\s#{}$\]]+`, LiteralString, nil}, - {`/[^\s#]*`, Name, nil}, - {`\s+`, Text, nil}, - }, +func caddyfileCommonRules() Rules { + return Rules{ + "site_block_common": { + // Import keyword + {`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil}, + // Matcher definition + {`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")}, + // Matcher token stub for docs + {`\[\\]`, NameDecorator, Push("matcher")}, + // These cannot have matchers but may have things that look like + // matchers in their arguments, so we just parse as a subdirective. + {`try_files`, Keyword, Push("subdirective")}, + // These are special, they can nest more directives + {`handle_errors|handle|route|handle_path|not`, Keyword, Push("nested_directive")}, + // Any other directive + {`[^\s#]+`, Keyword, Push("directive")}, + Include("base"), + }, + "matcher": { + {`\{`, Punctuation, Push("block")}, + // Not can be one-liner + {`not`, Keyword, Push("deep_not_matcher")}, + // Any other same-line matcher + {`[^\s#]+`, Keyword, Push("arguments")}, + // Terminators + {`\n`, Text, Pop(1)}, + {`\}`, Punctuation, Pop(1)}, + Include("base"), + }, + "block": { + {`\}`, Punctuation, Pop(2)}, + // Not can be one-liner + {`not`, Keyword, Push("not_matcher")}, + // Any other subdirective + {`[^\s#]+`, Keyword, Push("subdirective")}, + Include("base"), + }, + "nested_block": { + {`\}`, Punctuation, Pop(2)}, + // Matcher definition + {`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")}, + // Something that starts with literally < is probably a docs stub + {`\<[^#]+\>`, Keyword, Push("nested_directive")}, + // Any other directive + {`[^\s#]+`, Keyword, Push("nested_directive")}, + Include("base"), + }, + "not_matcher": { + {`\}`, Punctuation, Pop(2)}, + {`\{(?=\s)`, Punctuation, Push("block")}, + {`[^\s#]+`, Keyword, Push("arguments")}, + {`\s+`, Text, nil}, + }, + "deep_not_matcher": { + {`\}`, Punctuation, Pop(2)}, + {`\{(?=\s)`, Punctuation, Push("block")}, + {`[^\s#]+`, Keyword, Push("deep_subdirective")}, + {`\s+`, Text, nil}, + }, + "directive": { + {`\{(?=\s)`, Punctuation, Push("block")}, + Include("matcher_token"), + Include("comments_pop_1"), + {`\n`, Text, Pop(1)}, + Include("base"), + }, + "nested_directive": { + {`\{(?=\s)`, Punctuation, Push("nested_block")}, + Include("matcher_token"), + Include("comments_pop_1"), + {`\n`, Text, Pop(1)}, + Include("base"), + }, + "subdirective": { + {`\{(?=\s)`, Punctuation, Push("block")}, + Include("comments_pop_1"), + {`\n`, Text, Pop(1)}, + Include("base"), + }, + "arguments": { + {`\{(?=\s)`, Punctuation, Push("block")}, + Include("comments_pop_2"), + {`\\\n`, Text, nil}, // Skip escaped newlines + {`\n`, Text, Pop(2)}, + Include("base"), + }, + "deep_subdirective": { + {`\{(?=\s)`, Punctuation, Push("block")}, + Include("comments_pop_3"), + {`\n`, Text, Pop(3)}, + Include("base"), + }, + "matcher_token": { + {`@[^\s]+`, NameDecorator, Push("arguments")}, // Named matcher + {`/[^\s]+`, NameDecorator, Push("arguments")}, // Path matcher + {`\*`, NameDecorator, Push("arguments")}, // Wildcard path matcher + {`\[\\]`, NameDecorator, Push("arguments")}, // Matcher token stub for docs + }, + "comments": { + {`^#.*\n`, CommentSingle, nil}, // Comment at start of line + {`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace + }, + "comments_pop_1": { + {`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line + {`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace + }, + "comments_pop_2": { + {`^#.*\n`, CommentSingle, Pop(2)}, // Comment at start of line + {`\s+#.*\n`, CommentSingle, Pop(2)}, // Comment preceded by whitespace + }, + "comments_pop_3": { + {`^#.*\n`, CommentSingle, Pop(3)}, // Comment at start of line + {`\s+#.*\n`, CommentSingle, Pop(3)}, // Comment preceded by whitespace + }, + "base": { + Include("comments"), + {`(on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace)\b`, NameConstant, nil}, + {`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil}, + {`[a-z-]+/[a-z-+]+`, LiteralString, nil}, + {`[0-9]+[km]?\b`, LiteralNumberInteger, nil}, + {`\{[\w+.\$-]+\}`, LiteralStringEscape, nil}, // Placeholder + {`\[(?=[^#{}$]+\])`, Punctuation, nil}, + {`\]|\|`, Punctuation, nil}, + {`[^\s#{}$\]]+`, LiteralString, nil}, + {`/[^\s#]*`, Name, nil}, + {`\s+`, Text, nil}, + }, + } } // Caddyfile lexer. -var Caddyfile = internal.Register(MustNewLexer( +var Caddyfile = internal.Register(MustNewLazyLexer( &Config{ Name: "Caddyfile", Aliases: []string{"caddyfile", "caddy"}, Filenames: []string{"Caddyfile*"}, MimeTypes: []string{}, }, - Rules{ + caddyfileRules, +)) + +func caddyfileRules() Rules { + return Rules{ "root": { Include("comments"), // Global options block @@ -186,21 +192,25 @@ var Caddyfile = internal.Register(MustNewLexer( {`\}`, Punctuation, Pop(2)}, Include("site_block_common"), }, - }.Merge(caddyfileCommon), -)) + }.Merge(caddyfileCommonRules()) +} // Caddyfile directive-only lexer. -var CaddyfileDirectives = internal.Register(MustNewLexer( +var CaddyfileDirectives = internal.Register(MustNewLazyLexer( &Config{ Name: "Caddyfile Directives", Aliases: []string{"caddyfile-directives", "caddyfile-d", "caddy-d"}, Filenames: []string{}, MimeTypes: []string{}, }, - Rules{ + caddyfileDirectivesRules, +)) + +func caddyfileDirectivesRules() Rules { + return Rules{ // Same as "site_block" in Caddyfile "root": { Include("site_block_common"), }, - }.Merge(caddyfileCommon), -)) + }.Merge(caddyfileCommonRules()) +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/capnproto.go b/vendor/github.com/alecthomas/chroma/lexers/c/capnproto.go index 0f9d03c..ec0d892 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/capnproto.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/capnproto.go @@ -6,14 +6,18 @@ import ( ) // Cap'N'Proto Proto lexer. -var CapNProto = internal.Register(MustNewLexer( +var CapNProto = internal.Register(MustNewLazyLexer( &Config{ Name: "Cap'n Proto", Aliases: []string{"capnp"}, Filenames: []string{"*.capnp"}, MimeTypes: []string{}, }, - Rules{ + capNProtoRules, +)) + +func capNProtoRules() Rules { + return Rules{ "root": { {`#.*?$`, CommentSingle, nil}, {`@[0-9a-zA-Z]*`, NameDecorator, nil}, @@ -57,5 +61,5 @@ var CapNProto = internal.Register(MustNewLexer( {`[])]`, NameAttribute, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/ceylon.go b/vendor/github.com/alecthomas/chroma/lexers/c/ceylon.go index 07324ca..9d424d4 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/ceylon.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/ceylon.go @@ -6,7 +6,7 @@ import ( ) // Ceylon lexer. -var Ceylon = internal.Register(MustNewLexer( +var Ceylon = internal.Register(MustNewLazyLexer( &Config{ Name: "Ceylon", Aliases: []string{"ceylon"}, @@ -14,7 +14,11 @@ var Ceylon = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-ceylon"}, DotAll: true, }, - Rules{ + ceylonRules, +)) + +func ceylonRules() Rules { + return Rules{ "root": { {`^(\s*(?:[a-zA-Z_][\w.\[\]]*\s+)+?)([a-zA-Z_]\w*)(\s*)(\()`, ByGroups(UsingSelf("root"), NameFunction, Text, Operator), nil}, {`[^\S\n]+`, Text, nil}, @@ -59,5 +63,5 @@ var Ceylon = internal.Register(MustNewLexer( {`\*/`, CommentMultiline, Pop(1)}, {`[*/]`, CommentMultiline, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/cfengine3.go b/vendor/github.com/alecthomas/chroma/lexers/c/cfengine3.go index f96252f..f305034 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/cfengine3.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/cfengine3.go @@ -6,14 +6,18 @@ import ( ) // Cfengine3 lexer. -var Cfengine3 = internal.Register(MustNewLexer( +var Cfengine3 = internal.Register(MustNewLazyLexer( &Config{ Name: "CFEngine3", Aliases: []string{"cfengine3", "cf3"}, Filenames: []string{"*.cf"}, MimeTypes: []string{}, }, - Rules{ + cfengine3Rules, +)) + +func cfengine3Rules() Rules { + return Rules{ "root": { {`#.*?\n`, Comment, nil}, {`(body)(\s+)(\S+)(\s+)(control)`, ByGroups(Keyword, Text, Keyword, Text, Keyword), nil}, @@ -52,5 +56,5 @@ var Cfengine3 = internal.Register(MustNewLexer( {`\w+`, NameVariable, nil}, {`\s+`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/chaiscript.go b/vendor/github.com/alecthomas/chroma/lexers/c/chaiscript.go index d2aa50d..58db9aa 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/chaiscript.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/chaiscript.go @@ -6,7 +6,7 @@ import ( ) // Chaiscript lexer. -var Chaiscript = internal.Register(MustNewLexer( +var Chaiscript = internal.Register(MustNewLazyLexer( &Config{ Name: "ChaiScript", Aliases: []string{"chai", "chaiscript"}, @@ -14,7 +14,11 @@ var Chaiscript = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-chaiscript", "application/x-chaiscript"}, DotAll: true, }, - Rules{ + chaiscriptRules, +)) + +func chaiscriptRules() Rules { + return Rules{ "commentsandwhitespace": { {`\s+`, Text, nil}, {`//.*?\n`, CommentSingle, nil}, @@ -59,5 +63,5 @@ var Chaiscript = internal.Register(MustNewLexer( {`[^\\"$]+`, LiteralStringDouble, nil}, {`"`, LiteralStringDouble, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/cheetah.go b/vendor/github.com/alecthomas/chroma/lexers/c/cheetah.go index b2cb9c4..bd5fb9d 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/cheetah.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/cheetah.go @@ -7,14 +7,18 @@ import ( ) // Cheetah lexer. -var Cheetah = internal.Register(MustNewLexer( +var Cheetah = internal.Register(MustNewLazyLexer( &Config{ Name: "Cheetah", Aliases: []string{"cheetah", "spitfire"}, Filenames: []string{"*.tmpl", "*.spt"}, MimeTypes: []string{"application/x-cheetah", "application/x-spitfire"}, }, - Rules{ + cheetahRules, +)) + +func cheetahRules() Rules { + return Rules{ "root": { {`(##[^\n]*)$`, ByGroups(Comment), nil}, {`#[*](.|\n)*?[*]#`, Comment, nil}, @@ -33,5 +37,5 @@ var Cheetah = internal.Register(MustNewLexer( `, Other, nil}, {`\s+`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/cl.go b/vendor/github.com/alecthomas/chroma/lexers/c/cl.go index fdc9729..bb16273 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/cl.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/cl.go @@ -230,7 +230,7 @@ var ( ) // Common Lisp lexer. -var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLexer( +var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLazyLexer( &Config{ Name: "Common Lisp", Aliases: []string{"common-lisp", "cl", "lisp"}, @@ -238,7 +238,19 @@ var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLexer( MimeTypes: []string{"text/x-common-lisp"}, CaseInsensitive: true, }, - Rules{ + commonLispRules, +), TypeMapping{ + {NameVariable, NameFunction, clBuiltinFunctions}, + {NameVariable, Keyword, clSpecialForms}, + {NameVariable, NameBuiltin, clMacros}, + {NameVariable, Keyword, clLambdaListKeywords}, + {NameVariable, Keyword, clDeclarations}, + {NameVariable, KeywordType, clBuiltinTypes}, + {NameVariable, NameClass, clBuiltinClasses}, +})) + +func commonLispRules() Rules { + return Rules{ "root": { Default(Push("body")), }, @@ -294,13 +306,5 @@ var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLexer( {`\(`, Punctuation, Push("body")}, {`\)`, Punctuation, Pop(1)}, }, - }, -), TypeMapping{ - {NameVariable, NameFunction, clBuiltinFunctions}, - {NameVariable, Keyword, clSpecialForms}, - {NameVariable, NameBuiltin, clMacros}, - {NameVariable, Keyword, clLambdaListKeywords}, - {NameVariable, Keyword, clDeclarations}, - {NameVariable, KeywordType, clBuiltinTypes}, - {NameVariable, NameClass, clBuiltinClasses}, -})) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/clojure.go b/vendor/github.com/alecthomas/chroma/lexers/c/clojure.go index e63752a..f99f906 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/clojure.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/clojure.go @@ -6,14 +6,18 @@ import ( ) // Clojure lexer. -var Clojure = internal.Register(MustNewLexer( +var Clojure = internal.Register(MustNewLazyLexer( &Config{ Name: "Clojure", Aliases: []string{"clojure", "clj"}, Filenames: []string{"*.clj"}, MimeTypes: []string{"text/x-clojure", "application/x-clojure"}, }, - Rules{ + clojureRules, +)) + +func clojureRules() Rules { + return Rules{ "root": { {`;.*$`, CommentSingle, nil}, {`[,\s]+`, Text, nil}, @@ -34,5 +38,5 @@ var Clojure = internal.Register(MustNewLexer( {`(\{|\})`, Punctuation, nil}, {`(\(|\))`, Punctuation, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/cmake.go b/vendor/github.com/alecthomas/chroma/lexers/c/cmake.go index 163f17d..0e0708d 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/cmake.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/cmake.go @@ -6,14 +6,18 @@ import ( ) // Cmake lexer. -var Cmake = internal.Register(MustNewLexer( +var Cmake = internal.Register(MustNewLazyLexer( &Config{ Name: "CMake", Aliases: []string{"cmake"}, Filenames: []string{"*.cmake", "CMakeLists.txt"}, MimeTypes: []string{"text/x-cmake"}, }, - Rules{ + cmakeRules, +)) + +func cmakeRules() Rules { + return Rules{ "root": { {`\b(\w+)([ \t]*)(\()`, ByGroups(NameBuiltin, Text, Punctuation), Push("args")}, Include("keywords"), @@ -40,5 +44,5 @@ var Cmake = internal.Register(MustNewLexer( {`[ \t]+`, Text, nil}, {`#.*\n`, Comment, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/cobol.go b/vendor/github.com/alecthomas/chroma/lexers/c/cobol.go index e9ae0bb..8b2f6d9 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/cobol.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/cobol.go @@ -6,7 +6,7 @@ import ( ) // Cobol lexer. -var Cobol = internal.Register(MustNewLexer( +var Cobol = internal.Register(MustNewLazyLexer( &Config{ Name: "COBOL", Aliases: []string{"cobol"}, @@ -14,7 +14,11 @@ var Cobol = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-cobol"}, CaseInsensitive: true, }, - Rules{ + cobolRules, +)) + +func cobolRules() Rules { + return Rules{ "root": { Include("comment"), Include("strings"), @@ -47,5 +51,5 @@ var Cobol = internal.Register(MustNewLexer( {`[+-]?\d*\.\d+(E[-+]?\d+)?`, LiteralNumberFloat, nil}, {`[+-]?\d+\.\d*(E[-+]?\d+)?`, LiteralNumberFloat, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/coffee.go b/vendor/github.com/alecthomas/chroma/lexers/c/coffee.go index e402b8f..381a8fe 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/coffee.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/coffee.go @@ -6,7 +6,7 @@ import ( ) // Coffeescript lexer. -var Coffeescript = internal.Register(MustNewLexer( +var Coffeescript = internal.Register(MustNewLazyLexer( &Config{ Name: "CoffeeScript", Aliases: []string{"coffee-script", "coffeescript", "coffee"}, @@ -15,7 +15,11 @@ var Coffeescript = internal.Register(MustNewLexer( NotMultiline: true, DotAll: true, }, - Rules{ + coffeescriptRules, +)) + +func coffeescriptRules() Rules { + return Rules{ "commentsandwhitespace": { {`\s+`, Text, nil}, {`###[^#].*?###`, CommentMultiline, nil}, @@ -87,5 +91,5 @@ var Coffeescript = internal.Register(MustNewLexer( {`#|\\.|\'|"`, LiteralString, nil}, Include("strings"), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/coldfusion.go b/vendor/github.com/alecthomas/chroma/lexers/c/coldfusion.go index 2f12472..bc28bc3 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/coldfusion.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/coldfusion.go @@ -6,7 +6,7 @@ import ( ) // Cfstatement lexer. -var Cfstatement = internal.Register(MustNewLexer( +var Cfstatement = internal.Register(MustNewLazyLexer( &Config{ Name: "cfstatement", Aliases: []string{"cfs"}, @@ -15,7 +15,11 @@ var Cfstatement = internal.Register(MustNewLexer( NotMultiline: true, CaseInsensitive: true, }, - Rules{ + cfstatementRules, +)) + +func cfstatementRules() Rules { + return Rules{ "root": { {`//.*?\n`, CommentSingle, nil}, {`/\*(?:.|\n)*?\*/`, CommentMultiline, nil}, @@ -44,5 +48,5 @@ var Cfstatement = internal.Register(MustNewLexer( {`#`, LiteralStringDouble, nil}, {`"`, LiteralStringDouble, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/coq.go b/vendor/github.com/alecthomas/chroma/lexers/c/coq.go index e69a5c1..e0103ef 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/coq.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/coq.go @@ -6,14 +6,18 @@ import ( ) // Coq lexer. -var Coq = internal.Register(MustNewLexer( +var Coq = internal.Register(MustNewLazyLexer( &Config{ Name: "Coq", Aliases: []string{"coq"}, Filenames: []string{"*.v"}, MimeTypes: []string{"text/x-coq"}, }, - Rules{ + coqRules, +)) + +func coqRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`false|true|\(\)|\[\]`, NameBuiltinPseudo, nil}, @@ -59,5 +63,5 @@ var Coq = internal.Register(MustNewLexer( {`[a-z][a-z0-9_\']*`, Name, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/cpp.go b/vendor/github.com/alecthomas/chroma/lexers/c/cpp.go index 104be24..3f4a1fd 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/cpp.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/cpp.go @@ -6,7 +6,7 @@ import ( ) // CPP lexer. -var CPP = internal.Register(MustNewLexer( +var CPP = internal.Register(MustNewLazyLexer( &Config{ Name: "C++", Aliases: []string{"cpp", "c++"}, @@ -14,7 +14,11 @@ var CPP = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-c++hdr", "text/x-c++src"}, EnsureNL: true, }, - Rules{ + cppRules, +)) + +func cppRules() Rules { + return Rules{ "statements": { {Words(``, `\b`, `catch`, `const_cast`, `delete`, `dynamic_cast`, `explicit`, `export`, `friend`, `mutable`, `namespace`, `new`, `operator`, `private`, `protected`, `public`, `reinterpret_cast`, `restrict`, `static_cast`, `template`, `this`, `throw`, `throws`, `try`, `typeid`, `typename`, `using`, `virtual`, `constexpr`, `nullptr`, `decltype`, `thread_local`, `alignas`, `alignof`, `static_assert`, `noexcept`, `override`, `final`, `concept`, `requires`, `consteval`, `co_await`, `co_return`, `co_yield`), Keyword, nil}, {`(enum)\b(\s+)(class)\b(\s*)`, ByGroups(Keyword, Text, Keyword, Text), Push("classname")}, @@ -102,5 +106,5 @@ var CPP = internal.Register(MustNewLexer( {`^\s*#endif.*?(?=~!@#%^&|`?-]+", Operator, nil}, - {`(?s)(java|javascript)(\s+)(AS)(\s+)('|\$\$)(.*?)(\5)`, + { + `(?s)(java|javascript)(\s+)(AS)(\s+)('|\$\$)(.*?)(\5)`, UsingByGroup( internal.Get, 1, 6, @@ -65,5 +70,5 @@ var CassandraCQL = internal.Register(MustNewLexer( {`[^\$]+`, LiteralStringHeredoc, nil}, {`\$\$`, LiteralStringHeredoc, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/crystal.go b/vendor/github.com/alecthomas/chroma/lexers/c/crystal.go index 69e053c..f06830d 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/crystal.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/crystal.go @@ -6,7 +6,7 @@ import ( ) // Crystal lexer. -var Crystal = internal.Register(MustNewLexer( +var Crystal = internal.Register(MustNewLazyLexer( &Config{ Name: "Crystal", Aliases: []string{"cr", "crystal"}, @@ -14,7 +14,11 @@ var Crystal = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-crystal"}, DotAll: true, }, - Rules{ + crystalRules, +)) + +func crystalRules() Rules { + return Rules{ "root": { {`#.*?$`, CommentSingle, nil}, {Words(``, `\b`, `abstract`, `asm`, `as`, `begin`, `break`, `case`, `do`, `else`, `elsif`, `end`, `ensure`, `extend`, `ifdef`, `if`, `include`, `instance_sizeof`, `next`, `of`, `pointerof`, `private`, `protected`, `rescue`, `return`, `require`, `sizeof`, `super`, `then`, `typeof`, `unless`, `until`, `when`, `while`, `with`, `yield`), Keyword, nil}, @@ -258,5 +262,5 @@ var Crystal = internal.Register(MustNewLexer( {`[\\#<>]`, LiteralStringRegex, nil}, {`[^\\#<>]+`, LiteralStringRegex, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/csharp.go b/vendor/github.com/alecthomas/chroma/lexers/c/csharp.go index c6a5f46..725bcb8 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/csharp.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/csharp.go @@ -6,7 +6,7 @@ import ( ) // CSharp lexer. -var CSharp = internal.Register(MustNewLexer( +var CSharp = internal.Register(MustNewLazyLexer( &Config{ Name: "C#", Aliases: []string{"csharp", "c#"}, @@ -15,7 +15,11 @@ var CSharp = internal.Register(MustNewLexer( DotAll: true, EnsureNL: true, }, - Rules{ + cSharpRules, +)) + +func cSharpRules() Rules { + return Rules{ "root": { {`^\s*\[.*?\]`, NameAttribute, nil}, {`[^\S\n]+`, Text, nil}, @@ -29,7 +33,7 @@ var CSharp = internal.Register(MustNewLexer( {`\$@?"(""|[^"])*"`, LiteralString, nil}, {`"(\\\\|\\"|[^"\n])*["\n]`, LiteralString, nil}, {`'\\.'|'[^\\]'`, LiteralStringChar, nil}, - {`[0-9](\.[0-9]*)?([eE][+-][0-9]+)?[flFLdD]?|0[xX][0-9a-fA-F]+[Ll]?`, LiteralNumber, nil}, + {`0[xX][0-9a-fA-F]+[Ll]?|[0-9_](\.[0-9]*)?([eE][+-]?[0-9]+)?[flFLdD]?`, LiteralNumber, nil}, {`#[ \t]*(if|endif|else|elif|define|undef|line|error|warning|region|endregion|pragma)\b.*?\n`, CommentPreproc, nil}, {`\b(extern)(\s+)(alias)\b`, ByGroups(Keyword, Text, Keyword), nil}, {`(abstract|as|async|await|base|break|by|case|catch|checked|const|continue|default|delegate|do|else|enum|event|explicit|extern|false|finally|fixed|for|foreach|goto|if|implicit|in|interface|internal|is|let|lock|new|null|on|operator|out|override|params|private|protected|public|readonly|ref|return|sealed|sizeof|stackalloc|static|switch|this|throw|true|try|typeof|unchecked|unsafe|virtual|void|while|get|set|new|partial|yield|add|remove|value|alias|ascending|descending|from|group|into|orderby|select|thenby|where|join|equals)\b`, Keyword, nil}, @@ -47,5 +51,5 @@ var CSharp = internal.Register(MustNewLexer( {`(?=\()`, Text, Pop(1)}, {`(@?[_a-zA-Z]\w*|\.)+`, NameNamespace, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/css.go b/vendor/github.com/alecthomas/chroma/lexers/c/css.go index fedc809..9f3a01d 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/css.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/css.go @@ -6,14 +6,18 @@ import ( ) // CSS lexer. -var CSS = internal.Register(MustNewLexer( +var CSS = internal.Register(MustNewLazyLexer( &Config{ Name: "CSS", Aliases: []string{"css"}, Filenames: []string{"*.css"}, MimeTypes: []string{"text/css"}, }, - Rules{ + cssRules, +)) + +func cssRules() Rules { + return Rules{ "root": { Include("basics"), }, @@ -39,6 +43,18 @@ var CSS = internal.Register(MustNewLexer( Include("basics"), {`\}`, Punctuation, Pop(2)}, }, + "atparenthesis": { + Include("common-values"), + {`/\*(?:.|\n)*?\*/`, Comment, nil}, + Include("numeric-values"), + {`[*+/-]`, Operator, nil}, + {`[,]`, Punctuation, nil}, + {`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil}, + {`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil}, + {`[a-zA-Z_-]\w*`, Name, nil}, + {`\(`, Punctuation, Push("atparenthesis")}, + {`\)`, Punctuation, Pop(1)}, + }, "content": { {`\s+`, Text, nil}, {`\}`, Punctuation, Pop(1)}, @@ -73,6 +89,7 @@ var CSS = internal.Register(MustNewLexer( {`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil}, {`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil}, {`[a-zA-Z_-]\w*`, Name, nil}, + {`\(`, Punctuation, Push("atparenthesis")}, {`\)`, Punctuation, Pop(1)}, }, "common-values": { @@ -100,5 +117,5 @@ var CSS = internal.Register(MustNewLexer( {`%`, KeywordType, nil}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/c/cython.go b/vendor/github.com/alecthomas/chroma/lexers/c/cython.go index 701e2b7..0cce204 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/c/cython.go +++ b/vendor/github.com/alecthomas/chroma/lexers/c/cython.go @@ -6,14 +6,18 @@ import ( ) // Cython lexer. -var Cython = internal.Register(MustNewLexer( +var Cython = internal.Register(MustNewLazyLexer( &Config{ Name: "Cython", Aliases: []string{"cython", "pyx", "pyrex"}, Filenames: []string{"*.pyx", "*.pxd", "*.pxi"}, MimeTypes: []string{"text/x-cython", "application/x-cython"}, }, - Rules{ + cythonRules, +)) + +func cythonRules() Rules { + return Rules{ "root": { {`\n`, Text, nil}, {`^(\s*)("""(?:.|\n)*?""")`, ByGroups(Text, LiteralStringDoc), nil}, @@ -131,5 +135,5 @@ var Cython = internal.Register(MustNewLexer( Include("strings"), Include("nl"), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/circular/php.go b/vendor/github.com/alecthomas/chroma/lexers/circular/php.go index 2107cb7..517fb69 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/circular/php.go +++ b/vendor/github.com/alecthomas/chroma/lexers/circular/php.go @@ -6,7 +6,7 @@ import ( ) // PHP lexer for pure PHP code (not embedded in HTML). -var PHP = internal.Register(MustNewLexer( +var PHP = internal.Register(MustNewLazyLexer( &Config{ Name: "PHP", Aliases: []string{"php", "php3", "php4", "php5"}, @@ -16,65 +16,71 @@ var PHP = internal.Register(MustNewLexer( CaseInsensitive: true, EnsureNL: true, }, - phpCommonRules.Rename("php", "root"), + phpRules, )) -var phpCommonRules = Rules{ - "php": { - {`\?>`, CommentPreproc, Pop(1)}, - {`(<<<)([\'"]?)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)(\2\n.*?\n\s*)(\3)(;?)(\n)`, ByGroups(LiteralString, LiteralString, LiteralStringDelimiter, LiteralString, LiteralStringDelimiter, Punctuation, Text), nil}, - {`\s+`, Text, nil}, - {`#.*?\n`, CommentSingle, nil}, - {`//.*?\n`, CommentSingle, nil}, - {`/\*\*/`, CommentMultiline, nil}, - {`/\*\*.*?\*/`, LiteralStringDoc, nil}, - {`/\*.*?\*/`, CommentMultiline, nil}, - {`(->|::)(\s*)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)`, ByGroups(Operator, Text, NameAttribute), nil}, - {`[~!%^&*+=|:.<>/@-]+`, Operator, nil}, - {`\?`, Operator, nil}, - {`[\[\]{}();,]+`, Punctuation, nil}, - {`(class)(\s+)`, ByGroups(Keyword, Text), Push("classname")}, - {`(function)(\s*)(?=\()`, ByGroups(Keyword, Text), nil}, - {`(function)(\s+)(&?)(\s*)`, ByGroups(Keyword, Text, Operator, Text), Push("functionname")}, - {`(const)(\s+)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)`, ByGroups(Keyword, Text, NameConstant), nil}, - {`(and|E_PARSE|old_function|E_ERROR|or|as|E_WARNING|parent|eval|PHP_OS|break|exit|case|extends|PHP_VERSION|cfunction|FALSE|print|for|require|continue|foreach|require_once|declare|return|default|static|do|switch|die|stdClass|echo|else|TRUE|elseif|var|empty|if|xor|enddeclare|include|virtual|endfor|include_once|while|endforeach|global|endif|list|endswitch|new|endwhile|not|array|E_ALL|NULL|final|php_user_filter|interface|implements|public|private|protected|abstract|clone|try|catch|throw|this|use|namespace|trait|yield|finally)\b`, Keyword, nil}, - {`(true|false|null)\b`, KeywordConstant, nil}, - Include("magicconstants"), - {`\$\{\$+(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*\}`, NameVariable, nil}, - {`\$+(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameVariable, nil}, - {`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameOther, nil}, - {`(\d+\.\d*|\d*\.\d+)(e[+-]?[0-9]+)?`, LiteralNumberFloat, nil}, - {`\d+e[+-]?[0-9]+`, LiteralNumberFloat, nil}, - {`0[0-7]+`, LiteralNumberOct, nil}, - {`0x[a-f0-9]+`, LiteralNumberHex, nil}, - {`\d+`, LiteralNumberInteger, nil}, - {`0b[01]+`, LiteralNumberBin, nil}, - {`'([^'\\]*(?:\\.[^'\\]*)*)'`, LiteralStringSingle, nil}, - {"`([^`\\\\]*(?:\\\\.[^`\\\\]*)*)`", LiteralStringBacktick, nil}, - {`"`, LiteralStringDouble, Push("string")}, - }, - "magicfuncs": { - {Words(``, `\b`, `__construct`, `__destruct`, `__call`, `__callStatic`, `__get`, `__set`, `__isset`, `__unset`, `__sleep`, `__wakeup`, `__toString`, `__invoke`, `__set_state`, `__clone`, `__debugInfo`), NameFunctionMagic, nil}, - }, - "magicconstants": { - {Words(``, `\b`, `__LINE__`, `__FILE__`, `__DIR__`, `__FUNCTION__`, `__CLASS__`, `__TRAIT__`, `__METHOD__`, `__NAMESPACE__`), NameConstant, nil}, - }, - "classname": { - {`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameClass, Pop(1)}, - }, - "functionname": { - Include("magicfuncs"), - {`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameFunction, Pop(1)}, - Default(Pop(1)), - }, - "string": { - {`"`, LiteralStringDouble, Pop(1)}, - {`[^{$"\\]+`, LiteralStringDouble, nil}, - {`\\([nrt"$\\]|[0-7]{1,3}|x[0-9a-f]{1,2})`, LiteralStringEscape, nil}, - {`\$(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*(\[\S+?\]|->(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)?`, LiteralStringInterpol, nil}, - {`(\{\$\{)(.*?)(\}\})`, ByGroups(LiteralStringInterpol, UsingSelf("root"), LiteralStringInterpol), nil}, - {`(\{)(\$.*?)(\})`, ByGroups(LiteralStringInterpol, UsingSelf("root"), LiteralStringInterpol), nil}, - {`(\$\{)(\S+)(\})`, ByGroups(LiteralStringInterpol, NameVariable, LiteralStringInterpol), nil}, - {`[${\\]`, LiteralStringDouble, nil}, - }, +func phpRules() Rules { + return phpCommonRules().Rename("php", "root") +} + +func phpCommonRules() Rules { + return Rules{ + "php": { + {`\?>`, CommentPreproc, Pop(1)}, + {`(<<<)([\'"]?)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)(\2\n.*?\n\s*)(\3)(;?)(\n)`, ByGroups(LiteralString, LiteralString, LiteralStringDelimiter, LiteralString, LiteralStringDelimiter, Punctuation, Text), nil}, + {`\s+`, Text, nil}, + {`#.*?\n`, CommentSingle, nil}, + {`//.*?\n`, CommentSingle, nil}, + {`/\*\*/`, CommentMultiline, nil}, + {`/\*\*.*?\*/`, LiteralStringDoc, nil}, + {`/\*.*?\*/`, CommentMultiline, nil}, + {`(->|::)(\s*)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)`, ByGroups(Operator, Text, NameAttribute), nil}, + {`[~!%^&*+=|:.<>/@-]+`, Operator, nil}, + {`\?`, Operator, nil}, + {`[\[\]{}();,]+`, Punctuation, nil}, + {`(class)(\s+)`, ByGroups(Keyword, Text), Push("classname")}, + {`(function)(\s*)(?=\()`, ByGroups(Keyword, Text), nil}, + {`(function)(\s+)(&?)(\s*)`, ByGroups(Keyword, Text, Operator, Text), Push("functionname")}, + {`(const)(\s+)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)`, ByGroups(Keyword, Text, NameConstant), nil}, + {`(and|E_PARSE|old_function|E_ERROR|or|as|E_WARNING|parent|eval|PHP_OS|break|exit|case|extends|PHP_VERSION|cfunction|FALSE|print|for|require|continue|foreach|require_once|declare|return|default|static|do|switch|die|stdClass|echo|else|TRUE|elseif|var|empty|if|xor|enddeclare|include|virtual|endfor|include_once|while|endforeach|global|endif|list|endswitch|new|endwhile|not|array|E_ALL|NULL|final|php_user_filter|interface|implements|public|private|protected|abstract|clone|try|catch|throw|this|use|namespace|trait|yield|finally)\b`, Keyword, nil}, + {`(true|false|null)\b`, KeywordConstant, nil}, + Include("magicconstants"), + {`\$\{\$+(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*\}`, NameVariable, nil}, + {`\$+(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameVariable, nil}, + {`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameOther, nil}, + {`(\d+\.\d*|\d*\.\d+)(e[+-]?[0-9]+)?`, LiteralNumberFloat, nil}, + {`\d+e[+-]?[0-9]+`, LiteralNumberFloat, nil}, + {`0[0-7]+`, LiteralNumberOct, nil}, + {`0x[a-f0-9_]+`, LiteralNumberHex, nil}, + {`[\d_]+`, LiteralNumberInteger, nil}, + {`0b[01]+`, LiteralNumberBin, nil}, + {`'([^'\\]*(?:\\.[^'\\]*)*)'`, LiteralStringSingle, nil}, + {"`([^`\\\\]*(?:\\\\.[^`\\\\]*)*)`", LiteralStringBacktick, nil}, + {`"`, LiteralStringDouble, Push("string")}, + }, + "magicfuncs": { + {Words(``, `\b`, `__construct`, `__destruct`, `__call`, `__callStatic`, `__get`, `__set`, `__isset`, `__unset`, `__sleep`, `__wakeup`, `__toString`, `__invoke`, `__set_state`, `__clone`, `__debugInfo`), NameFunctionMagic, nil}, + }, + "magicconstants": { + {Words(``, `\b`, `__LINE__`, `__FILE__`, `__DIR__`, `__FUNCTION__`, `__CLASS__`, `__TRAIT__`, `__METHOD__`, `__NAMESPACE__`), NameConstant, nil}, + }, + "classname": { + {`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameClass, Pop(1)}, + }, + "functionname": { + Include("magicfuncs"), + {`(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*`, NameFunction, Pop(1)}, + Default(Pop(1)), + }, + "string": { + {`"`, LiteralStringDouble, Pop(1)}, + {`[^{$"\\]+`, LiteralStringDouble, nil}, + {`\\([nrt"$\\]|[0-7]{1,3}|x[0-9a-f]{1,2})`, LiteralStringEscape, nil}, + {`\$(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*(\[\S+?\]|->(?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)?`, LiteralStringInterpol, nil}, + {`(\{\$\{)(.*?)(\}\})`, ByGroups(LiteralStringInterpol, UsingSelf("root"), LiteralStringInterpol), nil}, + {`(\{)(\$.*?)(\})`, ByGroups(LiteralStringInterpol, UsingSelf("root"), LiteralStringInterpol), nil}, + {`(\$\{)(\S+)(\})`, ByGroups(LiteralStringInterpol, NameVariable, LiteralStringInterpol), nil}, + {`[${\\]`, LiteralStringDouble, nil}, + }, + } } diff --git a/vendor/github.com/alecthomas/chroma/lexers/circular/phtml.go b/vendor/github.com/alecthomas/chroma/lexers/circular/phtml.go index b9bffd3..fc2e2ea 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/circular/phtml.go +++ b/vendor/github.com/alecthomas/chroma/lexers/circular/phtml.go @@ -9,26 +9,31 @@ import ( ) // PHTML lexer is PHP in HTML. -var PHTML = internal.Register(DelegatingLexer(h.HTML, MustNewLexer( +var PHTML = internal.Register(DelegatingLexer(h.HTML, MustNewLazyLexer( &Config{ Name: "PHTML", Aliases: []string{"phtml"}, - Filenames: []string{"*.phtml"}, - MimeTypes: []string{"application/x-php", "application/x-httpd-php", "application/x-httpd-php3", "application/x-httpd-php4", "application/x-httpd-php5"}, + Filenames: []string{"*.phtml", "*.php", "*.php[345]", "*.inc"}, + MimeTypes: []string{"application/x-php", "application/x-httpd-php", "application/x-httpd-php3", "application/x-httpd-php4", "application/x-httpd-php5", "text/x-php"}, DotAll: true, CaseInsensitive: true, EnsureNL: true, + Priority: 2, }, - Rules{ - "root": { - {`<\?(php)?`, CommentPreproc, Push("php")}, - {`[^<]+`, Other, nil}, - {`<`, Other, nil}, - }, - }.Merge(phpCommonRules), + phtmlRules, ).SetAnalyser(func(text string) float32 { if strings.Contains(text, "\s|()?+*,]+`, NameAttribute, nil}, {`>`, Keyword, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/d/dylan.go b/vendor/github.com/alecthomas/chroma/lexers/d/dylan.go new file mode 100644 index 0000000..feda748 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/d/dylan.go @@ -0,0 +1,76 @@ +package d + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// Dylan lexer. +var Dylan = internal.Register(MustNewLazyLexer( + &Config{ + Name: "Dylan", + Aliases: []string{"dylan"}, + Filenames: []string{"*.dylan", "*.dyl", "*.intr"}, + MimeTypes: []string{"text/x-dylan"}, + CaseInsensitive: true, + }, + func() Rules { + return Rules{ + "root": { + {`\s+`, Whitespace, nil}, + {`//.*?\n`, CommentSingle, nil}, + {`([a-z0-9-]+:)([ \t]*)(.*(?:\n[ \t].+)*)`, ByGroups(NameAttribute, Whitespace, LiteralString), nil}, + Default(Push("code")), + }, + "code": { + {`\s+`, Whitespace, nil}, + {`//.*?\n`, CommentSingle, nil}, + {`/\*`, CommentMultiline, Push("comment")}, + {`"`, LiteralString, Push("string")}, + {`'(\\.|\\[0-7]{1,3}|\\x[a-f0-9]{1,2}|[^\\\'\n])'`, LiteralStringChar, nil}, + {`#b[01]+`, LiteralNumberBin, nil}, + {`#o[0-7]+`, LiteralNumberOct, nil}, + {`[-+]?(\d*\.\d+([ed][-+]?\d+)?|\d+(\.\d*)?e[-+]?\d+)`, LiteralNumberFloat, nil}, + {`[-+]?\d+`, LiteralNumberInteger, nil}, + {`#x[0-9a-f]+`, LiteralNumberHex, nil}, + + {`(\?\\?)([\w!&*<>|^$%@+~?/=-]+)(:)(token|name|variable|expression|body|case-body|\*)`, + ByGroups(Operator, NameVariable, Operator, NameBuiltin), nil}, + {`(\?)(:)(token|name|variable|expression|body|case-body|\*)`, + ByGroups(Operator, Operator, NameVariable), nil}, + {`(\?\\?)([\w!&*<>|^$%@+~?/=-]+)`, ByGroups(Operator, NameVariable), nil}, + + {`(=>|::|#\(|#\[|##|\?\?|\?=|\?|[(){}\[\],.;])`, Punctuation, nil}, + {`:=`, Operator, nil}, + {`#[tf]`, Literal, nil}, + {`#"`, LiteralStringSymbol, Push("symbol")}, + {`#[a-z0-9-]+`, Keyword, nil}, + {`#(all-keys|include|key|next|rest)`, Keyword, nil}, + {`[\w!&*<>|^$%@+~?/=-]+:`, KeywordConstant, nil}, + {`<[\w!&*<>|^$%@+~?/=-]+>`, NameClass, nil}, + {`\*[\w!&*<>|^$%@+~?/=-]+\*`, NameVariableGlobal, nil}, + {`\$[\w!&*<>|^$%@+~?/=-]+`, NameConstant, nil}, + {`(let|method|function)([ \t]+)([\w!&*<>|^$%@+~?/=-]+)`, ByGroups(NameBuiltin, Whitespace, NameVariable), nil}, + {`(error|signal|return|break)`, NameException, nil}, + {`(\\?)([\w!&*<>|^$%@+~?/=-]+)`, ByGroups(Operator, Name), nil}, + }, + "comment": { + {`[^*/]`, CommentMultiline, nil}, + {`/\*`, CommentMultiline, Push()}, + {`\*/`, CommentMultiline, Pop(1)}, + {`[*/]`, CommentMultiline, nil}, + }, + "symbol": { + {`"`, LiteralStringSymbol, Pop(1)}, + {`[^\\"]+`, LiteralStringSymbol, nil}, + }, + "string": { + {`"`, LiteralString, Pop(1)}, + {`\\([\\abfnrtv"\']|x[a-f0-9]{2,4}|[0-7]{1,3})`, LiteralStringEscape, nil}, + {`[^\\"\n]+`, LiteralString, nil}, + {`\\\n`, LiteralString, nil}, + {`\\`, LiteralString, nil}, + }, + } + }, +)) diff --git a/vendor/github.com/alecthomas/chroma/lexers/e/ebnf.go b/vendor/github.com/alecthomas/chroma/lexers/e/ebnf.go index 42a3a37..5ccdd38 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/e/ebnf.go +++ b/vendor/github.com/alecthomas/chroma/lexers/e/ebnf.go @@ -6,14 +6,18 @@ import ( ) // Ebnf lexer. -var Ebnf = internal.Register(MustNewLexer( +var Ebnf = internal.Register(MustNewLazyLexer( &Config{ Name: "EBNF", Aliases: []string{"ebnf"}, Filenames: []string{"*.ebnf"}, MimeTypes: []string{"text/x-ebnf"}, }, - Rules{ + ebnfRules, +)) + +func ebnfRules() Rules { + return Rules{ "root": { Include("whitespace"), Include("comment_start"), @@ -47,5 +51,5 @@ var Ebnf = internal.Register(MustNewLexer( "identifier": { {`([a-zA-Z][\w \-]*)`, Keyword, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/e/elixir.go b/vendor/github.com/alecthomas/chroma/lexers/e/elixir.go index 11dc844..f283f84 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/e/elixir.go +++ b/vendor/github.com/alecthomas/chroma/lexers/e/elixir.go @@ -6,14 +6,18 @@ import ( ) // Elixir lexer. -var Elixir = internal.Register(MustNewLexer( +var Elixir = internal.Register(MustNewLazyLexer( &Config{ Name: "Elixir", Aliases: []string{"elixir", "ex", "exs"}, Filenames: []string{"*.ex", "*.exs"}, MimeTypes: []string{"text/x-elixir"}, }, - Rules{ + elixirRules, +)) + +func elixirRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`#.*$`, CommentSingle, nil}, @@ -273,5 +277,5 @@ var Elixir = internal.Register(MustNewLexer( {`\\.`, LiteralStringOther, nil}, {`'[a-zA-Z]*`, LiteralStringOther, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/e/elm.go b/vendor/github.com/alecthomas/chroma/lexers/e/elm.go index a71c627..0fb6689 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/e/elm.go +++ b/vendor/github.com/alecthomas/chroma/lexers/e/elm.go @@ -6,14 +6,18 @@ import ( ) // Elm lexer. -var Elm = internal.Register(MustNewLexer( +var Elm = internal.Register(MustNewLazyLexer( &Config{ Name: "Elm", Aliases: []string{"elm"}, Filenames: []string{"*.elm"}, MimeTypes: []string{"text/x-elm"}, }, - Rules{ + elmRules, +)) + +func elmRules() Rules { + return Rules{ "root": { {`\{-`, CommentMultiline, Push("comment")}, {`--.*`, CommentSingle, nil}, @@ -55,5 +59,5 @@ var Elm = internal.Register(MustNewLexer( {`\|\]`, NameEntity, Pop(1)}, {`.*\n`, NameEntity, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/e/emacs.go b/vendor/github.com/alecthomas/chroma/lexers/e/emacs.go index 78ffda1..51c4910 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/e/emacs.go +++ b/vendor/github.com/alecthomas/chroma/lexers/e/emacs.go @@ -522,14 +522,24 @@ var ( ) // EmacsLisp lexer. -var EmacsLisp = internal.Register(TypeRemappingLexer(MustNewLexer( +var EmacsLisp = internal.Register(TypeRemappingLexer(MustNewLazyLexer( &Config{ Name: "EmacsLisp", Aliases: []string{"emacs", "elisp", "emacs-lisp"}, Filenames: []string{"*.el"}, MimeTypes: []string{"text/x-elisp", "application/x-elisp"}, }, - Rules{ + emacsLispRules, +), TypeMapping{ + {NameVariable, NameFunction, emacsBuiltinFunction}, + {NameVariable, NameBuiltin, emacsSpecialForms}, + {NameVariable, NameException, emacsErrorKeywords}, + {NameVariable, NameBuiltin, append(emacsBuiltinFunctionHighlighted, emacsMacros...)}, + {NameVariable, KeywordPseudo, emacsLambdaListKeywords}, +})) + +func emacsLispRules() Rules { + return Rules{ "root": { Default(Push("body")), }, @@ -572,11 +582,5 @@ var EmacsLisp = internal.Register(TypeRemappingLexer(MustNewLexer( {`\\\n`, LiteralString, nil}, {`"`, LiteralString, Pop(1)}, }, - }, -), TypeMapping{ - {NameVariable, NameFunction, emacsBuiltinFunction}, - {NameVariable, NameBuiltin, emacsSpecialForms}, - {NameVariable, NameException, emacsErrorKeywords}, - {NameVariable, NameBuiltin, append(emacsBuiltinFunctionHighlighted, emacsMacros...)}, - {NameVariable, KeywordPseudo, emacsLambdaListKeywords}, -})) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/e/erlang.go b/vendor/github.com/alecthomas/chroma/lexers/e/erlang.go index 63cd59a..5f5c9ca 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/e/erlang.go +++ b/vendor/github.com/alecthomas/chroma/lexers/e/erlang.go @@ -6,14 +6,18 @@ import ( ) // Erlang lexer. -var Erlang = internal.Register(MustNewLexer( +var Erlang = internal.Register(MustNewLazyLexer( &Config{ Name: "Erlang", Aliases: []string{"erlang"}, Filenames: []string{"*.erl", "*.hrl", "*.es", "*.escript"}, MimeTypes: []string{"text/x-erlang"}, }, - Rules{ + erlangRules, +)) + +func erlangRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`%.*\n`, Comment, nil}, @@ -62,5 +66,5 @@ var Erlang = internal.Register(MustNewLexer( {`,`, Punctuation, Pop(1)}, {`(?=\})`, Punctuation, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/f/factor.go b/vendor/github.com/alecthomas/chroma/lexers/f/factor.go index 26c0d56..d88beb2 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/f/factor.go +++ b/vendor/github.com/alecthomas/chroma/lexers/f/factor.go @@ -6,14 +6,18 @@ import ( ) // Factor lexer. -var Factor = internal.Register(MustNewLexer( +var Factor = internal.Register(MustNewLazyLexer( &Config{ Name: "Factor", Aliases: []string{"factor"}, Filenames: []string{"*.factor"}, MimeTypes: []string{"text/x-factor"}, }, - Rules{ + factorRules, +)) + +func factorRules() Rules { + return Rules{ "root": { {`#!.*$`, CommentPreproc, nil}, Default(Push("base")), @@ -111,5 +115,5 @@ var Factor = internal.Register(MustNewLexer( {`;\s`, Keyword, Pop(1)}, {`\S+`, NameFunction, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/f/fish.go b/vendor/github.com/alecthomas/chroma/lexers/f/fish.go index 185fc92..c350900 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/f/fish.go +++ b/vendor/github.com/alecthomas/chroma/lexers/f/fish.go @@ -6,18 +6,43 @@ import ( ) // Fish lexer. -var Fish = internal.Register(MustNewLexer( +var Fish = internal.Register(MustNewLazyLexer( &Config{ Name: "Fish", Aliases: []string{"fish", "fishshell"}, Filenames: []string{"*.fish", "*.load"}, MimeTypes: []string{"application/x-fish"}, }, - Rules{ + fishRules, +)) + +func fishRules() Rules { + keywords := []string{ + `begin`, `end`, `if`, `else`, `while`, `break`, `for`, `return`, `function`, `block`, + `case`, `continue`, `switch`, `not`, `and`, `or`, `set`, `echo`, `exit`, `pwd`, `true`, + `false`, `cd`, `cdh`, `count`, `test`, + } + keywordsPattern := Words(`\b`, `\b`, keywords...) + + builtins := []string{ + `alias`, `bg`, `bind`, `breakpoint`, `builtin`, `argparse`, `abbr`, `string`, `command`, + `commandline`, `complete`, `contains`, `dirh`, `dirs`, `disown`, `emit`, `eval`, `exec`, + `fg`, `fish`, `fish_add_path`, `fish_breakpoint_prompt`, `fish_command_not_found`, + `fish_config`, `fish_git_prompt`, `fish_greeting`, `fish_hg_prompt`, `fish_indent`, + `fish_is_root_user`, `fish_key_reader`, `fish_mode_prompt`, `fish_opt`, `fish_pager`, + `fish_prompt`, `fish_right_prompt`, `fish_status_to_signal`, `fish_svn_prompt`, + `fish_title`, `fish_update_completions`, `fish_vcs_prompt`, `fishd`, `funced`, + `funcsave`, `functions`, `help`, `history`, `isatty`, `jobs`, `math`, `mimedb`, `nextd`, + `open`, `prompt_pwd`, `realpath`, `popd`, `prevd`, `psub`, `pushd`, `random`, `read`, + `set_color`, `source`, `status`, `suspend`, `trap`, `type`, `ulimit`, `umask`, `vared`, + `fc`, `getopts`, `hash`, `kill`, `printf`, `time`, `wait`, + } + + return Rules{ "root": { Include("basic"), - Include("data"), Include("interp"), + Include("data"), }, "interp": { {`\$\(\(`, Keyword, Push("math")}, @@ -25,13 +50,20 @@ var Fish = internal.Register(MustNewLexer( {`\$#?(\w+|.)`, NameVariable, nil}, }, "basic": { - {`\b(begin|end|if|else|while|break|for|in|return|function|block|case|continue|switch|not|and|or|set|echo|exit|pwd|true|false|cd|count|test)(\s*)\b`, ByGroups(Keyword, Text), nil}, - {`\b(alias|bg|bind|breakpoint|builtin|command|commandline|complete|contains|dirh|dirs|emit|eval|exec|fg|fish|fish_config|fish_indent|fish_pager|fish_prompt|fish_right_prompt|fish_update_completions|fishd|funced|funcsave|functions|help|history|isatty|jobs|math|mimedb|nextd|open|popd|prevd|psub|pushd|random|read|set_color|source|status|trap|type|ulimit|umask|vared|fc|getopts|hash|kill|printf|time|wait)\s*\b(?!\.)`, NameBuiltin, nil}, + {Words(`(?<=(?:^|\A|;|&&|\|\||\||`+keywordsPattern+`)\s*)`, `(?=;?\b)`, keywords...), Keyword, nil}, + {`(?<=for\s+\S+\s+)in\b`, Keyword, nil}, + {Words(`\b`, `\s*\b(?!\.)`, builtins...), NameBuiltin, nil}, + {`#!.*\n`, CommentHashbang, nil}, {`#.*\n`, Comment, nil}, {`\\[\w\W]`, LiteralStringEscape, nil}, {`(\b\w+)(\s*)(=)`, ByGroups(NameVariable, Text, Operator), nil}, - {`[\[\]()=]`, Operator, nil}, + {`[\[\]()={}]`, Operator, nil}, + {`(?<=\[[^\]]+)\.\.|-(?=[^\[]+\])`, Operator, nil}, {`<<-?\s*(\'?)\\?(\w+)[\w\W]+?\2`, LiteralString, nil}, + {`(?<=set\s+(?:--?[^\d\W][\w-]*\s+)?)\w+`, NameVariable, nil}, + {`(?<=for\s+)\w[\w-]*(?=\s+in)`, NameVariable, nil}, + {`(?<=function\s+)\w(?:[^\n])*?(?= *[-\n])`, NameFunction, nil}, + {`(?<=(?:^|\b(?:and|or|sudo)\b|;|\|\||&&|\||\(|(?:\b\w+\s*=\S+\s)) *)\w[\w-]*`, NameFunction, nil}, }, "data": { {`(?s)\$?"(\\\\|\\[0-7]+|\\.|[^"\\$])*"`, LiteralStringDouble, nil}, @@ -39,10 +71,11 @@ var Fish = internal.Register(MustNewLexer( {`(?s)\$'(\\\\|\\[0-7]+|\\.|[^'\\])*'`, LiteralStringSingle, nil}, {`(?s)'.*?'`, LiteralStringSingle, nil}, {`;`, Punctuation, nil}, - {`&|\||\^|<|>`, Operator, nil}, + {`&&|\|\||&|\||\^|<|>`, Operator, nil}, {`\s+`, Text, nil}, - {`\d+(?= |\Z)`, LiteralNumber, nil}, - {"[^=\\s\\[\\]{}()$\"\\'`\\\\<&|;]+", Text, nil}, + {`\b\d+\b`, LiteralNumber, nil}, + {`--?[^\d][\w-]*`, NameAttribute, nil}, + {".+?", Text, nil}, }, "string": { {`"`, LiteralStringDouble, Pop(1)}, @@ -61,5 +94,5 @@ var Fish = internal.Register(MustNewLexer( {`\d+`, LiteralNumber, nil}, Include("root"), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/f/forth.go b/vendor/github.com/alecthomas/chroma/lexers/f/forth.go index 47de636..8d66708 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/f/forth.go +++ b/vendor/github.com/alecthomas/chroma/lexers/f/forth.go @@ -6,7 +6,7 @@ import ( ) // Forth lexer. -var Forth = internal.Register(MustNewLexer( +var Forth = internal.Register(MustNewLazyLexer( &Config{ Name: "Forth", Aliases: []string{"forth"}, @@ -14,7 +14,11 @@ var Forth = internal.Register(MustNewLexer( MimeTypes: []string{"application/x-forth"}, CaseInsensitive: true, }, - Rules{ + forthRules, +)) + +func forthRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`\\.*?\n`, CommentSingle, nil}, @@ -36,5 +40,5 @@ var Forth = internal.Register(MustNewLexer( "stringdef": { {`[^"]+`, LiteralString, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/f/fortran.go b/vendor/github.com/alecthomas/chroma/lexers/f/fortran.go index 6c57afa..af4a969 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/f/fortran.go +++ b/vendor/github.com/alecthomas/chroma/lexers/f/fortran.go @@ -6,7 +6,7 @@ import ( ) // Fortran lexer. -var Fortran = internal.Register(MustNewLexer( +var Fortran = internal.Register(MustNewLazyLexer( &Config{ Name: "Fortran", Aliases: []string{"fortran"}, @@ -14,7 +14,11 @@ var Fortran = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-fortran"}, CaseInsensitive: true, }, - Rules{ + fortranRules, +)) + +func fortranRules() Rules { + return Rules{ "root": { {`^#.*\n`, CommentPreproc, nil}, {`!.*\n`, Comment, nil}, @@ -43,5 +47,5 @@ var Fortran = internal.Register(MustNewLexer( {`[+-]?\d*\.\d+([ed][-+]?\d+)?(_[a-z]\w+)?`, LiteralNumberFloat, nil}, {`[+-]?\d+\.\d*([ed][-+]?\d+)?(_[a-z]\w+)?`, LiteralNumberFloat, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/f/fortran_fixed.go b/vendor/github.com/alecthomas/chroma/lexers/f/fortran_fixed.go new file mode 100644 index 0000000..7c64638 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/f/fortran_fixed.go @@ -0,0 +1,39 @@ +package f + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// FortranFixed lexer. +var FortranFixed = internal.Register(MustNewLazyLexer( + &Config{ + Name: "FortranFixed", + Aliases: []string{"fortranfixed"}, + Filenames: []string{"*.f", "*.F"}, + MimeTypes: []string{"text/x-fortran"}, + NotMultiline: true, + CaseInsensitive: true, + }, + func() Rules { + return Rules{ + "root": { + {`[C*].*\n`, Comment, nil}, + {`#.*\n`, CommentPreproc, nil}, + {`[\t ]*!.*\n`, Comment, nil}, + {`(.{5})`, NameLabel, Push("cont-char")}, + {`.*\n`, Using(Fortran), nil}, + }, + "cont-char": { + {` `, Text, Push("code")}, + {`0`, Comment, Push("code")}, + {`.`, GenericStrong, Push("code")}, + }, + "code": { + {`(.{66})(.*)(\n)`, ByGroups(Using(Fortran), Comment, Text), Push("root")}, + {`.*\n`, Using(Fortran), Push("root")}, + Default(Push("root")), + }, + } + }, +)) diff --git a/vendor/github.com/alecthomas/chroma/lexers/f/fsharp.go b/vendor/github.com/alecthomas/chroma/lexers/f/fsharp.go index d00f63d..44fced4 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/f/fsharp.go +++ b/vendor/github.com/alecthomas/chroma/lexers/f/fsharp.go @@ -6,14 +6,18 @@ import ( ) // Fsharp lexer. -var Fsharp = internal.Register(MustNewLexer( +var Fsharp = internal.Register(MustNewLazyLexer( &Config{ Name: "FSharp", Aliases: []string{"fsharp"}, Filenames: []string{"*.fs", "*.fsi"}, MimeTypes: []string{"text/x-fsharp"}, }, - Rules{ + fsharpRules, +)) + +func fsharpRules() Rules { + return Rules{ "escape-sequence": { {`\\[\\"\'ntbrafv]`, LiteralStringEscape, nil}, {`\\[0-9]{3}`, LiteralStringEscape, nil}, @@ -90,5 +94,5 @@ var Fsharp = internal.Register(MustNewLexer( {`"""B?`, LiteralString, Pop(1)}, {`"`, LiteralString, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/g/gas.go b/vendor/github.com/alecthomas/chroma/lexers/g/gas.go index a922806..1f733f6 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/g/gas.go +++ b/vendor/github.com/alecthomas/chroma/lexers/g/gas.go @@ -6,14 +6,18 @@ import ( ) // Gas lexer. -var Gas = internal.Register(MustNewLexer( +var Gas = internal.Register(MustNewLazyLexer( &Config{ Name: "GAS", Aliases: []string{"gas", "asm"}, Filenames: []string{"*.s", "*.S"}, MimeTypes: []string{"text/x-gas"}, }, - Rules{ + gasRules, +)) + +func gasRules() Rules { + return Rules{ "root": { Include("whitespace"), {`(?:[a-zA-Z$_][\w$.@-]*|\.[\w$.@-]+):`, NameLabel, nil}, @@ -51,5 +55,5 @@ var Gas = internal.Register(MustNewLexer( "punctuation": { {`[-*,.()\[\]!:]+`, Punctuation, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/g/gdscript.go b/vendor/github.com/alecthomas/chroma/lexers/g/gdscript.go index bfe3063..2b6af97 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/g/gdscript.go +++ b/vendor/github.com/alecthomas/chroma/lexers/g/gdscript.go @@ -6,14 +6,18 @@ import ( ) // GDScript lexer. -var GDScript = internal.Register(MustNewLexer( +var GDScript = internal.Register(MustNewLazyLexer( &Config{ Name: "GDScript", Aliases: []string{"gdscript", "gd"}, Filenames: []string{"*.gd"}, MimeTypes: []string{"text/x-gdscript", "application/x-gdscript"}, }, - Rules{ + gdscriptRules, +)) + +func gdscriptRules() Rules { + return Rules{ "root": { {`\n`, Text, nil}, {`^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")`, ByGroups(Text, LiteralStringAffix, LiteralStringDoc), nil}, @@ -120,5 +124,5 @@ var GDScript = internal.Register(MustNewLexer( Include("strings-single"), {`\n`, LiteralStringSingle, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/g/genshi.go b/vendor/github.com/alecthomas/chroma/lexers/g/genshi.go index 0d3663a..dc4d4b1 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/g/genshi.go +++ b/vendor/github.com/alecthomas/chroma/lexers/g/genshi.go @@ -7,14 +7,18 @@ import ( ) // Genshi Text lexer. -var GenshiText = internal.Register(MustNewLexer( +var GenshiText = internal.Register(MustNewLazyLexer( &Config{ Name: "Genshi Text", Aliases: []string{"genshitext"}, Filenames: []string{}, MimeTypes: []string{"application/x-genshi-text", "text/x-genshi"}, }, - Rules{ + genshiTextRules, +)) + +func genshiTextRules() Rules { + return Rules{ "root": { {`[^#$\s]+`, Other, nil}, {`^(\s*)(##.*)$`, ByGroups(Text, Comment), nil}, @@ -33,11 +37,11 @@ var GenshiText = internal.Register(MustNewLexer( {`(?)`, ByGroups(CommentPreproc, Using(Python), CommentPreproc), nil}, - {`<\s*(script|style)\s*.*?>.*?<\s*/\1\s*>`, Other, nil}, - {`<\s*py:[a-zA-Z0-9]+`, NameTag, Push("pytag")}, - {`<\s*[a-zA-Z0-9:.]+`, NameTag, Push("tag")}, - Include("variable"), - {`[<$]`, Other, nil}, - }, - "pytag": { - {`\s+`, Text, nil}, - {`[\w:-]+\s*=`, NameAttribute, Push("pyattr")}, - {`/?\s*>`, NameTag, Pop(1)}, - }, - "pyattr": { - {`(")(.*?)(")`, ByGroups(LiteralString, Using(Python), LiteralString), Pop(1)}, - {`(')(.*?)(')`, ByGroups(LiteralString, Using(Python), LiteralString), Pop(1)}, - {`[^\s>]+`, LiteralString, Pop(1)}, - }, - "tag": { - {`\s+`, Text, nil}, - {`py:[\w-]+\s*=`, NameAttribute, Push("pyattr")}, - {`[\w:-]+\s*=`, NameAttribute, Push("attr")}, - {`/?\s*>`, NameTag, Pop(1)}, - }, - "attr": { - {`"`, LiteralString, Push("attr-dstring")}, - {`'`, LiteralString, Push("attr-sstring")}, - {`[^\s>]*`, LiteralString, Pop(1)}, - }, - "attr-dstring": { - {`"`, LiteralString, Pop(1)}, - Include("strings"), - {`'`, LiteralString, nil}, - }, - "attr-sstring": { - {`'`, LiteralString, Pop(1)}, - Include("strings"), - {`'`, LiteralString, nil}, - }, - "strings": { - {`[^"'$]+`, LiteralString, nil}, - Include("variable"), - }, - "variable": { - {`(?)`, ByGroups(CommentPreproc, Using(Python), CommentPreproc), nil}, + {`<\s*(script|style)\s*.*?>.*?<\s*/\1\s*>`, Other, nil}, + {`<\s*py:[a-zA-Z0-9]+`, NameTag, Push("pytag")}, + {`<\s*[a-zA-Z0-9:.]+`, NameTag, Push("tag")}, + Include("variable"), + {`[<$]`, Other, nil}, + }, + "pytag": { + {`\s+`, Text, nil}, + {`[\w:-]+\s*=`, NameAttribute, Push("pyattr")}, + {`/?\s*>`, NameTag, Pop(1)}, + }, + "pyattr": { + {`(")(.*?)(")`, ByGroups(LiteralString, Using(Python), LiteralString), Pop(1)}, + {`(')(.*?)(')`, ByGroups(LiteralString, Using(Python), LiteralString), Pop(1)}, + {`[^\s>]+`, LiteralString, Pop(1)}, + }, + "tag": { + {`\s+`, Text, nil}, + {`py:[\w-]+\s*=`, NameAttribute, Push("pyattr")}, + {`[\w:-]+\s*=`, NameAttribute, Push("attr")}, + {`/?\s*>`, NameTag, Pop(1)}, + }, + "attr": { + {`"`, LiteralString, Push("attr-dstring")}, + {`'`, LiteralString, Push("attr-sstring")}, + {`[^\s>]*`, LiteralString, Pop(1)}, + }, + "attr-dstring": { + {`"`, LiteralString, Pop(1)}, + Include("strings"), + {`'`, LiteralString, nil}, + }, + "attr-sstring": { + {`'`, LiteralString, Pop(1)}, + Include("strings"), + {`'`, LiteralString, nil}, + }, + "strings": { + {`[^"'$]+`, LiteralString, nil}, + Include("variable"), + }, + "variable": { + {`(?=!()\[\]{}.,;:]`, Punctuation, nil}, {`[^\W\d]\w*`, NameOther, nil}, }, - }, -).SetAnalyser(func(text string) float32 { - if strings.Contains(text, "fmt.") && strings.Contains(text, "package ") { - return 0.5 } - if strings.Contains(text, "package ") { - return 0.1 - } - return 0.0 -})) - -var goTemplateRules = Rules{ - "root": { - {`{{[-]?`, CommentPreproc, Push("template")}, - {`[^{]+`, Other, nil}, - {`{`, Other, nil}, - }, - "template": { - {`[-]?}}`, CommentPreproc, Pop(1)}, - {`/\*.*?\*/`, Comment, nil}, - {`(?=}})`, CommentPreproc, Pop(1)}, // Terminate the pipeline - {`\(`, Operator, Push("subexpression")}, - {`"(\\\\|\\"|[^"])*"`, LiteralString, nil}, - Include("expression"), - }, - "subexpression": { - {`\)`, Operator, Pop(1)}, - Include("expression"), - }, - "expression": { - {`\s+`, Whitespace, nil}, - {`\(`, Operator, Push("subexpression")}, - {`(range|if|else|while|with|template|end|true|false|nil|and|call|html|index|js|len|not|or|print|printf|println|urlquery|eq|ne|lt|le|gt|ge)\b`, Keyword, nil}, - {`\||:=`, Operator, nil}, - {`[$]?[^\W\d]\w*`, NameOther, nil}, - {`[$]?\.(?:[^\W\d]\w*)?`, NameAttribute, nil}, - {`"(\\\\|\\"|[^"])*"`, LiteralString, nil}, - {`\d+i`, LiteralNumber, nil}, - {`\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil}, - {`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil}, - {`\d+[Ee][-+]\d+i`, LiteralNumber, nil}, - {`\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil}, - {`\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil}, - {`0[0-7]+`, LiteralNumberOct, nil}, - {`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil}, - {`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil}, - {`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil}, - {"`[^`]*`", LiteralString, nil}, - }, } -var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLexer( +func goTemplateRules() Rules { + return Rules{ + "root": { + {`{{(- )?/\*(.|\n)*?\*/( -)?}}`, CommentMultiline, nil}, + {`{{[-]?`, CommentPreproc, Push("template")}, + {`[^{]+`, Other, nil}, + {`{`, Other, nil}, + }, + "template": { + {`[-]?}}`, CommentPreproc, Pop(1)}, + {`(?=}})`, CommentPreproc, Pop(1)}, // Terminate the pipeline + {`\(`, Operator, Push("subexpression")}, + {`"(\\\\|\\"|[^"])*"`, LiteralString, nil}, + Include("expression"), + }, + "subexpression": { + {`\)`, Operator, Pop(1)}, + Include("expression"), + }, + "expression": { + {`\s+`, Whitespace, nil}, + {`\(`, Operator, Push("subexpression")}, + {`(range|if|else|while|with|template|end|true|false|nil|and|call|html|index|js|len|not|or|print|printf|println|urlquery|eq|ne|lt|le|gt|ge)\b`, Keyword, nil}, + {`\||:?=|,`, Operator, nil}, + {`[$]?[^\W\d]\w*`, NameOther, nil}, + {`\$|[$]?\.(?:[^\W\d]\w*)?`, NameAttribute, nil}, + {`"(\\\\|\\"|[^"])*"`, LiteralString, nil}, + {`-?\d+i`, LiteralNumber, nil}, + {`-?\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil}, + {`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil}, + {`-?\d+[Ee][-+]\d+i`, LiteralNumber, nil}, + {`-?\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil}, + {`-?\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil}, + {`-?0[0-7]+`, LiteralNumberOct, nil}, + {`-?0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil}, + {`-?(0|[1-9][0-9]*)`, LiteralNumberInteger, nil}, + {`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil}, + {"`[^`]*`", LiteralString, nil}, + }, + } +} + +var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLazyLexer( &Config{ Name: "Go HTML Template", Aliases: []string{"go-html-template"}, @@ -106,7 +112,7 @@ var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLexer( goTemplateRules, ))) -var GoTextTemplate = internal.Register(MustNewLexer( +var GoTextTemplate = internal.Register(MustNewLazyLexer( &Config{ Name: "Go Text Template", Aliases: []string{"go-text-template"}, diff --git a/vendor/github.com/alecthomas/chroma/lexers/g/graphql.go b/vendor/github.com/alecthomas/chroma/lexers/g/graphql.go index a57e693..7d465cd 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/g/graphql.go +++ b/vendor/github.com/alecthomas/chroma/lexers/g/graphql.go @@ -6,13 +6,17 @@ import ( ) // Go lexer. -var Graphql = internal.Register(MustNewLexer( +var Graphql = internal.Register(MustNewLazyLexer( &Config{ Name: "GraphQL", Aliases: []string{"graphql", "graphqls", "gql"}, Filenames: []string{"*.graphql", "*.graphqls"}, }, - Rules{ + graphqlRules, +)) + +func graphqlRules() Rules { + return Rules{ "root": { {`(query|mutation|subscription|fragment|scalar|implements|interface|union|enum|input|type)`, KeywordDeclaration, Push("type")}, {`(on|extend|schema|directive|\.\.\.)`, KeywordDeclaration, nil}, @@ -41,5 +45,5 @@ var Graphql = internal.Register(MustNewLexer( {`[^\W\d]\w*`, NameClass, Pop(1)}, Include("root"), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/g/groff.go b/vendor/github.com/alecthomas/chroma/lexers/g/groff.go new file mode 100644 index 0000000..65a7093 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/g/groff.go @@ -0,0 +1,47 @@ +package g + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// Groff lexer. +var Groff = internal.Register(MustNewLazyLexer( + &Config{ + Name: "Groff", + Aliases: []string{"groff", "nroff", "man"}, + Filenames: []string{"*.[1-9]", "*.1p", "*.3pm", "*.man"}, + MimeTypes: []string{"application/x-troff", "text/troff"}, + }, + func() Rules { + return Rules{ + "root": { + {`(\.)(\w+)`, ByGroups(Text, Keyword), Push("request")}, + {`\.`, Punctuation, Push("request")}, + {`[^\\\n]+`, Text, Push("textline")}, + Default(Push("textline")), + }, + "textline": { + Include("escapes"), + {`[^\\\n]+`, Text, nil}, + {`\n`, Text, Pop(1)}, + }, + "escapes": { + {`\\"[^\n]*`, Comment, nil}, + {`\\[fn]\w`, LiteralStringEscape, nil}, + {`\\\(.{2}`, LiteralStringEscape, nil}, + {`\\.\[.*\]`, LiteralStringEscape, nil}, + {`\\.`, LiteralStringEscape, nil}, + {`\\\n`, Text, Push("request")}, + }, + "request": { + {`\n`, Text, Pop(1)}, + Include("escapes"), + {`"[^\n"]+"`, LiteralStringDouble, nil}, + {`\d+`, LiteralNumber, nil}, + {`\S+`, LiteralString, nil}, + {`\s+`, Text, nil}, + }, + } + }, +)) diff --git a/vendor/github.com/alecthomas/chroma/lexers/g/groovy.go b/vendor/github.com/alecthomas/chroma/lexers/g/groovy.go index a395415..8d37bd8 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/g/groovy.go +++ b/vendor/github.com/alecthomas/chroma/lexers/g/groovy.go @@ -6,7 +6,7 @@ import ( ) // Groovy lexer. -var Groovy = internal.Register(MustNewLexer( +var Groovy = internal.Register(MustNewLazyLexer( &Config{ Name: "Groovy", Aliases: []string{"groovy"}, @@ -14,7 +14,11 @@ var Groovy = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-groovy"}, DotAll: true, }, - Rules{ + groovyRules, +)) + +func groovyRules() Rules { + return Rules{ "root": { {`#!(.*?)$`, CommentPreproc, Push("base")}, Default(Push("base")), @@ -54,5 +58,5 @@ var Groovy = internal.Register(MustNewLexer( "import": { {`[\w.]+\*?`, NameNamespace, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/h/handlebars.go b/vendor/github.com/alecthomas/chroma/lexers/h/handlebars.go index 07072da..d34ef3a 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/h/handlebars.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/handlebars.go @@ -6,14 +6,18 @@ import ( ) // Handlebars lexer. -var Handlebars = internal.Register(MustNewLexer( +var Handlebars = internal.Register(MustNewLazyLexer( &Config{ Name: "Handlebars", - Aliases: []string{"handlebars"}, - Filenames: []string{"*.handlebars"}, + Aliases: []string{"handlebars", "hbs"}, + Filenames: []string{"*.handlebars", "*.hbs"}, MimeTypes: []string{}, }, - Rules{ + handlebarsRules, +)) + +func handlebarsRules() Rules { + return Rules{ "root": { {`[^{]+`, Other, nil}, {`\{\{!.*\}\}`, Comment, nil}, @@ -52,5 +56,5 @@ var Handlebars = internal.Register(MustNewLexer( {`:?'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil}, {`[0-9](\.[0-9]*)?(eE[+-][0-9])?[flFLdD]?|0[xX][0-9a-fA-F]+[Ll]?`, LiteralNumber, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/h/haskell.go b/vendor/github.com/alecthomas/chroma/lexers/h/haskell.go index b018eab..9780481 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/h/haskell.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/haskell.go @@ -6,14 +6,18 @@ import ( ) // Haskell lexer. -var Haskell = internal.Register(MustNewLexer( +var Haskell = internal.Register(MustNewLazyLexer( &Config{ Name: "Haskell", Aliases: []string{"haskell", "hs"}, Filenames: []string{"*.hs"}, MimeTypes: []string{"text/x-haskell"}, }, - Rules{ + haskellRules, +)) + +func haskellRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`--(?![!#$%&*+./<=>?@^|_~:\\]).*?$`, CommentSingle, nil}, @@ -95,5 +99,5 @@ var Haskell = internal.Register(MustNewLexer( {`\d+`, LiteralStringEscape, Pop(1)}, {`\s+\\`, LiteralStringEscape, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/h/haxe.go b/vendor/github.com/alecthomas/chroma/lexers/h/haxe.go index 5958543..cc8c693 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/h/haxe.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/haxe.go @@ -6,7 +6,7 @@ import ( ) // Haxe lexer. -var Haxe = internal.Register(MustNewLexer( +var Haxe = internal.Register(MustNewLazyLexer( &Config{ Name: "Haxe", Aliases: []string{"hx", "haxe", "hxsl"}, @@ -14,7 +14,11 @@ var Haxe = internal.Register(MustNewLexer( MimeTypes: []string{"text/haxe", "text/x-haxe", "text/x-hx"}, DotAll: true, }, - Rules{ + haxeRules, +)) + +func haxeRules() Rules { + return Rules{ "root": { Include("spaces"), Include("meta"), @@ -609,8 +613,8 @@ var Haxe = internal.Register(MustNewLexer( {`\}`, Punctuation, Pop(1)}, {`,`, Punctuation, Push("#pop", "object")}, }, - }, -)) + } +} func haxePreProcMutator(state *LexerState) error { stack, ok := state.Get("haxe-pre-proc").([][]string) diff --git a/vendor/github.com/alecthomas/chroma/lexers/h/hcl.go b/vendor/github.com/alecthomas/chroma/lexers/h/hcl.go index ce7064b..7206fba 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/h/hcl.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/hcl.go @@ -6,14 +6,18 @@ import ( ) // HCL lexer. -var HCL = internal.Register(MustNewLexer( +var HCL = internal.Register(MustNewLazyLexer( &Config{ Name: "HCL", Aliases: []string{"hcl"}, Filenames: []string{"*.hcl"}, MimeTypes: []string{"application/x-hcl"}, }, - Rules{ + hclRules, +)) + +func hclRules() Rules { + return Rules{ "root": { Include("string"), Include("punctuation"), @@ -65,5 +69,5 @@ var HCL = internal.Register(MustNewLexer( {`\s+`, Text, nil}, {`\\\n`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/h/hexdump.go b/vendor/github.com/alecthomas/chroma/lexers/h/hexdump.go index 8b7e7bd..0893537 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/h/hexdump.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/hexdump.go @@ -6,14 +6,18 @@ import ( ) // Hexdump lexer. -var Hexdump = internal.Register(MustNewLexer( +var Hexdump = internal.Register(MustNewLazyLexer( &Config{ Name: "Hexdump", Aliases: []string{"hexdump"}, Filenames: []string{}, MimeTypes: []string{}, }, - Rules{ + hexdumpRules, +)) + +func hexdumpRules() Rules { + return Rules{ "root": { {`\n`, Text, nil}, Include("offset"), @@ -63,5 +67,5 @@ var Hexdump = internal.Register(MustNewLexer( {`\s`, Text, nil}, {`^\*`, Punctuation, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/hlb.go b/vendor/github.com/alecthomas/chroma/lexers/h/hlb.go similarity index 95% rename from vendor/github.com/alecthomas/chroma/lexers/hlb.go rename to vendor/github.com/alecthomas/chroma/lexers/h/hlb.go index 4dcf8ed..6c5f637 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/hlb.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/hlb.go @@ -1,4 +1,4 @@ -package lexers +package h import ( . "github.com/alecthomas/chroma" // nolint @@ -6,14 +6,18 @@ import ( ) // HLB lexer. -var HLB = internal.Register(MustNewLexer( +var HLB = internal.Register(MustNewLazyLexer( &Config{ Name: "HLB", Aliases: []string{"hlb"}, Filenames: []string{"*.hlb"}, MimeTypes: []string{}, }, - Rules{ + hlbRules, +)) + +func hlbRules() Rules { + return Rules{ "root": { {`(#.*)`, ByGroups(CommentSingle), nil}, {`((\b(0(b|B|o|O|x|X)[a-fA-F0-9]+)\b)|(\b(0|[1-9][0-9]*)\b))`, ByGroups(LiteralNumber), nil}, @@ -50,5 +54,5 @@ var HLB = internal.Register(MustNewLexer( {`(\n|\r|\r\n)`, Text, nil}, {`.`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/h/html.go b/vendor/github.com/alecthomas/chroma/lexers/h/html.go index 07fc27e..b9ca1e1 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/h/html.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/html.go @@ -8,7 +8,7 @@ import ( ) // HTML lexer. -var HTML = internal.Register(MustNewLexer( +var HTML = internal.Register(MustNewLazyLexer( &Config{ Name: "HTML", Aliases: []string{"html"}, @@ -18,7 +18,11 @@ var HTML = internal.Register(MustNewLexer( DotAll: true, CaseInsensitive: true, }, - Rules{ + htmlRules, +)) + +func htmlRules() Rules { + return Rules{ "root": { {`[^<&]+`, Text, nil}, {`&\S*?;`, NameEntity, nil}, @@ -55,5 +59,5 @@ var HTML = internal.Register(MustNewLexer( {`'.*?'`, LiteralString, Pop(1)}, {`[^\s>]+`, LiteralString, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/h/http.go b/vendor/github.com/alecthomas/chroma/lexers/h/http.go index 135ec73..c515ed4 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/h/http.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/http.go @@ -8,7 +8,7 @@ import ( ) // HTTP lexer. -var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLexer( +var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLazyLexer( &Config{ Name: "HTTP", Aliases: []string{"http"}, @@ -17,7 +17,11 @@ var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLexer( NotMultiline: true, DotAll: true, }, - Rules{ + httpRules, +))) + +func httpRules() Rules { + return Rules{ "root": { {`(GET|POST|PUT|DELETE|HEAD|OPTIONS|TRACE|PATCH|CONNECT)( +)([^ ]+)( +)(HTTP)(/)([12]\.[01])(\r?\n|\Z)`, ByGroups(NameFunction, Text, NameNamespace, Text, KeywordReserved, Operator, LiteralNumber, Text), Push("headers")}, {`(HTTP)(/)([12]\.[01])( +)(\d{3})( +)([^\r\n]+)(\r?\n|\Z)`, ByGroups(KeywordReserved, Operator, LiteralNumber, Text, LiteralNumber, Text, NameException, Text), Push("headers")}, @@ -30,17 +34,17 @@ var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLexer( "content": { {`.+`, EmitterFunc(httpContentBlock), nil}, }, - }, -))) + } +} -func httpContentBlock(groups []string, lexer Lexer) Iterator { +func httpContentBlock(groups []string, state *LexerState) Iterator { tokens := []Token{ {Generic, groups[0]}, } return Literator(tokens...) } -func httpHeaderBlock(groups []string, lexer Lexer) Iterator { +func httpHeaderBlock(groups []string, state *LexerState) Iterator { tokens := []Token{ {Name, groups[1]}, {Text, groups[2]}, @@ -52,7 +56,7 @@ func httpHeaderBlock(groups []string, lexer Lexer) Iterator { return Literator(tokens...) } -func httpContinuousHeaderBlock(groups []string, lexer Lexer) Iterator { +func httpContinuousHeaderBlock(groups []string, state *LexerState) Iterator { tokens := []Token{ {Text, groups[1]}, {Literal, groups[2]}, diff --git a/vendor/github.com/alecthomas/chroma/lexers/h/hy.go b/vendor/github.com/alecthomas/chroma/lexers/h/hy.go index 17385e8..7a07897 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/h/hy.go +++ b/vendor/github.com/alecthomas/chroma/lexers/h/hy.go @@ -6,14 +6,18 @@ import ( ) // Hy lexer. -var Hy = internal.Register(MustNewLexer( +var Hy = internal.Register(MustNewLazyLexer( &Config{ Name: "Hy", Aliases: []string{"hylang"}, Filenames: []string{"*.hy"}, MimeTypes: []string{"text/x-hy", "application/x-hy"}, }, - Rules{ + hyRules, +)) + +func hyRules() Rules { + return Rules{ "root": { {`;.*$`, CommentSingle, nil}, {`[,\s]+`, Text, nil}, @@ -47,5 +51,5 @@ var Hy = internal.Register(MustNewLexer( {`(??@^|_~:\\]).*?)$`, ByGroups(Text, CommentSingle), nil}, @@ -76,5 +80,5 @@ var Idris = internal.Register(MustNewLexer( {`\d+`, LiteralStringEscape, Pop(1)}, {`\s+\\`, LiteralStringEscape, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/i/igor.go b/vendor/github.com/alecthomas/chroma/lexers/i/igor.go index d704a4f..bbb1d72 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/i/igor.go +++ b/vendor/github.com/alecthomas/chroma/lexers/i/igor.go @@ -6,7 +6,7 @@ import ( ) // Igor lexer. -var Igor = internal.Register(MustNewLexer( +var Igor = internal.Register(MustNewLazyLexer( &Config{ Name: "Igor", Aliases: []string{"igor", "igorpro"}, @@ -14,7 +14,11 @@ var Igor = internal.Register(MustNewLexer( MimeTypes: []string{"text/ipf"}, CaseInsensitive: true, }, - Rules{ + igorRules, +)) + +func igorRules() Rules { + return Rules{ "root": { {`//.*$`, CommentSingle, nil}, {`"([^"\\]|\\.)*"`, LiteralString, nil}, @@ -28,5 +32,5 @@ var Igor = internal.Register(MustNewLexer( {`.`, Text, nil}, {`\n|\r`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/i/ini.go b/vendor/github.com/alecthomas/chroma/lexers/i/ini.go index e57f865..46b2ce2 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/i/ini.go +++ b/vendor/github.com/alecthomas/chroma/lexers/i/ini.go @@ -6,14 +6,18 @@ import ( ) // Ini lexer. -var Ini = internal.Register(MustNewLexer( +var Ini = internal.Register(MustNewLazyLexer( &Config{ Name: "INI", Aliases: []string{"ini", "cfg", "dosini"}, Filenames: []string{"*.ini", "*.cfg", "*.inf", ".gitconfig", ".editorconfig"}, MimeTypes: []string{"text/x-ini", "text/inf"}, }, - Rules{ + iniRules, +)) + +func iniRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`[;#].*`, CommentSingle, nil}, @@ -21,5 +25,5 @@ var Ini = internal.Register(MustNewLexer( {`(.*?)([ \t]*)(=)([ \t]*)(.*(?:\n[ \t].+)*)`, ByGroups(NameAttribute, Text, Operator, Text, LiteralString), nil}, {`(.+?)$`, NameAttribute, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/i/io.go b/vendor/github.com/alecthomas/chroma/lexers/i/io.go index 840feea..8b2e53a 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/i/io.go +++ b/vendor/github.com/alecthomas/chroma/lexers/i/io.go @@ -6,14 +6,18 @@ import ( ) // Io lexer. -var Io = internal.Register(MustNewLexer( +var Io = internal.Register(MustNewLazyLexer( &Config{ Name: "Io", Aliases: []string{"io"}, Filenames: []string{"*.io"}, MimeTypes: []string{"text/x-iosrc"}, }, - Rules{ + ioRules, +)) + +func ioRules() Rules { + return Rules{ "root": { {`\n`, Text, nil}, {`\s+`, Text, nil}, @@ -36,5 +40,5 @@ var Io = internal.Register(MustNewLexer( {`\+/`, CommentMultiline, Pop(1)}, {`[+/]`, CommentMultiline, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/internal/api.go b/vendor/github.com/alecthomas/chroma/lexers/internal/api.go index 08ec6ff..5c7970a 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/internal/api.go +++ b/vendor/github.com/alecthomas/chroma/lexers/internal/api.go @@ -11,6 +11,19 @@ import ( "github.com/alecthomas/chroma" ) +var ( + ignoredSuffixes = [...]string{ + // Editor backups + "~", ".bak", ".old", ".orig", + // Debian and derivatives apt/dpkg backups + ".dpkg-dist", ".dpkg-old", + // Red Hat and derivatives rpm backups + ".rpmnew", ".rpmorig", ".rpmsave", + // Build system input/template files + ".in", + } +) + // Registry of Lexers. var Registry = struct { Lexers chroma.Lexers @@ -93,6 +106,13 @@ func Match(filename string) chroma.Lexer { for _, glob := range config.Filenames { if fnmatch.Match(glob, filename, 0) { matched = append(matched, lexer) + } else { + for _, suf := range &ignoredSuffixes { + if fnmatch.Match(glob+suf, filename, 0) { + matched = append(matched, lexer) + break + } + } } } } @@ -107,6 +127,13 @@ func Match(filename string) chroma.Lexer { for _, glob := range config.AliasFilenames { if fnmatch.Match(glob, filename, 0) { matched = append(matched, lexer) + } else { + for _, suf := range &ignoredSuffixes { + if fnmatch.Match(glob+suf, filename, 0) { + matched = append(matched, lexer) + break + } + } } } } @@ -146,16 +173,19 @@ func Register(lexer chroma.Lexer) chroma.Lexer { return lexer } -// Used for the fallback lexer as well as the explicit plaintext lexer -var PlaintextRules = chroma.Rules{ - "root": []chroma.Rule{ - {`.+`, chroma.Text, nil}, - {`\n`, chroma.Text, nil}, - }, +// PlaintextRules is used for the fallback lexer as well as the explicit +// plaintext lexer. +func PlaintextRules() chroma.Rules { + return chroma.Rules{ + "root": []chroma.Rule{ + {`.+`, chroma.Text, nil}, + {`\n`, chroma.Text, nil}, + }, + } } // Fallback lexer if no other is found. -var Fallback chroma.Lexer = chroma.MustNewLexer(&chroma.Config{ +var Fallback chroma.Lexer = chroma.MustNewLazyLexer(&chroma.Config{ Name: "fallback", Filenames: []string{"*"}, }, PlaintextRules) diff --git a/vendor/github.com/alecthomas/chroma/lexers/j/j.go b/vendor/github.com/alecthomas/chroma/lexers/j/j.go index 686e53b..9a2a4e3 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/j/j.go +++ b/vendor/github.com/alecthomas/chroma/lexers/j/j.go @@ -6,14 +6,18 @@ import ( ) // J lexer. -var J = internal.Register(MustNewLexer( +var J = internal.Register(MustNewLazyLexer( &Config{ Name: "J", Aliases: []string{"j"}, Filenames: []string{"*.ijs"}, MimeTypes: []string{"text/x-j"}, }, - Rules{ + jRules, +)) + +func jRules() Rules { + return Rules{ "root": { {`#!.*$`, CommentPreproc, nil}, {`NB\..*`, CommentSingle, nil}, @@ -69,5 +73,5 @@ var J = internal.Register(MustNewLexer( {`''`, LiteralString, nil}, {`'`, LiteralString, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/j/java.go b/vendor/github.com/alecthomas/chroma/lexers/j/java.go index c6b9a76..48a9d9f 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/j/java.go +++ b/vendor/github.com/alecthomas/chroma/lexers/j/java.go @@ -6,15 +6,20 @@ import ( ) // Java lexer. -var Java = internal.Register(MustNewLexer( +var Java = internal.Register(MustNewLazyLexer( &Config{ Name: "Java", Aliases: []string{"java"}, Filenames: []string{"*.java"}, MimeTypes: []string{"text/x-java"}, DotAll: true, + EnsureNL: true, }, - Rules{ + javaRules, +)) + +func javaRules() Rules { + return Rules{ "root": { {`[^\S\n]+`, Text, nil}, {`//.*?\n`, CommentSingle, nil}, @@ -47,5 +52,5 @@ var Java = internal.Register(MustNewLexer( "import": { {`[\w.]+\*?`, NameNamespace, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/j/javascript.go b/vendor/github.com/alecthomas/chroma/lexers/j/javascript.go index a50cb24..6bb3145 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/j/javascript.go +++ b/vendor/github.com/alecthomas/chroma/lexers/j/javascript.go @@ -26,11 +26,11 @@ var JavascriptRules = Rules{ {`\A#! ?/.*?\n`, CommentHashbang, nil}, {`^(?=\s|/|`, `||`, `&&`, `>`, `<`, `>=`, `≥`, `<=`, `≤`, `==`, `===`, `≡`, `!=`, `≠`, `!==`, `≢`, `.>`, `.<`, `.>=`, `.≥`, `.<=`, `.≤`, `.==`, `.!=`, `.≠`, `.=`, `.!`, `<:`, `>:`, `∈`, `∉`, `∋`, `∌`, `⊆`, `⊈`, `⊂`, `⊄`, `⊊`, `|>`, `<|`, `:`, `+`, `-`, `.+`, `.-`, `|`, `∪`, `$`, `<<`, `>>`, `>>>`, `.<<`, `.>>`, `.>>>`, `*`, `/`, `./`, `÷`, `.÷`, `%`, `⋅`, `.%`, `.*`, `\`, `.\`, `&`, `∩`, `//`, `.//`, `^`, `.^`, `::`, `.`, `+`, `-`, `!`, `√`, `∛`, `∜`), Operator, nil}, + {`[\[\](),;]`, Punctuation, nil}, + {`((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))(\s*)(:)((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))`, ByGroups(Name, Text, Operator, Name), nil}, + {`(?\d.])(:(?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))`, LiteralStringSymbol, nil}, + {`(?<=::)(\s*)((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))\b(?![(\[])`, ByGroups(Text, KeywordType), nil}, + {`((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))(\s*)([<>]:)(\s*)((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))\b(?![(\[])`, ByGroups(KeywordType, Text, Operator, Text, KeywordType), nil}, + {`([<>]:)(\s*)((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))\b(?![(\[])`, ByGroups(Operator, Text, KeywordType), nil}, + {`\b((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))(\s*)([<>]:)`, ByGroups(KeywordType, Text, Operator), nil}, + {Words(``, `[²³¹ʰʲʳʷʸˡˢˣᴬᴮᴰᴱᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾᴿᵀᵁᵂᵃᵇᵈᵉᵍᵏᵐᵒᵖᵗᵘᵛᵝᵞᵟᵠᵡᵢᵣᵤᵥᵦᵧᵨᵩᵪᶜᶠᶥᶦᶫᶰᶸᶻᶿ′″‴‵‶‷⁗⁰ⁱ⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾ⁿ₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎ₐₑₒₓₕₖₗₘₙₚₛₜⱼⱽ]*`, `->`, `:=`, `$=`, `?`, `||`, `&&`, `:`, `$`, `::`, `=`, `+=`, `-=`, `*=`, `/=`, `//=`, `\=`, `^=`, `÷=`, `%=`, `<<=`, `>>=`, `>>>=`, `|=`, `&=`, `⊻=`, `≔`, `⩴`, `≕'`, `~`, `=>`, `→`, `↔`, `↚`, `↛`, `↞`, `↠`, `↢`, `↣`, `↦`, `↤`, `↮`, `⇎`, `⇍`, `⇏`, `⇐`, `⇒`, `⇔`, `⇴`, `⇶`, `⇷`, `⇸`, `⇹`, `⇺`, `⇻`, `⇼`, `⇽`, `⇾`, `⇿`, `⟵`, `⟶`, `⟷`, `⟹`, `⟺`, `⟻`, `⟼`, `⟽`, `⟾`, `⟿`, `⤀`, `⤁`, `⤂`, `⤃`, `⤄`, `⤅`, `⤆`, `⤇`, `⤌`, `⤍`, `⤎`, `⤏`, `⤐`, `⤑`, `⤔`, `⤕`, `⤖`, `⤗`, `⤘`, `⤝`, `⤞`, `⤟`, `⤠`, `⥄`, `⥅`, `⥆`, `⥇`, `⥈`, `⥊`, `⥋`, `⥎`, `⥐`, `⥒`, `⥓`, `⥖`, `⥗`, `⥚`, `⥛`, `⥞`, `⥟`, `⥢`, `⥤`, `⥦`, `⥧`, `⥨`, `⥩`, `⥪`, `⥫`, `⥬`, `⥭`, `⥰`, `⧴`, `⬱`, `⬰`, `⬲`, `⬳`, `⬴`, `⬵`, `⬶`, `⬷`, `⬸`, `⬹`, `⬺`, `⬻`, `⬼`, `⬽`, `⬾`, `⬿`, `⭀`, `⭁`, `⭂`, `⭃`, `⭄`, `⭇`, `⭈`, `⭉`, `⭊`, `⭋`, `⭌`, `←`, `→`, `⇜`, `⇝`, `↜`, `↝`, `↩`, `↪`, `↫`, `↬`, `↼`, `↽`, `⇀`, `⇁`, `⇄`, `⇆`, `⇇`, `⇉`, `⇋`, `⇌`, `⇚`, `⇛`, `⇠`, `⇢`, `↷`, `↶`, `↺`, `↻`, `-->`, `<--`, `<-->`, `>`, `<`, `>=`, `≥`, `<=`, `≤`, `==`, `===`, `≡`, `!=`, `≠`, `!==`, `≢`, `∈`, `∉`, `∋`, `∌`, `⊆`, `⊈`, `⊂`, `⊄`, `⊊`, `∝`, `∊`, `∍`, `∥`, `∦`, `∷`, `∺`, `∻`, `∽`, `∾`, `≁`, `≃`, `≂`, `≄`, `≅`, `≆`, `≇`, `≈`, `≉`, `≊`, `≋`, `≌`, `≍`, `≎`, `≐`, `≑`, `≒`, `≓`, `≖`, `≗`, `≘`, `≙`, `≚`, `≛`, `≜`, `≝`, `≞`, `≟`, `≣`, `≦`, `≧`, `≨`, `≩`, `≪`, `≫`, `≬`, `≭`, `≮`, `≯`, `≰`, `≱`, `≲`, `≳`, `≴`, `≵`, `≶`, `≷`, `≸`, `≹`, `≺`, `≻`, `≼`, `≽`, `≾`, `≿`, `⊀`, `⊁`, `⊃`, `⊅`, `⊇`, `⊉`, `⊋`, `⊏`, `⊐`, `⊑`, `⊒`, `⊜`, `⊩`, `⊬`, `⊮`, `⊰`, `⊱`, `⊲`, `⊳`, `⊴`, `⊵`, `⊶`, `⊷`, `⋍`, `⋐`, `⋑`, `⋕`, `⋖`, `⋗`, `⋘`, `⋙`, `⋚`, `⋛`, `⋜`, `⋝`, `⋞`, `⋟`, `⋠`, `⋡`, `⋢`, `⋣`, `⋤`, `⋥`, `⋦`, `⋧`, `⋨`, `⋩`, `⋪`, `⋫`, `⋬`, `⋭`, `⋲`, `⋳`, `⋴`, `⋵`, `⋶`, `⋷`, `⋸`, `⋹`, `⋺`, `⋻`, `⋼`, `⋽`, `⋾`, `⋿`, `⟈`, `⟉`, `⟒`, `⦷`, `⧀`, `⧁`, `⧡`, `⧣`, `⧤`, `⧥`, `⩦`, `⩧`, `⩪`, `⩫`, `⩬`, `⩭`, `⩮`, `⩯`, `⩰`, `⩱`, `⩲`, `⩳`, `⩵`, `⩶`, `⩷`, `⩸`, `⩹`, `⩺`, `⩻`, `⩼`, `⩽`, `⩾`, `⩿`, `⪀`, `⪁`, `⪂`, `⪃`, `⪄`, `⪅`, `⪆`, `⪇`, `⪈`, `⪉`, `⪊`, `⪋`, `⪌`, `⪍`, `⪎`, `⪏`, `⪐`, `⪑`, `⪒`, `⪓`, `⪔`, `⪕`, `⪖`, `⪗`, `⪘`, `⪙`, `⪚`, `⪛`, `⪜`, `⪝`, `⪞`, `⪟`, `⪠`, `⪡`, `⪢`, `⪣`, `⪤`, `⪥`, `⪦`, `⪧`, `⪨`, `⪩`, `⪪`, `⪫`, `⪬`, `⪭`, `⪮`, `⪯`, `⪰`, `⪱`, `⪲`, `⪳`, `⪴`, `⪵`, `⪶`, `⪷`, `⪸`, `⪹`, `⪺`, `⪻`, `⪼`, `⪽`, `⪾`, `⪿`, `⫀`, `⫁`, `⫂`, `⫃`, `⫄`, `⫅`, `⫆`, `⫇`, `⫈`, `⫉`, `⫊`, `⫋`, `⫌`, `⫍`, `⫎`, `⫏`, `⫐`, `⫑`, `⫒`, `⫓`, `⫔`, `⫕`, `⫖`, `⫗`, `⫘`, `⫙`, `⫷`, `⫸`, `⫹`, `⫺`, `⊢`, `⊣`, `⟂`, `<:`, `>:`, `<|`, `|>`, `…`, `⁝`, `⋮`, `⋱`, `⋰`, `⋯`, `+`, `-`, `¦`, `|`, `⊕`, `⊖`, `⊞`, `⊟`, `++`, `∪`, `∨`, `⊔`, `±`, `∓`, `∔`, `∸`, `≏`, `⊎`, `⊻`, `⊽`, `⋎`, `⋓`, `⧺`, `⧻`, `⨈`, `⨢`, `⨣`, `⨤`, `⨥`, `⨦`, `⨧`, `⨨`, `⨩`, `⨪`, `⨫`, `⨬`, `⨭`, `⨮`, `⨹`, `⨺`, `⩁`, `⩂`, `⩅`, `⩊`, `⩌`, `⩏`, `⩐`, `⩒`, `⩔`, `⩖`, `⩗`, `⩛`, `⩝`, `⩡`, `⩢`, `⩣`, `*`, `/`, `⌿`, `÷`, `%`, `&`, `⋅`, `∘`, `×`, `\`, `∩`, `∧`, `⊗`, `⊘`, `⊙`, `⊚`, `⊛`, `⊠`, `⊡`, `⊓`, `∗`, `∙`, `∤`, `⅋`, `≀`, `⊼`, `⋄`, `⋆`, `⋇`, `⋉`, `⋊`, `⋋`, `⋌`, `⋏`, `⋒`, `⟑`, `⦸`, `⦼`, `⦾`, `⦿`, `⧶`, `⧷`, `⨇`, `⨰`, `⨱`, `⨲`, `⨳`, `⨴`, `⨵`, `⨶`, `⨷`, `⨸`, `⨻`, `⨼`, `⨽`, `⩀`, `⩃`, `⩄`, `⩋`, `⩍`, `⩎`, `⩑`, `⩓`, `⩕`, `⩘`, `⩚`, `⩜`, `⩞`, `⩟`, `⩠`, `⫛`, `⊍`, `▷`, `⨝`, `⟕`, `⟖`, `⟗`, `⨟`, `//`, `>>`, `<<`, `>>>`, `^`, `↑`, `↓`, `⇵`, `⟰`, `⟱`, `⤈`, `⤉`, `⤊`, `⤋`, `⤒`, `⤓`, `⥉`, `⥌`, `⥍`, `⥏`, `⥑`, `⥔`, `⥕`, `⥘`, `⥙`, `⥜`, `⥝`, `⥠`, `⥡`, `⥣`, `⥥`, `⥮`, `⥯`, `↑`, `↓`, `!`, `¬`, `√`, `∛`, `∜`), Operator, nil}, + {Words(``, `[²³¹ʰʲʳʷʸˡˢˣᴬᴮᴰᴱᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾᴿᵀᵁᵂᵃᵇᵈᵉᵍᵏᵐᵒᵖᵗᵘᵛᵝᵞᵟᵠᵡᵢᵣᵤᵥᵦᵧᵨᵩᵪᶜᶠᶥᶦᶫᶰᶸᶻᶿ′″‴‵‶‷⁗⁰ⁱ⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾ⁿ₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎ₐₑₒₓₕₖₗₘₙₚₛₜⱼⱽ]*`, `.=`, `.+=`, `.-=`, `.*=`, `./=`, `.//=`, `.\=`, `.^=`, `.÷=`, `.%=`, `.<<=`, `.>>=`, `.>>>=`, `.|=`, `.&=`, `.⊻=`, `.≔`, `.⩴`, `.≕'`, `.~`, `.=>`, `.→`, `.↔`, `.↚`, `.↛`, `.↞`, `.↠`, `.↢`, `.↣`, `.↦`, `.↤`, `.↮`, `.⇎`, `.⇍`, `.⇏`, `.⇐`, `.⇒`, `.⇔`, `.⇴`, `.⇶`, `.⇷`, `.⇸`, `.⇹`, `.⇺`, `.⇻`, `.⇼`, `.⇽`, `.⇾`, `.⇿`, `.⟵`, `.⟶`, `.⟷`, `.⟹`, `.⟺`, `.⟻`, `.⟼`, `.⟽`, `.⟾`, `.⟿`, `.⤀`, `.⤁`, `.⤂`, `.⤃`, `.⤄`, `.⤅`, `.⤆`, `.⤇`, `.⤌`, `.⤍`, `.⤎`, `.⤏`, `.⤐`, `.⤑`, `.⤔`, `.⤕`, `.⤖`, `.⤗`, `.⤘`, `.⤝`, `.⤞`, `.⤟`, `.⤠`, `.⥄`, `.⥅`, `.⥆`, `.⥇`, `.⥈`, `.⥊`, `.⥋`, `.⥎`, `.⥐`, `.⥒`, `.⥓`, `.⥖`, `.⥗`, `.⥚`, `.⥛`, `.⥞`, `.⥟`, `.⥢`, `.⥤`, `.⥦`, `.⥧`, `.⥨`, `.⥩`, `.⥪`, `.⥫`, `.⥬`, `.⥭`, `.⥰`, `.⧴`, `.⬱`, `.⬰`, `.⬲`, `.⬳`, `.⬴`, `.⬵`, `.⬶`, `.⬷`, `.⬸`, `.⬹`, `.⬺`, `.⬻`, `.⬼`, `.⬽`, `.⬾`, `.⬿`, `.⭀`, `.⭁`, `.⭂`, `.⭃`, `.⭄`, `.⭇`, `.⭈`, `.⭉`, `.⭊`, `.⭋`, `.⭌`, `.←`, `.→`, `.⇜`, `.⇝`, `.↜`, `.↝`, `.↩`, `.↪`, `.↫`, `.↬`, `.↼`, `.↽`, `.⇀`, `.⇁`, `.⇄`, `.⇆`, `.⇇`, `.⇉`, `.⇋`, `.⇌`, `.⇚`, `.⇛`, `.⇠`, `.⇢`, `.↷`, `.↶`, `.↺`, `.↻`, `.-->`, `.<--`, `.<-->`, `.>`, `.<`, `.>=`, `.≥`, `.<=`, `.≤`, `.==`, `.===`, `.≡`, `.!=`, `.≠`, `.!==`, `.≢`, `.∈`, `.∉`, `.∋`, `.∌`, `.⊆`, `.⊈`, `.⊂`, `.⊄`, `.⊊`, `.∝`, `.∊`, `.∍`, `.∥`, `.∦`, `.∷`, `.∺`, `.∻`, `.∽`, `.∾`, `.≁`, `.≃`, `.≂`, `.≄`, `.≅`, `.≆`, `.≇`, `.≈`, `.≉`, `.≊`, `.≋`, `.≌`, `.≍`, `.≎`, `.≐`, `.≑`, `.≒`, `.≓`, `.≖`, `.≗`, `.≘`, `.≙`, `.≚`, `.≛`, `.≜`, `.≝`, `.≞`, `.≟`, `.≣`, `.≦`, `.≧`, `.≨`, `.≩`, `.≪`, `.≫`, `.≬`, `.≭`, `.≮`, `.≯`, `.≰`, `.≱`, `.≲`, `.≳`, `.≴`, `.≵`, `.≶`, `.≷`, `.≸`, `.≹`, `.≺`, `.≻`, `.≼`, `.≽`, `.≾`, `.≿`, `.⊀`, `.⊁`, `.⊃`, `.⊅`, `.⊇`, `.⊉`, `.⊋`, `.⊏`, `.⊐`, `.⊑`, `.⊒`, `.⊜`, `.⊩`, `.⊬`, `.⊮`, `.⊰`, `.⊱`, `.⊲`, `.⊳`, `.⊴`, `.⊵`, `.⊶`, `.⊷`, `.⋍`, `.⋐`, `.⋑`, `.⋕`, `.⋖`, `.⋗`, `.⋘`, `.⋙`, `.⋚`, `.⋛`, `.⋜`, `.⋝`, `.⋞`, `.⋟`, `.⋠`, `.⋡`, `.⋢`, `.⋣`, `.⋤`, `.⋥`, `.⋦`, `.⋧`, `.⋨`, `.⋩`, `.⋪`, `.⋫`, `.⋬`, `.⋭`, `.⋲`, `.⋳`, `.⋴`, `.⋵`, `.⋶`, `.⋷`, `.⋸`, `.⋹`, `.⋺`, `.⋻`, `.⋼`, `.⋽`, `.⋾`, `.⋿`, `.⟈`, `.⟉`, `.⟒`, `.⦷`, `.⧀`, `.⧁`, `.⧡`, `.⧣`, `.⧤`, `.⧥`, `.⩦`, `.⩧`, `.⩪`, `.⩫`, `.⩬`, `.⩭`, `.⩮`, `.⩯`, `.⩰`, `.⩱`, `.⩲`, `.⩳`, `.⩵`, `.⩶`, `.⩷`, `.⩸`, `.⩹`, `.⩺`, `.⩻`, `.⩼`, `.⩽`, `.⩾`, `.⩿`, `.⪀`, `.⪁`, `.⪂`, `.⪃`, `.⪄`, `.⪅`, `.⪆`, `.⪇`, `.⪈`, `.⪉`, `.⪊`, `.⪋`, `.⪌`, `.⪍`, `.⪎`, `.⪏`, `.⪐`, `.⪑`, `.⪒`, `.⪓`, `.⪔`, `.⪕`, `.⪖`, `.⪗`, `.⪘`, `.⪙`, `.⪚`, `.⪛`, `.⪜`, `.⪝`, `.⪞`, `.⪟`, `.⪠`, `.⪡`, `.⪢`, `.⪣`, `.⪤`, `.⪥`, `.⪦`, `.⪧`, `.⪨`, `.⪩`, `.⪪`, `.⪫`, `.⪬`, `.⪭`, `.⪮`, `.⪯`, `.⪰`, `.⪱`, `.⪲`, `.⪳`, `.⪴`, `.⪵`, `.⪶`, `.⪷`, `.⪸`, `.⪹`, `.⪺`, `.⪻`, `.⪼`, `.⪽`, `.⪾`, `.⪿`, `.⫀`, `.⫁`, `.⫂`, `.⫃`, `.⫄`, `.⫅`, `.⫆`, `.⫇`, `.⫈`, `.⫉`, `.⫊`, `.⫋`, `.⫌`, `.⫍`, `.⫎`, `.⫏`, `.⫐`, `.⫑`, `.⫒`, `.⫓`, `.⫔`, `.⫕`, `.⫖`, `.⫗`, `.⫘`, `.⫙`, `.⫷`, `.⫸`, `.⫹`, `.⫺`, `.⊢`, `.⊣`, `.⟂`, `.<:`, `.>:`, `.<|`, `.|>`, `.…`, `.⁝`, `.⋮`, `.⋱`, `.⋰`, `.⋯`, `.+`, `.-`, `.¦`, `.|`, `.⊕`, `.⊖`, `.⊞`, `.⊟`, `.++`, `.∪`, `.∨`, `.⊔`, `.±`, `.∓`, `.∔`, `.∸`, `.≏`, `.⊎`, `.⊻`, `.⊽`, `.⋎`, `.⋓`, `.⧺`, `.⧻`, `.⨈`, `.⨢`, `.⨣`, `.⨤`, `.⨥`, `.⨦`, `.⨧`, `.⨨`, `.⨩`, `.⨪`, `.⨫`, `.⨬`, `.⨭`, `.⨮`, `.⨹`, `.⨺`, `.⩁`, `.⩂`, `.⩅`, `.⩊`, `.⩌`, `.⩏`, `.⩐`, `.⩒`, `.⩔`, `.⩖`, `.⩗`, `.⩛`, `.⩝`, `.⩡`, `.⩢`, `.⩣`, `.*`, `./`, `.⌿`, `.÷`, `.%`, `.&`, `.⋅`, `.∘`, `.×`, `.\`, `.∩`, `.∧`, `.⊗`, `.⊘`, `.⊙`, `.⊚`, `.⊛`, `.⊠`, `.⊡`, `.⊓`, `.∗`, `.∙`, `.∤`, `.⅋`, `.≀`, `.⊼`, `.⋄`, `.⋆`, `.⋇`, `.⋉`, `.⋊`, `.⋋`, `.⋌`, `.⋏`, `.⋒`, `.⟑`, `.⦸`, `.⦼`, `.⦾`, `.⦿`, `.⧶`, `.⧷`, `.⨇`, `.⨰`, `.⨱`, `.⨲`, `.⨳`, `.⨴`, `.⨵`, `.⨶`, `.⨷`, `.⨸`, `.⨻`, `.⨼`, `.⨽`, `.⩀`, `.⩃`, `.⩄`, `.⩋`, `.⩍`, `.⩎`, `.⩑`, `.⩓`, `.⩕`, `.⩘`, `.⩚`, `.⩜`, `.⩞`, `.⩟`, `.⩠`, `.⫛`, `.⊍`, `.▷`, `.⨝`, `.⟕`, `.⟖`, `.⟗`, `.⨟`, `.//`, `.>>`, `.<<`, `.>>>`, `.^`, `.↑`, `.↓`, `.⇵`, `.⟰`, `.⟱`, `.⤈`, `.⤉`, `.⤊`, `.⤋`, `.⤒`, `.⤓`, `.⥉`, `.⥌`, `.⥍`, `.⥏`, `.⥑`, `.⥔`, `.⥕`, `.⥘`, `.⥙`, `.⥜`, `.⥝`, `.⥠`, `.⥡`, `.⥣`, `.⥥`, `.⥮`, `.⥯`, `.↑`, `.↓`, `.!`, `.¬`, `.√`, `.∛`, `.∜`), Operator, nil}, + {Words(``, ``, `...`, `..`), Operator, nil}, {`'(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,3}|\\u[a-fA-F0-9]{1,4}|\\U[a-fA-F0-9]{1,6}|[^\\\'\n])'`, LiteralStringChar, nil}, - {`(?<=[.\w)\]])\'+`, Operator, nil}, - {`"""`, LiteralString, Push("tqstring")}, - {`"`, LiteralString, Push("string")}, - {`r"""`, LiteralStringRegex, Push("tqregex")}, - {`r"`, LiteralStringRegex, Push("regex")}, - {"`", LiteralStringBacktick, Push("command")}, - {`((?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*)(')?`, ByGroups(Name, Operator), nil}, - {`(@(?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*)(')?`, ByGroups(NameDecorator, Operator), nil}, - {`(\d+(_\d+)+\.\d*|\d*\.\d+(_\d+)+)([eEf][+-]?[0-9]+)?`, LiteralNumberFloat, nil}, - {`(\d+\.\d*|\d*\.\d+)([eEf][+-]?[0-9]+)?`, LiteralNumberFloat, nil}, - {`\d+(_\d+)+[eEf][+-]?[0-9]+`, LiteralNumberFloat, nil}, - {`\d+[eEf][+-]?[0-9]+`, LiteralNumberFloat, nil}, - {`0b[01]+(_[01]+)+`, LiteralNumberBin, nil}, - {`0b[01]+`, LiteralNumberBin, nil}, - {`0o[0-7]+(_[0-7]+)+`, LiteralNumberOct, nil}, - {`0o[0-7]+`, LiteralNumberOct, nil}, - {`0x[a-fA-F0-9]+(_[a-fA-F0-9]+)+`, LiteralNumberHex, nil}, - {`0x[a-fA-F0-9]+`, LiteralNumberHex, nil}, - {`\d+(_\d+)+`, LiteralNumberInteger, nil}, - {`\d+`, LiteralNumberInteger, nil}, + {`(?<=[.\w)\]])(\'[²³¹ʰʲʳʷʸˡˢˣᴬᴮᴰᴱᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾᴿᵀᵁᵂᵃᵇᵈᵉᵍᵏᵐᵒᵖᵗᵘᵛᵝᵞᵟᵠᵡᵢᵣᵤᵥᵦᵧᵨᵩᵪᶜᶠᶥᶦᶫᶰᶸᶻᶿ′″‴‵‶‷⁗⁰ⁱ⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾ⁿ₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎ₐₑₒₓₕₖₗₘₙₚₛₜⱼⱽ]*)+`, Operator, nil}, + {`(raw)(""")`, ByGroups(LiteralStringAffix, LiteralString), Push("tqrawstring")}, + {`(raw)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("rawstring")}, + {`(r)(""")`, ByGroups(LiteralStringAffix, LiteralStringRegex), Push("tqregex")}, + {`(r)(")`, ByGroups(LiteralStringAffix, LiteralStringRegex), Push("regex")}, + {`((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))?(""")`, ByGroups(LiteralStringAffix, LiteralString), Push("tqstring")}, + {`((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))?(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")}, + {"((?:[a-zA-Z_\u00a1-\U0010ffff][a-zA-Z_0-9!\u00a1-\U0010ffff]*))?(```)", ByGroups(LiteralStringAffix, LiteralStringBacktick), Push("tqcommand")}, + {"((?:[a-zA-Z_\u00a1-\U0010ffff][a-zA-Z_0-9!\u00a1-\U0010ffff]*))?(`)", ByGroups(LiteralStringAffix, LiteralStringBacktick), Push("command")}, + {`((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))(\{)`, ByGroups(KeywordType, Punctuation), Push("curly")}, + {`(where)(\s+)((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))`, ByGroups(Keyword, Text, KeywordType), nil}, + {`(\{)`, Punctuation, Push("curly")}, + {`(abstract[ \t]+type|primitive[ \t]+type|mutable[ \t]+struct|struct)([\s()]+)((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*))`, ByGroups(Keyword, Text, KeywordType), nil}, + {`@(?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*)`, NameDecorator, nil}, + {Words(`@`, `[²³¹ʰʲʳʷʸˡˢˣᴬᴮᴰᴱᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾᴿᵀᵁᵂᵃᵇᵈᵉᵍᵏᵐᵒᵖᵗᵘᵛᵝᵞᵟᵠᵡᵢᵣᵤᵥᵦᵧᵨᵩᵪᶜᶠᶥᶦᶫᶰᶸᶻᶿ′″‴‵‶‷⁗⁰ⁱ⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾ⁿ₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎ₐₑₒₓₕₖₗₘₙₚₛₜⱼⱽ]*`, `->`, `:=`, `$=`, `?`, `||`, `&&`, `:`, `$`, `::`, `..`, `.`, `=`, `+=`, `-=`, `*=`, `/=`, `//=`, `\=`, `^=`, `÷=`, `%=`, `<<=`, `>>=`, `>>>=`, `|=`, `&=`, `⊻=`, `≔`, `⩴`, `≕'`, `~`, `=>`, `→`, `↔`, `↚`, `↛`, `↞`, `↠`, `↢`, `↣`, `↦`, `↤`, `↮`, `⇎`, `⇍`, `⇏`, `⇐`, `⇒`, `⇔`, `⇴`, `⇶`, `⇷`, `⇸`, `⇹`, `⇺`, `⇻`, `⇼`, `⇽`, `⇾`, `⇿`, `⟵`, `⟶`, `⟷`, `⟹`, `⟺`, `⟻`, `⟼`, `⟽`, `⟾`, `⟿`, `⤀`, `⤁`, `⤂`, `⤃`, `⤄`, `⤅`, `⤆`, `⤇`, `⤌`, `⤍`, `⤎`, `⤏`, `⤐`, `⤑`, `⤔`, `⤕`, `⤖`, `⤗`, `⤘`, `⤝`, `⤞`, `⤟`, `⤠`, `⥄`, `⥅`, `⥆`, `⥇`, `⥈`, `⥊`, `⥋`, `⥎`, `⥐`, `⥒`, `⥓`, `⥖`, `⥗`, `⥚`, `⥛`, `⥞`, `⥟`, `⥢`, `⥤`, `⥦`, `⥧`, `⥨`, `⥩`, `⥪`, `⥫`, `⥬`, `⥭`, `⥰`, `⧴`, `⬱`, `⬰`, `⬲`, `⬳`, `⬴`, `⬵`, `⬶`, `⬷`, `⬸`, `⬹`, `⬺`, `⬻`, `⬼`, `⬽`, `⬾`, `⬿`, `⭀`, `⭁`, `⭂`, `⭃`, `⭄`, `⭇`, `⭈`, `⭉`, `⭊`, `⭋`, `⭌`, `←`, `→`, `⇜`, `⇝`, `↜`, `↝`, `↩`, `↪`, `↫`, `↬`, `↼`, `↽`, `⇀`, `⇁`, `⇄`, `⇆`, `⇇`, `⇉`, `⇋`, `⇌`, `⇚`, `⇛`, `⇠`, `⇢`, `↷`, `↶`, `↺`, `↻`, `-->`, `<--`, `<-->`, `>`, `<`, `>=`, `≥`, `<=`, `≤`, `==`, `===`, `≡`, `!=`, `≠`, `!==`, `≢`, `∈`, `∉`, `∋`, `∌`, `⊆`, `⊈`, `⊂`, `⊄`, `⊊`, `∝`, `∊`, `∍`, `∥`, `∦`, `∷`, `∺`, `∻`, `∽`, `∾`, `≁`, `≃`, `≂`, `≄`, `≅`, `≆`, `≇`, `≈`, `≉`, `≊`, `≋`, `≌`, `≍`, `≎`, `≐`, `≑`, `≒`, `≓`, `≖`, `≗`, `≘`, `≙`, `≚`, `≛`, `≜`, `≝`, `≞`, `≟`, `≣`, `≦`, `≧`, `≨`, `≩`, `≪`, `≫`, `≬`, `≭`, `≮`, `≯`, `≰`, `≱`, `≲`, `≳`, `≴`, `≵`, `≶`, `≷`, `≸`, `≹`, `≺`, `≻`, `≼`, `≽`, `≾`, `≿`, `⊀`, `⊁`, `⊃`, `⊅`, `⊇`, `⊉`, `⊋`, `⊏`, `⊐`, `⊑`, `⊒`, `⊜`, `⊩`, `⊬`, `⊮`, `⊰`, `⊱`, `⊲`, `⊳`, `⊴`, `⊵`, `⊶`, `⊷`, `⋍`, `⋐`, `⋑`, `⋕`, `⋖`, `⋗`, `⋘`, `⋙`, `⋚`, `⋛`, `⋜`, `⋝`, `⋞`, `⋟`, `⋠`, `⋡`, `⋢`, `⋣`, `⋤`, `⋥`, `⋦`, `⋧`, `⋨`, `⋩`, `⋪`, `⋫`, `⋬`, `⋭`, `⋲`, `⋳`, `⋴`, `⋵`, `⋶`, `⋷`, `⋸`, `⋹`, `⋺`, `⋻`, `⋼`, `⋽`, `⋾`, `⋿`, `⟈`, `⟉`, `⟒`, `⦷`, `⧀`, `⧁`, `⧡`, `⧣`, `⧤`, `⧥`, `⩦`, `⩧`, `⩪`, `⩫`, `⩬`, `⩭`, `⩮`, `⩯`, `⩰`, `⩱`, `⩲`, `⩳`, `⩵`, `⩶`, `⩷`, `⩸`, `⩹`, `⩺`, `⩻`, `⩼`, `⩽`, `⩾`, `⩿`, `⪀`, `⪁`, `⪂`, `⪃`, `⪄`, `⪅`, `⪆`, `⪇`, `⪈`, `⪉`, `⪊`, `⪋`, `⪌`, `⪍`, `⪎`, `⪏`, `⪐`, `⪑`, `⪒`, `⪓`, `⪔`, `⪕`, `⪖`, `⪗`, `⪘`, `⪙`, `⪚`, `⪛`, `⪜`, `⪝`, `⪞`, `⪟`, `⪠`, `⪡`, `⪢`, `⪣`, `⪤`, `⪥`, `⪦`, `⪧`, `⪨`, `⪩`, `⪪`, `⪫`, `⪬`, `⪭`, `⪮`, `⪯`, `⪰`, `⪱`, `⪲`, `⪳`, `⪴`, `⪵`, `⪶`, `⪷`, `⪸`, `⪹`, `⪺`, `⪻`, `⪼`, `⪽`, `⪾`, `⪿`, `⫀`, `⫁`, `⫂`, `⫃`, `⫄`, `⫅`, `⫆`, `⫇`, `⫈`, `⫉`, `⫊`, `⫋`, `⫌`, `⫍`, `⫎`, `⫏`, `⫐`, `⫑`, `⫒`, `⫓`, `⫔`, `⫕`, `⫖`, `⫗`, `⫘`, `⫙`, `⫷`, `⫸`, `⫹`, `⫺`, `⊢`, `⊣`, `⟂`, `<:`, `>:`, `<|`, `|>`, `…`, `⁝`, `⋮`, `⋱`, `⋰`, `⋯`, `+`, `-`, `¦`, `|`, `⊕`, `⊖`, `⊞`, `⊟`, `++`, `∪`, `∨`, `⊔`, `±`, `∓`, `∔`, `∸`, `≏`, `⊎`, `⊻`, `⊽`, `⋎`, `⋓`, `⧺`, `⧻`, `⨈`, `⨢`, `⨣`, `⨤`, `⨥`, `⨦`, `⨧`, `⨨`, `⨩`, `⨪`, `⨫`, `⨬`, `⨭`, `⨮`, `⨹`, `⨺`, `⩁`, `⩂`, `⩅`, `⩊`, `⩌`, `⩏`, `⩐`, `⩒`, `⩔`, `⩖`, `⩗`, `⩛`, `⩝`, `⩡`, `⩢`, `⩣`, `*`, `/`, `⌿`, `÷`, `%`, `&`, `⋅`, `∘`, `×`, `\`, `∩`, `∧`, `⊗`, `⊘`, `⊙`, `⊚`, `⊛`, `⊠`, `⊡`, `⊓`, `∗`, `∙`, `∤`, `⅋`, `≀`, `⊼`, `⋄`, `⋆`, `⋇`, `⋉`, `⋊`, `⋋`, `⋌`, `⋏`, `⋒`, `⟑`, `⦸`, `⦼`, `⦾`, `⦿`, `⧶`, `⧷`, `⨇`, `⨰`, `⨱`, `⨲`, `⨳`, `⨴`, `⨵`, `⨶`, `⨷`, `⨸`, `⨻`, `⨼`, `⨽`, `⩀`, `⩃`, `⩄`, `⩋`, `⩍`, `⩎`, `⩑`, `⩓`, `⩕`, `⩘`, `⩚`, `⩜`, `⩞`, `⩟`, `⩠`, `⫛`, `⊍`, `▷`, `⨝`, `⟕`, `⟖`, `⟗`, `⨟`, `//`, `>>`, `<<`, `>>>`, `^`, `↑`, `↓`, `⇵`, `⟰`, `⟱`, `⤈`, `⤉`, `⤊`, `⤋`, `⤒`, `⤓`, `⥉`, `⥌`, `⥍`, `⥏`, `⥑`, `⥔`, `⥕`, `⥘`, `⥙`, `⥜`, `⥝`, `⥠`, `⥡`, `⥣`, `⥥`, `⥮`, `⥯`, `↑`, `↓`, `!`, `¬`, `√`, `∛`, `∜`), NameDecorator, nil}, + {Words(``, `\b`, `baremodule`, `begin`, `break`, `catch`, `ccall`, `const`, `continue`, `do`, `else`, `elseif`, `end`, `export`, `finally`, `for`, `function`, `global`, `if`, `import`, `in`, `isa`, `let`, `local`, `macro`, `module`, `quote`, `return`, `try`, `using`, `where`, `while`), Keyword, nil}, + {Words(``, `\b`, `AbstractArray`, `AbstractChannel`, `AbstractChar`, `AbstractDict`, `AbstractDisplay`, `AbstractFloat`, `AbstractIrrational`, `AbstractMatch`, `AbstractMatrix`, `AbstractPattern`, `AbstractRange`, `AbstractSet`, `AbstractString`, `AbstractUnitRange`, `AbstractVecOrMat`, `AbstractVector`, `Any`, `ArgumentError`, `Array`, `AssertionError`, `BigFloat`, `BigInt`, `BitArray`, `BitMatrix`, `BitSet`, `BitVector`, `Bool`, `BoundsError`, `CapturedException`, `CartesianIndex`, `CartesianIndices`, `Cchar`, `Cdouble`, `Cfloat`, `Channel`, `Char`, `Cint`, `Cintmax_t`, `Clong`, `Clonglong`, `Cmd`, `Colon`, `Complex`, `ComplexF16`, `ComplexF32`, `ComplexF64`, `ComposedFunction`, `CompositeException`, `Condition`, `Cptrdiff_t`, `Cshort`, `Csize_t`, `Cssize_t`, `Cstring`, `Cuchar`, `Cuint`, `Cuintmax_t`, `Culong`, `Culonglong`, `Cushort`, `Cvoid`, `Cwchar_t`, `Cwstring`, `DataType`, `DenseArray`, `DenseMatrix`, `DenseVecOrMat`, `DenseVector`, `Dict`, `DimensionMismatch`, `Dims`, `DivideError`, `DomainError`, `EOFError`, `Enum`, `ErrorException`, `Exception`, `ExponentialBackOff`, `Expr`, `Float16`, `Float32`, `Float64`, `Function`, `GlobalRef`, `HTML`, `IO`, `IOBuffer`, `IOContext`, `IOStream`, `IdDict`, `IndexCartesian`, `IndexLinear`, `IndexStyle`, `InexactError`, `InitError`, `Int`, `Int128`, `Int16`, `Int32`, `Int64`, `Int8`, `Integer`, `InterruptException`, `InvalidStateException`, `Irrational`, `KeyError`, `LinRange`, `LineNumberNode`, `LinearIndices`, `LoadError`, `MIME`, `Matrix`, `Method`, `MethodError`, `Missing`, `MissingException`, `Module`, `NTuple`, `NamedTuple`, `Nothing`, `Number`, `OrdinalRange`, `OutOfMemoryError`, `OverflowError`, `Pair`, `PartialQuickSort`, `PermutedDimsArray`, `Pipe`, `ProcessFailedException`, `Ptr`, `QuoteNode`, `Rational`, `RawFD`, `ReadOnlyMemoryError`, `Real`, `ReentrantLock`, `Ref`, `Regex`, `RegexMatch`, `RoundingMode`, `SegmentationFault`, `Set`, `Signed`, `Some`, `StackOverflowError`, `StepRange`, `StepRangeLen`, `StridedArray`, `StridedMatrix`, `StridedVecOrMat`, `StridedVector`, `String`, `StringIndexError`, `SubArray`, `SubString`, `SubstitutionString`, `Symbol`, `SystemError`, `Task`, `TaskFailedException`, `Text`, `TextDisplay`, `Timer`, `Tuple`, `Type`, `TypeError`, `TypeVar`, `UInt`, `UInt128`, `UInt16`, `UInt32`, `UInt64`, `UInt8`, `UndefInitializer`, `UndefKeywordError`, `UndefRefError`, `UndefVarError`, `Union`, `UnionAll`, `UnitRange`, `Unsigned`, `Val`, `Vararg`, `VecElement`, `VecOrMat`, `Vector`, `VersionNumber`, `WeakKeyDict`, `WeakRef`), KeywordType, nil}, + {Words(``, `\b`, `ARGS`, `C_NULL`, `DEPOT_PATH`, `ENDIAN_BOM`, `ENV`, `Inf`, `Inf16`, `Inf32`, `Inf64`, `InsertionSort`, `LOAD_PATH`, `MergeSort`, `NaN`, `NaN16`, `NaN32`, `NaN64`, `PROGRAM_FILE`, `QuickSort`, `RoundDown`, `RoundFromZero`, `RoundNearest`, `RoundNearestTiesAway`, `RoundNearestTiesUp`, `RoundToZero`, `RoundUp`, `VERSION`, `devnull`, `false`, `im`, `missing`, `nothing`, `pi`, `stderr`, `stdin`, `stdout`, `true`, `undef`, `π`, `ℯ`), NameBuiltin, nil}, + {`(?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*)`, Name, nil}, + {`(\d+((_\d+)+)?\.(?!\.)(\d+((_\d+)+)?)?|\.\d+((_\d+)+)?)([eEf][+-]?[0-9]+)?`, LiteralNumberFloat, nil}, + {`\d+((_\d+)+)?[eEf][+-]?[0-9]+`, LiteralNumberFloat, nil}, + {`0x[a-fA-F0-9]+((_[a-fA-F0-9]+)+)?(\.([a-fA-F0-9]+((_[a-fA-F0-9]+)+)?)?)?p[+-]?\d+`, LiteralNumberFloat, nil}, + {`0b[01]+((_[01]+)+)?`, LiteralNumberBin, nil}, + {`0o[0-7]+((_[0-7]+)+)?`, LiteralNumberOct, nil}, + {`0x[a-fA-F0-9]+((_[a-fA-F0-9]+)+)?`, LiteralNumberHex, nil}, + {`\d+((_\d+)+)?`, LiteralNumberInteger, nil}, + {Words(``, ``, `.`), Operator, nil}, }, "blockcomment": { {`[^=#]`, CommentMultiline, nil}, @@ -56,40 +68,67 @@ var Julia = internal.Register(MustNewLexer( {`=#`, CommentMultiline, Pop(1)}, {`[=#]`, CommentMultiline, nil}, }, - "string": { - {`"`, LiteralString, Pop(1)}, - {`\\([\\"\'$nrbtfav]|(x|u|U)[a-fA-F0-9]+|\d+)`, LiteralStringEscape, nil}, - {`\$(?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*`, LiteralStringInterpol, nil}, - {`(\$)(\()`, ByGroups(LiteralStringInterpol, Punctuation), Push("in-intp")}, - {`%[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?[hlL]?[E-GXc-giorsux%]`, LiteralStringInterpol, nil}, - {`.|\s`, LiteralString, nil}, + "curly": { + {`\{`, Punctuation, Push()}, + {`\}`, Punctuation, Pop(1)}, + {`(?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*)`, KeywordType, nil}, + Include("root"), }, - "tqstring": { + "tqrawstring": { {`"""`, LiteralString, Pop(1)}, - {`\\([\\"\'$nrbtfav]|(x|u|U)[a-fA-F0-9]+|\d+)`, LiteralStringEscape, nil}, - {`\$(?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*`, LiteralStringInterpol, nil}, + {`([^"]|"[^"][^"])+`, LiteralString, nil}, + }, + "rawstring": { + {`"`, LiteralString, Pop(1)}, + {`\\"`, LiteralStringEscape, nil}, + {`([^"\\]|\\[^"])+`, LiteralString, nil}, + }, + "interp": { + {`\$(?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*)`, LiteralStringInterpol, nil}, {`(\$)(\()`, ByGroups(LiteralStringInterpol, Punctuation), Push("in-intp")}, - {`.|\s`, LiteralString, nil}, - }, - "regex": { - {`"`, LiteralStringRegex, Pop(1)}, - {`\\"`, LiteralStringRegex, nil}, - {`.|\s`, LiteralStringRegex, nil}, - }, - "tqregex": { - {`"""`, LiteralStringRegex, Pop(1)}, - {`.|\s`, LiteralStringRegex, nil}, - }, - "command": { - {"`", LiteralStringBacktick, Pop(1)}, - {`\$(?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*`, LiteralStringInterpol, nil}, - {`(\$)(\()`, ByGroups(LiteralStringInterpol, Punctuation), Push("in-intp")}, - {`.|\s`, LiteralStringBacktick, nil}, }, "in-intp": { {`\(`, Punctuation, Push()}, {`\)`, Punctuation, Pop(1)}, Include("root"), }, - }, -)) + "string": { + {`(")((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*)|\d+)?`, ByGroups(LiteralString, LiteralStringAffix), Pop(1)}, + {`\\([\\"\'$nrbtfav]|(x|u|U)[a-fA-F0-9]+|\d+)`, LiteralStringEscape, nil}, + Include("interp"), + {`%[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?[hlL]?[E-GXc-giorsux%]`, LiteralStringInterpol, nil}, + {`[^"$%\\]+`, LiteralString, nil}, + {`.`, LiteralString, nil}, + }, + "tqstring": { + {`(""")((?:[a-zA-Z_¡-􏿿][a-zA-Z_0-9!¡-􏿿]*)|\d+)?`, ByGroups(LiteralString, LiteralStringAffix), Pop(1)}, + {`\\([\\"\'$nrbtfav]|(x|u|U)[a-fA-F0-9]+|\d+)`, LiteralStringEscape, nil}, + Include("interp"), + {`[^"$%\\]+`, LiteralString, nil}, + {`.`, LiteralString, nil}, + }, + "regex": { + {`(")([imsxa]*)?`, ByGroups(LiteralStringRegex, LiteralStringAffix), Pop(1)}, + {`\\"`, LiteralStringRegex, nil}, + {`[^\\"]+`, LiteralStringRegex, nil}, + }, + "tqregex": { + {`(""")([imsxa]*)?`, ByGroups(LiteralStringRegex, LiteralStringAffix), Pop(1)}, + {`[^"]+`, LiteralStringRegex, nil}, + }, + "command": { + {"(`)((?:[a-zA-Z_\u00a1-\U0010ffff][a-zA-Z_0-9!\u00a1-\U0010ffff]*)|\\d+)?", ByGroups(LiteralStringBacktick, LiteralStringAffix), Pop(1)}, + {"\\\\[`$]", LiteralStringEscape, nil}, + Include("interp"), + {"[^\\\\`$]+", LiteralStringBacktick, nil}, + {`.`, LiteralStringBacktick, nil}, + }, + "tqcommand": { + {"(```)((?:[a-zA-Z_\u00a1-\U0010ffff][a-zA-Z_0-9!\u00a1-\U0010ffff]*)|\\d+)?", ByGroups(LiteralStringBacktick, LiteralStringAffix), Pop(1)}, + {`\\\$`, LiteralStringEscape, nil}, + Include("interp"), + {"[^\\\\`$]+", LiteralStringBacktick, nil}, + {`.`, LiteralStringBacktick, nil}, + }, + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/j/jungle.go b/vendor/github.com/alecthomas/chroma/lexers/j/jungle.go index 83d46a4..5dbda9f 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/j/jungle.go +++ b/vendor/github.com/alecthomas/chroma/lexers/j/jungle.go @@ -5,14 +5,18 @@ import ( "github.com/alecthomas/chroma/lexers/internal" ) -var Jungle = internal.Register(MustNewLexer( +var Jungle = internal.Register(MustNewLazyLexer( &Config{ Name: "Jungle", Aliases: []string{"jungle"}, Filenames: []string{"*.jungle"}, MimeTypes: []string{"text/x-jungle"}, }, - Rules{ + jungleRules, +)) + +func jungleRules() Rules { + return Rules{ "root": { {`[^\S\n]+`, Text, nil}, {`\n`, Text, nil}, @@ -46,5 +50,5 @@ var Jungle = internal.Register(MustNewLexer( {`[a-zA-Z_]\w*`, Name, nil}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/k/kotlin.go b/vendor/github.com/alecthomas/chroma/lexers/k/kotlin.go index 17cdfa6..671f85e 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/k/kotlin.go +++ b/vendor/github.com/alecthomas/chroma/lexers/k/kotlin.go @@ -5,10 +5,8 @@ import ( "github.com/alecthomas/chroma/lexers/internal" ) -var kotlinIdentifier = "_A-Z\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa\uff21-\uff3aa-z\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0561-\u0587\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7fa\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\uaa70\uaadd\uaaf3-\uaaf4\uff70\uff9e-\uff9f\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef][A-Z\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa\uff21-\uff3aa-z\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0561-\u0587\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7fa\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\uaa70\uaadd\uaaf3-\uaaf4\uff70\uff9e-\uff9f\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19_\u203f-\u2040\u2054\ufe33-\ufe34\ufe4d-\ufe4f\uff3f\u00ad\u0600-\u0604\u061c\u06dd\u070f\u180e\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u206f\ufeff\ufff9-\ufffb\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b62-\u0b63\u0b82\u0bc0\u0bcd\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0cbc\u0cbf\u0cc6\u0ccc-\u0ccd\u0ce2-\u0ce3\u0d41-\u0d44\u0d4d\u0d62-\u0d63\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u3099-\u309a\ua66f\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\u0903\u093b\u093e-\u0940\u0949-\u094c\u094e-\u094f\u0982-\u0983\u09be-\u09c0\u09c7-\u09c8\u09cb-\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb-\u0acc\u0b02-\u0b03\u0b3e\u0b40\u0b47-\u0b48\u0b4b-\u0b4c\u0b57\u0bbe-\u0bbf\u0bc1-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82-\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7-\u0cc8\u0cca-\u0ccb\u0cd5-\u0cd6\u0d02-\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82-\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2-\u0df3\u0f3e-\u0f3f\u0f7f\u102b-\u102c\u1031\u1038\u103b-\u103c\u1056-\u1057\u1062-\u1064\u1067-\u106d\u1083-\u1084\u1087-\u108c\u108f\u109a-\u109c\u17b6\u17be-\u17c5\u17c7-\u17c8\u1923-\u1926\u1929-\u192b\u1930-\u1931\u1933-\u1938\u19b0-\u19c0\u19c8-\u19c9\u1a19-\u1a1a\u1a55\u1a57\u1a61\u1a63-\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43-\u1b44\u1b82\u1ba1\u1ba6-\u1ba7\u1baa\u1bac-\u1bad\u1be7\u1bea-\u1bec\u1bee\u1bf2-\u1bf3\u1c24-\u1c2b\u1c34-\u1c35\u1ce1\u1cf2-\u1cf3\u302e-\u302f\ua823-\ua824\ua827\ua880-\ua881\ua8b4-\ua8c3\ua952-\ua953\ua983\ua9b4-\ua9b5\ua9ba-\ua9bb\ua9bd-\ua9c0\uaa2f-\uaa30\uaa33-\uaa34\uaa4d\uaa7b\uaaeb\uaaee-\uaaef\uaaf5\uabe3-\uabe4\uabe6-\uabe7\uabe9-\uabea\uabec]*|`@?[_A-Z\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa\uff21-\uff3aa-z\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0561-\u0587\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7fa\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\uaa70\uaadd\uaaf3-\uaaf4\uff70\uff9e-\uff9f\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef][A-Z\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa\uff21-\uff3aa-z\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0561-\u0587\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7fa\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\uaa70\uaadd\uaaf3-\uaaf4\uff70\uff9e-\uff9f\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19_\u203f-\u2040\u2054\ufe33-\ufe34\ufe4d-\ufe4f\uff3f\u00ad\u0600-\u0604\u061c\u06dd\u070f\u180e\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u206f\ufeff\ufff9-\ufffb\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b62-\u0b63\u0b82\u0bc0\u0bcd\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0cbc\u0cbf\u0cc6\u0ccc-\u0ccd\u0ce2-\u0ce3\u0d41-\u0d44\u0d4d\u0d62-\u0d63\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u3099-\u309a\ua66f\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\u0903\u093b\u093e-\u0940\u0949-\u094c\u094e-\u094f\u0982-\u0983\u09be-\u09c0\u09c7-\u09c8\u09cb-\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb-\u0acc\u0b02-\u0b03\u0b3e\u0b40\u0b47-\u0b48\u0b4b-\u0b4c\u0b57\u0bbe-\u0bbf\u0bc1-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82-\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7-\u0cc8\u0cca-\u0ccb\u0cd5-\u0cd6\u0d02-\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82-\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2-\u0df3\u0f3e-\u0f3f\u0f7f\u102b-\u102c\u1031\u1038\u103b-\u103c\u1056-\u1057\u1062-\u1064\u1067-\u106d\u1083-\u1084\u1087-\u108c\u108f\u109a-\u109c\u17b6\u17be-\u17c5\u17c7-\u17c8\u1923-\u1926\u1929-\u192b\u1930-\u1931\u1933-\u1938\u19b0-\u19c0\u19c8-\u19c9\u1a19-\u1a1a\u1a55\u1a57\u1a61\u1a63-\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43-\u1b44\u1b82\u1ba1\u1ba6-\u1ba7\u1baa\u1bac-\u1bad\u1be7\u1bea-\u1bec\u1bee\u1bf2-\u1bf3\u1c24-\u1c2b\u1c34-\u1c35\u1ce1\u1cf2-\u1cf3\u302e-\u302f\ua823-\ua824\ua827\ua880-\ua881\ua8b4-\ua8c3\ua952-\ua953\ua983\ua9b4-\ua9b5\ua9ba-\ua9bb\ua9bd-\ua9c0\uaa2f-\uaa30\uaa33-\uaa34\uaa4d\uaa7b\uaaeb\uaaee-\uaaef\uaaf5\uabe3-\uabe4\uabe6-\uabe7\uabe9-\uabea\uabec" - // Kotlin lexer. -var Kotlin = internal.Register(MustNewLexer( +var Kotlin = internal.Register(MustNewLazyLexer( &Config{ Name: "Kotlin", Aliases: []string{"kotlin"}, @@ -16,7 +14,13 @@ var Kotlin = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-kotlin"}, DotAll: true, }, - Rules{ + kotlinRules, +)) + +func kotlinRules() Rules { + const kotlinIdentifier = "_A-Z\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa\uff21-\uff3aa-z\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0561-\u0587\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7fa\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\uaa70\uaadd\uaaf3-\uaaf4\uff70\uff9e-\uff9f\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef][A-Z\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa\uff21-\uff3aa-z\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0561-\u0587\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7fa\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\uaa70\uaadd\uaaf3-\uaaf4\uff70\uff9e-\uff9f\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19_\u203f-\u2040\u2054\ufe33-\ufe34\ufe4d-\ufe4f\uff3f\u00ad\u0600-\u0604\u061c\u06dd\u070f\u180e\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u206f\ufeff\ufff9-\ufffb\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b62-\u0b63\u0b82\u0bc0\u0bcd\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0cbc\u0cbf\u0cc6\u0ccc-\u0ccd\u0ce2-\u0ce3\u0d41-\u0d44\u0d4d\u0d62-\u0d63\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u3099-\u309a\ua66f\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\u0903\u093b\u093e-\u0940\u0949-\u094c\u094e-\u094f\u0982-\u0983\u09be-\u09c0\u09c7-\u09c8\u09cb-\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb-\u0acc\u0b02-\u0b03\u0b3e\u0b40\u0b47-\u0b48\u0b4b-\u0b4c\u0b57\u0bbe-\u0bbf\u0bc1-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82-\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7-\u0cc8\u0cca-\u0ccb\u0cd5-\u0cd6\u0d02-\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82-\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2-\u0df3\u0f3e-\u0f3f\u0f7f\u102b-\u102c\u1031\u1038\u103b-\u103c\u1056-\u1057\u1062-\u1064\u1067-\u106d\u1083-\u1084\u1087-\u108c\u108f\u109a-\u109c\u17b6\u17be-\u17c5\u17c7-\u17c8\u1923-\u1926\u1929-\u192b\u1930-\u1931\u1933-\u1938\u19b0-\u19c0\u19c8-\u19c9\u1a19-\u1a1a\u1a55\u1a57\u1a61\u1a63-\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43-\u1b44\u1b82\u1ba1\u1ba6-\u1ba7\u1baa\u1bac-\u1bad\u1be7\u1bea-\u1bec\u1bee\u1bf2-\u1bf3\u1c24-\u1c2b\u1c34-\u1c35\u1ce1\u1cf2-\u1cf3\u302e-\u302f\ua823-\ua824\ua827\ua880-\ua881\ua8b4-\ua8c3\ua952-\ua953\ua983\ua9b4-\ua9b5\ua9ba-\ua9bb\ua9bd-\ua9c0\uaa2f-\uaa30\uaa33-\uaa34\uaa4d\uaa7b\uaaeb\uaaee-\uaaef\uaaf5\uabe3-\uabe4\uabe6-\uabe7\uabe9-\uabea\uabec]*|`@?[_A-Z\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa\uff21-\uff3aa-z\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0561-\u0587\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7fa\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\uaa70\uaadd\uaaf3-\uaaf4\uff70\uff9e-\uff9f\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef][A-Z\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa\uff21-\uff3aa-z\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0561-\u0587\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7fa\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\uaa70\uaadd\uaaf3-\uaaf4\uff70\uff9e-\uff9f\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19_\u203f-\u2040\u2054\ufe33-\ufe34\ufe4d-\ufe4f\uff3f\u00ad\u0600-\u0604\u061c\u06dd\u070f\u180e\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u206f\ufeff\ufff9-\ufffb\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b62-\u0b63\u0b82\u0bc0\u0bcd\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0cbc\u0cbf\u0cc6\u0ccc-\u0ccd\u0ce2-\u0ce3\u0d41-\u0d44\u0d4d\u0d62-\u0d63\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u3099-\u309a\ua66f\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\u0903\u093b\u093e-\u0940\u0949-\u094c\u094e-\u094f\u0982-\u0983\u09be-\u09c0\u09c7-\u09c8\u09cb-\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb-\u0acc\u0b02-\u0b03\u0b3e\u0b40\u0b47-\u0b48\u0b4b-\u0b4c\u0b57\u0bbe-\u0bbf\u0bc1-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82-\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7-\u0cc8\u0cca-\u0ccb\u0cd5-\u0cd6\u0d02-\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82-\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2-\u0df3\u0f3e-\u0f3f\u0f7f\u102b-\u102c\u1031\u1038\u103b-\u103c\u1056-\u1057\u1062-\u1064\u1067-\u106d\u1083-\u1084\u1087-\u108c\u108f\u109a-\u109c\u17b6\u17be-\u17c5\u17c7-\u17c8\u1923-\u1926\u1929-\u192b\u1930-\u1931\u1933-\u1938\u19b0-\u19c0\u19c8-\u19c9\u1a19-\u1a1a\u1a55\u1a57\u1a61\u1a63-\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43-\u1b44\u1b82\u1ba1\u1ba6-\u1ba7\u1baa\u1bac-\u1bad\u1be7\u1bea-\u1bec\u1bee\u1bf2-\u1bf3\u1c24-\u1c2b\u1c34-\u1c35\u1ce1\u1cf2-\u1cf3\u302e-\u302f\ua823-\ua824\ua827\ua880-\ua881\ua8b4-\ua8c3\ua952-\ua953\ua983\ua9b4-\ua9b5\ua9ba-\ua9bb\ua9bd-\ua9c0\uaa2f-\uaa30\uaa33-\uaa34\uaa4d\uaa7b\uaaeb\uaaee-\uaaef\uaaf5\uabe3-\uabe4\uabe6-\uabe7\uabe9-\uabea\uabec" + + return Rules{ "root": { {`^\s*\[.*?\]`, NameAttribute, nil}, {`[^\S\n]+`, Text, nil}, @@ -90,5 +94,5 @@ var Kotlin = internal.Register(MustNewLexer( {`\$[` + kotlinIdentifier + `]+`, LiteralStringInterpol, nil}, {`\${[^}\n]*}`, LiteralStringInterpol, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/l/lighttpd.go b/vendor/github.com/alecthomas/chroma/lexers/l/lighttpd.go index 799b77c..6d83298 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/l/lighttpd.go +++ b/vendor/github.com/alecthomas/chroma/lexers/l/lighttpd.go @@ -6,14 +6,18 @@ import ( ) // Lighttpd Configuration File lexer. -var Lighttpd = internal.Register(MustNewLexer( +var Lighttpd = internal.Register(MustNewLazyLexer( &Config{ Name: "Lighttpd configuration file", Aliases: []string{"lighty", "lighttpd"}, Filenames: []string{}, MimeTypes: []string{"text/x-lighttpd-conf"}, }, - Rules{ + lighttpdRules, +)) + +func lighttpdRules() Rules { + return Rules{ "root": { {`#.*\n`, CommentSingle, nil}, {`/\S*`, Name, nil}, @@ -26,5 +30,5 @@ var Lighttpd = internal.Register(MustNewLexer( {`"([^"\\]*(?:\\.[^"\\]*)*)"`, LiteralStringDouble, nil}, {`\s+`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/l/llvm.go b/vendor/github.com/alecthomas/chroma/lexers/l/llvm.go index 8f5b0b1..e9ea319 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/l/llvm.go +++ b/vendor/github.com/alecthomas/chroma/lexers/l/llvm.go @@ -6,14 +6,18 @@ import ( ) // Llvm lexer. -var Llvm = internal.Register(MustNewLexer( +var Llvm = internal.Register(MustNewLazyLexer( &Config{ Name: "LLVM", Aliases: []string{"llvm"}, Filenames: []string{"*.ll"}, MimeTypes: []string{"text/x-llvm"}, }, - Rules{ + llvmRules, +)) + +func llvmRules() Rules { + return Rules{ "root": { Include("whitespace"), {`([-a-zA-Z$._][\w\-$.]*|"[^"]*?")\s*:`, NameLabel, nil}, @@ -39,5 +43,5 @@ var Llvm = internal.Register(MustNewLexer( {Words(``, ``, `void`, `half`, `float`, `double`, `x86_fp80`, `fp128`, `ppc_fp128`, `label`, `metadata`, `token`), KeywordType, nil}, {`i[1-9]\d*`, Keyword, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/l/lua.go b/vendor/github.com/alecthomas/chroma/lexers/l/lua.go index c397de0..db574a1 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/l/lua.go +++ b/vendor/github.com/alecthomas/chroma/lexers/l/lua.go @@ -6,14 +6,18 @@ import ( ) // Lua lexer. -var Lua = internal.Register(MustNewLexer( +var Lua = internal.Register(MustNewLazyLexer( &Config{ Name: "Lua", Aliases: []string{"lua"}, Filenames: []string{"*.lua", "*.wlua"}, MimeTypes: []string{"text/x-lua", "application/x-lua"}, }, - Rules{ + luaRules, +)) + +func luaRules() Rules { + return Rules{ "root": { {`#!.*`, CommentPreproc, nil}, Default(Push("base")), @@ -71,5 +75,5 @@ var Lua = internal.Register(MustNewLexer( {`"`, LiteralStringDouble, Pop(1)}, {`[^\\"]+`, LiteralStringDouble, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/lexers.go b/vendor/github.com/alecthomas/chroma/lexers/lexers.go index de2d7ce..2b42921 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/lexers.go +++ b/vendor/github.com/alecthomas/chroma/lexers/lexers.go @@ -3,7 +3,7 @@ // Sub-packages contain lexer implementations. package lexers -// nolint: golint +// nolint import ( "github.com/alecthomas/chroma" _ "github.com/alecthomas/chroma/lexers/a" diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/make.go b/vendor/github.com/alecthomas/chroma/lexers/m/make.go index eb9d9e6..905491a 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/m/make.go +++ b/vendor/github.com/alecthomas/chroma/lexers/m/make.go @@ -7,7 +7,7 @@ import ( ) // Makefile lexer. -var Makefile = internal.Register(MustNewLexer( +var Makefile = internal.Register(MustNewLazyLexer( &Config{ Name: "Base Makefile", Aliases: []string{"make", "makefile", "mf", "bsdmake"}, @@ -15,7 +15,11 @@ var Makefile = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-makefile"}, EnsureNL: true, }, - Rules{ + makefileRules, +)) + +func makefileRules() Rules { + return Rules{ "root": { {`^(?:[\t ]+.*\n|\n)+`, Using(Bash), nil}, {`\$[<@$+%?|*]`, Keyword, nil}, @@ -50,5 +54,5 @@ var Makefile = internal.Register(MustNewLexer( {`\n`, Text, Pop(1)}, {`.`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/mako.go b/vendor/github.com/alecthomas/chroma/lexers/m/mako.go index f7c140d..6f777dd 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/m/mako.go +++ b/vendor/github.com/alecthomas/chroma/lexers/m/mako.go @@ -7,14 +7,18 @@ import ( ) // Mako lexer. -var Mako = internal.Register(MustNewLexer( +var Mako = internal.Register(MustNewLazyLexer( &Config{ Name: "Mako", Aliases: []string{"mako"}, Filenames: []string{"*.mao"}, MimeTypes: []string{"application/x-mako"}, }, - Rules{ + makoRules, +)) + +func makoRules() Rules { + return Rules{ "root": { {`(\s*)(%)(\s*end(?:\w+))(\n|\Z)`, ByGroups(Text, CommentPreproc, Keyword, Other), nil}, {`(\s*)(%)([^\n]*)(\n|\Z)`, ByGroups(Text, CommentPreproc, Using(Python), Other), nil}, @@ -56,5 +60,5 @@ var Mako = internal.Register(MustNewLexer( {`'.*?'`, LiteralString, Pop(1)}, {`[^\s>]+`, LiteralString, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/markdown.go b/vendor/github.com/alecthomas/chroma/lexers/m/markdown.go index dd78ec0..e50e470 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/m/markdown.go +++ b/vendor/github.com/alecthomas/chroma/lexers/m/markdown.go @@ -7,14 +7,18 @@ import ( ) // Markdown lexer. -var Markdown = internal.Register(DelegatingLexer(h.HTML, MustNewLexer( +var Markdown = internal.Register(DelegatingLexer(h.HTML, MustNewLazyLexer( &Config{ Name: "markdown", Aliases: []string{"md", "mkd"}, Filenames: []string{"*.md", "*.mkd", "*.markdown"}, MimeTypes: []string{"text/x-markdown"}, }, - Rules{ + markdownRules, +))) + +func markdownRules() Rules { + return Rules{ "root": { {`^(#[^#].+\n)`, ByGroups(GenericHeading), nil}, {`^(#{2,6}.+\n)`, ByGroups(GenericSubheading), nil}, @@ -23,7 +27,8 @@ var Markdown = internal.Register(DelegatingLexer(h.HTML, MustNewLexer( {`^(\s*)([0-9]+\.)( .+\n)`, ByGroups(Text, Keyword, UsingSelf("inline")), nil}, {`^(\s*>\s)(.+\n)`, ByGroups(Keyword, GenericEmph), nil}, {"^(```\\n)([\\w\\W]*?)(^```$)", ByGroups(String, Text, String), nil}, - {"^(```)(\\w+)(\\n)([\\w\\W]*?)(^```$)", + { + "^(```)(\\w+)(\\n)([\\w\\W]*?)(^```$)", UsingByGroup( internal.Get, 2, 4, @@ -35,7 +40,7 @@ var Markdown = internal.Register(DelegatingLexer(h.HTML, MustNewLexer( }, "inline": { {`\\.`, Text, nil}, - {`(\s)([*_][^*_]+[*_])(\W|\n)`, ByGroups(Text, GenericEmph, Text), nil}, + {`(\s)(\*|_)((?:(?!\2).)*)(\2)((?=\W|\n))`, ByGroups(Text, GenericEmph, GenericEmph, GenericEmph, Text), nil}, {`(\s)((\*\*|__).*?)\3((?=\W|\n))`, ByGroups(Text, GenericStrong, GenericStrong, Text), nil}, {`(\s)(~~[^~]+~~)((?=\W|\n))`, ByGroups(Text, GenericDeleted, Text), nil}, {"`[^`]+`", LiteralStringBacktick, nil}, @@ -44,5 +49,5 @@ var Markdown = internal.Register(DelegatingLexer(h.HTML, MustNewLexer( {`[^\\\s]+`, Other, nil}, {`.|\n`, Other, nil}, }, - }, -))) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/mason.go b/vendor/github.com/alecthomas/chroma/lexers/m/mason.go index 5c70ab0..bc48f5c 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/m/mason.go +++ b/vendor/github.com/alecthomas/chroma/lexers/m/mason.go @@ -8,7 +8,7 @@ import ( ) // Mason lexer. -var Mason = internal.Register(MustNewLexer( +var Mason = internal.Register(MustNewLazyLexer( &Config{ Name: "Mason", Aliases: []string{"mason"}, @@ -16,7 +16,11 @@ var Mason = internal.Register(MustNewLexer( MimeTypes: []string{"application/x-mason"}, Priority: 0.1, }, - Rules{ + masonRules, +)) + +func masonRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`(<%doc>)(.*?)()(?s)`, ByGroups(NameTag, CommentMultiline, NameTag), nil}, @@ -39,5 +43,5 @@ var Mason = internal.Register(MustNewLexer( \Z # end of string )`, ByGroups(Using(HTML), Operator), nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/mathematica.go b/vendor/github.com/alecthomas/chroma/lexers/m/mathematica.go index 3d1f641..ed1ea24 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/m/mathematica.go +++ b/vendor/github.com/alecthomas/chroma/lexers/m/mathematica.go @@ -6,14 +6,18 @@ import ( ) // Mathematica lexer. -var Mathematica = internal.Register(MustNewLexer( +var Mathematica = internal.Register(MustNewLazyLexer( &Config{ Name: "Mathematica", Aliases: []string{"mathematica", "mma", "nb"}, Filenames: []string{"*.nb", "*.cdf", "*.nbp", "*.ma"}, MimeTypes: []string{"application/mathematica", "application/vnd.wolfram.mathematica", "application/vnd.wolfram.mathematica.package", "application/vnd.wolfram.cdf"}, }, - Rules{ + mathematicaRules, +)) + +func mathematicaRules() Rules { + return Rules{ "root": { {`(?s)\(\*.*?\*\)`, Comment, nil}, {"([a-zA-Z]+[A-Za-z0-9]*`)", NameNamespace, nil}, @@ -28,5 +32,5 @@ var Mathematica = internal.Register(MustNewLexer( {`".*?"`, LiteralString, nil}, {`\s+`, TextWhitespace, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/matlab.go b/vendor/github.com/alecthomas/chroma/lexers/m/matlab.go index 5b0baa5..4e98d69 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/m/matlab.go +++ b/vendor/github.com/alecthomas/chroma/lexers/m/matlab.go @@ -6,14 +6,18 @@ import ( ) // Matlab lexer. -var Matlab = internal.Register(MustNewLexer( +var Matlab = internal.Register(MustNewLazyLexer( &Config{ Name: "Matlab", Aliases: []string{"matlab"}, Filenames: []string{"*.m"}, MimeTypes: []string{"text/matlab"}, }, - Rules{ + matlabRules, +)) + +func matlabRules() Rules { + return Rules{ "root": { {`\n`, Text, nil}, {`^!.*`, LiteralStringOther, nil}, @@ -47,5 +51,5 @@ var Matlab = internal.Register(MustNewLexer( {`(\s*)(?:(.+)(\s*)(=)(\s*))?(.+)(\()(.*)(\))(\s*)`, ByGroups(TextWhitespace, Text, TextWhitespace, Punctuation, TextWhitespace, NameFunction, Punctuation, Text, Punctuation, TextWhitespace), Pop(1)}, {`(\s*)([a-zA-Z_]\w*)`, ByGroups(Text, NameFunction), Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/mcfunction.go b/vendor/github.com/alecthomas/chroma/lexers/m/mcfunction.go new file mode 100644 index 0000000..7baec6d --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/m/mcfunction.go @@ -0,0 +1,109 @@ +package m + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// mcfunction lexer. +var MCFunction = internal.Register(MustNewLazyLexer( + &Config{ + Name: "mcfunction", + Aliases: []string{"mcfunction"}, + Filenames: []string{"*.mcfunction"}, + MimeTypes: []string{}, + NotMultiline: true, + DotAll: true, + }, + func() Rules { + return Rules{ + "simplevalue": { + {`(true|false)`, KeywordConstant, nil}, + {`[01]b`, LiteralNumber, nil}, + {`-?(0|[1-9]\d*)(\.\d+[eE](\+|-)?\d+|[eE](\+|-)?\d+|\.\d+)`, LiteralNumberFloat, nil}, + {`(-?\d+)(\.\.)(-?\d+)`, ByGroups(LiteralNumberInteger, Punctuation, LiteralNumberInteger), nil}, + {`-?(0|[1-9]\d*)`, LiteralNumberInteger, nil}, + {`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil}, + {`'[^']+'`, LiteralStringSingle, nil}, + {`([!#]?)(\w+)`, ByGroups(Punctuation, Text), nil}, + }, + "nbtobjectattribute": { + Include("nbtvalue"), + {`:`, Punctuation, nil}, + {`,`, Punctuation, Pop(1)}, + {`\}`, Punctuation, Pop(2)}, + }, + "nbtobjectvalue": { + {`("(\\\\|\\"|[^"])*"|[a-zA-Z0-9_]+)`, NameTag, Push("nbtobjectattribute")}, + {`\}`, Punctuation, Pop(1)}, + }, + "nbtarrayvalue": { + Include("nbtvalue"), + {`,`, Punctuation, nil}, + {`\]`, Punctuation, Pop(1)}, + }, + "nbtvalue": { + Include("simplevalue"), + {`\{`, Punctuation, Push("nbtobjectvalue")}, + {`\[`, Punctuation, Push("nbtarrayvalue")}, + }, + "argumentvalue": { + Include("simplevalue"), + {`,`, Punctuation, Pop(1)}, + {`[}\]]`, Punctuation, Pop(2)}, + }, + "argumentlist": { + {`(nbt)(={)`, ByGroups(NameAttribute, Punctuation), Push("nbtobjectvalue")}, + {`([A-Za-z0-9/_!]+)(={)`, ByGroups(NameAttribute, Punctuation), Push("argumentlist")}, + {`([A-Za-z0-9/_!]+)(=)`, ByGroups(NameAttribute, Punctuation), Push("argumentvalue")}, + Include("simplevalue"), + {`,`, Punctuation, nil}, + {`[}\]]`, Punctuation, Pop(1)}, + }, + "root": { + {`#.*?\n`, CommentSingle, nil}, + {Words(`/?`, `\b`, `ability`, `attributes`, `advancement`, + `ban`, `ban-ip`, `banlist`, `bossbar`, + `camerashake`, `classroommode`, `clear`, + `clearspawnpoint`, `clone`, `code`, `collect`, + `createagent`, `data`, `datapack`, `debug`, + `defaultgamemode`, `deop`, `destroy`, `detect`, + `detectredstone`, `difficulty`, `dropall`, + `effect`, `enchant`, `event`, `execute`, + `experience`, `fill`, `flog`, `forceload`, + `function`, `gamemode`, `gamerule`, + `geteduclientinfo`, `give`, `help`, `item`, + `immutableworld`, `kick`, `kill`, `list`, + `locate`, `locatebiome`, `loot`, `me`, `mixer`, + `mobevent`, `move`, `msg`, `music`, `op`, + `pardon`, `particle`, `playanimation`, + `playsound`, `position`, `publish`, + `raytracefog`, `recipe`, `reload`, `remove`, + `replaceitem`, `ride`, `save`, `save-all`, + `save-off`, `save-on`, `say`, `schedule`, + `scoreboard`, `seed`, `setblock`, + `setidletimeout`, `setmaxplayers`, + `setworldspawn`, `spawnpoint`, `spectate`, + `spreadplayers`, `stop`, `stopsound`, + `structure`, `summon`, `tag`, `team`, `teammsg`, + `teleport`, `tell`, `tellraw`, `testfor`, + `testforblock`, `testforblocks`, `tickingarea`, + `time`, `title`, `toggledownfall`, `tp`, + `tpagent`, `transfer`, `transferserver`, + `trigger`, `turn`, `w`, `weather`, `whitelist`, + `worldborder`, `worldbuilder`, `wsserver`, `xp`, + ), KeywordReserved, nil}, + {Words(``, ``, `@p`, `@r`, `@a`, `@e`, `@s`, `@c`, `@v`), + KeywordConstant, nil}, + {`\[`, Punctuation, Push("argumentlist")}, + {`{`, Punctuation, Push("nbtobjectvalue")}, + {`~`, NameBuiltin, nil}, + {`([a-zA-Z_]+:)?[a-zA-Z_]+\b`, Text, nil}, + {`([a-z]+)(\.)([0-9]+)\b`, ByGroups(Text, Punctuation, LiteralNumber), nil}, + {`([<>=]|<=|>=)`, Punctuation, nil}, + Include("simplevalue"), + {`\s+`, TextWhitespace, nil}, + }, + } + }, +)) diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/metal.go b/vendor/github.com/alecthomas/chroma/lexers/m/metal.go new file mode 100644 index 0000000..4a9ba2b --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/m/metal.go @@ -0,0 +1,101 @@ +package m + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// Metal lexer. +var Metal = internal.Register(MustNewLazyLexer( + &Config{ + Name: "Metal", + Aliases: []string{"metal"}, + Filenames: []string{"*.metal"}, + MimeTypes: []string{"text/x-metal"}, + EnsureNL: true, + }, + metalRules, +)) + +func metalRules() Rules { + return Rules{ + "statements": { + {Words(``, `\b`, `namespace`, `operator`, `template`, `this`, `using`, `constexpr`), Keyword, nil}, + {`(enum)\b(\s+)(class)\b(\s*)`, ByGroups(Keyword, Text, Keyword, Text), Push("classname")}, + {`(class|struct|enum|union)\b(\s*)`, ByGroups(Keyword, Text), Push("classname")}, + {`\[\[.+\]\]`, NameAttribute, nil}, + {`(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*`, LiteralNumberFloat, nil}, + {`(\d+\.\d*|\.\d+|\d+[fF])[fF]?`, LiteralNumberFloat, nil}, + {`0[xX]([0-9A-Fa-f]('?[0-9A-Fa-f]+)*)[LlUu]*`, LiteralNumberHex, nil}, + {`0('?[0-7]+)+[LlUu]*`, LiteralNumberOct, nil}, + {`0[Bb][01]('?[01]+)*[LlUu]*`, LiteralNumberBin, nil}, + {`[0-9]('?[0-9]+)*[LlUu]*`, LiteralNumberInteger, nil}, + {`\*/`, Error, nil}, + {`[~!%^&*+=|?:<>/-]`, Operator, nil}, + {`[()\[\],.]`, Punctuation, nil}, + {Words(``, `\b`, `break`, `case`, `const`, `continue`, `do`, `else`, `enum`, `extern`, `for`, `if`, `return`, `sizeof`, `static`, `struct`, `switch`, `typedef`, `union`, `while`), Keyword, nil}, + {`(bool|float|half|long|ptrdiff_t|size_t|unsigned|u?char|u?int((8|16|32|64)_t)?|u?short)\b`, KeywordType, nil}, + {`(bool|float|half|u?(char|int|long|short))(2|3|4)\b`, KeywordType, nil}, + {`packed_(float|half|long|u?(char|int|short))(2|3|4)\b`, KeywordType, nil}, + {`(float|half)(2|3|4)x(2|3|4)\b`, KeywordType, nil}, + {`atomic_u?int\b`, KeywordType, nil}, + {`(rg?(8|16)(u|s)norm|rgba(8|16)(u|s)norm|srgba8unorm|rgb10a2|rg11b10f|rgb9e5)\b`, KeywordType, nil}, + {`(array|depth(2d|cube)(_array)?|depth2d_ms(_array)?|sampler|texture_buffer|texture(1|2)d(_array)?|texture2d_ms(_array)?|texture3d|texturecube(_array)?|uniform|visible_function_table)\b`, KeywordType, nil}, + {`(true|false|NULL)\b`, NameBuiltin, nil}, + {Words(``, `\b`, `device`, `constant`, `ray_data`, `thread`, `threadgroup`, `threadgroup_imageblock`), Keyword, nil}, + {`([a-zA-Z_]\w*)(\s*)(:)(?!:)`, ByGroups(NameLabel, Text, Punctuation), nil}, + {`[a-zA-Z_]\w*`, Name, nil}, + }, + "root": { + Include("whitespace"), + {`(fragment|kernel|vertex)?((?:[\w*\s])+?(?:\s|[*]))([a-zA-Z_]\w*)(\s*\([^;]*?\))([^;{]*)(\{)`, ByGroups(Keyword, UsingSelf("root"), NameFunction, UsingSelf("root"), UsingSelf("root"), Punctuation), Push("function")}, + {`(fragment|kernel|vertex)?((?:[\w*\s])+?(?:\s|[*]))([a-zA-Z_]\w*)(\s*\([^;]*?\))([^;]*)(;)`, ByGroups(Keyword, UsingSelf("root"), NameFunction, UsingSelf("root"), UsingSelf("root"), Punctuation), nil}, + Default(Push("statement")), + }, + "classname": { + {`(\[\[.+\]\])(\s*)`, ByGroups(NameAttribute, Text), nil}, + {`[a-zA-Z_]\w*`, NameClass, Pop(1)}, + {`\s*(?=[>{])`, Text, Pop(1)}, + }, + "whitespace": { + {`^#if\s+0`, CommentPreproc, Push("if0")}, + {`^#`, CommentPreproc, Push("macro")}, + {`^(\s*(?:/[*].*?[*]/\s*)?)(#if\s+0)`, ByGroups(UsingSelf("root"), CommentPreproc), Push("if0")}, + {`^(\s*(?:/[*].*?[*]/\s*)?)(#)`, ByGroups(UsingSelf("root"), CommentPreproc), Push("macro")}, + {`\n`, Text, nil}, + {`\s+`, Text, nil}, + {`\\\n`, Text, nil}, + {`//(\n|[\w\W]*?[^\\]\n)`, CommentSingle, nil}, + {`/(\\\n)?[*][\w\W]*?[*](\\\n)?/`, CommentMultiline, nil}, + {`/(\\\n)?[*][\w\W]*`, CommentMultiline, nil}, + }, + "statement": { + Include("whitespace"), + Include("statements"), + {`[{]`, Punctuation, Push("root")}, + {`[;}]`, Punctuation, Pop(1)}, + }, + "function": { + Include("whitespace"), + Include("statements"), + {`;`, Punctuation, nil}, + {`\{`, Punctuation, Push()}, + {`\}`, Punctuation, Pop(1)}, + }, + "macro": { + {`(include)(\s*(?:/[*].*?[*]/\s*)?)([^\n]+)`, ByGroups(CommentPreproc, Text, CommentPreprocFile), nil}, + {`[^/\n]+`, CommentPreproc, nil}, + {`/[*](.|\n)*?[*]/`, CommentMultiline, nil}, + {`//.*?\n`, CommentSingle, Pop(1)}, + {`/`, CommentPreproc, nil}, + {`(?<=\\)\n`, CommentPreproc, nil}, + {`\n`, CommentPreproc, Pop(1)}, + }, + "if0": { + {`^\s*#if.*?(?=|>|!=)`, Operator, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/myghty.go b/vendor/github.com/alecthomas/chroma/lexers/m/myghty.go index 02a20ea..eac082c 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/m/myghty.go +++ b/vendor/github.com/alecthomas/chroma/lexers/m/myghty.go @@ -7,24 +7,28 @@ import ( ) // Myghty lexer. -var Myghty = internal.Register(MustNewLexer( +var Myghty = internal.Register(MustNewLazyLexer( &Config{ Name: "Myghty", Aliases: []string{"myghty"}, Filenames: []string{"*.myt", "autodelegate"}, MimeTypes: []string{"application/x-myghty"}, }, - Rules{ + myghtyRules, +)) + +func myghtyRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`(<%(?:def|method))(\s*)(.*?)(>)(.*?)()(?s)`, ByGroups(NameTag, Text, NameFunction, NameTag, UsingSelf("root"), NameTag), nil}, - {`(<%\w+)(.*?)(>)(.*?)()(?s)`, ByGroups(NameTag, NameFunction, NameTag, Using(Python), NameTag), nil}, - {`(<&[^|])(.*?)(,.*?)?(&>)`, ByGroups(NameTag, NameFunction, Using(Python), NameTag), nil}, - {`(<&\|)(.*?)(,.*?)?(&>)(?s)`, ByGroups(NameTag, NameFunction, Using(Python), NameTag), nil}, + {`(<%\w+)(.*?)(>)(.*?)()(?s)`, ByGroups(NameTag, NameFunction, NameTag, Using(Python2), NameTag), nil}, + {`(<&[^|])(.*?)(,.*?)?(&>)`, ByGroups(NameTag, NameFunction, Using(Python2), NameTag), nil}, + {`(<&\|)(.*?)(,.*?)?(&>)(?s)`, ByGroups(NameTag, NameFunction, Using(Python2), NameTag), nil}, {``, NameTag, nil}, - {`(<%!?)(.*?)(%>)(?s)`, ByGroups(NameTag, Using(Python), NameTag), nil}, + {`(<%!?)(.*?)(%>)(?s)`, ByGroups(NameTag, Using(Python2), NameTag), nil}, {`(?<=^)#[^\n]*(\n|\Z)`, Comment, nil}, - {`(?<=^)(%)([^\n]*)(\n|\Z)`, ByGroups(NameTag, Using(Python), Other), nil}, + {`(?<=^)(%)([^\n]*)(\n|\Z)`, ByGroups(NameTag, Using(Python2), Other), nil}, {`(?sx) (.+?) # anything, followed by: (?: @@ -36,5 +40,5 @@ var Myghty = internal.Register(MustNewLexer( \Z # end of string )`, ByGroups(Other, Operator), nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/m/mysql.go b/vendor/github.com/alecthomas/chroma/lexers/m/mysql.go index 9f47e32..2738628 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/m/mysql.go +++ b/vendor/github.com/alecthomas/chroma/lexers/m/mysql.go @@ -1,12 +1,19 @@ package m import ( + "regexp" + . "github.com/alecthomas/chroma" // nolint "github.com/alecthomas/chroma/lexers/internal" ) +var ( + mysqlAnalyserNameBetweenBacktickRe = regexp.MustCompile("`[a-zA-Z_]\\w*`") + mysqlAnalyserNameBetweenBracketRe = regexp.MustCompile(`\[[a-zA-Z_]\w*\]`) +) + // MySQL lexer. -var MySQL = internal.Register(MustNewLexer( +var MySQL = internal.Register(MustNewLazyLexer( &Config{ Name: "MySQL", Aliases: []string{"mysql"}, @@ -15,9 +22,31 @@ var MySQL = internal.Register(MustNewLexer( NotMultiline: true, CaseInsensitive: true, }, - Rules{ + mySQLRules, +).SetAnalyser(func(text string) float32 { + nameBetweenBacktickCount := len(mysqlAnalyserNameBetweenBacktickRe.FindAllString(text, -1)) + nameBetweenBracketCount := len(mysqlAnalyserNameBetweenBracketRe.FindAllString(text, -1)) + + var result float32 + + // Same logic as above in the TSQL analysis. + dialectNameCount := nameBetweenBacktickCount + nameBetweenBracketCount + if dialectNameCount >= 1 && nameBetweenBacktickCount >= (2*nameBetweenBracketCount) { + // Found at least twice as many `name` as [name]. + result += 0.5 + } else if nameBetweenBacktickCount > nameBetweenBracketCount { + result += 0.2 + } else if nameBetweenBacktickCount > 0 { + result += 0.1 + } + + return result +})) + +func mySQLRules() Rules { + return Rules{ "root": { - {`\s+`, Text, nil}, + {`\s+`, TextWhitespace, nil}, {`(#|--\s+).*\n?`, CommentSingle, nil}, {`/\*`, CommentMultiline, Push("multiline-comments")}, {`[0-9]+`, LiteralNumberInteger, nil}, @@ -25,11 +54,11 @@ var MySQL = internal.Register(MustNewLexer( {`((?:_[a-z0-9]+)?)(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("string")}, {`((?:_[a-z0-9]+)?)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("double-string")}, {"[+*/<>=~!@#%^&|`?-]", Operator, nil}, - {`\b(tinyint|smallint|mediumint|int|integer|bigint|date|datetime|time|bit|bool|tinytext|mediumtext|longtext|text|tinyblob|mediumblob|longblob|blob|float|double|double\s+precision|real|numeric|dec|decimal|timestamp|year|char|varchar|varbinary|varcharacter|enum|set)(\b\s*)(\()?`, ByGroups(KeywordType, Text, Punctuation), nil}, + {`\b(tinyint|smallint|mediumint|int|integer|bigint|date|datetime|time|bit|bool|tinytext|mediumtext|longtext|text|tinyblob|mediumblob|longblob|blob|float|double|double\s+precision|real|numeric|dec|decimal|timestamp|year|char|varchar|varbinary|varcharacter|enum|set)(\b\s*)(\()?`, ByGroups(KeywordType, TextWhitespace, Punctuation), nil}, {`\b(add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|fetch|flush|float|float4|float8|for|force|foreign|from|fulltext|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|identified|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|lines|load|localtime|localtimestamp|lock|long|loop|low_priority|match|minute_microsecond|minute_second|mod|modifies|natural|no_write_to_binlog|not|numeric|on|optimize|option|optionally|or|order|out|outer|outfile|precision|primary|privileges|procedure|purge|raid0|read|reads|real|references|regexp|release|rename|repeat|replace|require|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|smallint|soname|spatial|specific|sql|sql_big_result|sql_calc_found_rows|sql_small_result|sqlexception|sqlstate|sqlwarning|ssl|starting|straight_join|table|terminated|then|to|trailing|trigger|undo|union|unique|unlock|unsigned|update|usage|use|user|using|utc_date|utc_time|utc_timestamp|values|varying|when|where|while|with|write|x509|xor|year_month|zerofill)\b`, Keyword, nil}, {`\b(auto_increment|engine|charset|tables)\b`, KeywordPseudo, nil}, {`(true|false|null)`, NameConstant, nil}, - {`([a-z_]\w*)(\s*)(\()`, ByGroups(NameFunction, Text, Punctuation), nil}, + {`([a-z_]\w*)(\s*)(\()`, ByGroups(NameFunction, TextWhitespace, Punctuation), nil}, {`[a-z_]\w*`, Name, nil}, {`@[a-z0-9]*[._]*[a-z0-9]*`, NameVariable, nil}, {`[;:()\[\],.]`, Punctuation, nil}, @@ -50,5 +79,5 @@ var MySQL = internal.Register(MustNewLexer( {`""`, LiteralStringDouble, nil}, {`"`, LiteralStringDouble, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/n/nasm.go b/vendor/github.com/alecthomas/chroma/lexers/n/nasm.go index d769d15..de6734e 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/n/nasm.go +++ b/vendor/github.com/alecthomas/chroma/lexers/n/nasm.go @@ -6,7 +6,7 @@ import ( ) // Nasm lexer. -var Nasm = internal.Register(MustNewLexer( +var Nasm = internal.Register(MustNewLazyLexer( &Config{ Name: "NASM", Aliases: []string{"nasm"}, @@ -14,7 +14,11 @@ var Nasm = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-nasm"}, CaseInsensitive: true, }, - Rules{ + nasmRules, +)) + +func nasmRules() Rules { + return Rules{ "root": { {`^\s*%`, CommentPreproc, Push("preproc")}, Include("whitespace"), @@ -55,5 +59,5 @@ var Nasm = internal.Register(MustNewLexer( {`seg|wrt|strict`, OperatorWord, nil}, {`byte|[dq]?word`, KeywordType, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/n/newspeak.go b/vendor/github.com/alecthomas/chroma/lexers/n/newspeak.go index 1a6a37b..c9d3ae0 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/n/newspeak.go +++ b/vendor/github.com/alecthomas/chroma/lexers/n/newspeak.go @@ -6,14 +6,18 @@ import ( ) // Newspeak lexer. -var Newspeak = internal.Register(MustNewLexer( +var Newspeak = internal.Register(MustNewLazyLexer( &Config{ Name: "Newspeak", Aliases: []string{"newspeak"}, Filenames: []string{"*.ns2"}, MimeTypes: []string{"text/x-newspeak"}, }, - Rules{ + newspeakRules, +)) + +func newspeakRules() Rules { + return Rules{ "root": { {`\b(Newsqueak2)\b`, KeywordDeclaration, nil}, {`'[^']*'`, LiteralString, nil}, @@ -51,5 +55,5 @@ var Newspeak = internal.Register(MustNewLexer( {`\s+`, Text, nil}, {`"[^"]*"`, Comment, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/n/nginx.go b/vendor/github.com/alecthomas/chroma/lexers/n/nginx.go index 840d100..6d80523 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/n/nginx.go +++ b/vendor/github.com/alecthomas/chroma/lexers/n/nginx.go @@ -6,14 +6,18 @@ import ( ) // Nginx Configuration File lexer. -var Nginx = internal.Register(MustNewLexer( +var Nginx = internal.Register(MustNewLazyLexer( &Config{ Name: "Nginx configuration file", Aliases: []string{"nginx"}, Filenames: []string{"nginx.conf"}, MimeTypes: []string{"text/x-nginx-conf"}, }, - Rules{ + nginxRules, +)) + +func nginxRules() Rules { + return Rules{ "root": { {`(include)(\s+)([^\s;]+)`, ByGroups(Keyword, Text, Name), nil}, {`[^\s;#]+`, Keyword, Push("stmt")}, @@ -43,5 +47,5 @@ var Nginx = internal.Register(MustNewLexer( {`\s+`, Text, nil}, {`[$;]`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/n/nim.go b/vendor/github.com/alecthomas/chroma/lexers/n/nim.go index b08c2f9..3f98086 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/n/nim.go +++ b/vendor/github.com/alecthomas/chroma/lexers/n/nim.go @@ -6,7 +6,7 @@ import ( ) // Nim lexer. -var Nim = internal.Register(MustNewLexer( +var Nim = internal.Register(MustNewLazyLexer( &Config{ Name: "Nim", Aliases: []string{"nim", "nimrod"}, @@ -14,7 +14,11 @@ var Nim = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-nim"}, CaseInsensitive: true, }, - Rules{ + nimRules, +)) + +func nimRules() Rules { + return Rules{ "root": { {`#\[[\s\S]*?\]#`, CommentMultiline, nil}, {`##.*$`, LiteralStringDoc, nil}, @@ -89,5 +93,5 @@ var Nim = internal.Register(MustNewLexer( {`\'i(8|16)`, LiteralNumberInteger, nil}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/n/nix.go b/vendor/github.com/alecthomas/chroma/lexers/n/nix.go index 7e21dd7..874560a 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/n/nix.go +++ b/vendor/github.com/alecthomas/chroma/lexers/n/nix.go @@ -7,18 +7,22 @@ import ( "github.com/alecthomas/chroma/lexers/internal" ) -// nixb matches right boundary of a nix word. Use it instead of \b. -const nixb = `(?![a-zA-Z0-9_'-])` - // Nix lexer. -var Nix = internal.Register(MustNewLexer( +var Nix = internal.Register(MustNewLazyLexer( &Config{ Name: "Nix", Aliases: []string{"nixos", "nix"}, Filenames: []string{"*.nix"}, MimeTypes: []string{"text/x-nix"}, }, - Rules{ + nixRules, +)) + +func nixRules() Rules { + // nixb matches right boundary of a nix word. Use it instead of \b. + const nixb = `(?![a-zA-Z0-9_'-])` + + return Rules{ "root": { Include("keywords"), Include("builtins"), @@ -118,5 +122,5 @@ var Nix = internal.Register(MustNewLexer( "space": { {`[ \t\r\n]+`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/o/objectivec.go b/vendor/github.com/alecthomas/chroma/lexers/o/objectivec.go index e3d0b1c..0ae3029 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/o/objectivec.go +++ b/vendor/github.com/alecthomas/chroma/lexers/o/objectivec.go @@ -6,14 +6,18 @@ import ( ) // Objective-C lexer. -var ObjectiveC = internal.Register(MustNewLexer( +var ObjectiveC = internal.Register(MustNewLazyLexer( &Config{ Name: "Objective-C", Aliases: []string{"objective-c", "objectivec", "obj-c", "objc"}, Filenames: []string{"*.m", "*.h"}, MimeTypes: []string{"text/x-objective-c"}, }, - Rules{ + objectiveCRules, +)) + +func objectiveCRules() Rules { + return Rules{ "statements": { {`@"`, LiteralString, Push("string")}, {`@(YES|NO)`, LiteralNumber, nil}, @@ -161,5 +165,5 @@ var ObjectiveC = internal.Register(MustNewLexer( {`^\s*#endif.*?(?]*)(>)", ByGroups(Punctuation, CommentPreprocFile, Punctuation), nil}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/o/org.go b/vendor/github.com/alecthomas/chroma/lexers/o/org.go index 1064eaf..00f6df4 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/o/org.go +++ b/vendor/github.com/alecthomas/chroma/lexers/o/org.go @@ -6,14 +6,18 @@ import ( ) // Org mode lexer. -var Org = internal.Register(MustNewLexer( +var Org = internal.Register(MustNewLazyLexer( &Config{ Name: "Org Mode", Aliases: []string{"org", "orgmode"}, Filenames: []string{"*.org"}, MimeTypes: []string{"text/org"}, // https://lists.gnu.org/r/emacs-orgmode/2017-09/msg00087.html }, - Rules{ + orgRules, +)) + +func orgRules() Rules { + return Rules{ "root": { {`^# .*$`, Comment, nil}, // Headings @@ -45,7 +49,8 @@ var Org = internal.Register(MustNewLexer( // - Comment Blocks {`(?i)^( *#\+begin_comment *\n)([\w\W]*?)(^ *#\+end_comment *$)`, ByGroups(Comment, Comment, Comment), nil}, // - Src Blocks - {`(?i)^( *#\+begin_src )([^ \n]+)(.*?\n)([\w\W]*?)(^ *#\+end_src *$)`, + { + `(?i)^( *#\+begin_src )([^ \n]+)(.*?\n)([\w\W]*?)(^ *#\+end_src *$)`, UsingByGroup( internal.Get, 2, 4, @@ -54,7 +59,8 @@ var Org = internal.Register(MustNewLexer( nil, }, // - Export Blocks - {`(?i)^( *#\+begin_export )(\w+)( *\n)([\w\W]*?)(^ *#\+end_export *$)`, + { + `(?i)^( *#\+begin_export )(\w+)( *\n)([\w\W]*?)(^ *#\+end_export *$)`, UsingByGroup( internal.Get, 2, 4, @@ -98,5 +104,5 @@ var Org = internal.Register(MustNewLexer( // Any other text {`.`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/pacman.go b/vendor/github.com/alecthomas/chroma/lexers/p/pacman.go index 807b67c..00c6255 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/pacman.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/pacman.go @@ -6,14 +6,18 @@ import ( ) // Pacmanconf lexer. -var Pacmanconf = internal.Register(MustNewLexer( +var Pacmanconf = internal.Register(MustNewLazyLexer( &Config{ Name: "PacmanConf", Aliases: []string{"pacmanconf"}, Filenames: []string{"pacman.conf"}, MimeTypes: []string{}, }, - Rules{ + pacmanconfRules, +)) + +func pacmanconfRules() Rules { + return Rules{ "root": { {`#.*$`, CommentSingle, nil}, {`^\s*\[.*?\]\s*$`, Keyword, nil}, @@ -22,5 +26,5 @@ var Pacmanconf = internal.Register(MustNewLexer( {Words(``, `\b`, `$repo`, `$arch`, `%o`, `%u`), NameVariable, nil}, {`.`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/perl.go b/vendor/github.com/alecthomas/chroma/lexers/p/perl.go index 0a2b35b..6aa338a 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/perl.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/perl.go @@ -6,7 +6,7 @@ import ( ) // Perl lexer. -var Perl = internal.Register(MustNewLexer( +var Perl = internal.Register(MustNewLazyLexer( &Config{ Name: "Perl", Aliases: []string{"perl", "pl"}, @@ -14,7 +14,11 @@ var Perl = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-perl", "application/x-perl"}, DotAll: true, }, - Rules{ + perlRules, +)) + +func perlRules() Rules { + return Rules{ "balanced-regex": { {`/(\\\\|\\[^\\]|[^\\/])*/[egimosx]*`, LiteralStringRegex, Pop(1)}, {`!(\\\\|\\[^\\]|[^\\!])*![egimosx]*`, LiteralStringRegex, Pop(1)}, @@ -134,5 +138,5 @@ var Perl = internal.Register(MustNewLexer( "end-part": { {`.+`, CommentPreproc, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/pig.go b/vendor/github.com/alecthomas/chroma/lexers/p/pig.go index 0dbc591..f2852c1 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/pig.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/pig.go @@ -6,7 +6,7 @@ import ( ) // Pig lexer. -var Pig = internal.Register(MustNewLexer( +var Pig = internal.Register(MustNewLazyLexer( &Config{ Name: "Pig", Aliases: []string{"pig"}, @@ -14,7 +14,11 @@ var Pig = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-pig"}, CaseInsensitive: true, }, - Rules{ + pigRules, +)) + +func pigRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`--.*`, Comment, nil}, @@ -53,5 +57,5 @@ var Pig = internal.Register(MustNewLexer( {`(eq|gt|lt|gte|lte|neq|matches)\b`, Operator, nil}, {`(==|<=|<|>=|>|!=)`, Operator, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/pkgconfig.go b/vendor/github.com/alecthomas/chroma/lexers/p/pkgconfig.go index 0a4872e..9e02410 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/pkgconfig.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/pkgconfig.go @@ -6,14 +6,18 @@ import ( ) // Pkgconfig lexer. -var Pkgconfig = internal.Register(MustNewLexer( +var Pkgconfig = internal.Register(MustNewLazyLexer( &Config{ Name: "PkgConfig", Aliases: []string{"pkgconfig"}, Filenames: []string{"*.pc"}, MimeTypes: []string{}, }, - Rules{ + pkgconfigRules, +)) + +func pkgconfigRules() Rules { + return Rules{ "root": { {`#.*$`, CommentSingle, nil}, {`^(\w+)(=)`, ByGroups(NameAttribute, Operator), nil}, @@ -37,5 +41,5 @@ var Pkgconfig = internal.Register(MustNewLexer( {`[^${}#\n]+`, Text, nil}, {`.`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/plaintext.go b/vendor/github.com/alecthomas/chroma/lexers/p/plaintext.go index 7b25293..058c02a 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/plaintext.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/plaintext.go @@ -5,7 +5,7 @@ import ( "github.com/alecthomas/chroma/lexers/internal" ) -var Plaintext = internal.Register(MustNewLexer( +var Plaintext = internal.Register(MustNewLazyLexer( &Config{ Name: "plaintext", Aliases: []string{"text", "plain", "no-highlight"}, diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/plsql.go b/vendor/github.com/alecthomas/chroma/lexers/p/plsql.go index a6068fd..324d3fe 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/plsql.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/plsql.go @@ -6,7 +6,7 @@ import ( ) // Pl/Pgsql lexer. -var PLpgSQL = internal.Register(MustNewLexer( +var PLpgSQL = internal.Register(MustNewLazyLexer( &Config{ Name: "PL/pgSQL", Aliases: []string{"plpgsql"}, @@ -15,13 +15,17 @@ var PLpgSQL = internal.Register(MustNewLexer( NotMultiline: true, CaseInsensitive: true, }, - Rules{ + plpgSQLRules, +)) + +func plpgSQLRules() Rules { + return Rules{ "root": { {`\%[a-z]\w*\b`, NameBuiltin, nil}, {`:=`, Operator, nil}, {`\<\<[a-z]\w*\>\>`, NameLabel, nil}, {`\#[a-z]\w*\b`, KeywordPseudo, nil}, - {`\s+`, Text, nil}, + {`\s+`, TextWhitespace, nil}, {`--.*\n?`, CommentSingle, nil}, {`/\*`, CommentMultiline, Push("multiline-comments")}, {`(bigint|bigserial|bit|bit\s+varying|bool|boolean|box|bytea|char|character|character\s+varying|cidr|circle|date|decimal|double\s+precision|float4|float8|inet|int|int2|int4|int8|integer|interval|json|jsonb|line|lseg|macaddr|money|numeric|path|pg_lsn|point|polygon|real|serial|serial2|serial4|serial8|smallint|smallserial|text|time|timestamp|timestamptz|timetz|tsquery|tsvector|txid_snapshot|uuid|varbit|varchar|with\s+time\s+zone|without\s+time\s+zone|xml|anyarray|anyelement|anyenum|anynonarray|anyrange|cstring|fdw_handler|internal|language_handler|opaque|record|void)\b`, NameBuiltin, nil}, @@ -54,5 +58,5 @@ var PLpgSQL = internal.Register(MustNewLexer( {`""`, LiteralStringName, nil}, {`"`, LiteralStringName, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/pony.go b/vendor/github.com/alecthomas/chroma/lexers/p/pony.go index 9696b20..41d5682 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/pony.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/pony.go @@ -6,14 +6,18 @@ import ( ) // Pony lexer. -var Pony = internal.Register(MustNewLexer( +var Pony = internal.Register(MustNewLazyLexer( &Config{ Name: "Pony", Aliases: []string{"pony"}, Filenames: []string{"*.pony"}, MimeTypes: []string{}, }, - Rules{ + ponyRules, +)) + +func ponyRules() Rules { + return Rules{ "root": { {`\n`, Text, nil}, {`[^\S\n]+`, Text, nil}, @@ -55,5 +59,5 @@ var Pony = internal.Register(MustNewLexer( {`\\"`, LiteralString, nil}, {`[^\\"]+`, LiteralString, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/postgres.go b/vendor/github.com/alecthomas/chroma/lexers/p/postgres.go index 3afa54d..8977e2c 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/postgres.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/postgres.go @@ -6,7 +6,7 @@ import ( ) // Postgresql Sql Dialect lexer. -var PostgreSQL = internal.Register(MustNewLexer( +var PostgreSQL = internal.Register(MustNewLazyLexer( &Config{ Name: "PostgreSQL SQL dialect", Aliases: []string{"postgresql", "postgres"}, @@ -15,13 +15,18 @@ var PostgreSQL = internal.Register(MustNewLexer( NotMultiline: true, CaseInsensitive: true, }, - Rules{ + postgreSQLRules, +)) + +func postgreSQLRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`--.*\n?`, CommentSingle, nil}, {`/\*`, CommentMultiline, Push("multiline-comments")}, {`(bigint|bigserial|bit|bit\s+varying|bool|boolean|box|bytea|char|character|character\s+varying|cidr|circle|date|decimal|double\s+precision|float4|float8|inet|int|int2|int4|int8|integer|interval|json|jsonb|line|lseg|macaddr|money|numeric|path|pg_lsn|point|polygon|real|serial|serial2|serial4|serial8|smallint|smallserial|text|time|timestamp|timestamptz|timetz|tsquery|tsvector|txid_snapshot|uuid|varbit|varchar|with\s+time\s+zone|without\s+time\s+zone|xml|anyarray|anyelement|anyenum|anynonarray|anyrange|cstring|fdw_handler|internal|language_handler|opaque|record|void)\b`, NameBuiltin, nil}, - {`(?s)(DO)(\s+)(?:(LANGUAGE)?(\s+)('?)(\w+)?('?)(\s+))?(\$)([^$]*)(\$)(.*?)(\$)(\10)(\$)`, + { + `(?s)(DO)(\s+)(?:(LANGUAGE)?(\s+)('?)(\w+)?('?)(\s+))?(\$)([^$]*)(\$)(.*?)(\$)(\10)(\$)`, UsingByGroup( internal.Get, 6, 12, @@ -41,7 +46,8 @@ var PostgreSQL = internal.Register(MustNewLexer( {`[0-9]+`, LiteralNumberInteger, nil}, {`((?:E|U&)?)(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("string")}, {`((?:U&)?)(")`, ByGroups(LiteralStringAffix, LiteralStringName), Push("quoted-ident")}, - {`(?s)(\$)([^$]*)(\$)(.*?)(\$)(\2)(\$)(\s+)(LANGUAGE)?(\s+)('?)(\w+)?('?)`, + { + `(?s)(\$)([^$]*)(\$)(.*?)(\$)(\2)(\$)(\s+)(LANGUAGE)?(\s+)('?)(\w+)?('?)`, UsingByGroup(internal.Get, 12, 4, StringHeredoc, StringHeredoc, StringHeredoc, // $tag$ @@ -73,5 +79,5 @@ var PostgreSQL = internal.Register(MustNewLexer( {`""`, LiteralStringName, nil}, {`"`, LiteralStringName, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/postscript.go b/vendor/github.com/alecthomas/chroma/lexers/p/postscript.go index 0cfa3a5..0b51ba5 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/postscript.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/postscript.go @@ -6,14 +6,18 @@ import ( ) // Postscript lexer. -var Postscript = internal.Register(MustNewLexer( +var Postscript = internal.Register(MustNewLazyLexer( &Config{ Name: "PostScript", Aliases: []string{"postscript", "postscr"}, Filenames: []string{"*.ps", "*.eps"}, MimeTypes: []string{"application/postscript"}, }, - Rules{ + postscriptRules, +)) + +func postscriptRules() Rules { + return Rules{ "root": { {`^%!.+\n`, CommentPreproc, nil}, {`%%.*\n`, CommentSpecial, nil}, @@ -42,5 +46,5 @@ var Postscript = internal.Register(MustNewLexer( {`[0-8]{3}|n|r|t|b|f|\\|\(|\)`, LiteralStringEscape, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/povray.go b/vendor/github.com/alecthomas/chroma/lexers/p/povray.go index 6f1bb52..2d870f1 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/povray.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/povray.go @@ -6,14 +6,18 @@ import ( ) // Povray lexer. -var Povray = internal.Register(MustNewLexer( +var Povray = internal.Register(MustNewLazyLexer( &Config{ Name: "POVRay", Aliases: []string{"pov"}, Filenames: []string{"*.pov", "*.inc"}, MimeTypes: []string{"text/x-povray"}, }, - Rules{ + povrayRules, +)) + +func povrayRules() Rules { + return Rules{ "root": { {`/\*[\w\W]*?\*/`, CommentMultiline, nil}, {`//.*\n`, CommentSingle, nil}, @@ -31,5 +35,5 @@ var Povray = internal.Register(MustNewLexer( {`"(\\\\|\\"|[^"])*"`, LiteralString, nil}, {`\s+`, Text, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/powerquery.go b/vendor/github.com/alecthomas/chroma/lexers/p/powerquery.go new file mode 100644 index 0000000..0302420 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/p/powerquery.go @@ -0,0 +1,38 @@ +package p + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// PowerQuery lexer. +var PowerQuery = internal.Register(MustNewLazyLexer( + &Config{ + Name: "PowerQuery", + Aliases: []string{"powerquery", "pq"}, + Filenames: []string{"*.pq"}, + MimeTypes: []string{"text/x-powerquery"}, + DotAll: true, + CaseInsensitive: true, + }, + powerqueryRules, +)) + +func powerqueryRules() Rules { + return Rules{ + "root": { + {`\s+`, Text, nil}, + {`//.*?\n`, CommentSingle, nil}, + {`/\*.*?\*/`, CommentMultiline, nil}, + {`"(\\\\|\\"|[^"])*"`, LiteralString, nil}, + {`(and|as|each|else|error|false|if|in|is|let|meta|not|null|or|otherwise|section|shared|then|true|try|type)\b`, Keyword, nil}, + {`(#binary|#date|#datetime|#datetimezone|#duration|#infinity|#nan|#sections|#shared|#table|#time)\b`, KeywordType, nil}, + {`(([a-zA-Z]|_)[\w|._]*|#"[^"]+")`, Name, nil}, + {`0[xX][0-9a-fA-F][0-9a-fA-F_]*[lL]?`, LiteralNumberHex, nil}, + {`([0-9]+\.[0-9]+|\.[0-9]+)([eE][0-9]+)?`, LiteralNumberFloat, nil}, + {`[0-9]+`, LiteralNumberInteger, nil}, + {`[\(\)\[\]\{\}]`, Punctuation, nil}, + {`\.\.|\.\.\.|=>|<=|>=|<>|[@!?,;=<>\+\-\*\/&]`, Operator, nil}, + }, + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/powershell.go b/vendor/github.com/alecthomas/chroma/lexers/p/powershell.go index 10eba4f..9b7b56e 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/powershell.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/powershell.go @@ -6,16 +6,20 @@ import ( ) // Powershell lexer. -var Powershell = internal.Register(MustNewLexer( +var Powershell = internal.Register(MustNewLazyLexer( &Config{ Name: "PowerShell", - Aliases: []string{"powershell", "posh", "ps1", "psm1"}, - Filenames: []string{"*.ps1", "*.psm1"}, + Aliases: []string{"powershell", "posh", "ps1", "psm1", "psd1"}, + Filenames: []string{"*.ps1", "*.psm1", "*.psd1"}, MimeTypes: []string{"text/x-powershell"}, DotAll: true, CaseInsensitive: true, }, - Rules{ + powershellRules, +)) + +func powershellRules() Rules { + return Rules{ "root": { {`\(`, Punctuation, Push("child")}, {`\s+`, Text, nil}, @@ -29,9 +33,9 @@ var Powershell = internal.Register(MustNewLexer( {`"`, LiteralStringDouble, Push("string")}, {`'([^']|'')*'`, LiteralStringSingle, nil}, {`(\$|@@|@)((global|script|private|env):)?\w+`, NameVariable, nil}, + {`[a-z]\w*-[a-z]\w*\b`, NameBuiltin, nil}, {`(while|validateset|validaterange|validatepattern|validatelength|validatecount|until|trap|switch|return|ref|process|param|parameter|in|if|global:|function|foreach|for|finally|filter|end|elseif|else|dynamicparam|do|default|continue|cmdletbinding|break|begin|alias|\?|%|#script|#private|#local|#global|mandatory|parametersetname|position|valuefrompipeline|valuefrompipelinebypropertyname|valuefromremainingarguments|helpmessage|try|catch|throw)\b`, Keyword, nil}, {`-(and|as|band|bnot|bor|bxor|casesensitive|ccontains|ceq|cge|cgt|cle|clike|clt|cmatch|cne|cnotcontains|cnotlike|cnotmatch|contains|creplace|eq|exact|f|file|ge|gt|icontains|ieq|ige|igt|ile|ilike|ilt|imatch|ine|inotcontains|inotlike|inotmatch|ireplace|is|isnot|le|like|lt|match|ne|not|notcontains|notlike|notmatch|or|regex|replace|wildcard)\b`, Operator, nil}, - {`(write|where|watch|wait|use|update|unregister|unpublish|unprotect|unlock|uninstall|undo|unblock|trace|test|tee|take|sync|switch|suspend|submit|stop|step|start|split|sort|skip|show|set|send|select|search|scroll|save|revoke|resume|restore|restart|resolve|resize|reset|request|repair|rename|remove|register|redo|receive|read|push|publish|protect|pop|ping|out|optimize|open|new|move|mount|merge|measure|lock|limit|join|invoke|install|initialize|import|hide|group|grant|get|format|foreach|find|export|expand|exit|enter|enable|edit|dismount|disconnect|disable|deny|debug|cxnew|copy|convertto|convertfrom|convert|connect|confirm|compress|complete|compare|close|clear|checkpoint|block|backup|assert|approve|aggregate|add)-[a-z_]\w*\b`, NameBuiltin, nil}, {`(ac|asnp|cat|cd|cfs|chdir|clc|clear|clhy|cli|clp|cls|clv|cnsn|compare|copy|cp|cpi|cpp|curl|cvpa|dbp|del|diff|dir|dnsn|ebp|echo|epal|epcsv|epsn|erase|etsn|exsn|fc|fhx|fl|foreach|ft|fw|gal|gbp|gc|gci|gcm|gcs|gdr|ghy|gi|gjb|gl|gm|gmo|gp|gps|gpv|group|gsn|gsnp|gsv|gu|gv|gwmi|h|history|icm|iex|ihy|ii|ipal|ipcsv|ipmo|ipsn|irm|ise|iwmi|iwr|kill|lp|ls|man|md|measure|mi|mount|move|mp|mv|nal|ndr|ni|nmo|npssc|nsn|nv|ogv|oh|popd|ps|pushd|pwd|r|rbp|rcjb|rcsn|rd|rdr|ren|ri|rjb|rm|rmdir|rmo|rni|rnp|rp|rsn|rsnp|rujb|rv|rvpa|rwmi|sajb|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spjb|spps|spsv|start|sujb|sv|swmi|tee|trcm|type|wget|where|wjb|write)\s`, NameBuiltin, nil}, {"\\[[a-z_\\[][\\w. `,\\[\\]]*\\]", NameConstant, nil}, {`-[a-z_]\w*`, Name, nil}, @@ -62,5 +66,5 @@ var Powershell = internal.Register(MustNewLexer( {`[^@\n]+"]`, LiteralStringHeredoc, nil}, {`.`, LiteralStringHeredoc, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/prolog.go b/vendor/github.com/alecthomas/chroma/lexers/p/prolog.go index 08b4812..a2f346b 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/prolog.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/prolog.go @@ -6,14 +6,18 @@ import ( ) // Prolog lexer. -var Prolog = internal.Register(MustNewLexer( +var Prolog = internal.Register(MustNewLazyLexer( &Config{ Name: "Prolog", Aliases: []string{"prolog"}, Filenames: []string{"*.ecl", "*.prolog", "*.pro", "*.pl"}, MimeTypes: []string{"text/x-prolog"}, }, - Rules{ + prologRules, +)) + +func prologRules() Rules { + return Rules{ "root": { {`/\*`, CommentMultiline, Push("nested-comment")}, {`%.*`, CommentSingle, nil}, @@ -46,5 +50,5 @@ var Prolog = internal.Register(MustNewLexer( {`[^*/]+`, CommentMultiline, nil}, {`[*/]`, CommentMultiline, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/promql.go b/vendor/github.com/alecthomas/chroma/lexers/p/promql.go new file mode 100644 index 0000000..e80b926 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/p/promql.go @@ -0,0 +1,59 @@ +package p + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// Promql lexer. +var Promql = internal.Register(MustNewLazyLexer( + &Config{ + Name: "PromQL", + Aliases: []string{"promql"}, + Filenames: []string{"*.promql"}, + MimeTypes: []string{}, + }, + promqlRules, +)) + +func promqlRules() Rules { + return Rules{ + "root": { + {`\n`, TextWhitespace, nil}, + {`\s+`, TextWhitespace, nil}, + {`,`, Punctuation, nil}, + {Words(``, `\b`, `bool`, `by`, `group_left`, `group_right`, `ignoring`, `offset`, `on`, `without`), Keyword, nil}, + {Words(``, `\b`, `sum`, `min`, `max`, `avg`, `group`, `stddev`, `stdvar`, `count`, `count_values`, `bottomk`, `topk`, `quantile`), Keyword, nil}, + {Words(``, `\b`, `abs`, `absent`, `absent_over_time`, `avg_over_time`, `ceil`, `changes`, `clamp_max`, `clamp_min`, `count_over_time`, `day_of_month`, `day_of_week`, `days_in_month`, `delta`, `deriv`, `exp`, `floor`, `histogram_quantile`, `holt_winters`, `hour`, `idelta`, `increase`, `irate`, `label_join`, `label_replace`, `ln`, `log10`, `log2`, `max_over_time`, `min_over_time`, `minute`, `month`, `predict_linear`, `quantile_over_time`, `rate`, `resets`, `round`, `scalar`, `sort`, `sort_desc`, `sqrt`, `stddev_over_time`, `stdvar_over_time`, `sum_over_time`, `time`, `timestamp`, `vector`, `year`), KeywordReserved, nil}, + {`[1-9][0-9]*[smhdwy]`, LiteralString, nil}, + {`-?[0-9]+\.[0-9]+`, LiteralNumberFloat, nil}, + {`-?[0-9]+`, LiteralNumberInteger, nil}, + {`#.*?$`, CommentSingle, nil}, + {`(\+|\-|\*|\/|\%|\^)`, Operator, nil}, + {`==|!=|>=|<=|<|>`, Operator, nil}, + {`and|or|unless`, OperatorWord, nil}, + {`[_a-zA-Z][a-zA-Z0-9_]+`, NameVariable, nil}, + {`(["\'])(.*?)(["\'])`, ByGroups(Punctuation, LiteralString, Punctuation), nil}, + {`\(`, Operator, Push("function")}, + {`\)`, Operator, nil}, + {`\{`, Punctuation, Push("labels")}, + {`\[`, Punctuation, Push("range")}, + }, + "labels": { + {`\}`, Punctuation, Pop(1)}, + {`\n`, TextWhitespace, nil}, + {`\s+`, TextWhitespace, nil}, + {`,`, Punctuation, nil}, + {`([_a-zA-Z][a-zA-Z0-9_]*?)(\s*?)(=~|!=|=|!~)(\s*?)("|')(.*?)("|')`, ByGroups(NameLabel, TextWhitespace, Operator, TextWhitespace, Punctuation, LiteralString, Punctuation), nil}, + }, + "range": { + {`\]`, Punctuation, Pop(1)}, + {`[1-9][0-9]*[smhdwy]`, LiteralString, nil}, + }, + "function": { + {`\)`, Operator, Pop(1)}, + {`\(`, Operator, Push()}, + Default(Pop(1)), + }, + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/protobuf.go b/vendor/github.com/alecthomas/chroma/lexers/p/protobuf.go index 3014013..76576cb 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/protobuf.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/protobuf.go @@ -6,14 +6,18 @@ import ( ) // ProtocolBuffer lexer. -var ProtocolBuffer = internal.Register(MustNewLexer( +var ProtocolBuffer = internal.Register(MustNewLazyLexer( &Config{ Name: "Protocol Buffer", Aliases: []string{"protobuf", "proto"}, Filenames: []string{"*.proto"}, MimeTypes: []string{}, }, - Rules{ + protocolBufferRules, +)) + +func protocolBufferRules() Rules { + return Rules{ "root": { {`[ \t]+`, Text, nil}, {`[,;{}\[\]()<>]`, Punctuation, nil}, @@ -49,5 +53,5 @@ var ProtocolBuffer = internal.Register(MustNewLexer( {`[a-zA-Z_]\w*`, Name, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/puppet.go b/vendor/github.com/alecthomas/chroma/lexers/p/puppet.go index a1db0d2..b32caed 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/puppet.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/puppet.go @@ -6,14 +6,18 @@ import ( ) // Puppet lexer. -var Puppet = internal.Register(MustNewLexer( +var Puppet = internal.Register(MustNewLazyLexer( &Config{ Name: "Puppet", Aliases: []string{"puppet"}, Filenames: []string{"*.pp"}, MimeTypes: []string{}, }, - Rules{ + puppetRules, +)) + +func puppetRules() Rules { + return Rules{ "root": { Include("comments"), Include("keywords"), @@ -52,5 +56,5 @@ var Puppet = internal.Register(MustNewLexer( {`"([^"])*"`, LiteralString, nil}, {`'(\\'|[^'])*'`, LiteralString, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/python.go b/vendor/github.com/alecthomas/chroma/lexers/p/python.go index 77f2c8d..b432a42 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/p/python.go +++ b/vendor/github.com/alecthomas/chroma/lexers/p/python.go @@ -6,112 +6,176 @@ import ( ) // Python lexer. -var Python = internal.Register(MustNewLexer( +var Python = internal.Register(MustNewLazyLexer( &Config{ Name: "Python", - Aliases: []string{"python", "py", "sage"}, - Filenames: []string{"*.py", "*.pyw", "*.sc", "SConstruct", "SConscript", "*.tac", "*.sage"}, - MimeTypes: []string{"text/x-python", "application/x-python"}, + Aliases: []string{"python", "py", "sage", "python3", "py3"}, + Filenames: []string{"*.py", "*.pyi", "*.pyw", "*.jy", "*.sage", "*.sc", "SConstruct", "SConscript", "*.bzl", "BUCK", "BUILD", "BUILD.bazel", "WORKSPACE", "*.tac"}, + MimeTypes: []string{"text/x-python", "application/x-python", "text/x-python3", "application/x-python3"}, }, - Rules{ + pythonRules, +)) + +func pythonRules() Rules { + const pythonIdentifier = `[A-Z_a-zªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶ-ͷͻ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙՠ-ֈא-תׯ-ײؠ-يٮ-ٯٱ-ۓەۥ-ۦۮ-ۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴ-ߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࡠ-ࡪࢠ-ࢴࢶ-ࢽऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রলশ-হঽৎড়-ঢ়য়-ৡৰ-ৱৼਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽૐૠ-ૡૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽଡ଼-ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கங-சஜஞ-டண-தந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘ-ౚౠ-ౡಀಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽൎൔ-ൖൟ-ൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาเ-ๆກ-ຂຄງ-ຈຊຍດ-ທນ-ຟມ-ຣລວສ-ຫອ-ະາຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥ-ၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡸᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᲀ-ᲈᲐ-ᲺᲽ-Ჿᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕ℘-ℝℤΩℨK-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〇〡-〩〱-〵〸-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄯㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿯ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞹꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꣽ-ꣾꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵ-ꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﮱﯓ-ﱝﱤ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷹﹱﹳﹷﹹﹻﹽﹿ-ﻼA-Za-zヲ-ンᅠ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐅀-𐅴𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌭-𐍊𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐏑-𐏕𐐀-𐒝𐒰-𐓓𐓘-𐓻𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈𐠊-𐠵𐠷-𐠸𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨵𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𐴀-𐴣𐼀-𐼜𐼧𐼰-𐽅𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅄𑅐-𑅲𑅶𑆃-𑆲𑇁-𑇄𑇚𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽𑍐𑍝-𑍡𑐀-𑐴𑑇-𑑊𑒀-𑒯𑓄-𑓅𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄𑚀-𑚪𑜀-𑜚𑠀-𑠫𑢠-𑣟𑣿𑨀𑨋-𑨲𑨺𑩐𑩜-𑪃𑪆-𑪉𑪝𑫀-𑫸𑰀-𑰈𑰊-𑰮𑱀𑱲-𑲏𑴀-𑴆𑴈-𑴉𑴋-𑴰𑵆𑵠-𑵥𑵧-𑵨𑵪-𑶉𑶘𑻠-𑻲𒀀-𒎙𒐀-𒑮𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖹀-𖹿𖼀-𖽄𖽐𖾓-𖾟𖿠-𖿡𗀀-𘟱𘠀-𘫲𛀀-𛄞𛅰-𛋻𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞤀-𞥃𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤𞸧𞸩-𞸲𞸴-𞸷𞸹𞸻𞹂𞹇𞹉𞹋𞹍-𞹏𞹑-𞹒𞹔𞹗𞹙𞹛𞹝𞹟𞹡-𞹢𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡𬺰-𮯠丽-𪘀][0-9A-Z_a-zªµ·ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮ̀-ʹͶ-ͷͻ-ͽͿΆ-ΊΌΎ-ΡΣ-ϵϷ-ҁ҃-҇Ҋ-ԯԱ-Ֆՙՠ-ֈ֑-ֽֿׁ-ׂׄ-ׇׅא-תׯ-ײؐ-ؚؠ-٩ٮ-ۓە-ۜ۟-۪ۨ-ۼۿܐ-݊ݍ-ޱ߀-ߵߺ߽ࠀ-࠭ࡀ-࡛ࡠ-ࡪࢠ-ࢴࢶ-ࢽ࣓-ࣣ࣡-ॣ०-९ॱ-ঃঅ-ঌএ-ঐও-নপ-রলশ-হ়-ৄে-ৈো-ৎৗড়-ঢ়য়-ৣ০-ৱৼ৾ਁ-ਃਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹ਼ਾ-ੂੇ-ੈੋ-੍ੑਖ਼-ੜਫ਼੦-ੵઁ-ઃઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હ઼-ૅે-ૉો-્ૐૠ-ૣ૦-૯ૹ-૿ଁ-ଃଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହ଼-ୄେ-ୈୋ-୍ୖ-ୗଡ଼-ଢ଼ୟ-ୣ୦-୯ୱஂ-ஃஅ-ஊஎ-ஐஒ-கங-சஜஞ-டண-தந-பம-ஹா-ூெ-ைொ-்ௐௗ௦-௯ఀ-ఌఎ-ఐఒ-నప-హఽ-ౄె-ైొ-్ౕ-ౖౘ-ౚౠ-ౣ౦-౯ಀ-ಃಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹ಼-ೄೆ-ೈೊ-್ೕ-ೖೞೠ-ೣ೦-೯ೱ-ೲഀ-ഃഅ-ഌഎ-ഐഒ-ൄെ-ൈൊ-ൎൔ-ൗൟ-ൣ൦-൯ൺ-ൿං-ඃඅ-ඖක-නඳ-රලව-ෆ්ා-ුූෘ-ෟ෦-෯ෲ-ෳก-ฺเ-๎๐-๙ກ-ຂຄງ-ຈຊຍດ-ທນ-ຟມ-ຣລວສ-ຫອ-ູົ-ຽເ-ໄໆ່-ໍ໐-໙ໜ-ໟༀ༘-༙༠-༩༹༵༷༾-ཇཉ-ཬཱ-྄྆-ྗྙ-ྼ࿆က-၉ၐ-ႝႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚ፝-፟፩-፱ᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-᜔ᜠ-᜴ᝀ-ᝓᝠ-ᝬᝮ-ᝰᝲ-ᝳក-៓ៗៜ-៝០-៩᠋-᠍᠐-᠙ᠠ-ᡸᢀ-ᢪᢰ-ᣵᤀ-ᤞᤠ-ᤫᤰ-᤻᥆-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉ᧐-᧚ᨀ-ᨛᨠ-ᩞ᩠-᩿᩼-᪉᪐-᪙ᪧ᪰-᪽ᬀ-ᭋ᭐-᭙᭫-᭳ᮀ-᯳ᰀ-᰷᱀-᱉ᱍ-ᱽᲀ-ᲈᲐ-ᲺᲽ-Ჿ᳐-᳔᳒-᳹ᴀ-᷹᷻-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼ‿-⁀⁔ⁱⁿₐ-ₜ⃐-⃥⃜⃡-⃰ℂℇℊ-ℓℕ℘-ℝℤΩℨK-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯ⵿-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⷠ-ⷿ々-〇〡-〯〱-〵〸-〼ぁ-ゖ゙-゚ゝ-ゟァ-ヺー-ヿㄅ-ㄯㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿯ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘫꙀ-꙯ꙴ-꙽ꙿ-꛱ꜗ-ꜟꜢ-ꞈꞋ-ꞹꟷ-ꠧꡀ-ꡳꢀ-ꣅ꣐-꣙꣠-ꣷꣻꣽ-꤭ꤰ-꥓ꥠ-ꥼꦀ-꧀ꧏ-꧙ꧠ-ꧾꨀ-ꨶꩀ-ꩍ꩐-꩙ꩠ-ꩶꩺ-ꫂꫛ-ꫝꫠ-ꫯꫲ-꫶ꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯪ꯬-꯭꯰-꯹가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-ﬨשׁ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﮱﯓ-ﱝﱤ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷹ︀-️︠-︯︳-︴﹍-﹏ﹱﹳﹷﹹﹻﹽﹿ-ﻼ0-9A-Z_a-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐅀-𐅴𐇽𐊀-𐊜𐊠-𐋐𐋠𐌀-𐌟𐌭-𐍊𐍐-𐍺𐎀-𐎝𐎠-𐏃𐏈-𐏏𐏑-𐏕𐐀-𐒝𐒠-𐒩𐒰-𐓓𐓘-𐓻𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈𐠊-𐠵𐠷-𐠸𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨃𐨅-𐨆𐨌-𐨓𐨕-𐨗𐨙-𐨵𐨸-𐨿𐨺𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫦𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𐴀-𐴧𐴰-𐴹𐼀-𐼜𐼧𐼰-𐽐𑀀-𑁆𑁦-𑁯𑁿-𑂺𑃐-𑃨𑃰-𑃹𑄀-𑄴𑄶-𑄿𑅄-𑅆𑅐-𑅳𑅶𑆀-𑇄𑇉-𑇌𑇐-𑇚𑇜𑈀-𑈑𑈓-𑈷𑈾𑊀-𑊆𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋪𑋰-𑋹𑌀-𑌃𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌻-𑍄𑍇-𑍈𑍋-𑍍𑍐𑍗𑍝-𑍣𑍦-𑍬𑍰-𑍴𑐀-𑑊𑑐-𑑙𑑞𑒀-𑓅𑓇𑓐-𑓙𑖀-𑖵𑖸-𑗀𑗘-𑗝𑘀-𑙀𑙄𑙐-𑙙𑚀-𑚷𑛀-𑛉𑜀-𑜚𑜝-𑜫𑜰-𑜹𑠀-𑠺𑢠-𑣩𑣿𑨀-𑨾𑩇𑩐-𑪃𑪆-𑪙𑪝𑫀-𑫸𑰀-𑰈𑰊-𑰶𑰸-𑱀𑱐-𑱙𑱲-𑲏𑲒-𑲧𑲩-𑲶𑴀-𑴆𑴈-𑴉𑴋-𑴶𑴺𑴼-𑴽𑴿-𑵇𑵐-𑵙𑵠-𑵥𑵧-𑵨𑵪-𑶎𑶐-𑶑𑶓-𑶘𑶠-𑶩𑻠-𑻶𒀀-𒎙𒐀-𒑮𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖩠-𖩩𖫐-𖫭𖫰-𖫴𖬀-𖬶𖭀-𖭃𖭐-𖭙𖭣-𖭷𖭽-𖮏𖹀-𖹿𖼀-𖽄𖽐-𖽾𖾏-𖾟𖿠-𖿡𗀀-𘟱𘠀-𘫲𛀀-𛄞𛅰-𛋻𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𛲝-𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𝟎-𝟿𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣-𞀤𞀦-𞀪𞠀-𞣄𞣐-𞣖𞤀-𞥊𞥐-𞥙𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤𞸧𞸩-𞸲𞸴-𞸷𞸹𞸻𞹂𞹇𞹉𞹋𞹍-𞹏𞹑-𞹒𞹔𞹗𞹙𞹛𞹝𞹟𞹡-𞹢𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡𬺰-𮯠丽-𪘀󠄀-󠇯]*` + + return Rules{ "root": { {`\n`, Text, nil}, {`^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")`, ByGroups(Text, LiteralStringAffix, LiteralStringDoc), nil}, {`^(\s*)([rRuUbB]{,2})('''(?:.|\n)*?''')`, ByGroups(Text, LiteralStringAffix, LiteralStringDoc), nil}, - {`[^\S\n]+`, Text, nil}, {`\A#!.+$`, CommentHashbang, nil}, {`#.*$`, CommentSingle, nil}, - {`[]{}:(),;[]`, Punctuation, nil}, {`\\\n`, Text, nil}, {`\\`, Text, nil}, - {`(in|is|and|or|not)\b`, OperatorWord, nil}, - {`!=|==|<<|>>|[-~+/*%=<>&^|.]`, Operator, nil}, Include("keywords"), {`(def)((?:\s|\\\s)+)`, ByGroups(Keyword, Text), Push("funcname")}, {`(class)((?:\s|\\\s)+)`, ByGroups(Keyword, Text), Push("classname")}, {`(from)((?:\s|\\\s)+)`, ByGroups(KeywordNamespace, Text), Push("fromimport")}, {`(import)((?:\s|\\\s)+)`, ByGroups(KeywordNamespace, Text), Push("import")}, - Include("builtins"), - Include("magicfuncs"), - Include("magicvars"), - Include("backtick"), - {`([rR]|[uUbB][rR]|[rR][uUbB])(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("tdqs")}, - {`([rR]|[uUbB][rR]|[rR][uUbB])(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("tsqs")}, - {`([rR]|[uUbB][rR]|[rR][uUbB])(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("dqs")}, - {`([rR]|[uUbB][rR]|[rR][uUbB])(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("sqs")}, + Include("expr"), + }, + "expr": { + {`(?i)(rf|fr)(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("rfstringescape", "tdqf")}, + {`(?i)(rf|fr)(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("rfstringescape", "tsqf")}, + {`(?i)(rf|fr)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("rfstringescape", "dqf")}, + {`(?i)(rf|fr)(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("rfstringescape", "sqf")}, + {`([fF])(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("fstringescape", "tdqf")}, + {`([fF])(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("fstringescape", "tsqf")}, + {`([fF])(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("fstringescape", "dqf")}, + {`([fF])(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("fstringescape", "sqf")}, + {`(?i)(rb|br|r)(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("tdqs")}, + {`(?i)(rb|br|r)(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("tsqs")}, + {`(?i)(rb|br|r)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("dqs")}, + {`(?i)(rb|br|r)(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("sqs")}, {`([uUbB]?)(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("stringescape", "tdqs")}, {`([uUbB]?)(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("stringescape", "tsqs")}, {`([uUbB]?)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("stringescape", "dqs")}, {`([uUbB]?)(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("stringescape", "sqs")}, - Include("name"), + {`[^\S\n]+`, Text, nil}, Include("numbers"), + {`!=|==|<<|>>|:=|[-~+/*%=<>&^|.]`, Operator, nil}, + {`[]{}:(),;[]`, Punctuation, nil}, + {`(in|is|and|or|not)\b`, OperatorWord, nil}, + Include("expr-keywords"), + Include("builtins"), + Include("magicfuncs"), + Include("magicvars"), + Include("name"), + }, + "expr-inside-fstring": { + {`[{([]`, Punctuation, Push("expr-inside-fstring-inner")}, + {`(=\s*)?(\![sraf])?\}`, LiteralStringInterpol, Pop(1)}, + {`(=\s*)?(\![sraf])?:`, LiteralStringInterpol, Pop(1)}, + {`\s+`, Text, nil}, + Include("expr"), + }, + "expr-inside-fstring-inner": { + {`[{([]`, Punctuation, Push("expr-inside-fstring-inner")}, + {`[])}]`, Punctuation, Pop(1)}, + {`\s+`, Text, nil}, + Include("expr"), + }, + "expr-keywords": { + {Words(``, `\b`, `async for`, `await`, `else`, `for`, `if`, `lambda`, `yield`, `yield from`), Keyword, nil}, + {Words(``, `\b`, `True`, `False`, `None`), KeywordConstant, nil}, }, "keywords": { - {Words(``, `\b`, `assert`, `break`, `continue`, `del`, `elif`, `else`, `except`, `exec`, `finally`, `for`, `global`, `if`, `lambda`, `pass`, `print`, `raise`, `return`, `try`, `while`, `yield`, `yield from`, `as`, `with`), Keyword, nil}, + {Words(``, `\b`, `assert`, `async`, `await`, `break`, `continue`, `del`, `elif`, `else`, `except`, `finally`, `for`, `global`, `if`, `lambda`, `pass`, `raise`, `nonlocal`, `return`, `try`, `while`, `yield`, `yield from`, `as`, `with`), Keyword, nil}, + {Words(``, `\b`, `True`, `False`, `None`), KeywordConstant, nil}, }, "builtins": { - {Words(`(?=\^])?[-+ ]?#?0?(\d+)?,?(\.\d+)?[E-GXb-gnosx%]?)?\}`, LiteralStringInterpol, nil}, + {`[^\\\'"%{\n]+`, LiteralStringSingle, nil}, + {`[\'"\\]`, LiteralStringSingle, nil}, + {`%|(\{{1,2})`, LiteralStringSingle, nil}, }, "strings-double": { - {`%(\(\w+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?[hlL]?[E-GXc-giorsux%]`, LiteralStringInterpol, nil}, - {`[^\\\'"%\n]+`, LiteralStringDouble, nil}, + {`%(\(\w+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?[hlL]?[E-GXc-giorsaux%]`, LiteralStringInterpol, nil}, + {`\{((\w+)((\.\w+)|(\[[^\]]+\]))*)?(\![sra])?(\:(.?[<>=\^])?[-+ ]?#?0?(\d+)?,?(\.\d+)?[E-GXb-gnosx%]?)?\}`, LiteralStringInterpol, nil}, + {`[^\\\'"%{\n]+`, LiteralStringDouble, nil}, {`[\'"\\]`, LiteralStringDouble, nil}, - {`%`, LiteralStringDouble, nil}, + {`%|(\{{1,2})`, LiteralStringDouble, nil}, + }, + "dqf": { + {`"`, LiteralStringDouble, Pop(1)}, + {`\\\\|\\"|\\\n`, LiteralStringEscape, nil}, + Include("fstrings-double"), + }, + "sqf": { + {`'`, LiteralStringSingle, Pop(1)}, + {`\\\\|\\'|\\\n`, LiteralStringEscape, nil}, + Include("fstrings-single"), }, "dqs": { {`"`, LiteralStringDouble, Pop(1)}, @@ -123,6 +187,16 @@ var Python = internal.Register(MustNewLexer( {`\\\\|\\'|\\\n`, LiteralStringEscape, nil}, Include("strings-single"), }, + "tdqf": { + {`"""`, LiteralStringDouble, Pop(1)}, + Include("fstrings-double"), + {`\n`, LiteralStringDouble, nil}, + }, + "tsqf": { + {`'''`, LiteralStringSingle, Pop(1)}, + Include("fstrings-single"), + {`\n`, LiteralStringSingle, nil}, + }, "tdqs": { {`"""`, LiteralStringDouble, Pop(1)}, Include("strings-double"), @@ -133,5 +207,5 @@ var Python = internal.Register(MustNewLexer( Include("strings-single"), {`\n`, LiteralStringSingle, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/p/python2.go b/vendor/github.com/alecthomas/chroma/lexers/p/python2.go new file mode 100644 index 0000000..f1f6036 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/p/python2.go @@ -0,0 +1,141 @@ +package p + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// Python2 lexer. +var Python2 = internal.Register(MustNewLazyLexer( + &Config{ + Name: "Python 2", + Aliases: []string{"python2", "py2"}, + Filenames: []string{}, + MimeTypes: []string{"text/x-python2", "application/x-python2"}, + }, + python2Rules, +)) + +func python2Rules() Rules { + return Rules{ + "root": { + {`\n`, Text, nil}, + {`^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")`, ByGroups(Text, LiteralStringAffix, LiteralStringDoc), nil}, + {`^(\s*)([rRuUbB]{,2})('''(?:.|\n)*?''')`, ByGroups(Text, LiteralStringAffix, LiteralStringDoc), nil}, + {`[^\S\n]+`, Text, nil}, + {`\A#!.+$`, CommentHashbang, nil}, + {`#.*$`, CommentSingle, nil}, + {`[]{}:(),;[]`, Punctuation, nil}, + {`\\\n`, Text, nil}, + {`\\`, Text, nil}, + {`(in|is|and|or|not)\b`, OperatorWord, nil}, + {`!=|==|<<|>>|[-~+/*%=<>&^|.]`, Operator, nil}, + Include("keywords"), + {`(def)((?:\s|\\\s)+)`, ByGroups(Keyword, Text), Push("funcname")}, + {`(class)((?:\s|\\\s)+)`, ByGroups(Keyword, Text), Push("classname")}, + {`(from)((?:\s|\\\s)+)`, ByGroups(KeywordNamespace, Text), Push("fromimport")}, + {`(import)((?:\s|\\\s)+)`, ByGroups(KeywordNamespace, Text), Push("import")}, + Include("builtins"), + Include("magicfuncs"), + Include("magicvars"), + Include("backtick"), + {`([rR]|[uUbB][rR]|[rR][uUbB])(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("tdqs")}, + {`([rR]|[uUbB][rR]|[rR][uUbB])(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("tsqs")}, + {`([rR]|[uUbB][rR]|[rR][uUbB])(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("dqs")}, + {`([rR]|[uUbB][rR]|[rR][uUbB])(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("sqs")}, + {`([uUbB]?)(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("stringescape", "tdqs")}, + {`([uUbB]?)(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("stringescape", "tsqs")}, + {`([uUbB]?)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("stringescape", "dqs")}, + {`([uUbB]?)(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("stringescape", "sqs")}, + Include("name"), + Include("numbers"), + }, + "keywords": { + {Words(``, `\b`, `assert`, `break`, `continue`, `del`, `elif`, `else`, `except`, `exec`, `finally`, `for`, `global`, `if`, `lambda`, `pass`, `print`, `raise`, `return`, `try`, `while`, `yield`, `yield from`, `as`, `with`), Keyword, nil}, + }, + "builtins": { + {Words(`(?>|[-~+/*%=<>&^|.]`, Operator, nil}, - Include("keywords"), - {`(def)((?:\s|\\\s)+)`, ByGroups(Keyword, Text), Push("funcname")}, - {`(class)((?:\s|\\\s)+)`, ByGroups(Keyword, Text), Push("classname")}, - {`(from)((?:\s|\\\s)+)`, ByGroups(KeywordNamespace, Text), Push("fromimport")}, - {`(import)((?:\s|\\\s)+)`, ByGroups(KeywordNamespace, Text), Push("import")}, - Include("builtins"), - Include("magicfuncs"), - Include("magicvars"), - Include("backtick"), - {`([rR]|[uUbB][rR]|[rR][uUbB])(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("tdqs")}, - {`([rR]|[uUbB][rR]|[rR][uUbB])(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("tsqs")}, - {`([rR]|[uUbB][rR]|[rR][uUbB])(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("dqs")}, - {`([rR]|[uUbB][rR]|[rR][uUbB])(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Push("sqs")}, - {`([uUbB]?)(""")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("stringescape", "tdqs")}, - {`([uUbB]?)(''')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("stringescape", "tsqs")}, - {`([uUbB]?)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Combined("stringescape", "dqs")}, - {`([uUbB]?)(')`, ByGroups(LiteralStringAffix, LiteralStringSingle), Combined("stringescape", "sqs")}, - Include("name"), - Include("numbers"), - }, - "keywords": { - {Words(``, `\b`, `assert`, `async`, `await`, `break`, `continue`, `del`, `elif`, `else`, `except`, `finally`, `for`, `global`, `if`, `lambda`, `pass`, `raise`, `nonlocal`, `return`, `try`, `while`, `yield`, `yield from`, `as`, `with`), Keyword, nil}, - {Words(``, `\b`, `True`, `False`, `None`), KeywordConstant, nil}, - }, - "builtins": { - {Words(`(?=\^])?[-+ ]?#?0?(\d+)?,?(\.\d+)?[E-GXb-gnosx%]?)?\}`, LiteralStringInterpol, nil}, - {`[^\\\'"%{\n]+`, LiteralStringSingle, nil}, - {`[\'"\\]`, LiteralStringSingle, nil}, - {`%|(\{{1,2})`, LiteralStringSingle, nil}, - }, - "strings-double": { - {`%(\(\w+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?[hlL]?[E-GXc-giorsux%]`, LiteralStringInterpol, nil}, - {`\{((\w+)((\.\w+)|(\[[^\]]+\]))*)?(\![sra])?(\:(.?[<>=\^])?[-+ ]?#?0?(\d+)?,?(\.\d+)?[E-GXb-gnosx%]?)?\}`, LiteralStringInterpol, nil}, - {`[^\\\'"%{\n]+`, LiteralStringDouble, nil}, - {`[\'"\\]`, LiteralStringDouble, nil}, - {`%|(\{{1,2})`, LiteralStringDouble, nil}, - }, - "dqs": { - {`"`, LiteralStringDouble, Pop(1)}, - {`\\\\|\\"|\\\n`, LiteralStringEscape, nil}, - Include("strings-double"), - }, - "sqs": { - {`'`, LiteralStringSingle, Pop(1)}, - {`\\\\|\\'|\\\n`, LiteralStringEscape, nil}, - Include("strings-single"), - }, - "tdqs": { - {`"""`, LiteralStringDouble, Pop(1)}, - Include("strings-double"), - {`\n`, LiteralStringDouble, nil}, - }, - "tsqs": { - {`'''`, LiteralStringSingle, Pop(1)}, - Include("strings-single"), - {`\n`, LiteralStringSingle, nil}, - }, - }, -)) diff --git a/vendor/github.com/alecthomas/chroma/lexers/q/qbasic.go b/vendor/github.com/alecthomas/chroma/lexers/q/qbasic.go index fd47c08..1e36f86 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/q/qbasic.go +++ b/vendor/github.com/alecthomas/chroma/lexers/q/qbasic.go @@ -6,14 +6,18 @@ import ( ) // Qbasic lexer. -var Qbasic = internal.Register(MustNewLexer( +var Qbasic = internal.Register(MustNewLazyLexer( &Config{ Name: "QBasic", Aliases: []string{"qbasic", "basic"}, Filenames: []string{"*.BAS", "*.bas"}, MimeTypes: []string{"text/basic"}, }, - Rules{ + qbasicRules, +)) + +func qbasicRules() Rules { + return Rules{ "root": { {`\n+`, Text, nil}, {`\s+`, TextWhitespace, nil}, @@ -63,5 +67,5 @@ var Qbasic = internal.Register(MustNewLexer( "keywords": { {`\b(ACCESS|ALIAS|ANY|APPEND|AS|BASE|BINARY|BYVAL|CASE|CDECL|DOUBLE|ELSE|ELSEIF|ENDIF|INTEGER|IS|LIST|LOCAL|LONG|LOOP|MOD|NEXT|OFF|ON|OUTPUT|RANDOM|SIGNAL|SINGLE|STEP|STRING|THEN|TO|UNTIL|USING|WEND)\b`, Keyword, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/q/qml.go b/vendor/github.com/alecthomas/chroma/lexers/q/qml.go new file mode 100644 index 0000000..dfd3c75 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/q/qml.go @@ -0,0 +1,58 @@ +package q + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// Qml lexer. +var Qml = internal.Register(MustNewLazyLexer( + &Config{ + Name: "QML", + Aliases: []string{"qml", "qbs"}, + Filenames: []string{"*.qml", "*.qbs"}, + MimeTypes: []string{"application/x-qml", "application/x-qt.qbs+qml"}, + DotAll: true, + }, + qmlRules, +)) + +func qmlRules() Rules { + return Rules{ + "commentsandwhitespace": { + {`\s+`, Text, nil}, + {``, `role`, `state`, `sub`, `no`, + `submethod`, `subset`, `succeed`, `supersede`, `try`, `unit`, `unless`, `until`, + `use`, `when`, `while`, `with`, `without`, `export`, `native`, `repr`, `required`, `rw`, + `symbol`, `default`, `cached`, `DEPRECATED`, `dynamic`, `hidden-from-backtrace`, `nodal`, + `pure`, `raw`, `start`, `react`, `supply`, `whenever`, `also`, `rule`, `token`, `regex`, + `dynamic-scope`, `built`, `temp`, + } + + keywordsPattern := Words(`(?)`, `(>=)`, `minmax`, `notandthen`, `S`, + } + + wordOperatorsPattern := Words(`(?<=^|\b|\s)`, `(?=$|\b|\s)`, wordOperators...) + + operators := []string{ + `++`, `--`, `-`, `**`, `!`, `+`, `~`, `?`, `+^`, `~^`, `?^`, `^`, `*`, `/`, `%`, `%%`, `+&`, + `+<`, `+>`, `~&`, `~<`, `~>`, `?&`, `+|`, `+^`, `~|`, `~^`, `?`, `?|`, `?^`, `&`, `^`, + `<=>`, `^…^`, `^…`, `…^`, `…`, `...`, `...^`, `^...`, `^...^`, `..`, `..^`, `^..`, `^..^`, + `::=`, `:=`, `!=`, `==`, `<=`, `<`, `>=`, `>`, `~~`, `===`, `&&`, `||`, `|`, `^^`, `//`, + `??`, `!!`, `^fff^`, `^ff^`, `<==`, `==>`, `<<==`, `==>>`, `=>`, `=`, `<<`, `«`, `>>`, `»`, + `,`, `>>.`, `».`, `.&`, `.=`, `.^`, `.?`, `.+`, `.*`, `.`, `∘`, `∩`, `⊍`, `∪`, `⊎`, `∖`, + `⊖`, `≠`, `≤`, `≥`, `=:=`, `=~=`, `≅`, `∈`, `∉`, `≡`, `≢`, `∋`, `∌`, `⊂`, `⊄`, `⊆`, `⊈`, + `⊃`, `⊅`, `⊇`, `⊉`, `:`, `!!!`, `???`, `¯`, `×`, `÷`, `−`, `⁺`, `⁻`, + } + + operatorsPattern := Words(``, ``, operators...) + + builtinTypes := []string{ + `False`, `True`, `Order`, `More`, `Less`, `Same`, `Any`, `Array`, `Associative`, `AST`, + `atomicint`, `Attribute`, `Backtrace`, `Backtrace::Frame`, `Bag`, `Baggy`, `BagHash`, + `Blob`, `Block`, `Bool`, `Buf`, `Callable`, `CallFrame`, `Cancellation`, `Capture`, + `CArray`, `Channel`, `Code`, `compiler`, `Complex`, `ComplexStr`, `CompUnit`, + `CompUnit::PrecompilationRepository`, `CompUnit::Repository`, `Empty`, + `CompUnit::Repository::FileSystem`, `CompUnit::Repository::Installation`, `Cool`, + `CurrentThreadScheduler`, `CX::Warn`, `CX::Take`, `CX::Succeed`, `CX::Return`, `CX::Redo`, + `CX::Proceed`, `CX::Next`, `CX::Last`, `CX::Emit`, `CX::Done`, `Cursor`, `Date`, `Dateish`, + `DateTime`, `Distribution`, `Distribution::Hash`, `Distribution::Locally`, + `Distribution::Path`, `Distribution::Resource`, `Distro`, `Duration`, `Encoding`, + `Encoding::Registry`, `Endian`, `Enumeration`, `Exception`, `Failure`, `FatRat`, `Grammar`, + `Hash`, `HyperWhatever`, `Instant`, `Int`, `int`, `int16`, `int32`, `int64`, `int8`, `str`, + `IntStr`, `IO`, `IO::ArgFiles`, `IO::CatHandle`, `IO::Handle`, `IO::Notification`, + `IO::Notification::Change`, `IO::Path`, `IO::Path::Cygwin`, `IO::Path::Parts`, + `IO::Path::QNX`, `IO::Path::Unix`, `IO::Path::Win32`, `IO::Pipe`, `IO::Socket`, + `IO::Socket::Async`, `IO::Socket::Async::ListenSocket`, `IO::Socket::INET`, `IO::Spec`, + `IO::Spec::Cygwin`, `IO::Spec::QNX`, `IO::Spec::Unix`, `IO::Spec::Win32`, `IO::Special`, + `Iterable`, `Iterator`, `Junction`, `Kernel`, `Label`, `List`, `Lock`, `Lock::Async`, + `Lock::ConditionVariable`, `long`, `longlong`, `Macro`, `Map`, `Match`, + `Metamodel::AttributeContainer`, `Metamodel::C3MRO`, `Metamodel::ClassHOW`, + `Metamodel::ConcreteRoleHOW`, `Metamodel::CurriedRoleHOW`, `Metamodel::DefiniteHOW`, + `Metamodel::Documenting`, `Metamodel::EnumHOW`, `Metamodel::Finalization`, + `Metamodel::MethodContainer`, `Metamodel::Mixins`, `Metamodel::MROBasedMethodDispatch`, + `Metamodel::MultipleInheritance`, `Metamodel::Naming`, `Metamodel::Primitives`, + `Metamodel::PrivateMethodContainer`, `Metamodel::RoleContainer`, `Metamodel::RolePunning`, + `Metamodel::Stashing`, `Metamodel::Trusting`, `Metamodel::Versioning`, `Method`, `Mix`, + `MixHash`, `Mixy`, `Mu`, `NFC`, `NFD`, `NFKC`, `NFKD`, `Nil`, `Num`, `num32`, `num64`, + `Numeric`, `NumStr`, `ObjAt`, `Order`, `Pair`, `Parameter`, `Perl`, `Pod::Block`, + `Pod::Block::Code`, `Pod::Block::Comment`, `Pod::Block::Declarator`, `Pod::Block::Named`, + `Pod::Block::Para`, `Pod::Block::Table`, `Pod::Heading`, `Pod::Item`, `Pointer`, + `Positional`, `PositionalBindFailover`, `Proc`, `Proc::Async`, `Promise`, `Proxy`, + `PseudoStash`, `QuantHash`, `RaceSeq`, `Raku`, `Range`, `Rat`, `Rational`, `RatStr`, + `Real`, `Regex`, `Routine`, `Routine::WrapHandle`, `Scalar`, `Scheduler`, `Semaphore`, + `Seq`, `Sequence`, `Set`, `SetHash`, `Setty`, `Signature`, `size_t`, `Slip`, `Stash`, + `Str`, `StrDistance`, `Stringy`, `Sub`, `Submethod`, `Supplier`, `Supplier::Preserving`, + `Supply`, `Systemic`, `Tap`, `Telemetry`, `Telemetry::Instrument::Thread`, + `Telemetry::Instrument::ThreadPool`, `Telemetry::Instrument::Usage`, `Telemetry::Period`, + `Telemetry::Sampler`, `Thread`, `Test`, `ThreadPoolScheduler`, `UInt`, `uint16`, `uint32`, + `uint64`, `uint8`, `Uni`, `utf8`, `ValueObjAt`, `Variable`, `Version`, `VM`, `Whatever`, + `WhateverCode`, `WrapHandle`, `NativeCall`, + // Pragmas + `precompilation`, `experimental`, `worries`, `MONKEY-TYPING`, `MONKEY-SEE-NO-EVAL`, + `MONKEY-GUTS`, `fatal`, `lib`, `isms`, `newline`, `nqp`, `soft`, + `strict`, `trace`, `variables`, + } + + builtinTypesPattern := Words(`(? 0 { + nextOpenPos := indexAt(text, openingChars, searchPos+nChars) + nextClosePos = indexAt(text, closingChars, searchPos+nChars) + + switch { + case nextClosePos == -1: + nextClosePos = len(text) + nestingLevel = 0 + case nextOpenPos != -1 && nextOpenPos < nextClosePos: + nestingLevel++ + nChars = len(openingChars) + searchPos = nextOpenPos + default: // next_close_pos < next_open_pos + nestingLevel-- + nChars = len(closingChars) + searchPos = nextClosePos + } + } + + endPos = nextClosePos + } + + if endPos < 0 { + // if we didn't find a closer, just highlight the + // rest of the text in this class + endPos = len(text) + } + + adverbre := regexp.MustCompile(`:to\b|:heredoc\b`) + var heredocTerminator []rune + if adverbre.MatchString(string(adverbs)) { + heredocTerminator = text[state.Pos:endPos] + if len(heredocTerminator) > 0 { + endHeredocPos := indexAt(text[endPos:], heredocTerminator, 0) + nChars = len(heredocTerminator) + endPos += endHeredocPos + } else { + endPos = len(text) + } + } + + textBetweenBrackets := string(text[state.Pos:endPos]) + switch tokenClass { + case rakuPod, rakuPodDeclaration, rakuNameAttribute: + state.NamedGroups[`value`] = textBetweenBrackets + state.NamedGroups[`closing_delimiters`] = string(closingChars) + case rakuQuote: + if len(heredocTerminator) > 0 { + // Length of heredoc terminator + closing chars + `;` + heredocFristPunctuationLen := len(heredocTerminator) + len(openingChars) + 1 + + state.NamedGroups[`opening_delimiters`] = string(openingChars) + + string(text[state.Pos:state.Pos+heredocFristPunctuationLen]) + + state.NamedGroups[`value`] = + string(text[state.Pos+heredocFristPunctuationLen : endPos]) + + state.NamedGroups[`closing_delimiters`] = string(heredocTerminator) + } else { + state.NamedGroups[`value`] = textBetweenBrackets + state.NamedGroups[`closing_delimiters`] = string(closingChars) + } + default: + state.Groups = []string{state.Groups[0] + string(text[state.Pos:endPos+nChars])} + } + + state.Pos = endPos + nChars + + return nil + } + } + + // Raku rules + // Empty capture groups are placeholders and will be replaced by bracketsFinder. + // DO NOT REMOVE THEM! + return Rules{ + "root": { + Include("common"), + {`[{}();]`, Punctuation, nil}, + {`\[|\]`, Operator, nil}, + {`.+?`, Text, nil}, + }, + "common": { + {`^#![^\n]*$`, CommentHashbang, nil}, + Include("pod"), + // Multi-line, Embedded comment + { + "#`(?(?" + bracketsPattern + `)\k*)`, + CommentMultiline, + bracketsFinder(rakuMultilineComment), + }, + {`#[^\n]*$`, CommentSingle, nil}, + // /regex/ + { + `(?<=(?:^|\(|=|:|~~|\[|,|=>)\s*)(/)(?!\]|\))((?:\\\\|\\/|.)*?)((?>)(\S+?)(<<)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, + {`(»)(\S+?)(«)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, + // Hyperoperator | «*« + {`(<<)(\S+?)(<<)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, + {`(«)(\S+?)(«)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, + // Hyperoperator | »*» + {`(>>)(\S+?)(>>)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, + {`(»)(\S+?)(»)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, + // <> + {`(?>)[^\n])+?[},;] *\n)(?!(?:(?!>>).)+?>>\S+?>>)`, Punctuation, Push("<<")}, + // «quoted words» + {`(? operators | something < onething > something + { + `(?<=[$@%&]?\w[\w':-]* +)(<=?)( *[^ ]+? *)(>=?)(?= *[$@%&]?\w[\w':-]*)`, + ByGroups(Operator, UsingSelf("root"), Operator), + nil, + }, + // + { + `(?])+?)(>)(?!\s*(?:\d+|\.(?:Int|Numeric)|[$@%]\w[\w':-]*[^(]|\s+\[))`, + ByGroups(Punctuation, String, Punctuation), + nil, + }, + {`C?X::['\w:-]+`, NameException, nil}, + Include("metaoperator"), + // Pair | (key) => value + { + `(\([^)]+\))(\s*)(=>)(\s*)([^,\n]+)(,?\n*)`, + ByGroups(UsingSelf("root"), Text, Operator, Text, UsingSelf("root"), Text), + nil, + }, + // Pair | key => value + { + `(\w[\w'-]*)(\s*)(=>)(\s*)([^,\n]+)(,?\n*)`, + ByGroups(String, Text, Operator, Text, UsingSelf("root"), Text), + nil, + }, + Include("colon-pair"), + // Token + { + // Token with adverbs + `(?<=(?:^|\s)(?:regex|token|rule)(\s+))(['\w:-]+)(?=:['\w-]+` + + colonPairOpeningBrackets + `.+?` + colonPairClosingBrackets + `[({])`, + NameFunction, + Push("token", "name-adverb"), + }, + { + // Token without adverbs + `(?<=(?:^|\s)(?:regex|token|rule)(?:\s+))(['\w:-]+)`, + NameFunction, + Push("token"), + }, + // Substitution + {`(?<=^|\b|\s)(?(?:qq|q|Q))(?(?::?(?:heredoc|to|qq|ww|q|w|s|a|h|f|c|b|to|v|x))*)(?\s*)(?(?[^0-9a-zA-Z:\s])\k*)`, + EmitterFunc(quote), + bracketsFinder(rakuQuote), + }, + // Function + { + `\b(?:\w['\w:-]*)(?=:['\w-]+` + + colonPairOpeningBrackets + `.+?` + colonPairClosingBrackets + `\()`, + NameFunction, + Push("name-adverb"), + }, + {`\b(?:\w['\w:-]*)(?=\()`, NameFunction, nil}, + // Method + // Method with adverb + { + `(?(?[^\w:\s])\k*)`, + ByGroupNames(map[string]Emitter{ + `opening_delimiters`: Punctuation, + `delimiter`: nil, + }), + Mutators(Pop(1), bracketsFinder(rakuMatchRegex)), + }, + }, + "substitution": { + Include("colon-pair-attribute"), + // Substitution | s{regex} = value + { + `(?(?` + bracketsPattern + `)\k*)`, + ByGroupNames(map[string]Emitter{ + `opening_delimiters`: Punctuation, + `delimiter`: nil, + }), + Mutators(Pop(1), bracketsFinder(rakuSubstitutionSingleRegex)), + }, + // Substitution | s/regex/string/ + { + `([^\w:\s])((?:\\\\|\\/|.)*?)(\1)((?:\\\\|\\/|.)*?)(\1)`, + ByGroups( + Punctuation, UsingSelf("regex"), Punctuation, UsingSelf("qq"), Punctuation, + ), + Mutators(Pop(1), MutatorFunc(makeRegexPoppingRule)), + }, + }, + "number": { + {`0_?[0-7]+(_[0-7]+)*`, LiteralNumberOct, nil}, + {`0x[0-9A-Fa-f]+(_[0-9A-Fa-f]+)*`, LiteralNumberHex, nil}, + {`0b[01]+(_[01]+)*`, LiteralNumberBin, nil}, + { + `(?i)(\d*(_\d*)*\.\d+(_\d*)*|\d+(_\d*)*\.\d+(_\d*)*)(e[+-]?\d+)?`, + LiteralNumberFloat, + nil, + }, + {`(?i)\d+(_\d*)*e[+-]?\d+(_\d*)*`, LiteralNumberFloat, nil}, + {`(?<=\d+)i`, NameConstant, nil}, + {`\d+(_\d+)*`, LiteralNumberInteger, nil}, + }, + "name-adverb": { + Include("colon-pair-attribute-keyvalue"), + Default(Pop(1)), + }, + "colon-pair": { + // :key(value) + {colonPairPattern, colonPair(String), bracketsFinder(rakuNameAttribute)}, + // :123abc + { + `(:)(\d+)(\w[\w'-]*)(\s*[,;)]?\s*$)`, + ByGroups(Punctuation, UsingSelf("number"), String, Text), + nil, + }, + // :key + {`(:!?)(\w[\w'-]*)`, ByGroups(Punctuation, String), nil}, + {`\s+`, Text, nil}, + }, + "colon-pair-attribute": { + // :key(value) + {colonPairPattern, colonPair(NameAttribute), bracketsFinder(rakuNameAttribute)}, + // :123abc + { + `(:)(\d+)(\w+)(\s*[,;)]?\s*$)`, + ByGroups(Punctuation, UsingSelf("number"), NameAttribute, Text), + nil, + }, + // :key + {`(:!?)(\w[\w'-]*)`, ByGroups(Punctuation, NameAttribute), nil}, + {`\s+`, Text, nil}, + }, + "colon-pair-attribute-keyvalue": { + // :key(value) + {colonPairPattern, colonPair(NameAttribute), bracketsFinder(rakuNameAttribute)}, + }, + "escape-qq": { + { + `(? + { + `(?)`, + ByGroups(Punctuation, Operator, Punctuation, UsingSelf("root"), Punctuation), + nil, + }, + // {code} + {`(?>|»|\+|\*\*|\*|\?|=|~|<~~>`, Operator, nil}, + // Anchors + {`\^\^|\^|\$\$|\$`, NameEntity, nil}, + {`\.`, NameEntity, nil}, + {`#[^\n]*\n`, CommentSingle, nil}, + // Lookaround + { + `(?)`, + ByGroups(Punctuation, Operator, OperatorWord, Punctuation), + nil, + }, + // <$variable> + { + `(?)`, + ByGroups(Punctuation, NameVariable, Punctuation), + nil, + }, + // Capture markers + {`(?`, Operator, nil}, + {`(?)`, Punctuation, Pop(1)}, + {`(?`, Punctuation, Pop(1)}, + Include("regex-class-builtin"), + Include("variable"), + // | | + { + `(?:(\w[\w-:]*)(=\.?))?(&?\w[\w'-:]+?)(\(.+?\))?(?=>)`, + ByGroups( + NameVariable, Operator, NameFunction, UsingSelf("root"), + ), + nil, + }, + // + { + `(&?\w[\w':-]*?)(:)((?:.*?(?:\$<\w[\w':-]*>)?.*?)*?)(?=>)`, + ByGroups( + NameFunction, Punctuation, UsingSelf("root"), + ), + nil, + }, + Include("colon-pair-attribute"), + {`(?] + { + `\b([RZX]+)\b(\[)([^\s\]]+?)(\])`, + ByGroups(OperatorWord, Punctuation, UsingSelf("root"), Punctuation), + nil, + }, + // Z=> + {`\b([RZX]+)\b([^\s\]]+)`, ByGroups(OperatorWord, UsingSelf("operator")), nil}, + }, + "operator": { + // Word Operator + {wordOperatorsPattern, OperatorWord, nil}, + // Operator + {operatorsPattern, Operator, nil}, + }, + "pod": { + // Single-line pod declaration + {`(#[|=])\s`, Keyword, Push("pod-single")}, + // Multi-line pod declaration + { + "(?#[|=])(?(?" + bracketsPattern + `)\k*)(?)(?)`, + ByGroupNames( + map[string]Emitter{ + `keyword`: Keyword, + `opening_delimiters`: Punctuation, + `delimiter`: nil, + `value`: UsingSelf("pod-begin"), + `closing_delimiters`: Punctuation, + }), + bracketsFinder(rakuPodDeclaration), + }, + Include("pod-blocks"), + }, + "pod-blocks": { + // =begin code + { + `(?<=^ *)(? *)(?=begin)(? +)(?code)(?[^\n]*)(?.*?)(?^\k)(?=end)(? +)\k`, + EmitterFunc(podCode), + nil, + }, + // =begin + { + `(?<=^ *)(? *)(?=begin)(? +)(?!code)(?\w[\w'-]*)(?[^\n]*)(?)(?)`, + ByGroupNames( + map[string]Emitter{ + `ws`: Comment, + `keyword`: Keyword, + `ws2`: StringDoc, + `name`: Keyword, + `config`: EmitterFunc(podConfig), + `value`: UsingSelf("pod-begin"), + `closing_delimiters`: Keyword, + }), + bracketsFinder(rakuPod), + }, + // =for ... + { + `(?<=^ *)(? *)(?=(?:for|defn))(? +)(?\w[\w'-]*)(?[^\n]*\n)`, + ByGroups(Comment, Keyword, StringDoc, Keyword, EmitterFunc(podConfig)), + Push("pod-paragraph"), + }, + // =config + { + `(?<=^ *)(? *)(?=config)(? +)(?\w[\w'-]*)(?[^\n]*\n)`, + ByGroups(Comment, Keyword, StringDoc, Keyword, EmitterFunc(podConfig)), + nil, + }, + // =alias + { + `(?<=^ *)(? *)(?=alias)(? +)(?\w[\w'-]*)(?[^\n]*\n)`, + ByGroups(Comment, Keyword, StringDoc, Keyword, StringDoc), + nil, + }, + // =encoding + { + `(?<=^ *)(? *)(?=encoding)(? +)(?[^\n]+)`, + ByGroups(Comment, Keyword, StringDoc, Name), + nil, + }, + // =para ... + { + `(?<=^ *)(? *)(?=(?:para|table|pod))(?(? *)(?=head\d+)(? *)(?#?)`, + ByGroups(Comment, Keyword, GenericHeading, Keyword), + Push("pod-single-heading"), + }, + // =item ... + { + `(?<=^ *)(? *)(?=(?:item\d*|comment|data|[A-Z]+))(? *)(?#?)`, + ByGroups(Comment, Keyword, StringDoc, Keyword), + Push("pod-single"), + }, + { + `(?<=^ *)(? *)(?=finish)(?[^\n]*)`, + ByGroups(Comment, Keyword, EmitterFunc(podConfig)), + Push("pod-finish"), + }, + // ={custom} ... + { + `(?<=^ *)(? *)(?=\w[\w'-]*)(? *)(?#?)`, + ByGroups(Comment, Name, StringDoc, Keyword), + Push("pod-single"), + }, + // = podconfig + { + `(?<=^ *)(? *=)(? *)(?(?::\w[\w'-]*(?:` + colonPairOpeningBrackets + `.+?` + + colonPairClosingBrackets + `) *)*\n)`, + ByGroups(Keyword, StringDoc, EmitterFunc(podConfig)), + nil, + }, + }, + "pod-begin": { + Include("pod-blocks"), + Include("pre-pod-formatter"), + {`.+?`, StringDoc, nil}, + }, + "pod-paragraph": { + {`\n\s*?\n`, StringDoc, Pop(1)}, + Include("pre-pod-formatter"), + {`.+?`, StringDoc, nil}, + }, + "pod-single": { + {`\n`, StringDoc, Pop(1)}, + Include("pre-pod-formatter"), + {`.+?`, StringDoc, nil}, + }, + "pod-single-heading": { + {`\n`, GenericHeading, Pop(1)}, + Include("pre-pod-formatter"), + {`.+?`, GenericHeading, nil}, + }, + "pod-finish": { + {`\z`, nil, Pop(1)}, + Include("pre-pod-formatter"), + {`.+?`, StringDoc, nil}, + }, + "pre-pod-formatter": { + // C, B, ... + { + `(?[CBIUDTKRPAELZVMSXN])(?<+|«)`, + ByGroups(Keyword, Punctuation), + Mutators( + bracketsFinder(rakuPodFormatter), + Push("pod-formatter"), MutatorFunc(podFormatter), + ), + }, + }, + "pod-formatter": { + // Placeholder rule, will be replaced by podFormatter. DO NOT REMOVE! + {`>`, Punctuation, Pop(1)}, + Include("pre-pod-formatter"), + // Placeholder rule, will be replaced by podFormatter. DO NOT REMOVE! + {`.+?`, StringOther, nil}, + }, + "variable": { + {variablePattern, NameVariable, Push("name-adverb")}, + {globalVariablePattern, NameVariableGlobal, Push("name-adverb")}, + {`[$@](?:<.*?>)+`, NameVariable, nil}, + {`\$/`, NameVariable, nil}, + {`\$!`, NameVariable, nil}, + {`[$@%]`, NameVariable, nil}, + }, + "single-quote": { + {`(?>(?!\s*(?:\d+|\.(?:Int|Numeric)|[$@%][\w':-]+|\s+\[))`, Punctuation, Pop(1)}, + Include("ww"), + }, + "«": { + {`»(?!\s*(?:\d+|\.(?:Int|Numeric)|[$@%][\w':-]+|\s+\[))`, Punctuation, Pop(1)}, + Include("ww"), + }, + "ww": { + Include("single-quote"), + Include("qq"), + }, + "qq": { + Include("qq-variable"), + // Function with adverb + { + `\w[\w:'-]+(?=:['\w-]+` + + colonPairOpeningBrackets + `.+?` + colonPairClosingBrackets + `\()`, + NameFunction, + Push("qq-function", "name-adverb"), + }, + // Function without adverb + {`\w[\w:'-]+(?=\((?!"))`, NameFunction, Push("qq-function")}, + Include("closure"), + Include("escape-hexadecimal"), + Include("escape-c-name"), + Include("escape-qq"), + {`.+?`, StringDouble, nil}, + }, + "qq-function": { + {`(\([^"]*?\))`, UsingSelf("root"), nil}, + Default(Pop(1)), + }, + "qq-variable": { + { + `(?>|<.*?>|«.*?»)+`, UsingSelf("root"), nil}, + // Method + { + `(\.)([^(\s]+)(\([^"]*?\))`, + ByGroups(Operator, NameFunction, UsingSelf("root")), + nil, + }, + Default(Pop(1)), + }, + "Q": { + Include("escape-qq"), + {`.+?`, String, nil}, + }, + "Q-closure": { + Include("escape-qq"), + Include("closure"), + {`.+?`, String, nil}, + }, + "Q-variable": { + Include("escape-qq"), + Include("qq-variable"), + {`.+?`, String, nil}, + }, + "closure": { + {`(? -1 { + idx = utf8.RuneCountInString(text[:idx]) + idx += pos + } + + return idx +} + +// Tells if an array of string contains a string +func contains(s []string, e string) bool { + for _, value := range s { + if value == e { + return true + } + } + return false +} + +type RakuFormatterRules struct { + pop, formatter *CompiledRule +} + +// Pop from the pod_formatter_stack and reformat the pod code +func podFormatterPopper(state *LexerState) error { + stack, ok := state.Get("pod_formatter_stack").([]RakuFormatterRules) + + if ok && len(stack) > 0 { + // Pop from stack + stack = stack[:len(stack)-1] + state.Set("pod_formatter_stack", stack) + // Call podFormatter to use the last formatter rules + err := podFormatter(state) + if err != nil { + panic(err) + } + } + + return nil +} + +// Use the rules from pod_formatter_stack to format the pod code +func podFormatter(state *LexerState) error { + stack, ok := state.Get("pod_formatter_stack").([]RakuFormatterRules) + if ok && len(stack) > 0 { + rules := stack[len(stack)-1] + state.Rules["pod-formatter"][0] = rules.pop + state.Rules["pod-formatter"][len(state.Rules["pod-formatter"])-1] = rules.formatter + } + + return nil +} + +type RulePosition int + +const ( + topRule RulePosition = iota + 1000 + bottomRule +) + +type RuleMakingConfig struct { + delimiter []rune + pattern string + tokenType TokenType + mutator Mutator + rulePosition RulePosition + state *LexerState + stateName string + pushToStack bool + numberOfDelimiterChars int +} + +// Makes compiled rules and returns them, If rule position is given, rules are added to the state +// If pushToStack is true, state name will be added to the state stack +func makeRuleAndPushMaybe(config RuleMakingConfig) *CompiledRule { + var rePattern string + if len(config.delimiter) > 0 { + delimiter := strings.Repeat(string(config.delimiter), config.numberOfDelimiterChars) + rePattern = regexp2.Escape(delimiter) + } else { + rePattern = config.pattern + } + regex := regexp2.MustCompile(rePattern, regexp2.None) + + cRule := &CompiledRule{ + Rule: Rule{rePattern, config.tokenType, config.mutator}, + Regexp: regex, + } + state := config.state + stateName := config.stateName + switch config.rulePosition { + case topRule: + state.Rules[stateName] = + append([]*CompiledRule{cRule}, state.Rules[stateName][1:]...) + case bottomRule: + state.Rules[stateName] = + append(state.Rules[stateName][:len(state.Rules[stateName])-1], cRule) + } + + // Push state name to stack if asked + if config.pushToStack { + state.Stack = append(state.Stack, config.stateName) + } + + return cRule +} + +// Used when the regex knows its own delimiter and uses `UsingSelf("regex")`, +// it only puts a placeholder rule at the top of "regex" state +func makeRegexPoppingRule(state *LexerState) error { + makeRuleAndPushMaybe(RuleMakingConfig{ + pattern: `^$`, + rulePosition: topRule, + state: state, + stateName: "regex", + }) + + return nil +} + +// Emitter for colon pairs, changes token state based on key and brackets +func colonPair(tokenClass TokenType) Emitter { + return EmitterFunc(func(groups []string, state *LexerState) Iterator { + iterators := []Iterator{} + tokens := []Token{ + {Punctuation, state.NamedGroups[`colon`]}, + {Punctuation, state.NamedGroups[`opening_delimiters`]}, + {Punctuation, state.NamedGroups[`closing_delimiters`]}, + } + + // Append colon + iterators = append(iterators, Literator(tokens[0])) + + if tokenClass == NameAttribute { + iterators = append(iterators, Literator(Token{NameAttribute, state.NamedGroups[`key`]})) + } else { + var keyTokenState string + keyre := regexp.MustCompile(`^\d+$`) + if keyre.MatchString(state.NamedGroups[`key`]) { + keyTokenState = "common" + } else { + keyTokenState = "Q" + } + + // Use token state to Tokenise key + if keyTokenState != "" { + iterator, err := state.Lexer.Tokenise( + &TokeniseOptions{ + State: keyTokenState, + Nested: true, + }, state.NamedGroups[`key`]) + + if err != nil { + panic(err) + } else { + // Append key + iterators = append(iterators, iterator) + } + } + } + + // Append punctuation + iterators = append(iterators, Literator(tokens[1])) + + var valueTokenState string + + switch state.NamedGroups[`opening_delimiters`] { + case "(", "{", "[": + valueTokenState = "root" + case "<<", "«": + valueTokenState = "ww" + case "<": + valueTokenState = "Q" + } + + // Use token state to Tokenise value + if valueTokenState != "" { + iterator, err := state.Lexer.Tokenise( + &TokeniseOptions{ + State: valueTokenState, + Nested: true, + }, state.NamedGroups[`value`]) + + if err != nil { + panic(err) + } else { + // Append value + iterators = append(iterators, iterator) + } + } + // Append last punctuation + iterators = append(iterators, Literator(tokens[2])) + + return Concaterator(iterators...) + }) +} + +// Emitter for quoting constructs, changes token state based on quote name and adverbs +func quote(groups []string, state *LexerState) Iterator { + keyword := state.NamedGroups[`keyword`] + adverbsStr := state.NamedGroups[`adverbs`] + iterators := []Iterator{} + tokens := []Token{ + {Keyword, keyword}, + {StringAffix, adverbsStr}, + {Text, state.NamedGroups[`ws`]}, + {Punctuation, state.NamedGroups[`opening_delimiters`]}, + {Punctuation, state.NamedGroups[`closing_delimiters`]}, + } + + // Append all tokens before dealing with the main string + iterators = append(iterators, Literator(tokens[:4]...)) + + var tokenStates []string + + // Set tokenStates based on adverbs + adverbs := strings.Split(adverbsStr, ":") + for _, adverb := range adverbs { + switch adverb { + case "c", "closure": + tokenStates = append(tokenStates, "Q-closure") + case "qq": + tokenStates = append(tokenStates, "qq") + case "ww": + tokenStates = append(tokenStates, "ww") + case "s", "scalar", "a", "array", "h", "hash", "f", "function": + tokenStates = append(tokenStates, "Q-variable") + } + } + + var tokenState string + + switch { + case keyword == "qq" || contains(tokenStates, "qq"): + tokenState = "qq" + case adverbsStr == "ww" || contains(tokenStates, "ww"): + tokenState = "ww" + case contains(tokenStates, "Q-closure") && contains(tokenStates, "Q-variable"): + tokenState = "qq" + case contains(tokenStates, "Q-closure"): + tokenState = "Q-closure" + case contains(tokenStates, "Q-variable"): + tokenState = "Q-variable" + default: + tokenState = "Q" + } + + iterator, err := state.Lexer.Tokenise( + &TokeniseOptions{ + State: tokenState, + Nested: true, + }, state.NamedGroups[`value`]) + + if err != nil { + panic(err) + } else { + iterators = append(iterators, iterator) + } + + // Append the last punctuation + iterators = append(iterators, Literator(tokens[4])) + + return Concaterator(iterators...) +} + +// Emitter for pod config, tokenises the properties with "colon-pair-attribute" state +func podConfig(groups []string, state *LexerState) Iterator { + // Tokenise pod config + iterator, err := state.Lexer.Tokenise( + &TokeniseOptions{ + State: "colon-pair-attribute", + Nested: true, + }, groups[0]) + + if err != nil { + panic(err) + } else { + return iterator + } +} + +// Emitter for pod code, tokenises the code based on the lang specified +func podCode(groups []string, state *LexerState) Iterator { + iterators := []Iterator{} + tokens := []Token{ + {Comment, state.NamedGroups[`ws`]}, + {Keyword, state.NamedGroups[`keyword`]}, + {Keyword, state.NamedGroups[`ws2`]}, + {Keyword, state.NamedGroups[`name`]}, + {StringDoc, state.NamedGroups[`value`]}, + {Comment, state.NamedGroups[`ws3`]}, + {Keyword, state.NamedGroups[`end_keyword`]}, + {Keyword, state.NamedGroups[`ws4`]}, + {Keyword, state.NamedGroups[`name`]}, + } + + // Append all tokens before dealing with the pod config + iterators = append(iterators, Literator(tokens[:4]...)) + + // Tokenise pod config + iterators = append(iterators, podConfig([]string{state.NamedGroups[`config`]}, state)) + + langMatch := regexp.MustCompile(`:lang\W+(\w+)`).FindStringSubmatch(state.NamedGroups[`config`]) + var lang string + if len(langMatch) > 1 { + lang = langMatch[1] + } + + // Tokenise code based on lang property + sublexer := internal.Get(lang) + if sublexer != nil { + iterator, err := sublexer.Tokenise(nil, state.NamedGroups[`value`]) + + if err != nil { + panic(err) + } else { + iterators = append(iterators, iterator) + } + } else { + iterators = append(iterators, Literator(tokens[4])) + } + + // Append the rest of the tokens + iterators = append(iterators, Literator(tokens[5:]...)) + + return Concaterator(iterators...) +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/r/reasonml.go b/vendor/github.com/alecthomas/chroma/lexers/r/reasonml.go index 0bceb18..0ade569 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/r/reasonml.go +++ b/vendor/github.com/alecthomas/chroma/lexers/r/reasonml.go @@ -6,14 +6,18 @@ import ( ) // Reasonml lexer. -var Reasonml = internal.Register(MustNewLexer( +var Reasonml = internal.Register(MustNewLazyLexer( &Config{ Name: "ReasonML", Aliases: []string{"reason", "reasonml"}, Filenames: []string{"*.re", "*.rei"}, MimeTypes: []string{"text/x-reasonml"}, }, - Rules{ + reasonmlRules, +)) + +func reasonmlRules() Rules { + return Rules{ "escape-sequence": { {`\\[\\"\'ntbr]`, LiteralStringEscape, nil}, {`\\[0-9]{3}`, LiteralStringEscape, nil}, @@ -63,5 +67,5 @@ var Reasonml = internal.Register(MustNewLexer( {`[a-z_][\w\']*`, Name, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/r/regedit.go b/vendor/github.com/alecthomas/chroma/lexers/r/regedit.go index 7ee9cb5..6177234 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/r/regedit.go +++ b/vendor/github.com/alecthomas/chroma/lexers/r/regedit.go @@ -6,14 +6,18 @@ import ( ) // Reg lexer. -var Reg = internal.Register(MustNewLexer( +var Reg = internal.Register(MustNewLazyLexer( &Config{ Name: "reg", Aliases: []string{"registry"}, Filenames: []string{"*.reg"}, MimeTypes: []string{"text/x-windows-registry"}, }, - Rules{ + regRules, +)) + +func regRules() Rules { + return Rules{ "root": { {`Windows Registry Editor.*`, Text, nil}, {`\s+`, Text, nil}, @@ -28,5 +32,5 @@ var Reg = internal.Register(MustNewLexer( {`.+`, LiteralString, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/r/rexx.go b/vendor/github.com/alecthomas/chroma/lexers/r/rexx.go index 1f5550a..38ca768 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/r/rexx.go +++ b/vendor/github.com/alecthomas/chroma/lexers/r/rexx.go @@ -6,7 +6,7 @@ import ( ) // Rexx lexer. -var Rexx = internal.Register(MustNewLexer( +var Rexx = internal.Register(MustNewLazyLexer( &Config{ Name: "Rexx", Aliases: []string{"rexx", "arexx"}, @@ -15,7 +15,11 @@ var Rexx = internal.Register(MustNewLexer( NotMultiline: true, CaseInsensitive: true, }, - Rules{ + rexxRules, +)) + +func rexxRules() Rules { + return Rules{ "root": { {`\s`, TextWhitespace, nil}, {`/\*`, CommentMultiline, Push("comment")}, @@ -55,5 +59,5 @@ var Rexx = internal.Register(MustNewLexer( {`\*/`, CommentMultiline, Pop(1)}, {`\*`, CommentMultiline, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/r/rst.go b/vendor/github.com/alecthomas/chroma/lexers/r/rst.go index f09dad0..2a87479 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/r/rst.go +++ b/vendor/github.com/alecthomas/chroma/lexers/r/rst.go @@ -8,14 +8,18 @@ import ( ) // Restructuredtext lexer. -var Restructuredtext = internal.Register(MustNewLexer( +var Restructuredtext = internal.Register(MustNewLazyLexer( &Config{ Name: "reStructuredText", Aliases: []string{"rst", "rest", "restructuredtext"}, Filenames: []string{"*.rst", "*.rest"}, MimeTypes: []string{"text/x-rst", "text/prs.fallenstein.rst"}, }, - Rules{ + restructuredtextRules, +)) + +func restructuredtextRules() Rules { + return Rules{ "root": { {"^(=+|-+|`+|:+|\\.+|\\'+|\"+|~+|\\^+|_+|\\*+|\\++|#+)([ \\t]*\\n)(.+)(\\n)(\\1)(\\n)", ByGroups(GenericHeading, Text, GenericHeading, Text, GenericHeading, Text), nil}, {"^(\\S.*)(\\n)(={3,}|-{3,}|`{3,}|:{3,}|\\.{3,}|\\'{3,}|\"{3,}|~{3,}|\\^{3,}|_{3,}|\\*{3,}|\\+{3,}|#{3,})(\\n)", ByGroups(GenericHeading, Text, GenericHeading, Text), nil}, @@ -56,10 +60,10 @@ var Restructuredtext = internal.Register(MustNewLexer( {"``((?=$)|(?=[-/:.,; \\n\\x00\\\u2010\\\u2011\\\u2012\\\u2013\\\u2014\\\u00a0\\'\\\"\\)\\]\\}\\>\\\u2019\\\u201d\\\u00bb\\!\\?]))", LiteralString, Pop(1)}, {"`", LiteralString, nil}, }, - }, -)) + } +} -func rstCodeBlock(groups []string, lexer Lexer) Iterator { +func rstCodeBlock(groups []string, state *LexerState) Iterator { iterators := []Iterator{} tokens := []Token{ {Punctuation, groups[1]}, @@ -71,7 +75,7 @@ func rstCodeBlock(groups []string, lexer Lexer) Iterator { {Text, groups[7]}, } code := strings.Join(groups[8:], "") - lexer = internal.Get(groups[6]) + lexer := internal.Get(groups[6]) if lexer == nil { tokens = append(tokens, Token{String, code}) iterators = append(iterators, Literator(tokens...)) diff --git a/vendor/github.com/alecthomas/chroma/lexers/r/ruby.go b/vendor/github.com/alecthomas/chroma/lexers/r/ruby.go index 6af8db2..296cae9 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/r/ruby.go +++ b/vendor/github.com/alecthomas/chroma/lexers/r/ruby.go @@ -6,7 +6,7 @@ import ( ) // Ruby lexer. -var Ruby = internal.Register(MustNewLexer( +var Ruby = internal.Register(MustNewLazyLexer( &Config{ Name: "Ruby", Aliases: []string{"rb", "ruby", "duby"}, @@ -14,7 +14,11 @@ var Ruby = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-ruby", "application/x-ruby"}, DotAll: true, }, - Rules{ + rubyRules, +)) + +func rubyRules() Rules { + return Rules{ "root": { {`\A#!.+?$`, CommentHashbang, nil}, {`#.*?$`, CommentSingle, nil}, @@ -39,7 +43,7 @@ var Ruby = internal.Register(MustNewLexer( {`(0_?[0-7]+(?:_[0-7]+)*)(\s*)([/?])?`, ByGroups(LiteralNumberOct, Text, Operator), nil}, {`(0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*)(\s*)([/?])?`, ByGroups(LiteralNumberHex, Text, Operator), nil}, {`(0b[01]+(?:_[01]+)*)(\s*)([/?])?`, ByGroups(LiteralNumberBin, Text, Operator), nil}, - {`([\d]+(?:_\d+)*)(\s*)([/?])?`, ByGroups(LiteralNumberInteger, Text, Operator), nil}, + {`([\d]+(?:[_e]\d+)*)(\s*)([/?])?`, ByGroups(LiteralNumberInteger, Text, Operator), nil}, {`@@[a-zA-Z_]\w*`, NameVariableClass, nil}, {`@[a-zA-Z_]\w*`, NameVariableInstance, nil}, {`\$\w+`, NameVariableGlobal, nil}, @@ -246,5 +250,5 @@ var Ruby = internal.Register(MustNewLexer( {`[\\#<>]`, LiteralStringRegex, nil}, {`[^\\#<>]+`, LiteralStringRegex, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/r/rust.go b/vendor/github.com/alecthomas/chroma/lexers/r/rust.go index 191d1be..25d42e5 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/r/rust.go +++ b/vendor/github.com/alecthomas/chroma/lexers/r/rust.go @@ -6,7 +6,7 @@ import ( ) // Rust lexer. -var Rust = internal.Register(MustNewLexer( +var Rust = internal.Register(MustNewLazyLexer( &Config{ Name: "Rust", Aliases: []string{"rust"}, @@ -14,7 +14,11 @@ var Rust = internal.Register(MustNewLexer( MimeTypes: []string{"text/rust"}, EnsureNL: true, }, - Rules{ + rustRules, +)) + +func rustRules() Rules { + return Rules{ "root": { {`#![^[\r\n].*$`, CommentPreproc, nil}, Default(Push("base")), @@ -28,18 +32,18 @@ var Rust = internal.Register(MustNewLexer( {`/\*\*(\n|[^/*])`, LiteralStringDoc, Push("doccomment")}, {`/\*!`, LiteralStringDoc, Push("doccomment")}, {`/\*`, CommentMultiline, Push("comment")}, - {`r#*"(?:\\.|[^\\\r\n;])*"#*`, LiteralString, nil}, - {`"(?:\\.|[^\\\r\n"])*"`, LiteralString, nil}, + {`r#*"(?:\\.|[^\\;])*"#*`, LiteralString, nil}, + {`"(?:\\.|[^\\"])*"`, LiteralString, nil}, {`\$([a-zA-Z_]\w*|\(,?|\),?|,?)`, CommentPreproc, nil}, - {Words(``, `\b`, `as`, `box`, `const`, `crate`, `else`, `extern`, `for`, `if`, `impl`, `in`, `loop`, `match`, `move`, `mut`, `pub`, `ref`, `return`, `static`, `super`, `trait`, `unsafe`, `use`, `where`, `while`), Keyword, nil}, - {Words(``, `\b`, `abstract`, `alignof`, `become`, `do`, `final`, `macro`, `offsetof`, `override`, `priv`, `proc`, `pure`, `sizeof`, `typeof`, `unsized`, `virtual`, `yield`), KeywordReserved, nil}, + {Words(``, `\b`, `as`, `async`, `await`, `const`, `crate`, `else`, `extern`, `for`, `if`, `impl`, `in`, `loop`, `match`, `move`, `mut`, `pub`, `ref`, `return`, `static`, `super`, `trait`, `unsafe`, `use`, `where`, `while`), Keyword, nil}, + {Words(``, `\b`, `abstract`, `become`, `box`, `do`, `final`, `macro`, `override`, `priv`, `try`, `typeof`, `unsized`, `virtual`, `yield`), KeywordReserved, nil}, {`(true|false)\b`, KeywordConstant, nil}, {`mod\b`, Keyword, Push("modname")}, {`let\b`, KeywordDeclaration, nil}, {`fn\b`, Keyword, Push("funcname")}, {`(struct|enum|type|union)\b`, Keyword, Push("typename")}, {`(default)(\s+)(type|fn)\b`, ByGroups(Keyword, Text, Keyword), nil}, - {Words(``, `\b`, `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`, `usize`, `isize`, `f32`, `f64`, `str`, `bool`), KeywordType, nil}, + {Words(``, `\b`, `u8`, `u16`, `u32`, `u64`, `u128`, `i8`, `i16`, `i32`, `i64`, `i128`, `usize`, `isize`, `f32`, `f64`, `str`, `bool`), KeywordType, nil}, {`self\b`, NameBuiltinPseudo, nil}, {Words(``, `\b`, `Copy`, `Send`, `Sized`, `Sync`, `Drop`, `Fn`, `FnMut`, `FnOnce`, `Box`, `ToOwned`, `Clone`, `PartialEq`, `PartialOrd`, `Eq`, `Ord`, `AsRef`, `AsMut`, `Into`, `From`, `Default`, `Iterator`, `Extend`, `IntoIterator`, `DoubleEndedIterator`, `ExactSizeIterator`, `Option`, `Some`, `None`, `Result`, `Ok`, `Err`, `SliceConcatExt`, `String`, `ToString`, `Vec`), NameBuiltin, nil}, {`::\b`, Text, nil}, @@ -131,5 +135,5 @@ var Rust = internal.Register(MustNewLexer( {`\);?`, CommentPreproc, Pop(1)}, {`[^")]+`, CommentPreproc, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/sas.go b/vendor/github.com/alecthomas/chroma/lexers/s/sas.go index 47a67ed..016a91b 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/sas.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/sas.go @@ -6,7 +6,7 @@ import ( ) // Sas lexer. -var Sas = internal.Register(MustNewLexer( +var Sas = internal.Register(MustNewLazyLexer( &Config{ Name: "SAS", Aliases: []string{"sas"}, @@ -14,7 +14,11 @@ var Sas = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-sas", "text/sas", "application/x-sas"}, CaseInsensitive: true, }, - Rules{ + sasRules, +)) + +func sasRules() Rules { + return Rules{ "root": { Include("comments"), Include("proc-data"), @@ -90,5 +94,5 @@ var Sas = internal.Register(MustNewLexer( "special": { {`(null|missing|_all_|_automatic_|_character_|_n_|_infile_|_name_|_null_|_numeric_|_user_|_webout_)`, KeywordConstant, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/sass.go b/vendor/github.com/alecthomas/chroma/lexers/s/sass.go index 6200f6a..1b73377 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/sass.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/sass.go @@ -6,7 +6,7 @@ import ( ) // Sass lexer. -var Sass = internal.Register(MustNewLexer( +var Sass = internal.Register(MustNewLazyLexer( &Config{ Name: "Sass", Aliases: []string{"sass"}, @@ -14,7 +14,11 @@ var Sass = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-sass"}, CaseInsensitive: true, }, - Rules{ + sassRules, +)) + +func sassRules() Rules { + return Rules{ // "root": { // }, "root": { @@ -140,5 +144,5 @@ var Sass = internal.Register(MustNewLexer( {`(from|to|through)`, OperatorWord, nil}, Include("value"), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/scala.go b/vendor/github.com/alecthomas/chroma/lexers/s/scala.go index 20932de..2885d01 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/scala.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/scala.go @@ -7,15 +7,8 @@ import ( "github.com/alecthomas/chroma/lexers/internal" ) -var ( - scalaOp = "[-~\\^\\*!%&\\\\<>\\|+=:/?@\xa6-\xa7\xa9\xac\xae\xb0-\xb1\xb6\xd7\xf7\u03f6\u0482\u0606-\u0608\u060e-\u060f\u06e9\u06fd-\u06fe\u07f6\u09fa\u0b70\u0bf3-\u0bf8\u0bfa\u0c7f\u0cf1-\u0cf2\u0d79\u0f01-\u0f03\u0f13-\u0f17\u0f1a-\u0f1f\u0f34\u0f36\u0f38\u0fbe-\u0fc5\u0fc7-\u0fcf\u109e-\u109f\u1360\u1390-\u1399\u1940\u19e0-\u19ff\u1b61-\u1b6a\u1b74-\u1b7c\u2044\u2052\u207a-\u207c\u208a-\u208c\u2100-\u2101\u2103-\u2106\u2108-\u2109\u2114\u2116-\u2118\u211e-\u2123\u2125\u2127\u2129\u212e\u213a-\u213b\u2140-\u2144\u214a-\u214d\u214f\u2190-\u2328\u232b-\u244a\u249c-\u24e9\u2500-\u2767\u2794-\u27c4\u27c7-\u27e5\u27f0-\u2982\u2999-\u29d7\u29dc-\u29fb\u29fe-\u2b54\u2ce5-\u2cea\u2e80-\u2ffb\u3004\u3012-\u3013\u3020\u3036-\u3037\u303e-\u303f\u3190-\u3191\u3196-\u319f\u31c0-\u31e3\u3200-\u321e\u322a-\u3250\u3260-\u327f\u328a-\u32b0\u32c0-\u33ff\u4dc0-\u4dff\ua490-\ua4c6\ua828-\ua82b\ufb29\ufdfd\ufe62\ufe64-\ufe66\uff0b\uff1c-\uff1e\uff5c\uff5e\uffe2\uffe4\uffe8-\uffee\ufffc-\ufffd]+" - scalaUpper = "[A-Z\\$_\xc0-\xd6\xd8-\xde\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038f\u0391-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0531-\u0556\u10a0-\u10c5\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59-\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c6f\u2c72\u2c75\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\uff21-\uff3a]" - scalaLetter = `[a-zA-Z\\$_ªµºÀ-ÖØ-öø-ʯͰ-ͳͶ-ͷͻ-ͽΆΈ-ϵϷ-ҁҊ-Ֆա-ևא-ײء-ؿف-يٮ-ٯٱ-ۓەۮ-ۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪऄ-हऽॐक़-ॡॲ-ॿঅ-হঽৎড়-ৡৰ-ৱਅ-ਹਖ਼-ਫ਼ੲ-ੴઅ-હઽૐ-ૡଅ-ହଽଡ଼-ୡୱஃ-ஹௐఅ-ఽౘ-ౡಅ-ಹಽೞ-ೡഅ-ഽൠ-ൡൺ-ൿඅ-ෆก-ะา-ำเ-ๅກ-ະາ-ຳຽ-ໄໜ-ༀཀ-ཬྈ-ྋက-ဪဿၐ-ၕၚ-ၝၡၥ-ၦၮ-ၰၵ-ႁႎႠ-ჺᄀ-ፚᎀ-ᎏᎠ-ᙬᙯ-ᙶᚁ-ᚚᚠ-ᛪᛮ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝰក-ឳៜᠠ-ᡂᡄ-ᢨᢪ-ᤜᥐ-ᦩᧁ-ᧇᨀ-ᨖᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᰀ-ᰣᱍ-ᱏᱚ-ᱷᴀ-ᴫᵢ-ᵷᵹ-ᶚḀ-ᾼιῂ-ῌῐ-Ίῠ-Ῥῲ-ῼⁱⁿℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-ⱼⲀ-ⳤⴀ-ⵥⶀ-ⷞ〆-〇〡-〩〸-〺〼ぁ-ゖゟァ-ヺヿ-ㆎㆠ-ㆷㇰ-ㇿ㐀-䶵一-ꀔꀖ-ꒌꔀ-ꘋꘐ-ꘟꘪ-ꙮꚀ-ꚗꜢ-ꝯꝱ-ꞇꞋ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꤊ-ꤥꤰ-ꥆꨀ-ꨨꩀ-ꩂꩄ-ꩋ가-힣豈-יִײַ-ﬨשׁ-ﴽﵐ-ﷻﹰ-ﻼA-Za-zヲ-ッア-ンᅠ-ᅵ]` - scalaIDRest = fmt.Sprintf(`%s(?:%s|[0-9])*(?:(?<=_)%s)?`, scalaLetter, scalaLetter, scalaOp) -) - // Scala lexer. -var Scala = internal.Register(MustNewLexer( +var Scala = internal.Register(MustNewLazyLexer( &Config{ Name: "Scala", Aliases: []string{"scala"}, @@ -23,7 +16,18 @@ var Scala = internal.Register(MustNewLexer( MimeTypes: []string{"text/x-scala"}, DotAll: true, }, - Rules{ + scalaRules, +)) + +func scalaRules() Rules { + var ( + scalaOp = "[-~\\^\\*!%&\\\\<>\\|+=:/?@\xa6-\xa7\xa9\xac\xae\xb0-\xb1\xb6\xd7\xf7\u03f6\u0482\u0606-\u0608\u060e-\u060f\u06e9\u06fd-\u06fe\u07f6\u09fa\u0b70\u0bf3-\u0bf8\u0bfa\u0c7f\u0cf1-\u0cf2\u0d79\u0f01-\u0f03\u0f13-\u0f17\u0f1a-\u0f1f\u0f34\u0f36\u0f38\u0fbe-\u0fc5\u0fc7-\u0fcf\u109e-\u109f\u1360\u1390-\u1399\u1940\u19e0-\u19ff\u1b61-\u1b6a\u1b74-\u1b7c\u2044\u2052\u207a-\u207c\u208a-\u208c\u2100-\u2101\u2103-\u2106\u2108-\u2109\u2114\u2116-\u2118\u211e-\u2123\u2125\u2127\u2129\u212e\u213a-\u213b\u2140-\u2144\u214a-\u214d\u214f\u2190-\u2328\u232b-\u244a\u249c-\u24e9\u2500-\u2767\u2794-\u27c4\u27c7-\u27e5\u27f0-\u2982\u2999-\u29d7\u29dc-\u29fb\u29fe-\u2b54\u2ce5-\u2cea\u2e80-\u2ffb\u3004\u3012-\u3013\u3020\u3036-\u3037\u303e-\u303f\u3190-\u3191\u3196-\u319f\u31c0-\u31e3\u3200-\u321e\u322a-\u3250\u3260-\u327f\u328a-\u32b0\u32c0-\u33ff\u4dc0-\u4dff\ua490-\ua4c6\ua828-\ua82b\ufb29\ufdfd\ufe62\ufe64-\ufe66\uff0b\uff1c-\uff1e\uff5c\uff5e\uffe2\uffe4\uffe8-\uffee\ufffc-\ufffd]+" + scalaUpper = "[A-Z\\$_\xc0-\xd6\xd8-\xde\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u0386\u0388-\u038f\u0391-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0531-\u0556\u10a0-\u10c5\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59-\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c6f\u2c72\u2c75\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\uff21-\uff3a]" + scalaLetter = `[a-zA-Z\\$_ªµºÀ-ÖØ-öø-ʯͰ-ͳͶ-ͷͻ-ͽΆΈ-ϵϷ-ҁҊ-Ֆա-ևא-ײء-ؿف-يٮ-ٯٱ-ۓەۮ-ۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪऄ-हऽॐक़-ॡॲ-ॿঅ-হঽৎড়-ৡৰ-ৱਅ-ਹਖ਼-ਫ਼ੲ-ੴઅ-હઽૐ-ૡଅ-ହଽଡ଼-ୡୱஃ-ஹௐఅ-ఽౘ-ౡಅ-ಹಽೞ-ೡഅ-ഽൠ-ൡൺ-ൿඅ-ෆก-ะา-ำเ-ๅກ-ະາ-ຳຽ-ໄໜ-ༀཀ-ཬྈ-ྋက-ဪဿၐ-ၕၚ-ၝၡၥ-ၦၮ-ၰၵ-ႁႎႠ-ჺᄀ-ፚᎀ-ᎏᎠ-ᙬᙯ-ᙶᚁ-ᚚᚠ-ᛪᛮ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝰក-ឳៜᠠ-ᡂᡄ-ᢨᢪ-ᤜᥐ-ᦩᧁ-ᧇᨀ-ᨖᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᰀ-ᰣᱍ-ᱏᱚ-ᱷᴀ-ᴫᵢ-ᵷᵹ-ᶚḀ-ᾼιῂ-ῌῐ-Ίῠ-Ῥῲ-ῼⁱⁿℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-ⱼⲀ-ⳤⴀ-ⵥⶀ-ⷞ〆-〇〡-〩〸-〺〼ぁ-ゖゟァ-ヺヿ-ㆎㆠ-ㆷㇰ-ㇿ㐀-䶵一-ꀔꀖ-ꒌꔀ-ꘋꘐ-ꘟꘪ-ꙮꚀ-ꚗꜢ-ꝯꝱ-ꞇꞋ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꤊ-ꤥꤰ-ꥆꨀ-ꨨꩀ-ꩂꩄ-ꩋ가-힣豈-יִײַ-ﬨשׁ-ﴽﵐ-ﷻﹰ-ﻼA-Za-zヲ-ッア-ンᅠ-ᅵ]` + scalaIDRest = fmt.Sprintf(`%s(?:%s|[0-9])*(?:(?<=_)%s)?`, scalaLetter, scalaLetter, scalaOp) + ) + + return Rules{ "root": { {`(class|trait|object)(\s+)`, ByGroups(Keyword, Text), Push("class")}, {`[^\S\n]+`, Text, nil}, @@ -108,5 +112,5 @@ var Scala = internal.Register(MustNewLexer( {`\{`, LiteralStringInterpol, Push()}, Include("root"), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/scheme.go b/vendor/github.com/alecthomas/chroma/lexers/s/scheme.go index b721d68..d2f177e 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/scheme.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/scheme.go @@ -8,14 +8,18 @@ import ( // nolint // Scheme lexer. -var SchemeLang = internal.Register(MustNewLexer( +var SchemeLang = internal.Register(MustNewLazyLexer( &Config{ Name: "Scheme", Aliases: []string{"scheme", "scm"}, Filenames: []string{"*.scm", "*.ss"}, MimeTypes: []string{"text/x-scheme", "application/x-scheme"}, }, - Rules{ + schemeLangRules, +)) + +func schemeLangRules() Rules { + return Rules{ "root": { {`;.*$`, CommentSingle, nil}, {`#\|`, CommentMultiline, Push("multiline-comment")}, @@ -49,5 +53,5 @@ var SchemeLang = internal.Register(MustNewLexer( {`\)`, Comment, Pop(1)}, {`[^()]+`, Comment, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/scilab.go b/vendor/github.com/alecthomas/chroma/lexers/s/scilab.go index 87fa66c..f816492 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/scilab.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/scilab.go @@ -6,14 +6,18 @@ import ( ) // Scilab lexer. -var Scilab = internal.Register(MustNewLexer( +var Scilab = internal.Register(MustNewLazyLexer( &Config{ Name: "Scilab", Aliases: []string{"scilab"}, Filenames: []string{"*.sci", "*.sce", "*.tst"}, MimeTypes: []string{"text/scilab"}, }, - Rules{ + scilabRules, +)) + +func scilabRules() Rules { + return Rules{ "root": { {`//.*?$`, CommentSingle, nil}, {`^\s*function`, Keyword, Push("deffunc")}, @@ -40,5 +44,5 @@ var Scilab = internal.Register(MustNewLexer( {`(\s*)(?:(.+)(\s*)(=)(\s*))?(.+)(\()(.*)(\))(\s*)`, ByGroups(TextWhitespace, Text, TextWhitespace, Punctuation, TextWhitespace, NameFunction, Punctuation, Text, Punctuation, TextWhitespace), Pop(1)}, {`(\s*)([a-zA-Z_]\w*)`, ByGroups(Text, NameFunction), Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/scss.go b/vendor/github.com/alecthomas/chroma/lexers/s/scss.go index 48195de..e489ade 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/scss.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/scss.go @@ -6,7 +6,7 @@ import ( ) // Scss lexer. -var Scss = internal.Register(MustNewLexer( +var Scss = internal.Register(MustNewLazyLexer( &Config{ Name: "SCSS", Aliases: []string{"scss"}, @@ -16,24 +16,47 @@ var Scss = internal.Register(MustNewLexer( DotAll: true, CaseInsensitive: true, }, - Rules{ + scssRules, +)) + +func scssRules() Rules { + cssProperties := []string{`src`, `align-content`, `align-items`, `align-self`, `all`, `animation`, `animation-delay`, `animation-direction`, `animation-duration`, `animation-fill-mode`, `animation-iteration-count`, `animation-name`, `animation-play-state`, `animation-timing-function`, `appearance`, `aspect-ratio`, `backface-visibility`, `background`, `background-attachment`, `background-blend-mode`, `background-clip`, `background-color`, `background-image`, `background-origin`, `background-position`, `background-repeat`, `background-size`, `block-size`, `border`, `border-block`, `border-block-color`, `border-block-end`, `border-block-end-color`, `border-block-end-style`, `border-block-end-width`, `border-block-start`, `border-block-start-color`, `border-block-start-style`, `border-block-start-width`, `border-block-style`, `border-block-width`, `border-bottom`, `border-bottom-color`, `border-bottom-left-radius`, `border-bottom-right-radius`, `border-bottom-style`, `border-bottom-width`, `border-collapse`, `border-color`, `border-end-end-radius`, `border-end-start-radius`, `border-image`, `border-image-outset`, `border-image-repeat`, `border-image-slice`, `border-image-source`, `border-image-width`, `border-inline`, `border-inline-color`, `border-inline-end`, `border-inline-end-color`, `border-inline-end-style`, `border-inline-end-width`, `border-inline-start`, `border-inline-start-color`, `border-inline-start-style`, `border-inline-start-width`, `border-inline-style`, `border-inline-width`, `border-left`, `border-left-color`, `border-left-style`, `border-left-width`, `border-radius`, `border-right`, `border-right-color`, `border-right-style`, `border-right-width`, `border-spacing`, `border-start-end-radius`, `border-start-start-radius`, `border-style`, `border-top`, `border-top-color`, `border-top-left-radius`, `border-top-right-radius`, `border-top-style`, `border-top-width`, `border-width`, `bottom`, `box-decoration-break`, `box-shadow`, `box-sizing`, `break-after`, `break-before`, `break-inside`, `caption-side`, `caret-color`, `clear`, `clip`, `clip-path`, `color`, `color-adjust`, `column-count`, `column-fill`, `column-gap`, `column-rule`, `column-rule-color`, `column-rule-style`, `column-rule-width`, `column-span`, `column-width`, `columns`, `content`, `content-visibility`, `counter-increment`, `counter-reset`, `counter-set`, `cursor`, `direction`, `display`, `empty-cells`, `filter`, `flex`, `flex-basis`, `flex-direction`, `flex-flow`, `flex-grow`, `flex-shrink`, `flex-wrap`, `float`, `font`, `font-family`, `font-feature-settings`, `font-kerning`, `font-language-override`, `font-optical-sizing`, `font-size`, `font-size-adjust`, `font-stretch`, `font-style`, `font-synthesis`, `font-variant`, `font-variant-caps`, `font-variant-east-asian`, `font-variant-emoji`, `font-variant-ligatures`, `font-variant-numeric`, `font-variant-position`, `font-weight`, `footnote-display`, `footnote-policy`, `forced-color-adjust`, `gap`, `grid`, `grid-area`, `grid-auto-columns`, `grid-auto-flow`, `grid-auto-rows`, `grid-column`, `grid-column-end`, `grid-column-start`, `grid-row`, `grid-row-end`, `grid-row-start`, `grid-template`, `grid-template-areas`, `grid-template-columns`, `grid-template-rows`, `hanging-punctuation`, `height`, `hyphens`, `image-orientation`, `image-rendering`, `image-resolution`, `initial-letter`, `initial-letter-align`, `initial-letter-wrap`, `inline-size`, `inline-sizing`, `inset`, `inset-block`, `inset-block-end`, `inset-block-start`, `inset-inline`, `inset-inline-end`, `inset-inline-start`, `isolation`, `justify-content`, `justify-items`, `justify-self`, `left`, `letter-spacing`, `lighting-color`, `line-break`, `line-clamp`, `line-grid`, `line-height`, `line-padding`, `line-snap`, `list-style`, `list-style-image`, `list-style-position`, `list-style-type`, `margin`, `margin-block`, `margin-block-end`, `margin-block-start`, `margin-bottom`, `margin-break`, `margin-inline`, `margin-inline-end`, `margin-inline-start`, `margin-left`, `margin-right`, `margin-top`, `margin-trim`, `mask`, `mask-border`, `mask-border-mode`, `mask-border-repeat`, `mask-border-slice`, `mask-border-source`, `mask-border-width`, `mask-clip`, `mask-composite`, `mask-image`, `mask-mode`, `mask-origin`, `mask-position`, `mask-repeat`, `mask-size`, `mask-type`, `max-block-size`, `max-height`, `max-lines`, `max-width`, `min-height`, `min-width`, `mix-blend-mode`, `nav-down`, `nav-left`, `nav-right`, `nav-up`, `object-fit`, `object-position`, `offset`, `offset-anchor`, `offset-distance`, `offset-path`, `offset-position`, `offset-rotate`, `opacity`, `order`, `orphans`, `outline`, `outline-color`, `outline-offset`, `outline-style`, `outline-width`, `overflow`, `overflow-anchor`, `overflow-block`, `overflow-clip-margin`, `overflow-inline`, `overflow-wrap`, `overflow-x`, `overflow-y`, `overscroll-behavior`, `overscroll-behavior-block`, `overscroll-behavior-inline`, `overscroll-behavior-x`, `overscroll-behavior-y`, `padding`, `padding-block`, `padding-block-end`, `padding-block-start`, `padding-bottom`, `padding-inline`, `padding-inline-end`, `padding-inline-start`, `padding-left`, `padding-right`, `padding-top`, `page`, `page-break-after`, `page-break-before`, `page-break-inside`, `page-orientation`, `perspective`, `perspective-origin`, `place-content`, `place-items`, `place-self`, `pointer-events`, `position`, `quotes`, `resize`, `right`, `rotate`, `row-gap`, `scale`, `scroll-behavior`, `scroll-margin`, `scroll-margin-block`, `scroll-margin-block-end`, `scroll-margin-block-start`, `scroll-margin-bottom`, `scroll-margin-inline`, `scroll-margin-inline-end`, `scroll-margin-inline-start`, `scroll-margin-left`, `scroll-margin-right`, `scroll-margin-top`, `scroll-padding`, `scroll-padding-block`, `scroll-padding-block-end`, `scroll-padding-block-start`, `scroll-padding-bottom`, `scroll-padding-inline`, `scroll-padding-inline-end`, `scroll-padding-inline-start`, `scroll-padding-left`, `scroll-padding-right`, `scroll-padding-top`, `scroll-snap-align`, `scroll-snap-stop`, `scroll-snap-type`, `scrollbar-color`, `scrollbar-gutter`, `scrollbar-width`, `shape-image-threshold`, `shape-inside`, `shape-margin`, `shape-outside`, `shape-padding`, `spatial-navigation-action`, `spatial-navigation-contain`, `spatial-navigation-function`, `string-set`, `tab-size`, `table-layout`, `text-align`, `text-align-all`, `text-align-last`, `text-combine-upright`, `text-decoration`, `text-decoration-color`, `text-decoration-line`, `text-decoration-skip`, `text-decoration-style`, `text-decoration-thickness`, `text-emphasis`, `text-emphasis-position`, `text-emphasis-style`, `text-group-align`, `text-indent`, `text-justify`, `text-orientation`, `text-overflow`, `text-rendering`, `text-shadow`, `text-size-adjust`, `text-space-trim`, `text-spacing`, `text-transform`, `text-underline-offset`, `text-underline-position`, `text-wrap`, `top`, `touch-action`, `transform`, `transform-box`, `transform-origin`, `transform-style`, `transition`, `transition-delay`, `transition-duration`, `transition-property`, `transition-timing-function`, `translate`, `unicode-bidi`, `user-select`, `vertical-align`, `visibility`, `white-space`, `widows`, `width`, `will-change`, `word-break`, `word-spacing`, `word-wrap`, `wrap-after`, `wrap-before`, `wrap-flow`, `wrap-inside`, `wrap-through`, `writing-mode`, `z-index`} + + cssPropertyValues := []string{ + `stretch`, `flex-start`, `flex-end`, `center`, `space-between`, `space-around`, `normal`, `baseline`, `first`, `last`, `space-evenly`, `start`, `end`, `safe`, `unsafe`, `self-start`, `self-end`, `auto`, `initial`, `inherit`, `unset`, `revert`, `reverse`, `alternate-reverse`, `alternate`, `none`, `forwards`, `both`, `backwards`, `infinite`, `running`, `paused`, `ease`, `linear`, `step-start`, `step-end`, `ease-in`, `ease-out`, `ease-in-out`, `cubic-bezier`, `textfield`, `menulist-button`, `searchfield`, `textarea`, `push-button`, `slider-horizontal`, `checkbox`, `radio`, `square-button`, `menulist`, `listbox`, `meter`, `progress-bar`, `button`, `visible`, `hidden`, `scroll`, `fixed`, `local`, `multiply`, `screen`, `overlay`, `darken`, `lighten`, `color-dodge`, `color-burn`, `hard-light`, `soft-light`, `difference`, `exclusion`, `hue`, `saturation`, `color`, `luminosity`, `border-box`, `padding-box`, `content-box`, `text`, `transparent`, `currentColor`, `url`, `element`, `image`, `image-set`, `cross-fade`, `top`, `bottom`, `left`, `right`, `repeat`, `no-repeat`, `space`, `round`, `repeat-y`, `repeat-x`, `cover`, `contain`, `max-content`, `min-content`, `available`, `fit-content`, `dotted`, `dashed`, `solid`, `double`, `groove`, `ridge`, `inset`, `outset`, `medium`, `thin`, `thick`, `separate`, `collapse`, `slice`, `clone`, `avoid`, `always`, `all`, `avoid-page`, `page`, `recto`, `verso`, `avoid-column`, `column`, `avoid-region`, `region`, `inline-start`, `inline-end`, `rect`, `circle`, `ellipse`, `polygon`, `path`, `margin-box`, `fill-box`, `stroke-box`, `view-box`, `economy`, `exact`, `balance`, `balance-all`, `open-quote`, `close-quote`, `no-open-quote`, `no-close-quote`, `contents`, `attr`, `target-counter`, `target-text`, `leader`, `default`, `context-menu`, `help`, `pointer`, `progress`, `wait`, `cell`, `crosshair`, `vertical-text`, `alias`, `copy`, `move`, `no-drop`, `not-allowed`, `grab`, `grabbing`, `all-scroll`, `col-resize`, `row-resize`, `n-resize`, `s-resize`, `w-resize`, `ne-resize`, `nw-resize`, `se-resize`, `sw-resize`, `ew-resize`, `ns-resize`, `nesw-resize`, `nwse-resize`, `zoom-in`, `zoom-out`, `ltr`, `rtl`, `inline`, `block`, `inline-block`, `inline-table`, `run-in`, `flow`, `flow-root`, `table`, `flex`, `grid`, `ruby`, `list-item`, `table-row-group`, `table-header-group`, `table-footer-group`, `table-row`, `table-cell`, `table-column-group`, `table-column`, `table-caption`, `ruby-base`, `ruby-text`, `ruby-base-container`, `ruby-text-container`, `inline-flex`, `inline-grid`, `show`, `hide`, `url;`, `blur`, `brightness`, `contrast`, `drop-shadow`, `grayscale`, `hue-rotate`, `invert`, `opacity`, `saturate`, `sepia`, `content`, `row`, `row-reverse`, `column-reverse`, `nowrap`, `wrap`, `wrap-reverse`, `block-start`, `block-end`, `caption`, `icon`, `menu`, `message-box`, `small-caption`, `status-bar`, `serif`, `sans-serif`, `cursive`, `fantasy`, `monospace`, `system-ui`, `emoji`, `math`, `fangsong`, `ui-serif`, `ui-sans-serif`, `ui-monospace`, `ui-rounded`, `xx-small`, `x-small`, `small`, `large`, `x-large`, `xx-large`, `xxx-large`, `smaller`, `larger`, `semi-condensed`, `condensed`, `extra-condensed`, `ultra-condensed`, `semi-expanded`, `expanded`, `extra-expanded`, `ultra-expanded`, `italic`, `weight`, `style`, `small-caps`, `all-small-caps`, `petite-caps`, `all-petite-caps`, `unicase`, `titling-caps`, `jis78`, `jis83`, `jis90`, `jis04`, `simplified`, `traditional`, `full-width`, `proportional-width`, `unicode`, `common-ligatures`, `no-common-ligatures`, `discretionary-ligatures`, `no-discretionary-ligatures`, `historical-ligatures`, `no-historical-ligatures`, `contextual`, `no-contextual`, `ordinal`, `slashed-zero`, `lining-nums`, `oldstyle-nums`, `proportional-nums`, `tabular-nums`, `diagonal-fractions`, `stacked-fractions`, `sub`, `super`, `bold`, `lighter`, `bolder`, `line`, `auto‑flow`, `minmax`, `auto;`, `dense`, `subgrid`, `masonry`, `force-end`, `allow-end`, `manual`, `from-image`, `smooth`, `high-quality`, `crisp-edges`, `pixelated`, `snap`, `alphabetic`, `ideographic`, `hebrew`, `hanging`, `isolate`, `legacy`, `white`, `strict`, `loose`, `anywhere`, `match-parent`, `create`, `outside`, `inside`, `disc`, `square`, `decimal`, `symbols`, `cjk-decimal`, `decimal-leading-zero`, `lower-roman`, `upper-roman`, `lower-greek`, `lower-alpha`, `lower-latin`, `upper-alpha`, `upper-latin`, `arabic-indic`, `armenian`, `bengali`, `cambodian`, `cjk-earthly-branch`, `cjk-heavenly-stem`, `cjk-ideographic`, `devanagari`, `ethiopic-numeric`, `georgian`, `gujarati`, `gurmukhi`, `hiragana`, `hiragana-iroha`, `japanese-formal`, `japanese-informal`, `kannada`, `katakana`, `katakana-iroha`, `khmer`, `korean-hangul-formal`, `korean-hanja-formal`, `korean-hanja-informal`, `lao`, `lower-armenian`, `malayalam`, `mongolian`, `myanmar`, `oriya`, `persian`, `simp-chinese-formal`, `simp-chinese-informal`, `tamil`, `telugu`, `thai`, `tibetan`, `trad-chinese-formal`, `trad-chinese-informal`, `upper-armenian`, `disclosure-open`, `disclosure-closed`, `keep`, `discard`, `in-flow`, `alpha`, `luminance`, `no-clip`, `add`, `subtract`, `intersect`, `exclude`, `match-source`, `current`, `fill`, `scale-down`, `ray`, `clip`, `break-word`, `upright`, `rotate-left`, `rotate-right`, `static`, `relative`, `absolute`, `sticky`, `horizontal`, `vertical`, `x`, `y`, `z`, `mandatory`, `proximity`, `dark`, `light`, `stable`, `force`, `outside-shape`, `display`, `focus`, `justify`, `justify-all`, `underline`, `overline`, `line-through`, `blink`, `spelling-error`, `grammar-error`, `wavy`, `from-font`, `over`, `under`, `filled`, `open`, `dot`, `double-circle`, `triangle`, `sesame`, `inter-word`, `inter-character`, `mixed`, `sideways`, `ellipsis`, `optimizeSpeed`, `optimizeLegibility`, `geometricPrecision`, `trim-inner`, `discard-before`, `discard-after`, `trim-start`, `space-start`, `space-first`, `trim-end`, `space-end`, `trim-adjacent`, `space-adjacent`, `no-compress`, `ideograph-alpha`, `ideograph-numeric`, `punctuation`, `capitalize`, `uppercase`, `lowercase`, `full-size-kana`, `pretty`, `pan-x`, `pan-left`, `pan-right`, `pan-y`, `pan-up`, `pan-down`, `manipulation`, `matrix`, `matrix3d`, `translate`, `translateX`, `translateY`, `translate3d`, `translateZ`, `scale`, `scaleX`, `scaleY`, `scaleZ`, `rotate`, `rotate3d`, `rotateX`, `rotateY`, `rotateZ`, `perspective`, `skew`, `skewX`, `skewY`, `flat`, `preserve-3d`, `border-bottom`, `embed`, `bidi-override`, `isolate-override`, `plaintext`, `middle`, `text-top`, `text-bottom`, `pre`, `pre-wrap`, `pre-line`, `scroll-position`, `transform`, `width`, `keep-all`, `break-all`, `avoid-line`, `avoid-flex`, `minimum`, `maximum`, `clear`, `horizontal-tb`, `vertical-rl`, `vertical-lr`, `sideways-rl`, `sideways-lr`, + } + + cssColorNames := []string{`AliceBlue`, `AntiqueWhite`, `Aqua`, `Aquamarine`, `Azure`, `Beige`, `Bisque`, `Black`, `BlanchedAlmond`, `Blue`, `BlueViolet`, `Brown`, `BurlyWood`, `CadetBlue`, `Chartreuse`, `Chocolate`, `Coral`, `CornflowerBlue`, `Cornsilk`, `Crimson`, `Cyan`, `DarkBlue`, `DarkCyan`, `DarkGoldenRod`, `DarkGray`, `DarkGrey`, `DarkGreen`, `DarkKhaki`, `DarkMagenta`, `DarkOliveGreen`, `DarkOrange`, `DarkOrchid`, `DarkRed`, `DarkSalmon`, `DarkSeaGreen`, `DarkSlateBlue`, `DarkSlateGray`, `DarkSlateGrey`, `DarkTurquoise`, `DarkViolet`, `DeepPink`, `DeepSkyBlue`, `DimGray`, `DimGrey`, `DodgerBlue`, `FireBrick`, `FloralWhite`, `ForestGreen`, `Fuchsia`, `Gainsboro`, `GhostWhite`, `Gold`, `GoldenRod`, `Gray`, `Grey`, `Green`, `GreenYellow`, `HoneyDew`, `HotPink`, `IndianRed`, `Indigo`, `Ivory`, `Khaki`, `Lavender`, `LavenderBlush`, `LawnGreen`, `LemonChiffon`, `LightBlue`, `LightCoral`, `LightCyan`, `LightGoldenRodYellow`, `LightGray`, `LightGrey`, `LightGreen`, `LightPink`, `LightSalmon`, `LightSeaGreen`, `LightSkyBlue`, `LightSlateGray`, `LightSlateGrey`, `LightSteelBlue`, `LightYellow`, `Lime`, `LimeGreen`, `Linen`, `Magenta`, `Maroon`, `MediumAquaMarine`, `MediumBlue`, `MediumOrchid`, `MediumPurple`, `MediumSeaGreen`, `MediumSlateBlue`, `MediumSpringGreen`, `MediumTurquoise`, `MediumVioletRed`, `MidnightBlue`, `MintCream`, `MistyRose`, `Moccasin`, `NavajoWhite`, `Navy`, `OldLace`, `Olive`, `OliveDrab`, `Orange`, `OrangeRed`, `Orchid`, `PaleGoldenRod`, `PaleGreen`, `PaleTurquoise`, `PaleVioletRed`, `PapayaWhip`, `PeachPuff`, `Peru`, `Pink`, `Plum`, `PowderBlue`, `Purple`, `RebeccaPurple`, `Red`, `RosyBrown`, `RoyalBlue`, `SaddleBrown`, `Salmon`, `SandyBrown`, `SeaGreen`, `SeaShell`, `Sienna`, `Silver`, `SkyBlue`, `SlateBlue`, `SlateGray`, `SlateGrey`, `Snow`, `SpringGreen`, `SteelBlue`, `Tan`, `Teal`, `Thistle`, `Tomato`, `Turquoise`, `Violet`, `Wheat`, `White`, `WhiteSmoke`, `Yellow`, `YellowGreen`} + + const cssPropertyPattern = `(?|+=@:,./?-]+`, Operator, nil}, {`[\[\]()]+`, Punctuation, nil}, @@ -76,15 +100,16 @@ var Scss = internal.Register(MustNewLexer( {`[ \t]+`, Text, nil}, {`\:`, NameDecorator, Push("pseudo-class")}, {`\.`, NameClass, Push("class")}, - {`\#`, NameNamespace, Push("id")}, - {`[\w-]+`, NameTag, nil}, {`#\{`, LiteralStringInterpol, Push("interpolation")}, + {`\#`, NameNamespace, Push("id")}, {`&`, Keyword, nil}, {`[~^*!&\[\]()<>|+=@:,./?-]`, Operator, nil}, + {`(%)([\w-]+)`, ByGroups(Operator, NameClass), nil}, {`"`, LiteralStringDouble, Push("string-double")}, {`'`, LiteralStringSingle, Push("string-single")}, {`\n`, Text, nil}, {`[;{}]`, Punctuation, Pop(1)}, + {`[\w-]+`, NameTag, nil}, }, "string-double": { {`(\\.|#(?=[^\n{])|[^\n"#])+`, LiteralStringDouble, nil}, @@ -120,5 +145,9 @@ var Scss = internal.Register(MustNewLexer( {`(from|to|through)`, OperatorWord, nil}, Include("value"), }, - }, -)) + "each": { + {`in`, OperatorWord, nil}, + Include("value"), + }, + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/smalltalk.go b/vendor/github.com/alecthomas/chroma/lexers/s/smalltalk.go index db64707..b4143d0 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/smalltalk.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/smalltalk.go @@ -6,14 +6,18 @@ import ( ) // Smalltalk lexer. -var Smalltalk = internal.Register(MustNewLexer( +var Smalltalk = internal.Register(MustNewLazyLexer( &Config{ Name: "Smalltalk", Aliases: []string{"smalltalk", "squeak", "st"}, Filenames: []string{"*.st"}, MimeTypes: []string{"text/x-smalltalk"}, }, - Rules{ + smalltalkRules, +)) + +func smalltalkRules() Rules { + return Rules{ "root": { {`(<)(\w+:)(.*?)(>)`, ByGroups(Text, Keyword, Text, Text), nil}, Include("squeak fileout"), @@ -95,5 +99,5 @@ var Smalltalk = internal.Register(MustNewLexer( {`(!\n)(\].*)(! !)$`, ByGroups(Keyword, Text, Keyword), nil}, {`! !$`, Keyword, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/smarty.go b/vendor/github.com/alecthomas/chroma/lexers/s/smarty.go index c364ffa..566efbb 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/smarty.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/smarty.go @@ -7,7 +7,7 @@ import ( ) // Smarty lexer. -var Smarty = internal.Register(MustNewLexer( +var Smarty = internal.Register(MustNewLazyLexer( &Config{ Name: "Smarty", Aliases: []string{"smarty"}, @@ -15,7 +15,11 @@ var Smarty = internal.Register(MustNewLexer( MimeTypes: []string{"application/x-smarty"}, DotAll: true, }, - Rules{ + smartyRules, +)) + +func smartyRules() Rules { + return Rules{ "root": { {`[^{]+`, Other, nil}, {`(\{)(\*.*?\*)(\})`, ByGroups(CommentPreproc, Comment, CommentPreproc), nil}, @@ -36,5 +40,5 @@ var Smarty = internal.Register(MustNewLexer( {`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil}, {`[a-zA-Z_]\w*`, NameAttribute, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/sml.go b/vendor/github.com/alecthomas/chroma/lexers/s/sml.go index f716d92..c795ea8 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/sml.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/sml.go @@ -6,14 +6,18 @@ import ( ) // Standard ML lexer. -var StandardML = internal.Register(MustNewLexer( +var StandardML = internal.Register(MustNewLazyLexer( &Config{ Name: "Standard ML", Aliases: []string{"sml"}, Filenames: []string{"*.sml", "*.sig", "*.fun"}, MimeTypes: []string{"text/x-standardml", "application/x-standardml"}, }, - Rules{ + standardMLRules, +)) + +func standardMLRules() Rules { + return Rules{ "whitespace": { {`\s+`, Text, nil}, {`\(\*`, CommentMultiline, Push("comment")}, @@ -196,5 +200,5 @@ var StandardML = internal.Register(MustNewLexer( {`\*\)`, CommentMultiline, Pop(1)}, {`[(*)]`, CommentMultiline, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/snobol.go b/vendor/github.com/alecthomas/chroma/lexers/s/snobol.go index c999b50..4529034 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/snobol.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/snobol.go @@ -6,14 +6,18 @@ import ( ) // Snobol lexer. -var Snobol = internal.Register(MustNewLexer( +var Snobol = internal.Register(MustNewLazyLexer( &Config{ Name: "Snobol", Aliases: []string{"snobol"}, Filenames: []string{"*.snobol"}, MimeTypes: []string{"text/x-snobol"}, }, - Rules{ + snobolRules, +)) + +func snobolRules() Rules { + return Rules{ "root": { {`\*.*\n`, Comment, nil}, {`[+.] `, Punctuation, Push("statement")}, @@ -44,5 +48,5 @@ var Snobol = internal.Register(MustNewLexer( "heredoc": { {`.*\n`, LiteralStringHeredoc, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/solidity.go b/vendor/github.com/alecthomas/chroma/lexers/s/solidity.go index d7cf0f9..62a3a40 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/solidity.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/solidity.go @@ -6,7 +6,7 @@ import ( ) // Solidity lexer. -var Solidity = internal.Register(MustNewLexer( +var Solidity = internal.Register(MustNewLazyLexer( &Config{ Name: "Solidity", Aliases: []string{"sol", "solidity"}, @@ -14,7 +14,11 @@ var Solidity = internal.Register(MustNewLexer( MimeTypes: []string{}, DotAll: true, }, - Rules{ + solidityRules, +)) + +func solidityRules() Rules { + return Rules{ "assembly": { Include("comments"), Include("numbers"), @@ -35,17 +39,16 @@ var Solidity = internal.Register(MustNewLexer( {`/[*][\w\W]*`, CommentMultiline, nil}, }, "keywords-other": { - {Words(``, `\b`, `for`, `in`, `while`, `do`, `break`, `return`, `returns`, `continue`, `if`, `else`, `throw`, `new`, `delete`), Keyword, nil}, + {Words(``, `\b`, `for`, `in`, `while`, `do`, `break`, `return`, `returns`, `continue`, `if`, `else`, `try`, `catch`, `throw`, `_`, `new`, `delete`, `is`, `as`, `from`, `memory`, `storage`), Keyword, nil}, {`assembly\b`, Keyword, Push("assembly")}, - {Words(``, `\b`, `contract`, `interface`, `enum`, `event`, `function`, `library`, `mapping`, `modifier`, `struct`, `var`), KeywordDeclaration, nil}, + {`(contract|interface|enum|event|struct)(\s+)([a-zA-Z_]\w*)`, ByGroups(KeywordDeclaration, Text, NameClass), nil}, + {`(function|modifier)(\s+)([a-zA-Z_]\w*)`, ByGroups(KeywordDeclaration, Text, NameFunction), nil}, + {Words(``, `\b`, `contract`, `interface`, `enum`, `event`, `constructor`, `function`, `library`, `mapping`, `modifier`, `struct`, `var`), KeywordDeclaration, nil}, + {Words(``, `\b`, `abstract`, `external`, `internal`, `private`, `public`), Keyword, nil}, + {Words(``, `\b`, `anonymous`, `constant`, `immutable`, `indexed`, `override`, `payable`, `pure`, `view`, `virtual`), Keyword, nil}, {`(import|using)\b`, KeywordNamespace, nil}, - {`pragma (solidity|experimental)\b`, KeywordReserved, nil}, - {`(_|as|constant|default|from|is)\b`, KeywordReserved, nil}, - {`payable\b`, KeywordReserved, nil}, - {`(memory|storage)\b`, KeywordReserved, nil}, - {`(external|internal|private|public)\b`, KeywordReserved, nil}, - {`(anonymous|indexed)\b`, KeywordReserved, nil}, - {`(abstract|pure|static|view)\b`, KeywordReserved, nil}, + {`pragma (solidity|experimental)\b`, Keyword, nil}, + {Words(``, `\b`, `after`, `alias`, `apply`, `auto`, `case`, `copyof`, `default`, `define`, `final`, `implements`, `inline`, `let`, `macro`, `match`, `mutable`, `null`, `of`, `partial`, `promise`, `reference`, `relocatable`, `sealed`, `sizeof`, `static`, `supports`, `switch`, `typedef`, `typeof`, `unchecked`), KeywordReserved, nil}, {`(true|false)\b`, KeywordConstant, nil}, {`(wei|finney|szabo|ether)\b`, KeywordConstant, nil}, {`(seconds|minutes|hours|days|weeks|years)\b`, KeywordConstant, nil}, @@ -95,16 +98,21 @@ var Solidity = internal.Register(MustNewLexer( {`\+\+|--|\*\*|\?|:|~|&&|\|\||=>|==?|!=?|(<<|>>>?|[-<>+*%&|^/])=?`, Operator, nil}, {`[{(\[;,]`, Punctuation, nil}, {`[})\].]`, Punctuation, nil}, - {`(block|msg|now|this|super|tx)\b`, NameBuiltin, nil}, - {`(sender|origin)\b`, NameBuiltin, nil}, - {`(gas|value)\b`, NameBuiltin, nil}, + {`(abi|block|msg|tx)\b`, NameBuiltin, nil}, + {`(?!abi\.)(decode|encode|encodePacked|encodeWithSelector|encodeWithSignature|encodeWithSelector)\b`, NameBuiltin, nil}, + {`(?!block\.)(chainid|coinbase|difficulty|gaslimit|number|timestamp)\b`, NameBuiltin, nil}, + {`(?!msg\.)(data|gas|sender|value)\b`, NameBuiltin, nil}, + {`(?!tx\.)(gasprice|origin)\b`, NameBuiltin, nil}, + {`(type)(\()([a-zA-Z_]\w*)(\))`, ByGroups(NameBuiltin, Punctuation, NameClass, Punctuation), nil}, + {`(?!type\([a-zA-Z_]\w*\)\.)(creationCode|interfaceId|max|min|name|runtimeCode)\b`, NameBuiltin, nil}, + {`(now|this|super|gasleft)\b`, NameBuiltin, nil}, {`(selfdestruct|suicide)\b`, NameBuiltin, nil}, - {`(balance|send|transfer)\b`, NameBuiltin, nil}, + {`(?!0x[0-9a-fA-F]+\.)(balance|code|codehash|send|transfer)\b`, NameBuiltin, nil}, {`(assert|revert|require)\b`, NameBuiltin, nil}, {`(call|callcode|delegatecall)\b`, NameBuiltin, nil}, {`selector\b`, NameBuiltin, nil}, - {`(addmod|ecrecover|keccak256|mulmod|ripemd160|sha256|sha3)\b`, NameFunction, nil}, + {`(addmod|blockhash|ecrecover|keccak256|mulmod|ripemd160|sha256|sha3)\b`, NameBuiltin, nil}, {`[a-zA-Z_]\w*`, Name, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/sparql.go b/vendor/github.com/alecthomas/chroma/lexers/s/sparql.go index 47a1716..eef73d9 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/sparql.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/sparql.go @@ -6,14 +6,18 @@ import ( ) // Sparql lexer. -var Sparql = internal.Register(MustNewLexer( +var Sparql = internal.Register(MustNewLazyLexer( &Config{ Name: "SPARQL", Aliases: []string{"sparql"}, Filenames: []string{"*.rq", "*.sparql"}, MimeTypes: []string{"application/sparql-query"}, }, - Rules{ + sparqlRules, +)) + +func sparqlRules() Rules { + return Rules{ "root": { {`\s+`, Text, nil}, {`((?i)select|construct|describe|ask|where|filter|group\s+by|minus|distinct|reduced|from\s+named|from|order\s+by|desc|asc|limit|offset|bindings|load|clear|drop|create|add|move|copy|insert\s+data|delete\s+data|delete\s+where|delete|insert|using\s+named|using|graph|default|named|all|optional|service|silent|bind|union|not\s+in|in|as|having|to|prefix|base)\b`, Keyword, nil}, @@ -65,5 +69,5 @@ var Sparql = internal.Register(MustNewLexer( {`\^\^`, Operator, Pop(2)}, Default(Pop(2)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/sql.go b/vendor/github.com/alecthomas/chroma/lexers/s/sql.go index 6f4e3e0..fb8c8ed 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/sql.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/sql.go @@ -6,7 +6,7 @@ import ( ) // SQL lexer. -var SQL = internal.Register(MustNewLexer( +var SQL = internal.Register(MustNewLazyLexer( &Config{ Name: "SQL", Aliases: []string{"sql"}, @@ -15,9 +15,13 @@ var SQL = internal.Register(MustNewLexer( NotMultiline: true, CaseInsensitive: true, }, - Rules{ + sqlRules, +)) + +func sqlRules() Rules { + return Rules{ "root": { - {`\s+`, Text, nil}, + {`\s+`, TextWhitespace, nil}, {`--.*\n?`, CommentSingle, nil}, {`/\*`, CommentMultiline, Push("multiline-comments")}, {`'`, LiteralStringSingle, Push("string")}, @@ -45,5 +49,5 @@ var SQL = internal.Register(MustNewLexer( {`""`, LiteralStringDouble, nil}, {`"`, LiteralStringDouble, Pop(1)}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/squid.go b/vendor/github.com/alecthomas/chroma/lexers/s/squid.go index 1f16190..b4da3da 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/s/squid.go +++ b/vendor/github.com/alecthomas/chroma/lexers/s/squid.go @@ -6,7 +6,7 @@ import ( ) // Squidconf lexer. -var Squidconf = internal.Register(MustNewLexer( +var Squidconf = internal.Register(MustNewLazyLexer( &Config{ Name: "SquidConf", Aliases: []string{"squidconf", "squid.conf", "squid"}, @@ -15,7 +15,11 @@ var Squidconf = internal.Register(MustNewLexer( NotMultiline: true, CaseInsensitive: true, }, - Rules{ + squidconfRules, +)) + +func squidconfRules() Rules { + return Rules{ "root": { {`\s+`, TextWhitespace, nil}, {`#`, Comment, Push("comment")}, @@ -34,5 +38,5 @@ var Squidconf = internal.Register(MustNewLexer( {`.+`, Comment, Pop(1)}, Default(Pop(1)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/stylus.go b/vendor/github.com/alecthomas/chroma/lexers/s/stylus.go new file mode 100644 index 0000000..159077f --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/s/stylus.go @@ -0,0 +1,66 @@ +package s + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/internal" +) + +// Stylus lexer. +var Stylus = internal.Register(MustNewLazyLexer( + &Config{ + Name: "Stylus", + Aliases: []string{"stylus"}, + Filenames: []string{"*.styl"}, + MimeTypes: []string{"text/x-styl"}, + CaseInsensitive: true, + }, + stylusRules, +)) + +func stylusRules() Rules { + return Rules{ + // "root": { + // }, + "root": { + {`([ \t]*\n|\s+)`, Text, nil}, + {`[!$][\w-]+`, NameVariable, nil}, + {`@[\w-]+`, KeywordPseudo, Push("atrule")}, + {`(\.)([\w-]+)`, ByGroups(Punctuation, NameClass), nil}, + {`for|if|else if|else|unless|return|\&`, Keyword, nil}, + {`([\w-]+)(\()`, ByGroups(NameDecorator, Punctuation), Push("function-start")}, + {`(\+)([\w-]+)(\(\))`, ByGroups(Keyword, NameDecorator, Punctuation), nil}, + {Words(``, ``, `-ms-`, `mso-`, `-moz-`, `-o-`, `-xv-`, `-atsc-`, `-wap-`, `-khtml-`, `-webkit-`, `prince-`, `-ah-`, `-hp-`, `-ro-`, `-rim-`, `-tc-`), NameProperty, nil}, + {`\b(align-content|align-items|align-self|alignment-baseline|all|animation|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|appearance|azimuth|backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|baseline-shift|bookmark-label|bookmark-level|bookmark-state|border|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-boundary|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|bottom|box-decoration-break|box-shadow|box-sizing|box-snap|box-suppress|break-after|break-before|break-inside|caption-side|caret|caret-animation|caret-color|caret-shape|chains|clear|clip|clip-path|clip-rule|color|color-interpolation-filters|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|counter-set|crop|cue|cue-after|cue-before|cursor|direction|display|dominant-baseline|elevation|empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-shrink|flex-wrap|float|float-defer|float-offset|float-reference|flood-color|flood-opacity|flow|flow-from|flow-into|font|font-family|font-feature-settings|font-kerning|font-language-override|font-size|font-size-adjust|font-stretch|font-style|font-synthesis|font-variant|font-variant-alternates|font-variant-caps|font-variant-east-asian|font-variant-ligatures|font-variant-numeric|font-variant-position|font-weight|footnote-display|footnote-policy|glyph-orientation-vertical|grid|grid-area|grid-auto-columns|grid-auto-flow|grid-auto-rows|grid-column|grid-column-end|grid-column-gap|grid-column-start|grid-gap|grid-row|grid-row-end|grid-row-gap|grid-row-start|grid-template|grid-template-areas|grid-template-columns|grid-template-rows|hanging-punctuation|height|hyphenate-character|hyphenate-limit-chars|hyphenate-limit-last|hyphenate-limit-lines|hyphenate-limit-zone|hyphens|image-orientation|image-resolution|initial-letter|initial-letter-align|initial-letter-wrap|isolation|justify-content|justify-items|justify-self|left|letter-spacing|lighting-color|line-break|line-grid|line-height|line-snap|list-style|list-style-image|list-style-position|list-style-type|margin|margin-bottom|margin-left|margin-right|margin-top|marker-side|marquee-direction|marquee-loop|marquee-speed|marquee-style|mask|mask-border|mask-border-mode|mask-border-outset|mask-border-repeat|mask-border-slice|mask-border-source|mask-border-width|mask-clip|mask-composite|mask-image|mask-mode|mask-origin|mask-position|mask-repeat|mask-size|mask-type|max-height|max-lines|max-width|min-height|min-width|mix-blend-mode|motion|motion-offset|motion-path|motion-rotation|move-to|nav-down|nav-left|nav-right|nav-up|object-fit|object-position|offset-after|offset-before|offset-end|offset-start|opacity|order|orphans|outline|outline-color|outline-offset|outline-style|outline-width|overflow|overflow-style|overflow-wrap|overflow-x|overflow-y|padding|padding-bottom|padding-left|padding-right|padding-top|page|page-break-after|page-break-before|page-break-inside|page-policy|pause|pause-after|pause-before|perspective|perspective-origin|pitch|pitch-range|play-during|polar-angle|polar-distance|position|presentation-level|quotes|region-fragment|resize|rest|rest-after|rest-before|richness|right|rotation|rotation-point|ruby-align|ruby-merge|ruby-position|running|scroll-snap-coordinate|scroll-snap-destination|scroll-snap-points-x|scroll-snap-points-y|scroll-snap-type|shape-image-threshold|shape-inside|shape-margin|shape-outside|size|speak|speak-as|speak-header|speak-numeral|speak-punctuation|speech-rate|stress|string-set|tab-size|table-layout|text-align|text-align-last|text-combine-upright|text-decoration|text-decoration-color|text-decoration-line|text-decoration-skip|text-decoration-style|text-emphasis|text-emphasis-color|text-emphasis-position|text-emphasis-style|text-indent|text-justify|text-orientation|text-overflow|text-shadow|text-space-collapse|text-space-trim|text-spacing|text-transform|text-underline-position|text-wrap|top|transform|transform-origin|transform-style|transition|transition-delay|transition-duration|transition-property|transition-timing-function|unicode-bidi|user-select|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch|voice-range|voice-rate|voice-stress|voice-volume|volume|white-space|widows|width|will-change|word-break|word-spacing|word-wrap|wrap-after|wrap-before|wrap-flow|wrap-inside|wrap-through|writing-mode|z-index)\b(\:)?`, ByGroups(NameProperty, Punctuation), Push("values")}, + {`\b(a|abbr|acronym|address|applet|area|article|aside|audio|b|base(?:front)?|bd(?:i|o)|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|data|datalist|d(?:d|l|t)|del|details|dfn|dialog|dir|div|em(?:bed)?|fieldset|fig(?:caption|ure)|font|footer|form|frame(?:set)?|h[1-6]+|head(?:er)?|hr|html|i|iframe|img|input|ins|kbd|label|legend|li|link|main|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|picture|pre|progress|q|r(?:p|t|uby)|s|samp|script|section|select|small|source|span|strike|strong|style|sub|summary|sup|svg|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr)\b`, NameTag, nil}, + {Words(`\b`, `\b`, `above`, `aural`, `behind`, `bidi-override`, `center-left`, `center-right`, `cjk-ideographic`, `continuous`, `crop`, `cross`, `embed`, `far-left`, `far-right`, `fast`, `faster`, `hebrew`, `high`, `higher`, `hiragana`, `hiragana-iroha`, `katakana`, `katakana-iroha`, `landscape`, `left-side`, `leftwards`, `level`, `loud`, `low`, `lower`, `message-box`, `middle`, `mix`, `narrower`, `once`, `portrait`, `right-side`, `rightwards`, `silent`, `slow`, `slower`, `small-caption`, `soft`, `spell-out`, `status-bar`, `super`, `text-bottom`, `text-top`, `wider`, `x-fast`, `x-high`, `x-loud`, `x-low`, `x-soft`, `yes`, `pre`, `pre-wrap`, `pre-line`), KeywordConstant, nil}, + {Words(`\b`, `\b`, `aliceblue`, `antiquewhite`, `aqua`, `aquamarine`, `azure`, `beige`, `bisque`, `black`, `blanchedalmond`, `blue`, `blueviolet`, `brown`, `burlywood`, `cadetblue`, `chartreuse`, `chocolate`, `coral`, `cornflowerblue`, `cornsilk`, `crimson`, `cyan`, `darkblue`, `darkcyan`, `darkgoldenrod`, `darkgray`, `darkgreen`, `darkgrey`, `darkkhaki`, `darkmagenta`, `darkolivegreen`, `darkorange`, `darkorchid`, `darkred`, `darksalmon`, `darkseagreen`, `darkslateblue`, `darkslategray`, `darkslategrey`, `darkturquoise`, `darkviolet`, `deeppink`, `deepskyblue`, `dimgray`, `dimgrey`, `dodgerblue`, `firebrick`, `floralwhite`, `forestgreen`, `fuchsia`, `gainsboro`, `ghostwhite`, `gold`, `goldenrod`, `gray`, `green`, `greenyellow`, `grey`, `honeydew`, `hotpink`, `indianred`, `indigo`, `ivory`, `khaki`, `lavender`, `lavenderblush`, `lawngreen`, `lemonchiffon`, `lightblue`, `lightcoral`, `lightcyan`, `lightgoldenrodyellow`, `lightgray`, `lightgreen`, `lightgrey`, `lightpink`, `lightsalmon`, `lightseagreen`, `lightskyblue`, `lightslategray`, `lightslategrey`, `lightsteelblue`, `lightyellow`, `lime`, `limegreen`, `linen`, `magenta`, `maroon`, `mediumaquamarine`, `mediumblue`, `mediumorchid`, `mediumpurple`, `mediumseagreen`, `mediumslateblue`, `mediumspringgreen`, `mediumturquoise`, `mediumvioletred`, `midnightblue`, `mintcream`, `mistyrose`, `moccasin`, `navajowhite`, `navy`, `oldlace`, `olive`, `olivedrab`, `orange`, `orangered`, `orchid`, `palegoldenrod`, `palegreen`, `paleturquoise`, `palevioletred`, `papayawhip`, `peachpuff`, `peru`, `pink`, `plum`, `powderblue`, `purple`, `rebeccapurple`, `red`, `rosybrown`, `royalblue`, `saddlebrown`, `salmon`, `sandybrown`, `seagreen`, `seashell`, `sienna`, `silver`, `skyblue`, `slateblue`, `slategray`, `slategrey`, `snow`, `springgreen`, `steelblue`, `tan`, `teal`, `thistle`, `tomato`, `turquoise`, `violet`, `wheat`, `white`, `whitesmoke`, `yellow`, `yellowgreen`, `transparent`), KeywordConstant, nil}, + {`(\{|\}|\(|\)|\[|\]|,|:|;)`, Punctuation, nil}, + {`(\.|\!|\-|\+|\~|\*\*|\*|\/|\%|\.\.\.|\.\.|\<\=|\>\=|\<|\>|\=\=|\!\=|\&\&|\|\||\=|\:\=|\?\=|\+\=|\-\=|\*\=|\/\=|\%\=|\?|\:)`, Operator, nil}, + {`\b(and|if unless|in|is|is a|is defined|is not|isnt|or|not)\b`, OperatorWord, nil}, + {`(\#[a-f0-9]{3,6})`, LiteralNumberHex, nil}, + {`\n`, Text, nil}, + }, + "inline-comment": { + {`\*/`, Comment, Pop(1)}, + }, + "atrule": { + {`\{`, Punctuation, Push("atcontent")}, + {`$`, Punctuation, Pop(1)}, + Include("root"), + }, + "atcontent": { + Include("root"), + {`\}`, Punctuation, Pop(2)}, + }, + "function-start": { + {`\)`, Punctuation, Pop(1)}, + Include("root"), + }, + "values": { + {`\s+`, Text, nil}, + {`(\#[a-f0-9]{3,6})`, LiteralNumberHex, nil}, + {Words(`\b`, `\b`, `absolute`, `alias`, `all`, `all-petite-caps`, `all-scroll`, `all-small-caps`, `allow-end`, `alpha`, `alternate`, `alternate-reverse`, `always`, `armenian`, `auto`, `avoid`, `avoid-column`, `avoid-page`, `backwards`, `balance`, `baseline`, `below`, `blink`, `block`, `bold`, `bolder`, `border-box`, `both`, `bottom`, `box-decoration`, `break-word`, `capitalize`, `cell`, `center`, `circle`, `clip`, `clone`, `close-quote`, `col-resize`, `collapse`, `color`, `color-burn`, `color-dodge`, `column`, `column-reverse`, `compact`, `condensed`, `contain`, `container`, `content-box`, `context-menu`, `copy`, `cover`, `crisp-edges`, `crosshair`, `currentColor`, `cursive`, `darken`, `dashed`, `decimal`, `decimal-leading-zero`, `default`, `descendants`, `difference`, `digits`, `disc`, `distribute`, `dot`, `dotted`, `double`, `double-circle`, `e-resize`, `each-line`, `ease`, `ease-in`, `ease-in-out`, `ease-out`, `edges`, `ellipsis`, `end`, `ew-resize`, `exclusion`, `expanded`, `extra-condensed`, `extra-expanded`, `fantasy`, `fill`, `fill-box`, `filled`, `first`, `fixed`, `flat`, `flex`, `flex-end`, `flex-start`, `flip`, `force-end`, `forwards`, `from-image`, `full-width`, `geometricPrecision`, `georgian`, `groove`, `hanging`, `hard-light`, `help`, `hidden`, `hide`, `horizontal`, `hue`, `icon`, `infinite`, `inherit`, `initial`, `ink`, `inline`, `inline-block`, `inline-flex`, `inline-table`, `inset`, `inside`, `inter-word`, `invert`, `isolate`, `italic`, `justify`, `large`, `larger`, `last`, `left`, `lighten`, `lighter`, `line-through`, `linear`, `list-item`, `local`, `loose`, `lower-alpha`, `lower-greek`, `lower-latin`, `lower-roman`, `lowercase`, `ltr`, `luminance`, `luminosity`, `mandatory`, `manipulation`, `manual`, `margin-box`, `match-parent`, `medium`, `mixed`, `monospace`, `move`, `multiply`, `n-resize`, `ne-resize`, `nesw-resize`, `no-close-quote`, `no-drop`, `no-open-quote`, `no-repeat`, `none`, `normal`, `not-allowed`, `nowrap`, `ns-resize`, `nw-resize`, `nwse-resize`, `objects`, `oblique`, `off`, `on`, `open`, `open-quote`, `optimizeLegibility`, `optimizeSpeed`, `outset`, `outside`, `over`, `overlay`, `overline`, `padding-box`, `page`, `pan-down`, `pan-left`, `pan-right`, `pan-up`, `pan-x`, `pan-y`, `paused`, `petite-caps`, `pixelated`, `pointer`, `preserve-3d`, `progress`, `proximity`, `relative`, `repeat`, `repeat no-repeat`, `repeat-x`, `repeat-y`, `reverse`, `ridge`, `right`, `round`, `row`, `row-resize`, `row-reverse`, `rtl`, `ruby`, `ruby-base`, `ruby-base-container`, `ruby-text`, `ruby-text-container`, `run-in`, `running`, `s-resize`, `sans-serif`, `saturation`, `scale-down`, `screen`, `scroll`, `se-resize`, `semi-condensed`, `semi-expanded`, `separate`, `serif`, `sesame`, `show`, `sideways`, `sideways-left`, `sideways-right`, `slice`, `small`, `small-caps`, `smaller`, `smooth`, `snap`, `soft-light`, `solid`, `space`, `space-around`, `space-between`, `spaces`, `square`, `start`, `static`, `step-end`, `step-start`, `sticky`, `stretch`, `strict`, `stroke-box`, `style`, `sw-resize`, `table`, `table-caption`, `table-cell`, `table-column`, `table-column-group`, `table-footer-group`, `table-header-group`, `table-row`, `table-row-group`, `text`, `thick`, `thin`, `titling-caps`, `to`, `top`, `triangle`, `ultra-condensed`, `ultra-expanded`, `under`, `underline`, `unicase`, `unset`, `upper-alpha`, `upper-latin`, `upper-roman`, `uppercase`, `upright`, `use-glyph-orientation`, `vertical`, `vertical-text`, `view-box`, `visible`, `w-resize`, `wait`, `wavy`, `weight`, `weight style`, `wrap`, `wrap-reverse`, `x-large`, `x-small`, `xx-large`, `xx-small`, `zoom-in`, `zoom-out`), KeywordConstant, nil}, + {`\;?`, Punctuation, Pop(1)}, + }, + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/s/svelte.go b/vendor/github.com/alecthomas/chroma/lexers/s/svelte.go new file mode 100644 index 0000000..1f91a21 --- /dev/null +++ b/vendor/github.com/alecthomas/chroma/lexers/s/svelte.go @@ -0,0 +1,73 @@ +package s + +import ( + . "github.com/alecthomas/chroma" // nolint + "github.com/alecthomas/chroma/lexers/h" + "github.com/alecthomas/chroma/lexers/internal" + "github.com/alecthomas/chroma/lexers/t" +) + +// Svelte lexer. +var Svelte = internal.Register(DelegatingLexer(h.HTML, MustNewLazyLexer( + &Config{ + Name: "Svelte", + Aliases: []string{"svelte"}, + Filenames: []string{"*.svelte"}, + MimeTypes: []string{"application/x-svelte"}, + DotAll: true, + }, + svelteRules, +))) + +func svelteRules() Rules { + return Rules{ + "root": { + // Let HTML handle the comments, including comments containing script and style tags + {``, Other, Pop(1)}, + {`.+?`, Other, nil}, + }, + "templates": { + {`}`, Punctuation, Pop(1)}, + // Let TypeScript handle strings and the curly braces inside them + {`(?\"{}|^`\\\\\\x00-\\x20]*>)(\\s*)(\\.?)", ByGroups(Keyword, TextWhitespace, NameVariable, TextWhitespace, Punctuation), nil}, @@ -63,5 +67,5 @@ var Turtle = internal.Register(MustNewLexer( {`(\^\^)((?:[a-z][\w-]*)?\:)([a-z][\w-]*)`, ByGroups(Operator, GenericEmph, GenericEmph), Pop(2)}, Default(Pop(2)), }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/t/twig.go b/vendor/github.com/alecthomas/chroma/lexers/t/twig.go index 56aa9b9..0e0c1f1 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/t/twig.go +++ b/vendor/github.com/alecthomas/chroma/lexers/t/twig.go @@ -6,7 +6,7 @@ import ( ) // Twig lexer. -var Twig = internal.Register(MustNewLexer( +var Twig = internal.Register(MustNewLazyLexer( &Config{ Name: "Twig", Aliases: []string{"twig"}, @@ -14,7 +14,11 @@ var Twig = internal.Register(MustNewLexer( MimeTypes: []string{"application/x-twig"}, DotAll: true, }, - Rules{ + twigRules, +)) + +func twigRules() Rules { + return Rules{ "root": { {`[^{]+`, Other, nil}, {`\{\{`, CommentPreproc, Push("var")}, @@ -50,5 +54,5 @@ var Twig = internal.Register(MustNewLexer( Include("varnames"), {`.`, Punctuation, nil}, }, - }, -)) + } +} diff --git a/vendor/github.com/alecthomas/chroma/lexers/t/typescript.go b/vendor/github.com/alecthomas/chroma/lexers/t/typescript.go index 5205e01..0625bb0 100644 --- a/vendor/github.com/alecthomas/chroma/lexers/t/typescript.go +++ b/vendor/github.com/alecthomas/chroma/lexers/t/typescript.go @@ -6,7 +6,7 @@ import ( ) // TypeScript lexer. -var TypeScript = internal.Register(MustNewLexer( +var TypeScript = internal.Register(MustNewLazyLexer( &Config{ Name: "TypeScript", Aliases: []string{"ts", "tsx", "typescript"}, @@ -15,7 +15,11 @@ var TypeScript = internal.Register(MustNewLexer( DotAll: true, EnsureNL: true, }, - Rules{ + typeScriptRules, +)) + +func typeScriptRules() Rules { + return Rules{ "commentsandwhitespace": { {`\s+`, Text, nil}, {` which includes the use of that to permit +// conditionals as per https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/ms537512(v=vs.85)?redirectedfrom=MSDN +// +// What is not permitted are CDATA XML comments, as the x/net/html package we depend +// on does not handle this fully and we are not choosing to take on that work: +// https://pkg.go.dev/golang.org/x/net/html#Tokenizer.AllowCDATA . If the x/net/html +// package changes this then these will be considered, otherwise if you AllowComments +// but provide a CDATA comment, then as per the documentation in x/net/html this will +// be treated as a plain HTML comment. +func (p *Policy) AllowComments() { + p.allowComments = true +} + // AllowNoAttrs says that attributes on element are optional. // // The attribute policy is only added to the core policy when OnElements(...) @@ -262,8 +286,7 @@ func (abp *attrPolicyBuilder) AllowNoAttrs() *attrPolicyBuilder { } // Matching allows a regular expression to be applied to a nascent attribute -// policy, and returns the attribute policy. Calling this more than once will -// replace the existing regexp. +// policy, and returns the attribute policy. func (abp *attrPolicyBuilder) Matching(regex *regexp.Regexp) *attrPolicyBuilder { abp.regexp = regex @@ -281,7 +304,7 @@ func (abp *attrPolicyBuilder) OnElements(elements ...string) *Policy { for _, attr := range abp.attrNames { if _, ok := abp.p.elsAndAttrs[element]; !ok { - abp.p.elsAndAttrs[element] = make(map[string]attrPolicy) + abp.p.elsAndAttrs[element] = make(map[string][]attrPolicy) } ap := attrPolicy{} @@ -289,14 +312,14 @@ func (abp *attrPolicyBuilder) OnElements(elements ...string) *Policy { ap.regexp = abp.regexp } - abp.p.elsAndAttrs[element][attr] = ap + abp.p.elsAndAttrs[element][attr] = append(abp.p.elsAndAttrs[element][attr], ap) } if abp.allowEmpty { abp.p.setOfElementsAllowedWithoutAttrs[element] = struct{}{} if _, ok := abp.p.elsAndAttrs[element]; !ok { - abp.p.elsAndAttrs[element] = make(map[string]attrPolicy) + abp.p.elsAndAttrs[element] = make(map[string][]attrPolicy) } } } @@ -309,19 +332,19 @@ func (abp *attrPolicyBuilder) OnElements(elements ...string) *Policy { func (abp *attrPolicyBuilder) OnElementsMatching(regex *regexp.Regexp) *Policy { for _, attr := range abp.attrNames { if _, ok := abp.p.elsMatchingAndAttrs[regex]; !ok { - abp.p.elsMatchingAndAttrs[regex] = make(map[string]attrPolicy) + abp.p.elsMatchingAndAttrs[regex] = make(map[string][]attrPolicy) } ap := attrPolicy{} if abp.regexp != nil { ap.regexp = abp.regexp } - abp.p.elsMatchingAndAttrs[regex][attr] = ap + abp.p.elsMatchingAndAttrs[regex][attr] = append(abp.p.elsMatchingAndAttrs[regex][attr], ap) } if abp.allowEmpty { abp.p.setOfElementsMatchingAllowedWithoutAttrs = append(abp.p.setOfElementsMatchingAllowedWithoutAttrs, regex) if _, ok := abp.p.elsMatchingAndAttrs[regex]; !ok { - abp.p.elsMatchingAndAttrs[regex] = make(map[string]attrPolicy) + abp.p.elsMatchingAndAttrs[regex] = make(map[string][]attrPolicy) } } @@ -334,7 +357,7 @@ func (abp *attrPolicyBuilder) Globally() *Policy { for _, attr := range abp.attrNames { if _, ok := abp.p.globalAttrs[attr]; !ok { - abp.p.globalAttrs[attr] = attrPolicy{} + abp.p.globalAttrs[attr] = []attrPolicy{} } ap := attrPolicy{} @@ -342,7 +365,7 @@ func (abp *attrPolicyBuilder) Globally() *Policy { ap.regexp = abp.regexp } - abp.p.globalAttrs[attr] = ap + abp.p.globalAttrs[attr] = append(abp.p.globalAttrs[attr], ap) } return abp.p @@ -350,7 +373,7 @@ func (abp *attrPolicyBuilder) Globally() *Policy { // AllowStyles takes a range of CSS property names and returns a // style policy builder that allows you to specify the pattern and scope of -// the whitelisted property. +// the allowed property. // // The style policy is only added to the core policy when either Globally() // or OnElements(...) are called. @@ -370,8 +393,7 @@ func (p *Policy) AllowStyles(propertyNames ...string) *stylePolicyBuilder { } // Matching allows a regular expression to be applied to a nascent style -// policy, and returns the style policy. Calling this more than once will -// replace the existing regexp. +// policy, and returns the style policy. func (spb *stylePolicyBuilder) Matching(regex *regexp.Regexp) *stylePolicyBuilder { spb.regexp = regex @@ -380,8 +402,7 @@ func (spb *stylePolicyBuilder) Matching(regex *regexp.Regexp) *stylePolicyBuilde } // MatchingEnum allows a list of allowed values to be applied to a nascent style -// policy, and returns the style policy. Calling this more than once will -// replace the existing list of allowed values. +// policy, and returns the style policy. func (spb *stylePolicyBuilder) MatchingEnum(enum ...string) *stylePolicyBuilder { spb.enum = enum @@ -390,8 +411,7 @@ func (spb *stylePolicyBuilder) MatchingEnum(enum ...string) *stylePolicyBuilder } // MatchingHandler allows a handler to be applied to a nascent style -// policy, and returns the style policy. Calling this more than once will -// replace the existing handler. +// policy, and returns the style policy. func (spb *stylePolicyBuilder) MatchingHandler(handler func(string) bool) *stylePolicyBuilder { spb.handler = handler @@ -409,7 +429,7 @@ func (spb *stylePolicyBuilder) OnElements(elements ...string) *Policy { for _, attr := range spb.propertyNames { if _, ok := spb.p.elsAndStyles[element]; !ok { - spb.p.elsAndStyles[element] = make(map[string]stylePolicy) + spb.p.elsAndStyles[element] = make(map[string][]stylePolicy) } sp := stylePolicy{} @@ -420,9 +440,9 @@ func (spb *stylePolicyBuilder) OnElements(elements ...string) *Policy { } else if spb.regexp != nil { sp.regexp = spb.regexp } else { - sp.handler = getDefaultHandler(attr) + sp.handler = css.GetDefaultHandler(attr) } - spb.p.elsAndStyles[element][attr] = sp + spb.p.elsAndStyles[element][attr] = append(spb.p.elsAndStyles[element][attr], sp) } } @@ -433,25 +453,25 @@ func (spb *stylePolicyBuilder) OnElements(elements ...string) *Policy { // and return the updated policy func (spb *stylePolicyBuilder) OnElementsMatching(regex *regexp.Regexp) *Policy { - for _, attr := range spb.propertyNames { + for _, attr := range spb.propertyNames { - if _, ok := spb.p.elsMatchingAndStyles[regex]; !ok { - spb.p.elsMatchingAndStyles[regex] = make(map[string]stylePolicy) - } - - sp := stylePolicy{} - if spb.handler != nil { - sp.handler = spb.handler - } else if len(spb.enum) > 0 { - sp.enum = spb.enum - } else if spb.regexp != nil { - sp.regexp = spb.regexp - } else { - sp.handler = getDefaultHandler(attr) - } - spb.p.elsMatchingAndStyles[regex][attr] = sp + if _, ok := spb.p.elsMatchingAndStyles[regex]; !ok { + spb.p.elsMatchingAndStyles[regex] = make(map[string][]stylePolicy) } + sp := stylePolicy{} + if spb.handler != nil { + sp.handler = spb.handler + } else if len(spb.enum) > 0 { + sp.enum = spb.enum + } else if spb.regexp != nil { + sp.regexp = spb.regexp + } else { + sp.handler = css.GetDefaultHandler(attr) + } + spb.p.elsMatchingAndStyles[regex][attr] = append(spb.p.elsMatchingAndStyles[regex][attr], sp) + } + return spb.p } @@ -461,7 +481,7 @@ func (spb *stylePolicyBuilder) Globally() *Policy { for _, attr := range spb.propertyNames { if _, ok := spb.p.globalStyles[attr]; !ok { - spb.p.globalStyles[attr] = stylePolicy{} + spb.p.globalStyles[attr] = []stylePolicy{} } // Use only one strategy for validating styles, fallback to default @@ -473,15 +493,15 @@ func (spb *stylePolicyBuilder) Globally() *Policy { } else if spb.regexp != nil { sp.regexp = spb.regexp } else { - sp.handler = getDefaultHandler(attr) + sp.handler = css.GetDefaultHandler(attr) } - spb.p.globalStyles[attr] = sp + spb.p.globalStyles[attr] = append(spb.p.globalStyles[attr], sp) } return spb.p } -// AllowElements will append HTML elements to the whitelist without applying an +// AllowElements will append HTML elements to the allowlist without applying an // attribute policy to those elements (the elements are permitted // sans-attributes) func (p *Policy) AllowElements(names ...string) *Policy { @@ -491,17 +511,19 @@ func (p *Policy) AllowElements(names ...string) *Policy { element = strings.ToLower(element) if _, ok := p.elsAndAttrs[element]; !ok { - p.elsAndAttrs[element] = make(map[string]attrPolicy) + p.elsAndAttrs[element] = make(map[string][]attrPolicy) } } return p } +// AllowElementsMatching will append HTML elements to the allowlist if they +// match a regexp. func (p *Policy) AllowElementsMatching(regex *regexp.Regexp) *Policy { p.init() if _, ok := p.elsMatchingAndAttrs[regex]; !ok { - p.elsMatchingAndAttrs[regex] = make(map[string]attrPolicy) + p.elsMatchingAndAttrs[regex] = make(map[string][]attrPolicy) } return p } @@ -558,6 +580,16 @@ func (p *Policy) RequireNoReferrerOnFullyQualifiedLinks(require bool) *Policy { return p } +// RequireCrossOriginAnonymous will result in all audio, img, link, script, and +// video tags having a crossorigin="anonymous" added to them if one does not +// already exist +func (p *Policy) RequireCrossOriginAnonymous(require bool) *Policy { + + p.requireCrossOriginAnonymous = require + + return p +} + // AddTargetBlankToFullyQualifiedLinks will result in all a, area and link tags // that point to a non-local destination (i.e. starts with a protocol and has a // host) having a target="_blank" added to them if one does not already exist @@ -598,7 +630,7 @@ func (p *Policy) AllowRelativeURLs(require bool) *Policy { return p } -// AllowURLSchemes will append URL schemes to the whitelist +// AllowURLSchemes will append URL schemes to the allowlist // Example: p.AllowURLSchemes("mailto", "http", "https") func (p *Policy) AllowURLSchemes(schemes ...string) *Policy { p.init() @@ -616,7 +648,7 @@ func (p *Policy) AllowURLSchemes(schemes ...string) *Policy { } // AllowURLSchemeWithCustomPolicy will append URL schemes with -// a custom URL policy to the whitelist. +// a custom URL policy to the allowlist. // Only the URLs with matching schema and urlPolicy(url) // returning true will be allowed. func (p *Policy) AllowURLSchemeWithCustomPolicy( @@ -630,13 +662,13 @@ func (p *Policy) AllowURLSchemeWithCustomPolicy( scheme = strings.ToLower(scheme) - p.allowURLSchemes[scheme] = urlPolicy + p.allowURLSchemes[scheme] = append(p.allowURLSchemes[scheme], urlPolicy) return p } // AddSpaceWhenStrippingTag states whether to add a single space " " when -// removing tags that are not whitelisted by the policy. +// removing tags that are not allowed by the policy. // // This is useful if you expect to strip tags in dense markup and may lose the // value of whitespace. diff --git a/vendor/github.com/microcosm-cc/bluemonday/sanitize.go b/vendor/github.com/microcosm-cc/bluemonday/sanitize.go index 103f39f..5f4b60d 100644 --- a/vendor/github.com/microcosm-cc/bluemonday/sanitize.go +++ b/vendor/github.com/microcosm-cc/bluemonday/sanitize.go @@ -31,6 +31,7 @@ package bluemonday import ( "bytes" + "fmt" "io" "net/url" "regexp" @@ -39,7 +40,7 @@ import ( "golang.org/x/net/html" - cssparser "github.com/chris-ramon/douceur/parser" + "github.com/aymerick/douceur/parser" ) var ( @@ -47,10 +48,11 @@ var ( dataAttributeXMLPrefix = regexp.MustCompile("^xml.+") dataAttributeInvalidChars = regexp.MustCompile("[A-Z;]+") cssUnicodeChar = regexp.MustCompile(`\\[0-9a-f]{1,6} ?`) + dataURIbase64Prefix = regexp.MustCompile(`^data:[^,]*;base64,`) ) // Sanitize takes a string that contains a HTML fragment or document and applies -// the given policy whitelist. +// the given policy allowlist. // // It returns a HTML string that has been sanitized by the policy or an empty // string if an error has occurred (most likely as a consequence of extremely @@ -60,11 +62,11 @@ func (p *Policy) Sanitize(s string) string { return s } - return p.sanitize(strings.NewReader(s)).String() + return p.sanitizeWithBuff(strings.NewReader(s)).String() } // SanitizeBytes takes a []byte that contains a HTML fragment or document and applies -// the given policy whitelist. +// the given policy allowlist. // // It returns a []byte containing the HTML that has been sanitized by the policy // or an empty []byte if an error has occurred (most likely as a consequence of @@ -74,26 +76,32 @@ func (p *Policy) SanitizeBytes(b []byte) []byte { return b } - return p.sanitize(bytes.NewReader(b)).Bytes() + return p.sanitizeWithBuff(bytes.NewReader(b)).Bytes() } // SanitizeReader takes an io.Reader that contains a HTML fragment or document -// and applies the given policy whitelist. +// and applies the given policy allowlist. // // It returns a bytes.Buffer containing the HTML that has been sanitized by the // policy. Errors during sanitization will merely return an empty result. func (p *Policy) SanitizeReader(r io.Reader) *bytes.Buffer { - return p.sanitize(r) + return p.sanitizeWithBuff(r) +} + +// SanitizeReaderToWriter takes an io.Reader that contains a HTML fragment or document +// and applies the given policy allowlist and writes to the provided writer returning +// an error if there is one. +func (p *Policy) SanitizeReaderToWriter(r io.Reader, w io.Writer) error { + return p.sanitize(r, w) } const escapedURLChars = "'<>\"\r" -func escapeUrlComponent(val string) string { - w := bytes.NewBufferString("") +func escapeUrlComponent(w stringWriterWriter, val string) error { i := strings.IndexAny(val, escapedURLChars) for i != -1 { if _, err := w.WriteString(val[:i]); err != nil { - return w.String() + return err } var esc string switch val[i] { @@ -114,73 +122,119 @@ func escapeUrlComponent(val string) string { } val = val[i+1:] if _, err := w.WriteString(esc); err != nil { - return w.String() + return err } i = strings.IndexAny(val, escapedURLChars) } - w.WriteString(val) - return w.String() + _, err := w.WriteString(val) + return err } -func sanitizedUrl(val string) (string, error) { +// Query represents a single part of the query string, a query param +type Query struct { + Key string + Value string + HasValue bool +} + +func parseQuery(query string) (values []Query, err error) { + // This is essentially a copy of parseQuery from + // https://golang.org/src/net/url/url.go but adjusted to build our values + // based on our type, which we need to preserve the ordering of the query + // string + for query != "" { + key := query + if i := strings.IndexAny(key, "&;"); i >= 0 { + key, query = key[:i], key[i+1:] + } else { + query = "" + } + if key == "" { + continue + } + value := "" + hasValue := false + if i := strings.Index(key, "="); i >= 0 { + key, value = key[:i], key[i+1:] + hasValue = true + } + key, err1 := url.QueryUnescape(key) + if err1 != nil { + if err == nil { + err = err1 + } + continue + } + value, err1 = url.QueryUnescape(value) + if err1 != nil { + if err == nil { + err = err1 + } + continue + } + values = append(values, Query{ + Key: key, + Value: value, + HasValue: hasValue, + }) + } + return values, err +} + +func encodeQueries(queries []Query) string { + var buff bytes.Buffer + for i, query := range queries { + buff.WriteString(url.QueryEscape(query.Key)) + if query.HasValue { + buff.WriteString("=") + buff.WriteString(url.QueryEscape(query.Value)) + } + if i < len(queries)-1 { + buff.WriteString("&") + } + } + return buff.String() +} + +func sanitizedURL(val string) (string, error) { u, err := url.Parse(val) if err != nil { return "", err } - // sanitize the url query params - sanitizedQueryValues := make(url.Values, 0) - queryValues := u.Query() - for k, vals := range queryValues { - sk := html.EscapeString(k) - for _, v := range vals { - sv := v - sanitizedQueryValues.Add(sk, sv) - } + + // we use parseQuery but not u.Query to keep the order not change because + // url.Values is a map which has a random order. + queryValues, err := parseQuery(u.RawQuery) + if err != nil { + return "", err } - u.RawQuery = sanitizedQueryValues.Encode() + // sanitize the url query params + for i, query := range queryValues { + queryValues[i].Key = html.EscapeString(query.Key) + } + u.RawQuery = encodeQueries(queryValues) // u.String() will also sanitize host/scheme/user/pass return u.String(), nil } -func (p *Policy) writeLinkableBuf(buff *bytes.Buffer, token *html.Token) { - // do not escape multiple query parameters - tokenBuff := bytes.NewBufferString("") - tokenBuff.WriteString("<") - tokenBuff.WriteString(token.Data) - for _, attr := range token.Attr { - tokenBuff.WriteByte(' ') - tokenBuff.WriteString(attr.Key) - tokenBuff.WriteString(`="`) - switch attr.Key { - case "href", "src": - u, ok := p.validURL(attr.Val) - if !ok { - tokenBuff.WriteString(html.EscapeString(attr.Val)) - continue - } - u, err := sanitizedUrl(u) - if err == nil { - tokenBuff.WriteString(u) - } else { - // fallthrough - tokenBuff.WriteString(html.EscapeString(attr.Val)) - } - default: - // re-apply - tokenBuff.WriteString(html.EscapeString(attr.Val)) - } - tokenBuff.WriteByte('"') +// Performs the actual sanitization process. +func (p *Policy) sanitizeWithBuff(r io.Reader) *bytes.Buffer { + var buff bytes.Buffer + if err := p.sanitize(r, &buff); err != nil { + return &bytes.Buffer{} } - if token.Type == html.SelfClosingTagToken { - tokenBuff.WriteString("/") - } - tokenBuff.WriteString(">") - buff.WriteString(tokenBuff.String()) + return &buff } -// Performs the actual sanitization process. -func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { +type asStringWriter struct { + io.Writer +} +func (a *asStringWriter) WriteString(s string) (int, error) { + return a.Write([]byte(s)) +} + +func (p *Policy) sanitize(r io.Reader, w io.Writer) error { // It is possible that the developer has created the policy via: // p := bluemonday.Policy{} // rather than: @@ -189,8 +243,12 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { // would initiliaze the maps, then we need to do that. p.init() + buff, ok := w.(stringWriterWriter) + if !ok { + buff = &asStringWriter{w} + } + var ( - buff bytes.Buffer skipElementContent bool skippingElementsCount int64 skipClosingTag bool @@ -204,11 +262,11 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { err := tokenizer.Err() if err == io.EOF { // End of input means end of processing - return &buff + return nil } // Raw tokenizer error - return &bytes.Buffer{} + return err } token := tokenizer.Token() @@ -226,10 +284,14 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { case html.CommentToken: // Comments are ignored by default + if p.allowComments { + // But if allowed then write the comment out as-is + buff.WriteString(token.String()) + } case html.StartTagToken: - mostRecentlyStartedToken = strings.ToLower(token.Data) + mostRecentlyStartedToken = normaliseElementName(token.Data) aps, ok := p.elsAndAttrs[token.Data] if !ok { @@ -240,14 +302,18 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { skippingElementsCount++ } if p.addSpaces { - buff.WriteString(" ") + if _, err := buff.WriteString(" "); err != nil { + return err + } } break } aps = aa } if len(token.Attr) != 0 { - token.Attr = p.sanitizeAttrs(token.Data, token.Attr, aps) + token.Attr = escapeAttributes( + p.sanitizeAttrs(token.Data, token.Attr, aps), + ) } if len(token.Attr) == 0 { @@ -255,24 +321,23 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { skipClosingTag = true closingTagToSkipStack = append(closingTagToSkipStack, token.Data) if p.addSpaces { - buff.WriteString(" ") + if _, err := buff.WriteString(" "); err != nil { + return err + } } break } } if !skipElementContent { - // do not escape multiple query parameters - if linkable(token.Data) { - p.writeLinkableBuf(&buff, &token) - } else { - buff.WriteString(token.String()) + if _, err := buff.WriteString(token.String()); err != nil { + return err } } case html.EndTagToken: - if mostRecentlyStartedToken == strings.ToLower(token.Data) { + if mostRecentlyStartedToken == normaliseElementName(token.Data) { mostRecentlyStartedToken = "" } @@ -282,7 +347,9 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { skipClosingTag = false } if p.addSpaces { - buff.WriteString(" ") + if _, err := buff.WriteString(" "); err != nil { + return err + } } break } @@ -303,14 +370,18 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { } if !match { if p.addSpaces { - buff.WriteString(" ") + if _, err := buff.WriteString(" "); err != nil { + return err + } } break } } if !skipElementContent { - buff.WriteString(token.String()) + if _, err := buff.WriteString(token.String()); err != nil { + return err + } } case html.SelfClosingTagToken: @@ -320,7 +391,9 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { aa, matched := p.matchRegex(token.Data) if !matched { if p.addSpaces && !matched { - buff.WriteString(" ") + if _, err := buff.WriteString(" "); err != nil { + return err + } } break } @@ -328,21 +401,20 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { } if len(token.Attr) != 0 { - token.Attr = p.sanitizeAttrs(token.Data, token.Attr, aps) + token.Attr = escapeAttributes(p.sanitizeAttrs(token.Data, token.Attr, aps)) } if len(token.Attr) == 0 && !p.allowNoAttrs(token.Data) { if p.addSpaces { - buff.WriteString(" ") + if _, err := buff.WriteString(" "); err != nil { + return err + } break } } if !skipElementContent { - // do not escape multiple query parameters - if linkable(token.Data) { - p.writeLinkableBuf(&buff, &token) - } else { - buff.WriteString(token.String()) + if _, err := buff.WriteString(token.String()); err != nil { + return err } } @@ -350,23 +422,29 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { if !skipElementContent { switch mostRecentlyStartedToken { - case "script": + case `script`: // not encouraged, but if a policy allows JavaScript we // should not HTML escape it as that would break the output - buff.WriteString(token.Data) + if _, err := buff.WriteString(token.Data); err != nil { + return err + } case "style": // not encouraged, but if a policy allows CSS styles we // should not HTML escape it as that would break the output - buff.WriteString(token.Data) + if _, err := buff.WriteString(token.Data); err != nil { + return err + } default: // HTML escape the text - buff.WriteString(token.String()) + if _, err := buff.WriteString(token.String()); err != nil { + return err + } } } default: // A token that didn't exist in the html package when we wrote this - return &bytes.Buffer{} + return fmt.Errorf("unknown token: %v", token) } } } @@ -377,7 +455,7 @@ func (p *Policy) sanitize(r io.Reader) *bytes.Buffer { func (p *Policy) sanitizeAttrs( elementName string, attrs []html.Attribute, - aps map[string]attrPolicy, + aps map[string][]attrPolicy, ) []html.Attribute { if len(attrs) == 0 { @@ -402,8 +480,9 @@ func (p *Policy) sanitizeAttrs( } // Builds a new attribute slice based on the whether the attribute has been - // whitelisted explicitly or globally. + // allowed explicitly or globally. cleanAttrs := []html.Attribute{} +attrsLoop: for _, htmlAttr := range attrs { if p.allowDataAttributes { // If we see a data attribute, let it through. @@ -426,27 +505,32 @@ func (p *Policy) sanitizeAttrs( } // Is there an element specific attribute policy that applies? - if ap, ok := aps[htmlAttr.Key]; ok { - if ap.regexp != nil { - if ap.regexp.MatchString(htmlAttr.Val) { + if apl, ok := aps[htmlAttr.Key]; ok { + for _, ap := range apl { + if ap.regexp != nil { + if ap.regexp.MatchString(htmlAttr.Val) { + cleanAttrs = append(cleanAttrs, htmlAttr) + continue attrsLoop + } + } else { cleanAttrs = append(cleanAttrs, htmlAttr) - continue + continue attrsLoop } - } else { - cleanAttrs = append(cleanAttrs, htmlAttr) - continue } } // Is there a global attribute policy that applies? - if ap, ok := p.globalAttrs[htmlAttr.Key]; ok { - - if ap.regexp != nil { - if ap.regexp.MatchString(htmlAttr.Val) { + if apl, ok := p.globalAttrs[htmlAttr.Key]; ok { + for _, ap := range apl { + if ap.regexp != nil { + if ap.regexp.MatchString(htmlAttr.Val) { + htmlAttr.Val = escapeAttribute(htmlAttr.Val) + cleanAttrs = append(cleanAttrs, htmlAttr) + } + } else { + htmlAttr.Val = escapeAttribute(htmlAttr.Val) cleanAttrs = append(cleanAttrs, htmlAttr) } - } else { - cleanAttrs = append(cleanAttrs, htmlAttr) } } } @@ -470,7 +554,7 @@ func (p *Policy) sanitizeAttrs( tmpAttrs := []html.Attribute{} for _, htmlAttr := range cleanAttrs { switch elementName { - case "a", "area", "link": + case "a", "area", "base", "link": if htmlAttr.Key == "href" { if u, ok := p.validURL(htmlAttr.Val); ok { htmlAttr.Val = u @@ -479,7 +563,7 @@ func (p *Policy) sanitizeAttrs( break } tmpAttrs = append(tmpAttrs, htmlAttr) - case "blockquote", "q": + case "blockquote", "del", "ins", "q": if htmlAttr.Key == "cite" { if u, ok := p.validURL(htmlAttr.Val); ok { htmlAttr.Val = u @@ -488,7 +572,7 @@ func (p *Policy) sanitizeAttrs( break } tmpAttrs = append(tmpAttrs, htmlAttr) - case "img", "script": + case "audio", "embed", "iframe", "img", "script", "source", "track", "video": if htmlAttr.Key == "src" { if u, ok := p.validURL(htmlAttr.Val); ok { htmlAttr.Val = u @@ -513,7 +597,7 @@ func (p *Policy) sanitizeAttrs( // Add rel="nofollow" if a "href" exists switch elementName { - case "a", "area", "link": + case "a", "area", "base", "link": var hrefFound bool var externalLink bool for _, htmlAttr := range cleanAttrs { @@ -664,20 +748,40 @@ func (p *Policy) sanitizeAttrs( } } + if p.requireCrossOriginAnonymous && len(cleanAttrs) > 0 { + switch elementName { + case "audio", "img", "link", "script", "video": + var crossOriginFound bool + for _, htmlAttr := range cleanAttrs { + if htmlAttr.Key == "crossorigin" { + crossOriginFound = true + htmlAttr.Val = "anonymous" + } + } + + if !crossOriginFound { + crossOrigin := html.Attribute{} + crossOrigin.Key = "crossorigin" + crossOrigin.Val = "anonymous" + cleanAttrs = append(cleanAttrs, crossOrigin) + } + } + } + return cleanAttrs } func (p *Policy) sanitizeStyles(attr html.Attribute, elementName string) html.Attribute { sps := p.elsAndStyles[elementName] if len(sps) == 0 { - sps = map[string]stylePolicy{} + sps = map[string][]stylePolicy{} // check for any matching elements, if we don't already have a policy found // if multiple matches are found they will be overwritten, it's best // to not have overlapping matchers for regex, policies := range p.elsMatchingAndStyles { if regex.MatchString(elementName) { for k, v := range policies { - sps[k] = v + sps[k] = append(sps[k], v...) } } } @@ -687,7 +791,7 @@ func (p *Policy) sanitizeStyles(attr html.Attribute, elementName string) html.At if len(attr.Val) > 0 && attr.Val[len(attr.Val)-1] != ';' { attr.Val = attr.Val + ";" } - decs, err := cssparser.ParseDeclarations(attr.Val) + decs, err := parser.ParseDeclarations(attr.Val) if err != nil { attr.Val = "" return attr @@ -695,46 +799,51 @@ func (p *Policy) sanitizeStyles(attr html.Attribute, elementName string) html.At clean := []string{} prefixes := []string{"-webkit-", "-moz-", "-ms-", "-o-", "mso-", "-xv-", "-atsc-", "-wap-", "-khtml-", "prince-", "-ah-", "-hp-", "-ro-", "-rim-", "-tc-"} +decLoop: for _, dec := range decs { - addedProperty := false tempProperty := strings.ToLower(dec.Property) tempValue := removeUnicode(strings.ToLower(dec.Value)) for _, i := range prefixes { tempProperty = strings.TrimPrefix(tempProperty, i) } - if sp, ok := sps[tempProperty]; ok { - if sp.handler != nil { - if sp.handler(tempValue) { - clean = append(clean, dec.Property+": "+dec.Value) - addedProperty = true + if spl, ok := sps[tempProperty]; ok { + for _, sp := range spl { + if sp.handler != nil { + if sp.handler(tempValue) { + clean = append(clean, dec.Property+": "+dec.Value) + continue decLoop + } + } else if len(sp.enum) > 0 { + if stringInSlice(tempValue, sp.enum) { + clean = append(clean, dec.Property+": "+dec.Value) + continue decLoop + } + } else if sp.regexp != nil { + if sp.regexp.MatchString(tempValue) { + clean = append(clean, dec.Property+": "+dec.Value) + continue decLoop + } } - } else if len(sp.enum) > 0 { - if stringInSlice(tempValue, sp.enum) { - clean = append(clean, dec.Property+": "+dec.Value) - addedProperty = true - } - } else if sp.regexp != nil { - if sp.regexp.MatchString(tempValue) { - clean = append(clean, dec.Property+": "+dec.Value) - addedProperty = true - } - continue } } - if sp, ok := p.globalStyles[tempProperty]; ok && !addedProperty { - if sp.handler != nil { - if sp.handler(tempValue) { - clean = append(clean, dec.Property+": "+dec.Value) + if spl, ok := p.globalStyles[tempProperty]; ok { + for _, sp := range spl { + if sp.handler != nil { + if sp.handler(tempValue) { + clean = append(clean, dec.Property+": "+dec.Value) + continue decLoop + } + } else if len(sp.enum) > 0 { + if stringInSlice(tempValue, sp.enum) { + clean = append(clean, dec.Property+": "+dec.Value) + continue decLoop + } + } else if sp.regexp != nil { + if sp.regexp.MatchString(tempValue) { + clean = append(clean, dec.Property+": "+dec.Value) + continue decLoop + } } - } else if len(sp.enum) > 0 { - if stringInSlice(tempValue, sp.enum) { - clean = append(clean, dec.Property+": "+dec.Value) - } - } else if sp.regexp != nil { - if sp.regexp.MatchString(tempValue) { - clean = append(clean, dec.Property+": "+dec.Value) - } - continue } } } @@ -765,11 +874,28 @@ func (p *Policy) validURL(rawurl string) (string, bool) { rawurl = strings.TrimSpace(rawurl) // URLs cannot contain whitespace, unless it is a data-uri - if (strings.Contains(rawurl, " ") || + if strings.Contains(rawurl, " ") || strings.Contains(rawurl, "\t") || - strings.Contains(rawurl, "\n")) && - !strings.HasPrefix(rawurl, `data:`) { - return "", false + strings.Contains(rawurl, "\n") { + if !strings.HasPrefix(rawurl, `data:`) { + return "", false + } + + // Remove \r and \n from base64 encoded data to pass url.Parse. + matched := dataURIbase64Prefix.FindString(rawurl) + if matched != "" { + rawurl = matched + strings.Replace( + strings.Replace( + rawurl[len(matched):], + "\r", + "", + -1, + ), + "\n", + "", + -1, + ) + } } // URLs are valid if they parse @@ -780,16 +906,21 @@ func (p *Policy) validURL(rawurl string) (string, bool) { if u.Scheme != "" { - urlPolicy, ok := p.allowURLSchemes[u.Scheme] + urlPolicies, ok := p.allowURLSchemes[u.Scheme] if !ok { return "", false - } - if urlPolicy == nil || urlPolicy(u) == true { + if len(urlPolicies) == 0 { return u.String(), true } + for _, urlPolicy := range urlPolicies { + if urlPolicy(u) == true { + return u.String(), true + } + } + return "", false } @@ -807,7 +938,14 @@ func (p *Policy) validURL(rawurl string) (string, bool) { func linkable(elementName string) bool { switch elementName { - case "a", "area", "blockquote", "img", "link", "script": + case "a", "area", "base", "link": + // elements that allow .href + return true + case "blockquote", "del", "ins", "q": + // elements that allow .cite + return true + case "audio", "embed", "iframe", "img", "input", "script", "track", "video": + // elements that allow .src return true default: return false @@ -874,16 +1012,50 @@ func removeUnicode(value string) string { return substitutedValue } -func (p *Policy) matchRegex(elementName string) (map[string]attrPolicy, bool) { - aps := make(map[string]attrPolicy, 0) +func (p *Policy) matchRegex(elementName string) (map[string][]attrPolicy, bool) { + aps := make(map[string][]attrPolicy, 0) matched := false for regex, attrs := range p.elsMatchingAndAttrs { if regex.MatchString(elementName) { matched = true for k, v := range attrs { - aps[k] = v + aps[k] = append(aps[k], v...) } } } return aps, matched } + +// normaliseElementName takes a HTML element like