diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..7acbc21 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,46 @@ + Copyright 2022 idk (hankhill19580@gmail.com) + + 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. + + ======================================================================== + Includes code from zzzot: + + Copyright 2010 zzz (zzz@mail.i2p) + + 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. + + ======================================================================== + Includes code from Jetty 5.1.15: + + Copyright 199-2004 Mort Bay Consulting Pty. Ltd. + ------------------------------------------------------------------------ + 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 index 692d12b..5039c82 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Within a particular ecosystem, there may be a common way of installing things, s Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. ## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. +Tell people where they can go to for help. It can be any combination of an issue firefox, a chat room, an email address, etc. ## Roadmap If you have ideas for releases in the future, it is a good idea to list them in the README. diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..76b3450 --- /dev/null +++ b/build.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugin/LICENSE.txt b/plugin/LICENSE.txt new file mode 100644 index 0000000..e69de29 diff --git a/plugin/clients.config b/plugin/clients.config new file mode 100644 index 0000000..39d99e6 --- /dev/null +++ b/plugin/clients.config @@ -0,0 +1,8 @@ +clientApp.0.main=net.i2p.i2pfirefox.I2PFirefoxController +clientApp.0.name=I2PFirefox +clientApp.0.args=-d $PLUGIN start +clientApp.0.stopargs=-d $PLUGIN stop +clientApp.0.delay=0 +clientApp.0.startOnLoad=true +# we also use i2p.jar and i2ptunnel.jar, they are in the standard router classpath +clientApp.0.classpath=$PLUGIN/lib/i2pfirefox.jar,$I2P/lib/i2psnark.jar diff --git a/plugin/templates/contexts/base-context.xml b/plugin/templates/contexts/base-context.xml new file mode 100644 index 0000000..8fec760 --- /dev/null +++ b/plugin/templates/contexts/base-context.xml @@ -0,0 +1,23 @@ + + + + + + + / + $PLUGIN/eepsite/docroot/ + + cacheControl + max-age=3600,public + + + net.i2p.servlet.I2PDefaultServlet + / + + + diff --git a/plugin/templates/contexts/cgi-context.xml b/plugin/templates/contexts/cgi-context.xml new file mode 100644 index 0000000..33377db --- /dev/null +++ b/plugin/templates/contexts/cgi-context.xml @@ -0,0 +1,36 @@ + + + + + + + /cgi-bin + $PLUGIN/eepsite/cgi-bin/ + + Path + /usr/local/bin:/bin:/usr/bin + + + org.eclipse.jetty.servlets.CGI + / + + diff --git a/plugin/templates/etc/realm.properties b/plugin/templates/etc/realm.properties new file mode 100644 index 0000000..f9e4e7f --- /dev/null +++ b/plugin/templates/etc/realm.properties @@ -0,0 +1,21 @@ +# +# This file defines users passwords and roles for a HashUserRealm +# +# The format is +# : [, ...] +# +# Passwords may be clear text, obfuscated or checksummed. The class +# org.mortbay.util.Password should be used to generate obfuscated +# passwords or password checksums +# +# If DIGEST Authentication is used, the password must be in a recoverable +# format, either plain text or OBF:. +# +jetty: MD5:164c88b302622e17050af52c89945d44,user +admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin +other: OBF:1xmk1w261u9r1w1c1xmq +plain: plain +user: password + +# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password +digest: MD5:6e120743ad67abfbc385bc2bb754e297 diff --git a/plugin/templates/etc/webdefault.xml b/plugin/templates/etc/webdefault.xml new file mode 100644 index 0000000..d0a6f4b --- /dev/null +++ b/plugin/templates/etc/webdefault.xml @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + + + + + + + + + + Default web.xml file. + This file is applied to a Web application before it's own WEB_INF/web.xml file + + + + + + + + + + org.eclipse.jetty.webapp.NoTLDJarPattern + start.jar|ant-.*\.jar|dojo-.*\.jar|jetty-.*\.jar|jsp-api-.*\.jar|junit-.*\.jar|servlet-api-.*\.jar|dnsns\.jar|rt\.jar|jsse\.jar|tools\.jar|sunpkcs11\.jar|sunjce_provider\.jar|xerces.*\.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + org.eclipse.jetty.servlet.DefaultServlet + + acceptRanges + true + + + dirAllowed + true + + + welcomeServlets + false + + + redirectWelcome + false + + + maxCacheSize + 256000000 + + + maxCachedFileSize + 10000000 + + + maxCachedFiles + 1000 + + + cacheType + both + + + gzip + true + + + useFileMappedBuffer + true + + + cacheControl + max-age=3600,public + + 0 + + + default / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jsp + org.apache.jasper.servlet.JspServlet + + logVerbosityLevel + DEBUG + + + fork + false + + + xpoweredBy + false + + + 0 + + + + jsp + *.jsp + *.jspf + *.jspx + *.xsp + *.JSP + *.JSPF + *.JSPX + *.XSP + + + + + + + + + + + + + + + + + + + + + + + + + + + + 30 + + + + + + + + + + + + + index.html + index.htm + index.jsp + + + + + arISO-8859-6 + beISO-8859-5 + bgISO-8859-5 + caISO-8859-1 + csISO-8859-2 + daISO-8859-1 + deISO-8859-1 + elISO-8859-7 + enISO-8859-1 + esISO-8859-1 + etISO-8859-1 + fiISO-8859-1 + frISO-8859-1 + hrISO-8859-2 + huISO-8859-2 + isISO-8859-1 + itISO-8859-1 + iwISO-8859-8 + jaShift_JIS + koEUC-KR + ltISO-8859-2 + lvISO-8859-2 + mkISO-8859-5 + nlISO-8859-1 + noISO-8859-1 + plISO-8859-2 + ptISO-8859-1 + roISO-8859-2 + ruISO-8859-5 + shISO-8859-5 + skISO-8859-2 + slISO-8859-2 + sqISO-8859-2 + srISO-8859-5 + svISO-8859-1 + trISO-8859-9 + ukISO-8859-5 + zhGB2312 + zh_TWBig5 + + + + + Disable TRACE + / + TRACE + + + + + + diff --git a/plugin/templates/help.html b/plugin/templates/help.html new file mode 100644 index 0000000..c001625 --- /dev/null +++ b/plugin/templates/help.html @@ -0,0 +1,360 @@ + + + + + + I2P Firefox | HELP + + + + + +
+ +
+ + + diff --git a/plugin/templates/index.html b/plugin/templates/index.html new file mode 100644 index 0000000..ddf6d83 --- /dev/null +++ b/plugin/templates/index.html @@ -0,0 +1,25 @@ + + + + + + + I2P Firefox + + + + + +
+
+ i2pfirefox + $B32 +
+
+ + + diff --git a/plugin/templates/jetty.xml b/plugin/templates/jetty.xml new file mode 100644 index 0000000..ad56ae7 --- /dev/null +++ b/plugin/templates/jetty.xml @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 20 + 3 + 60000 + + + 50 + + + 4 + 20 + 60000 + true + I2PFirefox Jetty + + + + + + + + + + + + + + + + + 1 + 0 + + + + + + + false + true + + + + + + + 127.0.0.1 + 7662 + 600000 + + + + + + + + + + + + + + + + + + + + true + false + requestedPath + + + + + /help + /help.html + + + + + /help/ + /help.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern + .*/.*jsp-api-[^/]*\.jar$|.*/.*jsp-[^/]*\.jar$|.*/.*taglibs[^/]*\.jar$ + + + + + + + + + + + + + + + + + + + + + $PLUGIN/contexts + 120 + + + + + + + + + + + + + + + + + + + + + + + $PLUGIN/eepsite/webapps + false + false + $PLUGIN/etc/webdefault.xml + + + + + + + + + + + + + + + + + + + + + + + + + $PLUGIN/eepsite/logs/yyyy_mm_dd.request.log + yyyy_MM_dd + 90 + true + false + false + GMT + + + + + + + + true + 1000 + + diff --git a/scripts/build.number b/scripts/build.number new file mode 100644 index 0000000..0994948 --- /dev/null +++ b/scripts/build.number @@ -0,0 +1,3 @@ +#Build Number for ANT. Do not edit! +#Sun Aug 07 01:58:20 EDT 2022 +build.number=24 diff --git a/scripts/favicon.png b/scripts/favicon.png new file mode 100644 index 0000000..ae712dc Binary files /dev/null and b/scripts/favicon.png differ diff --git a/scripts/firefox-purple.css b/scripts/firefox-purple.css new file mode 100644 index 0000000..232af94 --- /dev/null +++ b/scripts/firefox-purple.css @@ -0,0 +1,235 @@ +/* I2P Firefox theme (purrrrple) */ +/* Author: dr|z3d 2019 */ + +html, body { + margin: 0; + padding: 0; + min-height: 100%; + color: #fef; + background: #111; + font-size: 14pt; + font-family: "Droid Sans", "Open Sans", "Noto Sans", Ubuntu, "Segoe UI", "Lucida Grande", Verdana, Helvetica, sans-serif; + +} + +@supports (background-blend-mode: overlay) { + html, body { + background: repeating-linear-gradient(45deg, #313, #000 2px, #000 3px), repeating-linear-gradient(135deg, #414, #313 2px, #212 3px); + background-blend-mode: overlay, normal; + background-size: 100% 100%, 100% 100%; + background-attachment: fixed; + } +} + +#container { + padding: 2%; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + display: table; + text-align: center; + box-sizing: border-box; +} + +#panel { + padding: 20px; + position: relative; + display: table-cell; + vertical-align: middle; + text-align: center; + border: 1px solid #535; + box-shadow: inset 0 0 0 1px #111, inset 0 0 2px 1px #444, 0 0 2px 2px #000; + background: #180618; + background: repeating-linear-gradient(to right, rgba(255, 200, 255, .05), rgba(0, 0, 0, .08) 2px), repeating-linear-gradient(to bottom, #212, #101 2px); /* purple */ + background-blend-mode: overlay; + will-change: transform; +} + +code { + font-family: "Droid Sans Mono", "Noto Mono", "DejaVu Sans Mono", "Lucida Console", monospace; +} + +#sitename, #sitename:hover, #sitename:focus { + margin: 0 auto; + font-size: 10em; + font-weight: bold; + text-transform: uppercase; + line-height: 1; + letter-spacing: .05em; + transition: ease background .3s; + color: #731; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +#stats #sitename, #stats #sitename:hover, #stats #sitename:focus { + font-size: 8em; +} + +#sitename:hover, #sitename:focus { + color: #951; +} + +@supports (-webkit-text-stroke-width: 1px) { + #sitename, #sitename:hover, #sitename:focus { + background: #731; + background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .2), rgba(0, 0, 0, .5) 2px), linear-gradient(to bottom, rgba(255, 96, 0, .2), rgba(0, 0, 0, .9) 100%), linear-gradient(to bottom, #414, #313 15%, #fff 50%, #313 80%); + -moz-background-clip: text !important; + -webkit-background-clip: text !important; + background-clip: text !important; + -moz-text-fill-color: transparent !important; + -webkit-text-fill-color: transparent !important; + text-fill-color: transparent !important; + filter: hue-rotate(0) drop-shadow(0 0 2px #181818) drop-shadow(0 3px 0.01em #000); + -webkit-text-stroke-color: #fef; + -webkit-text-stroke-width: 0.02em; + animation: ease-in-out spinwash 120s alternate infinite; + mix-blend-mode: soft-light; + } + + #sitename:hover, #sitename:focus { + background: #951; + background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .2), rgba(0, 0, 0, .3) 2px), linear-gradient(to bottom, rgba(255, 255, 255, .2), rgba(0, 0, 0, .95)), linear-gradient(to bottom, #d59, #a39 15%, #fff 50%, #839 70%, #000); + filter: drop-shadow(0 0 0.02em #f00); + -webkit-text-stroke-color: #fef; + opacity: .5; + mix-blend-mode: normal; + background-blend-mode: overlay; + animation: none; + } +} + +@keyframes spinwash { + from { + background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .2), rgba(0, 0, 0, .3) 2px), linear-gradient(45deg, rgba(64,16,64,.1), rgba(16,0,16,.2)), linear-gradient(to bottom, rgba(255, 255, 255, .2), rgba(0, 0, 0, .7) 100%), linear-gradient(to bottom, #930, #d50 15%, #fff 50%, #930 80%, #000 100%, #ff0 150%); + filter: sepia(0) hue-rotate(0) drop-shadow(0 0 2px #181818) drop-shadow(0 3px 0.01em #000); + } + to { + background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .2), rgba(0, 0, 0, .3) 2px), linear-gradient(45deg, rgba(16,0,16,.1), rgba(64,16,64,.2)), linear-gradient(to bottom, rgba(255, 255, 255, .2), rgba(0, 0, 0, .7) 100%), linear-gradient(to bottom, #930, #d50 15%, #fff 50%, #930 80%, #000 100%, #ff0 150%); + filter: sepia(0) hue-rotate(1440deg) drop-shadow(0 0 2px #181818) drop-shadow(0 3px 0.01em #000); + } +} + +a, a:visited { + color: #f60; + text-decoration: none; + outline: none; +} + +a:hover, a:focus { + color: #f90; +} + +hr { + margin: 20px 10px; + height: 1px; + color: transparent; + border: none; + background: #555; + background: linear-gradient(to right, rgba(0, 0, 0, 0), #535, rgba(0, 0, 0, 0)); +} + +::selection, +::-moz-selection { + text-shadow: none; + background: #515; + color: #fff; +} + +#totals { + padding-top: 6px; + line-height: 140%; + text-shadow: 0 1px 1px #000; +} + +#footer { + padding: 4px; + position: absolute; + bottom: 0; + left: 0; + right: 0; + font-size: 11pt; + font-weight: bold; + border-top: 1px solid #535; + box-shadow: inset 0 0 0 1px #000, inset 0 0 2px 1px #333; + background: rgba(16, 0, 16, .5); + -moz-user-select: all; + -webkit-user-select: all; + user-select: all; +} + +#footer.version { + font-size: 9.5pt; +} + +#footer.version a { + margin: 0 1px 0 2px; +} + +#footer.version::before { + margin-left: -10px; + content: ""; + display: inline-block; + margin-top: 1px; + width: 20px; + height: 18px; + vertical-align: middle; + background: url(/favicon.png) left top no-repeat; + background-size: 16px 16px; + filter: hue-rotate(-110deg) saturate(.4) brightness(1.4); +} + +#initializing::before { + margin-left: -20px; + content: ""; + display: inline-block; + width: 28px; + height: 24px; + vertical-align: text-bottom; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABRhJREFUeNq0Vd1vk1UYP+f9bruPrmu70W1lrLKJzE0o+BEFt4yLRZJpgl4YZ6IXhiuT/Slcqlw6QyIauNEYIhHlAgMrJDjUDQejdF3Xj7Xv24/3+xyf01LWOpArTvLr6XnOOc/X7znPiyml6HkOgf28+cXDxwLMcYgDsBljHAS8AeJjgDFAGMAByoAk4Ddw8GdAihKCmLMcz7N7s7CXu/JpOCE8xbAXMC0KaGYwLMeG9yj7ujuEPkXmAiDnDZNYasUx1jeNqVTWOG3Z6CLIzwK2AfNgaOGRniNPMtADB+ZiEXl8Yn9nTOD4AcMgnXoVydUy4R4FKXtFQT482tU98YIvcvtuuf+fhzUW6RXiuvMfn4zEv/4hnXicIhA209MlYDrz6rg/Gu33BlWViLbtPDW/lQpBoojlw2Pdw8Fu0Xd9uRh9/8TAIU0jiDjODgcuLCBvEqY0fnQyEOzrUXybmzZqFgDsMUWI53F97boU2Tat71sWQrUaRn0BJXRqJhJKpy3U3S3AGXfHAAGCQEn0xeFOPyj3bm5a9ctMsSxjkteqhdRWNV8qWyxFnL9TUgb7fIFgl7fXNCnPzqbTO5FacMxtjQBSJMsSHz4w4vekUnrdQ6Zc8WDnxp+5B4WSsQqCH+HoHRZQxrQnMrnKh71+5fgro6GYoVOptdwtC7cbcGy7JzbUIWsli9drdqOMfDxZupNNbavGZSi975nBJl9w+VdYD23l7COel/sktWi0cWOZHNPZxkHXUL9Pym2V4T+lmMNORrdT2Xx5GRTVlZt6DYJohM7z/DwsFk4eG4kn10u7yDcNuisCiSOE08t19/OixOfXN0oaHPqdUoKqmlo/LCkeNs06jrMwNx2Lq0WoXWl3dVHi/CcCWDimqVpGTW2sOVRUa1XXJduu20KeriNBFHMs3xcu/Z14RpdItEbw+cXLq/Fn9RVK6GkovwSk7EhTBpyIHIdfOjDY6WvKIgM96NK1da2Vg/hHHxz6XwPfnL/FPAoxkiVFqZMNqQKjJNDhk4dtjLtY9cGwq7arurajtUaAdIugm8vpXYoPj0fQt98tMa/PQBP8yTZNVCmVkCBJjGz2+o+HwsFxmxd4m7oFxmFZtwnotNo4qDoUGbzYpnxyfxCdO3ctAX6dgeWiY1moJTUICvdUj987HR7slZPZSg7xHPbKAtpIFyzISksEEGqFYKQL8mMFPkVAEJTlD/i8+az6FqSC9fTbjArAQSD6HdgbfW3qoLyypRead30y56aSOdOxnWJbBJrLI13cMaBDKyEqlV6fjY9m7m323l/deLuU19iLIv5gF9k3OoD7R/aQv7JmfhvuIpFHHTKP0itrulHVs5BSs63ZlVHDQCwgoZTmINMhaAMyks+4/N7IQDg+ujfcIXH17FQsUs5UnOLVjF0wHZDBPVngkJHZqKVXH5SAl2Tz5TcMQD41JKJQQEQ3Fy/c6j06OYijwyGd8cLyojKw7ui2MAQKMLwyoM0jQO9JrldTN/7IU1bGlFqo1QDr3RUsoNTZxQRsLG5dvT7lGytMipMTewzFK0MwT/7egvOKUbP1pdv56spaEu5eBu815O44gtmrFN/9aulR42eluAiyAJD6GZbl9+ThaB8fGwlQf49CPR7WGFys69u4VNxy1+7dN9eTa9Q0meJfADX2uWsO4/wnDQPC3JdxmEOsztlHm8lYGcI8COdOAI4DooBOFjAgC1gBXAVcg3znucabQE808DzHvwIMALq5vhJjsCXwAAAAAElFTkSuQmCC") center center no-repeat; + background-size: 16px 16px; + filter: hue-rotate(90deg) saturate(.6); + animation: spin linear 3s forwards infinite; +} + +@keyframes spin { + from { + transform: rotate(0) + } + to { + transform: rotate(360deg) + } +} + +@media screen and (max-height: 600px) { + #container { + padding: 1%; + } +} + +@media screen and (max-width: 1000px) { + html, body { + font-size: 12pt; + } + #container { + padding: 1%; + } + #sitename, #sitename:hover, #sitename:focus { + font-size: 8em; + } + #stats #sitename, #stats #sitename:hover, #stas #sitename:focus { + font-size: 6em; + } + #footer.b32 { + font-size: 10pt; + } + #footer.version { + font-size: 8.5pt; + } + #initializing::before { + height: 20px; + } +} diff --git a/scripts/firefox.css b/scripts/firefox.css new file mode 100644 index 0000000..cf818f0 --- /dev/null +++ b/scripts/firefox.css @@ -0,0 +1,247 @@ +/* I2P Firefox theme */ +/* Author: dr|z3d 2019 */ + +html, body { + margin: 0; + padding: 0; + min-height: 100%; + color: #bbb; + background: #111; + font-size: 14pt; + font-family: "Droid Sans", "Open Sans", "Noto Sans", Ubuntu, "Segoe UI", "Lucida Grande", Verdana, Helvetica, sans-serif; +} + +@supports (background-blend-mode: overlay) { + html, body { + background: repeating-linear-gradient(45deg, #333, #111 2px, #111 3px), + repeating-linear-gradient(135deg, #444, #333 2px, #222 3px); + background-blend-mode: overlay, normal; + background-size: 100% 100%, 100% 100%; + background-attachment: fixed; + } +} + +#container { + padding: 2%; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + display: table; + text-align: center; + box-sizing: border-box; +} + +#panel { + padding: 20px; + position: relative; + display: table-cell; + vertical-align: middle; + text-align: center; + border: 1px solid #555; + box-shadow: inset 0 0 0 1px #111, inset 0 0 2px 1px #444, 0 0 2px 2px #000; + background: #181818; + background: repeating-linear-gradient(to right, rgba(255, 255, 255, .05), rgba(0, 0, 0, .08) 2px), + repeating-linear-gradient(to bottom, #222, #111 2px); + background-blend-mode: overlay; + will-change: transform; +} + +code { + font-family: "Droid Sans Mono", "Noto Mono", "DejaVu Sans Mono", "Lucida Console", monospace; +} + +#sitename, #sitename:hover, #sitename:focus { + margin: 0 auto; + font-size: 10em; + font-weight: bold; + text-transform: uppercase; + line-height: 1; + letter-spacing: .05em; + transition: ease background .3s; + color: #731; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +#stats #sitename, #stats #sitename:hover, #stats #sitename:focus { + font-size: 8em; +} + +#sitename:hover, #sitename:focus { + color: #951; +} + +@supports (-webkit-text-stroke-width: 1px) { + #sitename, #sitename:hover, #sitename:focus { + background: #731; + background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .2), rgba(0, 0, 0, .5) 2px), + linear-gradient(to bottom, rgba(255, 96, 0, .2), rgba(0, 0, 0, .9) 100%), + linear-gradient(to bottom, #210, #310 15%, #fff 50%, #310 80%); + -moz-background-clip: text !important; + -webkit-background-clip: text !important; + background-clip: text !important; + -moz-text-fill-color: transparent !important; + -webkit-text-fill-color: transparent !important; + text-fill-color: transparent !important; + filter: drop-shadow(0 0 2px #000); + -webkit-text-stroke-color: #999; + -webkit-text-stroke-width: 0.02em; + animation: ease-in-out spinwash 60s 15s forwards infinite; + } + + #sitename:hover, #sitename:focus { + background: #951; + background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .2), rgba(0, 0, 0, .3) 2px), + linear-gradient(to bottom, rgba(255, 255, 255, .2), rgba(0, 0, 0, .7) 100%), + linear-gradient(to bottom, #930, #d50 15%, #fff 50%, #930 80%, #000 100%, #ff0 150%); + filter: drop-shadow(0 0 2px #b00); + -webkit-text-stroke-color: #bbb; + animation: none; + } +} + +@keyframes spinwash { + from { + filter: hue-rotate(0) drop-shadow(0 0 2px #000); + } + to { + filter: hue-rotate(360deg) drop-shadow(0 0 2px #000); + } +} + +a, a:visited { + font-weight: bold; + color: #c4ad9d; + text-decoration: none; + outline: none; +} + +a:hover, a:focus { + color: #e88b44; +} + +a:active { + color: #f60; +} + +hr { + margin: 20px 10px; + height: 1px; + color: transparent; + border: none; + background: #555; + background: linear-gradient(to right, rgba(0,0,0,0) 35%, rgba(255,255,255,.3), rgba(0,0,0,0) 65%), + linear-gradient(to right, rgba(0, 0, 0, 0), #605555, rgba(0, 0, 0, 0)); +} + +::selection, +::-moz-selection { + text-shadow: none; + background: #431; + color: #fff; +} + +#totals { + padding-top: 6px; + line-height: 140%; + text-shadow: 0 1px 1px #000; +} + +#footer { + padding: 4px; + position: absolute; + bottom: 0; + left: 0; + right: 0; + font-size: 11pt; + font-weight: bold; + border-top: 1px solid #555; + box-shadow: inset 0 0 0 1px #000, inset 0 0 2px 1px #333; + background: rgba(0, 0, 0, .5); + -moz-user-select: all; + -webkit-user-select: all; + user-select: all; +} + +#footer.version { + padding: 4px; + line-height: 19px; + font-size: 9.5pt; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +#footer.version a { + margin: 0 1px 0 2px; +} + +#footer.version::before { + margin-left: -10px; + content: ""; + display: inline-block; + margin-top: 1px; + width: 20px; + height: 18px; + vertical-align: middle; + background: url(/favicon.png) left top no-repeat; + background-size: 16px 16px; + mix-blend-mode: luminosity; +} + +#initializing::before { + margin-left: -20px; + content: ""; + display: inline-block; + width: 28px; + height: 24px; + vertical-align: text-bottom; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABRhJREFUeNq0Vd1vk1UYP+f9bruPrmu70W1lrLKJzE0o+BEFt4yLRZJpgl4YZ6IXhiuT/Slcqlw6QyIauNEYIhHlAgMrJDjUDQejdF3Xj7Xv24/3+xyf01LWOpArTvLr6XnOOc/X7znPiyml6HkOgf28+cXDxwLMcYgDsBljHAS8AeJjgDFAGMAByoAk4Ddw8GdAihKCmLMcz7N7s7CXu/JpOCE8xbAXMC0KaGYwLMeG9yj7ujuEPkXmAiDnDZNYasUx1jeNqVTWOG3Z6CLIzwK2AfNgaOGRniNPMtADB+ZiEXl8Yn9nTOD4AcMgnXoVydUy4R4FKXtFQT482tU98YIvcvtuuf+fhzUW6RXiuvMfn4zEv/4hnXicIhA209MlYDrz6rg/Gu33BlWViLbtPDW/lQpBoojlw2Pdw8Fu0Xd9uRh9/8TAIU0jiDjODgcuLCBvEqY0fnQyEOzrUXybmzZqFgDsMUWI53F97boU2Tat71sWQrUaRn0BJXRqJhJKpy3U3S3AGXfHAAGCQEn0xeFOPyj3bm5a9ctMsSxjkteqhdRWNV8qWyxFnL9TUgb7fIFgl7fXNCnPzqbTO5FacMxtjQBSJMsSHz4w4vekUnrdQ6Zc8WDnxp+5B4WSsQqCH+HoHRZQxrQnMrnKh71+5fgro6GYoVOptdwtC7cbcGy7JzbUIWsli9drdqOMfDxZupNNbavGZSi975nBJl9w+VdYD23l7COel/sktWi0cWOZHNPZxkHXUL9Pym2V4T+lmMNORrdT2Xx5GRTVlZt6DYJohM7z/DwsFk4eG4kn10u7yDcNuisCiSOE08t19/OixOfXN0oaHPqdUoKqmlo/LCkeNs06jrMwNx2Lq0WoXWl3dVHi/CcCWDimqVpGTW2sOVRUa1XXJduu20KeriNBFHMs3xcu/Z14RpdItEbw+cXLq/Fn9RVK6GkovwSk7EhTBpyIHIdfOjDY6WvKIgM96NK1da2Vg/hHHxz6XwPfnL/FPAoxkiVFqZMNqQKjJNDhk4dtjLtY9cGwq7arurajtUaAdIugm8vpXYoPj0fQt98tMa/PQBP8yTZNVCmVkCBJjGz2+o+HwsFxmxd4m7oFxmFZtwnotNo4qDoUGbzYpnxyfxCdO3ctAX6dgeWiY1moJTUICvdUj987HR7slZPZSg7xHPbKAtpIFyzISksEEGqFYKQL8mMFPkVAEJTlD/i8+az6FqSC9fTbjArAQSD6HdgbfW3qoLyypRead30y56aSOdOxnWJbBJrLI13cMaBDKyEqlV6fjY9m7m323l/deLuU19iLIv5gF9k3OoD7R/aQv7JmfhvuIpFHHTKP0itrulHVs5BSs63ZlVHDQCwgoZTmINMhaAMyks+4/N7IQDg+ujfcIXH17FQsUs5UnOLVjF0wHZDBPVngkJHZqKVXH5SAl2Tz5TcMQD41JKJQQEQ3Fy/c6j06OYijwyGd8cLyojKw7ui2MAQKMLwyoM0jQO9JrldTN/7IU1bGlFqo1QDr3RUsoNTZxQRsLG5dvT7lGytMipMTewzFK0MwT/7egvOKUbP1pdv56spaEu5eBu815O44gtmrFN/9aulR42eluAiyAJD6GZbl9+ThaB8fGwlQf49CPR7WGFys69u4VNxy1+7dN9eTa9Q0meJfADX2uWsO4/wnDQPC3JdxmEOsztlHm8lYGcI8COdOAI4DooBOFjAgC1gBXAVcg3znucabQE808DzHvwIMALq5vhJjsCXwAAAAAElFTkSuQmCC") center center no-repeat; + background-size: 16px 16px; + filter: hue-rotate(180deg) saturate(.6); + animation: spin linear 3s forwards infinite; +} + +@keyframes spin { + from { + transform: rotate(0) + } + to { + transform: rotate(360deg) + } +} + +@media screen and (max-height: 600px) { + #container { + padding: 1%; + } +} + +@media screen and (max-width: 1000px) { + html, body { + font-size: 12pt; + } + #container { + padding: 1%; + } + #sitename, #sitename:hover, #sitename:focus { + font-size: 8em; + } + #stats #sitename, #stats #sitename:hover, #stas #sitename:focus { + font-size: 6em; + } + #footer.b32 { + font-size: 10pt; + } + #footer.version { + margin-top: 0; + line-height: 18px; + font-size: 8.5pt; + } + #initializing::before { + height: 20px; + } +} diff --git a/scripts/i2pfirefox.config b/scripts/i2pfirefox.config new file mode 100644 index 0000000..af8e7a4 --- /dev/null +++ b/scripts/i2pfirefox.config @@ -0,0 +1,3 @@ +# announce interval in seconds +# minimum 900 (15 minutes), maximum 21600 (6 hours) +interval=1620 diff --git a/scripts/i2ptunnel.config b/scripts/i2ptunnel.config new file mode 100644 index 0000000..4816bc2 --- /dev/null +++ b/scripts/i2ptunnel.config @@ -0,0 +1,41 @@ +configFile=/home/idk/.i2p/i2ptunnel.config.d/00-I2P HTTP Proxy-i2ptunnel.config +description=HTTP proxy for browsing eepsites and the web +interface=127.0.0.1 +listenPort=7695 +name=I2P HTTP Proxy for Browsing Only +option.i2cp.closeIdleTime=1800000 +option.i2cp.closeOnIdle=true +option.i2cp.delayOpen=false +option.i2cp.destination.sigType=7 +option.i2cp.leaseSetEncType=4,0 +option.i2cp.newDestOnResume=true +option.i2cp.reduceIdleTime=900000 +option.i2cp.reduceOnIdle=true +option.i2cp.reduceQuantity=1 +option.i2p.streaming.connectDelay=0 +option.i2ptunnel.httpclient.SSLOutproxies=exit.stormycloud.i2p +option.i2ptunnel.httpclient.allowInternalSSL=true +option.i2ptunnel.httpclient.jumpServers=http://stats.i2p/cgi-bin/jump.cgi?a=,http://i2pjump.i2p/jump/,http://notbob.i2p/cgi-bin/jump.cgi?q= +option.i2ptunnel.httpclient.sendAccept=false +option.i2ptunnel.httpclient.sendReferer=false +option.i2ptunnel.httpclient.sendUserAgent=false +option.i2ptunnel.useLocalOutproxy=false +option.inbound.backupQuantity=3 +option.inbound.length=1 +option.inbound.lengthVariance=0 +option.inbound.nickname=shared clients +option.inbound.quantity=3 +option.outbound.backupQuantity=3 +option.outbound.length=1 +option.outbound.lengthVariance=0 +option.outbound.nickname=shared clients +option.outbound.priority=10 +option.outbound.quantity=3 +option.outproxyAuth=false +option.persistentClientKey=false +option.sslManuallySet=true +option.useSSL=false +proxyList=exit.stormycloud.i2p +sharedClient=true +startOnLoad=true +type=httpclient diff --git a/scripts/makeplugin.sh b/scripts/makeplugin.sh new file mode 100755 index 0000000..ed055a6 --- /dev/null +++ b/scripts/makeplugin.sh @@ -0,0 +1,147 @@ +#!/bin/sh +# +# basic packaging up of a plugin +# +# usage: makeplugin.sh plugindir +# +# zzz 2010-02 +# zzz 2014-08 added support for su3 files +# + +if [ -z "$I2P" -a -d "$PWD/../i2p.i2p/pkg-temp" ]; then + export I2P=../i2p.i2p/pkg-temp +fi + +if [ ! -d "$I2P" ]; then + echo "Can't locate your I2P installation. Please add a environment variable named I2P with the path to the folder as value" + echo "On OSX this solved with running: export I2P=/Applications/i2p if default install directory is used." + exit 1 +fi + +PUBKEYDIR=$HOME/.i2p-plugin-keys +PUBKEYFILE=$PUBKEYDIR/plugin-public-signing.key +PRIVKEYFILE=$PUBKEYDIR/plugin-private-signing.key +B64KEYFILE=$PUBKEYDIR/plugin-public-signing.txt +PUBKEYSTORE=$PUBKEYDIR/plugin-su3-public-signing.crt +PRIVKEYSTORE=$PUBKEYDIR/plugin-su3-keystore.ks +KEYTYPE=RSA_SHA512_4096 + +PLUGINDIR=${1:-plugin} + +PC=plugin.config +PCT=${PC}.tmp + +if [ ! -d $PLUGINDIR ] +then + echo "You must have a $PLUGINDIR directory" + exit 1 +fi + +if [ ! -f $PLUGINDIR/$PC ] +then + echo "You must have a $PLUGINDIR/$PC file" + exit 1 +fi + +SIGNER=`grep '^signer=' $PLUGINDIR/$PC` +if [ "$?" -ne "0" ] +then + echo "You must have a plugin name in $PC" + echo 'For example name=foo' + exit 1 +fi +SIGNER=`echo $SIGNER | cut -f 2 -d '='` + +if [ ! -f $PRIVKEYFILE ] +then + echo "Creating new XPI2P DSA keys" + mkdir -p $PUBKEYDIR || exit 1 + java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate keygen $PUBKEYFILE $PRIVKEYFILE || exit 1 + java -cp $I2P/lib/i2p.jar net.i2p.data.Base64 encode $PUBKEYFILE $B64KEYFILE || exit 1 + rm -rf logs/ + chmod 444 $PUBKEYFILE $B64KEYFILE + chmod 400 $PRIVKEYFILE + echo "Created new XPI2P keys: $PUBKEYFILE $PRIVKEYFILE" +fi + +if [ ! -f $PRIVKEYSTORE ] +then + echo "Creating new SU3 $KEYTYPE keys for $SIGNER" + java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File keygen -t $KEYTYPE $PUBKEYSTORE $PRIVKEYSTORE $SIGNER || exit 1 + echo '*** Save your password in a safe place!!! ***' + rm -rf logs/ + # copy to the router dir so verify will work + CDIR=$I2P/certificates/plugin + mkdir -p $CDIR || exit 1 + CFILE=$CDIR/`echo $SIGNER | sed s/@/_at_/`.crt + cp $PUBKEYSTORE $CFILE + chmod 444 $PUBKEYSTORE + chmod 400 $PRIVKEYSTORE + chmod 644 $CFILE + echo "Created new SU3 keys: $PUBKEYSTORE $PRIVKEYSTORE" + echo "Copied public key to $CFILE for testing" +fi + +rm -f plugin.zip + +OPWD=$PWD +cd $PLUGINDIR + +grep -q '^name=' $PC +if [ "$?" -ne "0" ] +then + echo "You must have a plugin name in $PC" + echo 'For example name=foo' + exit 1 +fi + +grep -q '^version=' $PC +if [ "$?" -ne "0" ] +then + echo "You must have a version in $PC" + echo 'For example version=0.1.2' + exit 1 +fi + +# update the date +grep -v '^date=' $PC > $PCT +DATE=`date '+%s000'` +echo "date=$DATE" >> $PCT +mv $PCT $PC || exit 1 + +# add our Base64 key +grep -v '^key=' $PC > $PCT +B64KEY=`cat $B64KEYFILE` +echo "key=$B64KEY" >> $PCT || exit 1 +mv $PCT $PC || exit 1 + +# zip it +zip -r $OPWD/plugin.zip * || exit 1 + +# get the version and use it for the sud header +VERSION=`grep '^version=' $PC | cut -f 2 -d '='` +# get the name and use it for the file name +NAME=`grep '^name=' $PC | cut -f 2 -d '='` +XPI2P=${NAME}.xpi2p +SU3=${NAME}.su3 +cd $OPWD + +# sign it +echo 'Signing. ...' +java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate sign plugin.zip $XPI2P $PRIVKEYFILE $VERSION || exit 1 +java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File sign -c PLUGIN -t $KEYTYPE plugin.zip $SU3 $PRIVKEYSTORE $VERSION $SIGNER || exit 1 +rm -f plugin.zip + +# verify +echo 'Verifying. ...' +java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate showversion $XPI2P || exit 1 +java -cp $I2P/lib/i2p.jar -Drouter.trustedUpdateKeys=$B64KEY net.i2p.crypto.TrustedUpdate verifysig $XPI2P || exit 1 +java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File showversion $SU3 || exit 1 +java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File verifysig -k $PUBKEYSTORE $SU3 || exit 1 +rm -rf logs/ + +echo 'Plugin files created: ' +wc -c $XPI2P +wc -c $SU3 + +exit 0 diff --git a/scripts/plugin.config b/scripts/plugin.config new file mode 100644 index 0000000..0f6fcb6 --- /dev/null +++ b/scripts/plugin.config @@ -0,0 +1,14 @@ +name=i2pfirefox +signer=idki2p@mail.i2p +consoleLinkName=I2PFirefox +consoleLinkURL=http://127.0.0.1:7662/firefox/ +consoleLinkTooltip=Firefox process manager for I2P +icon-code=iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABm1BMVEUAAAAZGRkZGRkaGhoZGRkZGRkZGRkZGRkYGBgZGRkYGBgZGRkYGBgZGRkZGRkXFxcYGBgZGRkZGRkZGRkZGRkAAAAZGRnziRYTExPzfhbzbhbzdxbzgxbzlRYLCwvzjhbzcxbMzMzzkBb~~~~~~Pl0dHRdXV3GxsYnJyfe3t7OycbBwcGcnJyHh4cjEgP39~f96dSurq5~f397e3tra2tlZWU7OzseHh7haRSGSAsOBwGpqKeWlpbgpnRUVFRNTU00NDTxmynPbRJwNgpXLwdEJQY4IAUVCwLy8vL83sK7u7uysrL7yqf6v5Tdr4H4t3H4rGz2pEvnjUnqnkQvLy~zii30gyjxdCLqdhXLexK9bhGQTQ1-QAtlLgn-9u~Pxr7Uvqr71KbYuJz6yZn5v4T3pVv3s1rkmVr1nzr1kzLyjiPzex~pbBXJYxLJXRK~XxG4aBCYRQ5iNQlMKgctGgT7-~vas4zhnGj2qlNERETlhRTefxTedRTVfxOsZhC0YBC4UhCpWw9wQgr4sH~kqF7sizVpSyfWXxOZVw56Yx8pAAAAFXRSTlMAjPQOr8vV7eVwaVtPNyUa27WCwoZvol0xAAAEx0lEQVRYw72XZ1PbQBCGXQEnVMNJAjtyjpPcbWxsMB2SQOg1tCT0EiA9kN578rOzd4eQZUuO8iXPjGfkmdv3dm-v7DqsaKht8XhrBKDG6~HXNjj-iTpnlVBClbPOrrXb18htJElmSNK5hs9tx9zp4saCXOgOq6qaH-qWkCQzEZf~rxKXqvnU0c6pCUKIohDKREKNckeqL1U0r~cyc6kzRpTJg8OTILBysji~nyEkpnKJ5npr-8suZp7sUHbvXTFybX6SvEhKVMJ12creSaeXUx1bB6utJqzsKx0pthZOc3sPnX4kpsw-uNozmr5xtZzVGRIboU54zOyb6PQ5kjkWxbdphNBd0YTFDFGpE03m88v9ZD8Ew04R8Fw0I7RLsrKZD05qH1EWqKePEUNz~GGPIY4FMkUVnCXrT-2nlMNWyhhirLM~66MIpZ-0FnGoJKjCZUP-XWCfJTx3txHnNvt3hoBxQ0rvKf2g4CreD83ggErmg4xRxPkUBE7ZZ1~QwALJgQveov0L9iNkpo3Rg855Bn82-Odmm5FZMgIKF7vaXQ0BxDIil7-rCWzo39eDRsRMDIKo1k6WHxxIkcV2TloTGG3~iDjP20s5VlJ6JtywglLHTIDzCHHo2mtfvYEyZjskWEfugg8cSCqrAc4NdEGf9tFTLvBgKwku-JhAFazAi93QOeOojLGQCQfUhUZ2~7EUnoicp6icL6IJ95VOcKGOb2I5NqklaBOZkN589ritlJmYDMvII4iSBW2f9iErxt63GlgkURZDAzigkmtXOHeQNaNXjLAYGhy1sASJjCZ7iiqwbnRhcgoup1pHiyCgiVktMMsI-N428G0C0UVogl1E5kWOdQQmV8xrIkhwsXgFqZu8DnG-oop8CBVzTLolOJI1gjxEVq5yxlFFjBdtgIRlocYBSciTVf0cVOTs7qOAjqLCTnCwLLZzepENbn79-JYP39IEwttBThrZ5IwNx2FNIM7z8gvZ5jMMX8NDIEAXcRgHGbYi0O~LFfwGFpGmcRnznTyGbMJv7Ft4mabRAxsJL7VSxpFtrsPwIww3QhM9zSjxir1AyD70sRpMwFZuYYdpYI~vY~uIwE5SpoepAQS64iLw-98E7rMsQvnXKEgFvAQubSLb9MHwI1yQhKrzKy37EhblJrJNLwzfmz6~0upYDJDIPmSTsQ-0aGIRsOKzkVYGg8H3yB7jX4KUOSzzCPjD0rm99hnZ4sbDNspaPAcO-PSnLTLYa-ckbmjP7FxEpk-bXt7k8c-~GffeCV1wC-fBAX~x8z7dX3HmJ-uGl3Eny5734gIjilXruAMlzOEoLzA0vDSVeBhZ8DRk5DtLYXNpkZWKdFsJiAZu4RQrssrKvGTCQsH4si7FB1iZZ1JoDuBhq9OvcxRPskLTtNRN4Zz5~aMzx~wXPBbFdhj3Ryt58GMHd-nFtpkP0SzOSWX3TxtnbRBPR1m5X6nhyEciaonEO17UDG5H8rzhqNjyyHIO44FhuViAbt6X8Uhn5ZYHqG8WmER4GuN-dWhEYq4Ull7txXG2izdd3nobbZ8sF8LJBGZE4JcY6CrYavsAt98lcA0kLb8ZCofDw8sSor4DLqfbVutbZd76Nvrc~6P51tt~v97-t1i3~38A57d5M52iLPcAAAAASUVORK5CYII= +description=Firefox process manager for I2P +author=idk +updateURL=http://idk.i2p/i2p.plugins.firefox/plugins/i2pfirefox-update.xpi2p +updateURL.su3=http://idk.i2p/i2p.plugins.firefox/plugins/i2pfirefox-update.su3 +websiteURL=http://idk.i2p/i2p.plugins.firefox/ +license=Apache 2.0 +min-jetty-version=9 +min-i2p-version=0.9.31 diff --git a/scripts/robots.txt b/scripts/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/scripts/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/src/build.xml b/src/build.xml new file mode 100644 index 0000000..4ee0ad5 --- /dev/null +++ b/src/build.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/net/I2PFirefox.java b/src/java/net/I2PFirefox.java new file mode 100644 index 0000000..1feaa88 --- /dev/null +++ b/src/java/net/I2PFirefox.java @@ -0,0 +1,246 @@ +package net; + +import java.io.File; +import java.util.ArrayList; + +public class I2PFirefox { + private final String[] FIREFOX_SEARCH_PATHS = FIREFOX_FINDER(); + + I2PFirefox() { + for (String path : FIREFOX_SEARCH_PATHS) { + File f = new File(path); + if (f.exists()) { + System.out.println("Found Firefox at " + path); + return; + } + } + + } + + private static String[] FIND_FIREFOX_SEARCH_PATHS_UNIX(){ + String[] path = new String[]{"/usr/bin", "/usr/local/bin", "/opt/firefox/bin","/snap/bin"}; + String[] exes = new String[]{"firefox", "firefox-bin", "firefox-esr", "waterfox", "waterfox-bin", "librewolf"}; + String[] exePath = new String[path.length * exes.length]; + int i = 0; + for (String s : path) { + for (String exe : exes) { + exePath[i] = s + "/" + exe; + i++; + } + } + return exePath; + } + private static String[] FIND_FIREFOX_SEARCH_PATHS_OSX() { + String[] path = new String[]{"/Applications/Firefox.app/Contents/MacOS/", "/Applications/Waterfox.app/Contents/MacOS/", "/Applications/Librewolf.app/Contents/MacOS/"}; + String[] exes = new String[]{"firefox", "firefox-bin", "firefox-esr", "waterfox", "waterfox-bin", "librewolf"}; + String[] exePath = new String[path.length * exes.length]; + int i = 0; + for (String s : path) { + for (String exe : exes) { + exePath[i] = s + "/" + exe; + i++; + } + } + return exePath; + } + private static String[] FIND_FIREFOX_SEARCH_PATHS_WINDOWS() { + String[] path = new String[]{"C:/Program Files/Mozilla Firefox/", "C:/Program Files (x86)/Mozilla Firefox/", "C:/Program Files/Waterfox/", "C:/Program Files (x86)/Waterfox/", "C:/Program Files/Librewolf/"}; + String[] exes = new String[]{"firefox.exe", "firefox-bin.exe", "firefox-esr.exe", "waterfox.exe", "waterfox-bin.exe", "librewolf.exe"}; + String[] exePath = new String[path.length * exes.length]; + int i = 0; + for (String s : path) { + for (String exe : exes) { + exePath[i] = s + exe; + i++; + } + } + return exePath; + } + + private static String[] FIND_ALL_FIREFOX_SEARCH_PATHS() { + String[] Unix = FIND_FIREFOX_SEARCH_PATHS_UNIX(); + String[] Windows = FIND_FIREFOX_SEARCH_PATHS_WINDOWS(); + String[] Mac = FIND_FIREFOX_SEARCH_PATHS_OSX(); + String[] exePath = new String[Unix.length + Windows.length + Mac.length]; + int i = 0; + for (String s : Unix) { + exePath[i] = s; + i++; + } + for (String s : Windows) { + exePath[i] = s; + i++; + } + for (String s : Mac) { + exePath[i] = s; + i++; + } + return exePath; + } + + private static String[] FIND_FIREFOX_SEARCH_PATHS() { + switch (getOperatingSystem()) { + case "Windows": + return FIND_FIREFOX_SEARCH_PATHS_WINDOWS(); + case "Linux": + return FIND_FIREFOX_SEARCH_PATHS_UNIX(); + case "Mac": + return FIND_FIREFOX_SEARCH_PATHS_OSX(); + case "BSD": + return FIND_FIREFOX_SEARCH_PATHS_UNIX(); + default: + return FIND_ALL_FIREFOX_SEARCH_PATHS(); + } + } + + private static String[] NEARBY_FIREFOX_SEARCH_PATHS() { + // obtain the PLUGIN environment variable + String plugin = System.getenv("PLUGIN"); + // search the plugin directory for anything named "firefox", "firefox-bin", "firefox-esr", "waterfox", "waterfox-bin", "librewolf" + // up to a depth of 2 directories deep. + // list the directories in the plugin directory + File pluginDir = new File(plugin); + if (pluginDir.exists()) { + File[] pluginDirs = pluginDir.listFiles(); + // list the files in the plugin directory + for (File pluginDir1 : pluginDirs) { + File[] pluginFiles = pluginDir1.listFiles(); + // list the files in the plugin directory + for (File pluginFile : pluginFiles) { + if (pluginFile.getName().equals("firefox") || pluginFile.getName().equals("firefox-bin") || pluginFile.getName().equals("firefox-esr") || pluginFile.getName().equals("waterfox") || pluginFile.getName().equals("waterfox-bin") || pluginFile.getName().equals("librewolf")) { + return new String[]{pluginFile.getAbsolutePath()}; + } + } + } + } + // now, do the same thing, but with user.dir instead of plugin + // list the directories in the user.dir directory + File userDir = new File(System.getProperty("user.dir")); + if (userDir.exists()) { + File[] userDirs = userDir.listFiles(); + // list the files in the user.dir directory + for (File userDir1 : userDirs) { + File[] userFiles = userDir1.listFiles(); + // list the files in the user.dir directory + for (File userFile : userFiles) { + if (userFile.getName().equals("firefox") || userFile.getName().equals("firefox-bin") || userFile.getName().equals("firefox-esr") || userFile.getName().equals("waterfox") || userFile.getName().equals("waterfox-bin") || userFile.getName().equals("librewolf")) { + return new String[]{userFile.getAbsolutePath()}; + } + } + } + } + return new String[]{}; + } + + private static String[] FIREFOX_FINDER() { + String[] nearby = NEARBY_FIREFOX_SEARCH_PATHS(); + String[] all = FIND_FIREFOX_SEARCH_PATHS(); + if (nearby.length > 0) { + return nearby; + } else if (all.length > 0) { + return all; + } else { + return new String[]{}; + } + } + + private static String getOperatingSystem() { + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + return "Windows"; + } else if (os.contains("Linux")) { + return "Linux"; + } else if (os.contains("BSD")) { + return "BSD"; + } else if (os.contains("Mac")) { + return "Mac"; + } + return "Unknown"; + } + + public String[] OnlyValidFirefoxes() { + String[] firefoxes = FIREFOX_FINDER(); + ArrayList validFirefoxes = new ArrayList(); + for (String firefox : firefoxes) { + File firefoxFile = new File(firefox); + if (firefoxFile.exists()) { + validFirefoxes.add(firefox); + } + } + return validFirefoxes.toArray(new String[validFirefoxes.size()]); + } + + public String TopFirefox() { + // get the FIREFOX environment variable + String firefox = System.getenv("FIREFOX"); + // if it is not null and not empty + if (firefox != null && !firefox.isEmpty()) { + // check if the file exists + File firefoxFile = new File(firefox); + if (firefoxFile.exists()) { + // if it does, return it + return firefox; + } + } + String[] firefoxes = OnlyValidFirefoxes(); + if (firefoxes.length > 0) { + return firefoxes[0]; + } else { + return ""; + } + } + public String TopFirefox(String overrideFirefox) { + if (overrideFirefox != null && !overrideFirefox.isEmpty()) { + File firefoxFile = new File(overrideFirefox); + if (firefoxFile.exists()) { + return overrideFirefox; + } + } + return TopFirefox(); + } + + public ProcessBuilder defaultProcessBuilder() { + return processBuilder(new String[]{}); + } + + public ProcessBuilder processBuilder(String[] args) { + String firefox = TopFirefox(); + if (!firefox.isEmpty()) { + String[] newArgs = new String[args.length+2]; + newArgs[0] = firefox; + newArgs[1] = "--profile"; + newArgs[2] = I2PFirefoxProfileBuilder.profileDirectory(); + for (int i = 0; i < args.length; i++) { + newArgs[i+3] = args[i]; + } + return new ProcessBuilder(newArgs).directory(I2PFirefoxProfileBuilder.RuntimeDirectory(true)); + } else { + return new ProcessBuilder(args); + } + } + + public static void main(String[] args) { + System.out.println("I2PFirefox"); + I2PFirefox i2pFirefox = new I2PFirefox(); + String profileDirectory = I2PFirefoxProfileBuilder.profileDirectory(); + if (I2PFirefoxProfileChecker.validateProfileDirectory(profileDirectory)) { + System.out.println("Valid profile directory: "+profileDirectory); + } else { + System.out.println("Invalid profile directory: "+profileDirectory+" rebuilding..."); + if (!I2PFirefoxProfileBuilder.CopyBaseProfiletoProfile()) { + System.out.println("Failed to rebuild profile directory: "+profileDirectory); + return; + } else { + System.out.println("Rebuilt profile directory: "+profileDirectory); + } + } + ProcessBuilder pb = i2pFirefox.defaultProcessBuilder(); + try{ + pb.start(); + }catch(Exception e){ + System.out.println("Error: "+e.getMessage()); + }finally{ + System.out.println("I2PFirefox"); + } + } +} diff --git a/src/java/net/I2PFirefoxProfileBuilder.java b/src/java/net/I2PFirefoxProfileBuilder.java new file mode 100644 index 0000000..b7db2fc --- /dev/null +++ b/src/java/net/I2PFirefoxProfileBuilder.java @@ -0,0 +1,151 @@ +package net; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; + +public class I2PFirefoxProfileBuilder { + private static boolean strict; + + private static String profileDir(String file) { + File profileDir = new File(file, "i2p.firefox.profile"); + // make sure the directory exists + if (profileDir.exists()) { + return profileDir.getAbsolutePath(); + } else { + // create the directory + profileDir.mkdir(); + return profileDir.getAbsolutePath(); + } + } + + public static String profileDirectory() { + String rtd = RuntimeDirectory(); + return profileDir(rtd); + } + + private static String baseProfileDir(String file) { + File profileDir = new File(file, "i2p.firefox.base.profile"); + // make sure the directory exists + if (profileDir.exists()) { + return profileDir.getAbsolutePath(); + } else { + // create the directory + profileDir.mkdir(); + return profileDir.getAbsolutePath(); + } + } + + public static String baseProfileDirectory() { + String rtd = RuntimeDirectory(); + return baseProfileDir(rtd); + } + + public static File RuntimeDirectory(boolean create) { + String rtd = RuntimeDirectory(); + File rtdFile = new File(rtd); + if (create) { + if (!rtdFile.exists()) { + rtdFile.mkdir(); + } + } + return new File(rtd); + } + + public static String RuntimeDirectory() { + // get the I2P_FIREFOX_DIR environment variable + String rtd = System.getenv("I2P_FIREFOX_DIR"); + // if it is not null and not empty + if (rtd != null && !rtd.isEmpty()) { + // check if the file exists + File rtdFile = new File(rtd); + if (rtdFile.exists()) { + // if it does, return it + return rtd; + } + } + // obtain the PLUGIN environment variable + String plugin = System.getenv("PLUGIN"); + if (plugin != null && !plugin.isEmpty()) { + File pluginDir = new File(plugin); + if (pluginDir.exists()) { + return pluginDir.toString(); + } + } + String userDir = System.getProperty("user.dir"); + if (userDir != null && !userDir.isEmpty()) { + File userDir1 = new File(userDir); + if (userDir1.exists()) { + return userDir1.toString(); + } + } + String homeDir = System.getProperty("user.home"); + if (homeDir != null && !homeDir.isEmpty()) { + File homeDir1 = new File(homeDir+"/.i2p"); + if (homeDir1.exists()) { + return homeDir.toString(); + } + File homeDir2 = new File(homeDir+"/i2p"); + if (homeDir2.exists()) { + return homeDir2.toString(); + } + } + return ""; + } + public static boolean CopyBaseProfiletoProfile() { + String baseProfile = baseProfileDirectory(); + String profile = profileDirectory(); + if (baseProfile.isEmpty() || profile.isEmpty()) { + return false; + } + File baseProfileDir = new File(baseProfile); + File profileDir = new File(profile); + if (!baseProfileDir.exists() || !profileDir.exists()) { + return false; + } + try { + Files.copy(baseProfileDir.toPath(), profileDir.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + System.out.println("Error copying base profile to profile"+e); + return false; + } + if (!CopyStrictOptions()){ + return false; + } + return true; + } + public static boolean CopyStrictOptions() { + if (!strict){ + return true; + } + String baseProfile = baseProfileDirectory(); + String profile = profileDirectory(); + if (baseProfile.isEmpty() || profile.isEmpty()) { + return false; + } + File baseProfileDir = new File(baseProfile); + File profileDir = new File(profile); + if (!baseProfileDir.exists() || !profileDir.exists()) { + return false; + } + File baseOverrides = new File(baseProfile, "strict-overrides.js"); + File userOverrides = new File(baseProfile, "user-overrides.js"); + if (!baseOverrides.exists()) { + return false; + } + try { + Files.copy(baseOverrides.toPath(), userOverrides.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + System.out.println("Error copying base profile to profile"+e); + return false; + } + return true; + } + + I2PFirefoxProfileBuilder() { + I2PFirefoxProfileBuilder.strict = false; + } + I2PFirefoxProfileBuilder(boolean strict) { + I2PFirefoxProfileBuilder.strict = strict; + } +} diff --git a/src/java/net/I2PFirefoxProfileChecker.java b/src/java/net/I2PFirefoxProfileChecker.java new file mode 100644 index 0000000..59a66eb --- /dev/null +++ b/src/java/net/I2PFirefoxProfileChecker.java @@ -0,0 +1,96 @@ +package net; + +import java.io.File; + +public class I2PFirefoxProfileChecker { + public static void main(String[] args) { + String profileDirectory = I2PFirefoxProfileBuilder.profileDirectory(); + if (profileDirectory == null) { + System.out.println("No profile directory found"); + return; + } + System.out.println("Profile directory: " + profileDirectory); + boolean ok = validateProfileDirectory(profileDirectory); + if (ok) { + System.out.println("Profile directory is valid"); + } else { + System.out.println("Profile directory is invalid"); + } + } + public static boolean validateProfileDirectory(String profileDirectory) { + File profileDir = new File(profileDirectory); + if (!profileDir.exists()) { + System.out.println("Profile directory does not exist"); + return false; + } + if (!profileDir.isDirectory()) { + System.out.println("Profile directory is not a directory"); + return false; + } + if (!profileDir.canRead()) { + System.out.println("Profile directory is not readable"); + return false; + } + if (!profileDir.canWrite()) { + System.out.println("Profile directory is not writable"); + return false; + } + if (!validateFile(profileDir+"/prefs.js")){ + System.out.println("prefs.js is not valid"); + return false; + } + if (!validateFile(profileDir+"/user.js")){ + System.out.println("user.js is not valid"); + return false; + } + if (!validateFile(profileDir+"/user-overrides.js")){ + System.out.println("user-overrides.js is not valid"); + return false; + } + if (!validateExtensionDirectory(profileDir+"/extensions")){ + System.out.println("extensions directory is invalid"); + return false; + } + return true; + } + public static boolean validateFile(String file) { + File f = new File(file); + if (!f.exists()) { + System.out.println("User JavaScript file does not exist"); + return false; + } + if (!f.isFile()) { + System.out.println("User JavaScript file is not a file"); + return false; + } + if (!f.canRead()) { + System.out.println("User JavaScript file is not readable"); + return false; + } + if (!f.canWrite()) { + System.out.println("User JavaScript file is not writable"); + return false; + } + return true; + } + public static boolean validateExtensionDirectory(String extensionDirectory) { + File extensionDir = new File(extensionDirectory); + if (!extensionDir.exists()) { + System.out.println("Extension directory does not exist"); + return false; + } + if (!extensionDir.isDirectory()) { + System.out.println("Extension directory is not a directory"); + return false; + } + if (!extensionDir.canRead()) { + System.out.println("Extension directory is not readable"); + return false; + } + if (!extensionDir.canWrite()) { + System.out.println("Extension directory is not writable"); + return false; + } + return true; + } +} diff --git a/src/jsp/WEB-INF/web.xml b/src/jsp/WEB-INF/web.xml new file mode 100644 index 0000000..69660db --- /dev/null +++ b/src/jsp/WEB-INF/web.xml @@ -0,0 +1,50 @@ + + + + + + + index.jsp + + + + net.i2p.i2pfirefox.index_jsp + / + + + + net.i2p.i2pfirefox.index_jsp + /index + + + + net.i2p.i2pfirefox.index_jsp + /index.html + + + + net.i2p.i2pfirefox.announce_jsp + /announce.php + + + + net.i2p.i2pfirefox.announce_jsp + /announce + + + + net.i2p.i2pfirefox.announce_jsp + /a + + + + net.i2p.i2pfirefox.scrape_jsp + /scrape + + + + net.i2p.i2pfirefox.scrape_jsp + /scrape.php + + + diff --git a/src/jsp/index.jsp b/src/jsp/index.jsp new file mode 100644 index 0000000..539887b --- /dev/null +++ b/src/jsp/index.jsp @@ -0,0 +1,23 @@ +<%@page trimDirectiveWhitespaces="true"%> + + + + + +I2P Browser Manager + + + + +
+
+I2P Browser Manager
+

+

+I2P Browser Manager +
+
+ + +