Ejemplo n.º 1
0
 int 
 mp_convert_to_v2(id3_tag *tag)
 {
	 id3v1_tag *v1;
	 id3_tag *tmp;
	 id3_content* content;
	 
	 if(tag->version == 2) return 0;
	 else if(tag->version == -1) return MP_EVERSION;
	 
	 tmp = mp_alloc_tag_with_version(2);
	 
	 v1 = (id3v1_tag*)tag->tag;
	 
	 content = mp_assemble_text_content(v1->artist, ISO_8859_1);
	 if(v1->artist) mp_set_content(tmp, MP_ARTIST, content);
	 
	 content = mp_assemble_text_content(v1->title, ISO_8859_1);
	 if(v1->title) mp_set_content(tmp, MP_TITLE, content);
	 
	 content = mp_assemble_text_content(v1->album, ISO_8859_1);
	 if(v1->album) mp_set_content(tmp, MP_ALBUM, content);
	 
	 content = mp_assemble_text_content(v1->year, ISO_8859_1);
	 if(v1->year) mp_set_content(tmp, MP_YEAR, content);
	 
	 content = mp_assemble_comment_content(v1->comment, NULL, ISO_8859_1, NULL);
	 if(v1->comment) mp_set_content(tmp, MP_COMMENT, content);
	 
	 if(v1->genre != 0xFF)
	 {
		 char *c = xmallocd(strlen(genre_list[v1->genre]) + 1,
				    "mp_convert_to_v2:c");
		 strcpy(c, genre_list[v1->genre]);
		 content = mp_assemble_text_content(c, ISO_8859_1);
		 mp_set_content(tmp, MP_GENRE, content);
	 }
	 if(v1->track > 0)
	 {
		 char *trk = (char *)xmallocd(4, "mp_convert_to_v2:trk");
		 snprintf(trk, 3, "%d", v1->track);
		 trk[3] = 0;
		 content = mp_assemble_text_content(trk, ISO_8859_1);
		 mp_set_content(tmp, MP_TRACK, content);
	 }
	 
	 tag->version = 2;
	 tag->tag = tmp->tag;
	 
	 id3v1_free_tag(v1);
	 xfree(tmp);
	 
	 return 0;
 }
