#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#ifndef NO_ICONV
#include <iconv.h>
-
-#ifdef NO_STRCASESTR
-extern char *gitstrcasestr(const char *haystack, const char *needle);
#endif
+#include "git-compat-util.h"
+#include "cache.h"
static FILE *cmitmsg, *patchfile;
static int keep_subject = 0;
-static int metainfo_utf8 = 0;
+static char *metainfo_charset = NULL;
static char line[1000];
static char date[1000];
static char name[1000];
return name;
}
+static int bogus_from(char *line)
+{
+ /* John Doe <johndoe> */
+ char *bra, *ket, *dst, *cp;
+
+ /* This is fallback, so do not bother if we already have an
+ * e-mail address.
+ */
+ if (*email)
+ return 0;
+
+ bra = strchr(line, '<');
+ if (!bra)
+ return 0;
+ ket = strchr(bra, '>');
+ if (!ket)
+ return 0;
+
+ for (dst = email, cp = bra+1; cp < ket; )
+ *dst++ = *cp++;
+ *dst = 0;
+ for (cp = line; isspace(*cp); cp++)
+ ;
+ for (bra--; isspace(*bra); bra--)
+ *bra = 0;
+ cp = sanity_check(cp, email);
+ strcpy(name, cp);
+ return 1;
+}
+
static int handle_from(char *line)
{
char *at = strchr(line, '@');
char *dst;
if (!at)
- return 0;
+ return bogus_from(line);
/*
* If we already have one email, don't take any confusing lines
return ~0;
}
-static int decode_q_segment(char *in, char *ot, char *ep)
+static int decode_q_segment(char *in, char *ot, char *ep, int rfc2047)
{
int c;
while ((c = *in++) != 0 && (in <= ep)) {
if (d == '\n' || !d)
break; /* drop trailing newline */
*ot++ = ((hexval(d) << 4) | hexval(*in++));
+ continue;
}
- else
- *ot++ = c;
+ if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */
+ c = 0x20;
+ *ot++ = c;
}
*ot = 0;
return 0;
static void convert_to_utf8(char *line, char *charset)
{
- if (*charset) {
- char *in, *out;
- size_t insize, outsize, nrc;
- char outbuf[4096]; /* cheat */
- iconv_t conv = iconv_open("utf-8", charset);
-
- if (conv == (iconv_t) -1) {
- fprintf(stderr, "cannot convert from %s to utf-8\n",
- charset);
+#ifndef NO_ICONV
+ char *in, *out;
+ size_t insize, outsize, nrc;
+ char outbuf[4096]; /* cheat */
+ static char latin_one[] = "latin1";
+ char *input_charset = *charset ? charset : latin_one;
+ iconv_t conv = iconv_open(metainfo_charset, input_charset);
+
+ if (conv == (iconv_t) -1) {
+ static int warned_latin1_once = 0;
+ if (input_charset != latin_one) {
+ fprintf(stderr, "cannot convert from %s to %s\n",
+ input_charset, metainfo_charset);
*charset = 0;
- return;
}
- in = line;
- insize = strlen(in);
- out = outbuf;
- outsize = sizeof(outbuf);
- nrc = iconv(conv, &in, &insize, &out, &outsize);
- iconv_close(conv);
- if (nrc == (size_t) -1)
- return;
- *out = 0;
- strcpy(line, outbuf);
+ else if (!warned_latin1_once) {
+ warned_latin1_once = 1;
+ fprintf(stderr, "tried to convert from %s to %s, "
+ "but your iconv does not work with it.\n",
+ input_charset, metainfo_charset);
+ }
+ return;
}
+ in = line;
+ insize = strlen(in);
+ out = outbuf;
+ outsize = sizeof(outbuf);
+ nrc = iconv(conv, &in, &insize, &out, &outsize);
+ iconv_close(conv);
+ if (nrc == (size_t) -1)
+ return;
+ *out = 0;
+ strcpy(line, outbuf);
+#endif
}
static void decode_header_bq(char *it)
sz = decode_b_segment(cp + 3, piecebuf, ep);
break;
case 'q':
- sz = decode_q_segment(cp + 3, piecebuf, ep);
+ sz = decode_q_segment(cp + 3, piecebuf, ep, 1);
break;
}
if (sz < 0)
return;
- if (metainfo_utf8)
+ if (metainfo_charset)
convert_to_utf8(piecebuf, charset_q);
strcpy(out, piecebuf);
out += strlen(out);
switch (transfer_encoding) {
case TE_QP:
ep = line + strlen(line);
- decode_q_segment(line, line, ep);
+ decode_q_segment(line, line, ep, 0);
break;
case TE_BASE64:
ep = line + strlen(line);
* normalize the log message to UTF-8.
*/
decode_transfer_encoding(line);
- if (metainfo_utf8)
+ if (metainfo_charset)
convert_to_utf8(line, charset);
fputs(line, cmitmsg);
} while (fgets(line, sizeof(line), stdin) != NULL);
if (!len) {
if (handle_multipart_one_part() < 0)
return;
+ /* Reset per part headers */
+ transfer_encoding = TE_DONTCARE;
+ charset[0] = 0;
}
else
check_subheader_line(line, len);
}
static const char mailinfo_usage[] =
- "git-mailinfo [-k] [-u] msg patch <mail >info";
-
-static void usage(void) {
- fprintf(stderr, "%s\n", mailinfo_usage);
- exit(1);
-}
+ "git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info";
int main(int argc, char **argv)
{
+ /* NEEDSWORK: might want to do the optional .git/ directory
+ * discovery
+ */
+ git_config(git_default_config);
+
while (1 < argc && argv[1][0] == '-') {
if (!strcmp(argv[1], "-k"))
keep_subject = 1;
else if (!strcmp(argv[1], "-u"))
- metainfo_utf8 = 1;
+ metainfo_charset = git_commit_encoding;
+ else if (!strncmp(argv[1], "--encoding=", 11))
+ metainfo_charset = argv[1] + 11;
else
- usage();
+ usage(mailinfo_usage);
argc--; argv++;
}
if (argc != 3)
- usage();
+ usage(mailinfo_usage);
cmitmsg = fopen(argv[1], "w");
if (!cmitmsg) {
perror(argv[1]);