package gargl.generators; import gargl.typedefinitions.Function; import gargl.utilities.Parameter; import java.util.Set; import java.util.List; import java.util.Map; public class PowerShellModuleGenerator extends Generator { private static String POWERSHELL_MAKE_REQUEST_FORMAT = "\tif($WebSession) {\n" + "\t\tInvoke-WebRequest -Uri $url -Headers $headers -Body $body -Method $method -WebSession $WebSession\n" + "\t}\n" + "\telse {\n" + "\t\tInvoke-WebRequest -Uri $url -Headers $headers -Body $body -Method $method -SessionVariable $SessionVariable\n" + "\t\tInvoke-Expression \"`$global:$SessionVariable = `$$SessionVariable\"\n" + "\t}"; private static String POWERSHELL_KEYVALUE_FORMAT = "\t\t\"%1$s\" = %2$s;\n"; private static String POWERSHELL_REQUEST_STRING_CONCAT_FORMAT = " + \"&%1$s=\" + [System.Web.HttpUtility]::UrlEncode(%2$s)"; private static String POWERSHELL_VARIABLE_FORMAT = "$%1$s"; private static String POWERSHELL_STRING_VARIABLE_DECLARATION_FORMAT = "$%1$s = \"%2$s\"\n\n"; private static String POWERSHELL_CODE_VARIABLE_DECLARATION_FORMAT = "\t$%1$s = %2$s\n\n"; private static String POWERSHELL_MODULE_FORMAT = "Add-Type -AssemblyName System.Web\n\n" + "%1$s\n" + "Export-ModuleMember %2$s"; private static String POWERSHELL_FUNCTION_FORMAT = "function %1$s {\n" + "\t%2$s\n\n" + "\tif(!$SessionVariable) { $SessionVariable = \"_session\" }\n\n" + "\t%3$s\n" + "}\n\n"; private static String POWERSHELL_FUNCTION_NAME_FORMAT = "Invoke-%1$s%2$s"; private static String POWERSHELL_PARAMETER_FORMAT = "\n\t\t[Parameter(Mandatory=$%3$s)][%1$s] $%2$s"; public String generateFunction(String moduleName, Function function) { Set<Parameter> parameters = function.getParameters(); StringBuilder parametersSB = new StringBuilder("param("); for(Parameter parameter : parameters) { parametersSB.append(String.format(POWERSHELL_PARAMETER_FORMAT, "string", parameter.getParameterName(), "true")); parametersSB.append(","); } parametersSB.append(String.format(POWERSHELL_PARAMETER_FORMAT, "string", "SessionVariable", "false") + ","); parametersSB.append(String.format(POWERSHELL_PARAMETER_FORMAT, "Microsoft.PowerShell.Commands.WebRequestSession", "WebSession", "false")); parametersSB.append("\n\t)"); StringBuilder functionBodySB = new StringBuilder(""); functionBodySB.append(String.format(POWERSHELL_STRING_VARIABLE_DECLARATION_FORMAT, "method", function.getMethod())); Map<String,String> headers = function.getHeaders(); StringBuilder headersStringSB = new StringBuilder("@{\n"); for(String headerKey : headers.keySet()) { if(headerKey.equalsIgnoreCase("Connection")) continue; headersStringSB.append(String.format(POWERSHELL_KEYVALUE_FORMAT, headerKey, Parameter.processParameter(headers.get(headerKey).replace("\"","`\""), function, POWERSHELL_VARIABLE_FORMAT))); } headersStringSB.append("\t}"); functionBodySB.append(String.format(POWERSHELL_CODE_VARIABLE_DECLARATION_FORMAT, "headers", headersStringSB.toString())); Map<String,String> queryString = function.getQueryString(); StringBuilder queryStringSB = new StringBuilder("\"?\""); for(String queryStringKey : queryString.keySet()) { queryStringSB.append(String.format(POWERSHELL_REQUEST_STRING_CONCAT_FORMAT, queryStringKey, Parameter.processParameter(queryString.get(queryStringKey).replace("\"","`\""), function, POWERSHELL_VARIABLE_FORMAT))); } functionBodySB.append(String.format(POWERSHELL_CODE_VARIABLE_DECLARATION_FORMAT, "queryString", queryStringSB.toString())); Map<String,String> postData = function.getPostData(); StringBuilder postDataSB = new StringBuilder("@{\n"); for(String postDataKey : postData.keySet()) { postDataSB.append(String.format(POWERSHELL_KEYVALUE_FORMAT, postDataKey, Parameter.processParameter(postData.get(postDataKey).replace("\"","`\""), function, POWERSHELL_VARIABLE_FORMAT))); } postDataSB.append("\t}"); functionBodySB.append(String.format(POWERSHELL_CODE_VARIABLE_DECLARATION_FORMAT, "body", postDataSB.toString())); List<String> urlParts = Parameter.processURLParameters(function.getUrl(), function, POWERSHELL_VARIABLE_FORMAT); StringBuilder urlStringSB = new StringBuilder(); for(String urlPart : urlParts) { urlStringSB.append(urlPart); urlStringSB.append(" + "); } urlStringSB.append("$queryString"); functionBodySB.append(String.format(POWERSHELL_CODE_VARIABLE_DECLARATION_FORMAT, "url", urlStringSB.toString())); functionBodySB.append(String.format(POWERSHELL_MAKE_REQUEST_FORMAT, function.getMethod())); String functionName = String.format(POWERSHELL_FUNCTION_NAME_FORMAT, moduleName, function.getFunctionName()); return String.format(POWERSHELL_FUNCTION_FORMAT, functionName, parametersSB.toString(), functionBodySB.toString()); } @Override public void generateClass(String outputLocation) { String moduleName = this.module.name; if(this.module.name == null || this.module.name.isEmpty()){ moduleName = "gargl_output"; System.out.println("WARNING: No module name given, module name defaulting to " + moduleName); } StringBuilder functionsSB = new StringBuilder(); for (Function function : this.module.functions) { functionsSB.append(generateFunction(moduleName, function)); System.out.println("LOG: Function " + function.getFunctionName() + " created"); } String moduleMembersString = generateModuleMembersDeclaration(moduleName, this.module.functions); // File name is currently forced to be the same as module name writeFile(outputLocation + moduleName + ".psm1", String.format(POWERSHELL_MODULE_FORMAT, functionsSB.toString(), moduleMembersString) ); } private String generateModuleMembersDeclaration(String moduleName, List<Function> functions) { StringBuilder moduleMembersDeclarationSB = new StringBuilder(); for (int i = 0; i < functions.size(); i ++) { moduleMembersDeclarationSB.append(String.format(POWERSHELL_FUNCTION_NAME_FORMAT, moduleName, functions.get(i).getFunctionName())); if(i != functions.size() - 1) moduleMembersDeclarationSB.append(", "); } return moduleMembersDeclarationSB.toString(); } }