Ejemplo n.º 2
0
static int
id3v1_del_tag(int fd) 
{
	int nlength;
	unsigned char *c;
	struct stat fs;
	
	if(fstat(fd, &fs)) return 1;
	
	if(fs.st_size < 128) return 1; /* Hardly a valid mpeg file.. */

	c = (char *)xmallocd(3, "id3v1_del_tag:c");
	if(lseek(fd, -128L, SEEK_END) == -1) goto exit_on_error;
	if(read(fd, c, 3) < 3) goto exit_on_error;
	if(strncmp(c, "TAG", 3)) goto exit_on_error;
	xfree(c);
		
	nlength = fs.st_size - 128;
		
	if(ftruncate(fd, nlength)) return 1;  
		
	return 0;

 exit_on_error:
	xfree(c);
	return 1;
}
Ejemplo n.º 3
0
static int
id3v2_del_tag(int fd, id3v2_tag *t)
{
	unsigned char *c;
	long tag_len, file_len;
	FILE *file, *tmp;
	int read;
	void *ptr;
	id3v2_tag *tfound = NULL;;
	
	if(!t)
	{
	    t = id3v2_get_tag(fd);
	    if(!t) return 0;
	    else tfound = t;
	}
	
	ptr =  xmallocd(4096, "id3v2_del_tag:ptr");
	
	tag_len = t->header->total_tag_size;
	file_len = lseek(fd, 0, SEEK_END);
	if(file_len < 1 || tag_len < 1) goto exit_on_error;
	
	/* use os system buffering */
	file = fdopen(fd, "r+b");
	tmp = tmpfile();
	if(!(file && tmp)) goto exit_on_error;
	
	fseek(file, tag_len, SEEK_SET);
	fseek(tmp, 0, SEEK_SET);
	while(!feof(file))
	{
		read = fread(ptr, 1, 4096, file);
		if(fwrite(ptr, 1, read, tmp) != read && !feof(file))
		    goto exit_on_error;
	}
	
	fflush(tmp);
	
	fseek(file, 0, SEEK_SET);
	fseek(tmp, 0, SEEK_SET);
	while(!feof(tmp))
	{
		read = fread(ptr, 1, 4096, tmp);
		if(fwrite(ptr, 1, read, file) != read && !feof(tmp)) 
		    goto exit_on_error;
	}
	
	fclose(tmp);
	xfree(ptr);
	if(tfound) id3v2_free_tag(tfound);
	return 0;

 exit_on_error:
	fclose(tmp);
	xfree(ptr);
	if(tfound) id3v2_free_tag(tfound);
	return 1;
}
Ejemplo n.º 4
0
int 
mp_set_custom_content_at_pos(id3_tag* tag, char* field, id3_content* new_content, int pos)
{
	id3v2_tag *v2;
	
	if(!tag || !field || strlen(field) != 4) return MP_EERROR;
	
	if(tag->version == 1)
	{
		if(mp_convert_to_v2(tag))
			return MP_EERROR;
	}
	else if(tag->version == -1) return MP_EVERSION;
	
	v2 = (id3v2_tag*)tag->tag;
	if(!v2->frame_list)
	{
		v2->frame_list = XMALLOCD0(id3v2_frame_list, 
				 "mp_set_custom_content_at_pos:v2->frame_list");
		id3_add_frame(v2->frame_list, field, new_content->data, new_content->length);
	}
	else
	{
		id3v2_frame *frame;
		
		if((frame = id3_lookup_frame(v2->frame_list, field, pos)))
		{
			if(new_content) 
			{
				long len, len_sync;
				/* make sync safe */
				len = new_content->length;
				len_sync = id3_sync(new_content->data, len);
				
				xfree(frame->data);
				frame->data = xmallocd(new_content->length,
					      "mp_set_custom_content_at_pos:frame->data");
				memcpy(frame->data, new_content->data, new_content->length);
				frame->status_flag = 0;
				if(len != len_sync) frame->format_flag = 64;
				else frame->format_flag = 0;
				frame->data_size = len_sync;
			}
			else id3_remove_frame(v2->frame_list, frame);
		}
		else if(pos == 0) id3_add_frame(v2->frame_list, field, new_content->data, new_content->length);
		else return MP_EFNF;
	}
	
	return 0;
}
Ejemplo n.º 5
0
static id3v1_tag*
id3v1_get_tag(int fd)
{
	id3v1_tag *tag;
	char *c;
	
	tag = XMALLOCD0(id3v1_tag, "id3v1_get_tag:tag");
	
	c = (char *)xmallocd(3, "id3v1_get_tag:c");
	
	if(lseek(fd, -128L, SEEK_END) == -1) goto exit_on_error;
	if(read(fd, c, 3) < 3) goto exit_on_error;
	if(strncmp(c, "TAG", 3) != 0) goto exit_on_error;

	tag->title = (char *)xmallocd(31, "id3v1_get_tag:tag->title");
	if(read(fd, tag->title, 30) < 30) goto exit_on_error;
	if(tag->title[0] == 0 || id3_is_only_space(tag->title, 30)) {
	    xfree(tag->title);
	    tag->title = NULL;
	} else tag->title[30] = 0;
	
	tag->artist = (char*)xmallocd(31, "id3v1_get_tag:tag->artist");
	if(read(fd, tag->artist, 30) < 30) goto exit_on_error;
	if(tag->artist[0] == 0 || id3_is_only_space(tag->artist, 30)) {
	    xfree(tag->artist);
	    tag->artist = NULL;
	} else tag->artist[30] = 0;
	
	tag->album = (char*)xmallocd(31, "id3v1_get_tag:tag->album");
	if(read(fd, tag->album, 30) < 30) goto exit_on_error;
	if(tag->album[0] == 0 || id3_is_only_space(tag->album, 30)) {
	    xfree(tag->album);
	    tag->album = NULL;
	} else tag->album[30] = 0;
	
	tag->year = (char*)xmallocd(5, "id3v1_get_tag:tag->year");
	if(read(fd, tag->year, 4) < 4) goto exit_on_error;
	if(tag->year[0] == 0 || id3_is_only_space(tag->year, 4)) {
	    xfree(tag->year);
	    tag->year = NULL;
	} else tag->year[4] = 0;
	
	tag->comment = (char*)xmallocd(31, "id3v1_get_tag:tag->comment");
	if(read(fd, tag->comment, 30) < 30) goto exit_on_error;
	tag->comment[30] = 0;
	
	if(read(fd, &(tag->genre), 1) < 1) goto exit_on_error;
	
	/* Looking for v1.1 track info */
	if(tag->comment && tag->comment[28] == 0 && tag->comment[29] != 0)
	{
		tag->track = tag->comment[29];
		tag->comment[29] = 0;
	} 
	else 
	{
		tag->track = 0;
	}
	
	/* Set comment to NULL if not set - this happens at this point because */
	/* there maybe a track info anyway */
	if(tag->comment[0] == 0 || id3_is_only_space(tag->comment, 28)) {
	    xfree(tag->comment);
	    tag->comment = NULL;
	}
	
	xfree(c);
	return tag;

	exit_on_error:
	
	xfree(c);
	id3v1_free_tag(tag);
	return NULL;
}
Ejemplo n.º 6
0
static int 
id3v2_add_tag(int fd, id3v2_tag *tag, id3v2_tag *old)
{
	unsigned char *btag, *btag_start;
	unsigned char flag = 0;
	int i, j;
	char *b_tag, *b_tag_start, *d;
	id3v2_frame_list *frame_list;
	id3v2_frame *frame;

	/* at first we are going to write the tags raw data into
	the btag byte array */
	btag = btag_start = xmallocd0(tag->header->total_tag_size,
			    "id3v2_add_tag:btag");
	strncpy(btag, "ID3", 3); btag += 3;
	*btag = (char)tag->header->version_minor; btag += 1;
	*btag = (char)tag->header->version_revision; btag += 1;
	flag |= ((tag->header->unsyncronization & 1) << 7);
	flag |= ((tag->header->has_extended_header & 1) << 6);
	flag |= ((tag->header->is_experimental & 1) << 5);
	flag |= ((tag->header->has_footer & 1) << 4);
	memcpy(btag, &flag, 1); btag += 1;
	
	if(old)
	{
		i = old->header->total_tag_size - 10;
		if(old->header->has_footer) i -= 10;
	}
	else
	{
		i = tag->header->total_tag_size - 10;
		if(tag->header->has_footer) i -= 10;
		/* add padding to total size we mean to store on disk */
		/* mplib does not use any kind of padding internaly */
		i += 1024;
	}
	
	d = id3_sync32(i); 
	btag[0] = d[0];
	btag[1] = d[1];
	btag[2] = d[2];
	btag[3] = d[3];
	xfree(d);
	btag += 4;
	
	if(tag->header->has_extended_header)
	{
		d = id3_sync32(tag->header->extended_header->size);
		btag[0] = d[0];
		btag[1] = d[1];
		btag[2] = d[2];
		btag[3] = d[3];
		xfree(d);
		btag += 4;
		
		*btag = (char)tag->header->extended_header->no_flag_bytes; btag += 1;
		flag = ((tag->header->extended_header->is_update & 1) << 6);
		flag |= ((tag->header->extended_header->crc_data_present & 1) << 5);
		flag |= ((tag->header->extended_header->restrictions & 1) << 4);
		memcpy(btag, &flag, 1); btag += 1;
		if(tag->header->extended_header->is_update) 
		{
			btag[0] = 0; btag += 1;
		}
		if(tag->header->extended_header->crc_data_present) 
		{
			int length = tag->header->extended_header->crc_data_length ? tag->header->extended_header->crc_data_length : 5;
			*btag = (char)length; btag += 1;
			memcpy(btag, tag->header->extended_header->crc_data, length); btag += 1;
		}
		if(tag->header->extended_header->restrictions) 
		{
			int length = tag->header->extended_header->restrictions_data_length ? tag->header->extended_header->restrictions_data_length : 5;
			*btag = (char)length; btag += 1;
			memcpy(btag, tag->header->extended_header->restrictions_data, length); btag += 1;
		}
	}
	
	frame_list = tag->frame_list;
	while(frame_list) {
		int j;
		frame = frame_list->data;
		
		strncpy(btag, frame->frame_id, 4); btag += 4;
		d = id3_sync32(frame->data_size);
		btag[0] = d[0];
		btag[1] = d[1];
		btag[2] = d[2];
		btag[3] = d[3];
		xfree(d);
		btag += 4;
		memcpy(btag, &frame->status_flag, 1); btag += 1;
		memcpy(btag, &frame->format_flag, 1); btag += 1;
		
		memcpy(btag, frame->data, frame->data_size); btag += frame->data_size;
		
		frame_list = frame_list->next;
	}
	
	/* XXX footer not supported yet */
	
	/* if an old tag was provided it is desired to overwrite it */
	/* else this is a brand new tag */
	if(old) {  
		FILE *file;
		void *ptr = xmallocd0(old->header->total_tag_size - tag->header->total_tag_size, "id3v2_add_tag:ptr");
		if(!(file = fdopen(fd, "r+b")))
		{
		    xfree(ptr);
		    goto exit_on_error;
		}
		
		fseek(file, 0, SEEK_SET);
		if(fwrite(btag_start, tag->header->total_tag_size, 1, file) < 1)
		{
		    xfree(ptr);
		    goto exit_on_error;
		}
		
		/* write padding till end of old tag */
		if(fwrite(ptr, old->header->total_tag_size - tag->header->total_tag_size, 1, file) < 1) {
		    xfree(ptr);
		    goto exit_on_error;
		}
		
		fflush(file);
		xfree(ptr);
				
	} else {
		FILE *file, *tmp;
		int read;
		void *ptr, *blank;
		unsigned char *c;

		ptr = xmallocd(4096, "id3v2_add_tag:ptr");
		blank = xmallocd0(1024, "id3v2_add_tag:blank");

		file = fdopen(fd, "r+b");
		tmp = tmpfile();
		if(!(file && tmp)) 
		{
		    fflush(file);
		    fclose(tmp);
		    xfree(ptr);
		    xfree(blank);
		    goto exit_on_error;
		}

		fseek(file, 0, SEEK_SET);
		fseek(tmp, 0, SEEK_SET);

		/* write tag in tmp file */
		fwrite(btag_start, tag->header->total_tag_size, 1, tmp);

		/* Write 1024b padding */
		fwrite(blank, 1024, 1, tmp);

		/* write rest of file */
		while(!feof(file))
		{
			read = fread(ptr, 1, 4096, file);
			if(fwrite(ptr, 1, read, tmp) != read && !feof(file))
			{
			    fflush(file);
			    fclose(tmp);
			    xfree(ptr);
			    xfree(blank);
			    goto exit_on_error;
			}
		}

		fflush(tmp);

		fseek(file, 0, SEEK_SET);
		fseek(tmp, 0, SEEK_SET);
		while(!feof(tmp))
		{
			read = fread(ptr, 1, 4096, tmp);
			if(fwrite(ptr, 1, read, file) != read && !feof(tmp))
			{
			    fflush(file);
			    fclose(tmp);
			    xfree(ptr);
			    xfree(blank);
			    goto exit_on_error;
			}
		}

		fflush(file);
		fclose(tmp);

		xfree(ptr);
		xfree(blank);
	    }

	xfree(btag_start);
	return 0;

 exit_on_error:
	xfree(btag_start);
	return MP_EERROR;
}
Ejemplo n.º 7
0
static int 
id3v1_add_tag(int fd, id3v1_tag *tag) 
{
	int i, j;
	void *blank, *set;
	char *b_tag, *b_tag_start;
	
	blank = xmallocd0(30, "id3v1_add_tag:blank");
	set = xmallocd(30, "id3v1_add_tag:set");
	memset(set, 0xFF, 30);
	b_tag = b_tag_start = (char *)xmallocd0(128, "id3v1_add_tag:b_tag");
	
	strncpy(b_tag, "TAG", 3); b_tag += 3;
	
	if(tag->title) 
	{
		j = strlen(tag->title);
		strncpy(b_tag, tag->title, j); b_tag += j;
		i = 30 - j;
		if(i > 0) 
		{
			strncpy(b_tag, blank, i); b_tag += i;
		}
	}
	else 
	{
		strncpy(b_tag, blank, 30); b_tag += 30;
	}
	
	if(tag->artist) 
	{
		j = strlen(tag->artist);
		strncpy(b_tag, tag->artist, j); b_tag += j;
		i = 30 - j;
		if(i > 0) 
		{
			strncpy(b_tag, blank, i); b_tag += i;
		}
	} 
	else
	{
		strncpy(b_tag, blank, 30); b_tag += 30;
	}
	
	if(tag->album)
	{
		j = strlen(tag->album);
		strncpy(b_tag, tag->album, j); b_tag += j;
		i = 30 - j;
		if(i > 0)
		{
			strncpy(b_tag, blank, i); b_tag += i;
		}
	}
	else
	{
		strncpy(b_tag, blank, 30); b_tag += 30;
	}
	
	if(tag->year) 
	{
		j = strlen(tag->year);
		strncpy(b_tag, tag->year, j); b_tag += j;
		i = 4 - j;
		if(i > 0) 
		{
			strncpy(b_tag, blank, i); b_tag += i;
		}
	}
	else 
	{
		strncpy(b_tag, blank, 4); b_tag += 4;
	}
	
	if(tag->comment)
	{
		int hastrack = 0;
		j = strlen(tag->comment);
		if(tag->track > 0) hastrack = 1;
		if(hastrack && j > 28) 
		{
			strncpy(b_tag, tag->comment, 28); b_tag += 28;
		}
		else
		{
			strncpy(b_tag, tag->comment, j); b_tag += j;
			i = ((tag->track > 0) ? 28 : 30) - j;
		}
		if(i > 0)
		{
			strncpy(b_tag, blank, i); b_tag += i;
		}
	} 
	else 
	{ 
		strncpy(b_tag, blank, (tag->track > 0) ? 28 : 30); 
		b_tag += (tag->track > 0) ? 28 : 30;
	}
	
	if(tag->track > 0) 
	{
		strncpy(b_tag, blank, 1); b_tag += 1;
		strncpy(b_tag, &(tag->track), 1); b_tag += 1;
	}
	if(tag->genre != 0xFF) 
	{
		strncpy(b_tag, &(tag->genre), 1); b_tag += 1;
	}
	else 
	{
		strncpy(b_tag, set, 1); b_tag += 1;
	}
	
	j = 0;
	
	if(lseek(fd, 0L, SEEK_END) != -1)
	{
	    if(write(fd, b_tag - 128, 128) < 128) j = 1;
	}
	else j = 1;

	xfree(b_tag_start);
	xfree(blank);
	xfree(set);
	
	return j;
}
Ejemplo n.º 8
0
/* This function is recursivly scaning a directory and all file in it for a match */
void
desc_dir(char *dir, unsigned int parent_depth)
{
    DIR *dir_struct = NULL;
    struct dirent *entry;

#ifdef DEBUG
    assert(dir && parent_depth >= 0);
#endif
    
    /* Check max depth */
    if(MAXDEPTH > 0 && parent_depth > MAXDEPTH)
    {
#ifdef DEBUG
	printf("DEBUG: Max depth prevents mpfind descending into level %d (trying to scan %s)\n", parent_depth, dir);
#endif
	return;
    }
    ++parent_depth;
    
    /* Change dir */
    if(chdir(dir) == -1)
    {
#ifdef DEBUG
	puts("DEBUG: Could not change directory");
#endif
	perror(dir);
	return;
    }
    
    dir_struct = opendir(dir);
    if(!dir_struct) perror(dir);

  /* Looping through every dir-entry and examine file or descend down further */
    while(1)
    {
	struct stat stats;
	
	entry = readdir(dir_struct);

	if(!entry)
	{
#ifdef DEBUG
	    puts("DEBUG: EOF");
#endif
	    /* perror(dir);*/
	    break;
	}
	
	/* skipping . and .. */
	if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
	{
	    continue;
	}
	
#ifdef DEBUG
	printf("DEBUG: Checking dir entry %s\n", entry->d_name);
#endif
	
      /* Get stats for entry */
	if(stat(entry->d_name, &stats) == -1)
	{
	    char *fullfilename = xmallocd(NAME_MAX + 1, "ignore");
#ifdef DEBUG
	    printf("DEBUG: Could not get stats for %s\n", entry->d_name);
#endif
	    if(dir[strlen(dir)-1] == '/') snprintf(fullfilename, NAME_MAX, "%s%s", dir, entry->d_name);
	    else snprintf(fullfilename, NAME_MAX, "%s/%s", dir, entry->d_name);
	    perror(fullfilename);
	    xfree(fullfilename);
	    continue;
	}

	/* init inode list if necessary and check if inode was allready scanned */
	if(!first_elem)
	{
	    /* First run, eh? */
#ifdef DEBUG
	    puts("DEBUG: Setting up list of scanned inodes");
#endif
	    last_elem = xmallocd(sizeof(proc_list), "ignore");
	    last_elem->inode = stats.st_ino;
	    last_elem->next = NULL;
	    first_elem = last_elem;
	}
	else
	{
	    proc_list *ptr;
	    int skip = 0;
	    
#ifdef DEBUG
	    assert(last_elem && first_elem);
#endif
	    
	    ptr = first_elem;
	    while(ptr)
	    {
		if(stats.st_ino == ptr->inode)
		{
#ifdef DEBUG
		    puts("DEBUG: Inode allready scanned, skipping");
#endif
		    skip = 1;
		    break;
		}
		ptr = (proc_list*)ptr->next;
	    }
	    if(skip) continue;
	    
	    /* Add this inode to the end of the list */
	    last_elem->next = xmallocd(sizeof(proc_list), "ignore");
	    last_elem = (proc_list*)last_elem->next;
	    last_elem->inode = stats.st_ino;
	    last_elem->next = NULL;
	}
	
	
	if(access(entry->d_name, F_OK | R_OK) == -1)
	{
	    char *fullfilename = xmallocd(NAME_MAX + 1, "ignore");
	    if(dir[strlen(dir)-1] == '/') snprintf(fullfilename, NAME_MAX, "%s%s", dir, entry->d_name);
	    else snprintf(fullfilename, NAME_MAX, "%s/%s", dir, entry->d_name);
	    perror(fullfilename);
	    continue;
	}
	
	
#ifdef DEBUG
	printf("DEBUG: Scanning inode %d\n", stats.st_ino);
#endif
	
	/* Checking stats and decide what to do */
	stats.st_mode &= S_IFMT;
	if((stats.st_mode & S_IFLNK) == S_IFLNK)
	{
#ifdef DEBUG
	    puts("DEBUG: inode is symbolic link, going to ignore for now..");
#endif
	    continue;
	}
	if((stats.st_mode & S_IFREG) == S_IFREG)
	{
#ifdef DEBUG
	    puts("DEBUG: inode is a regular file.");
#endif
	    
	    if(stats.st_size > 128)
	    {
		do_expr(dir, entry->d_name);
	    }
#ifdef DEBUG
	    else
	    {
		puts("DEBUG: File has invalid size to have a tag");
	    }
#endif
	}
	else if((stats.st_mode & S_IFDIR) == S_IFDIR)
	{
	    char *todesc;
#ifdef DEBUG
	    puts("DEBUG: inode is a directory");
#endif
	    if(access(entry->d_name, R_OK | X_OK) == -1) 
	    {
		perror(entry->d_name);
	    }
	    else
	    {
		todesc = xmallocd(NAME_MAX + 1, "ignore");
		memset(todesc, 0, NAME_MAX+1);
		if(dir[strlen(dir)-1] == '/') snprintf(todesc, NAME_MAX+1, "%s%s", dir, entry->d_name);
		else snprintf(todesc, NAME_MAX+1, "%s/%s", dir, entry->d_name);
		desc_dir(todesc, parent_depth) ;
		
		/* Change back to our dir */
		if(chdir(dir) == -1)
		{
#ifdef DEBUG
		    puts("DEBUG: Could not change directory");
#endif
		    perror(dir);
		    return;
		}
	    }
	}
    }
    
    closedir(dir_struct);
}