]> git.p6c8.net - jirafeau.git/commitdiff
Merged next-release into master
authorPatrick Canterino <patrick@patrick-canterino.de>
Thu, 27 Jun 2024 10:15:52 +0000 (12:15 +0200)
committerPatrick Canterino <patrick@patrick-canterino.de>
Thu, 27 Jun 2024 10:15:52 +0000 (12:15 +0200)
64 files changed:
.gitlab-ci.yml
README.md
admin.php
docker/README.md
docker/docker_config.php
docker/lighttpd.conf
f.php
index.php
install.php
lib/config.original.php
lib/functions.js.php
lib/functions.php
lib/locales/ar.json
lib/locales/be.json
lib/locales/bn_IN.json
lib/locales/bo.json
lib/locales/ca.json
lib/locales/ckb.json
lib/locales/cs.json
lib/locales/da.json
lib/locales/de.json
lib/locales/el.json
lib/locales/en.json
lib/locales/es.json
lib/locales/et.json
lib/locales/fi.json
lib/locales/fr.json
lib/locales/he.json
lib/locales/hi.json
lib/locales/hr.json
lib/locales/hu.json
lib/locales/id.json
lib/locales/it.json
lib/locales/ja.json
lib/locales/ko.json
lib/locales/la.json
lib/locales/mfe.json
lib/locales/ms.json
lib/locales/nb_NO.json
lib/locales/nl.json
lib/locales/pl.json
lib/locales/ps.json
lib/locales/pt.json
lib/locales/pt_BR.json
lib/locales/ro.json
lib/locales/ru.json
lib/locales/sh.json
lib/locales/si.json
lib/locales/sk.json
lib/locales/sl.json
lib/locales/sq.json
lib/locales/sr.json
lib/locales/sv.json
lib/locales/ta.json
lib/locales/template.json
lib/locales/th.json
lib/locales/tr.json
lib/locales/uk.json
lib/locales/vi.json
lib/locales/zh.json
lib/locales/zh_TW.json
lib/settings.php
lib/template/header.php
script.php

index cddf9409209f5ad1b3ba9bbdffc83a94a97ccc65..0d2d9c4a51ab8160a903b2431f48fa72e4b12598 100644 (file)
@@ -1,5 +1,5 @@
 # Select docker image from https://hub.docker.com/_/php/
-image: php:7.3
+image: php:8.1
 
 # Select what we should cache
 cache:
@@ -17,44 +17,19 @@ before_script:
   - curl -sS https://getcomposer.org/installer | php
   # Create composer.json file manually, since this is a project without any non-dev dependencies yet
   - php composer.phar require --dev php-parallel-lint/php-parallel-lint
-  - php composer.phar require --dev friendsofphp/php-cs-fixer
+  - php composer.phar require --dev friendsofphp/php-cs-fixer:3.10.0
   # Install all project dependencies
   - php composer.phar install
 
 # Run tests
-test_app_phpdefaultversion:
+job_lint_app_81:
+  image: php:8.1
   script:
     - ./vendor/bin/parallel-lint --exclude vendor .
-    - ./vendor/bin/php-cs-fixer -vvv fix . --dry-run --diff --using-cache=no --rules=@PSR2
+    - ./vendor/bin/php-cs-fixer -vvv fix . --dry-run --using-cache=no --rules=@PSR2
 
-job_lint_app_phpnextversion:
+job_lint_app_74:
   image: php:7.4
   script:
     - ./vendor/bin/parallel-lint --exclude vendor .
