static gboolean cloud_config_simplify(GNode *node, __unused__ gpointer data) { if (node->data) { return false; } GNode *child = g_node_last_child(node); while (child) { if (child->data) { child = g_node_prev_sibling(child); continue; } GNode *remove = child; child = g_node_prev_sibling(child); g_node_append(node->parent, g_node_copy(remove)); g_node_unlink(remove); g_node_destroy(remove); } if (g_node_n_children(node) == 0) { g_node_unlink(node); g_node_destroy(node); } return false; }
static void glade_eprop_model_data_delete_selected (GladeEditorProperty * eprop) { GtkTreeIter iter; GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (eprop); GladeProperty *property = glade_editor_property_get_property (eprop); GNode *data_tree = NULL, *row; gint rownum = -1; /* NOTE: This will trigger row-deleted below... */ if (!gtk_tree_selection_get_selected (eprop_data->selection, NULL, &iter)) return; gtk_tree_model_get (GTK_TREE_MODEL (eprop_data->store), &iter, COLUMN_ROW, &rownum, -1); g_assert (rownum >= 0); /* if theres a sected row, theres data... */ glade_property_get (property, &data_tree); g_assert (data_tree); data_tree = glade_model_data_tree_copy (data_tree); row = g_node_nth_child (data_tree, rownum); g_node_unlink (row); glade_model_data_tree_free (row); if (eprop_data->pending_data_tree) glade_model_data_tree_free (eprop_data->pending_data_tree); eprop_data->pending_data_tree = data_tree; g_idle_add ((GSourceFunc) update_data_tree_idle, eprop); }
static GnomeVFSResult remove_fake_node_by_uri (const GnomeVFSURI *uri) { FakeNode *file; GNode *gnode; file = get_fake_node_from_uri (uri); if (!file) { return GNOME_VFS_ERROR_INVALID_URI; } gnode = file->gnode; g_node_unlink (gnode); g_node_traverse (gnode, G_PRE_ORDER, G_TRAVERSE_ALL, -1, free_files_func, NULL); g_node_destroy (gnode); print_tree (root, 0); return GNOME_VFS_OK; }
static GNode * cert_subject_public_key_from_attributes (GckAttributes *attributes) { const GckAttribute *attr; GBytes *bytes; GNode *cert; GNode *asn; attr = gck_attributes_find (attributes, CKA_VALUE); if (attr == NULL || gck_attribute_is_invalid (attr)) { _gcr_debug ("no value attribute for certificate"); return NULL; } bytes = g_bytes_new_with_free_func (attr->value, attr->length, gck_attributes_unref, gck_attributes_ref (attributes)); cert = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", bytes); g_bytes_unref (bytes); if (cert == NULL) { _gcr_debug ("couldn't parse certificate value"); return NULL; } asn = egg_asn1x_node (cert, "tbsCertificate", "subjectPublicKeyInfo", NULL); g_return_val_if_fail (asn != NULL, NULL); /* Remove the subject public key out of the certificate */ g_node_unlink (asn); egg_asn1x_destroy (cert); return asn; }
// remove the whole sub tree under parent, parent is excluded static void se_delete_subtree( GNode *parent ) { g_assert( parent ); GNode *np = g_node_first_child( parent ); while ( np ) { g_node_unlink( np ); g_node_destroy( np ); np = g_node_first_child( parent ); } }
/** * g_node_destroy: * @root: the root of the tree/subtree to destroy * * Removes @root and its children from the tree, freeing any memory * allocated. */ void g_node_destroy (GNode *root) { g_return_if_fail (root != NULL); if (!G_NODE_IS_ROOT (root)) g_node_unlink (root); g_nodes_free (root); }
/** * Look for begin/end statements to begin processing * of actions. **/ static gboolean enclosing_process_func(GNode *node, gpointer data) { if (node == NULL) { return TRUE; } struct Result *result = (struct Result*)data; struct VyattaNode *gp = (struct VyattaNode *) node->data; struct Config *c = &(gp->_config); struct Data *d = &(gp->_data); //does this node contain a begin or end statement? if (c->_def.actions && (c->_def.actions[end_act].vtw_list_head || c->_def.actions[begin_act].vtw_list_head)) { /* gotten to this point need to do a call around this enclosing * being/end node */ g_node_unlink(node); //removed this... d_dplog("commit2::enclosing_process_func(): enclosing statement found " "on: %s", d->_path); //perform recursive calling on new process node... int i; for (i = 0; i < g_num_actions; ++i) { // again should be enum GTraverseType order; if (delete_act != ActionOrder[i]) { order = G_PRE_ORDER; } else { order = G_POST_ORDER; } result->_action = ActionOrder[i]; g_node_traverse((GNode*)node, order, G_TRAVERSE_ALL, -1, (GNodeTraverseFunc)process_func, (gpointer)result); if (result->_err_code != 0) { //EXECUTE_LIST RETURNS FALSE ON FAILURE.... d_dplog("commit2::enclosing_process_func(): FAILURE: status: %d", result->_err_code); return TRUE; //WILL STOP AT THIS POINT } } } return FALSE; }
static void save_children(struct print_manager *pm, GNode * node) { prong_assert(node != NULL); prong_assert(node->data != NULL); struct job_node_data *data = (struct job_node_data *) node->data; long long parent_abs_off = contract_get_absolute_offset(data->node_contract); // This should never be called on nodes with offsets of -1 prong_assert(parent_abs_off != -1); GNode *child = node->children; while (child != NULL) { GNode *next = child->next; g_node_unlink(child); data = (struct job_node_data *) child->data; // We only care if the children are on abs_offsets in the future long long abs_off = contract_get_absolute_offset(data->node_contract); if (abs_off > pm->current_offset) { if (g_tree_lookup(pm->abs_tree, &abs_off) == NULL) { //printf("Inserting %lld into abs_tree\n", abs_off); data->parent_absolute_offset = parent_abs_off; long long *p_abs_off = (long long *) g_malloc(sizeof(long long)); *p_abs_off = abs_off; g_tree_insert(pm->abs_tree, p_abs_off, child); } else { // A child is already in the tree at this address??? g_node_safe_destroy(child); } } else { // Child has an offset in the past (or -1) g_node_safe_destroy(child); } child = next; } //printf("Tree altered.\n"); //debug_print_state_of_play(pm); }
void glade_model_data_reorder_column (GNode * node, gint column, gint nth) { GNode *row, *item; g_return_if_fail (node != NULL); for (row = node->children; row; row = row->next) { g_return_if_fail (nth >= 0 && nth < g_node_n_children (row)); item = g_node_nth_child (row, column); g_node_unlink (item); g_node_insert (row, nth, item); } }
gboolean sort_func_priority_extended(GNode *node, gpointer data) { struct VyattaNode *gp = (struct VyattaNode *) node->data; struct Config *gcfg = &(gp->_config); GNode *root_node = (GNode*)data; //WILL STOP AT DEPTH OF 10 REFERENCES //GET PARENT WORKING FIRST.... //change action state of node according to enclosing behavior if (gcfg->_priority_extended) { //only if priority is specified. GNode *new_node = g_node_copy(node); //NOW, we need to figure out where this node belongs in the priority chain if (strncmp(gcfg->_priority_extended, "PARENT", 6) == 0) { //needs to walk up parents until priority is found and insert there.... GNode *n = node; while (TRUE) { n = n->parent; if (n == NULL) { break; } gpointer nd = ((GNode*)n)->data; if (((struct VyattaNode*)nd)->_config._priority != LOWEST_PRIORITY) { //means we are done--found anchor in parent g_node_unlink(node); if (IS_DELETE(gp->_data._operation)) { g_node_insert_before(root_node,n,new_node); } else { g_node_insert_after(root_node,n,new_node); } break; } } } } return FALSE; }
void remmina_file_manager_free_group_tree(GNode* node) { RemminaGroupData* data; GNode* child; if (!node) return; data = (RemminaGroupData*) node->data; if (data) { g_free(data->name); g_free(data->group); g_free(data); node->data = NULL; } for (child = g_node_first_child(node); child; child = g_node_next_sibling(child)) { remmina_file_manager_free_group_tree(child); } g_node_unlink(node); }
static void plist_free_node(GNode * node, gpointer none) { g_node_unlink(node); plist_data_t data = plist_get_data(node); if (data) { switch (data->type) { case PLIST_KEY: case PLIST_STRING: free(data->strval); break; case PLIST_DATA: free(data->buff); break; default: break; } free(data); } node->data = NULL; g_node_children_foreach(node, G_TRAVERSE_ALL, plist_free_node, NULL); }
gboolean remove_from_tree(GNode *file, gboolean unmount) { int position = g_list_position(lines, FILE(file)->line); gboolean refresh_needed = FALSE; GList *line_ptr, *line_ptr2; GNode *dir_ptr; if (G_NODE_IS_ROOT(file)) { endwin(); clean_up(); printf("The tree root was removed\n"); exit(EXIT_SUCCESS); } if (g_node_is_ancestor(file, NODE(selected_line))) select_file(file); if (FILE(file)->type == directory_type) { close_directory(file); destroy_directory_content_real(file, FALSE); if (unmount) return TRUE; } else if (FILE(file)->type == file_type) { for (dir_ptr = file->parent; !G_NODE_IS_ROOT(dir_ptr); dir_ptr = dir_ptr->parent) { if (FILE(dir_ptr)->open == FALSE) { g_node_unlink(file); return FALSE; } } if (FILE(dir_ptr)->open == FALSE) { g_node_unlink(file); return FALSE; } } g_node_unlink(file); if (g_list_position(lines, first_line) <= position && position <= g_list_position(lines, last_line)) { if (first_line == FILE(file)->line && selected_line == FILE(file)->line) { selected_line = first_line = g_list_previous(first_line); lines = g_list_delete_link(lines, FILE(file)->line); print_lines(first_line, first_line, FALSE); } else if (position < g_list_position(lines, selected_line)) { if (first_line == FILE(file)->line) first_line = g_list_next(first_line); line_ptr = g_list_previous(FILE(file)->line); lines = g_list_delete_link(lines, FILE(file)->line); if ((line_ptr2 = g_list_previous(first_line)) != NULL) { first_line = line_ptr2; print_lines(first_line, line_ptr, FALSE); } else if ((line_ptr2 = g_list_next(last_line)) != NULL) { last_line = line_ptr2; print_lines(line_ptr, last_line, FALSE); } else print_lines(line_ptr, last_line, TRUE); } else { if (FILE(file)->line == selected_line) selected_line = g_list_previous(selected_line); if (last_line == FILE(file)->line) last_line = g_list_previous(last_line); line_ptr = g_list_previous(FILE(file)->line); lines = g_list_delete_link(lines, FILE(file)->line); if ((line_ptr2 = g_list_next(last_line)) != NULL) { last_line = line_ptr2; print_lines(line_ptr, last_line, FALSE); } else print_lines(line_ptr, last_line, TRUE); } refresh_needed = TRUE; } else { if (last_line == g_list_previous(FILE(file)->line)) { lines = g_list_delete_link(lines, FILE(file)->line); print_lines(last_line, last_line, FALSE); refresh_needed = TRUE; } else lines = g_list_delete_link(lines, FILE(file)->line); } free_node_data(file, NULL); g_node_destroy(file); return refresh_needed; }
static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo) { MimeInfo *decinfo, *parseinfo; gpgme_data_t cipher, plain; FILE *dstfp; gchar *fname; gchar *textdata = NULL; static gint id = 0; const gchar *src_codeset = NULL; gpgme_verify_result_t sigstat = 0; PrivacyDataPGP *data = NULL; gpgme_ctx_t ctx; gchar *chars; size_t len; const gchar *begin_indicator = "-----BEGIN PGP MESSAGE-----"; const gchar *end_indicator = "-----END PGP MESSAGE-----"; gchar *pos; if (gpgme_new(&ctx) != GPG_ERR_NO_ERROR) return NULL; gpgme_set_textmode(ctx, 1); gpgme_set_armor(ctx, 1); cm_return_val_if_fail(mimeinfo != NULL, NULL); cm_return_val_if_fail(pgpinline_is_encrypted(mimeinfo), NULL); if (procmime_mimeinfo_parent(mimeinfo) == NULL || mimeinfo->type != MIMETYPE_TEXT) { gpgme_release(ctx); privacy_set_error(_("Couldn't parse mime part.")); return NULL; } textdata = get_part_as_string(mimeinfo); if (!textdata) { gpgme_release(ctx); privacy_set_error(_("Couldn't get text data.")); return NULL; } debug_print("decrypting '%s'\n", textdata); gpgme_data_new_from_mem(&cipher, textdata, (size_t)strlen(textdata), 1); plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx); if (sigstat && !sigstat->signatures) sigstat = NULL; gpgme_data_release(cipher); if (plain == NULL) { gpgme_release(ctx); return NULL; } fname = g_strdup_printf("%s%cplaintext.%08x", get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id); if ((dstfp = g_fopen(fname, "wb")) == NULL) { FILE_OP_ERROR(fname, "fopen"); privacy_set_error(_("Couldn't open decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); return NULL; } src_codeset = procmime_mimeinfo_get_parameter(mimeinfo, "charset"); if (src_codeset == NULL) src_codeset = CS_ISO_8859_1; if (fprintf(dstfp, "MIME-Version: 1.0\r\n" "Content-Type: text/plain; charset=%s\r\n" "Content-Transfer-Encoding: 8bit\r\n" "\r\n", src_codeset) < 0) { FILE_OP_ERROR(fname, "fprintf"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } /* Store any part before encrypted text */ pos = pgp_locate_armor_header(textdata, begin_indicator); if (pos != NULL && (pos - textdata) > 0) { if (fwrite(textdata, 1, pos - textdata, dstfp) < pos - textdata) { FILE_OP_ERROR(fname, "fwrite"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } } if (fwrite(_("\n--- Start of PGP/Inline encrypted data ---\n"), 1, strlen(_("\n--- Start of PGP/Inline encrypted data ---\n")), dstfp) < strlen(_("\n--- Start of PGP/Inline encrypted data ---\n"))) { FILE_OP_ERROR(fname, "fwrite"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } chars = sgpgme_data_release_and_get_mem(plain, &len); if (len > 0) { if (fwrite(chars, 1, len, dstfp) < len) { FILE_OP_ERROR(fname, "fwrite"); g_free(chars); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } } g_free(chars); /* Store any part after encrypted text */ if (fwrite(_("--- End of PGP/Inline encrypted data ---\n"), 1, strlen(_("--- End of PGP/Inline encrypted data ---\n")), dstfp) < strlen(_("--- End of PGP/Inline encrypted data ---\n"))) { FILE_OP_ERROR(fname, "fwrite"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } if (pos != NULL) { pos = pgp_locate_armor_header(pos, end_indicator); if (pos != NULL && *pos != '\0') { pos += strlen(end_indicator); if (fwrite(pos, 1, strlen(pos), dstfp) < strlen(pos)) { FILE_OP_ERROR(fname, "fwrite"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } } } if (fclose(dstfp) == EOF) { FILE_OP_ERROR(fname, "fclose"); privacy_set_error(_("Couldn't close decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); return NULL; } parseinfo = procmime_scan_file(fname); g_free(fname); if (parseinfo == NULL) { gpgme_release(ctx); privacy_set_error(_("Couldn't scan decrypted file.")); return NULL; } decinfo = g_node_first_child(parseinfo->node) != NULL ? g_node_first_child(parseinfo->node)->data : NULL; if (decinfo == NULL) { gpgme_release(ctx); privacy_set_error(_("Couldn't scan decrypted file parts.")); return NULL; } g_node_unlink(decinfo->node); procmime_mimeinfo_free_all(parseinfo); decinfo->tmp = TRUE; if (sigstat != GPGME_SIG_STAT_NONE) { if (decinfo->privacy != NULL) { data = (PrivacyDataPGP *) decinfo->privacy; } else { data = pgpinline_new_privacydata(); decinfo->privacy = (PrivacyData *) data; } if (data != NULL) { data->done_sigtest = TRUE; data->is_signed = TRUE; data->sigstatus = sigstat; if (data->ctx) gpgme_release(data->ctx); data->ctx = ctx; } } else gpgme_release(ctx); return decinfo; FILE_ERROR: fclose(dstfp); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); return NULL; }
/* return the reversed thread tree */ GNode *procmsg_get_thread_tree(GSList *mlist) { GNode *root, *parent, *node, *next; GHashTable *msgid_table; GRelation *subject_relation; MsgInfo *msginfo; const gchar *msgid; root = g_node_new(NULL); msgid_table = g_hash_table_new(g_str_hash, g_str_equal); subject_relation = g_relation_new(2); g_relation_index(subject_relation, 0, g_str_hash, g_str_equal); for (; mlist != NULL; mlist = mlist->next) { msginfo = (MsgInfo *)mlist->data; parent = root; if (msginfo->inreplyto) { parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto); if (parent == NULL) { parent = root; } } node = g_node_insert_data_before (parent, parent == root ? parent->children : NULL, msginfo); if ((msgid = msginfo->msgid) && g_hash_table_lookup(msgid_table, msgid) == NULL) g_hash_table_insert(msgid_table, (gchar *)msgid, node); /* CLAWS: add subject to relation (without prefix) */ if (prefs_common.thread_by_subject) { subject_relation_insert(subject_relation, node); } } /* complete the unfinished threads */ for (node = root->children; node != NULL; ) { parent = NULL; next = node->next; msginfo = (MsgInfo *)node->data; if (msginfo->inreplyto) { parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto); /* node should not be the parent, and node should not be an ancestor of parent (circular reference) */ if (parent && parent != node && !g_node_is_ancestor(node, parent)) { g_node_unlink(node); g_node_insert_before (parent, parent->children, node); } } node = next; } if (prefs_common.thread_by_subject) { for (node = root->children; node && node != NULL;) { next = node->next; msginfo = (MsgInfo *) node->data; parent = subject_relation_lookup(subject_relation, msginfo); /* the node may already be threaded by IN-REPLY-TO, so go up * in the tree to find the parent node */ if (parent != NULL) { if (g_node_is_ancestor(node, parent)) parent = NULL; if (parent == node) parent = NULL; } if (parent) { g_node_unlink(node); g_node_append(parent, node); } node = next; } } g_relation_destroy(subject_relation); g_hash_table_destroy(msgid_table); return root; }
gboolean sort_func(GNode *node, gpointer data, boolean priority_mode) { struct VyattaNode *gp = (struct VyattaNode *) node->data; struct Data *d = &(gp->_data); GNode *root_node = (GNode*)data; d_dplog("commit2::sort_func(): %s, node count: %d", (d->_name ? d->_name : "[n/a]"), g_node_n_children(root_node)); //change action state of node according to enclosing behavior /* XXX this is ugly. originally the condition for the if is the following: * (c1 && c2 || (c3 || c4) && c5) * * this causes compiler warning for mixing && and || without (). the * previous warning removal attempt changed the condition to the * following: * ((c1 && c2) || (c3 || (c4 && c5))) * * which was incorrect (c3 and c4 should be at the same "level") and * therefore was reverted. * * now changing the condition to the following to avoid compiler * warning: * ((c1 && c2) || ((c3 || c4) && c5)) * * note that since the current goal is simply cleanup, no attempt is * made to understand the logic here, and the change is purely based * on operator precendence to maintain the original logic. * * XXX now removing deactivate-handling code, which involves c2. * * note that c2 is (d->_disable_op != K_NO_DISABLE_OP), which means * the node is "deactivated" (in working or active config or both). * this in turn means that the (c1 && c2) part of the logic can only * be true if the node is deactivated. * * however, since activate/deactivate has not actually been exposed, * this means that in actual usage the (c1 && c2) part is never true. * therefore, we can simply remove the whole part, and the logic * becomes: * ((c3 || c4) && c5) */ NODE_OPERATION op = d->_operation; if (((/* c3 */ IS_SET_OR_CREATE(op)) || (/* c4 */ IS_DELETE(op))) && (/* c5 */ IS_NOOP(((struct VyattaNode*) (node->parent->data))->_data._operation))) { //first check if there is enclosing behavior boolean enclosing = FALSE; GNode *n = node; while (TRUE) { n = n->parent; vtw_def def = ((struct VyattaNode*)(n->data))->_config._def; if (def.actions[end_act].vtw_list_head || def.actions[begin_act].vtw_list_head) { enclosing = TRUE; break; } if (G_NODE_IS_ROOT(n) == TRUE) { break; } } //walk back up and flip operations until enclosing behavior if (enclosing == TRUE) { GNode *n = node; while (TRUE) { n = n->parent; vtw_def def = ((struct VyattaNode*)(n->data))->_config._def; if (((struct VyattaNode*)(n->data))->_data._operation == K_NO_OP) { /* XXX this is ugly. _operation is intended to be a bitmap, in which * case it doesn't make sense to make it an enum type (should * just be, e.g., int). this causes g++ to (rightly) complain. * work around it for now to avoid impacting other code since * the current goal is simply cleanup. */ int op = ((struct VyattaNode*)(n->data))->_data._operation; op |= K_ACTIVE_OP; ((struct VyattaNode*)(n->data))->_data._operation = (NODE_OPERATION) op; } if (def.actions[end_act].vtw_list_head || def.actions[begin_act].vtw_list_head) { break; } if (G_NODE_IS_ROOT(n) == TRUE) { break; } } } } if (priority_mode) { int gprio = gp->_config._priority; if (gprio < LOWEST_PRIORITY) { // only if priority is specified. //unlink from original tree g_node_unlink(node); GNode *new_node = g_node_copy(node); GNode *sibling = root_node->children; //now iterate through siblings of root_node and compare priority while (sibling && gprio > ((struct VyattaNode*)(sibling->data)) ->_config._priority) { sibling = sibling->next; if (!sibling || gprio < ((struct VyattaNode*)(sibling->data)) ->_config._priority) { // XXX isn't this redundant??? just cleaning up so not changing it break; } } d_dplog("commit2::sort_func(): inserting %s into transaction, " "priority: %d BEFORE %d", d->_name, gprio, (sibling ? ((struct VyattaNode*)(sibling->data))->_config._priority : LOWEST_PRIORITY)); g_node_insert_before(root_node,sibling,new_node); } } else { if (g_node_depth(node) == 2) { d_dplog("commit2::sort_func(): insert %s into transaction", d->_name); GNode *new_node = g_node_copy(node); g_node_insert(root_node,-1,new_node); //make a flat structure for now } } return FALSE; }
gboolean pgpmime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data) { MimeInfo *msgcontent, *encmultipart, *newinfo; FILE *fp; gchar *boundary, *enccontent; size_t len; gchar *textstr; gpgme_data_t gpgtext = NULL, gpgenc = NULL; gpgme_ctx_t ctx = NULL; gpgme_key_t *kset = NULL; gchar **fprs = g_strsplit(encrypt_data, " ", -1); gint i = 0; gpgme_error_t err; while (fprs[i] && strlen(fprs[i])) { i++; } kset = g_malloc(sizeof(gpgme_key_t)*(i+1)); memset(kset, 0, sizeof(gpgme_key_t)*(i+1)); if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) { debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err)); privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); g_free(kset); return FALSE; } i = 0; while (fprs[i] && strlen(fprs[i])) { gpgme_key_t key; err = gpgme_get_key(ctx, fprs[i], &key, 0); if (err) { debug_print("can't add key '%s'[%d] (%s)\n", fprs[i],i, gpgme_strerror(err)); privacy_set_error(_("Couldn't add GPG key %s, %s"), fprs[i], gpgme_strerror(err)); g_free(kset); return FALSE; } debug_print("found %s at %d\n", fprs[i], i); kset[i] = key; i++; } debug_print("Encrypting message content\n"); /* remove content node from message */ msgcontent = (MimeInfo *) mimeinfo->node->children->data; g_node_unlink(msgcontent->node); /* create temporary multipart for content */ encmultipart = procmime_mimeinfo_new(); encmultipart->type = MIMETYPE_MULTIPART; encmultipart->subtype = g_strdup("encrypted"); boundary = generate_mime_boundary("Encrypt"); g_hash_table_insert(encmultipart->typeparameters, g_strdup("boundary"), g_strdup(boundary)); g_hash_table_insert(encmultipart->typeparameters, g_strdup("protocol"), g_strdup("application/pgp-encrypted")); g_node_append(encmultipart->node, msgcontent->node); /* write message content to temporary file */ fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file, %s"), g_strerror(errno)); g_free(kset); return FALSE; } procmime_write_mimeinfo(encmultipart, fp); rewind(fp); /* read temporary file into memory */ textstr = get_canonical_content(fp, boundary); g_free(boundary); claws_fclose(fp); /* encrypt data */ gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0); gpgme_data_new(&gpgenc); gpgme_set_armor(ctx, 1); cm_gpgme_data_rewind(gpgtext); err = gpgme_op_encrypt(ctx, kset, GPGME_ENCRYPT_ALWAYS_TRUST, gpgtext, gpgenc); enccontent = sgpgme_data_release_and_get_mem(gpgenc, &len); gpgme_data_release(gpgtext); g_free(textstr); g_free(kset); if (enccontent == NULL || len <= 0) { g_warning("sgpgme_data_release_and_get_mem failed"); privacy_set_error(_("Encryption failed, %s"), gpgme_strerror(err)); gpgme_release(ctx); g_free(enccontent); return FALSE; } /* create encrypted multipart */ g_node_unlink(msgcontent->node); procmime_mimeinfo_free_all(&msgcontent); g_node_append(mimeinfo->node, encmultipart->node); newinfo = procmime_mimeinfo_new(); newinfo->type = MIMETYPE_APPLICATION; newinfo->subtype = g_strdup("pgp-encrypted"); newinfo->content = MIMECONTENT_MEM; newinfo->data.mem = g_strdup("Version: 1\n"); g_node_append(encmultipart->node, newinfo->node); newinfo = procmime_mimeinfo_new(); newinfo->type = MIMETYPE_APPLICATION; newinfo->subtype = g_strdup("octet-stream"); newinfo->content = MIMECONTENT_MEM; newinfo->data.mem = g_malloc(len + 1); g_memmove(newinfo->data.mem, enccontent, len); newinfo->data.mem[len] = '\0'; g_node_append(encmultipart->node, newinfo->node); g_free(enccontent); gpgme_release(ctx); return TRUE; }
gboolean pgpmime_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *from_addr) { MimeInfo *msgcontent, *sigmultipart, *newinfo; gchar *textstr, *micalg = NULL; FILE *fp; gchar *boundary = NULL; gchar *sigcontent; gpgme_ctx_t ctx; gpgme_data_t gpgtext, gpgsig; gpgme_error_t err; size_t len; struct passphrase_cb_info_s info; gpgme_sign_result_t result = NULL; gchar *test_msg; fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno)); return FALSE; } procmime_write_mimeinfo(mimeinfo, fp); rewind(fp); /* read temporary file into memory */ test_msg = file_read_stream_to_str(fp); claws_fclose(fp); memset (&info, 0, sizeof info); /* remove content node from message */ msgcontent = (MimeInfo *) mimeinfo->node->children->data; g_node_unlink(msgcontent->node); /* create temporary multipart for content */ sigmultipart = procmime_mimeinfo_new(); sigmultipart->type = MIMETYPE_MULTIPART; sigmultipart->subtype = g_strdup("signed"); do { g_free(boundary); boundary = generate_mime_boundary("Sig"); } while (strstr(test_msg, boundary) != NULL); g_free(test_msg); g_hash_table_insert(sigmultipart->typeparameters, g_strdup("boundary"), g_strdup(boundary)); g_hash_table_insert(sigmultipart->typeparameters, g_strdup("protocol"), g_strdup("application/pgp-signature")); g_node_append(sigmultipart->node, msgcontent->node); g_node_append(mimeinfo->node, sigmultipart->node); /* write message content to temporary file */ fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno)); return FALSE; } procmime_write_mimeinfo(sigmultipart, fp); rewind(fp); /* read temporary file into memory */ textstr = get_canonical_content(fp, boundary); g_free(boundary); claws_fclose(fp); gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0); gpgme_data_new(&gpgsig); if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) { debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err)); privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); return FALSE; } gpgme_set_textmode(ctx, 1); gpgme_set_armor(ctx, 1); gpgme_signers_clear (ctx); if (!sgpgme_setup_signers(ctx, account, from_addr)) { gpgme_release(ctx); return FALSE; } prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent); if (g_getenv("GPG_AGENT_INFO") && prefs_gpg_get_config()->use_gpg_agent) { debug_print("GPG_AGENT_INFO environment defined, running without passphrase callback\n"); } else { info.c = ctx; gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); } err = gpgme_op_sign(ctx, gpgtext, gpgsig, GPGME_SIG_MODE_DETACH); if (err != GPG_ERR_NO_ERROR) { if (err == GPG_ERR_CANCELED) { /* ignore cancelled signing */ privacy_reset_error(); debug_print("gpgme_op_sign cancelled\n"); } else { privacy_set_error(_("Data signing failed, %s"), gpgme_strerror(err)); debug_print("gpgme_op_sign error : %x\n", err); } gpgme_release(ctx); return FALSE; } result = gpgme_op_sign_result(ctx); if (result && result->signatures) { gpgme_new_signature_t sig = result->signatures; if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { gchar *down_algo = g_ascii_strdown(gpgme_hash_algo_name( result->signatures->hash_algo), -1); micalg = g_strdup_printf("pgp-%s", down_algo); g_free(down_algo); } else { micalg = g_strdup(gpgme_hash_algo_name( result->signatures->hash_algo)); } while (sig) { debug_print("valid signature: %s\n", sig->fpr); sig = sig->next; } } else if (result && result->invalid_signers) { gpgme_invalid_key_t invalid = result->invalid_signers; while (invalid) { g_warning("invalid signer: %s (%s)", invalid->fpr, gpgme_strerror(invalid->reason)); privacy_set_error(_("Data signing failed due to invalid signer: %s"), gpgme_strerror(invalid->reason)); invalid = invalid->next; } gpgme_release(ctx); return FALSE; } else { /* can't get result (maybe no signing key?) */ debug_print("gpgme_op_sign_result error\n"); privacy_set_error(_("Data signing failed, no results.")); gpgme_release(ctx); return FALSE; } sigcontent = sgpgme_data_release_and_get_mem(gpgsig, &len); gpgme_data_release(gpgtext); g_free(textstr); if (sigcontent == NULL || len <= 0) { g_warning("sgpgme_data_release_and_get_mem failed"); privacy_set_error(_("Data signing failed, no contents.")); g_free(micalg); g_free(sigcontent); return FALSE; } /* add signature */ g_hash_table_insert(sigmultipart->typeparameters, g_strdup("micalg"), micalg); newinfo = procmime_mimeinfo_new(); newinfo->type = MIMETYPE_APPLICATION; newinfo->subtype = g_strdup("pgp-signature"); newinfo->description = g_strdup(_("OpenPGP digital signature")); newinfo->content = MIMECONTENT_MEM; newinfo->data.mem = g_malloc(len + 1); g_memmove(newinfo->data.mem, sigcontent, len); newinfo->data.mem[len] = '\0'; g_node_append(sigmultipart->node, newinfo->node); g_free(sigcontent); gpgme_release(ctx); return TRUE; }
static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo) { MimeInfo *encinfo, *decinfo, *parseinfo; gpgme_data_t cipher = NULL, plain = NULL; static gint id = 0; FILE *dstfp; gchar *fname; gpgme_verify_result_t sigstat = NULL; PrivacyDataPGP *data = NULL; gpgme_ctx_t ctx; gchar *chars; size_t len; gpgme_error_t err; if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) { debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err)); privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); return NULL; } cm_return_val_if_fail(pgpmime_is_encrypted(mimeinfo), NULL); encinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, 1)->data; cipher = sgpgme_data_from_mimeinfo(encinfo); plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx); gpgme_data_release(cipher); if (plain == NULL) { debug_print("plain is null!\n"); gpgme_release(ctx); return NULL; } fname = g_strdup_printf("%s%cplaintext.%08x", get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id); if ((dstfp = claws_fopen(fname, "wb")) == NULL) { FILE_OP_ERROR(fname, "claws_fopen"); privacy_set_error(_("Couldn't open decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); debug_print("can't open!\n"); return NULL; } if (fprintf(dstfp, "MIME-Version: 1.0\n") < 0) { FILE_OP_ERROR(fname, "fprintf"); claws_fclose(dstfp); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); debug_print("can't open!\n"); return NULL; } chars = sgpgme_data_release_and_get_mem(plain, &len); if (len > 0) { if (claws_fwrite(chars, 1, len, dstfp) < len) { FILE_OP_ERROR(fname, "claws_fwrite"); g_free(chars); claws_fclose(dstfp); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); debug_print("can't open!\n"); return NULL; } } g_free(chars); if (claws_safe_fclose(dstfp) == EOF) { FILE_OP_ERROR(fname, "claws_fclose"); privacy_set_error(_("Couldn't close decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); debug_print("can't open!\n"); return NULL; } parseinfo = procmime_scan_file(fname); g_free(fname); if (parseinfo == NULL) { gpgme_release(ctx); privacy_set_error(_("Couldn't parse decrypted file.")); return NULL; } decinfo = g_node_first_child(parseinfo->node) != NULL ? g_node_first_child(parseinfo->node)->data : NULL; if (decinfo == NULL) { privacy_set_error(_("Couldn't parse decrypted file parts.")); gpgme_release(ctx); return NULL; } g_node_unlink(decinfo->node); procmime_mimeinfo_free_all(&parseinfo); decinfo->tmp = TRUE; if (sigstat != NULL && sigstat->signatures != NULL) { if (decinfo->privacy != NULL) { data = (PrivacyDataPGP *) decinfo->privacy; } else { data = pgpmime_new_privacydata(); decinfo->privacy = (PrivacyData *) data; } if (data != NULL) { data->done_sigtest = TRUE; data->is_signed = TRUE; data->sigstatus = sigstat; if (data->ctx) gpgme_release(data->ctx); data->ctx = ctx; } } else gpgme_release(ctx); return decinfo; }