選択できるのは25トピックまでです。
トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
130 行
2.7 KiB
130 行
2.7 KiB
#include <iconv.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
|
#include "blaze822.h" |
|
|
|
int |
|
blaze822_mime2231_parameter(char *s, char *name, |
|
char *dst, size_t dlen, char *tgtenc) |
|
{ |
|
static signed char hex[] = { |
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, |
|
-1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
|
-1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 |
|
}; |
|
|
|
int i = 0; |
|
char namenum[64]; |
|
|
|
char *srcenc = 0; |
|
|
|
char *dststart = dst; |
|
char *dstend = dst + dlen; |
|
|
|
char *sbuf, *ebuf; |
|
|
|
snprintf(namenum, sizeof namenum, "%s*", name); |
|
if (blaze822_mime_parameter(s, namenum, &sbuf, &ebuf)) { |
|
i = 100; |
|
goto found_extended; |
|
} |
|
if (blaze822_mime_parameter(s, name, &sbuf, &ebuf)) { |
|
i = 100; |
|
goto found_plain; |
|
} |
|
|
|
while (i < 100) { |
|
snprintf(namenum, sizeof namenum, "%s*%d*", name, i); |
|
if (blaze822_mime_parameter(s, namenum, &sbuf, &ebuf)) { |
|
found_extended: |
|
// decode extended |
|
if (i == 0 || i == 100) { // extended-initial-value |
|
char *encstart = sbuf; |
|
sbuf = strchr(sbuf, '\''); |
|
if (!sbuf) |
|
return 0; |
|
srcenc = strndup(encstart, sbuf - encstart); |
|
if (!srcenc) |
|
return 0; |
|
sbuf = strchr(sbuf+1, '\''); |
|
if (!sbuf) { |
|
free(srcenc); |
|
return 0; |
|
} |
|
sbuf++; |
|
} |
|
while (sbuf < ebuf && dst < dstend) { |
|
if (sbuf[0] == '%') { |
|
unsigned char c1 = sbuf[1]; |
|
unsigned char c2 = sbuf[2]; |
|
if (c1 < 127 && c2 < 127 && |
|
hex[c1] > -1 && hex[c2] > -1) { |
|
*dst++ = (hex[c1] << 4) | hex[c2]; |
|
sbuf += 3; |
|
} else { |
|
*dst++ = *sbuf++; |
|
} |
|
} else { |
|
*dst++ = *sbuf++; |
|
} |
|
} |
|
*dst = 0; |
|
} else { |
|
namenum[strlen(namenum) - 1] = 0; // strip last * |
|
if (blaze822_mime_parameter(s, namenum, &sbuf, &ebuf)) { |
|
found_plain: |
|
// copy plain |
|
if (ebuf - sbuf < dstend - dst) { |
|
memcpy(dst, sbuf, ebuf - sbuf); |
|
dst += ebuf - sbuf; |
|
} |
|
*dst = 0; |
|
} else { |
|
break; |
|
} |
|
} |
|
i++; |
|
} |
|
|
|
if (i <= 0) |
|
return 0; |
|
|
|
if (!srcenc) |
|
return 1; |
|
|
|
iconv_t ic = iconv_open(tgtenc, srcenc); |
|
free(srcenc); |
|
if (ic == (iconv_t)-1) |
|
return 1; |
|
|
|
size_t tmplen = dlen; |
|
char *tmp = malloc(tmplen); |
|
if (!tmp) |
|
return 1; |
|
char *tmpend = tmp; |
|
|
|
size_t dstlen = dst - dststart; |
|
dst = dststart; |
|
|
|
size_t r = iconv(ic, &dst, &dstlen, &tmpend, &tmplen); |
|
if (r == (size_t)-1) { |
|
free(tmp); |
|
return 1; |
|
} |
|
|
|
iconv_close(ic); |
|
|
|
// copy back |
|
memcpy(dststart, tmp, tmpend - tmp); |
|
dststart[tmpend - tmp] = 0; |
|
free(tmp); |
|
|
|
return 1; |
|
}
|
|
|