Git init
[profile/ivi/libsoup2.4.git] / libsoup / soup-directory-input-stream.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2008, 2010 Red Hat, Inc.
4  * Copyright (C) 2010 Igalia, S.L.
5  *
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.
10  *
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.
15  *
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.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "soup-directory-input-stream.h"
27
28 #include <libsoup/soup.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #define INIT_STRING "<html><head><title>OMG!</title></head><body><table>"
33 #define EXIT_STRING "</table></html>"
34
35 G_DEFINE_TYPE (SoupDirectoryInputStream, soup_directory_input_stream, G_TYPE_INPUT_STREAM)
36
37 static SoupBuffer *
38 soup_directory_input_stream_parse_info (SoupDirectoryInputStream *stream,
39                                         GFileInfo *info)
40 {
41         SoupBuffer *buffer;
42         GString *string;
43         const char *s;
44         char *escaped, *path, *xml_string;
45
46         if (!g_file_info_get_name (info))
47                 return NULL;
48
49         s = g_file_info_get_display_name (info);
50         if (!s) {
51                 s = g_file_info_get_name (info);
52                 /* FIXME: convert somehow? */
53                 if (!g_utf8_validate (s, -1, NULL))
54                         return NULL;
55         }
56         string = g_string_new ("<tr>");
57
58         xml_string = g_markup_escape_text (s, -1);
59         escaped = g_uri_escape_string (g_file_info_get_name (info), NULL, FALSE);
60         path = g_strconcat (stream->uri, "/", escaped, NULL);
61         g_free (escaped);
62         g_string_append_printf (string, "<td><a href=\"%s\">%s</a></td>", path, xml_string);
63         g_free (path);
64         g_free (xml_string);
65         g_string_append (string, "</tr>");
66
67         buffer = soup_buffer_new (SOUP_MEMORY_TAKE, string->str, string->len);
68         g_string_free (string, FALSE);
69
70         return buffer;
71 }
72
73 static SoupBuffer *
74 soup_directory_input_stream_read_next_file (SoupDirectoryInputStream  *stream,
75                                             GCancellable              *cancellable,
76                                             GError                   **error)
77 {
78         GFileInfo *info;
79         SoupBuffer *buffer;
80         GError *err = NULL;
81
82         do {
83                 info = g_file_enumerator_next_file (stream->enumerator, cancellable, &err);
84                 if (info == NULL) {
85                         if (err) {
86                                 g_propagate_error (error, err);
87                                 return NULL;
88                         } else if (!stream->done) {
89                                 stream->done = TRUE;
90                                 return soup_buffer_new (SOUP_MEMORY_STATIC,
91                                                         EXIT_STRING,
92                                                         sizeof (EXIT_STRING));
93                         } else {
94                                 return NULL;
95                         }
96                 }
97
98                 buffer = soup_directory_input_stream_parse_info (stream, info);
99                 g_object_unref (info);
100         } while (buffer == NULL);
101
102         return buffer;
103 }
104
105 static gssize
106 soup_directory_input_stream_read (GInputStream  *input,
107                                   void          *buffer,
108                                   gsize          count,
109                                   GCancellable  *cancellable,
110                                   GError       **error)
111 {
112         SoupDirectoryInputStream *stream = SOUP_DIRECTORY_INPUT_STREAM (input);
113         gsize total, size;
114
115         for (total = 0; total < count; total += size) {
116                 if (stream->buffer == NULL) {
117                         stream->buffer = soup_directory_input_stream_read_next_file (stream, cancellable, error);
118                         if (stream->buffer == NULL) {
119                                 /* FIXME: Is this correct or should we forward the error? */
120                                 if (total)
121                                         g_clear_error (error);
122                                 return total;
123                         }
124                 }
125
126                 size = MIN (stream->buffer->length, count - total);
127                 memcpy ((char *)buffer + total, stream->buffer->data, size);
128                 if (size == stream->buffer->length) {
129                         soup_buffer_free (stream->buffer);
130                         stream->buffer = NULL;
131                 } else {
132                         SoupBuffer *sub = soup_buffer_new_subbuffer (stream->buffer,
133                                                                      size,
134                                                                      stream->buffer->length - size);
135                         soup_buffer_free (stream->buffer);
136                         stream->buffer = sub;
137                 }
138         }
139
140         return total;
141 }
142
143 static gboolean
144 soup_directory_input_stream_close (GInputStream  *input,
145                                    GCancellable  *cancellable,
146                                    GError       **error)
147 {
148         SoupDirectoryInputStream *stream = SOUP_DIRECTORY_INPUT_STREAM (input);
149         gboolean result;
150
151         if (stream->buffer) {
152                 soup_buffer_free (stream->buffer);
153                 stream->buffer = NULL;
154         }
155
156         result = g_file_enumerator_close (stream->enumerator,
157                                           cancellable,
158                                           error);
159         g_object_unref (stream->enumerator);
160         stream->enumerator = NULL;
161
162         g_free (stream->uri);
163         stream->uri = NULL;
164
165         return result;
166 }
167
168 static void
169 soup_directory_input_stream_class_init (SoupDirectoryInputStreamClass *stream_class)
170 {
171         GInputStreamClass *inputstream_class = G_INPUT_STREAM_CLASS (stream_class);
172
173         inputstream_class->read_fn = soup_directory_input_stream_read;
174         inputstream_class->close_fn = soup_directory_input_stream_close;
175 }
176
177 static void
178 soup_directory_input_stream_init (SoupDirectoryInputStream *stream)
179 {
180         stream->buffer = soup_buffer_new (SOUP_MEMORY_STATIC,
181                                           INIT_STRING,
182                                           sizeof (INIT_STRING));
183 }
184
185 GInputStream *
186 soup_directory_input_stream_new (GFileEnumerator *enumerator,
187                                  SoupURI         *uri)
188 {
189         GInputStream *stream;
190
191         g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
192         g_return_val_if_fail (uri != NULL, NULL);
193
194         stream = g_object_new (SOUP_TYPE_DIRECTORY_INPUT_STREAM, NULL);
195
196         SOUP_DIRECTORY_INPUT_STREAM (stream)->enumerator = g_object_ref (enumerator);
197         SOUP_DIRECTORY_INPUT_STREAM (stream)->uri = soup_uri_to_string (uri, FALSE);
198
199         return stream;
200 }
201