29 #include "plugins_internal.h"
43 static const char b64_etable[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
58 binary_base64_encode(
const struct ly_ctx *ctx,
const char *data,
size_t size,
char **str,
size_t *str_len)
63 *str_len = (size + 2) / 3 * 4;
64 *str = malloc(*str_len + 1);
72 for (i = 0; i < size - 2; i += 3) {
73 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
74 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
75 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2) | ((int)(data[i + 2] & 0xC0) >> 6)];
76 *ptr++ = b64_etable[data[i + 2] & 0x3F];
79 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
80 if (i == (size - 1)) {
81 *ptr++ = b64_etable[((data[i] & 0x3) << 4)];
84 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
85 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2)];
97 static const int b64_dtable[256] = {
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55,
101 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
102 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,
103 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
104 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
119 binary_base64_decode(
const char *value,
size_t value_len,
void **data,
size_t *size)
121 unsigned char *ptr = (
unsigned char *)value;
122 uint32_t pad_chars, octet_count;
125 if (!value_len || (ptr[value_len - 1] !=
'=')) {
127 }
else if (ptr[value_len - 2] ==
'=') {
133 octet_count = ((value_len + 3) / 4 - (pad_chars ? 1 : 0)) * 4;
134 *size = octet_count / 4 * 3 + pad_chars;
136 str = malloc(*size + 1);
140 for (uint32_t i = 0, j = 0; i < octet_count; i += 4) {
141 int n = b64_dtable[ptr[i]] << 18 | b64_dtable[ptr[i + 1]] << 12 | b64_dtable[ptr[i + 2]] << 6 | b64_dtable[ptr[i + 3]];
143 str[j++] = n >> 8 & 0xFF;
147 int n = b64_dtable[ptr[octet_count]] << 18 | b64_dtable[ptr[octet_count + 1]] << 12;
148 str[*size - pad_chars] = n >> 16;
150 if (pad_chars == 2) {
151 n |= b64_dtable[ptr[octet_count + 2]] << 6;
153 str[*size - pad_chars + 1] = n;
171 binary_base64_validate(
const char *value,
size_t value_len,
const struct lysc_type_bin *type,
struct ly_err_item **err)
177 while ((idx < value_len) &&
178 (((
'A' <= value[idx]) && (value[idx] <=
'Z')) ||
179 ((
'a' <= value[idx]) && (value[idx] <=
'z')) ||
180 ((
'0' <= value[idx]) && (value[idx] <=
'9')) ||
181 (
'+' == value[idx]) || (
'/' == value[idx]))) {
187 while ((idx + pad < value_len) && (pad < 2) && (value[idx + pad] ==
'=')) {
192 if (value_len != idx + pad) {
193 if (isprint(value[idx + pad])) {
207 const uint32_t octet_count = ((idx + pad) / 4) * 3 - pad;
224 binary_base64_newlines(
char **value,
size_t *value_len, uint32_t *options,
struct ly_err_item **err)
229 if ((*value_len < 65) || ((*value)[64] !=
'\n')) {
236 *value = strndup(*value, *value_len);
237 LY_CHECK_RET(!*value,
LY_EMEM);
244 if (val[64] !=
'\n') {
250 memmove(val + 64, val + 65, len - 64);
261 uint32_t options,
LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), uint32_t hints,
262 const struct lysc_node *UNUSED(ctx_node),
struct lyd_value *storage,
struct lys_glob_unres *UNUSED(unres),
270 memset(storage, 0,
sizeof *storage);
272 LY_CHECK_ERR_GOTO(!val, ret =
LY_EMEM, cleanup);
278 val->
data = (
void *)value;
280 }
else if (value_len) {
281 val->
data = malloc(value_len);
282 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
283 memcpy(val->
data, value, value_len);
285 val->
data = strdup(
"");
286 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
290 val->
size = value_len;
298 LY_CHECK_GOTO(ret, cleanup);
302 ret = binary_base64_newlines((
char **)&value, &value_len, &options, err);
303 LY_CHECK_GOTO(ret, cleanup);
306 ret = binary_base64_validate(value, value_len, type_bin, err);
307 LY_CHECK_GOTO(ret, cleanup);
311 ret = binary_base64_decode(value, value_len, &val->
data, &val->
size);
312 LY_CHECK_GOTO(ret, cleanup);
318 LY_CHECK_GOTO(ret, cleanup);
321 LY_CHECK_GOTO(ret, cleanup);
353 LIBYANG_API_DEF
const void *
355 void *UNUSED(prefix_data),
ly_bool *dynamic,
size_t *value_len)
366 *value_len = val->
size;
374 if (binary_base64_encode(ctx, val->
data, val->
size, &ret, &ret_len)) {
390 *value_len = ret_len ? ret_len : strlen(value->
_canonical);
401 memset(dup, 0,
sizeof *dup);
404 LY_CHECK_GOTO(ret, error);
407 LY_CHECK_ERR_GOTO(!dup_val, ret =
LY_EMEM, error);
411 dup_val->
data = orig_val->
size ? malloc(orig_val->
size) : strdup(
"");
412 LY_CHECK_ERR_GOTO(!dup_val->
data, ret =
LY_EMEM, error);
450 .name = LY_TYPE_BINARY_STR,
452 .plugin.id =
"libyang 2 - binary, version 1",
454 .plugin.validate = NULL,
460 .plugin.lyb_data_len = -1,