Skip to content

Commit 5cded24

Browse files
committed
System Touch
1 parent 9a99e00 commit 5cded24

9 files changed

Lines changed: 180 additions & 3 deletions

File tree

bash/nwe-install.sh

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ echo " Moved $MOVED file(s)."
8383

8484
# ── 4. ClamAV install (Linux only) ───────────────────────────────────────────
8585
if [[ "$(uname -s)" == "Linux" ]]; then
86-
echo "[4/4] Checking ClamAV..."
86+
echo "[4/5] Checking ClamAV..."
8787
if command -v clamscan &>/dev/null; then
8888
echo " ClamAV already installed: $(clamscan --version 2>&1 | head -1)"
8989
else
@@ -103,7 +103,40 @@ if [[ "$(uname -s)" == "Linux" ]]; then
103103
fi
104104
fi
105105
else
106-
echo "[4/4] Non-Linux system detected — skipping ClamAV install."
106+
echo "[4/5] Non-Linux system detected — skipping ClamAV install."
107+
fi
108+
109+
# ── 5. Apache2 install (Linux only) ──────────────────────────────────────────
110+
NWE_APACHE_DIR="/var/www/html/nwe"
111+
if [[ "$(uname -s)" == "Linux" ]]; then
112+
echo "[5/5] Checking Apache2..."
113+
if command -v apache2 &>/dev/null || command -v httpd &>/dev/null; then
114+
echo " Apache2 already installed."
115+
else
116+
if command -v apt-get &>/dev/null; then
117+
echo " Installing Apache2 via apt-get (requires sudo)..."
118+
sudo apt-get install -y apache2
119+
sudo systemctl enable apache2
120+
sudo systemctl start apache2
121+
echo " Apache2 installed and started."
122+
elif command -v yum &>/dev/null; then
123+
echo " Installing Apache2 (httpd) via yum (requires sudo)..."
124+
sudo yum install -y httpd
125+
sudo systemctl enable httpd
126+
sudo systemctl start httpd
127+
echo " httpd installed and started."
128+
else
129+
echo " WARN: Cannot detect package manager — install Apache2 manually."
130+
fi
131+
fi
132+
echo " Ensuring NWE Apache directory: $NWE_APACHE_DIR"
133+
sudo mkdir -p "$NWE_APACHE_DIR"
134+
sudo chown -R www-data:www-data "$NWE_APACHE_DIR" 2>/dev/null \
135+
|| sudo chown -R apache:apache "$NWE_APACHE_DIR" 2>/dev/null || true
136+
sudo chmod -R 755 "$NWE_APACHE_DIR"
137+
echo " Done."
138+
else
139+
echo "[5/5] Non-Linux system detected — skipping Apache2 install."
107140
fi
108141

109142
echo ""

configuration/nwe-config.xml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,41 @@
166166
</description>
167167
</server>
168168

169+
<!-- ═══════════════════════════════════════════════════════════════════
170+
WEATHER SERVER
171+
════════════════════════════════════════════════════════════════════ -->
172+
<server id="WEATHER">
173+
<enabled>true</enabled>
174+
<name>WeatherServer</name>
175+
<thread>WeatherServer</thread>
176+
<host>localhost</host>
177+
<port>49133</port>
178+
<description>
179+
Telnet weather service. Send a city name or lat,lon; returns
180+
current conditions from wttr.in. Supports lang command.
181+
</description>
182+
</server>
183+
184+
<!-- ═══════════════════════════════════════════════════════════════════
185+
BINARY HTTP SERVER
186+
apache-root: Apache2 document root subdirectory for stored files.
187+
apache-url: Public base URL served by Apache2.
188+
════════════════════════════════════════════════════════════════════ -->
189+
<server id="BINARY_HTTP">
190+
<enabled>true</enabled>
191+
<name>BinaryHttpServer</name>
192+
<thread>BinaryHttpServer</thread>
193+
<host>localhost</host>
194+
<port>49144</port>
195+
<description>
196+
Binary data → HTTP link server. PUT: accepts length-prefixed binary,
197+
writes file to apache-root, returns HTTP URL.
198+
GET: downloads a URL, saves to apache-root, returns HTTP URL.
199+
</description>
200+
</server>
201+
<apache-root>/var/www/html/nwe</apache-root>
202+
<apache-url>http://localhost/nwe</apache-url>
203+
169204
<!-- ═══════════════════════════════════════════════════════════════════
170205
ANTIVIRUS SCANNER
171206
schedule: hourly | daily | weekly | monthly | yearly

logging/exceptions.log

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,3 +1811,17 @@ java.base/java.net.ServerSocket.bind(ServerSocket.java:326)
18111811
java.base/java.net.ServerSocket.<init>(ServerSocket.java:222)
18121812
server.nitro.ConnectionStatusServer.run(ConnectionStatusServer.java:58)
18131813
------------------------------------------------------------
1814+
[EXCEPTION] 2026-06-09T05:09:52.559519953Z
1815+
Type: java.nio.file.AccessDeniedException
1816+
Message: /var/www
1817+
Origin: java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
1818+
StackTrace:
1819+
java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
1820+
java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
1821+
java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
1822+
java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:418)
1823+
java.base/java.nio.file.Files.createDirectory(Files.java:647)
1824+
java.base/java.nio.file.Files.createAndCheckIsDirectory(Files.java:734)
1825+
java.base/java.nio.file.Files.createDirectories(Files.java:720)
1826+
http.BinaryHttpServer.run(BinaryHttpServer.java:52)
1827+
------------------------------------------------------------

scripts/startup.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@
44

55
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
66

7+
# Run as root if apache-root is under /var/www (requires root to create/write).
8+
# If already root, just exec directly.
9+
APACHE_DIR=$(grep -oP '(?<=<apache-root>)[^<]+' "$ROOT/configuration/nwe-config.xml" 2>/dev/null || echo "/var/www/html/nwe")
10+
11+
if [[ "$APACHE_DIR" == /var/www/* ]] && [[ "$(id -u)" -ne 0 ]]; then
12+
echo "[startup] Apache dir $APACHE_DIR requires root — restarting with sudo..."
13+
exec sudo java \
14+
-Xms512m \
15+
-Xmx4g \
16+
-XX:+UseG1GC \
17+
-XX:MaxGCPauseMillis=100 \
18+
-XX:G1HeapRegionSize=16m \
19+
-XX:+ParallelRefProcEnabled \
20+
-XX:+DisableExplicitGC \
21+
-cp "$ROOT/out" \
22+
Main
23+
fi
24+
725
exec java \
826
-Xms512m \
927
-Xmx4g \

source/Main.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ public Main()
135135
if (configuration.NweConfig.isEnabled("COMMUNICATOR"))
136136
NITRO.BRIDGE.COMMUNICATOR = new communicator.Communicator(COMMUNICATOR_HOST);
137137

138+
if (configuration.NweConfig.isEnabled("BINARY_HTTP"))
139+
NITRO.BRIDGE.BINARY_HTTP_SERVER = new http.BinaryHttpServer("localhost");
140+
141+
if (configuration.NweConfig.isEnabled("WEATHER"))
142+
NITRO.BRIDGE.WEATHER_SERVER = new weather.WeatherServer("localhost");
143+
138144
if (configuration.NweConfig.isEnabled("ANTIVIRUS"))
139145
new antivirus.AntivirusScanner(
140146
configuration.NweConfig.antivirusSchedule(),

source/configuration/NweConfig.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,23 @@ public static boolean isEnabled(final String SERVER_ID)
6161
public static String antivirusSchedule() { return get().ANTIVIRUS_SCHEDULE; }
6262
public static String antivirusScanPath() { return get().ANTIVIRUS_SCAN_PATH; }
6363

64+
/** Return the text content of the first top-level &lt;key&gt; element, or null. */
65+
public static String get(final String KEY)
66+
{
67+
if (INSTANCE == null) load();
68+
try
69+
{
70+
Document doc = DocumentBuilderFactory.newInstance()
71+
.newDocumentBuilder().parse(new File(CONFIG_FILE));
72+
doc.getDocumentElement().normalize();
73+
NodeList nl = doc.getDocumentElement().getElementsByTagName(KEY);
74+
if (nl.getLength() == 0) return null;
75+
String v = nl.item(0).getTextContent().trim();
76+
return v.isEmpty() ? null : v;
77+
}
78+
catch (Exception e) { return null; }
79+
}
80+
6481
/** Load (or reload) configuration from disk. Called once from Main(). */
6582
public static synchronized NweConfig load()
6683
{

source/heuristics/HeuristicClassifier.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ public class HeuristicClassifier
3434
6682, // Bitcoin WebExpress
3535
49155, // ConnectionStatusServer
3636
49188, // ModuleLoaderDaemon
37-
49199 // Communicator
37+
49199, // Communicator
38+
49144, // BinaryHttpServer
39+
49133 // WeatherServer
3840
// RSA / DSA ports resolved at runtime via NitroWebExpress.Aspect constants
3941
);
4042

source/server/nitro/NitroWebExpress.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ public static class Aspect
120120

121121
public communicator.Communicator COMMUNICATOR;
122122

123+
public http.BinaryHttpServer BINARY_HTTP_SERVER;
124+
125+
public weather.WeatherServer WEATHER_SERVER;
126+
123127
/** Start CONNECTION_STATUS and NitroWebExpress.SELF together. */
124128
public void start()
125129
{
@@ -130,6 +134,8 @@ public void start()
130134
if (ASCII_CREATOR_SERVER != null) ASCII_CREATOR_SERVER.start();
131135
if (MODULE_LOADER_DAEMON != null) MODULE_LOADER_DAEMON.start();
132136
if (COMMUNICATOR != null) COMMUNICATOR.start();
137+
if (BINARY_HTTP_SERVER != null) BINARY_HTTP_SERVER.start();
138+
if (WEATHER_SERVER != null) WEATHER_SERVER.start();
133139
if (NitroWebExpress.SELF != null) NitroWebExpress.SELF.start();
134140
}
135141

structure/STRUCTURE.txt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Source root: source/
77
PORT REGISTRY (authoritative reference)
88
================================================================================
99

10+
49133 WeatherServer Current weather by city or lat,lon (wttr.in)
11+
49144 BinaryHttpServer Binary data → HTTP link (PUT/GET to Apache2 dir)
1012
49152 NitroWebExpress (WebExpress) Telnet proxy / main entry point
1113
49155 ConnectionStatusServer Server health, geo, threads, live IPs
1214
49166 ModuleInstallationService Install / unload / manage NWE modules
@@ -28,6 +30,7 @@ ENTRY POINT
2830
Main (source/Main.java)
2931
Port constants:
3032
WEBEXPRESS_PORT = 49152
33+
BINARY_HTTP_SERVER_PORT = http.BinaryHttpServer.PORT (49144)
3134
AES2_WEBEXPRESS_SERVER_SOCKET = 5512
3235
BITCOIN_WEBEXPRESS_SERVER_SOCKET = 6682
3336
RSA_WEBEXPRESS_SERVER_SOCKET = NitroWebExpress.Aspect.RSACompliant.DEFAULT_PORT
@@ -51,6 +54,8 @@ Main (source/Main.java)
5154
ASCII_CREATOR → ASCIICreatorServer (49177)
5255
MODULE_LOADER_DAEMON → ModuleLoaderDaemon (49188)
5356
COMMUNICATOR → Communicator (49199)
57+
BINARY_HTTP → BinaryHttpServer (49144)
58+
WEATHER → WeatherServer (49133)
5459
ANTIVIRUS → AntivirusScanner (no port; scheduled daemon)
5560
MySQLComponent → N21Store init
5661
N21XmlFallback.replayFallback()
@@ -188,6 +193,45 @@ connections.logic.IPGeoParser IP → GeoInfo (city, country, region, lat, lon,
188193
connections.RecordedConnections / InternationalConnections / NationalConnections
189194
connections.GalacticConnections / MexicoConnections
190195

196+
================================================================================
197+
WEATHER SERVER (source/weather/)
198+
================================================================================
199+
200+
weather.WeatherServer (extends Thread, daemon) PORT = 49133
201+
Banner: "[ NWE port 49133 — Weather Service ]"
202+
Backend: wttr.in?format=3 (no API key; plain-text one-liner response)
203+
Commands:
204+
<city> Current weather for a city name (e.g. "Tokyo")
205+
<lat,lon> Current weather by coordinates (e.g. "35.68,139.69")
206+
lang <code> LanguagePack language switch
207+
help Show command list
208+
quit Disconnect
209+
210+
================================================================================
211+
BINARY HTTP SERVER (source/http/)
212+
================================================================================
213+
214+
http.BinaryHttpServer (extends Thread, daemon) PORT = 49144
215+
Apache dir: /var/www/html/nwe (override via <apache-root> in nwe-config.xml)
216+
Public URL: http://localhost/nwe (override via <apache-url> in nwe-config.xml)
217+
218+
Protocol (raw TCP, newline-framed header then binary payload):
219+
220+
PUT <filename>\n
221+
<4-byte big-endian length><binary bytes>
222+
→ writes file to apache-root/<8-char-uuid>-<filename>
223+
→ returns: OK http://localhost/nwe/<uuid>-<filename>
224+
225+
GET <url>\n
226+
→ downloads http/https URL (10s connect / 30s read timeout)
227+
→ saves to apache-root/<8-char-uuid>-<basename>
228+
→ returns: OK http://localhost/nwe/<uuid>-<basename>
229+
230+
Security:
231+
- Only http/https GET URLs accepted (no file://, no arbitrary schemes)
232+
- Filenames stripped to [a-zA-Z0-9._-] via safeName()
233+
- Path.getFileName() used to prevent directory traversal on both PUT and GET
234+
191235
================================================================================
192236
COMMUNICATOR (source/communicator/)
193237
================================================================================
@@ -398,6 +442,8 @@ NWE opens 10 public TCP ports at startup (all gated by nwe-config.xml):
398442

399443
PORT SERVICE PURPOSE
400444
───── ──────────────────────── ─────────────────────────────────────────────
445+
49133 WeatherServer Current weather by city or lat,lon via wttr.in
446+
49144 BinaryHttpServer Binary → HTTP link; PUT binary or GET URL → Apache2 dir
401447
49152 NitroWebExpress Main entry; telnet proxy; AES/BTC bridge hub
402448
5512 AESCompliant AES 2.0 DSS 5.0 encryption sub-server
403449
6682 BitcoinCompliant Bitcoin lightweight trading sub-server

0 commit comments

Comments
 (0)