luci-mod-system: use "system" new "validate_firmware_image" ubus method
authorRafał Miłecki <rafal@milecki.pl>
Wed, 25 Sep 2019 14:51:37 +0000 (16:51 +0200)
committerJo-Philipp Wich <jo@mein.io>
Wed, 2 Oct 2019 07:46:18 +0000 (09:46 +0200)
This new ubus method provides more properly-formatted details about
firmware file. Use it to check if uploaded image is valid.

The old "sysupgrade --test" method is left for now to provide stderr
output.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
[Added missing ACL, add default value for the ubus failure case]
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json
modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js

index 31c154cbcb8f78decfde7d6637f057b4bdac1ddd..182f2498843cf914f9f9eca60a71b63ddc7a24e0 100644 (file)
@@ -44,6 +44,7 @@
                                "network.device": [ "status" ],
                                "network.interface": [ "dump" ],
                                "network": [ "get_proto_handlers" ],
+                               "system": [ "validate_firmware_image" ],
                                "uci": [ "changes", "get" ]
                        },
                        "uci": [ "*" ]
index 08c97650ea5b7ab1b23531ceabc1e3c89bcfca19..49bbf238848f7900654d13eedc965c51c513a2c9 100644 (file)
@@ -2,7 +2,7 @@
 'require form';
 'require rpc';
 
-var callFileStat, callFileRead, callFileWrite, callFileExec, callFileRemove;
+var callFileStat, callFileRead, callFileWrite, callFileExec, callFileRemove, callSystemValidateFirmwareImage;
 
 callFileStat = rpc.declare({
        object: 'file',
@@ -38,6 +38,13 @@ callFileRemove = rpc.declare({
        params: [ 'path' ]
 });
 
+callSystemValidateFirmwareImage = rpc.declare({
+       object: 'system',
+       method: 'validate_firmware_image',
+       params: [ 'path' ],
+       expect: { '': { valid: false, forcable: true } }
+});
+
 function pingDevice(proto, ipaddr) {
        var target = '%s://%s%s?%s'.format(proto || 'http', ipaddr || window.location.host, L.resource('icons/loading.gif'), Math.random());
 
@@ -345,13 +352,17 @@ return L.view.extend({
                                        E('span', { 'class': 'spinning' }, _('Verifying the uploaded image file.'))
                                ]);
 
+                               return callSystemValidateFirmwareImage('/tmp/firmware.bin')
+                                       .then(function(res) { return [ reply, res ]; });
+                       }, this, ev.target))
+                       .then(L.bind(function(btn, reply) {
                                return callFileExec('/sbin/sysupgrade', [ '--test', '/tmp/firmware.bin' ])
-                                       .then(function(res) { return [ reply, res ] });
+                                       .then(function(res) { reply.push(res); return reply; });
                        }, this, ev.target))
                        .then(L.bind(function(btn, res) {
                                var keep = document.querySelector('[data-name="keep"] input[type="checkbox"]'),
                                    force = E('input', { type: 'checkbox' }),
-                                   is_invalid = (res[1].code != 0),
+                                   is_valid = res[1].valid,
                                    is_too_big = (storage_size > 0 && res[0].size > storage_size),
                                    body = [];
 
@@ -363,7 +374,7 @@ return L.view.extend({
                                        E('li', {}, keep.checked ? _('Configuration files will be kept') : _('Caution: Configuration files will be erased'))
                                ]));
 
-                               if (is_invalid || is_too_big)
+                               if (!is_valid || is_too_big)
                                        body.push(E('hr'));
 
                                if (is_too_big)
@@ -371,15 +382,15 @@ return L.view.extend({
                                                _('It appears that you are trying to flash an image that does not fit into the flash memory, please verify the image file!')
                                        ]));
 
-                               if (is_invalid)
+                               if (!is_valid)
                                        body.push(E('p', { 'class': 'alert-message' }, [
-                                               res[1].stderr ? res[1].stderr : '',
-                                               res[1].stderr ? E('br') : '',
-                                               res[1].stderr ? E('br') : '',
+                                               res[2].stderr ? res[2].stderr : '',
+                                               res[2].stderr ? E('br') : '',
+                                               res[2].stderr ? E('br') : '',
                                                _('The uploaded image file does not contain a supported format. Make sure that you choose the generic image format for your platform.')
                                        ]));
 
-                               if (is_invalid || is_too_big)
+                               if (!is_valid || is_too_big)
                                        body.push(E('p', {}, E('label', { 'class': 'btn alert-message danger' }, [
                                                force, ' ', _('Force upgrade'),
                                                E('br'), E('br'),
@@ -389,7 +400,7 @@ return L.view.extend({
                                var cntbtn = E('button', {
                                        'class': 'btn cbi-button-action important',
                                        'click': L.ui.createHandlerFn(this, 'handleSysupgradeConfirm', btn, keep.checked, force.checked),
-                                       'disabled': (is_invalid || is_too_big) ? true : null
+                                       'disabled': (!is_valid || is_too_big) ? true : null
                                }, [ _('Continue') ]);
 
                                body.push(E('div', { 'class': 'right' }, [