nautilus-3.6.3/libnautilus-private/nautilus-file-utilities.c

No issues found

   1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
   2 
   3 /* nautilus-file-utilities.c - implementation of file manipulation routines.
   4 
   5    Copyright (C) 1999, 2000, 2001 Eazel, Inc.
   6 
   7    The Gnome Library is free software; you can redistribute it and/or
   8    modify it under the terms of the GNU Library General Public License as
   9    published by the Free Software Foundation; either version 2 of the
  10    License, or (at your option) any later version.
  11 
  12    The Gnome Library is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15    Library General Public License for more details.
  16 
  17    You should have received a copy of the GNU Library General Public
  18    License along with the Gnome Library; see the file COPYING.LIB.  If not,
  19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20    Boston, MA 02111-1307, USA.
  21 
  22    Authors: John Sullivan <sullivan@eazel.com>
  23 */
  24 
  25 #include <config.h>
  26 #include "nautilus-file-utilities.h"
  27 
  28 #include "nautilus-global-preferences.h"
  29 #include "nautilus-icon-names.h"
  30 #include "nautilus-lib-self-check-functions.h"
  31 #include "nautilus-metadata.h"
  32 #include "nautilus-file.h"
  33 #include "nautilus-file-operations.h"
  34 #include "nautilus-search-directory.h"
  35 #include "nautilus-signaller.h"
  36 #include <eel/eel-glib-extensions.h>
  37 #include <eel/eel-stock-dialogs.h>
  38 #include <eel/eel-string.h>
  39 #include <eel/eel-debug.h>
  40 #include <glib.h>
  41 #include <glib/gi18n.h>
  42 #include <glib/gstdio.h>
  43 #include <gio/gio.h>
  44 #include <unistd.h>
  45 #include <stdlib.h>
  46 
  47 #define NAUTILUS_USER_DIRECTORY_NAME "nautilus"
  48 #define DEFAULT_NAUTILUS_DIRECTORY_MODE (0755)
  49 
  50 #define DESKTOP_DIRECTORY_NAME "Desktop"
  51 #define LEGACY_DESKTOP_DIRECTORY_NAME ".gnome-desktop"
  52 #define DEFAULT_DESKTOP_DIRECTORY_MODE (0755)
  53 
  54 static void update_xdg_dir_cache (void);
  55 static void schedule_user_dirs_changed (void);
  56 static void desktop_dir_changed (void);
  57 
  58 
  59 /* Allowed characters outside alphanumeric for unreserved. */
  60 #define G_URI_OTHER_UNRESERVED "-._~"
  61 
  62 /* This or something equivalent will eventually go into glib/guri.h */
  63 gboolean
  64 nautilus_uri_parse (const char  *uri,
  65 		    char       **host,
  66 		    guint16     *port,
  67 		    char       **userinfo)
  68 {
  69   char *tmp_str;
  70   const char *start, *p;
  71   char c;
  72 
  73   g_return_val_if_fail (uri != NULL, FALSE);
  74 
  75   if (host)
  76     *host = NULL;
  77 
  78   if (port)
  79     *port = 0;
  80 
  81   if (userinfo)
  82     *userinfo = NULL;
  83 
  84   /* From RFC 3986 Decodes:
  85    * URI          = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
  86    * hier-part    = "//" authority path-abempty
  87    * path-abempty = *( "/" segment )
  88    * authority    = [ userinfo "@" ] host [ ":" port ]
  89    */
  90 
  91   /* Check we have a valid scheme */
  92   tmp_str = g_uri_parse_scheme (uri);
  93 
  94   if (tmp_str == NULL)
  95     return FALSE;
  96 
  97   g_free (tmp_str);
  98 
  99   /* Decode hier-part:
 100    *  hier-part   = "//" authority path-abempty
 101    */
 102   p = uri;
 103   start = strstr (p, "//");
 104 
 105   if (start == NULL)
 106     return FALSE;
 107 
 108   start += 2;
 109 
 110   if (strchr (start, '@') != NULL)
 111     {
 112       /* Decode userinfo:
 113        * userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
 114        * unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 115        * pct-encoded   = "%" HEXDIG HEXDIG
 116        */
 117       p = start;
 118       while (1)
 119 	{
 120 	  c = *p++;
 121 
 122 	  if (c == '@')
 123 	    break;
 124 
 125 	  /* pct-encoded */
 126 	  if (c == '%')
 127 	    {
 128 	      if (!(g_ascii_isxdigit (p[0]) ||
 129 		    g_ascii_isxdigit (p[1])))
 130 		return FALSE;
 131 
 132 	      p++;
 133 
 134 	      continue;
 135 	    }
 136 
 137 	  /* unreserved /  sub-delims / : */
 138 	  if (!(g_ascii_isalnum (c) ||
 139 		strchr (G_URI_OTHER_UNRESERVED, c) ||
 140 		strchr (G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, c) ||
 141 		c == ':'))
 142 	    return FALSE;
 143 	}
 144 
 145       if (userinfo)
 146 	*userinfo = g_strndup (start, p - start - 1);
 147 
 148       start = p;
 149     }
 150   else
 151     {
 152       p = start;
 153     }
 154 
 155 
 156   /* decode host:
 157    * host          = IP-literal / IPv4address / reg-name
 158    * reg-name      = *( unreserved / pct-encoded / sub-delims )
 159    */
 160 
 161   /* If IPv6 or IPvFuture */
 162   if (*p == '[')
 163     {
 164       start++;
 165       p++;
 166       while (1)
 167 	{
 168 	  c = *p++;
 169 
 170 	  if (c == ']')
 171 	    break;
 172 
 173 	  /* unreserved /  sub-delims */
 174 	  if (!(g_ascii_isalnum (c) ||
 175 		strchr (G_URI_OTHER_UNRESERVED, c) ||
 176 		strchr (G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, c) ||
 177 		c == ':' ||
 178 		c == '.'))
 179 	    goto error;
 180 	}
 181     }
 182   else
 183     {
 184       while (1)
 185 	{
 186 	  c = *p++;
 187 
 188 	  if (c == ':' ||
 189 	      c == '/' ||
 190 	      c == '?' ||
 191 	      c == '#' ||
 192 	      c == '\0')
 193 	    break;
 194 
 195 	  /* pct-encoded */
 196 	  if (c == '%')
 197 	    {
 198 	      if (!(g_ascii_isxdigit (p[0]) ||
 199 		    g_ascii_isxdigit (p[1])))
 200 		goto error;
 201 
 202 	      p++;
 203 
 204 	      continue;
 205 	    }
 206 
 207 	  /* unreserved /  sub-delims */
 208 	  if (!(g_ascii_isalnum (c) ||
 209 		strchr (G_URI_OTHER_UNRESERVED, c) ||
 210 		strchr (G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, c)))
 211 	    goto error;
 212 	}
 213     }
 214 
 215   if (host)
 216     *host = g_uri_unescape_segment (start, p - 1, NULL);
 217 
 218   if (c == ':')
 219     {
 220       /* Decode pot:
 221        *  port          = *DIGIT
 222        */
 223       guint tmp = 0;
 224 
 225       while (1)
 226 	{
 227 	  c = *p++;
 228 
 229 	  if (c == '/' ||
 230 	      c == '?' ||
 231 	      c == '#' ||
 232 	      c == '\0')
 233 	    break;
 234 
 235 	  if (!g_ascii_isdigit (c))
 236 	    goto error;
 237 
 238 	  tmp = (tmp * 10) + (c - '0');
 239 
 240 	  if (tmp > 65535)
 241 	    goto error;
 242 	}
 243       if (port)
 244 	*port = (guint16) tmp;
 245     }
 246 
 247   return TRUE;
 248 
 249 error:
 250   if (host && *host)
 251     {
 252       g_free (*host);
 253       *host = NULL;
 254     }
 255 
 256   if (userinfo && *userinfo)
 257     {
 258       g_free (*userinfo);
 259       *userinfo = NULL;
 260     }
 261 
 262   return FALSE;
 263 }
 264 
 265 char *
 266 nautilus_compute_title_for_location (GFile *location)
 267 {
 268 	NautilusFile *file;
 269 	char *title;
 270 
 271 	/* TODO-gio: This doesn't really work all that great if the
 272 	   info about the file isn't known atm... */
 273 
 274 	if (nautilus_is_home_directory (location)) {
 275 		return g_strdup (_("Home"));
 276 	}
 277 	
 278 	title = NULL;
 279 	if (location) {
 280 		file = nautilus_file_get (location);
 281 		title = nautilus_file_get_description (file);
 282 		if (title == NULL) {
 283 			title = nautilus_file_get_display_name (file);
 284 		}
 285 		nautilus_file_unref (file);
 286 	}
 287 
 288 	if (title == NULL) {
 289 		title = g_file_get_basename (location);
 290 	}
 291 	
 292 	return title;
 293 }
 294 
 295 
 296 /**
 297  * nautilus_get_user_directory:
 298  * 
 299  * Get the path for the directory containing nautilus settings.
 300  *
 301  * Return value: the directory path.
 302  **/
 303 char *
 304 nautilus_get_user_directory (void)
 305 {
 306 	char *user_directory = NULL;
 307 
 308 	user_directory = g_build_filename (g_get_user_config_dir (),
 309 					   NAUTILUS_USER_DIRECTORY_NAME,
 310 					   NULL);
 311 	
 312 	if (!g_file_test (user_directory, G_FILE_TEST_EXISTS)) {
 313 		g_mkdir (user_directory, DEFAULT_NAUTILUS_DIRECTORY_MODE);
 314 		/* FIXME bugzilla.gnome.org 41286: 
 315 		 * How should we handle the case where this mkdir fails? 
 316 		 * Note that nautilus_application_startup will refuse to launch if this 
 317 		 * directory doesn't get created, so that case is OK. But the directory 
 318 		 * could be deleted after Nautilus was launched, and perhaps
 319 		 * there is some bad side-effect of not handling that case.
 320 		 */
 321 	}
 322 
 323 	return user_directory;
 324 }
 325 
 326 /**
 327  * nautilus_get_accel_map_file:
 328  * 
 329  * Get the path for the filename containing nautilus accelerator map.
 330  * The filename need not exist.
 331  *
 332  * Return value: the filename path
 333  **/
 334 char *
 335 nautilus_get_accel_map_file (void)
 336 {
 337 	return g_build_filename (g_get_user_config_dir (), "nautilus", "accels", NULL);
 338 }
 339 
 340 /**
 341  * nautilus_get_scripts_directory_path:
 342  *
 343  * Get the path for the directory containing nautilus scripts.
 344  *
 345  * Return value: the directory path containing nautilus scripts
 346  **/
 347 char *
 348 nautilus_get_scripts_directory_path (void)
 349 {
 350 	return g_build_filename (g_get_user_data_dir (), "nautilus", "scripts", NULL);
 351 }
 352 
 353 typedef struct {
 354 	char *type;
 355 	char *path;
 356 	NautilusFile *file;
 357 } XdgDirEntry;
 358 
 359 
 360 static XdgDirEntry *
 361 parse_xdg_dirs (const char *config_file)
 362 {
 363   GArray *array;
 364   char *config_file_free = NULL;
 365   XdgDirEntry dir;
 366   char *data;
 367   char **lines;
 368   char *p, *d;
 369   int i;
 370   char *type_start, *type_end;
 371   char *value, *unescaped;
 372   gboolean relative;
 373 
 374   array = g_array_new (TRUE, TRUE, sizeof (XdgDirEntry));
 375   
 376   if (config_file == NULL)
 377     {
 378       config_file_free = g_build_filename (g_get_user_config_dir (),
 379 					   "user-dirs.dirs", NULL);
 380       config_file = (const char *)config_file_free;
 381     }
 382 
 383   if (g_file_get_contents (config_file, &data, NULL, NULL))
 384     {
 385       lines = g_strsplit (data, "\n", 0);
 386       g_free (data);
 387       for (i = 0; lines[i] != NULL; i++)
 388 	{
 389 	  p = lines[i];
 390 	  while (g_ascii_isspace (*p))
 391 	    p++;
 392       
 393 	  if (*p == '#')
 394 	    continue;
 395       
 396 	  value = strchr (p, '=');
 397 	  if (value == NULL)
 398 	    continue;
 399 	  *value++ = 0;
 400       
 401 	  g_strchug (g_strchomp (p));
 402 	  if (!g_str_has_prefix (p, "XDG_"))
 403 	    continue;
 404 	  if (!g_str_has_suffix (p, "_DIR"))
 405 	    continue;
 406 	  type_start = p + 4;
 407 	  type_end = p + strlen (p) - 4;
 408       
 409 	  while (g_ascii_isspace (*value))
 410 	    value++;
 411       
 412 	  if (*value != '"')
 413 	    continue;
 414 	  value++;
 415       
 416 	  relative = FALSE;
 417 	  if (g_str_has_prefix (value, "$HOME"))
 418 	    {
 419 	      relative = TRUE;
 420 	      value += 5;
 421 	      while (*value == '/')
 422 		      value++;
 423 	    }
 424 	  else if (*value != '/')
 425 	    continue;
 426 	  
 427 	  d = unescaped = g_malloc (strlen (value) + 1);
 428 	  while (*value && *value != '"')
 429 	    {
 430 	      if ((*value == '\\') && (*(value + 1) != 0))
 431 		value++;
 432 	      *d++ = *value++;
 433 	    }
 434 	  *d = 0;
 435       
 436 	  *type_end = 0;
 437 	  dir.type = g_strdup (type_start);
 438 	  if (relative)
 439 	    {
 440 	      dir.path = g_build_filename (g_get_home_dir (), unescaped, NULL);
 441 	      g_free (unescaped);
 442 	    }
 443 	  else 
 444 	    dir.path = unescaped;
 445       
 446 	  g_array_append_val (array, dir);
 447 	}
 448       
 449       g_strfreev (lines);
 450     }
 451   
 452   g_free (config_file_free);
 453   
 454   return (XdgDirEntry *)g_array_free (array, FALSE);
 455 }
 456 
 457 static XdgDirEntry *cached_xdg_dirs = NULL;
 458 static GFileMonitor *cached_xdg_dirs_monitor = NULL;
 459 
 460 static void
 461 xdg_dir_changed (NautilusFile *file,
 462 		 XdgDirEntry *dir)
 463 {
 464 	GFile *location, *dir_location;
 465 	char *path;
 466 
 467 	location = nautilus_file_get_location (file);
 468 	dir_location = g_file_new_for_path (dir->path);
 469 	if (!g_file_equal (location, dir_location)) {
 470 		path = g_file_get_path (location);
 471 
 472 		if (path) {
 473 			char *argv[5];
 474 			int i;
 475 			
 476 			g_free (dir->path);
 477 			dir->path = path;
 478 
 479 			i = 0;
 480 			argv[i++] = "xdg-user-dirs-update";
 481 			argv[i++] = "--set";
 482 			argv[i++] = dir->type;
 483 			argv[i++] = dir->path;
 484 			argv[i++] = NULL;
 485 
 486 			/* We do this sync, to avoid possible race-conditions
 487 			   if multiple dirs change at the same time. Its
 488 			   blocking the main thread, but these updates should
 489 			   be very rare and very fast. */
 490 			g_spawn_sync (NULL, 
 491 				      argv, NULL,
 492 				      G_SPAWN_SEARCH_PATH |
 493 				      G_SPAWN_STDOUT_TO_DEV_NULL |
 494 				      G_SPAWN_STDERR_TO_DEV_NULL,
 495 				      NULL, NULL,
 496 				      NULL, NULL, NULL, NULL);
 497 			g_reload_user_special_dirs_cache ();
 498 			schedule_user_dirs_changed ();
 499 			desktop_dir_changed ();
 500 			/* Icon might have changed */
 501 			nautilus_file_invalidate_attributes (file, NAUTILUS_FILE_ATTRIBUTE_INFO);
 502 		}
 503 	}
 504 	g_object_unref (location);
 505 	g_object_unref (dir_location);
 506 }
 507 
 508 static void 
 509 xdg_dir_cache_changed_cb (GFileMonitor  *monitor,
 510 			  GFile *file,
 511 			  GFile *other_file,
 512 			  GFileMonitorEvent event_type)
 513 {
 514 	if (event_type == G_FILE_MONITOR_EVENT_CHANGED ||
 515 	    event_type == G_FILE_MONITOR_EVENT_CREATED) {
 516 		update_xdg_dir_cache ();
 517 	}
 518 }
 519 
 520 static int user_dirs_changed_tag = 0;
 521 
 522 static gboolean
 523 emit_user_dirs_changed_idle (gpointer data)
 524 {
 525 	g_signal_emit_by_name (nautilus_signaller_get_current (),
 526 			       "user_dirs_changed");
 527 	user_dirs_changed_tag = 0;
 528 	return FALSE;
 529 }
 530 
 531 static void
 532 schedule_user_dirs_changed (void)
 533 {
 534 	if (user_dirs_changed_tag == 0) {
 535 		user_dirs_changed_tag = g_idle_add (emit_user_dirs_changed_idle, NULL);
 536 	}
 537 }
 538 
 539 static void
 540 unschedule_user_dirs_changed (void)
 541 {
 542 	if (user_dirs_changed_tag != 0) {
 543 		g_source_remove (user_dirs_changed_tag);
 544 		user_dirs_changed_tag = 0;
 545 	}
 546 }
 547 
 548 static void
 549 free_xdg_dir_cache (void)
 550 {
 551 	int i;
 552 
 553 	if (cached_xdg_dirs != NULL) {
 554 		for (i = 0; cached_xdg_dirs[i].type != NULL; i++) {
 555 			if (cached_xdg_dirs[i].file != NULL) {
 556 				nautilus_file_monitor_remove (cached_xdg_dirs[i].file,
 557 							      &cached_xdg_dirs[i]);
 558 				g_signal_handlers_disconnect_by_func (cached_xdg_dirs[i].file,
 559 								      G_CALLBACK (xdg_dir_changed),
 560 								      &cached_xdg_dirs[i]);
 561 				nautilus_file_unref (cached_xdg_dirs[i].file);
 562 			}
 563 			g_free (cached_xdg_dirs[i].type);
 564 			g_free (cached_xdg_dirs[i].path);
 565 		}
 566 		g_free (cached_xdg_dirs);
 567 	}
 568 }
 569 
 570 static void
 571 destroy_xdg_dir_cache (void)
 572 {
 573 	free_xdg_dir_cache ();
 574 	unschedule_user_dirs_changed ();
 575 	desktop_dir_changed ();
 576 
 577 	if (cached_xdg_dirs_monitor != NULL) {
 578 		g_object_unref  (cached_xdg_dirs_monitor);
 579 		cached_xdg_dirs_monitor = NULL;
 580 	}
 581 }
 582 
 583 static void
 584 update_xdg_dir_cache (void)
 585 {
 586 	GFile *file;
 587 	char *config_file, *uri;
 588 	int i;
 589 
 590 	free_xdg_dir_cache ();
 591 	g_reload_user_special_dirs_cache ();
 592 	schedule_user_dirs_changed ();
 593 	desktop_dir_changed ();
 594 
 595 	cached_xdg_dirs = parse_xdg_dirs (NULL);
 596 	
 597 	for (i = 0 ; cached_xdg_dirs[i].type != NULL; i++) {
 598 		cached_xdg_dirs[i].file = NULL;
 599 		if (strcmp (cached_xdg_dirs[i].path, g_get_home_dir ()) != 0) {
 600 			uri = g_filename_to_uri (cached_xdg_dirs[i].path, NULL, NULL);
 601 			cached_xdg_dirs[i].file = nautilus_file_get_by_uri (uri);
 602 			nautilus_file_monitor_add (cached_xdg_dirs[i].file,
 603 						   &cached_xdg_dirs[i],
 604 						   NAUTILUS_FILE_ATTRIBUTE_INFO);
 605 			g_signal_connect (cached_xdg_dirs[i].file,
 606 					  "changed", G_CALLBACK (xdg_dir_changed), &cached_xdg_dirs[i]);
 607 			g_free (uri);
 608 		}
 609 	}
 610 
 611 	if (cached_xdg_dirs_monitor == NULL) {
 612 		config_file = g_build_filename (g_get_user_config_dir (),
 613 						     "user-dirs.dirs", NULL);
 614 		file = g_file_new_for_path (config_file);
 615 		cached_xdg_dirs_monitor = g_file_monitor_file (file, 0, NULL, NULL);
 616 		g_signal_connect (cached_xdg_dirs_monitor, "changed",
 617 				  G_CALLBACK (xdg_dir_cache_changed_cb), NULL);
 618 		g_object_unref (file);
 619 		g_free (config_file);
 620 
 621 		eel_debug_call_at_shutdown (destroy_xdg_dir_cache); 
 622 	}
 623 }
 624 
 625 char *
 626 nautilus_get_xdg_dir (const char *type)
 627 {
 628 	int i;
 629 
 630 	if (cached_xdg_dirs == NULL) {
 631 		update_xdg_dir_cache ();
 632 	}
 633 
 634 	for (i = 0 ; cached_xdg_dirs != NULL && cached_xdg_dirs[i].type != NULL; i++) {
 635 		if (strcmp (cached_xdg_dirs[i].type, type) == 0) {
 636 			return g_strdup (cached_xdg_dirs[i].path);
 637 		}
 638 	}
 639 	if (strcmp ("DESKTOP", type) == 0) {
 640 		return g_build_filename (g_get_home_dir (), DESKTOP_DIRECTORY_NAME, NULL);
 641 	}
 642 	if (strcmp ("TEMPLATES", type) == 0) {
 643 		return g_build_filename (g_get_home_dir (), "Templates", NULL);
 644 	}
 645 	
 646 	return g_strdup (g_get_home_dir ());
 647 }
 648 
 649 static char *
 650 get_desktop_path (void)
 651 {
 652 	return nautilus_get_xdg_dir ("DESKTOP");
 653 }
 654 
 655 /**
 656  * nautilus_get_desktop_directory:
 657  * 
 658  * Get the path for the directory containing files on the desktop.
 659  *
 660  * Return value: the directory path.
 661  **/
 662 char *
 663 nautilus_get_desktop_directory (void)
 664 {
 665 	char *desktop_directory;
 666 	
 667 	desktop_directory = get_desktop_path ();
 668 
 669 	/* Don't try to create a home directory */
 670 	if (!g_file_test (desktop_directory, G_FILE_TEST_EXISTS)) {
 671 		g_mkdir (desktop_directory, DEFAULT_DESKTOP_DIRECTORY_MODE);
 672 		/* FIXME bugzilla.gnome.org 41286: 
 673 		 * How should we handle the case where this mkdir fails? 
 674 		 * Note that nautilus_application_startup will refuse to launch if this 
 675 		 * directory doesn't get created, so that case is OK. But the directory 
 676 		 * could be deleted after Nautilus was launched, and perhaps
 677 		 * there is some bad side-effect of not handling that case.
 678 		 */
 679 	}
 680 
 681 	return desktop_directory;
 682 }
 683 
 684 GFile *
 685 nautilus_get_desktop_location (void)
 686 {
 687 	char *desktop_directory;
 688 	GFile *res;
 689 	
 690 	desktop_directory = get_desktop_path ();
 691 
 692 	res = g_file_new_for_path (desktop_directory);
 693 	g_free (desktop_directory);
 694 	return res;
 695 }
 696 
 697 /**
 698  * nautilus_get_desktop_directory_uri:
 699  * 
 700  * Get the uri for the directory containing files on the desktop.
 701  *
 702  * Return value: the directory path.
 703  **/
 704 char *
 705 nautilus_get_desktop_directory_uri (void)
 706 {
 707 	char *desktop_path;
 708 	char *desktop_uri;
 709 	
 710 	desktop_path = nautilus_get_desktop_directory ();
 711 	desktop_uri = g_filename_to_uri (desktop_path, NULL, NULL);
 712 	g_free (desktop_path);
 713 
 714 	return desktop_uri;
 715 }
 716 
 717 char *
 718 nautilus_get_home_directory_uri (void)
 719 {
 720 	return  g_filename_to_uri (g_get_home_dir (), NULL, NULL);
 721 }
 722 
 723 
 724 gboolean
 725 nautilus_should_use_templates_directory (void)
 726 {
 727 	char *dir;
 728 	gboolean res;
 729 	
 730 	dir = nautilus_get_xdg_dir ("TEMPLATES");
 731 	res = strcmp (dir, g_get_home_dir ()) != 0;
 732 	g_free (dir);
 733 	return res;
 734 }
 735 
 736 char *
 737 nautilus_get_templates_directory (void)
 738 {
 739 	return nautilus_get_xdg_dir ("TEMPLATES");
 740 }
 741 
 742 void
 743 nautilus_create_templates_directory (void)
 744 {
 745 	char *dir;
 746 
 747 	dir = nautilus_get_templates_directory ();
 748 	if (!g_file_test (dir, G_FILE_TEST_EXISTS)) {
 749 		g_mkdir (dir, DEFAULT_NAUTILUS_DIRECTORY_MODE);
 750 	}
 751 	g_free (dir);
 752 }
 753 
 754 char *
 755 nautilus_get_templates_directory_uri (void)
 756 {
 757 	char *directory, *uri;
 758 
 759 	directory = nautilus_get_templates_directory ();
 760 	uri = g_filename_to_uri (directory, NULL, NULL);
 761 	g_free (directory);
 762 	return uri;
 763 }
 764 
 765 char *
 766 nautilus_get_searches_directory (void)
 767 {
 768 	char *user_dir;
 769 	char *searches_dir;
 770 
 771 	user_dir = nautilus_get_user_directory ();
 772 	searches_dir = g_build_filename (user_dir, "searches", NULL);
 773 	g_free (user_dir);
 774 	
 775 	if (!g_file_test (searches_dir, G_FILE_TEST_EXISTS))
 776 		g_mkdir (searches_dir, DEFAULT_NAUTILUS_DIRECTORY_MODE);
 777 
 778 	return searches_dir;
 779 }
 780 
 781 /* These need to be reset to NULL when desktop_is_home_dir changes */
 782 static GFile *desktop_dir = NULL;
 783 static GFile *desktop_dir_dir = NULL;
 784 static char *desktop_dir_filename = NULL;
 785 
 786 
 787 static void
 788 desktop_dir_changed (void)
 789 {
 790 	if (desktop_dir) {
 791 		g_object_unref (desktop_dir);
 792 	}
 793 	if (desktop_dir_dir) {
 794 		g_object_unref (desktop_dir_dir);
 795 	}
 796 	g_free (desktop_dir_filename);
 797 	desktop_dir = NULL;
 798 	desktop_dir_dir = NULL;
 799 	desktop_dir_filename = NULL;
 800 }
 801 
 802 static void
 803 update_desktop_dir (void)
 804 {
 805 	char *path;
 806 	char *dirname;
 807 
 808 	path = get_desktop_path ();
 809 	desktop_dir = g_file_new_for_path (path);
 810 	
 811 	dirname = g_path_get_dirname (path);
 812 	desktop_dir_dir = g_file_new_for_path (dirname);
 813 	g_free (dirname);
 814 	desktop_dir_filename = g_path_get_basename (path);
 815 	g_free (path);
 816 }
 817 
 818 gboolean
 819 nautilus_is_home_directory_file (GFile *dir,
 820 				 const char *filename)
 821 {
 822 	char *dirname;
 823 	static GFile *home_dir_dir = NULL;
 824 	static char *home_dir_filename = NULL;
 825 	
 826 	if (home_dir_dir == NULL) {
 827 		dirname = g_path_get_dirname (g_get_home_dir ());
 828 		home_dir_dir = g_file_new_for_path (dirname);
 829 		g_free (dirname);
 830 		home_dir_filename = g_path_get_basename (g_get_home_dir ());
 831 	}
 832 
 833 	return (g_file_equal (dir, home_dir_dir) &&
 834 		strcmp (filename, home_dir_filename) == 0);
 835 }
 836 
 837 gboolean
 838 nautilus_is_home_directory (GFile *dir)
 839 {
 840 	static GFile *home_dir = NULL;
 841 	
 842 	if (home_dir == NULL) {
 843 		home_dir = g_file_new_for_path (g_get_home_dir ());
 844 	}
 845 
 846 	return g_file_equal (dir, home_dir);
 847 }
 848 
 849 gboolean
 850 nautilus_is_root_directory (GFile *dir)
 851 {
 852 	static GFile *root_dir = NULL;
 853 	
 854 	if (root_dir == NULL) {
 855 		root_dir = g_file_new_for_path ("/");
 856 	}
 857 
 858 	return g_file_equal (dir, root_dir);
 859 }
 860 		
 861 		
 862 gboolean
 863 nautilus_is_desktop_directory_file (GFile *dir,
 864 				    const char *file)
 865 {
 866 
 867 	if (desktop_dir == NULL) {
 868 		update_desktop_dir ();
 869 	}
 870 
 871 	return (g_file_equal (dir, desktop_dir_dir) &&
 872 		strcmp (file, desktop_dir_filename) == 0);
 873 }
 874 
 875 gboolean
 876 nautilus_is_desktop_directory (GFile *dir)
 877 {
 878 
 879 	if (desktop_dir == NULL) {
 880 		update_desktop_dir ();
 881 	}
 882 
 883 	return g_file_equal (dir, desktop_dir);
 884 }
 885 
 886 GMount *
 887 nautilus_get_mounted_mount_for_root (GFile *location)
 888 {
 889 	GVolumeMonitor *volume_monitor;
 890 	GList *mounts;
 891 	GList *l;
 892 	GMount *mount;
 893 	GMount *result = NULL;
 894 	GFile *root = NULL;
 895 	GFile *default_location = NULL;
 896 
 897 	volume_monitor = g_volume_monitor_get ();
 898 	mounts = g_volume_monitor_get_mounts (volume_monitor);
 899 
 900 	for (l = mounts; l != NULL; l = l->next) {
 901 		mount = l->data;
 902 
 903 		if (g_mount_is_shadowed (mount)) {
 904 			continue;
 905 		}
 906 
 907 		root = g_mount_get_root (mount);
 908 		if (g_file_equal (location, root)) {
 909 			result = g_object_ref (mount);
 910 			break;
 911 		}
 912 
 913 		default_location = g_mount_get_default_location (mount);
 914 		if (!g_file_equal (default_location, root) &&
 915 		    g_file_equal (location, default_location)) {
 916 			result = g_object_ref (mount);
 917 			break;
 918 		}
 919 	}
 920 
 921 	g_clear_object (&root);
 922 	g_clear_object (&default_location);
 923 	g_list_free_full (mounts, g_object_unref);
 924 
 925 	return result;
 926 }
 927 
 928 char *
 929 nautilus_ensure_unique_file_name (const char *directory_uri,
 930 				  const char *base_name,
 931 				  const char *extension)
 932 {
 933 	GFileInfo *info;
 934 	char *filename;
 935 	GFile *dir, *child;
 936 	int copy;
 937 	char *res;
 938 
 939 	dir = g_file_new_for_uri (directory_uri);
 940 
 941 	info = g_file_query_info (dir, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL);
 942 	if (info == NULL) {
 943 		g_object_unref (dir);
 944 		return NULL;
 945 	}
 946 	g_object_unref (info);
 947 
 948 	filename = g_strdup_printf ("%s%s",
 949 				    base_name,
 950 				    extension);
 951 	child = g_file_get_child (dir, filename);
 952 	g_free (filename);
 953 	
 954 	copy = 1;
 955 	while ((info = g_file_query_info (child, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL)) != NULL) {
 956 		g_object_unref (info);
 957 		g_object_unref (child);
 958 		
 959 		filename = g_strdup_printf ("%s-%d%s",
 960 					    base_name,
 961 					    copy,
 962 					    extension);
 963 		child = g_file_get_child (dir, filename);
 964 		g_free (filename);
 965 		
 966 		copy++;
 967 	}
 968 
 969 	res = g_file_get_uri (child);
 970 	g_object_unref (child);
 971 	g_object_unref (dir);
 972 	
 973 	return res;
 974 }
 975 
 976 GFile *
 977 nautilus_find_existing_uri_in_hierarchy (GFile *location)
 978 {
 979 	GFileInfo *info;
 980 	GFile *tmp;
 981 
 982 	g_assert (location != NULL);
 983 
 984 	location = g_object_ref (location);
 985 	while (location != NULL) {
 986 		info = g_file_query_info (location,
 987 					  G_FILE_ATTRIBUTE_STANDARD_NAME,
 988 					  0, NULL, NULL);
 989 		g_object_unref (info);
 990 		if (info != NULL) {
 991 			return location;
 992 		}
 993 		tmp = location;
 994 		location = g_file_get_parent (location);
 995 		g_object_unref (tmp);
 996 	}
 997 	
 998 	return location;
 999 }
