static void to_zval_read_aggregation(const char *structure, zval *zarr, /* initialized array */ const field_descriptor *descriptors, res_context *ctx) { const field_descriptor *descr; assert(Z_TYPE_P(zarr) == IS_ARRAY); assert(Z_ARRVAL_P(zarr) != NULL); for (descr = descriptors; descr->name != NULL && !ctx->err.has_error; descr++) { zval *new_zv, tmp; if (descr->to_zval == NULL) { do_to_zval_err(ctx, "No information on how to convert native " "field into value for key '%s'", descr->name); break; } ZVAL_NULL(&tmp); new_zv = zend_symtable_str_update(Z_ARRVAL_P(zarr), descr->name, descr->name_size - 1, &tmp); zend_llist_add_element(&ctx->keys, (void*)&descr->name); descr->to_zval(structure + descr->field_offset, new_zv, ctx); zend_llist_remove_tail(&ctx->keys); } }
/* Generic Aggregated conversions */ static void from_zval_write_aggregation(const zval *container, char *structure, const field_descriptor *descriptors, ser_context *ctx) { const field_descriptor *descr; zval *elem; if (Z_TYPE_P(container) != IS_ARRAY) { do_from_zval_err(ctx, "%s", "expected an array here"); } for (descr = descriptors; descr->name != NULL && !ctx->err.has_error; descr++) { if ((elem = zend_hash_str_find(Z_ARRVAL_P(container), descr->name, descr->name_size - 1)) != NULL) { if (descr->from_zval == NULL) { do_from_zval_err(ctx, "No information on how to convert value " "of key '%s'", descr->name); break; } zend_llist_add_element(&ctx->keys, (void*)&descr->name); descr->from_zval(elem, ((char*)structure) + descr->field_offset, ctx); zend_llist_remove_tail(&ctx->keys); } else if (descr->required) { do_from_zval_err(ctx, "The key '%s' is required", descr->name); break; } } }
static unsigned from_array_iterate(const zval *arr, void (*func)(zval *elem, unsigned i, void **args, ser_context *ctx), void **args, ser_context *ctx) { HashPosition pos; unsigned i; zval *elem; char buf[sizeof("element #4294967295")]; char *bufp = buf; /* Note i starts at 1, not 0! */ for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos), i = 1; !ctx->err.has_error && (elem = zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), &pos)) != NULL; zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos), i++) { if (snprintf(buf, sizeof(buf), "element #%u", i) >= sizeof(buf)) { memcpy(buf, "element", sizeof("element")); } zend_llist_add_element(&ctx->keys, &bufp); func(elem, i, args, ctx); zend_llist_remove_tail(&ctx->keys); } return i -1; }
static unsigned from_array_iterate(const zval *arr, void (*func)(zval *elem, unsigned i, void **args, ser_context *ctx), void **args, ser_context *ctx) { unsigned i; zval *elem; char buf[sizeof("element #4294967295")]; char *bufp = buf; /* Note i starts at 1, not 0! */ i = 1; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), elem) { if ((size_t)snprintf(buf, sizeof(buf), "element #%u", i) >= sizeof(buf)) { memcpy(buf, "element", sizeof("element")); } zend_llist_add_element(&ctx->keys, &bufp); func(elem, i, args, ctx); zend_llist_remove_tail(&ctx->keys); if (ctx->err.has_error) { break; } i++; } ZEND_HASH_FOREACH_END(); return i -1; }
/* parse headers */ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header) { char *line; mime_header_entry prev_entry = {0}, entry; int prev_len, cur_len; /* didn't find boundary, abort */ if (!find_boundary(self, self->boundary)) { return 0; } /* get lines of text, or CRLF_CRLF */ while( (line = get_line(self)) && line[0] != '\0' ) { /* add header to table */ char *key = line; char *value = NULL; if (php_rfc1867_encoding_translation()) { self->input_encoding = zend_multibyte_encoding_detector(line, strlen(line), self->detect_order, self->detect_order_size); } /* space in the beginning means same header */ if (!isspace(line[0])) { value = strchr(line, ':'); } if (value) { *value = 0; do { value++; } while(isspace(*value)); entry.value = estrdup(value); entry.key = estrdup(key); } else if (zend_llist_count(header)) { /* If no ':' on the line, add to previous line */ prev_len = (int)strlen(prev_entry.value); cur_len = (int)strlen(line); entry.value = emalloc(prev_len + cur_len + 1); memcpy(entry.value, prev_entry.value, prev_len); memcpy(entry.value + prev_len, line, cur_len); entry.value[cur_len + prev_len] = '\0'; entry.key = estrdup(prev_entry.key); zend_llist_remove_tail(header); } else { continue; } zend_llist_add_element(header, &entry); prev_entry = entry; } return 1; }
static void from_zval_write_sockaddr_aux(const zval *container, struct sockaddr **sockaddr_ptr, socklen_t *sockaddr_len, ser_context *ctx) { int family; zval *elem; int fill_sockaddr; if (Z_TYPE_P(container) != IS_ARRAY) { do_from_zval_err(ctx, "%s", "expected an array here"); return; } fill_sockaddr = param_get_bool(ctx, KEY_FILL_SOCKADDR, 1); if ((elem = zend_hash_str_find(Z_ARRVAL_P(container), "family", sizeof("family") - 1)) != NULL && Z_TYPE_P(elem) != IS_NULL) { const char *node = "family"; zend_llist_add_element(&ctx->keys, &node); from_zval_write_int(elem, (char*)&family, ctx); zend_llist_remove_tail(&ctx->keys); } else { family = ctx->sock->type; } switch (family) { case AF_INET: /* though not all OSes support sockaddr_in used in IPv6 sockets */ if (ctx->sock->type != AF_INET && ctx->sock->type != AF_INET6) { do_from_zval_err(ctx, "the specified family (number %d) is not " "supported on this socket", family); return; } *sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_in), ctx); *sockaddr_len = sizeof(struct sockaddr_in); if (fill_sockaddr) { from_zval_write_sockaddr_in(container, (char*)*sockaddr_ptr, ctx); (*sockaddr_ptr)->sa_family = AF_INET; } break; #if HAVE_IPV6 case AF_INET6: if (ctx->sock->type != AF_INET6) { do_from_zval_err(ctx, "the specified family (AF_INET6) is not " "supported on this socket"); return; } *sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_in6), ctx); *sockaddr_len = sizeof(struct sockaddr_in6); if (fill_sockaddr) { from_zval_write_sockaddr_in6(container, (char*)*sockaddr_ptr, ctx); (*sockaddr_ptr)->sa_family = AF_INET6; } break; #endif /* HAVE_IPV6 */ case AF_UNIX: if (ctx->sock->type != AF_UNIX) { do_from_zval_err(ctx, "the specified family (AF_UNIX) is not " "supported on this socket"); return; } *sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_un), ctx); if (fill_sockaddr) { struct sockaddr_un *sock_un = (struct sockaddr_un*)*sockaddr_ptr; from_zval_write_sockaddr_un(container, (char*)*sockaddr_ptr, ctx); (*sockaddr_ptr)->sa_family = AF_UNIX; /* calculating length is more complicated here. Giving the size of * struct sockaddr_un here and relying on the nul termination of * sun_path does not work for paths in the abstract namespace. Note * that we always assume the path is not empty and nul terminated */ *sockaddr_len = offsetof(struct sockaddr_un, sun_path) + (sock_un->sun_path[0] == '\0' ? (1 + strlen(&sock_un->sun_path[1])) : strlen(sock_un->sun_path)); } else { *sockaddr_len = sizeof(struct sockaddr_un); } break; default: do_from_zval_err(ctx, "%s", "the only families currently supported are " "AF_INET, AF_INET6 and AF_UNIX"); break; }