/* * SNEP Core: read function * This function handles SNEP REQUEST codes: * GET, PUT and CONTINUE (REJECT is not handled). * * We read the first 6 bytes (the header) and check * - the read size ( should be 6 ) * - the version (on MAJOR) * * Then, we check snep_data. If it exists, it means that we are in * a fragment/continue situation (a 1st fragment was sent, and we * expect a CONTINUE for the remaining bytes). * If there's no existing snep_data, we create a new one and read the * missing bytes (llcp removes fragmentation issues) * */ bool near_snep_core_read(int client_fd, uint32_t adapter_idx, uint32_t target_idx, near_tag_io_cb cb, near_server_io req_get, near_server_io req_put, gpointer data) { struct p2p_snep_data *snep_data; struct p2p_snep_req_frame frame; int bytes_recv, ret; uint32_t ndef_length; DBG(""); /* Check previous/pending snep_data */ snep_data = g_hash_table_lookup(snep_client_hash, GINT_TO_POINTER(client_fd)); /* * If snep data is already there, and there are more bytes to read * we just go ahead and read more fragments from the client. */ if (snep_data && snep_data->nfc_data_length != snep_data->nfc_data_current_length) { ret = snep_core_read_ndef(client_fd, snep_data); if (ret) return ret; goto process_request; } /* * We already got something from this client, we should try * to continue reading. */ /* TODO Try with PEEK */ bytes_recv = recv(client_fd, &frame, sizeof(frame), 0); if (bytes_recv < 0) { near_error("Read error SNEP %d %s", bytes_recv, strerror(errno)); return false; } /* Check frame size */ if (bytes_recv != sizeof(frame)) { near_error("Bad frame size: %d", bytes_recv); return false; } /* If major is different, send UNSUPPORTED VERSION */ if (NEAR_SNEP_MAJOR(frame.version) != NEAR_SNEP_MAJOR(NEAR_SNEP_VERSION)) { near_error("Unsupported version (%d)", frame.version); near_snep_core_response_noinfo(client_fd, NEAR_SNEP_RESP_VERSION); return true; } /* * This is a fragmentation SNEP operation since we have pending * frames. But the ndef length and the current data length are * identical. So this is a CONTINUE for a fragmented GET, and * we should just process a CONTINUE frame and send the fragments * back to the client. This will be done from snep_core_process_request(). */ if (snep_data) { snep_data->request = frame.request; goto process_request; } /* This is a new request from the client */ snep_data = g_try_malloc0(sizeof(struct p2p_snep_data)); if (!snep_data) return false; /* the whole frame length */ ndef_length = GINT_FROM_BE(frame.length); snep_data->nfc_data = g_try_malloc0(ndef_length + TLV_SIZE); if (!snep_data->nfc_data) { g_free(snep_data); return false; } /* fill the struct */ snep_data->nfc_data_length = ndef_length; snep_data->nfc_data_ptr = snep_data->nfc_data; snep_data->adapter_idx = adapter_idx; snep_data->target_idx = target_idx; snep_data->request = frame.request; snep_data->respond_continue = FALSE; snep_data->cb = cb; /* Add to the client hash table */ g_hash_table_insert(snep_client_hash, GINT_TO_POINTER(client_fd), snep_data); if (ndef_length > 0) { if ((frame.request == NEAR_SNEP_REQ_GET) || (frame.request == NEAR_SNEP_REQ_PUT)) { /* We should read the missing bytes */ ret = snep_core_read_ndef(client_fd, snep_data); if (ret) return ret; } } process_request: return snep_core_process_request(client_fd, snep_data, req_get, req_put); }
// Get the (key,value) pairs back from KWallet. GHashTable* dt_pwstorage_kwallet_get(const backend_kwallet_context_t *context, const gchar* slot) { GHashTable *table = g_hash_table_new(g_str_hash, g_str_equal); GError* error = NULL; // Is there an entry in the wallet? gboolean has_entry = FALSE; int wallet_handle = get_wallet_handle(context); /* signature: * * in i handle, * in s folder, * in s key, * in s appid, * * out b arg_0 */ GVariant *ret = g_dbus_proxy_call_sync(context->proxy, "hasEntry", g_variant_new("(isss)", wallet_handle, kwallet_folder, slot, app_id), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if(check_error(error)) { g_variant_unref(ret); return table; } GVariant *child = g_variant_get_child_value(ret, 0); has_entry = g_variant_get_boolean(child); g_variant_unref(child); g_variant_unref(ret); if(!has_entry) return table; /* signature: * * in i handle, * in s folder, * in s key, * in s appid, * * out a{sv} arg_0) */ ret = g_dbus_proxy_call_sync(context->proxy, "readMapList", g_variant_new("(isss)", wallet_handle, kwallet_folder, slot, app_id), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if(check_error(error)) { g_variant_unref(ret); return table; } child = g_variant_get_child_value(ret, 0); // we are only interested in the first child. i am not even sure that there can legally be more than one if(g_variant_n_children(child)<1) { g_variant_unref(child); g_variant_unref(ret); return table; } GVariant *element = g_variant_get_child_value(child, 0); GVariant *v = NULL; g_variant_get(element, "{sv}", NULL, &v); const gchar *byte_array = g_variant_get_data(v); if(!byte_array) { g_variant_unref(v); g_variant_unref(element); g_variant_unref(child); g_variant_unref(ret); return table; } int entries = GINT_FROM_BE(*((int*)byte_array)); byte_array += sizeof(gint); for(int i=0; i<entries; i++) { guint length; gchar* key = array2string(byte_array, &length); byte_array += length; gchar* value = array2string(byte_array, &length); byte_array += length; dt_print(DT_DEBUG_PWSTORAGE,"[pwstorage_kwallet_get] reading (%s, %s)\n",(gchar*)key, (gchar*)value); g_hash_table_insert(table, key, value); } g_variant_unref(v); g_variant_unref(element); g_variant_unref(child); g_variant_unref(ret); return table; }
// Get the (key,value) pairs back from KWallet. GHashTable* dt_pwstorage_kwallet_get(const gchar* slot) { _context = (backend_kwallet_context_t*)(darktable.pwstorage->backend_context); GHashTable *table = g_hash_table_new(g_str_hash, g_str_equal); GError* error = NULL; // Is there an entry in the wallet? gboolean has_entry = FALSE; int wallet_handle = get_wallet_handle(); dbus_g_proxy_call(_context->proxy, "hasEntry", &error, G_TYPE_INT, wallet_handle, // handle G_TYPE_STRING, kwallet_folder, // folder G_TYPE_STRING, slot, // key G_TYPE_STRING, app_id, // appid G_TYPE_INVALID, G_TYPE_BOOLEAN, &has_entry, G_TYPE_INVALID); if (CheckError(error) || !has_entry) return table; GArray* byte_array = NULL; dbus_g_proxy_call(_context->proxy, "readMap", &error, G_TYPE_INT, wallet_handle, // handle G_TYPE_STRING, kwallet_folder, // folder G_TYPE_STRING, slot, // key G_TYPE_STRING, app_id, // appid G_TYPE_INVALID, DBUS_TYPE_G_UCHAR_ARRAY, &byte_array, G_TYPE_INVALID); if (CheckError(error) || !byte_array || !byte_array->len) return table; gint entries; memcpy(&entries, byte_array->data, sizeof(gint)); entries = GINT_FROM_BE(entries); gchar* pos = byte_array->data + sizeof(gint); gint i; for(i=0; i<entries; ++i) { guint length; gchar* key = array2string(pos, &length); pos += length; gchar* value = array2string(pos, &length); pos += length; dt_print(DT_DEBUG_PWSTORAGE,"[pwstorage_kwallet_get] reading (%s, %s)\n",(gchar*)key, (gchar*)value); g_hash_table_insert(table, key, value); } g_array_free(byte_array, TRUE); return table; }