1 /*
2 * Nautilus-Actions
3 * A Nautilus extension which offers configurable context menu actions.
4 *
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006-2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009-2014 Pierre Wieser and others (see AUTHORS)
8 *
9 * Nautilus-Actions is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * Nautilus-Actions is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Nautilus-Actions; see the file COPYING. If not, see
21 * <http://www.gnu.org/licenses/>.
22 *
23 * Authors:
24 * Frederic Ruaudel <grumz@grumz.net>
25 * Rodrigo Moya <rodrigo@gnome-db.org>
26 * Pierre Wieser <pwieser@trychlos.org>
27 * ... and many others (see AUTHORS)
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <glib/gi18n.h>
35 #include <string.h>
36
37 #include "na-gnome-vfs-uri.h"
38 #include "na-selected-info.h"
39
40 /* private class data
41 */
42 struct _NASelectedInfoClassPrivate {
43 void *empty; /* so that gcc -pedantic is happy */
44 };
45
46 /* private instance data
47 */
48 struct _NASelectedInfoPrivate {
49 gboolean dispose_has_run;
50 gchar *uri;
51 gchar *filename;
52 gchar *dirname;
53 gchar *basename;
54 gchar *hostname;
55 gchar *username;
56 gchar *scheme;
57 guint port;
58 gchar *mimetype;
59 GFileType file_type;
60 gboolean can_read;
61 gboolean can_write;
62 gboolean can_execute;
63 gchar *owner;
64 gboolean attributes_are_set;
65 };
66
67
68 static GObjectClass *st_parent_class = NULL;
69
70 static GType register_type( void );
71 static void class_init( NASelectedInfoClass *klass );
72 static void instance_init( GTypeInstance *instance, gpointer klass );
73 static void instance_dispose( GObject *object );
74 static void instance_finalize( GObject *object );
75
76 static void dump( const NASelectedInfo *nsi );
77 static const char *dump_file_type( GFileType type );
78 static NASelectedInfo *new_from_nautilus_file_info( NautilusFileInfo *item );
79 static NASelectedInfo *new_from_uri( const gchar *uri, const gchar *mimetype, gchar **errmsg );
80 static void query_file_attributes( NASelectedInfo *info, GFile *location, gchar **errmsg );
81
82 GType
na_selected_info_get_type(void)83 na_selected_info_get_type( void )
84 {
85 static GType object_type = 0;
86
87 if( !object_type ){
88 object_type = register_type();
89 }
90
91 return( object_type );
92 }
93
94 static GType
register_type(void)95 register_type( void )
96 {
97 static const gchar *thisfn = "na_selected_info_register_type";
98 GType type;
99
100 static GTypeInfo info = {
101 sizeof( NASelectedInfoClass ),
102 ( GBaseInitFunc ) NULL,
103 ( GBaseFinalizeFunc ) NULL,
104 ( GClassInitFunc ) class_init,
105 NULL,
106 NULL,
107 sizeof( NASelectedInfo ),
108 0,
109 ( GInstanceInitFunc ) instance_init
110 };
111
112 g_debug( "%s", thisfn );
113
114 type = g_type_register_static( G_TYPE_OBJECT, "NASelectedInfo", &info, 0 );
115
116 return( type );
117 }
118
119 static void
class_init(NASelectedInfoClass * klass)120 class_init( NASelectedInfoClass *klass )
121 {
122 static const gchar *thisfn = "na_selected_info_class_init";
123 GObjectClass *object_class;
124
125 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
126
127 st_parent_class = g_type_class_peek_parent( klass );
128
129 object_class = G_OBJECT_CLASS( klass );
130 object_class->dispose = instance_dispose;
131 object_class->finalize = instance_finalize;
132
133 klass->private = g_new0( NASelectedInfoClassPrivate, 1 );
134 }
135
136 static void
instance_init(GTypeInstance * instance,gpointer klass)137 instance_init( GTypeInstance *instance, gpointer klass )
138 {
139 static const gchar *thisfn = "na_selected_info_instance_init";
140 NASelectedInfo *self;
141
142 g_return_if_fail( NA_IS_SELECTED_INFO( instance ));
143
144 g_debug( "%s: instance=%p (%s), klass=%p",
145 thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
146
147 self = NA_SELECTED_INFO( instance );
148
149 self->private = g_new0( NASelectedInfoPrivate, 1 );
150
151 self->private->dispose_has_run = FALSE;
152 self->private->uri = NULL;
153 }
154
155 static void
instance_dispose(GObject * object)156 instance_dispose( GObject *object )
157 {
158 static const gchar *thisfn = "na_selected_info_instance_dispose";
159 NASelectedInfo *self;
160
161 g_return_if_fail( NA_IS_SELECTED_INFO( object ));
162 self = NA_SELECTED_INFO( object );
163
164 if( !self->private->dispose_has_run ){
165 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
166
167 self->private->dispose_has_run = TRUE;
168
169 /* chain up to the parent class */
170 if( G_OBJECT_CLASS( st_parent_class )->dispose ){
171 G_OBJECT_CLASS( st_parent_class )->dispose( object );
172 }
173 }
174 }
175
176 static void
instance_finalize(GObject * object)177 instance_finalize( GObject *object )
178 {
179 static const gchar *thisfn = "na_selected_info_instance_finalize";
180 NASelectedInfo *self;
181
182 g_return_if_fail( NA_IS_SELECTED_INFO( object ));
183
184 self = NA_SELECTED_INFO( object );
185
186 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
187
188 g_free( self->private->uri );
189 g_free( self->private->filename );
190 g_free( self->private->dirname );
191 g_free( self->private->basename );
192 g_free( self->private->hostname );
193 g_free( self->private->username );
194 g_free( self->private->scheme );
195 g_free( self->private->mimetype );
196 g_free( self->private->owner );
197
198 g_free( self->private );
199
200 /* chain call to parent class */
201 if( G_OBJECT_CLASS( st_parent_class )->finalize ){
202 G_OBJECT_CLASS( st_parent_class )->finalize( object );
203 }
204 }
205
206 /*
207 * na_selected_info_get_list_from_item:
208 * @item: a #NautilusFileInfo item
209 *
210 * Returns: a #GList list which contains a #NASelectedInfo item with the
211 * same URI that the @item.
212 */
213 GList *
na_selected_info_get_list_from_item(NautilusFileInfo * item)214 na_selected_info_get_list_from_item( NautilusFileInfo *item )
215 {
216 GList *selected;
217
218 selected = NULL;
219 NASelectedInfo *info = new_from_nautilus_file_info( item );
220
221 if( info ){
222 selected = g_list_prepend( NULL, info );
223 }
224
225 return( selected );
226 }
227
228 /*
229 * na_selected_info_get_list_from_list:
230 * @nautilus_selection: a #GList list of #NautilusFileInfo items.
231 *
232 * Returns: a #GList list of #NASelectedInfo items whose URI correspond
233 * to those of @nautilus_selection.
234 */
235 GList *
na_selected_info_get_list_from_list(GList * nautilus_selection)236 na_selected_info_get_list_from_list( GList *nautilus_selection )
237 {
238 GList *selected;
239 GList *it;
240
241 selected = NULL;
242
243 for( it = nautilus_selection ; it ; it = it->next ){
244 NASelectedInfo *info = new_from_nautilus_file_info( NAUTILUS_FILE_INFO( it->data ));
245
246 if( info ){
247 selected = g_list_prepend( selected, info );
248 }
249 }
250
251 return( selected ? g_list_reverse( selected ) : NULL );
252 }
253
254 /*
255 * na_selected_info_copy_list:
256 * @files: a #GList list of #NASelectedInfo items.
257 *
258 * Returns: a copy of the provided @files list.
259 */
260 GList *
na_selected_info_copy_list(GList * files)261 na_selected_info_copy_list( GList *files )
262 {
263 GList *copy;
264 GList *l;
265
266 copy = g_list_copy( files );
267
268 for( l = copy ; l != NULL ; l = l->next ){
269 g_object_ref( G_OBJECT( l->data ));
270 }
271
272 return( copy );
273 }
274
275 /*
276 * na_selected_info_free_list:
277 * @files: a #GList of #NASelectedInfo items.
278 *
279 * Frees up the #GList @files.
280 */
281 void
na_selected_info_free_list(GList * files)282 na_selected_info_free_list( GList *files )
283 {
284 g_list_foreach( files, ( GFunc ) g_object_unref, NULL );
285 g_list_free( files );
286 }
287
288 /*
289 * na_selected_info_get_basename:
290 * @nsi: this #NASelectedInfo object.
291 *
292 * Returns: the basename of the file associated with this
293 * #NASelectedInfo object, as a newly allocated string which
294 * must be g_free() by the caller.
295 */
296 gchar *
na_selected_info_get_basename(const NASelectedInfo * nsi)297 na_selected_info_get_basename( const NASelectedInfo *nsi )
298 {
299 gchar *basename;
300
301 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), NULL );
302
303 basename = NULL;
304
305 if( !nsi->private->dispose_has_run ){
306
307 basename = g_strdup( nsi->private->basename );
308 }
309
310 return( basename );
311 }
312
313 /*
314 * na_selected_info_get_dirname:
315 * @nsi: this #NASelectedInfo object.
316 *
317 * Returns: the dirname of the file associated with this
318 * #NASelectedInfo object, as a newly allocated string which
319 * must be g_free() by the caller.
320 */
321 gchar *
na_selected_info_get_dirname(const NASelectedInfo * nsi)322 na_selected_info_get_dirname( const NASelectedInfo *nsi )
323 {
324 gchar *dirname;
325
326 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), NULL );
327
328 dirname = NULL;
329
330 if( !nsi->private->dispose_has_run ){
331
332 dirname = g_strdup( nsi->private->dirname );
333 }
334
335 return( dirname );
336 }
337
338 /*
339 * na_selected_info_get_mime_type:
340 * @nsi: this #NASelectedInfo object.
341 *
342 * Returns: the mime type associated with this #NASelectedInfo object,
343 * as a newly allocated string which should be g_free() by the caller.
344 */
345 gchar *
na_selected_info_get_mime_type(const NASelectedInfo * nsi)346 na_selected_info_get_mime_type( const NASelectedInfo *nsi )
347 {
348 gchar *mimetype;
349
350 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), NULL );
351
352 mimetype = NULL;
353
354 if( !nsi->private->dispose_has_run ){
355
356 if( nsi->private->mimetype ){
357 mimetype = g_strdup( nsi->private->mimetype );
358 }
359 }
360
361 return( mimetype );
362 }
363
364 /*
365 * na_selected_info_get_path:
366 * @nsi: this #NASelectedInfo object.
367 *
368 * Returns: the filename of the item as a newly allocated string which
369 * should be g_free() by the caller.
370 */
371 gchar *
na_selected_info_get_path(const NASelectedInfo * nsi)372 na_selected_info_get_path( const NASelectedInfo *nsi )
373 {
374 gchar *path;
375
376 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), NULL );
377
378 path = NULL;
379
380 if( !nsi->private->dispose_has_run ){
381
382 path = g_strdup( nsi->private->filename );
383 }
384
385 return( path );
386 }
387
388 /*
389 * na_selected_info_get_uri:
390 * @nsi: this #NASelectedInfo object.
391 *
392 * Returns: the URI associated with this #NASelectedInfo object, as a
393 * newly allocated string which should be g_free() by the caller.
394 */
395 gchar *
na_selected_info_get_uri(const NASelectedInfo * nsi)396 na_selected_info_get_uri( const NASelectedInfo *nsi )
397 {
398 gchar *uri;
399
400 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), NULL );
401
402 uri = NULL;
403
404 if( !nsi->private->dispose_has_run ){
405
406 uri = g_strdup( nsi->private->uri );
407 }
408
409 return( uri );
410 }
411
412 /*
413 * na_selected_info_get_uri_host:
414 * @nsi: this #NASelectedInfo object.
415 *
416 * Returns: the host associated to this @nsi object, as a
417 * newly allocated string which should be g_free() by the caller.
418 */
419 gchar *
na_selected_info_get_uri_host(const NASelectedInfo * nsi)420 na_selected_info_get_uri_host( const NASelectedInfo *nsi )
421 {
422 gchar *host;
423
424 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), NULL );
425
426 host = NULL;
427
428 if( !nsi->private->dispose_has_run ){
429
430 host = g_strdup( nsi->private->hostname );
431 }
432
433 return( host );
434 }
435
436 /*
437 * na_selected_info_get_uri_user:
438 * @nsi: this #NASelectedInfo object.
439 *
440 * Returns: the user associated to this @nsi object, as a
441 * newly allocated string which should be g_free() by the caller.
442 */
443 gchar *
na_selected_info_get_uri_user(const NASelectedInfo * nsi)444 na_selected_info_get_uri_user( const NASelectedInfo *nsi )
445 {
446 gchar *user;
447
448 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), NULL );
449
450 user = NULL;
451
452 if( !nsi->private->dispose_has_run ){
453
454 user = g_strdup( nsi->private->username );
455 }
456
457 return( user );
458 }
459
460 /*
461 * na_selected_info_get_uri_port:
462 * @nsi: this #NASelectedInfo object.
463 *
464 * Returns: the port associated to this @nsi object.
465 */
466 guint
na_selected_info_get_uri_port(const NASelectedInfo * nsi)467 na_selected_info_get_uri_port( const NASelectedInfo *nsi )
468 {
469 guint port;
470
471 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), 0 );
472
473 port = 0;
474
475 if( !nsi->private->dispose_has_run ){
476
477 port = nsi->private->port;
478 }
479
480 return( port );
481 }
482
483 /*
484 * na_selected_info_get_uri_scheme:
485 * @nsi: this #NASelectedInfo object.
486 *
487 * Returns: the scheme associated to this @nsi object, as a
488 * newly allocated string which should be g_free() by the caller.
489 */
490 gchar *
na_selected_info_get_uri_scheme(const NASelectedInfo * nsi)491 na_selected_info_get_uri_scheme( const NASelectedInfo *nsi )
492 {
493 gchar *scheme;
494
495 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), NULL );
496
497 scheme = NULL;
498
499 if( !nsi->private->dispose_has_run ){
500
501 scheme = g_strdup( nsi->private->scheme );
502 }
503
504 return( scheme );
505 }
506
507 /*
508 * na_selected_info_is_directory:
509 * @nsi: this #NASelectedInfo object.
510 *
511 * Returns: %TRUE if the item is a directory, %FALSE else.
512 */
513 gboolean
na_selected_info_is_directory(const NASelectedInfo * nsi)514 na_selected_info_is_directory( const NASelectedInfo *nsi )
515 {
516 gboolean is_dir;
517
518 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
519
520 is_dir = FALSE;
521
522 if( !nsi->private->dispose_has_run ){
523
524 is_dir = ( nsi->private->file_type == G_FILE_TYPE_DIRECTORY );
525 }
526
527 return( is_dir );
528 }
529
530 /*
531 * na_selected_info_is_regular:
532 * @nsi: this #NASelectedInfo object.
533 *
534 * Returns: %TRUE if the item is a regular file, %FALSE else.
535 */
536 gboolean
na_selected_info_is_regular(const NASelectedInfo * nsi)537 na_selected_info_is_regular( const NASelectedInfo *nsi )
538 {
539 gboolean is_regular;
540
541 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
542
543 is_regular = FALSE;
544
545 if( !nsi->private->dispose_has_run ){
546
547 is_regular = ( nsi->private->file_type == G_FILE_TYPE_REGULAR );
548 }
549
550 return( is_regular );
551 }
552
553 /*
554 * na_selected_info_is_executable:
555 * @nsi: this #NASelectedInfo object.
556 *
557 * Returns: %TRUE if the item is executable by the user, %FALSE else.
558 */
559 gboolean
na_selected_info_is_executable(const NASelectedInfo * nsi)560 na_selected_info_is_executable( const NASelectedInfo *nsi )
561 {
562 gboolean is_exe;
563
564 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
565
566 is_exe = FALSE;
567
568 if( !nsi->private->dispose_has_run ){
569
570 is_exe = nsi->private->can_execute;
571 }
572
573 return( is_exe );
574 }
575
576 /*
577 * na_selected_info_is_local:
578 * @nsi: this #NASelectedInfo object.
579 *
580 * Returns: %TRUE if the item is on a local filesystem, %FALSE else.
581 */
582 gboolean
na_selected_info_is_local(const NASelectedInfo * nsi)583 na_selected_info_is_local( const NASelectedInfo *nsi )
584 {
585 gboolean is_local;
586 gchar *scheme;
587
588 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
589
590 is_local = FALSE;
591
592 if( !nsi->private->dispose_has_run ){
593
594 scheme = na_selected_info_get_uri_scheme( nsi );
595 is_local = ( strcmp( scheme, "file" ) == 0 );
596 g_free( scheme );
597 }
598
599 return( is_local );
600 }
601
602 /*
603 * na_selected_info_is_owner:
604 * @nsi: this #NASelectedInfo object.
605 * @user: the user to be tested against the owner of the @nsi object.
606 *
607 * Returns: %TRUE if the item is a owner, %FALSE else.
608 */
609 gboolean
na_selected_info_is_owner(const NASelectedInfo * nsi,const gchar * user)610 na_selected_info_is_owner( const NASelectedInfo *nsi, const gchar *user )
611 {
612 gboolean is_owner;
613
614 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
615
616 is_owner = FALSE;
617
618 if( !nsi->private->dispose_has_run ){
619
620 is_owner = ( strcmp( nsi->private->owner, user ) == 0 );
621 }
622
623 return( is_owner );
624 }
625
626 /*
627 * na_selected_info_is_readable:
628 * @nsi: this #NASelectedInfo object.
629 *
630 * Returns: %TRUE if the item is a readable, %FALSE else.
631 */
632 gboolean
na_selected_info_is_readable(const NASelectedInfo * nsi)633 na_selected_info_is_readable( const NASelectedInfo *nsi )
634 {
635 gboolean is_readable;
636
637 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
638
639 is_readable = FALSE;
640
641 if( !nsi->private->dispose_has_run ){
642
643 is_readable = nsi->private->can_read;
644 }
645
646 return( is_readable );
647 }
648
649 /*
650 * na_selected_info_is_writable:
651 * @nsi: this #NASelectedInfo object.
652 *
653 * Returns: %TRUE if the item is a writable, %FALSE else.
654 */
655 gboolean
na_selected_info_is_writable(const NASelectedInfo * nsi)656 na_selected_info_is_writable( const NASelectedInfo *nsi )
657 {
658 gboolean is_writable;
659
660 g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
661
662 is_writable = FALSE;
663
664 if( !nsi->private->dispose_has_run ){
665
666 is_writable = nsi->private->can_write;
667 }
668
669 return( is_writable );
670 }
671
672 /*
673 * na_selected_info_create_for_uri:
674 * @uri: an URI.
675 * @mimetype: the corresponding Nautilus mime type, or %NULL.
676 * @errmsg: a pointer to a string which will contain an error message on
677 * return.
678 *
679 * Returns: a newly allocated #NASelectedInfo object for the given @uri.
680 */
681 NASelectedInfo *
na_selected_info_create_for_uri(const gchar * uri,const gchar * mimetype,gchar ** errmsg)682 na_selected_info_create_for_uri( const gchar *uri, const gchar *mimetype, gchar **errmsg )
683 {
684 static const gchar *thisfn = "na_selected_info_create_for_uri";
685
686 g_debug( "%s: uri=%s, mimetype=%s", thisfn, uri, mimetype );
687
688 NASelectedInfo *obj = new_from_uri( uri, mimetype, errmsg );
689
690 return( obj );
691 }
692
693 static void
dump(const NASelectedInfo * nsi)694 dump( const NASelectedInfo *nsi )
695 {
696 static const gchar *thisfn = "na_selected_info_dump";
697
698 g_debug( "%s: uri=%s", thisfn, nsi->private->uri );
699 g_debug( "%s: mimetype=%s", thisfn, nsi->private->mimetype );
700 g_debug( "%s: filename=%s", thisfn, nsi->private->filename );
701 g_debug( "%s: dirname=%s", thisfn, nsi->private->dirname );
702 g_debug( "%s: basename=%s", thisfn, nsi->private->basename );
703 g_debug( "%s: hostname=%s", thisfn, nsi->private->hostname );
704 g_debug( "%s: username=%s", thisfn, nsi->private->username );
705 g_debug( "%s: scheme=%s", thisfn, nsi->private->scheme );
706 g_debug( "%s: port=%d", thisfn, nsi->private->port );
707 g_debug( "%s: attributes_are_set=%s", thisfn, nsi->private->attributes_are_set ? "True":"False" );
708 g_debug( "%s: file_type=%s", thisfn, dump_file_type( nsi->private->file_type ));
709 g_debug( "%s: can_read=%s", thisfn, nsi->private->can_read ? "True":"False" );
710 g_debug( "%s: can_write=%s", thisfn, nsi->private->can_write ? "True":"False" );
711 g_debug( "%s: can_execute=%s", thisfn, nsi->private->can_execute ? "True":"False" );
712 g_debug( "%s: owner=%s", thisfn, nsi->private->owner );
713 }
714
715 static const char *
dump_file_type(GFileType type)716 dump_file_type( GFileType type )
717 {
718 switch( type ){
719 case G_FILE_TYPE_REGULAR:
720 return( "regular" );
721 case G_FILE_TYPE_DIRECTORY:
722 return( "directory" );
723 case G_FILE_TYPE_SYMBOLIC_LINK:
724 return( "symbolic link" );
725 case G_FILE_TYPE_SPECIAL:
726 return( "special (socket, fifo, blockdev, chardev)" );
727 case G_FILE_TYPE_SHORTCUT:
728 return( "shortcut" );
729 case G_FILE_TYPE_MOUNTABLE:
730 return( "mountable" );
731 default:
732 break;
733 }
734 return( "unknown" );
735 }
736
737 static NASelectedInfo *
new_from_nautilus_file_info(NautilusFileInfo * item)738 new_from_nautilus_file_info( NautilusFileInfo *item )
739 {
740 gchar *uri = nautilus_file_info_get_uri( item );
741 gchar *mimetype = nautilus_file_info_get_mime_type( item );
742 NASelectedInfo *info = new_from_uri( uri, mimetype, NULL );
743 g_free( mimetype );
744 g_free( uri );
745
746 return( info );
747 }
748
749 /*
750 * Nautilus uses to address the desktop via the 'x-nautilus-desktop:///' URI.
751 * g_filename_from_uri() complains that
752 * "The URI 'x-nautilus-desktop:///' is not an absolute URI using the "file" scheme".
753 * In this case, we prefer the vfs->path member wich is just a decomposition of the
754 * URI, and does not try to interpret it.
755 *
756 * *********************************************************************************
757 * Extract from RFC 2396:
758 *
759 * 2.4.3. Excluded US-ASCII Characters
760 *
761 * Although they are disallowed within the URI syntax, we include here a
762 * description of those US-ASCII characters that have been excluded and
763 * the reasons for their exclusion.
764 *
765 * The control characters in the US-ASCII coded character set are not
766 * used within a URI, both because they are non-printable and because
767 * they are likely to be misinterpreted by some control mechanisms.
768 *
769 * control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
770 *
771 * The space character is excluded because significant spaces may
772 * disappear and insignificant spaces may be introduced when URI are
773 * transcribed or typeset or subjected to the treatment of word-
774 * processing programs. Whitespace is also used to delimit URI in many
775 * contexts.
776 *
777 * space = <US-ASCII coded character 20 hexadecimal>
778 *
779 * The angle-bracket "<" and ">" and double-quote (") characters are
780 * excluded because they are often used as the delimiters around URI in
781 * text documents and protocol fields. The character "#" is excluded
782 * because it is used to delimit a URI from a fragment identifier in URI
783 * references (Section 4). The percent character "%" is excluded because
784 * it is used for the encoding of escaped characters.
785 *
786 * delims = "<" | ">" | "#" | "%" | <">
787 *
788 * Other characters are excluded because gateways and other transport
789 * agents are known to sometimes modify such characters, or they are
790 * used as delimiters.
791 *
792 * unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
793 *
794 * Data corresponding to excluded characters must be escaped in order to
795 * be properly represented within a URI.
796 *
797 * pwi 2011-01-04:
798 * It results from the above excerpt that:
799 * - as double quotes are not valid character in URI, they have to be
800 * escaped as %22, and so Nautilus does
801 * - but simple quotes are not forbidden, and so have not to be
802 * escaped, and so Nautilus does not escape them
803 *
804 * As a result, we may have valid, non-escaped, simple quotes in an URI.
805 */
806 static NASelectedInfo *
new_from_uri(const gchar * uri,const gchar * mimetype,gchar ** errmsg)807 new_from_uri( const gchar *uri, const gchar *mimetype, gchar **errmsg )
808 {
809 GFile *location;
810 NAGnomeVFSURI *vfs;
811
812 NASelectedInfo *info = g_object_new( NA_TYPE_SELECTED_INFO, NULL );
813
814 info->private->uri = g_strdup( uri );
815 if( mimetype ){
816 info->private->mimetype = g_strdup( mimetype );
817 }
818
819 /* pwi 2011-05-18
820 * Filename and dirname should be taken from the GFile location, itself taken
821 * from the URI, so that we have dir='/home/pierre/.gvfs/sftp on stormy.trychlos.org/etc'
822 * Taking filename and dirname from URI just gives '/etc'
823 * see #650523
824 */
825 location = g_file_new_for_uri( uri );
826 info->private->filename = g_file_get_path( location );
827
828 vfs = g_new0( NAGnomeVFSURI, 1 );
829 na_gnome_vfs_uri_parse( vfs, uri );
830 if( !info->private->filename ){
831 g_debug( "na_selected_info_new_from_uri: uri='%s', filename=NULL, setting it to '%s'", uri, vfs->path );
832 info->private->filename = g_strdup( vfs->path );
833 }
834
835 info->private->basename = g_path_get_basename( info->private->filename );
836 info->private->dirname = g_path_get_dirname( info->private->filename );
837 info->private->hostname = g_strdup( vfs->host_name );
838 info->private->username = g_strdup( vfs->user_name );
839 info->private->scheme = g_strdup( vfs->scheme );
840 info->private->port = vfs->host_port;
841 na_gnome_vfs_uri_free( vfs );
842
843 query_file_attributes( info, location, errmsg );
844 g_object_unref( location );
845
846 dump( info );
847
848 return( info );
849 }
850
851 static void
query_file_attributes(NASelectedInfo * nsi,GFile * location,gchar ** errmsg)852 query_file_attributes( NASelectedInfo *nsi, GFile *location, gchar **errmsg )
853 {
854 static const gchar *thisfn = "na_selected_info_query_file_attributes";
855 GError *error;
856
857 error = NULL;
858 GFileInfo *info = g_file_query_info( location,
859 G_FILE_ATTRIBUTE_STANDARD_TYPE
860 "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
861 "," G_FILE_ATTRIBUTE_ACCESS_CAN_READ
862 "," G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
863 "," G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE
864 "," G_FILE_ATTRIBUTE_OWNER_USER,
865 G_FILE_QUERY_INFO_NONE, NULL, &error );
866
867 if( error ){
868 if( errmsg ){
869 *errmsg = g_strdup_printf( _( "Error when querying informations for %s URI: %s" ), nsi->private->uri, error->message );
870 } else {
871 g_warning( "%s: uri=%s, g_file_query_info: %s", thisfn, nsi->private->uri, error->message );
872 }
873 g_error_free( error );
874 return;
875 }
876
877 if( !nsi->private->mimetype ){
878 nsi->private->mimetype = g_strdup( g_file_info_get_attribute_as_string( info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ));
879 }
880
881 nsi->private->file_type = ( GFileType ) g_file_info_get_attribute_uint32( info, G_FILE_ATTRIBUTE_STANDARD_TYPE );
882
883 nsi->private->can_read = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ );
884 nsi->private->can_write = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE );
885 nsi->private->can_execute = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE );
886
887 nsi->private->owner = g_strdup( g_file_info_get_attribute_as_string( info, G_FILE_ATTRIBUTE_OWNER_USER ));
888
889 nsi->private->attributes_are_set = TRUE;
890
891 g_object_unref( info );
892 }
893