-    - ./vendor/bin/php-cs-fixer -vvv fix . --dry-run --diff --using-cache=no --rules=@PSR2
-  allow_failure: true
-
-# Run same tests with older supported versions
-test_app_php72:
-  image: php:7.2
-  script:
-    - ./vendor/bin/parallel-lint --exclude vendor .
-    - ./vendor/bin/php-cs-fixer -vvv fix . --dry-run --diff --using-cache=no --rules=@PSR2
-
-test_app_php71:
-  image: php:7.1
-  script:
-    - ./vendor/bin/parallel-lint --exclude vendor .
-    - ./vendor/bin/php-cs-fixer -vvv fix . --dry-run --diff --using-cache=no --rules=@PSR2
-
-test_app_php70:
-  image: php:7.0
-  script:
-    - ./vendor/bin/parallel-lint --exclude vendor .
-    - ./vendor/bin/php-cs-fixer -vvv fix . --dry-run --diff --using-cache=no --rules=@PSR2
-
-test_app_php56:
-  image: php:5.6
-  script:
-    - ./vendor/bin/parallel-lint --exclude vendor .
-    - ./vendor/bin/php-cs-fixer -vvv fix . --dry-run --diff --using-cache=no --rules=@PSR2
+    - ./vendor/bin/php-cs-fixer -vvv fix . --dry-run --using-cache=no --rules=@PSR2
index 3e9a1775648a7df88ba817398f911afd2ee6a0c0..765b5bd99dc95176838a86e0c5490b632bfd0ae9 100644 (file)
--- a/README.md
+++ b/README.md
@@ -25,6 +25,7 @@ See [jirafeau.net](https://jirafeau.net/) for a demo.
 - Shows progression: speed, percentage and remaining upload time
 - Preview content in browser (if possible)
 - Optional password protection (for uploading or downloading)
+- option to require, check or generate file download passwords
 - Set expiration time for downloads
 - Option to self-destruct after first download
 - Shortened URLs using base 64 encoding
@@ -127,13 +128,13 @@ An other obvious basic security is to let access users to the site by HTTPS (mak
 
 Data encryption can be activated in options. This feature makes the server encrypt data and send the decryt key to the user (inside download URL).
 The decrypt key is not stored on the server so if you loose an url, you won't be able to retrieve file content.
-Encryption is configured to use AES256 in OFB mode.
+Encryption is configured to use [XChaCha20-Poly1305](https://en.wikipedia.org/wiki/ChaCha20-Poly1305).
 In case of security troubles on the server, attacker won't be able to access files.
 
 By activating this feature, you have to be aware of few things:
 -  Data encryption has a cost (cpu) and it takes more time for downloads to complete once file sent.
 -  During the download, the server will decrypt on the fly (and use resource).
--  This feature needs to have the mcrypt php module.
+-  This feature needs to have the Sodium php module.
 -  File de-duplication will stop to work (as we can't compare two encrypted files).
 -  Be sure your server do not log client's requests.
 -  Don't forget to enable https.
index d05ce35bc726b6daab7c739af233f0c651b21468..0f8967f90736d5193841e4ba664a99dbad699b43 100644 (file)
--- a/admin.php
+++ b/admin.php
@@ -44,7 +44,8 @@ if (php_sapi_name() == "cli") {
     } else {
         die("No command found. Should be admin.php <clean_expired|clean_async>.\n");
     }
-} else {
+// Second check: Challenge by IP
+} elseif (true === jirafeau_challenge_admin_ip($cfg, get_ip_address($cfg))) {
     /* Disable admin interface if we have a empty admin password. */
     if (empty($cfg['admin_password']) && empty($cfg['admin_http_auth_user'])) {
         require(JIRAFEAU_ROOT . 'lib/template/header.php');
@@ -57,7 +58,7 @@ if (php_sapi_name() == "cli") {
 
     /* Logout if requested. */
     if (jirafeau_admin_session_logged() && isset($_POST['action']) && (strcmp($_POST['action'], 'logout') == 0)) {
-        jirafeau_admin_session_end();
+        jirafeau_session_end();
     }
 
     if (!jirafeau_admin_session_logged()) {
@@ -117,9 +118,13 @@ if (php_sapi_name() == "cli") {
     /* Show admin interface if not downloading a file. */
     if (!(isset($_POST['action']) && strcmp($_POST['action'], 'download') == 0)) {
         require(JIRAFEAU_ROOT . 'lib/template/header.php'); ?><h2><?php echo t('ADMIN_INTERFACE'); ?></h2><?php
-          ?><h2>(version <?php echo JIRAFEAU_VERSION ?>)</h2><?php
+        ?><h2>(version <?php echo JIRAFEAU_VERSION ?>)</h2><?php
+
+        if ($cfg['enable_crypt'] && !(extension_loaded('sodium'))) {
+            echo '<div class="error"><p>'.t('SODIUM_UNAVAILABLE').'</p></div>';
+        }
 
-          ?><div id = "admin">
+        ?><div id = "admin">
           <fieldset><legend><?php echo t('ACTIONS'); ?></legend>
           <table>
           <form method="post">
@@ -301,5 +306,8 @@ if (php_sapi_name() == "cli") {
     }
 
     require(JIRAFEAU_ROOT.'lib/template/footer.php');
+} else {
+    require(JIRAFEAU_ROOT . 'lib/template/header.php');
+    jirafeau_fatal_error(t('ACCESS_KO'), $cfg);
 }
 ?>
index daf5302bb4f202722b5d290194406adf6c03c841..5f9dce301084d17643ba7e17fe2e1a4ab2ef290d 100644 (file)
@@ -34,6 +34,7 @@ More details about options in `lib/config.original.php`.
 
 Available options:
 - `ADMIN_PASSWORD`: setup a specific admin password. If not set, a random password will be generated.
+- `ADMIN_IP`: set one or more ip allowed to access admin interface (separated by comma).
 - `WEB_ROOT`: setup a specific domain to point at when generating links (e.g. 'jirafeau.mydomain.com/').
 - `VAR_ROOT`: setup a specific path where to place files. default: '/data'.
 - `FILE_HASH`: can be set to `md5`, `partial_md5` or `random` (default).
@@ -41,7 +42,8 @@ Available options:
 - `TITLE`: set Jirafeau instance title.
 - `ORGANISATION`: set organisation (in ToS).
 - `CONTACTPERSON`: set contact person (in ToS).
-- `STYLE`: apply a specific style.
+- `STYLE`: apply a specific style from the media folder.
+- `DARK_STYLE`: apply a specific style for browsers in dark mode.
 - `AVAILABILITY_DEFAULT`: setup which availability shows by default.
 - `ONE_TIME_DOWNLOAD`: set to 1 or 0 to enable or disable one time downloads.
 - `ENABLE_CRYPT`: set to 1 or 0 to enable or disable server side encryption.
@@ -52,6 +54,11 @@ Available options:
 - `UPLOAD_IP_NO_PASSWORD`: set one or more ip allowed to upload files without password (separated by comma).
 - `PROXY_IP`: set one or more proxy ip (separated by comma).
 - `STORE_UPLOADER_IP`: set to 1 or 0 to enable or disable keeping sender's IP with the _link_ file.
+- `DOWNLOAD_PASSWORD_REQUIREMENT`: set to 'optional' (default), 'required' or 'generated' to make a password for downloading optional, required or generated
+- `DOWNLOAD_PASSWORD_GEN_LEN`: set length of generated download passwords
+- `DOWNLOAD_PASSWORD_GEN_CHARS`: set characters used for generated download passwords
+- `DOWNLOAD_PASSWORD_POLICY`: set to 'regex' to use a regular expression to check user provided download passwords for complexity constraints
+- `DOWNLOAD_PASSWORD_POLICY_REGEX`: regex to check against if password policy is set to regex
 
 Example:
 ```
index 6a03b7360aebd63308c0ac8ea49cde3f85e612f1..634d58bfdcc5373a2b24f648006bc174a1be732f 100644 (file)
@@ -161,20 +161,27 @@ function run_setup(&$cfg)
     setup_webroot($cfg);
     env_2_cfg_string($cfg, 'file_hash');
     env_2_cfg_bool($cfg, 'preview');
-    env_2_cfg_bool($cfg, 'title');
+    env_2_cfg_string($cfg, 'title', false);
     env_2_cfg_string($cfg, 'organisation');
     env_2_cfg_string($cfg, 'contactperson');
     env_2_cfg_string($cfg, 'style');
     env_2_cfg_string($cfg, 'availability_default');
+    env_2_cfg_string($cfg, 'dark_style');
     env_2_cfg_bool($cfg, 'one_time_download');
     env_2_cfg_bool($cfg, 'enable_crypt');
     env_2_cfg_bool($cfg, 'debug');
     env_2_cfg_int($cfg, 'maximal_upload_size');
     env_2_cfg_string_array($cfg, 'upload_password');
     env_2_cfg_string_array($cfg, 'upload_ip');
+    env_2_cfg_string_array($cfg, 'admin_ip');
     env_2_cfg_string_array($cfg, 'upload_ip_nopassword');
     env_2_cfg_string_array($cfg, 'proxy_ip');
     env_2_cfg_bool($cfg, 'store_uploader_ip');
+    env_2_cfg_string($cfg, 'download_password_requirement');
+    env_2_cfg_int($cfg, 'download_password_gen_len');
+    env_2_cfg_string($cfg, 'download_password_gen_chars');
+    env_2_cfg_string($cfg, 'download_password_policy');
+    env_2_cfg_string($cfg, 'download_password_policy_regex');
 
     if ($setup_ok) {
         $cfg['installation_done'] = true;
@@ -187,4 +194,4 @@ function run_setup(&$cfg)
     }
 }
 
-run_setup($cfg);
+run_setup($cfg);
\ No newline at end of file
index a137097a9efaddfe58ca4ec8ace39d97174d147f..680280fc8907a036b0ba75c85937aede1de9d540 100644 (file)
@@ -5,6 +5,7 @@ var.statedir = "/var/lib/lighttpd"
 server.port = 80
 server.modules = (
     "mod_access",
+#   "mod_usertrack",
     "mod_expire",
     "mod_accesslog"
 )
diff --git a/f.php b/f.php
index 5555523f708cfcb18607069e32b0ccfca9c92199..543fc1028cfb33371a009c49d111652c2f52c7c5 100644 (file)
--- a/f.php
+++ b/f.php
@@ -248,25 +248,13 @@ if ($cfg['litespeed_workaround']) {
                $_SERVER['QUERY_STRING'] . '&litespeed_workaround=phase2');
     }
 }
-/* Read encrypted file. */
+/* Read encrypted file (Sodium mode). */
 elseif ($link['crypted']) {
-    /* Init module */
-    $m = mcrypt_module_open('rijndael-256', '', 'ofb', '');
-    /* Extract key and iv. */
-    $hash_key = md5($crypt_key);
-    $iv = jirafeau_crypt_create_iv($hash_key, mcrypt_enc_get_iv_size($m));
-    /* Init module. */
-    mcrypt_generic_init($m, $hash_key, $iv);
-    /* Decrypt file. */
-    $r = fopen(VAR_FILES . $p . $link['hash'], 'r');
-    while (!feof($r)) {
-        $dec = mdecrypt_generic($m, fread($r, 1024));
-        print $dec;
-    }
-    fclose($r);
-    /* Cleanup. */
-    mcrypt_generic_deinit($m);
-    mcrypt_module_close($m);
+    jirafeau_decrypt_file(VAR_FILES . $p . $link['hash'], 'php://output', $crypt_key);
+}
+/* Read encrypted file (legacy mode using mcrypt). */
+elseif ($link['crypted_legacy']) {
+    jirafeau_decrypt_file_legacy(VAR_FILES . $p . $link['hash'], 'php://output', $crypt_key);
 }
 /* Read file. */
 else {
@@ -285,6 +273,9 @@ else {
 if ($link['onetime'] == 'O') {
     jirafeau_delete_link($link_name);
 }
+
+jirafeau_write_download_stats($link_name, get_ip_address($cfg));
+
 exit;
 
 ?>
index 33bb83ea6d34fbfd0e3284bf1712796a605bfdd9..24565bdc3d64c81f56c509a6e0c33568fe084950 100644 (file)
--- a/index.php
+++ b/index.php
@@ -25,6 +25,10 @@ require(JIRAFEAU_ROOT . 'lib/settings.php');
 require(JIRAFEAU_ROOT . 'lib/functions.php');
 require(JIRAFEAU_ROOT . 'lib/lang.php');
 
+if ($cfg['download_password_requirement'] === "generated"){
+    $download_pass = jirafeau_gen_download_pass($cfg['download_password_gen_len'], $cfg['download_password_gen_chars']);
+}
+
 check_errors($cfg);
 if (has_error()) {
     require(JIRAFEAU_ROOT . 'lib/template/header.php');
@@ -32,39 +36,37 @@ if (has_error()) {
     require(JIRAFEAU_ROOT . 'lib/template/footer.php');
     exit;
 }
-
 require(JIRAFEAU_ROOT . 'lib/template/header.php');
 
+// Logout action
+if (isset($_POST['action']) && (strcmp($_POST['action'], 'logout') == 0)) {
+    jirafeau_session_end();
+}
+
 /* Check if user is allowed to upload. */
-// First check: Challenge by IP NO PASSWORD
-if (true === jirafeau_challenge_upload_ip_without_password($cfg, get_ip_address($cfg))) {
-    $_SESSION['upload_auth'] = true;
-    $_POST['upload_password'] = '';
-    $_SESSION['user_upload_password'] = $_POST['upload_password'];
+// First check: Is user already logged
+if (jirafeau_user_session_logged()) {
+}
+// Second check: Challenge by IP NO PASSWORD
+elseif (true === jirafeau_challenge_upload_ip_without_password($cfg, get_ip_address($cfg))) {
+    jirafeau_user_session_start();
 }
-// Second check: Challenge by IP
+// Third check: Challenge by IP
 elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
     // Is an upload password required?
     if (jirafeau_has_upload_password($cfg)) {
-        // Logout action
-        if (isset($_POST['action']) && (strcmp($_POST['action'], 'logout') == 0)) {
-            session_unset();
-        }
-
         // Challenge by password
-        // …save successful logins in session
         if (isset($_POST['upload_password'])) {
             if (jirafeau_challenge_upload_password($cfg, $_POST['upload_password'])) {
-                $_SESSION['upload_auth'] = true;
-                $_SESSION['user_upload_password'] = $_POST['upload_password'];
+                jirafeau_user_session_start();
             } else {
-                $_SESSION['admin_auth'] = false;
+                jirafeau_session_end();
                 jirafeau_fatal_error(t('BAD_PSW'), $cfg);
             }
         }
 
         // Show login form if user session is not authorized yet
-        if (true === empty($_SESSION['upload_auth'])) {
+        if (!jirafeau_user_session_logged()) {
             ?>
             <form method="post" class="form login">
             <fieldset>
@@ -81,8 +83,7 @@ elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
                 </tr>
                 <tr class = "nav">
                     <td class = "nav next">
-                    <input type = "submit" name = "key" value =
-                    "<?php echo t('LOGIN'); ?>" />
+                    <input type = "submit" name = "key" value = "<?php echo t('LOGIN'); ?>" />
                     </td>
                 </tr>
                 </table>
@@ -111,8 +112,23 @@ elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
     </p>
     </div>
 
-    <?php if ($cfg['preview'] == true) {
+    <?php if ($cfg['download_password_requirement'] === "generated"){
     ?>
+    <div id="show_password">
+    <p><?php echo t('PSW') ?></p>
+
+    <div id="download_password">
+    <p>
+        <?php echo '<input id="output_key" value="' . $download_pass . '"/>'?>
+        <button id="password_copy_button">&#128203;</button>
+    </p>
+    </div>
+    </div>
+    <?php
+    }?>
+
+    <?php if ($cfg['preview'] == true) {
+        ?>
     <div id="upload_finished_preview">
     <p>
         <a id="preview_link" href=""><?php echo t('VIEW_LINK') ?></a>
@@ -122,7 +138,7 @@ elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
     </p>
     </div>
     <?php
-} ?>
+    } ?>
 
     <div id="upload_direct_download">
     <p>
@@ -161,19 +177,24 @@ elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
 </div>
 
 <div id="upload">
-<fieldset>
+<form id="upload-form" onsubmit="
+            event.preventDefault();
+            document.getElementById('upload').style.display = 'none';
+            document.getElementById('uploading').style.display = '';
+            upload (<?php echo jirafeau_get_max_upload_chunk_size_bytes($cfg['max_upload_chunk_size_bytes']); ?>);
+            "><fieldset>
     <legend>
     <?php echo t('SEL_FILE'); ?>
     </legend>
     <p>
         <input type="file" id="file_select" size="30"
     onchange="control_selected_file_size(<?php echo $cfg['maximal_upload_size'] ?>, '<?php
-        if ($cfg['maximal_upload_size'] >= 1024) {
-            echo t('2_BIG') . ', ' . t('FILE_LIM') . " " . number_format($cfg['maximal_upload_size']/1024, 2) . " GB.";
-        } elseif ($cfg['maximal_upload_size'] > 0) {
-            echo t('2_BIG') . ', ' . t('FILE_LIM') . " " . $cfg['maximal_upload_size'] . " MB.";
-        }
-    ?>')"/>
+            if ($cfg['maximal_upload_size'] >= 1024) {
+                echo t('2_BIG') . ', ' . t('FILE_LIM') . " " . number_format($cfg['maximal_upload_size']/1024, 2) . " GB.";
+            } elseif ($cfg['maximal_upload_size'] > 0) {
+                echo t('2_BIG') . ', ' . t('FILE_LIM') . " " . $cfg['maximal_upload_size'] . " MB.";
+            }
+?>')"/>
     </p>
 
     <div id="options">
@@ -183,102 +204,93 @@ elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
             echo '<tr><td>' . t('ONE_TIME_DL') . ':</td>';
             echo '<td><input type="checkbox" id="one_time_download" /></td></tr>';
         }
-        ?>
-        <tr>
-        <td><label for="input_key"><?php echo t('PSW') . ':'; ?></label></td>
-        <td><input type="password" name="key" id="input_key" autocomplete = "new-password"/></td>
-        </tr>
+        if ($cfg['download_password_requirement'] === 'generated'){
+            echo '<input type="hidden" name="key" id="input_key" value="' . $download_pass .'"/>';
+        }else{
+            echo '<tr><td><label for="input_key">' . t('PSW') . ':' . '</label></td>';
+            echo '<td><input type="password" name="key" id="input_key" autocomplete = "new-password"';
+            if ($cfg['download_password_policy'] === 'regex'){
+                echo ' pattern="' . substr($cfg['download_password_policy_regex'], 1, strlen($cfg['download_password_policy_regex']) - 2) . '"'; //remove php delimiters
+            }
+            if ($cfg['download_password_requirement'] === 'required'){
+                echo ' required';
+            }
+            echo '/></td></tr>';
+        }?>
         <tr>
         <td><label for="select_time"><?php echo t('TIME_LIM') . ':'; ?></label></td>
         <td><select name="time" id="select_time">
         <?php
-        $expirationTimeOptions = array(
-          array(
-            'value' => 'minute',
-            'label' => '1_MIN'
-          ),
-          array(
-            'value' => 'hour',
-            'label' => '1_H'
-          ),
-          array(
-            'value' => 'day',
-            'label' => '1_D'
-          ),
-          array(
-            'value' => 'week',
-            'label' => '1_W'
-          ),
-          array(
-              'value' => 'fortnight',
-              'label' => '2_W'
-          ),
-          array(
-            'value' => 'month',
-            'label' => '1_M'
-          ),
-          array(
-            'value' => 'quarter',
-            'label' => '1_Q'
-          ),
-          array(
-            'value' => 'year',
-            'label' => '1_Y'
-          ),
-          array(
-            'value' => 'none',
-            'label' => 'NONE'
-          )
-        );
-        foreach ($expirationTimeOptions as $expirationTimeOption) {
-            $selected = ($expirationTimeOption['value'] === $cfg['availability_default'])? 'selected="selected"' : '';
-            if (true === $cfg['availabilities'][$expirationTimeOption['value']]) {
-                echo '<option value="' . $expirationTimeOption['value'] . '" ' .
+$expirationTimeOptions = array(
+  array(
+    'value' => 'minute',
+    'label' => '1_MIN'
+  ),
+  array(
+    'value' => 'hour',
+    'label' => '1_H'
+  ),
+  array(
+    'value' => 'day',
+    'label' => '1_D'
+  ),
+  array(
+    'value' => 'week',
+    'label' => '1_W'
+  ),
+  array(
+      'value' => 'fortnight',
+      'label' => '2_W'
+  ),
+  array(
+    'value' => 'month',
+    'label' => '1_M'
+  ),
+  array(
+    'value' => 'quarter',
+    'label' => '1_Q'
+  ),
+  array(
+    'value' => 'year',
+    'label' => '1_Y'
+  ),
+  array(
+    'value' => 'none',
+    'label' => 'NONE'
+  )
+);
+foreach ($expirationTimeOptions as $expirationTimeOption) {
+    $selected = ($expirationTimeOption['value'] === $cfg['availability_default'])? 'selected="selected"' : '';
+    if (true === $cfg['availabilities'][$expirationTimeOption['value']]) {
+        echo '<option value="' . $expirationTimeOption['value'] . '" ' .
               $selected . '>' . t($expirationTimeOption['label']) . '</option>';
-            }
-        }
-        ?>
+    }
+}
+?>
         </select></td>
         </tr>
 
         <?php
-        if ($cfg['maximal_upload_size'] >= 1024) {
-            echo '<p class="config">' . t('FILE_LIM');
-            echo " " . number_format($cfg['maximal_upload_size'] / 1024, 2) . " GB.</p>";
-        } elseif ($cfg['maximal_upload_size'] > 0) {
-            echo '<p class="config">' . t('FILE_LIM');
-            echo " " . $cfg['maximal_upload_size'] . " MB.</p>";
-        } else {
-            echo '<p class="config"></p>';
-        }
-        ?>
+if ($cfg['maximal_upload_size'] >= 1024) {
+    echo '<p class="config">' . t('FILE_LIM');
+    echo " " . number_format($cfg['maximal_upload_size'] / 1024, 2) . " GB.</p>";
+} elseif ($cfg['maximal_upload_size'] > 0) {
+    echo '<p class="config">' . t('FILE_LIM');
+    echo " " . $cfg['maximal_upload_size'] . " MB.</p>";
+} else {
+    echo '<p class="config"></p>';
+}
+?>
 
         <p id="max_file_size" class="config"></p>
     <p>
-    <?php
-    if (jirafeau_has_upload_password($cfg) && $_SESSION['upload_auth']) {
-        ?>
-    <input type="hidden" id="upload_password" name="upload_password" value="<?php echo $_SESSION['user_upload_password'] ?>"/>
-    <?php
-    } else {
-        ?>
-    <input type="hidden" id="upload_password" name="upload_password" value=""/>
-    <?php
-    }
-    ?>
-    <input type="submit" id="send" value="<?php echo t('SEND'); ?>"
-    onclick="
-        document.getElementById('upload').style.display = 'none';
-        document.getElementById('uploading').style.display = '';
-        upload (<?php echo jirafeau_get_max_upload_chunk_size_bytes($cfg['max_upload_chunk_size_bytes']); ?>);
-    "/>
+    <input type="submit" id="send" value="<?php echo t('SEND'); ?>"/>
     </p>
         </table>
-    </div> </fieldset>
+    </div> </fieldset></form>
 
     <?php
-    if (jirafeau_has_upload_password($cfg)
-        && false === jirafeau_challenge_upload_ip_without_password($cfg, get_ip_address($cfg))) {
+    if (jirafeau_user_session_logged()) {
         ?>
     <form method="post" class="form logout">
         <input type = "hidden" name = "action" value = "logout"/>
@@ -286,7 +298,7 @@ elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
     </form>
     <?php
     }
-    ?>
+?>
 
 </div>
 
@@ -299,16 +311,17 @@ elseif (true === jirafeau_challenge_upload_ip($cfg, get_ip_address($cfg))) {
     document.getElementById('send').style.display = 'none';
     if (!check_html5_file_api ())
         document.getElementById('max_file_size').innerHTML = '<?php
-            $max_size = jirafeau_get_max_upload_size();
-            if ($max_size > 0) {
-                echo t('NO_BROWSER_SUPPORT') . $max_size;
-            }
-        ?>';
+        $max_size = jirafeau_get_max_upload_size();
+if ($max_size > 0) {
+    echo t('NO_BROWSER_SUPPORT') . $max_size;
+}
+?>';
 
     addCopyListener('upload_link_button', 'upload_link');
     addCopyListener('preview_link_button', 'preview_link');
     addCopyListener('direct_link_button', 'direct_link');
     addCopyListener('delete_link_button', 'delete_link');
+    addTextCopyListener('password_copy_button', 'output_key');
 // @license-end
 </script>
 <?php require(JIRAFEAU_ROOT . 'lib/template/footer.php'); ?>
index 6dbefb586e84463791d48a3b37db69f1ba82d7ef..ed99b19208642655512375150c34ca990633cde9 100644 (file)
@@ -62,26 +62,26 @@ if (!is_writable(JIRAFEAU_CFG) && !@chmod(JIRAFEAU_CFG, '0666')) {
 
 if (isset($_POST['step']) && isset($_POST['next'])) {
     switch ($_POST['step']) {
-    case 1:
-        if (strlen($_POST['admin_password'])) {
-            $cfg['admin_password'] = hash('sha256', $_POST['admin_password']);
-        } else {
-            $cfg['admin_password'] = '';
-        }
-        jirafeau_export_cfg($cfg);
-        break;
-
-    case 2:
-        $cfg['web_root'] = jirafeau_add_ending_slash($_POST['web_root']);
-        $cfg['var_root'] = jirafeau_add_ending_slash($_POST['var_root']);
-        jirafeau_export_cfg($cfg);
-        break;
-
-    case 3:
-        $cfg['web_root'] = jirafeau_add_ending_slash($_POST['web_root']);
-        $cfg['var_root'] = jirafeau_add_ending_slash($_POST['var_root']);
-        jirafeau_export_cfg($cfg);
-        break;
+        case 1:
+            if (strlen($_POST['admin_password'])) {
+                $cfg['admin_password'] = hash('sha256', $_POST['admin_password']);
+            } else {
+                $cfg['admin_password'] = '';
+            }
+            jirafeau_export_cfg($cfg);
+            break;
+
+        case 2:
+            $cfg['web_root'] = jirafeau_add_ending_slash($_POST['web_root']);
+            $cfg['var_root'] = jirafeau_add_ending_slash($_POST['var_root']);
+            jirafeau_export_cfg($cfg);
+            break;
+
+        case 3:
+            $cfg['web_root'] = jirafeau_add_ending_slash($_POST['web_root']);
+            $cfg['var_root'] = jirafeau_add_ending_slash($_POST['var_root']);
+            jirafeau_export_cfg($cfg);
+            break;
     }
 }
 
@@ -95,20 +95,20 @@ if (isset($_POST['next'])) {
 }
 
 switch ($current) {
-case 1:
-default:
-    ?><h2><?php printf(t('JI_INSTALL') . ' - ' . t('STEP') .
-    ' %d ' . t('OUT_OF') . ' %d', 1, 3);
-    ?></h2> <div id = "install"> <form method="post"> <input type =
+    case 1:
+    default:
+        ?><h2><?php printf(t('JI_INSTALL') . ' - ' . t('STEP') .
+        ' %d ' . t('OUT_OF') . ' %d', 1, 3);
+        ?></h2> <div id = "install"> <form method="post"> <input type =
         "hidden" name = "jirafeau" value =
         "<?php echo JIRAFEAU_VERSION; ?>" /><input type = "hidden" name =
         "step" value = "1" /><fieldset> <legend><?php
-        echo t('ADMIN_PSW');
-    ?></legend> <table> <tr> <td class = "info" colspan =
+            echo t('ADMIN_PSW');
+        ?></legend> <table> <tr> <td class = "info" colspan =
         "2"><?php echo t('ADMIN_INTERFACE_INFO');
-    ?></td> </tr> <tr> <td class = "label"><label for = "select_password"
+        ?></td> </tr> <tr> <td class = "label"><label for = "select_password"
        ><?php echo t('ADMIN_PSW') . ':';
-    ?></label></td>
+        ?></label></td>
         <td class = "field"><input type = "password" name = "admin_password"
         id = "admin_password" size = "40" autocomplete = "new-password"/></td>
         </tr>
@@ -117,90 +117,90 @@ default:
         <td class = "nav next">
         <input type = "submit"
         class = "navleft" name = "previous" value = "<?php
-        echo t('PREV_STEP'); ?>" />
+            echo t('PREV_STEP'); ?>" />
         <input type = "submit" name = "next" value =
         "<?php echo t('NEXT_STEP'); ?>" /></td> </tr> </table>
         </fieldset> </form> </div> <?php
 break;
 
-case 2:
-    ?><h2><?php printf(t('JI_INSTALL') . ' - ' . t('STEP') .
-    ' %d ' . t('OUT_OF') . ' %d', 2, 3);
-    ?></h2> <div id = "install"> <form method="post"> <input type =
+    case 2:
+        ?><h2><?php printf(t('JI_INSTALL') . ' - ' . t('STEP') .
+        ' %d ' . t('OUT_OF') . ' %d', 2, 3);
+        ?></h2> <div id = "install"> <form method="post"> <input type =
         "hidden" name = "jirafeau" value =
         "<?php echo JIRAFEAU_VERSION; ?>" /><input type = "hidden" name =
         "step" value =
         "2" /><fieldset> <legend><?php echo t('INFO');
-    ?></legend> <table> <tr> <td class = "info" colspan =
+        ?></legend> <table> <tr> <td class = "info" colspan =
         "2"><?php echo t('BASE_ADDR_INFO');
-    ?></td> </tr> <tr> <td class = "label"><label for = "input_web_root"
+        ?></td> </tr> <tr> <td class = "label"><label for = "input_web_root"
        ><?php echo t('BASE_ADDR') . ':';
-    ?></label></td>
+        ?></label></td>
         <td class = "field"><input type = "text" name = "web_root"
         id = "input_web_root" value = "<?php
-           echo(empty($cfg['web_root']) ? jirafeau_default_web_root() : $cfg['web_root']);
-      ?>" size = "40" /></td>
+               echo(empty($cfg['web_root']) ? jirafeau_default_web_root() : $cfg['web_root']);
+        ?>" size = "40" /></td>
         </tr> <tr> <td class = "info" colspan = "2"><?php
-        echo t('DATA_DIR_EXPLAINATION');
-    ?></td> </tr> <tr> <td class = "label"><label for = "input_var_root"
+          echo t('DATA_DIR_EXPLAINATION');
+        ?></td> </tr> <tr> <td class = "label"><label for = "input_var_root"
        ><?php echo t('DATA_DIR') . ':';
-    ?></label></td>
+        ?></label></td>
         <td class = "field"><input type = "text" name = "var_root"
         id = "input_var_root" value = "<?php
-        if (empty($cfg['var_root'])) {
-            $alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' .
+            if (empty($cfg['var_root'])) {
+                $alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' .
           'abcdefghijklmnopqrstuvwxyz' . '0123456789';
-            $len_alphanum = strlen($alphanum);
-            $var = 'var-';
-            for ($i = 0; $i <JIRAFEAU_VAR_RAND_LENGTH; $i++) {
-                $var .= substr($alphanum, mt_rand(0, $len_alphanum - 1), 1);
+                $len_alphanum = strlen($alphanum);
+                $var = 'var-';
+                for ($i = 0; $i <JIRAFEAU_VAR_RAND_LENGTH; $i++) {
+                    $var .= substr($alphanum, mt_rand(0, $len_alphanum - 1), 1);
+                }
+                echo JIRAFEAU_ROOT . $var . '/';
+            } else {
+                echo $cfg['var_root'];
             }
-            echo JIRAFEAU_ROOT . $var . '/';
-        } else {
-            echo $cfg['var_root'];
-        }
-      ?>" size = "40" /></td>
+        ?>" size = "40" /></td>
         </tr> <tr> <td colspan = "2"><input type = "submit"
         class = "navleft" name = "previous" value = "<?php
-        echo t('PREV_STEP'); ?>" />
+          echo t('PREV_STEP'); ?>" />
          <input type = "submit" class = "navright" name = "next" value = 
         "<?php echo t('NEXT_STEP'); ?>" />
         </td> </tr> </table> </fieldset>
         </form> </div> <?php
 break;
 
-case 3:
-    ?><h2><?php printf(t('JI_INSTALL') . ' - ' . t('STEP') .
-    ' %d ' . t('OUT_OF') . ' %d', 3, 3);
-    ?></h2> <div id = "install"> <form method="post"> <input type =
+    case 3:
+        ?><h2><?php printf(t('JI_INSTALL') . ' - ' . t('STEP') .
+        ' %d ' . t('OUT_OF') . ' %d', 3, 3);
+        ?></h2> <div id = "install"> <form method="post"> <input type =
         "hidden" name = "jirafeau" value =
         "<?php echo JIRAFEAU_VERSION; ?>" /><input type = "hidden" name =
         "step" value =
         "3" /><fieldset> <legend><?php echo t('FINALIZATION');
-    ?></legend> <table> <tr> <td class = "info" colspan =
+        ?></legend> <table> <tr> <td class = "info" colspan =
         "2"><?php echo t('SETTING_UP');
-    ?></td> </tr> <tr> <td class = "nav previous"><input type =
+        ?></td> </tr> <tr> <td class = "nav previous"><input type =
         "submit" name = "previous" value = " <?php echo t('PREV_STEP');
-    ?>" /></td> <td></td> </tr>
+        ?>" /></td> <td></td> </tr>
         </table> </fieldset> </form> </div>
     <?php
-    $err = jirafeau_check_var_dir($cfg['var_root']);
-    if ($err['has_error']) {
-        echo '<div class="error"><p>'.$err['why'].'<br />'.NL; ?><form method="post"> <input type = "hidden" name = "jirafeau" value =
+        $err = jirafeau_check_var_dir($cfg['var_root']);
+        if ($err['has_error']) {
+            echo '<div class="error"><p>'.$err['why'].'<br />'.NL; ?><form method="post"> <input type = "hidden" name = "jirafeau" value =
             "<?php echo JIRAFEAU_VERSION; ?>" /><input type = "hidden" name =
             "step" value = "3" /><input type = "submit" name =
             "retry" value =
             "<?php echo t('RETRY_STEP'); ?>" /></form>
             <?php echo '</p></div>';
-    } else {
-        $cfg['installation_done'] = true;
-        jirafeau_export_cfg($cfg);
-        echo '<div class="message"><p>' .
-             t('JI_FONCTIONAL') . ':' .
-             '<br /><a href="./">' .
-             $cfg['web_root'].'</a></p></div>';
-    }
-break;
+        } else {
+            $cfg['installation_done'] = true;
+            jirafeau_export_cfg($cfg);
+            echo '<div class="message"><p>' .
+                 t('JI_FONCTIONAL') . ':' .
+                 '<br /><a href="./">' .
+                 $cfg['web_root'].'</a></p></div>';
+        }
+        break;
 }
 
 require(JIRAFEAU_ROOT . 'lib/template/footer.php');
index 1f2e8b7073b441454bea055c5843c876371085c5..154308955d9f8c7ec81eacc78f126359a89aadf4 100644 (file)
@@ -108,6 +108,14 @@ $cfg['admin_password'] = '';
  */
 $cfg['admin_http_auth_user'] = '';
 
+/* List of IP allowed to access the admin interface.
+ * If the list is empty, then there is no admin interface restriction based on IP.
+ * Elements of the list can be a single IP (e.g. "123.45.67.89") or
+ * an IP range (e.g. "123.45.0.0/16").
+ * Note that CIDR notation is available for IPv4 only for the moment.
+ */
+$cfg['admin_ip'] = array();
+
 /* Allow user to select different options for file expiration time.
  * Possible values in array:
  * 'minute': file is available for one minute
@@ -222,3 +230,29 @@ $cfg['debug'] = false;
  * Set to 0 to remove limitation.
  */
 $cfg['max_upload_chunk_size_bytes'] = 100000000; // 100MB
+
+/* Set password requirement policy for downloading files
+ * Possible values:
+ * optional (default): Password may be set by the uploader, but is not mandatory
+ * required: Setting a password is mandatory to upload a file.
+ * generated: Passwords are automatically generated and shown to the uploader, when uploading a file
+ */
+$cfg['download_password_requirement'] = 'optional';
+
+/* Set length of generated passwords
+ */
+$cfg['download_password_gen_len'] = 10;
+
+/* Set allowed chars for password generation
+ */
+$cfg['download_password_gen_chars'] = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&*()_-=+;:,.?';
+/* Set password complexity policy for downloading files
+ * possible values:
+ * none (default): Passwords for downloading files can be of arbitrary complexity
+ * regex: Passwords are checked with a regex for complexity constraints
+ */
+$cfg['download_password_policy'] = 'none';
+/* Set the regex for regex download password policy
+ * Delimiters are need, but modifiers should not be used
+ */
+$cfg['download_password_policy_regex'] = '/.*/';
index e7bc339ce6fa62c3b9ab5e72f76f5c263f5df572..3052bf03a45e2b9cf6a21a04d3c401574b322325 100644 (file)
@@ -24,6 +24,7 @@ define('JIRAFEAU_ROOT', dirname(__FILE__) . '/../');
 require(JIRAFEAU_ROOT . 'lib/settings.php');
 require(JIRAFEAU_ROOT . 'lib/functions.php');
 require(JIRAFEAU_ROOT . 'lib/lang.php');
+
 ?>
 // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
 var web_root = "<?php echo $cfg['web_root']; ?>";
@@ -344,7 +345,7 @@ function add_time_string_to_date(d, time)
     return false;
 }
 
-function classic_upload (file, time, password, one_time, upload_password)
+function classic_upload (file, time, password, one_time)
 {
     // Delay time estimation init as we can't have file size
     upload_time_estimation_init(0);
@@ -397,9 +398,6 @@ function classic_upload (file, time, password, one_time, upload_password)
         form.append ("key", password);
     if (one_time)
         form.append ("one_time_download", '1');
-    if (upload_password.length > 0)
-        form.append ("upload_password", upload_password);
-
     req.send (form);
 }
 
@@ -416,7 +414,7 @@ var async_global_time;
 var async_global_transfering = 0;
 var async_global_last_code;
 
-function async_upload_start (max_size, file, time, password, one_time, upload_password)
+function async_upload_start (max_size, file, time, password, one_time)
 {
     async_global_transfered = 0;
     async_global_file = file;
@@ -455,8 +453,6 @@ function async_upload_start (max_size, file, time, password, one_time, upload_pa
         form.append ("key", password);
     if (one_time)
         form.append ("one_time_download", '1');
-    if (upload_password.length > 0)
-        form.append ("upload_password", upload_password);
 
     // Start time estimation
     upload_time_estimation_init(async_global_file.size);
@@ -607,8 +603,7 @@ function upload (max_chunk_size)
             document.getElementById('file_select').files[0],
             document.getElementById('select_time').value,
             document.getElementById('input_key').value,
-            one_time,
-            document.getElementById('upload_password').value
+            one_time
             );
     }
     else
@@ -617,8 +612,7 @@ function upload (max_chunk_size)
             document.getElementById('file_select').files[0],
             document.getElementById('select_time').value,
             document.getElementById('input_key').value,
-            one_time,
-            document.getElementById('upload_password').value
+            one_time
             );
     }
 }
@@ -792,22 +786,37 @@ function addCopyListener(button_id, link_id) {
     }
 }
 
+function copyTextToClipboard(text_id){
+    var copyText = document.getElementById(text_id);
+    copyText.select();
+    copyText.setSelectionRange(0, 99999); 
+    navigator.clipboard.writeText(copyText.value);
+}
+
+function addTextCopyListener(button_id, text_id) {
+    if(document.getElementById(button_id)){
+        document.getElementById(button_id)
+            .addEventListener("click", function() {
+                copyTextToClipboard(text_id);});
+    }
+}
+
 function set_dark_mode() {
     let steel_sheet = "<?php echo 'media/' . $cfg['dark_style'] . '/style.css.php'; ?>";
     let shortcut_icon = "<?php echo 'media/' . $cfg['dark_style'] . '/favicon.ico'; ?>";
     document.getElementById('stylesheet').href = steel_sheet;
-    document.getElementById('shortcut_icon').href = steel_sheet;
+    document.getElementById('shortcut_icon').href = shortcut_icon;
 }
 
 function set_light_mode() {
     let steel_sheet = "<?php echo 'media/' . $cfg['style'] . '/style.css.php'; ?>";
     let shortcut_icon = "<?php echo 'media/' . $cfg['style'] . '/favicon.ico'; ?>";
     document.getElementById('stylesheet').href = steel_sheet;
-    document.getElementById('shortcut_icon').href = steel_sheet;
+    document.getElementById('shortcut_icon').href = shortcut_icon;
 }
 
 function color_scheme_preferences() {
-    
+
     let dark_mode_steel_sheet = "<?php echo 'media/' . $cfg['dark_style'] . '/style.css.php'; ?>"
     if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
         set_dark_mode();
index 1e084fbe33d9064f7153fc366af43a66831910d8..b6672fb0ab12e683c6be14c1e6a4b859c1041304 100644 (file)
@@ -101,6 +101,19 @@ function jirafeau_gen_random($l)
     return $code;
 }
 
+function jirafeau_gen_download_pass($length, $allowed_chars)
+{
+    if ($length <= 0) {
+        return false;
+    }
+    $pass="";
+    for ($i = 0; $i < $length; $i++) {
+        $pass .= $allowed_chars[rand(0, strlen($allowed_chars) - 1)];
+    }
+
+    return $pass;
+}
+
 function is_ssl()
 {
     if (isset($_SERVER['HTTPS'])) {
@@ -130,8 +143,11 @@ function jirafeau_human_size($octets)
 // Convert UTC timestamp to a datetime field
 function jirafeau_get_datetimefield($timestamp)
 {
-    $content = '<span class="datetime" data-datetime="' . strftime('%Y-%m-%d %H:%M', $timestamp) . '">'
-        . strftime('%Y-%m-%d %H:%M', $timestamp) . ' (GMT)</span>';
+
+    $ts = date_create("@" . $timestamp);
+    $content = '<span class="datetime" data-datetime="' . date_format($ts, 'Y-m-d H:i') . '">'
+        . date_format($ts, 'Y-m-d H:i') . ' (GMT)</span>';
+    
     return $content;
 }
 
@@ -148,6 +164,9 @@ function jirafeau_clean_rm_link($link)
     if (file_exists(VAR_LINKS . $p . $link)) {
         unlink(VAR_LINKS . $p . $link);
     }
+    if (file_exists(VAR_LINKS . $p . $link . '_download')) {
+        unlink(VAR_LINKS . $p . $link . '_download');
+    }
     $parse = VAR_LINKS . $p;
     $scan = array();
     while (file_exists($parse)
@@ -190,23 +209,23 @@ function jirafeau_ini_to_bytes($value)
     $modifier = substr($value, -1);
     $bytes = substr($value, 0, -1);
     switch (strtoupper($modifier)) {
-    default:
-        return intval($value);
-        break;
-    case 'P':
-        $bytes *= 1024;
-        // no break
-    case 'T':
-        $bytes *= 1024;
-        // no break
-    case 'G':
-        $bytes *= 1024;
-        // no break
-    case 'M':
-        $bytes *= 1024;
-        // no break
-    case 'K':
-        $bytes *= 1024;
+        default:
+            return intval($value);
+            break;
+        case 'P':
+            $bytes *= 1024;
+            // no break
+        case 'T':
+            $bytes *= 1024;
+            // no break
+        case 'G':
+            $bytes *= 1024;
+            // no break
+        case 'M':
+            $bytes *= 1024;
+            // no break
+        case 'K':
+            $bytes *= 1024;
     }
     return $bytes;
 }
@@ -264,19 +283,19 @@ function jirafeau_get_max_upload_chunk_size_bytes($max_upload_chunk_size_bytes =
 function jirafeau_upload_errstr($code)
 {
     switch ($code) {
-    case UPLOAD_ERR_INI_SIZE:
-    case UPLOAD_ERR_FORM_SIZE:
-        return t('Your file exceeds the maximum authorized file size. ');
+        case UPLOAD_ERR_INI_SIZE:
+        case UPLOAD_ERR_FORM_SIZE:
+            return t('Your file exceeds the maximum authorized file size. ');
 
-    case UPLOAD_ERR_PARTIAL:
-    case UPLOAD_ERR_NO_FILE:
-        return
-            t('Your file was not uploaded correctly. You may succeed in retrying. ');
+        case UPLOAD_ERR_PARTIAL:
+        case UPLOAD_ERR_NO_FILE:
+            return
+                t('Your file was not uploaded correctly. You may succeed in retrying. ');
 
-    case UPLOAD_ERR_NO_TMP_DIR:
-    case UPLOAD_ERR_CANT_WRITE:
-    case UPLOAD_ERR_EXTENSION:
-        return t('Internal error. You may not succeed in retrying. ');
+        case UPLOAD_ERR_NO_TMP_DIR:
+        case UPLOAD_ERR_CANT_WRITE:
+        case UPLOAD_ERR_EXTENSION:
+            return t('Internal error. You may not succeed in retrying. ');
     }
     return t('Unknown error. ');
 }
@@ -435,13 +454,15 @@ function jirafeau_upload($file, $one_time_download, $key, $time, $ip, $crypt, $l
     /* Crypt file if option is enabled. */
     $crypted = false;
     $crypt_key = '';
-    if ($crypt == true && !(extension_loaded('mcrypt') == true)) {
-        error_log("PHP extension mcrypt not loaded, won't encrypt in Jirafeau");
+    if ($crypt == true && !(extension_loaded('sodium') == true)) {
+        error_log("PHP extension sodium not loaded, won't encrypt in Jirafeau");
     }
-    if ($crypt == true && extension_loaded('mcrypt') == true) {
-        $crypt_key = jirafeau_encrypt_file($file['tmp_name'], $file['tmp_name']);
+    if ($crypt == true && extension_loaded('sodium') == true) {
+        $crypt_key = jirafeau_encrypt_file($file['tmp_name'], $file['tmp_name'].'crypt');
         if (strlen($crypt_key) > 0) {
-            $crypted = true;
+            if (rename($file['tmp_name'].'crypt', $file['tmp_name']) === true) {
+                $crypted = true;
+            }
         }
     }
 
@@ -496,7 +517,7 @@ function jirafeau_upload($file, $one_time_download, $key, $time, $ip, $crypt, $l
         $handle,
         $name . NL. $mime_type . NL. $size . NL. $password . NL. $time .
             NL . $hash. NL . ($one_time_download ? 'O' : 'R') . NL . time() .
-            NL . $ip . NL. $delete_link_code . NL . ($crypted ? 'C' : 'O')
+            NL . $ip . NL. $delete_link_code . NL . ($crypted ? 'C2' : 'O')
     );
     fclose($handle);
     $hash_link = substr(base_16_to_64(md5_file($link_tmp_name)), 0, $link_name_length);
@@ -645,7 +666,8 @@ function jirafeau_get_link($hash)
     $out['upload_date'] = trim($c[7]);
     $out['ip'] = trim($c[8]);
     $out['link_code'] = trim($c[9]);
-    $out['crypted'] = trim($c[10]) == 'C';
+    $out['crypted'] = trim($c[10]) == 'C2';
+    $out['crypted_legacy'] = trim($c[10]) == 'C';
 
     return $out;
 }
@@ -693,6 +715,7 @@ function jirafeau_admin_list($name, $file_hash, $link_hash)
                 if (!count($l)) {
                     continue;
                 }
+                $ld = jirafeau_get_download_stats($node);
 
                 /* Filter. */
                 if (!empty($name) && !@preg_match("/$name/i", jirafeau_escape($l['file_name']))) {
@@ -717,6 +740,11 @@ function jirafeau_admin_list($name, $file_hash, $link_hash)
                 if (strlen($l['ip']) > 0) {
                     echo t('ORIGIN') . ': ' . $l['ip'] . '<br/>';
                 }
+                echo t('DOWNLOAD_COUNT') . ': ' . $ld['count'] . '<br/>';
+                if ($ld['count'] > 0) {
+                    echo t('DOWNLOAD_DATE') . ': ' . jirafeau_get_datetimefield($ld['date']) . '<br/>';
+                    echo t('DOWNLOAD_IP') . ': ' . $ld['ip'] . '<br/>';
+                }
                 echo '</td><td>';
                 echo '<form method="post">' .
                 '<input type = "hidden" name = "action" value = "download"/>' .
@@ -875,6 +903,7 @@ function jirafeau_admin_bug_report($cfg)
 
     $out .= "# PHP options<br/>";
     $out .= "- php version: " . phpversion() . "<br/>";
+    $out .= "- sodium version: " . phpversion('sodium') . "<br/>";
     $out .= "- mcrypt version: " . phpversion('mcrypt') . "<br/>";
     $php_options =  [
         'post_max_size',
@@ -1116,10 +1145,12 @@ function jirafeau_async_end($ref, $code, $crypt, $link_name_length, $file_hash_m
 
     $crypted = false;
     $crypt_key = '';
-    if ($crypt == true && extension_loaded('mcrypt') == true) {
-        $crypt_key = jirafeau_encrypt_file($p, $p);
+    if ($crypt == true && extension_loaded('sodium') == true) {
+        $crypt_key = jirafeau_encrypt_file($p, $p.'.crypt');
         if (strlen($crypt_key) > 0) {
-            $crypted = true;
+            if (rename($p.'.crypt', $p) === true) {
+                $crypted = true;
+            }
         }
     }
 
@@ -1154,7 +1185,7 @@ function jirafeau_async_end($ref, $code, $crypt, $link_name_length, $file_hash_m
         $handle,
         $a['file_name'] . NL . $a['mime_type'] . NL . $size . NL .
             $a['key'] . NL . $a['time'] . NL . $hash . NL . $a['onetime'] . NL .
-            time() . NL . $a['ip'] . NL . $delete_link_code . NL . ($crypted ? 'C' : 'O')
+            time() . NL . $a['ip'] . NL . $delete_link_code . NL . ($crypted ? 'C2' : 'O')
     );
     fclose($handle);
     $hash_link = substr(base_16_to_64(md5_file($link_tmp_name)), 0, $link_name_length);
@@ -1182,51 +1213,96 @@ function jirafeau_crypt_create_iv($base, $size)
 }
 
 /**
- * Crypt file and returns decrypt key.
+ * Crypt file using Sodium and returns decrypt key.
  * @param $fp_src file path to the file to crypt.
- * @param $fp_dst file path to the file to write crypted file (could be the same).
- * @return decrypt key composed of the key and the iv separated by a point ('.')
+ * @param $fp_dst file path to the file to write crypted file (must not be the same).
+ * @return key used to encrypt the file
  */
 function jirafeau_encrypt_file($fp_src, $fp_dst)
 {
     $fs = filesize($fp_src);
-    if ($fs === false || $fs == 0 || !(extension_loaded('mcrypt') == true)) {
+    if ($fs === false || $fs == 0 || extension_loaded('sodium') == false || $fp_src == $fp_dst) {
         return '';
     }
 
-    /* Prepare module. */
-    $m = mcrypt_module_open('rijndael-256', '', 'ofb', '');
     /* Generate key. */
-    $crypt_key = jirafeau_gen_random(10);
-    $hash_key = md5($crypt_key);
-    $iv = jirafeau_crypt_create_iv($hash_key, mcrypt_enc_get_iv_size($m));
+    $crypt_key = bin2hex(random_bytes(SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES / 2));
     /* Init module. */
-    mcrypt_generic_init($m, $hash_key, $iv);
+    [$crypt_state, $crypt_header] = sodium_crypto_secretstream_xchacha20poly1305_init_push($crypt_key);
     /* Crypt file. */
-    $r = fopen($fp_src, 'r');
-    $w = fopen($fp_dst, 'c');
-    while (!feof($r)) {
-        $enc = mcrypt_generic($m, fread($r, 1024));
+    $r = fopen($fp_src, 'rb');
+    $w = fopen($fp_dst, 'wb');
+    fwrite($w, $crypt_header);
+
+    for ($i = 0; $i < $fs; $i += JIRAFEAU_SODIUM_CHUNKSIZE) {
+        $to_enc = fread($r, JIRAFEAU_SODIUM_CHUNKSIZE);
+        $enc = sodium_crypto_secretstream_xchacha20poly1305_push($crypt_state, $to_enc);
+
         if (fwrite($w, $enc) === false) {
-            return '';
+           return '';
         }
     }
+
     fclose($r);
     fclose($w);
+
     /* Cleanup. */
-    mcrypt_generic_deinit($m);
-    mcrypt_module_close($m);
+    sodium_memzero($crypt_state);
+
     return $crypt_key;
 }
 
 /**
- * Decrypt file.
+ * Decrypt file using Sodium.
+ * @param $fp_src file path to the file to decrypt.
+ * @param $fp_dst file path to the file to write decrypted file (must not be the same).
+ * @param $k decryption key
+ * @return true if decryption succeeded, false otherwise
+ */
+function jirafeau_decrypt_file($fp_src, $fp_dst, $k)
+{
+    $fs = filesize($fp_src);
+    if ($fs === false || $fs == 0 || extension_loaded('sodium') == false || $fp_src == $fp_dst) {
+        return false;
+    }
+
+    /* Decrypt file. */
+    $r = fopen($fp_src, 'rb');
+    $w = fopen($fp_dst, 'wb');
+
+    $crypt_header = fread($r, SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES);
+
+    /* Init module. */
+    $crypt_state = sodium_crypto_secretstream_xchacha20poly1305_init_pull($crypt_header, $k);
+
+    /* Decrypt file. */
+
+    for ($i = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES; $i < $fs; $i += JIRAFEAU_SODIUM_CHUNKSIZE + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES) {
+        $to_dec = fread($r, JIRAFEAU_SODIUM_CHUNKSIZE + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES);
+        [$dec, $crypt_tag] = sodium_crypto_secretstream_xchacha20poly1305_pull($crypt_state, $to_dec);
+        
+        if (fwrite($w, $dec) === false) {
+            return false;
+        }
+    }
+
+    fclose($r);
+    fclose($w);
+
+    /* Cleanup. */
+    sodium_memzero($crypt_state);
+
+    return true;
+}
+
+/**
+ * Decrypt file using mcrypt.
  * @param $fp_src file path to the file to decrypt.
  * @param $fp_dst file path to the file to write decrypted file (could be the same).
  * @param $k string composed of the key and the iv separated by a point ('.')
- * @return key used to decrypt. a string of length 0 is returned if failed.
+ * @return true if decryption succeeded, false otherwise
  */
-function jirafeau_decrypt_file($fp_src, $fp_dst, $k)
+function jirafeau_decrypt_file_legacy($fp_src, $fp_dst, $k)
 {
     $fs = filesize($fp_src);
     if ($fs === false || $fs == 0 || extension_loaded('mcrypt') == false) {
@@ -1239,6 +1315,8 @@ function jirafeau_decrypt_file($fp_src, $fp_dst, $k)
     $crypt_key = $k;
     $hash_key = md5($crypt_key);
     $iv = jirafeau_crypt_create_iv($hash_key, mcrypt_enc_get_iv_size($m));
+    /* Init module. */
+    mcrypt_generic_init($m, $hash_key, $iv);
     /* Decrypt file. */
     $r = fopen($fp_src, 'r');
     $w = fopen($fp_dst, 'c');
@@ -1357,6 +1435,31 @@ function jirafeau_challenge_upload($cfg, $ip, $password)
             (jirafeau_challenge_upload_password($cfg, $password) && jirafeau_challenge_upload_ip($cfg, $ip));
 }
 
+/**
+ * Check if Jirafeau has a restriction on the IP address for accessing the admin interface.
+ * @return true if admin interface is IP restricted, false otherwise.
+ */
+function jirafeau_admin_has_ip_restriction($cfg)
+{
+    return count($cfg['admin_ip']) > 0;
+}
+
+/**
+ * Test if visitor's IP is authorized to access the admin interface.
+ *
+ * @param $cfg configuration
+ * @param $challengedIp IP to be challenged
+ * @return true if IP is authorized, false otherwise.
+ */
+function jirafeau_challenge_admin_ip($cfg, $challengedIp)
+{
+    // If no IP address have been listed, allow upload from any IP
+    if (!jirafeau_admin_has_ip_restriction($cfg)) {
+        return true;
+    }
+    return jirafeau_challenge_ip($cfg['admin_ip'], $challengedIp);
+}
+
 /** Tell if we have some HTTP headers generated by a proxy */
 function has_http_forwarded()
 {
@@ -1476,7 +1579,7 @@ function jirafeau_admin_session_start()
     $_SESSION['admin_csrf'] = md5(uniqid(mt_rand(), true));
 }
 
-function jirafeau_admin_session_end()
+function jirafeau_session_end()
 {
     $_SESSION = array();
     session_destroy();
@@ -1496,6 +1599,17 @@ function jirafeau_admin_csrf_field()
     return "<input type='hidden' name='admin_csrf' value='". $_SESSION['admin_csrf'] . "'/>";
 }
 
+function jirafeau_user_session_start()
+{
+    $_SESSION['user_auth'] = true;
+}
+
+function jirafeau_user_session_logged()
+{
+    return isset($_SESSION['user_auth']) &&
+        $_SESSION['user_auth'] === true;
+}
+
 function jirafeau_dir_size($dir)
 {
     $size = 0;
@@ -1574,5 +1688,35 @@ function jirafeau_add_ending_slash($path)
 
 function jirafeau_default_web_root()
 {
-    return $_SERVER['HTTP_HOST'] . str_replace('install.php', '', $_SERVER['REQUEST_URI']);
+    $url_scheme = (isset($_SERVER['HTTPS'])) ? 'https://' : 'http://';
+    return $url_scheme . $_SERVER['HTTP_HOST'] . str_replace('install.php', '', $_SERVER['REQUEST_URI']);
+}
+
+function jirafeau_get_download_stats($hash)
+{
+    $filename = VAR_LINKS . s2p("$hash") . $hash . '_download';
+
+    if (!file_exists($filename)) {
+        return array('count'=>0);
+    }
+
+    $c = file($filename);
+    $data['count'] = trim($c[0]);
+    $data['date'] = trim($c[1]);
+    $data['ip'] = trim($c[2]);
+
+    return $data;
+}
+
+function jirafeau_write_download_stats($hash, $ip)
+{
+    $data = jirafeau_get_download_stats($hash);
+    $count = $data['count'];
+    $count++;
+
+    $filename = VAR_LINKS . s2p("$hash") . $hash . '_download';
+
+    $handle = fopen($filename, 'w');
+    fwrite($handle, $count . NL . time() . NL . $ip);
+    fclose($handle);
 }
index 771da14ac96593d8b3b5e97242e27b6ad1b95309..a048c2b79d7a73bee3588239970580c598dd8066 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 4c7218ae626cfe3526565e44aa1c2bcf4116ea7b..7f38ca97e9794a69fc68ba2acd97c0eb3c81a52d 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index da6831affd3b5423742fb3989b2ba53945ba221d..796ceaa96fee4bf9e306dc36902e7bd9cd32a5a1 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 58a68454f3163160e227c3e0bbb12a980091aa2b..0a949679695979b42317d523f33246aa0af21e8d 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index fdcaa45d083ae29e9a2718a045ea0d557ece392b..9fa849998811ca5f62acc0694382b89f606dfe0f 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "Una quincena",
index 6bca483e0677e1cc6abc79fff29f2b64496a3e03..6277346fc5ae642fc71d3d72ec2230fccd3be7be 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 2803a33a1bdea7882d39707e87b2c8d9f2d0ddb4..8aee6260e31a42476f468f40cceddd6c6b973613 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 9fa71451471371772117283bd9e8ad4c600361e1..a08c46f369fe7c518af1ec9a74e345f35020dbf6 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 3b6d96f65bbc5ac0d27cbb7c108cc13648b6d025..24f3e0ca1cbb7d650a03ad6202e33ff6ebcf67e8 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "Verschlüsselung ist in der Konfiguration aktiviert, aber das PHP-Modul \"Sodium\" ist nicht verfügbar! Verschlüsselung ist nicht verfügbar!",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "Zwei Wochen",
@@ -14,7 +15,7 @@
     "ADMIN_PSW": "Admin-Passwort",
     "ERR_OCC": "Ein Fehler ist aufgetreten.",
     "BASE_ADDR": "Basisadresse",
-    "USING_SERVICE": "Durch die Nutzung unserer Dienste, akzeptierest du unsere",
+    "USING_SERVICE": "Durch die Nutzung unserer Dienste akzeptierest du unsere",
     "CLEAN": "Aufräumen",
     "CLEAN_EXPIRED": "Abgelaufene Dateien löschen",
     "CLEAN_INCOMPLETE": "Alte unfertige Übertragungen löschen",
@@ -43,7 +44,7 @@
     "INSTALL_SCRIPT_HERE": "Installer-Skript noch vorhanden",
     "INTERNAL_ERROR_DEL": "Interner Fehler während der Dateierstellung.",
     "JI_PROJECT": "Jirafeau-Projekt",
-    "ADMIN_INTERFACE_INFO": "Jirafeau hat eine Admin-Oberfläche (durch admin.php). Für den Zugriff auf die Schnittstelle kann ein Kennwort festlegt. werden. Um die Schnittstelle zu deaktivieren, Kennwort einfach leer lassen.",
+    "ADMIN_INTERFACE_INFO": "Jirafeau hat eine Admin-Oberfläche (durch admin.php). Für den Zugriff auf die Schnittstelle kann ein Passwort festlegt werden. Um die Schnittstelle zu deaktivieren, Passwort einfach leer lassen.",
     "JI_FONCTIONAL": "Jirafeau ist nun voll funktionsfähig",
     "SETTING_UP": "Jirafeau richtet die Webseite entsprechend der angegebenen Konfiguration ein.",
     "JI_WEB_RE": "Jirafeau, dein Web-Speicher für Dateien",
@@ -84,8 +85,8 @@
     "NO_ADMIN_AUTH": "Leider bist du nicht auf der Admin-Oberfläche angemeldet.",
     "TOS": "Allgemeine Geschäftsbedingungen",
     "ASYNC_DIR_W": "Das Async-Verzeichnis ist nicht beschreibbar.",
-    "BASE_ADDR_INFO": "Die Basisadresse von Jirafeau ist der erste Teil der URL, bis (einschließlich) dem letzten Schrägstrich. Zum Beispiel: „http://www.example.com/“. Abschließenden Schrägstrich nichrt vergessen!",
-    "DATA_DIR_EXPLAINATION": "Das Datenverzeichnis ist, wo deine Dateien und Informationen über deine Dateien gespeichert werden. Dieses Verzeichnis sollte sich außerhalb der Webseite befinden, oder zumindest beschränkten Zugriff haben. Abschließenden Schrägstrich nichrt vergessen!",
+    "BASE_ADDR_INFO": "Die Basisadresse von Jirafeau ist der erste Teil der URL, bis einschließlich dem letzten Schrägstrich, zum Beispiel: „http://www.example.com/“. Abschließenden Schrägstrich nicht vergessen!",
+    "DATA_DIR_EXPLAINATION": "Im Datenverzeichnis werden deine Dateien und zugehörige Informationen gespeichert. Dieses Verzeichnis sollte sich außerhalb der Webseite befinden oder zumindest beschränkten Zugriff haben. Abschließenden Schrägstrich nicht vergessen!",
     "FILE_DIR_W": "Das Dateiverzeichnis ist nicht beschreibbar.",
     "CANNOT_CREATE_DIR": "Der folgende Ordner konnte nicht erstellt werden",
     "DIR_NOT_W": "Das folgende Verzeichnis ist nicht beschreibbar",
     "CONF_SOLUTION_2": "Die lokale Konfiguration ist vom Webserver nicht schreibbar. Gib dem Webserver die Schreibberechtigung für die Datei <code>lib/config.local.php</code>.",
     "FILE_EXPIRED": "Die zeitliche Begrenzung dieser Datei ist abgelaufen.",
     "VALID_UNTIL": "Diese Datei ist gültig bis",
-    "CONF_AUTOGEN_COMMENT": "Diese Datei wurde vom Installationsprozess erezugt. Du kannst sie bearbeiten. Siehe config.original.php, um die Konfigurationsparameter zu verstehen.",
+    "CONF_AUTOGEN_COMMENT": "Diese Datei wurde vom Installationsprozess erzeugt. Du kannst sie bearbeiten. Siehe config.original.php, um die Konfigurationsparameter zu verstehen.",
     "TIME_LIM": "Ablauffrist",
     "TYPE": "Typ",
     "UPLOAD_DATE": "Datum",
     "UP_PSW": "Passwort",
     "UP": "Lädt hoch …",
     "VIEW_LINK": "Verknüpfung zeigen",
-    "AUTO_DESTRUCT": "Achtung, diese Datei wird automatisch gelöscht, nachdem diese gelesen wird",
+    "AUTO_DESTRUCT": "Achtung: Diese Datei wird automatisch gelöscht, nachdem sie heruntergeladen oder gelesen wurde!",
     "BAD_PSW": "Falsches Passwort.",
     "GONNA_DEL": "Du löschst",
     "NOW_DOWNLOADING": "Du lädst herunter",
index 1e8248a0ee503acadbfe06d0c5a725129a3517ef..a0da96f5b773bf88ebe1ab8e543e4ebbbff1f0ea 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index b3de22ca073959429c6a29e156259f398e6a2700..092980aa9b79e8f7c47a2816921e83b7c8194659 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "Encryption is enabled in configuration, but the Sodium PHP module is not loaded! Encryption is not available!",
     "INSTALL_FILE_NOT_FOUND_TITLE": "Installation file not found",
     "INSTALL_FILE_NOT_FOUND_DESC": "Installation is not complete and install.php file does not seem to exist",
     "REPORTING_AN_ISSUE": "Reporting an issue",
     "ONETIME": "One-time",
     "UPLOAD_DATE": "Upload date",
     "ORIGIN": "Origin",
+    "DOWNLOAD_COUNT": "Downloads",
+    "DOWNLOAD_DATE": "Last download",
+    "DOWNLOAD_IP": "Downloaded from",
     "ACTION": "Action",
     "DEL_LINK": "Del link",
     "DEL_FILE_LINKS": "Del file and links",
index 6ea061949c75c1447426ba4135848ce9ea4a5f00..50530410f4a766a10a63e76cf1fa6b7e30103b8c 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "Una quincena",
index 6bca483e0677e1cc6abc79fff29f2b64496a3e03..6277346fc5ae642fc71d3d72ec2230fccd3be7be 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 5bd161313aa9c61e329b2d2e2b0b4fe12f4381f1..db7eecf0e3d064d166abb7bbf071f1e144d20aba 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 5c5d76611e59bb2339fdf6b735cebb1ae6f34cce..a9162abd1bb580091477d7db431e674e9c858f7b 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "Fichier d'installation non-trouvé",
     "INSTALL_FILE_NOT_FOUND_DESC": "L'installation est incomplète et le ficher install.php est introuvable",
     "2_W": "Deux semaines",
index 21a4464fdc277535b0246a0df454ceba9a9f44ea..3e40020b7119f2d7c8fcd2cc60a630a67e1090f6 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 1c8538f99a57a0af2eda9d99db46ee0381f2b04c..5c19acc64f93edeeacfe53177537ff6a19d4208f 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 3a9ccb1c8f8cfcad8089a49aaf775c3b55aaece0..788ce9e12a1d8269a6acf3bfbe272ab39b13ddaf 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 129c3e5b90622ef43a6cb578cce96b2029de74ee..4d3b8e0e29e3c39d72b5ad0b8d2dff47eb3f65e3 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 95511635d9ad4f4a411db605b60c5c7455bd6c30..74fc27631d1e2523e80fb7d76497f4f25438d100 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 94a3abb01cfbf4125b2bea663f9636200587974c..c4e53b5258824d759de6728f42fc0c6101c1b041 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "Due settimane",
index 4d32118a7920fdbdef65131a779a3a77f6a888d9..ee6a2e818439c6b20c1132d866e06613974fca78 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 1c8538f99a57a0af2eda9d99db46ee0381f2b04c..5c19acc64f93edeeacfe53177537ff6a19d4208f 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 846f564179d224b96742a15c2df980b9f279369c..45aeaaa5358c925ea4c6eb3b13ad0f81655bf38d 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 6bca483e0677e1cc6abc79fff29f2b64496a3e03..6277346fc5ae642fc71d3d72ec2230fccd3be7be 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 066ecd8a91ab3099107475c525ba1e6a33e0aa60..c01c93d6c00ca863d9236f436c0d152c432b06f1 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index cacbca10a3419a1ac53396cabc868efb46f12a49..ce80c40d803a152dd23655bf6416d5d9492e5f90 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "To uker",
index 36243f9cee602334ede8a7bb6ddba007c9945e1f..1855d0bc5426798884263667522d819537af4ce5 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "Twee weken",
index eea531bb1d2eca33d333c873d70ba416981757a4..07a814a94747932944756b75a24ef8f9ef279fc1 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 6bca483e0677e1cc6abc79fff29f2b64496a3e03..6277346fc5ae642fc71d3d72ec2230fccd3be7be 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 782b63e866c645d7dfadd5a48752d8149cc7d8d1..9ec79a96c46feca94021e07e4e7b7ed960a3528c 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "Uma quinzena",
index 08d4104b8b6119508fa48da65f6345a23db24275..c902a9c4f32e735c1847e1cdb827eb151b1df158 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "Uma quinzena",
index f3d9841490fedb54b8854cb447f6eba0f9542e4c..dbe2046b563782ccf1a1d94858dca77d1d625df4 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index aba71f519859241a5e87ff9529e748561501e248..6452559d0b285db3dbf064728745050a90fb5078 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 6bca483e0677e1cc6abc79fff29f2b64496a3e03..6277346fc5ae642fc71d3d72ec2230fccd3be7be 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 786a8bfb9a7162933277f5930b4c4598cd023b38..54401df01ae1d6f5e72c2e941d4ecd0dc6365afb 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "REPORTING_AN_ISSUE": "",
     "SIZE_DATA": "",
     "INCOMPATIBLE_OPTIONS_W": "",
index bbf21ead2f7acb26d3d6d3c12d418ad1b79f1b8a..e40d2b95789c193cc35925778f87ded09e646696 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index aca3a2d5771bd6d270cca99295be3ea6f7cb2c90..7f06388f31c5cff4d6a3dc1a3ad92d92c303338a 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 6bca483e0677e1cc6abc79fff29f2b64496a3e03..6277346fc5ae642fc71d3d72ec2230fccd3be7be 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 2149291318d89cd2202c172a90ebb1aabef96584..53f23a27067579846d08a506cd1505ad2add0614 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 134763f5bdea23718c975496fbc09ee59f4565d1..01452063d0d999da0693c3e7b53639c5ecfbfc61 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "Två veckor",
index 16ee6fcbb287050c9609fa2b7794890690352aef..d6e0c1dc7321a66c995fc921dae8f94a8736d3b0 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 5a55190c5824fd8e9fb69dda617f3d886ca875e7..cfaefffe85b89c7b3751f84f800a59d0084a79c8 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 6bca483e0677e1cc6abc79fff29f2b64496a3e03..6277346fc5ae642fc71d3d72ec2230fccd3be7be 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index 6cfe69e33f357c54d439fe34230fde5c7f218a54..239a4329a7aa2ba0ca043b2c2b2ece481d0deeee 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "İki hafta",
index a93343416bb56ef6fc77222d6c67d0d7d4332598..6b9e17e573579a5a519b20efd1b7889842d4bc97 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index cf36cc7ab99a1e974b8978e1a5ea6a9dff98a0e4..bcfad0a769376f95d89873afd2238907a9627fa2 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index c3e89b42c91b66fc646255d07a733be6edc57a4f..cf65cc5a2691bf164e903ff18107334e269c4dde 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index b243155d24e19542b7788b17a58c7f07be6305e3..a571dcb09f3501ef89ccd9505bbe3ee0d35066da 100644 (file)
@@ -1,4 +1,5 @@
 {
+    "SODIUM_UNAVAILABLE": "",
     "INSTALL_FILE_NOT_FOUND_TITLE": "",
     "INSTALL_FILE_NOT_FOUND_DESC": "",
     "2_W": "",
index e2173bde63c173fea3bea0440adc5cf68a46d43e..e3399fd937c1c4cc25e1da8c69dc4fd1fc6ccc64 100644 (file)
@@ -75,5 +75,23 @@ define('JIRAFEAU_MONTH', 2592000); // JIRAFEAU_DAY * 30
 define('JIRAFEAU_QUARTER', 7776000); // JIRAFEAU_DAY * 90
 define('JIRAFEAU_YEAR', 31536000); // JIRAFEAU_DAY * 365
 
+define('JIRAFEAU_SODIUM_CHUNKSIZE', 1024);
+
+// Define some Sodium constants from newer PHP versions if they are not available
+
+if (extension_loaded('sodium')) {
+    if (!defined('SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES')) {
+        define('SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES', 32);
+    }
+
+    if (!defined('SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES')) {
+        define('SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES', 24);
+    }
+
+    if (!defined('SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES')) {
+        define('SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES', 17);
+    }
+}
+
 // set UTC as default timezone for all date/time functions
 date_default_timezone_set('UTC');
index 71b8857962beea748de406f723703877b2b89fe4..8be36c7213715974649826f308a7e007ad4267a7 100644 (file)
@@ -7,6 +7,7 @@ header('x-ua-compatible: ie=edge');
 <head>
   <meta charset="utf-8">
   <title><?php echo (true === empty($cfg['title']))? t('JI_WEB_RE') : $cfg['title']; ?></title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
   <link id="shortcut_icon" rel="shortcut icon" href="<?php echo 'media/' . $cfg['style'] . '/favicon.ico'; ?>">
   <link id="stylesheet" rel="stylesheet" href="<?php echo 'media/' . $cfg['style'] . '/style.css.php'; ?>" type="text/css" />
 </head>
index 0d4aeab43d59e7ad8cf8f74de6c1fc7e8c9b5942..600b1d5cc9f702955a9a1d558e27fc1ef3cf0612 100644 (file)
@@ -25,8 +25,8 @@ require(JIRAFEAU_ROOT . 'lib/settings.php');
 require(JIRAFEAU_ROOT . 'lib/functions.php');
 require(JIRAFEAU_ROOT . 'lib/lang.php');
 
- global $script_langages;
- $script_langages = array('bash' => 'Bash');
+global $script_langages;
+$script_langages = array('bash' => 'Bash');
 
 /* Operations may take a long time.
  * Be sure PHP's safe mode is off.
@@ -62,23 +62,34 @@ if (has_error()) {
     exit;
 }
 
+session_start();
+
 /* Upload file */
 if (isset($_FILES['file']) && is_writable(VAR_FILES)
     && is_writable(VAR_LINKS)) {
-    if (isset($_POST['upload_password'])) {
-        if (!jirafeau_challenge_upload($cfg, get_ip_address($cfg), $_POST['upload_password'])) {
+    if (!jirafeau_user_session_logged()) {
+        if (isset($_POST['upload_password']) &&
+            !jirafeau_challenge_upload($cfg, get_ip_address($cfg), $_POST['upload_password'])) {
             echo 'Error 3: Invalid password';
             exit;
-        }
-    } else {
-        if (!jirafeau_challenge_upload($cfg, get_ip_address($cfg), null)) {
+        } elseif (!jirafeau_challenge_upload($cfg, get_ip_address($cfg), null)) {
             echo 'Error 2: No password nor allowed IP';
             exit;
         }
     }
+
     $key = '';
     if (isset($_POST['key'])) {
         $key = $_POST['key'];
+        if ($cfg['download_password_requirement'] !== 'generated' && $cfg['download_password_policy'] === 'regex'){
+            if (!preg_match($cfg['download_password_policy_regex'], $key)){
+                echo 'Error 14: The download password is not complying to the security standards.';
+                exit;
+            }
+        }
+    }elseif ($cfg['download_password_requirement'] !== 'optional'){
+        echo 'Error 13: The parameter password is required.';
+        exit;
     }
 
     $time = time();
@@ -111,7 +122,7 @@ if (isset($_FILES['file']) && is_writable(VAR_FILES)
             case 'year':
                 $time += JIRAFEAU_YEAR;
                 break;
-           default:
+            default:
                 $time = JIRAFEAU_INFINITY;
                 break;
         }
@@ -135,7 +146,7 @@ if (isset($_FILES['file']) && is_writable(VAR_FILES)
     } else {
         $ip = "";
     }
-    
+
     $res = jirafeau_upload(
         $_FILES['file'],
         isset($_POST['one_time_download']),
@@ -164,6 +175,15 @@ if (isset($_FILES['file']) && is_writable(VAR_FILES)
     $key = '';
     if (isset($_POST['key'])) {
         $key = $_POST['key'];
+        if ($cfg['download_password_requirement'] !== 'generated' && $cfg['download_password_policy'] === 'regex'){
+            if (!preg_match($cfg['download_password_policy_regex'], $key)){
+                echo 'Error 14: The download password is not complying to the security standards.';
+                exit;
+            }
+        }
+    }elseif ($cfg['download_password_requirement'] !== 'optional'){
+        echo 'Error 13: The parameter password is required.';
+        exit;
     }
     $d = '';
     if (isset($_GET['d'])) {
@@ -405,7 +425,8 @@ fi
 }
 /* Initialize an asynchronous upload. */
 elseif (isset($_GET['init_async'])) {
-    if (isset($_POST['upload_password'])) {
+    if (jirafeau_user_session_logged()) {
+    } elseif (isset($_POST['upload_password'])) {
         if (!jirafeau_challenge_upload($cfg, get_ip_address($cfg), $_POST['upload_password'])) {
             echo 'Error 20: Invalid password';
             exit;
@@ -430,6 +451,15 @@ elseif (isset($_GET['init_async'])) {
     $key = '';
     if (isset($_POST['key'])) {
         $key = $_POST['key'];
+        if ($cfg['download_password_requirement'] !== 'generated' && $cfg['download_password_policy'] === 'regex'){
+            if (!preg_match($cfg['download_password_policy_regex'], $key)){
+                echo 'Error 14: The download password is not complying to the security standards.';
+                exit;
+            }
+        }
+    }elseif ($cfg['download_password_requirement'] !== 'optional'){
+        echo 'Error 13: The parameter password is required.';
+        exit;
     }
 
     // Check if one time download is enabled
@@ -479,7 +509,7 @@ elseif (isset($_GET['init_async'])) {
     } else {
         $ip = "";
     }
-    
+
     echo jirafeau_async_init(
         $_POST['filename'],
         $type,

patrick-canterino.de