1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2008, 2010 Red Hat, Inc.
4 * Copyright (C) 2010 Igalia, S.L.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include "soup-directory-input-stream.h"
28 #include <libsoup/soup.h>
32 #define INIT_STRING "<html>\n<body>\n<table><th align=\"left\">Name</th><th>Size</th><th>Date Modified</th>\n"
33 #define ROW_FORMAT "<td><a href=\"%s\">%s</a></td><td align=\"right\">%s</td><td align=\"right\" margin=8>%s</td>\n"
34 #define EXIT_STRING "</table>\n</html>\n"
36 G_DEFINE_TYPE (SoupDirectoryInputStream, soup_directory_input_stream, G_TYPE_INPUT_STREAM)
39 soup_directory_input_stream_parse_info (SoupDirectoryInputStream *stream,
44 const char *file_name;
45 char *escaped, *path, *xml_string, *size, *time;
47 GDateTime *modification_time;
49 if (!g_file_info_get_name (info))
52 file_name = g_file_info_get_display_name (info);
54 file_name = g_file_info_get_name (info);
55 /* FIXME: convert somehow? */
56 if (!g_utf8_validate (file_name, -1, NULL))
59 string = g_string_new ("<tr>");
61 xml_string = g_markup_escape_text (file_name, -1);
62 escaped = g_uri_escape_string (file_name, NULL, FALSE);
63 path = g_strconcat (stream->uri, G_DIR_SEPARATOR_S, escaped, NULL);
64 size = g_format_size_for_display (g_file_info_get_size (info));
65 g_file_info_get_modification_time (info, &modified);
66 modification_time = g_date_time_new_from_timeval_local (&modified);
67 time = g_date_time_format (modification_time, "%X %x");
68 g_date_time_unref (modification_time);
70 g_string_append_printf (string, ROW_FORMAT, path, xml_string, size, time);
71 g_string_append (string, "</tr>\n");
72 buffer = soup_buffer_new (SOUP_MEMORY_TAKE, string->str, string->len);
79 g_string_free (string, FALSE);
85 soup_directory_input_stream_read_next_file (SoupDirectoryInputStream *stream,
86 GCancellable *cancellable,
94 info = g_file_enumerator_next_file (stream->enumerator, cancellable, &err);
97 g_propagate_error (error, err);
99 } else if (!stream->done) {
101 return soup_buffer_new (SOUP_MEMORY_STATIC,
103 sizeof (EXIT_STRING));
109 buffer = soup_directory_input_stream_parse_info (stream, info);
110 g_object_unref (info);
111 } while (buffer == NULL);
117 soup_directory_input_stream_read (GInputStream *input,
120 GCancellable *cancellable,
123 SoupDirectoryInputStream *stream = SOUP_DIRECTORY_INPUT_STREAM (input);
126 for (total = 0; total < count; total += size) {
127 if (stream->buffer == NULL) {
128 stream->buffer = soup_directory_input_stream_read_next_file (stream, cancellable, error);
129 if (stream->buffer == NULL) {
130 /* FIXME: Is this correct or should we forward the error? */
132 g_clear_error (error);
137 size = MIN (stream->buffer->length, count - total);
138 memcpy ((char *)buffer + total, stream->buffer->data, size);
139 if (size == stream->buffer->length) {
140 soup_buffer_free (stream->buffer);
141 stream->buffer = NULL;
143 SoupBuffer *sub = soup_buffer_new_subbuffer (stream->buffer,
145 stream->buffer->length - size);
146 soup_buffer_free (stream->buffer);
147 stream->buffer = sub;
155 soup_directory_input_stream_close (GInputStream *input,
156 GCancellable *cancellable,
159 SoupDirectoryInputStream *stream = SOUP_DIRECTORY_INPUT_STREAM (input);
162 if (stream->buffer) {
163 soup_buffer_free (stream->buffer);
164 stream->buffer = NULL;
167 result = g_file_enumerator_close (stream->enumerator,
170 g_object_unref (stream->enumerator);
171 stream->enumerator = NULL;
173 g_free (stream->uri);
180 soup_directory_input_stream_class_init (SoupDirectoryInputStreamClass *stream_class)
182 GInputStreamClass *inputstream_class = G_INPUT_STREAM_CLASS (stream_class);
184 inputstream_class->read_fn = soup_directory_input_stream_read;
185 inputstream_class->close_fn = soup_directory_input_stream_close;
189 soup_directory_input_stream_init (SoupDirectoryInputStream *stream)
191 stream->buffer = soup_buffer_new (SOUP_MEMORY_STATIC,
193 sizeof (INIT_STRING));
197 soup_directory_input_stream_new (GFileEnumerator *enumerator,
200 GInputStream *stream;
202 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
203 g_return_val_if_fail (uri != NULL, NULL);
205 stream = g_object_new (SOUP_TYPE_DIRECTORY_INPUT_STREAM, NULL);
207 SOUP_DIRECTORY_INPUT_STREAM (stream)->enumerator = g_object_ref (enumerator);
208 SOUP_DIRECTORY_INPUT_STREAM (stream)->uri = soup_uri_to_string (uri, FALSE);