static gboolean vee_info_set_user_flag (CamelMessageInfo *mi, const gchar *name, gboolean value) { gint res = FALSE; CamelVeeFolder *vf = (CamelVeeFolder *) camel_folder_summary_get_folder (mi->summary); if (camel_debug("vfolderexp")) printf ( "Expression for vfolder '%s' is '%s'\n", camel_folder_get_full_name (camel_folder_summary_get_folder (mi->summary)), g_strescape (vf->expression, "")); if (mi->uid) { CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); HANDLE_NULL_INFO (FALSE); /* ignore changes done in the folder itself, * unless it's a vTrash or vJunk folder */ if (!CAMEL_IS_VTRASH_FOLDER (vf)) camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder (rmi->summary)); res = camel_message_info_set_user_flag (rmi, name, value); camel_message_info_free (rmi); } return res; }
static void mail_printer_print_finished_cb (WebKitPrintOperation *print_operation, GTask *task) { AsyncContext *async_context; if (camel_debug ("webkit:preview")) printf ("%s\n", G_STRFUNC); async_context = g_task_get_task_data (task); g_return_if_fail (async_context != NULL); async_context->print_result = GTK_PRINT_OPERATION_RESULT_APPLY; g_task_return_boolean (task, TRUE); g_object_unref (task); }
static gboolean vee_info_set_flags (CamelMessageInfo *mi, guint32 flags, guint32 set) { gint res = FALSE; CamelVeeFolder *vf = CAMEL_VEE_FOLDER (camel_folder_summary_get_folder (mi->summary)); if (camel_debug("vfolderexp")) printf ( "Expression for vfolder '%s' is '%s'\n", camel_folder_get_full_name (CAMEL_FOLDER (vf)), g_strescape (vf->expression, "")); /* first update original message info... */ if (mi->uid) { CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); HANDLE_NULL_INFO (FALSE); /* ignore changes done in the folder itself, * unless it's a vTrash or vJunk folder */ if (!CAMEL_IS_VTRASH_FOLDER (vf)) camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder (rmi->summary)); camel_folder_freeze (camel_folder_summary_get_folder (rmi->summary)); res = camel_message_info_set_flags (rmi, flags, set); ((CamelVeeMessageInfo *) mi)->old_flags = camel_message_info_flags (rmi); camel_folder_thaw (camel_folder_summary_get_folder (rmi->summary)); camel_message_info_free (rmi); } if (res) CAMEL_FOLDER_SUMMARY_CLASS (camel_vee_summary_parent_class)->info_set_flags (mi, flags, set); return res; }
static void mail_printer_print_failed_cb (WebKitPrintOperation *print_operation, GError *error, GTask *task) { AsyncContext *async_context; if (camel_debug ("webkit:preview")) printf ("%s\n", G_STRFUNC); async_context = g_task_get_task_data (task); g_return_if_fail (async_context != NULL); async_context->print_result = GTK_PRINT_OPERATION_RESULT_ERROR; if (error != NULL) g_task_return_error (task, error); else { g_warning ("WebKit print operation returned ERROR result without setting a GError"); g_task_return_boolean (task, FALSE); } g_object_unref (task); }
static gboolean vee_info_set_user_flag (CamelMessageInfo *mi, const gchar *name, gboolean value) { gint res = FALSE; gboolean hacked_unread_folder = FALSE; CamelVeeFolder *vf = (CamelVeeFolder *)mi->summary->folder; if (camel_debug("vfolderexp")) printf ( "Expression for vfolder '%s' is '%s'\n", camel_folder_get_full_name (mi->summary->folder), g_strescape (vf->expression, "")); if (camel_vee_folder_get_unread_vfolder (vf) == -1) camel_vee_summary_load_check_unread_vfolder (CAMEL_VEE_SUMMARY (mi->summary)); if (camel_vee_folder_get_unread_vfolder (vf) == 1) hacked_unread_folder = TRUE; if (mi->uid) { CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8); HANDLE_NULL_INFO (FALSE); if (hacked_unread_folder) camel_vee_folder_mask_event_folder_changed ((CamelVeeFolder *)mi->summary->folder, rmi->summary->folder); res = camel_message_info_set_user_flag (rmi, name, value); if (hacked_unread_folder) camel_vee_folder_unmask_event_folder_changed ((CamelVeeFolder *)mi->summary->folder, rmi->summary->folder); camel_message_info_free (rmi); } return res; }
static CamelSExpResult * junk_test (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelSExpResult *r; CamelMessageInfo *info = fms->info; CamelJunkFilter *junk_filter; CamelMessageFlags flags; CamelMimeMessage *message; CamelJunkStatus status; const GHashTable *ht; const struct _camel_header_param *node; gboolean sender_is_known; gboolean message_is_junk = FALSE; GError *error = NULL; junk_filter = camel_session_get_junk_filter (fms->session); if (junk_filter == NULL) goto exit; /* Check if the message is already classified. */ flags = camel_message_info_flags (info); if (flags & CAMEL_MESSAGE_JUNK) { if (camel_debug ("junk")) printf ( "Message has a Junk flag set already, " "skipping junk test...\n"); goto exit; } if (flags & CAMEL_MESSAGE_NOTJUNK) { if (camel_debug ("junk")) printf ( "Message has a NotJunk flag set already, " "skipping junk test...\n"); goto exit; } /* Check the headers for a junk designation. */ ht = camel_session_get_junk_headers (fms->session); node = camel_message_info_headers (info); while (node != NULL) { const gchar *value = NULL; if (node->name != NULL) value = g_hash_table_lookup ( (GHashTable *) ht, node->name); message_is_junk = (value != NULL) && (camel_strstrcase (node->value, value) != NULL); if (message_is_junk) { if (camel_debug ("junk")) printf ( "Message contains \"%s: %s\"", node->name, value); goto done; } node = node->next; } /* If the sender is known, the message is not junk. */ sender_is_known = camel_session_lookup_addressbook ( fms->session, camel_message_info_from (info)); if (camel_debug ("junk")) printf ( "Sender '%s' in book? %d\n", camel_message_info_from (info), sender_is_known); if (sender_is_known) goto done; /* Consult 3rd party junk filtering software. */ message = camel_filter_search_get_message (fms, f); status = camel_junk_filter_classify ( junk_filter, message, NULL, &error); if (error == NULL) { const gchar *status_desc; switch (status) { case CAMEL_JUNK_STATUS_INCONCLUSIVE: status_desc = "inconclusive"; message_is_junk = FALSE; break; case CAMEL_JUNK_STATUS_MESSAGE_IS_JUNK: status_desc = "junk"; message_is_junk = TRUE; break; case CAMEL_JUNK_STATUS_MESSAGE_IS_NOT_JUNK: status_desc = "not junk"; message_is_junk = FALSE; break; default: g_warn_if_reached (); status_desc = "invalid"; message_is_junk = FALSE; break; } if (camel_debug ("junk")) g_print ( "Junk filter classification: %s\n", status_desc); } else { g_warn_if_fail (status == CAMEL_JUNK_STATUS_ERROR); g_warning ("%s: %s", G_STRFUNC, error->message); g_error_free (error); message_is_junk = FALSE; } done: if (camel_debug ("junk")) printf ( "Message is determined to be %s\n", message_is_junk ? "*JUNK*" : "clean"); exit: r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); r->value.number = message_is_junk; return r; }
static gboolean vee_info_set_flags (CamelMessageInfo *mi, guint32 flags, guint32 set) { gint res = FALSE; CamelVeeFolder *vf = (CamelVeeFolder *)mi->summary->folder; gboolean hacked_unread_folder = FALSE; if (camel_debug("vfolderexp")) printf ( "Expression for vfolder '%s' is '%s'\n", camel_folder_get_full_name (mi->summary->folder), g_strescape (vf->expression, "")); if (camel_vee_folder_get_unread_vfolder (vf) == -1) camel_vee_summary_load_check_unread_vfolder (CAMEL_VEE_SUMMARY (mi->summary)); if (camel_vee_folder_get_unread_vfolder (vf) == 1) hacked_unread_folder = TRUE; if (mi->uid) { guint32 old_visible, visible, old_unread; CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8); CamelVeeSummary *vsummary = (CamelVeeSummary *)mi->summary; HANDLE_NULL_INFO (FALSE); old_visible = rmi->summary->visible_count; old_unread = mi->summary->unread_count; camel_folder_summary_update_counts_by_flags (mi->summary, camel_message_info_flags (rmi), TRUE); if (hacked_unread_folder) camel_vee_folder_mask_event_folder_changed ((CamelVeeFolder *)mi->summary->folder, rmi->summary->folder); camel_folder_freeze (rmi->summary->folder); res = camel_message_info_set_flags (rmi, flags, set); ((CamelVeeMessageInfo *) mi)->old_flags = camel_message_info_flags (rmi); camel_folder_thaw (rmi->summary->folder); if (hacked_unread_folder) camel_vee_folder_unmask_event_folder_changed ((CamelVeeFolder *)mi->summary->folder, rmi->summary->folder); visible = rmi->summary->visible_count; /* Keep the summary in sync */ camel_folder_summary_update_counts_by_flags (mi->summary, camel_message_info_flags (rmi), FALSE); if (hacked_unread_folder && !vsummary->fake_visible_count) vsummary->fake_visible_count = mi->summary->visible_count; if (vsummary->fake_visible_count || hacked_unread_folder) vsummary->fake_visible_count += visible - old_visible; d(printf("VF %d %d %d %d %d\n", mi->summary->unread_count, mi->summary->deleted_count, mi->summary->junk_count, mi->summary->junk_not_deleted_count, mi->summary->visible_count)); /* This is where the ugly-created-hack is used */ if (hacked_unread_folder && mi->summary->unread_count - old_unread != 0) { CamelFolderChangeInfo *changes = camel_folder_change_info_new (); GPtrArray *match, *array; camel_folder_change_info_change_uid (changes, mi->uid); array = g_ptr_array_new (); g_ptr_array_add (array, (gpointer)rmi->uid); match = camel_folder_search_by_uids (rmi->summary->folder, vf->expression, array, NULL); if ((match && !match->len) || !match) { vsummary->fake_visible_count--; } else { vsummary->fake_visible_count++; } g_ptr_array_free (array, TRUE); if (match) camel_folder_search_free (rmi->summary->folder, match); camel_folder_changed (mi->summary->folder, changes); camel_folder_change_info_free (changes); } camel_message_info_free (rmi); } return res; }
/* Given a line that is the start of an untagged response, read and * return the complete response, which may include an arbitrary number * of literals. */ static char * imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex) { int fulllen, ldigits, nread, n, i, sexp = 0; unsigned int length; GPtrArray *data; GString *str; char *end, *p, *s, *d; p = strrchr (line, '{'); if (!p) return line; data = g_ptr_array_new (); fulllen = 0; while (1) { str = g_string_new (line); g_free (line); fulllen += str->len; g_ptr_array_add (data, str); if (!(p = strrchr (str->str, '{')) || p[1] == '-') break; /* HACK ALERT: We scan the non-literal part of the string, looking for possible s expression braces. This assumes we're getting s-expressions, which we should be. This is so if we get a blank line after a literal, in an s-expression, we can keep going, since we do no other parsing at this level. TODO: handle quoted strings? */ for (s=str->str; s<p; s++) { if (*s == '(') sexp++; else if (*s == ')') sexp--; } length = strtoul (p + 1, &end, 10); if (*end != '}' || *(end + 1) || end == p + 1 || length >= UINT_MAX - 2) break; ldigits = end - (p + 1); /* Read the literal */ str = g_string_sized_new (length + 2); str->str[0] = '\n'; nread = 0; do { if ((n = camel_stream_read (store->istream, str->str + nread + 1, length - nread)) == -1) { if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); else camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, g_strerror (errno)); camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); g_string_free (str, TRUE); goto lose; } nread += n; } while (n > 0 && nread < length); if (nread < length) { camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, _("Server response ended too soon.")); camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); g_string_free (str, TRUE); goto lose; } str->str[length + 1] = '\0'; if (camel_debug("imap")) { printf("Literal: -->"); fwrite(str->str+1, 1, length, stdout); printf("<--\n"); } /* Fix up the literal, turning CRLFs into LF. Also, if * we find any embedded NULs, strip them. This is * dubious, but: * - The IMAP grammar says you can't have NULs here * anyway, so this will not affect our behavior * against any completely correct server. * - WU-imapd 12.264 (at least) will cheerily pass * NULs along if they are embedded in the message */ s = d = str->str + 1; end = str->str + 1 + length; while (s < end) { while (s < end && *s == '\0') { s++; length--; } if (*s == '\r' && *(s + 1) == '\n') { s++; length--; } *d++ = *s++; } *d = '\0'; str->len = length + 1; /* p points to the "{" in the line that starts the * literal. The length of the CR-less response must be * less than or equal to the length of the response * with CRs, therefore overwriting the old value with * the new value cannot cause an overrun. However, we * don't want it to be shorter either, because then the * GString's length would be off... */ sprintf (p, "{%0*u}", ldigits, length); fulllen += str->len; g_ptr_array_add (data, str); /* Read the next line. */ do { if (camel_imap_store_readline (store, &line, ex) < 0) goto lose; /* MAJOR HACK ALERT, gropuwise sometimes sends an extra blank line after literals, check that here But only do it if we're inside an sexpression */ if (line[0] == 0 && sexp > 0) g_warning("Server sent empty line after a literal, assuming in error"); } while (line[0] == 0 && sexp > 0); } /* Now reassemble the data. */ p = line = g_malloc (fulllen + 1); for (i = 0; i < data->len; i++) { str = data->pdata[i]; memcpy (p, str->str, str->len); p += str->len; g_string_free (str, TRUE); } *p = '\0'; g_ptr_array_free (data, TRUE); return line; lose: for (i = 0; i < data->len; i++) g_string_free (data->pdata[i], TRUE); g_ptr_array_free (data, TRUE); return NULL; }
/** * camel_scalix_stream_next_token: * @stream: scalix stream * @token: scalix token * * Reads the next token from the scalix stream and saves it in @token. * * Returns 0 on success or -1 on fail. **/ int camel_scalix_stream_next_token (CamelSCALIXStream *stream, camel_scalix_token_t *token) { register unsigned char *inptr; unsigned char *inend, *start, *p; gboolean escaped = FALSE; size_t literal = 0; guint32 nz_number; int ret; g_return_val_if_fail (CAMEL_IS_SCALIX_STREAM (stream), -1); g_return_val_if_fail (stream->mode != CAMEL_SCALIX_STREAM_MODE_LITERAL, -1); g_return_val_if_fail (token != NULL, -1); if (stream->have_unget) { memcpy (token, &stream->unget, sizeof (camel_scalix_token_t)); stream->have_unget = FALSE; return 0; } token_clear (stream); inptr = stream->inptr; inend = stream->inend; *inend = '\0'; do { if (inptr == inend) { if ((ret = scalix_fill (stream)) < 0) { token->token = CAMEL_SCALIX_TOKEN_ERROR; return -1; } else if (ret == 0) { token->token = CAMEL_SCALIX_TOKEN_NO_DATA; return 0; } inptr = stream->inptr; inend = stream->inend; *inend = '\0'; } while (*inptr == ' ' || *inptr == '\r') inptr++; } while (inptr == inend); do { if (inptr < inend) { if (*inptr == '"') { /* qstring token */ escaped = FALSE; start = inptr; /* eat the beginning " */ inptr++; p = inptr; while (inptr < inend) { if (*inptr == '"' && !escaped) break; if (*inptr == '\\' && !escaped) { token_save (stream, p, inptr - p); escaped = TRUE; inptr++; p = inptr; } else { inptr++; escaped = FALSE; } } token_save (stream, p, inptr - p); if (inptr == inend) { stream->inptr = start; goto refill; } /* eat the ending " */ inptr++; /* nul-terminate the atom token */ token_save (stream, "", 1); token->token = CAMEL_SCALIX_TOKEN_QSTRING; token->v.qstring = stream->tokenbuf; d(fprintf (stderr, "token: \"%s\"\n", token->v.qstring)); break; } else if (strchr ("+*()[]\n", *inptr)) { /* special character token */ token->token = *inptr++; if (camel_debug ("scalix:stream")) { if (token->token != '\n') fprintf (stderr, "token: %c\n", token->token); else fprintf (stderr, "token: \\n\n"); } break; } else if (*inptr == '{') { /* literal identifier token */ if ((p = strchr (inptr, '}')) && strchr (p, '\n')) { inptr++; while (isdigit ((int) *inptr) && literal < UINT_MAX / 10) literal = (literal * 10) + (*inptr++ - '0'); if (*inptr != '}') { if (isdigit ((int) *inptr)) g_warning ("illegal literal identifier: literal too large"); else if (*inptr != '+') g_warning ("illegal literal identifier: garbage following size"); while (*inptr != '}') inptr++; } /* skip over '}' */ inptr++; /* skip over any trailing whitespace */ while (*inptr == ' ' || *inptr == '\r') inptr++; if (*inptr != '\n') { g_warning ("illegal token following literal identifier: %s", inptr); /* skip ahead to the eoln */ inptr = strchr (inptr, '\n'); } /* skip over '\n' */ inptr++; token->token = CAMEL_SCALIX_TOKEN_LITERAL; token->v.literal = literal; d(fprintf (stderr, "token: {%zu}\n", literal)); stream->mode = CAMEL_SCALIX_STREAM_MODE_LITERAL; stream->literal = literal; stream->eol = FALSE; break; } else { stream->inptr = inptr; goto refill; } } else if (*inptr >= '0' && *inptr <= '9') { /* number token */ *inend = '\0'; nz_number = strtoul ((char *) inptr, (char **) &start, 10); if (start == inend) goto refill; if (*start == ':' || *start == ',') { /* workaround for 'set' tokens (APPENDUID / COPYUID) */ goto atom_token; } inptr = start; token->token = CAMEL_SCALIX_TOKEN_NUMBER; token->v.number = nz_number; d(fprintf (stderr, "token: %u\n", nz_number)); break; } else if (is_atom (*inptr)) { atom_token: /* simple atom token */ start = inptr; while (inptr < inend && is_atom (*inptr)) inptr++; if (inptr == inend) { stream->inptr = start; goto refill; } token_save (stream, start, inptr - start); /* nul-terminate the atom token */ token_save (stream, "", 1); if (!strcmp (stream->tokenbuf, "NIL")) { /* special atom token */ token->token = CAMEL_SCALIX_TOKEN_NIL; d(fprintf (stderr, "token: NIL\n")); } else { token->token = CAMEL_SCALIX_TOKEN_ATOM; token->v.atom = stream->tokenbuf; d(fprintf (stderr, "token: %s\n", token->v.atom)); } break; } else if (*inptr == '\\') { /* possible flag token ("\" atom) */ start = inptr++; while (inptr < inend && is_atom (*inptr)) inptr++; if (inptr == inend) { stream->inptr = start; goto refill; } /* handle the \* case */ if ((inptr - start) == 1 && *inptr == '*') inptr++; if ((inptr - start) > 1) { token_save (stream, start, inptr - start); /* nul-terminate the flag token */ token_save (stream, "", 1); token->token = CAMEL_SCALIX_TOKEN_FLAG; token->v.atom = stream->tokenbuf; d(fprintf (stderr, "token: %s\n", token->v.atom)); } else { token->token = '\\'; d(fprintf (stderr, "token: %c\n", token->token)); } break; } else if (is_lwsp (*inptr)) { inptr++; } else { /* unknown character token? */ token->token = *inptr++; d(fprintf (stderr, "token: %c\n", token->token)); break; } } else { refill: token_clear (stream); if (scalix_fill (stream) <= 0) { token->token = CAMEL_SCALIX_TOKEN_ERROR; return -1; } inptr = stream->inptr; inend = stream->inend; *inend = '\0'; } } while (inptr < inend); stream->inptr = inptr; return 0; }
static CamelSExpResult * junk_test (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelSExpResult *r; gboolean retval = FALSE; CamelMessageInfo *info = fms->info; CamelJunkFilter *junk_filter; junk_filter = camel_session_get_junk_filter (fms->session); d(printf("doing junk test for message from '%s'\n", camel_message_info_from (fms->info))); if (junk_filter != NULL && (camel_message_info_flags (info) & (CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK)) == 0) { const GHashTable *ht = camel_session_get_junk_headers (fms->session); const struct _camel_header_param *node = camel_message_info_headers (info); while (node && !retval) { if (node->name) { gchar *value = (gchar *) g_hash_table_lookup ((GHashTable *) ht, node->name); d(printf("JunkCheckMatch: %s %s %s\n", node->name, node->value, value)); if (value) retval = camel_strstrcase (node->value, value) != NULL; } node = node->next; } if (camel_debug ("junk")) printf("filtered based on junk header ? %d\n", retval); if (!retval) { retval = camel_session_lookup_addressbook (fms->session, camel_message_info_from (info)) != TRUE; if (camel_debug ("junk")) printf("Sender '%s' in book? %d\n", camel_message_info_from (info), !retval); if (retval) /* Not in book. Could be spam. So check for it */ { CamelMimeMessage *message; CamelJunkStatus status; gboolean success; d(printf("filtering message\n")); message = camel_filter_search_get_message (fms, f); success = camel_junk_filter_classify (junk_filter, message, &status, NULL, NULL); retval = success && (status == CAMEL_JUNK_STATUS_MESSAGE_IS_JUNK); } } if (camel_debug ("junk")) printf("junk filter => %s\n", retval ? "*JUNK*" : "clean"); } else if (junk_filter != NULL && camel_debug ("junk")) { if (camel_message_info_flags (info) & CAMEL_MESSAGE_JUNK) printf ("Message has a Junk flag set already, skipping junk test...\n"); else if (camel_message_info_flags (info) & CAMEL_MESSAGE_NOTJUNK) printf ("Message has a NotJunk flag set already, skipping junk test...\n"); } r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); r->value.number = retval; return r; }