1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: rfc2231.c 1012 2008-03-26 00:44:22Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2013-2021 Eduardo Chappa
8 * Copyright 2006-2008 University of Washington
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 #include "../pith/headers.h"
20 #include "../pith/rfc2231.h"
21 #include "../pith/mimedesc.h"
22 #include "../pith/state.h"
23 #include "../pith/conf.h"
24 #include "../pith/store.h"
25 #include "../pith/status.h"
26 #include "../pith/send.h"
27 #include "../pith/string.h"
31 * * * * * * * * * RFC 2231 support routines * * * * * * * *
36 #define RFC2231_MAX 64
40 rfc2231_get_param(PARAMETER
*parms
, char *name
,
41 char **charset
, char **lang
)
44 int decode
= 0, name_len
, i
;
47 name_len
= strlen(name
);
48 for(; parms
; parms
= parms
->next
)
49 if(!struncmp(name
, parms
->attribute
, name_len
)){
50 if(parms
->attribute
[name_len
] == '*'){
51 for(p
= &parms
->attribute
[name_len
+ 1], n
= 0; *(p
+n
); n
++)
54 decode
= *(p
+ n
- 1) == '*';
56 if(isdigit((unsigned char) *p
)){
57 char *pieces
[RFC2231_MAX
];
60 memset(pieces
, 0, RFC2231_MAX
* sizeof(char *));
65 n
= (n
* 10) + (*p
- '0');
66 while(isdigit(*++p
) && n
< RFC2231_MAX
);
69 pieces
[n
] = parms
->value
;
74 q_status_message1(SM_ORDER
| SM_DING
, 0, 3,
75 "Invalid attachment parameter segment number: %.25s",
77 return(NULL
); /* Too many segments! */
80 while((parms
= parms
->next
) != NULL
)
81 if(!struncmp(name
, parms
->attribute
, name_len
)){
82 if(*(p
= &parms
->attribute
[name_len
]) == '*'
83 && isdigit((unsigned char) *++p
))
86 return(NULL
); /* missing segment no.! */
90 for(i
= len
= 0; i
<= count
; i
++)
92 len
+= strlen(pieces
[i
]);
94 q_status_message1(SM_ORDER
| SM_DING
, 0, 3,
95 "Missing attachment parameter sequence: %.25s",
98 return(NULL
); /* hole! */
101 buf
= (char *) fs_get((len
+ 1) * sizeof(char));
103 for(i
= len
= 0; i
<= count
; i
++){
104 if((n
= *(p
= pieces
[i
]) == '\"') != 0) /* quoted? */
107 while(*p
&& !(n
&& *p
== '\"' && !*(p
+1)))
114 buf
= cpystr(parms
->value
);
116 /* Do any RFC 2231 decoding? */
118 char *converted
= NULL
, cs
[1000];
123 if((p
= strchr(buf
, '\'')) != NULL
){
126 strncpy(cs
, buf
, sizeof(cs
));
127 cs
[sizeof(cs
)-1] = '\0';
130 *charset
= cpystr(cs
);
132 if((p
= strchr(&buf
[n
], '\'')) != NULL
){
143 /* Suck out the charset & lang while decoding hex */
145 for(i
= 0; (buf
[i
] = *p
) != '\0'; i
++)
146 if(*p
++ == '%' && isxpair(p
)){
152 fs_give((void **) &buf
); /* problems!?! */
155 * Callers will expect the returned value to be UTF-8
156 * text, so we may need to translate here.
159 converted
= convert_to_utf8(buf
, cs
, 0);
161 if(converted
&& converted
!= buf
){
162 fs_give((void **) &buf
);
170 return(cpystr(parms
->value
? parms
->value
: ""));
178 rfc2231_output(STORE_S
*so
, char *attrib
, char *value
, char *specials
, char *charset
)
180 int i
, line
= 0, encode
= 0, quote
= 0;
183 * scan for hibit first since encoding clue has to
184 * come on first line if any parms are broken up...
186 for(i
= 0; value
&& value
[i
]; i
++)
193 if(!(value
&& value
[i
]) || i
> 80){ /* flush! */
194 if((line
++ && !so_puts(so
, ";\015\012 "))
195 || !so_puts(so
, attrib
))
199 if(((value
[i
] || line
> 1) /* more lines or already lines */
200 && !(so_writec('*', so
)
201 && so_puts(so
, int2string(line
- 1))))
202 || (encode
&& !so_writec('*', so
))
203 || !so_writec('=', so
)
204 || (quote
&& !so_writec('\"', so
))
205 || ((line
== 1 && encode
)
206 && !(so_puts(so
, charset
? charset
: UNKNOWN_CHARSET
)
207 && so_puts(so
, "''"))))
217 if(!(so_writec('%', so
) && so_puts(so
, tmp
)))
220 else if(((*value
== '\\' || *value
== '\"')
221 && !so_writec('\\', so
))
222 || !so_writec(*value
, so
))
228 if(quote
&& !so_writec('\"', so
))
231 if(*value
) /* more? */
232 i
= quote
= 0; /* reset! */
234 return(1); /* done! */
240 if(!quote
&& strchr(specials
, value
[i
]))
247 rfc2231_newparmlist(PARAMETER
*params
)
249 PARMLIST_S
*p
= NULL
;
252 p
= (PARMLIST_S
*) fs_get(sizeof(PARMLIST_S
));
253 memset(p
, 0, sizeof(PARMLIST_S
));
262 rfc2231_free_parmlist(PARMLIST_S
**p
)
266 fs_give((void **) &(*p
)->value
);
268 mail_free_body_parameter(&(*p
)->seen
);
269 fs_give((void **) p
);
275 rfc2231_list_params(PARMLIST_S
*plist
)
277 PARAMETER
*pp
, **ppp
;
281 fs_give((void **) &plist
->value
);
283 for(pp
= plist
->list
; pp
; pp
= pp
->next
){
285 for(i
= 0; i
< 32; i
++)
286 if(!(plist
->attrib
[i
] = pp
->attribute
[i
]) || pp
->attribute
[i
] == '*'){
287 plist
->attrib
[i
] = '\0';
289 for(ppp
= &plist
->seen
;
290 *ppp
&& strucmp((*ppp
)->attribute
, plist
->attrib
);
295 plist
->list
= pp
->next
;
296 *ppp
= mail_newbody_parameter(); /* add to seen list */
297 (*ppp
)->attribute
= cpystr(plist
->attrib
);
298 plist
->value
= parameter_val(pp
,plist
->attrib
);
306 q_status_message1(SM_ORDER
| SM_DING
, 0, 3,
307 "Overly long attachment parameter ignored: %.25s...",