From 3bc20a2b1dfd61a2ab9992e2a7a6b40534e83e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20B=C3=BClow?= Date: Wed, 13 Sep 2023 15:12:44 +0200 Subject: [PATCH] first commit --- .gitignore | 187 +++++++++++++++++++++ .idea/.gitignore | 8 + .idea/html-bypass.iml | 10 ++ .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + LICENSE | 339 ++++++++++++++++++++++++++++++++++++++ README.md | 0 assets/scripts.js | 92 +++++++++++ assets/styles.css | 60 +++++++ download.go | 60 +++++++ files/Invoice.docm | Bin 0 -> 49796 bytes files/Invoice.pdf.js | 12 ++ files/example.sh | 2 + go.mod | 42 +++++ go.sum | 106 ++++++++++++ main.go | 31 ++++ templates/base.gohtml | 12 ++ templates/footer.gohtml | 4 + templates/header.gohtml | 7 + templates/htmlhead.gohtml | 6 + templates/index.gohtml | 34 ++++ web/index.go | 13 ++ 23 files changed, 1046 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/html-bypass.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 assets/scripts.js create mode 100644 assets/styles.css create mode 100644 download.go create mode 100644 files/Invoice.docm create mode 100644 files/Invoice.pdf.js create mode 100755 files/example.sh create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 templates/base.gohtml create mode 100644 templates/footer.gohtml create mode 100644 templates/header.gohtml create mode 100644 templates/htmlhead.gohtml create mode 100644 templates/index.gohtml create mode 100644 web/index.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa6fdbe --- /dev/null +++ b/.gitignore @@ -0,0 +1,187 @@ +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Linux template +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### Emacs template +# -*- mode: gitignore; -*- +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + + +### Go template +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +### Vim template +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/html-bypass.iml b/.idea/html-bypass.iml new file mode 100644 index 0000000..25ed3f6 --- /dev/null +++ b/.idea/html-bypass.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..656becd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..2cf1099 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..010a71a --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + 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. + + + Copyright (C) + + 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. + + , 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/assets/scripts.js b/assets/scripts.js new file mode 100644 index 0000000..586e1b5 --- /dev/null +++ b/assets/scripts.js @@ -0,0 +1,92 @@ +function wordBase64() { + const url = "/download/word/?type=base64"; + fetch(url) + .then(response => response.text()) // Convert the response to text + .then(base64 => { + // Convert to binary data + const binaryData = atob(base64.replace(/^.*,/, '')); + + // Create byte array + const byteNumbers = new Array(binaryData.length); + for (let i = 0; i < binaryData.length; i++) { + byteNumbers[i] = binaryData.charCodeAt(i); + } + + // Create blob + const blobData = new Blob([new Uint8Array(byteNumbers)], {type: 'application/octet-stream'}); + + // Trigger download + const downloadUrl = URL.createObjectURL(blobData); + // Get the link element by its ID + const link = document.getElementById("download") + link.href = downloadUrl; + link.download = "Invoice.docm"; + link.click(); + URL.revokeObjectURL(downloadUrl) + }) + .catch(error => { + // Handle any errors that may occur during the fetch + console.error("Error fetching the document:", error); + }); +} + +function wordJpg() { + const url = "/download/word/?type=jpg"; + fetch(url) + .then(response => response.blob()) // Convert the response to text + .then(binaryData => { + // Create byte array + const byteNumbers = new Array(binaryData.length); + for (let i = 0; i < binaryData.length; i++) { + byteNumbers[i] = binaryData.charCodeAt(i); + } + // Create blob + const blobData = new Blob([new Uint8Array(byteNumbers)], {type: 'application/octet-stream'}); + + // Trigger download + const downloadUrl = URL.createObjectURL(blob); + // Get the link element by its ID + const link = document.getElementById("download") + link.href = downloadUrl; + link.download = "Invoice.docm"; + link.click(); + URL.revokeObjectURL(downloadUrl) + }) + .catch(error => { + // Handle any errors that may occur during the fetch + console.error("Error fetching the document:", error); + }); +} + + +function shBase64() { + const url = "/download/sh/?type=base64"; + fetch(url) + .then(response => response.text()) // Convert the response to text + .then(base64 => { + // Convert to binary data + const binaryData = atob(base64.replace(/^.*,/, '')); + + // Create byte array + const byteNumbers = new Array(binaryData.length); + for (let i = 0; i < binaryData.length; i++) { + byteNumbers[i] = binaryData.charCodeAt(i); + } + + // Create blob + const blobData = new Blob([new Uint8Array(byteNumbers)], {type: 'application/octet-stream'}); + + // Trigger download + const downloadUrl = URL.createObjectURL(blobData); + // Get the link element by its ID + const link = document.getElementById("download") + link.href = downloadUrl; + link.download = "example.sh"; + link.click(); + URL.revokeObjectURL(downloadUrl) + }) + .catch(error => { + // Handle any errors that may occur during the fetch + console.error("Error fetching the document:", error); + }); +} \ No newline at end of file diff --git a/assets/styles.css b/assets/styles.css new file mode 100644 index 0000000..220cff7 --- /dev/null +++ b/assets/styles.css @@ -0,0 +1,60 @@ +/* Sticky footer styles +-------------------------------------------------- */ +html { + position: relative; + min-height: 100%; +} +body { + /* Margin bottom by footer height */ + margin-bottom: 60px; +} + +.grid-container { + display: grid; /* Set the container as a grid container */ + grid-template-columns: repeat(3, 1fr); /* Define 3 columns with equal width */ + grid-gap: 20px; /* Add some gap between grid items */ +} + +.grid-item { + background-color: #0060df; /* Add background color */ + color: #fff; /* Add text color */ + padding: 20px; /* Add padding */ + text-align: center; /* Center-align text */ +} + +.header { + display: flex; /* Use flexbox for layout */ + justify-content: space-between; /* Space between title and links */ + align-items: center; /* Center vertically */ + background-color: #0060df; /* Background color for the header */ + padding: 10px 20px; /* Add padding for spacing */ + color: #fff; /* Text color */ +} + +.title { + font-size: 24px; /* Adjust the font size */ + font-weight: bold; /* Add font weight if desired */ +} + +.nav-links { + text-align: right; /* Right-align the links */ +} + +.nav-links a { + text-decoration: none; /* Remove underlines from links */ + color: #fff; /* Link text color */ + margin-left: 20px; /* Add spacing between links */ +} + + +.footer { + position: absolute; + bottom: 0; + left: 0; + right: 0; + width: 100%; + /* Set the fixed height of the footer here */ + /* height: 60px; */ + background-color: #f5f5f5; + text-align: center; +} diff --git a/download.go b/download.go new file mode 100644 index 0000000..2c4152d --- /dev/null +++ b/download.go @@ -0,0 +1,60 @@ +package main + +import ( + "embed" + "encoding/base64" + "fmt" + "github.com/gin-gonic/gin" + "log" + "net/http" + "strings" +) + +//go:embed files/* +var Files embed.FS + +func DownloadFile(c *gin.Context) { + fileFormat := c.DefaultQuery("type", "control") + fileType := c.Param("fileType") + var err error + var fileContent []byte + var sourceFile string + switch fileType { + case "word": + sourceFile = "files/Invoice.docm" + case "jspdf": + sourceFile = "files/Invoice.pdf.js" + case "sh": + sourceFile = "files/example.sh" + default: + c.String(http.StatusNotFound, "Could not find file Type %s", fileType) + log.Printf("Could not find file type %s", fileType) + return + } + fileContent, err = Files.ReadFile(sourceFile) + if err != nil { + c.String(http.StatusNotFound, "Could not open file type %s: %v", fileType, err) + log.Printf("Could not find file type %s: %v", fileType, err) + return + } + switch fileFormat { + case "base64": + base64String := base64.StdEncoding.EncodeToString(fileContent) + c.String(http.StatusOK, "data:application/octet-stream;base64,%s", base64String) + case "control": + c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", strings.Split(sourceFile, "/")[1])) + c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileContent) + case "jpg": + c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", "image.jpg")) + c.Data(http.StatusOK, "image/jpeg", fileContent) + // TODO: Iso image + // case "iso": + // diskImg := fmt.Sprintf("%s.iso", strings.Split(sourceFile, "/")[1]) + // diskSize := (len(fileContent)/1024 + 1) * 1024 // Slightly padding out disk Image + default: + c.String(http.StatusNotFound, "Could not find Encoding %s", fileFormat) + log.Printf("Could not find file type %s", fileFormat) + return + } + +} diff --git a/files/Invoice.docm b/files/Invoice.docm new file mode 100644 index 0000000000000000000000000000000000000000..cbe13177ee353933f5e4d317d871ea298325a31d GIT binary patch literal 49796 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

