Skip to content

Commit

Permalink
Add context menu option to save transfer payload to a file.
Browse files Browse the repository at this point in the history
  • Loading branch information
martinling committed Oct 11, 2024
1 parent 4986c7b commit eda1b98
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ impl CaptureReader {
}
}

fn transaction_bytes(&mut self, transaction: &Transaction)
pub fn transaction_bytes(&mut self, transaction: &Transaction)
-> Result<Vec<u8>, Error>
{
let data_packet_id = transaction.data_packet_id
Expand Down
67 changes: 65 additions & 2 deletions src/ui.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::Write;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::time::{Duration, Instant};

Expand Down Expand Up @@ -75,6 +76,7 @@ use crate::capture::{
ItemSource,
TrafficItem,
TrafficViewMode::{self,*},
TransferId,
DeviceItem,
DeviceViewMode,
};
Expand Down Expand Up @@ -1182,14 +1184,75 @@ pub fn start_capture() -> Result<(), Error> {
})
}

fn traffic_context_menu(_item: &TrafficItem) -> Option<PopoverMenu> {
None
fn traffic_context_menu(item: &TrafficItem) -> Option<PopoverMenu> {
use TrafficItem::*;
match item {
Transfer(transfer_id) => {
let context_menu = Menu::new();
let save_payload_item = MenuItem::new(
Some("Save payload data..."),
Some("context.save-payload"));
context_menu.append_item(&save_payload_item);
let popover = PopoverMenu::from_model(Some(&context_menu));
let context_actions = SimpleActionGroup::new();
let id = *transfer_id;
let save_payload_action = ActionEntry::builder("save-payload")
.activate(move |_,_,_| display_error(choose_payload_file(id)))
.build();
context_actions.add_action_entries([save_payload_action]);
popover.insert_action_group("context", Some(&context_actions));
Some(popover)
},
_ => None
}
}

fn device_context_menu(_item: &DeviceItem) -> Option<PopoverMenu> {
None
}

fn choose_payload_file(transfer_id: TransferId) -> Result<(), Error> {
use FileAction::Save;
choose_file(Save, "payload file", move |file| save_payload(file, transfer_id))
}

fn save_payload(file: gio::File, transfer_id: TransferId)
-> Result<(), Error>
{
with_ui(|ui| {
let cap = &mut ui.capture;
let entry = cap.transfer_index.get(transfer_id)?;
let endpoint_id = entry.endpoint_id();
let ep_transfer_id = entry.transfer_id();
let ep_traf = cap.endpoint_traffic(endpoint_id)?;
let ep_transaction_range = ep_traf.transfer_index.target_range(
ep_transfer_id, ep_traf.transaction_ids.len())?;
let data_range = ep_traf.transfer_data_range(&ep_transaction_range)?;
let mut dest = file
.replace(None, false, FileCreateFlags::NONE, Cancellable::NONE)?
.into_write();
let mut length = 0;
for data_id in data_range {
let ep_traf = cap.endpoint_traffic(endpoint_id)?;
let ep_transaction_id = ep_traf.data_transactions.get(data_id)?;
let transaction_id = ep_traf.transaction_ids.get(ep_transaction_id)?;
let transaction = cap.transaction(transaction_id)?;
let transaction_bytes = cap.transaction_bytes(&transaction)?;
dest.write_all(&transaction_bytes)?;
length += transaction_bytes.len();
}
println!(
"Saved {} of payload data to {}",
fmt_size(length as u64),
file.basename()
.map_or(
"<unnamed>".to_string(),
|path| path.to_string_lossy().to_string())
);
Ok(())
})
}

fn show_about() -> Result<(), Error> {
const LICENSE: &str = include_str!("../LICENSE");
let about = AboutDialog::builder()
Expand Down

0 comments on commit eda1b98

Please sign in to comment.