1 // Written in the D programming language. 2 3 /* Example application for SAP NetWeaver RFC 4 Reads a saplogon.ini file and creates a sapnwrfc.ini from the data. 5 */ 6 module createini; 7 8 private import std.string; 9 private import std.stdio; 10 private import std.traits : isSomeString; 11 12 import etc.c.sapnwrfc : RFC_CONNECTION_PARAMETER, cU; 13 import etc.c.sapuc : strlenU16; 14 15 enum VERSION = "0.1"; 16 17 /* 18 * Function to read the saplogon.ini file. 19 * 20 * For a description of the file format, please see https://service.sap.com/sap/support/notes/99435. 21 */ 22 23 // Parses the lines of the ini file 24 string[string][string] parse(string[] lines) 25 { 26 string[string][string] res; 27 auto section = ""; 28 29 foreach(line; lines) 30 { 31 line = line.strip; 32 33 // Ignore empty or comment lines 34 if (line.length == 0 || line.startsWith(";")) 35 continue; 36 37 // Start of new section? 38 if (line.startsWith("[") && line.endsWith("]")) 39 { 40 section = line[1..line.length-1]; 41 } 42 else 43 { 44 auto idx = line.indexOf('='); 45 if (idx < 1) 46 continue; // Ignore bad lines 47 48 auto key = line[0..idx].strip; 49 auto value = line[idx+1..line.length].strip; 50 res[section][key] = value; 51 } 52 } 53 54 return res; 55 } 56 57 // Maps the parsed values of the ini file to RFC_CONNECTION_PARAMETER values 58 RFC_CONNECTION_PARAMETER[][string] map(string[string][string] raw) 59 { 60 RFC_CONNECTION_PARAMETER[][string] res; 61 62 foreach (item, sysname; raw["MSSysName"]) 63 { 64 // Ignore systems without a "MSSysName" 65 if (sysname == "") 66 continue; 67 68 RFC_CONNECTION_PARAMETER[10] params; 69 int nextParam = 0; 70 71 void set(wstring param, string key) 72 { 73 auto val = raw[key][item]; 74 if (val.length) 75 { 76 params[nextParam++] = RFC_CONNECTION_PARAMETER(param.ptr, cU(val)); 77 } 78 } 79 80 params[nextParam++] = RFC_CONNECTION_PARAMETER("DEST"w.ptr, cU(sysname)); 81 auto origin = raw["Origin"][item]; 82 auto server = raw["Server"][item]; 83 if (origin == "MS_SEL_GROUPS") 84 { 85 set("GROUP", "Server"); 86 //set("MSHOST", "MSSrvName"); 87 // Assuming that "MSSysName" is always present 88 // set(Parameter.SYSID, "MSSysName"); 89 } 90 else //origin == "MS_SEL_SERVER" || origin == "USEREDIT" 91 { 92 set("ASHOST", "Server"); 93 // Assuming that "Database" is always present 94 // set(Parameter.SYSNR, "Database"); 95 } 96 set("SYSNR", "Database"); 97 set("MSHOST", "MSSrvName"); 98 set("MSSERV", "MSSrvPort"); 99 set("SAPROUTER", "Router"); 100 auto cpi = raw["CodepageIndex"][item]; 101 if (cpi.length > 0 && cpi != "-1") 102 set("CODEPAGE", "Codepage"); 103 auto sncChoice = raw["SncChoice"][item]; 104 if (sncChoice.length > 0 && sncChoice != "-1") 105 { 106 set("SNC_QOP", "SncChoice"); 107 set("SNC_PARTNERNAME", "SncName"); 108 set("SNC_SSO", raw["SncNoSSO"][item] == "0" ? "1" : "0"); 109 } 110 111 res[sysname] = params[0..nextParam].dup; 112 } 113 return res; 114 } 115 116 unittest 117 { 118 string[] lines = [ 119 "[Origin]", 120 "Item1=USEREDIT", 121 "; This is a comment!" 122 ]; 123 auto res = parse(lines); 124 assert("Origin" in res); 125 assert("Item1" in res["Origin"]); 126 assert(res["Origin"]["Item1"] == "USEREDIT"); 127 writeln("Success."); 128 } 129 130 void usage() 131 { 132 writefln("CreateIni V%s", VERSION); 133 writeln("\nUsage:"); 134 writeln(" createinit <SAPLOGONINI>"); 135 writeln("\nParameter:"); 136 writeln(" <SAPLOGONINI> Path to saplogon.ini"); 137 writeln("\nExample:"); 138 writeln(" createini C:\\Windows\\saplogon.ini"); 139 } 140 141 int main(string[] args) 142 { 143 if (args.length != 2) 144 { 145 usage(); 146 return 1; 147 } 148 149 import std.file : read; 150 auto rawcontent = read(args[1]); 151 version (Windows) 152 { 153 import core.sys.windows.windows; 154 import std.windows.syserror; 155 static import std.utf; 156 157 wchar[] result; 158 int readLen; 159 result.length = MultiByteToWideChar(CP_ACP, 0, cast(const(char)*)rawcontent.ptr, cast(int)rawcontent.length, null, 0); 160 if (result.length) 161 { 162 readLen = MultiByteToWideChar(CP_ACP, 0, cast(const(char)*)rawcontent.ptr, cast(int)rawcontent.length, result.ptr, cast(int)result.length); 163 } 164 if (!readLen || readLen != result.length) 165 { 166 throw new Exception("Couldn't convert string: " ~ sysErrorString(GetLastError())); 167 } 168 auto content = std.utf.toUTF8(result).split("\n"); 169 } 170 else 171 auto content = rawcontent.split("\n"); 172 173 auto config = map(parse(content)); 174 foreach (name, params; config) 175 { 176 foreach (param; params) 177 { 178 writefln("%s=%s", param.name[0..strlenU16(param.name)], param.value[0..strlenU16(param.value)]); 179 } 180 writeln(); 181 } 182 183 return 0; 184 }