static char *
sanitize_path (const char *str)
{
	char *res = NULL;
	char *s;

	/* Skip leading periods, otherwise files disappear... */
	while (*str == '.')
		str++;

	s = g_strdup (str);
	rb_sanitize_path_for_msdos_filesystem (s);
	res = g_uri_escape_string (s, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT, TRUE);
	g_free (s);
	return res;
}
Beispiel #2
0
static void
sanitize_for_mtp (char *str)
{
	rb_sanitize_path_for_msdos_filesystem (str);
	g_strdelimit (str, "/", '_');
}
/**
 * rb_sanitize_uri_for_filesystem:
 * @uri: a URI to sanitize
 *
 * Removes characters from @uri that are not allowed by the filesystem
 * on which it would be stored.  At present, this only supports MS DOS
 * filesystems.
 *
 * Return value: sanitized copy of @uri, must be freed by caller.
 */
char *
rb_sanitize_uri_for_filesystem (const char *uri)
{
	char *mountpoint = NULL;
	char *filesystem;
	char *sane_uri = NULL;

	filesystem = rb_uri_get_filesystem_type (uri, &mountpoint);
	if (!filesystem)
		return g_strdup (uri);

	if (!strcmp (filesystem, "fat") ||
	    !strcmp (filesystem, "vfat") ||
	    !strcmp (filesystem, "msdos")) {
	    	char *hostname = NULL;
		GError *error = NULL;
		char *full_path;
		char *fat_path;

		full_path = g_filename_from_uri (uri, &hostname, &error);

		if (error) {
			g_error_free (error);
			g_free (filesystem);
			g_free (full_path);
			g_free (mountpoint);
			return g_strdup (uri);
		}

		/* if we got a mount point, don't sanitize it.  the mountpoint must be
		 * valid for the filesystem that contains it, but it may not be valid for
		 * the filesystem it contains.  for example, a vfat filesystem mounted
		 * at "/media/Pl1:".
		 */
		fat_path = full_path;
		if (mountpoint != NULL) {
			char *mount_path;
			mount_path = g_filename_from_uri (mountpoint, NULL, &error);
			if (error) {
				rb_debug ("can't convert mountpoint %s to a path: %s", mountpoint, error->message);
				g_error_free (error);
			} else if (g_str_has_prefix (full_path, mount_path)) {
				fat_path = full_path + strlen (mount_path);
			} else {
				rb_debug ("path %s doesn't begin with mount path %s somehow", full_path, mount_path);
			}

			g_free (mount_path);
		} else {
			rb_debug ("couldn't get mount point for %s", uri);
		}

		rb_debug ("sanitizing path %s", fat_path);
		rb_sanitize_path_for_msdos_filesystem (fat_path);

		/* create a new uri from this */
		sane_uri = g_filename_to_uri (full_path, hostname, &error);
		rb_debug ("sanitized URI: %s", sane_uri);

		g_free (hostname);
		g_free (full_path);

		if (error) {
			g_error_free (error);
			g_free (filesystem);
			g_free (mountpoint);
			return g_strdup (uri);
		}
	}

	/* add workarounds for other filesystems limitations here */

	g_free (filesystem);
	g_free (mountpoint);
	return sane_uri ? sane_uri : g_strdup (uri);
}
static void
prepare_encoder_sink_cb (RBEncoderFactory *factory,
			 const char *stream_uri,
			 GObject *sink,
			 RBMtpSource *source)
{
	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
	RhythmDBEntry *entry;
	RhythmDB *db;
	LIBMTP_track_t *track;
	char **bits;
	char *extension;
	LIBMTP_filetype_t filetype;
	gulong track_id;
	GDate d;

	/* make sure this stream is for a file on our device */
	if (g_str_has_prefix (stream_uri, "xrbmtp://") == FALSE)
		return;

	/* extract the entry ID, extension, and MTP filetype from the URI */
	bits = g_strsplit (stream_uri + strlen ("xrbmtp://"), "/", 3);
	track_id = strtoul (bits[0], NULL, 0);
	extension = g_strdup (bits[1]);
	filetype = strtoul (bits[2], NULL, 0);
	g_strfreev (bits);

	db = get_db_for_source (source);
	entry = rhythmdb_entry_lookup_by_id (db, track_id);
	g_object_unref (db);
	if (entry == NULL) {
		g_free (extension);
		return;
	}

	track = LIBMTP_new_track_t ();
	track->title = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_TITLE);
	track->album = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ALBUM);
	track->artist = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ARTIST);
	track->genre = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_GENRE);

	/* build up device filename; may want to reconsider if we start creating folders */
	track->filename = g_strdup_printf ("%s - %s.%s",
					   rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST),
					   rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE),
					   extension);
	g_free (extension);

	/* ensure the filename is safe for FAT filesystems and doesn't contain slashes */
	rb_sanitize_path_for_msdos_filesystem (track->filename);
	g_strdelimit (track->filename, "/", '_');

	if (rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DATE) > 0) {
		g_date_set_julian (&d, rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DATE));
		track->date = gdate_to_char (&d);
	}
	track->tracknumber = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER);
	track->duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION) * 1000;
	track->rating = rhythmdb_entry_get_double (entry, RHYTHMDB_PROP_RATING) * 20;
	track->usecount = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_PLAY_COUNT);

	track->filetype = filetype;

	g_object_set (sink, "device-thread", priv->device_thread, "mtp-track", track, NULL);
	rhythmdb_entry_unref (entry);

	g_hash_table_insert (priv->track_transfer_map, g_strdup (stream_uri), track);
}