1000 
1001 static gboolean
1002 have_program_in_path (const char *name)
1003 {
1004         gchar *path;
1005         gboolean result;
1006 
1007         path = g_find_program_in_path (name);
1008         result = (path != NULL);
1009         g_free (path);
1010         return result;
1011 }
1012 
1013 static GIcon *
1014 special_directory_get_icon (GUserDirectory directory,
1015 			    gboolean symbolic)
1016 {
1017 
1018 #define ICON_CASE(x)							 \
1019 	case G_USER_DIRECTORY_ ## x:					 \
1020 		return (symbolic) ? g_themed_icon_new (NAUTILUS_ICON_FOLDER_ ## x) : g_themed_icon_new (NAUTILUS_ICON_FULLCOLOR_FOLDER_ ## x);
1021 
1022 	switch (directory) {
1023 
1024 		ICON_CASE (DOCUMENTS);
1025 		ICON_CASE (DOWNLOAD);
1026 		ICON_CASE (MUSIC);
1027 		ICON_CASE (PICTURES);
1028 		ICON_CASE (PUBLIC_SHARE);
1029 		ICON_CASE (TEMPLATES);
1030 		ICON_CASE (VIDEOS);
1031 
1032 	default:
1033 		return (symbolic) ? g_themed_icon_new (NAUTILUS_ICON_FOLDER) : g_themed_icon_new (NAUTILUS_ICON_FULLCOLOR_FOLDER);
1034 	}
1035 
1036 #undef ICON_CASE
1037 }
1038 
1039 GIcon *
1040 nautilus_special_directory_get_symbolic_icon (GUserDirectory directory)
1041 {
1042 	return special_directory_get_icon (directory, TRUE);
1043 }
1044 
1045 GIcon *
1046 nautilus_special_directory_get_icon (GUserDirectory directory)
1047 {
1048 	return special_directory_get_icon (directory, FALSE);
1049 }
1050 
1051 gboolean
1052 nautilus_is_file_roller_installed (void)
1053 {
1054 	static int installed = - 1;
1055 
1056 	if (installed < 0) {
1057 		if (have_program_in_path ("file-roller")) {
1058 			installed = 1;
1059 		} else {
1060 			installed = 0;
1061 		}
1062 	}
1063 
1064 	return installed > 0 ? TRUE : FALSE;
1065 }
1066 
1067 /* Returns TRUE if the file is in XDG_DATA_DIRS. This is used for
1068    deciding if a desktop file is "trusted" based on the path */
1069 gboolean
1070 nautilus_is_in_system_dir (GFile *file)
1071 {
1072 	const char * const * data_dirs; 
1073 	char *path;
1074 	int i;
1075 	gboolean res;
1076 	
1077 	if (!g_file_is_native (file)) {
1078 		return FALSE;
1079 	}
1080 
1081 	path = g_file_get_path (file);
1082 	
1083 	res = FALSE;
1084 
1085 	data_dirs = g_get_system_data_dirs ();
1086 	for (i = 0; path != NULL && data_dirs[i] != NULL; i++) {
1087 		if (g_str_has_prefix (path, data_dirs[i])) {
1088 			res = TRUE;
1089 			break;
1090 		}
1091 		
1092 	}
1093 
1094 	g_free (path);
1095 
1096 	return res;
1097 }
1098 
1099 GHashTable *
1100 nautilus_trashed_files_get_original_directories (GList *files,
1101 						 GList **unhandled_files)
1102 {
1103 	GHashTable *directories;
1104 	NautilusFile *file, *original_file, *original_dir;
1105 	GList *l, *m;
1106 
1107 	directories = NULL;
1108 
1109 	if (unhandled_files != NULL) {
1110 		*unhandled_files = NULL;
1111 	}
1112 
1113 	for (l = files; l != NULL; l = l->next) {
1114 		file = NAUTILUS_FILE (l->data);
1115 		original_file = nautilus_file_get_trash_original_file (file);
1116 
1117 		original_dir = NULL;
1118 		if (original_file != NULL) {
1119 			original_dir = nautilus_file_get_parent (original_file);
1120 		}
1121 
1122 		if (original_dir != NULL) {
1123 			if (directories == NULL) {
1124 				directories = g_hash_table_new_full (g_direct_hash, g_direct_equal,
1125 								     (GDestroyNotify) nautilus_file_unref,
1126 								     (GDestroyNotify) nautilus_file_list_free);
1127 			}
1128 			nautilus_file_ref (original_dir);
1129 			m = g_hash_table_lookup (directories, original_dir);
1130 			if (m != NULL) {
1131 				g_hash_table_steal (directories, original_dir);
1132 				nautilus_file_unref (original_dir);
1133 			}
1134 			m = g_list_append (m, nautilus_file_ref (file));
1135 			g_hash_table_insert (directories, original_dir, m);
1136 		} else if (unhandled_files != NULL) {
1137 			*unhandled_files = g_list_append (*unhandled_files, nautilus_file_ref (file));
1138 		}
1139 
1140 		if (original_file != NULL) {
1141 			nautilus_file_unref (original_file);
1142 		}
1143 
1144 		if (original_dir != NULL) {
1145 			nautilus_file_unref (original_dir);
1146 		}
1147 	}
1148 
1149 	return directories;
1150 }
1151 
1152 static GList *
1153 locations_from_file_list (GList *file_list)
1154 {
1155 	NautilusFile *file;
1156 	GList *l, *ret;
1157 
1158 	ret = NULL;
1159 
1160 	for (l = file_list; l != NULL; l = l->next) {
1161 		file = NAUTILUS_FILE (l->data);
1162 		ret = g_list_prepend (ret, nautilus_file_get_location (file));
1163 	}
1164 
1165 	return g_list_reverse (ret);
1166 }
1167 
1168 void
1169 nautilus_restore_files_from_trash (GList *files,
1170 				   GtkWindow *parent_window)
1171 {
1172 	NautilusFile *file, *original_dir;
1173 	GHashTable *original_dirs_hash;
1174 	GList *original_dirs, *unhandled_files;
1175 	GFile *original_dir_location;
1176 	GList *locations, *l;
1177 	char *message, *file_name;
1178 
1179 	original_dirs_hash = nautilus_trashed_files_get_original_directories (files, &unhandled_files);
1180 
1181 	for (l = unhandled_files; l != NULL; l = l->next) {
1182 		file = NAUTILUS_FILE (l->data);
1183 		file_name = nautilus_file_get_display_name (file);
1184 		message = g_strdup_printf (_("Could not determine original location of “%s” "), file_name);
1185 		g_free (file_name);
1186 
1187 		eel_show_warning_dialog (message,
1188 					 _("The item cannot be restored from trash"),
1189 					 parent_window);
1190 		g_free (message);
1191 	}
1192 
1193 	if (original_dirs_hash != NULL) {
1194 		original_dirs = g_hash_table_get_keys (original_dirs_hash);
1195 		for (l = original_dirs; l != NULL; l = l->next) {
1196 			original_dir = NAUTILUS_FILE (l->data);
1197 			original_dir_location = nautilus_file_get_location (original_dir);
1198 
1199 			files = g_hash_table_lookup (original_dirs_hash, original_dir);
1200 			locations = locations_from_file_list (files);
1201 
1202 			nautilus_file_operations_move
1203 				(locations, NULL, 
1204 				 original_dir_location,
1205 				 parent_window,
1206 				 NULL, NULL);
1207 
1208 			g_list_free_full (locations, g_object_unref);
1209 			g_object_unref (original_dir_location);
1210 		}
1211 
1212 		g_list_free (original_dirs);
1213 		g_hash_table_destroy (original_dirs_hash);
1214 	}
1215 
1216 	nautilus_file_list_unref (unhandled_files);
1217 }
1218 
1219 typedef struct {
1220 	NautilusMountGetContent callback;
1221 	gpointer user_data;
1222 } GetContentTypesData;
1223 
1224 static void
1225 get_types_cb (GObject *source_object,
1226 	      GAsyncResult *res,
1227 	      gpointer user_data)
1228 {
1229 	GetContentTypesData *data;
1230 	char **types;
1231 
1232 	data = user_data;
1233 	types = g_mount_guess_content_type_finish (G_MOUNT (source_object), res, NULL);
1234 
1235 	g_object_set_data_full (source_object,
1236 				"nautilus-content-type-cache",
1237 				g_strdupv (types),
1238 				(GDestroyNotify)g_strfreev);
1239 
1240 	if (data->callback) {
1241 		data->callback ((const char **) types, data->user_data);
1242 	}
1243 	g_strfreev (types);
1244 	g_slice_free (GetContentTypesData, data);
1245 }
1246 
1247 void
1248 nautilus_get_x_content_types_for_mount_async (GMount *mount,
1249 					      NautilusMountGetContent callback,
1250 					      GCancellable *cancellable,
1251 					      gpointer user_data)
1252 {
1253 	char **cached;
1254 	GetContentTypesData *data;
1255 
1256 	if (mount == NULL) {
1257 		if (callback) {
1258 			callback (NULL, user_data);
1259 		}
1260 		return;
1261 	}
1262 
1263 	cached = g_object_get_data (G_OBJECT (mount), "nautilus-content-type-cache");
1264 	if (cached != NULL) {
1265 		if (callback) {
1266 			callback ((const char **) cached, user_data);
1267 		}
1268 		return;
1269 	}
1270 
1271 	data = g_slice_new0 (GetContentTypesData);
1272 	data->callback = callback;
1273 	data->user_data = user_data;
1274 
1275 	g_mount_guess_content_type (mount,
1276 				    FALSE,
1277 				    cancellable,
1278 				    get_types_cb,
1279 				    data);
1280 }
1281 
1282 char **
1283 nautilus_get_cached_x_content_types_for_mount (GMount *mount)
1284 {
1285 	char **cached;
1286 
1287 	if (mount == NULL) {
1288 		return NULL;
1289 	}
1290 
1291 	cached = g_object_get_data (G_OBJECT (mount), "nautilus-content-type-cache");
1292 	if (cached != NULL) {
1293 		return g_strdupv (cached);
1294 	}
1295 
1296 	return NULL;
1297 }
1298 
1299 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
1300 
1301 void
1302 nautilus_self_check_file_utilities (void)
1303 {
1304 }
1305 
1306 #endif /* !NAUTILUS_OMIT_SELF_CHECK */