static void parse_query_string(sl_vm_t* vm, SLVAL dict, size_t len, uint8_t* query_string) { uint8_t *key = query_string, *value = NULL; size_t key_len = 0, value_len = 0; size_t i; SLVAL addee = dict, k, v; int bracket_mode = 0, in_bracket = 0; for(i = 0; i <= len; i++) { if(i == len || query_string[i] == '&') { if(key_len > 0) { k = sl_string_url_decode(vm, sl_make_string(vm, key, key_len)); if(value) { v = sl_string_url_decode(vm, sl_make_string(vm, value, value_len)); } sl_dict_set(vm, addee, k, value ? v : vm->lib.nil); } key = query_string + i + 1; key_len = 0; value = NULL; value_len = 0; addee = dict; in_bracket = 0; bracket_mode = 0; continue; } if(query_string[i] == '=' && !value) { value = query_string + i + 1; continue; } if(value) { value_len++; } else { if(query_string[i] == '[') { k = sl_make_string(vm, key, key_len); key = query_string + i + 1; key_len = 0; if(!sl_is_a(vm, sl_dict_get(vm, addee, k), vm->lib.Dict)) { sl_dict_set(vm, addee, k, sl_make_dict(vm, 0, NULL)); } addee = sl_dict_get(vm, addee, k); in_bracket = 1; bracket_mode = 1; continue; } if(query_string[i] == ']' && in_bracket) { in_bracket = 0; continue; } if(bracket_mode && !in_bracket) { /* skip until \0, & or = */ while(i + 1 < len && query_string[i + 1] != '&' && query_string[i + 1] != '=') { i++; } continue; } key_len++; } } }
static void parse_cookie_string(sl_vm_t* vm, SLVAL dict, size_t len, uint8_t* cookies) { uint8_t *key = NULL, *value = NULL; size_t key_len = 0, value_len = 0; size_t i; for(i = 0; i <= len; i++) { if(i == len || cookies[i] == ';') { if(key_len) { sl_dict_set(vm, dict, sl_string_url_decode(vm, sl_make_string(vm, key, key_len)), sl_string_url_decode(vm, sl_make_string(vm, value, value_len))); } key_len = 0; value_len = 0; key = NULL; value = NULL; } if(cookies[i] != ' ' && !key) { key = cookies + i; key_len++; continue; } if(cookies[i] == '=' && !value) { value = cookies + i + 1; continue; } if(!value) { key_len++; } else { value_len++; } } }
void sl_request_set_opts(sl_vm_t* vm, sl_request_opts_t* opts) { size_t i; SLVAL n, v, cookies; sl_string_t* str; sl_request_internal_opts_t* req = sl_alloc(vm->arena, sizeof(sl_request_internal_opts_t)); req->method = sl_make_cstring(vm, opts->method); req->uri = sl_make_cstring(vm, opts->uri); req->path_info = sl_make_cstring(vm, opts->path_info ? opts->path_info : ""); req->query_string = sl_make_cstring(vm, opts->query_string ? opts->query_string : ""); req->remote_addr = sl_make_cstring(vm, opts->remote_addr); req->headers = sl_make_dict(vm, 0, NULL); req->env = sl_make_dict(vm, 0, NULL); req->get = sl_make_dict(vm, 0, NULL); req->post = sl_make_dict(vm, 0, NULL); req->post_data = sl_make_string(vm, (uint8_t*)opts->post_data, opts->post_length); req->cookies = sl_make_dict(vm, 0, NULL); for(i = 0; i < opts->header_count; i++) { n = sl_make_cstring(vm, opts->headers[i].name); v = sl_make_cstring(vm, opts->headers[i].value); sl_dict_set(vm, req->headers, n, v); } for(i = 0; i < opts->env_count; i++) { n = sl_make_cstring(vm, opts->env[i].name); v = sl_make_cstring(vm, opts->env[i].value); sl_dict_set(vm, req->env, n, v); } if(opts->query_string) { parse_query_string(vm, req->get, strlen(opts->query_string), (uint8_t*)opts->query_string); } if(opts->content_type && strcmp(opts->content_type, "application/x-www-form-urlencoded") == 0) { parse_query_string(vm, req->post, opts->post_length, (uint8_t*)opts->post_data); } cookies = sl_dict_get(vm, req->headers, sl_make_cstring(vm, "Cookie")); if(sl_is_a(vm, cookies, vm->lib.String)) { str = (sl_string_t*)sl_get_ptr(cookies); parse_cookie_string(vm, req->cookies, str->buff_len, str->buff); } req->params = sl_dict_merge(vm, req->get, req->post); sl_vm_store_put(vm, &Request_opts, sl_make_ptr((sl_object_t*)req)); }
static SLVAL sl_mysql_stmt_execute(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { mysql_stmt_t* stmt = get_mysql_stmt(vm, self); size_t req = mysql_stmt_param_count(stmt->stmt); if(argc < req) { char buff[100]; sprintf(buff, "Prepared statement has %lu parameter markers, but only %lu parameters were given", req, argc); sl_throw_message2(vm, vm->lib.ArgumentError, buff); } if(!stmt->bind) { stmt->bind = sl_alloc(vm->arena, sizeof(MYSQL_BIND) * req); } for(size_t i = 0; i < req; i++) { stmt->bind[i].buffer_type = MYSQL_TYPE_STRING; sl_string_t* str = sl_get_string(vm, sl_to_s(vm, argv[i])); stmt->bind[i].buffer = str->buff; stmt->bind[i].buffer_length = str->buff_len; stmt->bind[i].length = NULL; stmt->bind[i].is_null = NULL; stmt->bind[i].is_unsigned = 1; stmt->bind[i].error = NULL; } if(mysql_stmt_bind_param(stmt->stmt, stmt->bind)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } if(mysql_stmt_execute(stmt->stmt)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } MYSQL_RES* res = mysql_stmt_result_metadata(stmt->stmt); if(!res) { /* query did not produce a result set */ return sl_make_int(vm, mysql_stmt_affected_rows(stmt->stmt)); } int field_count = mysql_stmt_field_count(stmt->stmt); MYSQL_FIELD* field; SLVAL field_names[field_count]; enum enum_field_types field_types[field_count]; size_t field_i = 0; while((field = mysql_fetch_field(res))) { field_names[field_i] = sl_make_cstring(vm, field->name); if(field->type == MYSQL_TYPE_LONG || field->type == MYSQL_TYPE_SHORT || field->type == MYSQL_TYPE_TINY) { field_types[field_i] = MYSQL_TYPE_LONG; } else { field_types[field_i] = MYSQL_TYPE_STRING; } field_i++; } MYSQL_BIND output_binds[field_count]; my_bool output_errors[field_count]; my_bool output_is_nulls[field_count]; unsigned long output_lengths[field_count]; for(int i = 0; i < field_count; i++) { output_binds[i].buffer_type = MYSQL_TYPE_STRING; output_binds[i].buffer = NULL; output_binds[i].buffer_length = 0; output_binds[i].length = &output_lengths[i]; output_binds[i].is_null = &output_is_nulls[i]; output_binds[i].error = &output_errors[i]; } if(mysql_stmt_bind_result(stmt->stmt, output_binds)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } SLVAL result_rows = sl_make_array(vm, 0, NULL); while(1) { int code = mysql_stmt_fetch(stmt->stmt); if(code == MYSQL_NO_DATA) { break; } if(code == 1) { sl_mysql_stmt_check_error(vm, stmt->stmt); } SLVAL row = sl_make_dict(vm, 0, NULL); for(int i = 0; i < field_count; i++) { MYSQL_BIND cell; cell.length = &output_lengths[i]; cell.is_null = &output_is_nulls[i]; cell.error = &output_errors[i]; cell.buffer_type = field_types[i]; int buffer_long; switch(field_types[i]) { case MYSQL_TYPE_LONG: cell.buffer = &buffer_long; cell.buffer_length = sizeof(buffer_long); break; default: /* MYSQL_TYPE_STRING */ cell.buffer = sl_alloc_buffer(vm->arena, output_lengths[i] + 1); cell.buffer_length = output_lengths[i]; break; } if(mysql_stmt_fetch_column(stmt->stmt, &cell, i, 0)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } switch(field_types[i]) { case MYSQL_TYPE_LONG: sl_dict_set(vm, row, field_names[i], sl_make_int(vm, buffer_long)); break; default: /* MYSQL_TYPE_STRING */ sl_dict_set(vm, row, field_names[i], sl_make_string(vm, cell.buffer, output_lengths[i])); break; } } sl_array_push(vm, result_rows, 1, &row); } return result_rows; }