├── CHANGELOG.md ├── LICENSE ├── README.md ├── html ├── actions.php ├── android-chrome-192x192.png ├── android-chrome-384x384.png ├── apple-touch-icon.png ├── arrow.png ├── browserconfig.xml ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── index.php ├── log.php ├── logo.png ├── mstile-150x150.png ├── safari-pinned-tab.svg ├── scripts │ ├── backButton.js │ ├── copyLogToClipboard.js │ └── toggleLightMode.js ├── site.webmanifest ├── style.css └── update_status.php ├── install_piRa1n-web.sh └── version /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # v2.2 - 2021-05-14 2 | # Changed 3 | - Made install script POSIX compliant 4 | - Updated odysseyra1n instructions 5 | 6 | # v2.1.1 - 2020-11-19 7 | # Fixed 8 | - Entering recovery mode 9 | 10 | # v2.1 - 2020-11-19 11 | # Added 12 | - Support to enter recovery mode 13 | 14 | # v2.0 15 | ### Changed 16 | - Rewrote everything 17 | ### Added 18 | - Button to switch between light and dark mode 19 | - Page to view the log 20 | 21 | # v1.3.1 - 2020-07-24 22 | ### Fixed 23 | - Shut down button 24 | 25 | # v1.3 - 2020-07-23 26 | ### Added 27 | - Odysseyra1n option 28 | - Space after if 29 | - Style for submit button in stylesheet.css 30 | 31 | # v1.2 - 2020-07-21 32 | ### Added 33 | - Second '[' and ']' to condition to check if network if available in look_for_updates.sh 34 | - Timeout to wget to check if network if available 35 | - Auto recovery mode 36 | - Exit recovery mode 37 | ### Changed 38 | - Use bash in most of scripts instead of sh 39 | - Reduce top margins of otherDiv in index.php 40 | ### Removed 41 | - Unnecessary echo in shutdown.php 42 | 43 | # v1.1 - 2020-07-02 44 | ### Added 45 | - Version of piRa1n in the ui 46 | ### Changed 47 | - "piRa1n is up to date!" to "piRa1n and Checkra1n are up to date!" 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 raspberryenvoie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

piRa1n-web

2 |

A web interface to control piRa1n.

3 |

Screenshot

