packetsnitch 1.5.600 → 1.5.602
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/.webpack/x64/main/index.js +2 -0
- package/.webpack/x64/main/index.js.map +1 -0
- package/.webpack/x64/renderer/main_window/index.html +3 -0
- package/.webpack/x64/renderer/main_window/index.js +3 -0
- package/.webpack/x64/renderer/main_window/index.js.LICENSE.txt +36 -0
- package/.webpack/x64/renderer/main_window/index.js.map +1 -0
- package/.webpack/x64/renderer/main_window/preload.js +2 -0
- package/.webpack/x64/renderer/main_window/preload.js.map +1 -0
- package/package.json +3 -3
- package/.webpack/main/index.js +0 -1697
- package/.webpack/main/index.js.map +0 -1
- package/.webpack/renderer/main_window/index.html +0 -1036
- package/.webpack/renderer/main_window/index.js +0 -4736
- package/.webpack/renderer/main_window/preload.js +0 -1418
- /package/.webpack/{renderer → x64/renderer}/assets/css/rubikglitch.woff2 +0 -0
- /package/.webpack/{renderer → x64/renderer}/assets/css/style.css +0 -0
- /package/.webpack/{renderer → x64/renderer}/assets/images/loading.gif +0 -0
- /package/.webpack/{renderer → x64/renderer}/assets/images/logo.webp +0 -0
- /package/.webpack/{renderer → x64/renderer}/assets/images/packet-snitch-tag.webp +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","mappings":";;;;;;;;;AAAA,WAAW,mBAAO,CAAC,kBAAM;AACzB,YAAY,iEAA8B;AAC1C,YAAY,mBAAO,CAAC,uFAAO;AAC3B,UAAU,qDAAuB;;AAEjC;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;;;;;ACnCA;AACA;AACA;AACA;AACA;;AAEA,UAAU,+HAAmC;AAC7C,WAAW;AACX,kBAAkB;AAClB,YAAY;AACZ,YAAY;AACZ,iBAAiB;AACjB,eAAe;AACf;AACA;AACA;;AAEA;AACA;AACA;;AAEA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,oBAAoB;AACpB;AACA;AACA,IAAI;AACJ;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,QAAQ;AACnB;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAM;AACN,MAAM,qBAAqB;AAC3B;AACA,IAAI;AACJ;;AAEA;AACA;AACA;AACA,YAAY,QAAQ;AACpB;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAI;;AAEJ;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY;AACZ;AACA;;AAEA;AACA;AACA;AACA,IAAI;AACJ;;;;;;;;;;;;ACvLA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,cAAc;AACd,eAAe;AACf,cAAc;AACd,eAAe;AACf,qHAAgC;;AAEhC;AACA;AACA;;AAEA,aAAa;AACb,aAAa;;AAEb;AACA;AACA;AACA;AACA;;AAEA,kBAAkB;;AAElB;AACA;AACA;;AAEA;;AAEA;AACA;AACA,WAAW,QAAQ;AACnB,YAAY;AACZ;AACA;;AAEA;AACA;;AAEA;AACA;AACA,eAAe;AACf;;AAEA;AACA;;AAEA;AACA;AACA;AACA,WAAW,QAAQ;AACnB,YAAY;AACZ;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oBAAoB,iBAAiB;AACrC;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,WAAW,QAAQ;AACnB;AACA;;AAEA;AACA;;AAEA,EAAE,aAAa;AACf,EAAE,aAAa;;AAEf;AACA;;AAEA,kBAAkB,SAAS;AAC3B,6BAA6B;AAC7B;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,QAAQ;AACnB,YAAY;AACZ;AACA;;AAEA;AACA;AACA,0CAA0C,SAAS;AACnD;AACA;AACA;AACA;AACA,0CAA0C,SAAS;AACnD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,OAAO;AAClB,YAAY;AACZ;AACA;;AAEA;AACA;AACA;AACA;;;;;;;;;;;ACzMA;AACA;AACA;AACA;;AAEA;AACA,EAAE,sIAAwC;AAC1C,EAAE;AACF,EAAE,gIAAqC;AACvC;;;;;;;;;;;ACTA;AACA;AACA;;AAEA,UAAU,mBAAO,CAAC,gBAAK;AACvB,WAAW,mBAAO,CAAC,kBAAM;;AAEzB;AACA;AACA;AACA;AACA;;AAEA,UAAU,+HAAmC;AAC7C,YAAY;AACZ,WAAW;AACX,kBAAkB;AAClB,YAAY;AACZ,YAAY;AACZ,iBAAiB;;AAEjB;AACA;AACA;;AAEA,cAAc;;AAEd;AACA;AACA;AACA;AACA;;AAEA,mBAAmB;AACnB;AACA,CAAC;AACD;AACA;AACA;AACA;AACA,4CAA4C,wBAAwB;;AAEpE;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,CAAC,IAAI;;AAEL;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,6BAA6B;AAC7B;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,oBAAoB;AACpB;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;;AAEA,oBAAoB;AACpB;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,sCAAsC;;AAEtC;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,QAAQ;AACnB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY,QAAQ;AACpB;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,eAAe,mBAAO,CAAC,cAAI;AAC3B,4CAA4C,kBAAkB;AAC9D;AACA;;AAEA;AACA;AACA,gBAAgB,mBAAO,CAAC,gBAAK;AAC7B;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,kBAAkB,iBAAiB;AACnC;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;;;;;ACvPA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,eAAe;AAC1B,WAAW,QAAQ;AACnB,YAAY,OAAO;AACnB,YAAY;AACZ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,QAAQ;AACnB,YAAY;AACZ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,QAAQ;AACnB,YAAY;AACZ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,QAAQ;AACnB,YAAY;AACZ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;ACvJA,QAAQ,yBAAyB,EAAE,mBAAO,CAAC,0BAAU;AACrD,QAAQ,OAAO,EAAE,mBAAO,CAAC,oCAAe;AACxC,WAAW,mBAAO,CAAC,cAAI;AACvB;AACA,aAAa,mBAAO,CAAC,kBAAM;AAC3B,WAAW,mBAAO,CAAC,cAAI;AACvB;AACA;AACA;AACA,sCAAsC,SAAS;AAC/C,iBAAiB,qDAAuB;AACxC;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAI;AACJ;AACA,IAAI;AACJ;AACA;;AAEA,6BAA6B,cAAc,KAAK,SAAS,WAAW,kBAAkB,GAAG,yBAAyB;;AAElH;AACA;AACA;AACA,mCAAmC,8BAA8B;AACjE;;AAEA;;AAEA;AACA,sDAAsD;AACtD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,KAAK;;AAEL;AACA,GAAG;AACH,CAAC;;;;;;;;;;;;ACrED,0C;;;;;;;;;;;ACAA,qC;;;;;;;;;;;ACAA,+B;;;;;;;;;;;ACAA,gC;;;;;;;;;;;ACAA,+B;;;;;;;;;;;ACAA,iC;;;;;;;;;;;ACAA,gC;;;;;;;;;;;ACAA,gC;;;;;;;;;;;ACAA,iC;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;;;;UC3BA,wG;;;;;;;;;ACDA,QAAQ,6CAA6C,EAAE,mBAAO,CAAC,0BAAU;AACzE,WAAW,mBAAO,CAAC,cAAI;AACvB,aAAa,mBAAO,CAAC,kBAAM;AAC3B,QAAQ,gBAAgB,EAAE,mBAAO,CAAC,gBAAK;AACvC,QAAQ,OAAO,EAAE,mBAAO,CAAC,oCAAe;AACxC,WAAW,mBAAO,CAAC,cAAI;AACvB,aAAa,mBAAO,CAAC,kBAAM;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,mBAAO,CAAC,oFAA2B;AACvC;AACA;;AAEA;AACA;AACA;AACA,gEAAgE;AAChE,2BAA2B;AAC3B,IAAI;AACJ;AACA,cAAc;AACd;AACA,CAAC;;AAED;AACA,6BAA6B,8BAA8B;;AAE3D;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA,wBAAwB;AACxB,QAAQ;AACR;AACA;AACA,KAAK;AACL,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,mGAAiC;AAChD;AACA;AACA,KAAK;AACL,GAAG;AACH,qBAAqB,8CAAyB;AAC9C;AACA,+CAA+C;AAC/C,GAAG;AACH;AACA;AACA;AACA,4CAA4C,iBAAiB;AAC7D;AACA,QAAQ,kBAAkB;AAC1B;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,aAAa,yBAAyB,WAAW,QAAQ;AACzD;;AAEA,kDAAkD;AAClD,UAAU,mBAAmB;AAC7B;AACA;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,yBAAyB,oBAAoB,QAAQ;AAC7D;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,UAAU,uBAAuB,KAAK;AACpE,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,QAAQ,yBAAyB,6CAA6C,iBAAiB;AAC/F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,IAAI,mBAAO,CAAC,uCAAa;AACzB;AACA,cAAc,sBAAsB;AACpC;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA,qCAAqC,8BAA8B;AACnE;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,IAAI;AACJ;AACA,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA,aAAa;AACb;;AAEA,UAAU,qBAAqB;AAC/B;AACA;AACA,gBAAgB,0CAA0C;AAC1D,GAAG;AACH,sCAAsC;;AAEtC;AACA;AACA,aAAa;AACb,IAAI;AACJ;AACA,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA,aAAa;AACb;AACA;;AAEA,UAAU,qBAAqB;AAC/B;AACA;AACA,gBAAgB,0CAA0C;AAC1D,GAAG;AACH,sCAAsC;;AAEtC;AACA;AACA,aAAa;AACb,IAAI;AACJ;AACA,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,UAAU,qBAAqB;AAC/B;AACA;AACA;AACA,QAAQ,2CAA2C;AACnD,QAAQ,sCAAsC;AAC9C;AACA,GAAG;AACH,sCAAsC;;AAEtC;AACA;AACA;AACA,aAAa;AACb,IAAI;AACJ;AACA,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA,aAAa;AACb;;AAEA,UAAU,qBAAqB;AAC/B;AACA;AACA;AACA,QAAQ,yCAAyC;AACjD,QAAQ,sCAAsC;AAC9C;AACA,GAAG;AACH,sCAAsC;;AAEtC;AACA;AACA,aAAa;AACb,IAAI;AACJ;AACA,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA,aAAa;AACb;;AAEA,UAAU,qBAAqB;AAC/B;AACA;AACA;AACA,QAAQ,yCAAyC;AACjD,QAAQ,sCAAsC;AAC9C;AACA,GAAG;AACH,sCAAsC;;AAEtC;AACA;AACA,aAAa;AACb,IAAI;AACJ;AACA,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA,2CAA2C;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,mDAAmD;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,qBAAqB;;AAErB;AACA,UAAU,qBAAqB;AAC/B;AACA,kEAAkE,IAAI;AACtE;AACA,QAAQ,sCAAsC;AAC9C,QAAQ,sCAAsC;AAC9C;AACA,GAAG;AACH,sCAAsC;;AAEtC;AACA;AACA,aAAa;AACb,IAAI;AACJ;AACA,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA,qBAAqB;;AAErB;AACA;AACA;AACA;AACA;AACA;AACA,sDAAsD,IAAI;AAC1D;AACA;AACA;AACA;AACA;AACA,+BAA+B,8BAA8B,gBAAgB;AAC7E,KAAK;AACL,aAAa;AACb,IAAI;AACJ;AACA,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA,aAAa;AACb,IAAI;AACJ,aAAa;AACb;AACA,CAAC;;AAED;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,2CAA2C,kBAAkB;AAC7D,WAAW;AACX,CAAC;;AAED;AACA;AACA,CAAC;;AAED;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA,wDAAwD,iBAAiB;AACzE;AACA,QAAQ,kBAAkB;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","sources":["webpack://packetsnitch/./node_modules/electron-squirrel-startup/index.js","webpack://packetsnitch/./node_modules/electron-squirrel-startup/node_modules/debug/src/browser.js","webpack://packetsnitch/./node_modules/electron-squirrel-startup/node_modules/debug/src/debug.js","webpack://packetsnitch/./node_modules/electron-squirrel-startup/node_modules/debug/src/index.js","webpack://packetsnitch/./node_modules/electron-squirrel-startup/node_modules/debug/src/node.js","webpack://packetsnitch/./node_modules/electron-squirrel-startup/node_modules/ms/index.js","webpack://packetsnitch/./src/back-comm.js","webpack://packetsnitch/external node-commonjs \"child_process\"","webpack://packetsnitch/external node-commonjs \"electron\"","webpack://packetsnitch/external node-commonjs \"fs\"","webpack://packetsnitch/external node-commonjs \"net\"","webpack://packetsnitch/external node-commonjs \"os\"","webpack://packetsnitch/external node-commonjs \"path\"","webpack://packetsnitch/external node-commonjs \"tty\"","webpack://packetsnitch/external node-commonjs \"url\"","webpack://packetsnitch/external node-commonjs \"util\"","webpack://packetsnitch/webpack/bootstrap","webpack://packetsnitch/webpack/runtime/compat","webpack://packetsnitch/./src/main.js"],"sourcesContent":["var path = require('path');\nvar spawn = require('child_process').spawn;\nvar debug = require('debug')('electron-squirrel-startup');\nvar app = require('electron').app;\n\nvar run = function(args, done) {\n var updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe');\n debug('Spawning `%s` with args `%s`', updateExe, args);\n spawn(updateExe, args, {\n detached: true\n }).on('close', done);\n};\n\nvar check = function() {\n if (process.platform === 'win32') {\n var cmd = process.argv[1];\n debug('processing squirrel command `%s`', cmd);\n var target = path.basename(process.execPath);\n\n if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {\n run(['--createShortcut=' + target + ''], app.quit);\n return true;\n }\n if (cmd === '--squirrel-uninstall') {\n run(['--removeShortcut=' + target + ''], app.quit);\n return true;\n }\n if (cmd === '--squirrel-obsolete') {\n app.quit();\n return true;\n }\n }\n return false;\n};\n\nmodule.exports = check();\n","/**\n * This is the web browser implementation of `debug()`.\n *\n * Expose `debug()` as the module.\n */\n\nexports = module.exports = require('./debug');\nexports.log = log;\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\nexports.storage = 'undefined' != typeof chrome\n && 'undefined' != typeof chrome.storage\n ? chrome.storage.local\n : localstorage();\n\n/**\n * Colors.\n */\n\nexports.colors = [\n 'lightseagreen',\n 'forestgreen',\n 'goldenrod',\n 'dodgerblue',\n 'darkorchid',\n 'crimson'\n];\n\n/**\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\n * and the Firebug extension (any Firefox version) are known\n * to support \"%c\" CSS customizations.\n *\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\n */\n\nfunction useColors() {\n // NB: In an Electron preload script, document will be defined but not fully\n // initialized. Since we know we're in Chrome, we'll just detect this case\n // explicitly\n if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {\n return true;\n }\n\n // is webkit? http://stackoverflow.com/a/16459606/376773\n // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\n return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||\n // is firebug? http://stackoverflow.com/a/398120/376773\n (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||\n // is firefox >= v31?\n // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\n (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||\n // double check webkit in userAgent just in case we are in a worker\n (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\/(\\d+)/));\n}\n\n/**\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\n */\n\nexports.formatters.j = function(v) {\n try {\n return JSON.stringify(v);\n } catch (err) {\n return '[UnexpectedJSONParseError]: ' + err.message;\n }\n};\n\n\n/**\n * Colorize log arguments if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n var useColors = this.useColors;\n\n args[0] = (useColors ? '%c' : '')\n + this.namespace\n + (useColors ? ' %c' : ' ')\n + args[0]\n + (useColors ? '%c ' : ' ')\n + '+' + exports.humanize(this.diff);\n\n if (!useColors) return;\n\n var c = 'color: ' + this.color;\n args.splice(1, 0, c, 'color: inherit')\n\n // the final \"%c\" is somewhat tricky, because there could be other\n // arguments passed either before or after the %c, so we need to\n // figure out the correct index to insert the CSS into\n var index = 0;\n var lastC = 0;\n args[0].replace(/%[a-zA-Z%]/g, function(match) {\n if ('%%' === match) return;\n index++;\n if ('%c' === match) {\n // we only are interested in the *last* %c\n // (the user may have provided their own)\n lastC = index;\n }\n });\n\n args.splice(lastC, 0, c);\n}\n\n/**\n * Invokes `console.log()` when available.\n * No-op when `console.log` is not a \"function\".\n *\n * @api public\n */\n\nfunction log() {\n // this hackery is required for IE8/9, where\n // the `console.log` function doesn't have 'apply'\n return 'object' === typeof console\n && console.log\n && Function.prototype.apply.call(console.log, console, arguments);\n}\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\n\nfunction save(namespaces) {\n try {\n if (null == namespaces) {\n exports.storage.removeItem('debug');\n } else {\n exports.storage.debug = namespaces;\n }\n } catch(e) {}\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\n\nfunction load() {\n var r;\n try {\n r = exports.storage.debug;\n } catch(e) {}\n\n // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\n if (!r && typeof process !== 'undefined' && 'env' in process) {\n r = process.env.DEBUG;\n }\n\n return r;\n}\n\n/**\n * Enable namespaces listed in `localStorage.debug` initially.\n */\n\nexports.enable(load());\n\n/**\n * Localstorage attempts to return the localstorage.\n *\n * This is necessary because safari throws\n * when a user disables cookies/localstorage\n * and you attempt to access it.\n *\n * @return {LocalStorage}\n * @api private\n */\n\nfunction localstorage() {\n try {\n return window.localStorage;\n } catch (e) {}\n}\n","\n/**\n * This is the common logic for both the Node.js and web browser\n * implementations of `debug()`.\n *\n * Expose `debug()` as the module.\n */\n\nexports = module.exports = createDebug.debug = createDebug['default'] = createDebug;\nexports.coerce = coerce;\nexports.disable = disable;\nexports.enable = enable;\nexports.enabled = enabled;\nexports.humanize = require('ms');\n\n/**\n * The currently active debug mode names, and names to skip.\n */\n\nexports.names = [];\nexports.skips = [];\n\n/**\n * Map of special \"%n\" handling functions, for the debug \"format\" argument.\n *\n * Valid key names are a single, lower or upper-case letter, i.e. \"n\" and \"N\".\n */\n\nexports.formatters = {};\n\n/**\n * Previous log timestamp.\n */\n\nvar prevTime;\n\n/**\n * Select a color.\n * @param {String} namespace\n * @return {Number}\n * @api private\n */\n\nfunction selectColor(namespace) {\n var hash = 0, i;\n\n for (i in namespace) {\n hash = ((hash << 5) - hash) + namespace.charCodeAt(i);\n hash |= 0; // Convert to 32bit integer\n }\n\n return exports.colors[Math.abs(hash) % exports.colors.length];\n}\n\n/**\n * Create a debugger with the given `namespace`.\n *\n * @param {String} namespace\n * @return {Function}\n * @api public\n */\n\nfunction createDebug(namespace) {\n\n function debug() {\n // disabled?\n if (!debug.enabled) return;\n\n var self = debug;\n\n // set `diff` timestamp\n var curr = +new Date();\n var ms = curr - (prevTime || curr);\n self.diff = ms;\n self.prev = prevTime;\n self.curr = curr;\n prevTime = curr;\n\n // turn the `arguments` into a proper Array\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i];\n }\n\n args[0] = exports.coerce(args[0]);\n\n if ('string' !== typeof args[0]) {\n // anything else let's inspect with %O\n args.unshift('%O');\n }\n\n // apply any `formatters` transformations\n var index = 0;\n args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {\n // if we encounter an escaped % then don't increase the array index\n if (match === '%%') return match;\n index++;\n var formatter = exports.formatters[format];\n if ('function' === typeof formatter) {\n var val = args[index];\n match = formatter.call(self, val);\n\n // now we need to remove `args[index]` since it's inlined in the `format`\n args.splice(index, 1);\n index--;\n }\n return match;\n });\n\n // apply env-specific formatting (colors, etc.)\n exports.formatArgs.call(self, args);\n\n var logFn = debug.log || exports.log || console.log.bind(console);\n logFn.apply(self, args);\n }\n\n debug.namespace = namespace;\n debug.enabled = exports.enabled(namespace);\n debug.useColors = exports.useColors();\n debug.color = selectColor(namespace);\n\n // env-specific initialization logic for debug instances\n if ('function' === typeof exports.init) {\n exports.init(debug);\n }\n\n return debug;\n}\n\n/**\n * Enables a debug mode by namespaces. This can include modes\n * separated by a colon and wildcards.\n *\n * @param {String} namespaces\n * @api public\n */\n\nfunction enable(namespaces) {\n exports.save(namespaces);\n\n exports.names = [];\n exports.skips = [];\n\n var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\\s,]+/);\n var len = split.length;\n\n for (var i = 0; i < len; i++) {\n if (!split[i]) continue; // ignore empty strings\n namespaces = split[i].replace(/\\*/g, '.*?');\n if (namespaces[0] === '-') {\n exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));\n } else {\n exports.names.push(new RegExp('^' + namespaces + '$'));\n }\n }\n}\n\n/**\n * Disable debug output.\n *\n * @api public\n */\n\nfunction disable() {\n exports.enable('');\n}\n\n/**\n * Returns true if the given mode name is enabled, false otherwise.\n *\n * @param {String} name\n * @return {Boolean}\n * @api public\n */\n\nfunction enabled(name) {\n var i, len;\n for (i = 0, len = exports.skips.length; i < len; i++) {\n if (exports.skips[i].test(name)) {\n return false;\n }\n }\n for (i = 0, len = exports.names.length; i < len; i++) {\n if (exports.names[i].test(name)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Coerce `val`.\n *\n * @param {Mixed} val\n * @return {Mixed}\n * @api private\n */\n\nfunction coerce(val) {\n if (val instanceof Error) return val.stack || val.message;\n return val;\n}\n","/**\n * Detect Electron renderer process, which is node, but we should\n * treat as a browser.\n */\n\nif (typeof process !== 'undefined' && process.type === 'renderer') {\n module.exports = require('./browser.js');\n} else {\n module.exports = require('./node.js');\n}\n","/**\n * Module dependencies.\n */\n\nvar tty = require('tty');\nvar util = require('util');\n\n/**\n * This is the Node.js implementation of `debug()`.\n *\n * Expose `debug()` as the module.\n */\n\nexports = module.exports = require('./debug');\nexports.init = init;\nexports.log = log;\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\n\n/**\n * Colors.\n */\n\nexports.colors = [6, 2, 3, 4, 5, 1];\n\n/**\n * Build up the default `inspectOpts` object from the environment variables.\n *\n * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js\n */\n\nexports.inspectOpts = Object.keys(process.env).filter(function (key) {\n return /^debug_/i.test(key);\n}).reduce(function (obj, key) {\n // camel-case\n var prop = key\n .substring(6)\n .toLowerCase()\n .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });\n\n // coerce string value into JS value\n var val = process.env[key];\n if (/^(yes|on|true|enabled)$/i.test(val)) val = true;\n else if (/^(no|off|false|disabled)$/i.test(val)) val = false;\n else if (val === 'null') val = null;\n else val = Number(val);\n\n obj[prop] = val;\n return obj;\n}, {});\n\n/**\n * The file descriptor to write the `debug()` calls to.\n * Set the `DEBUG_FD` env variable to override with another value. i.e.:\n *\n * $ DEBUG_FD=3 node script.js 3>debug.log\n */\n\nvar fd = parseInt(process.env.DEBUG_FD, 10) || 2;\n\nif (1 !== fd && 2 !== fd) {\n util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()\n}\n\nvar stream = 1 === fd ? process.stdout :\n 2 === fd ? process.stderr :\n createWritableStdioStream(fd);\n\n/**\n * Is stdout a TTY? Colored output is enabled when `true`.\n */\n\nfunction useColors() {\n return 'colors' in exports.inspectOpts\n ? Boolean(exports.inspectOpts.colors)\n : tty.isatty(fd);\n}\n\n/**\n * Map %o to `util.inspect()`, all on a single line.\n */\n\nexports.formatters.o = function(v) {\n this.inspectOpts.colors = this.useColors;\n return util.inspect(v, this.inspectOpts)\n .split('\\n').map(function(str) {\n return str.trim()\n }).join(' ');\n};\n\n/**\n * Map %o to `util.inspect()`, allowing multiple lines if needed.\n */\n\nexports.formatters.O = function(v) {\n this.inspectOpts.colors = this.useColors;\n return util.inspect(v, this.inspectOpts);\n};\n\n/**\n * Adds ANSI color escape codes if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n var name = this.namespace;\n var useColors = this.useColors;\n\n if (useColors) {\n var c = this.color;\n var prefix = ' \\u001b[3' + c + ';1m' + name + ' ' + '\\u001b[0m';\n\n args[0] = prefix + args[0].split('\\n').join('\\n' + prefix);\n args.push('\\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\\u001b[0m');\n } else {\n args[0] = new Date().toUTCString()\n + ' ' + name + ' ' + args[0];\n }\n}\n\n/**\n * Invokes `util.format()` with the specified arguments and writes to `stream`.\n */\n\nfunction log() {\n return stream.write(util.format.apply(util, arguments) + '\\n');\n}\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\n\nfunction save(namespaces) {\n if (null == namespaces) {\n // If you set a process.env field to null or undefined, it gets cast to the\n // string 'null' or 'undefined'. Just delete instead.\n delete process.env.DEBUG;\n } else {\n process.env.DEBUG = namespaces;\n }\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\n\nfunction load() {\n return process.env.DEBUG;\n}\n\n/**\n * Copied from `node/src/node.js`.\n *\n * XXX: It's lame that node doesn't expose this API out-of-the-box. It also\n * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.\n */\n\nfunction createWritableStdioStream (fd) {\n var stream;\n var tty_wrap = process.binding('tty_wrap');\n\n // Note stream._type is used for test-module-load-list.js\n\n switch (tty_wrap.guessHandleType(fd)) {\n case 'TTY':\n stream = new tty.WriteStream(fd);\n stream._type = 'tty';\n\n // Hack to have stream not keep the event loop alive.\n // See https://github.com/joyent/node/issues/1726\n if (stream._handle && stream._handle.unref) {\n stream._handle.unref();\n }\n break;\n\n case 'FILE':\n var fs = require('fs');\n stream = new fs.SyncWriteStream(fd, { autoClose: false });\n stream._type = 'fs';\n break;\n\n case 'PIPE':\n case 'TCP':\n var net = require('net');\n stream = new net.Socket({\n fd: fd,\n readable: false,\n writable: true\n });\n\n // FIXME Should probably have an option in net.Socket to create a\n // stream from an existing fd which is writable only. But for now\n // we'll just add this hack and set the `readable` member to false.\n // Test: ./node test/fixtures/echo.js < /etc/passwd\n stream.readable = false;\n stream.read = null;\n stream._type = 'pipe';\n\n // FIXME Hack to have stream not keep the event loop alive.\n // See https://github.com/joyent/node/issues/1726\n if (stream._handle && stream._handle.unref) {\n stream._handle.unref();\n }\n break;\n\n default:\n // Probably an error on in uv_guess_handle()\n throw new Error('Implement me. Unknown stream file type!');\n }\n\n // For supporting legacy API we put the FD here.\n stream.fd = fd;\n\n stream._isStdio = true;\n\n return stream;\n}\n\n/**\n * Init logic for `debug` instances.\n *\n * Create a new `inspectOpts` object in case `useColors` is set\n * differently for a particular `debug` instance.\n */\n\nfunction init (debug) {\n debug.inspectOpts = {};\n\n var keys = Object.keys(exports.inspectOpts);\n for (var i = 0; i < keys.length; i++) {\n debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];\n }\n}\n\n/**\n * Enable namespaces listed in `process.env.DEBUG` initially.\n */\n\nexports.enable(load());\n","/**\n * Helpers.\n */\n\nvar s = 1000;\nvar m = s * 60;\nvar h = m * 60;\nvar d = h * 24;\nvar y = d * 365.25;\n\n/**\n * Parse or format the given `val`.\n *\n * Options:\n *\n * - `long` verbose formatting [false]\n *\n * @param {String|Number} val\n * @param {Object} [options]\n * @throws {Error} throw an error if val is not a non-empty string or a number\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function(val, options) {\n options = options || {};\n var type = typeof val;\n if (type === 'string' && val.length > 0) {\n return parse(val);\n } else if (type === 'number' && isNaN(val) === false) {\n return options.long ? fmtLong(val) : fmtShort(val);\n }\n throw new Error(\n 'val is not a non-empty string or a valid number. val=' +\n JSON.stringify(val)\n );\n};\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n str = String(str);\n if (str.length > 100) {\n return;\n }\n var match = /^((?:\\d+)?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(\n str\n );\n if (!match) {\n return;\n }\n var n = parseFloat(match[1]);\n var type = (match[2] || 'ms').toLowerCase();\n switch (type) {\n case 'years':\n case 'year':\n case 'yrs':\n case 'yr':\n case 'y':\n return n * y;\n case 'days':\n case 'day':\n case 'd':\n return n * d;\n case 'hours':\n case 'hour':\n case 'hrs':\n case 'hr':\n case 'h':\n return n * h;\n case 'minutes':\n case 'minute':\n case 'mins':\n case 'min':\n case 'm':\n return n * m;\n case 'seconds':\n case 'second':\n case 'secs':\n case 'sec':\n case 's':\n return n * s;\n case 'milliseconds':\n case 'millisecond':\n case 'msecs':\n case 'msec':\n case 'ms':\n return n;\n default:\n return undefined;\n }\n}\n\n/**\n * Short format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtShort(ms) {\n if (ms >= d) {\n return Math.round(ms / d) + 'd';\n }\n if (ms >= h) {\n return Math.round(ms / h) + 'h';\n }\n if (ms >= m) {\n return Math.round(ms / m) + 'm';\n }\n if (ms >= s) {\n return Math.round(ms / s) + 's';\n }\n return ms + 'ms';\n}\n\n/**\n * Long format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtLong(ms) {\n return plural(ms, d, 'day') ||\n plural(ms, h, 'hour') ||\n plural(ms, m, 'minute') ||\n plural(ms, s, 'second') ||\n ms + ' ms';\n}\n\n/**\n * Pluralization helper.\n */\n\nfunction plural(ms, n, name) {\n if (ms < n) {\n return;\n }\n if (ms < n * 1.5) {\n return Math.floor(ms / n) + ' ' + name;\n }\n return Math.ceil(ms / n) + ' ' + name + 's';\n}\n","const { BrowserWindow, ipcMain } = require('electron');\nconst { exec } = require('child_process');\nconst os = require('os');\nconst platform = os.platform();\nconst path = require('path');\nconst fs = require('fs');\nconst systemTempDir = os.tmpdir();\nconst testcaseOutputDir = path.join(systemTempDir, 'testcases');\nipcMain.handle('run-backend-command', async (event, filename, useLLM) => {\n global.logBackend(`Received pcap: ${filename}`);\n const isDev = !require('electron').app.isPackaged;\n const basePath = isDev\n ? path.join(__dirname, '../..')\n : process.resourcesPath;\n let snitchExePath;\n\n if (platform === 'win32') {\n snitchExePath = path.join(basePath, '\\\\backend\\\\snitch\\\\snitch.exe');\n } else if (platform === 'linux') {\n snitchExePath = path.join(basePath, '/backend/snitch/snitch');\n } else {\n snitchExePath = path.join(basePath, '/backend/snitch/snitch');\n }\n\n const backendCommand = `\"${snitchExePath}\" \"${filename}\" -a -o \"${testcaseOutputDir}\"${useLLM ? '' : ' --nollm'}`;\n\n // Always start with a clean output directory so snitch never hits the\n // interactive overwrite prompt on second (and later) runs.\n if (fs.existsSync(testcaseOutputDir)) {\n fs.rmSync(testcaseOutputDir, { recursive: true, force: true });\n }\n\n global.logBackend('Command to run:', backendCommand);\n\n function sendError(message) {\n const mainWin = BrowserWindow.getAllWindows()[0]; // or track your main window\n if (mainWin) {\n mainWin.webContents.send('backend-error', message);\n }\n }\n\n return new Promise((resolve) => {\n exec(backendCommand, (error, stdout, stderr) => {\n resolve(stdout);\n global.logBackend('Backend output:', stdout);\n global.logBackend('Backend error output:', stderr);\n if (stdout.includes('Ollama')) {\n sendError('Backend LLM generation error!');\n }\n if (error) {\n if (stderr.includes('supported capture file')) {\n sendError('Unsupported file format!');\n } else {\n sendError('Backend execution error! ' + error);\n }\n } else {\n setTimeout(() => {\n const hostsJsonPath = path.join(testcaseOutputDir, 'hosts.json');\n const mainWin = BrowserWindow.getAllWindows()[0];\n if (mainWin && fs.existsSync(hostsJsonPath)) {\n const hostsJsonData = fs.readFileSync(hostsJsonPath, 'utf8');\n mainWin.webContents.send('json-data', hostsJsonData);\n }\n }, 200);\n }\n });\n\n global.logBackend('Backend started, waiting for completion...');\n });\n});\n","module.exports = require(\"child_process\");","module.exports = require(\"electron\");","module.exports = require(\"fs\");","module.exports = require(\"net\");","module.exports = require(\"os\");","module.exports = require(\"path\");","module.exports = require(\"tty\");","module.exports = require(\"url\");","module.exports = require(\"util\");","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","\nif (typeof __webpack_require__ !== 'undefined') __webpack_require__.ab = __dirname + \"/native_modules/\";","const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron');\nconst fs = require('fs');\nconst path = require('path');\nconst { pathToFileURL } = require('url');\nconst { exec } = require('child_process');\nconst os = require('os');\nconst util = require('util');\nconst platform = os.platform();\nconst testcaseTempDir = path.join(os.tmpdir(), 'testcases');\nconst CONSOLE_INSPECT_DEPTH = 6;\nconst CONSOLE_MAX_ARRAY_LENGTH = 50;\nlet mainWindow;\nlet selectedFilePath;\nlet isBackendLoaded = false;\nlet versionFilePath;\nlet activityLogFilePath;\nlet hasLoggedProgramShutdown = false;\nconst activityLogEntries = [];\nconst pendingActivityLogEntries = [];\nlet isFirstRunAfterInstall = false;\nlet cachedOllamaInstalled = false;\nif (require('electron-squirrel-startup')) {\n app.quit();\n}\n\nipcMain.handle('file-size', async () => {\n try {\n // Get file stats asynchronously\n const fileStats = await fs.promises.stat(selectedFilePath); // Using promises version of stat\n return fileStats.size; // Send back the file size\n } catch (fileError) {\n console.error('Error getting file stats:', fileError);\n return 0; // Return 0 if there's an error\n }\n});\n\n// make sure we have a fresh temp dir\nfs.rmSync(testcaseTempDir, { recursive: true, force: true });\n\nfunction killBackendProcess() {\n console.log('Killing backend proc...');\n if (platform === 'win32') {\n exec('taskkill /IM snitch.exe /T /F', (fileError) => {\n if (fileError) console.error(fileError);\n });\n }\n if (platform === 'linux') {\n exec('pkill -f \"testcases\"', (fileError) => {\n if (fileError) console.error(fileError);\n });\n }\n}\n\nfunction checkOllama() {\n return new Promise((resolve) => {\n exec('ollama --version', (execError) => {\n if (execError) {\n resolve(false); // not installed or not in PATH\n } else {\n resolve(true);\n }\n });\n });\n}\n\nfunction checkNewInstall() {\n if (!versionFilePath) return false;\n try {\n if (!fs.existsSync(versionFilePath)) {\n return true;\n }\n const storedVersion = fs.readFileSync(versionFilePath, 'utf8').trim();\n return storedVersion !== app.getVersion();\n } catch (err) {\n console.error('Error checking install version:', err);\n return true;\n }\n}\n\nfunction createWindow() {\n mainWindow = new BrowserWindow({\n minWidth: 1450,\n minHeight: 750,\n frame: false,\n webPreferences: {\n preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,\n contextIsolation: true,\n nodeIntegration: true,\n },\n });\n mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);\n mainWindow.webContents.on('did-finish-load', () => {\n mainWindow.webContents.setZoomFactor(0.8); // makes everything fit snuggly\n });\n mainWindow.once('close', () => {\n appendActivityLogLine(\n timestampLifecycleMessage(\n `Session closed for PacketSnitch v${app.getVersion()}`,\n ),\n { broadcast: false },\n );\n });\n}\n\nfunction formatConsoleArgs(args) {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n return arg.stack || arg.message;\n }\n if (typeof arg === 'string') {\n return arg;\n }\n return util.inspect(arg, {\n depth: CONSOLE_INSPECT_DEPTH,\n breakLength: Infinity,\n maxArrayLength: CONSOLE_MAX_ARRAY_LENGTH,\n });\n })\n .join(' ');\n}\n\nfunction appendActivityLogToFile(entry) {\n try {\n fs.appendFileSync(activityLogFilePath, entry + os.EOL, 'utf8');\n } catch (error) {\n console.error('Unable to append activity log:', error);\n }\n}\n\nfunction cacheActivityLogEntry(entry) {\n activityLogEntries.unshift(entry);\n}\n\nfunction broadcastActivityLogEntry(entry) {\n if (mainWindow && !mainWindow.isDestroyed()) {\n mainWindow.webContents.send('activity-log-entry', entry);\n }\n}\n\nfunction normalizeActivityLogEntry(entry) {\n if (typeof entry !== 'string' || entry.trim() === '') return null;\n return entry.trim();\n}\n\nfunction timestampLifecycleMessage(message) {\n return `[${new Date().toISOString()}] [Core] ${message}`;\n}\n\nfunction appendActivityLogLine(entry, options = {}) {\n const { broadcast = true } = options;\n const normalizedEntry = normalizeActivityLogEntry(entry);\n if (!normalizedEntry) return;\n cacheActivityLogEntry(normalizedEntry);\n if (activityLogFilePath) {\n appendActivityLogToFile(normalizedEntry);\n } else {\n pendingActivityLogEntries.push(normalizedEntry);\n }\n if (broadcast) {\n broadcastActivityLogEntry(normalizedEntry);\n }\n}\n\nfunction flushPendingActivityLogEntries() {\n if (!activityLogFilePath || pendingActivityLogEntries.length === 0) return;\n pendingActivityLogEntries.forEach((entry) => {\n appendActivityLogToFile(entry);\n });\n pendingActivityLogEntries.splice(0);\n}\n\nconst originalConsoleLog = console.log.bind(console);\nconsole.log = (...args) => {\n originalConsoleLog(...args);\n const message = formatConsoleArgs(args);\n if (!message) return;\n appendActivityLogLine(\n `[${new Date().toISOString()}] [Console][Main] ${message}`,\n );\n};\n\nglobal.logBackend = (...args) => {\n const message = formatConsoleArgs(args);\n if (!message) return;\n originalConsoleLog(message);\n const timestamp = new Date().toISOString();\n message.split(/\\r?\\n/).forEach((line) => {\n if (line.trim() === '') return;\n appendActivityLogLine(`[${timestamp}] [Console][Backend] ${line}`);\n });\n};\n\napp.whenReady().then(() => {\n versionFilePath = path.join(app.getPath('userData'), 'installed_version.txt');\n activityLogFilePath = path.join(app.getPath('userData'), 'activity-log.txt');\n flushPendingActivityLogEntries();\n appendActivityLogLine(\n `[${new Date().toISOString()}] [Core] Session started for PacketSnitch v${app.getVersion()}`,\n );\n isFirstRunAfterInstall = checkNewInstall();\n checkOllama().then((isInstalled) => {\n cachedOllamaInstalled = isInstalled;\n if (!isInstalled) {\n console.log(\n 'Ollama is not installed. LLM summarisation will be unavailable.',\n );\n }\n createWindow();\n app.on('activate', function () {\n if (BrowserWindow.getAllWindows().length === 0) createWindow();\n });\n console.log('App ready, waiting for file selection...');\n // start the process that listens for the file selection and runs the backend command\n require('./back-comm');\n ipcMain.handle('select-file', async () => {\n const { canceled, filePaths } = await dialog.showOpenDialog({\n properties: ['openFile'],\n });\n if (canceled) return null;\n console.log('Accepted pcapng.. Checking for json existence...');\n isBackendLoaded = true;\n // Remove stale output directory so snitch always starts with a clean slate\n if (fs.existsSync(testcaseTempDir)) {\n fs.rmSync(testcaseTempDir, { recursive: true, force: true });\n }\n console.log('File selected:', filePaths[0]);\n selectedFilePath = filePaths[0];\n return filePaths[0];\n });\n });\n});\n\nipcMain.handle('check-first-run', async () => {\n const isDev = !app.isPackaged;\n const basePath = isDev\n ? path.join(__dirname, '../..')\n : process.resourcesPath;\n const backendExe = platform === 'win32' ? 'snitch.exe' : 'snitch';\n const filesToCheck = [\n {\n name: 'PacketSnitch Backend (' + backendExe + ')',\n path: path.join(basePath, 'backend', backendExe),\n },\n {\n name: 'GeoIP Database (GeoLite2-City.mmdb)',\n path: path.join(basePath, 'backend', 'common', 'GeoLite2-City.mmdb'),\n },\n {\n name: 'MAC Vendors Database (mac-vendors-export.csv)',\n path: path.join(basePath, 'backend', 'common', 'mac-vendors-export.csv'),\n },\n {\n name: 'Services Database (service-names-port-numbers.csv)',\n path: path.join(\n basePath,\n 'backend',\n 'common',\n 'service-names-port-numbers.csv',\n ),\n },\n ];\n const installedFiles = filesToCheck.map((f) => ({\n name: f.name,\n path: f.path,\n exists: fs.existsSync(f.path),\n }));\n return {\n isFirstRun: isFirstRunAfterInstall,\n version: app.getVersion(),\n ollamaInstalled: cachedOllamaInstalled,\n installedFiles,\n };\n});\n\nipcMain.handle('dismiss-first-run', async () => {\n const currentVersion = app.getVersion();\n try {\n fs.writeFileSync(versionFilePath, currentVersion, 'utf8');\n isFirstRunAfterInstall = false;\n return { success: true };\n } catch (err) {\n console.error('Failed to write version file:', err);\n return { success: false, error: err.message };\n }\n});\n\nipcMain.handle('quit-app', () => {\n app.quit();\n});\n\nipcMain.handle('prompt-save-session-on-exit', async () => {\n const response = await dialog.showMessageBox({\n type: 'question',\n buttons: ['Save Session', \"Don't Save\", 'Cancel'],\n defaultId: 0,\n cancelId: 2,\n title: 'Save Session',\n message: 'Do you want to save your PacketSnitch session before exiting?',\n });\n if (response.response === 0) return 'save';\n if (response.response === 1) return 'discard';\n return 'cancel';\n});\n\nipcMain.handle('save-json', async (_event, jsonData) => {\n if (typeof jsonData !== 'string' || jsonData.trim() === '') {\n return { success: false, error: 'No JSON data to save' };\n }\n\n const { canceled, filePath } = await dialog.showSaveDialog({\n title: 'Save PacketSnitch Session',\n defaultPath: path.join(app.getPath('documents'), 'packetsnitch-session.json'),\n filters: [{ name: 'JSON Files', extensions: ['json'] }],\n });\n if (canceled || !filePath) return { success: false, canceled: true };\n\n try {\n await fs.promises.writeFile(filePath, jsonData, 'utf8');\n return { success: true };\n } catch (err) {\n console.error('Save error:', err);\n return { success: false, error: err.message };\n }\n});\n\nipcMain.handle('save-packet', async (_event, packetData) => {\n if (packetData === null || packetData === undefined) {\n return { success: false, error: 'No packet data to save' };\n }\n const packetJson = JSON.stringify(packetData, null, 2);\n\n const { canceled, filePath } = await dialog.showSaveDialog({\n title: 'Export Packet',\n defaultPath: path.join(app.getPath('documents'), 'packet.json'),\n filters: [{ name: 'JSON Files', extensions: ['json'] }],\n });\n if (canceled || !filePath) return { success: false, canceled: true };\n\n try {\n await fs.promises.writeFile(filePath, packetJson, 'utf8');\n return { success: true };\n } catch (err) {\n console.error('Packet export error:', err);\n return { success: false, error: err.message };\n }\n});\n\nipcMain.handle('save-payload', async (_event, payloadHex) => {\n if (typeof payloadHex !== 'string') {\n return { success: false, error: 'No payload data to save' };\n }\n const normalizedHex = payloadHex.replace(/\\s+/g, '');\n if (\n normalizedHex.length === 0 ||\n normalizedHex.length % 2 !== 0 ||\n !/^[\\da-fA-F]+$/.test(normalizedHex)\n ) {\n return {\n success: false,\n error: 'Payload must be a non-empty hex string with an even length',\n };\n }\n\n const { canceled, filePath } = await dialog.showSaveDialog({\n title: 'Export Packet Payload',\n defaultPath: path.join(app.getPath('documents'), 'packet-payload.bin'),\n filters: [\n { name: 'Binary Files', extensions: ['bin'] },\n { name: 'All Files', extensions: ['*'] },\n ],\n });\n if (canceled || !filePath) return { success: false, canceled: true };\n\n try {\n const payloadBuffer = Buffer.from(normalizedHex, 'hex');\n await fs.promises.writeFile(filePath, payloadBuffer);\n return { success: true };\n } catch (err) {\n console.error('Payload export error:', err);\n return { success: false, error: err.message };\n }\n});\n\nipcMain.handle('save-cookie-jar', async (_event, cookieJarText) => {\n if (typeof cookieJarText !== 'string' || cookieJarText.trim() === '') {\n return { success: false, error: 'No cookie jar data to save' };\n }\n\n const { canceled, filePath } = await dialog.showSaveDialog({\n title: 'Save Cookie Jar',\n defaultPath: path.join(app.getPath('documents'), 'cookie_jar.txt'),\n filters: [\n { name: 'Text Files', extensions: ['txt'] },\n { name: 'All Files', extensions: ['*'] },\n ],\n });\n if (canceled || !filePath) return { success: false, canceled: true };\n\n try {\n await fs.promises.writeFile(filePath, cookieJarText, 'utf8');\n return { success: true };\n } catch (err) {\n console.error('Cookie jar save error:', err);\n return { success: false, error: err.message };\n }\n});\n\nipcMain.handle('save-notes', async (_event, notesText) => {\n if (typeof notesText !== 'string' || notesText.trim() === '') {\n return { success: false, error: 'No notes data to save' };\n }\n\n const { canceled, filePath } = await dialog.showSaveDialog({\n title: 'Save Notes',\n defaultPath: path.join(app.getPath('documents'), 'packetsnitch-notes.txt'),\n filters: [\n { name: 'Text Files', extensions: ['txt'] },\n { name: 'All Files', extensions: ['*'] },\n ],\n });\n if (canceled || !filePath) return { success: false, canceled: true };\n\n try {\n await fs.promises.writeFile(filePath, notesText, 'utf8');\n return { success: true };\n } catch (err) {\n console.error('Notes save error:', err);\n return { success: false, error: err.message };\n }\n});\n\n// Map a Content-Type header value to a file extension for HTTP body exports.\nfunction extFromContentType(contentType) {\n const base = (contentType || '').split(';')[0].trim().toLowerCase();\n const map = {\n 'text/html': 'html',\n 'text/plain': 'txt',\n 'text/css': 'css',\n 'text/csv': 'csv',\n 'text/xml': 'xml',\n 'application/javascript': 'js',\n 'application/x-javascript': 'js',\n 'text/javascript': 'js',\n 'application/json': 'json',\n 'application/xml': 'xml',\n 'image/jpeg': 'jpg',\n 'image/png': 'png',\n 'image/gif': 'gif',\n 'image/svg+xml': 'svg',\n 'image/webp': 'webp',\n 'image/bmp': 'bmp',\n 'image/x-icon': 'ico',\n 'image/ico': 'ico',\n 'application/pdf': 'pdf',\n 'application/zip': 'zip',\n 'application/x-zip-compressed': 'zip',\n 'application/gzip': 'gz',\n 'application/x-gzip': 'gz',\n 'application/octet-stream': 'bin',\n };\n return map[base] || 'bin';\n}\n\n// Validate and decode a hex string into a Buffer; returns null on failure.\nfunction hexToBuffer(hex) {\n if (typeof hex !== 'string') return null;\n const normalized = hex.replace(/\\s+/g, '');\n if (normalized.length === 0 || normalized.length % 2 !== 0) return null;\n if (!/^[\\da-fA-F]+$/.test(normalized)) return null;\n return Buffer.from(normalized, 'hex');\n}\n\nipcMain.handle('save-http-body', async (_event, bodyHex, contentType) => {\n const buf = hexToBuffer(bodyHex);\n if (!buf) return { success: false, error: 'Invalid HTTP body data' };\n\n const ext = extFromContentType(contentType);\n const { canceled, filePath } = await dialog.showSaveDialog({\n title: 'Save HTTP Body',\n defaultPath: path.join(app.getPath('documents'), `http-body.${ext}`),\n filters: [\n { name: 'HTTP Body', extensions: [ext] },\n { name: 'All Files', extensions: ['*'] },\n ],\n });\n if (canceled || !filePath) return { success: false, canceled: true };\n\n try {\n await fs.promises.writeFile(filePath, buf);\n return { success: true };\n } catch (err) {\n console.error('HTTP body save error:', err);\n return { success: false, error: err.message };\n }\n});\n\nipcMain.handle('preview-http-body', async (_event, bodyHex, contentType) => {\n const buf = hexToBuffer(bodyHex);\n if (!buf) return { success: false, error: 'Invalid HTTP body data' };\n\n const ext = extFromContentType(contentType);\n try {\n // Use a unique temp directory per preview to avoid races and data leaks.\n const tmpDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), 'ps-preview-'),\n );\n const tmpFile = path.join(tmpDir, `http-preview.${ext}`);\n await fs.promises.writeFile(tmpFile, buf);\n const fileUrl = pathToFileURL(tmpFile).href;\n await shell.openExternal(fileUrl);\n // Schedule cleanup after a delay to give the browser time to read the file.\n setTimeout(() => {\n fs.promises.rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n }, 30000);\n return { success: true };\n } catch (err) {\n console.error('HTTP body preview error:', err);\n return { success: false, error: err.message };\n }\n});\n\nipcMain.handle('open-external-url', async (_event, rawUrl) => {\n if (typeof rawUrl !== 'string' || !rawUrl.trim()) {\n return { success: false, error: 'Invalid URL' };\n }\n try {\n const parsed = new URL(rawUrl.trim());\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return { success: false, error: 'Only HTTP/HTTPS URLs are supported' };\n }\n await shell.openExternal(parsed.href);\n return { success: true };\n } catch (err) {\n return { success: false, error: err?.message || 'Invalid URL' };\n }\n});\n\nipcMain.handle('append-activity-log', async (_event, entry) => {\n const normalizedEntry = normalizeActivityLogEntry(entry);\n if (!normalizedEntry) {\n return { success: false, error: 'Invalid log entry' };\n }\n // Renderer entries are already shown locally, so skip broadcasting them back.\n appendActivityLogLine(normalizedEntry, { broadcast: false });\n return { success: true, path: activityLogFilePath };\n});\n\nipcMain.handle('get-activity-log-path', async () => {\n return activityLogFilePath;\n});\n\nipcMain.handle('get-activity-log-entries', async () => {\n return [...activityLogEntries];\n});\n\napp.on('before-quit', () => {\n if (!hasLoggedProgramShutdown) {\n appendActivityLogLine(\n timestampLifecycleMessage(\n `Program shutdown requested for PacketSnitch v${app.getVersion()}`,\n ),\n { broadcast: false },\n );\n hasLoggedProgramShutdown = true;\n }\n // make sure the backend snitch process dies!\n if (isBackendLoaded) {\n killBackendProcess();\n }\n});\n"],"names":[],"sourceRoot":""}
|