Skip to content

Commit

Permalink
WIP: Multipart streams
Browse files Browse the repository at this point in the history
  • Loading branch information
arteymix committed Jul 2, 2015
1 parent ea78943 commit 62cc6e6
Showing 1 changed file with 128 additions and 0 deletions.
128 changes: 128 additions & 0 deletions src/vsgi/multipart.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using GLib;
using Soup;

namespace VSGI {

/**
* It provides similar APIs to {@link Soup.MultipartInputStream}.
*
* @since 0.3
*/
public class MultipartInputStream : FilterInputStream {

public MessageHeaders headers { construct; get; }

public MultipartInputStream (MessageHeaders headers, InputStream base_stream) {
Object (headers: headers, base_stream: base_stream);
}

/**
* Obtain the stream over the next part of that multipart message.
*
* @return a stream over the next part of null if none's available
*/
public InputStream? next_part (out MessageHeaders part_headers, Cancellable? cancellable = null) throws IOError {
HashTable<string, string> @params;
headers.get_content_type (out @params);

var boundary = @params["boundary"];

assert (@params.contains ("boundary"));

var line_reader = new DataInputStream (base_stream);

line_reader.newline_type = DataStreamNewlineType.CR_LF;

// read until the next boundary
do {
var line = line_reader.read_line (null, cancellable);

if (line == null)
break; // end of input

if (line == "--" + boundary) {
// consume current headers
var headers = new StringBuilder ();

do {
var header_line = line_reader.read_line (null, cancellable);

if (header_line == "")
break; // empty line preceeding the body

if (header_line == null)
return null; // end of input..?

headers.append (header_line + "\r\n");
} while (true);

headers_parse (headers.str, (int) headers.len, part_headers);

return base_stream;
}

if (line == "--" + boundary + "--")
return null; // end of multipart message (eiplogue follows...)
} while (true);

return null; // end of input
}

public override ssize_t read (uint8[] buffer, Cancellable? cancellable = null) throws IOError {
return base_stream.read (buffer, cancellable);
}

public override bool close (Cancellable? cancellable = null) throws IOError {
return base_stream.close (cancellable);
}
}

/**
*
* @since 0.3
*/
public class MultipartOutputStream : FilterOutputStream {

public MessageHeaders headers { construct; get; }

public MultipartOutputStream (MessageHeaders headers, OutputStream base_stream) {
Object (headers: headers, base_stream: base_stream);
}

/**
* Create a new part in this multipart message.
*/
public OutputStream new_part (MessageHeaders part_headers) throws IOError {
HashTable<string, string> @params;
headers.get_content_type (out @params);

var boundary = @params["boundary"];
var writer = new DataOutputStream (base_stream);

part_headers.foreach ((k, v) => {
writer.put_string ("%s: %s\r\n".printf (k, v));
});

writer.put_string ("\r\n");

return base_stream;
}

public override ssize_t write (uint8[] buffer, Cancellable? cancellable = null) throws IOError {
return base_stream.write (buffer, cancellable);
}

/**
* Append the final enclosing boundary and close the base stream.
*/
public override bool close (Cancellable? cancellable = null) throws IOError {
HashTable<string, string> @params;
headers.get_content_type (out @params);

var boundary = @params["boundary"];
var writer = new DataOutputStream (base_stream);

return writer.put_string ("--" + boundary + "--\r\n", cancellable) && base_stream.close (cancellable);
}
}
}

0 comments on commit 62cc6e6

Please sign in to comment.