Add AI prompt support in the source

parent ac3b4252
- If you need to rebuild the project, use always ./build.sh --clean && ./build.sh
- if you need to build the debian packages, use ./build.sh --debian
- when you finish a todo list and everything is complete, execute a git commit
- the html pages and the assets to add in wssshd are generated from the templates directory, using the script embed_assets.sh.
- the script embed_assets.sh is launched by the Makefile
- the Makefile is generated by the script configure.sh
- in wssshd webinterface, the vnc page and the rdp page uses different websocket implementation, looks at the specifics of web.c and vnc.c or rdp.c, the file websocket.c is user ALSO for the websockets in the communication port with wssshc and wsssht, if you modify something for vnc or rdp or anything in the web interface, don't break the implementation for the wssshc-wssshd-wsssht communication channel/protocol
......@@ -29,6 +29,8 @@
#include "html_pages/mstsc_page.h"
#include "html_pages/novnc_css_page.h"
#include "novnc_asset_map.c"
#include "rdp_assets.h"
#include "rdp_asset_map.c"
// HTML pages are now defined in separate header files in html_pages/ directory
// This file now only contains fallback definitions for compatibility
......@@ -76,6 +78,9 @@ const char *get_embedded_asset(const char *path, size_t *size) {
const char *content = get_novnc_asset(path);
if (content && size) *size = strlen(content);
return content;
} else if (strncmp(path, "/rdp/", 5) == 0) {
const char *content = get_rdp_asset(path, size);
return content;
}
return NULL;
......
......@@ -225,6 +225,75 @@ static const char *mstsc_js = "";
EOF
fi
# Embed RDP JS files
echo "Embedding RDP JS files..."
mkdir -p html_pages
# Generate rdp_assets.h
cat > rdp_assets.h << 'EOF'
#ifndef RDP_ASSETS_H
#define RDP_ASSETS_H
EOF
# Generate rdp_asset_map.c
cat > rdp_asset_map.c << 'EOF'
#include <string.h>
#include "rdp_assets.h"
const char *get_rdp_asset(const char *path, size_t *size) {
EOF
find templates/rdp -name "*.wasm" | sort | while read -r file; do
if [ -f "$file" ]; then
RELPATH=$(echo "$file" | sed 's|templates/rdp/||')
VARNAME=$(echo "$RELPATH" | sed 's|/|_|g; s|\.wasm$|_wasm|; s|\.|_|g')
HEADER_FILE="html_pages/rdp_${VARNAME}_page.h"
echo "Embedding $file as rdp_${VARNAME}"
# Create header with extern
cat > "$HEADER_FILE" << EOF
#ifndef RDP_${VARNAME^^}_PAGE_H
#define RDP_${VARNAME^^}_PAGE_H
extern const unsigned char rdp_${VARNAME}[];
extern const unsigned int rdp_${VARNAME}_len;
#endif /* RDP_${VARNAME^^}_PAGE_H */
EOF
# Add to rdp_assets.h
echo "#include \"html_pages/rdp_${VARNAME}_page.h\"" >> rdp_assets.h
# Embed binary file
xxd -i "$file" > temp_binary.h
# Rename the variables and add static
sed -i "s/templates_rdp_rdp_wasm/rdp_rdp_wasm/g" temp_binary.h
sed -i "s/unsigned char rdp_rdp_wasm\[\]/static unsigned char rdp_rdp_wasm[]/g" temp_binary.h
sed -i "s/unsigned int rdp_rdp_wasm_len/static unsigned int rdp_rdp_wasm_len/g" temp_binary.h
cat temp_binary.h >> rdp_asset_map.c
rm temp_binary.h
# Add to rdp_asset_map.c
echo " if (strcmp(path, \"/rdp/$RELPATH\") == 0) {" >> rdp_asset_map.c
echo " if (size) *size = rdp_${VARNAME}_len;" >> rdp_asset_map.c
echo " return (const char *)rdp_${VARNAME};" >> rdp_asset_map.c
echo " }" >> rdp_asset_map.c
fi
done
cat >> rdp_assets.h << 'EOF'
#endif /* RDP_ASSETS_H */
EOF
cat >> rdp_asset_map.c << 'EOF'
return NULL;
}
EOF
echo "RDP JS files embedded."
# Embed noVNC CSS
if [ -f templates/novnc.css ]; then
echo "Embedding novnc.css..."
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -18,8 +18,8 @@
#include "html_pages/novnc_input_fixedkeys_js_page.h"
#include "html_pages/novnc_input_gesturehandler_js_page.h"
#include "html_pages/novnc_input_keyboard_js_page.h"
#include "html_pages/novnc_input_keysymdef_js_page.h"
#include "html_pages/novnc_input_keysym_js_page.h"
#include "html_pages/novnc_input_keysymdef_js_page.h"
#include "html_pages/novnc_input_util_js_page.h"
#include "html_pages/novnc_input_vkeys_js_page.h"
#include "html_pages/novnc_input_xtscancodes_js_page.h"
......
......@@ -7,7 +7,12 @@
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<script src="/mstsc.js"></script>
<script src="/rdp/rdp.wasm.js"></script>
<script src="/rdp/clipboard.js"></script>
<script src="/rdp/out_stream.js"></script>
<script src="/rdp/rdp_graphics.js"></script>
<script src="/rdp/reversed_layouts.js"></script>
<script src="/rdp/scancodes.js"></script>
<style>
.navbar-brand {
font-weight: bold;
......@@ -26,7 +31,7 @@
max-height: none;
height: auto;
}
.rdp-container.full-size #mstsc_screen {
.rdp-container.full-size #canvas {
min-width: fit-content;
min-height: fit-content;
}
......@@ -129,10 +134,18 @@
.rdp-window.fullscreen .minimize-btn {
display: flex;
}
#mstsc_screen {
#canvas {
width: 100%;
height: 100%;
}
#canvasFocus {
width: 0px;
height: 0px;
position: absolute;
z-index: -10;
padding: 0;
margin: 0;
}
</style>
</head>
<body>
......@@ -170,9 +183,9 @@
</div>
<div class="window-content">
<div id="rdp" class="rdp-container w-100">
<div id="mstsc_screen">
<div id="mstsc_status">Click Connect to start RDP session</div>
<div id="mstsc_loading" style="display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #f8f8f2;">
<canvas id="canvas" width="1024" height="768"></canvas><input id="canvasFocus" type="text"/>
<div id="rdp_status" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #f8f8f2;">Click Connect to start RDP session</div>
<div id="rdp_loading" style="display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #f8f8f2;">
<div class="spinner-border text-primary mb-2" role="status">
<span class="visually-hidden">Loading...</span>
</div>
......@@ -185,13 +198,13 @@
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
let rdp = null;
let rdpclient = null;
let socket = null;
let connected = false;
document.getElementById('connectBtn').addEventListener('click', connect);
......@@ -204,6 +217,10 @@ document.querySelector('.maximize-btn').addEventListener('click', toggleFullscre
document.querySelector('.minimize-btn').addEventListener('click', toggleFullscreen);
document.getElementById('zoomBtn').addEventListener('click', toggleZoom);
// Input event handlers
let ecanvas = document.getElementById('canvas');
let ecanvasFocus = document.getElementById('canvasFocus');
function showNotification(message, type = 'info') {
const notificationArea = document.getElementById('notification-area');
const notification = document.createElement('div');
......@@ -236,7 +253,7 @@ function toggleFullscreen() {
}
function toggleZoom() {
if (!rdp || !connected) return;
if (!rdpclient || !connected) return;
const zoomBtn = document.getElementById('zoomBtn');
const zoomIcon = zoomBtn.querySelector('i');
......@@ -249,6 +266,11 @@ function toggleZoom() {
zoomIcon.className = 'fas fa-search-plus';
rdpContainer.classList.remove('full-size');
// Enable scaling, disable clipping
if (rdpclient.scaleViewport !== undefined) {
rdpclient.scaleViewport = true;
}
showNotification('Switched to scaled view (fit to window)', 'info');
} else {
// Switch to full-size view with scrollbars
......@@ -257,6 +279,11 @@ function toggleZoom() {
zoomIcon.className = 'fas fa-search-minus';
rdpContainer.classList.add('full-size');
// Disable scaling, enable clipping
if (rdpclient.scaleViewport !== undefined) {
rdpclient.scaleViewport = false;
}
showNotification('Switched to actual size view with scrollbars', 'info');
}
}
......@@ -265,68 +292,92 @@ function connect() {
if (connected) return;
// Hide the status text and show loading message
document.getElementById('mstsc_status').style.display = 'none';
document.getElementById('mstsc_loading').style.display = 'block';
document.getElementById('rdp_status').style.display = 'none';
document.getElementById('rdp_loading').style.display = 'block';
document.getElementById('cancelConnectBtn').style.display = 'inline-block';
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = wsProtocol + '//' + window.location.host + '/rdp/%s/ws';
try {
rdp = new Mstsc(document.getElementById('mstsc_screen'), {
url: wsUrl,
socket = new WebSocket(wsUrl);
socket.binaryType = 'arraybuffer';
socket.onopen = () => {
const canvas = document.getElementById('canvas');
const gd = new GraphicsDevice(canvas);
const config = {
width: 1024,
height: 768,
domain: '',
username: '',
password: '',
keyboard: true,
mouse: true,
clipboard: true
});
rdp.addEventListener('connect', () => {
domain: '',
bpp: 32,
verbosity: 0
};
rdpclient = new RdpClient(gd, config);
rdpclient.writeFirstPacket();
sendData();
connected = true;
document.getElementById('connectBtn').disabled = true;
document.getElementById('disconnectBtn').disabled = false;
// Hide loading message
document.getElementById('mstsc_loading').style.display = 'none';
document.getElementById('rdp_loading').style.display = 'none';
showNotification('RDP session connected', 'success');
});
};
socket.onmessage = (event) => {
rdpclient.processInputData(event.data);
sendData();
};
rdp.addEventListener('disconnect', () => {
socket.onclose = () => {
connected = false;
document.getElementById('connectBtn').disabled = false;
document.getElementById('disconnectBtn').disabled = true;
// Reset UI to initial state
document.getElementById('mstsc_status').style.display = 'block';
document.getElementById('mstsc_loading').style.display = 'none';
document.getElementById('rdp_status').style.display = 'block';
document.getElementById('rdp_loading').style.display = 'none';
document.getElementById('cancelConnectBtn').style.display = 'none';
showNotification('RDP session disconnected', 'info');
});
rdpclient = null;
socket = null;
};
rdp.addEventListener('error', (e) => {
console.error('RDP error:', e.detail);
showNotification('RDP error: ' + e.detail, 'danger');
});
socket.onerror = (e) => {
console.error('RDP WebSocket error:', e);
showNotification('RDP connection error', 'danger');
};
} catch (e) {
console.error('Failed to create RDP client:', e);
showNotification('Failed to connect RDP: ' + e.message, 'danger');
}
function sendData() {
if (socket && socket.readyState === WebSocket.OPEN && rdpclient) {
const data = rdpclient.getOutputData();
if (data && data.length > 0) {
socket.send(data);
}
}
}
}
function disconnect() {
if (rdp) {
rdp.disconnect();
rdp = null;
if (socket) {
socket.close();
socket = null;
}
if (rdpclient) {
rdpclient = null;
}
connected = false;
document.getElementById('connectBtn').disabled = false;
document.getElementById('disconnectBtn').disabled = true;
// Reset UI to initial state
document.getElementById('mstsc_status').style.display = 'block';
document.getElementById('mstsc_loading').style.display = 'none';
document.getElementById('rdp_status').style.display = 'block';
document.getElementById('rdp_loading').style.display = 'none';
document.getElementById('cancelConnectBtn').style.display = 'none';
setTimeout(() => {
location.reload();
......@@ -334,16 +385,19 @@ function disconnect() {
}
function cancelConnect() {
if (rdp) {
rdp.disconnect();
rdp = null;
if (socket) {
socket.close();
socket = null;
}
if (rdpclient) {
rdpclient = null;
}
connected = false;
document.getElementById('connectBtn').disabled = false;
document.getElementById('disconnectBtn').disabled = true;
// Reset UI to initial state
document.getElementById('mstsc_status').style.display = 'block';
document.getElementById('mstsc_loading').style.display = 'none';
document.getElementById('rdp_status').style.display = 'block';
document.getElementById('rdp_loading').style.display = 'none';
document.getElementById('cancelConnectBtn').style.display = 'none';
showNotification('RDP connection cancelled', 'warning');
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment