Skip to content

Commit

Permalink
feat: offer file picker if sharkd not found
Browse files Browse the repository at this point in the history
Offer "open file dialog..." to select sharkd path if its not found.
Included an option for Mac to check automatically from .app to .app/Contents/MacOS/...
  • Loading branch information
mbehr1 committed Oct 5, 2024
1 parent 061f3b0 commit 57c674f
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 120 deletions.
99 changes: 44 additions & 55 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from './websharkView';
import { TreeViewNode, TreeViewProvider } from './treeViewProvider';
import { filterPcap, extractDlt, removeTecmp } from './filterPcap';
import { fileExistsOrPick } from './utils';

Check failure on line 17 in src/extension.ts

View workflow job for this annotation

GitHub Actions / build

Cannot find module './utils' or its corresponding type declarations.

const extensionId = 'mbehr1.vsc-webshark';
let reporter: TelemetryReporter;
Expand Down Expand Up @@ -80,63 +81,51 @@ export function activate(context: vscode.ExtensionContext) {
// register our command to open pcap files in webshark view:
context.subscriptions.push(
vscode.commands.registerCommand('webshark.openFile', async () => {
let _sharkdPath = <string>vscode.workspace.getConfiguration().get('vsc-webshark.sharkdFullPath');
// check if _sharkdPath exists
if (!fileExists(_sharkdPath)) {
vscode.window
.showErrorMessage(
`sharkdFullPath setting not pointing to a file. Please check setting. Currently used: '${_sharkdPath}'`,
{ modal: true },
'open settings'
)
.then((value) => {
switch (value) {
case 'open settings':
vscode.commands.executeCommand('workbench.action.openSettings', 'vsc-webshark.sharkdFullPath');
break;
}
});
} else {
return vscode.window
.showOpenDialog({
canSelectFiles: true,
canSelectFolders: false,
canSelectMany: false,
filters: {
'pcap files': ['pcap', 'cap', 'pcapng'].flatMap((ext) => [ext, ext + '.gz', ext + '.zst', ext + '.lz4']),
},
openLabel: 'Select pcap file to open...',
})
.then(async (uris: vscode.Uri[] | undefined) => {
if (uris) {
uris.forEach((uri) => {
console.log(`webshark.openFile got URI=${uri.toString()}`);
const sharkd = new SharkdProcess(_sharkdPath);
sharkd.ready().then((ready) => {
if (ready) {
context.subscriptions.push(
new WebsharkView(undefined, context, treeDataProvider, _onDidChangeSelectedTime, uri, sharkd, activeViews, (r) => {
const idx = activeViews.indexOf(r);
console.log(` openFile dispose called( r idx = ${idx}) activeViews=${activeViews.length}`);
if (idx >= 0) {
activeViews.splice(idx, 1);
}
})
);
if (reporter) {
reporter.sendTelemetryEvent('open file', undefined, { err: 0 });
}
} else {
vscode.window.showErrorMessage(`sharkd connection not ready! Please check setting. Currently used: '${_sharkdPath}'`);
if (reporter) {
reporter.sendTelemetryEvent('open file', undefined, { err: -1 });
fileExistsOrPick('vsc-webshark.sharkdFullPath', 'sharkd')
.then((_sharkdPath) => {

Check failure on line 85 in src/extension.ts

View workflow job for this annotation

GitHub Actions / build

Parameter '_sharkdPath' implicitly has an 'any' type.
return vscode.window
.showOpenDialog({
canSelectFiles: true,
canSelectFolders: false,
canSelectMany: false,
filters: {
'pcap files': ['pcap', 'cap', 'pcapng'].flatMap((ext) => [ext, ext + '.gz', ext + '.zst', ext + '.lz4']),
},
openLabel: 'Select pcap file to open...',
})
.then(async (uris: vscode.Uri[] | undefined) => {
if (uris) {
uris.forEach((uri) => {
console.log(`webshark.openFile got URI=${uri.toString()}`);
const sharkd = new SharkdProcess(_sharkdPath);
sharkd.ready().then((ready) => {
if (ready) {
context.subscriptions.push(
new WebsharkView(undefined, context, treeDataProvider, _onDidChangeSelectedTime, uri, sharkd, activeViews, (r) => {
const idx = activeViews.indexOf(r);
console.log(` openFile dispose called( r idx = ${idx}) activeViews=${activeViews.length}`);
if (idx >= 0) {
activeViews.splice(idx, 1);
}
})
);
if (reporter) {
reporter.sendTelemetryEvent('open file', undefined, { err: 0 });
}
} else {
vscode.window.showErrorMessage(`sharkd connection not ready! Please check setting. Currently used: '${_sharkdPath}'`);
if (reporter) {
reporter.sendTelemetryEvent('open file', undefined, { err: -1 });
}
}
}
});
});
});
}
});
}
}
});
})
.catch((err) => {

Check failure on line 126 in src/extension.ts

View workflow job for this annotation

GitHub Actions / build

Parameter 'err' implicitly has an 'any' type.
throw Error(`sharkdPath not valid: ${err}`);
});
})
);

Expand Down
179 changes: 114 additions & 65 deletions src/websharkView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as path from 'path';
import { spawn, ChildProcess } from 'child_process';
import TelemetryReporter from '@vscode/extension-telemetry';
import { TreeViewProvider, TreeViewNode } from './treeViewProvider';
import { fileExistsOrPick } from './utils';

Check failure on line 11 in src/websharkView.ts

View workflow job for this annotation

GitHub Actions / build

Cannot find module './utils' or its corresponding type declarations.
let _nextSharkdId = 1;

const platformWin32: boolean = process.platform === 'win32';
Expand Down Expand Up @@ -190,78 +191,126 @@ export class SharkdProcess implements vscode.Disposable {
}

export class WebsharkViewSerializer implements vscode.WebviewPanelSerializer {
constructor(private reporter: TelemetryReporter, private treeViewProvider: TreeViewProvider, private _onDidChangeSelectedTime: vscode.EventEmitter<SelectedTimeData>, private sharkdPath: string, private context: vscode.ExtensionContext, private activeViews: WebsharkView[], private callOnDispose: (r: WebsharkView) => any) {

}
async deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel, state: any) {
console.log(`WebsharkView deserializeWebviewPanel called. state='${JSON.stringify(state)}'`);
try {
if ('uri' in state) {
const uri: vscode.Uri = vscode.Uri.parse(state.uri, true);
console.log(`creating WebsharkView for uri=${uri.toString()}`);

const sharkd = new SharkdProcess(this.sharkdPath);
sharkd.ready().then((ready) => {
if (ready) {
this.context.subscriptions.push(new WebsharkView(webviewPanel, this.context, this.treeViewProvider, this._onDidChangeSelectedTime, uri, sharkd, this.activeViews, this.callOnDispose));
if (this.reporter) { this.reporter.sendTelemetryEvent("open file", undefined, { 'err': 0 }); }
} else {
vscode.window.showErrorMessage(`sharkd connection not ready! Please check setting. Currently used: '${this.sharkdPath}'`);
if (this.reporter) { this.reporter.sendTelemetryEvent("open file", undefined, { 'err': -1 }); }
}
});

} else { console.warn(`deserializeWebviewPanel but no uri within state='${JSON.stringify(state)}'`); }
} catch (err) {
console.warn(`deserializeWebviewPanel got err=${err} with state='${JSON.stringify(state)}'`);
}
constructor(
private reporter: TelemetryReporter,
private treeViewProvider: TreeViewProvider,
private _onDidChangeSelectedTime: vscode.EventEmitter<SelectedTimeData>,
private sharkdPath: string,
private context: vscode.ExtensionContext,
private activeViews: WebsharkView[],
private callOnDispose: (r: WebsharkView) => any
) {}
async deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel, state: any) {
console.log(`WebsharkView deserializeWebviewPanel called. state='${JSON.stringify(state)}'`);
try {
if ('uri' in state) {
const uri: vscode.Uri = vscode.Uri.parse(state.uri, true);
console.log(`creating WebsharkView for uri=${uri.toString()}`);

const sharkd = new SharkdProcess(this.sharkdPath);
sharkd.ready().then((ready) => {
if (ready) {
this.context.subscriptions.push(
new WebsharkView(
webviewPanel,
this.context,
this.treeViewProvider,
this._onDidChangeSelectedTime,
uri,
sharkd,
this.activeViews,
this.callOnDispose
)
);
if (this.reporter) {
this.reporter.sendTelemetryEvent('open file', undefined, { err: 0 });
}
} else {
vscode.window.showErrorMessage(`sharkd connection not ready! Please check setting. Currently used: '${this.sharkdPath}'`);
if (this.reporter) {
this.reporter.sendTelemetryEvent('open file', undefined, { err: -1 });
}
}
});
} else {
console.warn(`deserializeWebviewPanel but no uri within state='${JSON.stringify(state)}'`);
}
} catch (err) {
console.warn(`deserializeWebviewPanel got err=${err} with state='${JSON.stringify(state)}'`);
}
}
}

class WebsharkViewCustomDocument implements vscode.CustomDocument {
constructor(public uri: vscode.Uri) {
console.log(`WebsharkViewCustomDocument(uri=${this.uri.toString()}) called`);
}
dispose() {
console.log(`WebsharkViewCustomDocument dispose(uri=${this.uri.toString()}) called`);
}
constructor(public uri: vscode.Uri) {
console.log(`WebsharkViewCustomDocument(uri=${this.uri.toString()}) called`);
}
dispose() {
console.log(`WebsharkViewCustomDocument dispose(uri=${this.uri.toString()}) called`);
}
}

export class WebsharkViewReadonlyEditorProvider implements vscode.CustomReadonlyEditorProvider<WebsharkViewCustomDocument> {
constructor(private reporter: TelemetryReporter, private treeViewProvider: TreeViewProvider, private _onDidChangeSelectedTime: vscode.EventEmitter<SelectedTimeData>, private context: vscode.ExtensionContext, private activeViews: WebsharkView[], private callOnDispose: (r: WebsharkView) => any) {
}
openCustomDocument(uri: vscode.Uri, openContext: vscode.CustomDocumentOpenContext, token: vscode.CancellationToken): Thenable<WebsharkViewCustomDocument> | WebsharkViewCustomDocument {
console.log(`WebsharkViewReadonlyEditorProvider openCustomDocument(uri=${uri.toString()}, openContext=${JSON.stringify(openContext)}) called`);
// we dont support backupId yet (necessary for readonly at all?)
return new WebsharkViewCustomDocument(uri);
}
resolveCustomEditor(document: WebsharkViewCustomDocument, webviewPanel: vscode.WebviewPanel, token: vscode.CancellationToken): Thenable<void> | void {
console.log(`WebsharkViewReadonlyEditorProvider resolveCustomEditor(document.uri=${document.uri.toString()}, webviewPanel:${webviewPanel}) called`);
const _wiresharkProfile = <string>(vscode.workspace.getConfiguration().get("vsc-webshark.wiresharkProfile"));
const _sharkdPath = <string>(vscode.workspace.getConfiguration().get("vsc-webshark.sharkdFullPath"));
if (!fileExists(_sharkdPath)) {
vscode.window.showErrorMessage(`sharkdFullPath setting not pointing to a file. Please check setting. Currently used: '${_sharkdPath}'`,
{ modal: true }, 'open settings').then((value) => {
switch (value) {
case 'open settings':
vscode.commands.executeCommand('workbench.action.openSettings', "vsc-webshark.sharkdFullPath");
break;
}
});
throw Error(`sharkdPath not pointing to a file`);
} else {
const sharkd = new SharkdProcess(_sharkdPath, _wiresharkProfile);
sharkd.ready().then((ready) => {
if (ready) {
this.context.subscriptions.push(new WebsharkView(webviewPanel, this.context, this.treeViewProvider, this._onDidChangeSelectedTime, document.uri, sharkd, this.activeViews, this.callOnDispose));
if (this.reporter) { this.reporter.sendTelemetryEvent("open file resolve custom editor", { fn: 'resolveCustomEditor' }, { 'err': 0 }); }
} else {
vscode.window.showErrorMessage(`sharkd connection not ready! Please check setting. Currently used: '${_sharkdPath}'`);
if (this.reporter) { this.reporter.sendTelemetryEvent("open file resolve custom editor", { fn: 'resolveCustomEditor' }, { 'err': -1 }); }
}
});
}
}
constructor(
private reporter: TelemetryReporter,
private treeViewProvider: TreeViewProvider,
private _onDidChangeSelectedTime: vscode.EventEmitter<SelectedTimeData>,
private context: vscode.ExtensionContext,
private activeViews: WebsharkView[],
private callOnDispose: (r: WebsharkView) => any
) {}
openCustomDocument(
uri: vscode.Uri,
openContext: vscode.CustomDocumentOpenContext,
token: vscode.CancellationToken
): Thenable<WebsharkViewCustomDocument> | WebsharkViewCustomDocument {
console.log(
`WebsharkViewReadonlyEditorProvider openCustomDocument(uri=${uri.toString()}, openContext=${JSON.stringify(openContext)}) called`
);
// we dont support backupId yet (necessary for readonly at all?)
return new WebsharkViewCustomDocument(uri);
}
resolveCustomEditor(
document: WebsharkViewCustomDocument,
webviewPanel: vscode.WebviewPanel,
token: vscode.CancellationToken
): Thenable<void> | void {
console.log(
`WebsharkViewReadonlyEditorProvider resolveCustomEditor(document.uri=${document.uri.toString()}, webviewPanel:${webviewPanel}) called`
);
const _wiresharkProfile = <string>vscode.workspace.getConfiguration().get('vsc-webshark.wiresharkProfile');
fileExistsOrPick('vsc-webshark.sharkdFullPath', 'sharkd')
.then((filePath) => {

Check failure on line 283 in src/websharkView.ts

View workflow job for this annotation

GitHub Actions / build

Parameter 'filePath' implicitly has an 'any' type.
const sharkd = new SharkdProcess(filePath, _wiresharkProfile);
sharkd.ready().then((ready) => {
if (ready) {
this.context.subscriptions.push(
new WebsharkView(
webviewPanel,
this.context,
this.treeViewProvider,
this._onDidChangeSelectedTime,
document.uri,
sharkd,
this.activeViews,
this.callOnDispose
)
);
if (this.reporter) {
this.reporter.sendTelemetryEvent('open file resolve custom editor', { fn: 'resolveCustomEditor' }, { err: 0 });
}
} else {
vscode.window.showErrorMessage(`sharkd connection not ready! Please check setting. Currently used: '${filePath}'`);
if (this.reporter) {
this.reporter.sendTelemetryEvent('open file resolve custom editor', { fn: 'resolveCustomEditor' }, { err: -1 });
}
}
});
})
.catch((err) => {

Check failure on line 310 in src/websharkView.ts

View workflow job for this annotation

GitHub Actions / build

Parameter 'err' implicitly has an 'any' type.
throw Error(`sharkdPath not valid: ${err}`);
});
}
}

interface ResponseData {
Expand Down

0 comments on commit 57c674f

Please sign in to comment.