]>
Commit | Line | Data |
---|---|---|
db9ee62e LAH |
1 | /*############################################################################# |
2 | # # | |
3 | # IPFire.org - A linux based firewall # | |
4 | # Copyright (C) 2007-2021 IPFire Team <info@ipfire.org> # | |
5 | # # | |
6 | # This program is free software: you can redistribute it and/or modify # | |
7 | # it under the terms of the GNU General Public License as published by # | |
8 | # the Free Software Foundation, either version 3 of the License, or # | |
9 | # (at your option) any later version. # | |
10 | # # | |
11 | # This program is distributed in the hope that it will be useful, # | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
14 | # GNU General Public License for more details. # | |
15 | # # | |
16 | # You should have received a copy of the GNU General Public License # | |
17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
18 | # # | |
19 | #############################################################################*/ | |
20 | ||
21 | "use strict"; | |
22 | ||
23 | // Pakfire Javascript functions (requires jQuery) | |
24 | class PakfireJS { | |
25 | constructor() { | |
26 | //--- Public properties --- | |
27 | // Translation strings | |
28 | this.i18n = new PakfireI18N(); | |
29 | ||
30 | //--- Private properties --- | |
31 | // Status flags (access outside constructor only with setter/getter) | |
32 | this._states = Object.create(null); | |
33 | this._states.running = false; | |
34 | this._states.reboot = false; | |
35 | ||
36 | // Status refresh helper | |
37 | this._autoRefresh = { | |
38 | delay: 1000, //Delay between requests (default: 1s) | |
39 | jsonAction: 'getstatus', //CGI POST action parameter | |
40 | timeout: 5000, //XHR timeout (5s) | |
41 | ||
42 | delayTimer: null, //setTimeout reference | |
43 | jqXHR: undefined, //jQuery.ajax promise reference | |
44 | get runningDelay() { //Waiting for end of delay | |
45 | return (this.delayTimer !== null); | |
46 | }, | |
47 | get runningXHR() { //Waiting for CGI response | |
48 | return (this.jqXHR && (this.jqXHR.state() === 'pending')); | |
49 | }, | |
50 | get isRunning() { | |
51 | return (this.runningDelay || this.runningXHR); | |
52 | } | |
53 | }; | |
54 | } | |
55 | ||
56 | //### Public properties ### | |
57 | ||
58 | // Pakfire is running (true/false) | |
59 | set running(state) { | |
60 | if(this._states.running !== state) { | |
61 | this._states.running = state; | |
62 | this._states_onChange('running'); | |
63 | } | |
64 | } | |
65 | get running() { | |
66 | return this._states.running; | |
67 | } | |
68 | ||
69 | // Reboot needed (true/false) | |
70 | set reboot(state) { | |
71 | if(this._states.reboot !== state) { | |
72 | this._states.reboot = state; | |
73 | this._states_onChange('reboot'); | |
74 | } | |
75 | } | |
76 | get reboot() { | |
77 | return this._states.reboot; | |
78 | } | |
79 | ||
80 | // Status refresh interval in ms | |
81 | set refreshInterval(delay) { | |
82 | if(delay < 500) { | |
83 | delay = 500; //enforce reasonable minimum | |
84 | } | |
85 | this._autoRefresh.delay = delay; | |
86 | } | |
87 | get refreshInterval() { | |
88 | return this._autoRefresh.delay; | |
89 | } | |
90 | ||
91 | // Document loaded (call once from jQuery.ready) | |
92 | documentReady() { | |
93 | // Status refresh late start | |
94 | if(this.running && (! this._autoRefresh.isRunning)) { | |
95 | this._autoRefresh_runNow(); | |
96 | } | |
97 | } | |
98 | ||
99 | //### Private properties ### | |
100 | ||
101 | // Pakfire status change handler | |
102 | // property: Affected status (running, reboot, ...) | |
103 | _states_onChange(property) { | |
104 | // Always update UI | |
105 | if(this.running) { | |
106 | $('#pflog-status').text(this.i18n.get('working')); | |
107 | $('#pflog-action').empty(); | |
108 | } else { | |
109 | $('#pflog-status').text(this.i18n.get('finished')); | |
110 | if(this.reboot) { //Enable return or reboot links in UI | |
111 | $('#pflog-action').html(this.i18n.get('link_reboot')); | |
112 | } else { | |
113 | $('#pflog-action').html(this.i18n.get('link_return')); | |
114 | } | |
115 | } | |
116 | ||
117 | // Start/stop status refresh if Pakfire started/stopped | |
118 | if(property === 'running') { | |
119 | if(this.running) { | |
120 | this._autoRefresh_runNow(); | |
121 | } else { | |
122 | this._autoRefresh_clearSchedule(); | |
123 | } | |
124 | } | |
125 | } | |
126 | ||
127 | //--- Status refresh scheduling functions --- | |
128 | ||
129 | // Immediately perform AJAX status refresh request | |
130 | _autoRefresh_runNow() { | |
131 | if(this._autoRefresh.runningXHR) { | |
132 | return; // Don't send multiple requests | |
133 | } | |
134 | this._autoRefresh_clearSchedule(); // Stop scheduled refresh, will send immediately | |
135 | ||
136 | // Send AJAX request, attach listeners | |
137 | this._autoRefresh.jqXHR = this._JSON_get(this._autoRefresh.jsonAction, this._autoRefresh.timeout); | |
138 | this._autoRefresh.jqXHR.done(function() { // Request succeeded | |
139 | if(this.running) { // Keep refreshing while Pakfire is running | |
140 | this._autoRefresh_scheduleRun(); | |
141 | } | |
142 | }); | |
143 | this._autoRefresh.jqXHR.fail(function() { // Request failed | |
144 | this._autoRefresh_scheduleRun(); // Try refreshing until valid status is received | |
145 | }); | |
146 | } | |
147 | ||
148 | // Schedule next refresh | |
149 | _autoRefresh_scheduleRun() { | |
150 | if(this._autoRefresh.runningDelay || this._autoRefresh.runningXHR) { | |
151 | return; // Refresh already scheduled or in progress | |
152 | } | |
153 | this._autoRefresh.delayTimer = window.setTimeout(function() { | |
154 | this._autoRefresh.delayTimer = null; | |
155 | this._autoRefresh_runNow(); | |
156 | }.bind(this), this._autoRefresh.delay); | |
157 | } | |
158 | ||
159 | // Stop scheduled refresh (can still be refreshed up to 1x if XHR is already sent) | |
160 | _autoRefresh_clearSchedule() { | |
161 | if(this._autoRefresh.runningDelay) { | |
162 | window.clearTimeout(this._autoRefresh.delayTimer); | |
163 | this._autoRefresh.delayTimer = null; | |
164 | } | |
165 | } | |
166 | ||
167 | //--- JSON request & data handling --- | |
168 | ||
169 | // Load JSON data from Pakfire CGI, using a POST request | |
170 | // action: POST paramter "json-[action]" | |
171 | // maxTime: XHR timeout, 0 = no timeout | |
172 | _JSON_get(action, maxTime = 0) { | |
173 | return $.ajax({ | |
174 | url: '/cgi-bin/pakfire.cgi', | |
175 | method: 'POST', | |
176 | timeout: maxTime, | |
177 | context: this, | |
178 | data: {'ACTION': `json-${action}`}, | |
179 | dataType: 'json' //automatically check and convert result | |
180 | }) | |
181 | .done(function(response) { | |
182 | this._JSON_process(action, response); | |
183 | }); | |
184 | } | |
185 | ||
186 | // Process successful response from Pakfire CGI | |
187 | // action: POST paramter "json-[action]" used to send request | |
188 | // data: JSON data object | |
189 | _JSON_process(action, data) { | |
190 | // Pakfire status refresh | |
191 | if(action === this._autoRefresh.jsonAction) { | |
192 | // Update status flags | |
193 | this.running = (data['running'] != '0'); | |
194 | this.reboot = (data['reboot'] != '0'); | |
195 | ||
196 | // Update timer display | |
197 | if(this.running && data['running_since']) { | |
198 | $('#pflog-time').text(this.i18n.get('since') + data['running_since']); | |
199 | } else { | |
200 | $('#pflog-time').empty(); | |
201 | } | |
202 | ||
203 | // Print log messages | |
204 | let messages = ""; | |
205 | data['messages'].forEach(function(line) { | |
206 | messages += `${line}\n`; | |
207 | }); | |
208 | $('#pflog-messages').text(messages); | |
209 | } | |
210 | } | |
211 | } | |
212 | ||
213 | // Simple translation strings helper | |
214 | // Format: {key: "translation"} | |
215 | class PakfireI18N { | |
216 | constructor() { | |
217 | this._strings = Object.create(null); //Object without prototypes | |
218 | } | |
219 | ||
220 | // Get translation | |
221 | get(key) { | |
222 | if(Object.prototype.hasOwnProperty.call(this._strings, key)) { | |
223 | return this._strings[key]; | |
224 | } | |
225 | return `(undefined string '${key}')`; | |
226 | } | |
227 | ||
228 | // Load key/translation object | |
229 | load(translations) { | |
230 | if(translations instanceof Object) { | |
231 | Object.assign(this._strings, translations); | |
232 | } | |
233 | } | |
234 | } | |
235 | ||
236 | //### Initialize Pakfire ### | |
237 | const pakfire = new PakfireJS(); | |
238 | ||
239 | $(function() { | |
240 | pakfire.documentReady(); | |
241 | }); |