diff --git a/luciexpress/htdocs/index.html b/luciexpress/htdocs/index.html
index 42fb9573b..34fe29352 100644
--- a/luciexpress/htdocs/index.html
+++ b/luciexpress/htdocs/index.html
@@ -1,5 +1,5 @@
-
+
LuCi Express
diff --git a/luciexpress/htdocs/js/app.js b/luciexpress/htdocs/js/app.js
index ac5f55f4b..174622aea 100644
--- a/luciexpress/htdocs/js/app.js
+++ b/luciexpress/htdocs/js/app.js
@@ -54,6 +54,7 @@ require([
angular.bootstrap(document, ['luci']);
});
*/
+
angular.module("luci", [
"ui.bootstrap",
"ui.router",
@@ -63,9 +64,9 @@ angular.module("luci", [
"ngAnimate",
"gettext",
"checklist-model"
- ]);
-
-angular.module("luci")
+]);
+
+ angular.module("luci")
.config(function ($stateProvider, $locationProvider, $compileProvider, $urlRouterProvider, $controllerProvider, $provide) {
//$locationProvider.otherwise({ redirectTo: "/" });
$locationProvider.hashPrefix('!');
@@ -83,7 +84,7 @@ angular.module("luci")
console.log(JSON.stringify($delegate[0]));
return $delegate;
});*/
-
+
$juci.$urlRouterProvider = $urlRouterProvider;
$juci.redirect = function(page){
window.location.href = "#!"+page;
@@ -121,7 +122,7 @@ angular.module("luci")
luci_config: {}
});
})
- .run(function($rootScope, $state, $session, gettextCatalog, $rpc, $uci, $config, $location, $navigation){
+ .run(function($rootScope, $state, $session, gettextCatalog, $rpc, $config, $location, $navigation){
$rootScope.config = $config;
//window.rpc = $rpc;
//window.uci = $uci;
@@ -130,8 +131,8 @@ angular.module("luci")
gettextCatalog.currentLanguage = "en";
gettextCatalog.debug = true;
/*$rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
- $rootScope.title = current.$$route.title;
- });*/
+ $rootScope.title = current.$$route.title;
+ });*/
var path = $location.path().replace(/\//g, "").replace(/\./g, "_");
$config.system = {};
@@ -156,26 +157,35 @@ angular.module("luci")
//$state.go("login");
});
})
+
+ .directive("luciFooter", function(){ return {} })
+ .directive("luciLayoutNaked", function(){ return {} })
+ .directive("luciLayoutSingleColumn", function(){ return {} })
+ .directive("luciLayoutWithSidebar", function(){ return {} })
+ .directive("luciNav", function(){ return {} })
+ .directive("luciNavbar", function(){ return {} })
+ .directive("luciTopBar", function(){ return {} })
+ .directive('ngOnload', [function(){
+ return {
+ scope: {
+ callBack: '&ngOnload'
+ },
+ link: function(scope, element, attrs){
+ element.on('load', function(){
+ return scope.callBack();
+ })
+ }
+ }}]);
-.directive("luciFooter", function(){ return {} })
-.directive("luciLayoutNaked", function(){ return {} })
-.directive("luciLayoutSingleColumn", function(){ return {} })
-.directive("luciLayoutWithSidebar", function(){ return {} })
-.directive("luciNav", function(){ return {} })
-.directive("luciNavbar", function(){ return {} })
-.directive("luciTopBar", function(){ return {} })
-.directive('ngOnload', [function(){
- return {
- scope: {
- callBack: '&ngOnload'
- },
- link: function(scope, element, attrs){
- element.on('load', function(){
- return scope.callBack();
- })
- }
-}}])
+angular.element(document).ready(function() {
+ window.rpc.$init().done(function(){
+ console.log("RPC INIT DONE!");
+ angular.bootstrap(document, ["luci"]);
+ });
+});
+
+/*
angular.module("luci")
.factory("$hosts", function($rpc, $uci){
var hosts = {};
@@ -266,4 +276,4 @@ angular.module("luci")
$(document).ready(function(){
$("#loading-indicator").hide();
-});
+}); */
diff --git a/luciexpress/htdocs/js/rpc.js b/luciexpress/htdocs/js/rpc.js
index c408dd5da..d208c8b7f 100644
--- a/luciexpress/htdocs/js/rpc.js
+++ b/luciexpress/htdocs/js/rpc.js
@@ -1,10 +1,69 @@
//! Author: Martin K. Schröder
-// luci rpc module for communicating with the server
-angular.module("luci")
-.factory('$rpc', function($rootScope, $config, gettext){
+(function(){
+ var RPC_HOST = ""; //(($config.rpc.host)?$config.rpc.host:"")
+ var RPC_SESSION_ID = "00000000000000000000000000000000";
+ var gettext = function(text){ return text; }
+ function rpc_request(type, namespace, method, data){
+ var sid = "";
+ var deferred = $.Deferred();
+ // setup default rpcs
+ $.jsonRPC.withOptions({
+ namespace: "",
+ endPoint: RPC_HOST+"/ubus"
+ }, function(){
+ //var sid = "00000000000000000000000000000000";
+ //if($rootScope.sid) sid = $rootScope.sid;
+ //data.ubus_rpc_session = sid;
+ this.request(type, {
+ params: [ RPC_SESSION_ID, namespace, method, data],
+ success: function(result){
+ //alert("SID: "+sid + " :: "+ JSON.stringify(result));
+ if(type == "call" && result && result.result) {
+ // TODO: modify all rpc UCI services so that they ALWAYS return at least
+ // an empty json object. Otherwise we have no way to differentiate success
+ // from failure of a request. This has to be done on the host side.
+ if(result.result[0] != 0){ // || result.result[1] == undefined) {
+ console.log("RPC succeeded, but returned error: "+JSON.stringify(result));
+ deferred.reject((function(){
+ switch(result.result[0]){
+ case 0: return gettext("Parse error");
+ case 1: return gettext("Invalid request");
+ case 2: return gettext("Invalid parameters");
+ case 3: return gettext("Internal error");
+ case 4: return gettext("Object not found");
+ case 5: return gettext("Session not found");
+ case 6: return gettext("Access denied");
+ case 7: return gettext("Timed out");
+ default: return gettext("RPC error #")+result.result[0]+": "+result.result[1];
+ }
+ })());
+ } else {
+ deferred.resolve(result.result[1]);
+ }
+ } else if(type == "list" && result && result.result){
+ deferred.resolve(result.result);
+ } else {
+ deferred.reject();
+ }
+ },
+ error: function(result){
+ console.error("RPC error ("+namespace+"."+method+"): "+JSON.stringify(result));
+ if(result && result.error){
+ deferred.reject(result.error);
+ //$rootScope.$broadcast("error", result.error.message);
+ }
+ }
+ })
+ });
+ return deferred.promise();
+ }
var rpc = window.rpc = {
- register_method: function(call){
+ $sid: function(sid){
+ if(sid) RPC_SESSION_ID = sid;
+ else return RPC_SESSION_ID;
+ },
+ $register: function(call){
//console.log("registering: "+call);
var self = this;
function _find(path, obj){
@@ -17,53 +76,8 @@ angular.module("luci")
(function(namespace, method){
// create the rpc method
obj[path[0]] = function(data){
- var func = (function(data){
- if(!data) data = { };
- var deferred = $.Deferred();
- $.jsonRPC.withOptions({
- namespace: "",
- endPoint: (($config.rpc.host)?$config.rpc.host:"")+"/ubus"
- }, function(){
- var sid = "00000000000000000000000000000000";
- if($rootScope.sid) sid = $rootScope.sid;
- //data.ubus_rpc_session = sid;
- this.request('call', {
- params: [ sid, namespace, method, data],
- success: function(result){
- //alert("SID: "+sid + " :: "+ JSON.stringify(result));
- if(result && result.result) {
- // TODO: modify all rpc UCI services so that they ALWAYS return at least
- // an empty json object. Otherwise we have no way to differentiate success
- // from failure of a request. This has to be done on the host side.
- if(result.result[0] != 0){ // || result.result[1] == undefined) {
- console.log("RPC succeeded, but returned error: "+JSON.stringify(result));
- deferred.reject((function(){
- switch(result.result[0]){
- case 6: return gettext("Access denied!");
- default: return gettext("RPC error #")+result.result[0]+": "+result.result[1];
- }
- })());
- } else {
- deferred.resolve(result.result[1]);
- }
- } else {
- deferred.reject();
- }
- },
- error: function(result){
- console.error("RPC error ("+namespace+"."+method+"): "+JSON.stringify(result));
- if(result && result.error){
- deferred.reject(result.error);
- $rootScope.$broadcast("error", result.error.message);
- } else {
- deferred.reject("RPC error ("+namespace+"."+method+"): "+JSON.stringify(result));
- }
- }
- })
- });
- return deferred.promise();
- });
- return func(data);
+ if(!data) data = { };
+ return rpc_request("call", namespace, method, data);
}
})(namespace, path[0]);
} else {
@@ -73,13 +87,49 @@ angular.module("luci")
}
}
_find(call.split("."), self);
+ },
+ $init: function(){
+ var self = this;
+ var deferred = $.Deferred();
+ // request list of all methods and construct rpc object containing all of the methods in javascript.
+ rpc_request("list", "*", "", {}).done(function(result){
+ //console.log("RESULT: "+JSON.stringify(result));
+ // TODO: make this less obscure of a method :)
+ function _processNode(obj, cur_path){
+ var is_leaf = true;
+ var leafs = {};
+ Object.keys(obj).map(function(x){
+ if((typeof obj[x]) == "object") {
+ leafs[x] = obj[x];
+ is_leaf = false;
+ } else {
+
+ }
+ });
+ if(is_leaf){
+ // add a new rpc call
+ //console.log("Leaf: "+namespace+", "+method);
+ self.$register(cur_path);
+ } else {
+ //console.log("Processing node: "+cur_path);
+ Object.keys(leafs).map(function(x){
+ var path = ((cur_path)?(cur_path+"."):"")+x;
+ //var namespace = parent[x] = {};
+ _processNode(leafs[x], path);
+ });
+ }
+ }
+ _processNode(result, null);
+ deferred.resolve();
+ });
+ return deferred.promise();
}
};
- // setup default rpcs
- if($config.rpc && $config.rpc.exposed_calls){
- $config.rpc.exposed_calls.forEach(function(call){
- rpc.register_method(call);
- });
- }
- return rpc;
+})();
+
+// luci rpc module for communicating with the server
+angular.module("luci")
+.factory('$rpc', function($rootScope, $config, gettext){
+
+ return window.rpc;
});
diff --git a/luciexpress/htdocs/js/session.js b/luciexpress/htdocs/js/session.js
index 9f0db2dac..4a41c643a 100644
--- a/luciexpress/htdocs/js/session.js
+++ b/luciexpress/htdocs/js/session.js
@@ -6,13 +6,13 @@ angular.module("luci")
var saved_sid = $localStorage.getItem("sid");
var default_sid = "00000000000000000000000000000000";
if(saved_sid){
- $rootScope.sid = saved_sid;
+ window.rpc.$sid(saved_sid);
}
function setupUbusRPC(acls){
Object.keys(acls).map(function(key){
acls[key].map(function(func){
- $rpc.register_method(key+"."+func);
+ //$rpc.register_method(key+"."+func);
});
});
}
@@ -53,7 +53,8 @@ angular.module("luci")
"username": obj.username,
"password": obj.password
}).done(function(result){
- $rootScope.sid = self.sid = result.ubus_rpc_session;
+ self.sid = result.ubus_rpc_session;
+ window.rpc.$sid(self.sid);
self.data = result;
$localStorage.setItem("sid", self.sid);
if(result && result.acls && result.acls.ubus) setupUbusRPC(result.acls.ubus);
diff --git a/luciexpress/htdocs/js/uci.js b/luciexpress/htdocs/js/uci.js
index 2e17a8bde..2fd45bcd7 100644
--- a/luciexpress/htdocs/js/uci.js
+++ b/luciexpress/htdocs/js/uci.js
@@ -226,7 +226,6 @@ angular.module("luci")
UCI.Field = UCIField;
})();
(function(){
-
function UCISection(config){
this[".config"] = config;
}
diff --git a/luciexpress/htdocs/plugins/core/widgets/luci.footer.js b/luciexpress/htdocs/plugins/core/widgets/luci.footer.js
index a4a6ee6e6..960f5d8c3 100644
--- a/luciexpress/htdocs/plugins/core/widgets/luci.footer.js
+++ b/luciexpress/htdocs/plugins/core/widgets/luci.footer.js
@@ -29,7 +29,7 @@ $juci.module("core")
controller: "luciFooterController"
};
})
-.controller("luciFooterController", function($scope, $rpc, $config, $languages, gettextCatalog, gettext, $tr, $status){
+.controller("luciFooterController", function($scope, $rpc, $config, $languages, gettextCatalog, gettext, $tr){
// TODO: move this into a higher level controller maybe?
$scope.languages = $languages.getLanguages();
$scope.isActiveLanguage = function(lang){
@@ -42,7 +42,7 @@ $juci.module("core")
$rpc.network.interface.dump().done(function(result){
if(result && result.interface) {
result.interface.map(function(i){
- if(i.interface == "wan" && i["ipv4-address"].length){
+ if(i.interface == "wan" && i["ipv4-address"] && i["ipv4-address"].length){
$scope.wanip = i["ipv4-address"][0].address;
}
});
diff --git a/luciexpress/htdocs/plugins/core/widgets/luci.login.js b/luciexpress/htdocs/plugins/core/widgets/luci.login.js
index b3e97984b..4075dbe8d 100644
--- a/luciexpress/htdocs/plugins/core/widgets/luci.login.js
+++ b/luciexpress/htdocs/plugins/core/widgets/luci.login.js
@@ -44,15 +44,17 @@ $juci.module("core")
$scope.loggedIn = $session.isLoggedIn();
$scope.errors = [];
$scope.showHost = 0;
- $rpc.local.features().done(function(features){
- if(features.list) features.list.map(function(x){
- if(x.indexOf("rpcforward") == 0) {
- $scope.showHost = 1;
- $scope.form.host = $localStorage.getItem("rpc_host")||"";
- }
+ if($rpc.local){
+ $rpc.local.features().done(function(features){
+ if(features.list) features.list.map(function(x){
+ if(x.indexOf("rpcforward") == 0) {
+ $scope.showHost = 1;
+ $scope.form.host = $localStorage.getItem("rpc_host")||"";
+ }
+ });
+ $scope.$apply();
});
- $scope.$apply();
- });
+ }
$scope.doLogin = function(){
$scope.errors = [];
async.series([
diff --git a/luciexpress/htdocs/plugins/core/widgets/luci.top_bar.js b/luciexpress/htdocs/plugins/core/widgets/luci.top_bar.js
index 0eb007bed..0f46fd771 100644
--- a/luciexpress/htdocs/plugins/core/widgets/luci.top_bar.js
+++ b/luciexpress/htdocs/plugins/core/widgets/luci.top_bar.js
@@ -7,7 +7,7 @@ $juci.module("core")
replace: true
};
})
-.controller("luciTopBarController", function($scope, $config, $session, $uci, $window, $localStorage, $state, gettext){
+.controller("luciTopBarController", function($scope, $config, $session, $uci, $rpc, $window, $localStorage, $state, gettext){
$uci.sync("system").done(function(){
var system = $uci.system["@system"];
if(system && system.length && system[0].displayname.value){
diff --git a/luciexpress/server.js b/luciexpress/server.js
index b41f13a4f..71dcefd10 100644
--- a/luciexpress/server.js
+++ b/luciexpress/server.js
@@ -82,7 +82,24 @@ app.post('/ubus', function(req, res) {
});
} else {
console.log("JSON_CALL (-> "+config.ubus_uri+"): "+JSON.stringify(data));
-
+
+ function sendResponse(body){
+ var json = JSON.stringify(body);
+ console.log("JSON_RESP: "+json);
+ res.write(json);
+ res.end();
+ }
+
+ var timedOut = false;
+ var timeout = setTimeout(function(){
+ var body = {
+ jsonrpc: "2.0",
+ result: [1, "ETIMEOUT"]
+ };
+ timedOut = true;
+ sendResponse(body);
+ }, 10000);
+
request({
url: config.ubus_uri,
method: "POST",
@@ -91,16 +108,16 @@ app.post('/ubus', function(req, res) {
}, function (error, response, body) {
if(error){
console.log("ERROR: "+error);
- body = JSON.stringify({
+ body = {
jsonrpc: "2.0",
result: [1, String(error)]
- });
+ };
//doLocalRPC();
}
- var json = JSON.stringify(body);
- console.log("JSON_RESP: "+json);
- res.write(json);
- res.end();
+ clearTimeout(timeout);
+ if(!timedOut){
+ sendResponse(body);
+ }
});
//console.log("Unknown RPC call "+name);
//res.end();
@@ -114,11 +131,29 @@ app.post('/ubus', function(req, res) {
});
var server = app.listen(3000, function () {
-
var host = server.address().address;
var port = server.address().port;
- console.log('Example app listening at http://%s:%s', host, port);
-
+ for(var i = 0; i < process.argv.length; i++){
+ switch(process.argv[i]){
+ case "-p": {
+ var paths = process.argv[++i].split(";");
+ paths.map(function(k){
+ var url, path;
+ if(k.indexOf(":") >= 0){
+ var parts = k.split(":");
+ path = parts[1];
+ url = parts[0];
+ } else {
+ url = k.split("/").pop();
+ path = k;
+ }
+ console.log("Adding extra plugin search path: "+path+" at "+url);
+ app.use(url, express.static(path + '/'));
+ });
+ } break;
+ }
+ }
+ console.log('Local server listening on http://%s:%s', host, port);
});