| |
| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
| <style> |
| body { |
| background: black; |
| color: rgb(80, 80, 80); |
| } |
| body, pre, #legend span { |
| font-family: Menlo, monospace; |
| font-weight: bold; |
| } |
| #topbar { |
| background: black; |
| position: fixed; |
| top: 0; left: 0; right: 0; |
| height: 42px; |
| border-bottom: 1px solid rgb(80, 80, 80); |
| } |
| #content { |
| margin-top: 50px; |
| } |
| #nav, #legend { |
| float: left; |
| margin-left: 10px; |
| } |
| #legend { |
| margin-top: 12px; |
| } |
| #nav { |
| margin-top: 10px; |
| } |
| #legend span { |
| margin: 0 5px; |
| } |
| .cov0 { color: rgb(192, 0, 0) } |
| .cov1 { color: rgb(128, 128, 128) } |
| .cov2 { color: rgb(116, 140, 131) } |
| .cov3 { color: rgb(104, 152, 134) } |
| .cov4 { color: rgb(92, 164, 137) } |
| .cov5 { color: rgb(80, 176, 140) } |
| .cov6 { color: rgb(68, 188, 143) } |
| .cov7 { color: rgb(56, 200, 146) } |
| .cov8 { color: rgb(44, 212, 149) } |
| .cov9 { color: rgb(32, 224, 152) } |
| .cov10 { color: rgb(20, 236, 155) } |
| |
| </style> |
| </head> |
| <body> |
| <div id="topbar"> |
| <div id="nav"> |
| <select id="files"> |
| |
| <option value="file0">github.com/SermoDigital/jose/base64.go (100.0%)</option> |
| |
| <option value="file1">github.com/SermoDigital/jose/header.go (58.1%)</option> |
| |
| </select> |
| </div> |
| <div id="legend"> |
| <span>not tracked</span> |
| |
| <span class="cov0">not covered</span> |
| <span class="cov8">covered</span> |
| |
| </div> |
| </div> |
| <div id="content"> |
| |
| <pre class="file" id="file0" >package jose |
| |
| import "encoding/base64" |
| |
| // Encoder is satisfied if the type can marshal itself into a valid |
| // structure for a JWS. |
| type Encoder interface { |
| // Base64 implies T -> JSON -> RawURLEncodingBase64 |
| Base64() ([]byte, error) |
| } |
| |
| // Base64Decode decodes a base64-encoded byte slice. |
| func Base64Decode(b []byte) ([]byte, error) <span class="cov8" title="1">{ |
| buf := make([]byte, base64.RawURLEncoding.DecodedLen(len(b))) |
| n, err := base64.RawURLEncoding.Decode(buf, b) |
| return buf[:n], err |
| }</span> |
| |
| // Base64Encode encodes a byte slice. |
| func Base64Encode(b []byte) []byte <span class="cov8" title="1">{ |
| buf := make([]byte, base64.RawURLEncoding.EncodedLen(len(b))) |
| base64.RawURLEncoding.Encode(buf, b) |
| return buf |
| }</span> |
| |
| // EncodeEscape base64-encodes a byte slice but escapes it for JSON. |
| // It'll return the format: `"base64"` |
| func EncodeEscape(b []byte) []byte <span class="cov8" title="1">{ |
| buf := make([]byte, base64.RawURLEncoding.EncodedLen(len(b))+2) |
| buf[0] = '"' |
| base64.RawURLEncoding.Encode(buf[1:], b) |
| buf[len(buf)-1] = '"' |
| return buf |
| }</span> |
| |
| // DecodeEscaped decodes a base64-encoded byte slice straight from a JSON |
| // structure. It assumes it's in the format: `"base64"`, but can handle |
| // cases where it's not. |
| func DecodeEscaped(b []byte) ([]byte, error) <span class="cov8" title="1">{ |
| if len(b) > 1 && b[0] == '"' && b[len(b)-1] == '"' </span><span class="cov8" title="1">{ |
| b = b[1 : len(b)-1] |
| }</span> |
| <span class="cov8" title="1">return Base64Decode(b)</span> |
| } |
| </pre> |
| |
| <pre class="file" id="file1" style="display: none">package jose |
| |
| import "encoding/json" |
| |
| // Header implements a JOSE Header with the addition of some helper |
| // methods, similar to net/url.Values. |
| type Header map[string]interface{} |
| |
| // Get retrieves the value corresponding with key from the Header. |
| func (h Header) Get(key string) interface{} <span class="cov8" title="1">{ |
| if h == nil </span><span class="cov8" title="1">{ |
| return nil |
| }</span> |
| <span class="cov8" title="1">return h[key]</span> |
| } |
| |
| // Set sets Claims[key] = val. It'll overwrite without warning. |
| func (h Header) Set(key string, val interface{}) <span class="cov8" title="1">{ |
| h[key] = val |
| }</span> |
| |
| // Del removes the value that corresponds with key from the Header. |
| func (h Header) Del(key string) <span class="cov8" title="1">{ |
| delete(h, key) |
| }</span> |
| |
| // Has returns true if a value for the given key exists inside the Header. |
| func (h Header) Has(key string) bool <span class="cov8" title="1">{ |
| _, ok := h[key] |
| return ok |
| }</span> |
| |
| // MarshalJSON implements json.Marshaler for Header. |
| func (h Header) MarshalJSON() ([]byte, error) <span class="cov8" title="1">{ |
| if h == nil || len(h) == 0 </span><span class="cov0" title="0">{ |
| return nil, nil |
| }</span> |
| <span class="cov8" title="1">b, err := json.Marshal(map[string]interface{}(h)) |
| if err != nil </span><span class="cov0" title="0">{ |
| return nil, err |
| }</span> |
| <span class="cov8" title="1">return EncodeEscape(b), nil</span> |
| } |
| |
| // Base64 implements the Encoder interface. |
| func (h Header) Base64() ([]byte, error) <span class="cov0" title="0">{ |
| return h.MarshalJSON() |
| }</span> |
| |
| // UnmarshalJSON implements json.Unmarshaler for Header. |
| func (h *Header) UnmarshalJSON(b []byte) error <span class="cov8" title="1">{ |
| if b == nil </span><span class="cov0" title="0">{ |
| return nil |
| }</span> |
| |
| <span class="cov8" title="1">b, err := DecodeEscaped(b) |
| if err != nil </span><span class="cov0" title="0">{ |
| return err |
| }</span> |
| |
| // Since json.Unmarshal calls UnmarshalJSON, |
| // calling json.Unmarshal on *p would be infinitely recursive |
| // A temp variable is needed because &map[string]interface{}(*p) is |
| // invalid Go. |
| |
| <span class="cov8" title="1">tmp := map[string]interface{}(*h) |
| if err = json.Unmarshal(b, &tmp); err != nil </span><span class="cov0" title="0">{ |
| return err |
| }</span> |
| <span class="cov8" title="1">*h = Header(tmp) |
| return nil</span> |
| } |
| |
| // Protected Headers are base64-encoded after they're marshaled into |
| // JSON. |
| type Protected Header |
| |
| // Get retrieves the value corresponding with key from the Protected Header. |
| func (p Protected) Get(key string) interface{} <span class="cov0" title="0">{ |
| if p == nil </span><span class="cov0" title="0">{ |
| return nil |
| }</span> |
| <span class="cov0" title="0">return p[key]</span> |
| } |
| |
| // Set sets Protected[key] = val. It'll overwrite without warning. |
| func (p Protected) Set(key string, val interface{}) <span class="cov0" title="0">{ |
| p[key] = val |
| }</span> |
| |
| // Del removes the value that corresponds with key from the Protected Header. |
| func (p Protected) Del(key string) <span class="cov0" title="0">{ |
| delete(p, key) |
| }</span> |
| |
| // Has returns true if a value for the given key exists inside the Protected |
| // Header. |
| func (p Protected) Has(key string) bool <span class="cov0" title="0">{ |
| _, ok := p[key] |
| return ok |
| }</span> |
| |
| // MarshalJSON implements json.Marshaler for Protected. |
| func (p Protected) MarshalJSON() ([]byte, error) <span class="cov8" title="1">{ |
| b, err := json.Marshal(map[string]interface{}(p)) |
| if err != nil </span><span class="cov0" title="0">{ |
| return nil, err |
| }</span> |
| <span class="cov8" title="1">return EncodeEscape(b), nil</span> |
| } |
| |
| // Base64 implements the Encoder interface. |
| func (p Protected) Base64() ([]byte, error) <span class="cov0" title="0">{ |
| b, err := json.Marshal(map[string]interface{}(p)) |
| if err != nil </span><span class="cov0" title="0">{ |
| return nil, err |
| }</span> |
| <span class="cov0" title="0">return Base64Encode(b), nil</span> |
| } |
| |
| // UnmarshalJSON implements json.Unmarshaler for Protected. |
| func (p *Protected) UnmarshalJSON(b []byte) error <span class="cov8" title="1">{ |
| var h Header |
| h.UnmarshalJSON(b) |
| *p = Protected(h) |
| return nil |
| }</span> |
| |
| var ( |
| _ json.Marshaler = (Protected)(nil) |
| _ json.Unmarshaler = (*Protected)(nil) |
| ) |
| </pre> |
| |
| </div> |
| </body> |
| <script> |
| (function() { |
| var files = document.getElementById('files'); |
| var visible = document.getElementById('file0'); |
| files.addEventListener('change', onChange, false); |
| function onChange() { |
| visible.style.display = 'none'; |
| visible = document.getElementById(files.value); |
| visible.style.display = 'block'; |
| window.scrollTo(0, 0); |
| } |
| })(); |
| </script> |
| </html> |