2013-09-21 01:22:48 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
// Code-hosting website
|
|
|
|
// ````````````````````
|
|
|
|
|
2015-11-07 05:15:01 +00:00
|
|
|
function mkshield($left_str, $right_str, $color_str) {
|
|
|
|
$filename = rawurlencode(str_replace('-', '--', $left_str)).'-'.rawurlencode(str_replace('-', '--', $right_str)).'-'.rawurlencode($color_str).'.svg';
|
|
|
|
$cache_path = __DIR__.'/../../shields_cache/'.$filename;
|
|
|
|
|
|
|
|
if (file_exists($cache_path)) {
|
|
|
|
return file_get_contents($cache_path);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
$retn = file_get_contents('https://img.shields.io/badge/'.$filename);
|
|
|
|
file_put_contents($cache_path, $retn);
|
|
|
|
return $retn;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-21 01:52:12 +00:00
|
|
|
/**
|
2013-09-21 03:10:24 +00:00
|
|
|
* Create a thumbnail of an image. It overscales, centers, and crops to fit the
|
|
|
|
* target dimensions.
|
2013-09-21 01:52:12 +00:00
|
|
|
*
|
|
|
|
* @param string $src_file
|
2013-09-21 07:01:49 +00:00
|
|
|
* @param string $dest_file Null to return an image handle
|
2013-09-21 01:52:12 +00:00
|
|
|
* @param int $width
|
|
|
|
* @param int $height
|
|
|
|
* @return boolean
|
|
|
|
*/
|
2013-09-21 01:22:48 +00:00
|
|
|
function mkthumbnail($src_file, $dest_file, $width, $height) {
|
2013-09-21 01:52:12 +00:00
|
|
|
list($src_width, $src_height) = getimagesize($src_file);
|
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
$im = imagecreatefromstring(file_get_contents($src_file));
|
|
|
|
|
|
|
|
$dest = imagecreatetruecolor($width, $height);
|
2013-11-09 00:36:24 +00:00
|
|
|
imagefilledrectangle($dest, 0, 0, $width, $height, imagecolorallocate($dest, 0xFF, 0xFF, 0xFF));
|
2013-09-21 01:52:12 +00:00
|
|
|
|
|
|
|
$scale = max( $width/$src_width, $height/$src_height ); // overscale + crop
|
|
|
|
|
|
|
|
$box_w = $width/$scale;
|
|
|
|
$box_h = $height/$scale;
|
|
|
|
|
|
|
|
$box_xoff = floor(($src_width - $box_w)/2);
|
|
|
|
$box_yoff = floor(($src_height - $box_h)/2);
|
|
|
|
|
|
|
|
imagecopyresampled(
|
|
|
|
$dest, $im,
|
|
|
|
0, 0,
|
|
|
|
$box_xoff, $box_yoff,
|
|
|
|
$width, $height, $box_w, $box_h
|
|
|
|
);
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2013-09-21 07:01:49 +00:00
|
|
|
imagedestroy($im);
|
|
|
|
|
|
|
|
if (is_null($dest_file)) {
|
|
|
|
return $dest;
|
|
|
|
} else {
|
|
|
|
return imagejpeg($dest, $dest_file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function mkspritesheet(array $handles, $dest_file, $width, $height) {
|
|
|
|
$im = imagecreatetruecolor($width, $height * count($handles));
|
|
|
|
|
|
|
|
for($i = 0, $e = count($handles); $i != $e; ++$i) {
|
|
|
|
imagecopy($im, $handles[$i], 0, $i * $height, 0, 0, $width, $height);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_null($dest_file)) {
|
|
|
|
return $dest_file;
|
|
|
|
} else {
|
|
|
|
return imagejpeg($im, $dest_file);
|
|
|
|
}
|
2013-09-21 01:22:48 +00:00
|
|
|
}
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
function fbytes($size, $suffixes='B|KiB|MiB|GiB|TiB') {
|
|
|
|
$sxlist = explode('|', $suffixes);
|
|
|
|
if ($size < 1024) {
|
|
|
|
return $size.$sxlist[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
while ($size > 1024 && count($sxlist) >= 2) {
|
|
|
|
array_shift($sxlist);
|
|
|
|
$size /= 1024;
|
|
|
|
}
|
|
|
|
return number_format($size, 2).array_shift($sxlist);
|
|
|
|
}
|
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
function str_ext($sz) {
|
|
|
|
$dpos = strrpos($sz, '.');
|
|
|
|
return substr($sz, $dpos+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
function is_image($sz) {
|
|
|
|
return in_array(strtolower(str_ext($sz)), ['jpg', 'png', 'jpeg']);
|
|
|
|
}
|
|
|
|
|
2013-09-21 01:52:12 +00:00
|
|
|
function hesc($sz) {
|
|
|
|
return @htmlentities($sz, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
|
|
|
}
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
function text2html($sz) {
|
2014-06-08 08:07:24 +00:00
|
|
|
|
|
|
|
$identity = function($sz) {
|
|
|
|
return $sz;
|
|
|
|
};
|
2013-09-28 01:07:52 +00:00
|
|
|
|
2014-06-08 08:07:24 +00:00
|
|
|
$splitInside = function($begin, $end, $sz) {
|
|
|
|
$parts = explode($begin, $sz);
|
|
|
|
if (count($parts) == 1) return [$sz];
|
2014-06-17 06:21:51 +00:00
|
|
|
|
2014-06-08 08:07:24 +00:00
|
|
|
$ret = [$parts[0]];
|
2014-06-17 06:21:51 +00:00
|
|
|
for($i = 1, $e = count($parts); $i !== $e; ++$i) {
|
|
|
|
$inner = explode($end, $parts[$i], 2);
|
2014-06-08 08:07:24 +00:00
|
|
|
$ret = array_merge($ret, $inner);
|
2013-09-28 01:07:52 +00:00
|
|
|
}
|
2014-06-08 08:07:24 +00:00
|
|
|
return $ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
$oddEven = function(array $parts, $odd, $even, $join='') {
|
|
|
|
$ret = [];
|
|
|
|
for($i = 0, $e = count($parts); $i != $e; ++$i) {
|
|
|
|
$ret[] = ($i % 2) ? $odd($parts[$i]) : $even($parts[$i]);
|
|
|
|
}
|
|
|
|
return implode($join, $ret);
|
|
|
|
};
|
|
|
|
|
2014-08-23 10:22:34 +00:00
|
|
|
$sectionFmt = function($sz) use($oddEven, $identity) {
|
|
|
|
$base = hesc($sz);
|
|
|
|
|
|
|
|
$base = preg_replace('~^=+(.+)=+~m', '<strong>\\1</strong>', $base);
|
|
|
|
$base = preg_replace('~(https?://[^ \\r\\n\\t]+)~i', '<a href="\\1">\\1</a>', $base);
|
2015-09-05 23:48:40 +00:00
|
|
|
$base = preg_replace('~\\[b\\](.+?)\\[/b\\]~m', '<strong>\\1</strong>', $base);
|
|
|
|
$base = preg_replace('~\\[i\\](.+?)\\[/i\\]~m', '<i>\\1</i>', $base);
|
|
|
|
$base = preg_replace('~\\[spoiler\\](.+?)\\[/spoiler\\]~m', '<span class="spoiler">\\1</span>', $base);
|
|
|
|
$base = preg_replace('~\\[entry=([^\\]]+?)\\](.+?)\\[/entry\\]~m', '<a href="\\1.html">\\2</a>', $base);
|
2015-11-07 22:35:29 +00:00
|
|
|
$base = preg_replace('~\n- ~ms', "\n• ", $base);
|
2014-08-23 10:22:34 +00:00
|
|
|
|
|
|
|
$btparts = explode('`', $base);
|
|
|
|
if (count($btparts) > 1 && (count($btparts) % 2)) {
|
|
|
|
for ($i = 1, $e = count($btparts); $i < $e; $i += 2) {
|
2015-11-07 22:35:07 +00:00
|
|
|
$class = 'code';
|
|
|
|
if (strpos($btparts[$i], "\n") !== false) {
|
|
|
|
$class .= ' code-multiline';
|
|
|
|
}
|
|
|
|
$btparts[$i] = '<span class="'.$class.'">'.$btparts[$i].'</span>';
|
2014-08-23 10:22:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $oddEven($btparts, $identity, 'nl2br');
|
|
|
|
};
|
|
|
|
|
2014-06-08 08:07:24 +00:00
|
|
|
$htmlSections = $splitInside('<html>', '</html>', $sz);
|
2014-06-17 06:21:51 +00:00
|
|
|
return $oddEven($htmlSections, $identity, $sectionFmt);
|
2013-09-21 03:10:24 +00:00
|
|
|
}
|
|
|
|
|
2014-05-10 02:47:26 +00:00
|
|
|
function array_decimate($array, $total, $partno) {
|
|
|
|
$ct = 0;
|
|
|
|
$ret = [];
|
|
|
|
foreach($array as $k => $v) {
|
|
|
|
if (++$ct % $total == ($partno - 1)) {
|
|
|
|
$ret[$k] = $v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
2013-09-21 01:22:48 +00:00
|
|
|
class CProject {
|
|
|
|
|
|
|
|
private $dir;
|
2013-09-21 03:10:24 +00:00
|
|
|
public $projname;
|
|
|
|
public $shortdesc = '(no description)';
|
2013-09-21 04:52:48 +00:00
|
|
|
public $subtag = '';
|
2015-04-05 04:22:46 +00:00
|
|
|
public $lastupdate = 0;
|
2013-09-21 01:22:48 +00:00
|
|
|
private $longdesc = '';
|
2015-11-07 05:25:48 +00:00
|
|
|
private $prefix_html = '';
|
2013-09-21 01:22:48 +00:00
|
|
|
private $images = array();
|
|
|
|
private $downloads = array();
|
2015-04-05 04:49:17 +00:00
|
|
|
private $downloads_hashes = array();
|
2014-05-09 23:12:14 +00:00
|
|
|
public $tags = array();
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2013-09-21 07:01:49 +00:00
|
|
|
public $homeimage = null;
|
2013-09-21 03:10:24 +00:00
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
public function __construct($dirname, $projname) {
|
|
|
|
$this->dir = BASEDIR.'data/'.$dirname.'/';
|
|
|
|
$this->projname = $projname;
|
|
|
|
|
|
|
|
// Identify resources in folder
|
|
|
|
|
|
|
|
$ls = scandir($this->dir);
|
2015-11-07 22:49:18 +00:00
|
|
|
$found_real_lastupdate = false;
|
2013-09-21 01:22:48 +00:00
|
|
|
foreach($ls as $file) {
|
|
|
|
if ($file[0] == '.') continue;
|
|
|
|
|
|
|
|
if ($file == 'README.txt') {
|
2015-11-07 22:49:18 +00:00
|
|
|
|
|
|
|
// Guess 'last update' time
|
|
|
|
$matches = [];
|
|
|
|
if (preg_match('~\n(\d\d\d\d-\d\d-\d\d)~', $this->longdesc, $matches)) {
|
|
|
|
// Use first date entry (assumed to be a CHANGELOG)
|
|
|
|
$this->lastupdate = strtotime($matches[1]);
|
|
|
|
$found_real_lastupdate = true;
|
|
|
|
|
|
|
|
}
|
2015-04-05 04:22:46 +00:00
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
$this->longdesc = file_get_contents($this->dir.'README.txt');
|
2015-11-07 05:15:01 +00:00
|
|
|
|
2013-09-21 04:52:48 +00:00
|
|
|
$matches = array();
|
|
|
|
if (preg_match('~Written in ([^\\r\\n]+)~', $this->longdesc, $matches)) {
|
|
|
|
$this->subtag = rtrim($matches[1], ' .');
|
|
|
|
}
|
|
|
|
|
2014-05-09 23:12:14 +00:00
|
|
|
if (preg_match('~Tags: ([^\\r\\n]+)~', $this->longdesc, $matches)) {
|
|
|
|
$this->tags = array_map('trim', explode(',', $matches[1]));
|
|
|
|
}
|
|
|
|
|
2014-05-10 02:47:26 +00:00
|
|
|
$parts = explode("\n", $this->longdesc);
|
|
|
|
$this->shortdesc = array_shift($parts);
|
2013-09-21 04:24:52 +00:00
|
|
|
$this->shortdesc[0] = strtolower($this->shortdesc[0]); // cosmetic lowercase
|
2015-11-07 05:15:01 +00:00
|
|
|
|
2015-11-07 22:35:43 +00:00
|
|
|
// Filter longdesc
|
|
|
|
$this->longdesc = str_replace("\r", "", $this->longdesc); // filter windows CR
|
|
|
|
|
2015-11-07 05:22:10 +00:00
|
|
|
$prefix_html = '';
|
2015-11-07 22:35:43 +00:00
|
|
|
$this->longdesc = preg_replace_callback('~\r?\nWritten in ([^\\n]+)~ms', function($matches) use (&$prefix_html) {
|
2015-11-07 05:22:10 +00:00
|
|
|
$prefix_html .= (
|
2015-11-07 05:20:17 +00:00
|
|
|
(SHIELDS_PREFIX ? mkshield('build', 'success', 'brightgreen').' ' : '').
|
2015-11-07 22:56:44 +00:00
|
|
|
mkshield('written in', rtrim($matches[1], '.'), 'blue')
|
2015-11-07 05:20:17 +00:00
|
|
|
);
|
2015-11-07 05:22:10 +00:00
|
|
|
return '';
|
2015-11-07 05:15:01 +00:00
|
|
|
}, $this->longdesc);
|
2015-11-07 22:35:43 +00:00
|
|
|
|
|
|
|
while(strpos($this->longdesc, "\n\n\n") !== false) {
|
|
|
|
$this->longdesc = str_replace("\n\n\n", "\n\n", $this->longdesc);
|
|
|
|
}
|
|
|
|
$this->longdesc = rtrim($this->longdesc, "\n");
|
|
|
|
|
2015-11-07 05:25:48 +00:00
|
|
|
$this->prefix_html = $prefix_html;
|
2015-11-07 05:15:01 +00:00
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
continue;
|
|
|
|
}
|
2015-11-07 22:49:18 +00:00
|
|
|
|
|
|
|
if (! $found_real_lastupdate) {
|
|
|
|
$this->lastupdate = max(
|
|
|
|
$this->lastupdate,
|
|
|
|
// filectime($this->dir.$file),
|
|
|
|
($file == 'README.txt' ? filectime($this->dir.$file) : filemtime($this->dir.$file)) // Don't count README updates
|
|
|
|
);
|
|
|
|
}
|
2015-04-05 04:22:46 +00:00
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
if (is_image($file)) {
|
|
|
|
$this->images[] = $file;
|
|
|
|
} else {
|
|
|
|
$this->downloads[] = $file;
|
|
|
|
}
|
|
|
|
}
|
2014-05-24 05:55:58 +00:00
|
|
|
|
|
|
|
natcasesort($this->downloads);
|
|
|
|
$this->downloads = array_reverse($this->downloads);
|
2015-04-05 04:49:17 +00:00
|
|
|
|
|
|
|
for($i = 0, $e = count($this->downloads); $i !== $e; ++$i) {
|
|
|
|
$this->downloads_hashes[] = (
|
|
|
|
sha1_file($this->dir.$this->downloads[$i])
|
|
|
|
);
|
|
|
|
}
|
2013-09-21 01:22:48 +00:00
|
|
|
}
|
|
|
|
|
2014-05-10 02:47:26 +00:00
|
|
|
public function genHomeImage() {
|
|
|
|
if (count($this->images)) {
|
|
|
|
|
|
|
|
$this->homeimage = mkthumbnail(
|
2015-04-05 03:50:03 +00:00
|
|
|
$this->dir.$this->images[0],
|
2014-05-10 02:47:26 +00:00
|
|
|
null, // raw handle
|
|
|
|
INDEX_THUMB_W, INDEX_THUMB_H
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-09-21 01:22:48 +00:00
|
|
|
public function write() {
|
|
|
|
|
|
|
|
// Generate image thumbnails
|
|
|
|
|
2013-09-21 01:52:12 +00:00
|
|
|
foreach($this->images as $idx => $image) {
|
|
|
|
$outfile = BASEDIR.'wwwroot/srv/'.$this->projname.'_'.$idx;
|
|
|
|
copy($this->dir.$image, $outfile.'.'.str_ext($image));
|
|
|
|
|
|
|
|
mkthumbnail($outfile.'.'.str_ext($image), $outfile.'_thumb.jpg', PAGE_THUMB_W, PAGE_THUMB_H);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy downloads to wwwroot
|
|
|
|
|
|
|
|
foreach($this->downloads as $idx => $filename) {
|
2015-04-05 04:49:17 +00:00
|
|
|
$cmkdir = @mkdir( BASEDIR.'wwwroot/srv/'.$this->downloads_hashes[$idx] );
|
|
|
|
|
|
|
|
if (! $cmkdir) {
|
|
|
|
fputs(
|
|
|
|
STDOUT,
|
|
|
|
"WARNING: Couldn't create directory ".$this->downloads_hashes[$idx].
|
|
|
|
" for file '${filename}'".
|
|
|
|
" in project '".$this->projname."'!\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
copy(
|
|
|
|
$this->dir.$filename,
|
|
|
|
BASEDIR.'wwwroot/srv/'.$this->downloads_hashes[$idx].'/'.$filename
|
|
|
|
);
|
2013-09-21 01:52:12 +00:00
|
|
|
}
|
2013-09-21 01:22:48 +00:00
|
|
|
|
|
|
|
// Generate index page
|
2013-09-21 01:52:12 +00:00
|
|
|
|
|
|
|
ob_start();
|
|
|
|
$this->index();
|
2013-09-21 03:10:24 +00:00
|
|
|
$idxfile = template($this->projname.' | '.SITE_TITLE, ob_get_clean());
|
2013-09-21 01:52:12 +00:00
|
|
|
file_put_contents(BASEDIR.'wwwroot/'.$this->projname.'.html', $idxfile);
|
2013-09-21 01:22:48 +00:00
|
|
|
}
|
|
|
|
|
2014-05-09 23:12:14 +00:00
|
|
|
public function getClassAttr() {
|
|
|
|
if (count($this->tags)) {
|
|
|
|
return 'taggedWith-'.implode(' taggedWith-', $this->tags);
|
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-21 01:52:12 +00:00
|
|
|
public function index() {
|
2013-09-21 03:10:24 +00:00
|
|
|
?>
|
2015-09-05 23:48:54 +00:00
|
|
|
<h2><?=hesc(str_replace('_', ' ', $this->projname))?></h2>
|
2013-09-21 03:10:24 +00:00
|
|
|
|
|
|
|
<div class="projinfo">
|
|
|
|
|
2013-09-21 04:24:52 +00:00
|
|
|
<div class="projbody projbody_<?=(count($this->images) ? 'half' : 'full')?>w">
|
2013-09-21 01:52:12 +00:00
|
|
|
|
2015-11-07 05:25:48 +00:00
|
|
|
<?php if (strlen($this->prefix_html)) { ?>
|
2015-11-07 05:33:58 +00:00
|
|
|
<p style="margin-top:0;"><?=$this->prefix_html?></p>
|
2015-11-07 05:25:48 +00:00
|
|
|
<?php } ?>
|
|
|
|
|
2015-09-05 23:48:26 +00:00
|
|
|
<strong><?=hesc(strtoupper(ARTICLE_HEADER))?></strong>
|
2013-09-21 01:52:12 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
<p><?=text2html($this->longdesc)?></p>
|
|
|
|
|
2015-04-04 06:29:33 +00:00
|
|
|
<?=file_get_contents(BASEDIR.'/footer.htm')?>
|
2013-11-09 00:35:38 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
<?php if (count($this->downloads)) { ?>
|
|
|
|
|
|
|
|
<strong>DOWNLOAD</strong>
|
2013-09-21 01:52:12 +00:00
|
|
|
|
|
|
|
<ul>
|
2015-04-05 04:49:17 +00:00
|
|
|
<?php foreach($this->downloads as $idx => $filename) { ?>
|
2013-09-21 03:10:24 +00:00
|
|
|
<li>
|
2015-04-05 04:49:17 +00:00
|
|
|
<a href="srv/<?=hesc($this->downloads_hashes[$idx])?>/<?=hesc(rawurlencode($filename))?>"><?=hesc($filename)?></a>
|
2013-09-21 03:10:24 +00:00
|
|
|
<small>
|
2015-04-05 04:49:17 +00:00
|
|
|
<?=hesc(fbytes(filesize(BASEDIR.'wwwroot/srv/'.$this->downloads_hashes[$idx].'/'.$filename)))?>
|
2013-09-21 03:10:24 +00:00
|
|
|
</small>
|
|
|
|
</li>
|
|
|
|
<?php } ?>
|
2013-09-21 01:52:12 +00:00
|
|
|
</ul>
|
2013-09-21 03:10:24 +00:00
|
|
|
<?php } ?>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<?php if (count($this->images)) { ?>
|
|
|
|
<div class="projimg">
|
|
|
|
<?php foreach($this->images as $idx => $origname) { ?>
|
|
|
|
<a href="srv/<?=hesc(urlencode($this->projname))?>_<?=$idx?>.<?=str_ext($origname)?>"><img src="srv/<?=hesc(urlencode($this->projname))?>_<?=$idx?>_thumb.jpg" class="thumbimage"></a>
|
2013-09-21 01:52:12 +00:00
|
|
|
<?php } ?>
|
2013-09-21 03:10:24 +00:00
|
|
|
</div>
|
2014-08-23 10:19:02 +00:00
|
|
|
|
|
|
|
<div style="clear:both;"></div>
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
<?php } ?>
|
|
|
|
|
|
|
|
</div>
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2013-09-21 01:52:12 +00:00
|
|
|
<?php
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
function template($title, $content) {
|
|
|
|
ob_start();
|
|
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >
|
2015-11-07 05:38:53 +00:00
|
|
|
<meta name="viewport" content="width=960" >
|
2013-11-09 00:36:04 +00:00
|
|
|
<link type="text/css" rel="stylesheet" href="normalize.css">
|
2013-09-21 03:10:24 +00:00
|
|
|
<link type="text/css" rel="stylesheet" href="style.css">
|
2014-05-10 02:19:25 +00:00
|
|
|
<script type="text/javascript" src="site.js"></script>
|
2013-09-21 03:10:24 +00:00
|
|
|
<title><?=hesc($title)?></title>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div id="container">
|
|
|
|
<div id="content">
|
2015-04-04 06:29:33 +00:00
|
|
|
<?=file_get_contents(BASEDIR.'/header.htm')?>
|
2013-09-21 03:10:24 +00:00
|
|
|
<?=$content?>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
<?php
|
|
|
|
return ob_get_clean();
|
|
|
|
}
|
|
|
|
|
2014-05-10 02:47:26 +00:00
|
|
|
function listprojects() {
|
2013-09-21 03:10:24 +00:00
|
|
|
// List projects
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
$ls = scandir(BASEDIR.'data');
|
2013-09-21 04:24:52 +00:00
|
|
|
rsort($ls);
|
2013-09-21 03:10:24 +00:00
|
|
|
$projects = array();
|
|
|
|
foreach($ls as $dirname) {
|
|
|
|
if ($dirname[0] == '.') continue;
|
2015-09-05 23:59:08 +00:00
|
|
|
if (! is_dir(BASEDIR.'data/'.$dirname)) continue;
|
2013-09-21 03:10:24 +00:00
|
|
|
$matches = array();
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
if (preg_match('~(?:\d+-)?(.+)~', $dirname, $matches)) {
|
|
|
|
$projects[$dirname] = $matches[1];
|
|
|
|
}
|
|
|
|
}
|
2014-05-10 02:47:26 +00:00
|
|
|
|
|
|
|
return $projects;
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildprojects($id, $projects) {
|
|
|
|
$count = 0;
|
|
|
|
|
|
|
|
foreach($projects as $dirname => $projectname) {
|
|
|
|
|
|
|
|
echo sprintf("@%1d [%3d/%3d] ".$projectname."...\n", $id, ++$count, count($projects));
|
|
|
|
|
|
|
|
$pr = new CProject($dirname, $projectname);
|
|
|
|
$pr->write();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildcommon() {
|
|
|
|
|
|
|
|
echo "@0 [ 0/ ?] Common files...\n";
|
|
|
|
|
|
|
|
$projects = listprojects();
|
2013-09-21 03:10:24 +00:00
|
|
|
|
|
|
|
// Build all projects
|
|
|
|
|
|
|
|
$plist = array();
|
|
|
|
|
2013-09-21 07:01:49 +00:00
|
|
|
$handles = array();
|
|
|
|
$handle_lookup = array();
|
|
|
|
|
2015-04-05 04:22:46 +00:00
|
|
|
$alphasort = [];
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
foreach($projects as $dirname => $projectname) {
|
|
|
|
|
2014-05-10 02:47:26 +00:00
|
|
|
$pr = new CProject($dirname, $projectname);
|
|
|
|
$pr->genHomeImage(); // thumbnail
|
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
$plist[] = $pr;
|
|
|
|
|
2013-09-21 07:01:49 +00:00
|
|
|
if (is_null($pr->homeimage)) {
|
|
|
|
$handle_lookup[$projectname] = null;
|
|
|
|
} else {
|
|
|
|
$handle_lookup[$projectname] = count($handles);
|
|
|
|
$handles[] = $pr->homeimage;
|
|
|
|
}
|
2015-04-05 04:22:46 +00:00
|
|
|
|
|
|
|
$alphasort[] = [$pr->projname, count($plist)-1];
|
|
|
|
}
|
|
|
|
|
|
|
|
usort($alphasort, function($a, $b) {
|
|
|
|
return strcasecmp($a[0], $b[0]);
|
|
|
|
});
|
|
|
|
|
|
|
|
$alphaidx = [];
|
|
|
|
|
|
|
|
foreach($alphasort as $a) {
|
|
|
|
$alphaidx[ $a[1] ] = count($alphaidx);
|
2014-05-10 02:47:26 +00:00
|
|
|
}
|
2013-09-21 03:10:24 +00:00
|
|
|
|
2013-09-21 07:01:49 +00:00
|
|
|
// Build homepage spritesheet
|
|
|
|
|
2015-04-05 04:51:52 +00:00
|
|
|
if (count($handles)) {
|
|
|
|
mkspritesheet($handles, BASEDIR.'wwwroot/logos.jpg', INDEX_THUMB_W, INDEX_THUMB_H);
|
|
|
|
array_map('imagedestroy', $handles); // free
|
|
|
|
}
|
2013-09-21 07:01:49 +00:00
|
|
|
|
2013-09-21 03:10:24 +00:00
|
|
|
// Build index page
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
?>
|
2013-09-28 01:07:52 +00:00
|
|
|
|
2013-09-28 01:27:42 +00:00
|
|
|
<?php if (file_exists(BASEDIR.'homepage_blurb.htm')) { ?>
|
2013-09-28 01:07:52 +00:00
|
|
|
<!-- homepage blurb {{ -->
|
|
|
|
<?=file_get_contents(BASEDIR.'homepage_blurb.htm')?>
|
|
|
|
<!-- }} -->
|
2013-09-28 01:27:42 +00:00
|
|
|
<?php } ?>
|
2013-09-21 03:10:24 +00:00
|
|
|
|
2015-04-05 04:22:46 +00:00
|
|
|
<table id="projtable-main" class="projtable">
|
|
|
|
<?php foreach ($plist as $i => $pr) { ?>
|
|
|
|
<tr class="<?=$pr->getClassAttr()?>"
|
|
|
|
data-sort-mt="-<?=$pr->lastupdate?>"
|
|
|
|
data-sort-ct="<?=$i?>"
|
|
|
|
data-sort-al="<?=$alphaidx[$i]?>"
|
|
|
|
>
|
2013-09-21 03:10:24 +00:00
|
|
|
<td>
|
2013-09-28 01:21:01 +00:00
|
|
|
<a href="<?=hesc(urlencode($pr->projname))?>.html"><?=(is_null($handle_lookup[$pr->projname]) ? '<div class="no-image"></div>' : '<div class="homeimage homeimage-sprite" style="background-position:0 -'.($handle_lookup[$pr->projname]*INDEX_THUMB_H).'px"></div>')?></a>
|
2013-09-21 03:10:24 +00:00
|
|
|
</td>
|
|
|
|
<td>
|
2015-11-01 00:50:25 +00:00
|
|
|
<strong><?=hesc(str_replace('_', ' ', $pr->projname))?></strong><?php if (SHOW_BLURBS) { ?>,
|
2013-09-21 03:10:24 +00:00
|
|
|
<?=hesc($pr->shortdesc)?>
|
2015-09-05 23:01:13 +00:00
|
|
|
<?php } ?>
|
2015-09-05 23:49:09 +00:00
|
|
|
<a href="<?=hesc(urlencode($pr->projname))?>.html" class="article-read-more">more...</a>
|
2014-05-09 23:12:14 +00:00
|
|
|
<?php if (strlen($pr->subtag) || count($pr->tags)) { ?>
|
2013-09-21 04:52:48 +00:00
|
|
|
<br>
|
2014-05-09 23:12:14 +00:00
|
|
|
<small>
|
|
|
|
<?=hesc($pr->subtag)?>
|
|
|
|
<?php if (strlen($pr->subtag) && count($pr->tags)) { ?>
|
|
|
|
::
|
|
|
|
<?php } ?>
|
|
|
|
<?php foreach($pr->tags as $tag) { ?>
|
2014-05-10 01:54:10 +00:00
|
|
|
<a class="tag tag-link" data-tag="<?=hesc($tag)?>"><?=hesc($tag)?></a>
|
2014-05-09 23:12:14 +00:00
|
|
|
<?php } ?>
|
|
|
|
</small>
|
2013-09-21 04:52:48 +00:00
|
|
|
<?php } ?>
|
2013-09-21 03:10:24 +00:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<?php } ?>
|
|
|
|
</table>
|
|
|
|
<?php
|
|
|
|
|
|
|
|
$index = template(SITE_TITLE, ob_get_clean());
|
|
|
|
file_put_contents(BASEDIR.'wwwroot/index.html', $index);
|
2014-05-10 02:47:26 +00:00
|
|
|
|
|
|
|
// Done
|
|
|
|
}
|
2013-09-21 03:10:24 +00:00
|
|
|
|
2015-04-05 04:35:54 +00:00
|
|
|
function buildredirects($redirects) {
|
|
|
|
foreach($redirects as $oldname => $newname) {
|
|
|
|
ob_start();
|
|
|
|
?>
|
|
|
|
<meta http-equiv="refresh" content="0; url=<?=hesc($newname)?>.html">
|
|
|
|
<a href="<?=hesc($newname)?>.html">Moved »</a>
|
|
|
|
<?php
|
|
|
|
$page = ob_get_clean();
|
|
|
|
file_put_contents(BASEDIR.'wwwroot/'.$oldname.'.html', $page);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-10 02:47:26 +00:00
|
|
|
function main($args) {
|
2015-04-05 04:07:50 +00:00
|
|
|
$basedir = './';
|
2015-04-04 06:29:33 +00:00
|
|
|
$total = $args[0];
|
|
|
|
$pos = $args[1];
|
|
|
|
|
|
|
|
// Parse configuration
|
|
|
|
|
|
|
|
$config = @parse_ini_file(
|
|
|
|
$basedir . 'config.ini',
|
|
|
|
true,
|
|
|
|
INI_SCANNER_RAW
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($config === false) {
|
|
|
|
die("[FATAL] Couldn't load '${basedir}/config.ini'!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
define('BASEDIR', $basedir);
|
|
|
|
define('SITE_TITLE', trim($config['codesite']['title']));
|
|
|
|
define('PAGE_THUMB_W', intval($config['codesite']['page_thumb_w']));
|
|
|
|
define('PAGE_THUMB_H', intval($config['codesite']['page_thumb_h']));
|
|
|
|
define('INDEX_THUMB_W', intval($config['codesite']['index_thumb_w']));
|
|
|
|
define('INDEX_THUMB_H', intval($config['codesite']['index_thumb_h']));
|
2015-09-05 23:01:13 +00:00
|
|
|
define('SHOW_BLURBS', !(isset($config['codesite']['blurbs']) && $config['codesite']['blurbs'] === 'off') );
|
2015-11-07 05:20:17 +00:00
|
|
|
define('ARTICLE_HEADER', (isset($config['codesite']['article_header']) ? $config['codesite']['article_header'] : 'ABOUT') );
|
|
|
|
define('SHIELDS_PREFIX', isset($config['codesite']['shields_prefix']));
|
2015-04-04 06:29:33 +00:00
|
|
|
|
|
|
|
// Perform build tasks
|
2014-05-10 02:47:26 +00:00
|
|
|
|
|
|
|
if ($pos == 0) {
|
|
|
|
buildcommon();
|
2015-04-05 04:35:54 +00:00
|
|
|
if (array_key_exists('redirect', $config)) {
|
|
|
|
buildredirects( $config['redirect'] );
|
|
|
|
}
|
2014-05-10 02:47:26 +00:00
|
|
|
} else {
|
|
|
|
buildprojects($pos, array_decimate(listprojects(), $total, $pos));
|
|
|
|
}
|
2013-09-21 03:10:24 +00:00
|
|
|
}
|
2013-09-21 01:22:48 +00:00
|
|
|
|
2014-05-10 02:47:26 +00:00
|
|
|
// Entry point
|
|
|
|
//
|
|
|
|
|
|
|
|
ini_set('display_errors', 'On');
|
2015-11-07 22:49:18 +00:00
|
|
|
date_default_timezone_set('Etc/UTC');
|
2014-05-10 02:47:26 +00:00
|
|
|
error_reporting(E_ALL);
|
|
|
|
|
|
|
|
main(array_slice($_SERVER['argv'], 1));
|