ali@0
|
1 |
/*
|
ali@0
|
2 |
* This program converts an attached file (which has previously been
|
ali@0
|
3 |
* downloaded from sourceforge) into bugzilla-style XML.
|
ali@0
|
4 |
*/
|
ali@0
|
5 |
|
ali@0
|
6 |
#include <stdlib.h>
|
ali@0
|
7 |
#include <stdio.h>
|
ali@0
|
8 |
#include <string.h>
|
ali@0
|
9 |
#ifdef __linux__
|
ali@0
|
10 |
#include <getopt.h>
|
ali@0
|
11 |
#endif
|
ali@0
|
12 |
|
ali@0
|
13 |
#ifdef __linux__
|
ali@0
|
14 |
static struct option long_options[] = {
|
ali@0
|
15 |
{"type", 1, 0, 't'},
|
ali@0
|
16 |
{"id", 1, 0, 'i'},
|
ali@0
|
17 |
{"patch", 0, 0, 'p'},
|
ali@0
|
18 |
{0, 0, 0, 0}
|
ali@0
|
19 |
};
|
ali@0
|
20 |
|
ali@0
|
21 |
static char *long_option_str(char opt)
|
ali@0
|
22 |
{
|
ali@0
|
23 |
int i;
|
ali@0
|
24 |
static char buf[100];
|
ali@0
|
25 |
for(i=0;long_options[i].name;i++)
|
ali@0
|
26 |
if (long_options[i].val==opt)
|
ali@0
|
27 |
{
|
ali@0
|
28 |
sprintf(buf,", --%s",long_options[i].name);
|
ali@0
|
29 |
return buf;
|
ali@0
|
30 |
}
|
ali@0
|
31 |
return "";
|
ali@0
|
32 |
}
|
ali@0
|
33 |
#else
|
ali@0
|
34 |
#define long_option_str(opt) ""
|
ali@0
|
35 |
#endif
|
ali@0
|
36 |
|
ali@0
|
37 |
usage()
|
ali@0
|
38 |
{
|
ali@0
|
39 |
fprintf(stderr,"Usage: xml_attached_file [OPTION] file\n");
|
ali@0
|
40 |
fprintf(stderr,"\n");
|
ali@0
|
41 |
fprintf(stderr," -t%s=MIME-type MIME type to use\n",
|
ali@0
|
42 |
long_option_str('t'));
|
ali@0
|
43 |
fprintf(stderr," -i%s=ID Attachment ID to use\n",
|
ali@0
|
44 |
long_option_str('i'));
|
ali@0
|
45 |
fprintf(stderr," -p%s Mark attachment as a patch\n",
|
ali@0
|
46 |
long_option_str('p'));
|
ali@0
|
47 |
exit(1);
|
ali@0
|
48 |
}
|
ali@0
|
49 |
|
ali@0
|
50 |
/* Note that we limit line lengths to 76 characters following RFC 2045
|
ali@0
|
51 |
* (bugzilla uses MIME::Base64). This isn't strictly compliant with RFC 4648.
|
ali@0
|
52 |
*/
|
ali@0
|
53 |
static void base64_encode(FILE *in,FILE *out)
|
ali@0
|
54 |
{
|
ali@0
|
55 |
int ng=0; /* 76 characters == 19 groups */
|
ali@0
|
56 |
size_t nb;
|
ali@0
|
57 |
unsigned char bytes[3];
|
ali@0
|
58 |
const char alphabet[64]=
|
ali@0
|
59 |
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
ali@0
|
60 |
while ((nb=fread(bytes,1,3,in))==3)
|
ali@0
|
61 |
{
|
ali@0
|
62 |
if (ng++>=19)
|
ali@0
|
63 |
{
|
ali@0
|
64 |
putc('\n',out);
|
ali@0
|
65 |
ng=1;
|
ali@0
|
66 |
}
|
ali@0
|
67 |
putc(alphabet[bytes[0]>>2],out);
|
ali@0
|
68 |
putc(alphabet[(bytes[0]<<4|bytes[1]>>4)&0x3F],out);
|
ali@0
|
69 |
putc(alphabet[(bytes[1]<<2|bytes[2]>>6)&0x3F],out);
|
ali@0
|
70 |
putc(alphabet[bytes[2]&0x3F],out);
|
ali@0
|
71 |
}
|
ali@0
|
72 |
if (nb)
|
ali@0
|
73 |
{
|
ali@0
|
74 |
if (ng>=19)
|
ali@0
|
75 |
putc('\n',out);
|
ali@0
|
76 |
putc(alphabet[bytes[0]>>2],out);
|
ali@0
|
77 |
if (nb==2)
|
ali@0
|
78 |
{
|
ali@0
|
79 |
putc(alphabet[(bytes[0]<<4|bytes[1]>>4)&0x3F],out);
|
ali@0
|
80 |
putc(alphabet[bytes[1]<<2&0x3F],out);
|
ali@0
|
81 |
}
|
ali@0
|
82 |
else
|
ali@0
|
83 |
{
|
ali@0
|
84 |
putc(alphabet[bytes[0]<<4&0x3F],out);
|
ali@0
|
85 |
putc('=',out);
|
ali@0
|
86 |
}
|
ali@0
|
87 |
putc('=',out);
|
ali@0
|
88 |
}
|
ali@0
|
89 |
}
|
ali@0
|
90 |
|
ali@0
|
91 |
int main(int argc,char **argv)
|
ali@0
|
92 |
{
|
ali@0
|
93 |
int c;
|
ali@0
|
94 |
FILE *fp;
|
ali@0
|
95 |
unsigned long id=0;
|
ali@0
|
96 |
int ispatch=0;
|
ali@0
|
97 |
char *type=NULL;
|
ali@0
|
98 |
for(;;)
|
ali@0
|
99 |
{
|
ali@0
|
100 |
#ifdef __linux__
|
ali@0
|
101 |
int option_index=0;
|
ali@0
|
102 |
c=getopt_long(argc,argv,"t:i:p",long_options,&option_index);
|
ali@0
|
103 |
#else
|
ali@0
|
104 |
c=getopt(argc,argv,"t:i:p");
|
ali@0
|
105 |
#endif
|
ali@0
|
106 |
if (c<0)
|
ali@0
|
107 |
break;
|
ali@0
|
108 |
switch(c)
|
ali@0
|
109 |
{
|
ali@0
|
110 |
case 't':
|
ali@0
|
111 |
type=optarg;
|
ali@0
|
112 |
break;
|
ali@0
|
113 |
case 'i':
|
ali@0
|
114 |
id=strtoul(optarg,NULL,10);
|
ali@0
|
115 |
break;
|
ali@0
|
116 |
case 'p':
|
ali@0
|
117 |
ispatch=1;
|
ali@0
|
118 |
break;
|
ali@0
|
119 |
default:
|
ali@0
|
120 |
usage();
|
ali@0
|
121 |
}
|
ali@0
|
122 |
}
|
ali@0
|
123 |
if (optind<argc)
|
ali@0
|
124 |
{
|
ali@0
|
125 |
fp=fopen(argv[optind],"rb");
|
ali@0
|
126 |
if (!fp)
|
ali@0
|
127 |
{
|
ali@0
|
128 |
perror(argv[optind]);
|
ali@0
|
129 |
exit(1);
|
ali@0
|
130 |
}
|
ali@0
|
131 |
}
|
ali@0
|
132 |
else
|
ali@0
|
133 |
fp=stdin;
|
ali@0
|
134 |
printf("<attachment ispatch=\"%d\">\n",ispatch);
|
ali@0
|
135 |
if (id)
|
ali@0
|
136 |
printf(" <attachid>%lu</attachid>\n",id);
|
ali@0
|
137 |
if (type)
|
ali@0
|
138 |
printf(" <type>%s</type>\n",type);
|
ali@0
|
139 |
printf(" <data encoding=\"base64\">\n");
|
ali@0
|
140 |
base64_encode(fp,stdout);
|
ali@0
|
141 |
printf("\n </data>\n");
|
ali@0
|
142 |
printf("</attachment>\n");
|
ali@0
|
143 |
exit(0);
|
ali@0
|
144 |
}
|