electerm 3.3.2 → 3.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -90,9 +90,6 @@ Check [https://electerm-repos.html5beta.com/deb](https://electerm-repos.html5bet
90
90
  ```bash
91
91
  npm i -g electerm
92
92
 
93
- # After installation, it will immediately open for windows and linux,
94
- # For macOS, it will open the drag to install panel
95
-
96
93
  ```
97
94
 
98
95
  ## Upgrade
package/npm/electerm CHANGED
@@ -34,6 +34,21 @@ function getElectermExePath () {
34
34
  return path.join(packageRoot, 'electerm', 'electerm')
35
35
  }
36
36
 
37
+ function isSandboxReady () {
38
+ // chrome-sandbox must be owned by root (uid 0) and have setuid bit set (mode 4755)
39
+ // This requires root during install, which npm global install does not provide.
40
+ try {
41
+ const sandboxPath = path.join(packageRoot, 'electerm', 'chrome-sandbox')
42
+ if (!fs.existsSync(sandboxPath)) return false
43
+ const stat = fs.statSync(sandboxPath)
44
+ const hasSetuid = (stat.mode & 0o4000) !== 0
45
+ const ownedByRoot = stat.uid === 0
46
+ return hasSetuid && ownedByRoot
47
+ } catch (e) {
48
+ return false
49
+ }
50
+ }
51
+
37
52
  function launchElecterm () {
38
53
  const exePath = getElectermExePath()
39
54
 
@@ -46,7 +61,12 @@ function launchElecterm () {
46
61
  process.exit(1)
47
62
  }
48
63
 
49
- const child = spawn(exePath, process.argv.slice(2), {
64
+ const extraArgs = []
65
+ if (plat === 'linux' && !isSandboxReady()) {
66
+ extraArgs.push('--no-sandbox')
67
+ }
68
+
69
+ const child = spawn(exePath, [...extraArgs, ...process.argv.slice(2)], {
50
70
  stdio: 'inherit',
51
71
  detached: plat !== 'win32',
52
72
  windowsHide: false
package/npm/install.js CHANGED
@@ -192,11 +192,15 @@ async function runLinux (folderName, filePattern) {
192
192
  mv(join(tmpDir, extractedFolder), extractDir)
193
193
 
194
194
  // Fix chrome-sandbox permissions on Linux (Electron requires specific permissions)
195
+ // Note: setting the setuid bit requires root ownership, which npm install cannot provide.
196
+ // The launcher handles this by passing --no-sandbox when the sandbox is not root-owned.
195
197
  if (plat === 'linux') {
196
198
  const chromeSandboxPath = join(extractDir, 'chrome-sandbox')
197
199
  if (fs.existsSync(chromeSandboxPath)) {
198
- console.log(' Fixing chrome-sandbox permissions...')
199
- fs.chmodSync(chromeSandboxPath, 0o4755)
200
+ console.log(' Note: To enable the Electron sandbox, run:')
201
+ console.log(` sudo chown root:root "${chromeSandboxPath}"`)
202
+ console.log(` sudo chmod 4755 "${chromeSandboxPath}"`)
203
+ console.log(' Otherwise, electerm will launch with --no-sandbox automatically.')
200
204
  }
201
205
  }
202
206
 
@@ -207,23 +211,16 @@ async function runLinux (folderName, filePattern) {
207
211
  }
208
212
 
209
213
  async function runWin (archName) {
210
- console.log(' [DEBUG] runWin started')
211
- console.log(` [DEBUG] packageRoot: ${packageRoot}`)
212
- console.log(` [DEBUG] extractDir: ${extractDir}`)
213
-
214
214
  const rawVer = await getVer()
215
215
  const ver = sanitizeVersion(rawVer)
216
216
 
217
- console.log(` [DEBUG] Raw version from server: ${rawVer}`)
218
- console.log(` Sanitized version: ${ver}`)
217
+ console.log(` Version: ${ver}`)
219
218
  console.log(` Target: win-${archName}`)
220
219
 
221
220
  const target = join(packageRoot, `electerm-${ver}-win-${archName}`)
222
- console.log(` [DEBUG] Target folder: ${target}`)
223
221
 
224
- console.log(' Cleaning old installations...')
225
222
  rm('-rf', [target, extractDir])
226
- console.log(' [DEBUG] Old installations cleaned')
223
+ fs.mkdirSync(extractDir, { recursive: true })
227
224
 
228
225
  const pattern = new RegExp(`electerm-\\d+\\.\\d+\\.\\d+-win-${archName}\\.tar\\.gz$`)
229
226
  console.log(' Fetching release info...')
@@ -231,70 +228,24 @@ async function runWin (archName) {
231
228
  if (!releaseInfo) {
232
229
  throw new Error(`No release found for Windows ${archName}`)
233
230
  }
234
- console.log(` [DEBUG] Release info found: ${JSON.stringify(releaseInfo, null, 2)}`)
235
231
 
232
+ // Download to a temp file, then extract directly to extractDir with strip:1
233
+ // (avoids a rename which can fail on Windows when AV has file locks)
236
234
  const tmpDir = join(packageRoot, '.electerm-tmp')
237
- console.log(` [DEBUG] Creating temp directory: ${tmpDir}`)
238
235
  rm('-rf', tmpDir)
239
236
  fs.mkdirSync(tmpDir, { recursive: true })
240
237
 
241
238
  const proxyUrl = applyProxy(releaseInfo.browser_download_url)
242
- console.log(` [DEBUG] Proxy URL: ${proxyUrl}`)
243
- console.log(` [DEBUG] Download URL: ${releaseInfo.browser_download_url}`)
239
+ console.log(` URL: ${proxyUrl}`)
244
240
 
245
- console.log(' Downloading...')
246
241
  const { filepath } = await download(releaseInfo.browser_download_url, tmpDir, { extract: false, displayName: releaseInfo.name })
247
- console.log(` [DEBUG] Downloaded to: ${filepath}`)
248
- console.log(` [DEBUG] File exists: ${fs.existsSync(filepath)}`)
249
- console.log(` [DEBUG] File size: ${fs.statSync(filepath).size}`)
250
-
251
- console.log(' Extracting...')
252
- await extractTarGz(filepath, tmpDir)
253
- console.log(' [DEBUG] Extraction complete')
254
-
255
- console.log(' [DEBUG] Listing temp directory contents:')
256
- const entries = fs.readdirSync(tmpDir)
257
- entries.forEach(e => {
258
- const fullPath = join(tmpDir, e)
259
- const stat = fs.statSync(fullPath)
260
- console.log(` [DEBUG] ${e} - ${stat.isDirectory() ? 'DIR' : 'FILE'} (${stat.size} bytes)`)
261
- })
262
-
263
- const extractedFolder = entries.find(e => fs.statSync(join(tmpDir, e)).isDirectory())
264
-
265
- if (!extractedFolder) {
266
- console.error(' [DEBUG] No directory found in extracted archive')
267
- console.error(' [DEBUG] All entries:', entries)
268
- throw new Error('No folder found in extracted archive')
269
- }
270
-
271
- console.log(` [DEBUG] Extracted folder: ${extractedFolder}`)
272
- console.log(' [DEBUG] Contents of extracted folder:')
273
- const extractedContents = fs.readdirSync(join(tmpDir, extractedFolder))
274
- extractedContents.forEach(e => {
275
- const fullPath = join(tmpDir, extractedFolder, e)
276
- const stat = fs.statSync(fullPath)
277
- console.log(` [DEBUG] ${e} - ${stat.isDirectory() ? 'DIR' : 'FILE'} (${stat.size} bytes)`)
278
- })
279
242
 
280
243
  console.log(` Installing to: ${extractDir}`)
281
- fs.renameSync(join(tmpDir, extractedFolder), extractDir)
282
- console.log(' [DEBUG] Renamed folder to extractDir')
283
-
284
- console.log(' [DEBUG] Verifying extractDir contents:')
285
- const installContents = fs.readdirSync(extractDir)
286
- installContents.forEach(e => {
287
- const fullPath = join(extractDir, e)
288
- const stat = fs.statSync(fullPath)
289
- console.log(` [DEBUG] ${e} - ${stat.isDirectory() ? 'DIR' : 'FILE'} (${stat.size} bytes)`)
290
- })
244
+ await extractTarGz(filepath, extractDir, 1)
291
245
 
292
246
  rm('-rf', tmpDir)
293
- console.log(' [DEBUG] Temp directory cleaned')
294
247
 
295
248
  const exePath = getElectermExePath()
296
- console.log(` [DEBUG] Expected exe path: ${exePath}`)
297
- console.log(` [DEBUG] Exe exists: ${fs.existsSync(exePath)}`)
298
249
  if (!fs.existsSync(exePath)) {
299
250
  throw new Error(`electerm.exe not found at ${exePath} after extraction. Archive may have an unexpected structure.`)
300
251
  }
@@ -303,93 +254,38 @@ async function runWin (archName) {
303
254
  }
304
255
 
305
256
  async function runWin7 () {
306
- console.log(' [DEBUG] runWin7 started')
307
- console.log(` [DEBUG] packageRoot: ${packageRoot}`)
308
- console.log(` [DEBUG] extractDir: ${extractDir}`)
309
-
310
257
  const rawVer = await getVer()
311
258
  const ver = sanitizeVersion(rawVer)
312
259
 
313
- console.log(` [DEBUG] Raw version from server: ${rawVer}`)
314
- console.log(` Sanitized version: ${ver}`)
260
+ console.log(` Version: ${ver}`)
315
261
  console.log(' Target: win7')
316
262
 
317
263
  const target = join(packageRoot, `electerm-${ver}-win7`)
318
- console.log(` [DEBUG] Target folder: ${target}`)
319
264
 
320
- console.log(' Cleaning old installations...')
321
265
  rm('-rf', [target, extractDir])
322
- console.log(' [DEBUG] Old installations cleaned')
266
+ fs.mkdirSync(extractDir, { recursive: true })
323
267
 
324
268
  console.log(' Fetching release info...')
325
269
  const releaseInfo = await getReleaseInfo(r => /electerm-\d+\.\d+\.\d+-win7\.tar\.gz$/.test(r.name))
326
270
  if (!releaseInfo) {
327
271
  throw new Error('No release found for Windows 7')
328
272
  }
329
- console.log(` [DEBUG] Release info found: ${JSON.stringify(releaseInfo, null, 2)}`)
330
273
 
331
274
  const tmpDir = join(packageRoot, '.electerm-tmp')
332
- console.log(` [DEBUG] Creating temp directory: ${tmpDir}`)
333
275
  rm('-rf', tmpDir)
334
276
  fs.mkdirSync(tmpDir, { recursive: true })
335
277
 
336
278
  const proxyUrl = applyProxy(releaseInfo.browser_download_url)
337
- console.log(` [DEBUG] Proxy URL: ${proxyUrl}`)
338
- console.log(` [DEBUG] Download URL: ${releaseInfo.browser_download_url}`)
279
+ console.log(` URL: ${proxyUrl}`)
339
280
 
340
- console.log(' Downloading...')
341
281
  const { filepath } = await download(releaseInfo.browser_download_url, tmpDir, { extract: false, displayName: releaseInfo.name })
342
- console.log(` [DEBUG] Downloaded to: ${filepath}`)
343
- console.log(` [DEBUG] File exists: ${fs.existsSync(filepath)}`)
344
- console.log(` [DEBUG] File size: ${fs.statSync(filepath).size}`)
345
-
346
- console.log(' Extracting...')
347
- await extractTarGz(filepath, tmpDir)
348
- console.log(' [DEBUG] Extraction complete')
349
-
350
- console.log(' [DEBUG] Listing temp directory contents:')
351
- const entries = fs.readdirSync(tmpDir)
352
- entries.forEach(e => {
353
- const fullPath = join(tmpDir, e)
354
- const stat = fs.statSync(fullPath)
355
- console.log(` [DEBUG] ${e} - ${stat.isDirectory() ? 'DIR' : 'FILE'} (${stat.size} bytes)`)
356
- })
357
-
358
- const extractedFolder = entries.find(e => fs.statSync(join(tmpDir, e)).isDirectory())
359
-
360
- if (!extractedFolder) {
361
- console.error(' [DEBUG] No directory found in extracted archive')
362
- console.error(' [DEBUG] All entries:', entries)
363
- throw new Error('No folder found in extracted archive')
364
- }
365
-
366
- console.log(` [DEBUG] Extracted folder: ${extractedFolder}`)
367
- console.log(' [DEBUG] Contents of extracted folder:')
368
- const extractedContents = fs.readdirSync(join(tmpDir, extractedFolder))
369
- extractedContents.forEach(e => {
370
- const fullPath = join(tmpDir, extractedFolder, e)
371
- const stat = fs.statSync(fullPath)
372
- console.log(` [DEBUG] ${e} - ${stat.isDirectory() ? 'DIR' : 'FILE'} (${stat.size} bytes)`)
373
- })
374
282
 
375
283
  console.log(` Installing to: ${extractDir}`)
376
- fs.renameSync(join(tmpDir, extractedFolder), extractDir)
377
- console.log(' [DEBUG] Renamed folder to extractDir')
378
-
379
- console.log(' [DEBUG] Verifying extractDir contents:')
380
- const installContents = fs.readdirSync(extractDir)
381
- installContents.forEach(e => {
382
- const fullPath = join(extractDir, e)
383
- const stat = fs.statSync(fullPath)
384
- console.log(` [DEBUG] ${e} - ${stat.isDirectory() ? 'DIR' : 'FILE'} (${stat.size} bytes)`)
385
- })
284
+ await extractTarGz(filepath, extractDir, 1)
386
285
 
387
286
  rm('-rf', tmpDir)
388
- console.log(' [DEBUG] Temp directory cleaned')
389
287
 
390
288
  const exePath = getElectermExePath()
391
- console.log(` [DEBUG] Expected exe path: ${exePath}`)
392
- console.log(` [DEBUG] Exe exists: ${fs.existsSync(exePath)}`)
393
289
  if (!fs.existsSync(exePath)) {
394
290
  throw new Error(`electerm.exe not found at ${exePath} after extraction. Archive may have an unexpected structure.`)
395
291
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electerm",
3
- "version": "3.3.2",
3
+ "version": "3.3.5",
4
4
  "description": "Terminal/ssh/telnet/serialport/sftp client(linux, mac, win)",
5
5
  "main": "app.js",
6
6
  "bin": "npm/electerm",