提取mp3文件ID3V2信息,通过curl命令发送请求,发布微博。ID3V2信息为UTF-16编码,需要在发送curl命令之前先转码成UTF-8
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
typedef struct id3_v2_head
{
char
Header[3];
//必须为"ID3"否则认为标签不存在
unsigned
char Ver;
//版本号ID3V2.3就记录3
unsigned
char
Revision;
//副版本号此版本记录为0
unsigned
char Flag;
//存放标志的字节,这个版本只定义了三位,稍后详细解说
unsigned
char Size[4];
//标签大小,包括标签头的10个字节和所有的标签帧的大小
}id3_v2_head_t;
typedef struct id3_v2_frame
{
char
FrameID[4]; //用四个字符标识一个帧,说明其内容,稍后有常用的标识对照表
unsigned
char Size[4];
//帧内容的大小,不包括帧头,不得小于1
unsigned
char Flags[2];
//存放标志,只定义了6位,稍后详细解说
}id3_v2_frame_t;
int get_id3_v2_info(char *string);
int publish_weibo(const char* hdr, const int info_idx[3][2]);
int convert_UTF16toUTF8(const char *input, int *insize, char *output, int *outsize);
int main(int argc,char **argv)
{
char
*filename;
if(argc!=2)
{
return -1;
}
filename =
argv[1];
get_id3_v2_info(filename);
return
0;
}
int get_id3_v2_info(char *string)
{
int
info_idx[3][2] = {0};
char
*filename=NULL;
int ret =
0;
id3_v2_head_t * id3_v2_head=NULL;
id3_v2_frame_t* id3_v2_frame=NULL;
int
fd;
char *hdr =
NULL;
long int
id3_v2_head_length=0;
long int
id3_v2_frame_length=0;
long int
total_read=0;
struct stat
sb;
char *info =
NULL;
filename=string;
fd =
open(filename, O_RDONLY);
if(fd==-1)
{
return -1;
}
fstat(fd,&sb);
hdr=(char*)mmap(NULL,sb.st_size,PROT_READ,MAP_PRIVATE,fd,0);
if(hdr==
MAP_FAILED)
{
return 0;
close(fd);
}
id3_v2_head=(id3_v2_head_t *)malloc(sizeof(id3_v2_head_t));
if(id3_v2_head==NULL)
{
munmap(hdr,sb.st_size);
close(fd);
return -1;
}
memcpy(id3_v2_head,hdr,sizeof(id3_v2_head_t));
if(strncmp(id3_v2_head->Header, "ID3", 3))
{
printf("have no id3 v2 info\n");
munmap(hdr,sb.st_size);
close(fd);
return -1;
}
printf("have id3 v2.%d.%d
info\n",id3_v2_head->Ver,id3_v2_head->Revision);
id3_v2_head_length =
(id3_v2_head->Size[0]&0x7F)*0x200000+(id3_v2_head->Size[1]&0x7F)*0x400+(id3_v2_head->Size[2]&0x7F)*0x80+(id3_v2_head->Size[3]&0x7F);
printf("head
length:%ld\n",id3_v2_head_length);
total_read
+= sizeof(id3_v2_head_t);
id3_v2_frame = (id3_v2_frame_t
*)malloc(sizeof(id3_v2_frame_t));
if(id3_v2_frame == NULL) {
close(fd);
munmap(hdr,sb.st_size);
return -1;
}
while(total_read < id3_v2_head_length)
{
memset(id3_v2_frame, 0, sizeof(id3_v2_frame_t));
memcpy((char*)id3_v2_frame, hdr+total_read,
sizeof(id3_v2_frame_t));
id3_v2_frame_length =
id3_v2_frame->Size[0]*0x100000000+id3_v2_frame->Size[1]*0x10000+id3_v2_frame->Size[2]*0x100+id3_v2_frame->Size[3];
if(id3_v2_frame_length == 0) {
printf("id3_v2_frame_length == 0\n");
break;
}
printf("size[0~3] = %d, %d, %d, %d, %d\n",
id3_v2_frame->Size[0],
id3_v2_frame->Size[1],
id3_v2_frame->Size[2],
id3_v2_frame->Size[3], id3_v2_frame_length);
total_read+=sizeof(id3_v2_frame_t);
info=(char*)malloc(id3_v2_frame_length);
if(info==NULL) {
printf("Failed to malloc.\n");
break;
}
memset(info, 0, id3_v2_frame_length);
memcpy(info, hdr+total_read+1, id3_v2_frame_length-1);
if (strcmp(id3_v2_frame->FrameID, "TPE1") == 0)
{
info_idx[0][0] = total_read+1;
info_idx[0][1] = id3_v2_frame_length-1;
} else if (strcmp(id3_v2_frame->FrameID, "TIT2") ==
0) {
info_idx[1][0] = total_read+1;
info_idx[1][1] = id3_v2_frame_length-1;
} else if (strcmp(id3_v2_frame->FrameID, "TALB") ==
0) {
info_idx[2][0] = total_read+1;
info_idx[2][1] = id3_v2_frame_length-1;
}
printf("%s:%s\n",id3_v2_frame->FrameID,info);
total_read += id3_v2_frame_length;
id3_v2_frame_length=0;
free(info);
}
ret =
publish_weibo(hdr, info_idx);
munmap(hdr,sb.st_size);
close(fd);
free(id3_v2_frame);
free(id3_v2_head);
return
ret;
}
int publish_weibo(const char* hdr, const int info_idx[3][2])
{
#if 1
// convert
UTF16 to UTF8
int insize =
0;
int outsize
= 0;
// publish
weibo
char *info =
NULL;
int ret =
0;
//const
char* s0 = "curl -k --header "Accept-Charset: utf-8" -F
access_token=2.00hone4D0ODM9ccc404334c1 37PJFB -F status="我正在听
";
const char*
s0 = "curl -k -F access_token=2.00hone4D0ODM9ccc404334c1 37PJFB -F
status="我正在听 ";
const char*
s2 = "" -F visible!=0 -F pic=@/home/zhangchunyan/tmp/test.jpg
https://upload.api.weibo.com/2/statuses/upload.json";
int offset =
0;
int length =
info_idx[0][1] + info_idx[1][1] + info_idx[2][1];
if (length
== 0) {
printf("info_idx[0][1] + info_idx[1][1] + info_idx[2][1] ==
0\n");
return -1;
}
length +=
strlen(s0)+strlen(s2)+128;
info=(char*)malloc(length);
if(info==NULL) {
printf("Failed to malloc.\n");
return -1;
}
memset(info,
0, length);
memcpy(info,
s0, strlen(s0));
offset +=
strlen(s0);
insize =
info_idx[0][1];
outsize =
info_idx[0][1]*2;
printf("outsize=%d\n", outsize);
convert_UTF16toUTF8(hdr+info_idx[0][0], &insize,
info+offset, &outsize);
printf("1:%s
outsize=%d\n", info+offset, outsize);
//for(int i
= 0; i < info_idx[0][1] - outsize+10; i++) {
//printf("%x ", *(info+offset+i));
//if (i == 10) printf("\n");
//}
printf("\n");
offset +=
outsize;
offset +=
sprintf(info+offset, "《");
insize =
info_idx[1][1];
outsize =
info_idx[1][1]*2;
printf("outsize=%d\n", outsize);
convert_UTF16toUTF8(hdr+info_idx[1][0], &insize,
info+offset, &outsize);
printf("2:%s
outsize=%d\n", info+offset, outsize);
//for(int i
= 0; i < info_idx[1][1] - outsize+10; i++) {
//printf("%x ", *(info+offset+i));
//if (i == 10) printf("\n");
//}
printf("\n");
offset +=
outsize;
offset +=
sprintf(info+offset, "》(分享自PIA)");
memcpy(info+offset, s2, strlen(s2));
printf("3:%s\n", info);
ret =
system(info);
free(info);
#endif
return
ret;
}
int convert_UTF16toUTF8(const char *input, int *insize, char *output, int *outsize)
{
char*
outstart = output;
const char*
processed = input;
char* outend
= output + *outsize;
unsigned
short* in = (unsigned short*) input;
unsigned
short* inend;
unsigned int
c, d, inlen;
char
*tmp;
int
bits;
int
isLittleEndian = 1;
if((*insize
% 2) == 1) (*insize)--;
inlen =
*insize / 2;
inend = in +
inlen;
while((in
< inend) && (output
- outstart + 5 < *outsize))
{
if(isLittleEndian)
{
c= *in++;
}
else
{
tmp = (char *) in;
c = *tmp++;
c = c | (((unsigned int)*tmp) <<
8);
in++;
}
if((c & 0xFC00) == 0xD800)
{
if(in >= inend) break;
if(isLittleEndian) {d = *in++;}
else
{
tmp = (char *) in;
d = *tmp++;
d = d | (((unsigned int)*tmp) <<
8);
in++;
}
if((d & 0xFC00) == 0xDC00)
{
c &= 0x03FF;
c <<= 10;
c |= d & 0x03FF;
c += 0x10000;
}
else
{
*outsize = output - outstart;
*insize = processed - input;
return -1;
}
}
if(output >= outend) break;
if (c < 0x80) {*output++ = c; bits= -6;}
else if(c < 0x800) {*output++ = ((c
>> 6) & 0x1F) | 0xC0;
bits= 0;}
else if(c < 0x10000) {*output++ = ((c
>> 12) & 0x0F) |
0xE0; bits= 6;}
else {*output++ = ((c >> 18)
& 0x07) | 0xF0; bits= 12;}
for(; bits >= 0; bits-= 6)
{
if (output >= outend)
break;
*output++ = ((c >> bits)
& 0x3F) | 0x80;
}
processed = (const char*) in;
}
*outsize =
output - outstart;
*insize =
processed - input;
return
0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
typedef struct id3_v2_head
{
}id3_v2_head_t;
typedef struct id3_v2_frame
{
}id3_v2_frame_t;
int get_id3_v2_info(char *string);
int publish_weibo(const char* hdr, const int info_idx[3][2]);
int convert_UTF16toUTF8(const char *input, int *insize, char *output, int *outsize);
int main(int argc,char **argv)
{
}
int get_id3_v2_info(char *string)
{
}
int publish_weibo(const char* hdr, const int info_idx[3][2])
{
}
int convert_UTF16toUTF8(const char *input, int *insize, char *output, int *outsize)
{
}
本文介绍了一个C语言程序,该程序用于从MP3文件中提取ID3 V2元数据,并将其转换为UTF-8编码,最终通过curl命令发布到微博。涉及的技术包括文件读取、内存映射、元数据解析及网络请求。

6996

被折叠的 条评论
为什么被折叠?



