diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3230451
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# ARGUS: GitHub Workflows Static Taint Tracker
+
+## Description
+
+ARGUS is ....
+
+
diff --git a/css/controls.css b/css/controls.css
new file mode 100644
index 0000000..0c355d6
--- /dev/null
+++ b/css/controls.css
@@ -0,0 +1,443 @@
+/*************************************************************************
+ * GitHub: https://github.com/yenchiah/project-website-template
+ * Version: v3.29
+ * This CSS file has control elements that do not require JavaScript
+ * If you want to keep this template updated, avoid modifying this file
+ * Instead, add your own CSS in the index.css
+ *************************************************************************/
+
+.custom-image-button {
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: stretch;
+ box-sizing: border-box;
+ text-decoration: none;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.custom-button {
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+ padding: 10px 20px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 15px;
+ outline: none;
+ border-radius: 2px;
+ cursor: pointer;
+ box-shadow: none;
+ transition: background-color 0.1s, box-shadow 0.1s, border 0.1s;
+ text-decoration: none;
+ display: block;
+ box-sizing: border-box;
+ color: white;
+ border: 1px solid #7d7d7d;
+ background-color: #7d7d7d;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.custom-button:not(:disabled):hover {
+ background-color: #4d4d4d;
+ border-color: #4d4d4d;
+}
+
+.custom-button:not(:disabled):active {
+ background-color: #4d4d4d;
+ border-color: #4d4d4d;
+}
+
+.custom-button:disabled {
+ opacity: 0.4;
+ cursor: default;
+}
+
+.custom-button-primary {
+ background-color: #007bff;
+ border-color: #007bff;
+}
+
+.custom-button-primary:not(:disabled):hover {
+ background-color: #005cbf;
+ border-color: #005cbf;
+}
+
+.custom-button-primary:not(:disabled):active {
+ background-color: #005cbf;
+ border-color: #005cbf;
+}
+
+.custom-button-danger {
+ background-color: #dc3545;
+ border-color: #dc3545;
+}
+
+.custom-button-danger:not(:disabled):hover {
+ background-color: #a71120;
+ border-color: #a71120;
+}
+
+.custom-button-danger:not(:disabled):active {
+ background-color: #a71120;
+ border-color: #a71120;
+}
+
+.custom-button-info {
+ background-color: #17a2b8;
+ border-color: #17a2b8;
+}
+
+.custom-button-info:not(:disabled):hover {
+ background-color: #007082;
+ border-color: #007082;
+}
+
+.custom-button-info:not(:disabled):active {
+ background-color: #007082;
+ border-color: #007082;
+}
+
+.custom-button-flat {
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+ text-align: center;
+ font-size: 16px;
+ line-height: 16px;
+ outline: none;
+ border-radius: 48px;
+ cursor: pointer;
+ box-shadow: none;
+ transition: background-color 0.1s, box-shadow 0.1s, border 0.1s;
+ text-decoration: none;
+ color: black;
+ border: 1px solid #777777;
+ background-color: white;
+ padding: 13px;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: center;
+ align-content: center;
+ box-sizing: border-box;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.custom-button-flat.large {
+ font-size: 18px;
+ line-height: 18px;
+ padding: 17px;
+ border-radius: 56px;
+}
+
+.custom-button-flat.small {
+ font-size: 14px;
+ line-height: 14px;
+ padding: 12px;
+ border-radius: 42px;
+}
+
+.custom-button-flat:disabled {
+ opacity: 0.4;
+ cursor: default;
+}
+
+.custom-button-flat img {
+ width: 20px;
+ height: 20px;
+}
+
+.custom-button-flat.small img {
+ width: 16px;
+ height: 16px;
+}
+
+.custom-button-flat.large img {
+ width: 24px;
+ height: 24px;
+}
+
+.custom-button-flat span {
+ margin-left: 6px;
+}
+
+input.custom-textbox,
+textarea.custom-textbox {
+ font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif;
+ box-sizing: border-box;
+ padding: 5px 10px;
+ background: rgb(255, 255, 255);
+ border: 1px solid #7d7d7d;
+ font-size: 16px;
+ outline: none;
+ border-radius: 2px;
+ resize: vertical;
+}
+
+input.custom-textbox {
+ min-height: 37px;
+ max-height: 37px;
+}
+
+textarea.custom-textbox {
+ min-height: 60px;
+ max-height: 200px;
+}
+
+input[readonly].custom-textbox,
+textarea[readonly].custom-textbox {
+ cursor: default;
+ background: rgb(230, 230, 230);
+}
+
+.control-group {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: center;
+ align-content: stretch;
+ box-sizing: border-box;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.control-group .custom-image-button {
+ margin: 10px 0 10px 0;
+}
+
+.control-group .custom-image-button:not(:last-child) {
+ margin-right: 15px;
+}
+
+.control-group .custom-button {
+ margin: 10px 0 10px 0;
+}
+
+.control-group .custom-button:not(:last-child) {
+ margin-right: 15px;
+}
+
+.control-group .custom-button-flat {
+ margin: 10px 0 10px 0;
+}
+
+.control-group .custom-button-flat:not(:last-child) {
+ margin-right: 15px;
+}
+
+.control-group .custom-textbox {
+ margin: 10px 0 10px 0;
+}
+
+.control-group .custom-textbox:not(:last-child) {
+ margin-right: 15px;
+}
+
+@media screen and (max-width: 500px) {
+ .stretch-on-mobile {
+ margin-left: 0 !important;
+ margin-right: 0 !important;
+ flex: 1 0 100%;
+ max-width: 100%;
+ }
+}
+
+.pulse-white {
+ box-shadow: 0 0 0 rgba(255, 255, 255, 0.5);
+ animation: pulse-white 2s infinite;
+}
+
+@-webkit-keyframes pulse-white {
+ 0% {
+ -webkit-box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.5);
+ }
+
+ 70% {
+ -webkit-box-shadow: 0 0 0 15px rgba(255, 255, 255, 0);
+ }
+
+ 100% {
+ -webkit-box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
+ }
+}
+
+@keyframes pulse-white {
+ 0% {
+ -moz-box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.5);
+ box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.5);
+ }
+
+ 70% {
+ -moz-box-shadow: 0 0 0 15px rgba(255, 255, 255, 0);
+ box-shadow: 0 0 0 15px rgba(255, 255, 255, 0);
+ }
+
+ 100% {
+ -moz-box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
+ box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
+ }
+}
+
+.pulse-black {
+ box-shadow: 0 0 0 rgba(0, 0, 0, 0.5);
+ animation: pulse-black 2s infinite;
+}
+
+@-webkit-keyframes pulse-black {
+ 0% {
+ -webkit-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.5);
+ }
+
+ 70% {
+ -webkit-box-shadow: 0 0 0 15px rgba(0, 0, 0, 0);
+ }
+
+ 100% {
+ -webkit-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
+ }
+}
+
+@keyframes pulse-black {
+ 0% {
+ -moz-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.5);
+ box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.5);
+ }
+
+ 70% {
+ -moz-box-shadow: 0 0 0 15px rgba(0, 0, 0, 0);
+ box-shadow: 0 0 0 15px rgba(0, 0, 0, 0);
+ }
+
+ 100% {
+ -moz-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
+ box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
+ }
+}
+
+.pulse-primary {
+ box-shadow: 0 0 0 rgba(0, 123, 255, 0.5);
+ animation: pulse-primary 2s infinite;
+}
+
+@-webkit-keyframes pulse-primary {
+ 0% {
+ -webkit-box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5);
+ }
+
+ 70% {
+ -webkit-box-shadow: 0 0 0 15px rgba(0, 123, 255, 0);
+ }
+
+ 100% {
+ -webkit-box-shadow: 0 0 0 0 rgba(0, 123, 255, 0);
+ }
+}
+
+@keyframes pulse-primary {
+ 0% {
+ -moz-box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5);
+ box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5);
+ }
+
+ 70% {
+ -moz-box-shadow: 0 0 0 15px rgba(0, 123, 255, 0);
+ box-shadow: 0 0 0 15px rgba(0, 123, 255, 0);
+ }
+
+ 100% {
+ -moz-box-shadow: 0 0 0 0 rgba(0, 123, 255, 0);
+ box-shadow: 0 0 0 0 rgba(0, 123, 255, 0);
+ }
+}
+
+.pulse-danger {
+ box-shadow: 0 0 0 rgba(220, 53, 69, 0.5);
+ animation: pulse-danger 2s infinite;
+}
+
+@-webkit-keyframes pulse-danger {
+ 0% {
+ -webkit-box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5);
+ }
+
+ 70% {
+ -webkit-box-shadow: 0 0 0 15px rgba(220, 53, 69, 0);
+ }
+
+ 100% {
+ -webkit-box-shadow: 0 0 0 0 rgba(220, 53, 69, 0);
+ }
+}
+
+@keyframes pulse-danger {
+ 0% {
+ -moz-box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5);
+ box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5);
+ }
+
+ 70% {
+ -moz-box-shadow: 0 0 0 15px rgba(220, 53, 69, 0);
+ box-shadow: 0 0 0 15px rgba(220, 53, 69, 0);
+ }
+
+ 100% {
+ -moz-box-shadow: 0 0 0 0 rgba(220, 53, 69, 0);
+ box-shadow: 0 0 0 0 rgba(220, 53, 69, 0);
+ }
+}
+
+.pulse-info {
+ box-shadow: 0 0 0 rgba(23, 162, 184, 0.5);
+ animation: pulse-info 2s infinite;
+}
+
+@-webkit-keyframes pulse-info {
+ 0% {
+ -webkit-box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5);
+ }
+
+ 70% {
+ -webkit-box-shadow: 0 0 0 15px rgba(23, 162, 184, 0);
+ }
+
+ 100% {
+ -webkit-box-shadow: 0 0 0 0 rgba(23, 162, 184, 0);
+ }
+}
+
+@keyframes pulse-info {
+ 0% {
+ -moz-box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5);
+ box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5);
+ }
+
+ 70% {
+ -moz-box-shadow: 0 0 0 15px rgba(23, 162, 184, 0);
+ box-shadow: 0 0 0 15px rgba(23, 162, 184, 0);
+ }
+
+ 100% {
+ -moz-box-shadow: 0 0 0 0 rgba(23, 162, 184, 0);
+ box-shadow: 0 0 0 0 rgba(23, 162, 184, 0);
+ }
+}
\ No newline at end of file
diff --git a/css/custom.css b/css/custom.css
new file mode 100644
index 0000000..a353ef2
--- /dev/null
+++ b/css/custom.css
@@ -0,0 +1,34 @@
+/*************************************************************************
+ * Your custom CSS file
+ *************************************************************************/
+
+.custom-dropdown {
+ width: 240px;
+}
+
+.custom-textbox {
+ width: 240px;
+}
+
+#dialog-1,
+#dialog-2,
+#dialog-3,
+#dialog-4,
+#share-dialog {
+ display: none;
+}
+
+#share-url {
+ width: 100%;
+ -webkit-touch-callout: default !important;
+ -webkit-user-select: text !important;
+ -khtml-user-select: text !important;
+ -moz-user-select: text !important;
+ -ms-user-select: text !important;
+ user-select: text !important;
+}
+
+#share-url-copy-prompt {
+ display: none;
+ color: #007bff;
+}
\ No newline at end of file
diff --git a/css/frame.css b/css/frame.css
new file mode 100644
index 0000000..0b210dc
--- /dev/null
+++ b/css/frame.css
@@ -0,0 +1,838 @@
+/*************************************************************************
+ * GitHub: https://github.com/yenchiah/project-website-template
+ * Version: v3.29
+ * This CSS file is for the website frame
+ * If you want to keep this template updated, avoid modifying this file
+ * Instead, add your own CSS in the index.css
+ *************************************************************************/
+
+html,
+body {
+ margin: 0;
+ padding: 0;
+ background-color: white;
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+ left: 0;
+ right: 0;
+ width: auto;
+}
+
+a {
+ outline: none;
+ cursor: pointer;
+}
+
+img {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+video {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+h2 {
+ font-size: 24px;
+ margin: 10px 0 0 0;
+ padding: 0;
+ font-weight: bold;
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+}
+
+h3 {
+ font-size: 18px;
+ margin: 10px 0 0 0;
+ padding: 0;
+ font-weight: bold;
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+}
+
+ul,
+ol {
+ margin: 10px 0 10px 0;
+}
+
+li ol,
+li ul {
+ margin: 0;
+}
+
+hr {
+ border: 0;
+ height: 1px;
+ background: #333;
+ margin: 0 0 10px 0;
+}
+
+.menu-container {
+ z-index: 2;
+ position: relative;
+ width: 100%;
+ background-color: #212121;
+ min-width: 300px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.menu {
+ position: relative;
+ margin: 0 auto;
+ max-width: 900px;
+}
+
+.menu-table {
+ padding: 10px 10px;
+ width: 100%;
+ margin: 0;
+}
+
+.menu-highlight {
+ color: rgb(255, 255, 255) !important;
+ opacity: 1 !important;
+ font-weight: 700 !important;
+}
+
+.logo {
+ margin-left: 20px;
+}
+
+.logo a {
+ color: rgba(255, 255, 255, 0.8);
+ font-family: 'Open Sans Condensed', Helvetica, Arial, sans-serif;
+ font-size: 30px;
+ text-decoration: none;
+ font-weight: 700;
+ flex: 1 auto;
+}
+
+.menu-button {
+ width: 40px;
+ height: 40px;
+ display: none;
+ cursor: pointer;
+ margin-right: 20px;
+}
+
+.menu-button img {
+ width: 30px;
+ height: 30px;
+}
+
+.menu-items a {
+ color: rgba(255, 255, 255, 0.8);
+ text-decoration: none;
+ font-weight: 400;
+ font-size: 18px;
+ flex: 1 auto;
+ transition: opacity 0.1s ease-in-out;
+ -moz-transition: opacity 0.1s ease-in-out;
+ -webkit-transition: opacity 0.1s ease-in-out;
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+ white-space: nowrap;
+}
+
+.menu-items a:not(:last-child) {
+ margin-right: 25px;
+}
+
+.menu-items a:hover {
+ color: rgb(255, 255, 255);
+ opacity: 1;
+}
+
+.content-container {
+ z-index: 1;
+ position: relative;
+ width: 100%;
+ min-width: 300px;
+}
+
+.content {
+ position: relative;
+ margin: 0 auto;
+ font-size: 16px;
+ font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif;
+ font-weight: 300;
+ line-height: 1.5;
+ max-width: 900px;
+ overflow-x: auto;
+}
+
+.content p a,
+.content ul a,
+.content ol a {
+ text-decoration: none;
+ color: #005cbf;
+}
+
+.content p a:hover,
+.content ul a:hover,
+.content ol a:hover {
+ text-decoration: underline;
+}
+
+.content-table {
+ padding: 20px 10px;
+ width: 100%;
+ margin: 0;
+}
+
+.flex-column {
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: stretch;
+ box-sizing: border-box;
+}
+
+.flex-row-space-between {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: center;
+ align-content: stretch;
+ box-sizing: border-box;
+}
+
+.flex-row {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: center;
+ align-content: stretch;
+ box-sizing: border-box;
+}
+
+.flex-row-center {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: center;
+ align-content: stretch;
+ box-sizing: border-box;
+}
+
+.flex-item-stretch {
+ flex: 1 auto;
+}
+
+.flex-item-stretch-2 {
+ flex: 1 auto;
+}
+
+.flex-item-stretch-3 {
+ flex: 1 auto;
+}
+
+.flex-item-stretch-4 {
+ flex: 1 auto;
+}
+
+.flex-item-stretch-5 {
+ flex: 1 auto;
+}
+
+.flex-item {
+ margin: 0 20px;
+}
+
+.left-align {
+ float: left;
+}
+
+.right-align {
+ float: right;
+}
+
+.full-width {
+ width: 100%;
+}
+
+.badge-text {
+ font-size: 30px;
+ font-weight: 700;
+}
+
+.text {
+ margin: 10px 0 10px 0;
+ padding: 0;
+}
+
+.text-large-margin {
+ margin: 15px 0 15px 0;
+ padding: 0;
+}
+
+.text-small-margin {
+ margin: 5px 0 5px 0;
+ padding: 0;
+}
+
+.text-no-margin {
+ margin: 0;
+ padding: 0;
+}
+
+.image {
+ border-radius: 2px;
+ width: 100%;
+ margin: 15px 0;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ display: flex;
+}
+
+.image.center {
+ align-self: center;
+}
+
+.image img,
+.image video {
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
+ display: table-cell;
+ overflow: hidden;
+ border-radius: 2px;
+}
+
+.adaptive-image {
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+}
+
+.image-wrap-text {
+ float: left;
+ margin: 5px 40px 25px 0;
+}
+
+.image-caption {
+ width: 100%;
+ text-align: center;
+ margin-top: -10px;
+ margin-bottom: 10px;
+}
+
+.max-width-400 {
+ max-width: 400px;
+}
+
+.max-width-140 {
+ max-width: 140px;
+}
+
+ol.publication {
+ display: flex;
+ flex-direction: column-reverse;
+ list-style: none;
+ margin: 7px 0 7px 0;
+ padding: 0;
+ flex-wrap: wrap;
+}
+
+ol.publication li {
+ display: flex;
+ align-items: baseline;
+ margin: 0;
+ padding: 0;
+}
+
+ol.publication li p:before {
+ line-height: 1;
+ margin-right: 5px;
+}
+
+ol.publication.C-list {
+ counter-reset: C-counter;
+}
+
+ol.publication.C-list li p {
+ counter-increment: C-counter;
+}
+
+ol.publication.C-list li p:before {
+ content: "[C"counter(C-counter)"]";
+}
+
+ol.publication.J-list {
+ counter-reset: J-counter;
+}
+
+ol.publication.J-list li p {
+ counter-increment: J-counter;
+}
+
+ol.publication.J-list li p:before {
+ content: "[J"counter(J-counter)"]";
+}
+
+ol.publication.T-list {
+ counter-reset: T-counter;
+}
+
+ol.publication.T-list li p {
+ counter-increment: T-counter;
+}
+
+ol.publication.T-list li p:before {
+ content: "[T"counter(T-counter)"]";
+}
+
+ol.publication.O-list {
+ counter-reset: O-counter;
+}
+
+ol.publication.O-list li p {
+ counter-increment: O-counter;
+}
+
+ol.publication.O-list li p:before {
+ content: "[O"counter(O-counter)"]";
+}
+
+ol.publication.P-list {
+ counter-reset: P-counter;
+}
+
+ol.publication.P-list li p {
+ counter-increment: P-counter;
+}
+
+ol.publication.P-list li p:before {
+ content: "[P"counter(P-counter)"]";
+}
+
+ol.publication.M-list {
+ counter-reset: M-counter;
+}
+
+ol.publication.M-list li p {
+ counter-increment: M-counter;
+}
+
+ol.publication.M-list li p:before {
+ content: "[M"counter(M-counter)"]";
+}
+
+ol.publication.F-list {
+ counter-reset: F-counter;
+}
+
+ol.publication.F-list li p {
+ counter-increment: F-counter;
+}
+
+ol.publication.F-list li p:before {
+ content: "[F"counter(F-counter)"]";
+}
+
+ol.publication.A-list {
+ counter-reset: A-counter;
+}
+
+ol.publication.A-list li p {
+ counter-increment: A-counter;
+}
+
+ol.publication.A-list li p:before {
+ content: "[A"counter(A-counter)"]";
+}
+
+ol.nested {
+ list-style: none;
+ counter-reset: item;
+}
+
+ol.nested>li:before {
+ counter-increment: item;
+ content: counters(item, ".") ". ";
+ padding-right: 0.6em;
+}
+
+.noselect {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.center-align-content {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.left-align-content {
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+}
+
+.text-large {
+ font-size: 20px;
+}
+
+.text-small {
+ font-size: 12px;
+}
+
+.text-italic {
+ font-style: italic;
+}
+
+.text-justify {
+ text-align: justify;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.iframe-container {
+ position: absolute;
+ top: 61px;
+ bottom: 0;
+ left: 0;
+ height: auto;
+ width: 100%;
+ min-width: 300px;
+}
+
+.iframe {
+ border: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.iframe-in-body {
+ width: 100%;
+ height: 400px;
+ border: 1px solid #666666;
+ margin: 15px 0;
+}
+
+.iframe-in-tab {
+ width: 100%;
+ height: 400px;
+ border: 0;
+ margin: 0;
+ padding: 0;
+}
+
+.force-no-scroll {
+ overflow-y: hidden;
+}
+
+.force-scroll {
+ overflow-y: scroll;
+}
+
+.highlight-text {
+ font-weight: bold;
+}
+
+.custom-text-info,
+.custom-text-info p,
+.custom-text-info a {
+ color: #17a2b8;
+}
+
+.custom-text-info a:hover {
+ color: #007082;
+}
+
+.custom-text-primary,
+.custom-text-primary p,
+.custom-text-primary a {
+ color: #007bff;
+}
+
+.custom-text-primary a:hover {
+ color: #005cbf;
+}
+
+.custom-text-danger,
+.custom-text-danger p,
+.custom-text-danger a {
+ color: #dc3545;
+}
+
+.custom-text-danger a:hover {
+ color: #a71120;
+}
+
+.gallery {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: center;
+ align-content: stretch;
+ box-sizing: border-box;
+ width: 100%;
+ padding: 0 10px;
+}
+
+.gallery a {
+ border: 1px solid rgba(0, 0, 0, 0);
+ color: black;
+ text-decoration: none;
+ padding: 10px;
+ cursor: default;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.gallery a>img,
+.gallery a>video {
+ border-radius: 2px;
+ width: 100%;
+ background-image: url(../img/loading.gif);
+ background-repeat: no-repeat;
+ background-size: 30px 30px;
+ background-position: center;
+ min-height: 50px;
+}
+
+.gallery a>div {
+ width: 100%;
+ text-align: center;
+}
+
+.custom-table-container {
+ display: grid;
+ width: fit-content;
+ width: -moz-fit-content;
+ margin: 15px 0;
+}
+
+.custom-table-container.center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.custom-table {
+ display: block;
+ overflow-x: auto;
+ border: 1px solid #666666;
+ border-collapse: collapse;
+ border-spacing: 0;
+ empty-cells: show;
+ margin: 0;
+ padding: 0;
+}
+
+.custom-table thead {
+ text-align: left;
+ border-bottom: 1px solid #666666;
+}
+
+.custom-table tfoot {
+ border-top: 1px solid #666666;
+}
+
+.custom-table tr.bg-color-gray {
+ background-color: #dadada;
+}
+
+.custom-table tr.bg-color-light-gray {
+ background-color: #efefef;
+}
+
+.custom-table td,
+.custom-table th {
+ padding: 5px 10px;
+}
+
+.no-top-margin {
+ margin-top: 0;
+}
+
+.no-bottom-margin {
+ margin-bottom: 0;
+}
+
+.break-long-url {
+ /* These are technically the same, but use both */
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+
+ -ms-word-break: break-all;
+ /* This is the dangerous one in WebKit, as it breaks things wherever */
+ word-break: break-all;
+ /* Instead use this non-standard one: */
+ word-break: break-word;
+
+ /* Adds a hyphen where the word breaks, if supported (No Blink) */
+ -ms-hyphens: auto;
+ -moz-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+
+.graph-title {
+ font-size: 20px;
+ margin-bottom: 0;
+ margin-top: 15px;
+}
+
+.add-top-margin {
+ margin-top: 15px;
+}
+
+.add-top-margin-small {
+ margin-top: 5px;
+}
+
+.add-top-margin-large {
+ margin-top: 20px;
+}
+
+.add-bottom-margin {
+ margin-bottom: 15px;
+}
+
+.add-bottom-margin-small {
+ margin-bottom: 5px;
+}
+
+.add-bottom-margin-large {
+ margin-bottom: 20px;
+}
+
+@media screen and (min-width: 900px) {
+ .flex-item-stretch {
+ flex: 1;
+ }
+
+ .flex-item-stretch-2 {
+ flex: 2;
+ }
+
+ .flex-item-stretch-3 {
+ flex: 3;
+ }
+
+ .flex-item-stretch-4 {
+ flex: 4;
+ }
+
+ .flex-item-stretch-5 {
+ flex: 5;
+ }
+}
+
+@media screen and (max-width: 750px) {
+ .logo {
+ -webkit-tap-highlight-color: transparent;
+ }
+
+ .menu-items {
+ display: none;
+ width: 100%;
+ }
+
+ .menu-items a:first-child {
+ margin-top: 10px;
+ }
+
+ .menu-items a {
+ width: 100%;
+ padding: 10px 0;
+ border-top: 1px solid rgba(255, 255, 255, 0.5);
+ }
+
+ .menu-button {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ align-items: center;
+ align-content: stretch;
+ box-sizing: border-box;
+ -webkit-tap-highlight-color: transparent;
+ }
+
+ .menu-button:focus {
+ pointer-events: none;
+ }
+
+ .menu-button:focus+.menu-items {
+ display: block;
+ }
+
+ .menu-button:focus+.menu-items a {
+ display: block;
+ }
+
+ .menu-items:hover {
+ display: block;
+ }
+
+ .menu-items>a {
+ display: block;
+ }
+
+ .image-wrap-text {
+ max-width: 100%;
+ margin-bottom: 20px;
+ margin-right: 0;
+ }
+}
+
+@media screen and (min-width: 900px) {
+ .gallery a {
+ flex: 1 0 25%;
+ max-width: 25%;
+ }
+}
+
+@media screen and (min-width: 700px) and (max-width: 900px) {
+ .gallery a {
+ flex: 1 0 33.3%;
+ max-width: 33.3%;
+ }
+}
+
+@media screen and (min-width: 500px) and (max-width: 700px) {
+ .gallery a {
+ flex: 1 0 50%;
+ max-width: 50%;
+ }
+}
+
+@media screen and (max-width: 500px) {
+ .gallery a {
+ flex: 1 0 100%;
+ max-width: 100%;
+ }
+}
\ No newline at end of file
diff --git a/css/widgets.css b/css/widgets.css
new file mode 100644
index 0000000..1bf76a2
--- /dev/null
+++ b/css/widgets.css
@@ -0,0 +1,619 @@
+/*************************************************************************
+ * GitHub: https://github.com/yenchiah/project-website-template
+ * Version: v3.29
+ * This CSS file has widgets for building interactive web applications
+ * Use this file with widgets.js
+ * If you want to keep this template updated, avoid modifying this file
+ * Instead, add your own CSS in the index.css
+ *************************************************************************/
+
+.custom-tab {
+ margin: 15px 0;
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: stretch;
+ box-sizing: border-box;
+}
+
+.custom-tab .custom-tab-menu {
+ overflow: hidden;
+ border: 1px solid #ccc;
+ background-color: #f1f1f1;
+ border-bottom: none;
+ width: fit-content;
+ width: -moz-fit-content;
+}
+
+.custom-tab .custom-tab-menu-item {
+ background-color: inherit;
+ float: left;
+ border: none;
+ outline: none;
+ cursor: pointer;
+ padding: 14px 16px;
+ transition: 0.3s;
+ font-size: 17px;
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+}
+
+.custom-tab .custom-tab-menu-item:hover {
+ background-color: #ddd;
+}
+
+.custom-tab .custom-tab-menu-item.active {
+ background-color: #ccc;
+}
+
+.custom-tab .custom-tab-content {
+ padding: 25px;
+ border: 1px solid #ccc;
+ display: none;
+ flex-direction: column;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: stretch;
+ box-sizing: border-box;
+}
+
+.custom-tab .custom-tab-menu.center,
+.custom-tab .custom-tab-content .image.center,
+.custom-tab .custom-tab-content p.center,
+.custom-tab .custom-tab-content table.center {
+ align-self: center;
+}
+
+.custom-tab .custom-tab-content.no-padding {
+ padding: 0;
+}
+
+.custom-tab .graph-title.add-top-right-left-padding {
+ padding-top: 25px;
+ padding-left: 25px;
+ padding-right: 25px;
+ padding-bottom: 5px;
+}
+
+.custom-tab .graph-title.add-bottom-border {
+ border-bottom: 1px solid #ccc;
+}
+
+.custom-tab .image:first-child,
+.custom-tab .custom-table-container:first-child,
+.custom-tab .text:first-child,
+.custom-tab .graph-title:first-child {
+ margin-top: 0;
+}
+
+.custom-tab .image:last-child,
+.custom-tab .custom-table-container:last-child,
+.custom-tab .text:last-child,
+.custom-tab .graph-title:last-child {
+ margin-bottom: 0;
+}
+
+.custom-radio {
+ padding: 0;
+ text-align: center;
+ outline: none;
+ cursor: pointer;
+ box-shadow: none;
+ transition: background-color 0.1s, box-shadow 0.1s;
+ text-decoration: none;
+ box-sizing: border-box;
+ background-color: white;
+ border: 0;
+ border-spacing: 0;
+ display: inline-block;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.custom-radio:not(:disabled):hover {
+ color: #333333;
+ background-color: #eeeeee;
+}
+
+.custom-radio:disabled {
+ opacity: 0.4;
+}
+
+.custom-radio.custom-radio-left [type="radio"]+label {
+ border-top-right-radius: 0 !important;
+ border-bottom-right-radius: 0 !important;
+ border-right: 0 !important;
+}
+
+.custom-radio.custom-radio-right [type="radio"]+label {
+ border-top-left-radius: 0 !important;
+ border-bottom-left-radius: 0 !important;
+}
+
+.custom-radio.custom-radio-middle [type="radio"]+label {
+ border-radius: 0 !important;
+ border-right: 0 !important;
+}
+
+.custom-radio [type="radio"]+label {
+ position: relative;
+ padding: 7px 13px 6px 29px;
+ cursor: pointer;
+ font-size: 14px;
+ line-height: 14px;
+ display: table-cell;
+ color: #666666;
+ border: 1px solid #bbbbbb;
+ border-radius: 2px;
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.custom-radio [type="radio"] {
+ position: absolute;
+ left: -9999px;
+}
+
+.custom-radio [type="radio"]:checked+label {
+ color: white;
+ background-color: #007bff;
+ border-color: #007bff;
+}
+
+.custom-radio [type="radio"]+label:before {
+ content: '';
+ position: absolute;
+ left: 11px;
+ top: 7px;
+ width: 12px;
+ height: 12px;
+ border: 1px solid #ddd;
+ border-radius: 100%;
+ background: #fff;
+}
+
+.custom-radio [type="radio"]+label:after {
+ content: '';
+ width: 8px;
+ height: 8px;
+ background: #005cbf;
+ position: absolute;
+ top: 10px;
+ left: 14px;
+ border-radius: 100%;
+ -webkit-transition: all 0.1s ease;
+ transition: all 0.1s ease;
+}
+
+.custom-radio [type="radio"]:not(:checked)+label:after {
+ opacity: 0;
+ -webkit-transform: scale(0);
+ transform: scale(0);
+}
+
+.custom-radio [type="radio"]:checked+label:after {
+ opacity: 1;
+ -webkit-transform: scale(1);
+ transform: scale(1);
+}
+
+.custom-dropdown {
+ position: relative;
+ display: block;
+ cursor: pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.custom-dropdown>a {
+ padding: 5px 26px 5px 8px;
+ outline: none;
+ border-radius: 2px;
+ box-shadow: none;
+ transition: background-color 0.1s, box-shadow 0.1s, border 0.1s;
+ text-decoration: none;
+ display: block;
+ box-sizing: border-box;
+ color: black;
+ height: 28px;
+ border: 1px solid #7d7d7d;
+ background-color: white;
+ width: 100%;
+ cursor: pointer;
+}
+
+.custom-dropdown.large>a {
+ height: 37px;
+ padding: 5px 31px 5px 10px;
+}
+
+.custom-dropdown>a>span {
+ text-align: left;
+ font-size: 14px !important;
+ line-height: 16px;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ text-overflow: ellipsis;
+}
+
+.custom-dropdown.large>a>span {
+ font-size: 16px !important;
+ line-height: 25px;
+}
+
+.custom-dropdown>a:after {
+ position: absolute;
+ content: "";
+ top: 13px;
+ right: 10px;
+ width: 0;
+ height: 0;
+ border: 4px solid transparent;
+ border-top-color: black;
+}
+
+.custom-dropdown.large>a:after {
+ top: 17px;
+ right: 13px;
+ border: 5px solid transparent;
+ border-top-color: black;
+}
+
+.custom-dropdown>div {
+ display: none;
+ position: absolute;
+ margin-top: -1px;
+ border: 1px solid #7d7d7d;
+ background-color: white;
+ z-index: 1;
+ box-sizing: border-box;
+ border-radius: 2px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+ min-width: 100%;
+}
+
+.custom-dropdown>a:focus {
+ pointer-events: none;
+}
+
+.custom-dropdown>a:focus+div {
+ display: block;
+}
+
+.custom-dropdown>div:hover {
+ display: block;
+}
+
+.custom-dropdown>div>a {
+ color: black;
+ padding: 5px 8px;
+ text-decoration: none;
+ text-align: left;
+ display: block;
+ outline: none;
+ font-size: 14px !important;
+ line-height: 16px;
+ height: 26px;
+ white-space: nowrap;
+ border-left: 0;
+ border-top: 0;
+ border-right: 0;
+ box-sizing: border-box;
+}
+
+.custom-dropdown.large>div>a {
+ font-size: 16px !important;
+ line-height: 25px;
+ height: 35px;
+ padding: 5px 10px;
+}
+
+.custom-dropdown>div>a:hover {
+ background-color: #e1e1e1;
+ color: black;
+}
+
+.custom-dropdown>div.force-hide {
+ display: none !important;
+}
+
+.custom-dialog-flat {
+ font-size: 16px;
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+ background-color: white;
+ background-image: none;
+ padding: 0;
+ margin: 0;
+ border-radius: 2px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.custom-dialog-flat .ui-dialog-content {
+ padding: 0 1.2em 1.2em 1.2em;
+ background-color: white;
+ background-image: none;
+}
+
+.custom-dialog-flat .ui-dialog-content p {
+ margin: 0.6em 0;
+}
+
+.custom-dialog-flat .ui-dialog-content p:first-child {
+ margin-top: 0;
+}
+
+.custom-dialog-flat .ui-dialog-content p:last-child {
+ margin-bottom: 0;
+}
+
+.custom-dialog-flat .ui-dialog-titlebar {
+ background-color: white;
+ background-image: none;
+ border: 0;
+ border-radius: 0px;
+ color: #2E2F30;
+ padding: 1.2em 1.2em 1.2em 1.2em;
+}
+
+.custom-dialog-flat .ui-dialog-titlebar .ui-dialog-title {
+ text-align: center;
+ margin: 0 0 0 0.5em;
+ font-size: 19px;
+}
+
+.custom-dialog-flat .ui-dialog-titlebar .ui-dialog-titlebar-close {
+ background: white none;
+ border: 0;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ right: 1.2em;
+ top: 1.3em;
+ text-indent: 0;
+}
+
+.custom-dialog-flat .ui-dialog-titlebar .ui-dialog-titlebar-close:focus {
+ outline: none;
+}
+
+.custom-dialog-flat .ui-dialog-titlebar .ui-dialog-titlebar-close:after {
+ content: '';
+ position: absolute;
+ top: -12px;
+ bottom: -12px;
+ left: -12px;
+ right: -12px;
+}
+
+.custom-dialog-flat .ui-dialog-titlebar .ui-dialog-titlebar-close.ui-state-default {
+ background: none;
+ border: none;
+ height: auto;
+}
+
+.custom-dialog-flat .ui-dialog-titlebar .ui-dialog-titlebar-close .ui-button-icon {
+ background: none;
+ border: 0;
+}
+
+.custom-dialog-flat .ui-dialog-titlebar .ui-dialog-titlebar-close .fa-lg {
+ vertical-align: -0.15em;
+}
+
+.custom-dialog-flat .ui-dialog-buttonpane {
+ border-width: 0;
+ margin: 0;
+ padding: 0em 1.2em 1.2em 1.2em;
+}
+
+.custom-dialog-flat .ui-dialog-buttonpane .ui-dialog-buttonset {
+ width: 100%;
+ text-align: right;
+}
+
+.custom-dialog-flat .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button {
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+ border: 1px solid #7d7d7d;
+ background: #7d7d7d none;
+ color: white;
+ border-radius: 2px;
+ margin: 0 0 0 1em;
+ outline: none;
+}
+
+.custom-dialog-flat .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button:first-child {
+ margin-left: 0;
+}
+
+.custom-dialog-flat .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-action-button {
+ background-color: #007bff;
+ border: 1px solid #007bff;
+}
+
+.custom-dialog-flat .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.full-width {
+ width: 100%;
+ margin-left: 0;
+}
+
+.custom-dialog-flat .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.full-width:not(:first-child) {
+ margin-top: 0.8em;
+}
+
+.custom-legend {
+ margin: 15px 0;
+}
+
+.custom-legend .legend-title {
+ text-align: left;
+ font-weight: bold;
+ margin-top: 0;
+ border: 0;
+ border-radius: 0;
+ background: rgba(255, 255, 255);
+ font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ padding: 11px 15px 10px 15px;
+ border: 1px solid #777;
+ color: #222;
+ line-height: 1.3;
+}
+
+.custom-legend .legend-title:hover {
+ background: rgba(255, 255, 255);
+ color: #222;
+}
+
+.custom-legend .legend-title:focus {
+ outline: none;
+}
+
+.custom-legend .legend-title .ui-accordion-header-icon {
+ float: right;
+ margin-top: 1px;
+}
+
+.custom-legend .legend-title .ui-icon-triangle-1-s {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ background:
+ linear-gradient(#fff, #fff),
+ #666;
+ background-position: center;
+ background-size: 50% 2px, 2px 50%;
+ /*thickness = 2px, length = 50% (25px)*/
+ background-repeat: no-repeat;
+ border-radius: 50%;
+}
+
+.custom-legend .legend-title .ui-icon-triangle-1-e {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ background:
+ linear-gradient(#fff, #fff),
+ linear-gradient(#fff, #fff),
+ #666;
+ background-position: center;
+ background-size: 50% 2px, 2px 50%;
+ /*thickness = 2px, length = 50% (25px)*/
+ background-repeat: no-repeat;
+ border-radius: 50%;
+}
+
+.custom-legend .legend-scale {
+ border: 0;
+ line-height: 1.3;
+ color: black;
+ border-radius: 0;
+ background: rgba(255, 255, 255, 0.9);
+ font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ padding: 12px 15px 12px 15px;
+ border-bottom: 1px solid #777;
+ border-right: 1px solid #777;
+ border-left: 1px solid #777;
+ border-top: 0;
+ overflow: hidden;
+}
+
+.custom-legend .legend-scale ul {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+.custom-legend .legend-scale ul li {
+ font-size: 80%;
+ list-style: none;
+ margin-left: 0;
+ line-height: 18px;
+}
+
+.custom-legend .legend-scale ul li:not(:last-child) {
+ margin-bottom: 4px;
+}
+
+.custom-legend ul.legend-labels li span {
+ display: block;
+ float: left;
+ height: 16px;
+ width: 30px;
+ margin-right: 7px;
+ margin-left: 0;
+ border: 1px solid #777;
+}
+
+.custom-legend .legend-source {
+ font-size: 12px;
+ color: #777;
+ clear: both;
+ padding-top: 6px;
+}
+
+.custom-legend a {
+ color: #777;
+}
+
+.ui-widget-overlay {
+ opacity: 0.7;
+ background-image: none;
+ background-color: black;
+}
+
+.control-group .custom-radio {
+ margin: 10px 0 10px 0;
+}
+
+.control-group .custom-dropdown {
+ margin: 10px 0 10px 0;
+}
+
+.control-group .custom-dropdown:not(:last-child) {
+ margin-right: 15px;
+}
+
+.no-x-scroll {
+ overflow-x: hidden;
+ overflow-y: scroll;
+ position: fixed;
+ height: 100vh;
+}
+
+.no-scroll {
+ overflow-x: hidden;
+ overflow-y: hidden;
+ position: fixed;
+ height: 100vh;
+}
+
+.fit-parent {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: auto;
+ height: auto;
+}
\ No newline at end of file
diff --git a/download.html b/download.html
new file mode 100644
index 0000000..cfe20b8
--- /dev/null
+++ b/download.html
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+ PatchDB
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Download Policy
+
+
+ We are happy to share PatchDB and hope you can find our dataset useful in your research. However, in order to prevent any misuse, we kindly ask you to fill out a request form to state your identity and research scope. We will verify them and then send you the download link of PatchDB dataset.
+
+
+ Request Steps:
+
+
+ 1. Please open the online request form in a browser.
+ Link to PatchDB Request Form: https://forms.gle/4CXnx9th1GcJAjC4A
+ (If you are unable to access the page, please contact SunLab by email.)
+
+
+ 2. Sign in to your Google account.
+ Since our request form and download link are facilitated by Google, please use your Gmail as the valid email to receive the form response.
+
+
+ 3. In the request form, please include your name, affiliation, work email, homepage, and the purpose of using PatchDB.
+ The information is needed for verification.
+ Note that your request may be ignored if we are not able to determine your identity or affiliation.
+ We do not share your personal information with any third parties.
+
+
+ 4. Acknowledge all the information you provided is correct.
+
+
+ 5. Read and acknowledge the Disclaimer & Download Agreement for PatchDB.
+
+
+ 6. Submit the request form.
+ A request receipt will be emailed to the email address you provided.
+ Once we verify your information, we will email the download link to you as soon as possible.
+
+
+
+
+
+
+
+
+
Disclaimer & Download Agreement
+
+
+ To download the PatchDB dataset, you must agree with the items of the succeeding Disclaimer & Download Agreement. You should carefully read the following terms before submitting the PatchDB request form.
+
+
+ PatchDB is constructed and cross-checked by 3 experts that work in security patch research. Due to the potential misclassification led by subjective factors, the Sun Security Laboratory (SunLab) cannot guarantee a 100% accuracy for samples in the dataset.
+
+ The copyright of the PatchDB dataset is owned by SunLab.
+
+ The purpose of using PatchDB should be non-commercial research and/or personal use. The dataset should not be used for commercial use and any profitable purpose.
+
+ The PatchDB dataset should not be re-selled or re-distributed. Anyone who has obtained PatchDB should not share the dataset with others without the permission from SunLab.
+
+
+
+
+
+
+
Citation
+
+
+ If you are using PatchDB for work that will result in a publication (thesis, dissertation, paper, article), please use the following citation:
+
+@inproceedings{wang2021PatchDB,
+ title={PatchDB: A Large-Scale Security Patch Dataset},
+ author={Wang, Xinda, Wang, Shu, Feng, Pengbin, Sun, Kun and Jajodia, Sushil},
+ booktitle={2021 51st Annual IEEE/IFIP International Conference on Dependable Systems and Networks (DSN)},
+ year={2021},
+ pages={149-160},
+ doi={10.1109/DSN48987.2021.00030}
+}
+ OR
+
Xinda Wang, Shu Wang, Pengbin Feng, Kun Sun and Sushil Jajodia, "PatchDB: A Large-Scale Security Patch Dataset," 2021 51st Annual IEEE/IFIP International Conference on Dependable Systems and Networks (DSN 2021), 2021, pp. 149-160, doi: 10.1109/DSN48987.2021.00030.
+
+
+
+
+
+
+
+ The PatchDB Dataset | Sun Security Laboratory at George Mason University
+
+
+
+
+
+
+
+
+
diff --git a/examples.html b/examples.html
new file mode 100644
index 0000000..e00ae61
--- /dev/null
+++ b/examples.html
@@ -0,0 +1,315 @@
+
+
+
+
+
+
+
+ PatchDB
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Typical Examples
+
+
+ Security Patches contains multiple categories.
+
+
+ buffer overflow
+ improper input validation
+ info leakage
+ double free/use after free
+ integer overflow
+ NULL pointer dereference
+ improper authentication
+ uncontrolled resource consumption
+ race condition
+ unintialized use
+ et al.
+
+
+ Below are some typical examples in PatchDB.
+
+
+
+ Example I: Buffer Overflow
+
+
+From 8514068150759c1d6a46d4605d2351babfde1601 Mon Sep 17 00:00:00 2001
+From: Johan Hedberg
+Date: Wed, 7 Sep 2016 08:45:12 +0300
+Subject: tools/csr: Fix possible buffer overflow
+
+Make sure we don't write past the end of the array.
+---
+ tools/csr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/csr.c b/tools/csr.c
+index 2c0918909..15ae7c4fb 100644
+--- a/tools/csr.c
++++ b/tools/csr.c
+@@ -2756,7 +2756,7 @@ static int parse_line(char *str)
+
+ off++;
+
+- while (1) {
++ while (length <= sizeof(array) - 2) {
+ value = strtol(off, &end, 16);
+ if (value == 0 && off == end)
+ break;
+--
+cgit 1.2-0.3.lf.el7
+
+
+
+ Example II: Info Leakage
+
+
+From 0f6ceabab0a8849b47f67d727aa526c2656089ba Mon Sep 17 00:00:00 2001
+From: Klas Lindfors
+Date: Tue, 3 Apr 2018 09:19:53 +0200
+Subject: [PATCH] util: make sure to close the authfile before returning
+ success
+
+fixes #136
+---
+ util.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/util.c b/util.c
+index 6cb4a79..32bca06 100644
+--- a/util.c
++++ b/util.c
+@@ -167,6 +167,8 @@ check_user_token (const char *authfile,
+ {
+ if(verbose)
+ D (debug_file, "Match user/token as %s/%s", username, otp_id);
++
++ fclose(opwfile);
+ return AUTH_FOUND;
+ }
+ }
+
+
+
+ Example III: Double Free
+
+
+From 9b54d816e00425c3a517514e0d677bb3cec49258 Mon Sep 17 00:00:00 2001
+From: Hou Tao
+Date: Fri, 3 Feb 2017 17:19:07 +0800
+Subject: [PATCH] blkcg: fix double free of new_blkg in blkcg_init_queue
+
+If blkg_create fails, new_blkg passed as an argument will
+be freed by blkg_create, so there is no need to free it again.
+
+Signed-off-by: Hou Tao
+Signed-off-by: Jens Axboe
+---
+ block/blk-cgroup.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
+index 37fe595cfd700..295e98c2c8ccd 100644
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -1079,10 +1079,8 @@ int blkcg_init_queue(struct request_queue *q)
+ if (preloaded)
+ radix_tree_preload_end();
+
+- if (IS_ERR(blkg)) {
+- blkg_free(new_blkg);
++ if (IS_ERR(blkg))
+ return PTR_ERR(blkg);
+- }
+
+ q->root_blkg = blkg;
+ q->root_rl.blkg = blkg;
+
+
+
+ Example IV: Integer Overflow
+
+
+From cab60de930684c33f67d4e32c7509b567f8c445b Mon Sep 17 00:00:00 2001
+From: Kevin Wolf
+Date: Wed, 26 Mar 2014 13:05:53 +0100
+Subject: [PATCH] qcow2: Fix new L1 table size check (CVE-2014-0143)
+
+The size in bytes is assigned to an int later, so check that instead of
+the number of entries.
+
+Signed-off-by: Kevin Wolf
+Reviewed-by: Max Reitz
+Signed-off-by: Stefan Hajnoczi
+---
+ block/qcow2-cluster.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
+index 9499df9..242e1f8 100644
+--- a/block/qcow2-cluster.c
++++ b/block/qcow2-cluster.c
+@@ -55,7 +55,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+ }
+ }
+
+- if (new_l1_size > INT_MAX) {
++ if (new_l1_size > INT_MAX / sizeof(uint64_t)) {
+ return -EFBIG;
+ }
+
+--
+1.8.3.1
+
+
+
+ Example V: NULL Pointer Dereference
+
+
+From f58c25069cf4a986fe17a80c5b38687e31feb539 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping
+Date: Wed, 10 Oct 2018 14:49:51 +0200
+Subject: [PATCH] ResetUri: Protect against NULL
+
+---
+ src/UriCommon.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/UriCommon.c b/src/UriCommon.c
+index 3775306..039beda 100644
+--- a/src/UriCommon.c
++++ b/src/UriCommon.c
+@@ -75,6 +75,9 @@
+
+
+ void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) {
++ if (uri == NULL) {
++ return;
++ }
+ memset(uri, 0, sizeof(URI_TYPE(Uri)));
+ }
+
+
+
+ Example VI: Race Condition
+
+
+From 2febc839133280d5a5e8e1179c94ea674489dae2 Mon Sep 17 00:00:00 2001
+From: Andy Honig
+Date: Wed, 27 Aug 2014 14:42:54 -0700
+Subject: [PATCH] KVM: x86: Improve thread safety in pit
+
+There's a race condition in the PIT emulation code in KVM. In
+__kvm_migrate_pit_timer the pit_timer object is accessed without
+synchronization. If the race condition occurs at the wrong time this
+can crash the host kernel.
+
+This fixes CVE-2014-3611.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Andrew Honig
+Signed-off-by: Paolo Bonzini
+---
+ arch/x86/kvm/i8254.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
+index 518d86471b76f..298781d4cfb44 100644
+--- a/arch/x86/kvm/i8254.c
++++ b/arch/x86/kvm/i8254.c
+@@ -262,8 +262,10 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
+ return;
+
+ timer = &pit->pit_state.timer;
++ mutex_lock(&pit->pit_state.lock);
+ if (hrtimer_cancel(timer))
+ hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
++ mutex_unlock(&pit->pit_state.lock);
+ }
+
+ static void destroy_pit_timer(struct kvm_pit *pit)
+
+
+
+ Example VII: Non-security Patch
+
+
+commit 822959238c224535e2d71e936e9f8c8d27a10a59
+Author: roberto@precise64
+Date: Thu Feb 23 16:58:36 2012 +0100
+
+ fixed a bug with --set
+
+diff --git a/uwsgi.c b/uwsgi.c
+index 3a24f6aa..178fb5db 100644
+--- a/uwsgi.c
++++ b/uwsgi.c
+@@ -3387,7 +3387,7 @@ void uwsgi_opt_set_placeholder(char *opt, char *value, void *none) {
+
+ p[0] = 0;
+ add_exported_option(uwsgi_str(value), p+1, 1);
+- p[1] = '=';
++ p[0] = '=';
+
+ }
+
+
+
+
+
+
+
+ ARGUS | PurS3 Lab at Purdue University | WSPR Lab at North Carolina State University
+
+
+
+
+
+
+
+
+
diff --git a/file/dsn21_PatchDB.bib b/file/dsn21_PatchDB.bib
new file mode 100644
index 0000000..bf71849
--- /dev/null
+++ b/file/dsn21_PatchDB.bib
@@ -0,0 +1,10 @@
+@inproceedings{wang2021PatchDB,
+ author={Wang, Xinda and Wang, Shu and Feng, Pengbin and Sun, Kun and Jajodia, Sushil},
+ booktitle={2021 51st Annual IEEE/IFIP International Conference on Dependable Systems and Networks (DSN)},
+ title={PatchDB: A Large-Scale Security Patch Dataset},
+ year={2021},
+ volume={},
+ number={},
+ pages={149-160},
+ doi={10.1109/DSN48987.2021.00030}}
+}
diff --git a/file/dsn21_slides_wang.pdf b/file/dsn21_slides_wang.pdf
new file mode 100644
index 0000000..67f9821
Binary files /dev/null and b/file/dsn21_slides_wang.pdf differ
diff --git a/img/book.png b/img/book.png
new file mode 100644
index 0000000..b7da756
Binary files /dev/null and b/img/book.png differ
diff --git a/img/brick2x2.jpg b/img/brick2x2.jpg
new file mode 100644
index 0000000..dd9af43
Binary files /dev/null and b/img/brick2x2.jpg differ
diff --git a/img/download.png b/img/download.png
new file mode 100644
index 0000000..2f26952
Binary files /dev/null and b/img/download.png differ
diff --git a/img/ncsu.png b/img/ncsu.png
new file mode 100644
index 0000000..6d9014a
Binary files /dev/null and b/img/ncsu.png differ
diff --git a/img/purdue.png b/img/purdue.png
new file mode 100644
index 0000000..5d9a774
Binary files /dev/null and b/img/purdue.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..f52a607
--- /dev/null
+++ b/index.html
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+ ARGUS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ARGUS Overview
+
+
+ ARGUS is a static taint tracker build to detect code injection vulnerabilities inside GitHub Workflows. Argus can track the dangerous sources across workflow configuration and JavaScript actions.
+ You can see examples page to see the type of vulnerabilities Argus can detect.
+
+
Getting Started
+
+ To improve the usability of Argus for developers, we created Docker image that contains all the required dependencies to run Argus and detect code injection vulnerabilities inside the workflows.
+
+ Following are step-by-step instructions on how to run Argus:
+
+
+ docker-compose build
+ ...
+ ...
+ ...
+
+
+
+
+ @inproceedings{muralee2021Argus,
+ title={ARGUS: A Framework for Staged Static Taint Analysis of GitHub Workflows and Actions},
+ author={S. Muralee, I. Koishybayev, A. Nahapetyan, G. Tystahl, B. Reaves, A. Bianchi, W. Enck,
+ A. Kapravelos, A. Machiry},
+ booktitle={32st USENIX Security Symposium (USENIX Security 23)},
+ year={2023},
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ARGUS | PurS3 Lab at Purdue University | WSPR Lab at North Carolina State University
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/custom.js b/js/custom.js
new file mode 100644
index 0000000..e0e87a1
--- /dev/null
+++ b/js/custom.js
@@ -0,0 +1,151 @@
+/*************************************************************************
+ * Your custom JS file
+ *************************************************************************/
+
+(function () {
+ "use strict";
+
+ // The widget object
+ var widgets;
+
+ function createShareButtonAndDialog() {
+ var $share_url_copy_prompt = $("#share-url-copy-prompt");
+
+ // Create the share dialog
+ var $share_dialog = widgets.createCustomDialog({
+ selector: "#share-dialog",
+ full_width_button: true,
+ action_text: "Copy to clipboard",
+ close_dialog_on_action: false,
+ show_cancel_btn: false,
+ action_callback: function () {
+ widgets.copyText("share-url");
+ $share_url_copy_prompt.show();
+ }
+ });
+ $share_dialog.on("dialogclose", function () {
+ $share_url_copy_prompt.hide();
+ });
+
+ // Set the event of the share url textbox
+ var $share_url = $("#share-url");
+ $share_url.focus(function () {
+ $(this).select();
+ }).click(function () {
+ $(this).select();
+ }).mouseup(function (e) {
+ e.preventDefault();
+ });
+
+ // Set the event of the share button
+ $("#share-btn").on("click", function () {
+ $share_dialog.dialog("open");
+ });
+ }
+
+ function init() {
+ // Create the widget object
+ widgets = new edaplotjs.Widgets();
+
+ // Set custom dropdown
+ widgets.setCustomDropdown($("#custom-dropdown"), {
+ items: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"],
+ //init_index: 0, // You can use this parameter to set the initial item for displaying
+ init_text: "Dropdown Menu (With JavaScript)",
+ on_item_click_callback: function ($ui) {
+ console.log($ui.text());
+ }
+ });
+ widgets.setCustomDropdown($("#custom-dropdown-large"), {
+ items: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"],
+ //init_index: 0, // You can use this parameter to set the initial item for displaying
+ init_text: "Large Dropdown Menu (With JavaScript)",
+ on_item_click_callback: function ($ui) {
+ console.log($ui.text());
+ }
+ });
+
+ // Set custom radio
+ $("input:radio[name='playback-speed']").on("change", function () {
+ console.log($(this).val());
+ });
+
+ // Set custom dialog type 1
+ var $dialog_1 = widgets.createCustomDialog({
+ selector: "#dialog-1",
+ full_width_button: true
+ });
+ $("#dialog-btn-1").on("click", function () {
+ $dialog_1.dialog("open");
+ });
+
+ // Set custom dialog type 2
+ var $dialog_2 = widgets.createCustomDialog({
+ selector: "#dialog-2",
+ action_callback: function () {
+ console.log("confirm");
+ },
+ cancel_callback: function () {
+ console.log("cancel");
+ }
+ });
+ $("#dialog-btn-2").on("click", function () {
+ $dialog_2.dialog("open");
+ });
+
+ // Set custom dialog type 3
+ var $dialog_3 = widgets.createCustomDialog({
+ selector: "#dialog-3",
+ parent: $(".content"),
+ show_cancel_btn: false,
+ cancel_callback: function () {
+ console.log("cancel");
+ },
+ });
+ $("#dialog-btn-3").on("click", function () {
+ $dialog_3.dialog("open");
+ });
+
+ // Set custom dialog type 4
+ var $dialog_4 = widgets.createCustomDialog({
+ selector: "#dialog-4",
+ action_text: "Action",
+ reverse_button_positions: true,
+ full_width_button: true,
+ action_callback: function () {
+ console.log("action");
+ },
+ cancel_text: "Back",
+ cancel_callback: function () {
+ console.log("back");
+ }
+ });
+ $("#dialog-btn-4").on("click", function () {
+ $dialog_4.dialog("open");
+ });
+
+ // Create the share button and dialog
+ createShareButtonAndDialog();
+
+ // Create the gallery
+ var $gallery = $(".gallery");
+ // In practice, these images urls may come from your server via http ajax requests.
+ for (var i = 0; i < 8; i++) {
+ var item = "" +
+ " " +
+ "Image Caption
" +
+ " ";
+ $gallery.append($(item));
+ }
+
+ // Create custom tabs
+ widgets.createCustomTab({
+ selector: "#custom-tab"
+ });
+
+ // Set the custom legend
+ widgets.setCustomLegend($("#custom-legend"));
+ }
+
+ $(init);
+})();
\ No newline at end of file
diff --git a/js/menu.js b/js/menu.js
new file mode 100644
index 0000000..d385cb9
--- /dev/null
+++ b/js/menu.js
@@ -0,0 +1,7 @@
+(function () {
+ "use strict";
+
+ $(function () {
+ $(".menu-container").load("menu.html");
+ });
+})();
\ No newline at end of file
diff --git a/js/widgets.js b/js/widgets.js
new file mode 100644
index 0000000..3983cbb
--- /dev/null
+++ b/js/widgets.js
@@ -0,0 +1,360 @@
+/*************************************************************************
+ * GitHub: https://github.com/yenchiah/project-website-template
+ * Version: v3.29
+ * This JS file has widgets for building interactive web applications
+ * Use this file with widgets.css
+ * If you want to keep this template updated, avoid modifying this file
+ * Instead, add your own JavaScript in the index.js
+ *************************************************************************/
+
+(function () {
+ "use strict";
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Create the class
+ //
+ var Widgets = function () {
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Variables
+ //
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Private methods
+ //
+
+ // Safely get the value from a variable, return a default value if undefined
+ function safeGet(v, default_val) {
+ if (typeof default_val === "undefined") default_val = "";
+ return (typeof v === "undefined") ? default_val : v;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Privileged methods
+ //
+ function createCustomTab(settings) {
+ settings = safeGet(settings, {});
+
+ // Specify the selector of the tab
+ var $selector = $(settings["selector"]);
+ if ($selector.length == 0) {
+ console.error("Cannot find selector: " + settings["selector"]);
+ return false;
+ }
+ if ($selector.length > 1) {
+ console.error("Multiple selectors were found. Please indicate only one at a time.");
+ return false;
+ }
+
+ // Get the menu items
+ var $menu_items = $selector.find(".custom-tab-menu-item");
+ var $all_contents = $selector.find(".custom-tab-content");
+ $menu_items.each(function (i, element) {
+ var $element = $(element);
+ var idx_content = $element.data("content");
+ var $desired_content = $selector.find(".custom-tab-content[data-content=" + idx_content + "]");
+ // Add click event
+ $element.on("click", function () {
+ $all_contents.hide();
+ $desired_content.css("display", "flex");
+ $menu_items.removeClass("active");
+ $element.addClass("active");
+ });
+ });
+ $selector.find(".custom-tab-menu-item.active").click();
+ }
+ this.createCustomTab = createCustomTab;
+
+ function createCustomDialog(settings) {
+ settings = safeGet(settings, {});
+
+ // Create a button for taking actions (e.g., confirm that users get the message)
+ // The default text for the button is "Confirm"
+ var has_action_callback = (typeof settings["action_callback"] === "function");
+ var action_text = safeGet(settings["action_text"], "Confirm");
+
+ // Create a button for cancellation
+ // The default text for the button is "Cancel" when there is an action button
+ // The default text for the button is "Ok" when there is no action button
+ var has_cancel_callback = (typeof settings["cancel_callback"] === "function");
+ var cancel_text = has_action_callback ? "Cancel" : "Ok";
+ cancel_text = safeGet(settings["cancel_text"], cancel_text);
+
+ // Hide the cancel button or not
+ var show_cancel_btn = safeGet(settings["show_cancel_btn"], true);
+
+ // Specify the style
+ var style_class = "custom-dialog-flat";
+
+ // Specify the selector of the dialog
+ // If no selector, a
will be created
+ var $selector = $(safeGet(settings["selector"], "
"));
+
+ // Specify the width of the dialog
+ var width = safeGet(settings["width"], 260);
+
+ // Specify if full width buttons
+ var full_width_button = safeGet(settings["full_width_button"], false);
+
+ // Show the close button or not
+ var show_close_button = safeGet(settings["show_close_button"], true);
+
+ // Close the dialog when the action button is clicked or not
+ var close_dialog_on_action = safeGet(settings["close_dialog_on_action"], true);
+
+ // Close the dialog when the cancel button is clicked or not
+ var close_dialog_on_cancel = safeGet(settings["close_dialog_on_cancel"], true);
+
+ // Reverse the positions of the action and cancel buttons
+ var reverse_button_positions = safeGet(settings["reverse_button_positions"], false);
+
+ // Specify buttons
+ var buttons = [];
+ if (show_cancel_btn) {
+ var btn_class = "ui-cancel-button";
+ if (full_width_button) {
+ btn_class += " full-width";
+ }
+ buttons.push({
+ class: btn_class,
+ text: cancel_text,
+ click: function () {
+ if (close_dialog_on_cancel) {
+ $(this).dialog("close");
+ }
+ if (has_cancel_callback) settings["cancel_callback"]();
+ }
+ });
+ }
+ if (has_action_callback) {
+ var btn_class = "ui-action-button";
+ if (full_width_button) {
+ btn_class += " full-width";
+ }
+ buttons.push({
+ class: btn_class,
+ text: action_text,
+ click: function () {
+ if (close_dialog_on_action) {
+ $(this).dialog("close");
+ }
+ if (has_action_callback) settings["action_callback"]();
+ }
+ });
+ }
+
+ // Reverse button positions or not
+ if (buttons.length == 2 && reverse_button_positions) {
+ var tmp = buttons[1];
+ buttons[1] = buttons[0];
+ buttons[0] = tmp;
+ }
+
+ // Create dialog
+ var $selector_container;
+ var dialog_settings = {
+ autoOpen: false,
+ resizable: false,
+ height: "auto",
+ draggable: false,
+ width: width,
+ modal: true,
+ classes: {
+ "ui-dialog": style_class
+ }, // this is for jquery 1.12 and after
+ dialogClass: style_class, // this is for before jquery 1.12
+ buttons: buttons,
+ closeText: "",
+ open: function (event, ui) {
+ var num_opened_dialog = 0;
+ $(".ui-dialog-content").each(function () {
+ if ($(this).dialog("isOpen")) num_opened_dialog += 1;
+ });
+ // Larger than 1 after opening means that there exists other opened dialog boxes
+ var is_other_dialog_opened = num_opened_dialog > 1;
+ // Check if parent element is specified
+ if (!is_other_dialog_opened) {
+ if (typeof settings["parent"] === "undefined") {
+ var $body = $("body");
+ if (!$body.hasClass("no-scroll") || !$body.hasClass("no-x-scroll")) {
+ // When the dialog is open, we want to set the top of the body to the scroll position
+ document.body.style.top = -window.scrollY + "px";
+ if (window.innerWidth > document.body.clientWidth) {
+ // This means that the page has a vertical scroll bar
+ $body.addClass("no-x-scroll");
+ } else {
+ // This means that the page has no vertical scroll bar
+ $body.addClass("no-scroll");
+ }
+ }
+ $selector_container.css({
+ position: "fixed",
+ top: "calc(50% - " + ($selector_container.height() / 2) + "px)",
+ margin: "0 auto",
+ left: "0",
+ right: "0",
+ overflow: "hidden"
+ });
+ } else {
+ // If there is a parent, need to fit the overlay to the parent element
+ var $overlay = $(".ui-widget-overlay");
+ if (!$overlay.hasClass("fit-parent")) {
+ $overlay.addClass("fit-parent");
+ }
+ }
+ }
+ },
+ close: function (event, ui) {
+ var num_opened_dialog = 0;
+ $(".ui-dialog-content").each(function () {
+ if ($(this).dialog("isOpen")) num_opened_dialog += 1;
+ });
+ // Larger than 0 after closing means that there exists other opened dialog boxes
+ var is_other_dialog_opened = num_opened_dialog > 0;
+ if (!is_other_dialog_opened) {
+ // Check if parent element is specified
+ if (typeof settings["parent"] === "undefined") {
+ var $body = $("body");
+ if ($body.hasClass("no-scroll") || $body.hasClass("no-x-scroll")) {
+ if ($body.hasClass("no-scroll")) {
+ $body.removeClass("no-scroll");
+ }
+ if ($body.hasClass("no-x-scroll")) {
+ $body.removeClass("no-x-scroll");
+ }
+ // When the dialog is hidden, we want to remain at the top of the scroll position
+ var scrollY = document.body.style.top;
+ document.body.style.top = "";
+ window.scrollTo(0, parseInt(scrollY || "0") * -1);
+ }
+ } else {
+ // If there is a parent, need to remove the class that fits the overlay to the parent
+ var $overlay = $(".ui-widget-overlay");
+ if ($overlay.hasClass("fit-parent")) {
+ $overlay.removeClass("fit-parent");
+ }
+ }
+ }
+ }
+ };
+
+ if (typeof settings["parent"] === "undefined") {
+ dialog_settings["position"] = {
+ my: "center",
+ at: "center",
+ of: window
+ };
+ } else {
+ dialog_settings["appendTo"] = settings["parent"];
+ dialog_settings["position"] = {
+ my: "center",
+ at: "center",
+ of: settings["parent"]
+ };
+ }
+ var $dialog = $selector.dialog(dialog_settings);
+ $selector_container = $selector.closest(".ui-dialog");
+ $selector_container.find(".ui-dialog-titlebar-close").empty().append(" ");
+ if (!show_close_button) {
+ $dialog.on("dialogopen", function () {
+ $(this).parent().find(".ui-dialog-titlebar-close").hide();
+ });
+ }
+ return $dialog;
+ }
+ this.createCustomDialog = createCustomDialog;
+
+ function setCustomDropdown($ui, settings) {
+ var items = settings["items"]; // the text that will appear for each item
+ var init_index = settings["init_index"];
+ var init_text = settings["init_text"];
+ var on_item_click_callback = settings["on_item_click_callback"];
+ var on_item_create_callback = settings["on_item_create_callback"];
+ var $menu = $ui.find("div").empty();
+ var $button_text = $ui.find("a > span").text("");
+ var $selected_item;
+ // Set initial button text
+ if (typeof init_text !== "undefined") {
+ $button_text.text(init_text);
+ } else {
+ if (typeof init_index !== "undefined" && typeof items !== "undefined") {
+ $button_text.text(items[init_index]);
+ }
+ }
+ // Set button event
+ // Note that the button is designed to use focusout and focus to determine its state
+ // "focusout" indicates that the menu is currently opened and should be closed
+ // "focus" indicates that the menu is currently closed and should be opened
+ $ui.find("a").off("focusout").on("focusout", function () {
+ // Find which item is hovered, and then simulate the click
+ if (typeof $selected_item !== "undefined") {
+ $button_text.text($selected_item.text()); // update the text on the button
+ if (typeof on_item_click_callback === "function") on_item_click_callback($selected_item, $selected_item.index());
+ $selected_item = undefined;
+ }
+ if ($menu.is(":visible")) $menu.addClass("force-hide"); // close the menu
+ }).off("focus").on("focus", function () {
+ if (!$menu.is(":visible")) $menu.removeClass("force-hide"); // open the menu
+ });
+ // Add events for menu items
+ for (var i = 0; i < items.length; i++) {
+ var $item = $("" + items[i] + " ");
+ // We need to let the focusout button event know which item is selected
+ // Note that we cannot use the click event to find this,
+ // because as soon as the item is clicked,
+ // the focusout event of the button is triggered,
+ // this closes the menu and we never get the click event from the items
+ $item.on("mouseover", function () {
+ $selected_item = $(this);
+ }).on("mouseout", function () {
+ $selected_item = undefined;
+ });
+ $menu.append($item);
+ if (typeof on_item_create_callback === "function") on_item_create_callback($item, i);
+ }
+ return $ui;
+ }
+ this.setCustomDropdown = setCustomDropdown;
+
+ function setCustomLegend($ui, settings) {
+ settings = safeGet(settings, {});
+ $ui.accordion({
+ collapsible: true,
+ animate: safeGet(settings["animate"], false)
+ });
+ return $ui;
+ }
+ this.setCustomLegend = setCustomLegend;
+
+ // Copy text in a input field
+ function copyText(element_id) {
+ // Get the text field
+ var copy = document.getElementById(element_id);
+ // Select the text field
+ copy.select();
+ copy.setSelectionRange(0, 99999); /*For mobile devices*/
+ // Copy the text inside the text field
+ document.execCommand("copy");
+ }
+ this.copyText = copyText;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constructor
+ //
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Register to window
+ //
+ if (window.edaplotjs) {
+ window.edaplotjs.Widgets = Widgets;
+ } else {
+ window.edaplotjs = {};
+ window.edaplotjs.Widgets = Widgets;
+ }
+})();
\ No newline at end of file
diff --git a/materials.html b/materials.html
new file mode 100644
index 0000000..2bad165
--- /dev/null
+++ b/materials.html
@@ -0,0 +1,96 @@
+
+
+
+
+ Argus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Materials
+
+
+ Usenix Security'23 Paper: "ARGUS: A Framework for Staged Static Taint Analysis of GitHub Workflows and Actions".
+
+
+
+ Video:
+
+
+
+
+
+ Your browser does not support the video tag.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ARGUS | PurS3 Lab at Purdue University | WSPR Lab at North Carolina State University
+
+
+
+
+
+
+
+
+
diff --git a/menu.html b/menu.html
new file mode 100644
index 0000000..5ac9d51
--- /dev/null
+++ b/menu.html
@@ -0,0 +1,16 @@
+
\ No newline at end of file
diff --git a/vid/DSN21_regular_176_wang.mp4 b/vid/DSN21_regular_176_wang.mp4
new file mode 100644
index 0000000..237c42d
Binary files /dev/null and b/vid/DSN21_regular_176_wang.mp4 differ