package com.lauriewired.handlers.set;
import com.lauriewired.handlers.Handler;
import com.sun.net.httpserver.HttpExchange;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.util.Msg;
import javax.swing.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import static com.lauriewired.util.ParseUtils.parsePostParams;
import static com.lauriewired.util.ParseUtils.sendResponse;
import static ghidra.program.util.GhidraProgramUtilities.getCurrentProgram;
/**
* Handler for renaming data at a specific address in the current program.
* Expects POST parameters: "address" (the address of the data) and "newName"
* (the new name).
*/
public final class RenameData extends Handler {
/**
* Constructs a new RenameData handler.
*
* @param tool the PluginTool instance to use for program access
*/
public RenameData(PluginTool tool) {
super(tool, "/renameData");
}
/**
* Handles the HTTP request to rename data at a specified address.
* Expects POST parameters "address" and "newName".
*
* @param exchange the HttpExchange object containing the request
* @throws IOException if an I/O error occurs
*/
@Override
public void handle(HttpExchange exchange) throws IOException {
Map<String, String> params = parsePostParams(exchange);
String response = renameDataAtAddress(params.get("address"), params.get("newName"));
sendResponse(exchange, response);
}
/**
* Renames the data at the specified address in the current program.
* Protects data with names from the original symbol table (IMPORTED source).
* If the data exists, it updates its name; otherwise, it creates a new label.
*
* @param addressStr the address of the data as a string
* @param newName the new name for the data
* @return result message indicating success, protection, or failure
*/
private String renameDataAtAddress(String addressStr, String newName) {
Program program = getCurrentProgram(tool);
if (program == null)
return "No program loaded";
final StringBuilder result = new StringBuilder();
try {
SwingUtilities.invokeAndWait(() -> {
int tx = program.startTransaction("Rename data");
boolean success = false;
try {
Address addr = program.getAddressFactory().getAddress(addressStr);
if (addr == null) {
result.append("Invalid address: " + addressStr);
return;
}
SymbolTable symTable = program.getSymbolTable();
Symbol symbol = symTable.getPrimarySymbol(addr);
if (symbol != null) {
// Check if the symbol comes from the original symbol table
if (symbol.getSource() == SourceType.IMPORTED) {
result.append("Protected: Cannot rename data '" + symbol.getName() +
"' at " + addressStr + " - name comes from original symbol table (imported symbols are protected)");
return;
}
symbol.setName(newName, SourceType.USER_DEFINED);
result.append("Successfully renamed data at " + addressStr + " to '" + newName + "'");
success = true;
} else {
// No existing symbol, create new label
symTable.createLabel(addr, newName, SourceType.USER_DEFINED);
result.append("Successfully created new label '" + newName + "' at " + addressStr);
success = true;
}
} catch (Exception e) {
result.append("Error renaming data: " + e.getMessage());
Msg.error(this, "Rename data error", e);
} finally {
program.endTransaction(tx, success);
}
});
} catch (InterruptedException | InvocationTargetException e) {
return "Failed to execute rename data on Swing thread: " + e.getMessage();
}
return result.toString();
}
}