| 131 | #define BASE64URL_CHAR(x) BASE64URL_CHARS[ (unsigned int)(x) & 0x3fu ] |
| 132 | |
| 133 | apr_size_t h2_util_base64url_decode(const char **decoded, const char *encoded, |
| 134 | apr_pool_t *pool) |
| 135 | { |
| 136 | const unsigned char *e = (const unsigned char *)encoded; |
| 137 | const unsigned char *p = e; |
| 138 | unsigned char *d; |
| 139 | unsigned int n; |
| 140 | long len, mlen, remain, i; |
| 141 | |
| 142 | while (*p && BASE64URL_UINT6[ *p ] != N6) { |
| 143 | ++p; |
| 144 | } |
| 145 | len = (int)(p - e); |
| 146 | mlen = (len/4)*4; |
| 147 | *decoded = apr_pcalloc(pool, (apr_size_t)len + 1); |
| 148 | |
| 149 | i = 0; |
| 150 | d = (unsigned char*)*decoded; |
| 151 | for (; i < mlen; i += 4) { |
| 152 | n = ((BASE64URL_UINT6[ e[i+0] ] << 18) + |
| 153 | (BASE64URL_UINT6[ e[i+1] ] << 12) + |
| 154 | (BASE64URL_UINT6[ e[i+2] ] << 6) + |
| 155 | (BASE64URL_UINT6[ e[i+3] ])); |
| 156 | *d++ = (unsigned char)(n >> 16); |
| 157 | *d++ = (unsigned char)(n >> 8 & 0xffu); |
| 158 | *d++ = (unsigned char)(n & 0xffu); |
| 159 | } |
| 160 | remain = len - mlen; |
| 161 | switch (remain) { |
| 162 | case 2: |
| 163 | n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) + |
| 164 | (BASE64URL_UINT6[ e[mlen+1] ] << 12)); |
| 165 | *d++ = (unsigned char)(n >> 16); |
| 166 | remain = 1; |
| 167 | break; |
| 168 | case 3: |
| 169 | n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) + |
| 170 | (BASE64URL_UINT6[ e[mlen+1] ] << 12) + |
| 171 | (BASE64URL_UINT6[ e[mlen+2] ] << 6)); |
| 172 | *d++ = (unsigned char)(n >> 16); |
| 173 | *d++ = (unsigned char)(n >> 8 & 0xffu); |
| 174 | remain = 2; |
| 175 | break; |
| 176 | default: /* do nothing */ |
| 177 | break; |
| 178 | } |
| 179 | return (apr_size_t)(mlen/4*3 + remain); |
| 180 | } |
| 181 | |
| 182 | const char *h2_util_base64url_encode(const char *data, |
| 183 | apr_size_t dlen, apr_pool_t *pool) |