diff --git a/lib/CProject.php b/lib/CProject.php new file mode 100644 index 0000000..0c0730a --- /dev/null +++ b/lib/CProject.php @@ -0,0 +1,213 @@ +dir = BASEDIR.'data/'.$dirname.'/'; + $this->projname = $projname; + + // Identify resources in folder + + $ls = scandir($this->dir); + $found_real_lastupdate = false; + foreach($ls as $file) { + if ($file[0] == '.') continue; + + if ($file == 'README.txt') { + + // 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; + + } + + $this->longdesc = file_get_contents($this->dir.'README.txt'); + + $matches = array(); + if (preg_match('~Written in ([^\\r\\n]+)~', $this->longdesc, $matches)) { + $this->subtag = rtrim($matches[1], ' .'); + } + + if (preg_match('~Tags: ([^\\r\\n]+)~', $this->longdesc, $matches)) { + $this->tags = array_map('trim', explode(',', $matches[1])); + } + + $parts = explode("\n", $this->longdesc); + $this->shortdesc = array_shift($parts); + $this->shortdesc[0] = strtolower($this->shortdesc[0]); // cosmetic lowercase + + // Filter longdesc + $this->longdesc = str_replace("\r", "", $this->longdesc); // filter windows CR + + $prefix_html = ''; + $this->longdesc = preg_replace_callback('~\r?\nWritten in ([^\\n]+)~ms', function($matches) use (&$prefix_html) { + $prefix_html .= ( + (SHIELDS_PREFIX ? mkshield('build', 'success', 'brightgreen').' ' : ''). + mkshield('written in', rtrim($matches[1], '.'), 'blue') + ); + return ''; + }, $this->longdesc); + + 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"); + + $this->prefix_html = $prefix_html; + + continue; + } + + 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 + ); + } + + if (is_image($file)) { + $this->images[] = $file; + } else { + $this->downloads[] = $file; + } + } + + natcasesort($this->downloads); + $this->downloads = array_reverse($this->downloads); + + for($i = 0, $e = count($this->downloads); $i !== $e; ++$i) { + $this->downloads_hashes[] = ( + sha1_file($this->dir.$this->downloads[$i]) + ); + } + } + + public function genHomeImage() { + if (count($this->images)) { + + $this->homeimage = mkthumbnail( + $this->dir.$this->images[0], + null, // raw handle + INDEX_THUMB_W, INDEX_THUMB_H + ); + } + + } + + public function write() { + + // Generate image thumbnails + + 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) { + $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 + ); + } + + // Generate index page + + ob_start(); + $this->index(); + $idxfile = template($this->projname.' | '.SITE_TITLE, ob_get_clean()); + file_put_contents(BASEDIR.'wwwroot/'.$this->projname.'.html', $idxfile); + } + + public function getClassAttr() { + if (count($this->tags)) { + return 'taggedWith-'.implode(' taggedWith-', $this->tags); + } else { + return ''; + } + } + + public function index() { +?> +

projname))?>

+ +
+ +
+ +prefix_html)) { ?> +

prefix_html?>

+ + + + +

longdesc)?>

+ + + +downloads)) { ?> + + DOWNLOAD + + + +
+ +images)) { ?> +
+ images as $idx => $origname) { ?> + + +
+ +
+ + + +
+ + + + + + + + + + + + <?=hesc($title)?> + + +
+
+ + +
+
+ + + $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(); + + // Build all projects + + $plist = array(); + + $handles = array(); + $handle_lookup = array(); + + $alphasort = []; + + foreach($projects as $dirname => $projectname) { + + $pr = new CProject($dirname, $projectname); + $pr->genHomeImage(); // thumbnail + + $plist[] = $pr; + + if (is_null($pr->homeimage)) { + $handle_lookup[$projectname] = null; + } else { + $handle_lookup[$projectname] = count($handles); + $handles[] = $pr->homeimage; + } + + $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); + } + + // Build homepage spritesheet + + if (count($handles)) { + mkspritesheet($handles, BASEDIR.'wwwroot/logos.jpg', INDEX_THUMB_W, INDEX_THUMB_H); + array_map('imagedestroy', $handles); // free + } + + // Build index page + + ob_start(); +?> + + + + + + + + + $pr) { ?> + + + + + +
+ projname]) ? '
' : '
')?>
+
+ projname))?>, + shortdesc)?> + + more... + subtag) || count($pr->tags)) { ?> +
+ + subtag)?> + subtag) && count($pr->tags)) { ?> + :: + + tags as $tag) { ?> + + + + +
+ $newname) { + ob_start(); +?> + +Moved » + 1024 && count($sxlist) >= 2) { + array_shift($sxlist); + $size /= 1024; + } + return number_format($size, 2).array_shift($sxlist); +} + +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']); +} + +function hesc($sz) { + return @htmlentities($sz, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); +} + +function text2html($sz) { + + $identity = function($sz) { + return $sz; + }; + + $splitInside = function($begin, $end, $sz) { + $parts = explode($begin, $sz); + if (count($parts) == 1) return [$sz]; + + $ret = [$parts[0]]; + for($i = 1, $e = count($parts); $i !== $e; ++$i) { + $inner = explode($end, $parts[$i], 2); + $ret = array_merge($ret, $inner); + } + 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); + }; + + $sectionFmt = function($sz) use($oddEven, $identity) { + $base = hesc($sz); + + $base = preg_replace('~^=+(.+)=+~m', '\\1', $base); + $base = preg_replace('~(https?://[^ \\r\\n\\t]+)~i', '\\1', $base); + $base = preg_replace('~\\[b\\](.+?)\\[/b\\]~m', '\\1', $base); + $base = preg_replace('~\\[i\\](.+?)\\[/i\\]~m', '\\1', $base); + $base = preg_replace('~\\[spoiler\\](.+?)\\[/spoiler\\]~m', '\\1', $base); + $base = preg_replace('~\\[entry=([^\\]]+?)\\](.+?)\\[/entry\\]~m', '\\2', $base); + $base = preg_replace('~\n- ~ms', "\n• ", $base); + + $btparts = explode('`', $base); + if (count($btparts) > 1 && (count($btparts) % 2)) { + for ($i = 1, $e = count($btparts); $i < $e; $i += 2) { + $class = 'code'; + if (strpos($btparts[$i], "\n") !== false) { + $class .= ' code-multiline'; + } + $btparts[$i] = ''.$btparts[$i].''; + } + } + + return $oddEven($btparts, $identity, 'nl2br'); + }; + + $htmlSections = $splitInside('', '', $sz); + return $oddEven($htmlSections, $identity, $sectionFmt); +} + +function array_decimate($array, $total, $partno) { + $ct = 0; + $ret = []; + foreach($array as $k => $v) { + if (++$ct % $total == ($partno - 1)) { + $ret[$k] = $v; + } + } + return $ret; +} diff --git a/rebuild.php b/rebuild.php deleted file mode 100644 index e2418b1..0000000 --- a/rebuild.php +++ /dev/null @@ -1,600 +0,0 @@ -#!/usr/bin/php - 1024 && count($sxlist) >= 2) { - array_shift($sxlist); - $size /= 1024; - } - return number_format($size, 2).array_shift($sxlist); -} - -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']); -} - -function hesc($sz) { - return @htmlentities($sz, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); -} - -function text2html($sz) { - - $identity = function($sz) { - return $sz; - }; - - $splitInside = function($begin, $end, $sz) { - $parts = explode($begin, $sz); - if (count($parts) == 1) return [$sz]; - - $ret = [$parts[0]]; - for($i = 1, $e = count($parts); $i !== $e; ++$i) { - $inner = explode($end, $parts[$i], 2); - $ret = array_merge($ret, $inner); - } - 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); - }; - - $sectionFmt = function($sz) use($oddEven, $identity) { - $base = hesc($sz); - - $base = preg_replace('~^=+(.+)=+~m', '\\1', $base); - $base = preg_replace('~(https?://[^ \\r\\n\\t]+)~i', '\\1', $base); - $base = preg_replace('~\\[b\\](.+?)\\[/b\\]~m', '\\1', $base); - $base = preg_replace('~\\[i\\](.+?)\\[/i\\]~m', '\\1', $base); - $base = preg_replace('~\\[spoiler\\](.+?)\\[/spoiler\\]~m', '\\1', $base); - $base = preg_replace('~\\[entry=([^\\]]+?)\\](.+?)\\[/entry\\]~m', '\\2', $base); - $base = preg_replace('~\n- ~ms', "\n• ", $base); - - $btparts = explode('`', $base); - if (count($btparts) > 1 && (count($btparts) % 2)) { - for ($i = 1, $e = count($btparts); $i < $e; $i += 2) { - $class = 'code'; - if (strpos($btparts[$i], "\n") !== false) { - $class .= ' code-multiline'; - } - $btparts[$i] = ''.$btparts[$i].''; - } - } - - return $oddEven($btparts, $identity, 'nl2br'); - }; - - $htmlSections = $splitInside('', '', $sz); - return $oddEven($htmlSections, $identity, $sectionFmt); -} - -function array_decimate($array, $total, $partno) { - $ct = 0; - $ret = []; - foreach($array as $k => $v) { - if (++$ct % $total == ($partno - 1)) { - $ret[$k] = $v; - } - } - return $ret; -} - -/** - * - */ -class CProject { - - private $dir; - public $projname; - public $shortdesc = '(no description)'; - public $subtag = ''; - public $lastupdate = 0; - private $longdesc = ''; - private $prefix_html = ''; - private $images = array(); - private $downloads = array(); - private $downloads_hashes = array(); - public $tags = array(); - - public $homeimage = null; - - public function __construct($dirname, $projname) { - $this->dir = BASEDIR.'data/'.$dirname.'/'; - $this->projname = $projname; - - // Identify resources in folder - - $ls = scandir($this->dir); - $found_real_lastupdate = false; - foreach($ls as $file) { - if ($file[0] == '.') continue; - - if ($file == 'README.txt') { - - // 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; - - } - - $this->longdesc = file_get_contents($this->dir.'README.txt'); - - $matches = array(); - if (preg_match('~Written in ([^\\r\\n]+)~', $this->longdesc, $matches)) { - $this->subtag = rtrim($matches[1], ' .'); - } - - if (preg_match('~Tags: ([^\\r\\n]+)~', $this->longdesc, $matches)) { - $this->tags = array_map('trim', explode(',', $matches[1])); - } - - $parts = explode("\n", $this->longdesc); - $this->shortdesc = array_shift($parts); - $this->shortdesc[0] = strtolower($this->shortdesc[0]); // cosmetic lowercase - - // Filter longdesc - $this->longdesc = str_replace("\r", "", $this->longdesc); // filter windows CR - - $prefix_html = ''; - $this->longdesc = preg_replace_callback('~\r?\nWritten in ([^\\n]+)~ms', function($matches) use (&$prefix_html) { - $prefix_html .= ( - (SHIELDS_PREFIX ? mkshield('build', 'success', 'brightgreen').' ' : ''). - mkshield('written in', rtrim($matches[1], '.'), 'blue') - ); - return ''; - }, $this->longdesc); - - 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"); - - $this->prefix_html = $prefix_html; - - continue; - } - - 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 - ); - } - - if (is_image($file)) { - $this->images[] = $file; - } else { - $this->downloads[] = $file; - } - } - - natcasesort($this->downloads); - $this->downloads = array_reverse($this->downloads); - - for($i = 0, $e = count($this->downloads); $i !== $e; ++$i) { - $this->downloads_hashes[] = ( - sha1_file($this->dir.$this->downloads[$i]) - ); - } - } - - public function genHomeImage() { - if (count($this->images)) { - - $this->homeimage = mkthumbnail( - $this->dir.$this->images[0], - null, // raw handle - INDEX_THUMB_W, INDEX_THUMB_H - ); - } - - } - - public function write() { - - // Generate image thumbnails - - 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) { - $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 - ); - } - - // Generate index page - - ob_start(); - $this->index(); - $idxfile = template($this->projname.' | '.SITE_TITLE, ob_get_clean()); - file_put_contents(BASEDIR.'wwwroot/'.$this->projname.'.html', $idxfile); - } - - public function getClassAttr() { - if (count($this->tags)) { - return 'taggedWith-'.implode(' taggedWith-', $this->tags); - } else { - return ''; - } - } - - public function index() { -?> -

projname))?>

- -
- -
- -prefix_html)) { ?> -

prefix_html?>

- - - - -

longdesc)?>

- - - -downloads)) { ?> - - DOWNLOAD - - - -
- -images)) { ?> -
- images as $idx => $origname) { ?> - - -
- -
- - - -
- - - - - - - - - - - - <?=hesc($title)?> - - -
-
- - -
-
- - - $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(); - - // Build all projects - - $plist = array(); - - $handles = array(); - $handle_lookup = array(); - - $alphasort = []; - - foreach($projects as $dirname => $projectname) { - - $pr = new CProject($dirname, $projectname); - $pr->genHomeImage(); // thumbnail - - $plist[] = $pr; - - if (is_null($pr->homeimage)) { - $handle_lookup[$projectname] = null; - } else { - $handle_lookup[$projectname] = count($handles); - $handles[] = $pr->homeimage; - } - - $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); - } - - // Build homepage spritesheet - - if (count($handles)) { - mkspritesheet($handles, BASEDIR.'wwwroot/logos.jpg', INDEX_THUMB_W, INDEX_THUMB_H); - array_map('imagedestroy', $handles); // free - } - - // Build index page - - ob_start(); -?> - - - - - - - - - $pr) { ?> - - - - - -
- projname]) ? '
' : '
')?>
-
- projname))?>, - shortdesc)?> - - more... - subtag) || count($pr->tags)) { ?> -
- - subtag)?> - subtag) && count($pr->tags)) { ?> - :: - - tags as $tag) { ?> - - - - -
- $newname) { - ob_start(); -?> - -Moved » -