Port MACInfo module (#40)

* First commit, add module folder

* Added spinner and allowed input of full mac

* CheckMAC online function ( non working )

* reverted change to build script

* Added working check online

* Added more info output to lookup online

* Added beginning of tabs function

* removed modified build script

* MACInfo: fix selectors, fix resource URL paths, fix API import path

* Removed online button from offline tab and other way around

* Fixed space being registered in lookup

* Fixed spinner CSS

* Changed looks of box

* removed spinners

* Fixed spelling and removed unneeded titling

* macinfo: Fix layout

* Added compatibility with windows naming scheme

* Added breakline for text

* Regex to check for valid MAC address, going to work on showing as proper error

* Added regex check for offline

* removed second build file

* Bold fonts for result category

* Added error if no valid MAC adress was inputted

* Specified types for variables and checked for valid mac before file open for speed

* Removed unused onstart due to the dir automaticlly being created anyways

* Class rename

* Fix regex check for offline and online mac

* Opened json file on start instead of on request

* misc: Re-run checks

* Fix regex lookup

* Added web icon or online

* added desktop icon for offline mode

* Fixed icons completely.

* Fix invalid module error handling in API

* Fix regex check

* Update module icon

* removed unused icons.

Co-authored-by: Marc <foxtrot@malloc.me>
Co-authored-by: Theodor Johanson <theo@pc.localdomain>
pull/49/head
Theo 2021-07-09 23:55:26 +02:00 committed by GitHub
parent 07dd54a336
commit 7f043cbc5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 33280 additions and 0 deletions

13
MACInfo/.editorconfig Normal file
View File

@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

46
MACInfo/.gitignore vendored Normal file
View File

@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

47
MACInfo/angular.json Normal file
View File

@ -0,0 +1,47 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"MACInfo": {
"projectType": "library",
"root": "projects/MACInfo",
"sourceRoot": "projects/MACInfo/src",
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/MACInfo/tsconfig.lib.json",
"project": "projects/MACInfo/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/MACInfo/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/MACInfo/src/test.ts",
"tsConfig": "projects/MACInfo/tsconfig.spec.json",
"karmaConfig": "projects/MACInfo/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/MACInfo/tsconfig.lib.json",
"projects/MACInfo/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}},
"defaultProject": "MACInfo"
}

90
MACInfo/build.sh Executable file
View File

@ -0,0 +1,90 @@
#!/bin/bash
MODULENAME=$(basename $PWD)
check_workspace() {
if [[ ! -d "node_modules" ]]; then
while true; do
read -p "[!!] The Angular workspace has not been prepared. Would you like to do it now? [Y\n] " yn
case $yn in
[Yy]* ) prepare_workspace; break;;
[Nn]* ) exit 1;;
* ) prepare_workspace; break;;
esac
done
fi
}
prepare_workspace() {
echo "[*] Preparing the Angular workspace."
if ! command -v npm &> /dev/null; then
echo "[!] NPM does not appear to be installed on this system. Failed to create workspace."
return
fi
if ! npm install &> /dev/null; then
echo "[!] Failed to prepare workspace. Run npm install to see why."
return
fi
echo "[*] Prepared the Angular workspace successfully."
}
build_module() {
ng build --prod > /dev/null 2>&1
RET=$?
if [[ $RET -ne 0 ]]; then
echo "[!] Angular Build Failed: Run 'ng build --prod' to figure out why."
exit 1
else
echo "[*] Angular Build Succeeded"
fi
# Step 2: Copy the required files to the build output
cp -r projects/$MODULENAME/src/module.svg dist/$MODULENAME/bundles/
cp -r projects/$MODULENAME/src/module.json dist/$MODULENAME/bundles/
cp -r projects/$MODULENAME/src/module.py dist/$MODULENAME/bundles/ > /dev/null 2>&1
cp -r projects/$MODULENAME/src/module.php dist/$MODULENAME/bundles/ > /dev/null 2>&1
cp -r projects/$MODULENAME/src/assets/ dist/$MODULENAME/bundles/ > /dev/null 2>&1
# Step 3: Clean up
rm -rf dist/$MODULENAME/bundles/*.map
rm -rf dist/$MODULENAME/bundles/*.min*
rm -rf bundletmp
mv dist/$MODULENAME/bundles/ bundletmp
rm -rf dist/$MODULENAME/*
mv bundletmp/* dist/$MODULENAME/
rm -rf bundletmp
}
package() {
VERS=$(cat dist/$MODULENAME/module.json | grep "version" | awk '{split($0, a, ": "); gsub("\"", "", a[2]); gsub(",", "", a[2]); print a[2]}')
rm -rf $MODULENAME-$VERS.tar.gz
echo "[*] Packaging $MODULENAME (Version $VERS)"
cd dist/
tar -pczf $MODULENAME-$VERS.tar.gz $MODULENAME
mv $MODULENAME-$VERS.tar.gz ../
cd ../
}
copy_to_device() {
echo "[*] Copying module to WiFi Pineapple via SCP"
scp -r dist/$MODULENAME root@172.16.42.1:/pineapple/modules
}
main() {
check_workspace
build_module
if [[ $1 == "package" ]]; then
package
elif [[ $1 == "copy" ]]; then
copy_to_device
fi
echo "[*] Success!"
}
main $1

32121
MACInfo/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

52
MACInfo/package.json Normal file
View File

@ -0,0 +1,52 @@
{
"name": "MACInfo",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~9.1.11",
"@angular/cdk": "^9.2.4",
"@angular/common": "~9.1.11",
"@angular/compiler": "~9.1.11",
"@angular/core": "~9.1.11",
"@angular/flex-layout": "^9.0.0-beta.31",
"@angular/forms": "~9.1.11",
"@angular/material": "^9.2.4",
"@angular/platform-browser": "~9.1.11",
"@angular/platform-browser-dynamic": "~9.1.11",
"@angular/router": "~9.1.11",
"rxjs": "~6.5.5",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.901.8",
"@angular-devkit/build-ng-packagr": "~0.901.8",
"@angular/cli": "~9.1.8",
"@angular/compiler-cli": "~9.1.11",
"@angular/language-service": "~9.1.11",
"@types/jasmine": "~3.5.10",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~5.0.2",
"karma": "~5.1.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.3",
"karma-jasmine": "~3.3.1",
"karma-jasmine-html-reporter": "^1.4.0",
"ng-packagr": "^9.1.5",
"protractor": "~7.0.0",
"ts-node": "~8.10.2",
"tslint": "~6.1.2",
"typescript": "^3.6.5"
}
}

View File

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/MACInfo",
"lib": {
"entryFile": "src/public-api.ts"
}
}

View File

@ -0,0 +1,11 @@
{
"name": "MACInfo",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^8.2.14",
"@angular/core": "^8.2.14"
},
"scripts": {
"build": "ng build --prod"
}
}

View File

@ -0,0 +1,40 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MACInfoComponent } from './components/MACInfo.component';
import { MACInfoOfflineComponent } from './components/subviews/macinfo-offline/macinfo-offline.component';
import { MACInfoOnlineComponent } from './components/subviews/macinfo-online/macinfo-online.component';
import { RouterModule, Routes } from '@angular/router';
import {MaterialModule} from './modules/material/material.module';
import {FlexLayoutModule} from '@angular/flex-layout';
import {FormsModule} from '@angular/forms';
const routes: Routes = [
{
path: '',
component: MACInfoComponent,
children: [
{ path: '', component: MACInfoOfflineComponent, pathMatch: 'full' },
{ path: 'online', component: MACInfoOnlineComponent }
]
}
];
@NgModule({
declarations: [
MACInfoComponent,
MACInfoOfflineComponent,
MACInfoOnlineComponent
],
imports: [
CommonModule,
RouterModule.forChild(routes),
MaterialModule,
FlexLayoutModule,
FormsModule,
],
exports: [MACInfoComponent]
})
export class MACInfoModule { }

View File

@ -0,0 +1,14 @@
.macinfo-center-card {
display: flex;
justify-content: center;
align-items: center;
}
.macinfo-lookup-button {
display: flex;
justify-content: center;
align-items: center;
height: 34px;
}

View File

@ -0,0 +1,29 @@
<nav mat-tab-nav-bar color="accent">
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="link.link"
routerLinkActive #rla="routerLinkActive"
[routerLinkActiveOptions]="{exact: true}"
[active]="rla.isActive">
<mat-icon *ngIf="link.label === 'Offline Lookup'">
<svg style="width:24px;height:24px" id="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path class="cls-1" d="M18.06,4.78H1.28A1.29,1.29,0,0,0,0,6.07V41.93a1.29,1.29,0,0,0,1.28,1.29H18.06a1.28,1.28,0,0,0,1.28-1.29V6.07A1.28,1.28,0,0,0,18.06,4.78Zm-1.66,34a.52.52,0,0,1-.51.52H3.45a.51.51,0,0,1-.51-.52v-.6a.51.51,0,0,1,.51-.52H15.89a.52.52,0,0,1,.51.52Zm0-3.43a.51.51,0,0,1-.51.51H3.45a.51.51,0,0,1-.51-.51v-.61a.51.51,0,0,1,.51-.51H15.89a.51.51,0,0,1,.51.51Zm0-3.43a.51.51,0,0,1-.51.51H3.45a.51.51,0,0,1-.51-.51v-.61a.51.51,0,0,1,.51-.51H15.89a.51.51,0,0,1,.51.51Zm0-3.43a.51.51,0,0,1-.51.51H3.45a.51.51,0,0,1-.51-.51V27.9a.51.51,0,0,1,.51-.51H15.89a.51.51,0,0,1,.51.51Zm-1.67-11a1.68,1.68,0,1,1,1.67-1.68A1.68,1.68,0,0,1,14.73,17.5Zm1.67-7.14a.51.51,0,0,1-.51.51H3.45a.51.51,0,0,1-.51-.51v-2a.51.51,0,0,1,.51-.51H15.89a.51.51,0,0,1,.51.51Z"/>
<path class="cls-1" d="M46.72,9.54H23.14a1.28,1.28,0,0,0-1.28,1.29v24.3a1.29,1.29,0,0,0,1.28,1.29H46.72A1.29,1.29,0,0,0,48,35.13V10.83A1.29,1.29,0,0,0,46.72,9.54ZM45.06,32.8a.52.52,0,0,1-.51.51H25.31a.51.51,0,0,1-.51-.51V13.15a.51.51,0,0,1,.51-.51H44.55a.51.51,0,0,1,.51.51Z"/>
<path class="cls-1" d="M43.53,40.23H38.07V37.49H31.79v2.74H26.33a.51.51,0,0,0-.51.51v2a.51.51,0,0,0,.51.51h17.2a.51.51,0,0,0,.51-.51v-2A.51.51,0,0,0,43.53,40.23Z"/>
</svg>
</mat-icon>
<mat-icon *ngIf="link.label === 'Online Lookup'">
<svg style="width:24px;height:24px" id="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path d="M24,0A24,24,0,1,0,48,23.94,24,24,0,0,0,24,0Zm9.74,22.57H25.42V14.06a43.27,43.27,0,0,1,6.78.62A47.5,47.5,0,0,1,33.69,22.57Zm1.72-7a28.44,28.44,0,0,1,9.37,5c.14.61.14,1.34.25,2.06H36.52A55.66,55.66,0,0,0,35.41,15.55Zm-10-4.32V3a9.58,9.58,0,0,1,2,.25,47.3,47.3,0,0,1,3.82,8.38A46.55,46.55,0,0,0,25.42,11.23Zm-3,.12a39.85,39.85,0,0,0-6.79,1.25,35,35,0,0,1,4.07-9.27A10.17,10.17,0,0,1,22.46,3Zm0,3v8.26h-8.4a28.86,28.86,0,0,1,.74-6.78A38.81,38.81,0,0,1,22.46,14.31ZM11.23,22.57H3a11.15,11.15,0,0,1,.25-2.06,54,54,0,0,1,8.64-3.85A29.58,29.58,0,0,0,11.23,22.57ZM3,25.43h8.27A31,31,0,0,0,12,32.09a34.79,34.79,0,0,1-8.75-3.94A17.84,17.84,0,0,1,3,25.43Zm11.1,0h8.4V34a37,37,0,0,1-7.41-1A33,33,0,0,1,14.06,25.43Zm8.4,11.34V45a17.69,17.69,0,0,1-2.6-.37A48.91,48.91,0,0,1,15.91,36,50.63,50.63,0,0,0,22.46,36.77Zm3,0a68.77,68.77,0,0,0,6.9-.73,29.56,29.56,0,0,1-4.81,8.77c-.74.11-1.35.11-2.09.23Zm0-2.82V25.43H33.8a36.87,36.87,0,0,1-.61,7.39A47.92,47.92,0,0,1,25.42,34Zm11.35-8.52H45c-.11,1-.25,1.85-.36,2.72a45.11,45.11,0,0,1-8.41,3.69A35.64,35.64,0,0,0,36.77,25.43Zm6.66-9.38a30.53,30.53,0,0,0-9-3.84,47.35,47.35,0,0,0-3.21-8A21.37,21.37,0,0,1,43.43,16.05ZM15.8,4.57a41.05,41.05,0,0,0-3.34,8.76A57.55,57.55,0,0,0,4.2,16.78,20.51,20.51,0,0,1,15.8,4.57ZM4.44,32.21a44.14,44.14,0,0,0,8.28,3.08,36.86,36.86,0,0,0,3.19,8.15A21.34,21.34,0,0,1,4.44,32.21ZM32,43.58a31.18,31.18,0,0,0,3.58-8.4,47.39,47.39,0,0,0,7.89-3.09A21,21,0,0,1,32,43.58Z"/>
</svg>
</mat-icon>
<div [fxShow.sm]="false" [fxShow.xs]="false">
&nbsp;&nbsp;
{{ link.label }}
</div>
</a>
</nav>
<br/>
<div>
<router-outlet></router-outlet>
</div>

View File

@ -0,0 +1,30 @@
import {Component, OnInit, ViewChild} from '@angular/core';
@Component({
selector: 'lib-MACInfo',
templateUrl: './MACInfo.component.html',
styleUrls: ['./MACInfo.component.css']
})
export class MACInfoComponent implements OnInit {
navLinks: any[];
@ViewChild('rla') rla;
constructor() {
this.navLinks = [
{
label: 'Offline Lookup',
link: './',
index: 0
},
{
label: 'Online Lookup',
link: './online',
index: 1
},
]
}
ngOnInit() {
}
}

View File

@ -0,0 +1,12 @@
.macinfo-offline-card {
min-width: 40%;
}
.macinfo-offline-lookup-field {
width: 100%;
}
.macinfo-offline-card-content {
display: flex;
flex-direction: column;
}

View File

@ -0,0 +1,32 @@
<div class="macinfo-center-card">
<mat-card class="macinfo-offline-card">
<mat-card-title>MAC Address Lookup</mat-card-title>
<mat-card-content class="macinfo-offline-card-content">
<mat-form-field class="macinfo-offline-lookup-field">
<mat-label>MAC Address</mat-label>
<input matInput [(ngModel)]="userInput" />
</mat-form-field>
<div *ngIf="company">
<span><strong>Company:</strong> {{ company }}</span>
<br/>
<br/>
</div>
<div *ngIf="!validMAC">
<span><strong>Please enter a valid MAC address</strong></span>
</div>
<button mat-flat-button class="macinfo-lookup-button"
color="accent"
(click)="check_mac();"
[disabled]="isLoading">
<span *ngIf="!isLoading">Lookup MAC Address</span>
<span *ngIf="isLoading">
<mat-spinner diameter="20"></mat-spinner>
</span>
</button>
</mat-card-content>
</mat-card>
</div>
<br/>

View File

@ -0,0 +1,36 @@
import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../../services/api.service';
@Component({
selector: 'lib-MACInfo-offlineinfo',
templateUrl: './macinfo-offline.component.html',
styleUrls: ['../../MACInfo.component.css', './macinfo-offline.component.css']
})
export class MACInfoOfflineComponent implements OnInit {
constructor(private API: ApiService) { }
userInput : string = '';
company : string = '';
nomac : string = '';
isLoading : boolean = false;
validMAC : boolean = true;
check_mac(): void {
this.isLoading = true;
this.API.request({
module: 'MACInfo',
action: 'check_mac',
user_input: this.userInput
}, (response) => {
this.isLoading = false;
this.company = response.company;
this.nomac = response.nomac;
if (this.nomac === "Not a valid MAC address"){
this.validMAC = false;
}
})
}
ngOnInit() {
}
}

View File

@ -0,0 +1,21 @@
.macinfo-online-card {
min-width: 40%;
}
.macinfo-online-card-content {
display: flex;
flex-direction: column;
}
.macinfo-online-lookup-field {
width: 100%;
}
.macinfo-online-results {
display: flex;
justify-content: space-evenly;
}
.macinfo-online-results-left {
word-break: break-word;
max-width: 300px;
}

View File

@ -0,0 +1,57 @@
<div class="macinfo-center-card">
<mat-card class="macinfo-online-card">
<mat-card-title>MAC Address Online Lookup</mat-card-title>
<mat-card-content class="macinfo-online-card-content">
<mat-form-field class="macinfo-online-lookup-field">
<mat-label>MAC Address</mat-label>
<input matInput [(ngModel)]="userInput" />
</mat-form-field>
<div *ngIf="!validMAC">
<span><strong>Please enter a valid MAC address</strong></span>
</div>
<div *ngIf="company" class="macinfo-online-results">
<br/>
<div class="macinfo-online-results-left">
<span>
<strong>Company:</strong> {{ company }}
</span>
<br/>
<span>
<strong>Address:</strong> {{ address }}
</span>
<br/>
<span>
<strong>Type:</strong> {{ mactype }}
</span>
</div>
<div>
<span>
<strong>Country:</strong> {{ maccountry }}
</span>
<br/>
<span>
<strong>Start hex:</strong> {{ start_hex }}
</span>
<br/>
<span>
<strong>End hex:</strong> {{ end_hex }}
</span>
</div>
<br/>
</div>
<button mat-flat-button class="macinfo-lookup-button"
color="accent"
(click)="check_mac_online();"
[disabled]="isLoading">
<span *ngIf="!isLoading">Lookup MAC Address Online</span>
<span *ngIf="isLoading">
<mat-spinner diameter="20"></mat-spinner>
</span>
</button>
</mat-card-content>
</mat-card>
</div>
<br/>

View File

@ -0,0 +1,47 @@
import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../../services/api.service';
@Component({
selector: 'lib-MACInfo-onlinecomponent',
templateUrl: './macinfo-online.component.html',
styleUrls: ['../../MACInfo.component.css', './macinfo-online.component.css']
})
export class MACInfoOnlineComponent implements OnInit {
constructor(private API: ApiService) { }
userInput : string = '';
isLoading : boolean = false;
nomac : string = '';
company : string = '';
address : string = '';
mactype : string = '';
maccountry : string = '';
start_hex : string = '';
end_hex : string = '';
validMAC: boolean = true;
check_mac_online(): void {
this.isLoading = true;
this.API.request({
module: 'MACInfo',
action: 'check_mac_online',
user_input: this.userInput
}, (response) => {
this.isLoading = false;
this.company = response.company;
this.address = response.address;
this.mactype = response.mactype;
this.maccountry = response.maccountry;
this.start_hex = response.start_hex;
this.end_hex = response.end_hex;
this.nomac = response.nomac;
if (this.nomac == "Not a valid MAC address"){
this.validMAC = false;
}
})
}
ngOnInit() {
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2018 Hak5 LLC.
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { A11yModule } from '@angular/cdk/a11y';
import { BidiModule } from '@angular/cdk/bidi';
import { ObserversModule } from '@angular/cdk/observers';
import { OverlayModule } from '@angular/cdk/overlay';
import { PlatformModule } from '@angular/cdk/platform';
import { PortalModule } from '@angular/cdk/portal';
import { CdkStepperModule } from '@angular/cdk/stepper';
import { CdkTableModule } from '@angular/cdk/table';
import { CdkTreeModule } from '@angular/cdk/tree';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatBadgeModule } from '@angular/material/badge';
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatRadioModule } from '@angular/material/radio';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatSliderModule } from '@angular/material/slider';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatStepperModule } from '@angular/material/stepper';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTreeModule } from '@angular/material/tree';
@NgModule({
imports: [ CommonModule],
exports: [
// CDK
A11yModule,
BidiModule,
ObserversModule,
OverlayModule,
PlatformModule,
PortalModule,
CdkStepperModule,
CdkTableModule,
CdkTreeModule,
// Material
MatAutocompleteModule,
MatBadgeModule,
MatBottomSheetModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,
MatDividerModule,
MatExpansionModule,
MatFormFieldModule,
MatGridListModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatSnackBarModule,
MatSortModule,
MatStepperModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatTreeModule,
],
declarations: []
})
export class MaterialModule {
}

View File

@ -0,0 +1,8 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MACInfoService {
constructor() {}
}

View File

@ -0,0 +1,185 @@
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Router} from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class ApiService {
public static totalRequests = 0;
apiModuleBusy = document.getElementById('ApiModuleBusy');
constructor(private http: HttpClient,
private router: Router) {}
emptyResponse = {error: 'Request returned empty response'};
unauth(): void {
localStorage.removeItem('authToken');
if (this.router.url !== '/Login' && this.router.url !== '/Setup') {
this.router.navigateByUrl('/Login');
}
}
setBusy(): void {
this.apiModuleBusy.style.display = 'block';
}
setNotBusy(): void {
this.apiModuleBusy.style.display = 'none';
}
request(payload: any, callback: (any) => void) {
this.setBusy();
let resp;
this.http.post('/api/module/request', payload).subscribe((r: any) => {
if (r === undefined || r === null) {
resp = this.emptyResponse;
} else if (r.error) {
resp = r;
} else {
resp = r.payload;
}
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
this.setNotBusy();
callback(resp);
}, () => {
this.setNotBusy();
callback(resp);
});
ApiService.totalRequests++;
}
APIGet(path: string, callback: (any) => void): any {
ApiService.totalRequests++;
let resp;
this.http.get(path).subscribe((r) => {
if (r === undefined || r === null) {
r = this.emptyResponse;
}
resp = r;
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
callback(resp);
}, () => {
callback(resp);
});
}
async APIGetAsync(path: string): Promise<any> {
ApiService.totalRequests++;
return await this.http.get(path).toPromise();
}
APIPut(path: string, body: any, callback: (any) => void): any {
ApiService.totalRequests++;
let resp;
this.http.put(path, body).subscribe((r) => {
if (r === undefined || r === null) {
r = this.emptyResponse;
}
resp = r;
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
callback(resp);
}, () => {
callback(resp);
});
}
async APIPutAsync(path: string, body: any): Promise<any> {
return await this.http.put(path, body).toPromise();
}
APIPost(path: string, body: any, callback: (any) => void): any {
ApiService.totalRequests++;
let resp;
this.http.post(path, body).subscribe((r) => {
if (r === undefined || r === null) {
resp = this.emptyResponse;
}
resp = r;
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
callback(resp);
}, () => {
callback(resp);
});
}
async APIPostAsync(path: string, body: any): Promise<any> {
return await this.http.post(path, body).toPromise();
}
APIDelete(path: string, body: any, callback: (any) => void): any {
ApiService.totalRequests++;
const opts = {
headers: null,
body: body
};
let resp;
this.http.delete(path, opts).subscribe((r) => {
if (r === undefined || r === null) {
r = this.emptyResponse;
}
resp = r;
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
callback(resp);
}, () => {
callback(resp);
});
}
async APIDeleteAsync(path: string, body: any): Promise<any> {
return await this.http.delete(path, body).toPromise();
}
APIDownload(fullpath: string, filename: string): void {
ApiService.totalRequests++;
const body = {
filename: fullpath
};
this.http.post('/api/download', body, {responseType: 'blob'}).subscribe((r) => {
const url = window.URL.createObjectURL(r);
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
});
}
}

View File

@ -0,0 +1,9 @@
{
"name": "MACInfo",
"title": "MAC Info",
"description": "Lookup information on MAC Adresses",
"version": "1.1",
"author": "KoalaV2",
"firmware_required": "1.0.0"
}

View File

@ -0,0 +1,80 @@
#!/usr/bin/env python3
import logging
from pineapple.modules import Module, Request
import json
import os
import urllib.request
import re
module = Module('MACInfo', logging.DEBUG)
OUI_FILE = '/etc/pineapple/ouis'
ONLINE_URL = 'https://macvendors.co/api/'
@module.on_start()
def on_start():
with open(OUI_FILE) as f:
global OUIS
OUIS = json.load(f)
@module.handles_action('check_mac_online')
def check_mac_online(request: Request):
mac = request.user_input.upper()
strip_mac = mac.replace(' ','')
if '-' in strip_mac:
strip_mac = mac.replace('-',':')
module.logger.debug("Running regex check")
strip_mac = re.search("^[a-fA-F0-9]{2}([:\-]?[a-fA-F0-9]{2}){2,5}$",strip_mac)
if strip_mac:
strip_mac = strip_mac.group(0)
if strip_mac:
module.logger.debug("MATCH FOUND")
module.logger.debug(strip_mac)
response = urllib.request.urlopen(f'{ONLINE_URL}/{strip_mac}/JSON')
data = response.read()
output_json = json.loads(data)
jsonData = output_json["result"]
company = jsonData.get('company')
mac_prefix = jsonData.get('mac_prefix')
maccountry = jsonData.get('country')
if maccountry == None:
maccountry = "Country not found"
address = jsonData.get('address')
start_hex = jsonData.get('start_hex')
end_hex = jsonData.get('end_hex')
mactype = jsonData.get('type')
return{'company':company,'address':address,'maccountry':maccountry,'mac_prefix':mac_prefix,'start_hex':start_hex,'end_hex':end_hex,'mactype':mactype}
else:
module.logger.debug("Not a valid MAC address")
return{'nomac':'Not a valid MAC address'}
@module.handles_action('check_mac')
def check_mac(request: Request):
module.logger.debug("Opening file")
mac = request.user_input.upper()
nospace_mac = mac.replace(' ','')
if ':' in nospace_mac:
strip_mac = mac.replace(':','')
elif '-' in nospace_mac:
strip_mac = mac.replace('-','')
reg_mac = re.search("^[a-fA-F0-9]{2}([:\-]?[a-fA-F0-9]{2}){2,5}$",nospace_mac)
if reg_mac:
reg_mac = reg_mac.group(0)
module.logger.debug("User inputted: " + mac)
module.logger.debug(strip_mac[:6])
new_mac = strip_mac[:6]
company = OUIS.get(new_mac)
return{'company':company}
else:
module.logger.debug("Not a valid MAC address")
return{'nomac':'Not a valid MAC address'}
if __name__ == '__main__':
module.start()

View File

@ -0,0 +1 @@
<svg id="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><g id="_9" data-name="9"><path d="M4.7,18.52l-.23,0a1.25,1.25,0,0,1-1-1.45,20.88,20.88,0,0,1,41-.38,1.24,1.24,0,0,1-2.43.5,18.39,18.39,0,0,0-36.1.33A1.26,1.26,0,0,1,4.7,18.52Z"/><path d="M4.37,27.09a1.29,1.29,0,0,1-.79-.28,1.24,1.24,0,0,1-.17-1.75l1.88-2.31A6.92,6.92,0,0,0,6.8,19.28a17.35,17.35,0,0,1,34.37-.21,7.09,7.09,0,0,0,1.69,3.7l1.7,1.91a1.24,1.24,0,0,1-1.85,1.65L41,24.42a9.56,9.56,0,0,1-2.29-5,14.87,14.87,0,0,0-29.46.18,9.34,9.34,0,0,1-2,4.72L5.33,26.63A1.26,1.26,0,0,1,4.37,27.09Z"/><path d="M5.39,33.27a1.25,1.25,0,0,1-.92-2.08l2.88-3.12a11.1,11.1,0,0,0,2.39-4.14l.14-.47A10.1,10.1,0,0,0,10.36,21,13.35,13.35,0,0,1,23.72,8.56H24A13.68,13.68,0,0,1,37.56,20.5a11.31,11.31,0,0,0,.7,2.82,10.81,10.81,0,0,0,3,4.14L44,29.89a1.24,1.24,0,1,1-1.61,1.88L39.6,29.34A13.22,13.22,0,0,1,36,24.24a14.38,14.38,0,0,1-.87-3.43A11.19,11.19,0,0,0,24,11h-.28A10.92,10.92,0,0,0,12.84,21.18a13,13,0,0,1-.59,3l-.15.47a13.46,13.46,0,0,1-2.93,5.07L6.3,32.87A1.21,1.21,0,0,1,5.39,33.27Z"/><path d="M7,38.39a1.24,1.24,0,0,1-.69-2.28c8.27-5.45,7.85-13.12,7.84-13.2v-.08a9.83,9.83,0,0,1,19.66-.3c0,.25.62,8.66,8.53,11.64a1.24,1.24,0,0,1-.88,2.32c-9.57-3.61-10.13-13.78-10.13-13.88a7.35,7.35,0,0,0-14.7.19,15.32,15.32,0,0,1-.9,5.38,19.7,19.7,0,0,1-8,10A1.23,1.23,0,0,1,7,38.39Z"/><path d="M26.2,48a1.09,1.09,0,0,1-.43-.08A1.24,1.24,0,0,1,25,46.33c2.94-8,3.77-16.71,2.23-23.19a5,5,0,0,0-1-2.22,3.18,3.18,0,0,0-2.26-1h0a3.46,3.46,0,0,0-3.26,3.46,8.53,8.53,0,0,1-.09.95c-.4,3.09-2.2,13.54-8.6,18.3a1.24,1.24,0,1,1-1.48-2C16.32,36.35,17.92,26,18.18,24c0-.22.06-.48.07-.73A6,6,0,0,1,24,17.43h0a5.58,5.58,0,0,1,4,1.78,7.14,7.14,0,0,1,1.59,3.35A36.51,36.51,0,0,1,30.23,35a53.06,53.06,0,0,1-2.86,12.16A1.24,1.24,0,0,1,26.2,48Z"/><path d="M20.53,48a1.17,1.17,0,0,1-.57-.14,1.23,1.23,0,0,1-.54-1.66c4.4-8.64,4.9-15.47,4.85-18.53-.46,3.24-2,9.85-7.25,17.92a1.24,1.24,0,1,1-2.08-1.35,47.65,47.65,0,0,0,6-13,25.37,25.37,0,0,0,1-5.57v-.05c0-.12,0-.24,0-.36a6.78,6.78,0,0,1,.18-1.51A1.83,1.83,0,0,1,24,22.3a2.44,2.44,0,0,1,2,1A3.27,3.27,0,0,1,26.55,25c0,.19,0,.38.07.59v.14a28.12,28.12,0,0,1-.33,7.73,47.12,47.12,0,0,1-4.67,13.9A1.24,1.24,0,0,1,20.53,48Z"/><path d="M31.48,46.35a1.27,1.27,0,0,1-.34,0,1.24,1.24,0,0,1-.86-1.53A46.12,46.12,0,0,0,31.56,33,1.24,1.24,0,0,1,34,32.52a10.2,10.2,0,0,0,5.76,5.77,1.43,1.43,0,0,1,.64.47,1.24,1.24,0,0,1-1.61,1.82l-.06,0A15,15,0,0,1,34,37.19a40.11,40.11,0,0,1-1.28,8.26A1.23,1.23,0,0,1,31.48,46.35Z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,7 @@
/*
* Public API Surface of MACInfo
*/
export * from './lib/services/MACInfo.service';
export * from './lib/components/MACInfo.component';
export * from './lib/MACInfo.module';

View File

@ -0,0 +1,25 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"inlineSources": true,
"types": [],
"lib": [
"dom",
"es2018"
]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
"enableResourceInlining": true
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}

