Skip to content

Commit 9918016

Browse files
committed
System Touch
1 parent 85be8d5 commit 9918016

2 files changed

Lines changed: 155 additions & 8 deletions

File tree

‎source/database/N21Store.java‎

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,89 @@ public static void storeStatusSnapshot(final int ACTIVECONNECTIONS, final long U
894894
"used_memory_mb", String.valueOf(USEDMB));
895895
}
896896

897+
// ── user_proxy_selections ─────────────────────────────────────────────────
898+
899+
public static void createUserProxySelectionsTable()
900+
{
901+
if (!dbOk()) return;
902+
try
903+
{
904+
java.sql.Statement st = N21DataSource.get().createStatement();
905+
st.executeUpdate(
906+
"CREATE TABLE IF NOT EXISTS user_proxy_selections (" +
907+
" id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY," +
908+
" national_id BIGINT UNSIGNED NOT NULL," +
909+
" proxy_host VARCHAR(255) NOT NULL," +
910+
" proxy_port INT UNSIGNED NOT NULL," +
911+
" active TINYINT(1) NOT NULL DEFAULT 1," +
912+
" created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP," +
913+
" updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
914+
" UNIQUE KEY uq_national_proxy (national_id)" +
915+
") ENGINE=InnoDB");
916+
st.close();
917+
}
918+
catch (Exception e) { fail("user_proxy_selections", e); }
919+
}
920+
921+
public static void storeProxySelection(final long NATIONAL_ID, final String HOST, final int PORT)
922+
{
923+
if (dbOk())
924+
{
925+
try
926+
{
927+
PreparedStatement ps = N21DataSource.get().prepareStatement(
928+
"INSERT INTO user_proxy_selections (national_id, proxy_host, proxy_port) VALUES (?,?,?) " +
929+
"ON DUPLICATE KEY UPDATE proxy_host=VALUES(proxy_host), proxy_port=VALUES(proxy_port), active=1");
930+
ps.setLong(1, NATIONAL_ID);
931+
ps.setString(2, HOST);
932+
ps.setInt(3, PORT);
933+
ps.executeUpdate(); ps.close();
934+
return;
935+
}
936+
catch (Exception e) { fail("user_proxy_selections", e); }
937+
}
938+
N21XmlFallback.append("user_proxy_selections",
939+
"national_id", String.valueOf(NATIONAL_ID), "proxy_host", HOST, "proxy_port", String.valueOf(PORT));
940+
}
941+
942+
public static String[] loadProxySelection(final long NATIONAL_ID)
943+
{
944+
if (dbOk())
945+
{
946+
try
947+
{
948+
PreparedStatement ps = N21DataSource.get().prepareStatement(
949+
"SELECT proxy_host, proxy_port FROM user_proxy_selections WHERE national_id=? AND active=1");
950+
ps.setLong(1, NATIONAL_ID);
951+
java.sql.ResultSet rs = ps.executeQuery();
952+
if (rs.next())
953+
{
954+
String[] result = { rs.getString("proxy_host"), String.valueOf(rs.getInt("proxy_port")) };
955+
rs.close(); ps.close();
956+
return result;
957+
}
958+
rs.close(); ps.close();
959+
}
960+
catch (Exception e) { fail("user_proxy_selections", e); }
961+
}
962+
return null;
963+
}
964+
965+
public static void clearProxySelection(final long NATIONAL_ID)
966+
{
967+
if (dbOk())
968+
{
969+
try
970+
{
971+
PreparedStatement ps = N21DataSource.get().prepareStatement(
972+
"UPDATE user_proxy_selections SET active=0 WHERE national_id=?");
973+
ps.setLong(1, NATIONAL_ID);
974+
ps.executeUpdate(); ps.close();
975+
}
976+
catch (Exception e) { fail("user_proxy_selections", e); }
977+
}
978+
}
979+
897980
// ── helpers ───────────────────────────────────────────────────────────────
898981

899982
/** Returns true only if a live DB connection can be obtained. */

‎source/national/NationalFinanceIDFeeder.java‎

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ public static NationalFinanceID greet(final Connection CONN)
161161

162162
private static void financePrompt(final Connection CONN, final NationalFinanceID NFID)
163163
{
164+
// Ensure proxy table exists
165+
N21Store.createUserProxySelectionsTable();
166+
164167
write(CONN, "National ID Finance");
165168
write(CONN, "");
166169

@@ -175,6 +178,23 @@ private static void financePrompt(final Connection CONN, final NationalFinanceID
175178
cryptoPrompt(CONN, NFID);
176179
write(CONN, line + " < Returned from crypto management.");
177180
}
181+
else if (input.trim().toLowerCase().startsWith("set proxy"))
182+
{
183+
write(CONN, line + " < " + handleSetProxy(CONN, input, NFID));
184+
}
185+
else if (input.trim().toLowerCase().startsWith("clear proxy"))
186+
{
187+
N21Store.clearProxySelection(NFID.nationalId);
188+
write(CONN, line + " < Proxy cleared. Using default (localhost).");
189+
}
190+
else if (input.trim().toLowerCase().startsWith("show proxy"))
191+
{
192+
String[] sel = N21Store.loadProxySelection(NFID.nationalId);
193+
if (sel != null)
194+
write(CONN, line + " < Proxy: " + sel[0] + ":" + sel[1]);
195+
else
196+
write(CONN, line + " < No proxy set (using default localhost).");
197+
}
178198
else
179199
{
180200
write(CONN, line + " < " + trade(input, NFID));
@@ -183,6 +203,47 @@ private static void financePrompt(final Connection CONN, final NationalFinanceID
183203
}
184204
}
185205

206+
/**
207+
* Handles "set proxy <host> <port>" — validates host resolves and port is connectable,
208+
* stores in MySQL if OK, otherwise falls back to default.
209+
*/
210+
private static String handleSetProxy(final Connection CONN, final String INPUT, final NationalFinanceID NFID)
211+
{
212+
// Parse: "set proxy host port"
213+
String[] parts = INPUT.trim().split("\\s+");
214+
if (parts.length < 4)
215+
return "Usage: set proxy <host> <port>";
216+
217+
String host = parts[2];
218+
int port;
219+
try { port = Integer.parseInt(parts[3]); }
220+
catch (NumberFormatException e) { return "Invalid port number: " + parts[3]; }
221+
222+
if (port < 1 || port > 65535)
223+
return "Port must be 1–65535.";
224+
225+
// Validate host resolves
226+
try { java.net.InetAddress.getByName(host); }
227+
catch (java.net.UnknownHostException e)
228+
{
229+
return "✗ Host '" + host + "' does not resolve. Keeping default.";
230+
}
231+
232+
// Validate port is connectable (2s timeout)
233+
try (java.net.Socket test = new java.net.Socket())
234+
{
235+
test.connect(new java.net.InetSocketAddress(host, port), 2000);
236+
}
237+
catch (Exception e)
238+
{
239+
return "✗ Cannot connect to " + host + ":" + port + " — " + e.getMessage() + ". Keeping default.";
240+
}
241+
242+
// Store selection
243+
N21Store.storeProxySelection(NFID.nationalId, host, port);
244+
return "✔ Proxy set to " + host + ":" + port + " (verified reachable). Stored.";
245+
}
246+
186247
/**
187248
* Produce a trading-context reply for the given input.
188249
* Recognises basic directives; anything else echoes a market acknowledgement.
@@ -205,14 +266,17 @@ private static String trade(final String INPUT, final NationalFinanceID NFID)
205266
"\r\n" +
206267
" Commands\r\n" +
207268
" ────────────────────────────────────────────────────\r\n" +
208-
" buy <amount> Place a BUY order on the market\r\n" +
209-
" sell <amount> Place a SELL order on the market\r\n" +
210-
" balance Show your promissory note balance (USD)\r\n" +
211-
" id Show your National ID and profile summary\r\n" +
212-
" status Show full account status and trust level\r\n" +
213-
" crypto Manage cryptographic keys (RSA/DSA/AES)\r\n" +
214-
" help Show this command list\r\n" +
215-
" quit / exit End this session\r\n" +
269+
" buy <amount> Place a BUY order on the market\r\n" +
270+
" sell <amount> Place a SELL order on the market\r\n" +
271+
" balance Show your promissory note balance (USD)\r\n" +
272+
" id Show your National ID and profile summary\r\n" +
273+
" status Show full account status and trust level\r\n" +
274+
" crypto Manage cryptographic keys (RSA/DSA/AES)\r\n" +
275+
" set proxy <host> <port> Set remote proxy (validated before storing)\r\n" +
276+
" show proxy Show current proxy selection\r\n" +
277+
" clear proxy Reset proxy to default (localhost)\r\n" +
278+
" help Show this command list\r\n" +
279+
" quit / exit End this session\r\n" +
216280
" ────────────────────────────────────────────────────";
217281

218282
// ─────────────────────────────────────────────────────────────────────────

0 commit comments

Comments
 (0)