Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/nextcloudpi.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornachoparker <nacho@ownyourbits.com>2017-07-14 00:43:13 +0300
committernachoparker <nacho@ownyourbits.com>2017-08-11 00:17:51 +0300
commit41e71b4cbb02a9c3d0be01d25dd49aa39d06b8c8 (patch)
treeb8a56b7d52bab9298a6b2d188c6c41b5b093d6ac
parentc0a69703aeaf84f8bdad6e9d64d44d1719a77521 (diff)
added ncp-webv0.17.0
-rwxr-xr-xbatch.sh2
-rwxr-xr-xetc/library.sh8
-rw-r--r--etc/nextcloudpi-config.d/nc-nextcloud.sh20
-rw-r--r--ncp-web/csrf.php50
-rw-r--r--ncp-web/favicon.pngbin0 -> 1825 bytes
-rw-r--r--ncp-web/index.php130
-rw-r--r--ncp-web/loading-small.gifbin0 -> 1771 bytes
-rw-r--r--ncp-web/menu.svg1
-rw-r--r--ncp-web/minified.js1
-rw-r--r--ncp-web/ncp-launcher.php107
-rw-r--r--ncp-web/ncp-logo.pngbin0 -> 4842 bytes
-rw-r--r--ncp-web/ncp.css1037
-rw-r--r--ncp-web/ncp.js96
-rw-r--r--nextcloudpi.sh48
-rwxr-xr-xupdate.sh8
15 files changed, 1494 insertions, 14 deletions
diff --git a/batch.sh b/batch.sh
index 7fb33e80..666b9cfd 100755
--- a/batch.sh
+++ b/batch.sh
@@ -30,7 +30,7 @@ NO_HALT_STEP=1 ./installer.sh prepare.sh $IP $IMGBASE ||
./installer.sh $NC_INSTALL $IP $( ls -1t *.img | head -1 ) || exit 1
./installer.sh $NC_CONFIG $IP $( ls -1t *.img | head -1 ) || exit 1
./installer.sh nextcloudpi.sh $IP $( ls -1t *.img | head -1 ) || exit 1
-# ./installer.sh test-devel.sh $IP $( ls -1t *.img | head -1 ) || exit 1
+# ./installer.sh build-devel.sh $IP $( ls -1t *.img | head -1 ) || exit 1
IMGFILE=$( ls -1t *.img | head -1 )
IMGNAME=$( basename "$IMGFILE" _base_prepare_lamp_nc-nextcloud_nc-init_nextcloudpi.img )
diff --git a/etc/library.sh b/etc/library.sh
index 1823cddc..2e25b1ef 100755
--- a/etc/library.sh
+++ b/etc/library.sh
@@ -205,10 +205,16 @@ function install_script()
function activate_script()
{
+ local SCRIPT=$1
+ echo -e "Activating \e[1m$( basename $SCRIPT .sh )\e[0m"
+ launch_script $SCRIPT
+}
+
+function launch_script()
+{
(
local SCRIPT=$1
source ./$SCRIPT
- echo -e "Activating \e[1m$( basename $SCRIPT .sh )\e[0m"
set +x
configure
)
diff --git a/etc/nextcloudpi-config.d/nc-nextcloud.sh b/etc/nextcloudpi-config.d/nc-nextcloud.sh
index 59d4a7ff..385097cb 100644
--- a/etc/nextcloudpi-config.d/nc-nextcloud.sh
+++ b/etc/nextcloudpi-config.d/nc-nextcloud.sh
@@ -116,14 +116,14 @@ EOF
chown ${rootuser}:${htgroup} ${ocpath}/data/.htaccess
fi
- # create and configure opcache dir
- OPCACHEDIR=/var/www/nextcloud/data/.opcache
- sed -i "s|^opcache.file_cache=.*|opcache.file_cache=$OPCACHEDIR|" /etc/php/7.0/mods-available/opcache.ini
- mkdir -p $OPCACHEDIR
- chown -R www-data:www-data $OPCACHEDIR
-
- ## SET APACHE VHOST
- cat > /etc/apache2/sites-available/nextcloud.conf <<'EOF'
+ # create and configure opcache dir
+ OPCACHEDIR=/var/www/nextcloud/data/.opcache
+ sed -i "s|^opcache.file_cache=.*|opcache.file_cache=$OPCACHEDIR|" /etc/php/7.0/mods-available/opcache.ini
+ mkdir -p $OPCACHEDIR
+ chown -R www-data:www-data $OPCACHEDIR
+
+## SET APACHE VHOST
+ cat > /etc/apache2/sites-available/nextcloud.conf <<'EOF'
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
DocumentRoot /var/www/nextcloud
@@ -144,10 +144,10 @@ EOF
</Directory>
</IfModule>
EOF
- a2ensite nextcloud
+ a2ensite nextcloud
echo "Setting up Apache..."
-cat > /etc/apache2/sites-available/000-default.conf <<'EOF'
+ cat > /etc/apache2/sites-available/000-default.conf <<'EOF'
<VirtualHost _default_:80>
DocumentRoot /var/www/nextcloud
<IfModule mod_rewrite.c>
diff --git a/ncp-web/csrf.php b/ncp-web/csrf.php
new file mode 100644
index 00000000..68574599
--- /dev/null
+++ b/ncp-web/csrf.php
@@ -0,0 +1,50 @@
+<?php
+///
+// NextcloudPi Web Panel CSRF protection library
+//
+// Inspired by http://blog.ircmaxell.com/2013/02/preventing-csrf-attacks.html
+//
+// Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
+// GPL licensed (see end of file) * Use at your own risk!
+//
+// More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/
+///
+
+function getCSRFToken()
+{
+ $nonce = base64_encode( random_bytes(32) );
+ if (empty($_SESSION['csrf_tokens']))
+ $_SESSION['csrf_tokens'] = array();
+
+ $_SESSION['csrf_tokens'][$nonce] = true;
+ return $nonce;
+}
+
+function validateCSRFToken($token)
+{
+ if (isset($_SESSION['csrf_tokens'][$token]))
+ {
+ unset($_SESSION['csrf_tokens'][$token]);
+ return true;
+ }
+ return false;
+}
+
+
+// License
+//
+// This script is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This script is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this script; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
+?>
diff --git a/ncp-web/favicon.png b/ncp-web/favicon.png
new file mode 100644
index 00000000..759614a0
--- /dev/null
+++ b/ncp-web/favicon.png
Binary files differ
diff --git a/ncp-web/index.php b/ncp-web/index.php
new file mode 100644
index 00000000..59730370
--- /dev/null
+++ b/ncp-web/index.php
@@ -0,0 +1,130 @@
+<!--
+ NextcloudPi Web Panel javascript library
+
+ Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
+ GPL licensed (see end of file) * Use at your own risk!
+
+ More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/
+-->
+
+<!DOCTYPE html>
+<html class="ng-csp" data-placeholder-focus="false" lang="en" >
+<head>
+ <meta charset="utf-8">
+ <title>NextCloudPi Panel</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <meta name="referrer" content="never">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
+ <meta name="mobile-web-app-capable" content="yes">
+<?php
+ session_start();
+
+ // security headers
+ header("Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';");
+ header("X-XSS-Protection: 1; mode=block");
+ header("X-Content-Type-Options: nosniff");
+ header("X-Robots-Tag: none");
+ header("X-Permitted-Cross-Domain-Policies: none");
+ header("X-Frame-Options: DENY");
+ header("Cache-Control: max-age=15778463");
+ ini_set('session.cookie_httponly', 1);
+ if ( isset($_SERVER['HTTPS']) )
+ ini_set('session.cookie_secure', 1);
+
+ // HTTP2 push headers
+ header("Link: </minified.js>; rel=preload; as=script;,</ncp.js>; rel=preload; as=script;,</ncp.css>; rel=preload; as=style;,</ncp-logo.png>; rel=preload; as=image;, </loading-small.gif>; rel=preload; as=image;, rel=preconnect href=ncp-launcher.php;");
+?>
+<link rel="icon" type="image/png" href="favicon.png" />
+<link rel="stylesheet" href="ncp.css">
+</head>
+<body id="body-user">
+ <noscript>
+ <div id="nojavascript"> <div>This application requires JavaScript for correct operation. Please <a href="http://enable-javascript.com/" target="_blank" rel="noreferrer">enable JavaScript</a> and reload the page. </div> </div>
+ </noscript>
+ <div id="notification-container">
+ <div id="notification"></div>
+ </div>
+
+ <header role="banner"><div id="header">
+ <div id="header-left">
+ <a href="https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/"
+ id="nextcloudpi" tabindex="1" target="_blank">
+ <div class="logo-icon">
+ <h1 class="hidden-visually">NextCloudPi</h1>
+ </div>
+ </a>
+ </div>
+ </header>
+
+ <div id="content-wrapper">
+ <div id="content" class="app-files" role="main">
+ <div id="app-navigation">
+ <ul id="ncp-options">
+ <?php
+
+ // fill options with contents from directory
+ $path = '/usr/local/etc/nextcloudpi-config.d/';
+ $files = array_diff(scandir($path), array('.', '..','nc-wifi.sh'));
+
+ foreach($files as $file)
+ {
+ $script = pathinfo( $file , PATHINFO_FILENAME );
+ $fh = fopen( $path . $file ,'r');
+ while ($line = fgets($fh))
+ if ( preg_match('/^DESCRIPTION="(.*)"$/', $line, $matches) )
+ {
+ echo "<li id=\"$script\" class=\"nav-recent\">";
+ echo "<a href=\"#\"> $script </a>";
+ echo "<input type=\"hidden\" value=\"$matches[1]\" />";
+ echo "</li>";
+ }
+ fclose($fh);
+ }
+ ?>
+ </ul>
+ </div>
+
+ <div id="app-content">
+ <h2 id="config-box-title">Configure NextCloudPi features</h2>
+ <br/>
+ <div id="config-box-wrapper" class="hidden">
+ <form>
+ <div id="config-box"></div>
+ <div id="config-button-wrapper">
+ <button id="config-button">Run</button>
+ <img id="loading-gif" src="loading-small.gif">
+ </div>
+ </form>
+ <textarea readonly id="details-box" rows="25" cols="60"></textarea>
+ </div>
+ </div>
+
+ </div>
+
+ <?php
+ include ('csrf.php');
+ echo '<input type="hidden" id="csrf-token" name="csrf-token" value="' . getCSRFToken() . '"/>';
+ ?>
+ <script src="minified.js"></script>
+ <script src="ncp.js"></script>
+</body>
+</html>
+
+<!--
+ License
+
+ This script is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This script is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this script; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+-->
diff --git a/ncp-web/loading-small.gif b/ncp-web/loading-small.gif
new file mode 100644
index 00000000..83587a63
--- /dev/null
+++ b/ncp-web/loading-small.gif
Binary files differ
diff --git a/ncp-web/menu.svg b/ncp-web/menu.svg
new file mode 100644
index 00000000..222b39ea
--- /dev/null
+++ b/ncp-web/menu.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"><path d="M2 2v2h12V2zm0 5v2h12V7zm0 5v2h12v-2z"/></svg> \ No newline at end of file
diff --git a/ncp-web/minified.js b/ncp-web/minified.js
new file mode 100644
index 00000000..251866b7
--- /dev/null
+++ b/ncp-web/minified.js
@@ -0,0 +1 @@
+/^u/.test(typeof define)&&function(a){var b=this.require=function(b){return a[b]};this.define=function(c,d){a[c]=a[c]||d(b)}}({}),define("minified",function(){function a(a){return a.substr(0,3)}function b(a){return a!=Eb?""+a:""}function c(a){return"string"==typeof a}function d(a){return!!a&&"object"==typeof a}function e(a){return a&&a.nodeType}function f(a){return"number"==typeof a}function g(a){return d(a)&&!!a.getDay}function h(a){return!0===a||!1===a}function i(a){var b=typeof a;return"object"==b?!(!a||!a.getDay):"string"==b||"number"==b||h(a)}function j(a){return a}function k(a){return a+1}function l(a,c,d){return b(a).replace(c,d!=Eb?d:"")}function m(a){return l(a,/[\\\[\]\/{}()*+?.$|^-]/g,"\\$&")}function n(a){return l(a,/^\s+|\s+$/g)}function o(a,b,c){for(var d in a)a.hasOwnProperty(d)&&b.call(c||a,d,a[d]);return a}function p(a,b,c){if(a)for(var d=0;d<a.length;d++)b.call(c||a,a[d],d);return a}function q(a,b,c){var d=[],e=db(b)?b:function(a){return b!=a};return p(a,function(b,f){e.call(c||a,b,f)&&d.push(b)}),d}function r(a,b,c,d){var e=[];return a(b,function(a,f){eb(a=c.call(d||b,a,f))?p(a,function(a){e.push(a)}):a!=Eb&&e.push(a)}),e}function s(a,b,c){return r(p,a,b,c)}function t(a){var b=0;return o(a,function(){b++}),b}function u(a){var b=[];return o(a,function(a){b.push(a)}),b}function v(a,b,c){var d=[];return p(a,function(e,f){d.push(b.call(c||a,e,f))}),d}function w(a,b){if(eb(a)){var c=vb(b);return M(G(a,0,c.length),c)}return b!=Eb&&a.substr(0,b.length)==b}function x(a,b){if(eb(a)){var c=vb(b);return M(G(a,-c.length),c)||!c.length}return b!=Eb&&a.substr(a.length-b.length)==b}function y(a){var b=a.length;return eb(a)?new ub(v(a,function(){return a[--b]})):l(a,/[\s\S]/g,function(){return a.charAt(--b)})}function z(a,b){var c={};return p(a,function(a){c[a]=b}),c}function A(a,b){var c,d=b||{};for(c in a)d[c]=a[c];return d}function B(a,b){for(var c=b,d=0;d<a.length;d++)c=A(a[d],c);return c}function C(a){return db(a)?a:function(b,c){return a===b?c:void 0}}function D(a,b,c){return b==Eb?c:0>b?Math.max(a.length+b,0):Math.min(a.length,b)}function E(a,b,c,d){b=C(b),d=D(a,d,a.length);for(var e=D(a,c,0);d>e;e++)if((c=b.call(a,a[e],e))!=Eb)return c}function F(a,b,c,d){b=C(b),d=D(a,d,-1);for(var e=D(a,c,a.length-1);e>d;e--)if((c=b.call(a,a[e],e))!=Eb)return c}function G(a,b,c){var d=[];if(a)for(c=D(a,c,a.length),b=D(a,b,0);c>b;b++)d.push(a[b]);return d}function H(a){return v(a,j)}function I(a){return function(){return new ub(O(a,arguments))}}function J(a){var b={};return q(a,function(a){return b[a]?!1:b[a]=1})}function K(a,b){var c=z(b,1);return q(a,function(a){var b=c[a];return c[a]=0,b})}function L(a,b){for(var c=0;c<a.length;c++)if(a[c]==b)return!0;return!1}function M(a,b){var c,d=db(a)?a():a,e=db(b)?b():b;return d==e?!0:d==Eb||e==Eb?!1:i(d)||i(e)?g(d)&&g(e)&&+d==+e:eb(d)?d.length==e.length&&!E(d,function(a,b){return M(a,e[b])?void 0:!0}):!eb(e)&&(c=u(d)).length==t(e)&&!E(c,function(a){return M(d[a],e[a])?void 0:!0})}function N(a,b,c){return db(a)?a.apply(c&&b,v(c||b,j)):void 0}function O(a,b,c){return v(a,function(a){return N(a,b,c)})}function P(a,b,c,d){return function(){return N(a,b,s([c,arguments,d],j))}}function Q(a,b){for(var c=0>b?"-":"",d=(c?-b:b).toFixed(0);d.length<a;)d="0"+d;return c+d}function R(a,b,c){var d,e=0,f=c?b:y(b);return a=(c?a:y(a)).replace(/./g,function(a){return"0"==a?(d=!1,f.charAt(e++)||"0"):"#"==a?(d=!0,f.charAt(e++)||""):d&&!f.charAt(e)?"":a}),c?a:b.substr(0,b.length-e)+y(a)}function S(a,b,c){return b!=Eb&&a?60*parseFloat(a[b]+a[b+1])+parseFloat(a[b]+a[b+2])+c.getTimezoneOffset():0}function T(a){return new Date(+a)}function U(a,b,c){return a["set"+b](a["get"+b]()+c),a}function V(a,b,c){return c==Eb?V(new Date,a,b):U(T(a),b.charAt(0).toUpperCase()+b.substr(1),c)}function W(a,b,c){var d=+b,e=+c,f=e-d;if(0>f)return-W(a,c,b);if(b={milliseconds:1,seconds:1e3,minutes:6e4,hours:36e5}[a])return f/b;for(b=a.charAt(0).toUpperCase()+a.substr(1),a=Math.floor(f/{fullYear:31536e6,month:2628e6,date:864e5}[a]-2),d=U(new Date(d),b,a),f=a;1.2*a+4>f;f++)if(+U(d,b,1)>e)return f}function X(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}function Y(a){return l(a,/[\x00-\x1f'"\u2028\u2029]/g,X)}function Z(a,b){function c(a,c){var d=[];return e.call(c||a,a,function(a,b){eb(a)?p(a,function(a,c){b.call(a,a,c)}):o(a,function(a,c){b.call(c,a,c)})},b||j,function(){N(d.push,d,arguments)},vb),d.join("")}if(Lb[a])return Lb[a];var d="with(_.isObject(obj)?obj:{}){"+v(a.split(/{{|}}}?/g),function(a,b){var c,d=n(a),e=l(d,/^{/),d=d==e?"esc(":"";return b%2?(c=/^each\b(\s+([\w_]+(\s*,\s*[\w_]+)?)\s*:)?(.*)/.exec(e))?"each("+(n(c[4])?c[4]:"this")+", function("+c[2]+"){":(c=/^if\b(.*)/.exec(e))?"if("+c[1]+"){":(c=/^else\b\s*(if\b(.*))?/.exec(e))?"}else "+(c[1]?"if("+c[2]+")":"")+"{":(c=/^\/(if)?/.exec(e))?c[1]?"}\n":"});\n":(c=/^(var\s.*)/.exec(e))?c[1]+";":(c=/^#(.*)/.exec(e))?c[1]:(c=/(.*)::\s*(.*)/.exec(e))?"print("+d+'_.formatValue("'+Y(c[2])+'",'+(n(c[1])?c[1]:"this")+(d&&")")+"));\n":"print("+d+(n(e)?e:"this")+(d&&")")+");\n":a?'print("'+Y(a)+'");\n':void 0}).join("")+"}",e=Function("obj","each","esc","print","_",d);return 99<Mb.push(c)&&delete Lb[Mb.shift()],Lb[a]=c}function $(a){return l(a,/[<>'"&]/g,function(a){return"&#"+a.charCodeAt(0)+";"})}function _(a,b){return Z(a,$)(b)}function ab(a){return function(b,c){return new ub(a(this,b,c))}}function bb(a){return function(b,c,d){return a(this,b,c,d)}}function cb(a){return function(b,c,d){return new ub(a(b,c,d))}}function db(a){return"function"==typeof a&&!a.item}function eb(a){return a&&a.length!=Eb&&!c(a)&&!e(a)&&!db(a)&&a!==xb}function fb(a){return parseFloat(l(a,/^[^\d-]+/))}function gb(a){return a.Nia=a.Nia||++Ab}function hb(a,b){var c,d=[],e={};return rb(a,function(a){rb(b(a),function(a){e[c=gb(a)]||(d.push(a),e[c]=!0)})}),d}function ib(a,b){var c={$position:"absolute",$visibility:"hidden",$display:"block",$height:Eb},d=a.get(c),c=a.set(c).get("clientHeight");return a.set(d),c*b+"px"}function jb(a){Bb?Bb.push(a):setTimeout(a,0)}function kb(a,b,c){return ob(a,b,c)[0]}function lb(a,b,c){return a=nb(document.createElement(a)),eb(b)||b!=Eb&&!d(b)?a.add(b):a.set(b).add(c)}function mb(a){return r(rb,a,function(a){return eb(a)?mb(a):(e(a)&&(a=a.cloneNode(!0),a.removeAttribute&&a.removeAttribute("id")),a)})}function nb(a,b,c){return db(a)?jb(a):new ub(ob(a,b,c))}function ob(a,b,d){function f(a){return eb(a)?r(rb,a,f):a}function g(a){return q(r(rb,a,f),function(a){for(;a=a.parentNode;)if(a==b[0]||d)return a==b[0]})}return b?1!=(b=ob(b)).length?hb(b,function(b){return ob(a,b,d)}):c(a)?1!=e(b[0])?[]:d?g(b[0].querySelectorAll(a)):b[0].querySelectorAll(a):g(a):c(a)?document.querySelectorAll(a):r(rb,a,f)}function pb(a,b){function d(a,b){var c=RegExp("(^|\\s+)"+a+"(?=$|\\s)","i");return function(d){return a?c.test(d[b]):!0}}var g,h,i={},j=i;return db(a)?a:f(a)?function(b,c){return c==a}:!a||"*"==a||c(a)&&(j=/^([\w-]*)\.?([\w-]*)$/.exec(a))?(g=d(j[1],"tagName"),h=d(j[2],"className"),function(a){return 1==e(a)&&g(a)&&h(a)}):b?function(c){return nb(a,b).find(c)!=Eb}:(nb(a).each(function(a){i[gb(a)]=!0}),function(a){return i[gb(a)]})}function qb(a){var b=pb(a);return function(a){return b(a)?Eb:!0}}function rb(a,b){return eb(a)?p(a,b):a!=Eb&&b(a,0),a}function sb(){this.state=null,this.values=[],this.parent=null}function tb(){var a,b,c=[],e=arguments,f=e.length,g=0,h=0,i=new sb;return i.errHandled=function(){h++,i.parent&&i.parent.errHandled()},a=i.fire=function(a,b){return null==i.state&&null!=a&&(i.state=!!a,i.values=eb(b)?b:[b],setTimeout(function(){p(c,function(a){a()})},0)),i},p(e,function j(b,c){try{b.then?b.then(function(b){(d(b)||db(b))&&db(b.then)?j(b,c):(i.values[c]=H(arguments),++g==f&&a(!0,2>f?i.values[c]:i.values))},function(){i.values[c]=H(arguments),a(!1,2>f?i.values[c]:[i.values[c][0],i.values,c])}):b(function(){a(!0,H(arguments))},function(){a(!1,H(arguments))})}catch(e){a(!1,[e,i.values,c])}}),i.stop=function(){return p(e,function(a){a.stop&&a.stop()}),i.stop0&&N(i.stop0)},b=i.then=function(a,b){function e(){try{var c=i.state?a:b;db(c)?function g(a){try{var b,c=0;if((d(a)||db(a))&&db(b=a.then)){if(a===f)throw new TypeError;b.call(a,function(a){c++||g(a)},function(a){c++||f.fire(!1,[a])}),f.stop0=a.stop}else f.fire(!0,[a])}catch(e){if(!c++&&(f.fire(!1,[e]),!h))throw e}}(N(c,wb,i.values)):f.fire(i.state,i.values)}catch(e){if(f.fire(!1,[e]),!h)throw e}}var f=tb();return db(b)&&i.errHandled(),f.stop0=i.stop,f.parent=i,null!=i.state?setTimeout(e,0):c.push(e),f},i.always=function(a){return b(a,a)},i.error=function(a){return b(0,a)},i}function ub(a,b){var c,d,e,f,g,h=0;if(a)for(c=0,d=a.length;d>c;c++)if(e=a[c],b&&eb(e))for(f=0,g=e.length;g>f;f++)this[h++]=e[f];else this[h++]=e;else this[h++]=b;this.length=h,this._=!0}function vb(){return new ub(arguments,!0)}var wb,xb=window,yb={},zb={},Ab=1,Bb=/^[ic]/.test(document.readyState)?Eb:[],Cb={},Db=0,Eb=null,Fb="January,February,March,April,May,June,July,August,September,October,November,December".split(/,/g),Gb=v(Fb,a),Hb="Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(/,/g),Ib=v(Hb,a),Jb={y:["FullYear",j],Y:["FullYear",function(a){return a%100}],M:["Month",k],n:["Month",Gb],N:["Month",Fb],d:["Date",j],m:["Minutes",j],H:["Hours",j],h:["Hours",function(a){return a%12||12}],k:["Hours",k],K:["Hours",function(a){return a%12}],s:["Seconds",j],S:["Milliseconds",j],a:["Hours","am,am,am,am,am,am,am,am,am,am,am,am,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm".split(/,/g)],w:["Day",Ib],W:["Day",Hb],z:["TimezoneOffset",function(a,b,c){return c?c:(b=0>a?-a:a,(a>0?"-":"+")+Q(2,Math.floor(b/60))+Q(2,b%60))}]},Kb={y:0,Y:[0,-2e3],M:[1,1],n:[1,Gb],N:[1,Fb],d:2,m:4,H:3,h:3,K:[3,1],k:[3,1],s:5,S:6,a:[3,"am,pm".split(/,/g)]},Lb={},Mb=[];return A({each:bb(p),filter:ab(q),collect:ab(s),map:ab(v),toObject:bb(z),equals:bb(M),sub:ab(G),reverse:bb(y),find:bb(E),findLast:bb(F),startsWith:bb(w),endsWith:bb(x),contains:bb(L),call:ab(O),array:bb(H),unite:bb(I),merge:bb(B),uniq:ab(J),intersection:ab(K),join:function(a){return v(this,j).join(a)},reduce:function(a,b){return p(this,function(c,d){b=a.call(this,b,c,d)}),b},sort:function(a){return new ub(v(this,j).sort(a))},remove:function(){rb(this,function(a){a.parentNode.removeChild(a)})},text:function(){return r(rb,this,function(a){return a.textContent}).join("")},trav:function(a,b,c){var d=f(b),e=pb(d?Eb:b),g=d?b:c;return new ub(hb(this,function(b){for(var c=[];(b=b[a])&&c.length!=g;)e(b)&&c.push(b);return c}))},next:function(a,b){return this.trav("nextSibling",a,b||1)},up:function(a,b){return this.trav("parentNode",a,b||1)},select:function(a,b){return nb(a,this,b)},is:function(a){return!this.find(qb(a))},only:function(a){return new ub(q(this,pb(a)))},not:function(a){return new ub(q(this,qb(a)))},get:function(a,b){var d,e,f,g=this,h=g[0];return h?c(a)?(d=/^(\W*)(.*)/.exec(l(a,/^%/,"@data-")),e=d[1],h=zb[e]?zb[e](this,d[2]):"$"==a?g.get("className"):"$$"==a?g.get("@style"):"$$slide"==a?g.get("$height"):"$$fade"==a||"$$show"==a?"hidden"==g.get("$visibility")||"none"==g.get("$display")?0:"$$fade"==a?isNaN(g.get("$opacity",!0))?1:g.get("$opacity",!0):1:"$"==e?xb.getComputedStyle(h,Eb).getPropertyValue(l(d[2],/[A-Z]/g,function(a){return"-"+a.toLowerCase()})):"@"==e?h.getAttribute(d[2]):h[d[2]],b?fb(h):h):(f={},(eb(a)?rb:o)(a,function(a){f[a]=g.get(a,b)}),f):void 0},set:function(a,b){var d,e,f=this;return b!==wb?(d=/^(\W*)(.*)/.exec(l(l(a,/^\$float$/,"cssFloat"),/^%/,"@data-")),e=d[1],yb[e]?yb[e](this,d[2],b):"$$fade"==a?this.set({$visibility:b?"visible":"hidden",$opacity:b}):"$$slide"==a?f.set({$visibility:b?"visible":"hidden",$overflow:"hidden",$height:/px/.test(b)?b:function(a,c,d){return ib(nb(d),b)}}):"$$show"==a?b?f.set({$visibility:b?"visible":"hidden",$display:""}).set({$display:function(a){return"none"==a?"block":a}}):f.set({$display:"none"}):"$$"==a?f.set("@style",b):rb(this,function(c,f){var g=db(b)?b(nb(c).get(a),f,c):b;"$"==e?d[2]?c.style[d[2]]=g:rb(g&&g.split(/\s+/),function(a){var b=l(a,/^[+-]/),d=c.className||"",e=l(d,RegExp("(^|\\s+)"+b+"(?=$|\\s)"));(/^\+/.test(a)||b==a&&d==e)&&(e+=" "+b),c.className=n(e)}):"$$scrollX"==a?c.scroll(g,nb(c).get("$$scrollY")):"$$scrollY"==a?c.scroll(nb(c).get("$$scrollX"),g):"@"==e?g==Eb?c.removeAttribute(d[2]):c.setAttribute(d[2],g):c[d[2]]=g})):c(a)||db(a)?f.set("$",a):o(a,function(a,b){f.set(a,b)}),f},show:function(){return this.set("$$show",1)},hide:function(){return this.set("$$show",0)},add:function(a,b){return this.each(function(c,d){function f(a){eb(a)?rb(a,f):db(a)?f(a(c,d)):a!=Eb&&(a=e(a)?a:document.createTextNode(a),g?g.parentNode.insertBefore(a,g.nextSibling):b?b(a,c,c.parentNode):c.appendChild(a),g=a)}var g;f(d&&!db(a)?mb(a):a)})},fill:function(a){return this.each(function(a){nb(a.childNodes).remove()}).add(a)},addAfter:function(a){return this.add(a,function(a,b,c){c.insertBefore(a,b.nextSibling)})},addBefore:function(a){return this.add(a,function(a,b,c){c.insertBefore(a,b)})},addFront:function(a){return this.add(a,function(a,b){b.insertBefore(a,b.firstChild)})},replace:function(a){return this.add(a,function(a,b,c){c.replaceChild(a,b)})},clone:ab(mb),animate:function(a,b,c){var d,e=tb(),f=this,g=r(rb,this,function(b,d){var e,f=nb(b),g={};return o(e=f.get(a),function(c,e){var h=a[c];g[c]=db(h)?h(e,d,b):"$$slide"==c?ib(f,h):h}),f.dial(e,g,c)}),h=b||500;return e.stop0=function(){return e.fire(!1),d()},d=nb.loop(function(a){O(g,[a/h]),a>=h&&(d(),e.fire(!0,[f]))}),e},dial:function(a,c,d){function e(a,b){return/^#/.test(a)?parseInt(6<a.length?a.substr(2*b+1,2):(a=a.charAt(b+1))+a,16):fb(a.split(",")[b])}var f=this,g=d||0,h=db(g)?g:function(a,b,c){return c*(b-a)*(g+(1-g)*c*(3-2*c))+a};return function(d){o(a,function(a,g){var i=c[a],j=0;f.set(a,0>=d?g:d>=1?i:/^#|rgb\(/.test(i)?"rgb("+Math.round(h(e(g,j),e(i,j++),d))+","+Math.round(h(e(g,j),e(i,j++),d))+","+Math.round(h(e(g,j),e(i,j++),d))+")":l(i,/-?[\d.]+/,b(h(fb(g),fb(i),d))))})}},toggle:function(a,b,c,d){var e,f,g=this,h=!1;return b?(g.set(a),function(i){i!==h&&(f=(h=!0===i||!1===i?i:!h)?b:a,c?(e=g.animate(f,e?e.stop():c,d)).then(function(){e=Eb}):g.set(f))}):g.toggle(l(a,/\b(?=\w)/g,"-"),l(a,/\b(?=\w)/g,"+"))},values:function(a){var c=a||{};return this.each(function(a){var d=a.name||a.id,e=b(a.value);if(/form/i.test(a.tagName))for(d=0;d<a.elements.length;d++)nb(a.elements[d]).values(c);else!d||/ox|io/i.test(a.type)&&!a.checked||(c[d]=c[d]==Eb?e:r(rb,[c[d],e],j))}),c},offset:function(){for(var a=this[0],b={x:0,y:0};a;)b.x+=a.offsetLeft,b.y+=a.offsetTop,a=a.offsetParent;return b},on:function(a,d,e,f,g){return db(d)?this.on(Eb,a,d,e,f):c(f)?this.on(a,d,e,Eb,f):this.each(function(c,h){rb(a?ob(a,c):c,function(a){rb(b(d).split(/\s/),function(b){function c(b,c,d){var j,l=!g;if(d=g?d:a,g)for(j=pb(g,a);d&&d!=a&&!(l=j(d));)d=d.parentNode;return!l||i!=b||e.apply(nb(d),f||[c,h])&&"?"==k||"|"==k}function d(a){c(i,a,a.target)||(a.preventDefault(),a.stopPropagation())}var i=l(b,/[?|]/g),k=l(b,/[^?|]/g),m=("blur"==i||"focus"==i)&&!!g,n=Ab++;a.addEventListener(i,d,m),a.M||(a.M={}),a.M[n]=c,e.M=r(rb,[e.M,function(){a.removeEventListener(i,d,m),delete a.M[n]}],j)})})})},onOver:function(a,b){var c=this,d=[];return db(b)?this.on(a,"|mouseover |mouseout",function(a,e){var f=a.relatedTarget||a.toElement,g="mouseout"!=a.type;d[e]===g||!g&&f&&(f==c[e]||nb(f).up(c[e]).length)||(d[e]=g,b.call(this,g,a))}):this.onOver(Eb,a)},onFocus:function(a,b,c){return db(b)?this.on(a,"|blur",b,[!1],c).on(a,"|focus",b,[!0],c):this.onFocus(Eb,a,b)},onChange:function(a,b,c){return db(b)?this.on(a,"|input |change |click",function(a,c){var d=this[0],e=/ox|io/i.test(d.type)?d.checked:d.value;d.NiaP!=e&&b.call(this,d.NiaP=e,c)},c):this.onChange(Eb,a,b)},onClick:function(a,b,c,d){return db(b)?this.on(a,"click",b,c,d):this.onClick(Eb,a,b,c)},trigger:function(a,b){return this.each(function(c){for(var d=!0,e=c;e&&d;)o(e.M,function(e,f){d=d&&f(a,b,c)}),e=e.parentNode})},per:function(a,b){if(db(a))for(var c=this.length,d=0;c>d;d++)a.call(this,new ub(Eb,this[d]),d);else nb(a,this).per(b);return this},ht:function(a,b){var c=2<arguments.length?B(G(arguments,1)):b;return this.set("innerHTML",db(a)?a(c):/{{/.test(a)?_(a,c):/^#\S+$/.test(a)?_(kb(a).text,c):a)}},ub.prototype),A({request:function(a,c,d,e){e=e||{};var f,g=0,h=tb(),i=d&&d.constructor==e.constructor;try{h.xhr=f=new XMLHttpRequest,h.stop0=function(){f.abort()},i&&(d=r(o,d,function(a,b){return r(rb,b,function(b){return encodeURIComponent(a)+(b!=Eb?"="+encodeURIComponent(b):"")})}).join("&")),d==Eb||/post/i.test(a)||(c+="?"+d,d=Eb),f.open(a,c,!0,e.user,e.pass),i&&/post/i.test(a)&&f.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),o(e.headers,function(a,b){f.setRequestHeader(a,b)}),o(e.xhr,function(a,b){f[a]=b}),f.onreadystatechange=function(){4!=f.readyState||g++||(200<=f.status&&300>f.status?h.fire(!0,[f.responseText,f]):h.fire(!1,[f.status,f.responseText,f]))},f.send(d)}catch(j){g||h.fire(!1,[0,Eb,b(j)])}return h},toJSON:JSON.stringify,parseJSON:JSON.parse,ready:jb,loop:function(a){function b(a){o(Cb,function(b,c){c(a)}),Db&&g(b)}function c(){return Cb[f]&&(delete Cb[f],Db--),e}var d,e=0,f=Ab++,g=xb.requestAnimationFrame||function(a){setTimeout(function(){a(+new Date)},33)};return Cb[f]=function(b){d=d||b,a(e=b-d,c)},Db++||g(b),c},off:function(a){O(a.M),a.M=Eb},setCookie:function(a,b,c,e){document.cookie=a+"="+(e?b:escape(b))+(c?"; expires="+(d(c)?c:new Date(+new Date+864e5*c)).toUTCString():"")},getCookie:function(a,b){var c,d=(c=RegExp("(^|;)\\s*"+a+"=([^;]*)").exec(document.cookie))&&c[2];return b?d:d&&unescape(d)},wait:function(a,b){var c=tb(),d=setTimeout(function(){c.fire(!0,b)},a);return c.stop0=function(){c.fire(!1),clearTimeout(d)},c}},nb),A({filter:cb(q),collect:cb(s),map:cb(v),sub:cb(G),reverse:y,each:p,toObject:z,find:E,findLast:F,contains:L,startsWith:w,endsWith:x,equals:M,call:cb(O),array:H,unite:I,merge:B,uniq:cb(J),intersection:cb(K),keys:cb(u),values:cb(function(a,b){var c=[];return b?p(b,function(b){c.push(a[b])}):o(a,function(a,b){c.push(b)}),c}),copyObj:A,extend:function(a){return B(G(arguments,1),a)},range:function(a,b){for(var c=[],d=b==Eb?a:b,e=b!=Eb?a:0;d>e;e++)c.push(e);return new ub(c)},bind:P,partial:function(a,b,c){return P(a,this,b,c)},eachObj:o,mapObj:function(a,b,c){var d={};return o(a,function(e,f){d[e]=b.call(c||a,e,f)}),d},filterObj:function(a,b,c){var d={};return o(a,function(e,f){b.call(c||a,e,f)&&(d[e]=f)}),d},isList:eb,isFunction:db,isObject:d,isNumber:f,isBool:h,isDate:g,isValue:i,isString:c,toString:b,dateClone:T,dateAdd:V,dateDiff:W,dateMidnight:function(a){return a=a||new Date,new Date(a.getFullYear(),a.getMonth(),a.getDate())},pad:Q,formatValue:function(a,d){var e,h,i=l(a,/^\?/);return g(d)?((h=/^\[(([+-])(\d\d)(\d\d))\]\s*(.*)/.exec(i))&&(e=h[1],d=V(d,"minutes",S(h,2,d)),i=h[5]),l(i,/(\w)(\1*)(?:\[([^\]]+)\])?/g,function(a,b,f,g){return(b=Jb[b])&&(a=d["get"+b[0]](),g=g&&g.split(","),a=eb(b[1])?(g||b[1])[a]:b[1](a,g,e),a==Eb||c(a)||(a=Q(f.length+1,a))),a})):E(i.split(/\s*\|\s*/),function(a){var c,e;if(c=/^([<>]?)(=?)([^:]*?)\s*:\s*(.*)$/.exec(a)){if(a=d,e=+c[3],(isNaN(e)||!f(a))&&(a=a==Eb?"null":b(a),e=c[3]),c[1]){if(!c[2]&&a==e||"<"==c[1]&&a>e||">"==c[1]&&e>a)return Eb}else if(a!=e)return Eb;c=c[4]}else c=a;return f(d)?c.replace(/[0#](.*[0#])?/,function(a){var b,c=/^([^.]+)(\.)([^.]+)$/.exec(a)||/^([^,]+)(,)([^,]+)$/.exec(a),e=0>d?"-":"",f=/(\d+)(\.(\d+))?/.exec((e?-d:d).toFixed(c?c[3].length:0));return a=c?c[1]:a,b=c?R(c[3],l(f[3],/0+$/),!0):"",(e?"-":"")+("#"==a?f[1]:R(a,f[1]))+(b.length?c[2]:"")+b}):c})},parseDate:function(a,b){var c,d,e,f,g,h,i,j,k,o={},p=1,q=l(a,/^\?/);if(q!=a&&!n(b))return Eb;if((e=/^\[([+-])(\d\d)(\d\d)\]\s*(.*)/.exec(q))&&(c=e,q=e[4]),!(e=RegExp(q.replace(/(.)(\1*)(?:\[([^\]]*)\])?/g,function(a,b,c,e){return/[dmhkyhs]/i.test(b)?(o[p++]=b,a=c.length+1,"(\\d"+(2>a?"+":"{1,"+a+"}")+")"):"z"==b?(d=p,p+=3,"([+-])(\\d\\d)(\\d\\d)"):/[Nna]/.test(b)?(o[p++]=[b,e&&e.split(",")],"([a-zA-Z\\u0080-\\u1fff]+)"):/w/i.test(b)?"[a-zA-Z\\u0080-\\u1fff]+":/\s/.test(b)?"\\s+":m(a)})).exec(b)))return wb;for(q=[0,0,0,0,0,0,0],f=1;p>f;f++)if(g=e[f],h=o[f],eb(h)){if(i=h[0],j=Kb[i],k=j[0],h=E(h[1]||j[1],function(a,b){return w(g.toLowerCase(),a.toLowerCase())?b:void 0}),h==Eb)return wb;q[k]="a"==i?q[k]+12*h:h}else h&&(i=parseFloat(g),j=Kb[h],eb(j)?q[j[0]]+=i-j[1]:q[j]+=i);return q=new Date(q[0],q[1],q[2],q[3],q[4],q[5],q[6]),V(q,"minutes",-S(c,1,q)-S(e,d,q))},parseNumber:function(a,b){var c=l(a,/^\?/);return c==a||n(b)?(c=/(^|[^0#.,])(,|[0#.]*,[0#]+|[0#]+\.[0#]+\.[0#.,]*)($|[^0#.,])/.test(c)?",":".",c=parseFloat(l(l(l(b,","==c?/\./g:/,/g),c,"."),/^[^\d-]*(-?\d)/,"$1")),isNaN(c)?wb:c):Eb},trim:n,isEmpty:function(a,b){return a==Eb||!a.length||b&&/^\s*$/.test(a)},escapeRegExp:m,escapeHtml:$,format:function(a,b,c){return Z(a,c)(b)},template:Z,formatHtml:_,promise:tb},vb),document.addEventListener("DOMContentLoaded",function(){O(Bb),Bb=Eb},!1),{HTML:function(){var a=lb("div");return vb(N(a.ht,a,arguments)[0].childNodes)},_:vb,$:nb,$$:kb,EE:lb,M:ub,getter:zb,setter:yb}}); \ No newline at end of file
diff --git a/ncp-web/ncp-launcher.php b/ncp-web/ncp-launcher.php
new file mode 100644
index 00000000..43df0c8e
--- /dev/null
+++ b/ncp-web/ncp-launcher.php
@@ -0,0 +1,107 @@
+<?php
+///
+// NextcloudPi Web Panel backend
+//
+// Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
+// GPL licensed (see end of file) * Use at your own risk!
+//
+// More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/
+///
+
+include ('csrf.php');
+
+session_start();
+
+if ( !$_POST['ref'] ) exit( '{ "output": "Invalid request" }' );
+
+if ( $_POST['action'] == "cfgreq" )
+{
+ //CSFR check
+ $token = isset($_POST['csrf_token']) ? $_POST['csrf_token'] : '';
+ if ( empty($token) || !validateCSRFToken($token) )
+ exit( '{ "output": "Unauthorized request" }' );
+
+ $path = '/usr/local/etc/nextcloudpi-config.d/';
+ $files = array_diff(scandir($path), array('.', '..'));
+
+ $fh = fopen( $path . $_POST['ref'] . '.sh' ,'r')
+ or exit( '{ "output": "' . $file . ' read error" }' );
+
+ // Get new token
+ echo '{ "token": "' . getCSRFToken() . '",';
+ echo ' "output": ';
+
+ $output = "<table>";
+
+ while ( $line = fgets($fh) )
+ {
+ if ( preg_match('/^(\w+)_=(.*)$/', $line, $matches) )
+ {
+ $output = $output . "<tr>";
+ $output = $output . "<td><label for=\"$matches[1]\">$matches[1]</label></td>";
+ $output = $output . "<td><input type=\"text\" name=\"$matches[1]\" id=\"$matches[1]\" value=\"$matches[2]\" size=\"40\"></td>";
+ $output = $output . "</tr>";
+ }
+ }
+
+ $output = $output . "</table>";
+ fclose($fh);
+
+ echo json_encode( $output ) . ' }'; // close JSON
+}
+
+else if ( $_POST['action'] == "launch" && $_POST['config'] )
+{
+ // CSRF check
+ $token = isset($_POST['csrf_token']) ? $_POST['csrf_token'] : '';
+ if ( empty($token) || !validateCSRFToken($token) )
+ exit( '{ "output": "Unauthorized request" }' );
+
+ chdir('/usr/local/etc/nextcloudpi-config.d/');
+
+ $file = $_POST['ref'] . '.sh';
+
+ if ( $_POST['config'] != "{}" )
+ $params = json_decode( $_POST['config'], true )
+ or exit( '{ "output": "Invalid request" }' );
+
+ $code = file_get_contents( $file )
+ or exit( '{ "output": "' . $file . ' read error" }' );
+
+ foreach( $params as $name => $value)
+ {
+ preg_match( '/^[\w.@_\/-]+$/' , $value , $matches )
+ or exit( '{ "output": "Invalid input" , "token": "' . getCSRFToken() . '" }' );
+ $code = preg_replace( '/\n' . $name . '_=.*' . PHP_EOL . '/' ,
+ PHP_EOL . $name . '_=' . $value . PHP_EOL ,
+ $code )
+ or exit();
+ }
+
+ file_put_contents($file, $code )
+ or exit( '{ "output": "' . $file . ' write error" }' );
+
+ // Get new token
+ echo '{ "token": "' . getCSRFToken() . '",';
+ echo ' "output": ';
+
+ echo json_encode( shell_exec( 'bash -c "sudo /home/www/ncp-launcher.sh ' . $file . '"' ) ) . ' }';
+}
+
+// License
+//
+// This script is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This script is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this script; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
+?>
diff --git a/ncp-web/ncp-logo.png b/ncp-web/ncp-logo.png
new file mode 100644
index 00000000..b19b1a25
--- /dev/null
+++ b/ncp-web/ncp-logo.png
Binary files differ
diff --git a/ncp-web/ncp.css b/ncp-web/ncp.css
new file mode 100644
index 00000000..1abbe2f8
--- /dev/null
+++ b/ncp-web/ncp.css
@@ -0,0 +1,1037 @@
+/*
+ * NextcloudPi Web Panel style sheets. Based on official Nextcloud 12 datasheets
+ *
+ * Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
+ * GPL licensed (see end of file) * Use at your own risk!
+ *
+ * More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/
+*/
+
+
+html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,code,del,dfn,em,img,q,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,dialog,figure,footer,header,hgroup,nav,section {
+ margin:0;
+ padding:0;
+ border:0;
+ outline:0;
+ font-weight:inherit;
+ font-size:100%;
+ font-family:inherit;
+ vertical-align:baseline;
+ cursor:default
+}
+html,body {
+ height:100%
+}
+article,aside,dialog,figure,footer,header,hgroup,nav,section {
+ display:block
+}
+body {
+ line-height:1.5
+}
+table {
+ border-collapse:separate;
+ border-spacing:0;
+ white-space:nowrap
+}
+caption,th,td {
+ text-align:left;
+ font-weight:normal
+}
+table,td,th {
+ vertical-align:middle
+}
+a {
+ border:0;
+ color:#000;
+ text-decoration:none;
+ cursor:pointer
+}
+a * {
+ cursor:pointer
+}
+select,.button span,label {
+ cursor:pointer
+}
+ul {
+ list-style:none
+}
+body {
+ background-color:#fff;
+ font-weight:400;
+ font-size:0.8em;
+ line-height:1.6em;
+ font-family:'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif;
+ color:#000;
+ height:auto
+}
+#nojavascript {
+ position:fixed;
+ top:0;
+ bottom:0;
+ height:100%;
+ width:100%;
+ z-index:9000;
+ text-align:center;
+ background-color:rgba(0, 0, 0, 0.5);
+ color:#fff;
+ line-height:125%;
+ font-size:24px
+}
+#nojavascript div {
+ display:block;
+ position:relative;
+ width:50%;
+ top:35%;
+ margin:0px auto
+}
+#nojavascript a {
+ color:#fff;
+ border-bottom:2px dotted #fff
+}
+#nojavascript a:hover,#nojavascript a:focus {
+ color:#dbdbdb
+}
+::-webkit-scrollbar {
+ width:5px
+}
+::-webkit-scrollbar-track-piece {
+ background-color:transparent
+}
+::-webkit-scrollbar-thumb {
+ background:#dbdbdb;
+ border-radius:3px
+}
+#content {
+ position:relative;
+ height:100%;
+ width:100%
+}
+#content-wrapper {
+ position:absolute;
+ height:100%;
+ width:100%;
+ overflow-x:hidden;
+ padding-top:45px;
+ box-sizing:border-box
+}
+tbody tr:hover,tbody tr:focus,tbody tr:active {
+ background-color:#f7f7f7
+}
+code {
+ font-family:'Lucida Console', 'Lucida Sans Typewriter', 'DejaVu Sans Mono', monospace
+}
+@-ms-viewport {
+ width:device-width;
+}
+input,textarea,select,button {
+ font-family:'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif
+}
+select,button,input,textarea {
+ width:130px;
+ min-height:32px;
+ box-sizing:border-box
+}
+select,button,.button,input:not([type='range']),textarea,#quota,.pager li a {
+ margin:3px 3px 3px 0;
+ padding:7px 6px;
+ font-size:13px;
+ background-color:#fff;
+ color:#545454;
+ border:1px solid #dbdbdb;
+ outline:none;
+ border-radius:3px;
+}
+select:not(:disabled):not(.primary),button:not(:disabled):not(.primary),.button:not(:disabled):not(.primary),input:not([type='range']):not(:disabled):not(.primary),textarea:not(:disabled):not(.primary),#quota:not(:disabled):not(.primary),.pager li a:not(:disabled):not(.primary) {
+}
+select:not(:disabled):not(.primary):not(#quota):hover,button:not(:disabled):not(.primary):not(#quota):hover,.button:not(:disabled):not(.primary):not(#quota):hover,input:not([type='range']):not(:disabled):not(.primary):not(#quota):hover,textarea:not(:disabled):not(.primary):not(#quota):hover,#quota:not(:disabled):not(.primary):not(#quota):hover,.pager li a:not(:disabled):not(.primary):not(#quota):hover,select:not(:disabled):not(.primary):focus,button:not(:disabled):not(.primary):focus,.button:not(:disabled):not(.primary):focus,input:not([type='range']):not(:disabled):not(.primary):focus,textarea:not(:disabled):not(.primary):focus,#quota:not(:disabled):not(.primary):focus,.pager li a:not(:disabled):not(.primary):focus,select:not(:disabled):not(.primary).active,button:not(:disabled):not(.primary).active,.button:not(:disabled):not(.primary).active,input:not([type='range']):not(:disabled):not(.primary).active,textarea:not(:disabled):not(.primary).active,#quota:not(:disabled):not(.primary).active,.pager li a:not(:disabled):not(.primary).active {
+ border-color:#0082c9;
+ outline:none
+}
+select:not(:disabled):not(.primary):active,button:not(:disabled):not(.primary):active,.button:not(:disabled):not(.primary):active,input:not([type='range']):not(:disabled):not(.primary):active,textarea:not(:disabled):not(.primary):active,#quota:not(:disabled):not(.primary):active,.pager li a:not(:disabled):not(.primary):active {
+ outline:none;
+ background-color:#fff
+}
+select:disabled,button:disabled,.button:disabled,input:not([type='range']):disabled,textarea:disabled,#quota:disabled,.pager li a:disabled {
+ background-color:#ebebeb;
+ color:rgba(0, 0, 0, 0.4);
+ cursor:default;
+ opacity:0.5
+}
+select.primary,button.primary,.button.primary,input:not([type='range']).primary,textarea.primary,#quota.primary,.pager li a.primary {
+ border:1px solid #0082c9;
+ background-color:rgba(0, 130, 201, .7);
+ color:#fff;
+ cursor:pointer
+}
+select.primary:not(:disabled):hover,button.primary:not(:disabled):hover,.button.primary:not(:disabled):hover,input:not([type='range']).primary:not(:disabled):hover,textarea.primary:not(:disabled):hover,#quota.primary:not(:disabled):hover,.pager li a.primary:not(:disabled):hover,select.primary:not(:disabled):focus,button.primary:not(:disabled):focus,.button.primary:not(:disabled):focus,input:not([type='range']).primary:not(:disabled):focus,textarea.primary:not(:disabled):focus,#quota.primary:not(:disabled):focus,.pager li a.primary:not(:disabled):focus {
+ background-color:rgba(0, 130, 201, .85)
+}
+select.primary:not(:disabled):active,button.primary:not(:disabled):active,.button.primary:not(:disabled):active,input:not([type='range']).primary:not(:disabled):active,textarea.primary:not(:disabled):active,#quota.primary:not(:disabled):active,.pager li a.primary:not(:disabled):active {
+ background-color:rgba(0, 130, 201, .7)
+}
+select.primary:disabled,button.primary:disabled,.button.primary:disabled,input:not([type='range']).primary:disabled,textarea.primary:disabled,#quota.primary:disabled,.pager li a.primary:disabled {
+ background-color:rgba(0, 130, 201, .7);
+ color:#bababa
+}
+input {
+}
+input:not([type='radio']):not([type='checkbox']):not([type='range']):not([type='submit']):not([type='button']):not([type='reset']):not([type='color']):not([type='file']):not([type='image']) {
+ -webkit-appearance:textfield;
+ -moz-appearance:textfield
+}
+input[type='radio'],input[type='checkbox'],input[type='file'],input[type='image'] {
+ height:auto;
+ width:auto
+}
+input[type='color'] {
+ margin:3px;
+ padding:0 2px;
+ min-height:30px;
+ width:40px;
+ cursor:pointer
+}
+input[type='hidden'] {
+ height:0;
+ width:0
+}
+input[type='time'] {
+ width:initial
+}
+select,button,.button,input[type='button'],input[type='submit'],input[type='reset'] {
+ padding:6px 12px;
+ width:auto;
+ min-height:34px;
+ cursor:pointer;
+ box-sizing:border-box;
+ background-color:#f7f7f7
+}
+button,.button,input[type='button'],input[type='submit'],input[type='reset'] {
+ font-weight:bold;
+}
+button::-moz-focus-inner,.button::-moz-focus-inner,input[type='button']::-moz-focus-inner,input[type='submit']::-moz-focus-inner,input[type='reset']::-moz-focus-inner {
+ border:0
+}
+button,.button {
+}
+button > span[class^='icon-'],.button > span[class^='icon-'],button > span[class*=' icon-'],.button > span[class*=' icon-'] {
+ display:inline-block;
+ vertical-align:text-bottom;
+ opacity:0.5
+}
+textarea {
+ color:#545454;
+ cursor:text;
+ font-family:inherit;
+ height:auto
+}
+textarea:not(:disabled):active,textarea:not(:disabled):hover,textarea:not(:disabled):focus {
+ border-color:#dbdbdb !important;
+ background-color:#fff !important
+}
+select {
+ -webkit-appearance:none;
+ -moz-appearance:none;
+ appearance:none;
+ background:url('../../../core/css/../img/actions/triangle-s.svg') no-repeat right 4px center;
+ background-color:inherit;
+ outline:0;
+ padding-right:24px !important
+}
+button img,.button img {
+ cursor:pointer
+}
+input[type='checkbox'].radio,input[type='radio'].radio,input[type='checkbox'].checkbox,input[type='radio'].checkbox {
+ position:absolute;
+ left:-10000px;
+ top:auto;
+ width:1px;
+ height:1px;
+ overflow:hidden
+}
+input[type='checkbox'].radio + label,input[type='radio'].radio + label,input[type='checkbox'].checkbox + label,input[type='radio'].checkbox + label {
+ user-select:none
+}
+input[type='checkbox'].radio:disabled + label,input[type='radio'].radio:disabled + label,input[type='checkbox'].checkbox:disabled + label,input[type='radio'].checkbox:disabled + label,input[type='checkbox'].radio:disabled + label:before,input[type='radio'].radio:disabled + label:before,input[type='checkbox'].checkbox:disabled + label:before,input[type='radio'].checkbox:disabled + label:before {
+ cursor:default
+}
+input[type='checkbox'].radio + label:before,input[type='radio'].radio + label:before,input[type='checkbox'].checkbox + label:before,input[type='radio'].checkbox + label:before {
+ content:'';
+ display:inline-block;
+ height:12px;
+ width:12px;
+ vertical-align:middle;
+ border-radius:50%;
+ margin:3px;
+ margin-top:1px;
+ border:1px solid #878787
+}
+input[type='checkbox'].radio:not(:disabled):not(:checked) + label:hover:before,input[type='radio'].radio:not(:disabled):not(:checked) + label:hover:before,input[type='checkbox'].checkbox:not(:disabled):not(:checked) + label:hover:before,input[type='radio'].checkbox:not(:disabled):not(:checked) + label:hover:before,input[type='checkbox'].radio:focus + label:before,input[type='radio'].radio:focus + label:before,input[type='checkbox'].checkbox:focus + label:before,input[type='radio'].checkbox:focus + label:before {
+ border-color:#0082c9
+}
+input[type='checkbox'].radio:checked + label:before,input[type='radio'].radio:checked + label:before,input[type='checkbox'].checkbox:checked + label:before,input[type='radio'].checkbox:checked + label:before,input[type='checkbox'].radio.checkbox:indeterminate + label:before,input[type='radio'].radio.checkbox:indeterminate + label:before,input[type='checkbox'].checkbox.checkbox:indeterminate + label:before,input[type='radio'].checkbox.checkbox:indeterminate + label:before {
+ box-shadow:inset 0px 0px 0px 2px #fff;
+ background-color:#0082c9;
+ border-color:#0082c9
+}
+input[type='checkbox'].radio:disabled + label:before,input[type='radio'].radio:disabled + label:before,input[type='checkbox'].checkbox:disabled + label:before,input[type='radio'].checkbox:disabled + label:before {
+ border:1px solid #878787;
+ background-color:#bababa !important;
+}
+input[type='checkbox'].radio:checked:disabled + label:before,input[type='radio'].radio:checked:disabled + label:before,input[type='checkbox'].checkbox:checked:disabled + label:before,input[type='radio'].checkbox:checked:disabled + label:before {
+ background-color:#bababa
+}
+input[type='checkbox'].checkbox + label:before,input[type='radio'].checkbox + label:before {
+ border-radius:1px;
+ height:10px;
+ width:10px;
+ box-shadow:none !important;
+ background-position:center
+}
+input[type='checkbox'].checkbox:checked + label:before,input[type='radio'].checkbox:checked + label:before {
+ background-image:url('../../../core/css/../img/actions/checkbox-mark.svg')
+}
+input[type='checkbox'].checkbox:indeterminate + label:before,input[type='radio'].checkbox:indeterminate + label:before {
+ background-image:url('../../../core/css/../img/actions/checkbox-mixed.svg')
+}
+input[type='checkbox'].radio--white + label:before,input[type='radio'].radio--white + label:before,input[type='checkbox'].checkbox--white + label:before,input[type='radio'].checkbox--white + label:before {
+ border-color:#dbdbdb
+}
+input[type='checkbox'].radio--white:not(:disabled):not(:checked) + label:hover:before,input[type='radio'].radio--white:not(:disabled):not(:checked) + label:hover:before,input[type='checkbox'].checkbox--white:not(:disabled):not(:checked) + label:hover:before,input[type='radio'].checkbox--white:not(:disabled):not(:checked) + label:hover:before,input[type='checkbox'].radio--white:focus + label:before,input[type='radio'].radio--white:focus + label:before,input[type='checkbox'].checkbox--white:focus + label:before,input[type='radio'].checkbox--white:focus + label:before {
+ border-color:#fff
+}
+input[type='checkbox'].radio--white:checked + label:before,input[type='radio'].radio--white:checked + label:before,input[type='checkbox'].checkbox--white:checked + label:before,input[type='radio'].checkbox--white:checked + label:before {
+ box-shadow:inset 0px 0px 0px 2px #000;
+ background-color:#ebebeb;
+ border-color:#ebebeb
+}
+input[type='checkbox'].radio--white:disabled + label:before,input[type='radio'].radio--white:disabled + label:before,input[type='checkbox'].checkbox--white:disabled + label:before,input[type='radio'].checkbox--white:disabled + label:before {
+ background-color:#545454 !important;
+ border-color:rgba(0, 0, 0, 0.4) !important;
+}
+input[type='checkbox'].radio--white:checked:disabled + label:before,input[type='radio'].radio--white:checked:disabled + label:before,input[type='checkbox'].checkbox--white:checked:disabled + label:before,input[type='radio'].checkbox--white:checked:disabled + label:before {
+ box-shadow:inset 0px 0px 0px 2px #000;
+ border-color:#545454;
+ background-color:#545454
+}
+input[type='checkbox'].checkbox--white:checked + label:before,input[type='radio'].checkbox--white:checked + label:before,input[type='checkbox'].checkbox--white:indeterminate + label:before,input[type='radio'].checkbox--white:indeterminate + label:before {
+ background-color:transparent !important;
+ border-color:#fff !important;
+ background-image:url('../../../core/css/../img/actions/checkbox-mark-white.svg')
+}
+input[type='checkbox'].checkbox--white:indeterminate + label:before,input[type='radio'].checkbox--white:indeterminate + label:before {
+ background-image:url('../../../core/css/../img/actions/checkbox-mixed-white.svg')
+}
+input[type='checkbox'].checkbox--white:checked:disabled + label:after,input[type='radio'].checkbox--white:checked:disabled + label:after {
+ border-color:#bababa
+}
+input[type='checkbox'].checkbox--white:indeterminate:disabled + label:after,input[type='radio'].checkbox--white:indeterminate:disabled + label:after {
+ background-color:#bababa
+}
+#header,#navigation,#expanddiv {
+ -webkit-user-select:none;
+ -moz-user-select:none;
+ -ms-user-select:none
+}
+#body-user #header,#body-settings #header,#body-public #header {
+ display:inline-flex;
+ position:fixed;
+ top:0;
+ left:0;
+ right:0;
+ z-index:2000;
+ height:45px;
+ background-color:#0082c9;
+ box-sizing:border-box;
+ justify-content:space-between
+}
+#nextcloudpi {
+ padding:5px;
+ padding-bottom:0;
+ height:45px;
+ box-sizing:border-box;
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)';
+ opacity:1
+}
+#nextcloudpi:focus {
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=75)';
+ opacity:0.75
+}
+#nextcloudpi:hover,#nextcloudpi:active {
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)';
+ opacity:1
+}
+#header {
+}
+#header .logo {
+ background-image:url("logo.svg");
+ background-repeat:no-repeat;
+ background-size:175px;
+ background-position:center;
+ width:252px;
+ height:120px;
+ margin:0 auto
+}
+#header .logo img {
+ opacity:0;
+ max-width:100%;
+ max-height:200px
+}
+#header .logo-icon {
+ display:inline-block;
+ background-image:url('ncp-logo.png');
+ background-repeat:no-repeat;
+ background-position:center center;
+ background-size:contain;
+ width:62px;
+ height:34px
+}
+#header .header-appname-container {
+ display:none;
+ padding-top:22px;
+ padding-right:10px;
+ flex-shrink:0
+}
+#header .icon-caret {
+ display:inline-block;
+ width:12px;
+ height:12px;
+ margin:0;
+ margin-top:-21px;
+ padding:0;
+ vertical-align:middle
+}
+#header #header-left,#header #header-right {
+ display:inline-flex;
+ align-items:center
+}
+#header #header-left {
+ flex:0 0;
+ flex-grow:1
+}
+#header #header-right {
+ justify-content:flex-end
+}
+.header-appname-container .header-appname {
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=75)';
+ opacity:0.75
+}
+.menutoggle .icon-caret {
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=75)';
+ opacity:0.75
+}
+.menutoggle:hover .header-appname,.menutoggle:hover .icon-caret {
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)';
+ opacity:1
+}
+.menutoggle:focus .header-appname,.menutoggle:focus .icon-caret {
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)';
+ opacity:1
+}
+.menutoggle.active .header-appname,.menutoggle.active .icon-caret {
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)';
+ opacity:1
+}
+.header-appname {
+ display:inline-block;
+ position:relative;
+ color:#fff;
+ font-size:16px;
+ font-weight:300;
+ margin:0;
+ margin-top:-26px;
+ padding:7px 0 7px 5px;
+ vertical-align:middle
+}
+#body-public #header .icon-caret {
+ display:none
+}
+nav {
+ display:inline-block;
+ width:44px;
+ height:44px;
+ margin-left:-54px
+}
+[class^='icon-'],[class*=' icon-'] {
+ background-repeat:no-repeat;
+ background-position:center;
+ min-width:16px;
+ min-height:16px
+}
+@keyframes rotate {
+ from {
+ transform:rotate(0deg)
+ }
+ to {
+ transform:rotate(360deg)
+ }
+}
+@media (-webkit-max-device-pixel-ratio:1.3),(max-resolution:124.8dpi) {
+ @font-face {
+ font-family:'Open Sans';
+ font-style:normal;
+ font-weight:normal;
+ src:local('Open Sans'), local('OpenSans'), url('../../../core/css/../fonts/OpenSans-Regular.woff') format('woff');
+ }
+}
+@font-face {
+ font-family:'Open Sans';
+ font-style:normal;
+ font-weight:300;
+ src:local('Open Sans Light'), local('OpenSans-Light'), url('../../../core/css/../fonts/OpenSans-Light.woff') format('woff');
+}
+@font-face {
+ font-family:'Open Sans';
+ font-style:normal;
+ font-weight:600;
+ src:local('Open Sans Semibold'), local('OpenSans-Semibold'), url('../../../core/css/../fonts/OpenSans-Semibold.woff') format('woff');
+}
+h2 {
+ font-size:20px;
+ font-weight:300;
+ margin-bottom:12px;
+ line-height:140%
+}
+h3 {
+ font-size:15px;
+ font-weight:300;
+ margin:12px 0
+}
+em {
+ font-style:normal;
+ -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=50)';
+ opacity:0.5
+}
+dl {
+ padding:12px 0
+}
+dt,dd {
+ display:inline-block;
+ padding:12px;
+ padding-left:0
+}
+dt {
+ width:130px;
+ white-space:nowrap;
+ text-align:right
+}
+kbd {
+ padding:4px 10px;
+ border:1px solid #ccc;
+ box-shadow:0 1px 0 rgba(0, 0, 0, .2);
+ border-radius:3px;
+ display:inline-block;
+ white-space:nowrap
+}
+#app {
+ height:100%;
+ width:100%
+}
+#app * {
+ box-sizing:border-box
+}
+#app-navigation {
+ width:250px;
+ height:100%;
+ float:left;
+ box-sizing:border-box;
+ background-color:#fff;
+ padding-bottom:44px;
+ -webkit-user-select:none;
+ -moz-user-select:none;
+ -ms-user-select:none;
+ user-select:none;
+ border-right:1px solid #ebebeb;
+ display:flex;
+ flex-direction:column;
+}
+#app-navigation > ul {
+ position:relative;
+ height:100%;
+ width:inherit;
+ overflow:auto;
+ box-sizing:border-box
+}
+#app-navigation > ul > li:focus,#app-navigation > ul > li:hover,#app-navigation > ul > li.active,#app-navigation > ul > li a.selected,#app-navigation > ul > li:focus > a,#app-navigation > ul > li:hover > a,#app-navigation > ul > li.active > a,#app-navigation > ul > li a.selected > a {
+ opacity:1;
+ box-shadow:inset 2px 0 #0082c9
+}
+#app-navigation li {
+ position:relative;
+ width:100%;
+ box-sizing:border-box
+}
+#app-navigation.hidden {
+ display:none
+}
+#app-navigation.without-app-settings {
+ padding-bottom:0
+}
+#app-navigation .active.with-menu > a,#app-navigation .with-counter > a {
+ padding-right:50px
+}
+#app-navigation .active.with-menu.with-counter > a {
+ padding-right:90px
+}
+#app-navigation .with-icon a,#app-navigation .app-navigation-entry-loading a {
+ padding-left:44px;
+ background-size:16px 16px;
+ background-position:14px center;
+ background-repeat:no-repeat
+}
+#app-navigation li > a {
+ display:block;
+ width:100%;
+ line-height:44px;
+ min-height:44px;
+ padding:0 12px;
+ overflow:hidden;
+ box-sizing:border-box;
+ white-space:nowrap;
+ text-overflow:ellipsis;
+ color:#000;
+ opacity:0.57
+}
+#app-navigation li > a:first-child img {
+ margin-bottom:-3px;
+ margin-right:11px;
+ width:16px;
+ margin-left:2px
+}
+#app-navigation .collapse {
+ display:none;
+}
+#app-navigation .collapsible > .collapse {
+ position:absolute;
+ height:44px;
+ width:44px;
+ margin:0;
+ padding:0;
+ background:none;
+ background-image:url('../../../core/css/../img/actions/triangle-s.svg?v=1');
+ background-size:16px;
+ background-repeat:no-repeat;
+ background-position:center;
+ border:none;
+ border-radius:0;
+ outline:none !important;
+ box-shadow:none
+}
+#app-navigation .collapsible:hover > a,#app-navigation .collapsible:focus > a {
+ background-image:none
+}
+#app-navigation .collapsible:hover > .collapse,#app-navigation .collapsible:focus > .collapse {
+ display:block
+}
+#app-navigation .collapsible .collapse {
+ -webkit-transform:rotate(-90deg);
+ -ms-transform:rotate(-90deg);
+ transform:rotate(-90deg)
+}
+#app-navigation .collapsible.open {
+ background-image:linear-gradient(top, #ebebeb 0%, #f7f7f7 100%);
+ background-image:-webkit-linear-gradient(top, #ebebeb 0%, #f7f7f7 100%);
+ background-image:-ms-linear-gradient(top, #ebebeb 0%, #f7f7f7 100%)
+}
+#app-navigation .collapsible.open .collapse {
+ -webkit-transform:rotate(0);
+ -ms-transform:rotate(0);
+ transform:rotate(0)
+}
+#app-navigation > {
+}
+#app-navigation > ul ul {
+ display:none
+}
+#app-navigation > ul ul li > a {
+ padding-left:32px
+}
+#app-navigation > .with-icon ul li > a,#app-navigation > .with-icon ul li.app-navigation-entry-loading > a {
+ padding-left:68px;
+ background-position:44px center
+}
+#app-navigation > ul .collapsible.open:hover,#app-navigation > ul .collapsible.open:focus {
+ box-shadow:inset 0 0 3px rgba(51, 51, 51, 0.75)
+}
+#app-navigation > ul .collapsible.open ul {
+ display:block
+}
+#app-navigation .app-navigation-entry-deleted {
+ display:inline-block;
+ height:44px;
+ width:100%
+}
+#app-navigation .app-navigation-entry-deleted-description {
+ padding-left:12px;
+ position:relative;
+ white-space:nowrap;
+ text-overflow:ellipsis;
+ overflow:hidden;
+ display:inline-block;
+ width:calc(100% - 49px);
+ line-height:44px;
+ float:left
+}
+#app-navigation .app-navigation-entry-deleted-button {
+ margin:0;
+ height:44px;
+ width:44px;
+ line-height:44px;
+ border:0;
+ display:inline-block;
+ background-color:transparent;
+ opacity:0.5
+}
+#app-navigation .app-navigation-entry-deleted-button:hover,#app-navigation .app-navigation-entry-deleted-button:focus {
+ opacity:1
+}
+#app-navigation .utils {
+ position:absolute;
+ padding:7px 7px 0 0;
+ right:0;
+ top:0;
+ bottom:0;
+ font-size:12px
+}
+#app-navigation .utils button,#app-navigation .utils .counter {
+ width:44px;
+ height:44px;
+ padding-top:12px
+}
+#app-navigation .drag-and-drop {
+ -webkit-transition:padding-bottom 500ms ease 0s;
+ transition:padding-bottom 500ms ease 0s;
+ padding-bottom:40px
+}
+#app-navigation .error {
+ color:#e9322d
+}
+#app-navigation .app-navigation-separator {
+ border-bottom:1px solid #dbdbdb
+}
+#app-navigation .app-navigation-entry-utils {
+ position:absolute;
+ top:0;
+ right:0;
+ z-index:105
+}
+#app-navigation .app-navigation-entry-utils ul {
+ display:flex !important;
+ align-items:center;
+ justify-content:flex-end
+}
+#app-navigation .app-navigation-entry-utils li {
+ width:44px !important;
+ height:44px
+}
+#app-navigation .active > .app-navigation-entry-utils li {
+ display:inline-block
+}
+#app-navigation .app-navigation-entry-utils button {
+ height:100%;
+ width:100%;
+ margin:0;
+ box-shadow:none
+}
+#app-navigation .app-navigation-entry-utils-menu-button button {
+ border:0;
+ opacity:0.5;
+ background-color:transparent;
+ background-repeat:no-repeat;
+ background-position:center;
+ background-image:url('../../../core/css/../img/actions/more.svg?v=1')
+}
+#app-navigation .app-navigation-entry-utils-menu-button:hover button,#app-navigation .app-navigation-entry-utils-menu-button:focus button {
+ background-color:transparent;
+ opacity:1
+}
+#app-navigation .app-navigation-entry-utils-counter {
+ overflow:hidden;
+ text-overflow:hidden;
+ text-align:right;
+ font-size:9pt;
+ width:38px;
+ line-height:44px;
+ padding:0 10px
+}
+#app-navigation .app-navigation-entry-utils ul,#app-navigation .app-navigation-entry-menu ul {
+ list-style-type:none
+}
+#app-navigation .app-navigation-entry-edit {
+ padding-left:5px;
+ padding-right:5px;
+ display:inline-block;
+ height:39px;
+ width:100%
+}
+#app-navigation .app-navigation-entry-edit input {
+ border-bottom-right-radius:0;
+ border-top-right-radius:0;
+ width:calc(100% - 36px);
+ padding:5px;
+ margin-right:0;
+ height:38px;
+ float:left;
+ border:1px solid rgba(186, 186, 186, 0.9)
+}
+#app-navigation .app-navigation-entry-edit button,#app-navigation .app-navigation-entry-edit input[type='submit'] {
+ width:36px;
+ height:38px;
+ float:left
+}
+#app-navigation .app-navigation-entry-edit .icon-checkmark {
+ border-bottom-left-radius:0;
+ border-top-left-radius:0;
+ border-left:0;
+ margin-right:0
+}
+#app-content {
+ position:relative;
+ height:100%;
+ overflow-y:auto;
+}
+#app-content > .section:first-child {
+ border-top:none
+}
+#app-content.with-app-sidebar {
+ margin-right:27%
+}
+#app-content-wrapper {
+ min-width:100%;
+ min-height:100%
+}
+.pull-left {
+ float:left
+}
+.pull-right {
+ float:right
+}
+.clear-left {
+ clear:left
+}
+.clear-right {
+ clear:right
+}
+.clear-both {
+ clear:both
+}
+.hidden {
+ display:none
+}
+.hidden-visually {
+ position:absolute;
+ left:-10000px;
+ top:auto;
+ width:1px;
+ height:1px;
+ overflow:hidden
+}
+.bold {
+ font-weight:600
+}
+.center {
+ text-align:center
+}
+.inlineblock {
+ display:inline-block
+}
+::-moz-focus-inner {
+ border:0
+}
+select {
+ height:32px
+}
+.ie #show,.ie #show + label {
+ display:none;
+ visibility:hidden
+}
+@media only screen and (max-width:768px) {
+ #app-navigation,#app-content {
+ position:absolute !important;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0
+ }
+ #app-navigation {
+ width:250px !important
+ }
+ #app-content {
+ width:100% !important;
+ left:0 !important;
+ background-color:#fff;
+ overflow-x:hidden !important;
+ z-index:1000
+ }
+ #body-settings #app-content {
+ overflow-x:auto !important
+ }
+ #app-navigation-toggle {
+ position:fixed;
+ display:inline-block !important;
+ top:45px;
+ left:0;
+ width:44px;
+ height:44px;
+ z-index:149;
+ background-color:rgba(255, 255, 255, .7);
+ cursor:pointer;
+ opacity:0.6
+ }
+ #app-navigation-toggle:hover,#app-navigation-toggle:focus {
+ opacity:1
+ }
+ #controls {
+ min-width:initial !important;
+ left:0 !important;
+ padding-left:0
+ }
+ #app-navigation + #app-content #controls {
+ padding-left:44px
+ }
+ #body-user .app-files.viewer-mode #controls {
+ padding-left:0 !important
+ }
+ .app-files.viewer-mode #app-navigation-toggle {
+ display:none !important
+ }
+}
+.tooltip {
+ position:absolute;
+ display:block;
+ font-family:'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif;
+ font-style:normal;
+ font-weight:400;
+ letter-spacing:normal;
+ line-break:auto;
+ line-height:1.6;
+ text-align:left;
+ text-align:start;
+ text-decoration:none;
+ text-shadow:none;
+ text-transform:none;
+ white-space:normal;
+ word-break:normal;
+ word-spacing:normal;
+ word-wrap:normal;
+ font-size:12px;
+ opacity:0;
+ z-index:100000;
+ filter:alpha(opacity=0);
+}
+.tooltip.in {
+ opacity:1;
+ filter:alpha(opacity=100)
+}
+.tooltip.top {
+ margin-top:-3px;
+ padding:10px 0
+}
+.tooltip.bottom {
+ margin-top:3px;
+ padding:10px 0
+}
+.tooltip.right {
+ margin-left:3px;
+ padding:0 10px
+}
+.tooltip.right .tooltip-arrow {
+ top:50%;
+ left:0;
+ margin-top:-10px;
+ border-width:10px 10px 10px 0;
+ border-right-color:#fff
+}
+.tooltip.left {
+ margin-left:-3px;
+ padding:0 5px
+}
+.tooltip.left .tooltip-arrow {
+ top:50%;
+ right:0;
+ margin-top:-10px;
+ border-width:10px 0 10px 10px;
+ border-left-color:#fff
+}
+.tooltip.top .tooltip-arrow,.tooltip.top-left .tooltip-arrow,.tooltip.top-right .tooltip-arrow {
+ bottom:0;
+ border-width:10px 10px 0;
+ border-top-color:#fff
+}
+.tooltip.top .tooltip-arrow {
+ left:50%;
+ margin-left:-10px
+}
+.tooltip.top-left .tooltip-arrow {
+ right:10px;
+ margin-bottom:-10px
+}
+.tooltip.top-right .tooltip-arrow {
+ left:10px;
+ margin-bottom:-10px
+}
+.tooltip.bottom .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow {
+ top:0;
+ border-width:0 10px 10px;
+ border-bottom-color:#fff
+}
+.tooltip.bottom .tooltip-arrow {
+ left:50%;
+ margin-left:-10px
+}
+.tooltip.bottom-left .tooltip-arrow {
+ right:10px;
+ margin-top:-10px
+}
+.tooltip.bottom-right .tooltip-arrow {
+ left:10px;
+ margin-top:-10px
+}
+.tooltip-inner {
+ max-width:350px;
+ padding:5px 8px;
+ background-color:#fff;
+ color:#000;
+ box-shadow:0 1px 10px rgba(150, 150, 150, .75);
+ text-align:center;
+ border-radius:3px
+}
+.tooltip-arrow {
+ position:absolute;
+ width:0;
+ height:0;
+ border-color:transparent;
+ border-style:solid
+}
+
+#config-box-wrapper {
+ width: 450px ;
+ margin-left: auto ;
+ margin-right: auto ;
+}
+
+#config-box-wrapper table {
+ width: 100%;
+}
+
+#config-box-wrapper input {
+ width: 100%;
+}
+
+#details-box {
+ width: auto;
+}
+
+#loading-gif {
+ display: none;
+}
+
+#config-box-title {
+ text-align: center;
+}
+
+#config-button-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
diff --git a/ncp-web/ncp.js b/ncp-web/ncp.js
new file mode 100644
index 00000000..a643212f
--- /dev/null
+++ b/ncp-web/ncp.js
@@ -0,0 +1,96 @@
+///
+// NextcloudPi Web Panel javascript library
+//
+// Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
+// GPL licensed (see end of file) * Use at your own risk!
+//
+// More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/
+///
+
+var MINI = require('minified');
+var $ = MINI.$, $$ = MINI.$$, EE = MINI.EE;
+var selectedID = null;
+var confLock = false;
+
+function errorMsg()
+{
+ $('#config-box').fill( "Something went wrong. Try refreshing the page" );
+}
+
+$(function()
+{
+ // Show selected option configuration box
+ $( 'li' , '#app-navigation' ).on('click', function(e)
+ {
+ if ( confLock ) return;
+ confLock = true;
+
+ var that = this;
+ $.request('post', 'ncp-launcher.php', { action:'cfgreq',
+ ref:this.get('.id') ,
+ csrf_token: $( '#csrf-token' ).get( '.value' ) }).then(
+ function success( result )
+ {
+ selectedID = that.get('.id');
+ var ret = $.parseJSON( result );
+ if ( ret.token )
+ $('#csrf-token').set( { value: ret.token } );
+ $('#config-box').ht( ret.output );
+ $('#config-box-title').fill( $( 'input' , '#' + selectedID ).get( '.value' ) );
+ $('#config-box-wrapper').show();
+ confLock = false;
+ }).error( errorMsg );
+
+ //clear details box
+ $('#details-box').hide( '' );
+ });
+
+ // Launch selected script
+ $( '#config-button' ).on('click', function(e)
+ {
+ confLock = true;
+ $('#details-box').hide( '' );
+ $('#config-button').set('@disabled',true);
+ $('#loading-gif').set( { $display: 'inline' } );
+
+ // create configuration object
+ var cfg = {};
+ $( 'input' , '#config-box' ).each( function(item){
+ cfg[item.name] = item.value;
+ } );
+
+ // request
+ $.request('post', 'ncp-launcher.php', { action:'launch',
+ ref:selectedID ,
+ config: $.toJSON(cfg) ,
+ csrf_token: $( '#csrf-token' ).get( '.value' ) }).then(
+ function success( result )
+ {
+ var ret = $.parseJSON( result );
+ if ( ret.token )
+ $('#csrf-token').set( { value: ret.token } );
+ $('#details-box').fill(ret.output);
+ $('#details-box').show();
+ $('#config-button').set('@disabled',null);
+ $('#loading-gif').hide();
+ confLock = false;
+ }).error( errorMsg );
+ });
+});
+
+// License
+//
+// This script is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This script is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this script; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
diff --git a/nextcloudpi.sh b/nextcloudpi.sh
index e4cea1cc..1037fafa 100644
--- a/nextcloudpi.sh
+++ b/nextcloudpi.sh
@@ -30,6 +30,52 @@ install()
sed -i '/Change User Password/i"0 NextCloudPi Configuration" "Configuration of NextCloudPi" \\\\' /usr/bin/raspi-config
sed -i '/1\\\\ \*) do_change_pass ;;/i0\\\\ *) nextcloudpi-config ;;' /usr/bin/raspi-config
+
+ # NEXTCLOUDPI-CONFIG WEB
+ ##########################################
+ cat > /etc/apache2/sites-available/ncp.conf <<'EOF'
+Listen 8089
+<VirtualHost _default_:8089>
+ DocumentRoot /var/www/ncp-web
+</VirtualHost>
+<Directory /var/www/ncp-web/>
+ Require host localhost
+ Require ip 127.0.0.1
+ Require ip 192.168
+ Require ip 10
+</Directory>
+
+Listen 4443
+<VirtualHost _default_:4443>
+ DocumentRoot /var/www/ncp-web
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+ SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+</VirtualHost>
+<Directory /var/www/ncp-web/>
+ Require host localhost
+ Require ip 127.0.0.1
+ Require ip 192.168
+ Require ip 10
+</Directory>
+EOF
+ a2ensite ncp
+
+ mkdir /home/www -p
+ chown www-data:www-data /home/www
+ chmod 700 /home/www
+
+ cat > /home/www/ncp-launcher.sh <<'EOF'
+#!/bin/bash
+DIR=/usr/local/etc/nextcloudpi-config.d
+test -f $DIR/$1 || { echo "File not found"; exit 1; }
+source /usr/local/etc/library.sh
+cd $DIR
+launch_script $1
+EOF
+ chmod 700 /home/www/ncp-launcher.sh
+ echo "www-data ALL = NOPASSWD: /home/www/ncp-launcher.sh" >> /etc/sudoers
+
# NEXTCLOUDPI MOTD
##########################################
mkdir /etc/update-motd.d
@@ -121,7 +167,7 @@ EOF
mkdir -p "$UPLOADTMPDIR"
chown www-data:www-data "$UPLOADTMPDIR"
sed -i "s|^;\?upload_tmp_dir =.*$|upload_tmp_dir = $UPLOADTMPDIR|" /etc/php/7.0/fpm/php.ini
- sed -i "s|^;\?sys_temp_dir =.*$|sys_temp_dir = $UPLOADTMPDIR|" /etc/php/7.0/fpm/php.ini
+ sed -i "s|^;\?sys_temp_dir =.*$|sys_temp_dir = $UPLOADTMPDIR|" /etc/php/7.0/fpm/php.ini
# update to latest version from github as part of the build process
/usr/local/bin/ncp-update
diff --git a/update.sh b/update.sh
index b71272be..df5cdb38 100755
--- a/update.sh
+++ b/update.sh
@@ -42,7 +42,13 @@ for file in etc/nextcloudpi-config.d/*; do
done
# these files can contain sensitive information, such as passwords
-chmod 700 /usr/local/etc/nextcloudpi-config.d/*
+chown -R root:www-data /usr/local/etc/nextcloudpi-config.d
+chmod 660 /usr/local/etc/nextcloudpi-config.d/*
+
+# install web interface
+cp -r ncp-web /var/www/
+chown www-data:www-data /var/www/ncp-web
+chmod 770 /var/www/ncp-web
# License
#