コード例 #1
0
ファイル: main.c プロジェクト: tomohikoseven/http
static void
do_file_response
(
    struct HTTPRequest *req,    /* HTTP request */
    FILE *out,                  /* output fd    */
    char *docroot               /* docroot path */
)
{
    struct FileInfo *info = NULL;

    dbg( "req=%p, out=%p, docroot=%p\n", req, out, docroot );

    info = get_fileinfo( docroot, req->path );
    if( 0 == info->ok )
    {
        free_fileinfo( info );
        not_found( req, out );
        return ;
    }

    output_common_header_fields( req, out, "200 OK" );

    fprintf( out, "Content-Length: %ld\r\n", info->size              );
    fprintf( out, "Content-Type: %s\r\n", guess_content_type( info ) );
    fprintf( out, "\r\n"                                             );

    outputBodyFields( info, req, out );

    fflush( out );
    free_fileinfo( info );
}
コード例 #2
0
ファイル: utils.c プロジェクト: MaximeCheramy/zathura
bool
file_valid_extension(zathura_t* zathura, const char* path)
{
  if (zathura == NULL || path == NULL || zathura->plugins.manager == NULL) {
    return false;
  }

  const gchar* content_type = guess_content_type(path);
  if (content_type == NULL) {
    return false;
  }

  zathura_plugin_t* plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type);
  g_free((void*)content_type);

  return (plugin == NULL) ? false : true;
}
コード例 #3
0
ファイル: webif.cpp プロジェクト: qdk0901/webif
void send_file(evhtp_request_t* req, char* path)
{
	struct stat st;
	unsigned char data[1024];
	int fd;
	int n;
	evbuf_t* buf = NULL;
	
	if (stat(path, &st) < 0 || S_ISDIR(st.st_mode))
		goto file_error;
		
	fd = open(path, O_RDONLY);
	
	if (fd < 0)
		goto file_error;
		
	buf = evbuffer_new();
	
	evhtp_headers_add_header(req->headers_out,
								 evhtp_header_new("Content-Type", guess_content_type(path), 0, 0));
	
	evhtp_send_reply_chunk_start(req, EVHTP_RES_OK);
	do {
		n = read(fd, data, sizeof(data));
		evbuffer_add(buf, data, n);
		evhtp_send_reply_chunk(req, buf);
		evbuffer_drain(buf, -1);
	} while (n > 0);
	close(fd);
	
	evhtp_send_reply_chunk_end(req);
	evbuffer_free(buf);

	return;
	
file_error:
	evbuffer_add_printf(req->buffer_out, "ERROR:%s", path);
	evhtp_send_reply(req, EVHTP_RES_OK);		
}
コード例 #4
0
static void do_file_response(struct HTTPRequest *req, FILE *out, char *docroot) {
  struct FileInfo *info;

  info = get_fileinfo(docroot, req->path);
  if (!info->ok) {
    free_fileinfo(info);
    not_found(req, out);
    return;
  }
  output_common_header_fields(req, out, "200 OK");
  fprintf(out, "Content-Length: %ld\r\n", info->size);
  fprintf(out, "Content-Type: %s\r\n", guess_content_type(info));
  fprintf(out, "\r\n");
  if (strcmp(req->method, "HEAD") != 0) {
    int fd;
    char buf[BLOCK_BUF_SIZE];
    ssize_t n;

    fd = open(info->path, O_RDONLY);
    if (fd < 0) {
      log_exit("failed to open %s: %s", info->path, strerror(errno));
    }
    while (1) {
      n = read(fd, buf, BLOCK_BUF_SIZE);
      if (n < 0) {
          log_exit("failed to read %s: %s", info->path, strerror(errno));
      }
      if (n == 0) {
        break;
      }
      if (fwrite(buf, n, 1, out) < 1) {
        log_exit("failed to write to socket: %s", strerror(errno));
      }
    }
    close(fd);
  }
  fflush(out);
  free_fileinfo(info);
}
コード例 #5
0
static void send_document_cb(struct evhttp_request *req, void *arg) {
	struct evbuffer *evb = NULL;
	const char *uri = evhttp_request_get_uri(req);
	char *whole_path = NULL;
	int fd = -1, fsize;

	printf("Got a GET request for <%s>\n",  uri);

	fsize = encode_request_to_file_path(uri, &whole_path);
	if (!fsize) {
		goto err;
	}

	evb = evbuffer_new();

	const char *type = guess_content_type(whole_path);
	if ((fd = open(whole_path, O_RDONLY)) < 0) {
		perror("open");
		goto err;
	}

	evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", type);
	evbuffer_add_file(evb, fd, 0, fsize);

	evhttp_send_reply(req, 200, "OK", evb);
	goto done;
err:
	evhttp_send_error(req, 404, "Document was not found");
	if (fd>=0) {
		close(fd);
	}
done:
	if (whole_path) {
		free(whole_path);
	}
	if (evb) {
		evbuffer_free(evb);
	}
}
コード例 #6
0
ファイル: http.c プロジェクト: pearsonalan/stats
static void http_document_request_cb(struct evhttp_request *req, void *arg)
{
    struct evbuffer *evb = NULL;
    struct http *http = (struct http *) arg;
    const char *docroot = http->docroot;
    const char *uri = evhttp_request_get_uri(req);
    struct evhttp_uri *decoded = NULL;
    const char *path;
    char *decoded_path;
    char *whole_path = NULL;
    size_t len;
    int fd = -1;
    struct stat st;

    if (evhttp_request_get_command(req) != EVHTTP_REQ_GET)
    {
        evhttp_send_error(req, HTTP_BADREQUEST, 0);
        return;
    }

    printf("GET: %s\n",  uri);

    /* Decode the URI */
    decoded = evhttp_uri_parse(uri);
    if (!decoded)
    {
        evhttp_send_error(req, HTTP_BADREQUEST, 0);
        return;
    }

    /* Let's see what path the user asked for. */
    path = evhttp_uri_get_path(decoded);
    if (!path) path = "/";

    /* We need to decode it, to see what path the user really wanted. */
    decoded_path = evhttp_uridecode(path, 0, NULL);
    if (decoded_path == NULL)
        goto err;

    /* Don't allow any ".."s in the path, to avoid exposing stuff outside
     * of the docroot.  This test is both overzealous and underzealous:
     * it forbids aceptable paths like "/this/one..here", but it doesn't
     * do anything to prevent symlink following." */
    if (strstr(decoded_path, ".."))
        goto err;

    len = strlen(decoded_path) + strlen(docroot) + 2;
    if (!(whole_path = malloc(len)))
    {
        goto err;
    }

    snprintf(whole_path, len, "%s/%s", docroot, decoded_path);

    if (stat(whole_path, &st) < 0)
    {
        goto err;
    }

    /* This holds the content we're sending. */
    evb = evbuffer_new();

    if (S_ISDIR(st.st_mode))
    {
        /* TODO: send index.html if the request is for a directory */
        goto err;
    }
    else
    {
        /* Otherwise it's a file; add it to the buffer to get
         * sent via sendfile */
        const char *type = guess_content_type(decoded_path);
        if ((fd = open(whole_path, O_RDONLY)) < 0)
        {
            goto err;
        }

        if (fstat(fd, &st) < 0)
        {
            /* Make sure the length still matches, now that we
             * opened the file :/ */
            goto err;
        }

        evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", type);

        /* TODO: does this read the whole thing into memory??  well, we are only going to be
         * serving small files out of the static content directory, so its probably OK. */
        evbuffer_add_file(evb, fd, 0, st.st_size);
    }

    evhttp_send_reply(req, 200, "OK", evb);
    goto done;

err:
    evhttp_send_error(req, 404, "Document was not found");
    if (fd >= 0)
        close(fd);

done:
    if (decoded)
        evhttp_uri_free(decoded);

    if (decoded_path)
        free(decoded_path);

    if (whole_path)
        free(whole_path);

    if (evb)
        evbuffer_free(evb);
}
コード例 #7
0
static void static_list_request_cb(struct evhttp_request *req, void *arg)
{
	struct evbuffer *evb = NULL;
	struct evhttp_uri *decoded = NULL;
	const char *path;
	char *decoded_path;
	int fd = -1;
	struct stat st;
	char uri_root[512] = {0};
	struct evhttp_bound_socket *handle = (struct evhttp_bound_socket *)arg;

	size_t len;
	char *whole_path = NULL;

	const char *uri = evhttp_request_get_uri(req);
	get_uri_root(handle, uri_root, sizeof(uri_root));


	decoded = evhttp_uri_parse(uri);
	if (decoded == NULL) {
		LOG(LOG_ERROR, "%s", "evhttp_decode_uri error");
		evhttp_send_error(req, HTTP_BADREQUEST, 0);
		exit(1);
	}

	path = evhttp_uri_get_path(decoded);
	if (!path) path = "/";

	decoded_path = evhttp_uridecode(path, 0, NULL);
	if (decoded_path == NULL)
		goto err;

	if (strstr(decoded_path, ".."))
		goto err;

	len = strlen(decoded_path)+strlen(docroot)+2;
	if (!(whole_path = malloc(len))) {
		perror("malloc");
		goto err;
	}
	evutil_snprintf(whole_path, len, "%s/%s", docroot, decoded_path);

	if (stat(whole_path, &st)<0) {
		goto err;
	}

	evb = evbuffer_new();

	if (S_ISDIR(st.st_mode)) {
		DIR *d;
		struct dirent *ent;

		const char *trailing_slash = "";

		if (!strlen(path) || path[strlen(path)-1] != '/')
			trailing_slash = "/";

		if (!(d = opendir(whole_path)))
			goto err;

		evbuffer_add_printf(evb, "<html>\n <head>\n"
		    "  <title>%s</title>\n"
		    "  <base href='%s%s%s'>\n"
		    " </head>\n"
		    " <body>\n"
		    "  <h1>%s</h1>\n"
		    "  <ul>\n",
		    decoded_path, /* XXX html-escape this. */
		    uri_root, path, /* XXX html-escape this? */
		    trailing_slash,
		    decoded_path /* XXX html-escape this */);

		while((ent = readdir(d))) {
			const char *name = ent->d_name;
			evbuffer_add_printf(evb, "    <li><a href=\"%s\">%s</a>\n", name, name);
			evbuffer_add_printf(evb, "</ul></body></html>\n");
		}
		closedir(d);
		evhttp_add_header(evhttp_request_get_output_headers(req), "Content-type", "text/html");
	} else {
		const char *type = guess_content_type(decoded_path);
		if ((fd = open(whole_path, O_RDONLY)) < 0) {
			perror("open");
			goto err;
		}

		if (fstat(fd, &st)<0) {
					/* Make sure the length still matches, now that we
					 * opened the file :/ */
					perror("fstat");
					goto err;
		}

		evhttp_add_header(evhttp_request_get_output_headers(req),
			    "Content-Type", type);

		evbuffer_add_file(evb, fd, 0, st.st_size);
	}

	evhttp_send_reply(req, HTTP_OK, "OK", evb);
	goto done;

err:
	evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found");
	if (fd>=0)
		close(fd);

done:
	if (decoded)
		evhttp_uri_free(decoded);
	if (decoded_path)
		free(decoded_path);
	if (whole_path)
		free(whole_path);
	if (evb)
		evbuffer_free(evb);
}
コード例 #8
0
ファイル: httpd.c プロジェクト: jrswanson91/HTTPServer
/**
 * Send a file to the client.
 *
 * @param req The request.
 * @param filepath The path to the file (in UNIX space).
 * @param sb The result of calling 'stat' on the file.
 */
