Add MTR module. (#50)
* Semi working * Semi working * Working jobs * Working output in html * Working table * Add data to table * Add packet loss * Small fixes to CSS and renames * Working ( but ugly ) dependency installer. * Update CSS * Dependency dialouge license fix * Update title * Fix quotation * Fix quotation again * Disable button on load * Change module iconpull/51/head 1.1.0
parent
d35f8c983c
commit
04e4126c3b
|
@ -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
|
|
@ -0,0 +1,47 @@
|
|||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
build2.sh
|
||||
# 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
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"mtr": {
|
||||
"projectType": "library",
|
||||
"root": "projects/mtr",
|
||||
"sourceRoot": "projects/mtr/src",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "projects/mtr/tsconfig.lib.json",
|
||||
"project": "projects/mtr/ng-package.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"tsConfig": "projects/mtr/tsconfig.lib.prod.json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "projects/mtr/src/test.ts",
|
||||
"tsConfig": "projects/mtr/tsconfig.spec.json",
|
||||
"karmaConfig": "projects/mtr/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"projects/mtr/tsconfig.lib.json",
|
||||
"projects/mtr/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
"defaultProject": "mtr"
|
||||
}
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"name": "mtr",
|
||||
"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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../dist/mtr",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "mtr",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^8.2.14",
|
||||
"@angular/core": "^8.2.14"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "ng build --prod"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
This file is a placeholder for module assets that you may like to add.
|
|
@ -0,0 +1,11 @@
|
|||
.legal-textarea {
|
||||
width: 100%;
|
||||
min-height: 480px;
|
||||
resize: none;
|
||||
margin: 0 0 5px;
|
||||
padding: 0;
|
||||
background-color: #efefef;
|
||||
border-radius: 2px;
|
||||
border-color: #cecece;
|
||||
max-lines: 50;
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
<div class="right-left-split-container">
|
||||
<h1 mat-dialog-title>MTR License</h1>
|
||||
<span fxFlex></span>
|
||||
<button mat-icon-button (click)="closeDialog()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<textarea class="legal-textarea" readonly>
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
||||
</textarea>
|
||||
</div>
|
|
@ -0,0 +1,21 @@
|
|||
import {Component, OnInit} from '@angular/core';
|
||||
import {MatDialogRef} from "@angular/material/dialog";
|
||||
|
||||
@Component({
|
||||
selector: 'lib-license-dialog',
|
||||
templateUrl: './license-dialog.component.html',
|
||||
styleUrls: ['./license-dialog.component.css']
|
||||
})
|
||||
export class LicenseDialogComponent implements OnInit {
|
||||
|
||||
constructor(public dialogRef: MatDialogRef<LicenseDialogComponent>) {
|
||||
}
|
||||
|
||||
closeDialog(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
.spinner {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 4vh;
|
||||
}
|
||||
.mtr-button {
|
||||
/* display: flex; */
|
||||
/* justify-content: center; */
|
||||
/* align-items: center; */
|
||||
height: 4vh;
|
||||
}
|
||||
.mtr-lookup-field {
|
||||
padding-right: 2vh;
|
||||
}
|
||||
.dependency-card {
|
||||
max-width: 600px;
|
||||
min-height: 246px;
|
||||
}
|
||||
|
||||
.dependency-card-centered {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.dependency-card-button {
|
||||
width: 75%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.spinner-padding {
|
||||
margin-top: 6px;
|
||||
margin-bottom: 7px;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<div class="dependency-card-centered" *ngIf="!hasDependencies">
|
||||
<mat-card class="dependency-card">
|
||||
<mat-card-content>
|
||||
<mat-card-title>Welcome To MTR</mat-card-title>
|
||||
<mat-card-subtitle>Lets get started.</mat-card-subtitle>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
<br />
|
||||
|
||||
<p>
|
||||
You need to install some dependencies before you can use this
|
||||
module.
|
||||
</p>
|
||||
<p>This will make a request to the internet.</p>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="dependency-card-centered">
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
class="dependency-card-button"
|
||||
(click)="installDependencies()"
|
||||
[disabled]="isInstalling"
|
||||
>
|
||||
<span *ngIf="isInstalling">
|
||||
<mat-spinner
|
||||
[diameter]="20"
|
||||
class="spinner-padding"
|
||||
color="accent"
|
||||
></mat-spinner>
|
||||
</span>
|
||||
<span *ngIf="!isInstalling"> Install Dependencies </span>
|
||||
</button>
|
||||
</div>
|
||||
<br />
|
||||
<div class="dependency-card-centered">
|
||||
<button mat-button color="accent" (click)="showLicenseDialog()">
|
||||
View MTR License
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
<div *ngIf="hasDependencies">
|
||||
<mat-card>
|
||||
<mat-card-title>MTR: Traceroute and Ping</mat-card-title>
|
||||
<mat-card-content>
|
||||
<mat-form-field class="mtr-lookup-field">
|
||||
<mat-label> IP Address or Domain </mat-label>
|
||||
<input matInput [(ngModel)]="userInput" />
|
||||
</mat-form-field>
|
||||
|
||||
<button
|
||||
mat-flat-button
|
||||
class="mtr-button"
|
||||
color="accent"
|
||||
(click)="startmtr()"
|
||||
[disabled]="isLoading"
|
||||
>
|
||||
<span *ngIf="!isLoading">Start Traceroute</span>
|
||||
<span class="spinner" *ngIf="isLoading">
|
||||
<mat-spinner diameter="20"></mat-spinner>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<table
|
||||
class="mat-table"
|
||||
style="min-width: 100%; overflow-x: auto; justify-content: left"
|
||||
>
|
||||
<thead>
|
||||
<tr class="mat-header-row">
|
||||
<th class="mat-header-cell">Hops</th>
|
||||
<th class="mat-header-cell">Host</th>
|
||||
<th class="mat-header-cell">Packet loss %</th>
|
||||
<th class="mat-header-cell">Average ping m/s</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<ng-container *ngFor="let hub of hubs">
|
||||
<tr class="mat-row">
|
||||
<td class="mat-cell">
|
||||
{{ hub.count }}
|
||||
</td>
|
||||
<td class="mat-cell">
|
||||
{{ hub.host }}
|
||||
</td>
|
||||
<td class="mat-cell">
|
||||
{{ hub.LossPerc }}
|
||||
</td>
|
||||
<td class="mat-cell">
|
||||
{{ hub.Avg }}
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
</tbody>
|
||||
</table>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
|
@ -0,0 +1,151 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { JobResultDTO } from '../interfaces/jobresult.interface';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {LicenseDialogComponent} from './helpers/license-dialog/license-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'lib-mtr',
|
||||
templateUrl: './mtr.component.html',
|
||||
styleUrls: ['./mtr.component.css'],
|
||||
})
|
||||
export class mtrComponent implements OnInit {
|
||||
constructor(private API: ApiService, private dialog: MatDialog) {}
|
||||
|
||||
userInput = '';
|
||||
isLoading: boolean = false;
|
||||
commandfinished: boolean = false;
|
||||
hubs = '';
|
||||
backgroundJobInterval = null;
|
||||
hasDependencies: boolean = true;
|
||||
isInstalling: boolean = false;
|
||||
fileoutput = '';
|
||||
src = '';
|
||||
dst = '';
|
||||
|
||||
pollBackgroundJob<T>(
|
||||
jobId: string,
|
||||
onComplete: (result: JobResultDTO<T>) => void,
|
||||
onInterval?: Function
|
||||
): void {
|
||||
this.backgroundJobInterval = setInterval(() => {
|
||||
this.API.request(
|
||||
{
|
||||
module: 'mtr',
|
||||
action: 'poll_job',
|
||||
job_id: jobId,
|
||||
},
|
||||
(response: JobResultDTO<T>) => {
|
||||
if (response.is_complete) {
|
||||
onComplete(response);
|
||||
clearInterval(this.backgroundJobInterval);
|
||||
} else if (onInterval) {
|
||||
onInterval();
|
||||
}
|
||||
}
|
||||
);
|
||||
}, 2000);
|
||||
}
|
||||
checkForDependencies(): void {
|
||||
this.API.request(
|
||||
{
|
||||
module: 'mtr',
|
||||
action: 'check_dependencies',
|
||||
},
|
||||
(response) => {
|
||||
this.hasDependencies = response;
|
||||
}
|
||||
);
|
||||
}
|
||||
private monitorInstall(jobId: string): void {
|
||||
this.isInstalling = true;
|
||||
this.pollBackgroundJob(jobId, (result: JobResultDTO<boolean>) => {
|
||||
this.isInstalling = false;
|
||||
this.checkForDependencies();
|
||||
});
|
||||
}
|
||||
|
||||
rebindLastJob(): void {
|
||||
this.API.request(
|
||||
{
|
||||
module: 'mtr',
|
||||
action: 'rebind_last_job',
|
||||
},
|
||||
(response) => {
|
||||
if (response.job_id && response.job_type) {
|
||||
switch (response.job_type) {
|
||||
case 'opkg':
|
||||
this.monitorInstall(response.job_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
installDependencies(): void {
|
||||
this.API.request(
|
||||
{
|
||||
module: 'mtr',
|
||||
action: 'manage_dependencies',
|
||||
install: true,
|
||||
},
|
||||
(response) => {
|
||||
this.monitorInstall(response.job_id);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private monitormtr(jobId: string): void {
|
||||
this.isLoading = true;
|
||||
this.pollBackgroundJob(
|
||||
jobId,
|
||||
(result: JobResultDTO<boolean>) => {
|
||||
this.isLoading = false;
|
||||
this.getoutput();
|
||||
console.log('MTR has finished.');
|
||||
},
|
||||
() => {
|
||||
console.log('MTR still running..');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getoutput(): void {
|
||||
this.API.request(
|
||||
{
|
||||
module: 'mtr',
|
||||
action: 'load_output',
|
||||
},
|
||||
(response) => {
|
||||
console.log(response.report);
|
||||
this.hubs = response.report.hubs;
|
||||
console.log(this.hubs);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
startmtr(): void {
|
||||
this.isLoading = true;
|
||||
this.API.request(
|
||||
{
|
||||
module: 'mtr',
|
||||
action: 'startmtr',
|
||||
user_input: this.userInput,
|
||||
},
|
||||
(response) => {
|
||||
this.monitormtr(response.job_id);
|
||||
}
|
||||
);
|
||||
}
|
||||
showLicenseDialog(): void {
|
||||
this.dialog.open(LicenseDialogComponent, {
|
||||
hasBackdrop: true,
|
||||
width: '900px',
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.checkForDependencies();
|
||||
this.rebindLastJob();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export interface JobResultDTO<T> {
|
||||
is_complete: boolean;
|
||||
job_error: string,
|
||||
result: T
|
||||
}
|
|
@ -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 {
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { mtrComponent } from './components/mtr.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';
|
||||
|
||||
import { LicenseDialogComponent } from './components/helpers/license-dialog/license-dialog.component';
|
||||
|
||||
const routes: Routes = [{ path: '', component: mtrComponent }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [mtrComponent, LicenseDialogComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(routes),
|
||||
MaterialModule,
|
||||
FlexLayoutModule,
|
||||
FormsModule,
|
||||
],
|
||||
exports: [mtrComponent],
|
||||
entryComponents: [LicenseDialogComponent],
|
||||
})
|
||||
export class mtrModule {}
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class mtrService {
|
||||
constructor() {}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "mtr",
|
||||
"title": "MTR",
|
||||
"description": "Traceroute and ping a host.",
|
||||
"version": "1.0",
|
||||
"author": "KoalaV2",
|
||||
"firmware_required": "1.0.0"
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from typing import Optional
|
||||
from pineapple.modules import Module, Request
|
||||
import json
|
||||
import subprocess
|
||||
import logging
|
||||
from pineapple.jobs import Job,JobManager
|
||||
import pathlib
|
||||
from pineapple.helpers.opkg_helpers import OpkgJob
|
||||
import pineapple.helpers.notification_helpers as notifier
|
||||
import pineapple.helpers.opkg_helpers as opkg
|
||||
|
||||
module = Module('mtr', logging.DEBUG)
|
||||
job_manager = JobManager(name="mtr",module=module,log_level=logging.DEBUG)
|
||||
|
||||
root_folder = "/root/.mtr"
|
||||
json_file = f"{root_folder}/report.json"
|
||||
|
||||
class MTRJob(Job[bool]):
|
||||
def __init__(self,user_input: str):
|
||||
super().__init__()
|
||||
self.user_input = user_input
|
||||
def do_work(self,logger: logging.Logger) -> bool:
|
||||
logger.debug("MTR job started.")
|
||||
module.logger.debug(self.user_input)
|
||||
result = subprocess.check_output(["mtr", "-j", self.user_input], encoding='UTF-8')
|
||||
json_data = json.loads(result)
|
||||
with open(json_file,"w") as f:
|
||||
json.dump(json_data,f)
|
||||
module.logger.debug("Data written to file.")
|
||||
module.logger.debug("MTR has finished.")
|
||||
return True
|
||||
|
||||
def stop(self):
|
||||
subprocess.call(["killall","-9","mtr"])
|
||||
|
||||
@module.on_start()
|
||||
def make_root_directory():
|
||||
path = pathlib.Path(root_folder)
|
||||
|
||||
if not path.exists():
|
||||
module.logger.debug('Creating mtr directory.')
|
||||
path.mkdir(parents=True)
|
||||
|
||||
@module.handles_action("startmtr")
|
||||
def startmtr(request: Request):
|
||||
user_input = request.user_input
|
||||
job_id = job_manager.execute_job(MTRJob(user_input))
|
||||
return {'job_id':job_id}
|
||||
@module.handles_action("load_output")
|
||||
def load_output(request: Request):
|
||||
with open(json_file,"r") as f:
|
||||
file = json.load(f)
|
||||
file2 = file["report"]["hubs"]
|
||||
for k in file2:
|
||||
k['LossPerc'] = k.pop('Loss%')
|
||||
return file
|
||||
|
||||
def _notify_dependencies_finished(job: OpkgJob):
|
||||
if not job.was_successful:
|
||||
module.send_notification(job.error, notifier.ERROR)
|
||||
elif job.install:
|
||||
module.send_notification('MTR finished installing.', notifier.INFO)
|
||||
|
||||
@module.handles_action('rebind_last_job')
|
||||
def rebind_last_job(request: Request):
|
||||
module.logger.debug('GETTING LAST BACKGROUND JOB')
|
||||
last_job_id: Optional[str] = None
|
||||
last_job_type: Optional[str] = None
|
||||
job_info: Optional[str] = None
|
||||
|
||||
if len(job_manager.jobs) >= 1:
|
||||
last_job_id = list(job_manager.jobs.keys())[-1]
|
||||
if type(job_manager.jobs[last_job_id].job) is OpkgJob:
|
||||
last_job_type = 'opkg'
|
||||
else:
|
||||
last_job_type = 'unknown'
|
||||
|
||||
module.logger.debug(
|
||||
'BACKGROUND: ' + json.dumps(({'job_id': last_job_id, 'job_type': last_job_type, 'job_info': job_info})))
|
||||
return {'job_id': last_job_id, 'job_type': last_job_type, 'job_info': job_info}
|
||||
@module.handles_action('check_dependencies')
|
||||
def check_dependencies(request: Request):
|
||||
return opkg.check_if_installed('mtr', module.logger)
|
||||
@module.handles_action('manage_dependencies')
|
||||
def manage_dependencies(request: Request):
|
||||
return {
|
||||
'job_id': job_manager.execute_job(OpkgJob('mtr', request.install), callbacks=[_notify_dependencies_finished])
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
module.start()
|
|
@ -0,0 +1 @@
|
|||
<svg id="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path d="M47.85,35.91a4.52,4.52,0,0,0-2-2.94,4.43,4.43,0,0,0-.83-.39A6.56,6.56,0,0,0,43.89,25c-1.84-2-4.48-2.12-6.42-1.81a15.2,15.2,0,0,0-1.64-10.87C34.05,9.41,30.35,6,22.75,6.64,18.8,7,15.8,8.47,13.84,11.15,11,15,11.15,20.22,11.49,23,8,22.4,3.1,23,.89,28.62c-1.4,3.53-1.13,7.52.67,10.18a5.58,5.58,0,0,0,4.65,2.63H43.9A4,4,0,0,0,47.09,40,4.71,4.71,0,0,0,47.85,35.91ZM22.27,25.28l-1.56-1.56V34.48a1.24,1.24,0,0,1-2.48,0V23.72l-1.57,1.56a1.24,1.24,0,0,1-1.75-1.75l3.68-3.68a1.22,1.22,0,0,1,.88-.37,1.19,1.19,0,0,1,.87.37L24,23.53a1.25,1.25,0,0,1-.87,2.12A1.25,1.25,0,0,1,22.27,25.28Zm10.82,6.4-3.68,3.68a1.25,1.25,0,0,1-.88.36,1.27,1.27,0,0,1-.88-.36L24,31.68a1.24,1.24,0,0,1,1.76-1.75l1.56,1.56V20.72a1.24,1.24,0,1,1,2.48,0V31.49l1.57-1.56a1.23,1.23,0,0,1,1.75,0A1.24,1.24,0,0,1,33.09,31.68Z"/></svg>
|
After Width: | Height: | Size: 870 B |
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Public API Surface of mtr
|
||||
*/
|
||||
|
||||
export * from './lib/services/mtr.service';
|
||||
export * from './lib/components/mtr.component';
|
||||
export * from './lib/mtr.module';
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "./tsconfig.lib.json",
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts"
|
||||
],
|
||||
"include": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../tslint.json",
|
||||
"rules": {
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"lib",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"lib",
|
||||
"kebab-case"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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": {
|
||||
"mtr": [
|
||||
"dist/mtr"
|
||||
],
|
||||
"mtr/*": [
|
||||
"dist/mtr/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"fullTemplateTypeCheck": true,
|
||||
"strictInjectionParameters": true
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue