├── .gitignore ├── README.md ├── config.php ├── controller.php ├── framework.php ├── functions.php ├── i18n ├── README.md ├── fr_FR │ └── LC_MESSAGES │ │ ├── localization.mo │ │ └── localization.po └── localization.pot ├── index.php ├── lib ├── limonade.php ├── limonade │ ├── abstract.php │ ├── assertions.php │ ├── public │ │ ├── css │ │ │ └── screen.css │ │ └── img │ │ │ └── bg_header.png │ ├── tests.php │ └── views │ │ ├── _debug.html.php │ │ ├── _notices.html.php │ │ ├── default_layout.php │ │ └── error.html.php └── unix_func.php ├── public ├── bootstrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js ├── chat │ └── .gitfile ├── css │ ├── contextMenu.css │ ├── filedrop.css │ └── style.css ├── img │ ├── extensions │ │ ├── archive.png │ │ ├── audio.png │ │ ├── authors.png │ │ ├── bin.png │ │ ├── blank.png │ │ ├── bmp.png │ │ ├── c.png │ │ ├── calc.png │ │ ├── cd.png │ │ ├── copying.png │ │ ├── cpp.png │ │ ├── css.png │ │ ├── deb.png │ │ ├── default.png │ │ ├── doc.png │ │ ├── draw.png │ │ ├── eps.png │ │ ├── exe.png │ │ ├── folder-home.png │ │ ├── folder-open.png │ │ ├── folder-page.png │ │ ├── folder-parent.png │ │ ├── gif.png │ │ ├── gzip.png │ │ ├── h.png │ │ ├── hpp.png │ │ ├── html.png │ │ ├── ico.png │ │ ├── image.png │ │ ├── install.png │ │ ├── java.png │ │ ├── jpg.png │ │ ├── js.png │ │ ├── log.png │ │ ├── makefile.png │ │ ├── package.png │ │ ├── pdf.png │ │ ├── php.png │ │ ├── playlist.png │ │ ├── png.png │ │ ├── pres.png │ │ ├── psd.png │ │ ├── py.png │ │ ├── rar.png │ │ ├── rb.png │ │ ├── readme.png │ │ ├── rpm.png │ │ ├── rss.png │ │ ├── rtf.png │ │ ├── script.png │ │ ├── source.png │ │ ├── sql.png │ │ ├── svg.png │ │ ├── tar.png │ │ ├── tex.png │ │ ├── tiff.png │ │ ├── txt.png │ │ ├── unknown.png │ │ ├── vcal.png │ │ ├── video.png │ │ ├── xml.png │ │ └── zip.png │ ├── github.png │ └── loading.gif ├── jquery │ ├── jquery-2.1.1.min.js │ └── jquery.ui.position.js ├── js │ ├── contextMenu.js │ ├── events.js │ ├── filedrop.min.js │ └── functions.js └── uploads │ └── .gitfile ├── screenshots ├── piratebox1.png ├── piratebox10.png ├── piratebox2.png ├── piratebox3.png ├── piratebox4.png ├── piratebox5.png ├── piratebox6.png ├── piratebox7.png ├── piratebox8.png └── piratebox9.png └── views ├── _file.html.php ├── _folder.html.php ├── home.html.php └── layout.html.php /.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | public/uploads/* 3 | public/chat/* 4 | *.swp 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-piratebox 2 | ## Project 3 | 4 | A PirateBox is an anonymous offline file-sharing communications system, according to the [PirateBox project](http://www.piratebox.cc). 5 | 6 | This project is just a powerful web interface, conceived in this spirit. You can use it on any hardware configured with an HTTP server and a PHP backend. 7 | 8 | If you want to use it like a real PirateBox, you need to configure a wifi hotspot with a captive portal redirecting all web requests on it. For example, this project is also available as a [YunoHost](http://yunohost.org) application for this purpose. Thus, installing the [corresponding Yunohost application](https://github.com/labriqueinternet/piratebox_ynh) sets up all the necessary stuff for you, including the HTTP/PHP server side configurations. This last was integrated in the "[La Brique Internet](http://labriqueinter.net)" project. 9 | 10 | This project is not affiliated with the official PirateBox project. 11 | 12 | ## Features 13 | ### Overview 14 | 15 | * File-sharing without authentication 16 | * Integrated web chat (can be disabled) 17 | * Drag and drop supported with multiple files 18 | * Folders browsing 19 | * Pinned files or folders (marked with a star and cannot be deleted nor renamed) 20 | * Free folders creation (can be disabled) 21 | * Free files and folders renaming (can be disabled) 22 | * Free files and (empty) folders deleting (can be disabled) 23 | * Fancy URLs (can be disabled) 24 | * Keyboard shortcuts and context menus 25 | * Full AJAX with direct URLs and browser history 26 | * Do not require a database 27 | * Completely translatable with gettext 28 | * Responsive design (mobile-friendly) 29 | 30 | Some [screenshots](#screenshots) are available. 31 | 32 | ### Main shortcuts 33 | 34 | On the files tab: 35 | 36 | * **Right/Left arrows**: browses between files and folders 37 | * **Enter**: downloads the selected file or gets into the selected folder 38 | * **Del**: deletes the selected file 39 | * **F2**: renames the selected file or folder 40 | * **Escape**: unselects the selected file or folder 41 | * **Insert**: uploads files 42 | * **Page Down**: creates a folder 43 | * **F4**: shows the chat tab 44 | 45 | You also can directly download a file by double-clicking it. 46 | 47 | On the chat tab: 48 | 49 | * **Up arrow**: completes the input field with the last posted message 50 | * **Down arrow**: cleans the input field 51 | * **F3**: shows the files tab 52 | 53 | ### Options 54 | 55 | All options are available in */config.php*: 56 | 57 | * **app_name**: name of the service ("PirateBox" by default but brandable) 58 | * **enable_chat**: boolean for enabling the web chat or not 59 | * **allow_renaming**: boolean for allowing free renaming of the existing files or not 60 | * **allow_deleting**: boolean for allowing free deleting of the existing files or not 61 | * **default_pseudo**: default pseudo in the chat when the user has not defined one ("anonymous" by default, completed with a random number) 62 | * **time_format**: format to use for displaying dates, using the [PHP date](https://php.net/manual/en/function.date.php) syntax 63 | * **fancyurls**: boolean for enabling fancy URLs or not (see below the required specific configuration at the HTTP server side) 64 | * **base_path**: unix path of the root of the interface in the server 65 | * **base_uri**: root of the interface regarding the URLs (folders to add after the domain name) 66 | * **base_uploads**: optional unix path in case of the *uploads/* folder is located elsewhere in the server (see HTTP configuration below) 67 | * **base_chat**: optional unix path in case of the *chat/* folder (containing the chat log file) is located elsewhere in the server (see HTTP configuration below) 68 | * **max_space**: maximum available space in percent for the data, on the partition where *base_uploads* is located 69 | 70 | For pinning a file or a folder, just remove the write permission for the owner on the server: 71 | 72 | # chmod u-w /var/www/piratebox/public/uploads/foo.bar 73 | 74 | ## Server configuration 75 | ### HTTP server 76 | 77 | Example with nginx: 78 | 79 | # Max file size 80 | client_max_body_size 10G; 81 | 82 | # OPTIONAL 83 | location /public/uploads/ { 84 | 85 | # OPTIONAL: use a public/uploads/ folder located elsewhere 86 | # WITH: $options['base_uploads'] = '/var/spool/piratebox/public/uploads/' 87 | root /var/spool/piratebox/; 88 | 89 | # OPTIONAL: force download for all files 90 | add_header Content-Type "application/octet-stream"; 91 | add_header Content-Disposition "attachment; filename=$1"; 92 | } 93 | 94 | # OPTIONAL 95 | location /public/chat/ { 96 | 97 | # OPTIONAL: use a public/chat/ folder located elsewhere 98 | # WITH: $options['base_chat'] = '/var/spool/piratebox/public/chat/' 99 | root /var/spool/piratebox/; 100 | 101 | # OPTIONAL: deny direct access to the chat log 102 | deny all; 103 | return 403; 104 | } 105 | 106 | # PHP 107 | location ~ \.php { 108 | include /etc/nginx/fastcgi_params; 109 | 110 | fastcgi_index index.php; 111 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 112 | fastcgi_pass unix:/var/run/php.sock; 113 | 114 | # 10 minutes max for uploading a file 115 | fastcgi_send_timeout 600; 116 | } 117 | 118 | # OPTIONAL: use fancy urls 119 | # WITH: $options['fancyurls'] = true 120 | location @piratebox { 121 | 122 | # WITH: $options['base_uri'] = '/foobar/' 123 | rewrite ^/foobar/(.*)$ /foobar/?/get&dir=$1; 124 | } 125 | 126 | location / { 127 | index index.html index.php; 128 | 129 | # OPTIONAL: use fancy urls 130 | try_files $uri $uri/ @piratebox; 131 | } 132 | 133 | ### PHP backend 134 | 135 | Example with php-fpm: 136 | 137 | ; Max file size 138 | php_value[upload_max_filesize] = 10G 139 | php_value[post_max_size] = 10G 140 | 141 | ; 10 minutes max for uploading a file 142 | php_value[max_execution_time] = 600 143 | 144 | ### Permissions 145 | 146 | For example, if your PHP pool uses *www-data* as unix user: 147 | 148 | # chown www-data: public/uploads/ 149 | # chown www-data: public/chat/ 150 | 151 | ## Screenshots 152 | 153 | ![Files tab](/screenshots/piratebox1.png?raw=true "Files tab") 154 | ![Files tab (mobile)](/screenshots/piratebox4.png?raw=true "Files tab (mobile)") 155 | ![Tabs menu (mobile)](/screenshots/piratebox3.png?raw=true "Mobile tabs") 156 | ![Download file](/screenshots/piratebox8.png?raw=true "Download file") 157 | ![Download file (mobile)](/screenshots/piratebox2.png?raw=true "Download file (mobile)") 158 | ![Upload files (mobile)](/screenshots/piratebox9.png?raw=true "Upload files (mobile)") 159 | ![Chat tab](/screenshots/piratebox5.png?raw=true "Chat tab") 160 | ![Upload files](/screenshots/piratebox7.png?raw=true "Upload files") 161 | ![Chat tab (mobile)](/screenshots/piratebox6.png?raw=true "Chat tab (mobile)") 162 | ![Tabs menu 2 (mobile)](/screenshots/piratebox10.png?raw=true "Tabs menu 2 (mobile)") 163 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | "PirateBox", 5 | 6 | 'base_path' => "/var/www/piratebox/", 7 | 'base_uri' => "/", 8 | 'max_space' => 90, // in percent of the partition usage 9 | 10 | #'base_uploads' => "/var/spool/piratebox/public/uploads/", 11 | #'base_chat' => "/var/spool/piratebox/public/chat/", 12 | 13 | 'allow_renaming' => true, 14 | 'allow_deleting' => true, 15 | 'allow_newfolders' => true, 16 | 17 | 'enable_chat' => true, 18 | 'default_pseudo' => "anonymous", 19 | 20 | 'time_format' => "d/m/y H:i", 21 | 'fancyurls' => true, 22 | ]; 23 | 24 | ?> 25 | -------------------------------------------------------------------------------- /controller.php: -------------------------------------------------------------------------------- 1 | 5 | * Contribute at https://github.com/jvaubourg/php-piratebox 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | require_once('functions.php'); 22 | 23 | dispatch('/', function() { 24 | set('files', getFiles('/')); 25 | set('tab', 'files'); 26 | set('locked', true); 27 | set('cdir', '/'); 28 | 29 | header('Content-Type: text/html; charset=utf-8'); 30 | 31 | return render('home.html.php'); 32 | }); 33 | 34 | dispatch('/get', function() { 35 | $dir = sanitizeDirpath(urldecode($_GET['dir'])); 36 | $ajax = isset($_GET['ajax']) && $_GET['ajax']; 37 | 38 | if($ajax) { 39 | header('Content-Type: text/plain; charset=utf-8'); 40 | } else { 41 | header('Content-Type: text/html; charset=utf-8'); 42 | } 43 | 44 | if(empty($dir) || !is_dir(UPLOADS_PATH.$dir)) { 45 | if($ajax) { 46 | exit('ERR:'._("Invalid destination.".UPLOADS_PATH.$dir)); 47 | 48 | } else { 49 | header('Location: '.ROOT_DIR); 50 | exit(); 51 | } 52 | } 53 | 54 | if($ajax) { 55 | return getFiles($dir, true); 56 | } 57 | 58 | $perms = fileperms(UPLOADS_PATH.$dir); 59 | $locked = !($perms & 0x0080) || $dir == '/'; 60 | 61 | set('files', getFiles($dir)); 62 | set('tab', 'files'); 63 | set('locked', $locked); 64 | set('cdir', $dir); 65 | 66 | return render('home.html.php'); 67 | }); 68 | 69 | dispatch_post('/rename', function() { 70 | $cdir = sanitizeDirpath($_POST['cdir']); 71 | $oldName = sanitizeFilename($_POST['oldName']); 72 | $newName = sanitizeFilename($_POST['newName']); 73 | 74 | $oldFilePath = UPLOADS_PATH."$cdir/$oldName"; 75 | $newFilePath = UPLOADS_PATH."$cdir/$newName"; 76 | 77 | header('Content-Type: text/plain; charset=utf-8'); 78 | 79 | if(!option('allow_renaming')) { 80 | exit('ERR:'._("Unauthorized.")); 81 | } 82 | 83 | if(empty($oldName) || empty($newName)) { 84 | exit('ERR:'._("Invalid filename.")); 85 | } 86 | 87 | if(!file_exists($oldFilePath)) { 88 | exit('ERR:'._("File not found.")); 89 | } 90 | 91 | if(file_exists($newFilePath)) { 92 | exit('ERR:'._("File already exists.")); 93 | } 94 | 95 | if(!rename($oldFilePath, $newFilePath)) { 96 | exit('ERR:'._("Renaming failed.")); 97 | } 98 | 99 | if(is_dir($newFilePath)) { 100 | $folder = array( 101 | 'name' => $newName, 102 | 'dir' => "$cdir/$newName", 103 | ); 104 | 105 | set('folder', $folder); 106 | set('locked', false); 107 | set('newfolder', true); 108 | 109 | echo partial('_folder.html.php'); 110 | 111 | } else { 112 | $file = array( 113 | 'filename' => UPLOADS_DIR.str_replace('%2F', '/', rawurlencode($cdir)).'/'.rawurlencode($newName), 114 | 'name' => $newName, 115 | 'shortname' => getShortname($newName), 116 | 'img' => getExtensionImage($newFilePath), 117 | 'size' => fileSizeConvert(filesize($newFilePath)), 118 | 'date' => dateConvert(filemtime($newFilePath)), 119 | ); 120 | 121 | set('file', $file); 122 | set('locked', false); 123 | set('newfile', true); 124 | 125 | echo partial('_file.html.php'); 126 | } 127 | }); 128 | 129 | dispatch_post('/delete', function() { 130 | $cdir = sanitizeDirpath($_POST['cdir']); 131 | $name = sanitizeFilename($_POST['name']); 132 | 133 | $filePath = UPLOADS_PATH."$cdir/$name"; 134 | 135 | header('Content-Type: text/plain; charset=utf-8'); 136 | 137 | if(!option('allow_deleting')) { 138 | exit('ERR:'._("Unauthorized.")); 139 | } 140 | 141 | if(!file_exists($filePath)) { 142 | exit('ERR:'._("File not found.")); 143 | } 144 | 145 | if(is_dir($filePath)) { 146 | $files = scandir($filePath); 147 | 148 | if(!$files) { 149 | exit('ERR:'._("Cannot read this directory.")); 150 | } 151 | 152 | if(count($files) > 2) { 153 | exit('ERR:'._("Not empty directory.")); 154 | } 155 | 156 | if(!rmdir($filePath)) { 157 | exit('ERR:'._("Cannot delete this directory.")); 158 | } 159 | 160 | } else { 161 | if(!unlink($filePath)) { 162 | exit('ERR:'._("Cannot delete this file.")); 163 | } 164 | } 165 | }); 166 | 167 | dispatch_post('/upload', function() { 168 | $cdir = sanitizeDirpath(urldecode($_GET['cdir'])); 169 | $name = sanitizeFilename(urldecode(@$_SERVER['HTTP_X_FILE_NAME'])); 170 | 171 | $dirpath = UPLOADS_PATH."$cdir"; 172 | $filename = "$dirpath/$name"; 173 | 174 | header('Content-Type: text/plain; charset=utf-8'); 175 | 176 | if(empty($cdir) || !is_dir($dirpath)) { 177 | exit('ERR:'._("Invalid directory.")); 178 | } 179 | 180 | if(!hasAvailableSpace()) { 181 | exit('ERR:'._("The file system has reached the maximum limit of space.")); 182 | } 183 | 184 | if(empty($name)) { 185 | exit('ERR:'._("Invalid filename.")); 186 | } 187 | 188 | if(file_exists($filename)) { 189 | exit('ERR:'._("File already exists.")); 190 | } 191 | 192 | $src = fopen('php://input', 'r'); 193 | $dst = fopen($filename, 'w'); 194 | 195 | if(!$src || !$dst) { 196 | exit('ERR:'._("Uploading failed.")); 197 | } 198 | 199 | stream_copy_to_stream($src, $dst); 200 | 201 | $file = array( 202 | 'filename' => UPLOADS_DIR.str_replace('%2F', '/', rawurlencode($cdir)).'/'.rawurlencode($name), 203 | 'name' => $name, 204 | 'shortname' => getShortname($name), 205 | 'img' => getExtensionImage($filename), 206 | 'size' => fileSizeConvert(filesize($filename)), 207 | 'date' => dateConvert(filemtime($filename)), 208 | ); 209 | 210 | set('file', $file); 211 | set('locked', false); 212 | set('newfile', true); 213 | 214 | echo partial('_file.html.php'); 215 | }); 216 | 217 | dispatch_post('/createfolder', function() { 218 | $name = sanitizeDirname($_POST['name']); 219 | $cdir = sanitizeDirpath($_POST['cdir']); 220 | 221 | $dirpath = UPLOADS_PATH."$cdir"; 222 | $filename = "$dirpath/$name"; 223 | 224 | header('Content-Type: text/plain; charset=utf-8'); 225 | 226 | if(!option('allow_newfolders')) { 227 | exit('ERR:'._("Unauthorized.")); 228 | } 229 | 230 | if(!hasAvailableSpace()) { 231 | exit('ERR:'._("The file system has reached the maximum limit of space.")); 232 | } 233 | 234 | if(empty($cdir) || !is_dir($dirpath)) { 235 | exit('ERR:'._("Invalid directory.")); 236 | } 237 | 238 | if(empty($name)) { 239 | exit('ERR:'._("Invalid directory name.")); 240 | } 241 | 242 | if(file_exists($filename)) { 243 | exit('ERR:'._("File already exists.")); 244 | } 245 | 246 | if(!mkdir(UPLOADS_PATH."$cdir/$name")) { 247 | exit('ERR:'._("Creating folder failed.")); 248 | } 249 | 250 | $folder = array( 251 | 'name' => $name, 252 | 'dir' => "$cdir/$name", 253 | ); 254 | 255 | set('folder', $folder); 256 | set('locked', false); 257 | set('newfolder', true); 258 | 259 | echo partial('_folder.html.php'); 260 | }); 261 | 262 | dispatch('/chat', function() { 263 | header('Content-Type: text/html; charset=utf-8'); 264 | 265 | if(!option('enable_chat')) { 266 | exit('ERR:'._("Unauthorized.")); 267 | } 268 | 269 | set('files', getFiles('/')); 270 | set('tab', 'chat'); 271 | set('locked', true); 272 | set('cdir', '/'); 273 | 274 | return render('home.html.php'); 275 | }); 276 | 277 | dispatch_post('/chat', function() { 278 | $action = $_POST['action']; 279 | $logpath = CHAT_PATH.'log.html'; 280 | 281 | header('Content-Type: text/plain; charset=utf-8'); 282 | 283 | if(!option('enable_chat')) { 284 | exit('ERR:'._("Unauthorized.")); 285 | } 286 | 287 | switch($action) { 288 | case 'getLog': 289 | if(file_exists($logpath)) { 290 | $count = intval($_POST['count']); 291 | 292 | $log = file($logpath); 293 | $logSize = count($log); 294 | 295 | if(!$log) { 296 | exit('ERR:'._("Failed to open chat log.")); 297 | } 298 | 299 | if($count > $logSize) { 300 | exit('ERR:'._("Invalid count number.")); 301 | } 302 | 303 | if(!empty($log) && $count != $logSize) { 304 | $logDiff = array(); 305 | 306 | if($count < 1) { 307 | $logDiff = $log; 308 | 309 | } else { 310 | for($i = $count; $i < $logSize; $i++) { 311 | array_push($logDiff, $log[$i]); 312 | } 313 | } 314 | 315 | echo implode($logDiff); 316 | } 317 | } 318 | break; 319 | 320 | case 'post': 321 | $pseudo = substr(trim($_POST['pseudo']), 0, 12); 322 | $pseudo = htmlentities($pseudo); 323 | $comment = htmlentities(trim($_POST['comment'])); 324 | $date = date('d/m/y H:i'); 325 | 326 | if(empty($pseudo) || empty($comment)) { 327 | exit(); 328 | } 329 | 330 | $comment = preg_replace('/([\w\d]+\:\/\/(?:[\w\-\d]+\.)+[\w\-\d]+(?:\/[\w\-\d]+)*(?:\/|\.[\w\-\d]+)?(?:\?[\w\-\d]+\=[\w\-\d]+\&?)?(?:\#[\w\-\d]*)?)/i', '$1', $comment); 331 | 332 | $line = "

$pseudo $comment

\n"; 333 | $flog = fopen($logpath, 'a') or die("Can't open chat log."); 334 | 335 | fwrite($flog, $line); 336 | fclose($flog); 337 | break; 338 | 339 | case 'getLineCount': 340 | $count = intval(exec('wc -l '.escapeshellarg($logpath).' 2> /dev/null')); 341 | 342 | echo ($count >= 0) ? $count : 0; 343 | break; 344 | } 345 | }); 346 | 347 | dispatch('/lang/:locale', function($locale = 'en') { 348 | switch($locale) { 349 | case 'fr': 350 | $_SESSION['locale'] = 'fr'; 351 | break; 352 | 353 | default: 354 | $_SESSION['locale'] = 'en'; 355 | } 356 | 357 | redirect_to('/'); 358 | }); 359 | -------------------------------------------------------------------------------- /framework.php: -------------------------------------------------------------------------------- 1 | 5 | * Contribute at https://github.com/jvaubourg/php-piratebox 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | require('config.php'); 22 | 23 | // Limonade configuration 24 | function configure() { 25 | $GLOBALS['options']['public_dir'] = "public"; 26 | $GLOBALS['options']['public_uploads_dir'] = "uploads"; 27 | $GLOBALS['options']['public_chat_dir'] = "chat"; 28 | 29 | $GLOBALS['options']['base_path'] = preg_replace('/\/+$/', '', $GLOBALS['options']['base_path']); 30 | $GLOBALS['options']['base_uri'] = preg_replace('/\/+$/', '', $GLOBALS['options']['base_uri']); 31 | 32 | option('app_name', $GLOBALS['options']['app_name']); 33 | option('env', ENV_PRODUCTION); 34 | option('debug', false); 35 | option('base_path', $GLOBALS['options']['base_path'].'/'); 36 | option('base_uri', $GLOBALS['options']['base_uri'].'/'); 37 | option('max_space', $GLOBALS['options']['max_space']); 38 | 39 | option('allow_renaming', $GLOBALS['options']['allow_renaming']); 40 | option('allow_deleting', $GLOBALS['options']['allow_deleting']); 41 | option('allow_newfolders', $GLOBALS['options']['allow_newfolders']); 42 | option('enable_chat', $GLOBALS['options']['enable_chat']); 43 | option('default_pseudo', $GLOBALS['options']['default_pseudo']); 44 | option('time_format', $GLOBALS['options']['time_format']); 45 | option('fancyurls', $GLOBALS['options']['fancyurls']); 46 | 47 | layout("layout.html.php"); 48 | 49 | define('ROOT_DIR', option('base_uri')); 50 | define('PUBLIC_DIR', $GLOBALS['options']['public_dir'].'/'); 51 | define('UPLOADS_DIR', PUBLIC_DIR.$GLOBALS['options']['public_uploads_dir'].'/'); 52 | define('CHAT_DIR', PUBLIC_DIR.$GLOBALS['options']['public_chat_dir'].'/'); 53 | 54 | $uploads_path = isset($GLOBALS['options']['base_uploads']) ? $GLOBALS['options']['base_uploads'] : option('base_path').UPLOADS_DIR; 55 | $chat_path = isset($GLOBALS['options']['base_chat']) ? $GLOBALS['options']['base_chat'] : option('base_path').CHAT_DIR; 56 | 57 | $uploads_path = preg_replace('/\/+$/', '', $uploads_path); 58 | $chat_path = preg_replace('/\/+$/', '', $chat_path); 59 | 60 | define('UPLOADS_PATH', "$uploads_path/"); 61 | define('CHAT_PATH', "$chat_path/"); 62 | } 63 | 64 | // Before routing 65 | function before($route) { 66 | $lang_mapping = array( 67 | 'fr' => 'fr_FR' 68 | ); 69 | 70 | if(!isset($_SESSION['locale'])) { 71 | $locale = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); 72 | $_SESSION['locale'] = strtolower(substr(chop($locale[0]), 0, 2)); 73 | } 74 | 75 | $lang = $_SESSION['locale']; 76 | 77 | // Convert simple language code into full language code 78 | if(array_key_exists($lang, $lang_mapping)) { 79 | $lang = $lang_mapping[$lang]; 80 | } 81 | 82 | $lang = "$lang.utf8"; 83 | $textdomain = "localization"; 84 | 85 | putenv("LANGUAGE=$lang"); 86 | putenv("LANG=$lang"); 87 | putenv("LC_ALL=$lang"); 88 | putenv("LC_MESSAGES=$lang"); 89 | 90 | setlocale(LC_ALL, $lang); 91 | setlocale(LC_CTYPE, $lang); 92 | 93 | $locales_dir = dirname(__FILE__).'/i18n'; 94 | 95 | bindtextdomain($textdomain, $locales_dir); 96 | bind_textdomain_codeset($textdomain, 'UTF-8'); 97 | textdomain($textdomain); 98 | 99 | set('locale', $lang); 100 | } 101 | 102 | // After routing 103 | function after($output, $route) { 104 | return $output; 105 | } 106 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | 5 | * Contribute at https://github.com/jvaubourg/php-piratebox 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | $extensionsImages = [ 22 | 'sql' => 'sql.png', 23 | 'zip' => 'zip.png', 24 | 'rar' => 'rar.png', 25 | 'gz' => 'archive.png', 26 | 'tgz' => 'archive.png', 27 | '7z' => 'zip.png', 28 | 'gzip' => 'gzip.png', 29 | 'php' => 'php.png', 30 | 'py' => 'py.png', 31 | 'jsp' => 'html.png', 32 | 'html' => 'html.png', 33 | 'htm' => 'html.png', 34 | 'css' => 'css.png', 35 | 'java' => 'java.png', 36 | 'jar' => 'java.png', 37 | 'cpp' => 'cpp.png', 38 | 'cc' => 'cpp.png', 39 | 'c' => 'c.png', 40 | 'h' => 'h.png', 41 | 'hpp' => 'hpp.png', 42 | 'js' => 'js.png', 43 | 'rss' => 'rss.png', 44 | 'rb' => 'rb.png', 45 | 'vcard' => 'authors.png', 46 | 'exe' => 'exe.png', 47 | 'deb' => 'package.png', 48 | 'psd' => 'psd.png', 49 | 'nfo' => 'readme.png', 50 | 'csv' => 'calc.png', 51 | 'xls' => 'calc.png', 52 | 'xlsx' => 'calc.png', 53 | 'ppt' => 'pres.png', 54 | 'pptx' => 'pres.png', 55 | 'doc' => 'doc.png', 56 | 'odf' => 'doc.png', 57 | 'docx' => 'doc.png', 58 | 'otf' => 'doc.png', 59 | 'rtf' => 'rtf.png', 60 | 'txt' => 'txt.png', 61 | 'log' => 'log.png', 62 | 'src' => 'source.png', 63 | 'tex' => 'tex.png', 64 | 'bin' => 'bin.png', 65 | 'cd' => 'cd.png', 66 | 'sh' => 'script.png', 67 | 'bash' => 'script.png', 68 | 'bat' => 'script.png', 69 | 'vcal' => 'vcal.png', 70 | 'ical' => 'vcal.png', 71 | 'mp3' => 'playlist.png', 72 | 'avi' => 'playlist.png', 73 | 'mp4' => 'video.png', 74 | 'webm' => 'video.png', 75 | 'wmv' => 'video.png', 76 | 'mkv' => 'video.png', 77 | 'rpm' => 'rpm.png', 78 | 'tiff' => 'tiff.png', 79 | 'jpg' => 'jpg.png', 80 | 'jpeg' => 'jpg.png', 81 | 'png' => 'png.png', 82 | 'gif' => 'gif.png', 83 | 'bmp' => 'bmp.png', 84 | 'ico' => 'ico.png', 85 | 'eps' => 'draw.png', 86 | 'ai' => 'eps.png', 87 | 'pdf' => 'pdf.png', 88 | 'xml' => 'xml.png', 89 | 'fla' => 'makefile.png', 90 | 'swf' => 'makefile.png', 91 | 'svg' => 'svg.png', 92 | ]; 93 | 94 | function sanitizeFilename($name) { 95 | $name = str_replace('/', '', $name); 96 | $name = preg_replace('/^\.+/', '', $name); 97 | $name = substr($name, 0, 100); 98 | 99 | return $name; 100 | } 101 | 102 | function sanitizeDirpath($path) { 103 | $path = str_replace('..', '', $path); 104 | $path = trim($path); 105 | 106 | return $path; 107 | } 108 | 109 | function sanitizeDirname($name) { 110 | $name = sanitizeFilename($name); 111 | $name = substr($name, 0, 16); 112 | 113 | return $name; 114 | } 115 | 116 | function getShortname($name) { 117 | if(strpos($name, '.') === false) { 118 | $extension = ''; 119 | $shortname = $name; 120 | 121 | } else { 122 | $namecut = explode('.', $name); 123 | $extension = array_pop($namecut); 124 | $shortname = implode('.', $namecut); 125 | } 126 | 127 | $shortname = substr($shortname, 0, 17); 128 | $extension = substr($extension, -4); 129 | 130 | if(empty($extension)) { 131 | $shortname = ($shortname == $name) ? $name : "$shortname..."; 132 | } else { 133 | $shortname = ("$shortname.$extension" == $name) ? $name : "$shortname...$extension"; 134 | } 135 | 136 | return $shortname; 137 | } 138 | 139 | function getExtensionImage($filepath) { 140 | $extension = explode('.', $filepath); 141 | $extension = array_pop($extension); 142 | 143 | if(isset($GLOBALS['extensionsImages'][$extension])) { 144 | return $GLOBALS['extensionsImages'][$extension]; 145 | } 146 | 147 | return 'unknown.png'; 148 | } 149 | 150 | function fileSizeConvert($bytes) { 151 | $units = [ 152 | 0 => [ 153 | 'unit' => 'TB', 154 | 'value' => pow(1024, 4), 155 | ], 156 | 1 => [ 157 | 'unit' => 'GB', 158 | 'value' => pow(1024, 3), 159 | ], 160 | 2 => [ 161 | 'unit' => 'MB', 162 | 'value' => pow(1024, 2), 163 | ], 164 | 3 => [ 165 | 'unit' => 'KB', 166 | 'value' => 1024, 167 | ], 168 | 4 => [ 169 | 'unit' => 'B', 170 | 'value' => 1, 171 | ], 172 | ]; 173 | 174 | $bytes = floatval($bytes); 175 | 176 | foreach($units as $unit) { 177 | if($bytes > $unit['value']) { 178 | $size = $bytes / $unit['value']; 179 | $size = strval(round($size, 2)); 180 | $size .= $unit['unit']; 181 | 182 | break; 183 | } 184 | } 185 | 186 | return $size; 187 | } 188 | 189 | function dateConvert($timestamp) { 190 | return date(option('time_format'), $timestamp); 191 | } 192 | 193 | function getFiles($dir, $newfiles = false) { 194 | $files = ""; 195 | $finfo = new finfo; 196 | 197 | set('cdir', $dir); 198 | 199 | foreach(scandir(UPLOADS_PATH."$dir") as $name) { 200 | $filepath = UPLOADS_PATH."$dir/$name"; 201 | 202 | if(preg_match('/^\./', $name)) { 203 | continue; 204 | } 205 | 206 | $perms = fileperms($filepath); 207 | $locked = !($perms & 0x0080); 208 | 209 | set('locked', $locked); 210 | 211 | if(is_dir($filepath)) { 212 | $folder = array( 213 | 'name' => $name, 214 | 'dir' => "$dir/$name", 215 | ); 216 | 217 | set('newfolder', $newfiles); 218 | set('folder', $folder); 219 | 220 | $files .= partial('_folder.html.php'); 221 | 222 | } else { 223 | $file = array( 224 | 'filename' => ROOT_DIR.UPLOADS_DIR."$dir/".rawurlencode($name), 225 | 'name' => $name, 226 | 'shortname' => getShortname($name), 227 | 'img' => getExtensionImage($filepath), 228 | 'size' => fileSizeConvert(filesize($filepath)), 229 | 'date' => dateConvert(filemtime($filepath)), 230 | ); 231 | 232 | set('newfile', $newfiles); 233 | set('file', $file); 234 | 235 | $files .= partial('_file.html.php'); 236 | } 237 | } 238 | 239 | return $files; 240 | } 241 | 242 | function hasAvailableSpace() { 243 | exec('df '.escapeshellarg(UPLOADS_PATH), $output, $retcode); 244 | 245 | if($retcode == 0) { 246 | $usage = $output[count($output) - 1]; 247 | $percent = preg_replace('/^.*([0-9]+)%.*$/', '$1', $usage); 248 | 249 | if(is_numeric($percent)) { 250 | return $percent < option('max_space'); 251 | } 252 | } 253 | 254 | return false; 255 | } 256 | -------------------------------------------------------------------------------- /i18n/README.md: -------------------------------------------------------------------------------- 1 | ## Force language 2 | 3 | The default language of the web admin depends on your browser language. 4 | 5 | You can force a language by using (e.g. for French): 6 | ``` 7 | /?/lang/fr 8 | ``` 9 | 10 | English is the default language when the browser language is not available. 11 | 12 | ## Update the default string list 13 | 14 | Updating the pot file from template files: 15 | ``` 16 | xgettext views/* -o i18n/localization.pot 17 | xgettext *.php views/*.php -o i18n/localization.pot 18 | ``` 19 | 20 | ## Add a new language 21 | 22 | Create a new directory path (e.g. for French): 23 | ``` 24 | mkdir -p i18n/fr_FR/LC_MESSAGES/ 25 | ``` 26 | 27 | Generate the po file: 28 | ``` 29 | msginit --locale=fr_FR.UTF-8 --no-translator -i i18n/localization.pot -o i18n/fr_FR/LC_MESSAGES/localization.po 30 | ``` 31 | 32 | You can use poedit for translating the po: 33 | ``` 34 | poedit i18n/fr_FR/LC_MESSAGES/localization.po 35 | ``` 36 | 37 | With poedit, just save your modifications with the button and the *localization.mo* (compiled version of the po) file will automatically be created or updated. 38 | 39 | If you edited the po by hand, you have to compile the mo file: 40 | ``` 41 | msgfmt i18n/fr_FR/localization.po -o i18n/fr_FR/LC_MESSAGES/localization.mo 42 | ``` 43 | 44 | Change the default language of your browser, and test this new translation. 45 | 46 | You should add the locale to the list at the end of *controller.php*. 47 | -------------------------------------------------------------------------------- /i18n/fr_FR/LC_MESSAGES/localization.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jvaubourg/php-piratebox/d9cc1a57b9b99a0e4d63d0e518193f70876b221d/i18n/fr_FR/LC_MESSAGES/localization.mo -------------------------------------------------------------------------------- /i18n/fr_FR/LC_MESSAGES/localization.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # Simon Vieille , 2015. 6 | # 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2015-07-25 13:39+0200\n" 12 | "PO-Revision-Date: 2015-07-25 13:41+0100\n" 13 | "Last-Translator: Simon Vieille \n" 14 | "Language-Team: français <>\n" 15 | "Language: fr_FR\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 20 | "X-Generator: Poedit 1.6.10\n" 21 | 22 | #: controller.php:46 23 | msgid "Invalid destination." 24 | msgstr "Destination incorrecte." 25 | 26 | #: controller.php:80 controller.php:138 controller.php:227 controller.php:266 27 | #: controller.php:284 28 | msgid "Unauthorized." 29 | msgstr "Non autorisé." 30 | 31 | #: controller.php:84 controller.php:185 32 | msgid "Invalid filename." 33 | msgstr "Nom de fichier invalide." 34 | 35 | #: controller.php:88 controller.php:142 36 | msgid "File not found." 37 | msgstr "Fichier non trouvé." 38 | 39 | #: controller.php:92 controller.php:189 controller.php:243 40 | msgid "File already exists." 41 | msgstr "Le fichier existe déjà." 42 | 43 | #: controller.php:96 44 | msgid "Renaming failed." 45 | msgstr "Le renommage a échoué." 46 | 47 | #: controller.php:149 48 | msgid "Cannot read this directory." 49 | msgstr "Impossible de lire le répertoire." 50 | 51 | #: controller.php:153 52 | msgid "Not empty directory." 53 | msgstr "Le répertoire n'est pas vide." 54 | 55 | #: controller.php:157 56 | msgid "Cannot delete this directory." 57 | msgstr "Impossible de supprimer ce répertoire." 58 | 59 | #: controller.php:162 60 | msgid "Cannot delete this file." 61 | msgstr "Impossible de supprimer ce fichier." 62 | 63 | #: controller.php:177 controller.php:235 64 | msgid "Invalid directory." 65 | msgstr "Répertoire invalide." 66 | 67 | #: controller.php:181 controller.php:231 68 | msgid "The file system has reached the maximum limit of space." 69 | msgstr "Le système de fichiers a atteint la limite de la place disponible." 70 | 71 | #: controller.php:196 72 | msgid "Uploading failed." 73 | msgstr "Le téléversement a échoué." 74 | 75 | #: controller.php:239 76 | msgid "Invalid directory name." 77 | msgstr "Nom de répertoire invalide." 78 | 79 | #: controller.php:247 80 | msgid "Creating folder failed." 81 | msgstr "La création du répertoire a échoué." 82 | 83 | #: controller.php:296 84 | msgid "Failed to open chat log." 85 | msgstr "Impossible d'ouvrir l'historique du chat." 86 | 87 | #: controller.php:300 88 | msgid "Invalid count number." 89 | msgstr "Nombre invalide." 90 | 91 | #: views/home.html.php:34 92 | msgid "Files" 93 | msgstr "Fichiers" 94 | 95 | #: views/home.html.php:35 96 | msgid "Chat" 97 | msgstr "Chat" 98 | 99 | #: views/home.html.php:39 100 | msgid "Upload a new file" 101 | msgstr "Téléverser un fichier" 102 | 103 | #: views/home.html.php:40 104 | msgid "Pseudo" 105 | msgstr "Pseudo" 106 | 107 | #: views/home.html.php:48 108 | msgid "Are you sure you want to delete this file?" 109 | msgstr "Êtes-vous certain de vouloir supprimer ce fichier ?" 110 | 111 | #: views/home.html.php:49 112 | msgid "Are you sure you want to delete this folder?" 113 | msgstr "Êtes-vous certain de vouloir supprimer ce répertoire ?" 114 | 115 | #: views/home.html.php:50 116 | msgid "Open" 117 | msgstr "Ouvrir" 118 | 119 | #: views/home.html.php:51 views/home.html.php:61 120 | msgid "Download" 121 | msgstr "Télécharger" 122 | 123 | #: views/home.html.php:52 views/home.html.php:64 124 | msgid "Rename" 125 | msgstr "Renommer" 126 | 127 | #: views/home.html.php:53 views/home.html.php:65 128 | msgid "Delete" 129 | msgstr "Supprimer" 130 | 131 | #: views/home.html.php:70 132 | msgid "Download the others' files" 133 | msgstr "Télécharger les fichiers des autres" 134 | 135 | #: views/home.html.php:75 136 | msgid "Root" 137 | msgstr "Racine" 138 | 139 | #: views/home.html.php:83 140 | msgid "No files yet." 141 | msgstr "Aucun fichier." 142 | 143 | #: views/home.html.php:84 144 | msgid "Delete this folder" 145 | msgstr "Supprimer ce répertoire" 146 | 147 | #: views/home.html.php:91 148 | msgid "Share your own files" 149 | msgstr "Partager vos propres fichiers" 150 | 151 | #: views/home.html.php:96 152 | msgid "Drag & drop here" 153 | msgstr "Glissez/déposez ici" 154 | 155 | #: views/home.html.php:97 156 | msgid "or" 157 | msgstr "ou" 158 | 159 | #: views/home.html.php:98 160 | msgid "Click to open the file browser" 161 | msgstr "Cliquer pour sélectionner un fichier" 162 | 163 | #: views/home.html.php:104 164 | msgid "Create a folder" 165 | msgstr "Créer un répertoire" 166 | 167 | #: views/home.html.php:108 168 | msgid "Folder name" 169 | msgstr "Nom du répertoire" 170 | 171 | #: views/home.html.php:110 172 | msgid "OK" 173 | msgstr "OK" 174 | 175 | #: views/home.html.php:123 176 | msgid "No messages. You are the first!" 177 | msgstr "Aucun message. Vous êtes le premier !" 178 | 179 | #: views/home.html.php:126 180 | msgid "Comment" 181 | msgstr "Commenter" 182 | 183 | #: views/home.html.php:128 184 | msgid "Send" 185 | msgstr "Envoyer" 186 | 187 | #: views/layout.html.php:53 188 | msgid "Any problem? Contribute!" 189 | msgstr "Un problème ? Contribuez !" 190 | -------------------------------------------------------------------------------- /i18n/localization.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2015-07-25 13:39+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: controller.php:46 21 | msgid "Invalid destination." 22 | msgstr "" 23 | 24 | #: controller.php:80 controller.php:138 controller.php:227 controller.php:266 25 | #: controller.php:284 26 | msgid "Unauthorized." 27 | msgstr "" 28 | 29 | #: controller.php:84 controller.php:185 30 | msgid "Invalid filename." 31 | msgstr "" 32 | 33 | #: controller.php:88 controller.php:142 34 | msgid "File not found." 35 | msgstr "" 36 | 37 | #: controller.php:92 controller.php:189 controller.php:243 38 | msgid "File already exists." 39 | msgstr "" 40 | 41 | #: controller.php:96 42 | msgid "Renaming failed." 43 | msgstr "" 44 | 45 | #: controller.php:149 46 | msgid "Cannot read this directory." 47 | msgstr "" 48 | 49 | #: controller.php:153 50 | msgid "Not empty directory." 51 | msgstr "" 52 | 53 | #: controller.php:157 54 | msgid "Cannot delete this directory." 55 | msgstr "" 56 | 57 | #: controller.php:162 58 | msgid "Cannot delete this file." 59 | msgstr "" 60 | 61 | #: controller.php:177 controller.php:235 62 | msgid "Invalid directory." 63 | msgstr "" 64 | 65 | #: controller.php:181 controller.php:231 66 | msgid "The file system has reached the maximum limit of space." 67 | msgstr "" 68 | 69 | #: controller.php:196 70 | msgid "Uploading failed." 71 | msgstr "" 72 | 73 | #: controller.php:239 74 | msgid "Invalid directory name." 75 | msgstr "" 76 | 77 | #: controller.php:247 78 | msgid "Creating folder failed." 79 | msgstr "" 80 | 81 | #: controller.php:296 82 | msgid "Failed to open chat log." 83 | msgstr "" 84 | 85 | #: controller.php:300 86 | msgid "Invalid count number." 87 | msgstr "" 88 | 89 | #: views/home.html.php:34 90 | msgid "Files" 91 | msgstr "" 92 | 93 | #: views/home.html.php:35 94 | msgid "Chat" 95 | msgstr "" 96 | 97 | #: views/home.html.php:39 98 | msgid "Upload a new file" 99 | msgstr "" 100 | 101 | #: views/home.html.php:40 102 | msgid "Pseudo" 103 | msgstr "" 104 | 105 | #: views/home.html.php:48 106 | msgid "Are you sure you want to delete this file?" 107 | msgstr "" 108 | 109 | #: views/home.html.php:49 110 | msgid "Are you sure you want to delete this folder?" 111 | msgstr "" 112 | 113 | #: views/home.html.php:50 114 | msgid "Open" 115 | msgstr "" 116 | 117 | #: views/home.html.php:51 views/home.html.php:61 118 | msgid "Download" 119 | msgstr "" 120 | 121 | #: views/home.html.php:52 views/home.html.php:64 122 | msgid "Rename" 123 | msgstr "" 124 | 125 | #: views/home.html.php:53 views/home.html.php:65 126 | msgid "Delete" 127 | msgstr "" 128 | 129 | #: views/home.html.php:70 130 | msgid "Download the others' files" 131 | msgstr "" 132 | 133 | #: views/home.html.php:75 134 | msgid "Root" 135 | msgstr "" 136 | 137 | #: views/home.html.php:83 138 | msgid "No files yet." 139 | msgstr "" 140 | 141 | #: views/home.html.php:84 142 | msgid "Delete this folder" 143 | msgstr "" 144 | 145 | #: views/home.html.php:91 146 | msgid "Share your own files" 147 | msgstr "" 148 | 149 | #: views/home.html.php:96 150 | msgid "Drag & drop here" 151 | msgstr "" 152 | 153 | #: views/home.html.php:97 154 | msgid "or" 155 | msgstr "" 156 | 157 | #: views/home.html.php:98 158 | msgid "Click to open the file browser" 159 | msgstr "" 160 | 161 | #: views/home.html.php:104 162 | msgid "Create a folder" 163 | msgstr "" 164 | 165 | #: views/home.html.php:108 166 | msgid "Folder name" 167 | msgstr "" 168 | 169 | #: views/home.html.php:110 170 | msgid "OK" 171 | msgstr "" 172 | 173 | #: views/home.html.php:123 174 | msgid "No messages. You are the first!" 175 | msgstr "" 176 | 177 | #: views/home.html.php:126 178 | msgid "Comment" 179 | msgstr "" 180 | 181 | #: views/home.html.php:128 182 | msgid "Send" 183 | msgstr "" 184 | 185 | #: views/layout.html.php:53 186 | msgid "Any problem? Contribute!" 187 | msgstr "" 188 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 5 | * Contribute at https://github.com/jvaubourg/php-piratebox 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | require dirname(__FILE__).'/lib/limonade.php'; 22 | require dirname(__FILE__).'/controller.php'; 23 | require dirname(__FILE__).'/lib/unix_func.php'; 24 | //require '/usr/share/php/php-gettext/gettext.inc'; 25 | require dirname(__FILE__).'/framework.php'; 26 | 27 | run(); 28 | -------------------------------------------------------------------------------- /lib/limonade/abstract.php: -------------------------------------------------------------------------------- 1 | 40 | * function autoload_controller($callback) 41 | * { 42 | * require_once_dir(option('controllers_dir')); 43 | * } 44 | * 45 | * 46 | * 47 | * @param string $callback the callback defined in matching route 48 | * @return void 49 | */ 50 | function autoload_controller($callback) 51 | { 52 | return; 53 | } 54 | 55 | /** 56 | * Called before each request. 57 | * This is very useful to define a default layout or passing common variables 58 | * to the templates. 59 | * 60 | * @abstract this function might be redefined by user 61 | * @param array() $route array (like returned by {@link route_build()}, 62 | * with keys "method", "pattern", "names", "callback", "options") 63 | * @return void 64 | */ 65 | function before($route) 66 | { 67 | 68 | } 69 | 70 | /** 71 | * An `after` output filter 72 | * 73 | * Called after each request and can apply a transformation to the output 74 | * (except for `render_file` outputs which are sent directly to the output buffer). 75 | * 76 | * @abstract this function might be redefined by user 77 | * @param string $output 78 | * @param array() $route array (like returned by {@link route_find()}, 79 | * with keys "method", "pattern", "names", "callback", "params", "options") 80 | * @return string 81 | */ 82 | function after($output, $route) 83 | { 84 | # Call functions... 85 | # .. modifies $output... 86 | return $output; 87 | } 88 | 89 | /** 90 | * Not found error output 91 | * 92 | * @abstract this function might be redefined by user 93 | * @param string $errno 94 | * @param string $errstr 95 | * @param string $errfile 96 | * @param string $errline 97 | * @return string "not found" output string 98 | */ 99 | function not_found($errno, $errstr, $errfile=null, $errline=null) 100 | { 101 | 102 | } 103 | 104 | /** 105 | * Server error output 106 | * 107 | * @abstract this function might be redefined by user 108 | * @param string $errno 109 | * @param string $errstr 110 | * @param string $errfile 111 | * @param string $errline 112 | * @return string "server error" output string 113 | */ 114 | function server_error($errno, $errstr, $errfile=null, $errline=null) 115 | { 116 | 117 | } 118 | 119 | /** 120 | * Called when a route is not found. 121 | * 122 | * 123 | * @abstract this function might be redefined by user 124 | * @param string $request_method 125 | * @param string $request_uri 126 | * @return void 127 | */ 128 | function route_missing($request_method, $request_uri) 129 | { 130 | halt(NOT_FOUND, "($request_method) $request_uri"); # by default 131 | } 132 | 133 | /** 134 | * Called before stoppping and exiting application. 135 | * 136 | * @abstract this function might be redefined by user 137 | * @param boolean exit or not 138 | * @return void 139 | */ 140 | function before_exit($exit) 141 | { 142 | 143 | } 144 | 145 | /** 146 | * Rendering prefilter. 147 | * Useful if you want to transform your views before rendering. 148 | * The first three parameters are the same as those provided 149 | * to the `render` function. 150 | * 151 | * @abstract this function might be redefined by user 152 | * @param string $content_or_func a function, a file in current views dir or a string 153 | * @param string $layout 154 | * @param array $locals 155 | * @param array $view_path (by default file_path(option('views_dir'),$content_or_func);) 156 | * @return array with, in order, $content_or_func, $layout, $locals vars 157 | * and the calculated $view_path 158 | */ 159 | function before_render($content_or_func, $layout, $locals, $view_path) 160 | { 161 | # transform $content_or_func, $layout, $locals or $view_path… 162 | return array($content_or_func, $layout, $locals, $view_path); 163 | } 164 | 165 | 166 | /** 167 | * Called only if rendering $output is_null, 168 | * like in a controller with no return statement. 169 | * 170 | * @abstract this function might be defined by user 171 | * @param array() $route array (like returned by {@link route_build()}, 172 | * with keys "method", "pattern", "names", "callback", "options") 173 | * @return string 174 | */ 175 | function autorender($route) 176 | { 177 | # process output depending on $route 178 | return $output; 179 | } 180 | 181 | /** 182 | * Called if a header is about to be sent 183 | * 184 | * @abstract this function might be defined by user 185 | * @param string the headers that limonade will send 186 | * @return void 187 | */ 188 | function before_sending_header($header) 189 | { 190 | 191 | } 192 | 193 | 194 | -------------------------------------------------------------------------------- /lib/limonade/assertions.php: -------------------------------------------------------------------------------- 1 | should be TRUE') 18 | { 19 | test_run_assertion(); 20 | return assert('$value === TRUE; //'.$message); 21 | } 22 | 23 | function assert_false($value, $message = '<1> should be FALSE') 24 | { 25 | test_run_assertion(); 26 | return assert('$value === FALSE; //'.$message); 27 | } 28 | 29 | function assert_null($value, $message = '<1> should be NULL') 30 | { 31 | test_run_assertion(); 32 | return assert('$value === NULL; //'.$message); 33 | } 34 | 35 | function assert_not_null($value, $message = '<1> should not be NULL') 36 | { 37 | test_run_assertion(); 38 | return assert('$value !== NULL; //'.$message); 39 | } 40 | 41 | function assert_empty($value, $message = '<1> should be empty') 42 | { 43 | test_run_assertion(); 44 | return assert('empty($value); //'.$message); 45 | } 46 | 47 | function assert_not_empty($value, $message = '<1> should not be empty') 48 | { 49 | test_run_assertion(); 50 | return assert('!empty($value); //'.$message); 51 | } 52 | 53 | function assert_equal($expected, $value, $message = '<1> should be equal to <2>') 54 | { 55 | test_run_assertion(); 56 | return assert('$expected == $value; //'.$message); 57 | } 58 | 59 | function assert_not_equal($expected, $value, $message = '<1> should not equal to <2>') 60 | { 61 | test_run_assertion(); 62 | return assert('$expected != $value; //'.$message); 63 | } 64 | 65 | function assert_identical($expected, $value, $message = '<1> should be identical to <2>') 66 | { 67 | test_run_assertion(); 68 | return assert('$expected === $value; //'.$message); 69 | } 70 | 71 | function assert_not_identical($expected, $value, $message = '<1> should not be identical to <2>') 72 | { 73 | test_run_assertion(); 74 | return assert('$expected !== $value; //'.$message); 75 | } 76 | 77 | function assert_match($pattern, $string, $message = '<2> expected to match regular expression <1>') { 78 | test_run_assertion(); 79 | return assert('preg_match($pattern, $string); //'.$message); 80 | } 81 | 82 | function assert_no_match($pattern, $string, $message = '<2> expected to not match regular expression <1>') { 83 | test_run_assertion(); 84 | return assert('!preg_match($pattern, $string); //'.$message); 85 | } 86 | 87 | function assert_type($type, $value, $message = '<1> is not of type <2>') { 88 | test_run_assertion(); 89 | $predicate = 'is_' . strtolower(is_string($type) ? $type : gettype($type)); 90 | return assert('$predicate($value); //'.$message); 91 | } 92 | 93 | function assert_instance_of($class, $object, $message = '<2> is not an instance of class <1>') { 94 | test_run_assertion(); 95 | return assert('$object instanceof $class; //'.$message); 96 | } 97 | 98 | function assert_length_of($value, $length, $message = '<1> expected to be of length <2>') { 99 | test_run_assertion(); 100 | $count = is_string($value) ? 'strlen' : 'count'; 101 | return assert('$count($value) == $length; //'.$message); 102 | } 103 | 104 | function assert_trigger_error($callable, $args = array(), $message = '<1> should trigger an error') { 105 | test_run_assertion(); 106 | $trigger_errors = count($GLOBALS["limonade"]["test_errors"]); 107 | set_error_handler("test_error_handler"); 108 | $result = call_user_func_array($callable, $args); 109 | restore_error_handler(); 110 | return assert('$trigger_errors < count($GLOBALS["limonade"]["test_errors"]); //'.$message); 111 | } 112 | 113 | # TODO add web browser assertions assert_http_get, assert_http_response... as in SimpleTest (http://www.simpletest.org/en/web_tester_documentation.html) 114 | 115 | function assert_header($response, $expected_name, $expected_value = null, $message = "expected header '%s' to be equal to '%s' but received '%s: %s'") 116 | { 117 | test_run_assertion(); 118 | # see assert_header in http://github.com/fnando/voodoo-test/blob/f3b0994ef138a6ba94d5e7cef6c1fb1720797a86/lib/assertions.php 119 | $headers = preg_split("/^\s*$/ms", $response); 120 | //var_dump($headers); 121 | $headers = preg_replace("/\s*$/sm", "", $headers[0]); 122 | //var_dump($headers); 123 | 124 | $regex_header = str_replace("/", "\\/", $expected_name); 125 | $regex_header = str_replace(".", "\\.", $regex_header); 126 | 127 | $header = $expected_name; 128 | 129 | # from http://www.faqs.org/rfcs/rfc2616 130 | # Field names are case-insensitive 131 | if ($expected_value) { 132 | $regex = "/^{$regex_header}:(.*?)$/ism"; 133 | $header .= ": {$expected_value}"; 134 | } else { 135 | $regex = "/^{$regex_header}(:.*?)?$/ism"; 136 | } 137 | 138 | $has_header = preg_match($regex, $headers, $matches); 139 | $sent_header = trim((string)$matches[1]); 140 | 141 | 142 | if(empty($sent_header)) 143 | { 144 | if(is_null($expected_value)) 145 | { 146 | $message = "expected header '%s' but header has not been sent"; 147 | } 148 | else 149 | { 150 | $message = "expected header '%s' to be equal to '%s' but header has not been sent"; 151 | } 152 | 153 | $message = sprintf($message, $expected_name, $expected_value); 154 | return assert("false; //".$message); 155 | } 156 | else if($expected_value) 157 | { 158 | $message = sprintf($message, $expected_name, $expected_value, $expected_name, $sent_header); 159 | return assert('$expected_value && $sent_header == $expected_value; //'.$message); 160 | } 161 | return assert("true; //"); 162 | } 163 | 164 | function assert_status($response, $expected_status, $message = "expected status code to be equal to '%s' but received '%s'") 165 | { 166 | $lines = explode('\n', trim($response)); 167 | if (preg_match('/HTTP\/(\d+\.\d+)\s+(\d+)/i', $lines[0], $matches)) 168 | { 169 | $status = $matches[2]; 170 | return assert('$expected_status == $status; //'.sprintf($message, $expected_status, $status)); 171 | } 172 | return assert("false; //no status code returned in this response string"); 173 | } 174 | -------------------------------------------------------------------------------- /lib/limonade/public/css/screen.css: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | 3 | 4 | Blueprint CSS Framework 0.8 5 | http://blueprintcss.org 6 | 7 | * Copyright (c) 2007-Present. See LICENSE for more info. 8 | * See README for instructions on how to use Blueprint. 9 | * For credits and origins, see AUTHORS. 10 | * This is a compressed file. See the sources in the 'src' directory. 11 | 12 | ----------------------------------------------------------------------- */ 13 | 14 | /* reset.css */ 15 | 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 {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;} 16 | body {line-height:1.5;} 17 | table {border-collapse:separate;border-spacing:0;} 18 | caption, th, td {text-align:left;font-weight:normal;} 19 | table, td, th {vertical-align:middle;} 20 | blockquote:before, blockquote:after, q:before, q:after {content:"";} 21 | blockquote, q {quotes:"" "";} 22 | a img {border:none;} 23 | 24 | /* typography.css */ 25 | body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;} 26 | h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} 27 | h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} 28 | h2 {font-size:2em;margin-bottom:0.75em;} 29 | h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} 30 | h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;} 31 | h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} 32 | h6 {font-size:1em;font-weight:bold;} 33 | h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;} 34 | p {margin:0 0 1.5em;} 35 | p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;} 36 | p img.right {float:right;margin:1.5em 0 1.5em 1.5em;} 37 | a:focus, a:hover {color:#000;} 38 | a {color:#009;text-decoration:underline;} 39 | blockquote {margin:1.5em;color:#666;font-style:italic;} 40 | strong {font-weight:bold;} 41 | em, dfn {font-style:italic;} 42 | dfn {font-weight:bold;} 43 | sup, sub {line-height:0;} 44 | abbr, acronym {border-bottom:1px dotted #666;} 45 | address {margin:0 0 1.5em;font-style:italic;} 46 | del {color:#666;} 47 | pre {margin:1.5em 0;white-space:pre;} 48 | pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;} 49 | li ul, li ol {margin:0 1.5em;} 50 | ul, ol {margin:0 1.5em 1.5em 1.5em;} 51 | ul {list-style-type:disc;} 52 | ol {list-style-type:decimal;} 53 | dl {margin:0 0 1.5em 0;} 54 | dl dt {font-weight:bold;} 55 | dd {margin-left:1.5em;} 56 | table {margin-bottom:1.4em;width:100%;} 57 | th {font-weight:bold;} 58 | thead th {background:#c3d9ff;} 59 | th, td, caption {padding:4px 10px 4px 5px;} 60 | tr.even td {background:#e5ecf9;} 61 | tfoot {font-style:italic;} 62 | caption {background:#eee;} 63 | .small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;} 64 | .large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;} 65 | .hide {display:none;} 66 | .quiet {color:#666;} 67 | .loud {color:#000;} 68 | .highlight {background:#ff0;} 69 | .added {background:#060;color:#fff;} 70 | .removed {background:#900;color:#fff;} 71 | .first {margin-left:0;padding-left:0;} 72 | .last {margin-right:0;padding-right:0;} 73 | .top {margin-top:0;padding-top:0;} 74 | .bottom {margin-bottom:0;padding-bottom:0;} 75 | 76 | /* forms.css */ 77 | label {font-weight:bold;} 78 | fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;} 79 | legend {font-weight:bold;font-size:1.2em;} 80 | input.text, input.title, textarea, select {margin:0.5em 0;border:1px solid #bbb;} 81 | input.text:focus, input.title:focus, textarea:focus, select:focus {border:1px solid #666;} 82 | input.text, input.title {width:300px;padding:5px;} 83 | input.title {font-size:1.5em;} 84 | textarea {width:390px;height:250px;padding:5px;} 85 | .error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;} 86 | .error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;} 87 | .notice {background:#FFF6BF;color:#514721;border-color:#FFD324;} 88 | .success {background:#E6EFC2;color:#264409;border-color:#C6D880;} 89 | .error a {color:#8a1f11;} 90 | .notice a {color:#514721;} 91 | .success a {color:#264409;} 92 | 93 | .box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;} 94 | hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;} 95 | hr.space {background:#fff;color:#fff;} 96 | .clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} 97 | .clearfix, .container {display:block;} 98 | .clear {clear:both;} 99 | 100 | /* ----------------------------------------------------------------------- 101 | 102 | LIMONADE 103 | 104 | Design and logo by Minimau 105 | 106 | ----------------------------------------------------------------------- */ 107 | 108 | html { 109 | background-color: #b4a689; 110 | text-align: center; 111 | } 112 | body { 113 | width: auto; /* 16 col */ 114 | margin: 0 20px; 115 | text-align: left; 116 | /*background: #fff url(blueprint/src/grid.png);*/ 117 | font-family: Verdana, Geneva, sans-serif; 118 | color: #303030; 119 | } 120 | a, a:hover, a:visited { 121 | color: #4596cd; 122 | } 123 | a:hover { 124 | text-decoration: none; 125 | } 126 | #header, h1, h2, h3, h4 { 127 | font-family: "Arial Black", Gadget, sans-serif; 128 | } 129 | h1 { 130 | color: #b4a689; 131 | font-size: 2em; 132 | line-height: 2; 133 | border-bottom: 7px solid #000; 134 | margin-bottom: 0.75em; 135 | margin-top:0; 136 | } 137 | h2 { 138 | font-size: 1.5em; 139 | color: #cddb12; 140 | margin-top: 2em; 141 | line-height: 0.8; 142 | margin-bottom: 1.2em; 143 | } 144 | h3 { 145 | font-size: 1.33em; 146 | line-height: 0.89; 147 | margin-top: 2.66em; 148 | margin-bottom: 1.33em; 149 | color:#95b383; 150 | } 151 | pre { 152 | background-color: #cddb12; 153 | font-size: 12px; 154 | padding: 1.5em; 155 | margin-bottom: 1.5em; 156 | overflow: auto; 157 | } 158 | code { 159 | font: 10px Monaco, "Courier New", Courier, monospace; 160 | color: #0d562a; 161 | } 162 | #header { 163 | /*position:relative;*/ 164 | height: 187px; /* 12 lines */ 165 | background: #fff url() no-repeat 0 0; 166 | margin-top: 10px; 167 | padding:0; 168 | } 169 | #header h1 { 170 | position: absolute; 171 | left:-9999px; 172 | margin:0; 173 | } 174 | #footer { 175 | padding: 0 55px; 176 | background-color: #1a1818; 177 | color: #999; 178 | height: 2em; 179 | line-height: 2em; 180 | text-align: right; 181 | } 182 | #footer a { 183 | color: #a3d8de; 184 | text-decoration: none; 185 | } 186 | #footer a:hover { 187 | color: #fff; 188 | } 189 | #content { 190 | background-color: #fff; 191 | padding: 0 55px; 192 | min-height: 400px; 193 | } 194 | p.bt { 195 | text-align:right; 196 | } 197 | p.bt a { 198 | text-decoration:none; 199 | padding: 2px 4px; 200 | } 201 | p.bt a:hover { 202 | background-color: #4596cd; 203 | color: #fff; 204 | } 205 | #debug-menu { 206 | position: fixed; 207 | top: 0px; 208 | right:20px; 209 | background-color: rgba(100,100,100, 0.7); 210 | padding:5px; 211 | } 212 | #debug-menu a { 213 | color: #fff; 214 | font-size: 90%; 215 | text-decoration:none; 216 | } 217 | #debug-menu a:hover { 218 | text-decoration: underline; 219 | } 220 | -------------------------------------------------------------------------------- /lib/limonade/public/img/bg_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jvaubourg/php-piratebox/d9cc1a57b9b99a0e4d63d0e518193f70876b221d/lib/limonade/public/img/bg_header.png -------------------------------------------------------------------------------- /lib/limonade/tests.php: -------------------------------------------------------------------------------- 1 | >>> START $name tests suites\n", 'white'); 57 | echo test_cli_format("-----------------------------------------------------------\n", 'white'); 58 | } 59 | 60 | /** 61 | * Ends the last group of test suites 62 | * 63 | * @return void 64 | */ 65 | function end_test_suite() 66 | { 67 | $name = $GLOBALS["limonade"]["test_suites"]; 68 | $failures = 0; 69 | $tests = 0; 70 | $passed_tests = 0; 71 | $assertions = 0; 72 | 73 | foreach($GLOBALS["limonade"]["test_cases"] as $test) 74 | { 75 | $failures += $test['failures']; 76 | $assertions += $test['assertions']; 77 | if(empty($test['failures'])) $passed_tests++; 78 | $tests++; 79 | } 80 | echo ">> ENDING $name tests suites\n "; 81 | echo $failures > 0 ? test_cli_format("|FAILED!|", "red") : test_cli_format("|PASSED|", "green");; 82 | echo " Passes ".$passed_tests."/".$tests.", "; 83 | echo " {$failures} failures for {$assertions} assertions.\n"; 84 | echo test_cli_format("===========================================================\n", 'white'); 85 | } 86 | 87 | /** 88 | * Starting a new test case 89 | * 90 | * @param string $name 91 | * @return void 92 | */ 93 | function test_case($name) 94 | { 95 | $name = strtolower($name); // TODO: normalize name 96 | 97 | if(!array_key_exists($name, $GLOBALS["limonade"]["test_cases"])) 98 | { 99 | $GLOBALS["limonade"]["test_cases"][$name] = array( 100 | "name" => $name, 101 | "assertions" => 0, 102 | "failures" => 0, 103 | "description" => NULL 104 | ); 105 | $GLOBALS["limonade"]["test_case_current"] = $name; 106 | } 107 | else 108 | { 109 | 110 | } 111 | } 112 | 113 | /** 114 | * Displays and ending the current tests suite 115 | * 116 | * @return void 117 | */ 118 | function end_test_case() 119 | { 120 | $name = $GLOBALS["limonade"]["test_case_current"]; 121 | echo "## ".strtoupper($name)."\n"; 122 | 123 | $desc = test_case_describe(); 124 | if(!is_null($desc)) echo $desc."\n"; 125 | 126 | echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"; 127 | 128 | test_case_execute_current(); 129 | 130 | 131 | if(!is_null($name)) 132 | { 133 | $test = $GLOBALS["limonade"]["test_cases"][$name]; 134 | // closing previous test 135 | echo "\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"; 136 | echo $test['failures'] > 0 ? test_cli_format("|FAILED!|", "red") : test_cli_format("|PASSED|", "green"); 137 | echo " Test case '$name' finished: "; 138 | echo count(test_case_all_func())." tests, "; 139 | echo " {$test['failures']} failures for {$test['assertions']} assertions.\n"; 140 | 141 | echo "-----------------------------------------------------------\n"; 142 | } 143 | $GLOBALS["limonade"]["test_case_current"] = null; 144 | } 145 | 146 | /** 147 | * Describes the current tests suite 148 | * 149 | * @param string $msg 150 | * @return string tests description 151 | */ 152 | function test_case_describe($msg = NULL) 153 | { 154 | $test =& test_case_current(); 155 | if(!is_null($msg)) 156 | { 157 | $test["description"] = $msg; 158 | } 159 | //var_dump($test["description"]); 160 | return $test["description"]; 161 | } 162 | 163 | /** 164 | * Returns all user test case functions 165 | * 166 | * @access private 167 | * @return void 168 | */ 169 | function test_case_all_func() 170 | { 171 | $functions = get_defined_functions(); 172 | $functions = $functions['user']; 173 | $tests = array(); 174 | $name = $GLOBALS["limonade"]["test_case_current"]; 175 | while ($func = array_shift($functions)) { 176 | $regexp = "/^test_{$name}_(.*)$/"; 177 | if(!preg_match($regexp, $func)) continue; 178 | if($func == test_before_func_name()) continue; 179 | // TODO: adding break for all test api methods 180 | 181 | $tests[] = $func; 182 | } 183 | return $tests; 184 | } 185 | 186 | /** 187 | * Execute current test case 188 | * 189 | * @access private 190 | * @return void 191 | */ 192 | function test_case_execute_current() 193 | { 194 | $tests = test_case_all_func(); 195 | while($func = array_shift($tests)) 196 | { 197 | test_call_func(test_before_func_name()); 198 | call_user_func($func); 199 | } 200 | } 201 | 202 | 203 | function &test_case_current() 204 | { 205 | $name = $GLOBALS["limonade"]["test_case_current"]; 206 | return $GLOBALS["limonade"]["test_cases"][$name]; 207 | } 208 | 209 | 210 | 211 | function test_before_func_name() 212 | { 213 | $test = test_case_current(); 214 | $func = "before_each_test_in_".$test["name"]; 215 | return $func; 216 | } 217 | 218 | function test_before_assert_func_name() 219 | { 220 | $test = test_case_current(); 221 | $func = "before_each_assert_in_$name".$test["name"]; 222 | return $func; 223 | } 224 | 225 | function test_run_assertion() 226 | { 227 | $name = $GLOBALS["limonade"]["test_case_current"]; 228 | $GLOBALS["limonade"]["test_cases"][$name]['assertions']++; 229 | test_call_func(test_before_assert_func_name()); 230 | } 231 | 232 | /** 233 | * Calls a function if exists 234 | * 235 | * @param string $func the function name 236 | * @param mixed $arg,.. (optional) 237 | * @return mixed 238 | */ 239 | function test_call_func($func) 240 | { 241 | if(empty($func)) return; 242 | $args = func_get_args(); 243 | $func = array_shift($args); 244 | if(function_exists($func)) return call_user_func_array($func, $args); 245 | return; 246 | } 247 | 248 | /** 249 | * Error handler 250 | * 251 | * @access private 252 | * @return boolean true 253 | */ 254 | function test_error_handler($errno, $errstr, $errfile, $errline) 255 | { 256 | if($errno < E_USER_ERROR || $errno > E_USER_NOTICE) 257 | echo test_cli_format("!!! ERROR", "red") . " [$errno], $errstr in $errfile at line $errline\n"; 258 | $GLOBALS["limonade"]["test_errors"][] = array($errno, $errstr, $errfile, $errline); 259 | return true; 260 | } 261 | 262 | /** 263 | * Assert callback 264 | * 265 | * @access private 266 | * @param string $script 267 | * @param string $line 268 | * @param string $message 269 | * @return void 270 | */ 271 | function test_assert_failure($script, $line, $message) 272 | { 273 | // Using the stack trace, find the outermost assert*() call 274 | $stacktrace = array_slice(debug_backtrace(), 1); // skip self 275 | $assertion = reset($stacktrace); 276 | while ($stackframe = array_shift($stacktrace)) { 277 | if (!preg_match('/^assert/', $stackframe['function'])) 278 | break; 279 | $assertion = $stackframe; 280 | } 281 | 282 | extract($assertion, EXTR_PREFIX_ALL, 'assert'); 283 | $code = explode("\n", file_get_contents($assert_file)); 284 | $code = trim($code[$assert_line - 1]); 285 | 286 | list($assert_code, $message) = explode("//", $message); 287 | echo test_cli_format("Assertion failed", "yellow"); 288 | echo " in script *{$assert_file}* (line {$assert_line}):\n"; 289 | echo " * assertion: $code\n"; 290 | echo " * message: $message\n"; 291 | $name = $GLOBALS["limonade"]["test_case_current"]; 292 | $GLOBALS["limonade"]["test_cases"][$name]['failures']++; 293 | } 294 | 295 | function test_cli_format($text, $format) { 296 | $formats = array( 297 | "blue" => 34, 298 | "bold" => 1, 299 | "green" => 32, 300 | "highlight" => 7, 301 | "light_blue" => 36, 302 | "purple" => 35, 303 | "red" => 31, 304 | "underline" => 4, 305 | "white" => 37, 306 | "yellow" => 33 307 | ); 308 | 309 | if (array_key_exists($format, $formats)) $format = $formats[$format]; 310 | return chr(27) . "[01;{$format} m{$text}" . chr(27) . "[00m"; 311 | } 312 | 313 | /** 314 | * Do HTTP request and return the response content. 315 | * 316 | * @param string $url 317 | * @param string $method 318 | * @param bool $include_header 319 | * @return string 320 | * @author Nando Vieira 321 | */ 322 | function test_request($url, $method="GET", $include_header=false, $post_data=array(), $http_header=array()) { 323 | $method = strtoupper($method); 324 | $allowed_methods = array("GET", "PUT", "POST", "DELETE", "HEAD"); 325 | if(!in_array($method, $allowed_methods)) 326 | { 327 | $message = "The requested method '$method' is not allowed"; 328 | return assert('false; //'.$message); 329 | } 330 | 331 | $curl = curl_init($url); 332 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 333 | curl_setopt($curl, CURLOPT_HEADER, $include_header); 334 | curl_setopt($curl, CURLOPT_HTTPHEADER, $http_header); 335 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); 336 | curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); 337 | if($method == 'POST' || $method == 'PUT') 338 | { 339 | curl_setopt($curl, CURLOPT_POST, 1); 340 | curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); 341 | } 342 | if($method == 'HEAD') 343 | { 344 | curl_setopt($curl, CURLOPT_NOBODY, true); 345 | } 346 | $response = curl_exec($curl); 347 | curl_close($curl); 348 | 349 | return $response; 350 | } 351 | -------------------------------------------------------------------------------- /lib/limonade/views/_debug.html.php: -------------------------------------------------------------------------------- 1 | ENV_PRODUCTION && option('debug')): ?> 2 | 3 |

[] 4 | (in line ) 5 |

6 | 7 | 8 | 9 | 10 |

Debug arguments

11 |
12 | 13 | 14 |

Options

15 |
16 |

[ ↑ ]

17 | 18 |

Environment

19 |
20 |

[ ↑ ]

21 | 22 |

Backtrace

23 |
24 |

[ ↑ ]

25 | 26 |
27 | 28 | 29 | Debug arguments | 30 | 31 | Options | 32 | Environment | 33 | Backtrace | 34 | [ ↑ ] 35 |
36 | 37 | -------------------------------------------------------------------------------- /lib/limonade/views/_notices.html.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |

→ Notices and warnings

4 |
5 | 6 |
[]
7 |
8 | in 9 | line 10 |
11 | 12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /lib/limonade/views/default_layout.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Limonade, the fizzy PHP micro-framework 6 | 7 | 8 | 9 | 12 | 13 |
14 | 15 |
16 | 17 |
18 |
19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /lib/limonade/views/error.html.php: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/unix_func.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as 9 | * published by the Free Software Foundation, either version 3 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | function read_file($file, $lines = 20) { 22 | 23 | if (!$handle = fopen($file, "r")) 24 | return false; 25 | $linecounter = $lines; 26 | $pos = -2; 27 | $beginning = false; 28 | $text = array(); 29 | while ($linecounter > 0) { 30 | $t = " "; 31 | while ($t != "\n") { 32 | if(fseek($handle, $pos, SEEK_END) == -1) { 33 | $beginning = true; 34 | break; 35 | } 36 | $t = fgetc($handle); 37 | $pos --; 38 | } 39 | $linecounter --; 40 | if ($beginning) { 41 | rewind($handle); 42 | } 43 | $text[$lines-$linecounter-1] = fgets($handle); 44 | if ($beginning) break; 45 | } 46 | fclose ($handle); 47 | return array_reverse($text); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /public/bootstrap/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default, 8 | .btn-primary, 9 | .btn-success, 10 | .btn-info, 11 | .btn-warning, 12 | .btn-danger { 13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 16 | } 17 | .btn-default:active, 18 | .btn-primary:active, 19 | .btn-success:active, 20 | .btn-info:active, 21 | .btn-warning:active, 22 | .btn-danger:active, 23 | .btn-default.active, 24 | .btn-primary.active, 25 | .btn-success.active, 26 | .btn-info.active, 27 | .btn-warning.active, 28 | .btn-danger.active { 29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 31 | } 32 | .btn-default .badge, 33 | .btn-primary .badge, 34 | .btn-success .badge, 35 | .btn-info .badge, 36 | .btn-warning .badge, 37 | .btn-danger .badge { 38 | text-shadow: none; 39 | } 40 | .btn:active, 41 | .btn.active { 42 | background-image: none; 43 | } 44 | .btn-default { 45 | text-shadow: 0 1px 0 #fff; 46 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 47 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 48 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 49 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 50 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 51 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 52 | background-repeat: repeat-x; 53 | border-color: #dbdbdb; 54 | border-color: #ccc; 55 | } 56 | .btn-default:hover, 57 | .btn-default:focus { 58 | background-color: #e0e0e0; 59 | background-position: 0 -15px; 60 | } 61 | .btn-default:active, 62 | .btn-default.active { 63 | background-color: #e0e0e0; 64 | border-color: #dbdbdb; 65 | } 66 | .btn-default:disabled, 67 | .btn-default[disabled] { 68 | background-color: #e0e0e0; 69 | background-image: none; 70 | } 71 | .btn-primary { 72 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 73 | background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 74 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2)); 75 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); 76 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); 77 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 78 | background-repeat: repeat-x; 79 | border-color: #2b669a; 80 | } 81 | .btn-primary:hover, 82 | .btn-primary:focus { 83 | background-color: #2d6ca2; 84 | background-position: 0 -15px; 85 | } 86 | .btn-primary:active, 87 | .btn-primary.active { 88 | background-color: #2d6ca2; 89 | border-color: #2b669a; 90 | } 91 | .btn-primary:disabled, 92 | .btn-primary[disabled] { 93 | background-color: #2d6ca2; 94 | background-image: none; 95 | } 96 | .btn-success { 97 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 98 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 99 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 100 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 101 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 102 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 103 | background-repeat: repeat-x; 104 | border-color: #3e8f3e; 105 | } 106 | .btn-success:hover, 107 | .btn-success:focus { 108 | background-color: #419641; 109 | background-position: 0 -15px; 110 | } 111 | .btn-success:active, 112 | .btn-success.active { 113 | background-color: #419641; 114 | border-color: #3e8f3e; 115 | } 116 | .btn-success:disabled, 117 | .btn-success[disabled] { 118 | background-color: #419641; 119 | background-image: none; 120 | } 121 | .btn-info { 122 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 123 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 124 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 125 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 126 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 127 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 128 | background-repeat: repeat-x; 129 | border-color: #28a4c9; 130 | } 131 | .btn-info:hover, 132 | .btn-info:focus { 133 | background-color: #2aabd2; 134 | background-position: 0 -15px; 135 | } 136 | .btn-info:active, 137 | .btn-info.active { 138 | background-color: #2aabd2; 139 | border-color: #28a4c9; 140 | } 141 | .btn-info:disabled, 142 | .btn-info[disabled] { 143 | background-color: #2aabd2; 144 | background-image: none; 145 | } 146 | .btn-warning { 147 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 148 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 149 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 150 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 151 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 152 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 153 | background-repeat: repeat-x; 154 | border-color: #e38d13; 155 | } 156 | .btn-warning:hover, 157 | .btn-warning:focus { 158 | background-color: #eb9316; 159 | background-position: 0 -15px; 160 | } 161 | .btn-warning:active, 162 | .btn-warning.active { 163 | background-color: #eb9316; 164 | border-color: #e38d13; 165 | } 166 | .btn-warning:disabled, 167 | .btn-warning[disabled] { 168 | background-color: #eb9316; 169 | background-image: none; 170 | } 171 | .btn-danger { 172 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 173 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 174 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 175 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 176 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 177 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 178 | background-repeat: repeat-x; 179 | border-color: #b92c28; 180 | } 181 | .btn-danger:hover, 182 | .btn-danger:focus { 183 | background-color: #c12e2a; 184 | background-position: 0 -15px; 185 | } 186 | .btn-danger:active, 187 | .btn-danger.active { 188 | background-color: #c12e2a; 189 | border-color: #b92c28; 190 | } 191 | .btn-danger:disabled, 192 | .btn-danger[disabled] { 193 | background-color: #c12e2a; 194 | background-image: none; 195 | } 196 | .thumbnail, 197 | .img-thumbnail { 198 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 199 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 200 | } 201 | .dropdown-menu > li > a:hover, 202 | .dropdown-menu > li > a:focus { 203 | background-color: #e8e8e8; 204 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 205 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 206 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 207 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 208 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 209 | background-repeat: repeat-x; 210 | } 211 | .dropdown-menu > .active > a, 212 | .dropdown-menu > .active > a:hover, 213 | .dropdown-menu > .active > a:focus { 214 | background-color: #357ebd; 215 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 216 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); 217 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); 218 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 220 | background-repeat: repeat-x; 221 | } 222 | .navbar-default { 223 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 224 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); 225 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); 226 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 227 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 228 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 229 | background-repeat: repeat-x; 230 | border-radius: 4px; 231 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 232 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 233 | } 234 | .navbar-default .navbar-nav > .open > a, 235 | .navbar-default .navbar-nav > .active > a { 236 | background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 237 | background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 238 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); 239 | background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); 240 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); 241 | background-repeat: repeat-x; 242 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 243 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 244 | } 245 | .navbar-brand, 246 | .navbar-nav > li > a { 247 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 248 | } 249 | .navbar-inverse { 250 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 251 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 252 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 253 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 254 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 255 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 256 | background-repeat: repeat-x; 257 | } 258 | .navbar-inverse .navbar-nav > .open > a, 259 | .navbar-inverse .navbar-nav > .active > a { 260 | background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); 261 | background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); 262 | background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); 263 | background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); 264 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); 265 | background-repeat: repeat-x; 266 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 267 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 268 | } 269 | .navbar-inverse .navbar-brand, 270 | .navbar-inverse .navbar-nav > li > a { 271 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 272 | } 273 | .navbar-static-top, 274 | .navbar-fixed-top, 275 | .navbar-fixed-bottom { 276 | border-radius: 0; 277 | } 278 | .alert { 279 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 280 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 281 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 282 | } 283 | .alert-success { 284 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 285 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 286 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 287 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 288 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 289 | background-repeat: repeat-x; 290 | border-color: #b2dba1; 291 | } 292 | .alert-info { 293 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 294 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 295 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 296 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 297 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 298 | background-repeat: repeat-x; 299 | border-color: #9acfea; 300 | } 301 | .alert-warning { 302 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 303 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 304 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 305 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 306 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 307 | background-repeat: repeat-x; 308 | border-color: #f5e79e; 309 | } 310 | .alert-danger { 311 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 312 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 313 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 314 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 315 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 316 | background-repeat: repeat-x; 317 | border-color: #dca7a7; 318 | } 319 | .progress { 320 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 321 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 322 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 323 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 324 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 325 | background-repeat: repeat-x; 326 | } 327 | .progress-bar { 328 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); 329 | background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%); 330 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9)); 331 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 332 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 333 | background-repeat: repeat-x; 334 | } 335 | .progress-bar-success { 336 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 337 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 338 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 339 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 340 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 341 | background-repeat: repeat-x; 342 | } 343 | .progress-bar-info { 344 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 345 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 346 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 347 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 348 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 349 | background-repeat: repeat-x; 350 | } 351 | .progress-bar-warning { 352 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 353 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 354 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 355 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 356 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 357 | background-repeat: repeat-x; 358 | } 359 | .progress-bar-danger { 360 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 361 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 362 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 363 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 364 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 365 | background-repeat: repeat-x; 366 | } 367 | .progress-bar-striped { 368 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 369 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 370 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 371 | } 372 | .list-group { 373 | border-radius: 4px; 374 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 375 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 376 | } 377 | .list-group-item.active, 378 | .list-group-item.active:hover, 379 | .list-group-item.active:focus { 380 | text-shadow: 0 -1px 0 #3071a9; 381 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); 382 | background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%); 383 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3)); 384 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 385 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 386 | background-repeat: repeat-x; 387 | border-color: #3278b3; 388 | } 389 | .list-group-item.active .badge, 390 | .list-group-item.active:hover .badge, 391 | .list-group-item.active:focus .badge { 392 | text-shadow: none; 393 | } 394 | .panel { 395 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 396 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 397 | } 398 | .panel-default > .panel-heading { 399 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 400 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 401 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 402 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 403 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 404 | background-repeat: repeat-x; 405 | } 406 | .panel-primary > .panel-heading { 407 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 408 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); 409 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); 410 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 411 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 412 | background-repeat: repeat-x; 413 | } 414 | .panel-success > .panel-heading { 415 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 416 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 417 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 418 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 419 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 420 | background-repeat: repeat-x; 421 | } 422 | .panel-info > .panel-heading { 423 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 424 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 425 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 426 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 427 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 428 | background-repeat: repeat-x; 429 | } 430 | .panel-warning > .panel-heading { 431 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 432 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 433 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 434 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 435 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 436 | background-repeat: repeat-x; 437 | } 438 | .panel-danger > .panel-heading { 439 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 440 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 441 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 442 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 443 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 444 | background-repeat: repeat-x; 445 | } 446 | .well { 447 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 448 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 449 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 450 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 451 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 452 | background-repeat: repeat-x; 453 | border-color: #dcdcdc; 454 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 455 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 456 | } 457 | /*# sourceMappingURL=bootstrap-theme.css.map */ 458 | -------------------------------------------------------------------------------- /public/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-default .badge,.btn-primary .badge,.btn-success .badge,.btn-info .badge,.btn-warning .badge,.btn-danger .badge{text-shadow:none}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-o-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#2d6ca2));background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-primary:disabled,.btn-primary[disabled]{background-color:#2d6ca2;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.list-group-item.active .badge,.list-group-item.active:hover .badge,.list-group-item.active:focus .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /public/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jvaubourg/php-piratebox/d9cc1a57b9b99a0e4d63d0e518193f70876b221d/public/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jvaubourg/php-piratebox/d9cc1a57b9b99a0e4d63d0e518193f70876b221d/public/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jvaubourg/php-piratebox/d9cc1a57b9b99a0e4d63d0e518193f70876b221d/public/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /public/chat/.gitfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jvaubourg/php-piratebox/d9cc1a57b9b99a0e4d63d0e518193f70876b221d/public/chat/.gitfile -------------------------------------------------------------------------------- /public/css/contextMenu.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery contextMenu - Plugin for simple contextMenu handling 3 | * 4 | * Version: 1.6.6 5 | * 6 | * Authors: Rodney Rehm, Addy Osmani (patches for FF) 7 | * Web: http://medialize.github.com/jQuery-contextMenu/ 8 | * 9 | * Licensed under 10 | * MIT License http://www.opensource.org/licenses/mit-license 11 | * GPL v3 http://opensource.org/licenses/GPL-3.0 12 | * 13 | */ 14 | 15 | .context-menu-list { 16 | margin:0; 17 | padding:0; 18 | 19 | min-width: 120px; 20 | max-width: 250px; 21 | display: inline-block; 22 | position: absolute; 23 | list-style-type: none; 24 | 25 | border: 1px solid #000; 26 | background: #111; 27 | 28 | -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); 29 | -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); 30 | -ms-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); 31 | -o-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); 32 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5); 33 | 34 | font-size: 1em; 35 | text-shadow: .1em .1em #000; 36 | border-radius: 2px; 37 | opacity: .98; 38 | display: none; 39 | } 40 | 41 | .context-menu-item { 42 | padding: 3px 3px 7px 7px; 43 | background-color: #111; 44 | position: relative; 45 | -webkit-user-select: none; 46 | -moz-user-select: -moz-none; 47 | -ms-user-select: none; 48 | user-select: none; 49 | } 50 | 51 | .context-menu-separator { 52 | padding-bottom:0; 53 | border-bottom: 1px solid #000; 54 | } 55 | 56 | .context-menu-item > label > input, 57 | .context-menu-item > label > textarea { 58 | -webkit-user-select: text; 59 | -moz-user-select: text; 60 | -ms-user-select: text; 61 | user-select: text; 62 | } 63 | 64 | .context-menu-item.hover { 65 | cursor: pointer; 66 | background-color: #222; 67 | } 68 | 69 | .context-menu-item.disabled { 70 | color: #666; 71 | } 72 | 73 | .context-menu-input.hover, 74 | .context-menu-item.disabled.hover { 75 | cursor: default; 76 | background-color: #EEE; 77 | } 78 | 79 | .context-menu-submenu:after { 80 | content: ">"; 81 | color: #666; 82 | position: absolute; 83 | top: 0; 84 | right: 3px; 85 | z-index: 1; 86 | } 87 | 88 | /* icons 89 | #protip: 90 | In case you want to use sprites for icons (which I would suggest you do) have a look at 91 | http://css-tricks.com/13224-pseudo-spriting/ to get an idea of how to implement 92 | .context-menu-item.icon:before {} 93 | */ 94 | .context-menu-item.icon { min-height: 18px; background-repeat: no-repeat; background-position: 4px 2px; } 95 | .context-menu-item.icon-edit { background-image: url(../img/page_white_edit.png); } 96 | .context-menu-item.icon-cut { background-image: url(../img/cut.png); } 97 | .context-menu-item.icon-copy { background-image: url(../img/page_white_copy.png); } 98 | .context-menu-item.icon-paste { background-image: url(../img/page_white_paste.png); } 99 | .context-menu-item.icon-delete { background-image: url(../img/page_white_delete.png); } 100 | .context-menu-item.icon-add { background-image: url(../img/page_white_add.png); } 101 | .context-menu-item.icon-quit { background-image: url(../img/door.png); } 102 | 103 | /* vertically align inside labels */ 104 | .context-menu-input > label > * { vertical-align: top; } 105 | 106 | /* position checkboxes and radios as icons */ 107 | .context-menu-input > label > input[type="checkbox"], 108 | .context-menu-input > label > input[type="radio"] { 109 | margin-left: -17px; 110 | } 111 | .context-menu-input > label > span { 112 | margin-left: 5px; 113 | } 114 | 115 | .context-menu-input > label, 116 | .context-menu-input > label > input[type="text"], 117 | .context-menu-input > label > textarea, 118 | .context-menu-input > label > select { 119 | display: block; 120 | width: 100%; 121 | 122 | -webkit-box-sizing: border-box; 123 | -moz-box-sizing: border-box; 124 | -ms-box-sizing: border-box; 125 | -o-box-sizing: border-box; 126 | box-sizing: border-box; 127 | } 128 | 129 | .context-menu-input > label > textarea { 130 | height: 100px; 131 | } 132 | .context-menu-item > .context-menu-list { 133 | display: none; 134 | /* re-positioned by js */ 135 | right: -5px; 136 | top: 5px; 137 | } 138 | 139 | .context-menu-item.hover > .context-menu-list { 140 | display: block; 141 | } 142 | 143 | .context-menu-accesskey { 144 | text-decoration: underline; 145 | } 146 | -------------------------------------------------------------------------------- /public/css/filedrop.css: -------------------------------------------------------------------------------- 1 | /*** 2 | Styles below are only required if you're using '+'
'+''+''+"
",i.firstChild.setAttribute("id",t),i.firstChild.style.display="none",i.lastChild.setAttribute("target",t);var s=e.firstChild;while(s&&(!n.isTag(s)||n.isTag(s,"legend")))s=s.nextSibling;return s?e.insertBefore(i,s):e.appendChild(i),i.lastChild.lastChild},r.abortIFrame=function(){if(r.opt.input.form){var e=n.byID(r.opt.input.form.getAttribute("target"));e&&e.setAttribute("src","javascript:false")}},r.sendViaIFrame=function(e){e=e||r.opt.iframe.url;var t=(r.opt.input||{}).form;if(e&&t){do var i=n.randomID();while(i in window);window[i]=function(t){typeof t!="object"&&(t={response:t,responseXML:"",responseText:(t||"").toString(),readyState:4,status:200,statusText:"OK",getAllResponseHeaders:function(){return""},getResponseHeader:function(){return""},setRequestHeader:function(){return this},statusCode:function(){return this},abort:function(){return this}}),n.extend(t,{iframe:!0,url:e}),n.callAllOfObject(r,"iframeDone",t)};var s=t.firstChild;while(s&&(!n.isTag(s,"input")||s.name!=r.opt.iframe.callbackParam))s=s.nextSibling;return s?s.value=i:e=e.replace(/[?&]+$/,"")+(e.indexOf("?")==-1?"?":"&")+r.opt.iframe.callbackParam+"="+i,t.setAttribute("action",e),n.callAllOfObject(r,"iframeSetup",t),t.submit(),setTimeout(r.resetForm,300),!0}},r.resetForm=function(){var e=r.opt.input&&r.opt.input.file;if(e){e.value="";if(r.opt.recreateInput){var t=r.opt.input.file=e.cloneNode(!0);e.parentNode.replaceChild(t,e),n.callAllOfObject(r,"inputSetup",[r.opt.input,e])}}},r.multiple=function(e){return r.opt.input&&typeof e!="undefined"&&(e?r.opt.input.file.setAttribute("multiple","multiple"):r.opt.input.file.removeAttribute("multiple")),r.opt.input&&!!r.opt.input.file.getAttribute("multiple")},r.event=function(e,t){return n.appendEventsToObject.apply(r,arguments)},r.preview=function(e,t){return n.previewToObject.apply(r,arguments)},r.onInputSetup=function(t,i){i?(t.file.clearAttributes&&t.file.clearAttributes(),t.file.mergeAttributes&&t.file.mergeAttributes(i)):r.multiple(r.opt.multiple),n.setClass(t.file,r.opt.inputClass),r.delegate(t.file,"change","upload");var s=t.file.parentNode;s&&s.style.display.match(/^(static)?$/)&&(s.style.position="relative");if(n.isTag(e,"fieldset")){var o=document.createElement("div");o.style.position="relative",o.style.overflow="hidden",e.parentNode.insertBefore(o,e),o.appendChild(e)}},r.onDragOver=function(e){n.stopEvent(e),e.dataTransfer&&(e.dataTransfer.dropEffect=r.opt.dropEffect)},r.onUpload=function(){for(var e=0;e0&&n.callAllOfObject(r,"send",[t]):!r.handle.sendViaIFrame()&&n.hasConsole&&console.warn("FileDrop fallback upload triggered but iframe options were not configured - doing nothing.")},r.eventFiles=function(e,t){var i=new n.FileList(e);if(e.dataTransfer&&(e.dataTransfer.length||e.dataTransfer.files))var s=e.dataTransfer;else var s=e.target&&e.target.files||e.srcElement&&e.srcElement.files;if(s){var o=s.items||[];s.files&&(s=s.files);var u={};for(var a=0;a0||f.nativeEntry)&&i.push(f)}}else t&&(i=!1);return i},n.extend(r,r.handle),r.event({upload:r.onUpload,send:r.resetForm,dragEnter:i(!0),dragLeave:i(!1),uploadElsewhere:i(!1)}),r.preview({upload:i(!1)})},n.FileList=function(e){var t=this;t.dropEffect=e&&e.dropEffect||"",t.length=0,e=null,t.push=function(e){return t[t.length++]=e,t},t.pop=function(){if(t.length>0){var e=t.last();return delete t[--t.length],e}},t.first=function(){return t[0]},t.last=function(){return t[t.length-1]},t.remove=function(e){for(;et[1]?1:e[1]0||t.end!=null&&t.end)t.blob.slice?(t.end==null&&(t.end=t.blob.size||t.blob.fileSize),t.blob=t.blob.slice(t.start,t.end,t.mime)):n.hasConsole&&console.warn("File Blob/slice() are unsupported - operating on entire File.");var s=new FileReader;s.onerror=function(e){i("read",e)},s.onload=function(e){e.target&&e.target.result?(t.func=="readAsBinaryString"&&(e.target.result=String.fromCharCode.apply(null,new Uint8Array(e.target.result))),t.onDone(e.target.result)):s.onerror(e)};var o=t.func;if(n.isArray(o)){var u=o[0];return o[0]=t.blob,s[u].apply(s,o)}if(!o||o=="bin")o="readAsBinaryString";else if(o=="url"||o=="uri"||o=="src")o="readAsDataURL";else if(o=="array")o="readAsArrayBuffer";else if(o=="text")o="readAsText";else if(o.substr(0,4)!="read")return s.readAsText(t.blob,o);return o=="readAsBinaryString"&&(o="readAsArrayBuffer"),s[o](t.blob)},r.listEntries=function(e,t){if(r.nativeEntry&&r.nativeEntry.isDirectory){t=t||new Function;var i=r.nativeEntry.createReader(),s=new n.FileList,o=0;function u(t){o-=t,o==0&&e&&(e(s),e=null)}return i.readEntries(function(e){for(var r=0;r 4 | * Contribute at https://github.com/jvaubourg/php-piratebox 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | ?> 20 | 21 |
22 | data-locked="" 23 | data-name="" 24 | data-filename="" 25 | data-size="" 26 | data-date=""> 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 | -------------------------------------------------------------------------------- /views/_folder.html.php: -------------------------------------------------------------------------------- 1 | 4 | * Contribute at https://github.com/jvaubourg/php-piratebox 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | ?> 20 | 21 |
22 | data-locked="" 23 | data-dir=""> 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | -------------------------------------------------------------------------------- /views/home.html.php: -------------------------------------------------------------------------------- 1 | 4 | * Contribute at https://github.com/jvaubourg/php-piratebox 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | ?> 20 | 21 | 46 | 47 |
" 49 | data-txt-delfolder="" 50 | data-txt-open="" 51 | data-txt-download="" 52 | data-txt-rename="" 53 | data-txt-delete="" 54 | data-opt-allow-renaming="" 55 | data-opt-allow-deleting="" 56 | data-opt-allow-newfolders=""> 57 | 58 |
59 | 60 | 61 | 62 | 63 | 64 | " > 65 | " > 66 |
67 | 68 |
69 |
70 |

71 |
72 | 73 |
74 | 77 | 78 |
79 | 80 |
81 | 82 | > 83 | 84 |
>
85 |
86 |
87 |
88 | 89 |
90 |
91 |

92 |
93 | 94 |
95 |
96 | 97 | -- 98 | 99 |
100 | 101 |
102 | 103 |
> 104 |   105 | 106 |
107 |
108 | " /> 109 | 110 | 111 | 112 |
113 |
114 |
115 |
116 |
117 |
118 | 119 |
120 | data-opt-enable-chat="" 121 | data-opt-default-pseudo=""> 122 | 123 |
124 |
125 |
126 | "> 127 | 128 | 129 | 130 |
131 |
132 |
133 | -------------------------------------------------------------------------------- /views/layout.html.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | <?= option('app_name') ?> 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 | 50 | 51 | 55 |
56 | 57 | 58 | 59 | --------------------------------------------------------------------------------