1 /* $Id: mailcap.c,v 1.13 2006/08/07 03:10:26 ukai Exp $ */
9 static struct mailcap DefaultMailcap[] = {
10 {"image/*", DEF_IMAGE_VIEWER " %s", 0, NULL, NULL, NULL}, /* */
11 {"audio/basic", DEF_AUDIO_PLAYER " %s", 0, NULL, NULL, NULL},
12 {NULL, NULL, 0, NULL, NULL, NULL}
15 static TextList *mailcap_list;
16 static struct mailcap **UserMailcap;
19 mailcapMatch(struct mailcap *mcap, char *type)
21 char *cap = mcap->type, *p;
23 for (p = cap; *p != '/'; p++) {
24 if (TOLOWER(*p) != TOLOWER(*type))
32 if (mcap->flags & MAILCAP_HTMLOUTPUT)
39 if (TOLOWER(*p) != TOLOWER(*type))
50 searchMailcap(struct mailcap *table, char *type)
53 struct mailcap *mcap = NULL;
58 for (; table->type; table++) {
59 i = mailcapMatch(table, type);
63 unquote_mailcap(table->test, type, NULL, NULL, NULL);
64 if (system(command->ptr) != 0)
75 matchMailcapAttr(char *p, char *attr, int len, Str *value)
80 if (strncasecmp(p, attr, len) == 0) {
89 while (*p && (quoted || *p != ';')) {
90 if (quoted || !IS_SPACE(*p))
96 Strcat_char(*value, *p);
100 Strshrink(*value, p - q - 1);
105 if (*p == '\0' || *p == ';') {
114 extractMailcapEntry(char *mcap_entry, struct mailcap *mcap)
121 bzero(mcap, sizeof(struct mailcap));
125 for (j = 0; p[j] && p[j] != ';'; j++) {
129 mcap->type = allocStr(p, (k >= 0) ? k + 1 : j);
137 for (j = 0; p[j] && (quoted || p[j] != ';'); j++) {
138 if (quoted || !IS_SPACE(p[j]))
142 else if (p[j] == '\\')
145 mcap->viewer = allocStr(p, (k >= 0) ? k + 1 : j);
151 if (matchMailcapAttr(p, "needsterminal", 13, NULL)) {
152 mcap->flags |= MAILCAP_NEEDSTERMINAL;
154 else if (matchMailcapAttr(p, "copiousoutput", 13, NULL)) {
155 mcap->flags |= MAILCAP_COPIOUSOUTPUT;
157 else if (matchMailcapAttr(p, "x-htmloutput", 12, NULL) ||
158 matchMailcapAttr(p, "htmloutput", 10, NULL)) {
159 mcap->flags |= MAILCAP_HTMLOUTPUT;
161 else if (matchMailcapAttr(p, "test", 4, &tmp)) {
162 mcap->test = allocStr(tmp->ptr, tmp->length);
164 else if (matchMailcapAttr(p, "nametemplate", 12, &tmp)) {
165 mcap->nametemplate = allocStr(tmp->ptr, tmp->length);
167 else if (matchMailcapAttr(p, "edit", 4, &tmp)) {
168 mcap->edit = allocStr(tmp->ptr, tmp->length);
171 while (*p && (quoted || *p != ';')) {
182 static struct mailcap *
183 loadMailcap(char *filename)
188 struct mailcap *mcap;
190 f = fopen(expandPath(filename), "r");
194 while (tmp = Strfgets(f), tmp->length > 0) {
195 if (tmp->ptr[0] != '#')
200 mcap = New_N(struct mailcap, n + 1);
202 while (tmp = Strfgets(f), tmp->length > 0) {
203 if (tmp->ptr[0] == '#')
206 while (IS_SPACE(Strlastchar(tmp)))
208 if (Strlastchar(tmp) == '\\') {
211 Strcat(tmp, Strfgets(f));
214 if (extractMailcapEntry(tmp->ptr, &mcap[i]))
217 bzero(&mcap[i], sizeof(struct mailcap));
228 if (non_null(mailcap_files))
229 mailcap_list = make_domain_list(mailcap_files);
232 if (mailcap_list == NULL)
234 UserMailcap = New_N(struct mailcap *, mailcap_list->nitem);
235 for (i = 0, tl = mailcap_list->first; tl; i++, tl = tl->next)
236 UserMailcap[i] = loadMailcap(tl->ptr);
241 acceptableMimeTypes()
243 static Str types = NULL;
252 /* generate acceptable media types */
254 mhash = newHash_si(16); /* XXX */
255 /* pushText(l, "text"); */
256 putHash_si(mhash, "text", 1);
257 pushText(l, "image");
258 putHash_si(mhash, "image", 1);
259 for (i = 0; i < mailcap_list->nitem; i++) {
260 struct mailcap *mp = UserMailcap[i];
264 for (; mp->type; mp++) {
265 p = strchr(mp->type, '/');
268 mt = allocStr(mp->type, p - mp->type);
269 if (getHash_si(mhash, mt, 0) == 0) {
271 putHash_si(mhash, mt, 1);
276 Strcat_charp(types, "text/html, text/*;q=0.5");
277 while ((p = popText(l)) != NULL) {
278 Strcat_charp(types, ", ");
279 Strcat_charp(types, p);
280 Strcat_charp(types, "/*");
286 searchExtViewer(char *type)
291 if (mailcap_list == NULL)
292 goto no_user_mailcap;
294 for (i = 0; i < mailcap_list->nitem; i++) {
295 if ((p = searchMailcap(UserMailcap[i], type)) != NULL)
300 return searchMailcap(DefaultMailcap, type);
308 #define MCF_SQUOTED (1 << 0)
309 #define MCF_DQUOTED (1 << 1)
312 quote_mailcap(char *s, int flag)
326 if (!(flag & MCF_SQUOTED))
327 Strcat_char(d, '\\');
332 if (flag & MCF_SQUOTED) {
333 Strcat_charp(d, "'\\''");
337 if (!flag && !IS_ALNUM(*s))
338 Strcat_char(d, '\\');
352 unquote_mailcap_loop(char *qstr, char *type, char *name, char *attr,
353 int *mc_stat, int flag0)
355 Str str, tmp, test, then;
357 int status = MC_NORMAL, prev_status = MC_NORMAL, sp = 0, flag;
366 tmp = test = then = NULL;
368 for (flag = flag0, p = qstr; *p; p++) {
369 if (status == MC_QUOTED) {
370 if (prev_status == MC_PREC2)
371 Strcat_char(tmp, *p);
373 Strcat_char(str, *p);
374 status = prev_status;
377 else if (*p == '\\') {
378 prev_status = status;
389 if (!flag0 && flag & MCF_SQUOTED)
390 flag &= ~MCF_SQUOTED;
394 else if (*p == '"') {
395 if (!flag0 && flag & MCF_DQUOTED)
396 flag &= ~MCF_DQUOTED;
400 Strcat_char(str, *p);
408 Strcat_charp(str, quote_mailcap(name, flag)->ptr);
410 *mc_stat |= MCSTAT_REPNAME;
415 Strcat_charp(str, quote_mailcap(type, flag)->ptr);
417 *mc_stat |= MCSTAT_REPTYPE;
423 else if (*p == '{') {
428 else if (*p == '%') {
429 Strcat_char(str, *p);
433 if (sp > 0 || *p == '{') {
434 Strcat_char(tmp, *p);
447 else if (*p == '}') {
449 if (attr && (q = strcasestr(attr, tmp->ptr)) != NULL &&
450 (q == attr || IS_SPACE(*(q - 1)) || *(q - 1) == ';') &&
451 matchattr(q, tmp->ptr, tmp->length, &tmp)) {
452 Strcat_charp(str, quote_mailcap(tmp->ptr, flag)->ptr);
454 *mc_stat |= MCSTAT_REPPARAM;
459 Strcat_char(tmp, *p);
468 unquote_mailcap(char *qstr, char *type, char *name, char *attr, int *mc_stat)
470 return unquote_mailcap_loop(qstr, type, name, attr, mc_stat, 0);