View File

@ -0,0 +1,6 @@
{
"extends": "./tsconfig.lib.json",
"angularCompilerOptions": {
"enableIvy": false
}
}

View File

@ -0,0 +1,17 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"src/test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View File

@ -0,0 +1,17 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"lib",
"camelCase"
],
"component-selector": [
true,
"element",
"lib",
"kebab-case"
]
}
}

34
MACInfo/tsconfig.json Normal file
View File

@ -0,0 +1,34 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
],
"paths": {
"MACInfo": [
"dist/MACInfo"
],
"MACInfo/*": [
"dist/MACInfo/*"
]
}
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}

79
MACInfo/tslint.json Normal file
View File

@ -0,0 +1,79 @@
{
"extends": "tslint:recommended",
"rulesDirectory": [
"codelyzer"
],
"rules": {
"array-type": false,
"arrow-parens": false,
"deprecation": {
"severity": "warning"
},
"import-blacklist": [
true,
"rxjs/Rx"
],
"interface-name": false,
"max-classes-per-file": false,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-consecutive-blank-lines": false,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-empty": false,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-var-requires": false,
"object-literal-key-quotes": [
true,
"as-needed"
],
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [
true,
"single"
],
"trailing-comma": false,
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"no-conflicting-lifecycle": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-inputs-metadata-property": true,
"no-output-native": true,
"no-output-on-prefix": true,
"no-output-rename": true,
"no-outputs-metadata-property": true,
"template-banana-in-box": true,
"template-no-negated-async": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true
}
}