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.listing.Function;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.SourceType;
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 a function in the current program.
* Expects POST parameters: oldName and newName.
*/
public final class RenameFunction extends Handler {
/**
* Constructor for RenameFunction handler.
*
* @param tool the PluginTool instance to interact with Ghidra
*/
public RenameFunction(PluginTool tool) {
super(tool, "/renameFunction");
}
/**
* Handles the HTTP request to rename a function.
* Expects parameters "oldName" and "newName" in the POST request.
*
* @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 = rename(params.get("oldName"), params.get("newName"));
sendResponse(exchange, response);
}
/**
* Renames a function in the current program.
* Functions with names from the original symbol table (IMPORTED source) are protected and cannot be renamed.
*
* @param oldName the current name of the function
* @param newName the new name to set for the function
* @return result message indicating success, protection, or failure
*/
private String rename(String oldName, 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 function via HTTP");
boolean success = false;
try {
Function foundFunc = null;
for (Function func : program.getFunctionManager().getFunctions(true)) {
if (func.getName().equals(oldName)) {
foundFunc = func;
break;
}
}
if (foundFunc == null) {
result.append("Function '" + oldName + "' not found");
return;
}
// Check if the function name comes from the original symbol table
if (foundFunc.getSymbol().getSource() == SourceType.IMPORTED) {
result.append("Protected: Cannot rename function '" + oldName +
"' - name comes from original symbol table (imported symbols are protected)");
return;
}
foundFunc.setName(newName, SourceType.USER_DEFINED);
result.append("Successfully renamed function '" + oldName + "' to '" + newName + "'");
success = true;
} catch (Exception e) {
result.append("Error renaming function: " + e.getMessage());
Msg.error(this, "Error renaming function", e);
} finally {
program.endTransaction(tx, success);
}
});
} catch (InterruptedException | InvocationTargetException e) {
return "Failed to execute rename on Swing thread: " + e.getMessage();
}
return result.toString();
}
}