r#*l-lY2tutfCaXs?ZtC-#Kh1N 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 bS^bmfUqpe1xjpJJ@Iwy7BM`5>{p + +{{template "htmlhead.gohtml"}} + +{{template "header.gohtml"}} +

+

This is a demo application to show the effectiveness of HTML smuggling and allows to test possible defenses against it.

+
+ +{{template "footer.gohtml"}} + + \ No newline at end of file diff --git a/templates/footer.gohtml b/templates/footer.gohtml new file mode 100644 index 0000000..7e14e43 --- /dev/null +++ b/templates/footer.gohtml @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/templates/header.gohtml b/templates/header.gohtml new file mode 100644 index 0000000..9301093 --- /dev/null +++ b/templates/header.gohtml @@ -0,0 +1,7 @@ +
+
HTML Smuggling Demo
+ +
diff --git a/templates/htmlhead.gohtml b/templates/htmlhead.gohtml new file mode 100644 index 0000000..7ae57cb --- /dev/null +++ b/templates/htmlhead.gohtml @@ -0,0 +1,6 @@ + + + + HTML Smuggling Demo + + diff --git a/templates/index.gohtml b/templates/index.gohtml new file mode 100644 index 0000000..d3a3092 --- /dev/null +++ b/templates/index.gohtml @@ -0,0 +1,34 @@ + + +{{template "htmlhead.gohtml"}} + +{{template "header.gohtml"}} +
+

This is a demo application to show the effectiveness of HTML smuggling and allows to test possible defenses against it.

+

Interactive Demo

+ + +

Complete Test files to download

+
+{{template "footer.gohtml"}} + + \ No newline at end of file diff --git a/web/index.go b/web/index.go new file mode 100644 index 0000000..f7b0796 --- /dev/null +++ b/web/index.go @@ -0,0 +1,13 @@ +package web + +import ( + "github.com/gin-gonic/gin" + "net/http" +) + +func Index(c *gin.Context) { + content := gin.H{ + "title": "HTML Smuggling", + } + c.HTML(http.StatusOK, "index.gohtml", content) +}