11import { IPty } from '@homebridge/node-pty-prebuilt-multiarch' ;
2+ import * as fs from 'node:fs/promises' ;
23import { Server as HttpServer , IncomingMessage } from 'node:http' ;
4+ import os from 'node:os' ;
5+ import path from 'node:path' ;
36import { Duplex } from 'node:stream' ;
47import { v4 as uuid } from 'uuid' ;
58import WebSocket , { WebSocketServer } from 'ws' ;
@@ -122,10 +125,17 @@ export class SocketServer {
122125 this . mainConnections . set ( clientId , ws ) ;
123126 ws . send ( JSON . stringify ( { key : 'opened' , data : { clientId, startTimestamp : this . startTimestamp . toISOString ( ) } } ) ) ;
124127
125- ws . on ( 'message' , ( message ) => {
128+ ws . on ( 'message' , async ( message ) => {
126129 const data = JSON . parse ( message . toString ( 'utf8' ) ) ;
130+
127131 if ( data . key === 'terminate' ) {
128132 process . exit ( 0 ) ;
133+ return ;
134+ }
135+
136+ if ( data . key === 'update-config' ) {
137+ await this . handleConfigUpdate ( ws , data ) ;
138+ return ;
129139 }
130140 } ) ;
131141
@@ -134,6 +144,74 @@ export class SocketServer {
134144 } )
135145 }
136146
147+ private async handleConfigUpdate ( ws : WebSocket , data : { sessionId : string ; config : string } ) {
148+ try {
149+ const { sessionId, config : configContent } = data ;
150+
151+ if ( ! sessionId || ! configContent ) {
152+ ws . send ( JSON . stringify ( {
153+ key : 'update-config-response' ,
154+ success : false ,
155+ sessionId,
156+ error : 'Missing sessionId or config'
157+ } ) ) ;
158+ return ;
159+ }
160+
161+ const session = this . sessions . get ( sessionId ) ;
162+ if ( ! session ) {
163+ ws . send ( JSON . stringify ( {
164+ key : 'update-config-response' ,
165+ success : false ,
166+ sessionId,
167+ error : 'Session not found'
168+ } ) ) ;
169+ return ;
170+ }
171+
172+ const filePath = session . additionalData . filePath as string | undefined ;
173+ if ( ! filePath ) {
174+ ws . send ( JSON . stringify ( {
175+ key : 'update-config-response' ,
176+ success : false ,
177+ sessionId,
178+ error : 'File path not found in session'
179+ } ) ) ;
180+ return ;
181+ }
182+
183+ // Security: Ensure file path is in temp directory
184+ const tmpDir = os . tmpdir ( ) ;
185+ const resolvedPath = path . resolve ( filePath ) ;
186+ if ( ! resolvedPath . startsWith ( tmpDir ) ) {
187+ console . error ( 'Security: Attempted to write outside temp directory' , filePath ) ;
188+ ws . send ( JSON . stringify ( {
189+ key : 'update-config-response' ,
190+ success : false ,
191+ sessionId,
192+ error : 'Invalid file path'
193+ } ) ) ;
194+ return ;
195+ }
196+
197+ await fs . writeFile ( filePath , configContent , 'utf8' ) ;
198+
199+ ws . send ( JSON . stringify ( {
200+ key : 'update-config-response' ,
201+ success : true ,
202+ sessionId
203+ } ) ) ;
204+ } catch ( error ) {
205+ console . error ( 'Error updating config:' , error ) ;
206+ ws . send ( JSON . stringify ( {
207+ key : 'update-config-response' ,
208+ success : false ,
209+ sessionId : data . sessionId ,
210+ error : error instanceof Error ? error . message : 'Unknown error'
211+ } ) ) ;
212+ }
213+ }
214+
137215 private validateOrigin = ( origin : string ) : boolean =>
138216 config . corsAllowedOrigins . includes ( origin )
139217
0 commit comments