├── configuration.php ├── assets ├── index.html ├── css │ ├── index.html │ ├── select-search.min.css │ ├── select-search.css │ ├── style.min.css │ └── style.css └── js │ ├── index.html │ ├── variables.js │ ├── ip-address.min.js │ ├── currency-input.min.js │ ├── sign-in.min.js │ ├── ip-address.js │ ├── currency-input.js │ ├── sign-in.js │ ├── auto-complete.min.js │ ├── select-search.min.js │ ├── settings.min.js │ ├── search.min.js │ ├── auto-complete.js │ ├── provider.min.js │ ├── select-search.js │ ├── settings.js │ ├── provider.js │ └── search.js ├── includes ├── index.html └── functions.php ├── logs └── index.html ├── pages ├── index.html ├── json.user.php ├── json.currency.php ├── json.provider.php └── sign-in.php ├── storage └── index.html ├── libraries ├── index.html ├── autoload.php ├── Error │ └── Handler.php ├── Cookie │ └── Cookie.php ├── Session │ └── Session.php ├── Security │ └── Form.php ├── Http │ ├── Request.php │ └── Client.php └── SQLite │ └── Database.php ├── favicon.ico ├── api ├── .htaccess ├── config.php └── index.php ├── docker-compose.yml ├── LICENSE ├── index.php ├── 403.html ├── 50x.html ├── 404.html ├── install ├── tables.sql └── index.php └── README.md /configuration.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/index.html: -------------------------------------------------------------------------------- 1 | Access denied. -------------------------------------------------------------------------------- /includes/index.html: -------------------------------------------------------------------------------- 1 | Access denied. -------------------------------------------------------------------------------- /logs/index.html: -------------------------------------------------------------------------------- 1 | Access denied. -------------------------------------------------------------------------------- /pages/index.html: -------------------------------------------------------------------------------- 1 | Access denied. -------------------------------------------------------------------------------- /storage/index.html: -------------------------------------------------------------------------------- 1 | Access denied. -------------------------------------------------------------------------------- /assets/css/index.html: -------------------------------------------------------------------------------- 1 | Access denied. -------------------------------------------------------------------------------- /assets/js/index.html: -------------------------------------------------------------------------------- 1 | Access denied. -------------------------------------------------------------------------------- /libraries/index.html: -------------------------------------------------------------------------------- 1 | Access denied. -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seikan/carotu/HEAD/favicon.ico -------------------------------------------------------------------------------- /assets/js/variables.js: -------------------------------------------------------------------------------- 1 | const variables = { 2 | diskTypes: ['HDD', 'NVMe', 'SSD'], 3 | virtualizations: ['Dedicated', 'OpenStack', 'OpenVZ', 'HyperV', 'KVM', 'LXD', 'VMWare', 'XEN'], 4 | }; 5 | -------------------------------------------------------------------------------- /libraries/autoload.php: -------------------------------------------------------------------------------- 1 | 20 | Order allow,deny 21 | Deny from all 22 | 23 | -------------------------------------------------------------------------------- /assets/css/select-search.css: -------------------------------------------------------------------------------- 1 | .select-search { 2 | -webkit-user-select: none; 3 | -ms-user-select: none; 4 | user-select: none; 5 | } 6 | 7 | .select-search.disabled { 8 | background-color: var(--bs-secondary-bg); 9 | opacity: 1; 10 | } 11 | 12 | .select-search.focus { 13 | border-color: #86b7fe; 14 | outline: 0; 15 | box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); 16 | } 17 | 18 | .select-search-input:focus { 19 | border: var(--bs-border-width) solid var(--bs-border-color) !important; 20 | box-shadow: none !important; 21 | } 22 | 23 | .select-search-item a code { 24 | color: var(--bs-gray-700); 25 | background-color: var(--bs-warning-border-subtle); 26 | font-family: inherit; 27 | } 28 | -------------------------------------------------------------------------------- /assets/js/ip-address.min.js: -------------------------------------------------------------------------------- 1 | class IpAddress{constructor(){this.address4=/^(\d{1,3}\.){3}\d{1,3}$/,this.address6=/^([\da-f]{1,4}:){7}[\da-f]{1,4}$/i}isAddress4(s){return!!this.address4.test(s)&&s.split(".").every((s=>parseInt(s)<=255))}isAddress6(s){return!!this.address6.test(this.expandAddress6(s))&&s.split(":").every((s=>s.length<=4))}expandAddress6(s){if(null===s.match(/:/g))return s;if(7===s.match(/:/g).length)return s;var r=0,t=[],d=s.split("::");d.forEach((function(s,t){r+=s.split(":").length})),t.push(d[0]);for(var e=0;e<8-r;e++)t.push("0000");return t.push(d[1]),t.filter((s=>s)).forEach((function(s,r){t[r]=t[r].toString().padStart(4,"0")})),t.join(":")}isValid(s){return this.isAddress4(s)||this.isAddress6(s)}} -------------------------------------------------------------------------------- /assets/js/currency-input.min.js: -------------------------------------------------------------------------------- 1 | !function(i){i.fn.currencyInput=function(l){var e=i.extend({decimalDigit:2,decimalSymbol:"."},l);return i.each(this,(function(l,t){i(t).is("input")&&i(t).on("input",(function(){i(this).val(i(this).val().replace(new RegExp("[^0-9"+e.decimalSymbol+"]","g"),"")),i(this).val().indexOf(e.decimalSymbol)>-1&&i(this).val().match(new RegExp(e.decimalSymbol.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"g")).length>1&&i(this).val(i(this).val().slice(0,-1)),i(this).val(i(this).val().replace(e.decimalSymbol,"")),i(this).val().length>e.decimalDigit?(i(this).val().length>e.decimalDigit+1&&i(this).val(i(this).val().replace(/^0/,"")),i(this).val(i(this).val().slice(0,-1*e.decimalDigit)+e.decimalSymbol+i(this).val().slice(-1*e.decimalDigit))):i(this).val("0"+e.decimalSymbol+"0".repeat(e.decimalDigit).slice(0,-1*i(this).val().length)+i(this).val())}))})),this}}(jQuery); -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | carotu: 3 | image: php:8.4-apache 4 | container_name: carotu 5 | restart: unless-stopped 6 | ports: 7 | - "80:80" 8 | volumes: 9 | - .:/var/www/html 10 | - ./storage:/var/www/html/storage 11 | environment: 12 | # Optional: For nginx-proxy setups, uncomment and configure: 13 | # - VIRTUAL_HOST=inventory.yourdomain.com 14 | # - LETSENCRYPT_HOST=inventory.yourdomain.com 15 | # - LETSENCRYPT_EMAIL=admin@yourdomain.com 16 | - VIRTUAL_PORT=80 17 | # For nginx-proxy networks, uncomment: 18 | # networks: 19 | # - webproxy 20 | 21 | # Enable Apache modules required for Carotu 22 | command: > 23 | bash -c " 24 | a2enmod rewrite headers && 25 | docker-php-ext-install pdo pdo_sqlite && 26 | apache2-foreground 27 | " 28 | 29 | # Uncomment if using nginx-proxy: 30 | # networks: 31 | # webproxy: 32 | # external: true 33 | # name: webproxy 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Sei Kan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/js/sign-in.min.js: -------------------------------------------------------------------------------- 1 | $((function(){$("#username, #password").on("input",(function(){$('button[type="submit"]').toggleClass("disabled",!($("#username").val()&&$("#password").val()))})),$("#toggle-password").on("click",(function(){$("#toggle-password i").toggleClass("bi-eye bi-eye-slash"),$('input[name="password"]').attr("type",(function(i,a){return"password"==a?"text":"password"}))})),$('button[type="submit"]').on("click",(function(i){i.preventDefault();var a=$(this),t=$("form").serialize();a.data("html",a.html()).css({width:a.outerWidth(),height:a.outerHeight()}).prop("disabled",!0).html('