static int send_file(FILE *stream, req_t *req, const char *filepath, struct stat *sb)
{
    // regular file, send it
    char *buf = g_malloc(BUFFER_SIZE);
    ssize_t nb;
    int result = 0;
    FILE *file = fopen(filepath, "rb");
    if (!file) {
        switch (errno) {
            case ENOENT:
                send_error(stream, 404, "Not Found",
                           "The resource %s could not be found.",
                           req_path(req));
                break;
            case EACCES:
                send_error(stream, 401, "Forbidden",
                           "The resource %s could not be read.",
                           req_path(req));
                break;
            default:
                send_error(stream, 500, "Internal Server Error",
                           "%s: %s", req_path(req), strerror(errno));
                break;
        }
        // the error should have been picked up earlier (calling 'stat'), so
        // return with error
        return -1;
    }

    fprintf(stream, "HTTP/1.0 200 OK\r\n");
    const char *ctype = guess_content_type(filepath);
    if (ctype != NULL) {
        fprintf(stream, "Content-Type: %s\r\n", ctype);
    }
    size_t length = sb->st_size;
    struct tm *mod_time = gmtime(&(sb->st_mtime));
    fprintf(stream, "Content-Length: %zd\r\n", length);
    char TIME_BUF[512];
    strftime(TIME_BUF, 512, "%a, %d %b %Y %H:%M:%S %Z", mod_time);
    fprintf(stream, "Last-Modified: %s\r\n", TIME_BUF);
    fprintf(stream, "\r\n");
    size_t total_bytes = 0;
    while ((nb = fread(buf, 1, BUFFER_SIZE, file)) > 0) {
        if (total_bytes + nb > length) {
            fprintf(stderr, "%s: file size changed\n", filepath);
            nb = length - total_bytes;
            result = -1;
            break;
        }
        size_t written = 0;
        while (written < nb) {
            size_t wr = fwrite(buf + written, 1, nb - written, stream);
            if (wr > 0) {
                written += wr;
            } else {
                // fwrite returns 0 for error
                // too late to send an error to the client to 
                perror("output");
                result = -1;
                break;
            }
        }
        total_bytes += nb;
    }
    if (!feof(file)) {
        perror(filepath);
        result = -1;
    }

    fclose(file);
    // TODO send stat data

    return result;
}
コード例 #9
0
static void test_foobar_null()
{
    const char *type = guess_content_type("foo.wombat");
    g_assert_null(type);
}
コード例 #10
0
static void test_double_extension()
{
    const char *type = guess_content_type("index.html.jpg");
    g_assert_cmpstr(type, ==, "image/jpeg");
}
コード例 #11
0
static void test_html_upcase()
{
    const char *type = guess_content_type("INDEX.HTML");
    g_assert_cmpstr(type, ==, "text/html");
}
コード例 #12
0
static void test_htm()
{
    const char *type = guess_content_type("index.htm");
    g_assert_cmpstr(type, ==, "text/html");
}