Commit 2e117586 authored by David Revoy's avatar David Revoy

Split the zip generator into seasons

Same cut as the French publishing of P&C; so the Zip rarely exceed
200MB and eat all CPU of the server. Also, for publishing a book,
I'll need only a pack of page according to this cut.

Aesthetic changes were also added as well as more security checks
and condition to save CPU and server.
parent dc64c257
......@@ -10,13 +10,13 @@ $lockstatus = 0;
# Storage path of the ZIPs.
$dir = "tmp/";
# Get new variable from URL; 'lang'
# Get new variable from URL; 'lang'.
$requestedlang = htmlspecialchars($_GET["l"]);
# Security filter: remove all special characters except a-z.
$requestedlang = preg_replace('/[^a-z]/', '', $requestedlang);
# Get new variable from URL; 'season'
# Get new variable from URL; 'season'.
$season = htmlspecialchars($_GET["s"]);
# Security filter: remove seasons superior to 4.
......@@ -33,7 +33,7 @@ if($requestedlang != '') {
# Block anything more than three letters.
if (strlen($requestedlang)<3) {
# Block invalid lang (test if they exist on episode 1)
# Block invalid lang (test if they exist on episode 1).
$testfolder = '0_sources/ep01_Potion-of-Flight/lang/'.$requestedlang.'';
if(is_dir($testfolder)) {
......@@ -48,7 +48,7 @@ if($requestedlang != '') {
}
}
# Our lang is now ready to be used
# Our lang is now ready to be used.
$lang = $requestedlang;
# Removing 24 hours (86400s) old generated zip stored in target folder.
......@@ -61,10 +61,10 @@ if($requestedlang != '') {
}
}
# Block generation of zip for 24h after more than 8
# Block generation of zip for 24h after more than 8 done.
if($zipcounter < 8 ) {
# Block request faster than 3min reload
# Block request faster than 3min reload.
if(!is_file(''.$dir.'/cachelock.txt')) {
# Get ISO date YYYY-MM-DD.
......@@ -77,98 +77,153 @@ if($requestedlang != '') {
$notification = "";
# Build a list of the episodes folders from 0_sources.
$sourcespath = '0_sources/';
$hidefromsourcespath = array('.', '..', '0_archives', '0ther', 'fonts');
$mainfolders = array_diff(scandir($sourcespath), $hidefromsourcespath);
sort($mainfolders);
# Define the path for outputs.
$download = 'tmp/'.$isodate.'_'.$lang.'_peppercarrot-all-pages.zip';
$mainfolders = glob("0_sources/ep[0-9][0-9]*");
# If a zip exist and was already generated (in less than 24h), don't redo it.
if(!is_file($download)) {
# Sort episodes alphabetically starting by ep01.
sort($mainfolders);
# Define our future zip object.
$zip->open($download, ZipArchive::CREATE);
# Loop on the episodes folders.
foreach($mainfolders as $foldername) {
# Build absolute path from root of website.
$projectpath = $sourcespath.$foldername;
# Security: check if the folder exists.
if(is_dir($projectpath)) {
# Check if the translation folder exist for the lang selected.
if (is_dir($projectpath."/lang/".$lang."/")) {
# Search for a pattern of txt-only pages (transparent PNG with text).
$searchtxt = glob($projectpath."/hi-res/txt-only/".$lang."_Pepper-and-Carrot_by-David-Revoy_E[0-9][0-9]P[0-9][0-9].*");
# Validate our episodes.
# ----------------------
# Create a table to store validated episodes folders.
$validatedfolders = array();
# Loop inside all the episodes found on 0_sources and check foders.
foreach($mainfolders as $folder) {
# Validate if the episode with the target lang folder is found on disk
$validationpattern = ''.$folder.'/lang/'.$lang.'';
if(is_dir($validationpattern)) {
# Redirect seasons
switch ($season) {
case 1:
# Allow Season 1 episodes only.
if(preg_match('/(01|02|03|04|05|06|07|08|09|10|11)/iu', $folder)) {
# Push the validated episodes inside the table.
array_push($validatedfolders, $folder);
}
break;
# Search for a pattern of gfx-only page (hi-resolution PNGs artworks, no text).
$searchgfx = glob($projectpath."/hi-res/gfx-only/gfx_Pepper-and-Carrot_by-David-Revoy_E[0-9][0-9]P[0-9][0-9].*");
case 2:
# Allow Season 2 episodes only.
if(preg_match('/(12|13|14|15|16|17|18|19|20|21)/iu', $folder)) {
# Push the validated episodes inside the table.
array_push($validatedfolders, $folder);
}
break;
# Merge the two previously search results.
$search = array_merge($searchtxt, $searchgfx);
case 3:
# Allow Season 3 episodes only.
if(preg_match('/(22|23|24|25|26|27|28|29)/iu', $folder)) {
# Push the validated episodes inside the table.
array_push($validatedfolders, $folder);
}
break;
# Generate the Zip
# ----------------
# Security: Block empty search result of pages.
if (!empty($search)) {
case 4:
# Allow Season 4 episodes only.
if(preg_match('/(30|31|32|33|34|35|36|37|38|39)/iu', $folder)) {
# Push the validated episodes inside the table.
array_push($validatedfolders, $folder);
}
break;
}
}
}
# Block if the table is empty: no episodes translated, canceling empty zip generation.
if (count($validatedfolders) != 0) {
# Create a filename zip output depending of the, date, lang and active season.
$download = 'tmp/'.$isodate.'_'.$lang.'_S0'.$season.'_peppercarrot-all-pages.zip';
# If a zip already exists and was generated in less than 24h, don't redo it...
if(!is_file($download)) {
# Define our future zip object.
$zip->open($download, ZipArchive::CREATE);
# Loop on the episodes folders.
foreach($validatedfolders as $foldername) {
# Build absolute path from root of website.
$projectpath = $sourcespath.$foldername;
# Security: check if the folder exists.
if(is_dir($projectpath)) {
# Check if the translation folder exist for the lang selected.
if (is_dir($projectpath."/lang/".$lang."/")) {
# Loop on result of the search.
foreach ($search as $key => $filepath) {
# Search for a pattern of txt-only pages (transparent PNG with text).
$searchtxt = glob($projectpath."/hi-res/txt-only/".$lang."_Pepper-and-Carrot_by-David-Revoy_E[0-9][0-9]P[0-9][0-9].*");
# Cleanup path of search results.
$filename = basename($filepath);
$fullpath = dirname($filepath);
# Security: Block path not pointing to real files.
if (file_exists($filepath)) {
# Search for a pattern of gfx-only page (hi-resolution PNGs artworks, no text).
$searchgfx = glob($projectpath."/hi-res/gfx-only/gfx_Pepper-and-Carrot_by-David-Revoy_E[0-9][0-9]P[0-9][0-9].*");
# Merge the two previously search results.
$search = array_merge($searchtxt, $searchgfx);
# Generate the Zip
# ----------------
# Security: Block empty search result of pages.
if (!empty($search)) {
# Loop on result of the search.
foreach ($search as $key => $filepath) {
# Store the file in the zip
$zip->addFile($filepath, $filename);
# Cleanup path of search results.
$filename = basename($filepath);
$fullpath = dirname($filepath);
# Security: Block path not pointing to real files.
if (file_exists($filepath)) {
# Store the file in the zip.
$zip->addFile($filepath, $filename);
}
}
}
}
}
}
}
# Store also this file in every ZIP automated to remind about license and usages.
$zip->addFile("downloader-notice.md", "README.md");
# Close our generated ZIP object.
$zip->close();
}
}
# User interface
# ---------------
# Search if the zip file is successfully created.
if(is_file($download)) {
# Switch message in memory for a success.
$notification = '<p class="notifok">&#128154; Success: your zip archive is ready.<p><br/><p>Find the download link within this list:</p>';
# Store also this file in every ZIP automated to remind about license and usages.
$zip->addFile("downloader-notice.md", "README.md");
# Log the ZIP generation
# ----------------------
# Get an IP to track abuse
$ip = $_SERVER['REMOTE_ADDR'];
# Get ISO date YYYY-MM-DD_HHhMM.
$logexactdate = date("Y-m-d_H\hi");
$logverboseline = '['.$logexactdate.'] ['.$ip.'] '.$download.''.PHP_EOL;
$log = ''.$dir.'/log.txt';
$logfile = fopen($log, 'a');
fwrite($logfile, $logverboseline);
fclose($logfile);
# Close our generated ZIP object.
$zip->close();
}
# User interface
# ---------------
# Search if the zip file is successfully created.
if(is_file($download)) {
} else {
# Switch message in memory for a failure.
$notification = '<p class="notifno">Error: couldn\'t generate the archive.<p><p>Ready for download:</p>';
}
# Switch message in memory for a success.
$notification = '<p class="notifok">&#128154; Success: your zip archive is ready.<p><br/><p>Find the download link within this list:</p>';
# Log the ZIP generation
# ----------------------
# Get an IP to track abuse.
$ip = $_SERVER['REMOTE_ADDR'];
# Get ISO date YYYY-MM-DD_HHhMM.
$logexactdate = date("Y-m-d_H\hi");
$logfileweight = (filesize($download) / 1024) / 1024;
$logverboseline = '['.$logexactdate.'] ['.$ip.'] '.$download.' ('.round($logfileweight, 2).'MB)'.PHP_EOL;
$log = ''.$dir.'/log.txt';
$logfile = fopen($log, 'a');
fwrite($logfile, $logverboseline);
fclose($logfile);
} else {
# Switch message in memory for a failure.
$notification = '<p class="notifno">Error: couldn\'t generate the archive.<p><p>Ready for download:</p>';
}
} else {
# Display a error the season has no translations.
$notification = '<p class="notifmeh">&#128533; <b>Nothing to do</b><br/><small>Season '.$season.' has no translated pages for ['.$lang.'] language.</small></p><p>Ready for download:</p>';
}
} else {
# Display a error message if the lang query is empty.
$notification = '<p class="notifinfo">&#128336; <b>Server CPU protection:</b><br/><small>&#128472; Too many requests. Please reload this page in 3 min.</small></p><p>Ready for download:</p>';
......@@ -217,19 +272,22 @@ echo '</head>';
echo '
<style type="text/css" media="screen">
body { font-family: Ubuntu, Arial, sans; margin: 2em; padding: 0; background: #F0F0F0; color: #666; font-size: 1rem; text-align: left; }
#wrapper { text-align: left; background: #fff; max-width: 500px; padding: 2rem; margin: 0 auto; border: 1px #dedede solid; }
#wrapper { text-align: left; background: #fff; max-width: 480px; padding: 2rem; margin: 0 auto; border: 1px #dedede solid; }
p { line-height: 160%; }
.notifok { padding: 1rem; background: #D5FF75; }
.notifno { padding: 1rem; background: #FFA075; }
.notifinfo { padding: 1rem; background: #C8EBFF; }
.filesize { color: #CCC; }
.notifmeh { padding: 1rem; background: #FADF94; }
.filesize { color: #ABABAB; font-size: 0.8rem; }
.button { display:block; box-shadow:inset 0px 1px 0px 0px #ffffff; background:linear-gradient(to bottom, #f9f9f9 5%, #e9e9e9 100%); background-color:#f9f9f9; border-radius:6px; border:1px solid #dcdcdc; color:#666666; padding:6px 24px; text-decoration:none; text-shadow:0px 1px 0px #ffffff;}
.button:hover { background:linear-gradient(to bottom, #e9e9e9 5%, #f9f9f9 100%); background-color:#e9e9e9; }
h1 { color: #555; font-size: 1.8rem; font-family: Ubuntu, Arial, sans; font-weight: bold; margin: 0 0 0.3rem 0; text-align: center; }
ul { margin-top: 20px; }
li { margin-top: 10px; }
ul { margin-top: 20px; padding: 0 0;}
li { list-style-type:none; margin: 6px 0 0 0; }
a { color: #666; text-decoration: none;}
a:hover { color: #222;}
@media (max-width: 500px) {
body { background: #FFF; font-size: 1rem; }
@media (max-width: 700px) {
body { background: #FFF; }
#wrapper { max-width: 100%; padding: 0; margin: 0 auto; border: none; }
h1 { font-size: 1.6rem;}
}
......@@ -242,7 +300,7 @@ echo '<center><img src="https://www.peppercarrot.com/plugins/vignette/plxthumbna
echo '<p>'.$notification.'</p>';
echo '<ul>';
# Counter for number of files in cache
# Counter for number of files in cache.
$count = 0;
# List all the zip founds on the folder.
......@@ -251,31 +309,35 @@ foreach (glob($dir."*.zip") as $file) {
# Cleanup path to display only filename.
$filenamelabel = basename($file);
# Get the weight of the zip
# Get the weight of the zip.
$fileweight = (filesize($file) / 1024) / 1024;
# Print the result as a list element.
echo '<li>&#128451; &#10515;<a href="'.$file.'" download>'.$filenamelabel.' <em class="filesize">('.round($fileweight, 2).'MB)</em></a></li>';
echo '<li> <a class="button" href="'.$file.'" download>&#128229; '.$filenamelabel.' <em class="filesize">('.round($fileweight, 2).'MB)</em></a></li>';
# Upgrade the counter.
$count = $count + 1;
}
# Display a special item if list is empty
# Display a special item if list is empty.
if ($count == 0) {
echo '<li><span style="color: #FFA075;">Error: No zip files in the cache.</span></li>';
echo '<li><span style="color: #FFA075;">No zip files ready on disk.</span></li>';
}
echo '</ul>';
echo '<br/><div align="right"><a style="color:#7373D7; text-decoration: underline; font-size: 0.8rem;" href="static6/sources&page=download">Go back to the selector</a></div>';
echo '<br/><p><small style="color:#aaa;"><b>Server friendly rules:</b><br/>- Files are stored here for 24h after their creation. <br/>- 8 zip generated per day maximum. <br/>- 3min wait between zip generations.</small></p>';
echo '<!-- Debug: ';
print_r($validatedfolders);
echo '-->';
echo '</div>';
echo '</body>';
# Regenerate a the cache lock
# ---------------------------
# Do it if necessary
# Do it if necessary.
if($lockstatus == 1) {
# Regenerate if doesn't exists
# Regenerate if doesn't exists.
if(!is_file(''.$dir.'/cachelock.txt')) {
# Get ISO date YYYY-MM-DD_HHhMM.
$tokkendate = date("Y-m-d_H\hi");
......
......@@ -381,7 +381,7 @@ if(isset($_GET['page'])) {
echo '</div>';
# Create a frame for the body.
echo '<section class="col sml-12 med-12 lrg-10 sml-centered">';
echo '<section class="col sml-12 med-10 lrg-8 sml-centered">';
# Create a table.
$langfolders = array();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment