On 15/03/2015 22:00, Luka Perkov wrote: > b64encode and b64decode functions were taken from zstream project which was > written by Steven Barth and John Crispin. >
i did not write this :) > Signed-off-by: Luka Perkov <l...@openwrt.org> > --- > file.c | 197 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 187 insertions(+), 10 deletions(-) > > diff --git a/file.c b/file.c > index 9e87a10..54f5d8a 100644 > --- a/file.c > +++ b/file.c > @@ -79,14 +79,27 @@ static const struct blobmsg_policy > rpc_file_r_policy[__RPC_F_R_MAX] = { > }; > > enum { > + RPC_F_RB_PATH, > + RPC_F_RB_BASE64, > + __RPC_F_RB_MAX, > +}; > + > +static const struct blobmsg_policy rpc_file_rb_policy[__RPC_F_RB_MAX] = { > + [RPC_F_RB_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, > + [RPC_F_RB_BASE64] = { .name = "base64", .type = BLOBMSG_TYPE_BOOL }, > +}; > + > +enum { > RPC_F_RW_PATH, > RPC_F_RW_DATA, > + RPC_F_RW_BASE64, > __RPC_F_RW_MAX, > }; > > static const struct blobmsg_policy rpc_file_rw_policy[__RPC_F_RW_MAX] = { > - [RPC_F_RW_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, > - [RPC_F_RW_DATA] = { .name = "data", .type = BLOBMSG_TYPE_STRING }, > + [RPC_F_RW_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, > + [RPC_F_RW_DATA] = { .name = "data", .type = BLOBMSG_TYPE_STRING }, > + [RPC_F_RW_BASE64] = { .name = "base64", .type = BLOBMSG_TYPE_BOOL }, > }; > > enum { > @@ -114,6 +127,122 @@ static const char *d_types[] = { > }; > > > +static const unsigned char b64encode_tbl[] = > + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; > + > +static char > +*b64encode(const void *in, size_t *len) > +{ > + size_t lenout, pad, i; > + const uint8_t *data = (const uint8_t *) in; > + > + lenout = *len / 3; > + lenout *= 4; > + pad = *len % 3; > + > + if (*len == 0) { > + return strdup(""); > + } else if (pad) { > + lenout += 4; > + } no need for brackets here > + > + char *out = calloc(lenout + 1, sizeof(char)); char *out; should eb at the start of the function. > + if (!out) > + return NULL; > + > + uint8_t *o = (uint8_t*)out; missing space here ^ > + for (i = 0; i < *len; i += 3) { > + uint32_t cv = (data[i] << 16) | (data[i+1] << 8) | data[i+2]; > + *(o+3) = b64encode_tbl[ cv & 0x3f]; > + *(o+2) = b64encode_tbl[(cv >> 6) & 0x3f]; > + *(o+1) = b64encode_tbl[(cv >> 12) & 0x3f]; > + *o = b64encode_tbl[(cv >> 18) & 0x3f]; > + o += 4; the *(x) syntax is wonky imho. this should be changed to o[x] and there are missing spaces here aswell > + } > + > + if (pad) { > + uint32_t cv = data[*len-pad] << 16; > + *(o-1) = '='; > + *(o-2) = '='; > + if (pad == 2) { > + cv |= data[*len-pad+1] << 8; > + *(o-2) = b64encode_tbl[(cv >> 6) & 0x3f]; > + } > + *(o-3) = b64encode_tbl[(cv >> 12) & 0x3f]; > + *(o-4) = b64encode_tbl[(cv >> 18) & 0x3f]; > + } lots of missing spaces here aswell. > + > + out[lenout] = 0; > + *len = lenout; > + return out; > +} > + the base64 code should probably be cleaned up and moved to libubox, same as md5. did not read the rest of the patch as it wont be merged as is. > +static const unsigned char b64decode_tbl[] = { > + 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, > + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, > + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, > + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, > + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, > + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, > + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, > + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, > + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, > + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33 > +}; > + > +static void > +*b64decode(const char *in, size_t *len) > +{ > + size_t lenout, i; > + > + if (*len == 0) { > + return strdup(""); > + } else if (*len % 4) { > + errno = EINVAL; > + return NULL; > + } > + > + lenout = *len / 4 * 3; > + > + unsigned char *out = calloc(lenout + 1, sizeof(char)); > + if (!out) > + return NULL; > + > + unsigned char *o = out; > + for (i = 0; i < *len; i += 4) { > + uint32_t cv = 0; > + for (int j = 0; j < 4; j++) { > + unsigned char c = in[i + j] - 43; > + if (c > 79 || (c = b64decode_tbl[c]) == 0xff) { > + free(out); > + errno = EINVAL; > + return NULL; > + } > + > + cv |= c; > + if (j != 3) { > + cv <<= 6; > + } > + } > + > + *(o+2) = (unsigned char)(cv & 0xff); > + *(o+1) = (unsigned char)((cv >> 8) & 0xff); > + *o = (unsigned char)((cv >> 16) & 0xff); > + o += 3; > + } > + > + if (in[*len-1] == '=') { > + lenout--; > + } > + > + if (in[*len-2] == '=') { > + lenout--; > + } > + > + *len = lenout; > + return out; > +} > + > static int > rpc_errno_status(void) > { > @@ -162,12 +291,22 @@ rpc_file_read(struct ubus_context *ctx, struct > ubus_object *obj, > struct ubus_request_data *req, const char *method, > struct blob_attr *msg) > { > - int fd, rv, len; > + static struct blob_attr *tb[__RPC_F_RB_MAX]; > + bool base64 = false; > + int fd, rv; > + ssize_t len; > char *path; > struct stat s; > char *wbuf; > > - if (!rpc_check_path(msg, &path, &s)) > + blobmsg_parse(rpc_file_rb_policy, __RPC_F_RB_MAX, tb, blob_data(msg), > blob_len(msg)); > + > + if (!tb[RPC_F_RB_PATH]) > + return rpc_errno_status(); > + > + path = blobmsg_data(tb[RPC_F_RB_PATH]); > + > + if (stat(path, &s)) > return rpc_errno_status(); > > if (s.st_size >= RPC_FILE_MAX_SIZE) > @@ -182,7 +321,14 @@ rpc_file_read(struct ubus_context *ctx, struct > ubus_object *obj, > > blob_buf_init(&buf, 0); > > - wbuf = blobmsg_alloc_string_buffer(&buf, "data", s.st_size + 1); > + if (tb[RPC_F_RB_BASE64]) > + base64 = blobmsg_get_bool(tb[RPC_F_RB_BASE64]); > + > + if (base64) { > + wbuf = blobmsg_alloc_string_buffer(&buf, "data", (s.st_size / > 3) * 4 + 5); > + } else { > + wbuf = blobmsg_alloc_string_buffer(&buf, "data", s.st_size + 1); > + } > > if (!wbuf) > { > @@ -196,14 +342,25 @@ rpc_file_read(struct ubus_context *ctx, struct > ubus_object *obj, > goto out; > } > > + if (base64) { > + void *data = b64encode(wbuf, (size_t *) &len); > + if (!data) { > + rv = UBUS_STATUS_UNKNOWN_ERROR; > + goto out; > + } > + > + memcpy(wbuf, data, len); > + free(data); > + } > + > *(wbuf + len) = 0; > blobmsg_add_string_buffer(&buf); > > ubus_send_reply(ctx, req, buf.head); > - blob_buf_free(&buf); > rv = UBUS_STATUS_OK; > > out: > + blob_buf_free(&buf); > close(fd); > return rv; > } > @@ -213,8 +370,11 @@ rpc_file_write(struct ubus_context *ctx, struct > ubus_object *obj, > struct ubus_request_data *req, const char *method, > struct blob_attr *msg) > { > - int fd; > struct blob_attr *tb[__RPC_F_RW_MAX]; > + bool base64 = false; > + int fd, rv = 0; > + void *rbuf; > + size_t rbuf_len; > > blobmsg_parse(rpc_file_rw_policy, __RPC_F_RW_MAX, tb, > blob_data(msg), blob_len(msg)); > @@ -222,10 +382,27 @@ rpc_file_write(struct ubus_context *ctx, struct > ubus_object *obj, > if (!tb[RPC_F_RW_PATH] || !tb[RPC_F_RW_DATA]) > return UBUS_STATUS_INVALID_ARGUMENT; > > - if ((fd = open(blobmsg_data(tb[RPC_F_RW_PATH]), O_CREAT | O_TRUNC | > O_WRONLY)) < 0) > + if ((fd = open(blobmsg_data(tb[RPC_F_RW_PATH]), O_CREAT | O_WRONLY | > O_TRUNC)) < 0) > return rpc_errno_status(); > > - if (write(fd, blobmsg_data(tb[RPC_F_RW_DATA]), > blobmsg_data_len(tb[RPC_F_RW_DATA])) < 0) > + if (tb[RPC_F_RW_BASE64]) > + base64 = blobmsg_get_bool(tb[RPC_F_RW_BASE64]); > + > + if (base64) { > + rbuf_len = blobmsg_data_len(tb[RPC_F_RW_DATA]) - 1; > + rbuf = b64decode(blobmsg_data(tb[RPC_F_RW_DATA]), &rbuf_len); > + } else { > + rbuf_len = blobmsg_data_len(tb[RPC_F_RW_DATA]); > + rbuf = blobmsg_data(tb[RPC_F_RW_DATA]); > + } > + > + if (write(fd, rbuf, rbuf_len) < 0) > + rv = -1; > + > + if (base64) > + free(rbuf); > + > + if (rv) > return rpc_errno_status(); > > if (fsync(fd) < 0) > @@ -643,7 +820,7 @@ static int > rpc_file_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx) > { > static const struct ubus_method file_methods[] = { > - UBUS_METHOD("read", rpc_file_read, rpc_file_r_policy), > + UBUS_METHOD("read", rpc_file_read, rpc_file_rb_policy), > UBUS_METHOD("write", rpc_file_write, rpc_file_rw_policy), > UBUS_METHOD("list", rpc_file_list, rpc_file_r_policy), > UBUS_METHOD("stat", rpc_file_stat, rpc_file_r_policy), > _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel