#include "intl.h"
#include "utils.h"
#include "socket.h"
+#include "../codeconv.h"
#define BUFFSIZE 8192
void trim_subject_for_compare(gchar *str)
{
gchar *srcp;
- int skip;
eliminate_parenthesis(str, '[', ']');
eliminate_parenthesis(str, '(', ')');
g_strstrip(str);
- srcp = str + subject_get_reply_prefix_length(str);
+ srcp = str + subject_get_prefix_length(str);
if (srcp != str)
memmove(str, srcp, strlen(srcp) + 1);
}
g_strstrip(str);
- srcp = str + subject_get_reply_prefix_length(str);
+ srcp = str + subject_get_prefix_length(str);
if (srcp != str)
memmove(str, srcp, strlen(srcp) + 1);
}
gchar op, cl;
gint in_brace;
- destp = str + subject_get_reply_prefix_length(str);
+ destp = str + subject_get_prefix_length(str);
if (*destp == '[') {
op = '[';
{
GList *result = NULL;
const gchar *p, *q;
- gchar *file;
+ gchar *escaped_utf8uri;
p = uri_list;
if (*p != '#') {
while (isspace(*p)) p++;
if (!strncmp(p, "file:", 5)) {
- p += 5;
q = p;
+ q += 5;
while (*q && *q != '\n' && *q != '\r') q++;
if (q > p) {
+ gchar *file, *locale_file = NULL;
q--;
while (q > p && isspace(*q)) q--;
- file = g_malloc(q - p + 2);
- strncpy(file, p, q - p + 1);
- file[q - p + 1] = '\0';
- result = g_list_append(result,file);
+ Xalloca(escaped_utf8uri, q - p + 2,
+ return result);
+ Xalloca(file, q - p + 2,
+ return result);
+ *file = '\0';
+ strncpy(escaped_utf8uri, p, q - p + 1);
+ escaped_utf8uri[q - p + 1] = '\0';
+ decode_uri(file, escaped_utf8uri);
+#warning FIXME_GTK2 /* should we use g_filename_from_utf8()? */
+ /*
+ * g_filename_from_uri() rejects escaped/locale encoded uri
+ * string which come from Nautilus.
+ */
+ if (g_utf8_validate(file, -1, NULL))
+ locale_file
+ = conv_codeset_strdup(
+ file + 5,
+ CS_UTF_8,
+ conv_get_current_charset_str());
+ if (!locale_file)
+ locale_file = g_strdup(file + 5);
+ result = g_list_append(result, locale_file);
}
}
}
* but as long as we are not able to do our own extensions to glibc, we do
* it here.
*/
-gchar *get_home_dir(void)
+const gchar *get_home_dir(void)
{
#if HAVE_DOSISH_SYSTEM
static gchar *home_dir;
#endif
}
-gchar *get_rc_dir(void)
+const gchar *get_rc_dir(void)
{
static gchar *rc_dir = NULL;
return rc_dir;
}
-gchar *get_news_cache_dir(void)
+const gchar *get_news_cache_dir(void)
{
static gchar *news_cache_dir = NULL;
return news_cache_dir;
}
-gchar *get_imap_cache_dir(void)
+const gchar *get_imap_cache_dir(void)
{
static gchar *imap_cache_dir = NULL;
return imap_cache_dir;
}
-gchar *get_mbox_cache_dir(void)
+const gchar *get_mbox_cache_dir(void)
{
static gchar *mbox_cache_dir = NULL;
return mbox_cache_dir;
}
-gchar *get_mime_tmp_dir(void)
+const gchar *get_mime_tmp_dir(void)
{
static gchar *mime_tmp_dir = NULL;
return mime_tmp_dir;
}
-gchar *get_template_dir(void)
+const gchar *get_template_dir(void)
{
static gchar *template_dir = NULL;
return template_dir;
}
-gchar *get_header_cache_dir(void)
+const gchar *get_header_cache_dir(void)
{
static gchar *header_dir = NULL;
return header_dir;
}
-gchar *get_tmp_dir(void)
+const gchar *get_tmp_dir(void)
{
static gchar *tmp_dir = NULL;
return tmp_file;
}
-gchar *get_domain_name(void)
+const gchar *get_domain_name(void)
{
static gchar *domain_name = NULL;
debug_mode = mode;
}
-gboolean debug_get_mode()
+gboolean debug_get_mode(void)
{
return debug_mode;
}
if (subject == NULL)
subject = "";
else
- subject += subject_get_reply_prefix_length(subject);
+ subject += subject_get_prefix_length(subject);
return g_hash_table_lookup(subject_table, subject);
}
{
if (subject == NULL || *subject == 0)
return;
- subject += subject_get_reply_prefix_length(subject);
+ subject += subject_get_prefix_length(subject);
g_hash_table_insert(subject_table, subject, data);
}
if (subject == NULL)
return;
- subject += subject_get_reply_prefix_length(subject);
+ subject += subject_get_prefix_length(subject);
g_hash_table_remove(subject_table, subject);
}
/*!
*\brief Check if a string is prefixed with known (combinations)
- * of reply prefixes. The function assumes that each prefix
+ * of prefixes. The function assumes that each prefix
* is terminated by zero or exactly _one_ space.
*
*\param str String to check for a prefixes
* for a "clean" subject line. If no prefix was found, 0
* is returned.
*/
-int subject_get_reply_prefix_length(const gchar *subject)
+int subject_get_prefix_length(const gchar *subject)
{
/*!< Array with allowable reply prefixes regexps. */
- static const gchar * const reply_prefixes[] = {
- "[Rr][Ee]\\:", /* "Re:" */
- "[Rr][Ee]\\[[1-9][0-9]*\\]\\:", /* Intelligent but stupidly non-conforming Re[XXX]:*/
- "[Aa][Nn][Tt][Ww]\\:" /* Overactive i18n / translation teams */
+ static const gchar * const prefixes[] = {
+ "Re\\:", /* "Re:" */
+ "Re\\[[1-9][0-9]*\\]\\:", /* "Re[XXX]:" (non-conforming news mail clients) */
+ "Antw\\:", /* "Antw:" (Dutch / German Outlook) */
+ "Aw\\:", /* "Aw:" (German) */
+ "Antwort\\:", /* "Antwort:" (German Lotus Notes) */
+ "Res\\:", /* "Res:" (Brazilian Outlook) */
+ "Fw\\:", /* "Fw:" Forward */
+ "Enc\\:" /* "Enc:" Forward (Brazilian Outlook) */
/* add more */
};
- const int REPLY_PREFIXES = sizeof reply_prefixes / sizeof reply_prefixes[0];
+ const int PREFIXES = sizeof prefixes / sizeof prefixes[0];
int n;
regmatch_t pos;
static regex_t regex;
if (!init_) {
GString *s = g_string_new("");
- for (n = 0; n < REPLY_PREFIXES; n++)
+ for (n = 0; n < PREFIXES; n++)
/* Terminate each prefix regexpression by a
* "\ ?" (zero or ONE space), and OR them */
g_string_sprintfa(s, "(%s\\ ?)%s",
- reply_prefixes[n],
- n < REPLY_PREFIXES - 1 ?
+ prefixes[n],
+ n < PREFIXES - 1 ?
"|" : "");
g_string_prepend(s, "(");
/* We now have something like "^\ *((PREFIX1\ ?)|(PREFIX2\ ?))+"
* TODO: Should this be "^\ *(((PREFIX1)|(PREFIX2))\ ?)+" ??? */
- if (regcomp(®ex, s->str, REG_EXTENDED)) {
+ if (regcomp(®ex, s->str, REG_EXTENDED | REG_ICASE)) {
debug_print("Error compiling regexp %s\n", s->str);
g_string_free(s, TRUE);
return 0;
{
return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
}
+
+gchar *generate_msgid(const gchar *address, gchar *buf, gint len)
+{
+ /* steal from compose.c::compose_generate_msgid() */
+ struct tm *lt;
+ time_t t;
+ gchar *addr;
+
+ t = time(NULL);
+ lt = localtime(&t);
+
+ if (address && *address) {
+ if (strchr(address, '@'))
+ addr = g_strdup(address);
+ else
+ addr = g_strconcat(address, "@", get_domain_name(), NULL);
+ } else
+ addr = g_strconcat(g_get_user_name(), "@", get_domain_name(),
+ NULL);
+
+ g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x.%s",
+ lt->tm_year + 1900, lt->tm_mon + 1,
+ lt->tm_mday, lt->tm_hour,
+ lt->tm_min, lt->tm_sec,
+ (guint)random(), addr);
+
+ g_free(addr);
+ return buf;
+}
+
+/**
+ * Create a new boundary in a way that it is very unlikely that this
+ * will occur in the following text. It would be easy to ensure
+ * uniqueness if everything is either quoted-printable or base64
+ * encoded (note that conversion is allowed), but because MIME bodies
+ * may be nested, it may happen that the same boundary has already
+ * been used. We avoid scanning the message for conflicts and hope the
+ * best.
+ *
+ * boundary := 0*69<bchars> bcharsnospace
+ * bchars := bcharsnospace / " "
+ * bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
+ * "+" / "_" / "," / "-" / "." /
+ * "/" / ":" / "=" / "?"
+ *
+ * ":" and "," removed because of buggy MTAs
+ */
+
+gchar *generate_mime_boundary(void)
+{
+ static gchar tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "1234567890'()+_./=?";
+ gchar bufuniq[17];
+ gchar bufdate[BUFFSIZE];
+ int i, equal;
+ int pid;
+
+ pid = getpid();
+
+ /* We make the boundary depend on the pid, so that all running
+ * processed generate different values even when they have been
+ * started within the same second and srand48(time(NULL)) has been
+ * used. I can't see whether this is really an advantage but it
+ * doesn't do any harm.
+ */
+ equal = -1;
+ for (i = 0; i < sizeof(bufuniq) - 1; i++) {
+ bufuniq[i] = tbl[(lrand48() ^ pid) % (sizeof(tbl) - 1)]; /* fill with random */
+ if (bufuniq[i] == '=' && equal == -1)
+ equal = i;
+ }
+ bufuniq[i] = 0;
+
+ /* now make sure that we do have the sequence "=." in it which cannot
+ * be matched by quoted-printable or base64 encoding */
+ if (equal != -1 && (equal + 1) < i)
+ bufuniq[equal + 1] = '.';
+ else {
+ bufuniq[0] = '=';
+ bufuniq[1] = '.';
+ }
+
+ get_rfc822_date(bufdate, sizeof(bufdate));
+ subst_char(bufdate, ' ', '_');
+ subst_char(bufdate, ',', '_');
+ subst_char(bufdate, ':', '_');
+
+ return g_strdup_printf("Multipart_%s_%s",
+ bufdate, bufuniq);
+}