aboutsummaryrefslogtreecommitdiff
path: root/plugins/http-files/src/file_provider.vala
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/http-files/src/file_provider.vala')
-rw-r--r--plugins/http-files/src/file_provider.vala49
1 files changed, 44 insertions, 5 deletions
diff --git a/plugins/http-files/src/file_provider.vala b/plugins/http-files/src/file_provider.vala
index e3382439..11885721 100644
--- a/plugins/http-files/src/file_provider.vala
+++ b/plugins/http-files/src/file_provider.vala
@@ -46,6 +46,38 @@ public class FileProvider : Dino.FileProvider, Object {
}
}
+ private class LimitInputStream : InputStream {
+ InputStream inner;
+ int64 remaining_size;
+
+ public LimitInputStream(InputStream inner, int64 max_size) {
+ this.inner = inner;
+ this.remaining_size = max_size;
+ }
+
+ private ssize_t check_limit(ssize_t read) throws IOError {
+ this.remaining_size -= read;
+ if (remaining_size < 0) throw new IOError.FAILED("Stream length exceeded limit");
+ return read;
+ }
+
+ public override ssize_t read(uint8[] buffer, Cancellable? cancellable = null) throws IOError {
+ return check_limit(inner.read(buffer, cancellable));
+ }
+
+ public override async ssize_t read_async(uint8[]? buffer, int io_priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws IOError {
+ return check_limit(yield inner.read_async(buffer, io_priority, cancellable));
+ }
+
+ public override bool close(Cancellable? cancellable = null) throws IOError {
+ return inner.close(cancellable);
+ }
+
+ public override async bool close_async(int io_priority = GLib.Priority.DEFAULT, Cancellable? cancellable = null) throws IOError {
+ return yield inner.close_async(io_priority, cancellable);
+ }
+ }
+
private void on_file_message(Entities.Message message, Conversation conversation) {
var additional_info = message.id.to_string();
@@ -64,9 +96,11 @@ public class FileProvider : Dino.FileProvider, Object {
if (http_receive_data == null) return file_meta;
var session = new Soup.Session();
+ session.user_agent = @"Dino/$(Dino.get_short_version()) ";
var head_message = new Soup.Message("HEAD", http_receive_data.url);
if (head_message != null) {
+ head_message.request_headers.append("Accept-Encoding", "identity");
try {
yield session.send_async(head_message, null);
} catch (Error e) {
@@ -75,12 +109,12 @@ public class FileProvider : Dino.FileProvider, Object {
string? content_type = null, content_length = null;
head_message.response_headers.foreach((name, val) => {
- if (name == "Content-Type") content_type = val;
- if (name == "Content-Length") content_length = val;
+ if (name.down() == "content-type") content_type = val;
+ if (name.down() == "content-length") content_length = val;
});
file_meta.mime_type = content_type;
if (content_length != null) {
- file_meta.size = int.parse(content_length);
+ file_meta.size = int64.parse(content_length);
}
}
@@ -97,9 +131,14 @@ public class FileProvider : Dino.FileProvider, Object {
try {
var session = new Soup.Session();
+ session.user_agent = @"Dino/$(Dino.get_short_version()) ";
Soup.Request request = session.request(http_receive_data.url);
-
- return yield request.send_async(null);
+ InputStream stream = yield request.send_async(file_transfer.cancellable);
+ if (file_meta.size != -1) {
+ return new LimitInputStream(stream, file_meta.size);
+ } else {
+ return stream;
+ }
} catch (Error e) {
throw new FileReceiveError.DOWNLOAD_FAILED("Downloading file error: %s".printf(e.message));
}