#include void handle_update(evapp_ctx *ctx) { char dbname[32]; HDF *hdf; evapp_db *db; uint64_t id; bool loaded = false, saved = false; struct app_settings *settings; struct evhttp_request *request = evapp_request(ctx); assert(request && ctx); settings = evapp_get_state(ctx); if (!settings) { send_error(ctx, "application state unavailable"); return; } if (request->type != EVHTTP_REQ_POST) { send_not_found(ctx, "Method disallowed for URI"); return; } if (!get_last_value_as_uint64(ctx, &id)) { send_not_found(ctx, "invalid object id"); return; } // returns a pointer back into the request object. if (!get_database_from_uri(request->uri, dbname, sizeof(dbname))) { send_not_found(ctx, "invalid object type"); return; } if (!parse_query((char *)EVBUFFER_DATA(request->input_buffer), EVBUFFER_LENGTH(request->input_buffer), false, false, &hdf, NULL)) { send_not_found(ctx, "failed to parse data"); return; } // Now check the xsrf token if (evapp_get_xsrf_protection(ctx)) { if (!check_xsrf(ctx, hdf_get_value(hdf, "token", NULL))) { hdf_destroy(&hdf); send_forbidden(ctx, "invalid or missing request token"); return; } } // Validate input ... hah! // Find our interface and call the loader. // Then merge and call the saver db = evapp_db_select(ctx, dbname); if (db && db->load && db->save) { HDF *old_hdf; loaded = db->load(ctx, id, &old_hdf); if (loaded && hdf_copy(old_hdf, NULL, hdf) == STATUS_OK) { /* Since we allow dupes, this is tricky. Need to delete first. */ db->del(ctx, id); saved = db->save(ctx, id, old_hdf); } if (loaded) hdf_destroy(&old_hdf); } if (!saved) { send_not_found(ctx, "unable to update object"); hdf_destroy(&hdf); return; } if (!template_render(ctx, hdf, "/update/", dbname)) send_created(ctx, dbname, id); hdf_destroy(&hdf); return; }