struct _JsonNode* mu_msg_to_json (MuMsg *msg, unsigned docid, const MuMsgIterThreadInfo *ti, MuMsgOptions opts) { JsonNode *node; JsonBuilder *bob; time_t t; size_t s; g_return_val_if_fail (msg, NULL); g_return_val_if_fail (!((opts & MU_MSG_OPTION_HEADERS_ONLY) && (opts & MU_MSG_OPTION_EXTRACT_IMAGES)),NULL); bob = json_builder_new (); bob = json_builder_begin_object (bob); if (ti) add_thread_info (bob, ti); add_string_member (bob, "subject", mu_msg_get_subject (msg)); /* in the no-headers-only case (see below) we get a more complete list * of contacts, so no need to get them here if that's the case */ if (opts & MU_MSG_OPTION_HEADERS_ONLY) add_contacts (bob, msg); t = mu_msg_get_date (msg); if (t != (time_t)-1) add_int_member (bob, "date", t); s = mu_msg_get_size (msg); if (s != (size_t)-1) add_int_member (bob, "size", s); add_string_member (bob, "message-id", mu_msg_get_msgid (msg)); add_string_member (bob, "mailing-list", mu_msg_get_mailing_list (msg)); add_string_member (bob, "path", mu_msg_get_path (msg)); add_string_member (bob, "maildir", mu_msg_get_maildir (msg)); add_string_member (bob, "priority", mu_msg_prio_name(mu_msg_get_prio(msg))); add_flags (bob, msg); add_list_member (bob, "tags", mu_msg_get_tags(msg)); add_list_member (bob, "references", mu_msg_get_references (msg)); add_string_member (bob, "in-reply-to", mu_msg_get_header (msg, "In-Reply-To")); /* headers are retrieved from the database, views from the * message file file attr things can only be gotten from the * file (ie., mu view), not from the database (mu find). */ if (!(opts & MU_MSG_OPTION_HEADERS_ONLY)) add_file_parts (bob, msg, opts); bob = json_builder_end_object (bob); node = json_builder_get_root (bob); g_clear_object (&bob); return node; }
static void /* 1B */ handle_references (GHashTable *id_table, MuContainer *c) { const GSList *refs, *cur; MuContainer *parent; gboolean created; refs = mu_msg_get_references (c->msg); if (!refs) return; /* nothing to do */ /* For each element in the message's References field: Find a MuContainer object for the given Message-ID: If there's one in id_table use that; Otherwise, make (and index) one with a null Message. */ /* go over over our list of refs, until 1 before the last... */ created = FALSE; for (parent = NULL, cur = refs; cur; cur = g_slist_next (cur)) { MuContainer *child; child = find_or_create_referred (id_table, (gchar*)cur->data, &created); /*Link the References field's MuContainers together in * the order implied by the References header. If they are already linked, don't change the existing links. Do not add a link if adding that link would introduce a loop: that is, before asserting A->B, search down the children of B to see if A is reachable, and also search down the children of A to see if B is reachable. If either is already reachable as a child of the other, don't add the link. */ if (child_elligible (parent, child, created)) parent = mu_container_append_children (parent, child); parent = child; } /* 'parent' points to the last ref: our direct parent; Set the parent of this message to be the last element in References. Note that this message may have a parent already: this can happen because we saw this ID in a References field, and presumed a parent based on the other entries in that field. Now that we have the actual message, we can be more definitive, so throw away the old parent and use this new one. Find this MuContainer in the parent's children list, and unlink it. Note that this could cause this message to now have no parent, if it has no references field, but some message referred to it as the non-first element of its references. (Which would have been some kind of lie...) Note that at all times, the various ``parent'' and ``child'' fields must be kept inter-consistent. */ /* optimization: if the the message was newly added, it's by * definition not reachable yet */ if (child_elligible (parent, c, created)) parent = mu_container_append_children (parent, c); }