4 | -------------------------------------------------------------------------------- /html/actions.php: -------------------------------------------------------------------------------- 1 | /dev/null 2>&1 &'); 12 | header("Location: /"); 13 | exit(); 14 | } elseif (isset($_POST['updateSubmit'])) { 15 | exec('nohup sudo /home/pi/piRa1n/piRa1n -U > /dev/null 2>&1 &'); 16 | header("Location: update_status.php"); 17 | exit(); 18 | } 19 | ?> 20 | 21 | 22 | 23 | 24 | piRa1n | Actions 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | back 38 | 39 | 42 |
43 | 44 | 49 | 50 | /dev/null 2>&1 &'); 53 | echo '
54 |
55 | Your Pi has been shut down. 56 |
57 |
'; 58 | } elseif (isset($_POST['odysseyra1nIntroSubmit'])) { 59 | echo '
60 |
1. If you\'re already jailbroken, restore system using the ckeckra1n app.
61 |
2. Jailbreak using checkra1n, but don’t open the ckeckra1n app.
62 |
(If "Auto shutdown" is enabled, you will need to unplug and replug the Pi to turn it back on.)
63 |
3. Unplug your iDevice and unlock.
64 | 65 |
'; 66 | } elseif (isset($_POST['odysseyra1nInstallSubmit'])) { 67 | exec('nohup sudo /home/pi/piRa1n/piRa1n -o > /dev/null 2>&1 &'); 68 | echo '
69 |
1. Replug your iDevice.
70 |
2. Wait while odysseyra1n is being installed.
71 |
3. Once Sileo is installed, click on \'Done\'
72 |
Note: You don\'t have to reinstall odysseyra1n after each reboot, just re-jailbreak using checkra1n.
73 | 74 |
'; 75 | } elseif (isset($_POST['exitRecoveryModeSubmit'])) { 76 | exec('nohup sudo /home/pi/piRa1n/piRa1n -e > /dev/null 2>&1 &'); 77 | echo '
78 |
79 | Your iDevice is exiting recovery mode... 80 |
81 |
'; 82 | } elseif (isset($_POST['recoveryModeSubmit'])) { 83 | exec('nohup sudo /home/pi/piRa1n/piRa1n -r > /dev/null 2>&1 &'); 84 | echo '
85 |
86 | Your iDevice is entering recovery mode... 87 |
88 |
'; 89 | } else { 90 | echo '
91 |
Doing nothing because no action was provided.
92 |
'; 93 | } 94 | ?> 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /html/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/android-chrome-192x192.png -------------------------------------------------------------------------------- /html/android-chrome-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/android-chrome-384x384.png -------------------------------------------------------------------------------- /html/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/apple-touch-icon.png -------------------------------------------------------------------------------- /html/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/arrow.png -------------------------------------------------------------------------------- /html/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /html/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/favicon-16x16.png -------------------------------------------------------------------------------- /html/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/favicon-32x32.png -------------------------------------------------------------------------------- /html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/favicon.ico -------------------------------------------------------------------------------- /html/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | piRa1n | Home 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 22 |
23 | 24 | 29 | 30 |
OPTIONS
31 |
32 |
33 | Auto recovery mode 34 | 38 |
39 |
40 | Auto shutdown 41 | 45 |
46 |
47 | Safe mode 48 | 52 |
53 |
54 | Verbose boot 55 | 59 |
60 | 61 |
62 | 63 |
64 | 65 |
66 | 67 |
68 | 69 |
70 | 71 |
IF YOU NEED TO BE IN RECOVERY MODE (CAN TAKE UP TO 15s, BE PATIENT)
72 |
73 | 74 |
75 |
IF YOU'RE STUCK IN RECOVERY MODE
76 |
77 | 78 |
79 | 80 |
UPDATES
81 |
82 | Everything is up-to-date'; 86 | } elseif ($lookForUpdates == 1) { 87 | echo ' '; 88 | } elseif ($lookForUpdates == 2) { 89 | echo '
You are offline
'; 90 | } else { 91 | echo '
Could not look for updates
'; 92 | } 93 | ?> 94 |
95 | What's new? 96 |
97 |
98 | 99 |
FOR MORE INFO
100 |
101 |
102 | Check out the wiki pages 103 |
104 |
105 | 106 |
LOG
107 |
108 |
109 | View the log 110 |
111 |
112 | 113 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /html/log.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | piRa1n | Log 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | back 19 | 20 | 23 |
24 | 25 | 30 | 31 |
REFRESH TO SEE THE LOG IN REAL TIME
32 |
33 |
34 | Refresh 35 |
36 |
37 | 38 |
JAILBREAK LOG
39 |
40 |
41 | 42 |
43 |
UPDATE LOG
44 |
45 |
46 | 47 |
48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /html/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/logo.png -------------------------------------------------------------------------------- /html/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberryenvoie/piRa1n-web/36547b7c82b07ea81982fde228ea928e43b5f2f3/html/mstile-150x150.png -------------------------------------------------------------------------------- /html/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 29 | 44 | 47 | 49 | 52 | 55 | 56 | 59 | 62 | 65 | 67 | 70 | 72 | 74 | 78 | 82 | 85 | 100 | 102 | 104 | 105 | 107 | 108 | 109 | 110 | 112 | 114 | 117 | 123 | 125 | 127 | 129 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 141 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /html/scripts/backButton.js: -------------------------------------------------------------------------------- 1 | // Redirect to "/" on click or enter 2 | 3 | const backButton = document.querySelector("#back"); 4 | 5 | backButton.addEventListener("click", () => { 6 | window.location.href="/"; 7 | }); 8 | 9 | backButton.addEventListener("keyup", function(event) { 10 | if (event.keyCode === 13) { 11 | window.location.href="/"; 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /html/scripts/copyLogToClipboard.js: -------------------------------------------------------------------------------- 1 | // Copy log to clipboard 2 | 3 | document.querySelector("#copyJailbreakLog").addEventListener("click", () => { 4 | const copyText = document.getElementById("jailbreakLog").textContent; 5 | const textArea = document.createElement("textarea"); 6 | textArea.textContent = copyText; 7 | document.body.append(textArea); 8 | textArea.select(); 9 | document.execCommand("copy"); 10 | textArea.remove(); 11 | }); 12 | 13 | document.querySelector("#copyUpdateLog").addEventListener("click", () => { 14 | const copyText = document.getElementById("updateLog").textContent; 15 | const textArea = document.createElement("textarea"); 16 | textArea.textContent = copyText; 17 | document.body.append(textArea); 18 | textArea.select(); 19 | document.execCommand("copy"); 20 | textArea.remove(); 21 | }); 22 | -------------------------------------------------------------------------------- /html/scripts/toggleLightMode.js: -------------------------------------------------------------------------------- 1 | console.log("Live happily :)"); 2 | 3 | let lightMode = localStorage.getItem("lightMode"); 4 | const toggleButton = document.querySelector("#toggle-light-mode"); 5 | 6 | // Toggle light mode 7 | if (lightMode === "enabled") { 8 | document.body.classList.add("lightmode"); 9 | } 10 | 11 | toggleButton.addEventListener("click", () => { 12 | document.body.classList.toggle("lightmode"); 13 | if (lightMode !== "enabled") { 14 | localStorage.setItem("lightMode", "enabled"); 15 | } else { 16 | localStorage.setItem("lightMode", null); 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /html/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-384x384.png", 12 | "sizes": "384x384", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /html/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --clr-text: #feffff; 3 | --clr-header: #121212; 4 | --clr-group: #1c1c1e; 5 | --clr-title: #8e8e93; 6 | --clr-background: #000000; 7 | --clr-switch-background: #39393d; 8 | --clr-switch-shadow: #353539; 9 | --invert-clr: 0; 10 | } 11 | 12 | .lightmode { 13 | --clr-text: #000000; 14 | --clr-header: #fafafc; 15 | --clr-group: #feffff; 16 | --clr-title: #6d6d72; 17 | --clr-background: #f2f2f7; 18 | --clr-switch-background: #e9e9ea; 19 | --clr-switch-shadow: #e3e3e5; 20 | --invert-clr: 1; 21 | } 22 | 23 | body { 24 | margin: 0; 25 | padding: 0; 26 | background-color: var(--clr-background); 27 | color: var(--clr-text); 28 | font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; 29 | } 30 | 31 | .header { 32 | position: -webkit-sticky; 33 | position: sticky; 34 | top: 0; 35 | width: 100%; 36 | height: 60px; 37 | background-color: var(--clr-header); 38 | display: flex; 39 | justify-content: center; 40 | align-items: center; 41 | z-index: 1; 42 | } 43 | 44 | .back { 45 | position: absolute; 46 | width: 14px; 47 | height: 25px; 48 | left: 0.8rem; 49 | cursor: pointer; 50 | } 51 | 52 | .logo { 53 | height: 55px; 54 | -webkit-filter: invert(var(--invert-clr)); 55 | filter: invert(var(--invert-clr)); 56 | } 57 | 58 | .toggle-light-mode { 59 | position: absolute; 60 | width: 30px; 61 | height: 30px; 62 | right: 0.8rem; 63 | color: var(--color-text); 64 | padding: 4px; 65 | background: transparent; 66 | cursor: pointer; 67 | border: none; 68 | } 69 | 70 | .title { 71 | position: relative; 72 | top: 45px; 73 | font-size: 0.9rem; 74 | color: var(--clr-title); 75 | margin-left: 0.8rem; 76 | } 77 | 78 | .group { 79 | position: relative; 80 | width: 100%; 81 | height: 100%; 82 | margin-top: 50px; 83 | background-color: var(--clr-group); 84 | font-size: 1.1rem; 85 | } 86 | 87 | .cell { 88 | position: relative; 89 | padding: 0.8rem; 90 | } 91 | 92 | .switchWrapper { 93 | position: absolute; 94 | display: inline-block; 95 | width: 50px; 96 | height: 30px; 97 | right: 0.8rem; 98 | } 99 | 100 | .slider { 101 | position: absolute; 102 | cursor: pointer; 103 | top: 0; 104 | left: 0; 105 | right: 0; 106 | bottom: 0; 107 | background-color: var(--clr-switch-background); 108 | transition: 400ms; 109 | border-radius: 15px; 110 | box-shadow: inset 0 0 5px var(--clr-switch-shadow); 111 | overflow: hidden; 112 | } 113 | 114 | .switchWrapper input[type="checkbox"] { 115 | display: none; 116 | } 117 | 118 | .slider::before { 119 | position: absolute; 120 | content: ""; 121 | height: 26px; 122 | width: 26px; 123 | left: 2px; 124 | bottom: 2px; 125 | background-color: #feffff; 126 | transition: 400ms; 127 | border-radius: 50%; 128 | box-shadow: 1px 1px 5px 1px var(--clr-switch-shadow); 129 | } 130 | 131 | input:checked + .slider { 132 | background-color: #30d158; 133 | box-shadow: none; 134 | } 135 | 136 | input:checked + .slider::before { 137 | transform: translateX(20px); 138 | box-shadow: none; 139 | } 140 | 141 | 142 | input[type="submit"] { 143 | padding: 0.8rem; 144 | border: none; 145 | color: #0984fe; 146 | background-color: transparent; 147 | font-size: 1.1rem; 148 | cursor: pointer; 149 | } 150 | 151 | .cellLink { 152 | text-decoration: none; 153 | color: #0984fe; 154 | } 155 | 156 | .footer { 157 | margin-top: 40px; 158 | color: var(--clr-title); 159 | text-align: center; 160 | font-size: 0.9rem; 161 | } 162 | 163 | .softwareVersion { 164 | color: inherit; 165 | text-decoration: none; 166 | } 167 | 168 | pre { 169 | font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; 170 | overflow: scroll; 171 | margin-bottom: 0; 172 | } 173 | 174 | #copyJailbreakLog { 175 | color: #0984fe; 176 | background: transparent; 177 | cursor: pointer; 178 | border: none; 179 | font-size: 1.1rem; 180 | } 181 | 182 | #copyUpdateLog { 183 | color: #0984fe; 184 | background: transparent; 185 | cursor: pointer; 186 | border: none; 187 | font-size: 1.1rem; 188 | } 189 | 190 | textarea { 191 | position: absolute; 192 | left: -100%; 193 | } 194 | -------------------------------------------------------------------------------- /html/update_status.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | piRa1n | Updating... 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | back 19 | 20 | 23 |
24 | 25 | 30 | 31 |
32 |
33 | Updating... Don't turn off your Pi. It may take a while. 34 |
35 |
36 | 37 |
38 |
39 | 
40 |       
41 |
42 | Refresh to see the status of updates in real time 43 |
44 |
45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /install_piRa1n-web.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ "$(id -u)" -ne 0 ] && { 3 | echo 'Please run as root' 4 | exit 1 5 | } 6 | 7 | [ -d /home/pi/piRa1n/ ] || { echo 'Install piRa1n first'; exit 1; } 8 | 9 | GREEN="$(tput setaf 2)" 10 | BLUE="$(tput setaf 6)" 11 | NORMAL="$(tput sgr0)" 12 | cat << EOF 13 | ${GREEN}#########################################${NORMAL} 14 | ${GREEN}# #${NORMAL} 15 | ${GREEN}# ${BLUE}Welcome to the piRa1n-web installer ${GREEN}#${NORMAL} 16 | ${GREEN}# ${BLUE}Made with <3 by raspberryenvoie ${GREEN}#${NORMAL} 17 | ${GREEN}# #${NORMAL} 18 | ${GREEN}#########################################${NORMAL} 19 | EOF 20 | 21 | # Update the system and install the dependencies 22 | apt update 23 | apt upgrade -y 24 | apt install apache2 php git -y 25 | 26 | # Install piRa1n-web 27 | git clone 'https://github.com/raspberryenvoie/piRa1n-web.git' /home/pi/piRa1n-web/ 28 | 29 | # Fix file permissions 30 | chown -R pi:pi /home/pi/piRa1n-web/ 31 | chmod -R 755 /home/pi/piRa1n-web/ 32 | 33 | # Copy files to /var/www/html 34 | rm -rf /var/www/html/* 35 | cp -R /home/pi/piRa1n-web/html/* /var/www/html/ 36 | 37 | # Add sudoers file 38 | cd /tmp/ || exit 39 | cat << EOF > piRa1n-web 40 | # piRa1n-web 41 | www-data ALL=(ALL) NOPASSWD: /home/pi/piRa1n/piRa1n 42 | EOF 43 | chmod 440 piRa1n-web 44 | if visudo -qcf piRa1n-web; then 45 | mv piRa1n-web /etc/sudoers.d/ 46 | else 47 | echo 'Failed to add the sudoers file! Add it youself.' 48 | fi 49 | rm -f piRa1n-web 50 | 51 | echo 'All done!' 52 | echo "Type $(hostname -I | awk '{print $1}') in a browser to access the web interface." 53 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | v2.2 2 | --------------------------------------------------------------------------------