├── 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 |
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 |
43 |
44 |
45 |
46 |
Please enable Javascript!
47 |
48 |
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 ' ';
66 | } elseif (isset($_POST['odysseyra1nInstallSubmit'])) {
67 | exec('nohup sudo /home/pi/piRa1n/piRa1n -o > /dev/null 2>&1 &');
68 | echo ' ';
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 |
23 |
24 |
25 |
26 |
Please enable Javascript!
27 |
28 |
29 |
30 | OPTIONS
31 |
62 |
63 |
66 |
67 |
70 |
71 | IF YOU NEED TO BE IN RECOVERY MODE (CAN TAKE UP TO 15s, BE PATIENT)
72 |
75 | IF YOU'RE STUCK IN RECOVERY MODE
76 |
79 |
80 | UPDATES
81 |
98 |
99 | FOR MORE INFO
100 |
105 |
106 | LOG
107 |
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 |
24 |
25 |
26 |
27 |
Please enable Javascript!
28 |
29 |
30 |
31 | REFRESH TO SEE THE LOG IN REAL TIME
32 |
37 |
38 | JAILBREAK LOG
39 |
40 |
41 |
Copy to clipboard
42 |
43 | UPDATE LOG
44 |
45 |
46 |
Copy to clipboard
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 |
24 |
25 |
26 |
27 |
Please enable Javascript!
28 |
29 |
30 |
31 |
32 |
33 | Updating... Don't turn off your Pi. It may take a while.
34 |
35 |
36 |
37 |
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 |
--------------------------------------------------------------------------------