Exemplo n.º 1
0
int parse_url(const char *url, struct http_parser_url *u, http_request *request)
{
	if (url == NULL) {
		return -1;
	}
	char real_url[1024] = {0};
	if ((is_match_pattern(url, REGEX_URL_SCHEME)) != 0)  {
		snprintf(real_url, 1024, "http://%s", url);
	} else {
		snprintf(real_url, 1024, "%s", url);
	}
	SCREEN(SCREEN_YELLOW, stdout, "Request url:\t\t");
	SCREEN(SCREEN_DARK_GREEN, stdout, "%s\n", real_url);

	int url_len = strlen(real_url);
	int ret = http_parser_parse_url(real_url, url_len, 0, u);
	if (ret != 0) {
		printf("Invalid request url!\n");
		return -1;
	}

	char strport[64] = {0};
	for (unsigned i = 0; i < UF_MAX; i++) {
		if ((u->field_set & (1 << i)) == 0) {
			continue;
		}
		switch (i) {
			case UF_SCHEMA:
				snprintf(request->scheme, 16, "%.*s", u->field_data[i].len, real_url + u->field_data[i].off);
				break;
			case UF_HOST:
				snprintf(request->host, 256, "%.*s", u->field_data[i].len, real_url + u->field_data[i].off);
				break;
			case UF_PORT:
				snprintf(strport, 64, "%.*s", u->field_data[i].len, real_url + u->field_data[i].off);
				request->port = atoi(strport);
				break;
			case UF_PATH:
				snprintf(request->path, 256, "%.*s", u->field_data[i].len, real_url + u->field_data[i].off);
				break;
			case UF_QUERY:
				snprintf(request->querystring, 1024, "%.*s", u->field_data[i].len, real_url + u->field_data[i].off);
				break;
			case UF_FRAGMENT:
				snprintf(request->fragment, 256, "%.*s", u->field_data[i].len, real_url + u->field_data[i].off);
				break;
			case UF_USERINFO:
				snprintf(request->userinfo, 256, "%.*s", u->field_data[i].len, real_url + u->field_data[i].off);
				break;
			default:
				break;
		}
	}
	return 0;
}
Exemplo n.º 2
0
const SpObject *SpVM::call_function(const std::string &name, const SpFunction *func, const SpExpr *call_expr, SpEnv *env) {
   // now, evaluate the arguments in a new scope
   // this is because Spooner is lexically scoped, so any this function call
   // can only access its arguments
   std::unique_ptr<SpEnv> call_env(new SpEnv());

   // check if the correct number of arguments are provided
   if (call_expr->length() - 1 != func->num_arguments())
      RUNTIME_ERROR_F("Function call to '%s' requires %lu arguments, "
         "but %d given", name.c_str(), func->num_arguments(),
         call_expr->length() - 1);

   size_t arg_index = 0;
   for (auto it = call_expr->cbegin(); it != call_expr->cend(); ++it, arg_index++) {
      // if there is a pattern for this argument
      if (arg_index < func->pattern()->length()) {
         // need to handle the quote pattern specially
         if (func->pattern(arg_index)->type() == T_NAME) {
            const char *name = ((SpName *)func->pattern(arg_index))->value();
            if (!strcmp(name, "quote")) {
               // we need to quote this argument and not evaluate it
               call_env->bind_name(func->arguments(arg_index), new SpExprObject(*it));
            } else if (!strcmp(name, "_")) {
               // wildcards match anything
               call_env->bind_name(func->arguments(arg_index), eval(*it, env));
            } else { 
               // TODO: allow names in patterns
               RUNTIME_ERROR("Names cannot be used in patterns yet...");
            }
         } else {
            // check if this pattern matches
            const SpObject *arg_result = eval(*it, env);
            if (is_match_pattern(func->pattern(arg_index), arg_result)) {
               // good, we'll bind this argument
               call_env->bind_name(func->arguments(arg_index), arg_result);
            } else {
               RUNTIME_ERROR_F("Arguments in function call to '%s' do not match any patterns", name.c_str());
            }
         }
      } else {
         // no pattern means anything matches
         call_env->bind_name(func->arguments(arg_index), eval(*it, env));
      }
   }

   // call the function (either natively or in the VM) using the new environment 
   return func->is_native() ?
      call_native_function((SpNativeFunction *)func, call_env.get()) :
      call_function_with_env(func, call_env.get());
}
Exemplo n.º 3
0
void compose_request_buffer(http_request* request)
{
	char *buffer = calloc(1, REQUEST_BUFFER_SIZE * sizeof(char));
	ASSERT_ALLOCATE(buffer);

	size_t offset = 0;
	
	/* Start line */
	int bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "%s ", get_method_name(request->method));
	offset += bytes;

	/* Path, querystring, fragment */
	if (strlen(request->path) > 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "%s", request->path);
		offset += bytes;
	}

	if (strlen(request->querystring) > 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "?%s", request->querystring);
		offset += bytes;
	}

	if (strlen(request->fragment) > 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "#%s ", request->fragment);
		offset += bytes;
	}

	bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, " %s\r\n", HTTP_1_1);
	offset += bytes;
	/* Start line ends here */
	bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Accept: */*\r\n");
	offset += bytes;

	/* Host */ 
	if (is_match_pattern(request->host, REGEX_IPV4) != 0 && strcasecmp(request->host, "localhost") != 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Host: %s\r\n", request->host);
		offset += bytes;
	} else {
		char host[256] = {'\0'};
		get_header_value("Host", request->additional_header, host);
		if (strlen(host) == 0) {
			if (request->port == PORT_HTTP) {
				bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Host: %s\r\n", request->host);
				offset += bytes;
			} else { 
				bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Host: %s:%d\r\n", request->host, request->port);
				offset += bytes;
			}
		}
	}

	if (request->http_keep_alive == HTTP_KEEP_ALIVE) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Connection: keep-alive\r\n");
		offset += bytes;
	}
	
	if (strlen(request->bodydata) != 0 && request->file_upload != NULL) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
		offset += bytes;
	} else if (strlen(request->content_type) > 0) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Content-Type: %s\r\n", request->content_type);
		offset += bytes;
	}

	if (request->additional_header != NULL) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "%s\r\n", request->additional_header);
		offset += bytes;
	}

	if (!(strlen(request->bodydata) != 0 && request->file_upload != NULL)) {
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Content-Length: %d\r\n", request->content_length);
		offset += bytes;

		/* Header ends here */
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "\r\n");
		offset += bytes;

		SCREEN(SCREEN_BLUE, stdout, "Http request header:\n");
		SCREEN(SCREEN_GREEN, stdout, "%s", buffer);

		if (request->file_upload != NULL) {
			int fd = open(request->file_upload, O_RDONLY);
			if (fd < 0) {
				perror("open(2)");
				exit(EXIT_FAILURE);
			}

			bytes = read(fd, buffer + offset, request->content_length);
			if (bytes != request->content_length) {
				SCREEN(SCREEN_RED, stderr, "Cannot read your input file: %s.\n", request->file_upload);
				exit(EXIT_FAILURE);
			}
			offset += bytes;
		} else if (strlen(request->bodydata) != 0) {
			bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "%s", request->bodydata);
			offset += bytes;
		} 

	} else {
		/* Two multi-part */
		/* We need to caculate Content-Length again */
		char *extrabuffer = (char *) calloc(1, (REQUEST_BUFFER_SIZE) * sizeof(char));
		ASSERT_ALLOCATE(extrabuffer);

		int bodyoffset = 0;
		bytes = snprintf(extrabuffer + bodyoffset, REQUEST_BUFFER_SIZE - bodyoffset, "%s\r\nContent-Disposition: form-data; name=\"img\", filename=\"%s\"\r\nContent-Type: image/jpeg\r\n\r\n", 
				boundary, basename(request->file_upload));
		bodyoffset += bytes;
		int fd = open(request->file_upload, O_RDONLY);
		if (fd < 0) {
			perror("open(2)");
			exit(EXIT_FAILURE);
		}

		bytes = read(fd, extrabuffer + bodyoffset, request->file_size);
		if (bytes != request->file_size) {
			SCREEN(SCREEN_RED, stderr, "Cannot read your input file: %s.\n", request->file_upload);
			exit(EXIT_FAILURE);
		}
		bodyoffset += request->file_size;

		bytes = snprintf(extrabuffer + bodyoffset, REQUEST_BUFFER_SIZE - bodyoffset, "\r\n%s\r\nContent-Disposition: form-data; name=\"json\"\r\n\r\n%s\r\n%s\r\n",  boundary, request->bodydata, boundary); 
		bodyoffset += bytes;

		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "Content-Length: %d\r\n", bodyoffset);
		offset += bytes;

		/* Header ends here */
		bytes = snprintf(buffer + offset, REQUEST_BUFFER_SIZE - offset, "\r\n");
		offset += bytes;

		SCREEN(SCREEN_BLUE, stdout, "Http request header:\n");
		SCREEN(SCREEN_GREEN, stdout, "%s", buffer);

		memmove(buffer + offset, extrabuffer, bodyoffset);
		offset += bodyoffset;
	} 


	request->send_buffer = buffer;
	request->total_length = offset;

	return;
}