1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2008 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * Author: Christian Kellner <gicmo@gnome.org>
21  */
22 
23 #include <config.h>
24 #include <string.h>
25 
26 #include <stdlib.h> /* atoi */
27 
28 #include <gio/gio.h>
29 #include <gvfsurimapper.h>
30 #include <gvfsuriutils.h>
31 
32 typedef struct _GVfsUriMapperHttp GVfsUriMapperHttp;
33 typedef struct _GVfsUriMapperHttpClass GVfsUriMapperHttpClass;
34 
35 struct _GVfsUriMapperHttp
36 {
37   GVfsUriMapper parent;
38 };
39 
40 struct _GVfsUriMapperHttpClass
41 {
42   GVfsUriMapperClass parent_class;
43 };
44 
45 GType g_vfs_uri_mapper_http_get_type (void);
46 void  g_vfs_uri_mapper_http_register (GIOModule *module);
47 
G_DEFINE_DYNAMIC_TYPE(GVfsUriMapperHttp,g_vfs_uri_mapper_http,G_VFS_TYPE_URI_MAPPER)48 G_DEFINE_DYNAMIC_TYPE (GVfsUriMapperHttp, g_vfs_uri_mapper_http, G_VFS_TYPE_URI_MAPPER)
49 
50 static void
51 g_vfs_uri_mapper_http_init (GVfsUriMapperHttp *vfs)
52 {
53 }
54 
55 static const char * const *
http_get_handled_schemes(GVfsUriMapper * mapper)56 http_get_handled_schemes (GVfsUriMapper *mapper)
57 {
58   static const char *schemes[] = {
59     "http",
60     "https",
61     "dav",
62     "davs",
63     NULL
64   };
65   return schemes;
66 }
67 
68 static inline gboolean
port_is_default_port(int port,gboolean ssl)69 port_is_default_port (int port, gboolean ssl)
70 {
71   if (ssl)
72     return port == 443;
73   else
74     return port == 80;
75 }
76 
77 static GMountSpec *
http_from_uri(GVfsUriMapper * mapper,const char * uri_str,char ** path)78 http_from_uri (GVfsUriMapper  *mapper,
79                const char     *uri_str,
80                char          **path)
81 {
82   GMountSpec *spec;
83   gboolean ssl;
84   GDecodedUri *uri;
85 
86   uri = g_vfs_decode_uri (uri_str);
87 
88   if (uri == NULL)
89     return NULL;
90 
91   if (!g_ascii_strncasecmp (uri->scheme, "http", 4))
92     {
93       spec = g_mount_spec_new ("http");
94       g_mount_spec_set (spec, "uri", uri_str);
95     }
96   else
97     {
98       spec = g_mount_spec_new ("dav");
99       ssl = !g_ascii_strcasecmp (uri->scheme, "davs");
100       g_mount_spec_set (spec, "ssl", ssl ? "true" : "false");
101 
102       if (uri->host && *uri->host)
103         g_mount_spec_set (spec, "host", uri->host);
104 
105       if (uri->userinfo && *uri->userinfo)
106         g_mount_spec_set (spec, "user", uri->userinfo);
107 
108       /* only set the port if it isn't the default port */
109       if (uri->port != -1 && ! port_is_default_port (uri->port, ssl))
110         {
111           char *port = g_strdup_printf ("%d", uri->port);
112           g_mount_spec_set (spec, "port", port);
113           g_free (port);
114         }
115     }
116 
117   *path = uri->path;
118   uri->path = NULL;
119   g_vfs_decoded_uri_free (uri);
120 
121   return spec;
122 }
123 
124 static GMountSpec *
http_get_mount_spec_for_path(GVfsUriMapper * mapper,GMountSpec * spec,const char * old_path,const char * new_path)125 http_get_mount_spec_for_path (GVfsUriMapper *mapper,
126 			      GMountSpec *spec,
127                               const char *old_path,
128 			      const char *new_path)
129 {
130   const char *type;
131 
132   type = g_mount_spec_get (spec, "type");
133 
134   if (strcmp (type, "http") == 0)
135     {
136       const char *uri_str;
137       char *new_uri;
138       GDecodedUri *uri;
139       GMountSpec *new_spec;
140 
141       uri_str = g_mount_spec_get (spec, "uri");
142 
143       uri = g_vfs_decode_uri (uri_str);
144 
145       if (uri == NULL)
146         return NULL;
147 
148       if (strcmp (uri->path, new_path) == 0)
149         {
150           g_vfs_decoded_uri_free (uri);
151           return NULL;
152         }
153 
154       g_free (uri->path);
155       uri->path = g_strdup (new_path);
156 
157       g_free (uri->query);
158       uri->query = NULL;
159 
160       g_free (uri->fragment);
161       uri->fragment = NULL;
162 
163       new_spec = g_mount_spec_new ("http");
164 
165       new_uri = g_vfs_encode_uri (uri, TRUE);
166       g_mount_spec_set (new_spec, "uri", new_uri);
167       g_free (new_uri);
168 
169       g_vfs_decoded_uri_free (uri);
170 
171       return new_spec;
172     }
173   else
174     return NULL;
175 }
176 
177 static const char * const *
http_get_handled_mount_types(GVfsUriMapper * mapper)178 http_get_handled_mount_types (GVfsUriMapper *mapper)
179 {
180   static const char *types[] = {
181     "http",
182     "dav",
183     NULL
184   };
185   return types;
186 }
187 
188 static char *
http_to_uri(GVfsUriMapper * mapper,GMountSpec * spec,const char * path,gboolean allow_utf8)189 http_to_uri (GVfsUriMapper *mapper,
190              GMountSpec    *spec,
191              const char    *path,
192              gboolean       allow_utf8)
193 {
194   char       *res;
195   const char *type;
196   const char *host;
197   const char *user;
198   const char *port;
199   const char *ssl;
200 
201   type = g_mount_spec_get (spec, "type");
202 
203   if (strcmp (type, "http") == 0)
204     {
205       res = g_strdup (g_mount_spec_get (spec, "uri"));
206     }
207   else
208     {
209       GDecodedUri *decoded_uri;
210       int          port_num;
211 
212       decoded_uri = g_new0 (GDecodedUri, 1);
213 
214       ssl  = g_mount_spec_get (spec, "ssl");
215       host = g_mount_spec_get (spec, "host");
216       user = g_mount_spec_get (spec, "user");
217       port = g_mount_spec_get (spec, "port");
218 
219       if (ssl && strcmp (ssl, "true") == 0)
220           decoded_uri->scheme = g_strdup ("davs");
221       else
222           decoded_uri->scheme = g_strdup ("dav");
223 
224       decoded_uri->host = g_strdup (host);
225       decoded_uri->userinfo = g_strdup (user);
226 
227       if (port && (port_num = atoi (port)))
228           decoded_uri->port = port_num;
229       else
230           decoded_uri->port = -1;
231 
232       decoded_uri->path = g_strdup (path);
233 
234       res = g_vfs_encode_uri (decoded_uri, allow_utf8);
235       g_vfs_decoded_uri_free (decoded_uri);
236     }
237 
238   return res;
239 }
240 
241 static const char *
http_to_uri_scheme(GVfsUriMapper * mapper,GMountSpec * spec)242 http_to_uri_scheme (GVfsUriMapper *mapper,
243                     GMountSpec    *spec)
244 {
245   const gchar *ssl;
246   const gchar *type;
247   gboolean     is_dav;
248   gboolean     is_ssl;
249 
250   ssl = g_mount_spec_get (spec, "ssl");
251   type = g_mount_spec_get (spec, "type");
252 
253   if (strcmp (type, "dav") == 0)
254      is_dav = TRUE;
255   else if (strcmp (type, "http") == 0)
256      is_dav = FALSE;
257   else
258      return NULL;
259 
260   is_ssl =
261     ssl != NULL &&
262     strcmp (ssl, "true") == 0;
263 
264   if (is_dav && is_ssl)
265     return "davs";
266   else if (is_dav && !is_ssl)
267     return "dav";
268   else if (!is_dav && is_ssl)
269     return "https";
270   else
271     return "http";
272 }
273 
274 static void
g_vfs_uri_mapper_http_class_finalize(GVfsUriMapperHttpClass * klass)275 g_vfs_uri_mapper_http_class_finalize (GVfsUriMapperHttpClass *klass)
276 {
277 }
278 
279 static void
g_vfs_uri_mapper_http_class_init(GVfsUriMapperHttpClass * class)280 g_vfs_uri_mapper_http_class_init (GVfsUriMapperHttpClass *class)
281 {
282   GVfsUriMapperClass *mapper_class;
283 
284   mapper_class = G_VFS_URI_MAPPER_CLASS (class);
285   mapper_class->get_handled_schemes     = http_get_handled_schemes;
286   mapper_class->from_uri                = http_from_uri;
287   mapper_class->get_mount_spec_for_path = http_get_mount_spec_for_path;
288   mapper_class->get_handled_mount_types = http_get_handled_mount_types;
289   mapper_class->to_uri                  = http_to_uri;
290   mapper_class->to_uri_scheme           = http_to_uri_scheme;
291 }
292 
293 void
g_vfs_uri_mapper_http_register(GIOModule * module)294 g_vfs_uri_mapper_http_register (GIOModule *module)
295 {
296   g_vfs_uri_mapper_http_register_type (G_TYPE_MODULE (module));
297 }
298