diff options
author | Minteck <nekostarfan@gmail.com> | 2021-08-08 12:04:30 +0200 |
---|---|---|
committer | Minteck <nekostarfan@gmail.com> | 2021-08-08 12:04:30 +0200 |
commit | 95112b1eb06a4be531ded59563d53a63a8d614e8 (patch) | |
tree | fd3dc676227309c87a39feab9ca458985e327907 /includes | |
parent | 87303b0d3540037fb94efdde24dbaacb2880d6cb (diff) | |
download | main-95112b1eb06a4be531ded59563d53a63a8d614e8.tar.gz main-95112b1eb06a4be531ded59563d53a63a8d614e8.tar.bz2 main-95112b1eb06a4be531ded59563d53a63a8d614e8.zip |
Opening!
Diffstat (limited to 'includes')
30 files changed, 6669 insertions, 527 deletions
diff --git a/includes/archive/main.php b/includes/archive/main.php index 28cb438..593c161 100644 --- a/includes/archive/main.php +++ b/includes/archive/main.php @@ -1,22 +1,42 @@ -<p><?= l("Download the old of the oldest software I made", "Téléchargez les plus vieux des vieux logiciels que j'ai créé") ?>. <?= l("Some of this software is", "Certains de ces logiciels sont") ?> <u><?= l("proprietary", "propriétaires") ?></u> <?= l("and you can't change or distribute it without my consent", "et vous ne pouvez pas les modifier ou les distribuer sans mon accord") ?>. <?= l("Active projects are not listed here and can be downloaded from their respective page", "Les projets en cours de développement ne sont pas listés ici et peuvent être téléchargés sur leur page respective") ?>.</p> - -<div class="list-group"> - <?php - - $files = scandir($_SERVER['DOCUMENT_ROOT'] . "/archive/get"); - - foreach ($files as $file) { - if (substr($file, -5) === ".json" && file_exists($_SERVER['DOCUMENT_ROOT'] . "/archive/get/" . substr($file, 0, -5) . ".zip")) { - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/archive/get/" . $file), true); - echo('<a href="/archive/get/'.substr($file, 0, -5).'.zip" class="list-group-item list-group-item-action"><span class="badge bg-secondary rounded-pill">'.$data['date'].'</span> '.$data['title']); - if ($data['unreleased']) { - echo(' <span class="badge bg-warning">' . l("Unreleased", "Jamais sorti") . '</span>'); - } - echo('</a>'); - } - } - - ?> -</div> -<br> +<p><?= l("Download the old of the oldest software I made", "Téléchargez les plus vieux des vieux logiciels que j'ai créé") ?>. <?= l("Some of this software is", "Certains de ces logiciels sont") ?> <u><?= l("proprietary", "propriétaires") ?></u> <?= l("and you can't change or distribute it without my consent", "et vous ne pouvez pas les modifier ou les distribuer sans mon accord") ?>. <?= l("Active projects are not listed here and can be downloaded from their respective page", "Les projets en cours de développement ne sont pas listés ici et peuvent être téléchargés sur leur page respective") ?>.</p>
+
+<div class="list-group">
+ <?php
+
+ $pfiles = scandir($_SERVER['DOCUMENT_ROOT'] . "/archive/get");
+ $files = [];
+
+ foreach ($pfiles as $file) {
+ if ($file !== "." && $file !== ".." && substr($file, -5) === ".json") {
+ $files[$file] = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/archive/get/" . $file), true);
+
+ $parts = explode("/", $files[$file]["date"]);
+ $files[$file]["rawdate"] = $parts[1] . "-" . $parts[0];
+ $files[$file]["id"] = $file;
+ }
+ }
+
+ usort($files, function($a, $b) {
+ return strtoupper($a['rawdate']) <=> strtoupper($b['rawdate']);
+ });
+
+ foreach ($files as $data) {
+ $file = $data["id"];
+
+ if (substr($file, -5) === ".json" && file_exists($_SERVER['DOCUMENT_ROOT'] . "/archive/get/" . substr($file, 0, -5) . ".zip")) {
+ echo('<a href="/archive/get/'.substr($file, 0, -5).'.zip" class="list-group-item list-group-item-action"><img src="'.(trim(file_exists($_SERVER['DOCUMENT_ROOT'] . "/static/archives/" . substr($file, 0, -5) . ".png") ? "/static/archives/" . substr($file, 0, -5) . ".png" : "/static/genericProjectIcon.png")).'" alt="" width="24px"> '.$data['title'] . ' ');
+ if (isset($data["description"])) {
+ echo('<span class="text-muted"> · ' . l($data["description"]["en"], $data["description"]["fr"]) . '</span>');
+ }
+ echo('<span class="badge bg-secondary rounded-pill" style="float:right;">'.$data['date'].'</span>');
+ if ($data['unreleased']) {
+ echo(' <span class="badge bg-warning">' . l("Unreleased", "Jamais sorti") . '</span>');
+ }
+ echo('</a>');
+ }
+ }
+
+ ?>
+</div>
+<br>
<small><p class="text-muted"><?= l("Project start dates are estimated and cannot always be accurate", "Les dates de début des projets sont des estimations et ne peuvent pas être toujours précises") ?></p></small>
\ No newline at end of file diff --git a/includes/blog/data/2020-05-01@something.json b/includes/blog/data/2020-05-01@something.json deleted file mode 100644 index 51021ea..0000000 --- a/includes/blog/data/2020-05-01@something.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Some article" -}
\ No newline at end of file diff --git a/includes/blog/data/2020-05-01@something.json.html b/includes/blog/data/2020-05-01@something.json.html deleted file mode 100644 index 12ed35a..0000000 --- a/includes/blog/data/2020-05-01@something.json.html +++ /dev/null @@ -1 +0,0 @@ -<b>This is some <i>test</i></b><u> or, <i>is it?</i></u>... We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here.
\ No newline at end of file diff --git a/includes/blog/data/2020-05-02@something2.json b/includes/blog/data/2020-05-02@something2.json deleted file mode 100644 index 51021ea..0000000 --- a/includes/blog/data/2020-05-02@something2.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Some article" -}
\ No newline at end of file diff --git a/includes/blog/data/2020-05-02@something2.json.html b/includes/blog/data/2020-05-02@something2.json.html deleted file mode 100644 index 12ed35a..0000000 --- a/includes/blog/data/2020-05-02@something2.json.html +++ /dev/null @@ -1 +0,0 @@ -<b>This is some <i>test</i></b><u> or, <i>is it?</i></u>... We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here.
\ No newline at end of file diff --git a/includes/blog/data/2020-05-03@something3.json b/includes/blog/data/2020-05-03@something3.json deleted file mode 100644 index 51021ea..0000000 --- a/includes/blog/data/2020-05-03@something3.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Some article" -}
\ No newline at end of file diff --git a/includes/blog/data/2020-05-03@something3.json.html b/includes/blog/data/2020-05-03@something3.json.html deleted file mode 100644 index 12ed35a..0000000 --- a/includes/blog/data/2020-05-03@something3.json.html +++ /dev/null @@ -1 +0,0 @@ -<b>This is some <i>test</i></b><u> or, <i>is it?</i></u>... We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here.
\ No newline at end of file diff --git a/includes/blog/data/2020-05-04@something4.json b/includes/blog/data/2020-05-04@something4.json deleted file mode 100644 index c8376de..0000000 --- a/includes/blog/data/2020-05-04@something4.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Some article", - "title.fr": "Un article" -}
\ No newline at end of file diff --git a/includes/blog/data/2020-05-04@something4.json.fr.html b/includes/blog/data/2020-05-04@something4.json.fr.html deleted file mode 100644 index 8bb1663..0000000 --- a/includes/blog/data/2020-05-04@something4.json.fr.html +++ /dev/null @@ -1 +0,0 @@ -<b>Il s'agit d'un <i>test</i></b><u> ou, <i>en est-il un ?</i></u>... Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici. Nous ne saurons jamais si il devait vraiment y avoir du texte ou quelque chose d'autre ici.
\ No newline at end of file diff --git a/includes/blog/data/2020-05-04@something4.json.html b/includes/blog/data/2020-05-04@something4.json.html deleted file mode 100644 index 12ed35a..0000000 --- a/includes/blog/data/2020-05-04@something4.json.html +++ /dev/null @@ -1 +0,0 @@ -<b>This is some <i>test</i></b><u> or, <i>is it?</i></u>... We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here. We would never know if there really should be any text or whatever thingy just in that place right here.
\ No newline at end of file diff --git a/includes/blog/home.php b/includes/blog/home.php index 49817e8..287ff64 100644 --- a/includes/blog/home.php +++ b/includes/blog/home.php @@ -1,29 +1,32 @@ -<div class="card-group"> - <?php - - $articles = scandir($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data"); - $i = 1; - $articles = array_reverse($articles); - foreach ($articles as $article): - - ?> - <?php if ($i <= 3 && strpos($article, "@") !== false && strpos($article, ".html") === false): ?> - <?php - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article), true); - if (l("a", "b") === "b" && file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article . ".fr.html")) { - $data['html'] = file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article . ".fr.html"); - } else { - $data['html'] = file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article . ".html"); - } - ?> - <div class="card"> - <div class="card-body"> - <h5 class="card-title"><?= l($data["title"], $data["title.fr"] ?? $data["title"]) ?></h5> - <p class="card-text"><?= strlen(strip_tags($data["html"])) > 150 ? substr(strip_tags($data["html"]), 0, 150) . "..." : strip_tags($data["html"]) ?></p> - <p class="card-text"><small class="text-muted"><?= l("Published", "Publié") ?> <?= strftime(l("%a %b %e, %Y", "%a %e %b %Y"), (int)DateTime::createFromFormat('Y-m-d', explode("@", $article)[0])->format("U")); ?></small></p> - <a href="/blog/article-<?= explode(".", $article)[0] ?>" class="card-link"><?= l("Read more...", "Lire plus...") ?></a> - </div> - </div> - <?php $i++;endif; ?> - <?php endforeach; ?> +<div class="card-group">
+ <?php
+
+ $articles = scandir($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data");
+ $i = 1;
+ $articles = array_reverse($articles);
+ foreach ($articles as $article):
+
+ ?>
+ <?php if ($i <= 3 && strpos($article, "@") !== false && strpos($article, ".html") === false && file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . substr($article, 0, -5) . ".json.md")): ?>
+ <?php
+ $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article), true);
+ if (l("a", "b") === "b" && file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article . ".fr.html")) {
+ $data['html'] = file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article . ".fr.md");
+ } else {
+ $data['html'] = file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article . ".md");
+ }
+
+ /** @var mixed $Parsedown */
+ $data['html'] = $Parsedown->text($data['html']);
+ ?>
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title"><?= l($data["title"], $data["title.fr"] ?? $data["title"]) ?></h5>
+ <p class="card-text"><?= strlen(strip_tags($data["html"])) > 150 ? substr(strip_tags($data["html"]), 0, 150) . "..." : strip_tags($data["html"]) ?></p>
+ <p class="card-text"><small class="text-muted"><?= l("Published", "Publié") ?> <?= strftime(l("%a %b %e, %Y", "%a %e %b %Y"), (int)DateTime::createFromFormat('Y-m-d', explode("@", $article)[0])->format("U")); ?></small></p>
+ <a href="/blog/article-<?= explode(".", $article)[0] ?>" class="card-link"><?= l("Read more...", "Lire plus...") ?></a>
+ </div>
+ </div>
+ <?php $i++;endif; ?>
+ <?php endforeach; ?>
</div>
\ No newline at end of file diff --git a/includes/blog/list.php b/includes/blog/list.php index 1c81630..4777027 100644 --- a/includes/blog/list.php +++ b/includes/blog/list.php @@ -1,15 +1,15 @@ -<div class="list-group"> - <?php - - $articles = scandir($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data"); - $i = 1; - $articles = array_reverse($articles); - foreach ($articles as $article): - - ?> - <?php if (strpos($article, "@") !== false && strpos($article, ".html") === false): ?> - <?php $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article), true); ?> - <a href="/blog/article-<?= explode(".", $article)[0] ?>" class="list-group-item list-group-item-action"><span class="text-muted"><?= strftime(l("%a %b %e, %Y", "%a %e %b %Y"), (int)DateTime::createFromFormat('Y-m-d', explode("@", $article)[0])->format("U")); ?></span> · <?= l($data["title"], $data["title.fr"] ?? $data["title"]) ?></a> - <?php endif;$i++; ?> - <?php endforeach; ?> +<div class="list-group">
+ <?php
+
+ $articles = scandir($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data");
+ $i = 1;
+ $articles = array_reverse($articles);
+ foreach ($articles as $article):
+
+ ?>
+ <?php if (strpos($article, "@") !== false && strpos($article, ".html") === false && file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . substr($article, 0, -5) . ".json.md")): ?>
+ <?php $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/blog/data/" . $article), true); ?>
+ <a href="/blog/article-<?= explode(".", $article)[0] ?>" class="list-group-item list-group-item-action"><span class="text-muted"><?= strftime(l("%a %b %e, %Y", "%a %e %b %Y"), (int)DateTime::createFromFormat('Y-m-d', explode("@", $article)[0])->format("U")); ?></span> · <?= l($data["title"], $data["title.fr"] ?? $data["title"]) ?></a>
+ <?php endif;$i++; ?>
+ <?php endforeach; ?>
</div>
\ No newline at end of file diff --git a/includes/categories.php b/includes/categories.php index b6ba521..38979f2 100644 --- a/includes/categories.php +++ b/includes/categories.php @@ -1,33 +1,33 @@ -<div class="card-group"> - <div class="card <?= isset($_ACTIVE) && $_ACTIVE === "furry" ? "bg-dark text-white" : "" ?>" style="text-align:center;padding-top:20px;padding-bottom:10px;"> - <img class="card-img-top" src="/static/icons/furry<?= !isset($_ACTIVE) || $_ACTIVE !== "furry" ? "" : "-dark" ?>.png" alt="Card image" style="width:64px;height:64px;text-align:center;margin-left:auto;margin-right:auto;"> - <div class="card-body"> - <h3><?= l("Furry fandom", "Fandom furry") ?></h3> - <p><?= l("I am active in the furry community (also made a lot of friends there)", "Je suis actif dans la communauté furry (je me suis fait plein d'amis là bas)") ?></p> - - <a href="/furry" class="card-link"><?= l("Learn more...", "En savoir plus...") ?></a> - </div> - </div> - <div class="card <?= isset($_ACTIVE) && ($_ACTIVE === "dev" || $_ACTIVE === "video") ? "bg-dark text-white" : "" ?>" style="text-align:center;padding-top:20px;padding-bottom:10px;"> - <div style="text-align:center;margin-left:auto;margin-right:auto;" class="card-img-top"> - <img src="/static/icons/code<?= !isset($_ACTIVE) || ($_ACTIVE !== "dev" && $_ACTIVE !== "video") ? "" : "-dark" ?>.png" alt="Card image" style="width:64px;height:64px;text-align:center;margin-left:auto;margin-right:auto;"> - <img src="/static/icons/media<?= !isset($_ACTIVE) || ($_ACTIVE !== "dev" && $_ACTIVE !== "video") ? "" : "-dark" ?>.png" alt="Card image" style="width:64px;height:64px;"> - </div> - <div class="card-body"> - <h3><?= l("Projects", "Projets") ?></h3> - <p><?= l("Developing software and making multimedia stuff is my passion", "Mon passe-temps est de coder des logiciels et de créer du contenu multimedia") ?></p> - - <a href="/creations" class="card-link"><?= l("Learn more...", "En savoir plus...") ?></a> - </div> - </div> - <div class="card <?= isset($_ACTIVE) && $_ACTIVE === "archive" ? "bg-dark text-white" : "" ?>" style="text-align:center;padding-top:20px;padding-bottom:10px;"> - <img class="card-img-top" src="/static/icons/archive<?= !isset($_ACTIVE) || $_ACTIVE !== "archive" ? "" : "-dark" ?>.png" alt="Card image" style="width:64px;height:64px;text-align:center;margin-left:auto;margin-right:auto;"> - <div class="card-body"> - <h3>Archives</h3> - <p><?= l("I give everyone the possibility to enjoy all my projects, from past to the future", "Je donne à tout le monde la possibilité d'apprécier mes projets, du passé au futur") ?></p> - - <a href="/archive" class="card-link"><?= l("Learn more...", "En savoir plus...") ?></a> - </div> - </div> -</div> +<div class="card-group">
+ <div class="card <?= isset($_ACTIVE) && $_ACTIVE === "furry" ? "bg-dark text-white" : "" ?>" style="text-align:center;padding-top:20px;padding-bottom:10px;">
+ <img class="card-img-top" src="/static/icons/furry<?= !isset($_ACTIVE) || $_ACTIVE !== "furry" ? "" : "-dark" ?>.png" alt="Card image" style="width:64px;height:64px;text-align:center;margin-left:auto;margin-right:auto;">
+ <div class="card-body">
+ <h3><?= l("Furry fandom", "Fandom furry") ?></h3>
+ <p><?= l("I am active in the furry community (also made a lot of friends there)", "Je suis actif dans la communauté furry (je me suis fait plein d'amis là bas)") ?></p>
+
+ <a href="/furry" class="card-link"><?= l("Learn more...", "En savoir plus...") ?></a>
+ </div>
+ </div>
+ <div class="card <?= isset($_ACTIVE) && ($_ACTIVE === "dev" || $_ACTIVE === "video") ? "bg-dark text-white" : "" ?>" style="text-align:center;padding-top:20px;padding-bottom:10px;">
+ <div style="text-align:center;margin-left:auto;margin-right:auto;" class="card-img-top">
+ <img src="/static/icons/code<?= !isset($_ACTIVE) || ($_ACTIVE !== "dev" && $_ACTIVE !== "video") ? "" : "-dark" ?>.png" alt="Card image" style="width:64px;height:64px;text-align:center;margin-left:auto;margin-right:auto;">
+ <img src="/static/icons/media<?= !isset($_ACTIVE) || ($_ACTIVE !== "dev" && $_ACTIVE !== "video") ? "" : "-dark" ?>.png" alt="Card image" style="width:64px;height:64px;">
+ </div>
+ <div class="card-body">
+ <h3><?= l("Projects", "Projets") ?></h3>
+ <p><?= l("Developing software and making multimedia stuff is my passion", "Mon passe-temps est de coder des logiciels et de créer du contenu multimedia") ?></p>
+
+ <a href="/creations" class="card-link"><?= l("Learn more...", "En savoir plus...") ?></a>
+ </div>
+ </div>
+ <div class="card <?= isset($_ACTIVE) && $_ACTIVE === "archive" ? "bg-dark text-white" : "" ?>" style="text-align:center;padding-top:20px;padding-bottom:10px;">
+ <img class="card-img-top" src="/static/icons/archive<?= !isset($_ACTIVE) || $_ACTIVE !== "archive" ? "" : "-dark" ?>.png" alt="Card image" style="width:64px;height:64px;text-align:center;margin-left:auto;margin-right:auto;">
+ <div class="card-body">
+ <h3>Archives</h3>
+ <p><?= l("I give everyone the possibility to enjoy all my projects, from past to the future", "Je donne à tout le monde la possibilité d'apprécier mes projets, du passé au futur") ?></p>
+
+ <a href="/archive" class="card-link"><?= l("Learn more...", "En savoir plus...") ?></a>
+ </div>
+ </div>
+</div>
<hr>
\ No newline at end of file diff --git a/includes/code/en.html b/includes/code/en.html index b8225a3..82bc2c4 100644 --- a/includes/code/en.html +++ b/includes/code/en.html @@ -1,54 +1,54 @@ -<p><i>Last update: July 27th 2021</i></p> - -<h1>Minteck Community Code of Conduct</h1> - -<h2>Acceptance of the Code of Conduct</h2> -<p>The Community Services that Minteck provides are subject to the following Code of Conduct. Minteck reserves the right to update the Code of Conduct at any time without notice to you. The most current version of the Code of Conduct can be reviewed by clicking on the « Code of conduct » hyperlink located at the bottom of the main website; or using this hyperlink: <a href="https://mt.ro.lt/cond">https://mt.ro.lt/cond</a></p> - -<h2>Personal and Non-Commercial Use Limitation</h2> -<p>Unless otherwise specified, the Community Services are for your personal and non-commercial use. You may not modify, copy, distribute, transmit, display, perform, reproduce, publish, license, create derivative works from, transfer, or sell any information obtained from the Community Services.</p> - -<h2>Moderation Rules</h2> -<p>Privileged users may have elevated permissions over the Community Services (« Moderator »). A Moderator have the exclusive right to restrict, change, or delete any content on the Community Services without prior notice and without a reason.</p> -<p>A user that does not gives respect and politeness over another user, or a Moderator, will get a Punishment.</p> - -<h2>Content Legality</h2> -<p>The content published on the Community Services is commonly hosted on a server in France (which you can confirm on the « Legal Notices » page). Therefore, and even if the content is not hosted in France, all content published on the Community Services in subject to French and international laws.</p> -For example, this means the following content is not allowed and will result in a Punishment: -<ul> - <li>content showing objects legally considered as weapons</li> - <li>content showing practices that infringe copyright laws (« Crack »)</li> - <li> - content showing practices whose objective is to introduce into an automated data processing system or bypass a system's intended behavior - <ul> - <li>Content whose objective is to introduce into an automated data processing system is <b>tolerated <u>only</u> if</b> the poster warns about the legal risks and do it on their own system or a system they got permission on.</li> - <li>Content whose objective is to bypass a system's intended behavior is <b>tolerated <u>only</u> if</b> the poster warns that doing so may lead to contract termination (e.g. a Limited Warranty) and do it on their own system or a system they got permission on.</li> - </ul> - </li> -</ul> - -<h2>Content Accuracy Warning</h2> -<p>At no time Minteck or any of the users of the Community Services makes the warranty that the content you have access to via the Community Services is accurate, confirmed, up-to-date, real, recent, or anything else that may indicate an approval.</p> -<p>If you need to prove an information is accurate, you may need to do so and search by yourself; nobody on the Community Services is forced to publish sources for their content.</p> - -<h2>Digital and Real Wellbeing</h2> -<p>Minteck attaches great importance to make every user of the Community Services feel good and happy; both inside of the Community Services and in their real life. If you feel comfortable enough talking about it to someone else online, you can talk about it to Minteck themself or to a qualified Moderator.</p> -<p>Minteck themself promise they will never copy, distribute, transmit, display, reproduce, publish, license, transfer or sell the information they are given through your online chat. The Community Services are a place where everyone should feel welcome.</p> - -<p><b>If <u>at any time</u> you feel like you are going to commit suicide, please <u>IMMEDIATELY</u> call your local suicide hotline. A list is available on <a href="https://ibpf.org/resource/list-of-international-suicide-hotlines/" target="_blank">the International Bipolar Foundation's website</a>.</b> Minteck will regularly ask if you are « okay » through a conversation to make sure there is no suicide intention behind what you are saying.</p> - -<h2>Punishments</h2> -Through breaking this Code of Conduct, a user may get Punishments. Punishments are not fixed and depends on who gives it and why they give it to the user. Common Punishments includes, but are not limited to: -<ul> - <li>inability to collaborate for a specific amount of time (« Mute »)</li> - <li>exclusion from the Community Services, which the user can join back at any time (« Kick »)</li> - <li>inability to access the Community Services for a specific amount of time (« Temporary Ban »)</li> - <li> - permanent and irrevocable inability to access the Community Services (« Permanent Ban ») - <ul> - <li><b>Only Minteck themself is qualified to revoke a permanent inability; and will do so only under extreme circonstances.</b></li> - </ul> - </li> -</ul> - +<p><i>Last update: July 27th 2021</i></p>
+
+<h1>Minteck Community Code of Conduct</h1>
+
+<h2>Acceptance of the Code of Conduct</h2>
+<p>The Community Services that Minteck provides are subject to the following Code of Conduct. Minteck reserves the right to update the Code of Conduct at any time without notice to you. The most current version of the Code of Conduct can be reviewed by clicking on the « Code of conduct » hyperlink located at the bottom of the main website; or using this hyperlink: <a href="https://mt.ro.lt/cond">https://mt.ro.lt/cond</a></p>
+
+<h2>Personal and Non-Commercial Use Limitation</h2>
+<p>Unless otherwise specified, the Community Services are for your personal and non-commercial use. You may not modify, copy, distribute, transmit, display, perform, reproduce, publish, license, create derivative works from, transfer, or sell any information obtained from the Community Services.</p>
+
+<h2>Moderation Rules</h2>
+<p>Privileged users may have elevated permissions over the Community Services (« Moderator »). A Moderator have the exclusive right to restrict, change, or delete any content on the Community Services without prior notice and without a reason.</p>
+<p>A user that does not gives respect and politeness over another user, or a Moderator, will get a Punishment.</p>
+
+<h2>Content Legality</h2>
+<p>The content published on the Community Services is commonly hosted on a server in France (which you can confirm on the « Legal Notices » page). Therefore, and even if the content is not hosted in France, all content published on the Community Services in subject to French and international laws.</p>
+For example, this means the following content is not allowed and will result in a Punishment:
+<ul>
+ <li>content showing objects legally considered as weapons</li>
+ <li>content showing practices that infringe copyright laws (« Crack »)</li>
+ <li>
+ content showing practices whose objective is to introduce into an automated data processing system or bypass a system's intended behavior
+ <ul>
+ <li>Content whose objective is to introduce into an automated data processing system is <b>tolerated <u>only</u> if</b> the poster warns about the legal risks and do it on their own system or a system they got permission on.</li>
+ <li>Content whose objective is to bypass a system's intended behavior is <b>tolerated <u>only</u> if</b> the poster warns that doing so may lead to contract termination (e.g. a Limited Warranty) and do it on their own system or a system they got permission on.</li>
+ </ul>
+ </li>
+</ul>
+
+<h2>Content Accuracy Warning</h2>
+<p>At no time Minteck or any of the users of the Community Services makes the warranty that the content you have access to via the Community Services is accurate, confirmed, up-to-date, real, recent, or anything else that may indicate an approval.</p>
+<p>If you need to prove an information is accurate, you may need to do so and search by yourself; nobody on the Community Services is forced to publish sources for their content.</p>
+
+<h2>Digital and Real Wellbeing</h2>
+<p>Minteck attaches great importance to make every user of the Community Services feel good and happy; both inside of the Community Services and in their real life. If you feel comfortable enough talking about it to someone else online, you can talk about it to Minteck themself or to a qualified Moderator.</p>
+<p>Minteck themself promise they will never copy, distribute, transmit, display, reproduce, publish, license, transfer or sell the information they are given through your online chat. The Community Services are a place where everyone should feel welcome.</p>
+
+<p><b>If <u>at any time</u> you feel like you are going to commit suicide, please <u>IMMEDIATELY</u> call your local suicide hotline. A list is available on <a href="https://ibpf.org/resource/list-of-international-suicide-hotlines/" target="_blank">the International Bipolar Foundation's website</a>.</b> Minteck will regularly ask if you are « okay » through a conversation to make sure there is no suicide intention behind what you are saying.</p>
+
+<h2>Punishments</h2>
+Through breaking this Code of Conduct, a user may get Punishments. Punishments are not fixed and depends on who gives it and why they give it to the user. Common Punishments includes, but are not limited to:
+<ul>
+ <li>inability to collaborate for a specific amount of time (« Mute »)</li>
+ <li>exclusion from the Community Services, which the user can join back at any time (« Kick »)</li>
+ <li>inability to access the Community Services for a specific amount of time (« Temporary Ban »)</li>
+ <li>
+ permanent and irrevocable inability to access the Community Services (« Permanent Ban »)
+ <ul>
+ <li><b>Only Minteck themself is qualified to revoke a permanent inability; and will do so only under extreme circonstances.</b></li>
+ </ul>
+ </li>
+</ul>
+
<p>If you suffer some behavioral disorders such as schizophrenia or bipolar disorder, you should tell it to the Moderators or to Minteck so they are more soft when giving Punishments.</p>
\ No newline at end of file diff --git a/includes/code/fr.html b/includes/code/fr.html index 06ae256..8365663 100644 --- a/includes/code/fr.html +++ b/includes/code/fr.html @@ -1,54 +1,54 @@ -<p><i>Dernière mise à jour : 27 juillet 2021 (traduction effectuée le 27 juillet 2021)</i></p> - -<h1>Code de Conduite de la communauté Minteck</h1> - -<h2>Acceptation du Code de Conduite</h2> -<p>Les Services de la Communauté que Minteck met à votre disposition sont assujettis au présent Code de Conduite. Minteck se réserve le droit de mettre à jour le Code de Conduite à n'importe quel moment sans vous en informer. La version la plus récente du Code de Conduite peut être relue en cliquant sur l'hyperlien « Code de conduite » situé en bas du site principal ; ou en utilisant cet hyperlien: <a href="https://mt.ro.lt/cond">https://mt.ro.lt/cond</a></p> - -<h2>Limitations d'utilisation personnelle et non-commerciale</h2> -<p>Sauf mention contraire, les Services de la Communauté sont réservés à un cadre d'utilisation personnel et non-commercial. Vous ne devez pas modifier, copier, distribuer, transmettre, afficher, présenter, reproduire, publier, licencier, créer des travaux dérivés de, transférer, ou vendre une quelconque information obtenue à partir des Services de la Communauté.</p> - -<h2>Règles de modération</h2> -<p>Des utilisateurs privilégiés pourraient avoir des permissions élevées sur les Services de la Communauté (« Modérateur »). Un Modérateur dispose du droit exclusif de restreindre, changer, ou supprimer n'importe quel contenu présent sur les Services de la Communauté sans avertissement préalable et sans raison donnée.</p> -<p>Un utilisateur qui ne se présente pas respectueux et poli envers un autre utilisateur, ou un Modérateur, obtiendra une Sanction.</p> - -<h2>Légalité du contenu</h2> -<p>Le contenu publié sur les Services de la Communauté sont généralement hébergés sur un serveur situé en France (vous pouvez confirmer cela sur la page « Mentions légales »). De ce fait, et même si le contenu n'est pas hébergé en France, tout le contenu publié sur les Services de la Communauté est sujet aux lois françaises et internationales.</p> -Par example, cela signifie que le contenu suivant n'est pas autorisé et résultera d'une Sanction : -<ul> - <li>contenu présentant des objets légalement considérés comme des armes</li> - <li>contenu présentant des pratiques qui consistent à violer la propriété intellectuelle d'autrui (« Piratage »)</li> - <li> - contenu présentant des pratiques dont l'objectif est de s'introduire dans un système de traitement automatisé de données ou d'outrepasser le fonctionnement premier d'un système - <ul> - <li>Le contenu dont l'objectif est de s'introduire dans un système de traitement automatisé de données est <b>toléré <u>uniquement</u> si</b> l'auteur avertit des risques légaux et l'exécute sur son propre système ou un système sur lequel il a obtenu une autorisation.</li> - <li>Le contenu don't l'objectif est d'outrepasser le fonctionnement premier d'un système est <b>toléré <u>uniquement</u> si</b> l'auteur avertit que cela pourrait constituer une rupture de contrat (par exemple une Garantie Limitée) et l'exécute sur son propre système ou un système sur lequel il a obtenu une autorisation.</li> - </ul> - </li> -</ul> - -<h2>Avertissement sur la véracité du contenu</h2> -<p>À aucun moment Minteck ou un utilisateur des Services de la Communauté garantit que le contenu auquel vous avez accès par le biais des Services de la Communauté est véridique, confirmé, actuel, vrai, récent, ou quelque chose d'autre qui permettrait d'indiquer une approbation.</p> -<p>Si vous avez besoin de prouver la véracité d'une information, vous devriez avoir à le faire par vous même et faire vos propres recherches; personne utilisant les Services de la Communauté est obligée de publier les sources de son contenu.</p> - -<h2>Bien-être numérique et réel</h2> -<p>Minteck attache une importance toute particulière à la volonté que chaque utilisateur des Services de la Communauté se sente bien et heureux ; aussi bien à l'intérieur des Services de la Communauté que dans sa vie réelle. Si vous êtes suffisamment à l'aise pour parler de vos problèmes avec quelqu'un en ligne, vous pouvez en parler à Minteck lui-même ou à un Modérateur compétent.</p> -<p>Minteck lui-même promet qu'il ne va jamais copier, distribuer, transmettre, afficher, reproduire, publier, licencier, transférer ou vendre les informations qu'il possède par le biais de votre discussion en ligne. Les Services de la Communauté se doivent d'être un espace où chacun doit pouvoir avoir sa place.</p> - -<p><b>Si <u>à un quelconque moment</u> vous pensez que vous allez effectuer un acte de suicide, merci d'appeler <u>IMMÉDIATEMENT</u> votre ligne d'écoute sur le suicide locale. Une liste est disponible sur <a href="https://ibpf.org/resource/list-of-international-suicide-hotlines/" target="_blank">le site de la International Bipolar Foundation</a>.</b> Minteck va régulièrement vous demander votre ressenti au travers d'une conversation pour s'assurer qu'il n'y a pas d'intention du suicide derrière ce que vous dîtes.</p> - -<h2>Sanctions</h2> -En rompant ce Code de Conduite, un utilisateur peut être amené à des Sanctions. Les Sanctions ne sont pas fixes et dépendent de qui les donnent et pourquoi il les donne à cet utilisateur. Les Sanctions générales incluent, mais ne sont pas limitées à : -<ul> - <li>impossibilité de collaborer pendant une certaine période de temps (« Mute »)</li> - <li>exclusion des Services de la Communauté, après quoi l'utilisateur peut de nouveau rejoindre à n'importe quel moment (« Kick »)</li> - <li>impossibilité d'accéder aux Services de la Communauté pendant une certaine période de temps (« Bannissement temporaire »)</li> - <li> - impossibilité permanente et irrévocable d'accéder aux Services de la Communauté (« Bannissement définitif ») - <ul> - <li><b>Seul Minteck lui-même est apte à révoquer une impossibilité permanente ; et ne le fera que sous des circonstances particulières.</b></li> - </ul> - </li> -</ul> - +<p><i>Dernière mise à jour : 27 juillet 2021 (traduction effectuée le 27 juillet 2021)</i></p>
+
+<h1>Code de Conduite de la communauté Minteck</h1>
+
+<h2>Acceptation du Code de Conduite</h2>
+<p>Les Services de la Communauté que Minteck met à votre disposition sont assujettis au présent Code de Conduite. Minteck se réserve le droit de mettre à jour le Code de Conduite à n'importe quel moment sans vous en informer. La version la plus récente du Code de Conduite peut être relue en cliquant sur l'hyperlien « Code de conduite » situé en bas du site principal ; ou en utilisant cet hyperlien: <a href="https://mt.ro.lt/cond">https://mt.ro.lt/cond</a></p>
+
+<h2>Limitations d'utilisation personnelle et non-commerciale</h2>
+<p>Sauf mention contraire, les Services de la Communauté sont réservés à un cadre d'utilisation personnel et non-commercial. Vous ne devez pas modifier, copier, distribuer, transmettre, afficher, présenter, reproduire, publier, licencier, créer des travaux dérivés de, transférer, ou vendre une quelconque information obtenue à partir des Services de la Communauté.</p>
+
+<h2>Règles de modération</h2>
+<p>Des utilisateurs privilégiés pourraient avoir des permissions élevées sur les Services de la Communauté (« Modérateur »). Un Modérateur dispose du droit exclusif de restreindre, changer, ou supprimer n'importe quel contenu présent sur les Services de la Communauté sans avertissement préalable et sans raison donnée.</p>
+<p>Un utilisateur qui ne se présente pas respectueux et poli envers un autre utilisateur, ou un Modérateur, obtiendra une Sanction.</p>
+
+<h2>Légalité du contenu</h2>
+<p>Le contenu publié sur les Services de la Communauté sont généralement hébergés sur un serveur situé en France (vous pouvez confirmer cela sur la page « Mentions légales »). De ce fait, et même si le contenu n'est pas hébergé en France, tout le contenu publié sur les Services de la Communauté est sujet aux lois françaises et internationales.</p>
+Par example, cela signifie que le contenu suivant n'est pas autorisé et résultera d'une Sanction :
+<ul>
+ <li>contenu présentant des objets légalement considérés comme des armes</li>
+ <li>contenu présentant des pratiques qui consistent à violer la propriété intellectuelle d'autrui (« Piratage »)</li>
+ <li>
+ contenu présentant des pratiques dont l'objectif est de s'introduire dans un système de traitement automatisé de données ou d'outrepasser le fonctionnement premier d'un système
+ <ul>
+ <li>Le contenu dont l'objectif est de s'introduire dans un système de traitement automatisé de données est <b>toléré <u>uniquement</u> si</b> l'auteur avertit des risques légaux et l'exécute sur son propre système ou un système sur lequel il a obtenu une autorisation.</li>
+ <li>Le contenu don't l'objectif est d'outrepasser le fonctionnement premier d'un système est <b>toléré <u>uniquement</u> si</b> l'auteur avertit que cela pourrait constituer une rupture de contrat (par exemple une Garantie Limitée) et l'exécute sur son propre système ou un système sur lequel il a obtenu une autorisation.</li>
+ </ul>
+ </li>
+</ul>
+
+<h2>Avertissement sur la véracité du contenu</h2>
+<p>À aucun moment Minteck ou un utilisateur des Services de la Communauté garantit que le contenu auquel vous avez accès par le biais des Services de la Communauté est véridique, confirmé, actuel, vrai, récent, ou quelque chose d'autre qui permettrait d'indiquer une approbation.</p>
+<p>Si vous avez besoin de prouver la véracité d'une information, vous devriez avoir à le faire par vous même et faire vos propres recherches; personne utilisant les Services de la Communauté est obligée de publier les sources de son contenu.</p>
+
+<h2>Bien-être numérique et réel</h2>
+<p>Minteck attache une importance toute particulière à la volonté que chaque utilisateur des Services de la Communauté se sente bien et heureux ; aussi bien à l'intérieur des Services de la Communauté que dans sa vie réelle. Si vous êtes suffisamment à l'aise pour parler de vos problèmes avec quelqu'un en ligne, vous pouvez en parler à Minteck lui-même ou à un Modérateur compétent.</p>
+<p>Minteck lui-même promet qu'il ne va jamais copier, distribuer, transmettre, afficher, reproduire, publier, licencier, transférer ou vendre les informations qu'il possède par le biais de votre discussion en ligne. Les Services de la Communauté se doivent d'être un espace où chacun doit pouvoir avoir sa place.</p>
+
+<p><b>Si <u>à un quelconque moment</u> vous pensez que vous allez effectuer un acte de suicide, merci d'appeler <u>IMMÉDIATEMENT</u> votre ligne d'écoute sur le suicide locale. Une liste est disponible sur <a href="https://ibpf.org/resource/list-of-international-suicide-hotlines/" target="_blank">le site de la International Bipolar Foundation</a>.</b> Minteck va régulièrement vous demander votre ressenti au travers d'une conversation pour s'assurer qu'il n'y a pas d'intention du suicide derrière ce que vous dîtes.</p>
+
+<h2>Sanctions</h2>
+En rompant ce Code de Conduite, un utilisateur peut être amené à des Sanctions. Les Sanctions ne sont pas fixes et dépendent de qui les donnent et pourquoi il les donne à cet utilisateur. Les Sanctions générales incluent, mais ne sont pas limitées à :
+<ul>
+ <li>impossibilité de collaborer pendant une certaine période de temps (« Mute »)</li>
+ <li>exclusion des Services de la Communauté, après quoi l'utilisateur peut de nouveau rejoindre à n'importe quel moment (« Kick »)</li>
+ <li>impossibilité d'accéder aux Services de la Communauté pendant une certaine période de temps (« Bannissement temporaire »)</li>
+ <li>
+ impossibilité permanente et irrévocable d'accéder aux Services de la Communauté (« Bannissement définitif »)
+ <ul>
+ <li><b>Seul Minteck lui-même est apte à révoquer une impossibilité permanente ; et ne le fera que sous des circonstances particulières.</b></li>
+ </ul>
+ </li>
+</ul>
+
<p>Si vous souffrez de trouble mentaux tels que de la schizophrénie ou de la bipolarité, vous devriez en informer les Modérateurs ou Minteck afin qu'ils soient plus laxistes en vous donnant des Sanctions, s'il y a lieu.</p>
\ No newline at end of file diff --git a/includes/footer.php b/includes/footer.php index 0b8de30..8688bad 100644 --- a/includes/footer.php +++ b/includes/footer.php @@ -1,16 +1,16 @@ - - - - - <div style="background: #f8f9fa;padding-top: 16px;text-align: center;" id="footer-space"> - <div class="container"> - <p>Copyright © 2011-<?= date('Y') ?> Minteck, <?= l("All rights reserved", "Tous droits réservés") ?><br> - <a href="/legal"><?= l("Legal Notices", "Mentions légales") ?></a> · <a href="https://github.com/Minteck/Website" target="_blank"><?= l("Open-source software", "Logiciel libre") ?></a> · <a href="/code-of-conduct"><?= l("Code of conduct", "Code de conduite") ?></a> · <a href="/contact"><?= l("Contact me", "Me contacter") ?></a> - </p> - </div> - <a href="/about/#art-credits" title="Click to view artwork credits"><img alt="Friends!" src="/banner.png" style="width:calc(60vw - 24px);margin-left:20vw;margin-right:20vw;"></a> - </div> - - <script src="/static/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> -</body> +
+
+
+
+ <div style="background: #f8f9fa;padding-top: 16px;text-align: center;" id="footer-space">
+ <div class="container">
+ <p>Copyright © 2011-<?= date('Y') ?> Minteck, <?= l("All rights reserved", "Tous droits réservés") ?><br>
+ <a href="/legal"><?= l("Legal Notices", "Mentions légales") ?></a> · <a href="https://github.com/Minteck/Website" target="_blank"><?= l("Open-source software", "Logiciel libre") ?></a> · <a href="/code-of-conduct"><?= l("Code of conduct", "Code de conduite") ?></a> · <a href="/contact"><?= l("Contact me", "Me contacter") ?></a>
+ </p>
+ </div>
+ <a href="/about/#art-credits" title="Click to view artwork credits"><img alt="Friends!" src="/banner.png" style="width:calc(60vw - 24px);margin-left:20vw;margin-right:20vw;"></a>
+ </div>
+
+ <script src="/static/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
+</body>
</html>
\ No newline at end of file diff --git a/includes/friends/home.php b/includes/friends/home.php index e549070..667bd86 100644 --- a/includes/friends/home.php +++ b/includes/friends/home.php @@ -1,68 +1,68 @@ -<div class="card-group"> - <div class="card"> - <div class="card-body"> - <!--suppress CssInvalidPropertyValue --> - <h5 class="card-title" style="font-weight: bold;background: radial-gradient(circle,#dec64c 0%,#d67541 100%);background-clip: text;-webkit-background-clip: text;-webkit-text-fill-color: transparent;">Retsuno</h5> - <h6 class="card-subtitle mb-2 text-muted"> </h6> - <p><?= l("We met by chance on Reddit and now we're best friends. Was the first furry I talked to after <i>really</i> joining the fandom (yes, at 1 AM).", "Nous nous sommes rencontrés par hasard sur Reddit et maintenant nous sommes meilleurs amis. Il a été le premier furry auquel j'ai parlé après avoir <i>réellement</i> rejoint le fandom (oui, à 1h du matin)"); ?></p> - </div> - </div> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">Mylo</h5> - <h6 class="card-subtitle mb-2 text-muted">@FENNECPARTY</h6> - <p><?= l("His photos are great, and the person behind them is awesome.", "Ses photos sont jolies, et la personne derrière est incroyable."); ?></p> - <a href="https://twitter.com/fennecparty" target="_blank" class="btn btn-primary">Twitter</a> - </div> - </div> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">Fleur</h5> - <h6 class="card-subtitle mb-2 text-muted">@Fleurfurr</h6> - <p><?= l("(Somehow we're friends on Discord, don't remember sending you a request... ^^) His art is good and with little details everywhere!", "(Apparement nous sommes amis sur Discord, je ne me souviens pas t'avoir envoyé de demande... ^^) Son art est beau et avec des petits détails partout !"); ?></p> - <a href="https://twitter.com/Fleurfurr" target="_blank" class="btn btn-primary">Twitter</a> - </div> - </div> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">Ayann</h5> - <h6 class="card-subtitle mb-2 text-muted">@ayann_fr</h6> - <p><?= l("Helped me keep all this up with mental fuel! Probably won't be there without him.", "M'a aidé à continuer mes efforts avec des messages de soutien ! Je ne serai probablement pas là sans lui."); ?></p> - <a href="https://twitter.com/ayann_fr" target="_blank" class="btn btn-primary">Twitter</a> - </div> - </div> -</div> -<div class="card-group"> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">Wishdream</h5> - <h6 class="card-subtitle mb-2 text-muted">@WishdreamStar</h6> - <p><?= l("Probably knows Linux as much as I know it. Very fun and interesting to talk to each other, and also very great art.", "Connaît probablement Linux autant que je le connais. Il est très amusant et intéressant de discuter ensemble, et aussi son art est joli."); ?></p> - <a href="https://twitter.com/WishdreamStar" target="_blank" class="btn btn-primary">Twitter</a> - </div> - </div> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">Brabbit</h5> - <h6 class="card-subtitle mb-2 text-muted">@TalkingTadPol</h6> - <p><?= l("We mutually supported each other during hard times without even knowing each other. What an amazing story!", "On se soutient mutuellement pendant des temps difficiles sans même se connaître. Quelle histoire incroyable !"); ?></p> - <a href="https://twitter.com/TalkingTadPol" target="_blank" class="btn btn-primary">Twitter</a> - </div> - </div> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">fiddle</h5> - <h6 class="card-subtitle mb-2 text-muted">@fiddleafox</h6> - <p><?= l("We are friends. Or are we? Who knows... We talked about <a href='/creations/kartik'>Kartik</a> a while back so maybe yes.", "Nous sommes amis. Ou sommes nous amis ? Qui sait... On a discuté de <a href='/creations/kartik'>Kartik</a> il y a quelques temps donc probablement."); ?></p> - <a href="https://twitter.com/TalkingTadPol" target="_blank" class="btn btn-primary">Twitter</a> - </div> - </div> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">russelbuck</h5> - <h6 class="card-subtitle mb-2 text-muted">@russelbuck</h6> - <p><?= l("Meaningful music that I enjoy listening to. I did a cover of <a href='/creations/gyrate-with-obliqueness'>Gyrate with Obliqueness</a> from them.", "Musique censée à laquelle j'adore écouter. J'ai fait une reprise de sa musique <a href='/creations/gyrate-with-obliqueness'>Gyrate with Obliqueness</a>."); ?></p> - <a href="https://twitter.com/russelbuck" target="_blank" class="btn btn-primary">Twitter</a> - </div> - </div> +<div class="card-group">
+ <div class="card">
+ <div class="card-body">
+ <!--suppress CssInvalidPropertyValue -->
+ <h5 class="card-title" style="font-weight: bold;background: radial-gradient(circle,#dec64c 0%,#d67541 100%);background-clip: text;-webkit-background-clip: text;-webkit-text-fill-color: transparent;">Retsuno</h5>
+ <h6 class="card-subtitle mb-2 text-muted"> </h6>
+ <p><?= l("We met by chance on Reddit and now we're best friends. Was the first furry I talked to after <i>really</i> joining the fandom (yes, at 1 AM).", "Nous nous sommes rencontrés par hasard sur Reddit et maintenant nous sommes meilleurs amis. Il a été le premier furry auquel j'ai parlé après avoir <i>réellement</i> rejoint le fandom (oui, à 1h du matin)"); ?></p>
+ </div>
+ </div>
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title">Mylo</h5>
+ <h6 class="card-subtitle mb-2 text-muted">@FENNECPARTY</h6>
+ <p><?= l("His photos are great, and the person behind them is awesome.", "Ses photos sont jolies, et la personne derrière est incroyable."); ?></p>
+ <a href="https://twitter.com/fennecparty" target="_blank" class="btn btn-primary">Twitter</a>
+ </div>
+ </div>
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title">Fleur</h5>
+ <h6 class="card-subtitle mb-2 text-muted">@Fleurfurr</h6>
+ <p><?= l("(Somehow we're friends on Discord, don't remember sending you a request... ^^) His art is good and with little details everywhere!", "(Apparement nous sommes amis sur Discord, je ne me souviens pas t'avoir envoyé de demande... ^^) Son art est beau et avec des petits détails partout !"); ?></p>
+ <a href="https://twitter.com/Fleurfurr" target="_blank" class="btn btn-primary">Twitter</a>
+ </div>
+ </div>
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title">Ayann</h5>
+ <h6 class="card-subtitle mb-2 text-muted">@ayann_fr</h6>
+ <p><?= l("Helped me keep all this up with mental fuel! Probably won't be there without him.", "M'a aidé à continuer mes efforts avec des messages de soutien ! Je ne serai probablement pas là sans lui."); ?></p>
+ <a href="https://twitter.com/ayann_fr" target="_blank" class="btn btn-primary">Twitter</a>
+ </div>
+ </div>
+</div>
+<div class="card-group">
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title">Wishdream</h5>
+ <h6 class="card-subtitle mb-2 text-muted">@WishdreamStar</h6>
+ <p><?= l("Probably knows Linux as much as I know it. Very fun and interesting to talk to each other, and also very great art.", "Connaît probablement Linux autant que je le connais. Il est très amusant et intéressant de discuter ensemble, et aussi son art est joli."); ?></p>
+ <a href="https://twitter.com/WishdreamStar" target="_blank" class="btn btn-primary">Twitter</a>
+ </div>
+ </div>
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title">Brabbit</h5>
+ <h6 class="card-subtitle mb-2 text-muted">@TalkingTadPol</h6>
+ <p><?= l("We mutually supported each other during hard times without even knowing each other. What an amazing story!", "On se soutient mutuellement pendant des temps difficiles sans même se connaître. Quelle histoire incroyable !"); ?></p>
+ <a href="https://twitter.com/TalkingTadPol" target="_blank" class="btn btn-primary">Twitter</a>
+ </div>
+ </div>
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title">fiddle</h5>
+ <h6 class="card-subtitle mb-2 text-muted">@fiddleafox</h6>
+ <p><?= l("We are friends. Or are we? Who knows... We talked about <a href='/creations/kartik'>Kartik</a> a while back so maybe yes.", "Nous sommes amis. Ou sommes nous amis ? Qui sait... On a discuté de <a href='/creations/kartik'>Kartik</a> il y a quelques temps donc probablement."); ?></p>
+ <a href="https://twitter.com/TalkingTadPol" target="_blank" class="btn btn-primary">Twitter</a>
+ </div>
+ </div>
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title">russelbuck</h5>
+ <h6 class="card-subtitle mb-2 text-muted">@russelbuck</h6>
+ <p><?= l("Meaningful music that I enjoy listening to. I did a cover of <a href='/creations/gyrate-with-obliqueness'>Gyrate with Obliqueness</a> from them.", "Musique censée à laquelle j'adore écouter. J'ai fait une reprise de sa musique <a href='/creations/gyrate-with-obliqueness'>Gyrate with Obliqueness</a>."); ?></p>
+ <a href="https://twitter.com/russelbuck" target="_blank" class="btn btn-primary">Twitter</a>
+ </div>
+ </div>
</div>
\ No newline at end of file diff --git a/includes/furry/main.php b/includes/furry/main.php index b3d9bbc..6fd199e 100644 --- a/includes/furry/main.php +++ b/includes/furry/main.php @@ -1 +1 @@ -<?php +<?php
diff --git a/includes/header.php b/includes/header.php index 3f16582..36d0fc1 100644 --- a/includes/header.php +++ b/includes/header.php @@ -1,108 +1,91 @@ -<?php - -$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); - -function l($en, $fr = null) { - global $lang; - - if ((($lang === "fr" && isset($fr)) || (isset($_GET['fr']) && isset($fr) || isset($_COOKIE['fr']))) && !isset($_GET['en']) && !isset($_COOKIE['en']) && isset($fr)) { - setlocale(LC_TIME, array('fr_FR.UTF-8','fr_FR@euro','fr_FR','french')); - return $fr; - } else { - return $en; - } -} - -$db = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/telemetry.json"), true); - -$ip = md5($_SERVER['REMOTE_ADDR']); -$day = date('d'); -$month = date('m'); -$year = date('y'); -$url = explode("?", $_SERVER['REQUEST_URI'])[0]; - -if (!isset($db[$year])) { - $db[$year] = []; -} -if (!isset($db[$year][$month])) { - $db[$year][$month] = []; -} -if (!isset($db[$year][$month][$day])) { - $db[$year][$month][$day] = []; -} -if (!isset($db[$year][$month][$day][$url])) { - $db[$year][$month][$day][$url] = []; -} - -if (!in_array($ip, $db[$year][$month][$day][$url])) { - array_push($db[$year][$month][$day][$url], $ip); -} - -function credit(string $name, string $description, string $image, bool $backwards) { - if ($backwards) { - return "<div class='artwork-credits-box--back'><div><h3>{$name}</h3>{$description}</div></div><img class='artwork-credits-image--back' src='{$image}' alt='{$name}'>"; - } else { - return "<img class='artwork-credits-image' src='{$image}' alt='{$name}'><div class='artwork-credits-box'><div><h3>{$name}</h3>{$description}</div></div>"; - } -} - -file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/telemetry.json", json_encode($db, JSON_PRETTY_PRINT)); - -?> -<!DOCTYPE html> -<html lang="<?= $lang === "fr" ? "fr" : "en" ?>"> -<head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="icon" href="/logo.svg"> - <link href="/static/css/darktheme.css" rel="stylesheet"> - <link href="/static/css/fonts" rel="stylesheet"> - <link href="/static/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> - <title><?php - - if (isset($_TITLE)) { - echo($_TITLE . " — "); - } - - ?><?= l("Minteck's space", "L'espace de Minteck") ?></title> -</head> -<body style="background-size: cover;background-position: center;background-repeat: no-repeat;background-attachment: fixed;"> - <!--<div style="height:16px;background:orange;position:fixed;color:black;font-size:12px;font-weight:bold;text-align:center;z-index:999;top:0;left:0;right:0;">Private beta of Minteck's space. Please report all bugs, issues or design details at <a href="mailto:nekostarfan@gmail.com">nekostarfan@gmail.com</a> or <a href="https://jetbrains.minteck.ro.lt:1024/youtrack/issues/MSS" target="_blank">on Minteck's YouTrack instance</a></div>--> - <nav style="z-index:99;" class="navbar fixed-top navbar-expand-lg navbar-light bg-light"> - <div class="container-fluid"> - <a class="navbar-brand" href="/"><img src="/logo.svg" alt="" width="36px"> <span style="vertical-align: middle;"><?= l("Minteck's space", "L'espace de Minteck") ?></span></a> - <button class="navbar-toggler" style="filter:invert(1);" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> - <span class="navbar-toggler-icon"></span> - </button> - <div class="collapse navbar-collapse" id="navbarSupportedContent"> - <ul class="navbar-nav me-auto mb-2 mb-lg-0"> - <li class="nav-item"><a class="nav-link" href="/"><?= l("Home", "Accueil") ?></a></li> - <li class="nav-item"><a class="nav-link" href="/blog">Blog</a></li> - <li class="nav-item dropdown"> - <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - <?= l("Creations", "Mes créations") ?> - </a> - <ul class="dropdown-menu" aria-labelledby="navbarDropdown"> - <li><a class="dropdown-item" href="/furry"><?= l("Furry fandom", "Fandom furry") ?></a></li> - <li><a class="dropdown-item" href="/creations"><?= l("My Projects", "Mes projets") ?></a></li> - <li><a class="dropdown-item" href="/archive"><?= l("Software Archive", "Archive des logiciels") ?></a></li> - </ul> - </li> - <li class="nav-item"><a class="nav-link" href="/about"><?= l("About me", "À propos de moi") ?></a></li> - <li class="nav-item"><a class="nav-link" href="/contact"><?= l("Contact me", "Me contacter") ?></a></li> - </ul> - - <div class="dropdown"> - <button id="apps_outer" class="dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false"><?= file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/static/apps.svg"); ?></button> - <ul class="dropdown-menu" style="position:fixed;top:48px;left:initial;right:10px;" aria-labelledby="apps_outer"> - <li><a href="https://github.com/Minteck" class="dropdown-item"><img alt="" src="/static/apps/github.png" class="app-icon"> <span class="app-title">GitHub</span></a></li> - <li><a href="https://kartik.hopto.org/online" class="dropdown-item"><img alt="" src="/static/apps/kartik.png" class="app-icon"> <span class="app-title">Kartik Online</span></a></li> - <li><a href="/" class="dropdown-item"><span class="app-title"><img alt="" src="/logo.svg" class="app-icon"> Minteck's Space</span></a></li> - <li><a href="https://unchainedtech.minteck.ro.lt" class="dropdown-item"><span class="app-title"><img alt="" src="/static/apps/unchainedtech.png" class="app-icon"> UnchainedTech</span></a></li> - <li><a href="https://jetbrains.minteck.ro.lt/hub" class="dropdown-item"><img alt="" src="/static/apps/hub.svg" class="app-icon"> <span class="app-title">Minteck's Hub</span></a></li> - <li><a href="https://jetbrains.minteck.ro.lt/youtrack" class="dropdown-item"><img alt="" src="/static/apps/youtrack.svg" class="app-icon"> <span class="app-title">YouTrack</span></a></li> - </ul> - </div> - </div> - </div> - </nav> +<?php
+
+if ($_SERVER['REMOTE_ADDR'] !== "92.152.77.195") {
+ header("Location: https://minteck-projects.alwaysdata.net");
+ die();
+}
+
+$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
+
+function l($en, $fr = null) {
+ global $lang;
+
+ if ((($lang === "fr" && isset($fr)) || (isset($_GET['fr']) && isset($fr) || isset($_COOKIE['fr']))) && !isset($_GET['en']) && !isset($_COOKIE['en']) && isset($fr)) {
+ setlocale(LC_TIME, array('fr_FR.UTF-8','fr_FR@euro','fr_FR','french'));
+ return $fr;
+ } else {
+ return $en;
+ }
+}
+
+require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/telemetry.php";
+
+function credit(string $name, string $description, string $image, bool $backwards) {
+ if ($backwards) {
+ return "<div class='artwork-credits-box--back'><div><h3>{$name}</h3>{$description}</div></div><img class='artwork-credits-image--back' src='{$image}' alt='{$name}'>";
+ } else {
+ return "<img class='artwork-credits-image' src='{$image}' alt='{$name}'><div class='artwork-credits-box'><div><h3>{$name}</h3>{$description}</div></div>";
+ }
+}
+
+require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/markdown.php";
+$Parsedown = new Parsedown();
+
+?>
+<!DOCTYPE html>
+<html lang="<?= $lang === "fr" ? "fr" : "en" ?>">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="icon" href="/logo.svg">
+ <link href="/static/css/darktheme.css" rel="stylesheet">
+ <link href="/static/css/fonts" rel="stylesheet">
+ <link href="/static/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
+ <title><?php
+
+ if (isset($_TITLE)) {
+ echo($_TITLE . " — ");
+ }
+
+ ?><?= l("Minteck's space", "L'espace de Minteck") ?></title>
+</head>
+<body style="background-size: cover;background-position: center;background-repeat: no-repeat;background-attachment: fixed;">
+ <!--<div style="height:16px;background:orange;position:fixed;color:black;font-size:12px;font-weight:bold;text-align:center;z-index:999;top:0;left:0;right:0;">Private beta of Minteck's space. Please report all bugs, issues or design details at <a href="mailto:nekostarfan@gmail.com">nekostarfan@gmail.com</a> or <a href="https://jetbrains.minteck.ro.lt:1024/youtrack/issues/MSS" target="_blank">on Minteck's YouTrack instance</a></div>-->
+ <nav style="z-index:99;" class="navbar fixed-top navbar-expand-lg navbar-light bg-light">
+ <div class="container-fluid">
+ <a class="navbar-brand" href="/"><img src="/logo.svg" alt="" width="36px"> <span style="vertical-align: middle;"><?= l("Minteck's space", "L'espace de Minteck") ?></span></a>
+ <button class="navbar-toggler" style="filter:invert(1);" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+ <div class="collapse navbar-collapse" id="navbarSupportedContent">
+ <ul class="navbar-nav me-auto mb-2 mb-lg-0">
+ <li class="nav-item"><a class="nav-link" href="/"><?= l("Home", "Accueil") ?></a></li>
+ <li class="nav-item"><a class="nav-link" href="/blog">Blog</a></li>
+ <li class="nav-item dropdown">
+ <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+ <?= l("Creations", "Mes créations") ?>
+ </a>
+ <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
+ <li><a class="dropdown-item" href="/furry"><?= l("Furry fandom", "Fandom furry") ?></a></li>
+ <li><a class="dropdown-item" href="/creations"><?= l("My Projects", "Mes projets") ?></a></li>
+ <li><a class="dropdown-item" href="/archive"><?= l("Software Archive", "Archive des logiciels") ?></a></li>
+ </ul>
+ </li>
+ <li class="nav-item"><a class="nav-link" href="/about"><?= l("About me", "À propos de moi") ?></a></li>
+ <li class="nav-item"><a class="nav-link" href="/contact"><?= l("Contact me", "Me contacter") ?></a></li>
+ </ul>
+
+ <div class="dropdown">
+ <button id="apps_outer" class="dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false"><?= file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/static/apps.svg"); ?></button>
+ <ul class="dropdown-menu" style="position:fixed;top:48px;left:initial;right:10px;" aria-labelledby="apps_outer">
+ <li><a href="https://github.com/Minteck" class="dropdown-item"><img alt="" src="/static/apps/github.png" class="app-icon"> <span class="app-title">GitHub</span></a></li>
+ <li><a href="https://kartik.hopto.org/online" class="dropdown-item"><img alt="" src="/static/apps/kartik.png" class="app-icon"> <span class="app-title">Kartik Online</span></a></li>
+ <li><a href="/" class="dropdown-item"><span class="app-title"><img alt="" src="/logo.svg" class="app-icon"> Minteck's Space</span></a></li>
+ <li><a href="https://unchainedtech.minteck.ro.lt" class="dropdown-item"><span class="app-title"><img alt="" src="/static/apps/unchainedtech.png" class="app-icon"> UnchainedTech</span></a></li>
+ <li><a href="https://jetbrains.minteck.ro.lt/hub" class="dropdown-item"><img alt="" src="/static/apps/hub.svg" class="app-icon"> <span class="app-title">Minteck's Hub</span></a></li>
+ <li><a href="https://jetbrains.minteck.ro.lt/youtrack" class="dropdown-item"><img alt="" src="/static/apps/youtrack.svg" class="app-icon"> <span class="app-title">YouTrack</span></a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </nav>
diff --git a/includes/markdown.php b/includes/markdown.php new file mode 100644 index 0000000..ae0cbde --- /dev/null +++ b/includes/markdown.php @@ -0,0 +1,1994 @@ +<?php + +# +# +# Parsedown +# http://parsedown.org +# +# (c) Emanuil Rusev +# http://erusev.com +# +# For the full license information, view the LICENSE file that was distributed +# with this source code. +# +# + +class Parsedown +{ + # ~ + + const version = '1.8.0-beta-7'; + + # ~ + + function text($text) + { + $Elements = $this->textElements($text); + + # convert to markup + $markup = $this->elements($Elements); + + # trim line breaks + $markup = trim($markup, "\n"); + + return $markup; + } + + protected function textElements($text) + { + # make sure no definitions are set + $this->DefinitionData = array(); + + # standardize line breaks + $text = str_replace(array("\r\n", "\r"), "\n", $text); + + # remove surrounding line breaks + $text = trim($text, "\n"); + + # split text into lines + $lines = explode("\n", $text); + + # iterate through lines to identify blocks + return $this->linesElements($lines); + } + + # + # Setters + # + + function setBreaksEnabled($breaksEnabled) + { + $this->breaksEnabled = $breaksEnabled; + + return $this; + } + + protected $breaksEnabled; + + function setMarkupEscaped($markupEscaped) + { + $this->markupEscaped = $markupEscaped; + + return $this; + } + + protected $markupEscaped; + + function setUrlsLinked($urlsLinked) + { + $this->urlsLinked = $urlsLinked; + + return $this; + } + + protected $urlsLinked = true; + + function setSafeMode($safeMode) + { + $this->safeMode = (bool) $safeMode; + + return $this; + } + + protected $safeMode; + + function setStrictMode($strictMode) + { + $this->strictMode = (bool) $strictMode; + + return $this; + } + + protected $strictMode; + + protected $safeLinksWhitelist = array( + 'http://', + 'https://', + 'ftp://', + 'ftps://', + 'mailto:', + 'tel:', + 'data:image/png;base64,', + 'data:image/gif;base64,', + 'data:image/jpeg;base64,', + 'irc:', + 'ircs:', + 'git:', + 'ssh:', + 'news:', + 'steam:', + ); + + # + # Lines + # + + protected $BlockTypes = array( + '#' => array('Header'), + '*' => array('Rule', 'List'), + '+' => array('List'), + '-' => array('SetextHeader', 'Table', 'Rule', 'List'), + '0' => array('List'), + '1' => array('List'), + '2' => array('List'), + '3' => array('List'), + '4' => array('List'), + '5' => array('List'), + '6' => array('List'), + '7' => array('List'), + '8' => array('List'), + '9' => array('List'), + ':' => array('Table'), + '<' => array('Comment', 'Markup'), + '=' => array('SetextHeader'), + '>' => array('Quote'), + '[' => array('Reference'), + '_' => array('Rule'), + '`' => array('FencedCode'), + '|' => array('Table'), + '~' => array('FencedCode'), + ); + + # ~ + + protected $unmarkedBlockTypes = array( + 'Code', + ); + + # + # Blocks + # + + protected function lines(array $lines) + { + return $this->elements($this->linesElements($lines)); + } + + protected function linesElements(array $lines) + { + $Elements = array(); + $CurrentBlock = null; + + foreach ($lines as $line) + { + if (chop($line) === '') + { + if (isset($CurrentBlock)) + { + $CurrentBlock['interrupted'] = (isset($CurrentBlock['interrupted']) + ? $CurrentBlock['interrupted'] + 1 : 1 + ); + } + + continue; + } + + while (($beforeTab = strstr($line, "\t", true)) !== false) + { + $shortage = 4 - mb_strlen($beforeTab, 'utf-8') % 4; + + $line = $beforeTab + . str_repeat(' ', $shortage) + . substr($line, strlen($beforeTab) + 1) + ; + } + + $indent = strspn($line, ' '); + + $text = $indent > 0 ? substr($line, $indent) : $line; + + # ~ + + $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); + + # ~ + + if (isset($CurrentBlock['continuable'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Continue'; + $Block = $this->$methodName($Line, $CurrentBlock); + + if (isset($Block)) + { + $CurrentBlock = $Block; + + continue; + } + else + { + if ($this->isBlockCompletable($CurrentBlock['type'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Complete'; + $CurrentBlock = $this->$methodName($CurrentBlock); + } + } + } + + # ~ + + $marker = $text[0]; + + # ~ + + $blockTypes = $this->unmarkedBlockTypes; + + if (isset($this->BlockTypes[$marker])) + { + foreach ($this->BlockTypes[$marker] as $blockType) + { + $blockTypes []= $blockType; + } + } + + # + # ~ + + foreach ($blockTypes as $blockType) + { + $Block = $this->{"block$blockType"}($Line, $CurrentBlock); + + if (isset($Block)) + { + $Block['type'] = $blockType; + + if ( ! isset($Block['identified'])) + { + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + $Block['identified'] = true; + } + + if ($this->isBlockContinuable($blockType)) + { + $Block['continuable'] = true; + } + + $CurrentBlock = $Block; + + continue 2; + } + } + + # ~ + + if (isset($CurrentBlock) and $CurrentBlock['type'] === 'Paragraph') + { + $Block = $this->paragraphContinue($Line, $CurrentBlock); + } + + if (isset($Block)) + { + $CurrentBlock = $Block; + } + else + { + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + $CurrentBlock = $this->paragraph($Line); + + $CurrentBlock['identified'] = true; + } + } + + # ~ + + if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Complete'; + $CurrentBlock = $this->$methodName($CurrentBlock); + } + + # ~ + + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + # ~ + + return $Elements; + } + + protected function extractElement(array $Component) + { + if ( ! isset($Component['element'])) + { + if (isset($Component['markup'])) + { + $Component['element'] = array('rawHtml' => $Component['markup']); + } + elseif (isset($Component['hidden'])) + { + $Component['element'] = array(); + } + } + + return $Component['element']; + } + + protected function isBlockContinuable($Type) + { + return method_exists($this, 'block' . $Type . 'Continue'); + } + + protected function isBlockCompletable($Type) + { + return method_exists($this, 'block' . $Type . 'Complete'); + } + + # + # Code + + protected function blockCode($Line, $Block = null) + { + if (isset($Block) and $Block['type'] === 'Paragraph' and ! isset($Block['interrupted'])) + { + return; + } + + if ($Line['indent'] >= 4) + { + $text = substr($Line['body'], 4); + + $Block = array( + 'element' => array( + 'name' => 'pre', + 'element' => array( + 'name' => 'code', + 'text' => $text, + ), + ), + ); + + return $Block; + } + } + + protected function blockCodeContinue($Line, $Block) + { + if ($Line['indent'] >= 4) + { + if (isset($Block['interrupted'])) + { + $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']); + + unset($Block['interrupted']); + } + + $Block['element']['element']['text'] .= "\n"; + + $text = substr($Line['body'], 4); + + $Block['element']['element']['text'] .= $text; + + return $Block; + } + } + + protected function blockCodeComplete($Block) + { + return $Block; + } + + # + # Comment + + protected function blockComment($Line) + { + if ($this->markupEscaped or $this->safeMode) + { + return; + } + + if (strpos($Line['text'], '<!--') === 0) + { + $Block = array( + 'element' => array( + 'rawHtml' => $Line['body'], + 'autobreak' => true, + ), + ); + + if (strpos($Line['text'], '-->') !== false) + { + $Block['closed'] = true; + } + + return $Block; + } + } + + protected function blockCommentContinue($Line, array $Block) + { + if (isset($Block['closed'])) + { + return; + } + + $Block['element']['rawHtml'] .= "\n" . $Line['body']; + + if (strpos($Line['text'], '-->') !== false) + { + $Block['closed'] = true; + } + + return $Block; + } + + # + # Fenced Code + + protected function blockFencedCode($Line) + { + $marker = $Line['text'][0]; + + $openerLength = strspn($Line['text'], $marker); + + if ($openerLength < 3) + { + return; + } + + $infostring = trim(substr($Line['text'], $openerLength), "\t "); + + if (strpos($infostring, '`') !== false) + { + return; + } + + $Element = array( + 'name' => 'code', + 'text' => '', + ); + + if ($infostring !== '') + { + /** + * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes + * Every HTML element may have a class attribute specified. + * The attribute, if specified, must have a value that is a set + * of space-separated tokens representing the various classes + * that the element belongs to. + * [...] + * The space characters, for the purposes of this specification, + * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), + * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and + * U+000D CARRIAGE RETURN (CR). + */ + $language = substr($infostring, 0, strcspn($infostring, " \t\n\f\r")); + + $Element['attributes'] = array('class' => "language-$language"); + } + + $Block = array( + 'char' => $marker, + 'openerLength' => $openerLength, + 'element' => array( + 'name' => 'pre', + 'element' => $Element, + ), + ); + + return $Block; + } + + protected function blockFencedCodeContinue($Line, $Block) + { + if (isset($Block['complete'])) + { + return; + } + + if (isset($Block['interrupted'])) + { + $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']); + + unset($Block['interrupted']); + } + + if (($len = strspn($Line['text'], $Block['char'])) >= $Block['openerLength'] + and chop(substr($Line['text'], $len), ' ') === '' + ) { + $Block['element']['element']['text'] = substr($Block['element']['element']['text'], 1); + + $Block['complete'] = true; + + return $Block; + } + + $Block['element']['element']['text'] .= "\n" . $Line['body']; + + return $Block; + } + + protected function blockFencedCodeComplete($Block) + { + return $Block; + } + + # + # Header + + protected function blockHeader($Line) + { + $level = strspn($Line['text'], '#'); + + if ($level > 6) + { + return; + } + + $text = trim($Line['text'], '#'); + + if ($this->strictMode and isset($text[0]) and $text[0] !== ' ') + { + return; + } + + $text = trim($text, ' '); + + $Block = array( + 'element' => array( + 'name' => 'h' . $level, + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $text, + 'destination' => 'elements', + ) + ), + ); + + return $Block; + } + + # + # List + + protected function blockList($Line, array $CurrentBlock = null) + { + list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]{1,9}+[.\)]'); + + if (preg_match('/^('.$pattern.'([ ]++|$))(.*+)/', $Line['text'], $matches)) + { + $contentIndent = strlen($matches[2]); + + if ($contentIndent >= 5) + { + $contentIndent -= 1; + $matches[1] = substr($matches[1], 0, -$contentIndent); + $matches[3] = str_repeat(' ', $contentIndent) . $matches[3]; + } + elseif ($contentIndent === 0) + { + $matches[1] .= ' '; + } + + $markerWithoutWhitespace = strstr($matches[1], ' ', true); + + $Block = array( + 'indent' => $Line['indent'], + 'pattern' => $pattern, + 'data' => array( + 'type' => $name, + 'marker' => $matches[1], + 'markerType' => ($name === 'ul' ? $markerWithoutWhitespace : substr($markerWithoutWhitespace, -1)), + ), + 'element' => array( + 'name' => $name, + 'elements' => array(), + ), + ); + $Block['data']['markerTypeRegex'] = preg_quote($Block['data']['markerType'], '/'); + + if ($name === 'ol') + { + $listStart = ltrim(strstr($matches[1], $Block['data']['markerType'], true), '0') ?: '0'; + + if ($listStart !== '1') + { + if ( + isset($CurrentBlock) + and $CurrentBlock['type'] === 'Paragraph' + and ! isset($CurrentBlock['interrupted']) + ) { + return; + } + + $Block['element']['attributes'] = array('start' => $listStart); + } + } + + $Block['li'] = array( + 'name' => 'li', + 'handler' => array( + 'function' => 'li', + 'argument' => !empty($matches[3]) ? array($matches[3]) : array(), + 'destination' => 'elements' + ) + ); + + $Block['element']['elements'] []= & $Block['li']; + + return $Block; + } + } + + protected function blockListContinue($Line, array $Block) + { + if (isset($Block['interrupted']) and empty($Block['li']['handler']['argument'])) + { + return null; + } + + $requiredIndent = ($Block['indent'] + strlen($Block['data']['marker'])); + + if ($Line['indent'] < $requiredIndent + and ( + ( + $Block['data']['type'] === 'ol' + and preg_match('/^[0-9]++'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches) + ) or ( + $Block['data']['type'] === 'ul' + and preg_match('/^'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches) + ) + ) + ) { + if (isset($Block['interrupted'])) + { + $Block['li']['handler']['argument'] []= ''; + + $Block['loose'] = true; + + unset($Block['interrupted']); + } + + unset($Block['li']); + + $text = isset($matches[1]) ? $matches[1] : ''; + + $Block['indent'] = $Line['indent']; + + $Block['li'] = array( + 'name' => 'li', + 'handler' => array( + 'function' => 'li', + 'argument' => array($text), + 'destination' => 'elements' + ) + ); + + $Block['element']['elements'] []= & $Block['li']; + + return $Block; + } + elseif ($Line['indent'] < $requiredIndent and $this->blockList($Line)) + { + return null; + } + + if ($Line['text'][0] === '[' and $this->blockReference($Line)) + { + return $Block; + } + + if ($Line['indent'] >= $requiredIndent) + { + if (isset($Block['interrupted'])) + { + $Block['li']['handler']['argument'] []= ''; + + $Block['loose'] = true; + + unset($Block['interrupted']); + } + + $text = substr($Line['body'], $requiredIndent); + + $Block['li']['handler']['argument'] []= $text; + + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $text = preg_replace('/^[ ]{0,'.$requiredIndent.'}+/', '', $Line['body']); + + $Block['li']['handler']['argument'] []= $text; + + return $Block; + } + } + + protected function blockListComplete(array $Block) + { + if (isset($Block['loose'])) + { + foreach ($Block['element']['elements'] as &$li) + { + if (end($li['handler']['argument']) !== '') + { + $li['handler']['argument'] []= ''; + } + } + } + + return $Block; + } + + # + # Quote + + protected function blockQuote($Line) + { + if (preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches)) + { + $Block = array( + 'element' => array( + 'name' => 'blockquote', + 'handler' => array( + 'function' => 'linesElements', + 'argument' => (array) $matches[1], + 'destination' => 'elements', + ) + ), + ); + + return $Block; + } + } + + protected function blockQuoteContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + if ($Line['text'][0] === '>' and preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches)) + { + $Block['element']['handler']['argument'] []= $matches[1]; + + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $Block['element']['handler']['argument'] []= $Line['text']; + + return $Block; + } + } + + # + # Rule + + protected function blockRule($Line) + { + $marker = $Line['text'][0]; + + if (substr_count($Line['text'], $marker) >= 3 and chop($Line['text'], " $marker") === '') + { + $Block = array( + 'element' => array( + 'name' => 'hr', + ), + ); + + return $Block; + } + } + + # + # Setext + + protected function blockSetextHeader($Line, array $Block = null) + { + if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) + { + return; + } + + if ($Line['indent'] < 4 and chop(chop($Line['text'], ' '), $Line['text'][0]) === '') + { + $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; + + return $Block; + } + } + + # + # Markup + + protected function blockMarkup($Line) + { + if ($this->markupEscaped or $this->safeMode) + { + return; + } + + if (preg_match('/^<[\/]?+(\w*)(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+(\/)?>/', $Line['text'], $matches)) + { + $element = strtolower($matches[1]); + + if (in_array($element, $this->textLevelElements)) + { + return; + } + + $Block = array( + 'name' => $matches[1], + 'element' => array( + 'rawHtml' => $Line['text'], + 'autobreak' => true, + ), + ); + + return $Block; + } + } + + protected function blockMarkupContinue($Line, array $Block) + { + if (isset($Block['closed']) or isset($Block['interrupted'])) + { + return; + } + + $Block['element']['rawHtml'] .= "\n" . $Line['body']; + + return $Block; + } + + # + # Reference + + protected function blockReference($Line) + { + if (strpos($Line['text'], ']') !== false + and preg_match('/^\[(.+?)\]:[ ]*+<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*+$/', $Line['text'], $matches) + ) { + $id = strtolower($matches[1]); + + $Data = array( + 'url' => $matches[2], + 'title' => isset($matches[3]) ? $matches[3] : null, + ); + + $this->DefinitionData['Reference'][$id] = $Data; + + $Block = array( + 'element' => array(), + ); + + return $Block; + } + } + + # + # Table + + protected function blockTable($Line, array $Block = null) + { + if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) + { + return; + } + + if ( + strpos($Block['element']['handler']['argument'], '|') === false + and strpos($Line['text'], '|') === false + and strpos($Line['text'], ':') === false + or strpos($Block['element']['handler']['argument'], "\n") !== false + ) { + return; + } + + if (chop($Line['text'], ' -:|') !== '') + { + return; + } + + $alignments = array(); + + $divider = $Line['text']; + + $divider = trim($divider); + $divider = trim($divider, '|'); + + $dividerCells = explode('|', $divider); + + foreach ($dividerCells as $dividerCell) + { + $dividerCell = trim($dividerCell); + + if ($dividerCell === '') + { + return; + } + + $alignment = null; + + if ($dividerCell[0] === ':') + { + $alignment = 'left'; + } + + if (substr($dividerCell, - 1) === ':') + { + $alignment = $alignment === 'left' ? 'center' : 'right'; + } + + $alignments []= $alignment; + } + + # ~ + + $HeaderElements = array(); + + $header = $Block['element']['handler']['argument']; + + $header = trim($header); + $header = trim($header, '|'); + + $headerCells = explode('|', $header); + + if (count($headerCells) !== count($alignments)) + { + return; + } + + foreach ($headerCells as $index => $headerCell) + { + $headerCell = trim($headerCell); + + $HeaderElement = array( + 'name' => 'th', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $headerCell, + 'destination' => 'elements', + ) + ); + + if (isset($alignments[$index])) + { + $alignment = $alignments[$index]; + + $HeaderElement['attributes'] = array( + 'style' => "text-align: $alignment;", + ); + } + + $HeaderElements []= $HeaderElement; + } + + # ~ + + $Block = array( + 'alignments' => $alignments, + 'identified' => true, + 'element' => array( + 'name' => 'table', + 'elements' => array(), + ), + ); + + $Block['element']['elements'] []= array( + 'name' => 'thead', + ); + + $Block['element']['elements'] []= array( + 'name' => 'tbody', + 'elements' => array(), + ); + + $Block['element']['elements'][0]['elements'] []= array( + 'name' => 'tr', + 'elements' => $HeaderElements, + ); + + return $Block; + } + + protected function blockTableContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + if (count($Block['alignments']) === 1 or $Line['text'][0] === '|' or strpos($Line['text'], '|')) + { + $Elements = array(); + + $row = $Line['text']; + + $row = trim($row); + $row = trim($row, '|'); + + preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]++`|`)++/', $row, $matches); + + $cells = array_slice($matches[0], 0, count($Block['alignments'])); + + foreach ($cells as $index => $cell) + { + $cell = trim($cell); + + $Element = array( + 'name' => 'td', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $cell, + 'destination' => 'elements', + ) + ); + + if (isset($Block['alignments'][$index])) + { + $Element['attributes'] = array( + 'style' => 'text-align: ' . $Block['alignments'][$index] . ';', + ); + } + + $Elements []= $Element; + } + + $Element = array( + 'name' => 'tr', + 'elements' => $Elements, + ); + + $Block['element']['elements'][1]['elements'] []= $Element; + + return $Block; + } + } + + # + # ~ + # + + protected function paragraph($Line) + { + return array( + 'type' => 'Paragraph', + 'element' => array( + 'name' => 'p', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $Line['text'], + 'destination' => 'elements', + ), + ), + ); + } + + protected function paragraphContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + $Block['element']['handler']['argument'] .= "\n".$Line['text']; + + return $Block; + } + + # + # Inline Elements + # + + protected $InlineTypes = array( + '!' => array('Image'), + '&' => array('SpecialCharacter'), + '*' => array('Emphasis'), + ':' => array('Url'), + '<' => array('UrlTag', 'EmailTag', 'Markup'), + '[' => array('Link'), + '_' => array('Emphasis'), + '`' => array('Code'), + '~' => array('Strikethrough'), + '\\' => array('EscapeSequence'), + ); + + # ~ + + protected $inlineMarkerList = '!*_&[:<`~\\'; + + # + # ~ + # + + public function line($text, $nonNestables = array()) + { + return $this->elements($this->lineElements($text, $nonNestables)); + } + + protected function lineElements($text, $nonNestables = array()) + { + # standardize line breaks + $text = str_replace(array("\r\n", "\r"), "\n", $text); + + $Elements = array(); + + $nonNestables = (empty($nonNestables) + ? array() + : array_combine($nonNestables, $nonNestables) + ); + + # $excerpt is based on the first occurrence of a marker + + while ($excerpt = strpbrk($text, $this->inlineMarkerList)) + { + $marker = $excerpt[0]; + + $markerPosition = strlen($text) - strlen($excerpt); + + $Excerpt = array('text' => $excerpt, 'context' => $text); + + foreach ($this->InlineTypes[$marker] as $inlineType) + { + # check to see if the current inline type is nestable in the current context + + if (isset($nonNestables[$inlineType])) + { + continue; + } + + $Inline = $this->{"inline$inlineType"}($Excerpt); + + if ( ! isset($Inline)) + { + continue; + } + + # makes sure that the inline belongs to "our" marker + + if (isset($Inline['position']) and $Inline['position'] > $markerPosition) + { + continue; + } + + # sets a default inline position + + if ( ! isset($Inline['position'])) + { + $Inline['position'] = $markerPosition; + } + + # cause the new element to 'inherit' our non nestables + + + $Inline['element']['nonNestables'] = isset($Inline['element']['nonNestables']) + ? array_merge($Inline['element']['nonNestables'], $nonNestables) + : $nonNestables + ; + + # the text that comes before the inline + $unmarkedText = substr($text, 0, $Inline['position']); + + # compile the unmarked text + $InlineText = $this->inlineText($unmarkedText); + $Elements[] = $InlineText['element']; + + # compile the inline + $Elements[] = $this->extractElement($Inline); + + # remove the examined text + $text = substr($text, $Inline['position'] + $Inline['extent']); + + continue 2; + } + + # the marker does not belong to an inline + + $unmarkedText = substr($text, 0, $markerPosition + 1); + + $InlineText = $this->inlineText($unmarkedText); + $Elements[] = $InlineText['element']; + + $text = substr($text, $markerPosition + 1); + } + + $InlineText = $this->inlineText($text); + $Elements[] = $InlineText['element']; + + foreach ($Elements as &$Element) + { + if ( ! isset($Element['autobreak'])) + { + $Element['autobreak'] = false; + } + } + + return $Elements; + } + + # + # ~ + # + + protected function inlineText($text) + { + $Inline = array( + 'extent' => strlen($text), + 'element' => array(), + ); + + $Inline['element']['elements'] = self::pregReplaceElements( + $this->breaksEnabled ? '/[ ]*+\n/' : '/(?:[ ]*+\\\\|[ ]{2,}+)\n/', + array( + array('name' => 'br'), + array('text' => "\n"), + ), + $text + ); + + return $Inline; + } + + protected function inlineCode($Excerpt) + { + $marker = $Excerpt['text'][0]; + + if (preg_match('/^(['.$marker.']++)[ ]*+(.+?)[ ]*+(?<!['.$marker.'])\1(?!'.$marker.')/s', $Excerpt['text'], $matches)) + { + $text = $matches[2]; + $text = preg_replace('/[ ]*+\n/', ' ', $text); + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'code', + 'text' => $text, + ), + ); + } + } + + protected function inlineEmailTag($Excerpt) + { + $hostnameLabel = '[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?'; + + $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@' + . $hostnameLabel . '(?:\.' . $hostnameLabel . ')*'; + + if (strpos($Excerpt['text'], '>') !== false + and preg_match("/^<((mailto:)?$commonMarkEmail)>/i", $Excerpt['text'], $matches) + ){ + $url = $matches[1]; + + if ( ! isset($matches[2])) + { + $url = "mailto:$url"; + } + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'a', + 'text' => $matches[1], + 'attributes' => array( + 'href' => $url, + ), + ), + ); + } + } + + protected function inlineEmphasis($Excerpt) + { + if ( ! isset($Excerpt['text'][1])) + { + return; + } + + $marker = $Excerpt['text'][0]; + + if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) + { + $emphasis = 'strong'; + } + elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) + { + $emphasis = 'em'; + } + else + { + return; + } + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => $emphasis, + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $matches[1], + 'destination' => 'elements', + ) + ), + ); + } + + protected function inlineEscapeSequence($Excerpt) + { + if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) + { + return array( + 'element' => array('rawHtml' => $Excerpt['text'][1]), + 'extent' => 2, + ); + } + } + + protected function inlineImage($Excerpt) + { + if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') + { + return; + } + + $Excerpt['text']= substr($Excerpt['text'], 1); + + $Link = $this->inlineLink($Excerpt); + + if ($Link === null) + { + return; + } + + $Inline = array( + 'extent' => $Link['extent'] + 1, + 'element' => array( + 'name' => 'img', + 'attributes' => array( + 'src' => $Link['element']['attributes']['href'], + 'alt' => $Link['element']['handler']['argument'], + ), + 'autobreak' => true, + ), + ); + + $Inline['element']['attributes'] += $Link['element']['attributes']; + + unset($Inline['element']['attributes']['href']); + + return $Inline; + } + + protected function inlineLink($Excerpt) + { + $Element = array( + 'name' => 'a', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => null, + 'destination' => 'elements', + ), + 'nonNestables' => array('Url', 'Link'), + 'attributes' => array( + 'href' => null, + 'title' => null, + ), + ); + + $extent = 0; + + $remainder = $Excerpt['text']; + + if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches)) + { + $Element['handler']['argument'] = $matches[1]; + + $extent += strlen($matches[0]); + + $remainder = substr($remainder, $extent); + } + else + { + return; + } + + if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches)) + { + $Element['attributes']['href'] = $matches[1]; + + if (isset($matches[2])) + { + $Element['attributes']['title'] = substr($matches[2], 1, - 1); + } + + $extent += strlen($matches[0]); + } + else + { + if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) + { + $definition = strlen($matches[1]) ? $matches[1] : $Element['handler']['argument']; + $definition = strtolower($definition); + + $extent += strlen($matches[0]); + } + else + { + $definition = strtolower($Element['handler']['argument']); + } + + if ( ! isset($this->DefinitionData['Reference'][$definition])) + { + return; + } + + $Definition = $this->DefinitionData['Reference'][$definition]; + + $Element['attributes']['href'] = $Definition['url']; + $Element['attributes']['title'] = $Definition['title']; + } + + return array( + 'extent' => $extent, + 'element' => $Element, + ); + } + + protected function inlineMarkup($Excerpt) + { + if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false) + { + return; + } + + if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*+[ ]*+>/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + + if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?+[^-])*-->/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + + if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*+(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+\/?>/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + } + + protected function inlineSpecialCharacter($Excerpt) + { + if (substr($Excerpt['text'], 1, 1) !== ' ' and strpos($Excerpt['text'], ';') !== false + and preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches) + ) { + return array( + 'element' => array('rawHtml' => '&' . $matches[1] . ';'), + 'extent' => strlen($matches[0]), + ); + } + + return; + } + + protected function inlineStrikethrough($Excerpt) + { + if ( ! isset($Excerpt['text'][1])) + { + return; + } + + if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) + { + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'del', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $matches[1], + 'destination' => 'elements', + ) + ), + ); + } + } + + protected function inlineUrl($Excerpt) + { + if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') + { + return; + } + + if (strpos($Excerpt['context'], 'http') !== false + and preg_match('/\bhttps?+:[\/]{2}[^\s<]+\b\/*+/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE) + ) { + $url = $matches[0][0]; + + $Inline = array( + 'extent' => strlen($matches[0][0]), + 'position' => $matches[0][1], + 'element' => array( + 'name' => 'a', + 'text' => $url, + 'attributes' => array( + 'href' => $url, + ), + ), + ); + + return $Inline; + } + } + + protected function inlineUrlTag($Excerpt) + { + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w++:\/{2}[^ >]++)>/i', $Excerpt['text'], $matches)) + { + $url = $matches[1]; + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'a', + 'text' => $url, + 'attributes' => array( + 'href' => $url, + ), + ), + ); + } + } + + # ~ + + protected function unmarkedText($text) + { + $Inline = $this->inlineText($text); + return $this->element($Inline['element']); + } + + # + # Handlers + # + + protected function handle(array $Element) + { + if (isset($Element['handler'])) + { + if (!isset($Element['nonNestables'])) + { + $Element['nonNestables'] = array(); + } + + if (is_string($Element['handler'])) + { + $function = $Element['handler']; + $argument = $Element['text']; + unset($Element['text']); + $destination = 'rawHtml'; + } + else + { + $function = $Element['handler']['function']; + $argument = $Element['handler']['argument']; + $destination = $Element['handler']['destination']; + } + + $Element[$destination] = $this->{$function}($argument, $Element['nonNestables']); + + if ($destination === 'handler') + { + $Element = $this->handle($Element); + } + + unset($Element['handler']); + } + + return $Element; + } + + protected function handleElementRecursive(array $Element) + { + return $this->elementApplyRecursive(array($this, 'handle'), $Element); + } + + protected function handleElementsRecursive(array $Elements) + { + return $this->elementsApplyRecursive(array($this, 'handle'), $Elements); + } + + protected function elementApplyRecursive($closure, array $Element) + { + $Element = call_user_func($closure, $Element); + + if (isset($Element['elements'])) + { + $Element['elements'] = $this->elementsApplyRecursive($closure, $Element['elements']); + } + elseif (isset($Element['element'])) + { + $Element['element'] = $this->elementApplyRecursive($closure, $Element['element']); + } + + return $Element; + } + + protected function elementApplyRecursiveDepthFirst($closure, array $Element) + { + if (isset($Element['elements'])) + { + $Element['elements'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['elements']); + } + elseif (isset($Element['element'])) + { + $Element['element'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['element']); + } + + $Element = call_user_func($closure, $Element); + + return $Element; + } + + protected function elementsApplyRecursive($closure, array $Elements) + { + foreach ($Elements as &$Element) + { + $Element = $this->elementApplyRecursive($closure, $Element); + } + + return $Elements; + } + + protected function elementsApplyRecursiveDepthFirst($closure, array $Elements) + { + foreach ($Elements as &$Element) + { + $Element = $this->elementApplyRecursiveDepthFirst($closure, $Element); + } + + return $Elements; + } + + protected function element(array $Element) + { + if ($this->safeMode) + { + $Element = $this->sanitiseElement($Element); + } + + # identity map if element has no handler + $Element = $this->handle($Element); + + $hasName = isset($Element['name']); + + $markup = ''; + + if ($hasName) + { + $markup .= '<' . $Element['name']; + + if (isset($Element['attributes'])) + { + foreach ($Element['attributes'] as $name => $value) + { + if ($value === null) + { + continue; + } + + $markup .= " $name=\"".self::escape($value).'"'; + } + } + } + + $permitRawHtml = false; + + if (isset($Element['text'])) + { + $text = $Element['text']; + } + // very strongly consider an alternative if you're writing an + // extension + elseif (isset($Element['rawHtml'])) + { + $text = $Element['rawHtml']; + + $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode']; + $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode; + } + + $hasContent = isset($text) || isset($Element['element']) || isset($Element['elements']); + + if ($hasContent) + { + $markup .= $hasName ? '>' : ''; + + if (isset($Element['elements'])) + { + $markup .= $this->elements($Element['elements']); + } + elseif (isset($Element['element'])) + { + $markup .= $this->element($Element['element']); + } + else + { + if (!$permitRawHtml) + { + $markup .= self::escape($text, true); + } + else + { + $markup .= $text; + } + } + + $markup .= $hasName ? '</' . $Element['name'] . '>' : ''; + } + elseif ($hasName) + { + $markup .= ' />'; + } + + return $markup; + } + + protected function elements(array $Elements) + { + $markup = ''; + + $autoBreak = true; + + foreach ($Elements as $Element) + { + if (empty($Element)) + { + continue; + } + + $autoBreakNext = (isset($Element['autobreak']) + ? $Element['autobreak'] : isset($Element['name']) + ); + // (autobreak === false) covers both sides of an element + $autoBreak = !$autoBreak ? $autoBreak : $autoBreakNext; + + $markup .= ($autoBreak ? "\n" : '') . $this->element($Element); + $autoBreak = $autoBreakNext; + } + + $markup .= $autoBreak ? "\n" : ''; + + return $markup; + } + + # ~ + + protected function li($lines) + { + $Elements = $this->linesElements($lines); + + if ( ! in_array('', $lines) + and isset($Elements[0]) and isset($Elements[0]['name']) + and $Elements[0]['name'] === 'p' + ) { + unset($Elements[0]['name']); + } + + return $Elements; + } + + # + # AST Convenience + # + + /** + * Replace occurrences $regexp with $Elements in $text. Return an array of + * elements representing the replacement. + */ + protected static function pregReplaceElements($regexp, $Elements, $text) + { + $newElements = array(); + + while (preg_match($regexp, $text, $matches, PREG_OFFSET_CAPTURE)) + { + $offset = $matches[0][1]; + $before = substr($text, 0, $offset); + $after = substr($text, $offset + strlen($matches[0][0])); + + $newElements[] = array('text' => $before); + + foreach ($Elements as $Element) + { + $newElements[] = $Element; + } + + $text = $after; + } + + $newElements[] = array('text' => $text); + + return $newElements; + } + + # + # Deprecated Methods + # + + function parse($text) + { + $markup = $this->text($text); + + return $markup; + } + + protected function sanitiseElement(array $Element) + { + static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/'; + static $safeUrlNameToAtt = array( + 'a' => 'href', + 'img' => 'src', + ); + + if ( ! isset($Element['name'])) + { + unset($Element['attributes']); + return $Element; + } + + if (isset($safeUrlNameToAtt[$Element['name']])) + { + $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]); + } + + if ( ! empty($Element['attributes'])) + { + foreach ($Element['attributes'] as $att => $val) + { + # filter out badly parsed attribute + if ( ! preg_match($goodAttribute, $att)) + { + unset($Element['attributes'][$att]); + } + # dump onevent attribute + elseif (self::striAtStart($att, 'on')) + { + unset($Element['attributes'][$att]); + } + } + } + + return $Element; + } + + protected function filterUnsafeUrlInAttribute(array $Element, $attribute) + { + foreach ($this->safeLinksWhitelist as $scheme) + { + if (self::striAtStart($Element['attributes'][$attribute], $scheme)) + { + return $Element; + } + } + + $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]); + + return $Element; + } + + # + # Static Methods + # + + protected static function escape($text, $allowQuotes = false) + { + return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8'); + } + + protected static function striAtStart($string, $needle) + { + $len = strlen($needle); + + if ($len > strlen($string)) + { + return false; + } + else + { + return strtolower(substr($string, 0, $len)) === strtolower($needle); + } + } + + static function instance($name = 'default') + { + if (isset(self::$instances[$name])) + { + return self::$instances[$name]; + } + + $instance = new static(); + + self::$instances[$name] = $instance; + + return $instance; + } + + private static $instances = array(); + + # + # Fields + # + + protected $DefinitionData; + + # + # Read-Only + + protected $specialCharacters = array( + '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', '~' + ); + + protected $StrongRegex = array( + '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*+[*])+?)[*]{2}(?![*])/s', + '_' => '/^__((?:\\\\_|[^_]|_[^_]*+_)+?)__(?!_)/us', + ); + + protected $EmRegex = array( + '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', + '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us', + ); + + protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+'; + + protected $voidElements = array( + 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', + ); + + protected $textLevelElements = array( + 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', + 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', + 'i', 'rp', 'del', 'code', 'strike', 'marquee', + 'q', 'rt', 'ins', 'font', 'strong', + 's', 'tt', 'kbd', 'mark', + 'u', 'xm', 'sub', 'nobr', + 'sup', 'ruby', + 'var', 'span', + 'wbr', 'time', + ); +} diff --git a/includes/projects/home.php b/includes/projects/home.php index 2f11b33..fdb1cb4 100644 --- a/includes/projects/home.php +++ b/includes/projects/home.php @@ -1,5 +1,5 @@ -<div class="list-group"> - <a href="/creations/kartik" class="list-group-item list-group-item-action"><img src="<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/kartik/icon.txt")) ?>" alt="" width="24px"> Kartik <span class="badge bg-secondary rounded-pill"><?= l("Development", "Programmation") ?></span></a> - <a href="/creations/neutron" class="list-group-item list-group-item-action"><img src="<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/neutron/icon.txt")) ?>" alt="" width="24px"> Neutron <span class="badge bg-secondary rounded-pill"><?= l("Development", "Programmation") ?></span></a> - <a href="/creations/gyrate-with-obliqueness" class="list-group-item list-group-item-action"><img src="/static/genericProjectIcon.png" alt="" width="24px"> Gyrate with Obliqueness <span class="badge bg-secondary rounded-pill"><?= l("Multimedia", "Multimédia") ?></span></a> +<div class="list-group">
+ <a href="/creations/kartik" class="list-group-item list-group-item-action"><img src="<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/kartik/icon.txt")) ?>" alt="" width="24px"> Kartik <span class="badge bg-secondary rounded-pill"><?= l("Development", "Programmation") ?></span></a>
+ <a href="/creations/neutron" class="list-group-item list-group-item-action"><img src="<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/neutron/icon.txt")) ?>" alt="" width="24px"> Neutron <span class="badge bg-secondary rounded-pill"><?= l("Development", "Programmation") ?></span></a>
+ <a href="/creations/gyrate-with-obliqueness" class="list-group-item list-group-item-action"><img src="/static/genericProjectIcon.png" alt="" width="24px"> Gyrate with Obliqueness <span class="badge bg-secondary rounded-pill"><?= l("Multimedia", "Multimédia") ?></span></a>
</div>
\ No newline at end of file diff --git a/includes/projects/list.php b/includes/projects/list.php index 136cf56..ef6cb2e 100644 --- a/includes/projects/list.php +++ b/includes/projects/list.php @@ -1,13 +1,13 @@ -<div class="list-group"> - <?php - - $articles = scandir($_SERVER['DOCUMENT_ROOT'] . "/creations"); - $i = 1; - foreach ($articles as $article): - - ?> - <?php if (trim($article) !== "." && trim($article) !== ".." && trim($article) !== "dev" && trim($article) !== "video" && is_dir($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article)): ?> - <a href="/creations/<?= $article ?>" class="list-group-item list-group-item-action"><img src="<?= trim(file_exists($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/icon.txt") ? file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/icon.txt") : "/static/genericProjectIcon.png") ?>" width="24px" alt=""> <?= file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/title.txt") ?><span class="text-muted"> · <?= l(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/description.txt"), file_exists($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/description.fr.txt") ? file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/description.fr.txt") : file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/description.txt")) ?></span></a> - <?php endif;$i++; ?> - <?php endforeach; ?> +<div class="list-group">
+ <?php
+
+ $articles = scandir($_SERVER['DOCUMENT_ROOT'] . "/creations");
+ $i = 1;
+ foreach ($articles as $article):
+
+ ?>
+ <?php if (trim($article) !== "." && trim($article) !== ".." && trim($article) !== "dev" && trim($article) !== "video" && is_dir($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article)): ?>
+ <a href="/creations/<?= $article ?>" class="list-group-item list-group-item-action"><img src="<?= trim(file_exists($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/icon.txt") ? file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/icon.txt") : "/static/genericProjectIcon.png") ?>" width="24px" alt=""> <?= file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/title.txt") ?><span class="text-muted"> · <?= l(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/description.txt"), file_exists($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/description.fr.txt") ? file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/description.fr.txt") : file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/" . $article . "/description.txt")) ?></span></a>
+ <?php endif;$i++; ?>
+ <?php endforeach; ?>
</div>
\ No newline at end of file diff --git a/includes/stats/apis.php b/includes/stats/apis.php index 5e8d05b..060ba18 100644 --- a/includes/stats/apis.php +++ b/includes/stats/apis.php @@ -1,23 +1,23 @@ -<?php - -class API { - private $keys; - - public function __construct() { - $this->keys = json_decode(file_get_contents("./credentials.json"), true); - } - - public function GitHub(string $path) { - exec("curl -A \"Minteck-Space/0.0.0 (nekostarfan@gmail.com)\" -H \"Authorization: token " . $this->keys["github"] . "\" https://api.github.com/" . $path, $op); - $result = implode("\n", $op); - - return $result; - } - - public function Reddit(string $path) { - exec("curl -A \"Minteck-Space/0.0.0 (nekostarfan@gmail.com)\" https://www.reddit.com/" . $path . ".json", $op); - $result = implode("\n", $op); - - return $result; - } -} +<?php
+
+class API {
+ private $keys;
+
+ public function __construct() {
+ $this->keys = json_decode(file_get_contents("./credentials.json"), true);
+ }
+
+ public function GitHub(string $path) {
+ exec("curl -A \"Minteck-Space/0.0.0 (nekostarfan@gmail.com)\" -H \"Authorization: token " . $this->keys["github"] . "\" https://api.github.com/" . $path, $op);
+ $result = implode("\n", $op);
+
+ return $result;
+ }
+
+ public function Reddit(string $path) {
+ exec("curl -A \"Minteck-Space/0.0.0 (nekostarfan@gmail.com)\" https://www.reddit.com/" . $path . ".json", $op);
+ $result = implode("\n", $op);
+
+ return $result;
+ }
+}
diff --git a/includes/stats/neutron.json b/includes/stats/neutron.json index 875bbef..32ee47d 100644 --- a/includes/stats/neutron.json +++ b/includes/stats/neutron.json @@ -1,5 +1,44 @@ [ { + "url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/releases\/46937809", + "assets_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/releases\/46937809\/assets", + "upload_url": "https:\/\/uploads.github.com\/repos\/Minteck-Projects\/Neutron-Core\/releases\/46937809\/assets{?name,label}", + "html_url": "https:\/\/github.com\/Minteck-Projects\/Neutron-Core\/releases\/tag\/10.0.217.50", + "id": 46937809, + "author": { + "login": "Minteck", + "id": 46352972, + "node_id": "MDQ6VXNlcjQ2MzUyOTcy", + "avatar_url": "https:\/\/avatars.githubusercontent.com\/u\/46352972?v=4", + "gravatar_id": "", + "url": "https:\/\/api.github.com\/users\/Minteck", + "html_url": "https:\/\/github.com\/Minteck", + "followers_url": "https:\/\/api.github.com\/users\/Minteck\/followers", + "following_url": "https:\/\/api.github.com\/users\/Minteck\/following{\/other_user}", + "gists_url": "https:\/\/api.github.com\/users\/Minteck\/gists{\/gist_id}", + "starred_url": "https:\/\/api.github.com\/users\/Minteck\/starred{\/owner}{\/repo}", + "subscriptions_url": "https:\/\/api.github.com\/users\/Minteck\/subscriptions", + "organizations_url": "https:\/\/api.github.com\/users\/Minteck\/orgs", + "repos_url": "https:\/\/api.github.com\/users\/Minteck\/repos", + "events_url": "https:\/\/api.github.com\/users\/Minteck\/events{\/privacy}", + "received_events_url": "https:\/\/api.github.com\/users\/Minteck\/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "MDc6UmVsZWFzZTQ2OTM3ODA5", + "tag_name": "10.0.217.50", + "target_commitish": "trunk", + "name": "Neutron 10 Release Candidate 1", + "draft": false, + "prerelease": true, + "created_at": "2021-07-26T02:07:52Z", + "published_at": "2021-07-28T22:23:03Z", + "assets": [], + "tarball_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/tarball\/10.0.217.50", + "zipball_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/zipball\/10.0.217.50", + "body": "" + }, + { "url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/releases\/46737727", "assets_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/releases\/46737727\/assets", "upload_url": "https:\/\/uploads.github.com\/repos\/Minteck-Projects\/Neutron-Core\/releases\/46737727\/assets{?name,label}", diff --git a/includes/stats/neutron2.json b/includes/stats/neutron2.json index b953c0c..373d655 100644 --- a/includes/stats/neutron2.json +++ b/includes/stats/neutron2.json @@ -1,5 +1,15 @@ [ { + "name": "10.0.217.50", + "zipball_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/zipball\/refs\/tags\/10.0.217.50", + "tarball_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/tarball\/refs\/tags\/10.0.217.50", + "commit": { + "sha": "f5f4ac7aa73d86335766ed4a09e4ba71d9edee45", + "url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/commits\/f5f4ac7aa73d86335766ed4a09e4ba71d9edee45" + }, + "node_id": "MDM6UmVmMzM1NzU4MDQ4OnJlZnMvdGFncy8xMC4wLjIxNy41MA==" + }, + { "name": "10.0.205.49", "zipball_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/zipball\/refs\/tags\/10.0.205.49", "tarball_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/tarball\/refs\/tags\/10.0.205.49", @@ -288,15 +298,5 @@ "url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/commits\/2bf3a0bdc8a56f033f2622108e5dea815f11a0d3" }, "node_id": "MDM6UmVmMzM1NzU4MDQ4OnJlZnMvdGFncy8yLjAuMQ==" - }, - { - "name": "2.0", - "zipball_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/zipball\/refs\/tags\/2.0", - "tarball_url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/tarball\/refs\/tags\/2.0", - "commit": { - "sha": "45585c983312edd77adefc4cb1bbafd817870ef6", - "url": "https:\/\/api.github.com\/repos\/Minteck-Projects\/Neutron-Core\/commits\/45585c983312edd77adefc4cb1bbafd817870ef6" - }, - "node_id": "MDM6UmVmMzM1NzU4MDQ4OnJlZnMvdGFncy8yLjA=" } ]
\ No newline at end of file diff --git a/includes/stats/refresh.php b/includes/stats/refresh.php index 4ff5487..531a057 100644 --- a/includes/stats/refresh.php +++ b/includes/stats/refresh.php @@ -1,52 +1,52 @@ -<?php - -require_once "./apis.php"; -$api = new API(); -$data = [ - "github" => [] -]; - -// ------------------------------------ -// GitHub - -$events = json_decode($api->GitHub("users/Minteck/events"), true); -$last = null; - -foreach ($events as $event) { - if ($event["type"] === "PushEvent") { - $last = $event; - break; - } -} - -$data["github"]["project"] = $last["repo"]["name"]; -$data["github"]["sha"] = substr($last["payload"]["commits"][0]["sha"], 0, 7); -$data["github"]["message"] = $last["payload"]["commits"][0]["message"]; - -// ------------------------------------ -// Reddit -$posts = json_decode($api->Reddit("user/Minteck"), true)["data"]["children"]; -$last = null; - -foreach ($posts as $post) { - if (!$post["pinned"]) { - $last = $post["data"]; - break; - } -} - -$data["reddit"]["sub"] = $last["subreddit"]; -$data["reddit"]["title"] = $last["title"]; -$data["reddit"]["score"] = $last["score"]; - -// ------------------------------------ -// Neutron Releases -$neutron = json_decode($api->GitHub("repos/Minteck-Projects/Neutron-Core/releases"), true); -file_put_contents("./neutron.json", json_encode($neutron, JSON_PRETTY_PRINT)); -$neutron = json_decode($api->GitHub("repos/Minteck-Projects/Neutron-Core/tags"), true); -file_put_contents("./neutron2.json", json_encode($neutron, JSON_PRETTY_PRINT)); - -// ------------------------------------ -// Dump - -file_put_contents("./stats.json", json_encode($data, JSON_PRETTY_PRINT)); +<?php
+
+require_once "./apis.php";
+$api = new API();
+$data = [
+ "github" => []
+];
+
+// ------------------------------------
+// GitHub
+
+$events = json_decode($api->GitHub("users/Minteck/events"), true);
+$last = null;
+
+foreach ($events as $event) {
+ if ($event["type"] === "PushEvent") {
+ $last = $event;
+ break;
+ }
+}
+
+$data["github"]["project"] = $last["repo"]["name"];
+$data["github"]["sha"] = substr($last["payload"]["commits"][0]["sha"], 0, 7);
+$data["github"]["message"] = $last["payload"]["commits"][0]["message"];
+
+// ------------------------------------
+// Reddit
+$posts = json_decode($api->Reddit("user/Minteck"), true)["data"]["children"];
+$last = null;
+
+foreach ($posts as $post) {
+ if (!$post["pinned"]) {
+ $last = $post["data"];
+ break;
+ }
+}
+
+$data["reddit"]["sub"] = $last["subreddit"];
+$data["reddit"]["title"] = $last["title"];
+$data["reddit"]["score"] = $last["score"];
+
+// ------------------------------------
+// Neutron Releases
+$neutron = json_decode($api->GitHub("repos/Minteck/Neutron/releases"), true);
+file_put_contents("./neutron.json", json_encode($neutron, JSON_PRETTY_PRINT));
+$neutron = json_decode($api->GitHub("repos/Minteck/Neutron/tags"), true);
+file_put_contents("./neutron2.json", json_encode($neutron, JSON_PRETTY_PRINT));
+
+// ------------------------------------
+// Dump
+
+file_put_contents("./stats.json", json_encode($data, JSON_PRETTY_PRINT));
diff --git a/includes/stats/stats.json b/includes/stats/stats.json index 15e6d1b..a8aab2d 100644 --- a/includes/stats/stats.json +++ b/includes/stats/stats.json @@ -1,12 +1,12 @@ { "github": { - "project": "Minteck\/UnchainedTech-Content", - "sha": "8703ba3", - "message": "Update how-was-windows-2000-made.md" + "project": "Minteck\/Website", + "sha": "87303b0", + "message": "SVN Confirmed!" }, "reddit": { "sub": "unixporn", "title": "[tty] Nintendo 3DS", - "score": 2274 + "score": 2285 } }
\ No newline at end of file diff --git a/includes/telemetry.php b/includes/telemetry.php new file mode 100644 index 0000000..3988679 --- /dev/null +++ b/includes/telemetry.php @@ -0,0 +1,30 @@ +<?php + +$db = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/telemetry.json"), true); + +$ip = md5($_SERVER['REMOTE_ADDR']); +$day = date('d'); +$month = date('m'); +$year = date('y'); +$url = "space:" .explode("?", $_SERVER['REQUEST_URI'])[0]; + +if (!isset($db[$year]) && $_SERVER['PHP_SELF'] !== "/404.php") { + $db[$year] = []; +} +if (!isset($db[$year][$month]) && $_SERVER['PHP_SELF'] !== "/404.php") { + $db[$year][$month] = []; +} +if (!isset($db[$year][$month][$day]) && $_SERVER['PHP_SELF'] !== "/404.php") { + $db[$year][$month][$day] = []; +} +if (!isset($db[$year][$month][$day][$url]) && $_SERVER['PHP_SELF'] !== "/404.php") { + $db[$year][$month][$day][$url] = []; +} + +if (!in_array($ip, $db[$year][$month][$day][$url]) && $_SERVER['PHP_SELF'] !== "/404.php") { + array_push($db[$year][$month][$day][$url], $ip); +} + +if (trim(json_encode($db, JSON_PRETTY_PRINT)) !== "null") { + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/telemetry.json", json_encode($db, JSON_PRETTY_PRINT)); +}
\ No newline at end of file diff --git a/includes/tinyfilemanager.php b/includes/tinyfilemanager.php new file mode 100644 index 0000000..24821b1 --- /dev/null +++ b/includes/tinyfilemanager.php @@ -0,0 +1,4091 @@ +<?php +//Default Configuration +$CONFIG = '{"lang":"en","error_reporting":false,"show_hidden":false,"hide_Cols":false,"calc_folder":false,"theme":"light"}'; + +/** + * H3K | Tiny File Manager V2.4.6 + * CCP Programmers | ccpprogrammers@gmail.com + * https://tinyfilemanager.github.io + */ + +//TFM version +define('VERSION', '2.4.6'); + +//Application Title +define('APP_TITLE', 'Tiny File Manager'); + +// --- EDIT BELOW CONFIGURATION CAREFULLY --- + +// Auth with login/password +// set true/false to enable/disable it +// Is independent from IP white- and blacklisting +$use_auth = false; + +// Login user name and password +// Users: array('Username' => 'Password', 'Username2' => 'Password2', ...) +// Generate secure password hash - https://tinyfilemanager.github.io/docs/pwd.html +$auth_users = array( + 'admin' => '$2y$10$/K.hjNr84lLNDt8fTXjoI.DBp6PpeyoJ.mGwrrLuCZfAwfSAGqhOW', //admin@123 + 'user' => '$2y$10$Fg6Dz8oH9fPoZ2jJan5tZuv6Z4Kp7avtQ9bDfrdRntXtPeiMAZyGO' //12345 +); + +// Readonly users +// e.g. array('users', 'guest', ...) +$readonly_users = array( + 'user' +); + +// Enable highlight.js (https://highlightjs.org/) on view's page +$use_highlightjs = true; + +// highlight.js style +// for dark theme use 'ir-black' +$highlightjs_style = 'ir-black'; + +// Enable ace.js (https://ace.c9.io/) on view's page +$edit_files = true; + +// Default timezone for date() and time() +// Doc - http://php.net/manual/en/timezones.php +$default_timezone = 'Europe/Paris'; // UTC + +// Root path for file manager +// use absolute path of directory i.e: '/var/www/folder' or $_SERVER['DOCUMENT_ROOT'].'/folder' +$root_path = $_SERVER['DOCUMENT_ROOT']; + +// Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder' +// Will not working if $root_path will be outside of server document root +$root_url = ''; + +// Server hostname. Can set manually if wrong +$http_host = $_SERVER['HTTP_HOST']; + +// user specific directories +// array('Username' => 'Directory path', 'Username2' => 'Directory path', ...) +$directories_users = array(); + +// input encoding for iconv +$iconv_input_encoding = 'UTF-8'; + +// date() format for file modification date +// Doc - https://www.php.net/manual/en/function.date.php +$datetime_format = 'd/m/y H:i'; + +// Allowed file extensions for create and rename files +// e.g. 'txt,html,css,js' +$allowed_file_extensions = ''; + +// Allowed file extensions for upload files +// e.g. 'gif,png,jpg,html,txt' +$allowed_upload_extensions = ''; + +// Favicon path. This can be either a full url to an .PNG image, or a path based on the document root. +// full path, e.g http://example.com/favicon.png +// local path, e.g images/icons/favicon.png +$favicon_path = ''; + +// Files and folders to excluded from listing +// e.g. array('myfile.html', 'personal-folder', '*.php', ...) +$exclude_items = array(); + +// Online office Docs Viewer +// Availabe rules are 'google', 'microsoft' or false +// google => View documents using Google Docs Viewer +// microsoft => View documents using Microsoft Web Apps Viewer +// false => disable online doc viewer +$online_viewer = 'false'; + +// Sticky Nav bar +// true => enable sticky header +// false => disable sticky header +$sticky_navbar = true; + +// Maximum file upload size +// Increase the following values in php.ini to work properly +// memory_limit, upload_max_filesize, post_max_size +$max_upload_size_bytes = 5000; + +// Possible rules are 'OFF', 'AND' or 'OR' +// OFF => Don't check connection IP, defaults to OFF +// AND => Connection must be on the whitelist, and not on the blacklist +// OR => Connection must be on the whitelist, or not on the blacklist +$ip_ruleset = 'OFF'; + +// Should users be notified of their block? +$ip_silent = true; + +// IP-addresses, both ipv4 and ipv6 +$ip_whitelist = array( + '127.0.0.1', // local ipv4 + '::1' // local ipv6 +); + +// IP-addresses, both ipv4 and ipv6 +$ip_blacklist = array( + '0.0.0.0', // non-routable meta ipv4 + '::' // non-routable meta ipv6 +); + +// if User has the customized config file, try to use it to override the default config above +$config_file = __DIR__.'/config.php'; +if (is_readable($config_file)) { + @include($config_file); +} + +// --- EDIT BELOW CAREFULLY OR DO NOT EDIT AT ALL --- + +// max upload file size +define('MAX_UPLOAD_SIZE', $max_upload_size_bytes); + +// private key and session name to store to the session +if ( !defined( 'FM_SESSION_ID')) { + define('FM_SESSION_ID', 'filemanager'); +} + +// Configuration +$cfg = new FM_Config(); + +// Default language +$lang = isset($cfg->data['lang']) ? $cfg->data['lang'] : 'en'; + +// Show or hide files and folders that starts with a dot +$show_hidden_files = isset($cfg->data['show_hidden']) ? $cfg->data['show_hidden'] : true; + +// PHP error reporting - false = Turns off Errors, true = Turns on Errors +$report_errors = isset($cfg->data['error_reporting']) ? $cfg->data['error_reporting'] : true; + +// Hide Permissions and Owner cols in file-listing +$hide_Cols = isset($cfg->data['hide_Cols']) ? $cfg->data['hide_Cols'] : true; + +// Show directory size: true or speedup output: false +$calc_folder = isset($cfg->data['calc_folder']) ? $cfg->data['calc_folder'] : true; + +// Theme +$theme = isset($cfg->data['theme']) ? $cfg->data['theme'] : 'dark'; + +define('FM_THEME', $theme); + +//available languages +$lang_list = array( + 'en' => 'English' +); + +if ($report_errors == true) { + @ini_set('error_reporting', E_ALL); + @ini_set('display_errors', 1); +} else { + @ini_set('error_reporting', E_ALL); + @ini_set('display_errors', 0); +} + +// if fm included +if (defined('FM_EMBED')) { + $use_auth = false; + $sticky_navbar = false; +} else { + @set_time_limit(600); + + date_default_timezone_set($default_timezone); + + ini_set('default_charset', 'UTF-8'); + if (version_compare(PHP_VERSION, '5.6.0', '<') && function_exists('mb_internal_encoding')) { + mb_internal_encoding('UTF-8'); + } + if (function_exists('mb_regex_encoding')) { + mb_regex_encoding('UTF-8'); + } + + session_cache_limiter(''); + session_name(FM_SESSION_ID ); + function session_error_handling_function($code, $msg, $file, $line) { + // Permission denied for default session, try to create a new one + if ($code == 2) { + session_abort(); + session_id(session_create_id()); + @session_start(); + } + } + set_error_handler('session_error_handling_function'); + session_start(); + restore_error_handler(); +} + +if (empty($auth_users)) { + $use_auth = false; +} + +$is_https = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) + || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'; + +// update $root_url based on user specific directories +if (isset($_SESSION[FM_SESSION_ID]['logged']) && !empty($directories_users[$_SESSION[FM_SESSION_ID]['logged']])) { + $wd = fm_clean_path(dirname($_SERVER['PHP_SELF'])); + $root_url = $root_url.$wd.DIRECTORY_SEPARATOR.$directories_users[$_SESSION[FM_SESSION_ID]['logged']]; +} +// clean $root_url +$root_url = fm_clean_path($root_url); + +// abs path for site +defined('FM_ROOT_URL') || define('FM_ROOT_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . (!empty($root_url) ? '/' . $root_url : '')); +defined('FM_SELF_URL') || define('FM_SELF_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . $_SERVER['PHP_SELF']); + +// logout +if (isset($_GET['logout'])) { + unset($_SESSION[FM_SESSION_ID]['logged']); + fm_redirect(FM_SELF_URL); +} + +// Validate connection IP +if($ip_ruleset != 'OFF'){ + $clientIp = $_SERVER['REMOTE_ADDR']; + + $proceed = false; + + $whitelisted = in_array($clientIp, $ip_whitelist); + $blacklisted = in_array($clientIp, $ip_blacklist); + + if($ip_ruleset == 'AND'){ + if($whitelisted == true && $blacklisted == false){ + $proceed = true; + } + } else + if($ip_ruleset == 'OR'){ + if($whitelisted == true || $blacklisted == false){ + $proceed = true; + } + } + + if($proceed == false){ + trigger_error('User connection denied from: ' . $clientIp, E_USER_WARNING); + + if($ip_silent == false){ + fm_set_msg(lng('Access denied. IP restriction applicable'), 'error'); + fm_show_header_login(); + fm_show_message(); + } + + exit(); + } +} + +// Auth +if ($use_auth) { + if (isset($_SESSION[FM_SESSION_ID]['logged'], $auth_users[$_SESSION[FM_SESSION_ID]['logged']])) { + // Logged + } elseif (isset($_POST['fm_usr'], $_POST['fm_pwd'])) { + // Logging In + sleep(1); + if(function_exists('password_verify')) { + if (isset($auth_users[$_POST['fm_usr']]) && isset($_POST['fm_pwd']) && password_verify($_POST['fm_pwd'], $auth_users[$_POST['fm_usr']])) { + $_SESSION[FM_SESSION_ID]['logged'] = $_POST['fm_usr']; + fm_set_msg(lng('You are logged in')); + fm_redirect(FM_SELF_URL . '?p='); + } else { + unset($_SESSION[FM_SESSION_ID]['logged']); + fm_set_msg(lng('Login failed. Invalid username or password'), 'error'); + fm_redirect(FM_SELF_URL); + } + } else { + fm_set_msg(lng('password_hash not supported, Upgrade PHP version'), 'error');; + } + } else { + // Form + unset($_SESSION[FM_SESSION_ID]['logged']); + fm_show_header_login(); + ?> + <section class="h-100"> + <div class="container h-100"> + <div class="row justify-content-md-center h-100"> + <div class="card-wrapper"> + <div class="card fat <?php echo fm_get_theme(); ?>"> + <div class="card-body"> + <form class="form-signin" action="" method="post" autocomplete="off"> + <div class="form-group"> + <div class="brand"> + <svg version="1.0" xmlns="http://www.w3.org/2000/svg" M1008 width="100%" height="80px" viewBox="0 0 238.000000 140.000000" aria-label="H3K Tiny File Manager"> + <g transform="translate(0.000000,140.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none"> + <path d="M160 700 l0 -600 110 0 110 0 0 260 0 260 70 0 70 0 0 -260 0 -260 110 0 110 0 0 600 0 600 -110 0 -110 0 0 -260 0 -260 -70 0 -70 0 0 260 0 260 -110 0 -110 0 0 -600z"/> + <path fill="#003500" d="M1008 1227 l-108 -72 0 -117 0 -118 110 0 110 0 0 110 0 110 70 0 70 0 0 -180 0 -180 -125 0 c-69 0 -125 -3 -125 -6 0 -3 23 -39 52 -80 l52 -74 73 0 73 0 0 -185 0 -185 -70 0 -70 0 0 115 0 115 -110 0 -110 0 0 -190 0 -190 181 0 181 0 109 73 108 72 1 181 0 181 -69 48 -68 49 68 50 69 49 0 249 0 248 -182 -1 -183 0 -107 -72z"/> + <path d="M1640 700 l0 -600 110 0 110 0 0 208 0 208 35 34 35 34 35 -34 35 -34 0 -208 0 -208 110 0 110 0 0 212 0 213 -87 87 -88 88 88 88 87 87 0 213 0 212 -110 0 -110 0 0 -208 0 -208 -70 -69 -70 -69 0 277 0 277 -110 0 -110 0 0 -600z"/></g> + </svg> + </div> + <div class="text-center"> + <h1 class="card-title"><?php echo APP_TITLE; ?></h1> + </div> + </div> + <hr /> + <div class="form-group"> + <label for="fm_usr"><?php echo lng('Username'); ?></label> + <input type="text" class="form-control" id="fm_usr" name="fm_usr" required autofocus> + </div> + + <div class="form-group"> + <label for="fm_pwd"><?php echo lng('Password'); ?></label> + <input type="password" class="form-control" id="fm_pwd" name="fm_pwd" required> + </div> + + <div class="form-group"> + <?php fm_show_message(); ?> + </div> + + <div class="form-group"> + <button type="submit" class="btn btn-success btn-block mt-4" role="button"> + <?php echo lng('Login'); ?> + </button> + </div> + </form> + </div> + </div> + <div class="footer text-center"> + —— © + <a href="https://tinyfilemanager.github.io/" target="_blank" class="text-muted" data-version="<?php echo VERSION; ?>">CCP Programmers</a> —— + </div> + </div> + </div> + </div> + </section> + + <?php + fm_show_footer_login(); + exit; + } +} + +// update root path +if ($use_auth && isset($_SESSION[FM_SESSION_ID]['logged'])) { + $root_path = isset($directories_users[$_SESSION[FM_SESSION_ID]['logged']]) ? $directories_users[$_SESSION[FM_SESSION_ID]['logged']] : $root_path; +} + +// clean and check $root_path +$root_path = rtrim($root_path, '\\/'); +$root_path = str_replace('\\', '/', $root_path); +if (!@is_dir($root_path)) { + echo "<h1>".lng('Root path')." \"{$root_path}\" ".lng('not found!')." </h1>"; + exit; +} + +defined('FM_SHOW_HIDDEN') || define('FM_SHOW_HIDDEN', $show_hidden_files); +defined('FM_ROOT_PATH') || define('FM_ROOT_PATH', $root_path); +defined('FM_LANG') || define('FM_LANG', $lang); +defined('FM_FILE_EXTENSION') || define('FM_FILE_EXTENSION', $allowed_file_extensions); +defined('FM_UPLOAD_EXTENSION') || define('FM_UPLOAD_EXTENSION', $allowed_upload_extensions); +defined('FM_EXCLUDE_ITEMS') || define('FM_EXCLUDE_ITEMS', (version_compare(PHP_VERSION, '7.0.0', '<') ? serialize($exclude_items) : $exclude_items)); +defined('FM_DOC_VIEWER') || define('FM_DOC_VIEWER', $online_viewer); +define('FM_READONLY', $use_auth && !empty($readonly_users) && isset($_SESSION[FM_SESSION_ID]['logged']) && in_array($_SESSION[FM_SESSION_ID]['logged'], $readonly_users)); +define('FM_IS_WIN', DIRECTORY_SEPARATOR == '\\'); + +// always use ?p= +if (!isset($_GET['p']) && empty($_FILES)) { + fm_redirect(FM_SELF_URL . '?p='); +} + +// get path +$p = isset($_GET['p']) ? $_GET['p'] : (isset($_POST['p']) ? $_POST['p'] : ''); + +// clean path +$p = fm_clean_path($p); + +// for ajax request - save +$input = file_get_contents('php://input'); +$_POST = (strpos($input, 'ajax') != FALSE && strpos($input, 'save') != FALSE) ? json_decode($input, true) : $_POST; + +// instead globals vars +define('FM_PATH', $p); +define('FM_USE_AUTH', $use_auth); +define('FM_EDIT_FILE', $edit_files); +defined('FM_ICONV_INPUT_ENC') || define('FM_ICONV_INPUT_ENC', $iconv_input_encoding); +defined('FM_USE_HIGHLIGHTJS') || define('FM_USE_HIGHLIGHTJS', $use_highlightjs); +defined('FM_HIGHLIGHTJS_STYLE') || define('FM_HIGHLIGHTJS_STYLE', $highlightjs_style); +defined('FM_DATETIME_FORMAT') || define('FM_DATETIME_FORMAT', $datetime_format); + +unset($p, $use_auth, $iconv_input_encoding, $use_highlightjs, $highlightjs_style); + +/*************************** ACTIONS ***************************/ + +// AJAX Request +if (isset($_POST['ajax']) && !FM_READONLY) { + + // save + if (isset($_POST['type']) && $_POST['type'] == "save") { + // get current path + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + // check path + if (!is_dir($path)) { + fm_redirect(FM_SELF_URL . '?p='); + } + $file = $_GET['edit']; + $file = fm_clean_path($file); + $file = str_replace('/', '', $file); + if ($file == '' || !is_file($path . '/' . $file)) { + fm_set_msg(lng('File not found'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + header('X-XSS-Protection:0'); + $file_path = $path . '/' . $file; + + $writedata = $_POST['content']; + $fd = fopen($file_path, "w"); + $write_results = @fwrite($fd, $writedata); + fclose($fd); + if ($write_results === false){ + header("HTTP/1.1 500 Internal Server Error"); + die("Could Not Write File! - Check Permissions / Ownership"); + } + die(true); + } + + //search : get list of files from the current folder + if(isset($_POST['type']) && $_POST['type']=="search") { + $dir = FM_ROOT_PATH; + $response = scan(fm_clean_path($_POST['path']), $_POST['content']); + echo json_encode($response); + exit(); + } + + // backup files + if (isset($_POST['type']) && $_POST['type'] == "backup" && !empty($_POST['file'])) { + $fileName = $_POST['file']; + $fullPath = FM_ROOT_PATH . '/'; + if (!empty($_POST['path'])) { + $relativeDirPath = fm_clean_path($_POST['path']); + $fullPath .= "{$relativeDirPath}/"; + } + $date = date("dMy-His"); + $newFileName = "{$fileName}-{$date}.bak"; + $fullyQualifiedFileName = $fullPath . $fileName; + try { + if (!file_exists($fullyQualifiedFileName)) { + throw new Exception("File {$fileName} not found"); + } + if (copy($fullyQualifiedFileName, $fullPath . $newFileName)) { + echo "Backup {$newFileName} created"; + } else { + throw new Exception("Could not copy file {$fileName}"); + } + } catch (Exception $e) { + echo $e->getMessage(); + } + } + + // Save Config + if (isset($_POST['type']) && $_POST['type'] == "settings") { + global $cfg, $lang, $report_errors, $show_hidden_files, $lang_list, $hide_Cols, $calc_folder, $theme; + $newLng = $_POST['js-language']; + fm_get_translations([]); + if (!array_key_exists($newLng, $lang_list)) { + $newLng = 'en'; + } + + $erp = isset($_POST['js-error-report']) && $_POST['js-error-report'] == "true" ? true : false; + $shf = isset($_POST['js-show-hidden']) && $_POST['js-show-hidden'] == "true" ? true : false; + $hco = isset($_POST['js-hide-cols']) && $_POST['js-hide-cols'] == "true" ? true : false; + $caf = isset($_POST['js-calc-folder']) && $_POST['js-calc-folder'] == "true" ? true : false; + $te3 = $_POST['js-theme-3']; + + if ($cfg->data['lang'] != $newLng) { + $cfg->data['lang'] = $newLng; + $lang = $newLng; + } + if ($cfg->data['error_reporting'] != $erp) { + $cfg->data['error_reporting'] = $erp; + $report_errors = $erp; + } + if ($cfg->data['show_hidden'] != $shf) { + $cfg->data['show_hidden'] = $shf; + $show_hidden_files = $shf; + } + if ($cfg->data['show_hidden'] != $shf) { + $cfg->data['show_hidden'] = $shf; + $show_hidden_files = $shf; + } + if ($cfg->data['hide_Cols'] != $hco) { + $cfg->data['hide_Cols'] = $hco; + $hide_Cols = $hco; + } + if ($cfg->data['calc_folder'] != $caf) { + $cfg->data['calc_folder'] = $caf; + $calc_folder = $caf; + } + if ($cfg->data['theme'] != $te3) { + $cfg->data['theme'] = $te3; + $theme = $te3; + } + $cfg->save(); + echo true; + } + + // new password hash + if (isset($_POST['type']) && $_POST['type'] == "pwdhash") { + $res = isset($_POST['inputPassword2']) && !empty($_POST['inputPassword2']) ? password_hash($_POST['inputPassword2'], PASSWORD_DEFAULT) : ''; + echo $res; + } + + //upload using url + if(isset($_POST['type']) && $_POST['type'] == "upload" && !empty($_REQUEST["uploadurl"])) { + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + + function event_callback ($message) { + global $callback; + echo json_encode($message); + } + + function get_file_path () { + global $path, $fileinfo, $temp_file; + return $path."/".basename($fileinfo->name); + } + + $url = !empty($_REQUEST["uploadurl"]) && preg_match("|^http(s)?://.+$|", stripslashes($_REQUEST["uploadurl"])) ? stripslashes($_REQUEST["uploadurl"]) : null; + + //prevent 127.* domain and known ports + $domain = parse_url($url, PHP_URL_HOST); + $port = parse_url($url, PHP_URL_PORT); + $knownPorts = [22, 23, 25, 3306]; + + if (preg_match("/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i", $domain) || in_array($port, $knownPorts)) { + $err = array("message" => "URL is not allowed"); + event_callback(array("fail" => $err)); + exit(); + } + + $use_curl = false; + $temp_file = tempnam(sys_get_temp_dir(), "upload-"); + $fileinfo = new stdClass(); + $fileinfo->name = trim(basename($url), ".\x00..\x20"); + + $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false; + $ext = strtolower(pathinfo($fileinfo->name, PATHINFO_EXTENSION)); + $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; + + $err = false; + + if(!$isFileAllowed) { + $err = array("message" => "File extension is not allowed"); + event_callback(array("fail" => $err)); + exit(); + } + + if (!$url) { + $success = false; + } else if ($use_curl) { + @$fp = fopen($temp_file, "w"); + @$ch = curl_init($url); + curl_setopt($ch, CURLOPT_NOPROGRESS, false ); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_FILE, $fp); + @$success = curl_exec($ch); + $curl_info = curl_getinfo($ch); + if (!$success) { + $err = array("message" => curl_error($ch)); + } + @curl_close($ch); + fclose($fp); + $fileinfo->size = $curl_info["size_download"]; + $fileinfo->type = $curl_info["content_type"]; + } else { + $ctx = stream_context_create(); + @$success = copy($url, $temp_file, $ctx); + if (!$success) { + $err = error_get_last(); + } + } + + if ($success) { + $success = rename($temp_file, get_file_path()); + } + + if ($success) { + event_callback(array("done" => $fileinfo)); + } else { + unlink($temp_file); + if (!$err) { + $err = array("message" => "Invalid url parameter"); + } + event_callback(array("fail" => $err)); + } + } + + exit(); +} + +// Delete file / folder +if (isset($_GET['del']) && !FM_READONLY) { + $del = str_replace( '/', '', fm_clean_path( $_GET['del'] ) ); + if ($del != '' && $del != '..' && $del != '.') { + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + $is_dir = is_dir($path . '/' . $del); + if (fm_rdelete($path . '/' . $del)) { + $msg = $is_dir ? lng('Folder').' <b>%s</b> '.lng('Deleted') : lng('File').' <b>%s</b> '.lng('Deleted'); + fm_set_msg(sprintf($msg, fm_enc($del))); + } else { + $msg = $is_dir ? lng('Folder').' <b>%s</b> '.lng('not deleted') : lng('File').' <b>%s</b> '.lng('not deleted'); + fm_set_msg(sprintf($msg, fm_enc($del)), 'error'); + } + } else { + fm_set_msg(lng('Invalid file or folder name'), 'error'); + } + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +// Create folder +if (isset($_GET['new']) && isset($_GET['type']) && !FM_READONLY) { + $type = $_GET['type']; + $new = str_replace( '/', '', fm_clean_path( strip_tags( $_GET['new'] ) ) ); + if (fm_isvalid_filename($new) && $new != '' && $new != '..' && $new != '.') { + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + if ($_GET['type'] == "file") { + if (!file_exists($path . '/' . $new)) { + if(fm_is_valid_ext($new)) { + @fopen($path . '/' . $new, 'w') or die('Cannot open file: ' . $new); + fm_set_msg(sprintf(lng('File').' <b>%s</b> '.lng('Created'), fm_enc($new))); + } else { + fm_set_msg(lng('File extension is not allowed'), 'error'); + } + } else { + fm_set_msg(sprintf(lng('File').' <b>%s</b> '.lng('already exists'), fm_enc($new)), 'alert'); + } + } else { + if (fm_mkdir($path . '/' . $new, false) === true) { + fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('Created'), $new)); + } elseif (fm_mkdir($path . '/' . $new, false) === $path . '/' . $new) { + fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('already exists'), fm_enc($new)), 'alert'); + } else { + fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('not created'), fm_enc($new)), 'error'); + } + } + } else { + fm_set_msg(lng('Invalid characters in file or folder name'), 'error'); + } + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +// Copy folder / file +if (isset($_GET['copy'], $_GET['finish']) && !FM_READONLY) { + // from + $copy = $_GET['copy']; + $copy = fm_clean_path($copy); + // empty path + if ($copy == '') { + fm_set_msg(lng('Source path not defined'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + // abs path from + $from = FM_ROOT_PATH . '/' . $copy; + // abs path to + $dest = FM_ROOT_PATH; + if (FM_PATH != '') { + $dest .= '/' . FM_PATH; + } + $dest .= '/' . basename($from); + // move? + $move = isset($_GET['move']); + // copy/move/duplicate + if ($from != $dest) { + $msg_from = trim(FM_PATH . '/' . basename($from), '/'); + if ($move) { // Move and to != from so just perform move + $rename = fm_rename($from, $dest); + if ($rename) { + fm_set_msg(sprintf(lng('Moved from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from))); + } elseif ($rename === null) { + fm_set_msg(lng('File or folder with this path already exists'), 'alert'); + } else { + fm_set_msg(sprintf(lng('Error while moving from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from)), 'error'); + } + } else { // Not move and to != from so copy with original name + if (fm_rcopy($from, $dest)) { + fm_set_msg(sprintf(lng('Copied from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from))); + } else { + fm_set_msg(sprintf(lng('Error while copying from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from)), 'error'); + } + } + } else { + if (!$move){ //Not move and to = from so duplicate + $msg_from = trim(FM_PATH . '/' . basename($from), '/'); + $fn_parts = pathinfo($from); + $extension_suffix = ''; + if(!is_dir($from)){ + $extension_suffix = '.'.$fn_parts['extension']; + } + //Create new name for duplicate + $fn_duplicate = $fn_parts['dirname'].'/'.$fn_parts['filename'].'-'.date('YmdHis').$extension_suffix; + $loop_count = 0; + $max_loop = 1000; + // Check if a file with the duplicate name already exists, if so, make new name (edge case...) + while(file_exists($fn_duplicate) & $loop_count < $max_loop){ + $fn_parts = pathinfo($fn_duplicate); + $fn_duplicate = $fn_parts['dirname'].'/'.$fn_parts['filename'].'-copy'.$extension_suffix; + $loop_count++; + } + if (fm_rcopy($from, $fn_duplicate, False)) { + fm_set_msg(sprintf('Copyied from <b>%s</b> to <b>%s</b>', fm_enc($copy), fm_enc($fn_duplicate))); + } else { + fm_set_msg(sprintf('Error while copying from <b>%s</b> to <b>%s</b>', fm_enc($copy), fm_enc($fn_duplicate)), 'error'); + } + } + else{ + fm_set_msg(lng('Paths must be not equal'), 'alert'); + } + } + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +// Mass copy files/ folders +if (isset($_POST['file'], $_POST['copy_to'], $_POST['finish']) && !FM_READONLY) { + // from + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + // to + $copy_to_path = FM_ROOT_PATH; + $copy_to = fm_clean_path($_POST['copy_to']); + if ($copy_to != '') { + $copy_to_path .= '/' . $copy_to; + } + if ($path == $copy_to_path) { + fm_set_msg(lng('Paths must be not equal'), 'alert'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + if (!is_dir($copy_to_path)) { + if (!fm_mkdir($copy_to_path, true)) { + fm_set_msg('Unable to create destination folder', 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + } + // move? + $move = isset($_POST['move']); + // copy/move + $errors = 0; + $files = $_POST['file']; + if (is_array($files) && count($files)) { + foreach ($files as $f) { + if ($f != '') { + // abs path from + $from = $path . '/' . $f; + // abs path to + $dest = $copy_to_path . '/' . $f; + // do + if ($move) { + $rename = fm_rename($from, $dest); + if ($rename === false) { + $errors++; + } + } else { + if (!fm_rcopy($from, $dest)) { + $errors++; + } + } + } + } + if ($errors == 0) { + $msg = $move ? 'Selected files and folders moved' : 'Selected files and folders copied'; + fm_set_msg($msg); + } else { + $msg = $move ? 'Error while moving items' : 'Error while copying items'; + fm_set_msg($msg, 'error'); + } + } else { + fm_set_msg(lng('Nothing selected'), 'alert'); + } + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +// Rename +if (isset($_GET['ren'], $_GET['to']) && !FM_READONLY) { + // old name + $old = $_GET['ren']; + $old = fm_clean_path($old); + $old = str_replace('/', '', $old); + // new name + $new = $_GET['to']; + $new = fm_clean_path(strip_tags($new)); + $new = str_replace('/', '', $new); + // path + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + // rename + if (fm_isvalid_filename($new) && $old != '' && $new != '') { + if (fm_rename($path . '/' . $old, $path . '/' . $new)) { + fm_set_msg(sprintf(lng('Renamed from').' <b>%s</b> '. lng('to').' <b>%s</b>', fm_enc($old), fm_enc($new))); + } else { + fm_set_msg(sprintf(lng('Error while renaming from').' <b>%s</b> '. lng('to').' <b>%s</b>', fm_enc($old), fm_enc($new)), 'error'); + } + } else { + fm_set_msg(lng('Invalid characters in file name'), 'error'); + } + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +// Download +if (isset($_GET['dl'])) { + $dl = $_GET['dl']; + $dl = fm_clean_path($dl); + $dl = str_replace('/', '', $dl); + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + if ($dl != '' && is_file($path . '/' . $dl)) { + fm_download_file($path . '/' . $dl, $dl, 1024); + exit; + } else { + fm_set_msg(lng('File not found'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } +} + +// Upload +if (!empty($_FILES) && !FM_READONLY) { + $override_file_name = false; + $f = $_FILES; + $path = FM_ROOT_PATH; + $ds = DIRECTORY_SEPARATOR; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + + $errors = 0; + $uploads = 0; + $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false; + $response = array ( + 'status' => 'error', + 'info' => 'Oops! Try again' + ); + + $filename = $f['file']['name']; + $tmp_name = $f['file']['tmp_name']; + $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; + + if(!fm_isvalid_filename($filename) && !fm_isvalid_filename($_REQUEST['fullpath'])) { + $response = array ( + 'status' => 'error', + 'info' => "Invalid File name!", + ); + echo json_encode($response); exit(); + } + + $targetPath = $path . $ds; + if ( is_writable($targetPath) ) { + $fullPath = $path . '/' . $_REQUEST['fullpath']; + $folder = substr($fullPath, 0, strrpos($fullPath, "/")); + + if(file_exists ($fullPath) && !$override_file_name) { + $ext_1 = $ext ? '.'.$ext : ''; + $fullPath = str_replace($ext_1, '', $fullPath) .'_'. date('ymdHis'). $ext_1; + } + + if (!is_dir($folder)) { + $old = umask(0); + mkdir($folder, 0777, true); + umask($old); + } + + if (empty($f['file']['error']) && !empty($tmp_name) && $tmp_name != 'none' && $isFileAllowed) { + if (move_uploaded_file($tmp_name, $fullPath)) { + // Be sure that the file has been uploaded + if ( file_exists($fullPath) ) { + $response = array ( + 'status' => 'success', + 'info' => "file upload successful" + ); + } else { + $response = array ( + 'status' => 'error', + 'info' => 'Couldn\'t upload the requested file.' + ); + } + } else { + $response = array ( + 'status' => 'error', + 'info' => "Error while uploading files. Uploaded files $uploads", + ); + } + } + } else { + $response = array ( + 'status' => 'error', + 'info' => 'The specified folder for upload isn\'t writeable.' + ); + } + // Return the response + echo json_encode($response); + exit(); +} + +// Mass deleting +if (isset($_POST['group'], $_POST['delete']) && !FM_READONLY) { + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + + $errors = 0; + $files = $_POST['file']; + if (is_array($files) && count($files)) { + foreach ($files as $f) { + if ($f != '') { + $new_path = $path . '/' . $f; + if (!fm_rdelete($new_path)) { + $errors++; + } + } + } + if ($errors == 0) { + fm_set_msg(lng('Selected files and folder deleted')); + } else { + fm_set_msg(lng('Error while deleting items'), 'error'); + } + } else { + fm_set_msg(lng('Nothing selected'), 'alert'); + } + + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +// Pack files +if (isset($_POST['group']) && (isset($_POST['zip']) || isset($_POST['tar'])) && !FM_READONLY) { + $path = FM_ROOT_PATH; + $ext = 'zip'; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + + //set pack type + $ext = isset($_POST['tar']) ? 'tar' : 'zip'; + + + if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) { + fm_set_msg(lng('Operations with archives are not available'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + + $files = $_POST['file']; + if (!empty($files)) { + chdir($path); + + if (count($files) == 1) { + $one_file = reset($files); + $one_file = basename($one_file); + $zipname = $one_file . '_' . date('ymd_His') . '.'.$ext; + } else { + $zipname = 'archive_' . date('ymd_His') . '.'.$ext; + } + + if($ext == 'zip') { + $zipper = new FM_Zipper(); + $res = $zipper->create($zipname, $files); + } elseif ($ext == 'tar') { + $tar = new FM_Zipper_Tar(); + $res = $tar->create($zipname, $files); + } + + if ($res) { + fm_set_msg(sprintf(lng('Archive').' <b>%s</b> '.lng('Created'), fm_enc($zipname))); + } else { + fm_set_msg(lng('Archive not created'), 'error'); + } + } else { + fm_set_msg(lng('Nothing selected'), 'alert'); + } + + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +// Unpack +if (isset($_GET['unzip']) && !FM_READONLY) { + $unzip = $_GET['unzip']; + $unzip = fm_clean_path($unzip); + $unzip = str_replace('/', '', $unzip); + $isValid = false; + + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + + if ($unzip != '' && is_file($path . '/' . $unzip)) { + $zip_path = $path . '/' . $unzip; + $ext = pathinfo($zip_path, PATHINFO_EXTENSION); + $isValid = true; + } else { + fm_set_msg(lng('File not found'), 'error'); + } + + + if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) { + fm_set_msg(lng('Operations with archives are not available'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + + if ($isValid) { + //to folder + $tofolder = ''; + if (isset($_GET['tofolder'])) { + $tofolder = pathinfo($zip_path, PATHINFO_FILENAME); + if (fm_mkdir($path . '/' . $tofolder, true)) { + $path .= '/' . $tofolder; + } + } + + if($ext == "zip") { + $zipper = new FM_Zipper(); + $res = $zipper->unzip($zip_path, $path); + } elseif ($ext == "tar") { + try { + $gzipper = new PharData($zip_path); + if (@$gzipper->extractTo($path,null, true)) { + $res = true; + } else { + $res = false; + } + } catch (Exception $e) { + //TODO:: need to handle the error + $res = true; + } + } + + if ($res) { + fm_set_msg(lng('Archive unpacked')); + } else { + fm_set_msg(lng('Archive not unpacked'), 'error'); + } + + } else { + fm_set_msg(lng('File not found'), 'error'); + } + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +// Change Perms (not for Windows) +if (isset($_POST['chmod']) && !FM_READONLY && !FM_IS_WIN) { + $path = FM_ROOT_PATH; + if (FM_PATH != '') { + $path .= '/' . FM_PATH; + } + + $file = $_POST['chmod']; + $file = fm_clean_path($file); + $file = str_replace('/', '', $file); + if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) { + fm_set_msg(lng('File not found'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + + $mode = 0; + if (!empty($_POST['ur'])) { + $mode |= 0400; + } + if (!empty($_POST['uw'])) { + $mode |= 0200; + } + if (!empty($_POST['ux'])) { + $mode |= 0100; + } + if (!empty($_POST['gr'])) { + $mode |= 0040; + } + if (!empty($_POST['gw'])) { + $mode |= 0020; + } + if (!empty($_POST['gx'])) { + $mode |= 0010; + } + if (!empty($_POST['or'])) { + $mode |= 0004; + } + if (!empty($_POST['ow'])) { + $mode |= 0002; + } + if (!empty($_POST['ox'])) { + $mode |= 0001; + } + + if (@chmod($path . '/' . $file, $mode)) { + fm_set_msg(lng('Permissions changed')); + } else { + fm_set_msg(lng('Permissions not changed'), 'error'); + } + + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); +} + +/*************************** /ACTIONS ***************************/ + +// get current path +$path = FM_ROOT_PATH; +if (FM_PATH != '') { + $path .= '/' . FM_PATH; +} + +// check path +if (!is_dir($path)) { + fm_redirect(FM_SELF_URL . '?p='); +} + +// get parent folder +$parent = fm_get_parent_path(FM_PATH); + +$objects = is_readable($path) ? scandir($path) : array(); +$folders = array(); +$files = array(); +$current_path = array_slice(explode("/",$path), -1)[0]; +if (is_array($objects) && fm_is_exclude_items($current_path)) { + foreach ($objects as $file) { + if ($file == '.' || $file == '..') { + continue; + } + if (!FM_SHOW_HIDDEN && substr($file, 0, 1) === '.') { + continue; + } + $new_path = $path . '/' . $file; + if (@is_file($new_path) && fm_is_exclude_items($file)) { + $files[] = $file; + } elseif (@is_dir($new_path) && $file != '.' && $file != '..' && fm_is_exclude_items($file)) { + $folders[] = $file; + } + } +} + +if (!empty($files)) { + natcasesort($files); +} +if (!empty($folders)) { + natcasesort($folders); +} + +// upload form +if (isset($_GET['upload']) && !FM_READONLY) { + fm_show_header(); // HEADER + fm_show_nav_path(FM_PATH); // current path + //get the allowed file extensions + function getUploadExt() { + $extArr = explode(',', FM_UPLOAD_EXTENSION); + if(FM_UPLOAD_EXTENSION && $extArr) { + array_walk($extArr, function(&$x) {$x = ".$x";}); + return implode(',', $extArr); + } + return ''; + } + ?> + + <link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.css" rel="stylesheet"> + <div class="path"> + + <div class="card mb-2 fm-upload-wrapper <?php echo fm_get_theme(); ?>"> + <div class="card-header"> + <ul class="nav nav-tabs card-header-tabs"> + <li class="nav-item"> + <a class="nav-link active" href="#fileUploader" data-target="#fileUploader"><i class="fa fa-arrow-circle-o-up"></i> <?php echo lng('UploadingFiles') ?></a> + </li> + <li class="nav-item"> + <a class="nav-link" href="#urlUploader" class="js-url-upload" data-target="#urlUploader"><i class="fa fa-link"></i> Upload from URL</a> + </li> + </ul> + </div> + <div class="card-body"> + <p class="card-text"> + <a href="?p=<?php echo FM_PATH ?>" class="float-right"><i class="fa fa-chevron-circle-left go-back"></i> <?php echo lng('Back')?></a> + <?php echo lng('DestinationFolder') ?>: <?php echo fm_enc(fm_convert_win(FM_PATH)) ?> + </p> + + <form action="<?php echo htmlspecialchars(FM_SELF_URL) . '?p=' . fm_enc(FM_PATH) ?>" class="dropzone card-tabs-container" id="fileUploader" enctype="multipart/form-data"> + <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>"> + <input type="hidden" name="fullpath" id="fullpath" value="<?php echo fm_enc(FM_PATH) ?>"> + <div class="fallback"> + <input name="file" type="file" multiple/> + </div> + </form> + + <div class="upload-url-wrapper card-tabs-container hidden" id="urlUploader"> + <form id="js-form-url-upload" class="form-inline" onsubmit="return upload_from_url(this);" method="POST" action=""> + <input type="hidden" name="type" value="upload" aria-label="hidden" aria-hidden="true"> + <input type="url" placeholder="URL" name="uploadurl" required class="form-control" style="width: 80%"> + <button type="submit" class="btn btn-primary ml-3"><?php echo lng('Upload') ?></button> + <div class="lds-facebook"><div></div><div></div><div></div></div> + </form> + <div id="js-url-upload__list" class="col-9 mt-3"></div> + </div> + </div> + </div> + </div> + <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.js"></script> + <script> + Dropzone.options.fileUploader = { + timeout: 120000, + maxFilesize: <?php echo MAX_UPLOAD_SIZE; ?>, + acceptedFiles : "<?php echo getUploadExt() ?>", + init: function () { + this.on("sending", function (file, xhr, formData) { + let _path = (file.fullPath) ? file.fullPath : file.name; + document.getElementById("fullpath").value = _path; + xhr.ontimeout = (function() { + toast('Error: Server Timeout'); + }); + }).on("success", function (res) { + let _response = JSON.parse(res.xhr.response); + if(_response.status == "error") { + toast(_response.info); + } + }).on("error", function(file, response) { + toast(response); + }); + } + } + </script> + <?php + fm_show_footer(); + exit; +} + +// copy form POST +if (isset($_POST['copy']) && !FM_READONLY) { + $copy_files = isset($_POST['file']) ? $_POST['file'] : null; + if (!is_array($copy_files) || empty($copy_files)) { + fm_set_msg(lng('Nothing selected'), 'alert'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + + fm_show_header(); // HEADER + fm_show_nav_path(FM_PATH); // current path + ?> + <div class="path"> + <div class="card <?php echo fm_get_theme(); ?>"> + <div class="card-header"> + <h6><?php echo lng('Copying') ?></h6> + </div> + <div class="card-body"> + <form action="" method="post"> + <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>"> + <input type="hidden" name="finish" value="1"> + <?php + foreach ($copy_files as $cf) { + echo '<input type="hidden" name="file[]" value="' . fm_enc($cf) . '">' . PHP_EOL; + } + ?> + <p class="break-word"><?php echo lng('Files') ?>: <b><?php echo implode('</b>, <b>', $copy_files) ?></b></p> + <p class="break-word"><?php echo lng('SourceFolder') ?>: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH)) ?><br> + <label for="inp_copy_to"><?php echo lng('DestinationFolder') ?>:</label> + <?php echo FM_ROOT_PATH ?>/<input type="text" name="copy_to" id="inp_copy_to" value="<?php echo fm_enc(FM_PATH) ?>"> + </p> + <p class="custom-checkbox custom-control"><input type="checkbox" name="move" value="1" id="js-move-files" class="custom-control-input"><label for="js-move-files" class="custom-control-label" style="vertical-align: sub"> <?php echo lng('Move') ?></label></p> + <p> + <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng('Copy') ?></button> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="btn btn-outline-primary"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></a></b> + </p> + </form> + </div> + </div> + </div> + <?php + fm_show_footer(); + exit; +} + +// copy form +if (isset($_GET['copy']) && !isset($_GET['finish']) && !FM_READONLY) { + $copy = $_GET['copy']; + $copy = fm_clean_path($copy); + if ($copy == '' || !file_exists(FM_ROOT_PATH . '/' . $copy)) { + fm_set_msg(lng('File not found'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + + fm_show_header(); // HEADER + fm_show_nav_path(FM_PATH); // current path + ?> + <div class="path"> + <p><b>Copying</b></p> + <p class="break-word"> + Source path: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . $copy)) ?><br> + Destination folder: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH)) ?> + </p> + <p> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1"><i class="fa fa-check-circle"></i> Copy</a></b> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1&move=1"><i class="fa fa-check-circle"></i> Move</a></b> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="fa fa-times-circle"></i> Cancel</a></b> + </p> + <p><i><?php echo lng('Select folder') ?></i></p> + <ul class="folders break-word"> + <?php + if ($parent !== false) { + ?> + <li><a href="?p=<?php echo urlencode($parent) ?>&copy=<?php echo urlencode($copy) ?>"><i class="fa fa-chevron-circle-left"></i> ..</a></li> + <?php + } + foreach ($folders as $f) { + ?> + <li> + <a href="?p=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>&copy=<?php echo urlencode($copy) ?>"><i class="fa fa-folder-o"></i> <?php echo fm_convert_win($f) ?></a></li> + <?php + } + ?> + </ul> + </div> + <?php + fm_show_footer(); + exit; +} + +if (isset($_GET['settings']) && !FM_READONLY) { + fm_show_header(); // HEADER + fm_show_nav_path(FM_PATH); // current path + global $cfg, $lang, $lang_list; + ?> + + <div class="col-md-8 offset-md-2 pt-3"> + <div class="card mb-2 <?php echo fm_get_theme(); ?>"> + <h6 class="card-header"> + <i class="fa fa-cog"></i> <?php echo lng('Settings') ?> + <a href="?p=<?php echo FM_PATH ?>" class="float-right"><i class="fa fa-window-close"></i> <?php echo lng('Cancel')?></a> + </h6> + <div class="card-body"> + <form id="js-settings-form" action="" method="post" data-type="ajax" onsubmit="return save_settings(this)"> + <input type="hidden" name="type" value="settings" aria-label="hidden" aria-hidden="true"> + <div class="form-group row"> + <label for="js-language" class="col-sm-3 col-form-label"><?php echo lng('Language') ?></label> + <div class="col-sm-5"> + <select class="form-control" id="js-language" name="js-language"> + <?php + function getSelected($l) { + global $lang; + return ($lang == $l) ? 'selected' : ''; + } + foreach ($lang_list as $k => $v) { + echo "<option value='$k' ".getSelected($k).">$v</option>"; + } + ?> + </select> + </div> + </div> + <?php + //get ON/OFF and active class + function getChecked($conf, $val, $txt) { + if($conf== 1 && $val ==1) { + return $txt; + } else if($conf == '' && $val == '') { + return $txt; + } else { + return ''; + } + } + ?> + <div class="form-group row"> + <label for="js-err-rpt-1" class="col-sm-3 col-form-label"><?php echo lng('ErrorReporting') ?></label> + <div class="col-sm-9"> + <div class="btn-group btn-group-toggle" data-toggle="buttons"> + <label class="btn btn-secondary <?php echo getChecked($report_errors, 1, 'active') ?>"> + <input type="radio" name="js-error-report" id="js-err-rpt-1" autocomplete="off" value="true" <?php echo getChecked($report_errors, 1, 'checked') ?> > ON + </label> + <label class="btn btn-secondary <?php echo getChecked($report_errors, '', 'active') ?>"> + <input type="radio" name="js-error-report" id="js-err-rpt-0" autocomplete="off" value="false" <?php echo getChecked($report_errors, '', 'checked') ?> > OFF + </label> + </div> + </div> + </div> + + <div class="form-group row"> + <label for="js-hdn-1" class="col-sm-3 col-form-label"><?php echo lng('ShowHiddenFiles') ?></label> + <div class="col-sm-9"> + <div class="btn-group btn-group-toggle" data-toggle="buttons"> + <label class="btn btn-secondary <?php echo getChecked($show_hidden_files, 1, 'active') ?>"> + <input type="radio" name="js-show-hidden" id="js-hdn-1" autocomplete="off" value="true" <?php echo getChecked($show_hidden_files, 1, 'checked') ?> > ON + </label> + <label class="btn btn-secondary <?php echo getChecked($show_hidden_files, '', 'active') ?>"> + <input type="radio" name="js-show-hidden" id="js-hdn-0" autocomplete="off" value="false" <?php echo getChecked($show_hidden_files, '', 'checked') ?> > OFF + </label> + </div> + </div> + </div> + + <div class="form-group row"> + <label for="js-hid-1" class="col-sm-3 col-form-label"><?php echo lng('HideColumns') ?></label> + <div class="col-sm-9"> + <div class="btn-group btn-group-toggle" data-toggle="buttons"> + <label class="btn btn-secondary <?php echo getChecked($hide_Cols, 1, 'active') ?>"> + <input type="radio" name="js-hide-cols" id="js-hid-1" autocomplete="off" value="true" <?php echo getChecked($hide_Cols, 1, 'checked') ?> > ON + </label> + <label class="btn btn-secondary <?php echo getChecked($hide_Cols, '', 'active') ?>"> + <input type="radio" name="js-hide-cols" id="js-hid-0" autocomplete="off" value="false" <?php echo getChecked($hide_Cols, '', 'checked') ?> > OFF + </label> + </div> + </div> + </div> + + <div class="form-group row"> + <label for="js-dir-1" class="col-sm-3 col-form-label"><?php echo lng('CalculateFolderSize') ?></label> + <div class="col-sm-9"> + <div class="btn-group btn-group-toggle" data-toggle="buttons"> + <label class="btn btn-secondary <?php echo getChecked($calc_folder, 1, 'active') ?>"> + <input type="radio" name="js-calc-folder" id="js-dir-1" autocomplete="off" value="true" <?php echo getChecked($calc_folder, 1, 'checked') ?> > ON + </label> + <label class="btn btn-secondary <?php echo getChecked($calc_folder, '', 'active') ?>"> + <input type="radio" name="js-calc-folder" id="js-dir-0" autocomplete="off" value="false" <?php echo getChecked($calc_folder, '', 'checked') ?> > OFF + </label> + </div> + </div> + </div> + + <div class="form-group row"> + <label for="js-3-1" class="col-sm-3 col-form-label"><?php echo lng('Theme') ?></label> + <div class="col-sm-5"> + <select class="form-control" id="js-3-0" name="js-theme-3" style="width:100px;"> + <option value='light' <?php if($theme == "light"){echo "selected";} ?>><?php echo lng('light') ?></option> + <option value='dark' <?php if($theme == "dark"){echo "selected";} ?>><?php echo lng('dark') ?></option> + </select> + </div> + </div> + + <div class="form-group row"> + <div class="col-sm-10"> + <button type="submit" class="btn btn-success"> <i class="fa fa-check-circle"></i> <?php echo lng('Save'); ?></button> + </div> + </div> + + </form> + </div> + </div> + </div> + <?php + fm_show_footer(); + exit; +} + +if (isset($_GET['help'])) { + fm_show_header(); // HEADER + fm_show_nav_path(FM_PATH); // current path + global $cfg, $lang; + ?> + + <div class="col-md-8 offset-md-2 pt-3"> + <div class="card mb-2 <?php echo fm_get_theme(); ?>"> + <h6 class="card-header"> + <i class="fa fa-exclamation-circle"></i> <?php echo lng('Help') ?> + <a href="?p=<?php echo FM_PATH ?>" class="float-right"><i class="fa fa-window-close"></i> <?php echo lng('Cancel')?></a> + </h6> + <div class="card-body"> + <div class="row"> + <div class="col-xs-12 col-sm-6"> + <p><h3><a href="https://github.com/prasathmani/tinyfilemanager" target="_blank" class="app-v-title"> Tiny File Manager <?php echo VERSION; ?></a></h3></p> + <p>Author: Prasath Mani</p> + <p>Mail Us: <a href="mailto:ccpprogrammers@gmail.com">ccpprogrammers[at]gmail.com</a> </p> + </div> + <div class="col-xs-12 col-sm-6"> + <div class="card"> + <ul class="list-group list-group-flush"> + <li class="list-group-item"><a href="https://github.com/prasathmani/tinyfilemanager/wiki" target="_blank"><i class="fa fa-question-circle"></i> <?php echo lng('Help Documents') ?> </a> </li> + <li class="list-group-item"><a href="https://github.com/prasathmani/tinyfilemanager/issues" target="_blank"><i class="fa fa-bug"></i> <?php echo lng('Report Issue') ?></a></li> + <li class="list-group-item"><a href="javascript:latest_release_info('<?php echo VERSION; ?>');"><i class="fa fa-link"> </i> <?php echo lng('Check Latest Version') ?></a></li> + <?php if(!FM_READONLY) { ?> + <li class="list-group-item"><a href="javascript:show_new_pwd();"><i class="fa fa-lock"></i> <?php echo lng('Generate new password hash') ?></a></li> + <?php } ?> + </ul> + </div> + </div> + </div> + <div class="row js-new-pwd hidden mt-2"> + <div class="col-12"> + <form class="form-inline" onsubmit="return new_password_hash(this)" method="POST" action=""> + <input type="hidden" name="type" value="pwdhash" aria-label="hidden" aria-hidden="true"> + <div class="form-group mb-2"> + <label for="staticEmail2"><?php echo lng('Generate new password hash') ?></label> + </div> + <div class="form-group mx-sm-3 mb-2"> + <label for="inputPassword2" class="sr-only"><?php echo lng('Password') ?></label> + <input type="text" class="form-control btn-sm" id="inputPassword2" name="inputPassword2" placeholder="Password" required> + </div> + <button type="submit" class="btn btn-success btn-sm mb-2"><?php echo lng('Generate') ?></button> + </form> + <textarea class="form-control" rows="2" readonly id="js-pwd-result"></textarea> + </div> + </div> + </div> + </div> + </div> + <?php + fm_show_footer(); + exit; +} + +// file viewer +if (isset($_GET['view'])) { + $file = $_GET['view']; + $quickView = (isset($_GET['quickView']) && $_GET['quickView'] == 1) ? true : false; + $file = fm_clean_path($file, false); + $file = str_replace('/', '', $file); + if ($file == '' || !is_file($path . '/' . $file) || in_array($file, $GLOBALS['exclude_items'])) { + fm_set_msg(lng('File not found'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + + if(!$quickView) { + fm_show_header(); // HEADER + fm_show_nav_path(FM_PATH); // current path + } + + $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file); + $file_path = $path . '/' . $file; + + $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION)); + $mime_type = fm_get_mime_type($file_path); + $filesize_raw = fm_get_size($file_path); + $filesize = fm_get_filesize($filesize_raw); + + $is_zip = false; + $is_gzip = false; + $is_image = false; + $is_audio = false; + $is_video = false; + $is_text = false; + $is_onlineViewer = false; + + $view_title = 'File'; + $filenames = false; // for zip + $content = ''; // for text + $online_viewer = strtolower(FM_DOC_VIEWER); + + if($online_viewer && $online_viewer !== 'false' && in_array($ext, fm_get_onlineViewer_exts())){ + $is_onlineViewer = true; + } + elseif ($ext == 'zip' || $ext == 'tar') { + $is_zip = true; + $view_title = 'Archive'; + $filenames = fm_get_zif_info($file_path, $ext); + } elseif (in_array($ext, fm_get_image_exts())) { + $is_image = true; + $view_title = 'Image'; + } elseif (in_array($ext, fm_get_audio_exts())) { + $is_audio = true; + $view_title = 'Audio'; + } elseif (in_array($ext, fm_get_video_exts())) { + $is_video = true; + $view_title = 'Video'; + } elseif (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) { + $is_text = true; + $content = file_get_contents($file_path); + } + + ?> + <div class="row"> + <div class="col-12"> + <?php if(!$quickView) { ?> + <p class="break-word"><b><?php echo $view_title ?> "<?php echo fm_enc(fm_convert_win($file)) ?>"</b></p> + <p class="break-word"> + Full path: <?php echo fm_enc(fm_convert_win($file_path)) ?><br> + File size: <?php echo ($filesize_raw <= 1000) ? "$filesize_raw bytes" : $filesize; ?><br> + MIME-type: <?php echo $mime_type ?><br> + <?php + // ZIP info + if (($is_zip || $is_gzip) && $filenames !== false) { + $total_files = 0; + $total_comp = 0; + $total_uncomp = 0; + foreach ($filenames as $fn) { + if (!$fn['folder']) { + $total_files++; + } + $total_comp += $fn['compressed_size']; + $total_uncomp += $fn['filesize']; + } + ?> + Files in archive: <?php echo $total_files ?><br> + Total size: <?php echo fm_get_filesize($total_uncomp) ?><br> + Size in archive: <?php echo fm_get_filesize($total_comp) ?><br> + Compression: <?php echo round(($total_comp / $total_uncomp) * 100) ?>%<br> + <?php + } + // Image info + if ($is_image) { + $image_size = getimagesize($file_path); + echo 'Image sizes: ' . (isset($image_size[0]) ? $image_size[0] : '0') . ' x ' . (isset($image_size[1]) ? $image_size[1] : '0') . '<br>'; + } + // Text info + if ($is_text) { + $is_utf8 = fm_is_utf8($content); + if (function_exists('iconv')) { + if (!$is_utf8) { + $content = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $content); + } + } + echo 'Charset: ' . ($is_utf8 ? 'utf-8' : '8 bit') . '<br>'; + } + ?> + </p> + <p> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($file) ?>"><i class="fa fa-cloud-download"></i> <?php echo lng('Download') ?></a></b> + <b><a href="<?php echo fm_enc($file_url) ?>" target="_blank"><i class="fa fa-external-link-square"></i> <?php echo lng('Open') ?></a></b> + + <?php + // ZIP actions + if (!FM_READONLY && ($is_zip || $is_gzip) && $filenames !== false) { + $zip_name = pathinfo($file_path, PATHINFO_FILENAME); + ?> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&unzip=<?php echo urlencode($file) ?>"><i class="fa fa-check-circle"></i> <?php echo lng('UnZip') ?></a></b> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&unzip=<?php echo urlencode($file) ?>&tofolder=1" title="UnZip to <?php echo fm_enc($zip_name) ?>"><i class="fa fa-check-circle"></i> + <?php echo lng('UnZipToFolder') ?></a></b> + <?php + } + if ($is_text && !FM_READONLY) { + ?> + <b><a href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>" class="edit-file"><i class="fa fa-pencil-square"></i> <?php echo lng('Edit') ?> + </a></b> + <b><a href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>&env=ace" + class="edit-file"><i class="fa fa-pencil-square-o"></i> <?php echo lng('AdvancedEditor') ?> + </a></b> + <?php } ?> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="fa fa-chevron-circle-left go-back"></i> <?php echo lng('Back') ?></a></b> + </p> + <?php + } + if($is_onlineViewer) { + if($online_viewer == 'google') { + echo '<iframe src="https://docs.google.com/viewer?embedded=true&hl=en&url=' . fm_enc($file_url) . '" frameborder="no" style="width:100%;min-height:460px"></iframe>'; + } else if($online_viewer == 'microsoft') { + echo '<iframe src="https://view.officeapps.live.com/op/embed.aspx?src=' . fm_enc($file_url) . '" frameborder="no" style="width:100%;min-height:460px"></iframe>'; + } + } elseif ($is_zip) { + // ZIP content + if ($filenames !== false) { + echo '<code class="maxheight">'; + foreach ($filenames as $fn) { + if ($fn['folder']) { + echo '<b>' . fm_enc($fn['name']) . '</b><br>'; + } else { + echo $fn['name'] . ' (' . fm_get_filesize($fn['filesize']) . ')<br>'; + } + } + echo '</code>'; + } else { + echo '<p>'.lng('Error while fetching archive info').'</p>'; + } + } elseif ($is_image) { + // Image content + if (in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico', 'svg', 'webp', 'avif'))) { + echo '<p><img src="' . fm_enc($file_url) . '" alt="" class="preview-img"></p>'; + } + } elseif ($is_audio) { + // Audio content + echo '<p><audio src="' . fm_enc($file_url) . '" controls preload="metadata"></audio></p>'; + } elseif ($is_video) { + // Video content + echo '<div class="preview-video"><video src="' . fm_enc($file_url) . '" width="640" height="360" controls preload="metadata"></video></div>'; + } elseif ($is_text) { + if (FM_USE_HIGHLIGHTJS) { + // highlight + $hljs_classes = array( + 'shtml' => 'xml', + 'htaccess' => 'apache', + 'phtml' => 'php', + 'lock' => 'json', + 'svg' => 'xml', + ); + $hljs_class = isset($hljs_classes[$ext]) ? 'lang-' . $hljs_classes[$ext] : 'lang-' . $ext; + if (empty($ext) || in_array(strtolower($file), fm_get_text_names()) || preg_match('#\.min\.(css|js)$#i', $file)) { + $hljs_class = 'nohighlight'; + } + $content = '<pre class="with-hljs"><code class="' . $hljs_class . '">' . fm_enc($content) . '</code></pre>'; + } elseif (in_array($ext, array('php', 'php4', 'php5', 'phtml', 'phps'))) { + // php highlight + $content = highlight_string($content, true); + } else { + $content = '<pre>' . fm_enc($content) . '</pre>'; + } + echo $content; + } + ?> + </div> + </div> + <?php + if(!$quickView) { + fm_show_footer(); + } + exit; +} + +// file editor +if (isset($_GET['edit'])) { + $file = $_GET['edit']; + $file = fm_clean_path($file, false); + $file = str_replace('/', '', $file); + if ($file == '' || !is_file($path . '/' . $file)) { + fm_set_msg(lng('File not found'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + header('X-XSS-Protection:0'); + fm_show_header(); // HEADER + fm_show_nav_path(FM_PATH); // current path + + $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file); + $file_path = $path . '/' . $file; + + // normal editer + $isNormalEditor = true; + if (isset($_GET['env'])) { + if ($_GET['env'] == "ace") { + $isNormalEditor = false; + } + } + + // Save File + if (isset($_POST['savedata'])) { + $writedata = $_POST['savedata']; + $fd = fopen($file_path, "w"); + @fwrite($fd, $writedata); + fclose($fd); + fm_set_msg(lng('File Saved Successfully')); + } + + $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION)); + $mime_type = fm_get_mime_type($file_path); + $filesize = filesize($file_path); + $is_text = false; + $content = ''; // for text + + if (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) { + $is_text = true; + $content = file_get_contents($file_path); + } + + ?> + <div class="path"> + <div class="row"> + <div class="col-xs-12 col-sm-5 col-lg-6 pt-1"> + <div class="btn-toolbar" role="toolbar"> + <?php if (!$isNormalEditor) { ?> + <div class="btn-group js-ace-toolbar"> + <button data-cmd="none" data-option="fullscreen" class="btn btn-sm btn-outline-secondary" id="js-ace-fullscreen" title="Fullscreen"><i class="fa fa-expand" title="Fullscreen"></i></button> + <button data-cmd="find" class="btn btn-sm btn-outline-secondary" id="js-ace-search" title="Search"><i class="fa fa-search" title="Search"></i></button> + <button data-cmd="undo" class="btn btn-sm btn-outline-secondary" id="js-ace-undo" title="Undo"><i class="fa fa-undo" title="Undo"></i></button> + <button data-cmd="redo" class="btn btn-sm btn-outline-secondary" id="js-ace-redo" title="Redo"><i class="fa fa-repeat" title="Redo"></i></button> + <button data-cmd="none" data-option="wrap" class="btn btn-sm btn-outline-secondary" id="js-ace-wordWrap" title="Word Wrap"><i class="fa fa-text-width" title="Word Wrap"></i></button> + <button data-cmd="none" data-option="help" class="btn btn-sm btn-outline-secondary" id="js-ace-goLine" title="Help"><i class="fa fa-question" title="Help"></i></button> + <select id="js-ace-mode" data-type="mode" title="Select Document Type" class="btn-outline-secondary border-left-0 d-none d-md-block"><option>-- Select Mode --</option></select> + <select id="js-ace-theme" data-type="theme" title="Select Theme" class="btn-outline-secondary border-left-0 d-none d-lg-block"><option>-- Select Theme --</option></select> + <select id="js-ace-fontSize" data-type="fontSize" title="Select Font Size" class="btn-outline-secondary border-left-0 d-none d-lg-block"><option>-- Select Font Size --</option></select> + </div> + <?php } ?> + </div> + </div> + <div class="edit-file-actions col-xs-12 col-sm-7 col-lg-6 text-right pt-1"> + <a title="<?php echo lng('Back') ?>" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&view=<?php echo urlencode($file) ?>"><i class="fa fa-reply-all"></i> <?php echo lng('Back') ?></a> + <a title="<?php echo lng('BackUp') ?>" class="btn btn-sm btn-outline-primary" href="javascript:void(0);" onclick="backup('<?php echo urlencode(trim(FM_PATH)) ?>','<?php echo urlencode($file) ?>')"><i class="fa fa-database"></i> <?php echo lng('BackUp') ?></a> + <?php if ($is_text) { ?> + <?php if ($isNormalEditor) { ?> + <a title="Advanced" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>&env=ace"><i class="fa fa-pencil-square-o"></i> <?php echo lng('AdvancedEditor') ?></a> + <button type="button" class="btn btn-sm btn-outline-primary name="Save" data-url="<?php echo fm_enc($file_url) ?>" onclick="edit_save(this,'nrl')"><i class="fa fa-floppy-o"></i> Save + </button> + <?php } else { ?> + <a title="Plain Editor" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>"><i class="fa fa-text-height"></i> <?php echo lng('NormalEditor') ?></a> + <button type="button" class="btn btn-sm btn-outline-primary" name="Save" data-url="<?php echo fm_enc($file_url) ?>" onclick="edit_save(this,'ace')"><i class="fa fa-floppy-o"></i> <?php echo lng('Save') ?> + </button> + <?php } ?> + <?php } ?> + </div> + </div> + <?php + if ($is_text && $isNormalEditor) { + echo '<textarea class="mt-2" id="normal-editor" rows="33" cols="120" style="width: 99.5%;">' . htmlspecialchars($content) . '</textarea>'; + } elseif ($is_text) { + echo '<div id="editor" contenteditable="true">' . htmlspecialchars($content) . '</div>'; + } else { + fm_set_msg(lng('FILE EXTENSION HAS NOT SUPPORTED'), 'error'); + } + ?> + </div> + <?php + fm_show_footer(); + exit; +} + +// chmod (not for Windows) +if (isset($_GET['chmod']) && !FM_READONLY && !FM_IS_WIN) { + $file = $_GET['chmod']; + $file = fm_clean_path($file); + $file = str_replace('/', '', $file); + if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) { + fm_set_msg(lng('File not found'), 'error'); + fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH)); + } + + fm_show_header(); // HEADER + fm_show_nav_path(FM_PATH); // current path + + $file_url = FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file; + $file_path = $path . '/' . $file; + + $mode = fileperms($path . '/' . $file); + + ?> + <div class="path"> + <div class="card mb-2 <?php echo fm_get_theme(); ?>"> + <h6 class="card-header"> + <?php echo lng('ChangePermissions') ?> + </h6> + <div class="card-body"> + <p class="card-text"> + Full path: <?php echo $file_path ?><br> + </p> + <form action="" method="post"> + <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>"> + <input type="hidden" name="chmod" value="<?php echo fm_enc($file) ?>"> + + <table class="table compact-table <?php echo fm_get_theme(); ?>"> + <tr> + <td></td> + <td><b><?php echo lng('Owner') ?></b></td> + <td><b><?php echo lng('Group') ?></b></td> + <td><b><?php echo lng('Other') ?></b></td> + </tr> + <tr> + <td style="text-align: right"><b><?php echo lng('Read') ?></b></td> + <td><label><input type="checkbox" name="ur" value="1"<?php echo ($mode & 00400) ? ' checked' : '' ?>></label></td> + <td><label><input type="checkbox" name="gr" value="1"<?php echo ($mode & 00040) ? ' checked' : '' ?>></label></td> + <td><label><input type="checkbox" name="or" value="1"<?php echo ($mode & 00004) ? ' checked' : '' ?>></label></td> + </tr> + <tr> + <td style="text-align: right"><b><?php echo lng('Write') ?></b></td> + <td><label><input type="checkbox" name="uw" value="1"<?php echo ($mode & 00200) ? ' checked' : '' ?>></label></td> + <td><label><input type="checkbox" name="gw" value="1"<?php echo ($mode & 00020) ? ' checked' : '' ?>></label></td> + <td><label><input type="checkbox" name="ow" value="1"<?php echo ($mode & 00002) ? ' checked' : '' ?>></label></td> + </tr> + <tr> + <td style="text-align: right"><b><?php echo lng('Execute') ?></b></td> + <td><label><input type="checkbox" name="ux" value="1"<?php echo ($mode & 00100) ? ' checked' : '' ?>></label></td> + <td><label><input type="checkbox" name="gx" value="1"<?php echo ($mode & 00010) ? ' checked' : '' ?>></label></td> + <td><label><input type="checkbox" name="ox" value="1"<?php echo ($mode & 00001) ? ' checked' : '' ?>></label></td> + </tr> + </table> + + <p> + <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng('Change') ?></button> + <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="btn btn-outline-primary"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></a></b> + </p> + </form> + </div> + </div> + </div> + <?php + fm_show_footer(); + exit; +} + +//--- FILEMANAGER MAIN +fm_show_header(); // HEADER +fm_show_nav_path(FM_PATH); // current path + +// messages +fm_show_message(); + +$num_files = count($files); +$num_folders = count($folders); +$all_files_size = 0; +$tableTheme = (FM_THEME == "dark") ? "text-white bg-dark table-dark" : "bg-white"; +?> +<form action="" method="post" class="pt-3"> + <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>"> + <input type="hidden" name="group" value="1"> + <div class="table-responsive"> + <table class="table table-bordered table-hover table-sm <?php echo $tableTheme; ?>" id="main-table"> + <thead class="thead-white"> + <tr> + <?php if (!FM_READONLY): ?> + <th style="width:3%" class="custom-checkbox-header"> + <div class="custom-control custom-checkbox"> + <input type="checkbox" class="custom-control-input" id="js-select-all-items" onclick="checkbox_toggle()"> + <label class="custom-control-label" for="js-select-all-items"></label> + </div> + </th><?php endif; ?> + <th><?php echo lng('Name') ?></th> + <th><?php echo lng('Size') ?></th> + <th><?php echo lng('Modified') ?></th> + <?php if (!FM_IS_WIN && !$hide_Cols): ?> + <th><?php echo lng('Perms') ?></th> + <th><?php echo lng('Owner') ?></th><?php endif; ?> + <th><?php echo lng('Actions') ?></th> + </tr> + </thead> + <?php + // link to parent folder + if ($parent !== false) { + ?> + <tr><?php if (!FM_READONLY): ?> + <td class="nosort"></td><?php endif; ?> + <td class="border-0"><a href="?p=<?php echo urlencode($parent) ?>"><i class="fa fa-chevron-circle-left go-back"></i> ..</a></td> + <td class="border-0"></td> + <td class="border-0"></td> + <td class="border-0"></td> + <?php if (!FM_IS_WIN && !$hide_Cols) { ?> + <td class="border-0"></td> + <td class="border-0"></td> + <?php } ?> + </tr> + <?php + } + $ii = 3399; + foreach ($folders as $f) { + $is_link = is_link($path . '/' . $f); + $img = $is_link ? 'icon-link_folder' : 'fa fa-folder-o'; + $modif_raw = filemtime($path . '/' . $f); + $modif = date(FM_DATETIME_FORMAT, $modif_raw); + if ($calc_folder) { + $filesize_raw = fm_get_directorysize($path . '/' . $f); + $filesize = fm_get_filesize($filesize_raw); + } + else { + $filesize_raw = ""; + $filesize = lng('Folder'); + } + $perms = substr(decoct(fileperms($path . '/' . $f)), -4); + if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) { + $owner = posix_getpwuid(fileowner($path . '/' . $f)); + $group = posix_getgrgid(filegroup($path . '/' . $f)); + } else { + $owner = array('name' => '?'); + $group = array('name' => '?'); + } + ?> + <tr> + <?php if (!FM_READONLY): ?> + <td class="custom-checkbox-td"> + <div class="custom-control custom-checkbox"> + <input type="checkbox" class="custom-control-input" id="<?php echo $ii ?>" name="file[]" value="<?php echo fm_enc($f) ?>"> + <label class="custom-control-label" for="<?php echo $ii ?>"></label> + </div> + </td><?php endif; ?> + <td> + <div class="filename"><a href="?p=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="<?php echo $img ?>"></i> <?php echo fm_convert_win(fm_enc($f)) ?> + </a><?php echo($is_link ? ' → <i>' . readlink($path . '/' . $f) . '</i>' : '') ?></div> + </td> + <td data-sort="a-<?php echo str_pad($filesize_raw, 18, "0", STR_PAD_LEFT);?>"> + <?php echo $filesize; ?> + </td> + <td data-sort="a-<?php echo $modif_raw;?>"><?php echo $modif ?></td> + <?php if (!FM_IS_WIN && !$hide_Cols): ?> + <td><?php if (!FM_READONLY): ?><a title="Change Permissions" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a><?php else: ?><?php echo $perms ?><?php endif; ?> + </td> + <td><?php echo $owner['name'] . ':' . $group['name'] ?></td> + <?php endif; ?> + <td class="inline-actions"><?php if (!FM_READONLY): ?> + <a title="<?php echo lng('Delete')?>" href="?p=<?php echo urlencode(FM_PATH) ?>&del=<?php echo urlencode($f) ?>" onclick="return confirm('<?php echo lng('Delete').' '.lng('Folder').'?'; ?>\n \n ( <?php echo urlencode($f) ?> )');"> <i class="fa fa-trash-o" aria-hidden="true"></i></a> + <a title="<?php echo lng('Rename')?>" href="#" onclick="rename('<?php echo fm_enc(addslashes(FM_PATH)) ?>', '<?php echo fm_enc(addslashes($f)) ?>');return false;"><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a> + <a title="<?php echo lng('CopyTo')?>..." href="?p=&copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="fa fa-files-o" aria-hidden="true"></i></a> + <?php endif; ?> + <a title="<?php echo lng('DirectLink')?>" href="<?php echo fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f . '/') ?>" target="_blank"><i class="fa fa-link" aria-hidden="true"></i></a> + </td> + </tr> + <?php + flush(); + $ii++; + } + $ik = 6070; + foreach ($files as $f) { + $is_link = is_link($path . '/' . $f); + $img = $is_link ? 'fa fa-file-text-o' : fm_get_file_icon_class($path . '/' . $f); + $modif_raw = filemtime($path . '/' . $f); + $modif = date(FM_DATETIME_FORMAT, $modif_raw); + $filesize_raw = fm_get_size($path . '/' . $f); + $filesize = fm_get_filesize($filesize_raw); + $filelink = '?p=' . urlencode(FM_PATH) . '&view=' . urlencode($f); + $all_files_size += $filesize_raw; + $perms = substr(decoct(fileperms($path . '/' . $f)), -4); + if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) { + $owner = posix_getpwuid(fileowner($path . '/' . $f)); + $group = posix_getgrgid(filegroup($path . '/' . $f)); + } else { + $owner = array('name' => '?'); + $group = array('name' => '?'); + } + ?> + <tr> + <?php if (!FM_READONLY): ?> + <td class="custom-checkbox-td"> + <div class="custom-control custom-checkbox"> + <input type="checkbox" class="custom-control-input" id="<?php echo $ik ?>" name="file[]" value="<?php echo fm_enc($f) ?>"> + <label class="custom-control-label" for="<?php echo $ik ?>"></label> + </div> + </td><?php endif; ?> + <td> + <div class="filename"> + <?php + if (in_array(strtolower(pathinfo($f, PATHINFO_EXTENSION)), array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico', 'svg', 'webp', 'avif'))): ?> + <?php $imagePreview = fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f); ?> + <a href="<?php echo $filelink ?>" data-preview-image="<?php echo $imagePreview ?>" title="<?php echo fm_enc($f) ?>"> + <?php else: ?> + <a href="<?php echo $filelink ?>" title="<?php echo $f ?>"> + <?php endif; ?> + <i class="<?php echo $img ?>"></i> <?php echo fm_convert_win(fm_enc($f)) ?> + </a> + <?php echo($is_link ? ' → <i>' . readlink($path . '/' . $f) . '</i>' : '') ?> + </div> + </td> + <td data-sort=b-"<?php echo str_pad($filesize_raw, 18, "0", STR_PAD_LEFT); ?>"><span title="<?php printf('%s bytes', $filesize_raw) ?>"> + <?php echo $filesize; ?> + </span></td> + <td data-sort="b-<?php echo $modif_raw;?>"><?php echo $modif ?></td> + <?php if (!FM_IS_WIN && !$hide_Cols): ?> + <td><?php if (!FM_READONLY): ?><a title="<?php echo 'Change Permissions' ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a><?php else: ?><?php echo $perms ?><?php endif; ?> + </td> + <td><?php echo fm_enc($owner['name'] . ':' . $group['name']) ?></td> + <?php endif; ?> + <td class="inline-actions"> + <a title="<?php echo lng('Preview') ?>" href="<?php echo $filelink.'&quickView=1'; ?>" data-toggle="lightbox" data-gallery="tiny-gallery" data-title="<?php echo fm_convert_win(fm_enc($f)) ?>" data-max-width="100%" data-width="100%"><i class="fa fa-eye"></i></a> + <?php if (!FM_READONLY): ?> + <a title="<?php echo lng('Delete') ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&del=<?php echo urlencode($f) ?>" onclick="return confirm('<?php echo lng('Delete').' '.lng('File').'?'; ?>\n \n ( <?php echo urlencode($f) ?> )');"> <i class="fa fa-trash-o"></i></a> + <a title="<?php echo lng('Rename') ?>" href="#" onclick="rename('<?php echo fm_enc(addslashes(FM_PATH)) ?>', '<?php echo fm_enc(addslashes($f)) ?>');return false;"><i class="fa fa-pencil-square-o"></i></a> + <a title="<?php echo lng('CopyTo') ?>..." + href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="fa fa-files-o"></i></a> + <?php endif; ?> + <a title="<?php echo lng('DirectLink') ?>" href="<?php echo fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f) ?>" target="_blank"><i class="fa fa-link"></i></a> + <a title="<?php echo lng('Download') ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($f) ?>"><i class="fa fa-download"></i></a> + </td> + </tr> + <?php + flush(); + $ik++; + } + + if (empty($folders) && empty($files)) { + ?> + <tfoot> + <tr><?php if (!FM_READONLY): ?> + <td></td><?php endif; ?> + <td colspan="<?php echo (!FM_IS_WIN && !$hide_Cols) ? '6' : '4' ?>"><em><?php echo 'Folder is empty' ?></em></td> + </tr> + </tfoot> + <?php + } else { + ?> + <tfoot> + <tr><?php if (!FM_READONLY): ?> + <td class="gray"></td><?php endif; ?> + <td class="gray" colspan="<?php echo (!FM_IS_WIN && !$hide_Cols) ? '6' : '4' ?>"> + <?php echo lng('FullSize').': <span class="badge badge-light">'.fm_get_filesize($all_files_size).'</span>' ?> + <?php echo lng('File').': <span class="badge badge-light">'.$num_files.'</span>' ?> + <?php echo lng('Folder').': <span class="badge badge-light">'.$num_folders.'</span>' ?> + <?php echo lng('PartitionSize').': <span class="badge badge-light">'.fm_get_filesize(@disk_free_space($path)) .'</span> '.lng('FreeOf').' <span class="badge badge-light">'.fm_get_filesize(@disk_total_space($path)).'</span>'; ?> + </td> + </tr> + </tfoot> + <?php + } + ?> + </table> + </div> + + <div class="row"> + <?php if (!FM_READONLY): ?> + <div class="col-xs-12 col-sm-9"> + <ul class="list-inline footer-action"> + <li class="list-inline-item"> <a href="#/select-all" class="btn btn-small btn-outline-primary btn-2" onclick="select_all();return false;"><i class="fa fa-check-square"></i> <?php echo lng('SelectAll') ?> </a></li> + <li class="list-inline-item"><a href="#/unselect-all" class="btn btn-small btn-outline-primary btn-2" onclick="unselect_all();return false;"><i class="fa fa-window-close"></i> <?php echo lng('UnSelectAll') ?> </a></li> + <li class="list-inline-item"><a href="#/invert-all" class="btn btn-small btn-outline-primary btn-2" onclick="invert_all();return false;"><i class="fa fa-th-list"></i> <?php echo lng('InvertSelection') ?> </a></li> + <li class="list-inline-item"><input type="submit" class="hidden" name="delete" id="a-delete" value="Delete" onclick="return confirm('<?php echo lng('Delete selected files and folders?'); ?>')"> + <a href="javascript:document.getElementById('a-delete').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-trash"></i> <?php echo lng('Delete') ?> </a></li> + <li class="list-inline-item"><input type="submit" class="hidden" name="zip" id="a-zip" value="zip" onclick="return confirm('<?php echo lng('Create archive?'); ?>')"> + <a href="javascript:document.getElementById('a-zip').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-file-archive-o"></i> <?php echo lng('Zip') ?> </a></li> + <li class="list-inline-item"><input type="submit" class="hidden" name="tar" id="a-tar" value="tar" onclick="return confirm('<?php echo lng('Create archive?'); ?>')"> + <a href="javascript:document.getElementById('a-tar').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-file-archive-o"></i> <?php echo lng('Tar') ?> </a></li> + <li class="list-inline-item"><input type="submit" class="hidden" name="copy" id="a-copy" value="Copy"> + <a href="javascript:document.getElementById('a-copy').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-files-o"></i> <?php echo lng('Copy') ?> </a></li> + </ul> + </div> + <div class="col-3 d-none d-sm-block"><a href="https://tinyfilemanager.github.io" target="_blank" class="float-right text-muted">Tiny File Manager <?php echo VERSION; ?></a></div> + <?php else: ?> + <div class="col-12"><a href="https://tinyfilemanager.github.io" target="_blank" class="float-right text-muted">Tiny File Manager <?php echo VERSION; ?></a></div> + <?php endif; ?> + </div> + +</form> + +<?php +fm_show_footer(); + +//--- END + +// Functions + +/** + * Check if the filename is allowed. + * @param string $filename + * @return bool + */ +function fm_is_file_allowed($filename) +{ + // By default, no file is allowed + $allowed = false; + + if (FM_EXTENSION) { + $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + + if (in_array($ext, explode(',', strtolower(FM_EXTENSION)))) { + $allowed = true; + } + } + + return $allowed; +} + +/** + * Delete file or folder (recursively) + * @param string $path + * @return bool + */ +function fm_rdelete($path) +{ + if (is_link($path)) { + return unlink($path); + } elseif (is_dir($path)) { + $objects = scandir($path); + $ok = true; + if (is_array($objects)) { + foreach ($objects as $file) { + if ($file != '.' && $file != '..') { + if (!fm_rdelete($path . '/' . $file)) { + $ok = false; + } + } + } + } + return ($ok) ? rmdir($path) : false; + } elseif (is_file($path)) { + return unlink($path); + } + return false; +} + +/** + * Recursive chmod + * @param string $path + * @param int $filemode + * @param int $dirmode + * @return bool + * @todo Will use in mass chmod + */ +function fm_rchmod($path, $filemode, $dirmode) +{ + if (is_dir($path)) { + if (!chmod($path, $dirmode)) { + return false; + } + $objects = scandir($path); + if (is_array($objects)) { + foreach ($objects as $file) { + if ($file != '.' && $file != '..') { + if (!fm_rchmod($path . '/' . $file, $filemode, $dirmode)) { + return false; + } + } + } + } + return true; + } elseif (is_link($path)) { + return true; + } elseif (is_file($path)) { + return chmod($path, $filemode); + } + return false; +} + +/** + * Check the file extension which is allowed or not + * @param string $filename + * @return bool + */ +function fm_is_valid_ext($filename) +{ + $allowed = (FM_FILE_EXTENSION) ? explode(',', FM_FILE_EXTENSION) : false; + + $ext = pathinfo($filename, PATHINFO_EXTENSION); + $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; + + return ($isFileAllowed) ? true : false; +} + +/** + * Safely rename + * @param string $old + * @param string $new + * @return bool|null + */ +function fm_rename($old, $new) +{ + $isFileAllowed = fm_is_valid_ext($new); + + if(!$isFileAllowed) return false; + + return (!file_exists($new) && file_exists($old)) ? rename($old, $new) : null; +} + +/** + * Copy file or folder (recursively). + * @param string $path + * @param string $dest + * @param bool $upd Update files + * @param bool $force Create folder with same names instead file + * @return bool + */ +function fm_rcopy($path, $dest, $upd = true, $force = true) +{ + if (is_dir($path)) { + if (!fm_mkdir($dest, $force)) { + return false; + } + $objects = scandir($path); + $ok = true; + if (is_array($objects)) { + foreach ($objects as $file) { + if ($file != '.' && $file != '..') { + if (!fm_rcopy($path . '/' . $file, $dest . '/' . $file)) { + $ok = false; + } + } + } + } + return $ok; + } elseif (is_file($path)) { + return fm_copy($path, $dest, $upd); + } + return false; +} + +/** + * Safely create folder + * @param string $dir + * @param bool $force + * @return bool + */ +function fm_mkdir($dir, $force) +{ + if (file_exists($dir)) { + if (is_dir($dir)) { + return $dir; + } elseif (!$force) { + return false; + } + unlink($dir); + } + return mkdir($dir, 0777, true); +} + +/** + * Safely copy file + * @param string $f1 + * @param string $f2 + * @param bool $upd Indicates if file should be updated with new content + * @return bool + */ +function fm_copy($f1, $f2, $upd) +{ + $time1 = filemtime($f1); + if (file_exists($f2)) { + $time2 = filemtime($f2); + if ($time2 >= $time1 && $upd) { + return false; + } + } + $ok = copy($f1, $f2); + if ($ok) { + touch($f2, $time1); + } + return $ok; +} + +/** + * Get mime type + * @param string $file_path + * @return mixed|string + */ +function fm_get_mime_type($file_path) +{ + if (function_exists('finfo_open')) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime = finfo_file($finfo, $file_path); + finfo_close($finfo); + return $mime; + } elseif (function_exists('mime_content_type')) { + return mime_content_type($file_path); + } elseif (!stristr(ini_get('disable_functions'), 'shell_exec')) { + $file = escapeshellarg($file_path); + $mime = shell_exec('file -bi ' . $file); + return $mime; + } else { + return '--'; + } +} + +/** + * HTTP Redirect + * @param string $url + * @param int $code + */ +function fm_redirect($url, $code = 302) +{ + header('Location: ' . $url, true, $code); + exit; +} + +/** + * Path traversal prevention and clean the url + * It replaces (consecutive) occurrences of / and \\ with whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine. + * @param $path + * @return string + */ +function get_absolute_path($path) { + $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); + $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen'); + $absolutes = array(); + foreach ($parts as $part) { + if ('.' == $part) continue; + if ('..' == $part) { + array_pop($absolutes); + } else { + $absolutes[] = $part; + } + } + return implode(DIRECTORY_SEPARATOR, $absolutes); +} + +/** + * Clean path + * @param string $path + * @return string + */ +function fm_clean_path($path, $trim = true) +{ + $path = $trim ? trim($path) : $path; + $path = trim($path, '\\/'); + $path = str_replace(array('../', '..\\'), '', $path); + $path = get_absolute_path($path); + if ($path == '..') { + $path = ''; + } + return str_replace('\\', '/', $path); +} + +/** + * Get parent path + * @param string $path + * @return bool|string + */ +function fm_get_parent_path($path) +{ + $path = fm_clean_path($path); + if ($path != '') { + $array = explode('/', $path); + if (count($array) > 1) { + $array = array_slice($array, 0, -1); + return implode('/', $array); + } + return ''; + } + return false; +} + +/** + * Check file is in exclude list + * @param string $file + * @return bool + */ +function fm_is_exclude_items($file) { + $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); + if (isset($exclude_items) and sizeof($exclude_items)) { + unset($exclude_items); + } + + $exclude_items = FM_EXCLUDE_ITEMS; + if (version_compare(PHP_VERSION, '7.0.0', '<')) { + $exclude_items = unserialize($exclude_items); + } + if (!in_array($file, $exclude_items) && !in_array("*.$ext", $exclude_items)) { + return true; + } + return false; +} + +/** + * get language translations from json file + * @param int $tr + * @return array + */ +function fm_get_translations($tr) { + try { + $content = @file_get_contents('translation.json'); + if($content !== FALSE) { + $lng = json_decode($content, TRUE); + global $lang_list; + foreach ($lng["language"] as $key => $value) + { + $code = $value["code"]; + $lang_list[$code] = $value["name"]; + if ($tr) + $tr[$code] = $value["translation"]; + } + return $tr; + } + + } + catch (Exception $e) { + echo $e; + } +} + +/** + * @param $file + * Recover all file sizes larger than > 2GB. + * Works on php 32bits and 64bits and supports linux + * @return int|string + */ +function fm_get_size($file) +{ + static $iswin; + static $isdarwin; + if (!isset($iswin)) { + $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); + } + if (!isset($isdarwin)) { + $isdarwin = (strtoupper(substr(PHP_OS, 0)) == "DARWIN"); + } + + static $exec_works; + if (!isset($exec_works)) { + $exec_works = (function_exists('exec') && !ini_get('safe_mode') && @exec('echo EXEC') == 'EXEC'); + } + + // try a shell command + if ($exec_works) { + $arg = escapeshellarg($file); + $cmd = ($iswin) ? "for %F in (\"$file\") do @echo %~zF" : ($isdarwin ? "stat -f%z $arg" : "stat -c%s $arg"); + @exec($cmd, $output); + if (is_array($output) && ctype_digit($size = trim(implode("\n", $output)))) { + return $size; + } + } + + // try the Windows COM interface + if ($iswin && class_exists("COM")) { + try { + $fsobj = new COM('Scripting.FileSystemObject'); + $f = $fsobj->GetFile( realpath($file) ); + $size = $f->Size; + } catch (Exception $e) { + $size = null; + } + if (ctype_digit($size)) { + return $size; + } + } + + // if all else fails + return filesize($file); +} + +/** + * Get nice filesize + * @param int $size + * @return string + */ +function fm_get_filesize($size) +{ + $size = (float) $size; + $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'); + $power = $size > 0 ? floor(log($size, 1024)) : 0; + return sprintf('%s %s', round($size / pow(1024, $power), 2), $units[$power]); +} + +/** + * Get director total size + * @param string $directory + * @return int + */ +function fm_get_directorysize($directory) { + global $calc_folder; + if ($calc_folder==true) { // Slower output + $size = 0; $count= 0; $dirCount= 0; + foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $file) + if ($file->isFile()) + { $size+=$file->getSize(); + $count++; + } + else if ($file->isDir()) { $dirCount++; } + // return [$size, $count, $dirCount]; + return $size; + } + else return 'Folder'; // Quick output +} + +/** + * Get info about zip archive + * @param string $path + * @return array|bool + */ +function fm_get_zif_info($path, $ext) { + if ($ext == 'zip' && function_exists('zip_open')) { + $arch = zip_open($path); + if ($arch) { + $filenames = array(); + while ($zip_entry = zip_read($arch)) { + $zip_name = zip_entry_name($zip_entry); + $zip_folder = substr($zip_name, -1) == '/'; + $filenames[] = array( + 'name' => $zip_name, + 'filesize' => zip_entry_filesize($zip_entry), + 'compressed_size' => zip_entry_compressedsize($zip_entry), + 'folder' => $zip_folder + //'compression_method' => zip_entry_compressionmethod($zip_entry), + ); + } + zip_close($arch); + return $filenames; + } + } elseif($ext == 'tar' && class_exists('PharData')) { + $archive = new PharData($path); + $filenames = array(); + foreach(new RecursiveIteratorIterator($archive) as $file) { + $parent_info = $file->getPathInfo(); + $zip_name = str_replace("phar://".$path, '', $file->getPathName()); + $zip_name = substr($zip_name, ($pos = strpos($zip_name, '/')) !== false ? $pos + 1 : 0); + $zip_folder = $parent_info->getFileName(); + $zip_info = new SplFileInfo($file); + $filenames[] = array( + 'name' => $zip_name, + 'filesize' => $zip_info->getSize(), + 'compressed_size' => $file->getCompressedSize(), + 'folder' => $zip_folder + ); + } + return $filenames; + } + return false; +} + +/** + * Encode html entities + * @param string $text + * @return string + */ +function fm_enc($text) +{ + return htmlspecialchars($text, ENT_QUOTES, 'UTF-8'); +} + +/** + * Prevent XSS attacks + * @param string $text + * @return string + */ +function fm_isvalid_filename($text) { + return (strpbrk($text, '/?%*:|"<>') === FALSE) ? true : false; +} + +/** + * Save message in session + * @param string $msg + * @param string $status + */ +function fm_set_msg($msg, $status = 'ok') +{ + $_SESSION[FM_SESSION_ID]['message'] = $msg; + $_SESSION[FM_SESSION_ID]['status'] = $status; +} + +/** + * Check if string is in UTF-8 + * @param string $string + * @return int + */ +function fm_is_utf8($string) +{ + return preg_match('//u', $string); +} + +/** + * Convert file name to UTF-8 in Windows + * @param string $filename + * @return string + */ +function fm_convert_win($filename) +{ + if (FM_IS_WIN && function_exists('iconv')) { + $filename = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $filename); + } + return $filename; +} + +/** + * @param $obj + * @return array + */ +function fm_object_to_array($obj) +{ + if (!is_object($obj) && !is_array($obj)) { + return $obj; + } + if (is_object($obj)) { + $obj = get_object_vars($obj); + } + return array_map('fm_object_to_array', $obj); +} + +/** + * Get CSS classname for file + * @param string $path + * @return string + */ +function fm_get_file_icon_class($path) +{ + // get extension + $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); + + switch ($ext) { + case 'ico': + case 'gif': + case 'jpg': + case 'jpeg': + case 'jpc': + case 'jp2': + case 'jpx': + case 'xbm': + case 'wbmp': + case 'png': + case 'bmp': + case 'tif': + case 'tiff': + case 'webp': + case 'avif': + case 'svg': + $img = 'fa fa-picture-o'; + break; + case 'passwd': + case 'ftpquota': + case 'sql': + case 'js': + case 'json': + case 'sh': + case 'config': + case 'twig': + case 'tpl': + case 'md': + case 'gitignore': + case 'c': + case 'cpp': + case 'cs': + case 'py': + case 'rs': + case 'map': + case 'lock': + case 'dtd': + $img = 'fa fa-file-code-o'; + break; + case 'txt': + case 'ini': + case 'conf': + case 'log': + case 'htaccess': + $img = 'fa fa-file-text-o'; + break; + case 'css': + case 'less': + case 'sass': + case 'scss': + $img = 'fa fa-css3'; + break; + case 'bz2': + case 'zip': + case 'rar': + case 'gz': + case 'tar': + case '7z': + case 'xz': + $img = 'fa fa-file-archive-o'; + break; + case 'php': + case 'php4': + case 'php5': + case 'phps': + case 'phtml': + $img = 'fa fa-code'; + break; + case 'htm': + case 'html': + case 'shtml': + case 'xhtml': + $img = 'fa fa-html5'; + break; + case 'xml': + case 'xsl': + $img = 'fa fa-file-excel-o'; + break; + case 'wav': + case 'mp3': + case 'mp2': + case 'm4a': + case 'aac': + case 'ogg': + case 'oga': + case 'wma': + case 'mka': + case 'flac': + case 'ac3': + case 'tds': + $img = 'fa fa-music'; + break; + case 'm3u': + case 'm3u8': + case 'pls': + case 'cue': + case 'xspf': + $img = 'fa fa-headphones'; + break; + case 'avi': + case 'mpg': + case 'mpeg': + case 'mp4': + case 'm4v': + case 'flv': + case 'f4v': + case 'ogm': + case 'ogv': + case 'mov': + case 'mkv': + case '3gp': + case 'asf': + case 'wmv': + $img = 'fa fa-file-video-o'; + break; + case 'eml': + case 'msg': + $img = 'fa fa-envelope-o'; + break; + case 'xls': + case 'xlsx': + case 'ods': + $img = 'fa fa-file-excel-o'; + break; + case 'csv': + $img = 'fa fa-file-text-o'; + break; + case 'bak': + case 'swp': + $img = 'fa fa-clipboard'; + break; + case 'doc': + case 'docx': + case 'odt': + $img = 'fa fa-file-word-o'; + break; + case 'ppt': + case 'pptx': + $img = 'fa fa-file-powerpoint-o'; + break; + case 'ttf': + case 'ttc': + case 'otf': + case 'woff': + case 'woff2': + case 'eot': + case 'fon': + $img = 'fa fa-font'; + break; + case 'pdf': + $img = 'fa fa-file-pdf-o'; + break; + case 'psd': + case 'ai': + case 'eps': + case 'fla': + case 'swf': + $img = 'fa fa-file-image-o'; + break; + case 'exe': + case 'msi': + $img = 'fa fa-file-o'; + break; + case 'bat': + $img = 'fa fa-terminal'; + break; + default: + $img = 'fa fa-info-circle'; + } + + return $img; +} + +/** + * Get image files extensions + * @return array + */ +function fm_get_image_exts() +{ + return array('ico', 'gif', 'jpg', 'jpeg', 'jpc', 'jp2', 'jpx', 'xbm', 'wbmp', 'png', 'bmp', 'tif', 'tiff', 'psd', 'svg', 'webp', 'avif'); +} + +/** + * Get video files extensions + * @return array + */ +function fm_get_video_exts() +{ + return array('avi', 'webm', 'wmv', 'mp4', 'm4v', 'ogm', 'ogv', 'mov', 'mkv'); +} + +/** + * Get audio files extensions + * @return array + */ +function fm_get_audio_exts() +{ + return array('wav', 'mp3', 'ogg', 'm4a'); +} + +/** + * Get text file extensions + * @return array + */ +function fm_get_text_exts() +{ + return array( + 'txt', 'css', 'ini', 'conf', 'log', 'htaccess', 'passwd', 'ftpquota', 'sql', 'js', 'json', 'sh', 'config', + 'php', 'php4', 'php5', 'phps', 'phtml', 'htm', 'html', 'shtml', 'xhtml', 'xml', 'xsl', 'm3u', 'm3u8', 'pls', 'cue', + 'eml', 'msg', 'csv', 'bat', 'twig', 'tpl', 'md', 'gitignore', 'less', 'sass', 'scss', 'c', 'cpp', 'cs', 'py', + 'map', 'lock', 'dtd', 'svg', 'scss', 'asp', 'aspx', 'asx', 'asmx', 'ashx', 'jsx', 'jsp', 'jspx', 'cfm', 'cgi' + ); +} + +/** + * Get mime types of text files + * @return array + */ +function fm_get_text_mimes() +{ + return array( + 'application/xml', + 'application/javascript', + 'application/x-javascript', + 'image/svg+xml', + 'message/rfc822', + ); +} + +/** + * Get file names of text files w/o extensions + * @return array + */ +function fm_get_text_names() +{ + return array( + 'license', + 'readme', + 'authors', + 'contributors', + 'changelog', + ); +} + +/** + * Get online docs viewer supported files extensions + * @return array + */ +function fm_get_onlineViewer_exts() +{ + return array('doc', 'docx', 'xls', 'xlsx', 'pdf', 'ppt', 'pptx', 'ai', 'psd', 'dxf', 'xps', 'rar', 'odt', 'ods'); +} + +function fm_get_file_mimes($extension) +{ + $fileTypes['swf'] = 'application/x-shockwave-flash'; + $fileTypes['pdf'] = 'application/pdf'; + $fileTypes['exe'] = 'application/octet-stream'; + $fileTypes['zip'] = 'application/zip'; + $fileTypes['doc'] = 'application/msword'; + $fileTypes['xls'] = 'application/vnd.ms-excel'; + $fileTypes['ppt'] = 'application/vnd.ms-powerpoint'; + $fileTypes['gif'] = 'image/gif'; + $fileTypes['png'] = 'image/png'; + $fileTypes['jpeg'] = 'image/jpg'; + $fileTypes['jpg'] = 'image/jpg'; + $fileTypes['webp'] = 'image/webp'; + $fileTypes['avif'] = 'image/avif'; + $fileTypes['rar'] = 'application/rar'; + + $fileTypes['ra'] = 'audio/x-pn-realaudio'; + $fileTypes['ram'] = 'audio/x-pn-realaudio'; + $fileTypes['ogg'] = 'audio/x-pn-realaudio'; + + $fileTypes['wav'] = 'video/x-msvideo'; + $fileTypes['wmv'] = 'video/x-msvideo'; + $fileTypes['avi'] = 'video/x-msvideo'; + $fileTypes['asf'] = 'video/x-msvideo'; + $fileTypes['divx'] = 'video/x-msvideo'; + + $fileTypes['mp3'] = 'audio/mpeg'; + $fileTypes['mp4'] = 'audio/mpeg'; + $fileTypes['mpeg'] = 'video/mpeg'; + $fileTypes['mpg'] = 'video/mpeg'; + $fileTypes['mpe'] = 'video/mpeg'; + $fileTypes['mov'] = 'video/quicktime'; + $fileTypes['swf'] = 'video/quicktime'; + $fileTypes['3gp'] = 'video/quicktime'; + $fileTypes['m4a'] = 'video/quicktime'; + $fileTypes['aac'] = 'video/quicktime'; + $fileTypes['m3u'] = 'video/quicktime'; + + $fileTypes['php'] = ['application/x-php']; + $fileTypes['html'] = ['text/html']; + $fileTypes['txt'] = ['text/plain']; + //Unknown mime-types should be 'application/octet-stream' + if(empty($fileTypes[$extension])) { + $fileTypes[$extension] = ['application/octet-stream']; + } + return $fileTypes[$extension]; +} + +/** + * This function scans the files and folder recursively, and return matching files + * @param string $dir + * @param string $filter + * @return json + */ + function scan($dir, $filter = '') { + $path = FM_ROOT_PATH.'/'.$dir; + if($dir) { + $ite = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); + $rii = new RegexIterator($ite, "/(" . $filter . ")/i"); + + $files = array(); + foreach ($rii as $file) { + if (!$file->isDir()) { + $fileName = $file->getFilename(); + $location = str_replace(FM_ROOT_PATH, '', $file->getPath()); + $files[] = array( + "name" => $fileName, + "type" => "file", + "path" => $location, + ); + } + } + return $files; + } +} + +/* +Parameters: downloadFile(File Location, File Name, +max speed, is streaming +If streaming - videos will show as videos, images as images +instead of download prompt +https://stackoverflow.com/a/13821992/1164642 +*/ + +function fm_download_file($fileLocation, $fileName, $chunkSize = 1024) +{ + if (connection_status() != 0) + return (false); + $extension = pathinfo($fileName, PATHINFO_EXTENSION); + + $contentType = fm_get_file_mimes($extension); + header("Cache-Control: public"); + header("Content-Transfer-Encoding: binary\n"); + header('Content-Type: $contentType'); + + $contentDisposition = 'attachment'; + + + if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { + $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1); + header("Content-Disposition: $contentDisposition;filename=\"$fileName\""); + } else { + header("Content-Disposition: $contentDisposition;filename=\"$fileName\""); + } + + header("Accept-Ranges: bytes"); + $range = 0; + $size = filesize($fileLocation); + + if (isset($_SERVER['HTTP_RANGE'])) { + list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']); + str_replace($range, "-", $range); + $size2 = $size - 1; + $new_length = $size - $range; + header("HTTP/1.1 206 Partial Content"); + header("Content-Length: $new_length"); + header("Content-Range: bytes $range$size2/$size"); + } else { + $size2 = $size - 1; + header("Content-Range: bytes 0-$size2/$size"); + header("Content-Length: " . $size); + } + + if ($size == 0) { + die('Zero byte file! Aborting download'); + } + @ini_set('magic_quotes_runtime', 0); + $fp = fopen("$fileLocation", "rb"); + + fseek($fp, $range); + + while (!feof($fp) and (connection_status() == 0)) { + set_time_limit(0); + print(@fread($fp, 1024*$chunkSize)); + flush(); + ob_flush(); + // sleep(1); + } + fclose($fp); + + return ((connection_status() == 0) and !connection_aborted()); +} + +function fm_get_theme() { + $result = ''; + if(FM_THEME == "dark") { + $result = "text-white bg-dark"; + } + return $result; +} + +/** + * Class to work with zip files (using ZipArchive) + */ +class FM_Zipper +{ + private $zip; + + public function __construct() + { + $this->zip = new ZipArchive(); + } + + /** + * Create archive with name $filename and files $files (RELATIVE PATHS!) + * @param string $filename + * @param array|string $files + * @return bool + */ + public function create($filename, $files) + { + $res = $this->zip->open($filename, ZipArchive::CREATE); + if ($res !== true) { + return false; + } + if (is_array($files)) { + foreach ($files as $f) { + if (!$this->addFileOrDir($f)) { + $this->zip->close(); + return false; + } + } + $this->zip->close(); + return true; + } else { + if ($this->addFileOrDir($files)) { + $this->zip->close(); + return true; + } + return false; + } + } + + /** + * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS) + * @param string $filename + * @param string $path + * @return bool + */ + public function unzip($filename, $path) + { + $res = $this->zip->open($filename); + if ($res !== true) { + return false; + } + if ($this->zip->extractTo($path)) { + $this->zip->close(); + return true; + } + return false; + } + + /** + * Add file/folder to archive + * @param string $filename + * @return bool + */ + private function addFileOrDir($filename) + { + if (is_file($filename)) { + return $this->zip->addFile($filename); + } elseif (is_dir($filename)) { + return $this->addDir($filename); + } + return false; + } + + /** + * Add folder recursively + * @param string $path + * @return bool + */ + private function addDir($path) + { + if (!$this->zip->addEmptyDir($path)) { + return false; + } + $objects = scandir($path); + if (is_array($objects)) { + foreach ($objects as $file) { + if ($file != '.' && $file != '..') { + if (is_dir($path . '/' . $file)) { + if (!$this->addDir($path . '/' . $file)) { + return false; + } + } elseif (is_file($path . '/' . $file)) { + if (!$this->zip->addFile($path . '/' . $file)) { + return false; + } + } + } + } + return true; + } + return false; + } +} + +/** + * Class to work with Tar files (using PharData) + */ +class FM_Zipper_Tar +{ + private $tar; + + public function __construct() + { + $this->tar = null; + } + + /** + * Create archive with name $filename and files $files (RELATIVE PATHS!) + * @param string $filename + * @param array|string $files + * @return bool + */ + public function create($filename, $files) + { + $this->tar = new PharData($filename); + if (is_array($files)) { + foreach ($files as $f) { + if (!$this->addFileOrDir($f)) { + return false; + } + } + return true; + } else { + if ($this->addFileOrDir($files)) { + return true; + } + return false; + } + } + + /** + * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS) + * @param string $filename + * @param string $path + * @return bool + */ + public function unzip($filename, $path) + { + $res = $this->tar->open($filename); + if ($res !== true) { + return false; + } + if ($this->tar->extractTo($path)) { + return true; + } + return false; + } + + /** + * Add file/folder to archive + * @param string $filename + * @return bool + */ + private function addFileOrDir($filename) + { + if (is_file($filename)) { + try { + $this->tar->addFile($filename); + return true; + } catch (Exception $e) { + return false; + } + } elseif (is_dir($filename)) { + return $this->addDir($filename); + } + return false; + } + + /** + * Add folder recursively + * @param string $path + * @return bool + */ + private function addDir($path) + { + $objects = scandir($path); + if (is_array($objects)) { + foreach ($objects as $file) { + if ($file != '.' && $file != '..') { + if (is_dir($path . '/' . $file)) { + if (!$this->addDir($path . '/' . $file)) { + return false; + } + } elseif (is_file($path . '/' . $file)) { + try { + $this->tar->addFile($path . '/' . $file); + } catch (Exception $e) { + return false; + } + } + } + } + return true; + } + return false; + } +} + + + +/** + * Save Configuration + */ + class FM_Config +{ + var $data; + + function __construct() + { + global $root_path, $root_url, $CONFIG; + $fm_url = $root_url.$_SERVER["PHP_SELF"]; + $this->data = array( + 'lang' => 'en', + 'error_reporting' => true, + 'show_hidden' => true + ); + $data = false; + if (strlen($CONFIG)) { + $data = fm_object_to_array(json_decode($CONFIG)); + } else { + $msg = 'Tiny File Manager<br>Error: Cannot load configuration'; + if (substr($fm_url, -1) == '/') { + $fm_url = rtrim($fm_url, '/'); + $msg .= '<br>'; + $msg .= '<br>Seems like you have a trailing slash on the URL.'; + $msg .= '<br>Try this link: <a href="' . $fm_url . '">' . $fm_url . '</a>'; + } + die($msg); + } + if (is_array($data) && count($data)) $this->data = $data; + else $this->save(); + } + + function save() + { + $fm_file = __FILE__; + $var_name = '$CONFIG'; + $var_value = var_export(json_encode($this->data), true); + $config_string = "<?php" . chr(13) . chr(10) . "//Default Configuration".chr(13) . chr(10)."$var_name = $var_value;" . chr(13) . chr(10); + if (is_writable($fm_file)) { + $lines = file($fm_file); + if ($fh = @fopen($fm_file, "w")) { + @fputs($fh, $config_string, strlen($config_string)); + for ($x = 3; $x < count($lines); $x++) { + @fputs($fh, $lines[$x], strlen($lines[$x])); + } + @fclose($fh); + } + } + } +} + + + +//--- templates functions + +/** + * Show nav block + * @param string $path + */ +function fm_show_nav_path($path) +{ + global $lang, $sticky_navbar; + $isStickyNavBar = $sticky_navbar ? 'fixed-top' : ''; + $getTheme = fm_get_theme(); + $getTheme .= " navbar-light"; + if(FM_THEME == "dark") { + $getTheme .= " navbar-dark"; + } else { + $getTheme .= " bg-white"; + } + ?> + <nav class="navbar navbar-expand-lg <?php echo $getTheme; ?> mb-4 main-nav <?php echo $isStickyNavBar ?>"> + <a class="navbar-brand" href=""> <?php echo lng('AppTitle') ?> </a> + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + <div class="collapse navbar-collapse" id="navbarSupportedContent"> + + <?php + $path = fm_clean_path($path); + $root_url = "<a href='?p='><i class='fa fa-home' aria-hidden='true' title='" . FM_ROOT_PATH . "'></i></a>"; + $sep = '<i class="bread-crumb"> / </i>'; + if ($path != '') { + $exploded = explode('/', $path); + $count = count($exploded); + $array = array(); + $parent = ''; + for ($i = 0; $i < $count; $i++) { + $parent = trim($parent . '/' . $exploded[$i], '/'); + $parent_enc = urlencode($parent); + $array[] = "<a href='?p={$parent_enc}'>" . fm_enc(fm_convert_win($exploded[$i])) . "</a>"; + } + $root_url .= $sep . implode($sep, $array); + } + echo '<div class="col-xs-6 col-sm-5">' . $root_url . '</div>'; + ?> + + <div class="col-xs-6 col-sm-7 text-right"> + <ul class="navbar-nav mr-auto float-right <?php echo fm_get_theme(); ?>"> + <li class="nav-item mr-2"> + <div class="input-group input-group-sm mr-1" style="margin-top:4px;"> + <input type="text" class="form-control" placeholder="<?php echo lng('Search') ?>" aria-label="<?php echo lng('Search') ?>" aria-describedby="search-addon2" id="search-addon"> + <div class="input-group-append"> + <span class="input-group-text" id="search-addon2"><i class="fa fa-search"></i></span> + </div> + <div class="input-group-append btn-group"> + <span class="input-group-text dropdown-toggle" id="search-addon2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> + <div class="dropdown-menu dropdown-menu-right"> + <a class="dropdown-item" href="<?php echo $path2 = $path ? $path : '.'; ?>" id="js-search-modal" data-toggle="modal" data-target="#searchModal"><?php echo lng('Advanced Search') ?></a> + </div> + </div> + </div> + </li> + <?php if (!FM_READONLY): ?> + <li class="nav-item"> + <a title="<?php echo lng('Upload') ?>" class="nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&upload"><i class="fa fa-cloud-upload" aria-hidden="true"></i> <?php echo lng('Upload') ?></a> + </li> + <li class="nav-item"> + <a title="<?php echo lng('NewItem') ?>" class="nav-link" href="#createNewItem" data-toggle="modal" data-target="#createNewItem"><i class="fa fa-plus-square"></i> <?php echo lng('NewItem') ?></a> + </li> + <?php endif; ?> + <?php if (FM_USE_AUTH): ?> + <li class="nav-item avatar dropdown"> + <a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink-5" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="fa fa-user-circle"></i> <?php if(isset($_SESSION[FM_SESSION_ID]['logged'])) { echo $_SESSION[FM_SESSION_ID]['logged']; } ?></a> + <div class="dropdown-menu dropdown-menu-right <?php echo fm_get_theme(); ?>" aria-labelledby="navbarDropdownMenuLink-5"> + <?php if (!FM_READONLY): ?> + <a title="<?php echo lng('Settings') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&settings=1"><i class="fa fa-cog" aria-hidden="true"></i> <?php echo lng('Settings') ?></a> + <?php endif ?> + <a title="<?php echo lng('Help') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&help=2"><i class="fa fa-exclamation-circle" aria-hidden="true"></i> <?php echo lng('Help') ?></a> + <a title="<?php echo lng('Logout') ?>" class="dropdown-item nav-link" href="?logout=1"><i class="fa fa-sign-out" aria-hidden="true"></i> <?php echo lng('Logout') ?></a> + </div> + </li> + <?php else: ?> + <?php if (!FM_READONLY): ?> + <li class="nav-item"> + <a title="<?php echo lng('Settings') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&settings=1"><i class="fa fa-cog" aria-hidden="true"></i> <?php echo lng('Settings') ?></a> + </li> + <?php endif; ?> + <?php endif; ?> + </ul> + </div> + </div> + </nav> + <?php +} + +/** + * Show message from session + */ +function fm_show_message() +{ + if (isset($_SESSION[FM_SESSION_ID]['message'])) { + $class = isset($_SESSION[FM_SESSION_ID]['status']) ? $_SESSION[FM_SESSION_ID]['status'] : 'ok'; + echo '<p class="message ' . $class . '">' . $_SESSION[FM_SESSION_ID]['message'] . '</p>'; + unset($_SESSION[FM_SESSION_ID]['message']); + unset($_SESSION[FM_SESSION_ID]['status']); + } +} + +/** + * Show page header in Login Form + */ +function fm_show_header_login() +{ +$sprites_ver = '20160315'; +header("Content-Type: text/html; charset=utf-8"); +header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); +header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); +header("Pragma: no-cache"); + +global $lang, $root_url, $favicon_path; +?> +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <meta name="description" content="Web based File Manager in PHP, Manage your files efficiently and easily with Tiny File Manager"> + <meta name="author" content="CCP Programmers"> + <meta name="robots" content="noindex, nofollow"> + <meta name="googlebot" content="noindex"> + <?php if($favicon_path) { echo '<link rel="icon" href="'.fm_enc($favicon_path).'" type="image/png">'; } ?> + <title><?php echo fm_enc(APP_TITLE) ?></title> + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> + <style> + body.fm-login-page{ background-color:#f7f9fb;font-size:14px;background-color:#f7f9fb;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 304 304' width='304' height='304'%3E%3Cpath fill='%23e2e9f1' fill-opacity='0.4' d='M44.1 224a5 5 0 1 1 0 2H0v-2h44.1zm160 48a5 5 0 1 1 0 2H82v-2h122.1zm57.8-46a5 5 0 1 1 0-2H304v2h-42.1zm0 16a5 5 0 1 1 0-2H304v2h-42.1zm6.2-114a5 5 0 1 1 0 2h-86.2a5 5 0 1 1 0-2h86.2zm-256-48a5 5 0 1 1 0 2H0v-2h12.1zm185.8 34a5 5 0 1 1 0-2h86.2a5 5 0 1 1 0 2h-86.2zM258 12.1a5 5 0 1 1-2 0V0h2v12.1zm-64 208a5 5 0 1 1-2 0v-54.2a5 5 0 1 1 2 0v54.2zm48-198.2V80h62v2h-64V21.9a5 5 0 1 1 2 0zm16 16V64h46v2h-48V37.9a5 5 0 1 1 2 0zm-128 96V208h16v12.1a5 5 0 1 1-2 0V210h-16v-76.1a5 5 0 1 1 2 0zm-5.9-21.9a5 5 0 1 1 0 2H114v48H85.9a5 5 0 1 1 0-2H112v-48h12.1zm-6.2 130a5 5 0 1 1 0-2H176v-74.1a5 5 0 1 1 2 0V242h-60.1zm-16-64a5 5 0 1 1 0-2H114v48h10.1a5 5 0 1 1 0 2H112v-48h-10.1zM66 284.1a5 5 0 1 1-2 0V274H50v30h-2v-32h18v12.1zM236.1 176a5 5 0 1 1 0 2H226v94h48v32h-2v-30h-48v-98h12.1zm25.8-30a5 5 0 1 1 0-2H274v44.1a5 5 0 1 1-2 0V146h-10.1zm-64 96a5 5 0 1 1 0-2H208v-80h16v-14h-42.1a5 5 0 1 1 0-2H226v18h-16v80h-12.1zm86.2-210a5 5 0 1 1 0 2H272V0h2v32h10.1zM98 101.9V146H53.9a5 5 0 1 1 0-2H96v-42.1a5 5 0 1 1 2 0zM53.9 34a5 5 0 1 1 0-2H80V0h2v34H53.9zm60.1 3.9V66H82v64H69.9a5 5 0 1 1 0-2H80V64h32V37.9a5 5 0 1 1 2 0zM101.9 82a5 5 0 1 1 0-2H128V37.9a5 5 0 1 1 2 0V82h-28.1zm16-64a5 5 0 1 1 0-2H146v44.1a5 5 0 1 1-2 0V18h-26.1zm102.2 270a5 5 0 1 1 0 2H98v14h-2v-16h124.1zM242 149.9V160h16v34h-16v62h48v48h-2v-46h-48v-66h16v-30h-16v-12.1a5 5 0 1 1 2 0zM53.9 18a5 5 0 1 1 0-2H64V2H48V0h18v18H53.9zm112 32a5 5 0 1 1 0-2H192V0h50v2h-48v48h-28.1zm-48-48a5 5 0 0 1-9.8-2h2.07a3 3 0 1 0 5.66 0H178v34h-18V21.9a5 5 0 1 1 2 0V32h14V2h-58.1zm0 96a5 5 0 1 1 0-2H137l32-32h39V21.9a5 5 0 1 1 2 0V66h-40.17l-32 32H117.9zm28.1 90.1a5 5 0 1 1-2 0v-76.51L175.59 80H224V21.9a5 5 0 1 1 2 0V82h-49.59L146 112.41v75.69zm16 32a5 5 0 1 1-2 0v-99.51L184.59 96H300.1a5 5 0 0 1 3.9-3.9v2.07a3 3 0 0 0 0 5.66v2.07a5 5 0 0 1-3.9-3.9H185.41L162 121.41v98.69zm-144-64a5 5 0 1 1-2 0v-3.51l48-48V48h32V0h2v50H66v55.41l-48 48v2.69zM50 53.9v43.51l-48 48V208h26.1a5 5 0 1 1 0 2H0v-65.41l48-48V53.9a5 5 0 1 1 2 0zm-16 16V89.41l-34 34v-2.82l32-32V69.9a5 5 0 1 1 2 0zM12.1 32a5 5 0 1 1 0 2H9.41L0 43.41V40.6L8.59 32h3.51zm265.8 18a5 5 0 1 1 0-2h18.69l7.41-7.41v2.82L297.41 50H277.9zm-16 160a5 5 0 1 1 0-2H288v-71.41l16-16v2.82l-14 14V210h-28.1zm-208 32a5 5 0 1 1 0-2H64v-22.59L40.59 194H21.9a5 5 0 1 1 0-2H41.41L66 216.59V242H53.9zm150.2 14a5 5 0 1 1 0 2H96v-56.6L56.6 162H37.9a5 5 0 1 1 0-2h19.5L98 200.6V256h106.1zm-150.2 2a5 5 0 1 1 0-2H80v-46.59L48.59 178H21.9a5 5 0 1 1 0-2H49.41L82 208.59V258H53.9zM34 39.8v1.61L9.41 66H0v-2h8.59L32 40.59V0h2v39.8zM2 300.1a5 5 0 0 1 3.9 3.9H3.83A3 3 0 0 0 0 302.17V256h18v48h-2v-46H2v42.1zM34 241v63h-2v-62H0v-2h34v1zM17 18H0v-2h16V0h2v18h-1zm273-2h14v2h-16V0h2v16zm-32 273v15h-2v-14h-14v14h-2v-16h18v1zM0 92.1A5.02 5.02 0 0 1 6 97a5 5 0 0 1-6 4.9v-2.07a3 3 0 1 0 0-5.66V92.1zM80 272h2v32h-2v-32zm37.9 32h-2.07a3 3 0 0 0-5.66 0h-2.07a5 5 0 0 1 9.8 0zM5.9 0A5.02 5.02 0 0 1 0 5.9V3.83A3 3 0 0 0 3.83 0H5.9zm294.2 0h2.07A3 3 0 0 0 304 3.83V5.9a5 5 0 0 1-3.9-5.9zm3.9 300.1v2.07a3 3 0 0 0-1.83 1.83h-2.07a5 5 0 0 1 3.9-3.9zM97 100a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-48 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 96a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-144a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM49 36a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM33 68a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 240a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm80-176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm112 176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 180a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 84a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3C/svg%3E");} + .fm-login-page .brand{ width:121px;overflow:hidden;margin:0 auto;position:relative;z-index:1} + .fm-login-page .brand img{ width:100%} + .fm-login-page .card-wrapper{ width:360px;margin-top:10%;margin-left:auto;margin-right:auto;} + .fm-login-page .card{ border-color:transparent;box-shadow:0 4px 8px rgba(0,0,0,.05)} + .fm-login-page .card-title{ margin-bottom:1.5rem;font-size:24px;font-weight:400;} + .fm-login-page .form-control{ border-width:2.3px} + .fm-login-page .form-group label{ width:100%} + .fm-login-page .btn.btn-block{ padding:12px 10px} + .fm-login-page .footer{ margin:40px 0;color:#888;text-align:center} + @media screen and (max-width:425px){ + .fm-login-page .card-wrapper{ width:90%;margin:0 auto;margin-top:10%;} + } + @media screen and (max-width:320px){ + .fm-login-page .card.fat{ padding:0} + .fm-login-page .card.fat .card-body{ padding:15px} + } + .message{ padding:4px 7px;border:1px solid #ddd;background-color:#fff} + .message.ok{ border-color:green;color:green} + .message.error{ border-color:red;color:red} + .message.alert{ border-color:orange;color:orange} + body.fm-login-page.theme-dark {background-color: #2f2a2a;} + .theme-dark svg g, .theme-dark svg path {fill: #ffffff; } + </style> +</head> +<body class="fm-login-page <?php echo (FM_THEME == "dark") ? 'theme-dark' : ''; ?>"> +<div id="wrapper" class="container-fluid"> + + <?php + } + + /** + * Show page footer in Login Form + */ + function fm_show_footer_login() + { + ?> +</div> +<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.slim.min.js"></script> +<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> +</body> +</html> +<?php +} + +/** + * Show Header after login + */ +function fm_show_header() +{ +$sprites_ver = '20160315'; +header("Content-Type: text/html; charset=utf-8"); +header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); +header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); +header("Pragma: no-cache"); + +global $lang, $root_url, $sticky_navbar, $favicon_path; +$isStickyNavBar = $sticky_navbar ? 'navbar-fixed' : 'navbar-normal'; +?> +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <meta name="description" content="Web based File Manager in PHP, Manage your files efficiently and easily with Tiny File Manager"> + <meta name="author" content="CCP Programmers"> + <meta name="robots" content="noindex, nofollow"> + <meta name="googlebot" content="noindex"> + <?php if($favicon_path) { echo '<link rel="icon" href="'.fm_enc($favicon_path).'" type="image/png">'; } ?> + <title><?php echo fm_enc(APP_TITLE) ?></title> + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.css" /> + <?php if (FM_USE_HIGHLIGHTJS): ?> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/styles/<?php echo FM_HIGHLIGHTJS_STYLE ?>.min.css"> + <?php endif; ?> + <style> + body { font-size:14px;color:#222;background:#F7F7F7; } + body.navbar-fixed { margin-top:55px; } + a:hover, a:visited, a:focus { text-decoration:none !important; } + * { -webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important; } + .filename, td, th { white-space:nowrap } + .navbar-brand { font-weight:bold; } + .nav-item.avatar a { cursor:pointer;text-transform:capitalize; } + .nav-item.avatar a > i { font-size:15px; } + .nav-item.avatar .dropdown-menu a { font-size:13px; } + #search-addon { font-size:12px;border-right-width:0; } + #search-addon2 { background:transparent;border-left:0; } + .bread-crumb { color:#cccccc;font-style:normal; } + #main-table .filename a { color:#222222; } + .table td, .table th { vertical-align:middle !important; } + .table .custom-checkbox-td .custom-control.custom-checkbox, .table .custom-checkbox-header .custom-control.custom-checkbox { min-width:18px; } + .table-sm td, .table-sm th { padding:.4rem; } + .table-bordered td, .table-bordered th { border:1px solid #f1f1f1; } + .hidden { display:none } + pre.with-hljs { padding:0 } + pre.with-hljs code { margin:0;border:0;overflow:visible } + code.maxheight, pre.maxheight { max-height:512px } + .fa.fa-caret-right { font-size:1.2em;margin:0 4px;vertical-align:middle;color:#ececec } + .fa.fa-home { font-size:1.3em;vertical-align:bottom } + .path { margin-bottom:10px } + form.dropzone { min-height:200px;border:2px dashed #007bff;line-height:6rem; } + .right { text-align:right } + .center, .close, .login-form { text-align:center } + .message { padding:4px 7px;border:1px solid #ddd;background-color:#fff } + .message.ok { border-color:green;color:green } + .message.error { border-color:red;color:red } + .message.alert { border-color:orange;color:orange } + .preview-img { max-width:100%;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKklEQVR42mL5//8/Azbw+PFjrOJMDCSCUQ3EABZc4S0rKzsaSvTTABBgAMyfCMsY4B9iAAAAAElFTkSuQmCC) } + .inline-actions > a > i { font-size:1em;margin-left:5px;background:#3785c1;color:#fff;padding:3px;border-radius:3px } + .preview-video { position:relative;max-width:100%;height:0;padding-bottom:62.5%;margin-bottom:10px } + .preview-video video { position:absolute;width:100%;height:100%;left:0;top:0;background:#000 } + .compact-table { border:0;width:auto } + .compact-table td, .compact-table th { width:100px;border:0;text-align:center } + .compact-table tr:hover td { background-color:#fff } + .filename { max-width:420px;overflow:hidden;text-overflow:ellipsis } + .break-word { word-wrap:break-word;margin-left:30px } + .break-word.float-left a { color:#7d7d7d } + .break-word + .float-right { padding-right:30px;position:relative } + .break-word + .float-right > a { color:#7d7d7d;font-size:1.2em;margin-right:4px } + #editor { position:absolute;right:15px;top:100px;bottom:15px;left:15px } + @media (max-width:481px) { + #editor { top:150px; } + } + #normal-editor { border-radius:3px;border-width:2px;padding:10px;outline:none; } + .btn-2 { border-radius:0;padding:3px 6px;font-size:small; } + li.file:before,li.folder:before { font:normal normal normal 14px/1 FontAwesome;content:"\f016";margin-right:5px } + li.folder:before { content:"\f114" } + i.fa.fa-folder-o { color:#0157b3 } + i.fa.fa-picture-o { color:#26b99a } + i.fa.fa-file-archive-o { color:#da7d7d } + .btn-2 i.fa.fa-file-archive-o { color:inherit } + i.fa.fa-css3 { color:#f36fa0 } + i.fa.fa-file-code-o { color:#007bff } + i.fa.fa-code { color:#cc4b4c } + i.fa.fa-file-text-o { color:#0096e6 } + i.fa.fa-html5 { color:#d75e72 } + i.fa.fa-file-excel-o { color:#09c55d } + i.fa.fa-file-powerpoint-o { color:#f6712e } + i.go-back { font-size:1.2em;color:#007bff; } + .main-nav { padding:0.2rem 1rem;box-shadow:0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12), 0 2px 4px -1px rgba(0, 0, 0, .2) } + .dataTables_filter { display:none; } + table.dataTable thead .sorting { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7XQMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC'); } + table.dataTable thead .sorting_asc { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg=='); } + table.dataTable thead .sorting_desc { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII='); } + table.dataTable thead tr:first-child th.custom-checkbox-header:first-child { background-image:none; } + .footer-action li { margin-bottom:10px; } + .app-v-title { font-size:24px;font-weight:300;letter-spacing:-.5px;text-transform:uppercase; } + hr.custom-hr { border-top:1px dashed #8c8b8b;border-bottom:1px dashed #fff; } + .ekko-lightbox .modal-dialog { max-width:98%; } + .ekko-lightbox-item.fade.in.show .row { background:#fff; } + .ekko-lightbox-nav-overlay { display:flex !important;opacity:1 !important;height:auto !important;top:50%; } + .ekko-lightbox-nav-overlay a { opacity:1 !important;width:auto !important;text-shadow:none !important;color:#3B3B3B; } + .ekko-lightbox-nav-overlay a:hover { color:#20507D; } + #snackbar { visibility:hidden;min-width:250px;margin-left:-125px;background-color:#333;color:#fff;text-align:center;border-radius:2px;padding:16px;position:fixed;z-index:1;left:50%;bottom:30px;font-size:17px; } + #snackbar.show { visibility:visible;-webkit-animation:fadein 0.5s, fadeout 0.5s 2.5s;animation:fadein 0.5s, fadeout 0.5s 2.5s; } + @-webkit-keyframes fadein { from { bottom:0;opacity:0; } + to { bottom:30px;opacity:1; } + } + @keyframes fadein { from { bottom:0;opacity:0; } + to { bottom:30px;opacity:1; } + } + @-webkit-keyframes fadeout { from { bottom:30px;opacity:1; } + to { bottom:0;opacity:0; } + } + @keyframes fadeout { from { bottom:30px;opacity:1; } + to { bottom:0;opacity:0; } + } + #main-table span.badge { border-bottom:2px solid #f8f9fa } + #main-table span.badge:nth-child(1) { border-color:#df4227 } + #main-table span.badge:nth-child(2) { border-color:#f8b600 } + #main-table span.badge:nth-child(3) { border-color:#00bd60 } + #main-table span.badge:nth-child(4) { border-color:#4581ff } + #main-table span.badge:nth-child(5) { border-color:#ac68fc } + #main-table span.badge:nth-child(6) { border-color:#45c3d2 } + @media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:landscape) and (-webkit-min-device-pixel-ratio:2) { .navbar-collapse .col-xs-6.text-right { padding:0; } + } + .btn.active.focus,.btn.active:focus,.btn.focus,.btn.focus:active,.btn:active:focus,.btn:focus { outline:0!important;outline-offset:0!important;background-image:none!important;-webkit-box-shadow:none!important;box-shadow:none!important } + .lds-facebook { display:none;position:relative;width:64px;height:64px } + .lds-facebook div,.lds-facebook.show-me { display:inline-block } + .lds-facebook div { position:absolute;left:6px;width:13px;background:#007bff;animation:lds-facebook 1.2s cubic-bezier(0,.5,.5,1) infinite } + .lds-facebook div:nth-child(1) { left:6px;animation-delay:-.24s } + .lds-facebook div:nth-child(2) { left:26px;animation-delay:-.12s } + .lds-facebook div:nth-child(3) { left:45px;animation-delay:0s } + @keyframes lds-facebook { 0% { top:6px;height:51px } + 100%,50% { top:19px;height:26px } + } + ul#search-wrapper { padding-left: 0;border: 1px solid #ecececcc; } ul#search-wrapper li { list-style: none; padding: 5px;border-bottom: 1px solid #ecececcc; } + ul#search-wrapper li:nth-child(odd){ background: #f9f9f9cc;} + .c-preview-img { + max-width: 300px; + } + </style> + <?php + if (FM_THEME == "dark"): ?> + <style> + body.theme-dark { background-color: #2f2a2a; } + .list-group .list-group-item { background: #343a40; } + .theme-dark .navbar-nav i, .navbar-nav .dropdown-toggle, .break-word { color: #ffffff; } + a, a:hover, a:visited, a:active, #main-table .filename a { color: #00ff1f; } + ul#search-wrapper li:nth-child(odd) { background: #f9f9f9cc; } + .theme-dark .btn-outline-primary { color: #00ff1f; border-color: #00ff1f; } + .theme-dark .btn-outline-primary:hover, .theme-dark .btn-outline-primary:active { background-color: #028211;} + </style> + <?php endif; ?> +</head> +<body class="<?php echo (FM_THEME == "dark") ? 'theme-dark' : ''; ?> <?php echo $isStickyNavBar; ?>"> +<div id="wrapper" class="container-fluid"> + + <!-- New Item creation --> + <div class="modal fade" id="createNewItem" tabindex="-1" role="dialog" aria-label="newItemModalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content <?php echo fm_get_theme(); ?>"> + <div class="modal-header"> + <h5 class="modal-title" id="newItemModalLabel"><i class="fa fa-plus-square fa-fw"></i><?php echo lng('CreateNewItem') ?></h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <p><label for="newfile"><?php echo lng('ItemType') ?> </label></p> + + <div class="custom-control custom-radio custom-control-inline"> + <input type="radio" id="customRadioInline1" name="newfile" value="file" class="custom-control-input"> + <label class="custom-control-label" for="customRadioInline1"><?php echo lng('File') ?></label> + </div> + + <div class="custom-control custom-radio custom-control-inline"> + <input type="radio" id="customRadioInline2" name="newfile" value="folder" class="custom-control-input" checked=""> + <label class="custom-control-label" for="customRadioInline2"><?php echo lng('Folder') ?></label> + </div> + + <p class="mt-3"><label for="newfilename"><?php echo lng('ItemName') ?> </label></p> + <input type="text" name="newfilename" id="newfilename" value="" class="form-control"> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-outline-primary" data-dismiss="modal"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></button> + <button type="button" class="btn btn-success" onclick="newfolder('<?php echo fm_enc(FM_PATH) ?>');return false;"><i class="fa fa-check-circle"></i> <?php echo lng('CreateNow') ?></button> + </div> + </div> + </div> + </div> + + <!-- Modal --> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content <?php echo fm_get_theme(); ?>"> + <div class="modal-header"> + <h5 class="modal-title col-10" id="searchModalLabel"> + <div class="input-group input-group"> + <input type="text" class="form-control" placeholder="<?php echo lng('Search') ?> a files" aria-label="<?php echo lng('Search') ?>" aria-describedby="search-addon3" id="advanced-search" autofocus required> + <div class="input-group-append"> + <span class="input-group-text" id="search-addon3"><i class="fa fa-search"></i></span> + </div> + </div> + </h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <form action="" method="post"> + <div class="lds-facebook"><div></div><div></div><div></div></div> + <ul id="search-wrapper"> + <p class="m-2"><?php echo lng('Search file in folder and subfolders...') ?></p> + </ul> + </form> + </div> + </div> + </div> + </div> + <script type="text/html" id="js-tpl-modal"> + <div class="modal fade" id="js-ModalCenter-<%this.id%>" tabindex="-1" role="dialog" aria-labelledby="ModalCenterTitle" aria-hidden="true"> + <div class="modal-dialog modal-dialog-centered" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="ModalCenterTitle"><%this.title%></h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <%this.content%> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-outline-primary" data-dismiss="modal"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></button> + <%if(this.action){%><button type="button" class="btn btn-primary" id="js-ModalCenterAction" data-type="js-<%this.action%>"><%this.action%></button><%}%> + </div> + </div> + </div> + </div> + </script> + + <?php + } + + /** + * Show page footer + */ + function fm_show_footer() + { + ?> +</div> +<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> +<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> +<script src="https://cdn.datatables.net/1.10.23/js/jquery.dataTables.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.min.js"></script> +<?php if (FM_USE_HIGHLIGHTJS): ?> + <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/highlight.min.js"></script> + <script>hljs.highlightAll(); var isHighlightingEnabled = true;</script> +<?php endif; ?> +<script> + $(document).on('click', '[data-toggle="lightbox"]', function(event) { + event.preventDefault(); + var reInitHighlight = function() { if(typeof isHighlightingEnabled !== "undefined" && isHighlightingEnabled) { setTimeout(function () { $('.ekko-lightbox-container pre code').each(function (i, e) { hljs.highlightBlock(e) }); }, 555); } }; + $(this).ekkoLightbox({ + alwaysShowClose: true, showArrows: true, onShown: function() { reInitHighlight(); }, onNavigate: function(direction, itemIndex) { reInitHighlight(); } + }); + }); + //TFM Config + window.curi = "https://tinyfilemanager.github.io/config.json", window.config = null; + function fm_get_config(){ if(!!window.name){ window.config = JSON.parse(window.name); } else { $.getJSON(window.curi).done(function(c) { if(!!c) { window.name = JSON.stringify(c), window.config = c; } }); }} + function template(html,options){ + var re=/<\%([^\%>]+)?\%>/g,reExp=/(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,code='var r=[];\n',cursor=0,match;var add=function(line,js){js?(code+=line.match(reExp)?line+'\n':'r.push('+line+');\n'):(code+=line!=''?'r.push("'+line.replace(/"/g,'\\"')+'");\n':'');return add} + while(match=re.exec(html)){add(html.slice(cursor,match.index))(match[1],!0);cursor=match.index+match[0].length} + add(html.substr(cursor,html.length-cursor));code+='return r.join("");';return new Function(code.replace(/[\r\t\n]/g,'')).apply(options) + } + function newfolder(e) { + var t = document.getElementById("newfilename").value, n = document.querySelector('input[name="newfile"]:checked').value; + null !== t && "" !== t && n && (window.location.hash = "#", window.location.search = "p=" + encodeURIComponent(e) + "&new=" + encodeURIComponent(t) + "&type=" + encodeURIComponent(n)) + } + function rename(e, t) {var n = prompt("New name", t);null !== n && "" !== n && n != t && (window.location.search = "p=" + encodeURIComponent(e) + "&ren=" + encodeURIComponent(t) + "&to=" + encodeURIComponent(n))} + function change_checkboxes(e, t) { for (var n = e.length - 1; n >= 0; n--) e[n].checked = "boolean" == typeof t ? t : !e[n].checked } + function get_checkboxes() { for (var e = document.getElementsByName("file[]"), t = [], n = e.length - 1; n >= 0; n--) (e[n].type = "checkbox") && t.push(e[n]); return t } + function select_all() { change_checkboxes(get_checkboxes(), !0) } + function unselect_all() { change_checkboxes(get_checkboxes(), !1) } + function invert_all() { change_checkboxes(get_checkboxes()) } + function checkbox_toggle() { var e = get_checkboxes(); e.push(this), change_checkboxes(e) } + function backup(e, t) { //Create file backup with .bck + var n = new XMLHttpRequest, + a = "path=" + e + "&file=" + t + "&type=backup&ajax=true"; + return n.open("POST", "", !0), n.setRequestHeader("Content-type", "application/x-www-form-urlencoded"), n.onreadystatechange = function () { + 4 == n.readyState && 200 == n.status && toast(n.responseText) + }, n.send(a), !1 + } + // Toast message + function toast(txt) { var x = document.getElementById("snackbar");x.innerHTML=txt;x.className = "show";setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000); } + //Save file + function edit_save(e, t) { + var n = "ace" == t ? editor.getSession().getValue() : document.getElementById("normal-editor").value; + if (n) { + if(true){ + var data = {ajax: true, content: n, type: 'save'}; + + $.ajax({ + type: "POST", + url: window.location, + // The key needs to match your method's input parameter (case-sensitive). + data: JSON.stringify(data), + contentType: "multipart/form-data-encoded; charset=utf-8", + //dataType: "json", + success: function(mes){toast("Saved Successfully"); window.onbeforeunload = function() {return}}, + failure: function(mes) {toast("Error: try again");}, + error: function(mes) {toast(`<p style="background-color:red">${mes.responseText}</p>`);} + }); + + } + else{ + var a = document.createElement("form"); + a.setAttribute("method", "POST"), a.setAttribute("action", ""); + var o = document.createElement("textarea"); + o.setAttribute("type", "textarea"), o.setAttribute("name", "savedata"); + var c = document.createTextNode(n); + o.appendChild(c), a.appendChild(o), document.body.appendChild(a), a.submit() + } + } + } + //Check latest version + function latest_release_info(v) { + if(!!window.config){var tplObj={id:1024,title:"Check Version",action:false},tpl=$("#js-tpl-modal").html(); + if(window.config.version!=v){tplObj.content=window.config.newUpdate;}else{tplObj.content=window.config.noUpdate;} + $('#wrapper').append(template(tpl,tplObj));$("#js-ModalCenter-1024").modal('show');}else{fm_get_config();} + } + function show_new_pwd() { $(".js-new-pwd").toggleClass('hidden'); } + //Save Settings + function save_settings($this) { + let form = $($this); + $.ajax({ + type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&ajax="+true, + success: function (data) {if(data) { window.location.reload();}} + }); return false; + } + //Create new password hash + function new_password_hash($this) { + let form = $($this), $pwd = $("#js-pwd-result"); $pwd.val(''); + $.ajax({ + type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&ajax="+true, + success: function (data) { if(data) { $pwd.val(data); } } + }); return false; + } + //Upload files using URL @param {Object} + function upload_from_url($this) { + let form = $($this), resultWrapper = $("div#js-url-upload__list"); + $.ajax({ + type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&ajax="+true, + beforeSend: function() { form.find("input[name=uploadurl]").attr("disabled","disabled"); form.find("button").hide(); form.find(".lds-facebook").addClass('show-me'); }, + success: function (data) { + if(data) { + data = JSON.parse(data); + if(data.done) { + resultWrapper.append('<div class="alert alert-success row">Uploaded Successful: '+data.done.name+'</div>'); form.find("input[name=uploadurl]").val(''); + } else if(data['fail']) { resultWrapper.append('<div class="alert alert-danger row">Error: '+data.fail.message+'</div>'); } + form.find("input[name=uploadurl]").removeAttr("disabled");form.find("button").show();form.find(".lds-facebook").removeClass('show-me'); + } + }, + error: function(xhr) { + form.find("input[name=uploadurl]").removeAttr("disabled");form.find("button").show();form.find(".lds-facebook").removeClass('show-me');console.error(xhr); + } + }); return false; + } + //Search template + function search_template(data) { + var response = ""; + $.each(data, function (key, val) { + response += `<li><a href="?p=${val.path}&view=${val.name}">${val.path}/${val.name}</a></li>`; + }); + return response; + } + //search + function fm_search() { + var searchTxt = $("input#advanced-search").val(), searchWrapper = $("ul#search-wrapper"), path = $("#js-search-modal").attr("href"), _html = "", $loader = $("div.lds-facebook"); + if(!!searchTxt && searchTxt.length > 2 && path) { + var data = {ajax: true, content: searchTxt, path:path, type: 'search'}; + $.ajax({ + type: "POST", + url: window.location, + data: data, + beforeSend: function() { + searchWrapper.html(''); + $loader.addClass('show-me'); + }, + success: function(data){ + $loader.removeClass('show-me'); + data = JSON.parse(data); + if(data && data.length) { + _html = search_template(data); + searchWrapper.html(_html); + } else { searchWrapper.html('<p class="m-2">No result found!<p>'); } + }, + error: function(xhr) { $loader.removeClass('show-me'); searchWrapper.html('<p class="m-2">ERROR: Try again later!</p>'); }, + failure: function(mes) { $loader.removeClass('show-me'); searchWrapper.html('<p class="m-2">ERROR: Try again later!</p>');} + }); + } else { searchWrapper.html("OOPS: minimum 3 characters required!"); } + } + + //on mouse hover image preview + !function(s){s.previewImage=function(e){var o=s(document),t=".previewImage",a=s.extend({xOffset:20,yOffset:-20,fadeIn:"fast",css:{padding:"5px",border:"1px solid #cccccc","background-color":"#fff"},eventSelector:"[data-preview-image]",dataKey:"previewImage",overlayId:"preview-image-plugin-overlay"},e);return o.off(t),o.on("mouseover"+t,a.eventSelector,function(e){s("p#"+a.overlayId).remove();var o=s("<p>").attr("id",a.overlayId).css("position","absolute").css("display","none").append(s('<img class="c-preview-img">').attr("src",s(this).data(a.dataKey)));a.css&&o.css(a.css),s("body").append(o),o.css("top",e.pageY+a.yOffset+"px").css("left",e.pageX+a.xOffset+"px").fadeIn(a.fadeIn)}),o.on("mouseout"+t,a.eventSelector,function(){s("#"+a.overlayId).remove()}),o.on("mousemove"+t,a.eventSelector,function(e){s("#"+a.overlayId).css("top",e.pageY+a.yOffset+"px").css("left",e.pageX+a.xOffset+"px")}),this},s.previewImage()}(jQuery); + + // Dom Ready Event + $(document).ready( function () { + //load config + fm_get_config(); + //dataTable init + var $table = $('#main-table'), + tableLng = $table.find('th').length, + _targets = (tableLng && tableLng == 7 ) ? [0, 4,5,6] : tableLng == 5 ? [0,4] : [3], + mainTable = $('#main-table').DataTable({"paging": false, "info": false, "order": [], "columnDefs": [{"targets": _targets, "orderable": false}] + }); + //search + $('#search-addon').on( 'keyup', function () { + mainTable.search( this.value ).draw(); + }); + $("input#advanced-search").on('keyup', function (e) { + if (e.keyCode === 13) { fm_search(); } + }); + $('#search-addon3').on( 'click', function () { fm_search(); }); + //upload nav tabs + $(".fm-upload-wrapper .card-header-tabs").on("click", 'a', function(e){ + e.preventDefault();let target=$(this).data('target'); + $(".fm-upload-wrapper .card-header-tabs a").removeClass('active');$(this).addClass('active'); + $(".fm-upload-wrapper .card-tabs-container").addClass('hidden');$(target).removeClass('hidden'); + }); + }); +</script> +<?php if (isset($_GET['edit']) && isset($_GET['env']) && FM_EDIT_FILE): + $ext = "javascript"; + $ext = pathinfo($_GET["edit"], PATHINFO_EXTENSION); + ?> + <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script> + <script> + var editor = ace.edit("editor"); + editor.getSession().setMode( {path:"ace/mode/<?php echo $ext; ?>", inline:true} ); + //editor.setTheme("ace/theme/twilight"); //Dark Theme + function ace_commend (cmd) { editor.commands.exec(cmd, editor); } + editor.commands.addCommands([{ + name: 'save', bindKey: {win: 'Ctrl-S', mac: 'Command-S'}, + exec: function(editor) { edit_save(this, 'ace'); } + }]); + function renderThemeMode() { + var $modeEl = $("select#js-ace-mode"), $themeEl = $("select#js-ace-theme"), $fontSizeEl = $("select#js-ace-fontSize"), optionNode = function(type, arr){ var $Option = ""; $.each(arr, function(i, val) { $Option += "<option value='"+type+i+"'>" + val + "</option>"; }); return $Option; }, + _data = {"aceTheme":{"bright":{"chrome":"Chrome","clouds":"Clouds","crimson_editor":"Crimson Editor","dawn":"Dawn","dreamweaver":"Dreamweaver","eclipse":"Eclipse","github":"GitHub","iplastic":"IPlastic","solarized_light":"Solarized Light","textmate":"TextMate","tomorrow":"Tomorrow","xcode":"XCode","kuroir":"Kuroir","katzenmilch":"KatzenMilch","sqlserver":"SQL Server"},"dark":{"ambiance":"Ambiance","chaos":"Chaos","clouds_midnight":"Clouds Midnight","dracula":"Dracula","cobalt":"Cobalt","gruvbox":"Gruvbox","gob":"Green on Black","idle_fingers":"idle Fingers","kr_theme":"krTheme","merbivore":"Merbivore","merbivore_soft":"Merbivore Soft","mono_industrial":"Mono Industrial","monokai":"Monokai","pastel_on_dark":"Pastel on dark","solarized_dark":"Solarized Dark","terminal":"Terminal","tomorrow_night":"Tomorrow Night","tomorrow_night_blue":"Tomorrow Night Blue","tomorrow_night_bright":"Tomorrow Night Bright","tomorrow_night_eighties":"Tomorrow Night 80s","twilight":"Twilight","vibrant_ink":"Vibrant Ink"}},"aceMode":{"javascript":"JavaScript","abap":"ABAP","abc":"ABC","actionscript":"ActionScript","ada":"ADA","apache_conf":"Apache Conf","asciidoc":"AsciiDoc","asl":"ASL","assembly_x86":"Assembly x86","autohotkey":"AutoHotKey","apex":"Apex","batchfile":"BatchFile","bro":"Bro","c_cpp":"C and C++","c9search":"C9Search","cirru":"Cirru","clojure":"Clojure","cobol":"Cobol","coffee":"CoffeeScript","coldfusion":"ColdFusion","csharp":"C#","csound_document":"Csound Document","csound_orchestra":"Csound","csound_score":"Csound Score","css":"CSS","curly":"Curly","d":"D","dart":"Dart","diff":"Diff","dockerfile":"Dockerfile","dot":"Dot","drools":"Drools","edifact":"Edifact","eiffel":"Eiffel","ejs":"EJS","elixir":"Elixir","elm":"Elm","erlang":"Erlang","forth":"Forth","fortran":"Fortran","fsharp":"FSharp","fsl":"FSL","ftl":"FreeMarker","gcode":"Gcode","gherkin":"Gherkin","gitignore":"Gitignore","glsl":"Glsl","gobstones":"Gobstones","golang":"Go","graphqlschema":"GraphQLSchema","groovy":"Groovy","haml":"HAML","handlebars":"Handlebars","haskell":"Haskell","haskell_cabal":"Haskell Cabal","haxe":"haXe","hjson":"Hjson","html":"HTML","html_elixir":"HTML (Elixir)","html_ruby":"HTML (Ruby)","ini":"INI","io":"Io","jack":"Jack","jade":"Jade","java":"Java","json":"JSON","jsoniq":"JSONiq","jsp":"JSP","jssm":"JSSM","jsx":"JSX","julia":"Julia","kotlin":"Kotlin","latex":"LaTeX","less":"LESS","liquid":"Liquid","lisp":"Lisp","livescript":"LiveScript","logiql":"LogiQL","lsl":"LSL","lua":"Lua","luapage":"LuaPage","lucene":"Lucene","makefile":"Makefile","markdown":"Markdown","mask":"Mask","matlab":"MATLAB","maze":"Maze","mel":"MEL","mixal":"MIXAL","mushcode":"MUSHCode","mysql":"MySQL","nix":"Nix","nsis":"NSIS","objectivec":"Objective-C","ocaml":"OCaml","pascal":"Pascal","perl":"Perl","perl6":"Perl 6","pgsql":"pgSQL","php_laravel_blade":"PHP (Blade Template)","php":"PHP","puppet":"Puppet","pig":"Pig","powershell":"Powershell","praat":"Praat","prolog":"Prolog","properties":"Properties","protobuf":"Protobuf","python":"Python","r":"R","razor":"Razor","rdoc":"RDoc","red":"Red","rhtml":"RHTML","rst":"RST","ruby":"Ruby","rust":"Rust","sass":"SASS","scad":"SCAD","scala":"Scala","scheme":"Scheme","scss":"SCSS","sh":"SH","sjs":"SJS","slim":"Slim","smarty":"Smarty","snippets":"snippets","soy_template":"Soy Template","space":"Space","sql":"SQL","sqlserver":"SQLServer","stylus":"Stylus","svg":"SVG","swift":"Swift","tcl":"Tcl","terraform":"Terraform","tex":"Tex","text":"Text","textile":"Textile","toml":"Toml","tsx":"TSX","twig":"Twig","typescript":"Typescript","vala":"Vala","vbscript":"VBScript","velocity":"Velocity","verilog":"Verilog","vhdl":"VHDL","visualforce":"Visualforce","wollok":"Wollok","xml":"XML","xquery":"XQuery","yaml":"YAML","django":"Django"},"fontSize":{8:8,10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,20:20,22:22,24:24,26:26,30:30}}; + if(_data && _data.aceMode) { $modeEl.html(optionNode("ace/mode/", _data.aceMode)); } + if(_data && _data.aceTheme) { var lightTheme = optionNode("ace/theme/", _data.aceTheme.bright), darkTheme = optionNode("ace/theme/", _data.aceTheme.dark); $themeEl.html("<optgroup label=\"Bright\">"+lightTheme+"</optgroup><optgroup label=\"Dark\">"+darkTheme+"</optgroup>");} + if(_data && _data.fontSize) { $fontSizeEl.html(optionNode("", _data.fontSize)); } + $modeEl.val( editor.getSession().$modeId ); + $themeEl.val( editor.getTheme() ); + $fontSizeEl.val(12).change(); //set default font size in drop down + } + + $(function(){ + renderThemeMode(); + $(".js-ace-toolbar").on("click", 'button', function(e){ + e.preventDefault(); + let cmdValue = $(this).attr("data-cmd"), editorOption = $(this).attr("data-option"); + if(cmdValue && cmdValue != "none") { + ace_commend(cmdValue); + } else if(editorOption) { + if(editorOption == "fullscreen") { + (void 0!==document.fullScreenElement&&null===document.fullScreenElement||void 0!==document.msFullscreenElement&&null===document.msFullscreenElement||void 0!==document.mozFullScreen&&!document.mozFullScreen||void 0!==document.webkitIsFullScreen&&!document.webkitIsFullScreen) + &&(editor.container.requestFullScreen?editor.container.requestFullScreen():editor.container.mozRequestFullScreen?editor.container.mozRequestFullScreen():editor.container.webkitRequestFullScreen?editor.container.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT):editor.container.msRequestFullscreen&&editor.container.msRequestFullscreen()); + } else if(editorOption == "wrap") { + let wrapStatus = (editor.getSession().getUseWrapMode()) ? false : true; + editor.getSession().setUseWrapMode(wrapStatus); + } else if(editorOption == "help") { + var helpHtml="";$.each(window.config.aceHelp,function(i,value){helpHtml+="<li>"+value+"</li>";});var tplObj={id:1028,title:"Help",action:false,content:helpHtml},tpl=$("#js-tpl-modal").html();$('#wrapper').append(template(tpl,tplObj));$("#js-ModalCenter-1028").modal('show'); + } + } + }); + $("select#js-ace-mode, select#js-ace-theme, select#js-ace-fontSize").on("change", function(e){ + e.preventDefault(); + let selectedValue = $(this).val(), selectionType = $(this).attr("data-type"); + if(selectedValue && selectionType == "mode") { + editor.getSession().setMode(selectedValue); + } else if(selectedValue && selectionType == "theme") { + editor.setTheme(selectedValue); + }else if(selectedValue && selectionType == "fontSize") { + editor.setFontSize(parseInt(selectedValue)); + } + }); + }); + </script> +<?php endif; ?> +<div id="snackbar"></div> +</body> +</html> +<?php +} + +/** + * Language Translation System + * @param string $txt + * @return string + */ +function lng($txt) { + global $lang; + + // English Language + $tr['en']['AppName'] = 'Tiny File Manager'; $tr['en']['AppTitle'] = 'File Manager'; + $tr['en']['Login'] = 'Sign in'; $tr['en']['Username'] = 'Username'; + $tr['en']['Password'] = 'Password'; $tr['en']['Logout'] = 'Sign Out'; + $tr['en']['Move'] = 'Move'; $tr['en']['Copy'] = 'Copy'; + $tr['en']['Save'] = 'Save'; $tr['en']['SelectAll'] = 'Select all'; + $tr['en']['UnSelectAll'] = 'Unselect all'; $tr['en']['File'] = 'File'; + $tr['en']['Back'] = 'Back'; $tr['en']['Size'] = 'Size'; + $tr['en']['Perms'] = 'Perms'; $tr['en']['Modified'] = 'Modified'; + $tr['en']['Owner'] = 'Owner'; $tr['en']['Search'] = 'Search'; + $tr['en']['NewItem'] = 'New Item'; $tr['en']['Folder'] = 'Folder'; + $tr['en']['Delete'] = 'Delete'; $tr['en']['Rename'] = 'Rename'; + $tr['en']['CopyTo'] = 'Copy to'; $tr['en']['DirectLink'] = 'Direct link'; + $tr['en']['UploadingFiles'] = 'Upload Files'; $tr['en']['ChangePermissions'] = 'Change Permissions'; + $tr['en']['Copying'] = 'Copying'; $tr['en']['CreateNewItem'] = 'Create New Item'; + $tr['en']['Name'] = 'Name'; $tr['en']['AdvancedEditor'] = 'Advanced Editor'; + $tr['en']['RememberMe'] = 'Remember Me'; $tr['en']['Actions'] = 'Actions'; + $tr['en']['Upload'] = 'Upload'; $tr['en']['Cancel'] = 'Cancel'; + $tr['en']['InvertSelection']= 'Invert Selection'; $tr['en']['DestinationFolder'] = 'Destination Folder'; + $tr['en']['ItemType'] = 'Item Type'; $tr['en']['ItemName'] = 'Item Name'; + $tr['en']['CreateNow'] = 'Create Now'; $tr['en']['Download'] = 'Download'; + $tr['en']['Open'] = 'Open'; $tr['en']['UnZip'] = 'UnZip'; + $tr['en']['UnZipToFolder'] = 'UnZip to folder'; $tr['en']['Edit'] = 'Edit'; + $tr['en']['NormalEditor'] = 'Normal Editor'; $tr['en']['BackUp'] = 'Back Up'; + $tr['en']['SourceFolder'] = 'Source Folder'; $tr['en']['Files'] = 'Files'; + $tr['en']['Move'] = 'Move'; $tr['en']['Change'] = 'Change'; + $tr['en']['Settings'] = 'Settings'; $tr['en']['Language'] = 'Language'; + $tr['en']['Folder is empty'] = 'Folder is empty'; $tr['en']['PartitionSize'] = 'Partition size'; + $tr['en']['ErrorReporting'] = 'Error Reporting'; $tr['en']['ShowHiddenFiles'] = 'Show Hidden Files'; + $tr['en']['Full size'] = 'Full size'; $tr['en']['Help'] = 'Help'; + $tr['en']['Free of'] = 'Free of'; $tr['en']['Preview'] = 'Preview'; + $tr['en']['Help Documents'] = 'Help Documents'; $tr['en']['Report Issue'] = 'Report Issue'; + $tr['en']['Generate'] = 'Generate'; $tr['en']['FullSize'] = 'Full Size'; + $tr['en']['FreeOf'] = 'free of'; $tr['en']['CalculateFolderSize']= 'Calculate folder size'; + $tr['en']['ProcessID'] = 'Process ID'; $tr['en']['Created'] = 'Created'; + $tr['en']['HideColumns'] = 'Hide Perms/Owner columns';$tr['en']['You are logged in'] = 'You are logged in'; + $tr['en']['Check Latest Version'] = 'Check Latest Version';$tr['en']['Generate new password hash'] = 'Generate new password hash'; + $tr['en']['Login failed. Invalid username or password'] = 'Login failed. Invalid username or password'; + $tr['en']['password_hash not supported, Upgrade PHP version'] = 'password_hash not supported, Upgrade PHP version'; + + // new - novos + + $tr['en']['Advanced Search'] = 'Advanced Search'; $tr['en']['Error while copying fro'] = 'Error while copying fro'; + $tr['en']['Nothing selected'] = 'Nothing selected'; $tr['en']['Paths must be not equal'] = 'Paths must be not equal'; + $tr['en']['Renamed from'] = 'Renamed from'; $tr['en']['Archive not unpacked'] = 'Archive not unpacked'; + $tr['en']['Deleted'] = 'Deleted'; $tr['en']['Archive not created'] = 'Archive not created'; + $tr['en']['Copied from'] = 'Copied from'; $tr['en']['Permissions changed'] = 'Permissions changed'; + $tr['en']['to'] = 'to'; $tr['en']['Saved Successfully'] = 'Saved Successfully'; + $tr['en']['not found!'] = 'not found!'; $tr['en']['File Saved Successfully'] = 'File Saved Successfully'; + $tr['en']['Archive'] = 'Archive'; $tr['en']['Permissions not changed'] = 'Permissions not changed'; + $tr['en']['Select folder'] = 'Select folder'; $tr['en']['Source path not defined'] = 'Source path not defined'; + $tr['en']['already exists'] = 'already exists'; $tr['en']['Error while moving from'] = 'Error while moving from'; + $tr['en']['Create archive?'] = 'Create archive?'; $tr['en']['Invalid file or folder name'] = 'Invalid file or folder name'; + $tr['en']['Archive unpacked'] = 'Archive unpacked'; $tr['en']['File extension is not allowed'] = 'File extension is not allowed'; + $tr['en']['Root path'] = 'Root path'; $tr['en']['Error while renaming from'] = 'Error while renaming from'; + $tr['en']['File not found'] = 'File not found'; $tr['en']['Error while deleting items'] = 'Error while deleting items'; + $tr['en']['Invalid characters in file name'] = 'Invalid characters in file name'; + $tr['en']['FILE EXTENSION HAS NOT SUPPORTED'] = 'FILE EXTENSION HAS NOT SUPPORTED'; + $tr['en']['Selected files and folder deleted'] = 'Selected files and folder deleted'; + $tr['en']['Error while fetching archive info'] = 'Error while fetching archive info'; + $tr['en']['Delete selected files and folders?'] = 'Delete selected files and folders?'; + $tr['en']['Search file in folder and subfolders...'] = 'Search file in folder and subfolders...'; + $tr['en']['Access denied. IP restriction applicable'] = 'Access denied. IP restriction applicable'; + $tr['en']['Invalid characters in file or folder name'] = 'Invalid characters in file or folder name'; + $tr['en']['Operations with archives are not available'] = 'Operations with archives are not available'; + $tr['en']['File or folder with this path already exists'] = 'File or folder with this path already exists'; + + $tr['en']['Moved from'] = 'Moved from'; + + $i18n = fm_get_translations($tr); + $tr = $i18n ? $i18n : $tr; + + if (!strlen($lang)) $lang = 'en'; + if (isset($tr[$lang][$txt])) return fm_enc($tr[$lang][$txt]); + else if (isset($tr['en'][$txt])) return fm_enc($tr['en'][$txt]); + else return "$txt"; +} + +?> diff --git a/includes/video/list.php b/includes/video/list.php index 0f090bf..57375d1 100644 --- a/includes/video/list.php +++ b/includes/video/list.php @@ -1,13 +1,13 @@ -<div class="list-group"> - <?php - - $articles = scandir($_SERVER['DOCUMENT_ROOT'] . "/creations/video"); - $i = 1; - foreach ($articles as $article): - - ?> - <?php if (trim($article) !== "." && trim($article) !== ".." && is_dir($_SERVER['DOCUMENT_ROOT'] . "/creations/video/" . $article)): ?> - <a href="/creations/video/<?= $article ?>" class="list-group-item list-group-item-action"><?= file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/video/" . $article . "/title.txt") ?></a> - <?php endif;$i++; ?> - <?php endforeach; ?> +<div class="list-group">
+ <?php
+
+ $articles = scandir($_SERVER['DOCUMENT_ROOT'] . "/creations/video");
+ $i = 1;
+ foreach ($articles as $article):
+
+ ?>
+ <?php if (trim($article) !== "." && trim($article) !== ".." && is_dir($_SERVER['DOCUMENT_ROOT'] . "/creations/video/" . $article)): ?>
+ <a href="/creations/video/<?= $article ?>" class="list-group-item list-group-item-action"><?= file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/creations/video/" . $article . "/title.txt") ?></a>
+ <?php endif;$i++; ?>
+ <?php endforeach; ?>
</div>
\ No newline at end of file |